diff options
| author | soryu <soryu@soryu.co> | 2026-05-02 15:07:33 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-02 15:07:33 +0100 |
| commit | 760516b2e7b97fa389fb3902e8d2314eea052ff0 (patch) | |
| tree | 69eb1dd212ef924ee9e451d8d88806f899c03e84 /makima/frontend/src/lib/api.ts | |
| parent | e11759447b1ac00becfb1e979e488f7f9c9cf478 (diff) | |
| download | soryu-760516b2e7b97fa389fb3902e8d2314eea052ff0.tar.gz soryu-760516b2e7b97fa389fb3902e8d2314eea052ff0.zip | |
feat: multi-document directives with ephemeral task lifecycle (#119)
* feat: soryu-co/soryu - makima: Fix folder/file naming and breadcrumb hash bugs
* WIP: heartbeat checkpoint
* WIP: heartbeat checkpoint
* WIP: heartbeat checkpoint
* feat: soryu-co/soryu - makima: Frontend: render multiple documents per directive folder
* WIP: heartbeat checkpoint
* WIP: heartbeat checkpoint
* WIP: heartbeat checkpoint
* Fix DirectiveRevision import in openapi.rs after merge
* Fix document-directives.tsx merge artifacts and add inactive status
Diffstat (limited to 'makima/frontend/src/lib/api.ts')
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index 4d664cf..80da511 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -3583,6 +3583,120 @@ export async function pickUpOrders(directiveId: string): Promise<PickUpOrdersRes } // ============================================================================= +// Directive Documents API +// +// A directive_document is one of N markdown documents owned by a directive. +// Each has its own lifecycle (draft → active → shipped → archived) and may be +// attached to a PR. The frontend never calls the /ship endpoint — the backend +// invokes that itself when PRs are raised. Editing a shipped document +// auto-reactivates it on the backend (see PATCH handler). +// ============================================================================= + +export type DirectiveDocumentStatus = "draft" | "active" | "shipped" | "archived"; + +export interface DirectiveDocument { + id: string; + directiveId: string; + title: string; + body: string; + status: DirectiveDocumentStatus; + prUrl: string | null; + prBranch: string | null; + shippedAt: string | null; + archivedAt: string | null; + version: number; + createdAt: string; + updatedAt: string; +} + +export interface CreateDirectiveDocumentRequest { + title?: string; + body?: string; +} + +export interface UpdateDirectiveDocumentRequest { + title?: string; + body?: string; +} + +export async function listDirectiveDocuments(directiveId: string): Promise<DirectiveDocument[]> { + const res = await authFetch(`${API_BASE}/api/v1/directives/${directiveId}/documents`); + if (!res.ok) throw new Error(`Failed to list directive documents: ${res.statusText}`); + return res.json(); +} + +export async function createDirectiveDocument( + directiveId: string, + req: CreateDirectiveDocumentRequest = {}, +): Promise<DirectiveDocument> { + const res = await authFetch(`${API_BASE}/api/v1/directives/${directiveId}/documents`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(req), + }); + if (!res.ok) throw new Error(`Failed to create directive document: ${res.statusText}`); + return res.json(); +} + +export async function getDirectiveDocument(documentId: string): Promise<DirectiveDocument> { + const res = await authFetch(`${API_BASE}/api/v1/directive-documents/${documentId}`); + if (!res.ok) throw new Error(`Failed to get directive document: ${res.statusText}`); + return res.json(); +} + +/** + * Update a directive document's title and/or body. The backend auto-reactivates + * a shipped document when its body changes (re-stamps status to `active`), + * which is why we don't expose a separate "reactivate" call. + */ +export async function updateDirectiveDocument( + documentId: string, + req: UpdateDirectiveDocumentRequest, +): Promise<DirectiveDocument> { + const res = await authFetch(`${API_BASE}/api/v1/directive-documents/${documentId}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(req), + }); + if (!res.ok) throw new Error(`Failed to update directive document: ${res.statusText}`); + return res.json(); +} + +export async function archiveDirectiveDocument(documentId: string): Promise<DirectiveDocument> { + const res = await authFetch(`${API_BASE}/api/v1/directive-documents/${documentId}/archive`, { + method: "POST", + }); + if (!res.ok) throw new Error(`Failed to archive directive document: ${res.statusText}`); + return res.json(); +} + +/** Steps and tasks attached to a single directive document. Drives the + * per-document `tasks/` subfolder in the sidebar — when the document + * ships, its tasks visually move with it under shipped/. */ +export interface DocumentTasksResponse { + steps: DirectiveStep[]; + tasks: Task[]; +} + +/** + * List the steps and ephemeral tasks attached to a specific directive + * document. Used by the sidebar to render a `tasks/` subfolder beside each + * document — including shipped documents, whose tasks remain attached so + * they continue to render under shipped/ alongside the document. + */ +export async function listDirectiveDocumentTasks( + documentId: string, +): Promise<DocumentTasksResponse> { + const res = await authFetch( + `${API_BASE}/api/v1/directive-documents/${documentId}/tasks`, + ); + if (!res.ok) { + throw new Error(`Failed to list directive document tasks: ${res.statusText}`); + } + return res.json(); +} + +// ============================================================================= // Directive Order Groups (DOGs) API // ============================================================================= |
