@ai-matrx/office 0.4.0 → 0.5.3

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/chunk-2UBGQUXW.cjs +37 -0
  3. package/dist/chunk-2UBGQUXW.cjs.map +1 -0
  4. package/dist/chunk-BWMAYLW4.cjs +272 -0
  5. package/dist/chunk-BWMAYLW4.cjs.map +1 -0
  6. package/dist/chunk-IDEA5UXK.js +272 -0
  7. package/dist/chunk-IDEA5UXK.js.map +1 -0
  8. package/dist/chunk-MPKXXZZV.js +37 -0
  9. package/dist/chunk-MPKXXZZV.js.map +1 -0
  10. package/dist/chunk-O6FTSXHE.cjs +463 -0
  11. package/dist/chunk-O6FTSXHE.cjs.map +1 -0
  12. package/dist/chunk-PI473GES.js +463 -0
  13. package/dist/chunk-PI473GES.js.map +1 -0
  14. package/dist/chunk-QZE7HBZB.cjs.map +1 -1
  15. package/dist/chunk-ZDZCCOUB.cjs.map +1 -1
  16. package/dist/docs-host.cjs +40 -0
  17. package/dist/docs-host.cjs.map +1 -0
  18. package/dist/docs-host.d.cts +28 -0
  19. package/dist/docs-host.d.ts +28 -0
  20. package/dist/docs-host.js +19 -0
  21. package/dist/docs-host.js.map +1 -0
  22. package/dist/docs-io.cjs +496 -0
  23. package/dist/docs-io.cjs.map +1 -0
  24. package/dist/docs-io.d.cts +147 -0
  25. package/dist/docs-io.d.ts +147 -0
  26. package/dist/docs-io.js +496 -0
  27. package/dist/docs-io.js.map +1 -0
  28. package/dist/docs-tools.cjs +217 -0
  29. package/dist/docs-tools.cjs.map +1 -0
  30. package/dist/docs-tools.d.cts +150 -0
  31. package/dist/docs-tools.d.ts +150 -0
  32. package/dist/docs-tools.js +217 -0
  33. package/dist/docs-tools.js.map +1 -0
  34. package/dist/docs.cjs +657 -0
  35. package/dist/docs.cjs.map +1 -0
  36. package/dist/docs.d.cts +582 -0
  37. package/dist/docs.d.ts +582 -0
  38. package/dist/docs.js +657 -0
  39. package/dist/docs.js.map +1 -0
  40. package/dist/matrxImagePorts-JDFYE4QI.cjs.map +1 -1
  41. package/dist/sheets-xlsx.cjs.map +1 -1
  42. package/dist/sheets.cjs.map +1 -1
  43. package/dist/univer-collab.cjs +3 -0
  44. package/dist/univer-collab.cjs.map +1 -1
  45. package/dist/univer-collab.d.cts +7 -0
  46. package/dist/univer-collab.d.ts +7 -0
  47. package/dist/univer-collab.js +3 -0
  48. package/dist/univer-collab.js.map +1 -1
  49. package/dist/xlsx-to-univer-AQAXU3TC.cjs.map +1 -1
  50. package/package.json +49 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-QZE7HBZB.cjs","../src/sheets/xlsx-to-univer.ts","../src/sheets/xlsx-to-univer-excel.ts","../src/sheets/xlsx-shared.ts"],"names":[],"mappings":"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","file":"/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-QZE7HBZB.cjs","sourcesContent":[null,"/**\n * xlsxToUniverWorkbook — parse a spreadsheet file into a Univer IWorkbookData\n * suitable for `apiRef.createWorkbook(...)` and for persistence as the initial\n * snapshot of a new workbook.\n *\n * ONE reader: ExcelJS (`xlsx-to-univer-excel`) holds styles, number formats,\n * widths, heights, frozen panes, merges, validation, conditional formatting,\n * filter range, notes, links and pictures. A file that is not already an\n * .xlsx (.xls, .ods, .csv, .tsv) is first re-written as an .xlsx by the\n * Alchemy workbook door — values, formulas and merges — and read by that same\n * reader, so there is no second import path to drift.\n */\n\nimport { readWorkbook } from \"@ai-matrx/alchemy/operate/read\";\nimport { writeWorkbookBytes } from \"@ai-matrx/alchemy/operate/formats/xlsx\";\nimport type { WorkbookJson } from \"@ai-matrx/alchemy/operate/read\";\nimport type { IWorkbookData } from \"@univerjs/core\";\nimport { importXlsxWithExcelJs, type XlsxImportOptions } from \"./xlsx-to-univer-excel\";\n\n/** A legacy or text spreadsheet as .xlsx bytes (values, formulas, merges). */\nasync function legacyToXlsxBytes(file: File): Promise<ArrayBuffer> {\n const wb = await readWorkbook(file, { dates: true, formulas: true });\n const json: WorkbookJson = {\n sheets: wb.sheets.map((ws) => {\n const range = ws.range ?? { s: { r: 0, c: 0 }, e: { r: -1, c: -1 } };\n const rows: WorkbookJson[\"sheets\"][number][\"rows\"] = [];\n for (let r = 0; r <= range.e.r; r++) {\n const row: WorkbookJson[\"sheets\"][number][\"rows\"][number] = [];\n for (let c = 0; c <= range.e.c; c++) {\n const cell = ws.cell(r, c);\n if (!cell || cell.v === undefined || cell.v === null) {\n row.push(null);\n continue;\n }\n const v = cell.v instanceof Date ? cell.v.toISOString().slice(0, 10) : cell.v;\n if (cell.f) row.push({ v: typeof v === \"boolean\" || typeof v === \"number\" ? v : String(v), f: cell.f.replace(/^=/, \"\") });\n else row.push(v);\n }\n rows.push(row);\n }\n return { name: ws.name.slice(0, 31) || \"Sheet1\", rows, merges: ws.merges };\n }),\n };\n const bytes = await writeWorkbookBytes(json);\n return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;\n}\n\n/**\n * Parse a spreadsheet file into a Univer workbook. Whatever could not be\n * carried is reported through `options.onDropped` (the caller tells the person).\n */\nexport async function xlsxToUniverWorkbook(\n file: File,\n options: XlsxImportOptions = {},\n): Promise<Partial<IWorkbookData>> {\n if (/\\.xlsx$/i.test(file.name)) return importXlsxWithExcelJs(file, options);\n const data = await legacyToXlsxBytes(file);\n return importXlsxWithExcelJs({ name: file.name, arrayBuffer: async () => data }, options);\n}\n","/**\n * Full-fidelity .xlsx -> Univer reader (ExcelJS). The inverse of\n * `univer-to-xlsx.ts`: styles, number formats, column widths, row heights,\n * frozen panes, merges, data validation, conditional formatting, the filter\n * range, notes, cell links and pictures. Free of Univer runtime imports (enums\n * are numbers) so it runs under tests as well as in the browser.\n */\n\nimport type { IWorkbookData } from \"@univerjs/core\";\nimport { loadExcelJs, type ExcelJSTypes } from \"@ai-matrx/print/xlsx-styled\";\nimport {\n H_ALIGN_IN,\n RESOURCE,\n V_ALIGN_IN,\n argbToColor,\n borderFromExcel,\n colCharsToPx,\n parseA1Range,\n rowPtToPx,\n writeResource,\n type RangeLike,\n type UniverResource,\n} from \"./xlsx-shared\";\n\nexport type XlsxImportOptions = {\n /** Stores a picture and returns its file id; without it pictures are reported, not imported. */\n uploadImage?: (bytes: Uint8Array, extension: string) => Promise<string>;\n /** Called once per thing the file held that could not be carried. */\n onDropped?: (what: string) => void;\n};\n\ntype Json = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Univer resource payloads are untyped JSON\n\nconst THEME = [\"FFFFFF\", \"000000\", \"E7E6E6\", \"44546A\", \"4472C4\", \"ED7D31\", \"A5A5A5\", \"FFC000\", \"5B9BD5\", \"70AD47\"];\nconst colorOf = (c: Partial<ExcelJSTypes.Color> | undefined): string | undefined =>\n c?.argb ? argbToColor(c.argb) : typeof c?.theme === \"number\" && THEME[c.theme] ? `#${THEME[c.theme]!.toLowerCase()}` : undefined;\n\nconst rid = (prefix: string) => `${prefix}${Math.random().toString(36).slice(2, 10)}`;\nconst sheetId = (name: string) => `${name.replace(/[^A-Za-z0-9_-]+/g, \"-\").slice(0, 32) || \"sheet\"}-${Math.random().toString(36).slice(2, 8)}`;\n\nexport async function importXlsxWithExcelJs(\n file: { name: string; arrayBuffer(): Promise<ArrayBuffer> },\n options: XlsxImportOptions = {},\n): Promise<Partial<IWorkbookData>> {\n const ExcelJS = await loadExcelJs();\n const wb = new ExcelJS.Workbook();\n await wb.xlsx.load(await file.arrayBuffer());\n\n const dropped = new Set<string>();\n const styles: Record<string, Json> = {};\n const styleIds = new Map<string, string>();\n const styleId = (st: Json): string => {\n const key = JSON.stringify(st);\n let id = styleIds.get(key);\n if (!id) {\n id = `s${styleIds.size + 1}`;\n styleIds.set(key, id);\n styles[id] = st;\n }\n return id;\n };\n\n const sheets: Record<string, Json> = {};\n const sheetOrder: string[] = [];\n const resources: UniverResource[] = [];\n const validation: Json = {};\n const conditional: Json = {};\n const filters: Json = {};\n const notes: Json = {};\n const drawings: Json = {};\n const unitId = `wb-${rid(\"\")}`;\n\n for (const ws of wb.worksheets) {\n const id = sheetId(ws.name);\n sheetOrder.push(id);\n const cellData: Record<number, Record<number, Json>> = {};\n let maxR = 0;\n let maxC = 0;\n const sheetNotes: Json = {};\n\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\n row.eachCell({ includeEmpty: false }, (cell, colNumber) => {\n const r = rowNumber - 1;\n const c = colNumber - 1;\n const out = toCell(cell, styleId);\n if (out) {\n (cellData[r] ??= {})[c] = out;\n maxR = Math.max(maxR, r);\n maxC = Math.max(maxC, c);\n }\n const note = cell.note;\n const text = typeof note === \"string\" ? note : (note as Json | undefined)?.texts?.map((t: Json) => t.text).join(\"\");\n if (text) {\n ((sheetNotes[r] ??= {}) as Json)[c] = { id: rid(\"n\"), row: r, col: c, width: 160, height: 72, note: text, show: false };\n }\n });\n });\n if (Object.keys(sheetNotes).length) notes[id] = sheetNotes;\n\n const sheet: Json = {\n id,\n name: ws.name.slice(0, 31),\n cellData,\n rowCount: Math.max(maxR + 1, ws.rowCount, 100),\n columnCount: Math.max(maxC + 1, ws.columnCount, 26),\n };\n\n const tab = colorOf(ws.properties?.tabColor);\n if (tab) sheet.tabColor = tab;\n\n const merges = (ws.model as Json).merges as string[] | undefined;\n const mergeData = (merges ?? []).map((m) => parseA1Range(m)).filter((m): m is RangeLike => !!m);\n if (mergeData.length) {\n sheet.mergeData = mergeData;\n sheet.rowCount = Math.max(sheet.rowCount, ...mergeData.map((m) => m.endRow + 1));\n sheet.columnCount = Math.max(sheet.columnCount, ...mergeData.map((m) => m.endColumn + 1));\n }\n\n const columnData: Json = {};\n for (let c = 1; c <= Math.min(ws.columnCount, 2000); c++) {\n const col = ws.getColumn(c);\n if (typeof col.width === \"number\" || col.hidden) {\n columnData[c - 1] = {\n ...(typeof col.width === \"number\" ? { w: colCharsToPx(col.width) } : {}),\n ...(col.hidden ? { hd: 1 } : {}),\n };\n }\n }\n if (Object.keys(columnData).length) sheet.columnData = columnData;\n\n const rowData: Json = {};\n ws.eachRow({ includeEmpty: true }, (row, n) => {\n if (typeof row.height === \"number\" || row.hidden) {\n rowData[n - 1] = {\n ...(typeof row.height === \"number\" ? { h: rowPtToPx(row.height), hd: row.hidden ? 1 : 0 } : { hd: 1 }),\n };\n }\n });\n if (Object.keys(rowData).length) sheet.rowData = rowData;\n\n const view = ws.views?.[0] as Json | undefined;\n if (view?.state === \"frozen\" && (view.xSplit || view.ySplit)) {\n sheet.freeze = {\n xSplit: view.xSplit ?? 0,\n ySplit: view.ySplit ?? 0,\n startColumn: view.xSplit ?? 0,\n startRow: view.ySplit ?? 0,\n };\n }\n\n // ── data validation\n const dvModel = ((ws as Json).dataValidations as Json | undefined)?.model as Record<string, Json> | undefined;\n const rules = dataValidationRules(dvModel ?? {});\n if (rules.length) validation[id] = rules;\n\n // ── conditional formatting\n const cf = conditionalRules(((ws as Json).conditionalFormattings ?? []) as Json[], dropped);\n if (cf.length) conditional[id] = cf;\n\n // ── filter range\n const af = ws.autoFilter as ExcelJSTypes.AutoFilter | undefined;\n if (af) {\n const range =\n typeof af === \"string\"\n ? parseA1Range(af)\n : af.from && af.to\n ? {\n startRow: (af.from as Json).row - 1,\n startColumn: (af.from as Json).column - 1,\n endRow: (af.to as Json).row - 1,\n endColumn: (af.to as Json).column - 1,\n }\n : null;\n if (range) filters[id] = { ref: range, filterColumns: [] };\n }\n\n // ── pictures\n const images = ws.getImages();\n if (images.length) {\n if (!options.uploadImage) {\n dropped.add(\"Pictures in the file were not imported\");\n } else {\n const data: Record<string, Json> = {};\n const order: string[] = [];\n for (const img of images) {\n try {\n const media = wb.getImage(Number(img.imageId)) as Json;\n const bytes = new Uint8Array(media.buffer as ArrayBuffer);\n const fileId = await options.uploadImage(bytes, String(media.extension ?? \"png\"));\n const tl = img.range.tl as Json;\n const ext = (img.range as Json).ext as Json | undefined;\n const br = img.range.br as Json | undefined;\n const width = ext?.width ?? ((br?.nativeCol ?? tl.nativeCol + 3) - tl.nativeCol) * 88;\n const height = ext?.height ?? ((br?.nativeRow ?? tl.nativeRow + 6) - tl.nativeRow) * 24;\n const drawingId = rid(\"img\");\n const column = Math.floor(tl.nativeCol ?? tl.col);\n const rowIdx = Math.floor(tl.nativeRow ?? tl.row);\n data[drawingId] = {\n unitId,\n subUnitId: id,\n drawingId,\n drawingType: 0,\n imageSourceType: \"URL\",\n source: `matrx-file:${fileId}`,\n transform: { left: column * 88, top: rowIdx * 24, width, height, angle: 0 },\n sheetTransform: {\n from: { column, columnOffset: 0, row: rowIdx, rowOffset: 0 },\n to: { column: column + Math.max(1, Math.round(width / 88)), columnOffset: 0, row: rowIdx + Math.max(1, Math.round(height / 24)), rowOffset: 0 },\n },\n };\n order.push(drawingId);\n } catch {\n dropped.add(\"Some pictures could not be stored and were left out\");\n }\n }\n if (order.length) drawings[id] = { data, order };\n }\n }\n\n if ((ws.getTables?.() ?? []).length) dropped.add(\"Excel tables became plain ranges (their data and styling are kept)\");\n sheets[id] = sheet;\n }\n\n if (Object.keys(validation).length) writeResource(resources, RESOURCE.validation, validation);\n if (Object.keys(conditional).length) writeResource(resources, RESOURCE.conditional, conditional);\n if (Object.keys(filters).length) writeResource(resources, RESOURCE.filter, filters);\n if (Object.keys(notes).length) writeResource(resources, RESOURCE.note, notes);\n if (Object.keys(drawings).length) writeResource(resources, RESOURCE.drawing, drawings);\n\n for (const d of dropped) options.onDropped?.(d);\n\n return {\n id: unitId,\n sheetOrder,\n name: file.name.replace(/\\.[^.]+$/, \"\"),\n appVersion: \"1\",\n locale: \"enUS\" as IWorkbookData[\"locale\"],\n styles,\n sheets,\n resources,\n } as Partial<IWorkbookData>;\n}\n\nfunction toStyle(cell: ExcelJSTypes.Cell): Json | undefined {\n const st: Json = {};\n const f = cell.font;\n if (f) {\n if (f.name) st.ff = f.name;\n if (f.size) st.fs = f.size;\n if (f.bold) st.bl = 1;\n if (f.italic) st.it = 1;\n if (f.underline) st.ul = { s: 1 };\n if (f.strike) st.st = { s: 1 };\n const cl = colorOf(f.color);\n if (cl) st.cl = { rgb: cl };\n }\n const fill = cell.fill as Json | undefined;\n if (fill?.type === \"pattern\" && fill.pattern === \"solid\") {\n const bg = colorOf(fill.fgColor);\n if (bg) st.bg = { rgb: bg };\n }\n const al = cell.alignment;\n if (al) {\n if (al.horizontal && H_ALIGN_IN[al.horizontal]) st.ht = H_ALIGN_IN[al.horizontal];\n if (al.vertical && V_ALIGN_IN[al.vertical]) st.vt = V_ALIGN_IN[al.vertical];\n if (al.wrapText) st.tb = 3;\n }\n const bd = cell.border as Json | undefined;\n if (bd) {\n const out: Json = {};\n for (const [side, key] of [[\"top\", \"t\"], [\"bottom\", \"b\"], [\"left\", \"l\"], [\"right\", \"r\"]] as const) {\n const s = borderFromExcel(bd[side]?.style);\n if (s) out[key] = { s, cl: { rgb: colorOf(bd[side]?.color) ?? \"#000000\" } };\n }\n if (Object.keys(out).length) st.bd = out;\n }\n if (cell.numFmt && cell.numFmt !== \"General\") st.n = { pattern: cell.numFmt };\n return Object.keys(st).length ? st : undefined;\n}\n\nconst EXCEL_EPOCH_OFFSET_DAYS = 25569;\n\nfunction toCell(cell: ExcelJSTypes.Cell, styleId: (s: Json) => string): Json | null {\n const out: Json = {};\n let st = toStyle(cell);\n const v = cell.value as unknown;\n const setNumber = (n: number) => {\n out.v = n;\n out.t = 2;\n };\n const apply = (value: unknown) => {\n if (value instanceof Date) {\n setNumber(value.getTime() / 86_400_000 + EXCEL_EPOCH_OFFSET_DAYS);\n st = { ...(st ?? {}), n: (st?.n as Json | undefined) ?? { pattern: \"yyyy-mm-dd\" } };\n } else if (typeof value === \"number\") setNumber(value);\n else if (typeof value === \"boolean\") {\n out.v = value ? 1 : 0;\n out.t = 3;\n } else if (typeof value === \"string\") {\n out.v = value;\n out.t = 1;\n } else if (value && typeof value === \"object\" && \"error\" in (value as Json)) {\n out.v = String((value as Json).error);\n out.t = 1;\n }\n };\n if (v && typeof v === \"object\" && !(v instanceof Date)) {\n const o = v as Json;\n if (\"formula\" in o || \"sharedFormula\" in o) {\n const f = o.formula ?? o.sharedFormula;\n if (f) out.f = `=${String(f).replace(/^=/, \"\")}`;\n apply(o.result);\n } else if (Array.isArray(o.richText)) {\n apply(o.richText.map((r: Json) => r.text).join(\"\"));\n } else if (\"hyperlink\" in o) {\n const text = String(typeof o.text === \"object\" ? (o.text?.richText ?? []).map((r: Json) => r.text).join(\"\") : (o.text ?? o.hyperlink));\n out.v = text;\n out.t = 1;\n out.p = linkDoc(text, String(o.hyperlink));\n } else apply(o);\n } else {\n apply(v);\n }\n if (st) out.s = styleId(st);\n return out.v === undefined && out.f === undefined && !out.s ? null : out;\n}\n\nfunction linkDoc(text: string, url: string): Json {\n return {\n id: \"d\",\n documentStyle: {},\n body: {\n dataStream: `${text}\\r\\n`,\n textRuns: [],\n paragraphs: [{ startIndex: text.length }],\n customRanges: [\n { startIndex: 0, endIndex: Math.max(0, text.length - 1), rangeId: rid(\"link\"), rangeType: 0, properties: { url } },\n ],\n },\n };\n}\n\nfunction dataValidationRules(model: Record<string, Json>): Json[] {\n const groups = new Map<string, { rule: Json; cells: [number, number][] }>();\n for (const [ref, dv] of Object.entries(model)) {\n const pos = parseA1Range(ref);\n if (!pos) continue;\n const type = String(dv.type);\n const rule: Json = {\n allowBlank: dv.allowBlank !== false,\n showErrorMessage: dv.showErrorMessage !== false,\n ...(dv.error ? { error: dv.error } : {}),\n ...(dv.errorTitle ? { errorTitle: dv.errorTitle } : {}),\n ...(dv.prompt ? { prompt: dv.prompt, showInputMessage: true } : {}),\n };\n const f = (dv.formulae ?? []) as unknown[];\n if (type === \"list\") {\n const raw = String(f[0] ?? \"\");\n const literal = /^\"(.*)\"$/.exec(raw);\n Object.assign(rule, { type: \"list\", formula1: literal ? literal[1] : raw, formula2: \"\", showDropDown: true });\n } else if ([\"whole\", \"decimal\", \"date\", \"time\", \"textLength\"].includes(type)) {\n Object.assign(rule, { type, operator: dv.operator ?? \"between\", formula1: String(f[0] ?? \"\"), formula2: f[1] !== undefined ? String(f[1]) : \"\" });\n } else if (type === \"custom\") {\n Object.assign(rule, { type: \"custom\", formula1: String(f[0] ?? \"\") });\n } else continue;\n const key = JSON.stringify(rule);\n const g = groups.get(key) ?? { rule, cells: [] };\n g.cells.push([pos.startRow, pos.startColumn]);\n groups.set(key, g);\n }\n return [...groups.values()].map(({ rule, cells }) => ({ uid: rid(\"dv\"), ...rule, ranges: compressCells(cells) }));\n}\n\n/** Single cells -> the fewest vertical runs. */\nfunction compressCells(cells: [number, number][]): RangeLike[] {\n const sorted = [...cells].sort((a, b) => a[1] - b[1] || a[0] - b[0]);\n const out: RangeLike[] = [];\n for (const [r, c] of sorted) {\n const last = out[out.length - 1];\n if (last && last.startColumn === c && last.endColumn === c && last.endRow === r - 1) last.endRow = r;\n else out.push({ startRow: r, endRow: r, startColumn: c, endColumn: c });\n }\n return out;\n}\n\nfunction dxfToStyle(style: Json | undefined): Json {\n const out: Json = {};\n const fg = colorOf(style?.font?.color);\n if (fg) out.cl = { rgb: fg };\n if (style?.font?.bold) out.bl = 1;\n if (style?.font?.italic) out.it = 1;\n const bg = colorOf(style?.fill?.bgColor) ?? colorOf(style?.fill?.fgColor);\n if (bg) out.bg = { rgb: bg };\n return out;\n}\n\nfunction conditionalRules(formats: Json[], dropped: Set<string>): Json[] {\n const out: Json[] = [];\n for (const cf of formats) {\n const ranges = String(cf.ref ?? \"\").split(/\\s+/).map((r) => parseA1Range(r)).filter((r): r is RangeLike => !!r);\n if (!ranges.length) continue;\n for (const rule of (cf.rules ?? []) as Json[]) {\n let mapped: Json | null = null;\n const style = dxfToStyle(rule.style);\n if (rule.type === \"cellIs\") {\n const nums = ((rule.formulae ?? []) as unknown[]).map(Number);\n const between = rule.operator === \"between\" || rule.operator === \"notBetween\";\n mapped = { type: \"highlightCell\", subType: \"number\", operator: rule.operator, value: between ? nums.slice(0, 2) : nums[0], style };\n } else if (rule.type === \"containsText\") {\n mapped = { type: \"highlightCell\", subType: \"text\", operator: \"containsText\", value: String(rule.text ?? \"\"), style };\n } else if (rule.type === \"expression\") {\n mapped = { type: \"highlightCell\", subType: \"formula\", value: `=${String((rule.formulae ?? [])[0] ?? \"\")}`, style };\n } else if (rule.type === \"colorScale\") {\n mapped = {\n type: \"colorScale\",\n config: ((rule.cfvo ?? []) as Json[]).map((v, i) => ({\n index: i,\n color: colorOf(rule.color?.[i]) ?? \"#ffffff\",\n value: { type: v.type, ...(v.value !== undefined ? { value: v.value } : {}) },\n })),\n };\n } else if (rule.type === \"dataBar\") {\n const [min, max] = (rule.cfvo ?? []) as Json[];\n mapped = {\n type: \"dataBar\",\n isShowValue: true,\n config: {\n min: { type: min?.type ?? \"min\" },\n max: { type: max?.type ?? \"max\" },\n isGradient: rule.gradient !== false,\n positiveColor: colorOf(rule.color) ?? \"#638ec6\",\n nativeColor: \"#ff0000\",\n },\n };\n }\n if (!mapped) {\n dropped.add(\"Some conditional formats (icon sets, top/bottom, date rules) were not imported\");\n continue;\n }\n out.push({ cfId: rid(\"cf\"), ranges, stopIfTrue: Boolean(rule.stopIfTrue), rule: mapped });\n }\n }\n return out;\n}\n","/**\n * Shared vocabulary between the xlsx importer and exporter: how Univer's\n * style numbers, colours and units map to the xlsx file's.\n *\n * Univer enums are written as numbers here so these helpers stay free of any\n * Univer import (they run in tests and in both directions).\n */\n\nexport const RESOURCE = {\n validation: \"SHEET_DATA_VALIDATION_PLUGIN\",\n conditional: \"SHEET_CONDITIONAL_FORMATTING_PLUGIN\",\n filter: \"SHEET_FILTER_PLUGIN\",\n note: \"SHEET_NOTE_PLUGIN\",\n comments: \"SHEET_UNIVER_THREAD_COMMENT_PLUGIN\",\n drawing: \"SHEET_DRAWING_PLUGIN\",\n table: \"SHEET_TABLE_PLUGIN\",\n} as const;\n\nexport type UniverResource = { name: string; data: string };\n\nexport function readResource<T = unknown>(\n resources: readonly UniverResource[] | undefined,\n name: string,\n): T | undefined {\n const raw = resources?.find((r) => r.name === name)?.data;\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n}\n\nexport function writeResource(resources: UniverResource[], name: string, value: unknown): void {\n const i = resources.findIndex((r) => r.name === name);\n const entry = { name, data: JSON.stringify(value) };\n if (i >= 0) resources[i] = entry;\n else resources.push(entry);\n}\n\n/** Excel column width (characters) <-> Univer pixels. */\nexport const colPxToChars = (px: number): number => Math.max(0, Math.round((px / 7) * 100) / 100);\nexport const colCharsToPx = (chars: number): number => Math.round(chars * 7);\n/** Excel row height (points) <-> Univer pixels. */\nexport const rowPxToPt = (px: number): number => Math.round(px * 0.75 * 100) / 100;\nexport const rowPtToPx = (pt: number): number => Math.round((pt / 0.75) * 100) / 100;\n\n/** Univer colour (\"#rrggbb\", \"rgb(r,g,b)\", \"rgba(...)\") -> ARGB hex, or undefined. */\nexport function colorToArgb(input: string | undefined | null): string | undefined {\n if (!input) return undefined;\n const s = input.trim();\n const hex = /^#?([0-9a-f]{6})$/i.exec(s);\n if (hex) return `FF${hex[1]!.toUpperCase()}`;\n const short = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(s);\n if (short) return `FF${short[1]}${short[1]}${short[2]}${short[2]}${short[3]}${short[3]}`.toUpperCase();\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i.exec(s);\n if (rgb) {\n const h = (n: string) => Number(n).toString(16).padStart(2, \"0\");\n return `FF${h(rgb[1]!)}${h(rgb[2]!)}${h(rgb[3]!)}`.toUpperCase();\n }\n return undefined;\n}\n\n/** ARGB (or RGB) hex from a file -> Univer \"#rrggbb\". */\nexport function argbToColor(argb: string | undefined | null): string | undefined {\n if (!argb) return undefined;\n const v = argb.replace(/^#/, \"\");\n if (v.length === 8) return `#${v.slice(2).toLowerCase()}`;\n if (v.length === 6) return `#${v.toLowerCase()}`;\n return undefined;\n}\n\n// Univer BorderStyleTypes number <-> ExcelJS border style name.\nconst BORDER_OUT: Record<number, string> = {\n 1: \"thin\", 2: \"hair\", 3: \"dotted\", 4: \"dashed\", 5: \"dashDot\", 6: \"dashDotDot\", 7: \"double\",\n 8: \"medium\", 9: \"mediumDashed\", 10: \"mediumDashDot\", 11: \"mediumDashDotDot\", 12: \"slantDashDot\", 13: \"thick\",\n};\nexport const borderToExcel = (n: number | undefined): string | undefined =>\n n === undefined ? undefined : BORDER_OUT[n];\nexport const borderFromExcel = (name: string | undefined): number | undefined => {\n if (!name) return undefined;\n const hit = Object.entries(BORDER_OUT).find(([, v]) => v === name);\n return hit ? Number(hit[0]) : undefined;\n};\n\nexport const H_ALIGN_OUT: Record<number, string> = { 1: \"left\", 2: \"center\", 3: \"right\", 4: \"justify\", 5: \"justify\", 6: \"distributed\" };\nexport const V_ALIGN_OUT: Record<number, string> = { 1: \"top\", 2: \"middle\", 3: \"bottom\" };\nexport const H_ALIGN_IN: Record<string, number> = { left: 1, center: 2, right: 3, justify: 4, fill: 1, centerContinuous: 2, distributed: 6 };\nexport const V_ALIGN_IN: Record<string, number> = { top: 1, middle: 2, bottom: 3, distributed: 2, justify: 2 };\n\n/** 0-based (row, col) -> \"A1\" (no $). */\nexport function a1(row: number, col: number): string {\n let n = col + 1;\n let letters = \"\";\n while (n > 0) {\n const m = (n - 1) % 26;\n letters = String.fromCharCode(65 + m) + letters;\n n = Math.floor((n - 1) / 26);\n }\n return `${letters}${row + 1}`;\n}\n\nexport type RangeLike = { startRow: number; endRow: number; startColumn: number; endColumn: number };\nexport const rangeToA1 = (r: RangeLike): string =>\n r.startRow === r.endRow && r.startColumn === r.endColumn\n ? a1(r.startRow, r.startColumn)\n : `${a1(r.startRow, r.startColumn)}:${a1(r.endRow, r.endColumn)}`;\n\n/** \"A1\" or \"A1:C5\" -> range (0-based), or null. */\nexport function parseA1Range(ref: string): RangeLike | null {\n const m = /^\\$?([A-Z]+)\\$?(\\d+)(?::\\$?([A-Z]+)\\$?(\\d+))?$/i.exec(ref.trim());\n if (!m) return null;\n const col = (s: string) => [...s.toUpperCase()].reduce((acc, ch) => acc * 26 + ch.charCodeAt(0) - 64, 0) - 1;\n const sc = col(m[1]!);\n const sr = Number(m[2]!) - 1;\n return { startRow: sr, startColumn: sc, endRow: m[4] ? Number(m[4]) - 1 : sr, endColumn: m[3] ? col(m[3]) : sc };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/_work/aidream/aidream/apps/shared/office/dist/chunk-QZE7HBZB.cjs","../src/sheets/xlsx-to-univer.ts","../src/sheets/xlsx-to-univer-excel.ts","../src/sheets/xlsx-shared.ts"],"names":[],"mappings":"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","file":"/home/runner/_work/aidream/aidream/apps/shared/office/dist/chunk-QZE7HBZB.cjs","sourcesContent":[null,"/**\n * xlsxToUniverWorkbook — parse a spreadsheet file into a Univer IWorkbookData\n * suitable for `apiRef.createWorkbook(...)` and for persistence as the initial\n * snapshot of a new workbook.\n *\n * ONE reader: ExcelJS (`xlsx-to-univer-excel`) holds styles, number formats,\n * widths, heights, frozen panes, merges, validation, conditional formatting,\n * filter range, notes, links and pictures. A file that is not already an\n * .xlsx (.xls, .ods, .csv, .tsv) is first re-written as an .xlsx by the\n * Alchemy workbook door — values, formulas and merges — and read by that same\n * reader, so there is no second import path to drift.\n */\n\nimport { readWorkbook } from \"@ai-matrx/alchemy/operate/read\";\nimport { writeWorkbookBytes } from \"@ai-matrx/alchemy/operate/formats/xlsx\";\nimport type { WorkbookJson } from \"@ai-matrx/alchemy/operate/read\";\nimport type { IWorkbookData } from \"@univerjs/core\";\nimport { importXlsxWithExcelJs, type XlsxImportOptions } from \"./xlsx-to-univer-excel\";\n\n/** A legacy or text spreadsheet as .xlsx bytes (values, formulas, merges). */\nasync function legacyToXlsxBytes(file: File): Promise<ArrayBuffer> {\n const wb = await readWorkbook(file, { dates: true, formulas: true });\n const json: WorkbookJson = {\n sheets: wb.sheets.map((ws) => {\n const range = ws.range ?? { s: { r: 0, c: 0 }, e: { r: -1, c: -1 } };\n const rows: WorkbookJson[\"sheets\"][number][\"rows\"] = [];\n for (let r = 0; r <= range.e.r; r++) {\n const row: WorkbookJson[\"sheets\"][number][\"rows\"][number] = [];\n for (let c = 0; c <= range.e.c; c++) {\n const cell = ws.cell(r, c);\n if (!cell || cell.v === undefined || cell.v === null) {\n row.push(null);\n continue;\n }\n const v = cell.v instanceof Date ? cell.v.toISOString().slice(0, 10) : cell.v;\n if (cell.f) row.push({ v: typeof v === \"boolean\" || typeof v === \"number\" ? v : String(v), f: cell.f.replace(/^=/, \"\") });\n else row.push(v);\n }\n rows.push(row);\n }\n return { name: ws.name.slice(0, 31) || \"Sheet1\", rows, merges: ws.merges };\n }),\n };\n const bytes = await writeWorkbookBytes(json);\n return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;\n}\n\n/**\n * Parse a spreadsheet file into a Univer workbook. Whatever could not be\n * carried is reported through `options.onDropped` (the caller tells the person).\n */\nexport async function xlsxToUniverWorkbook(\n file: File,\n options: XlsxImportOptions = {},\n): Promise<Partial<IWorkbookData>> {\n if (/\\.xlsx$/i.test(file.name)) return importXlsxWithExcelJs(file, options);\n const data = await legacyToXlsxBytes(file);\n return importXlsxWithExcelJs({ name: file.name, arrayBuffer: async () => data }, options);\n}\n","/**\n * Full-fidelity .xlsx -> Univer reader (ExcelJS). The inverse of\n * `univer-to-xlsx.ts`: styles, number formats, column widths, row heights,\n * frozen panes, merges, data validation, conditional formatting, the filter\n * range, notes, cell links and pictures. Free of Univer runtime imports (enums\n * are numbers) so it runs under tests as well as in the browser.\n */\n\nimport type { IWorkbookData } from \"@univerjs/core\";\nimport { loadExcelJs, type ExcelJSTypes } from \"@ai-matrx/print/xlsx-styled\";\nimport {\n H_ALIGN_IN,\n RESOURCE,\n V_ALIGN_IN,\n argbToColor,\n borderFromExcel,\n colCharsToPx,\n parseA1Range,\n rowPtToPx,\n writeResource,\n type RangeLike,\n type UniverResource,\n} from \"./xlsx-shared\";\n\nexport type XlsxImportOptions = {\n /** Stores a picture and returns its file id; without it pictures are reported, not imported. */\n uploadImage?: (bytes: Uint8Array, extension: string) => Promise<string>;\n /** Called once per thing the file held that could not be carried. */\n onDropped?: (what: string) => void;\n};\n\ntype Json = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any -- Univer resource payloads are untyped JSON\n\nconst THEME = [\"FFFFFF\", \"000000\", \"E7E6E6\", \"44546A\", \"4472C4\", \"ED7D31\", \"A5A5A5\", \"FFC000\", \"5B9BD5\", \"70AD47\"];\nconst colorOf = (c: Partial<ExcelJSTypes.Color> | undefined): string | undefined =>\n c?.argb ? argbToColor(c.argb) : typeof c?.theme === \"number\" && THEME[c.theme] ? `#${THEME[c.theme]!.toLowerCase()}` : undefined;\n\nconst rid = (prefix: string) => `${prefix}${Math.random().toString(36).slice(2, 10)}`;\nconst sheetId = (name: string) => `${name.replace(/[^A-Za-z0-9_-]+/g, \"-\").slice(0, 32) || \"sheet\"}-${Math.random().toString(36).slice(2, 8)}`;\n\nexport async function importXlsxWithExcelJs(\n file: { name: string; arrayBuffer(): Promise<ArrayBuffer> },\n options: XlsxImportOptions = {},\n): Promise<Partial<IWorkbookData>> {\n const ExcelJS = await loadExcelJs();\n const wb = new ExcelJS.Workbook();\n await wb.xlsx.load(await file.arrayBuffer());\n\n const dropped = new Set<string>();\n const styles: Record<string, Json> = {};\n const styleIds = new Map<string, string>();\n const styleId = (st: Json): string => {\n const key = JSON.stringify(st);\n let id = styleIds.get(key);\n if (!id) {\n id = `s${styleIds.size + 1}`;\n styleIds.set(key, id);\n styles[id] = st;\n }\n return id;\n };\n\n const sheets: Record<string, Json> = {};\n const sheetOrder: string[] = [];\n const resources: UniverResource[] = [];\n const validation: Json = {};\n const conditional: Json = {};\n const filters: Json = {};\n const notes: Json = {};\n const drawings: Json = {};\n const unitId = `wb-${rid(\"\")}`;\n\n for (const ws of wb.worksheets) {\n const id = sheetId(ws.name);\n sheetOrder.push(id);\n const cellData: Record<number, Record<number, Json>> = {};\n let maxR = 0;\n let maxC = 0;\n const sheetNotes: Json = {};\n\n ws.eachRow({ includeEmpty: false }, (row, rowNumber) => {\n row.eachCell({ includeEmpty: false }, (cell, colNumber) => {\n const r = rowNumber - 1;\n const c = colNumber - 1;\n const out = toCell(cell, styleId);\n if (out) {\n (cellData[r] ??= {})[c] = out;\n maxR = Math.max(maxR, r);\n maxC = Math.max(maxC, c);\n }\n const note = cell.note;\n const text = typeof note === \"string\" ? note : (note as Json | undefined)?.texts?.map((t: Json) => t.text).join(\"\");\n if (text) {\n ((sheetNotes[r] ??= {}) as Json)[c] = { id: rid(\"n\"), row: r, col: c, width: 160, height: 72, note: text, show: false };\n }\n });\n });\n if (Object.keys(sheetNotes).length) notes[id] = sheetNotes;\n\n const sheet: Json = {\n id,\n name: ws.name.slice(0, 31),\n cellData,\n rowCount: Math.max(maxR + 1, ws.rowCount, 100),\n columnCount: Math.max(maxC + 1, ws.columnCount, 26),\n };\n\n const tab = colorOf(ws.properties?.tabColor);\n if (tab) sheet.tabColor = tab;\n\n const merges = (ws.model as Json).merges as string[] | undefined;\n const mergeData = (merges ?? []).map((m) => parseA1Range(m)).filter((m): m is RangeLike => !!m);\n if (mergeData.length) {\n sheet.mergeData = mergeData;\n sheet.rowCount = Math.max(sheet.rowCount, ...mergeData.map((m) => m.endRow + 1));\n sheet.columnCount = Math.max(sheet.columnCount, ...mergeData.map((m) => m.endColumn + 1));\n }\n\n const columnData: Json = {};\n for (let c = 1; c <= Math.min(ws.columnCount, 2000); c++) {\n const col = ws.getColumn(c);\n if (typeof col.width === \"number\" || col.hidden) {\n columnData[c - 1] = {\n ...(typeof col.width === \"number\" ? { w: colCharsToPx(col.width) } : {}),\n ...(col.hidden ? { hd: 1 } : {}),\n };\n }\n }\n if (Object.keys(columnData).length) sheet.columnData = columnData;\n\n const rowData: Json = {};\n ws.eachRow({ includeEmpty: true }, (row, n) => {\n if (typeof row.height === \"number\" || row.hidden) {\n rowData[n - 1] = {\n ...(typeof row.height === \"number\" ? { h: rowPtToPx(row.height), hd: row.hidden ? 1 : 0 } : { hd: 1 }),\n };\n }\n });\n if (Object.keys(rowData).length) sheet.rowData = rowData;\n\n const view = ws.views?.[0] as Json | undefined;\n if (view?.state === \"frozen\" && (view.xSplit || view.ySplit)) {\n sheet.freeze = {\n xSplit: view.xSplit ?? 0,\n ySplit: view.ySplit ?? 0,\n startColumn: view.xSplit ?? 0,\n startRow: view.ySplit ?? 0,\n };\n }\n\n // ── data validation\n const dvModel = ((ws as Json).dataValidations as Json | undefined)?.model as Record<string, Json> | undefined;\n const rules = dataValidationRules(dvModel ?? {});\n if (rules.length) validation[id] = rules;\n\n // ── conditional formatting\n const cf = conditionalRules(((ws as Json).conditionalFormattings ?? []) as Json[], dropped);\n if (cf.length) conditional[id] = cf;\n\n // ── filter range\n const af = ws.autoFilter as ExcelJSTypes.AutoFilter | undefined;\n if (af) {\n const range =\n typeof af === \"string\"\n ? parseA1Range(af)\n : af.from && af.to\n ? {\n startRow: (af.from as Json).row - 1,\n startColumn: (af.from as Json).column - 1,\n endRow: (af.to as Json).row - 1,\n endColumn: (af.to as Json).column - 1,\n }\n : null;\n if (range) filters[id] = { ref: range, filterColumns: [] };\n }\n\n // ── pictures\n const images = ws.getImages();\n if (images.length) {\n if (!options.uploadImage) {\n dropped.add(\"Pictures in the file were not imported\");\n } else {\n const data: Record<string, Json> = {};\n const order: string[] = [];\n for (const img of images) {\n try {\n const media = wb.getImage(Number(img.imageId)) as Json;\n const bytes = new Uint8Array(media.buffer as ArrayBuffer);\n const fileId = await options.uploadImage(bytes, String(media.extension ?? \"png\"));\n const tl = img.range.tl as Json;\n const ext = (img.range as Json).ext as Json | undefined;\n const br = img.range.br as Json | undefined;\n const width = ext?.width ?? ((br?.nativeCol ?? tl.nativeCol + 3) - tl.nativeCol) * 88;\n const height = ext?.height ?? ((br?.nativeRow ?? tl.nativeRow + 6) - tl.nativeRow) * 24;\n const drawingId = rid(\"img\");\n const column = Math.floor(tl.nativeCol ?? tl.col);\n const rowIdx = Math.floor(tl.nativeRow ?? tl.row);\n data[drawingId] = {\n unitId,\n subUnitId: id,\n drawingId,\n drawingType: 0,\n imageSourceType: \"URL\",\n source: `matrx-file:${fileId}`,\n transform: { left: column * 88, top: rowIdx * 24, width, height, angle: 0 },\n sheetTransform: {\n from: { column, columnOffset: 0, row: rowIdx, rowOffset: 0 },\n to: { column: column + Math.max(1, Math.round(width / 88)), columnOffset: 0, row: rowIdx + Math.max(1, Math.round(height / 24)), rowOffset: 0 },\n },\n };\n order.push(drawingId);\n } catch {\n dropped.add(\"Some pictures could not be stored and were left out\");\n }\n }\n if (order.length) drawings[id] = { data, order };\n }\n }\n\n if ((ws.getTables?.() ?? []).length) dropped.add(\"Excel tables became plain ranges (their data and styling are kept)\");\n sheets[id] = sheet;\n }\n\n if (Object.keys(validation).length) writeResource(resources, RESOURCE.validation, validation);\n if (Object.keys(conditional).length) writeResource(resources, RESOURCE.conditional, conditional);\n if (Object.keys(filters).length) writeResource(resources, RESOURCE.filter, filters);\n if (Object.keys(notes).length) writeResource(resources, RESOURCE.note, notes);\n if (Object.keys(drawings).length) writeResource(resources, RESOURCE.drawing, drawings);\n\n for (const d of dropped) options.onDropped?.(d);\n\n return {\n id: unitId,\n sheetOrder,\n name: file.name.replace(/\\.[^.]+$/, \"\"),\n appVersion: \"1\",\n locale: \"enUS\" as IWorkbookData[\"locale\"],\n styles,\n sheets,\n resources,\n } as Partial<IWorkbookData>;\n}\n\nfunction toStyle(cell: ExcelJSTypes.Cell): Json | undefined {\n const st: Json = {};\n const f = cell.font;\n if (f) {\n if (f.name) st.ff = f.name;\n if (f.size) st.fs = f.size;\n if (f.bold) st.bl = 1;\n if (f.italic) st.it = 1;\n if (f.underline) st.ul = { s: 1 };\n if (f.strike) st.st = { s: 1 };\n const cl = colorOf(f.color);\n if (cl) st.cl = { rgb: cl };\n }\n const fill = cell.fill as Json | undefined;\n if (fill?.type === \"pattern\" && fill.pattern === \"solid\") {\n const bg = colorOf(fill.fgColor);\n if (bg) st.bg = { rgb: bg };\n }\n const al = cell.alignment;\n if (al) {\n if (al.horizontal && H_ALIGN_IN[al.horizontal]) st.ht = H_ALIGN_IN[al.horizontal];\n if (al.vertical && V_ALIGN_IN[al.vertical]) st.vt = V_ALIGN_IN[al.vertical];\n if (al.wrapText) st.tb = 3;\n }\n const bd = cell.border as Json | undefined;\n if (bd) {\n const out: Json = {};\n for (const [side, key] of [[\"top\", \"t\"], [\"bottom\", \"b\"], [\"left\", \"l\"], [\"right\", \"r\"]] as const) {\n const s = borderFromExcel(bd[side]?.style);\n if (s) out[key] = { s, cl: { rgb: colorOf(bd[side]?.color) ?? \"#000000\" } };\n }\n if (Object.keys(out).length) st.bd = out;\n }\n if (cell.numFmt && cell.numFmt !== \"General\") st.n = { pattern: cell.numFmt };\n return Object.keys(st).length ? st : undefined;\n}\n\nconst EXCEL_EPOCH_OFFSET_DAYS = 25569;\n\nfunction toCell(cell: ExcelJSTypes.Cell, styleId: (s: Json) => string): Json | null {\n const out: Json = {};\n let st = toStyle(cell);\n const v = cell.value as unknown;\n const setNumber = (n: number) => {\n out.v = n;\n out.t = 2;\n };\n const apply = (value: unknown) => {\n if (value instanceof Date) {\n setNumber(value.getTime() / 86_400_000 + EXCEL_EPOCH_OFFSET_DAYS);\n st = { ...(st ?? {}), n: (st?.n as Json | undefined) ?? { pattern: \"yyyy-mm-dd\" } };\n } else if (typeof value === \"number\") setNumber(value);\n else if (typeof value === \"boolean\") {\n out.v = value ? 1 : 0;\n out.t = 3;\n } else if (typeof value === \"string\") {\n out.v = value;\n out.t = 1;\n } else if (value && typeof value === \"object\" && \"error\" in (value as Json)) {\n out.v = String((value as Json).error);\n out.t = 1;\n }\n };\n if (v && typeof v === \"object\" && !(v instanceof Date)) {\n const o = v as Json;\n if (\"formula\" in o || \"sharedFormula\" in o) {\n const f = o.formula ?? o.sharedFormula;\n if (f) out.f = `=${String(f).replace(/^=/, \"\")}`;\n apply(o.result);\n } else if (Array.isArray(o.richText)) {\n apply(o.richText.map((r: Json) => r.text).join(\"\"));\n } else if (\"hyperlink\" in o) {\n const text = String(typeof o.text === \"object\" ? (o.text?.richText ?? []).map((r: Json) => r.text).join(\"\") : (o.text ?? o.hyperlink));\n out.v = text;\n out.t = 1;\n out.p = linkDoc(text, String(o.hyperlink));\n } else apply(o);\n } else {\n apply(v);\n }\n if (st) out.s = styleId(st);\n return out.v === undefined && out.f === undefined && !out.s ? null : out;\n}\n\nfunction linkDoc(text: string, url: string): Json {\n return {\n id: \"d\",\n documentStyle: {},\n body: {\n dataStream: `${text}\\r\\n`,\n textRuns: [],\n paragraphs: [{ startIndex: text.length }],\n customRanges: [\n { startIndex: 0, endIndex: Math.max(0, text.length - 1), rangeId: rid(\"link\"), rangeType: 0, properties: { url } },\n ],\n },\n };\n}\n\nfunction dataValidationRules(model: Record<string, Json>): Json[] {\n const groups = new Map<string, { rule: Json; cells: [number, number][] }>();\n for (const [ref, dv] of Object.entries(model)) {\n const pos = parseA1Range(ref);\n if (!pos) continue;\n const type = String(dv.type);\n const rule: Json = {\n allowBlank: dv.allowBlank !== false,\n showErrorMessage: dv.showErrorMessage !== false,\n ...(dv.error ? { error: dv.error } : {}),\n ...(dv.errorTitle ? { errorTitle: dv.errorTitle } : {}),\n ...(dv.prompt ? { prompt: dv.prompt, showInputMessage: true } : {}),\n };\n const f = (dv.formulae ?? []) as unknown[];\n if (type === \"list\") {\n const raw = String(f[0] ?? \"\");\n const literal = /^\"(.*)\"$/.exec(raw);\n Object.assign(rule, { type: \"list\", formula1: literal ? literal[1] : raw, formula2: \"\", showDropDown: true });\n } else if ([\"whole\", \"decimal\", \"date\", \"time\", \"textLength\"].includes(type)) {\n Object.assign(rule, { type, operator: dv.operator ?? \"between\", formula1: String(f[0] ?? \"\"), formula2: f[1] !== undefined ? String(f[1]) : \"\" });\n } else if (type === \"custom\") {\n Object.assign(rule, { type: \"custom\", formula1: String(f[0] ?? \"\") });\n } else continue;\n const key = JSON.stringify(rule);\n const g = groups.get(key) ?? { rule, cells: [] };\n g.cells.push([pos.startRow, pos.startColumn]);\n groups.set(key, g);\n }\n return [...groups.values()].map(({ rule, cells }) => ({ uid: rid(\"dv\"), ...rule, ranges: compressCells(cells) }));\n}\n\n/** Single cells -> the fewest vertical runs. */\nfunction compressCells(cells: [number, number][]): RangeLike[] {\n const sorted = [...cells].sort((a, b) => a[1] - b[1] || a[0] - b[0]);\n const out: RangeLike[] = [];\n for (const [r, c] of sorted) {\n const last = out[out.length - 1];\n if (last && last.startColumn === c && last.endColumn === c && last.endRow === r - 1) last.endRow = r;\n else out.push({ startRow: r, endRow: r, startColumn: c, endColumn: c });\n }\n return out;\n}\n\nfunction dxfToStyle(style: Json | undefined): Json {\n const out: Json = {};\n const fg = colorOf(style?.font?.color);\n if (fg) out.cl = { rgb: fg };\n if (style?.font?.bold) out.bl = 1;\n if (style?.font?.italic) out.it = 1;\n const bg = colorOf(style?.fill?.bgColor) ?? colorOf(style?.fill?.fgColor);\n if (bg) out.bg = { rgb: bg };\n return out;\n}\n\nfunction conditionalRules(formats: Json[], dropped: Set<string>): Json[] {\n const out: Json[] = [];\n for (const cf of formats) {\n const ranges = String(cf.ref ?? \"\").split(/\\s+/).map((r) => parseA1Range(r)).filter((r): r is RangeLike => !!r);\n if (!ranges.length) continue;\n for (const rule of (cf.rules ?? []) as Json[]) {\n let mapped: Json | null = null;\n const style = dxfToStyle(rule.style);\n if (rule.type === \"cellIs\") {\n const nums = ((rule.formulae ?? []) as unknown[]).map(Number);\n const between = rule.operator === \"between\" || rule.operator === \"notBetween\";\n mapped = { type: \"highlightCell\", subType: \"number\", operator: rule.operator, value: between ? nums.slice(0, 2) : nums[0], style };\n } else if (rule.type === \"containsText\") {\n mapped = { type: \"highlightCell\", subType: \"text\", operator: \"containsText\", value: String(rule.text ?? \"\"), style };\n } else if (rule.type === \"expression\") {\n mapped = { type: \"highlightCell\", subType: \"formula\", value: `=${String((rule.formulae ?? [])[0] ?? \"\")}`, style };\n } else if (rule.type === \"colorScale\") {\n mapped = {\n type: \"colorScale\",\n config: ((rule.cfvo ?? []) as Json[]).map((v, i) => ({\n index: i,\n color: colorOf(rule.color?.[i]) ?? \"#ffffff\",\n value: { type: v.type, ...(v.value !== undefined ? { value: v.value } : {}) },\n })),\n };\n } else if (rule.type === \"dataBar\") {\n const [min, max] = (rule.cfvo ?? []) as Json[];\n mapped = {\n type: \"dataBar\",\n isShowValue: true,\n config: {\n min: { type: min?.type ?? \"min\" },\n max: { type: max?.type ?? \"max\" },\n isGradient: rule.gradient !== false,\n positiveColor: colorOf(rule.color) ?? \"#638ec6\",\n nativeColor: \"#ff0000\",\n },\n };\n }\n if (!mapped) {\n dropped.add(\"Some conditional formats (icon sets, top/bottom, date rules) were not imported\");\n continue;\n }\n out.push({ cfId: rid(\"cf\"), ranges, stopIfTrue: Boolean(rule.stopIfTrue), rule: mapped });\n }\n }\n return out;\n}\n","/**\n * Shared vocabulary between the xlsx importer and exporter: how Univer's\n * style numbers, colours and units map to the xlsx file's.\n *\n * Univer enums are written as numbers here so these helpers stay free of any\n * Univer import (they run in tests and in both directions).\n */\n\nexport const RESOURCE = {\n validation: \"SHEET_DATA_VALIDATION_PLUGIN\",\n conditional: \"SHEET_CONDITIONAL_FORMATTING_PLUGIN\",\n filter: \"SHEET_FILTER_PLUGIN\",\n note: \"SHEET_NOTE_PLUGIN\",\n comments: \"SHEET_UNIVER_THREAD_COMMENT_PLUGIN\",\n drawing: \"SHEET_DRAWING_PLUGIN\",\n table: \"SHEET_TABLE_PLUGIN\",\n} as const;\n\nexport type UniverResource = { name: string; data: string };\n\nexport function readResource<T = unknown>(\n resources: readonly UniverResource[] | undefined,\n name: string,\n): T | undefined {\n const raw = resources?.find((r) => r.name === name)?.data;\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return undefined;\n }\n}\n\nexport function writeResource(resources: UniverResource[], name: string, value: unknown): void {\n const i = resources.findIndex((r) => r.name === name);\n const entry = { name, data: JSON.stringify(value) };\n if (i >= 0) resources[i] = entry;\n else resources.push(entry);\n}\n\n/** Excel column width (characters) <-> Univer pixels. */\nexport const colPxToChars = (px: number): number => Math.max(0, Math.round((px / 7) * 100) / 100);\nexport const colCharsToPx = (chars: number): number => Math.round(chars * 7);\n/** Excel row height (points) <-> Univer pixels. */\nexport const rowPxToPt = (px: number): number => Math.round(px * 0.75 * 100) / 100;\nexport const rowPtToPx = (pt: number): number => Math.round((pt / 0.75) * 100) / 100;\n\n/** Univer colour (\"#rrggbb\", \"rgb(r,g,b)\", \"rgba(...)\") -> ARGB hex, or undefined. */\nexport function colorToArgb(input: string | undefined | null): string | undefined {\n if (!input) return undefined;\n const s = input.trim();\n const hex = /^#?([0-9a-f]{6})$/i.exec(s);\n if (hex) return `FF${hex[1]!.toUpperCase()}`;\n const short = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(s);\n if (short) return `FF${short[1]}${short[1]}${short[2]}${short[2]}${short[3]}${short[3]}`.toUpperCase();\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i.exec(s);\n if (rgb) {\n const h = (n: string) => Number(n).toString(16).padStart(2, \"0\");\n return `FF${h(rgb[1]!)}${h(rgb[2]!)}${h(rgb[3]!)}`.toUpperCase();\n }\n return undefined;\n}\n\n/** ARGB (or RGB) hex from a file -> Univer \"#rrggbb\". */\nexport function argbToColor(argb: string | undefined | null): string | undefined {\n if (!argb) return undefined;\n const v = argb.replace(/^#/, \"\");\n if (v.length === 8) return `#${v.slice(2).toLowerCase()}`;\n if (v.length === 6) return `#${v.toLowerCase()}`;\n return undefined;\n}\n\n// Univer BorderStyleTypes number <-> ExcelJS border style name.\nconst BORDER_OUT: Record<number, string> = {\n 1: \"thin\", 2: \"hair\", 3: \"dotted\", 4: \"dashed\", 5: \"dashDot\", 6: \"dashDotDot\", 7: \"double\",\n 8: \"medium\", 9: \"mediumDashed\", 10: \"mediumDashDot\", 11: \"mediumDashDotDot\", 12: \"slantDashDot\", 13: \"thick\",\n};\nexport const borderToExcel = (n: number | undefined): string | undefined =>\n n === undefined ? undefined : BORDER_OUT[n];\nexport const borderFromExcel = (name: string | undefined): number | undefined => {\n if (!name) return undefined;\n const hit = Object.entries(BORDER_OUT).find(([, v]) => v === name);\n return hit ? Number(hit[0]) : undefined;\n};\n\nexport const H_ALIGN_OUT: Record<number, string> = { 1: \"left\", 2: \"center\", 3: \"right\", 4: \"justify\", 5: \"justify\", 6: \"distributed\" };\nexport const V_ALIGN_OUT: Record<number, string> = { 1: \"top\", 2: \"middle\", 3: \"bottom\" };\nexport const H_ALIGN_IN: Record<string, number> = { left: 1, center: 2, right: 3, justify: 4, fill: 1, centerContinuous: 2, distributed: 6 };\nexport const V_ALIGN_IN: Record<string, number> = { top: 1, middle: 2, bottom: 3, distributed: 2, justify: 2 };\n\n/** 0-based (row, col) -> \"A1\" (no $). */\nexport function a1(row: number, col: number): string {\n let n = col + 1;\n let letters = \"\";\n while (n > 0) {\n const m = (n - 1) % 26;\n letters = String.fromCharCode(65 + m) + letters;\n n = Math.floor((n - 1) / 26);\n }\n return `${letters}${row + 1}`;\n}\n\nexport type RangeLike = { startRow: number; endRow: number; startColumn: number; endColumn: number };\nexport const rangeToA1 = (r: RangeLike): string =>\n r.startRow === r.endRow && r.startColumn === r.endColumn\n ? a1(r.startRow, r.startColumn)\n : `${a1(r.startRow, r.startColumn)}:${a1(r.endRow, r.endColumn)}`;\n\n/** \"A1\" or \"A1:C5\" -> range (0-based), or null. */\nexport function parseA1Range(ref: string): RangeLike | null {\n const m = /^\\$?([A-Z]+)\\$?(\\d+)(?::\\$?([A-Z]+)\\$?(\\d+))?$/i.exec(ref.trim());\n if (!m) return null;\n const col = (s: string) => [...s.toUpperCase()].reduce((acc, ch) => acc * 26 + ch.charCodeAt(0) - 64, 0) - 1;\n const sc = col(m[1]!);\n const sr = Number(m[2]!) - 1;\n return { startRow: sr, startColumn: sc, endRow: m[4] ? Number(m[4]) - 1 : sr, endColumn: m[3] ? col(m[3]) : sc };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/aidream/aidream/apps/shared/office/dist/chunk-ZDZCCOUB.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-ZDZCCOUB.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\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\n/**\n * An independent copy of a workbook: its own row in the original's organization\n * and project, with the latest snapshot copied over. 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 const latest = await getLatestSnapshot(workbookId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveSnapshot({\n workbookId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.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"]}
1
+ {"version":3,"sources":["/home/runner/_work/aidream/aidream/apps/shared/office/dist/chunk-ZDZCCOUB.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-ZDZCCOUB.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\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\n/**\n * An independent copy of a workbook: its own row in the original's organization\n * and project, with the latest snapshot copied over. 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 const latest = await getLatestSnapshot(workbookId);\n if (!latest.success) return latest;\n if (latest.data) {\n const saved = await saveSnapshot({\n workbookId: created.data.id,\n snapshot: latest.data.snapshot,\n label: latest.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"]}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/docs/ports.ts
21
+ var ports_exports = {};
22
+ __export(ports_exports, {
23
+ configureDocsHost: () => configureDocsHost,
24
+ getDocsHost: () => getDocsHost
25
+ });
26
+ module.exports = __toCommonJS(ports_exports);
27
+ var SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.office.docs-host");
28
+ var slot = () => {
29
+ const g = globalThis;
30
+ return g[SLOT] ??= {};
31
+ };
32
+ function configureDocsHost(ports) {
33
+ slot().ports = ports;
34
+ }
35
+ function getDocsHost() {
36
+ const ports = slot().ports;
37
+ if (!ports) throw new Error("@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.");
38
+ return ports;
39
+ }
40
+ //# sourceMappingURL=docs-host.cjs.map
@@ -0,0 +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;AAsBA,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":[]}
@@ -0,0 +1,28 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+
3
+ /**
4
+ * The host ports of the Docs model and io.
5
+ *
6
+ * The package owns the document service, the open-document model and the converters, but two things
7
+ * belong to the app that mounts them: the database client (a package owns no client) and the server
8
+ * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).
9
+ * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot
10
+ * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming
11
+ * itself (nothing fails silently).
12
+ */
13
+
14
+ /** A Supabase client over any schema: the package cannot import the app's generated database types. */
15
+ type DocsSupabase = SupabaseClient<any, any, any>;
16
+ interface DocsHostPorts {
17
+ /** The app's database client (signed in as the person). */
18
+ getSupabase(): DocsSupabase;
19
+ /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */
20
+ requestRaw(path: string, init: {
21
+ method: "POST";
22
+ body: FormData;
23
+ }): Promise<Response>;
24
+ }
25
+ declare function configureDocsHost(ports: DocsHostPorts): void;
26
+ declare function getDocsHost(): DocsHostPorts;
27
+
28
+ export { type DocsHostPorts, type DocsSupabase, configureDocsHost, getDocsHost };
@@ -0,0 +1,28 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+
3
+ /**
4
+ * The host ports of the Docs model and io.
5
+ *
6
+ * The package owns the document service, the open-document model and the converters, but two things
7
+ * belong to the app that mounts them: the database client (a package owns no client) and the server
8
+ * request that converts a .docx to .odt / .rtf (the app owns the server URL, auth and error capture).
9
+ * The host states them once at start-up with `configureDocsHost`. State sits on a `globalThis` slot
10
+ * so a dual-bundled copy of the package still sees one host. An unconfigured port THROWS naming
11
+ * itself (nothing fails silently).
12
+ */
13
+
14
+ /** A Supabase client over any schema: the package cannot import the app's generated database types. */
15
+ type DocsSupabase = SupabaseClient<any, any, any>;
16
+ interface DocsHostPorts {
17
+ /** The app's database client (signed in as the person). */
18
+ getSupabase(): DocsSupabase;
19
+ /** An authenticated request to the Matrx server returning the raw `Response` (the open-format converter). */
20
+ requestRaw(path: string, init: {
21
+ method: "POST";
22
+ body: FormData;
23
+ }): Promise<Response>;
24
+ }
25
+ declare function configureDocsHost(ports: DocsHostPorts): void;
26
+ declare function getDocsHost(): DocsHostPorts;
27
+
28
+ export { type DocsHostPorts, type DocsSupabase, configureDocsHost, getDocsHost };
@@ -0,0 +1,19 @@
1
+ // src/docs/ports.ts
2
+ var SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.office.docs-host");
3
+ var slot = () => {
4
+ const g = globalThis;
5
+ return g[SLOT] ??= {};
6
+ };
7
+ function configureDocsHost(ports) {
8
+ slot().ports = ports;
9
+ }
10
+ function getDocsHost() {
11
+ const ports = slot().ports;
12
+ if (!ports) throw new Error("@ai-matrx/office/docs: configureDocsHost(ports) was not called before the document service ran.");
13
+ return ports;
14
+ }
15
+ export {
16
+ configureDocsHost,
17
+ getDocsHost
18
+ };
19
+ //# sourceMappingURL=docs-host.js.map
@@ -0,0 +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":";AAsBA,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":[]}