@opengeni/artifact-tool 0.2.2

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 (203) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +104 -0
  3. package/dist/bounded-zip.d.ts +28 -0
  4. package/dist/chunk-4BSENMAE.js +39 -0
  5. package/dist/chunk-4BSENMAE.js.map +1 -0
  6. package/dist/chunk-4FRFNNBM.js +276 -0
  7. package/dist/chunk-4FRFNNBM.js.map +1 -0
  8. package/dist/chunk-5XIA6KHZ.js +49 -0
  9. package/dist/chunk-5XIA6KHZ.js.map +1 -0
  10. package/dist/chunk-66CT2ZRP.js +2229 -0
  11. package/dist/chunk-66CT2ZRP.js.map +1 -0
  12. package/dist/chunk-72SYDU4O.js +319 -0
  13. package/dist/chunk-72SYDU4O.js.map +1 -0
  14. package/dist/chunk-B2ZJRZDA.js +279 -0
  15. package/dist/chunk-B2ZJRZDA.js.map +1 -0
  16. package/dist/chunk-DCTLTNPW.js +2458 -0
  17. package/dist/chunk-DCTLTNPW.js.map +1 -0
  18. package/dist/chunk-FGZM4FQ6.js +473 -0
  19. package/dist/chunk-FGZM4FQ6.js.map +1 -0
  20. package/dist/chunk-HTJBLBDE.js +591 -0
  21. package/dist/chunk-HTJBLBDE.js.map +1 -0
  22. package/dist/chunk-IYFXZQ34.js +5306 -0
  23. package/dist/chunk-IYFXZQ34.js.map +1 -0
  24. package/dist/chunk-J6N7IR44.js +172 -0
  25. package/dist/chunk-J6N7IR44.js.map +1 -0
  26. package/dist/chunk-N2IHNWBS.js +1002 -0
  27. package/dist/chunk-N2IHNWBS.js.map +1 -0
  28. package/dist/chunk-NAG44K67.js +549 -0
  29. package/dist/chunk-NAG44K67.js.map +1 -0
  30. package/dist/chunk-O24KTEGP.js +33 -0
  31. package/dist/chunk-O24KTEGP.js.map +1 -0
  32. package/dist/chunk-PI2AZVGK.js +2074 -0
  33. package/dist/chunk-PI2AZVGK.js.map +1 -0
  34. package/dist/chunk-Q2FFHEY7.js +40 -0
  35. package/dist/chunk-Q2FFHEY7.js.map +1 -0
  36. package/dist/chunk-RBGQADXA.js +57 -0
  37. package/dist/chunk-RBGQADXA.js.map +1 -0
  38. package/dist/chunk-U5G2BKM2.js +613 -0
  39. package/dist/chunk-U5G2BKM2.js.map +1 -0
  40. package/dist/chunk-VOJHMSM3.js +39 -0
  41. package/dist/chunk-VOJHMSM3.js.map +1 -0
  42. package/dist/chunk-VUNV25KB.js +16 -0
  43. package/dist/chunk-VUNV25KB.js.map +1 -0
  44. package/dist/chunk-XIFUNVBO.js +101 -0
  45. package/dist/chunk-XIFUNVBO.js.map +1 -0
  46. package/dist/chunk-ZCJYRJGB.js +489 -0
  47. package/dist/chunk-ZCJYRJGB.js.map +1 -0
  48. package/dist/chunk-ZZXPEE4S.js +2260 -0
  49. package/dist/chunk-ZZXPEE4S.js.map +1 -0
  50. package/dist/document-docx-api.d.ts +49 -0
  51. package/dist/document-docx-codec.d.ts +9 -0
  52. package/dist/document-docx-codec.js +4765 -0
  53. package/dist/document-docx-codec.js.map +1 -0
  54. package/dist/document-docx-import.d.ts +261 -0
  55. package/dist/document-docx-packer.d.ts +18 -0
  56. package/dist/document-docx-state.d.ts +12 -0
  57. package/dist/document-render.d.ts +3 -0
  58. package/dist/document-render.js +492 -0
  59. package/dist/document-render.js.map +1 -0
  60. package/dist/document.d.ts +432 -0
  61. package/dist/document.js +37 -0
  62. package/dist/document.js.map +1 -0
  63. package/dist/errors.d.ts +23 -0
  64. package/dist/file-blob.d.ts +11 -0
  65. package/dist/index.d.ts +4 -0
  66. package/dist/index.js +186 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/inspection.d.ts +12 -0
  69. package/dist/kernel.d.ts +101 -0
  70. package/dist/lib-GQLPACFK.js +9746 -0
  71. package/dist/lib-GQLPACFK.js.map +1 -0
  72. package/dist/materializer-cli-entry.d.ts +2 -0
  73. package/dist/materializer-cli-entry.js +29 -0
  74. package/dist/materializer-cli-entry.js.map +1 -0
  75. package/dist/materializer-cli.d.ts +24 -0
  76. package/dist/materializer-cli.js +24 -0
  77. package/dist/materializer-cli.js.map +1 -0
  78. package/dist/native-raster.d.ts +10 -0
  79. package/dist/native.d.ts +129 -0
  80. package/dist/native.js +31 -0
  81. package/dist/native.js.map +1 -0
  82. package/dist/office-import.d.ts +48 -0
  83. package/dist/office-import.js +154 -0
  84. package/dist/office-import.js.map +1 -0
  85. package/dist/presentation-pptx-api.d.ts +60 -0
  86. package/dist/presentation-pptx-import.d.ts +5 -0
  87. package/dist/presentation-pptx-state-digest-765CZZED.js +10 -0
  88. package/dist/presentation-pptx-state-digest-765CZZED.js.map +1 -0
  89. package/dist/presentation-pptx-state-digest.d.ts +3 -0
  90. package/dist/presentation-pptx-state.d.ts +4 -0
  91. package/dist/presentation-pptx-xml.d.ts +29 -0
  92. package/dist/presentation-pptx.d.ts +5 -0
  93. package/dist/presentation-pptx.js +2365 -0
  94. package/dist/presentation-pptx.js.map +1 -0
  95. package/dist/presentation-render.d.ts +29 -0
  96. package/dist/presentation-render.js +375 -0
  97. package/dist/presentation-render.js.map +1 -0
  98. package/dist/presentation.d.ts +565 -0
  99. package/dist/presentation.js +71 -0
  100. package/dist/presentation.js.map +1 -0
  101. package/dist/production-composite.d.ts +68 -0
  102. package/dist/production-document.d.ts +2 -0
  103. package/dist/production-document.js +176 -0
  104. package/dist/production-document.js.map +1 -0
  105. package/dist/production-native-codecs.d.ts +94 -0
  106. package/dist/production-presentation.d.ts +2 -0
  107. package/dist/production-presentation.js +176 -0
  108. package/dist/production-presentation.js.map +1 -0
  109. package/dist/production-sha256.d.ts +2 -0
  110. package/dist/production-spreadsheet-native.d.ts +12 -0
  111. package/dist/production-spreadsheet.d.ts +2 -0
  112. package/dist/production-spreadsheet.js +176 -0
  113. package/dist/production-spreadsheet.js.map +1 -0
  114. package/dist/production.d.ts +96 -0
  115. package/dist/raster-image.d.ts +34 -0
  116. package/dist/reference.d.ts +17 -0
  117. package/dist/reference.js +574 -0
  118. package/dist/reference.js.map +1 -0
  119. package/dist/runtime-cli-entry.d.ts +2 -0
  120. package/dist/runtime-cli-entry.js +21 -0
  121. package/dist/runtime-cli-entry.js.map +1 -0
  122. package/dist/runtime-cli.d.ts +76 -0
  123. package/dist/runtime-cli.js +26 -0
  124. package/dist/runtime-cli.js.map +1 -0
  125. package/dist/runtime-development.d.ts +73 -0
  126. package/dist/runtime-development.js +30 -0
  127. package/dist/runtime-development.js.map +1 -0
  128. package/dist/runtime-receipt.d.ts +19 -0
  129. package/dist/runtime.d.ts +355 -0
  130. package/dist/runtime.js +42 -0
  131. package/dist/runtime.js.map +1 -0
  132. package/dist/snapshot.d.ts +26 -0
  133. package/dist/snapshot.js +61 -0
  134. package/dist/snapshot.js.map +1 -0
  135. package/dist/spreadsheet-address.d.ts +18 -0
  136. package/dist/spreadsheet-file.d.ts +17 -0
  137. package/dist/spreadsheet-formula.d.ts +67 -0
  138. package/dist/spreadsheet-image.d.ts +17 -0
  139. package/dist/spreadsheet-render.d.ts +5 -0
  140. package/dist/spreadsheet-render.js +752 -0
  141. package/dist/spreadsheet-render.js.map +1 -0
  142. package/dist/spreadsheet-types.d.ts +155 -0
  143. package/dist/spreadsheet-xlsx-api.d.ts +88 -0
  144. package/dist/spreadsheet-xlsx-codec.d.ts +16 -0
  145. package/dist/spreadsheet-xlsx-codec.js +16 -0
  146. package/dist/spreadsheet-xlsx-codec.js.map +1 -0
  147. package/dist/spreadsheet-xlsx-state.d.ts +16 -0
  148. package/dist/spreadsheet.d.ts +724 -0
  149. package/dist/spreadsheet.js +67 -0
  150. package/dist/spreadsheet.js.map +1 -0
  151. package/package.json +129 -0
  152. package/src/bounded-zip.ts +450 -0
  153. package/src/document-docx-api.ts +64 -0
  154. package/src/document-docx-codec.ts +2253 -0
  155. package/src/document-docx-import.ts +3814 -0
  156. package/src/document-docx-packer.ts +72 -0
  157. package/src/document-docx-state.ts +59 -0
  158. package/src/document-render.ts +615 -0
  159. package/src/document.ts +2800 -0
  160. package/src/errors.ts +45 -0
  161. package/src/file-blob.ts +43 -0
  162. package/src/index.ts +4 -0
  163. package/src/inspection.ts +50 -0
  164. package/src/kernel.ts +525 -0
  165. package/src/materializer-cli-entry.ts +11 -0
  166. package/src/materializer-cli.ts +743 -0
  167. package/src/native-raster.ts +141 -0
  168. package/src/native.ts +390 -0
  169. package/src/office-import.ts +243 -0
  170. package/src/presentation-pptx-api.ts +107 -0
  171. package/src/presentation-pptx-import.ts +2065 -0
  172. package/src/presentation-pptx-state-digest.ts +46 -0
  173. package/src/presentation-pptx-state.ts +18 -0
  174. package/src/presentation-pptx-xml.ts +473 -0
  175. package/src/presentation-pptx.ts +447 -0
  176. package/src/presentation-render.ts +532 -0
  177. package/src/presentation.ts +2599 -0
  178. package/src/production-composite.ts +805 -0
  179. package/src/production-document.ts +2 -0
  180. package/src/production-native-codecs.ts +1141 -0
  181. package/src/production-presentation.ts +2 -0
  182. package/src/production-sha256.ts +150 -0
  183. package/src/production-spreadsheet-native.ts +686 -0
  184. package/src/production-spreadsheet.ts +2 -0
  185. package/src/production.ts +1022 -0
  186. package/src/raster-image.ts +586 -0
  187. package/src/reference.ts +17 -0
  188. package/src/runtime-cli-entry.ts +13 -0
  189. package/src/runtime-cli.ts +670 -0
  190. package/src/runtime-development.ts +689 -0
  191. package/src/runtime-receipt.ts +169 -0
  192. package/src/runtime.ts +1463 -0
  193. package/src/snapshot.ts +88 -0
  194. package/src/spreadsheet-address.ts +90 -0
  195. package/src/spreadsheet-file.ts +71 -0
  196. package/src/spreadsheet-formula.ts +1212 -0
  197. package/src/spreadsheet-image.ts +242 -0
  198. package/src/spreadsheet-render.ts +985 -0
  199. package/src/spreadsheet-types.ts +171 -0
  200. package/src/spreadsheet-xlsx-api.ts +123 -0
  201. package/src/spreadsheet-xlsx-codec.ts +3063 -0
  202. package/src/spreadsheet-xlsx-state.ts +191 -0
  203. package/src/spreadsheet.ts +5195 -0
@@ -0,0 +1,141 @@
1
+ const FONT_FILES_ENV = "OPENGENI_ARTIFACT_RASTER_FONT_FILES";
2
+ const DEFAULT_FONT_FAMILY_ENV = "OPENGENI_ARTIFACT_RASTER_DEFAULT_FONT_FAMILY";
3
+ const MAX_FONT_FILES = 16;
4
+ const MAX_FONT_FILE_BYTES = 32 * 1024 * 1024;
5
+
6
+ type ResvgOptions = {
7
+ background?: string;
8
+ fitTo?: { mode: "zoom"; value: number };
9
+ font: {
10
+ defaultFontFamily?: string;
11
+ fontFiles?: string[];
12
+ loadSystemFonts: boolean;
13
+ };
14
+ };
15
+
16
+ type ResvgRuntime = {
17
+ Resvg: new (svg: string, options: ResvgOptions) => { render(): { asPng(): Uint8Array } };
18
+ };
19
+
20
+ type FontAuthority = ResvgOptions["font"];
21
+
22
+ let cachedFontAuthority: { key: string; value: Promise<FontAuthority> } | undefined;
23
+
24
+ /**
25
+ * Rasterize with an explicit font authority when the host configures one.
26
+ * Resvg otherwise succeeds while silently dropping every glyph on minimal
27
+ * Linux images. Sandboxes pin regular/bold/italic-capable Liberation faces;
28
+ * desktop installs retain their native system-font fallback.
29
+ */
30
+ export async function rasterizeSvgToPng(
31
+ svg: string,
32
+ options: Readonly<{ background?: string; zoom?: number }> = {},
33
+ ): Promise<Uint8Array> {
34
+ const [{ Resvg }, font] = await Promise.all([
35
+ importNativeRuntime<ResvgRuntime>("@resvg/resvg-js"),
36
+ rasterFontAuthority(),
37
+ ]);
38
+ const resvgOptions: ResvgOptions = {
39
+ ...(options.background === undefined ? {} : { background: options.background }),
40
+ ...(options.zoom === undefined
41
+ ? {}
42
+ : { fitTo: { mode: "zoom" as const, value: options.zoom } }),
43
+ font,
44
+ };
45
+ return Uint8Array.from(new Resvg(svg, resvgOptions).render().asPng());
46
+ }
47
+
48
+ async function importNativeRuntime<T>(specifier: string): Promise<T> {
49
+ return (await import(/* @vite-ignore */ specifier)) as T;
50
+ }
51
+
52
+ async function rasterFontAuthority(): Promise<FontAuthority> {
53
+ const environment = typeof process === "undefined" ? undefined : process.env;
54
+ const filesJson = environment?.[FONT_FILES_ENV];
55
+ const defaultFontFamily = environment?.[DEFAULT_FONT_FAMILY_ENV];
56
+ if (filesJson === undefined && defaultFontFamily === undefined) {
57
+ return { loadSystemFonts: true };
58
+ }
59
+ if (
60
+ !filesJson ||
61
+ filesJson.length > 8_192 ||
62
+ !defaultFontFamily?.trim() ||
63
+ defaultFontFamily.length > 128 ||
64
+ /[\u0000-\u001f\u007f]/u.test(defaultFontFamily)
65
+ ) {
66
+ throw new Error(`${FONT_FILES_ENV} and ${DEFAULT_FONT_FAMILY_ENV} must be configured together`);
67
+ }
68
+ const key = `${filesJson}\u0000${defaultFontFamily}`;
69
+ if (cachedFontAuthority?.key === key) return await cachedFontAuthority.value;
70
+ const value = validateConfiguredFontAuthority(filesJson, defaultFontFamily.trim());
71
+ cachedFontAuthority = { key, value };
72
+ return await value;
73
+ }
74
+
75
+ async function validateConfiguredFontAuthority(
76
+ filesJson: string,
77
+ defaultFontFamily: string,
78
+ ): Promise<FontAuthority> {
79
+ let requested: unknown;
80
+ try {
81
+ requested = JSON.parse(filesJson);
82
+ } catch {
83
+ throw new Error(`${FONT_FILES_ENV} must be a JSON array of absolute font file paths`);
84
+ }
85
+ if (
86
+ !Array.isArray(requested) ||
87
+ requested.length === 0 ||
88
+ requested.length > MAX_FONT_FILES ||
89
+ requested.some((path) => typeof path !== "string" || path.length === 0)
90
+ ) {
91
+ throw new Error(`${FONT_FILES_ENV} must contain 1-${MAX_FONT_FILES} font file paths`);
92
+ }
93
+
94
+ // Keep browser HTML/SVG render paths free of Node builtins. This function is
95
+ // reached only by the native PNG/WebP branches with an explicit authority.
96
+ const fileSystemSpecifier = "node:fs/promises";
97
+ const pathSpecifier = "node:path";
98
+ const [{ open, realpath, stat }, { isAbsolute }] = await Promise.all([
99
+ import(/* @vite-ignore */ fileSystemSpecifier) as Promise<typeof import("node:fs/promises")>,
100
+ import(/* @vite-ignore */ pathSpecifier) as Promise<typeof import("node:path")>,
101
+ ]);
102
+ const fontFiles = await Promise.all(
103
+ requested.map(async (path) => {
104
+ if (!isAbsolute(path)) throw new Error(`${FONT_FILES_ENV} paths must be absolute`);
105
+ const canonical = await realpath(path);
106
+ const metadata = await stat(canonical);
107
+ if (!metadata.isFile() || metadata.size === 0 || metadata.size > MAX_FONT_FILE_BYTES) {
108
+ throw new Error(`Configured artifact raster font is not a bounded regular file: ${path}`);
109
+ }
110
+ const handle = await open(canonical, "r");
111
+ try {
112
+ const signature = new Uint8Array(4);
113
+ const { bytesRead } = await handle.read(signature, 0, signature.byteLength, 0);
114
+ const tag = new TextDecoder().decode(signature);
115
+ if (
116
+ bytesRead !== 4 ||
117
+ (tag !== "OTTO" && tag !== "ttcf" && !sameBytes(signature, [0, 1, 0, 0]))
118
+ ) {
119
+ throw new Error(`Configured artifact raster font has an unsupported signature: ${path}`);
120
+ }
121
+ } finally {
122
+ await handle.close();
123
+ }
124
+ return canonical;
125
+ }),
126
+ );
127
+ if (new Set(fontFiles).size !== fontFiles.length) {
128
+ throw new Error(`${FONT_FILES_ENV} must not contain duplicate files`);
129
+ }
130
+ return {
131
+ defaultFontFamily,
132
+ fontFiles,
133
+ loadSystemFonts: false,
134
+ };
135
+ }
136
+
137
+ function sameBytes(actual: Uint8Array, expected: readonly number[]): boolean {
138
+ return (
139
+ actual.length === expected.length && actual.every((value, index) => value === expected[index])
140
+ );
141
+ }
package/src/native.ts ADDED
@@ -0,0 +1,390 @@
1
+ import {
2
+ EDITABLE_ARTIFACT_INTENT_VERSION,
3
+ SPREADSHEET_ARTIFACT_COMMAND_VERSION,
4
+ assertCanonicalSpreadsheetArtifactCommandBytes,
5
+ decodeEditableArtifactMutationIntent,
6
+ encodeEditableArtifactMutationIntent,
7
+ encodeSpreadsheetArtifactCommandBatch,
8
+ hashEditableArtifactMutationIntentBytes,
9
+ type EditableArtifactMutationIntent,
10
+ type SpreadsheetArtifactCommandBatch,
11
+ } from "@opengeni/contracts/editable-artifacts";
12
+ import {
13
+ ArtifactCollaborationSession,
14
+ ArtifactDocumentSession,
15
+ ArtifactKernelRuntime,
16
+ ArtifactPresentationSession,
17
+ ArtifactRuntimeError,
18
+ ArtifactTextLayoutSession,
19
+ type ArtifactKernelCapabilities,
20
+ type NativeArtifactRuntimeTarget,
21
+ } from "./runtime";
22
+
23
+ export {
24
+ SPREADSHEET_ARTIFACT_COMMAND_VERSION,
25
+ assertCanonicalSpreadsheetArtifactCommandBytes,
26
+ decodeSpreadsheetArtifactCommandBatch,
27
+ editableArtifactStableId,
28
+ encodeSpreadsheetArtifactCommandBatch,
29
+ spreadsheetSheetId,
30
+ } from "@opengeni/contracts/editable-artifacts";
31
+ export type {
32
+ EditableArtifactStableId,
33
+ SpreadsheetArtifactCommand,
34
+ SpreadsheetArtifactCommandBatch,
35
+ SpreadsheetCellInput,
36
+ SpreadsheetCellPoint,
37
+ SpreadsheetCellRange,
38
+ SpreadsheetSheetGeneration,
39
+ SpreadsheetSheetPrecondition,
40
+ } from "@opengeni/contracts/editable-artifacts";
41
+
42
+ export type NativeArtifactModality = "spreadsheet" | "document" | "presentation";
43
+
44
+ export type NativeSpreadsheetIntentFields = Omit<
45
+ EditableArtifactMutationIntent,
46
+ | "envelopeVersion"
47
+ | "protocolVersion"
48
+ | "modelSchemaVersion"
49
+ | "commandProtocolVersion"
50
+ | "commandBytes"
51
+ >;
52
+
53
+ export type NativeSpreadsheetAuthorCommandsInput = Readonly<{
54
+ intent: NativeSpreadsheetIntentFields;
55
+ commands: SpreadsheetArtifactCommandBatch;
56
+ /** Exact authoritative OGACF001 base selected for this apply attempt. */
57
+ resolvedBaseBytes: Uint8Array;
58
+ }>;
59
+
60
+ export type NativeSpreadsheetAuthoredTransaction = Readonly<{
61
+ /** Exact canonical OGATX001 bytes passed to Rust. */
62
+ intentBytes: Uint8Array;
63
+ requestHash: string;
64
+ /** One whole canonical OGACO001 transaction returned by Rust. */
65
+ committedTransactionBytes: Uint8Array;
66
+ }>;
67
+
68
+ export type CreateNativeArtifactSessionInput = Readonly<{
69
+ modality: NativeArtifactModality;
70
+ replicaNamespace: bigint;
71
+ }>;
72
+
73
+ export type OpenNativeArtifactSessionInput = Readonly<{
74
+ modality: NativeArtifactModality;
75
+ snapshot: Uint8Array;
76
+ }>;
77
+
78
+ export type NativeArtifactSession =
79
+ | NativeSpreadsheetSession
80
+ | NativeDocumentSession
81
+ | NativePresentationSession;
82
+
83
+ /**
84
+ * Synchronous Node/Bun production spreadsheet session backed only by the
85
+ * verified Rust N-API collaboration kernel. It never selects the TypeScript
86
+ * reference model and deliberately rejects a browser/WASM runtime; browsers
87
+ * use the asynchronous `@opengeni/sdk/editable-artifacts` Worker API.
88
+ */
89
+ export class NativeSpreadsheetSession {
90
+ readonly kind = "native" as const;
91
+ readonly modality = "spreadsheet" as const;
92
+ readonly target: NativeArtifactRuntimeTarget;
93
+ readonly capabilities: ArtifactKernelCapabilities;
94
+ readonly buildIdentity: string;
95
+
96
+ private constructor(
97
+ private readonly runtime: ArtifactKernelRuntime,
98
+ private readonly session: ArtifactCollaborationSession,
99
+ ) {
100
+ requireNativeSpreadsheetRuntime(runtime);
101
+ this.target = runtime.target as NativeArtifactRuntimeTarget;
102
+ this.capabilities = runtime.capabilities;
103
+ this.buildIdentity = runtime.buildIdentity;
104
+ }
105
+
106
+ static create(
107
+ runtime: ArtifactKernelRuntime,
108
+ replicaNamespace: bigint,
109
+ ): NativeSpreadsheetSession {
110
+ requireNativeSpreadsheetRuntime(runtime);
111
+ return new NativeSpreadsheetSession(
112
+ runtime,
113
+ runtime.createCollaborationSession(replicaNamespace),
114
+ );
115
+ }
116
+
117
+ static open(runtime: ArtifactKernelRuntime, snapshot: Uint8Array): NativeSpreadsheetSession {
118
+ requireNativeSpreadsheetRuntime(runtime);
119
+ return new NativeSpreadsheetSession(runtime, runtime.openCollaborationSession(snapshot));
120
+ }
121
+
122
+ /**
123
+ * Authors one already-canonical mutation. Rust independently validates the
124
+ * exact OGATX/OGASC bytes, resolves typed operations, applies atomically, and
125
+ * returns the whole canonical OGACO transaction.
126
+ */
127
+ authorTransaction(intentBytes: Uint8Array, resolvedBaseBytes: Uint8Array): Uint8Array {
128
+ assertSpreadsheetIntent(intentBytes);
129
+ return this.session.authorTransaction(intentBytes, resolvedBaseBytes);
130
+ }
131
+
132
+ /** Encodes one identity-free typed command batch and authors it atomically. */
133
+ authorCommands(
134
+ input: NativeSpreadsheetAuthorCommandsInput,
135
+ ): NativeSpreadsheetAuthoredTransaction {
136
+ const commandBytes = encodeSpreadsheetArtifactCommandBatch(input.commands);
137
+ const intentBytes = encodeEditableArtifactMutationIntent({
138
+ ...input.intent,
139
+ envelopeVersion: EDITABLE_ARTIFACT_INTENT_VERSION,
140
+ protocolVersion: 1,
141
+ modelSchemaVersion: 1,
142
+ commandProtocolVersion: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
143
+ commandBytes,
144
+ });
145
+ const requestHash = hashEditableArtifactMutationIntentBytes(intentBytes);
146
+ const committedTransactionBytes = this.authorTransaction(intentBytes, input.resolvedBaseBytes);
147
+ return Object.freeze({ intentBytes, requestHash, committedTransactionBytes });
148
+ }
149
+
150
+ /** Replays one whole authoritative OGACO transaction atomically. */
151
+ applyCommitted(committedTransactionBytes: Uint8Array): void {
152
+ this.session.applyCommitted(committedTransactionBytes);
153
+ }
154
+
155
+ /**
156
+ * Executes one canonical OGAKQ request. Typed viewport/metadata helpers use
157
+ * the shared contract codec; this raw method remains useful at server byte
158
+ * boundaries and never exposes a Rust object layout.
159
+ */
160
+ query(queryBytes: Uint8Array): Uint8Array {
161
+ return this.session.query(queryBytes);
162
+ }
163
+
164
+ snapshot(): Uint8Array {
165
+ return this.session.snapshot();
166
+ }
167
+
168
+ frontier(): Uint8Array {
169
+ return this.session.frontier();
170
+ }
171
+
172
+ stateHash(): string {
173
+ return this.session.stateHash();
174
+ }
175
+
176
+ revision(): bigint {
177
+ return this.session.revision();
178
+ }
179
+
180
+ fork(): NativeSpreadsheetSession {
181
+ return new NativeSpreadsheetSession(this.runtime, this.session.fork());
182
+ }
183
+
184
+ isClosed(): boolean {
185
+ return this.session.isClosed();
186
+ }
187
+
188
+ dispose(): void {
189
+ this.session.dispose();
190
+ }
191
+ }
192
+
193
+ /** Exact synchronous N-API structured-document byte session. */
194
+ export class NativeDocumentSession {
195
+ readonly kind = "native" as const;
196
+ readonly modality = "document" as const;
197
+ readonly target: NativeArtifactRuntimeTarget;
198
+ readonly capabilities: ArtifactKernelCapabilities;
199
+ readonly buildIdentity: string;
200
+
201
+ private constructor(
202
+ private readonly runtime: ArtifactKernelRuntime,
203
+ private readonly session: ArtifactDocumentSession,
204
+ ) {
205
+ requireNativeRuntime(runtime);
206
+ this.target = runtime.target as NativeArtifactRuntimeTarget;
207
+ this.capabilities = runtime.capabilities;
208
+ this.buildIdentity = runtime.buildIdentity;
209
+ }
210
+
211
+ static create(runtime: ArtifactKernelRuntime, namespace: bigint): NativeDocumentSession {
212
+ requireNativeRuntime(runtime);
213
+ return new NativeDocumentSession(runtime, runtime.createDocumentSession(namespace));
214
+ }
215
+
216
+ static open(runtime: ArtifactKernelRuntime, snapshot: Uint8Array): NativeDocumentSession {
217
+ requireNativeRuntime(runtime);
218
+ return new NativeDocumentSession(runtime, runtime.openDocumentSession(snapshot));
219
+ }
220
+
221
+ applyCommands(commands: Uint8Array): Uint8Array {
222
+ return this.session.applyCommands(commands);
223
+ }
224
+ query(request: Uint8Array): Uint8Array {
225
+ return this.session.query(request);
226
+ }
227
+ snapshot(): Uint8Array {
228
+ return this.session.snapshot();
229
+ }
230
+ revision(): bigint {
231
+ return this.session.revision();
232
+ }
233
+ stateHash(): string {
234
+ return this.session.stateHash();
235
+ }
236
+ fork(): NativeDocumentSession {
237
+ return new NativeDocumentSession(this.runtime, this.session.fork());
238
+ }
239
+ isClosed(): boolean {
240
+ return this.session.isClosed();
241
+ }
242
+ dispose(): void {
243
+ this.session.dispose();
244
+ }
245
+ }
246
+
247
+ /** Exact synchronous N-API presentation byte session. */
248
+ export class NativePresentationSession {
249
+ readonly kind = "native" as const;
250
+ readonly modality = "presentation" as const;
251
+ readonly target: NativeArtifactRuntimeTarget;
252
+ readonly capabilities: ArtifactKernelCapabilities;
253
+ readonly buildIdentity: string;
254
+
255
+ private constructor(
256
+ private readonly runtime: ArtifactKernelRuntime,
257
+ private readonly session: ArtifactPresentationSession,
258
+ ) {
259
+ requireNativeRuntime(runtime);
260
+ this.target = runtime.target as NativeArtifactRuntimeTarget;
261
+ this.capabilities = runtime.capabilities;
262
+ this.buildIdentity = runtime.buildIdentity;
263
+ }
264
+
265
+ static create(runtime: ArtifactKernelRuntime, namespace: bigint): NativePresentationSession {
266
+ requireNativeRuntime(runtime);
267
+ return new NativePresentationSession(runtime, runtime.createPresentationSession(namespace));
268
+ }
269
+
270
+ static open(runtime: ArtifactKernelRuntime, snapshot: Uint8Array): NativePresentationSession {
271
+ requireNativeRuntime(runtime);
272
+ return new NativePresentationSession(runtime, runtime.openPresentationSession(snapshot));
273
+ }
274
+
275
+ applyCommands(commands: Uint8Array): Uint8Array {
276
+ return this.session.applyCommands(commands);
277
+ }
278
+ query(request: Uint8Array): Uint8Array {
279
+ return this.session.query(request);
280
+ }
281
+ snapshot(): Uint8Array {
282
+ return this.session.snapshot();
283
+ }
284
+ revision(): bigint {
285
+ return this.session.revision();
286
+ }
287
+ stateHash(): string {
288
+ return this.session.stateHash();
289
+ }
290
+ fork(): NativePresentationSession {
291
+ return new NativePresentationSession(this.runtime, this.session.fork());
292
+ }
293
+ isClosed(): boolean {
294
+ return this.session.isClosed();
295
+ }
296
+ dispose(): void {
297
+ this.session.dispose();
298
+ }
299
+ }
300
+
301
+ /** Exact synchronous N-API retained-font text-layout session. */
302
+ export class NativeTextLayoutSession {
303
+ readonly kind = "native" as const;
304
+ readonly modality = "text-layout" as const;
305
+ readonly target: NativeArtifactRuntimeTarget;
306
+ readonly capabilities: ArtifactKernelCapabilities;
307
+ readonly buildIdentity: string;
308
+
309
+ private constructor(
310
+ private readonly session: ArtifactTextLayoutSession,
311
+ runtime: ArtifactKernelRuntime,
312
+ ) {
313
+ requireNativeRuntime(runtime);
314
+ this.target = runtime.target as NativeArtifactRuntimeTarget;
315
+ this.capabilities = runtime.capabilities;
316
+ this.buildIdentity = runtime.buildIdentity;
317
+ }
318
+
319
+ static open(runtime: ArtifactKernelRuntime, fontBundle: Uint8Array): NativeTextLayoutSession {
320
+ requireNativeRuntime(runtime);
321
+ return new NativeTextLayoutSession(runtime.openTextLayoutSession(fontBundle), runtime);
322
+ }
323
+
324
+ layout(request: Uint8Array): Uint8Array {
325
+ return this.session.layout(request);
326
+ }
327
+ isClosed(): boolean {
328
+ return this.session.isClosed();
329
+ }
330
+ dispose(): void {
331
+ this.session.dispose();
332
+ }
333
+ }
334
+
335
+ /** Creates a production modality session; unsupported Rust modes fail closed. */
336
+ export function createNativeArtifactSession(
337
+ runtime: ArtifactKernelRuntime,
338
+ input: CreateNativeArtifactSessionInput,
339
+ ): NativeArtifactSession {
340
+ if (input.modality === "spreadsheet") {
341
+ return NativeSpreadsheetSession.create(runtime, input.replicaNamespace);
342
+ }
343
+ if (input.modality === "document") {
344
+ return NativeDocumentSession.create(runtime, input.replicaNamespace);
345
+ }
346
+ return NativePresentationSession.create(runtime, input.replicaNamespace);
347
+ }
348
+
349
+ /** Opens a production modality session; unsupported Rust modes fail closed. */
350
+ export function openNativeArtifactSession(
351
+ runtime: ArtifactKernelRuntime,
352
+ input: OpenNativeArtifactSessionInput,
353
+ ): NativeArtifactSession {
354
+ if (input.modality === "spreadsheet")
355
+ return NativeSpreadsheetSession.open(runtime, input.snapshot);
356
+ if (input.modality === "document") return NativeDocumentSession.open(runtime, input.snapshot);
357
+ return NativePresentationSession.open(runtime, input.snapshot);
358
+ }
359
+
360
+ function assertSpreadsheetIntent(intentBytes: Uint8Array): void {
361
+ const intent = decodeEditableArtifactMutationIntent(intentBytes);
362
+ if (
363
+ intent.envelopeVersion !== EDITABLE_ARTIFACT_INTENT_VERSION ||
364
+ intent.protocolVersion !== 1 ||
365
+ intent.modelSchemaVersion !== 1 ||
366
+ intent.commandProtocolVersion !== SPREADSHEET_ARTIFACT_COMMAND_VERSION
367
+ ) {
368
+ throw new ArtifactRuntimeError(
369
+ "ARTIFACT_RUNTIME_INCOMPATIBLE",
370
+ "Spreadsheet intent versions do not match the loaded production kernel",
371
+ );
372
+ }
373
+ assertCanonicalSpreadsheetArtifactCommandBytes(intent.commandBytes);
374
+ // Hashing decodes again by design and proves the exact outer bytes are an
375
+ // acceptable canonical request before they cross the native boundary.
376
+ hashEditableArtifactMutationIntentBytes(intentBytes);
377
+ }
378
+
379
+ function requireNativeSpreadsheetRuntime(runtime: ArtifactKernelRuntime): void {
380
+ requireNativeRuntime(runtime);
381
+ }
382
+
383
+ function requireNativeRuntime(runtime: ArtifactKernelRuntime): void {
384
+ if (runtime.kind !== "native" || runtime.target === "wasm-web") {
385
+ throw new ArtifactRuntimeError(
386
+ "ARTIFACT_RUNTIME_UNAVAILABLE",
387
+ "NativeSpreadsheetSession requires an exact local N-API kernel; browser editing uses @opengeni/sdk/editable-artifacts",
388
+ );
389
+ }
390
+ }