diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-01-01 22:06:40 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-01-01 22:06:40 +0900 |
| commit | 8dbe5c2a1d8dc15bbdd6810b2582c680e1c0bb9b (patch) | |
| tree | be39e1436f83c716fc45df133106fba7dd4bc23a /src/server/routes | |
| parent | 830b370f1b8e0f3a384b2d242ab120812e81977d (diff) | |
| download | kioku-8dbe5c2a1d8dc15bbdd6810b2582c680e1c0bb9b.tar.gz kioku-8dbe5c2a1d8dc15bbdd6810b2582c680e1c0bb9b.tar.zst kioku-8dbe5c2a1d8dc15bbdd6810b2582c680e1c0bb9b.zip | |
feat(import): add CSV bulk import for notes
Add client-side CSV parsing and bulk import API endpoint for importing
notes from CSV files. Supports quoted fields, newlines in values, and
escaped quotes.
- New POST /api/decks/{deckId}/notes/import endpoint for bulk creation
- CSV parser with RFC 4180 compliance
- Multi-phase import modal (upload → validate → preview → import)
- Client-side validation with per-row error reporting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/server/routes')
| -rw-r--r-- | src/server/routes/notes.test.ts | 1 | ||||
| -rw-r--r-- | src/server/routes/notes.ts | 32 |
2 files changed, 32 insertions, 1 deletions
diff --git a/src/server/routes/notes.test.ts b/src/server/routes/notes.test.ts index 2ca08f9..e354fa6 100644 --- a/src/server/routes/notes.test.ts +++ b/src/server/routes/notes.test.ts @@ -23,6 +23,7 @@ function createMockNoteRepo(): NoteRepository { create: vi.fn(), update: vi.fn(), softDelete: vi.fn(), + createMany: vi.fn(), }; } diff --git a/src/server/routes/notes.ts b/src/server/routes/notes.ts index 16ffb09..ea7b0d0 100644 --- a/src/server/routes/notes.ts +++ b/src/server/routes/notes.ts @@ -8,7 +8,11 @@ import { type NoteRepository, noteRepository, } from "../repositories/index.js"; -import { createNoteSchema, updateNoteSchema } from "../schemas/index.js"; +import { + bulkCreateNotesSchema, + createNoteSchema, + updateNoteSchema, +} from "../schemas/index.js"; export interface NoteDependencies { noteRepo: NoteRepository; @@ -86,6 +90,32 @@ export function createNotesRouter(deps: NoteDependencies) { } }, ) + // Bulk import notes + .post( + "/import", + zValidator("param", deckIdParamSchema), + zValidator("json", bulkCreateNotesSchema), + async (c) => { + const user = getAuthUser(c); + const { deckId } = c.req.valid("param"); + const data = c.req.valid("json"); + + const deck = await deckRepo.findById(deckId, user.id); + if (!deck) { + throw Errors.notFound("Deck not found", "DECK_NOT_FOUND"); + } + + const result = await noteRepo.createMany(deckId, data.notes); + + return c.json( + { + created: result.created, + failed: result.failed, + }, + 201, + ); + }, + ) // Get note with field values .get("/:noteId", zValidator("param", noteIdParamSchema), async (c) => { const user = getAuthUser(c); |
