@ai-matrx/office 0.8.24 → 0.8.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/dist/{chunk-TRA2BTPL.js → chunk-CAWDEHVL.js} +20 -6
- package/dist/chunk-CAWDEHVL.js.map +1 -0
- package/dist/{chunk-ZDZCCOUB.cjs → chunk-IJNET5TT.cjs} +20 -6
- package/dist/chunk-IJNET5TT.cjs.map +1 -0
- package/dist/{chunk-JMVPAJJA.cjs → chunk-LHTG72LS.cjs} +20 -6
- package/dist/chunk-LHTG72LS.cjs.map +1 -0
- package/dist/{chunk-WKBWRG7N.js → chunk-RREOARR4.js} +20 -6
- package/dist/chunk-RREOARR4.js.map +1 -0
- package/dist/docs-host.cjs.map +1 -1
- package/dist/docs-host.d.cts +8 -0
- package/dist/docs-host.d.ts +8 -0
- package/dist/docs-host.js.map +1 -1
- package/dist/docs-io.cjs +6 -6
- package/dist/docs-io.js +1 -1
- package/dist/docs.cjs +2 -2
- package/dist/docs.d.cts +9 -1
- package/dist/docs.d.ts +9 -1
- package/dist/docs.js +1 -1
- package/dist/sheets-xlsx.cjs +6 -6
- package/dist/sheets-xlsx.js +1 -1
- package/dist/sheets.cjs +3 -3
- package/dist/sheets.d.cts +9 -1
- package/dist/sheets.d.ts +9 -1
- package/dist/sheets.js +1 -1
- package/dist/univer-collab.cjs +66 -6
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +8 -0
- package/dist/univer-collab.d.ts +8 -0
- package/dist/univer-collab.js +66 -6
- package/dist/univer-collab.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-JMVPAJJA.cjs.map +0 -1
- package/dist/chunk-TRA2BTPL.js.map +0 -1
- package/dist/chunk-WKBWRG7N.js.map +0 -1
- package/dist/chunk-ZDZCCOUB.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.8.
|
|
3
|
+
## 0.8.26
|
|
4
4
|
### C9: comment anchors that follow concurrent edits
|
|
5
5
|
|
|
6
6
|
- **Docs:** `addCommentAnchorActions(body, start, end, id)` anchors a passage with a `COMMENT` custom range (Univer's own builder, so the op has the link family's shape C0 proved); `commentAnchorsOf(body)` reads every anchor back (split pieces joined, Univer's inclusive end as `[start, end)`); `removeCommentAnchorActions` takes a cancelled draft's anchor out; `commentPartAnchor` / `anchorIdOfPartAnchor` are the thread's `part_anchor` (`anchor:<id>`, quote as `label`). Fuzz on the C0 corpora: anchor × every captured family and anchor × anchor, 0 divergences in 180,000 checks at 2,000 seeds; red check without a transform.
|
|
@@ -154,6 +154,20 @@ async function saveDocumentSnapshot(args) {
|
|
|
154
154
|
await db().schema("workbench").from("udt_documents").update({ updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", args.documentId);
|
|
155
155
|
return { success: true, data };
|
|
156
156
|
}
|
|
157
|
+
async function currentSnapshotForCopy(documentId) {
|
|
158
|
+
const read = getDocsHost().readCurrentSnapshot;
|
|
159
|
+
if (read) {
|
|
160
|
+
try {
|
|
161
|
+
const cur = await read(documentId);
|
|
162
|
+
return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };
|
|
163
|
+
} catch (err) {
|
|
164
|
+
return { success: false, error: err instanceof Error ? err.message : "Could not read the current content to copy." };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const latest = await getLatestDocumentSnapshot(documentId);
|
|
168
|
+
if (!latest.success) return latest;
|
|
169
|
+
return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };
|
|
170
|
+
}
|
|
157
171
|
async function copyDocument(documentId, name) {
|
|
158
172
|
const original = await getDocument(documentId);
|
|
159
173
|
if (!original.success) return original;
|
|
@@ -169,13 +183,13 @@ async function copyDocument(documentId, name) {
|
|
|
169
183
|
isPublic: row.visibility === "public"
|
|
170
184
|
});
|
|
171
185
|
if (!created.success) return created;
|
|
172
|
-
const
|
|
173
|
-
if (!
|
|
174
|
-
if (
|
|
186
|
+
const source = await currentSnapshotForCopy(documentId);
|
|
187
|
+
if (!source.success) return source;
|
|
188
|
+
if (source.data) {
|
|
175
189
|
const saved = await saveDocumentSnapshot({
|
|
176
190
|
documentId: created.data.id,
|
|
177
|
-
snapshot:
|
|
178
|
-
label:
|
|
191
|
+
snapshot: source.data.snapshot,
|
|
192
|
+
label: source.data.label,
|
|
179
193
|
origin: "autosave"
|
|
180
194
|
});
|
|
181
195
|
if (!saved.success) return saved;
|
|
@@ -275,4 +289,4 @@ export {
|
|
|
275
289
|
listDocumentSnapshots,
|
|
276
290
|
sanitizeUniverDocSnapshot
|
|
277
291
|
};
|
|
278
|
-
//# sourceMappingURL=chunk-
|
|
292
|
+
//# sourceMappingURL=chunk-CAWDEHVL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/docs/ports.ts","../src/docs/document-service.ts","../src/docs/sanitize-univer-doc-snapshot.ts"],"sourcesContent":["/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(documentId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\nasync function currentSnapshotForCopy(\n documentId: string,\n): Promise<ServiceResult<{ snapshot: unknown; label: string | null } | null>> {\n const read = getDocsHost().readCurrentSnapshot;\n if (read) {\n try {\n const cur = await read(documentId);\n return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : \"Could not read the current content to copy.\" };\n }\n }\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };\n}\n\n/**\n * An independent copy of a document: its own row, with the CURRENT content copied over (the live room when people are co-editing), so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n // The copy starts from the CURRENT content: the live room's text when people are co-editing (the host's reader),\n // else the newest save. Typed-but-unsaved text is part of what \"Make a copy\" copies.\n const source = await currentSnapshotForCopy(documentId);\n if (!source.success) return source;\n if (source.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: source.data.snapshot,\n label: source.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * sanitizeUniverDocSnapshot — defensive normalizer for Univer document\n * snapshots loaded from storage.\n *\n * WHY THIS EXISTS (loud recovery layer):\n * Univer's `NamedStyleType` is a NUMERIC enum (`HEADING_1 = 4`, `HEADING_2 = 5`,\n * …). Some snapshots in storage were produced by an external markdown→Univer\n * converter that wrote the *string* name (`\"HEADING_1\"`) into\n * `paragraphStyle.namedStyleType` instead of the numeric value. At render time\n * Univer does `HEADING_ICON_MAP[namedStyleType]` → `undefined` →\n * `icon.key` throws `Cannot read properties of undefined (reading 'key')` inside\n * the `<ParagraphMenu>` component the moment the cursor lands in a heading. That\n * uncaught error tears down Univer's React root, so the document loads and then\n * vanishes. See `features/data-tables/FEATURE.md`.\n *\n * This normalizer converts those string enum values back to numbers BEFORE the\n * snapshot reaches `createUniverDoc`. It is a recovery layer: when it fires it\n * means malformed data slipped past the writer, so it SCREAMS (console.warn)\n * with a count and the document id. The proper long-term fix is to make the\n * writer emit numeric enum values; until then this keeps the editor alive.\n *\n * Returns the SAME object (mutated in place) for ergonomic call sites, plus a\n * `fixed` count via the second return slot is intentionally avoided — callers\n * only need the sanitized snapshot; the warning is the signal.\n */\nimport { NamedStyleType } from \"@univerjs/core\";\nimport type { IDocumentData } from \"@univerjs/core\";\n\nimport {\n defaultDocumentPageStyle,\n isLegacySqueezedPageStyle,\n} from \"../core\";\n\n/**\n * Map of every string name that could appear in a legacy snapshot to its\n * canonical numeric `NamedStyleType`. Built from the enum itself so it stays in\n * lockstep with Univer (numeric enums expose name→value on string keys).\n */\nconst NAMED_STYLE_STRING_TO_NUMBER: Record<string, number> = Object.fromEntries(\n Object.entries(NamedStyleType)\n .filter(([key, val]) => typeof val === \"number\" && isNaN(Number(key)))\n .map(([key, val]) => [key, val as number]),\n);\n\n/**\n * Normalize a Univer document snapshot in place. Currently fixes string-valued\n * `paragraphStyle.namedStyleType` (the confirmed `<ParagraphMenu>` crash). New\n * classes of string-vs-enum corruption should be added here, not patched at the\n * call site.\n *\n * @param snapshot The snapshot about to be passed to `createUniverDoc`.\n * @param docId Document id, for the loud warning only.\n * @param opts.quiet The co-editing state hash applies the same repair to compare what a seat will hold\n * (`asLoadedDocsSnapshot`); the warning belongs to the load, not to every hash.\n * @returns the same snapshot reference (mutated).\n */\nexport function sanitizeUniverDocSnapshot(\n snapshot: Partial<IDocumentData>,\n docId?: string,\n opts: { quiet?: boolean } = {},\n): Partial<IDocumentData> {\n restorePageStyle(snapshot, docId, opts.quiet === true);\n ensureTextRuns(snapshot);\n\n const paragraphs = snapshot?.body?.paragraphs;\n if (!Array.isArray(paragraphs)) return snapshot;\n\n let fixed = 0;\n for (const paragraph of paragraphs) {\n const style = paragraph?.paragraphStyle as\n { namedStyleType?: unknown } | undefined;\n const value = style?.namedStyleType;\n if (typeof value === \"string\") {\n const numeric = NAMED_STYLE_STRING_TO_NUMBER[value];\n if (numeric !== undefined) {\n (style as { namedStyleType?: number }).namedStyleType = numeric;\n fixed += 1;\n } else {\n // Unknown string we can't map — drop it so Univer falls back to\n // NORMAL_TEXT rather than crashing on the lookup.\n delete (style as { namedStyleType?: unknown }).namedStyleType;\n fixed += 1;\n }\n }\n }\n\n if (fixed > 0 && opts.quiet !== true) {\n console.warn(\n `[data-tables] RECOVERY: sanitized ${fixed} string namedStyleType value(s) ` +\n `to numeric NamedStyleType in document snapshot${docId ? ` ${docId}` : \"\"}. ` +\n `The snapshot was written with the wrong enum encoding (string instead of ` +\n `number) and would have crashed Univer's <ParagraphMenu>. Fix the snapshot ` +\n `writer to emit numeric NamedStyleType values.`,\n );\n }\n\n return snapshot;\n}\n\n/**\n * Second recovery: a snapshot with no `documentStyle.pageSize` has no page box,\n * so Univer lays the body out unbounded — text never wraps and the docs\n * viewport reports no scrollable extent, which reads to the user as \"the\n * document won't scroll\". Snapshots written by agents (`origin='agent'`) and by\n * older converters reach storage with `documentStyle: {}`. Stamp the canonical\n * page geometry back on and SCREAM: the writer is the real bug.\n */\nfunction restorePageStyle(snapshot: Partial<IDocumentData>, docId?: string, quiet = false) {\n if (!snapshot || typeof snapshot !== \"object\") return;\n\n // THE SQUEEZED PAGE (2026-10-15): documents carried A4-at-72dpi geometry in Univer's pageless\n // flavour — a 415px text column with no paper. Move them to a real Letter page, unchanged text.\n // A document with no flavour at all is a paginated page too (Univer would otherwise pick pageless).\n const style = snapshot.documentStyle;\n if (style?.pageSize?.width && isLegacySqueezedPageStyle(style)) {\n const page = defaultDocumentPageStyle();\n snapshot.documentStyle = { ...style, ...page, defaultParagraphStyle: style.defaultParagraphStyle ?? page.defaultParagraphStyle } as typeof style;\n return;\n }\n if (style?.pageSize?.width) {\n if (!style.documentFlavor) {\n const page = defaultDocumentPageStyle();\n Object.assign(style, { documentFlavor: page.documentFlavor });\n if (page.defaultParagraphStyle) style.defaultParagraphStyle ??= page.defaultParagraphStyle;\n }\n return;\n }\n\n snapshot.documentStyle = {\n ...defaultDocumentPageStyle(),\n ...(snapshot.documentStyle ?? {}),\n pageSize: defaultDocumentPageStyle().pageSize,\n } as NonNullable<typeof snapshot.documentStyle>;\n\n if (quiet) return;\n console.warn(\n `[data-tables] RECOVERY: document snapshot${docId ? ` ${docId}` : \"\"} had no ` +\n `documentStyle.pageSize — restored the default Letter page geometry. Without a ` +\n `page box Univer lays the body out unbounded: text does not wrap and the ` +\n `viewport has no scrollable extent, so the document appears frozen. Fix the ` +\n `snapshot writer (agent/markdown converters must stamp ` +\n `DEFAULT_DOCUMENT_PAGE_STYLE).`,\n );\n}\n\n/**\n * A body with no `textRuns` array is a body Univer silently refuses styled text for: its text\n * insert (`insertTextRuns`) returns early when the target has none, so every bold, italic, code\n * and size run of pasted or agent-written markdown vanished (found 2026-10-16: `**notes**` pasted\n * into a blank document stayed plain). An empty array is the same document and accepts the runs.\n */\nfunction ensureTextRuns(snapshot: Partial<IDocumentData>) {\n const body = snapshot?.body;\n if (body && typeof body === \"object\" && !Array.isArray(body.textRuns)) body.textRuns = [];\n}\n"],"mappings":"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","names":["error"]}
|
|
@@ -130,6 +130,20 @@ async function listTrashedWorkbooks() {
|
|
|
130
130
|
if (error) return { success: false, error: error.message };
|
|
131
131
|
return { success: true, data: _nullishCoalesce(data, () => ( [])) };
|
|
132
132
|
}
|
|
133
|
+
async function currentSnapshotForCopy(workbookId) {
|
|
134
|
+
const read = getSheetsHost().readCurrentSnapshot;
|
|
135
|
+
if (read) {
|
|
136
|
+
try {
|
|
137
|
+
const cur = await read(workbookId);
|
|
138
|
+
return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };
|
|
139
|
+
} catch (err) {
|
|
140
|
+
return { success: false, error: err instanceof Error ? err.message : "Could not read the current content to copy." };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const latest = await getLatestSnapshot(workbookId);
|
|
144
|
+
if (!latest.success) return latest;
|
|
145
|
+
return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: _nullishCoalesce(latest.data.label, () => ( null)) } : null };
|
|
146
|
+
}
|
|
133
147
|
async function copyWorkbook(workbookId, name) {
|
|
134
148
|
const original = await getWorkbook(workbookId);
|
|
135
149
|
if (!original.success) return original;
|
|
@@ -147,13 +161,13 @@ async function copyWorkbook(workbookId, name) {
|
|
|
147
161
|
projectId: _nullishCoalesce(row.project_id, () => ( null))
|
|
148
162
|
});
|
|
149
163
|
if (!created.success) return created;
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
if (
|
|
164
|
+
const source = await currentSnapshotForCopy(workbookId);
|
|
165
|
+
if (!source.success) return source;
|
|
166
|
+
if (source.data) {
|
|
153
167
|
const saved = await saveSnapshot({
|
|
154
168
|
workbookId: created.data.id,
|
|
155
|
-
snapshot:
|
|
156
|
-
label:
|
|
169
|
+
snapshot: source.data.snapshot,
|
|
170
|
+
label: source.data.label,
|
|
157
171
|
origin: "autosave"
|
|
158
172
|
});
|
|
159
173
|
if (!saved.success) return saved;
|
|
@@ -206,4 +220,4 @@ async function listSnapshots(workbookId, limit = 50) {
|
|
|
206
220
|
|
|
207
221
|
|
|
208
222
|
exports.configureSheetsHost = configureSheetsHost; exports.getSheetsHost = getSheetsHost; exports.workbookSourceLabel = workbookSourceLabel; exports.createWorkbook = createWorkbook; exports.listAccessibleWorkbooks = listAccessibleWorkbooks; exports.getWorkbook = getWorkbook; exports.renameWorkbook = renameWorkbook; exports.moveWorkbook = moveWorkbook; exports.updateWorkbookDescription = updateWorkbookDescription; exports.deleteWorkbook = deleteWorkbook; exports.discardFailedWorkbook = discardFailedWorkbook; exports.restoreWorkbook = restoreWorkbook; exports.listTrashedWorkbooks = listTrashedWorkbooks; exports.copyWorkbook = copyWorkbook; exports.getLatestSnapshot = getLatestSnapshot; exports.saveSnapshot = saveSnapshot; exports.listSnapshots = listSnapshots;
|
|
209
|
-
//# sourceMappingURL=chunk-
|
|
223
|
+
//# sourceMappingURL=chunk-IJNET5TT.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-IJNET5TT.cjs","../src/sheets/ports.ts","../src/sheets/workbook-service.ts"],"names":["error"],"mappings":"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","file":"/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-IJNET5TT.cjs","sourcesContent":[null,"/**\n * The host ports of the Sheets model and io.\n *\n * The package owns the workbook service, the page-setup store and the import flow, but three things\n * belong to the app that mounts them: the database client (a package owns no client), the\n * organization a write acts in (the active-organization ladder is app state) and the file store that\n * keeps a lossless copy of an imported file. The host states them once at start-up with\n * `configureSheetsHost`. State sits on a `globalThis` slot so a dual-bundled copy of the package\n * still sees one host. An unconfigured port THROWS naming itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type SheetsSupabase = SupabaseClient<any, any, any>;\n\nexport interface SheetsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): SheetsSupabase;\n /** The organization a write acts in: the record's own when given, otherwise the active one. */\n ensureOrgId(organizationId: string | null): Promise<string>;\n /** Keep the original of an imported spreadsheet in the file store, in `folderPath`. */\n uploadOriginalFile(file: File, options: { folderPath: string }): Promise<{ fileId: string }>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(workbookId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.sheets-host\");\ntype Slot = { ports?: SheetsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureSheetsHost(ports: SheetsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getSheetsHost(): SheetsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/sheets: configureSheetsHost(ports) was not called before the workbook service ran.\");\n return ports;\n}\n","/**\n * Workbook service — typed wrappers for `udt_workbooks` + `udt_workbook_snapshots`.\n *\n * Workbooks are the lossless-spreadsheet surface (P4): metadata in\n * `udt_workbooks`, content state in append-only `udt_workbook_snapshots`. The\n * editor (Univer or equivalent) hydrates from the LATEST snapshot and writes\n * a new snapshot per save (debounced on the client — see WorkbookEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - Realtime: @ai-matrx/office/univer/collab useWorkbookRealtime\n * - Component: the Sheets editor\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { Workbook, WorkbookSnapshot, WorkbookSnapshotOrigin } from \"../core/types\";\nimport { getSheetsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getSheetsHost().getSupabase();\n\n// ─── workbooks ────────────────────────────────────────────────────────────────\n\nconst WORKBOOK_SOURCE_LABELS: Record<string, string> = {\n created: \"Created\",\n imported_xlsx: \"Imported Excel\",\n imported_gsheet: \"Imported from Google Sheets\",\n imported_csv: \"Imported CSV\",\n linked_gsheet: \"Imported from Google Sheets\",\n};\n\n/** Honest, human label for `udt_workbooks.source`. */\nexport function workbookSourceLabel(source: string): string {\n return WORKBOOK_SOURCE_LABELS[source] ?? source.replace(/_/g, \" \");\n}\n\nexport type CreateWorkbookArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the workbook itself, mirrors `udt_workbooks.source`. */\n source?:\n | \"created\"\n | \"imported_xlsx\"\n | \"imported_gsheet\"\n | \"imported_csv\"\n | \"linked_gsheet\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (XLSX / CSV blob). Set on the import\n * flow so the lossless original is recoverable; FK is ON DELETE SET NULL,\n * so deleting the file just nulls the link — the workbook survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createWorkbook(\n args: CreateWorkbookArgs,\n): Promise<ServiceResult<Workbook>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a workbook.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .insert({\n workbook_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; legacy `is_public` is derived from it by the\n // workbench._bridge_legacy_owner trigger. A new workbook defaults to\n // `internal` — org work product, not an individual's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function listAccessibleWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n // RLS handles owner / published-to-the-web / shared access.\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\nexport async function getWorkbook(\n workbookId: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .eq(\"id\", workbookId)\n .is(\"deleted_at\", null)\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function renameWorkbook(\n workbookId: string,\n name: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ workbook_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Move the workbook into a project (or out of one with `null`). Sibling of\n * `renameWorkbook`: the one named setter for `project_id`.\n */\nexport async function moveWorkbook(\n workbookId: string,\n projectId: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Rewrite the workbook's description. Sibling of `renameWorkbook` — the two\n * human-authored fields on `udt_workbooks` each get a named setter so callers\n * never hand-roll a `.from(\"udt_workbooks\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Written by the import flow at creation (\"Imported from <file>\") and, since\n * the workbooks surface became agent-writable, by the `workbook_description`\n * write target on `/workbooks/[id]`.\n */\nexport async function updateWorkbookDescription(\n workbookId: string,\n description: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Soft delete — the workbook is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreWorkbook for undo.\n */\nexport async function deleteWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"delete\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a workbook this very flow just created and\n * failed to populate (see the import path in app/(core)/workbooks/page.tsx).\n * Never use this for a user-initiated delete: that is deleteWorkbook, which\n * tombstones and stays recoverable.\n */\nexport async function discardFailedWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"archive\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function restoreWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: null })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"restore\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/** Trash view: the caller's own archived workbooks (RLS decides what is readable). */\nexport async function listTrashedWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\nasync function currentSnapshotForCopy(\n workbookId: string,\n): Promise<ServiceResult<{ snapshot: unknown; label: string | null } | null>> {\n const read = getSheetsHost().readCurrentSnapshot;\n if (read) {\n try {\n const cur = await read(workbookId);\n return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : \"Could not read the current content to copy.\" };\n }\n }\n const latest = await getLatestSnapshot(workbookId);\n if (!latest.success) return latest;\n return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };\n}\n\n/**\n * An independent copy of a workbook: its own row in the original's organization\n * and project, with the CURRENT content copied over (the live room when people are co-editing). Editing the copy never\n * touches the original.\n */\nexport async function copyWorkbook(\n workbookId: string,\n name?: string,\n): Promise<ServiceResult<Workbook>> {\n const original = await getWorkbook(workbookId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return {\n success: false,\n error: \"This workbook has no organization and cannot be copied.\",\n };\n }\n const created = await createWorkbook({\n name: name ?? `Copy of ${row.workbook_name}`,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n });\n if (!created.success) return created;\n // The copy starts from the CURRENT content: the live room's cells when people are co-editing (the host's reader),\n // else the newest save. Typed-but-unsaved cells are part of what \"Make a copy\" copies.\n const source = await currentSnapshotForCopy(workbookId);\n if (!source.success) return source;\n if (source.data) {\n const saved = await saveSnapshot({\n workbookId: created.data.id,\n snapshot: source.data.snapshot,\n label: source.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n// ─── snapshots (workbook content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened workbook hydrates from. Returns\n * `data: null` (success path) when the workbook has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestSnapshot(\n workbookId: string,\n): Promise<ServiceResult<WorkbookSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .select(\"*\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as WorkbookSnapshot | null };\n}\n\nexport type SaveSnapshotArgs = {\n workbookId: string;\n snapshot: unknown; // opaque to us — editor library decides the shape\n label?: string | null;\n origin?: WorkbookSnapshotOrigin;\n};\n\nexport async function saveSnapshot(\n args: SaveSnapshotArgs,\n): Promise<ServiceResult<WorkbookSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n // A snapshot is a component of its workbook and carries the workbook's organization.\n const { data: workbook, error: workbookError } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"organization_id\")\n .eq(\"id\", args.workbookId)\n .single();\n if (workbookError) return { success: false, error: workbookError.message };\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .insert({\n organization_id: workbook.organization_id,\n workbook_id: args.workbookId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent workbook's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent workbook; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.workbookId);\n\n return { success: true, data: data as WorkbookSnapshot };\n}\n\nexport async function listSnapshots(\n workbookId: string,\n limit = 50,\n): Promise<ServiceResult<WorkbookSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, workbook_id, label, origin, created_by, created_at\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as WorkbookSnapshot[] };\n}\n"]}
|
|
@@ -154,6 +154,20 @@ async function saveDocumentSnapshot(args) {
|
|
|
154
154
|
await db().schema("workbench").from("udt_documents").update({ updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", args.documentId);
|
|
155
155
|
return { success: true, data };
|
|
156
156
|
}
|
|
157
|
+
async function currentSnapshotForCopy(documentId) {
|
|
158
|
+
const read = getDocsHost().readCurrentSnapshot;
|
|
159
|
+
if (read) {
|
|
160
|
+
try {
|
|
161
|
+
const cur = await read(documentId);
|
|
162
|
+
return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };
|
|
163
|
+
} catch (err) {
|
|
164
|
+
return { success: false, error: err instanceof Error ? err.message : "Could not read the current content to copy." };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const latest = await getLatestDocumentSnapshot(documentId);
|
|
168
|
+
if (!latest.success) return latest;
|
|
169
|
+
return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: _nullishCoalesce(latest.data.label, () => ( null)) } : null };
|
|
170
|
+
}
|
|
157
171
|
async function copyDocument(documentId, name) {
|
|
158
172
|
const original = await getDocument(documentId);
|
|
159
173
|
if (!original.success) return original;
|
|
@@ -169,13 +183,13 @@ async function copyDocument(documentId, name) {
|
|
|
169
183
|
isPublic: row.visibility === "public"
|
|
170
184
|
});
|
|
171
185
|
if (!created.success) return created;
|
|
172
|
-
const
|
|
173
|
-
if (!
|
|
174
|
-
if (
|
|
186
|
+
const source = await currentSnapshotForCopy(documentId);
|
|
187
|
+
if (!source.success) return source;
|
|
188
|
+
if (source.data) {
|
|
175
189
|
const saved = await saveDocumentSnapshot({
|
|
176
190
|
documentId: created.data.id,
|
|
177
|
-
snapshot:
|
|
178
|
-
label:
|
|
191
|
+
snapshot: source.data.snapshot,
|
|
192
|
+
label: source.data.label,
|
|
179
193
|
origin: "autosave"
|
|
180
194
|
});
|
|
181
195
|
if (!saved.success) return saved;
|
|
@@ -275,4 +289,4 @@ function ensureTextRuns(snapshot) {
|
|
|
275
289
|
|
|
276
290
|
|
|
277
291
|
exports.configureDocsHost = configureDocsHost; exports.getDocsHost = getDocsHost; exports.createDocument = createDocument; exports.listAccessibleDocuments = listAccessibleDocuments; exports.getDocument = getDocument; exports.renameDocument = renameDocument; exports.moveDocument = moveDocument; exports.updateDocumentDescription = updateDocumentDescription; exports.restoreDocument = restoreDocument; exports.discardFailedDocument = discardFailedDocument; exports.deleteDocument = deleteDocument; exports.getLatestDocumentSnapshot = getLatestDocumentSnapshot; exports.saveDocumentSnapshot = saveDocumentSnapshot; exports.copyDocument = copyDocument; exports.listTrashedDocuments = listTrashedDocuments; exports.listDocumentSnapshots = listDocumentSnapshots; exports.sanitizeUniverDocSnapshot = sanitizeUniverDocSnapshot;
|
|
278
|
-
//# sourceMappingURL=chunk-
|
|
292
|
+
//# sourceMappingURL=chunk-LHTG72LS.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-LHTG72LS.cjs","../src/docs/ports.ts","../src/docs/document-service.ts","../src/docs/sanitize-univer-doc-snapshot.ts"],"names":["error"],"mappings":"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","file":"/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-LHTG72LS.cjs","sourcesContent":[null,"/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(documentId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n","/**\n * Document service — typed wrappers for `udt_documents` + `udt_document_snapshots`.\n *\n * Cloud document editor backed by Univer's preset-docs-core. Same shape as\n * `workbook-service.ts` — metadata in `udt_documents`, content state in\n * append-only `udt_document_snapshots`. The editor hydrates from the LATEST\n * snapshot and writes a new snapshot per save (debounced on the client —\n * see DocumentEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - The open document (one model per id per tab: load, one save, realtime,\n * collab): features/documents/document-model/\n * - Component (a view of that model): features/documents/components/DocumentEditor\n *\n * Mirrors `workbook-service.ts`. If you're changing the shape of one, change\n * the other at the same time — see `features/data-tables/FEATURE.md`.\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { readAllRows, tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { DocumentRow, DocumentSnapshot, DocumentSnapshotOrigin } from \"../core\";\nimport { getDocsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getDocsHost().getSupabase();\n// ─── documents ───────────────────────────────────────────────────────────────\n\nexport type CreateDocumentArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the document itself, mirrors `udt_documents.source`. */\n source?: \"created\" | \"imported_docx\" | \"imported_md\" | \"imported_txt\" | \"linked_gdoc\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (DOCX / MD / TXT blob). Set on the\n * import flow so the lossless original is recoverable; FK is ON DELETE SET\n * NULL, so deleting the file just nulls the link — the document survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createDocument(\n args: CreateDocumentArgs,\n): Promise<ServiceResult<DocumentRow>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a document.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .insert({\n document_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; the legacy `is_public` boolean is derived from it by\n // the workbench._bridge_legacy_owner trigger, so writing both here would\n // be two authorities for one fact. A new document defaults to `internal`\n // — it is org work product, not an individual person's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function listAccessibleDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n // RLS handles owner / published-to-the-web / shared access. The library and\n // the pickers treat this list as COMPLETE (\"you have no such document\"), so\n // it pages past PostgREST's silent 1000-row cap (D190).\n try {\n const rows = await readAllRows<DocumentRow>(\n ({ from, to }) =>\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\", { count: \"exact\" })\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false })\n .order(\"id\", { ascending: true })\n .range(from, to)\n .returns<DocumentRow[]>(),\n { label: \"workbench.udt_documents accessible documents\" },\n );\n return { success: true, data: rows };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function getDocument(\n documentId: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .eq(\"id\", documentId)\n .is(\"deleted_at\", null)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n if (!data) {\n // A trashed or unreachable document is a state the person can act on,\n // never PostgREST's \"Cannot coerce the result to a single JSON object\".\n return {\n success: false,\n error:\n \"This document is in the trash or you no longer have access to it. Restore it from Trash, or ask its owner to share it again.\",\n };\n }\n return { success: true, data: data as DocumentRow };\n}\n\nexport async function renameDocument(\n documentId: string,\n name: string,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ document_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Move the document into a project (or out of one with `null`). Sibling of\n * `renameDocument`: the one named setter for `project_id`.\n */\nexport async function moveDocument(\n documentId: string,\n projectId: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Rewrite the document's description. Sibling of `renameDocument` — the two\n * human-authored fields on `udt_documents` each get a named setter so callers\n * never hand-roll a `.from(\"udt_documents\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Added when the documents surface became agent-writable: the\n * `document_description` write target on `/documents/[id]` is its caller, the\n * same way `updateWorkbookDescription` serves `workbook_description`. Keeping\n * the pair symmetric is this file's standing contract with `workbook-service`\n * (see the module header).\n */\nexport async function updateDocumentDescription(\n documentId: string,\n description: string | null,\n): Promise<ServiceResult<DocumentRow>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", documentId)\n .select(\"*\"),\n { action: \"update\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as DocumentRow };\n}\n\n/**\n * Soft delete — the document is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreDocument for undo. (aidream migration 0458.)\n */\nexport async function restoreDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: null })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"restore\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a document this very flow just created and\n * failed to populate. Never use for a user-initiated delete: that is\n * deleteDocument, which tombstones and stays recoverable.\n */\nexport async function discardFailedDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"archive\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function deleteDocument(\n documentId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", documentId)\n .select(\"id\"),\n { action: \"delete\", noun: \"document\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n// ─── snapshots (document content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened document hydrates from. Returns\n * `data: null` (success path) when the document has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestDocumentSnapshot(\n documentId: string,\n): Promise<ServiceResult<DocumentSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .select(\"*\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as DocumentSnapshot | null };\n}\n\nexport type SaveDocumentSnapshotArgs = {\n documentId: string;\n snapshot: unknown; // opaque to us — Univer IDocumentData decides the shape\n label?: string | null;\n origin?: DocumentSnapshotOrigin;\n};\n\nexport async function saveDocumentSnapshot(\n args: SaveDocumentSnapshotArgs,\n): Promise<ServiceResult<DocumentSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n .insert({\n document_id: args.documentId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent document's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent document; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.documentId);\n\n return { success: true, data: data as DocumentSnapshot };\n}\n\nasync function currentSnapshotForCopy(\n documentId: string,\n): Promise<ServiceResult<{ snapshot: unknown; label: string | null } | null>> {\n const read = getDocsHost().readCurrentSnapshot;\n if (read) {\n try {\n const cur = await read(documentId);\n return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : \"Could not read the current content to copy.\" };\n }\n }\n const latest = await getLatestDocumentSnapshot(documentId);\n if (!latest.success) return latest;\n return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };\n}\n\n/**\n * An independent copy of a document: its own row, with the CURRENT content copied over (the live room when people are co-editing), so editing the copy never\n * touches the original. The copy lives in the original's organization and project. Used by a board-template use.\n */\nexport async function copyDocument(\n documentId: string,\n name?: string,\n): Promise<ServiceResult<DocumentRow>> {\n const original = await getDocument(documentId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return { success: false, error: \"This document has no organization and cannot be copied.\" };\n }\n const created = await createDocument({\n name: name ?? row.document_name,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n isPublic: row.visibility === \"public\",\n });\n if (!created.success) return created;\n // The copy starts from the CURRENT content: the live room's text when people are co-editing (the host's reader),\n // else the newest save. Typed-but-unsaved text is part of what \"Make a copy\" copies.\n const source = await currentSnapshotForCopy(documentId);\n if (!source.success) return source;\n if (source.data) {\n const saved = await saveDocumentSnapshot({\n documentId: created.data.id,\n snapshot: source.data.snapshot,\n label: source.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n/** Trash view: the caller's own archived documents (RLS decides what is readable). */\nexport async function listTrashedDocuments(): Promise<\n ServiceResult<DocumentRow[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_documents\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentRow[] };\n}\n\nexport async function listDocumentSnapshots(\n documentId: string,\n limit = 50,\n): Promise<ServiceResult<DocumentSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_document_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, document_id, label, origin, created_by, created_at\")\n .eq(\"document_id\", documentId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as DocumentSnapshot[] };\n}\n","/**\n * sanitizeUniverDocSnapshot — defensive normalizer for Univer document\n * snapshots loaded from storage.\n *\n * WHY THIS EXISTS (loud recovery layer):\n * Univer's `NamedStyleType` is a NUMERIC enum (`HEADING_1 = 4`, `HEADING_2 = 5`,\n * …). Some snapshots in storage were produced by an external markdown→Univer\n * converter that wrote the *string* name (`\"HEADING_1\"`) into\n * `paragraphStyle.namedStyleType` instead of the numeric value. At render time\n * Univer does `HEADING_ICON_MAP[namedStyleType]` → `undefined` →\n * `icon.key` throws `Cannot read properties of undefined (reading 'key')` inside\n * the `<ParagraphMenu>` component the moment the cursor lands in a heading. That\n * uncaught error tears down Univer's React root, so the document loads and then\n * vanishes. See `features/data-tables/FEATURE.md`.\n *\n * This normalizer converts those string enum values back to numbers BEFORE the\n * snapshot reaches `createUniverDoc`. It is a recovery layer: when it fires it\n * means malformed data slipped past the writer, so it SCREAMS (console.warn)\n * with a count and the document id. The proper long-term fix is to make the\n * writer emit numeric enum values; until then this keeps the editor alive.\n *\n * Returns the SAME object (mutated in place) for ergonomic call sites, plus a\n * `fixed` count via the second return slot is intentionally avoided — callers\n * only need the sanitized snapshot; the warning is the signal.\n */\nimport { NamedStyleType } from \"@univerjs/core\";\nimport type { IDocumentData } from \"@univerjs/core\";\n\nimport {\n defaultDocumentPageStyle,\n isLegacySqueezedPageStyle,\n} from \"../core\";\n\n/**\n * Map of every string name that could appear in a legacy snapshot to its\n * canonical numeric `NamedStyleType`. Built from the enum itself so it stays in\n * lockstep with Univer (numeric enums expose name→value on string keys).\n */\nconst NAMED_STYLE_STRING_TO_NUMBER: Record<string, number> = Object.fromEntries(\n Object.entries(NamedStyleType)\n .filter(([key, val]) => typeof val === \"number\" && isNaN(Number(key)))\n .map(([key, val]) => [key, val as number]),\n);\n\n/**\n * Normalize a Univer document snapshot in place. Currently fixes string-valued\n * `paragraphStyle.namedStyleType` (the confirmed `<ParagraphMenu>` crash). New\n * classes of string-vs-enum corruption should be added here, not patched at the\n * call site.\n *\n * @param snapshot The snapshot about to be passed to `createUniverDoc`.\n * @param docId Document id, for the loud warning only.\n * @param opts.quiet The co-editing state hash applies the same repair to compare what a seat will hold\n * (`asLoadedDocsSnapshot`); the warning belongs to the load, not to every hash.\n * @returns the same snapshot reference (mutated).\n */\nexport function sanitizeUniverDocSnapshot(\n snapshot: Partial<IDocumentData>,\n docId?: string,\n opts: { quiet?: boolean } = {},\n): Partial<IDocumentData> {\n restorePageStyle(snapshot, docId, opts.quiet === true);\n ensureTextRuns(snapshot);\n\n const paragraphs = snapshot?.body?.paragraphs;\n if (!Array.isArray(paragraphs)) return snapshot;\n\n let fixed = 0;\n for (const paragraph of paragraphs) {\n const style = paragraph?.paragraphStyle as\n { namedStyleType?: unknown } | undefined;\n const value = style?.namedStyleType;\n if (typeof value === \"string\") {\n const numeric = NAMED_STYLE_STRING_TO_NUMBER[value];\n if (numeric !== undefined) {\n (style as { namedStyleType?: number }).namedStyleType = numeric;\n fixed += 1;\n } else {\n // Unknown string we can't map — drop it so Univer falls back to\n // NORMAL_TEXT rather than crashing on the lookup.\n delete (style as { namedStyleType?: unknown }).namedStyleType;\n fixed += 1;\n }\n }\n }\n\n if (fixed > 0 && opts.quiet !== true) {\n console.warn(\n `[data-tables] RECOVERY: sanitized ${fixed} string namedStyleType value(s) ` +\n `to numeric NamedStyleType in document snapshot${docId ? ` ${docId}` : \"\"}. ` +\n `The snapshot was written with the wrong enum encoding (string instead of ` +\n `number) and would have crashed Univer's <ParagraphMenu>. Fix the snapshot ` +\n `writer to emit numeric NamedStyleType values.`,\n );\n }\n\n return snapshot;\n}\n\n/**\n * Second recovery: a snapshot with no `documentStyle.pageSize` has no page box,\n * so Univer lays the body out unbounded — text never wraps and the docs\n * viewport reports no scrollable extent, which reads to the user as \"the\n * document won't scroll\". Snapshots written by agents (`origin='agent'`) and by\n * older converters reach storage with `documentStyle: {}`. Stamp the canonical\n * page geometry back on and SCREAM: the writer is the real bug.\n */\nfunction restorePageStyle(snapshot: Partial<IDocumentData>, docId?: string, quiet = false) {\n if (!snapshot || typeof snapshot !== \"object\") return;\n\n // THE SQUEEZED PAGE (2026-10-15): documents carried A4-at-72dpi geometry in Univer's pageless\n // flavour — a 415px text column with no paper. Move them to a real Letter page, unchanged text.\n // A document with no flavour at all is a paginated page too (Univer would otherwise pick pageless).\n const style = snapshot.documentStyle;\n if (style?.pageSize?.width && isLegacySqueezedPageStyle(style)) {\n const page = defaultDocumentPageStyle();\n snapshot.documentStyle = { ...style, ...page, defaultParagraphStyle: style.defaultParagraphStyle ?? page.defaultParagraphStyle } as typeof style;\n return;\n }\n if (style?.pageSize?.width) {\n if (!style.documentFlavor) {\n const page = defaultDocumentPageStyle();\n Object.assign(style, { documentFlavor: page.documentFlavor });\n if (page.defaultParagraphStyle) style.defaultParagraphStyle ??= page.defaultParagraphStyle;\n }\n return;\n }\n\n snapshot.documentStyle = {\n ...defaultDocumentPageStyle(),\n ...(snapshot.documentStyle ?? {}),\n pageSize: defaultDocumentPageStyle().pageSize,\n } as NonNullable<typeof snapshot.documentStyle>;\n\n if (quiet) return;\n console.warn(\n `[data-tables] RECOVERY: document snapshot${docId ? ` ${docId}` : \"\"} had no ` +\n `documentStyle.pageSize — restored the default Letter page geometry. Without a ` +\n `page box Univer lays the body out unbounded: text does not wrap and the ` +\n `viewport has no scrollable extent, so the document appears frozen. Fix the ` +\n `snapshot writer (agent/markdown converters must stamp ` +\n `DEFAULT_DOCUMENT_PAGE_STYLE).`,\n );\n}\n\n/**\n * A body with no `textRuns` array is a body Univer silently refuses styled text for: its text\n * insert (`insertTextRuns`) returns early when the target has none, so every bold, italic, code\n * and size run of pasted or agent-written markdown vanished (found 2026-10-16: `**notes**` pasted\n * into a blank document stayed plain). An empty array is the same document and accepts the runs.\n */\nfunction ensureTextRuns(snapshot: Partial<IDocumentData>) {\n const body = snapshot?.body;\n if (body && typeof body === \"object\" && !Array.isArray(body.textRuns)) body.textRuns = [];\n}\n"]}
|
|
@@ -130,6 +130,20 @@ async function listTrashedWorkbooks() {
|
|
|
130
130
|
if (error) return { success: false, error: error.message };
|
|
131
131
|
return { success: true, data: data ?? [] };
|
|
132
132
|
}
|
|
133
|
+
async function currentSnapshotForCopy(workbookId) {
|
|
134
|
+
const read = getSheetsHost().readCurrentSnapshot;
|
|
135
|
+
if (read) {
|
|
136
|
+
try {
|
|
137
|
+
const cur = await read(workbookId);
|
|
138
|
+
return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };
|
|
139
|
+
} catch (err) {
|
|
140
|
+
return { success: false, error: err instanceof Error ? err.message : "Could not read the current content to copy." };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const latest = await getLatestSnapshot(workbookId);
|
|
144
|
+
if (!latest.success) return latest;
|
|
145
|
+
return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };
|
|
146
|
+
}
|
|
133
147
|
async function copyWorkbook(workbookId, name) {
|
|
134
148
|
const original = await getWorkbook(workbookId);
|
|
135
149
|
if (!original.success) return original;
|
|
@@ -147,13 +161,13 @@ async function copyWorkbook(workbookId, name) {
|
|
|
147
161
|
projectId: row.project_id ?? null
|
|
148
162
|
});
|
|
149
163
|
if (!created.success) return created;
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
if (
|
|
164
|
+
const source = await currentSnapshotForCopy(workbookId);
|
|
165
|
+
if (!source.success) return source;
|
|
166
|
+
if (source.data) {
|
|
153
167
|
const saved = await saveSnapshot({
|
|
154
168
|
workbookId: created.data.id,
|
|
155
|
-
snapshot:
|
|
156
|
-
label:
|
|
169
|
+
snapshot: source.data.snapshot,
|
|
170
|
+
label: source.data.label,
|
|
157
171
|
origin: "autosave"
|
|
158
172
|
});
|
|
159
173
|
if (!saved.success) return saved;
|
|
@@ -206,4 +220,4 @@ export {
|
|
|
206
220
|
saveSnapshot,
|
|
207
221
|
listSnapshots
|
|
208
222
|
};
|
|
209
|
-
//# sourceMappingURL=chunk-
|
|
223
|
+
//# sourceMappingURL=chunk-RREOARR4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sheets/ports.ts","../src/sheets/workbook-service.ts"],"sourcesContent":["/**\n * The host ports of the Sheets model and io.\n *\n * The package owns the workbook service, the page-setup store and the import flow, but three things\n * belong to the app that mounts them: the database client (a package owns no client), the\n * organization a write acts in (the active-organization ladder is app state) and the file store that\n * keeps a lossless copy of an imported file. The host states them once at start-up with\n * `configureSheetsHost`. State sits on a `globalThis` slot so a dual-bundled copy of the package\n * still sees one host. An unconfigured port THROWS naming itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type SheetsSupabase = SupabaseClient<any, any, any>;\n\nexport interface SheetsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): SheetsSupabase;\n /** The organization a write acts in: the record's own when given, otherwise the active one. */\n ensureOrgId(organizationId: string | null): Promise<string>;\n /** Keep the original of an imported spreadsheet in the file store, in `folderPath`. */\n uploadOriginalFile(file: File, options: { folderPath: string }): Promise<{ fileId: string }>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(workbookId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.sheets-host\");\ntype Slot = { ports?: SheetsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureSheetsHost(ports: SheetsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getSheetsHost(): SheetsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/sheets: configureSheetsHost(ports) was not called before the workbook service ran.\");\n return ports;\n}\n","/**\n * Workbook service — typed wrappers for `udt_workbooks` + `udt_workbook_snapshots`.\n *\n * Workbooks are the lossless-spreadsheet surface (P4): metadata in\n * `udt_workbooks`, content state in append-only `udt_workbook_snapshots`. The\n * editor (Univer or equivalent) hydrates from the LATEST snapshot and writes\n * a new snapshot per save (debounced on the client — see WorkbookEditor).\n *\n * What lives elsewhere:\n * - Sharing / permissions: features/sharing/ + `has_permission(...)` RLS\n * - Realtime: @ai-matrx/office/univer/collab useWorkbookRealtime\n * - Component: the Sheets editor\n */\nimport { requireOrganizationContext } from \"@ai-matrx/api\";\nimport { getClaimsUser } from \"@ai-matrx/auth\";\nimport { tryWriteOne, writeOneRow } from \"@ai-matrx/data/db\";\nimport type { ServiceResult } from \"@ai-matrx/records/core\";\n\nimport type { Workbook, WorkbookSnapshot, WorkbookSnapshotOrigin } from \"../core/types\";\nimport { getSheetsHost } from \"./ports\";\n\n/** The app's database client, read through the host port at call time. */\nconst db = () => getSheetsHost().getSupabase();\n\n// ─── workbooks ────────────────────────────────────────────────────────────────\n\nconst WORKBOOK_SOURCE_LABELS: Record<string, string> = {\n created: \"Created\",\n imported_xlsx: \"Imported Excel\",\n imported_gsheet: \"Imported from Google Sheets\",\n imported_csv: \"Imported CSV\",\n linked_gsheet: \"Imported from Google Sheets\",\n};\n\n/** Honest, human label for `udt_workbooks.source`. */\nexport function workbookSourceLabel(source: string): string {\n return WORKBOOK_SOURCE_LABELS[source] ?? source.replace(/_/g, \" \");\n}\n\nexport type CreateWorkbookArgs = {\n name: string;\n description?: string | null;\n /** Origin label for the workbook itself, mirrors `udt_workbooks.source`. */\n source?:\n | \"created\"\n | \"imported_xlsx\"\n | \"imported_gsheet\"\n | \"imported_csv\"\n | \"linked_gsheet\";\n organizationId: string;\n projectId?: string | null;\n taskId?: string | null;\n isPublic?: boolean;\n /**\n * cld_files.id of the source upload (XLSX / CSV blob). Set on the import\n * flow so the lossless original is recoverable; FK is ON DELETE SET NULL,\n * so deleting the file just nulls the link — the workbook survives.\n */\n originalFileId?: string | null;\n};\n\nexport async function createWorkbook(\n args: CreateWorkbookArgs,\n): Promise<ServiceResult<Workbook>> {\n let organizationId: string;\n try {\n organizationId = requireOrganizationContext(undefined, args.organizationId);\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? error.message\n : \"Select an organization before creating a workbook.\",\n };\n }\n\n const { data: userData, error: userErr } = await getClaimsUser(db());\n if (userErr || !userData?.user) {\n return {\n success: false,\n error: userErr?.message ?? \"not authenticated\",\n };\n }\n\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .insert({\n workbook_name: args.name,\n description: args.description ?? null,\n source: args.source ?? \"created\",\n organization_id: organizationId,\n project_id: args.projectId ?? null,\n task_id: args.taskId ?? null,\n original_file_id: args.originalFileId ?? null,\n // CANONICAL columns (workbench_udt_canonical_step1). `visibility` is the\n // source of truth; legacy `is_public` is derived from it by the\n // workbench._bridge_legacy_owner trigger. A new workbook defaults to\n // `internal` — org work product, not an individual's private thing\n // (db-rules §6) — unless the caller explicitly asked for public.\n created_by: userData.user.id,\n visibility: args.isPublic ? \"public\" : \"internal\",\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function listAccessibleWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n // RLS handles owner / published-to-the-web / shared access.\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .is(\"deleted_at\", null)\n .order(\"updated_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\nexport async function getWorkbook(\n workbookId: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .eq(\"id\", workbookId)\n .is(\"deleted_at\", null)\n .single();\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\nexport async function renameWorkbook(\n workbookId: string,\n name: string,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ workbook_name: name, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Move the workbook into a project (or out of one with `null`). Sibling of\n * `renameWorkbook`: the one named setter for `project_id`.\n */\nexport async function moveWorkbook(\n workbookId: string,\n projectId: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ project_id: projectId, updated_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Rewrite the workbook's description. Sibling of `renameWorkbook` — the two\n * human-authored fields on `udt_workbooks` each get a named setter so callers\n * never hand-roll a `.from(\"udt_workbooks\").update(...)`. Pass `null` (or an\n * empty string) to clear it.\n *\n * Written by the import flow at creation (\"Imported from <file>\") and, since\n * the workbooks surface became agent-writable, by the `workbook_description`\n * write target on `/workbooks/[id]`.\n */\nexport async function updateWorkbookDescription(\n workbookId: string,\n description: string | null,\n): Promise<ServiceResult<Workbook>> {\n const { data, error } = await writeOneRow(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({\n description: description && description.length > 0 ? description : null,\n updated_at: new Date().toISOString(),\n })\n .eq(\"id\", workbookId)\n .select(\"*\"),\n { action: \"update\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: data as Workbook };\n}\n\n/**\n * Soft delete — the workbook is tombstoned, not destroyed, and its snapshots stay\n * with it. Every read path filters `deleted_at is null`. Pair with\n * restoreWorkbook for undo.\n */\nexport async function deleteWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"delete\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/**\n * Archive (delete means archive: never a hard delete) — only for rolling back a workbook this very flow just created and\n * failed to populate (see the import path in app/(core)/workbooks/page.tsx).\n * Never use this for a user-initiated delete: that is deleteWorkbook, which\n * tombstones and stays recoverable.\n */\nexport async function discardFailedWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: new Date().toISOString() })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"archive\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\nexport async function restoreWorkbook(\n workbookId: string,\n): Promise<ServiceResult<true>> {\n const { error } = await tryWriteOne(\n db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ deleted_at: null })\n .eq(\"id\", workbookId)\n .select(\"id\"),\n { action: \"restore\", noun: \"workbook\" },\n );\n if (error) return { success: false, error: error.message };\n return { success: true, data: true };\n}\n\n/** Trash view: the caller's own archived workbooks (RLS decides what is readable). */\nexport async function listTrashedWorkbooks(): Promise<\n ServiceResult<Workbook[]>\n> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"*\")\n .not(\"deleted_at\", \"is\", null)\n .order(\"deleted_at\", { ascending: false });\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as Workbook[] };\n}\n\nasync function currentSnapshotForCopy(\n workbookId: string,\n): Promise<ServiceResult<{ snapshot: unknown; label: string | null } | null>> {\n const read = getSheetsHost().readCurrentSnapshot;\n if (read) {\n try {\n const cur = await read(workbookId);\n return { success: true, data: cur.snapshot != null ? { snapshot: cur.snapshot, label: null } : null };\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : \"Could not read the current content to copy.\" };\n }\n }\n const latest = await getLatestSnapshot(workbookId);\n if (!latest.success) return latest;\n return { success: true, data: latest.data ? { snapshot: latest.data.snapshot, label: latest.data.label ?? null } : null };\n}\n\n/**\n * An independent copy of a workbook: its own row in the original's organization\n * and project, with the CURRENT content copied over (the live room when people are co-editing). Editing the copy never\n * touches the original.\n */\nexport async function copyWorkbook(\n workbookId: string,\n name?: string,\n): Promise<ServiceResult<Workbook>> {\n const original = await getWorkbook(workbookId);\n if (!original.success) return original;\n const row = original.data;\n if (!row.organization_id) {\n return {\n success: false,\n error: \"This workbook has no organization and cannot be copied.\",\n };\n }\n const created = await createWorkbook({\n name: name ?? `Copy of ${row.workbook_name}`,\n description: row.description ?? null,\n organizationId: row.organization_id,\n projectId: row.project_id ?? null,\n });\n if (!created.success) return created;\n // The copy starts from the CURRENT content: the live room's cells when people are co-editing (the host's reader),\n // else the newest save. Typed-but-unsaved cells are part of what \"Make a copy\" copies.\n const source = await currentSnapshotForCopy(workbookId);\n if (!source.success) return source;\n if (source.data) {\n const saved = await saveSnapshot({\n workbookId: created.data.id,\n snapshot: source.data.snapshot,\n label: source.data.label,\n origin: \"autosave\",\n });\n if (!saved.success) return saved;\n }\n return created;\n}\n\n// ─── snapshots (workbook content) ────────────────────────────────────────────\n\n/**\n * Latest-snapshot fetch — what an opened workbook hydrates from. Returns\n * `data: null` (success path) when the workbook has no snapshots yet (newly\n * created, never saved). Distinguish \"no snapshot\" from \"load error\" by\n * checking `result.data === null`.\n */\nexport async function getLatestSnapshot(\n workbookId: string,\n): Promise<ServiceResult<WorkbookSnapshot | null>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .select(\"*\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(1)\n .maybeSingle();\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? null) as WorkbookSnapshot | null };\n}\n\nexport type SaveSnapshotArgs = {\n workbookId: string;\n snapshot: unknown; // opaque to us — editor library decides the shape\n label?: string | null;\n origin?: WorkbookSnapshotOrigin;\n};\n\nexport async function saveSnapshot(\n args: SaveSnapshotArgs,\n): Promise<ServiceResult<WorkbookSnapshot>> {\n const { data: userData } = await getClaimsUser(db());\n // A snapshot is a component of its workbook and carries the workbook's organization.\n const { data: workbook, error: workbookError } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .select(\"organization_id\")\n .eq(\"id\", args.workbookId)\n .single();\n if (workbookError) return { success: false, error: workbookError.message };\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n .insert({\n organization_id: workbook.organization_id,\n workbook_id: args.workbookId,\n snapshot: args.snapshot as never,\n label: args.label ?? null,\n origin: args.origin ?? \"autosave\",\n created_by: userData?.user?.id ?? null,\n })\n .select(\"*\")\n .single();\n if (error) return { success: false, error: error.message };\n\n // Touch the parent workbook's updated_at so list views can sort by recency\n // without scanning snapshots. Best-effort — failure here is harmless.\n // write-lands-exempt: best-effort recency stamp on the parent workbook; the snapshot insert above is the real write\n await db()\n .schema(\"workbench\")\n .from(\"udt_workbooks\")\n .update({ updated_at: new Date().toISOString() })\n .eq(\"id\", args.workbookId);\n\n return { success: true, data: data as WorkbookSnapshot };\n}\n\nexport async function listSnapshots(\n workbookId: string,\n limit = 50,\n): Promise<ServiceResult<WorkbookSnapshot[]>> {\n const { data, error } = await db()\n .schema(\"workbench\")\n .from(\"udt_workbook_snapshots\")\n // component-created-by-ok: append-only snapshot with NO updated_by column and NO parent-rewrite trigger — created_by is the author the client wrote at insert (the only person field this table has)\n .select(\"id, workbook_id, label, origin, created_by, created_at\")\n .eq(\"workbook_id\", workbookId)\n .order(\"created_at\", { ascending: false })\n .limit(limit);\n if (error) return { success: false, error: error.message };\n return { success: true, data: (data ?? []) as WorkbookSnapshot[] };\n}\n"],"mappings":"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","names":["error"]}
|
package/dist/docs-host.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/docs/ports.ts"],"sourcesContent":["/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../src/docs/ports.ts"],"sourcesContent":["/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(documentId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BA,IAAM,OAAO,uBAAO,IAAI,2BAA2B;AAEnD,IAAM,OAAO,MAAY;AACvB,QAAM,IAAI;AACV,SAAQ,EAAE,IAAI,MAAM,CAAC;AACvB;AAEO,SAAS,kBAAkB,OAA4B;AAC5D,OAAK,EAAE,QAAQ;AACjB;AAEO,SAAS,cAA6B;AAC3C,QAAM,QAAQ,KAAK,EAAE;AACrB,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iGAAiG;AAC7H,SAAO;AACT;","names":[]}
|
package/dist/docs-host.d.cts
CHANGED
|
@@ -21,6 +21,14 @@ interface DocsHostPorts {
|
|
|
21
21
|
method: "POST";
|
|
22
22
|
body: FormData;
|
|
23
23
|
}): Promise<Response>;
|
|
24
|
+
/**
|
|
25
|
+
* The record's CURRENT content, including what people are typing in a live co-editing room and have not saved
|
|
26
|
+
* (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and
|
|
27
|
+
* a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.
|
|
28
|
+
*/
|
|
29
|
+
readCurrentSnapshot?(documentId: string): Promise<{
|
|
30
|
+
snapshot: unknown | null;
|
|
31
|
+
}>;
|
|
24
32
|
}
|
|
25
33
|
declare function configureDocsHost(ports: DocsHostPorts): void;
|
|
26
34
|
declare function getDocsHost(): DocsHostPorts;
|
package/dist/docs-host.d.ts
CHANGED
|
@@ -21,6 +21,14 @@ interface DocsHostPorts {
|
|
|
21
21
|
method: "POST";
|
|
22
22
|
body: FormData;
|
|
23
23
|
}): Promise<Response>;
|
|
24
|
+
/**
|
|
25
|
+
* The record's CURRENT content, including what people are typing in a live co-editing room and have not saved
|
|
26
|
+
* (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and
|
|
27
|
+
* a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.
|
|
28
|
+
*/
|
|
29
|
+
readCurrentSnapshot?(documentId: string): Promise<{
|
|
30
|
+
snapshot: unknown | null;
|
|
31
|
+
}>;
|
|
24
32
|
}
|
|
25
33
|
declare function configureDocsHost(ports: DocsHostPorts): void;
|
|
26
34
|
declare function getDocsHost(): DocsHostPorts;
|
package/dist/docs-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/docs/ports.ts"],"sourcesContent":["/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/docs/ports.ts"],"sourcesContent":["/**\n * The host ports of the Docs model and io.\n *\n * The package owns the document service, the open-document model and the converters, but two things\n * belong to the app that mounts them: the database client (a package owns no client) and the server\n * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).\n * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot\n * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming\n * itself (nothing fails silently).\n */\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\n\n/** A Supabase client over any schema: the package cannot import the app's generated database types. */\nexport type DocsSupabase = SupabaseClient<any, any, any>;\n\nexport interface DocsHostPorts {\n /** The app's database client (signed in as the person). */\n getSupabase(): DocsSupabase;\n /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */\n requestRaw(path: string, init: { method: \"POST\"; body: FormData }): Promise<Response>;\n /**\n * The record's CURRENT content, including what people are typing in a live co-editing room and have not saved\n * (the app folds the room; the package owns no server). Optional: a host without co-editing leaves it out and\n * a copy takes the newest saved snapshot. It may throw; the copy then fails with its message, never silently.\n */\n readCurrentSnapshot?(documentId: string): Promise<{ snapshot: unknown | null }>;\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.docs-host\");\ntype Slot = { ports?: DocsHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureDocsHost(ports: DocsHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getDocsHost(): DocsHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.\");\n return ports;\n}\n"],"mappings":";AA4BA,IAAM,OAAO,uBAAO,IAAI,2BAA2B;AAEnD,IAAM,OAAO,MAAY;AACvB,QAAM,IAAI;AACV,SAAQ,EAAE,IAAI,MAAM,CAAC;AACvB;AAEO,SAAS,kBAAkB,OAA4B;AAC5D,OAAK,EAAE,QAAQ;AACjB;AAEO,SAAS,cAA6B;AAC3C,QAAM,QAAQ,KAAK,EAAE;AACrB,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iGAAiG;AAC7H,SAAO;AACT;","names":[]}
|
package/dist/docs-io.cjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkLHTG72LScjs = require('./chunk-LHTG72LS.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
@@ -419,13 +419,13 @@ async function documentFileToMarkdown(file) {
|
|
|
419
419
|
async function importDocumentFile(file, organizationId) {
|
|
420
420
|
const { markdown, source } = await documentFileToMarkdown(file);
|
|
421
421
|
const name = file.name.replace(/\.[^.]+$/, "").trim() || _chunkXAIKXHHJcjs.deriveDocumentName.call(void 0, markdown);
|
|
422
|
-
const created = await
|
|
422
|
+
const created = await _chunkLHTG72LScjs.createDocument.call(void 0, { name, source, organizationId, description: `Imported from ${file.name}` });
|
|
423
423
|
if (!created.success) throw new Error(`Could not create the document: ${created.error}`);
|
|
424
424
|
const id = created.data.id;
|
|
425
|
-
const snapshot =
|
|
426
|
-
const saved = await
|
|
425
|
+
const snapshot = _chunkLHTG72LScjs.sanitizeUniverDocSnapshot.call(void 0, _chunkXAIKXHHJcjs.markdownToUniverDoc.call(void 0, markdown, name), id);
|
|
426
|
+
const saved = await _chunkLHTG72LScjs.saveDocumentSnapshot.call(void 0, { documentId: id, snapshot, origin: "imported", label: `Imported from ${file.name}` });
|
|
427
427
|
if (!saved.success) {
|
|
428
|
-
await
|
|
428
|
+
await _chunkLHTG72LScjs.deleteDocument.call(void 0, id);
|
|
429
429
|
throw new Error(`Could not save the imported content: ${saved.error}`);
|
|
430
430
|
}
|
|
431
431
|
return { id, name };
|
|
@@ -467,7 +467,7 @@ async function downloadOpenFormat(markdown, format, title) {
|
|
|
467
467
|
const form = new FormData();
|
|
468
468
|
form.append("file", new Blob([docx]), fileName.endsWith(".docx") ? fileName : `${fileName}.docx`);
|
|
469
469
|
form.append("target", target);
|
|
470
|
-
const res = await
|
|
470
|
+
const res = await _chunkLHTG72LScjs.getDocsHost.call(void 0, ).requestRaw("/office/convert-document", { method: "POST", body: form });
|
|
471
471
|
return new Uint8Array(await res.arrayBuffer());
|
|
472
472
|
},
|
|
473
473
|
save: (fileName, bytes, mime) => {
|