@opengeni/artifact-tool 0.2.8 → 0.3.4-canary.0

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 (57) hide show
  1. package/dist/{chunk-ZCJYRJGB.js → chunk-4XJE7NRA.js} +2 -2
  2. package/dist/{chunk-N2IHNWBS.js → chunk-4YYYUZQH.js} +15 -6
  3. package/dist/chunk-4YYYUZQH.js.map +1 -0
  4. package/dist/{chunk-U5G2BKM2.js → chunk-LMLPFF3S.js} +12 -6
  5. package/dist/{chunk-U5G2BKM2.js.map → chunk-LMLPFF3S.js.map} +1 -1
  6. package/dist/{chunk-B2ZJRZDA.js → chunk-LVPFJH2Z.js} +7 -5
  7. package/dist/chunk-LVPFJH2Z.js.map +1 -0
  8. package/dist/{chunk-QZI5POCC.js → chunk-OVXX4G35.js} +2 -2
  9. package/dist/{chunk-6PBM7FKI.js → chunk-QA3NXBAG.js} +8 -7
  10. package/dist/chunk-QA3NXBAG.js.map +1 -0
  11. package/dist/{chunk-XT2EJFCU.js → chunk-SYFNJGH5.js} +30 -8
  12. package/dist/chunk-SYFNJGH5.js.map +1 -0
  13. package/dist/{chunk-RU5G3HNF.js → chunk-XAZTHG6W.js} +20 -9
  14. package/dist/chunk-XAZTHG6W.js.map +1 -0
  15. package/dist/index.js +4 -4
  16. package/dist/kernel.d.ts +0 -19
  17. package/dist/materializer-cli-entry.js +7 -7
  18. package/dist/materializer-cli.d.ts +4 -3
  19. package/dist/materializer-cli.js +7 -7
  20. package/dist/native.d.ts +1 -1
  21. package/dist/native.js +2 -2
  22. package/dist/office-import.d.ts +15 -5
  23. package/dist/office-import.js +25 -8
  24. package/dist/office-import.js.map +1 -1
  25. package/dist/production-document.js +4 -4
  26. package/dist/production-presentation.js +4 -4
  27. package/dist/production-spreadsheet.js +4 -4
  28. package/dist/reference.js +1 -365
  29. package/dist/reference.js.map +1 -1
  30. package/dist/runtime-cli-entry.js +3 -3
  31. package/dist/runtime-cli.js +2 -2
  32. package/dist/runtime-development.js +3 -3
  33. package/dist/runtime-receipt.d.ts +3 -2
  34. package/dist/runtime.d.ts +8 -6
  35. package/dist/runtime.js +1 -1
  36. package/dist/snapshot.d.ts +13 -6
  37. package/dist/snapshot.js +23 -11
  38. package/dist/snapshot.js.map +1 -1
  39. package/dist/spreadsheet-xlsx-codec.js +2 -2
  40. package/dist/spreadsheet.js +1 -1
  41. package/package.json +5 -5
  42. package/src/kernel.ts +1 -397
  43. package/src/materializer-cli.ts +20 -9
  44. package/src/native.ts +7 -5
  45. package/src/office-import.ts +47 -18
  46. package/src/production-spreadsheet-native.ts +4 -3
  47. package/src/runtime-receipt.ts +16 -5
  48. package/src/runtime.ts +22 -10
  49. package/src/snapshot.ts +39 -17
  50. package/src/spreadsheet-formula.ts +35 -7
  51. package/dist/chunk-6PBM7FKI.js.map +0 -1
  52. package/dist/chunk-B2ZJRZDA.js.map +0 -1
  53. package/dist/chunk-N2IHNWBS.js.map +0 -1
  54. package/dist/chunk-RU5G3HNF.js.map +0 -1
  55. package/dist/chunk-XT2EJFCU.js.map +0 -1
  56. /package/dist/{chunk-ZCJYRJGB.js.map → chunk-4XJE7NRA.js.map} +0 -0
  57. /package/dist/{chunk-QZI5POCC.js.map → chunk-OVXX4G35.js.map} +0 -0
package/dist/snapshot.js CHANGED
@@ -5,26 +5,27 @@ import {
5
5
  NativeDocumentSession,
6
6
  NativePresentationSession,
7
7
  NativeSpreadsheetSession
8
- } from "./chunk-B2ZJRZDA.js";
9
- import "./chunk-N2IHNWBS.js";
8
+ } from "./chunk-LVPFJH2Z.js";
9
+ import "./chunk-4YYYUZQH.js";
10
10
  import "./chunk-VUNV25KB.js";
11
11
 
12
12
  // src/snapshot.ts
13
13
  import {
14
14
  COMMITTED_TRANSACTION_PROTOCOL_VERSION,
15
- EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,
16
- EDITABLE_ARTIFACT_SNAPSHOT_VERSION
15
+ DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,
16
+ DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,
17
+ PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,
18
+ PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,
19
+ SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
20
+ SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION
17
21
  } from "@opengeni/contracts/editable-artifact-versions";
18
22
  function createArtifactSnapshot(artifact) {
19
23
  const state = requireCompositeState(artifact);
20
24
  const native = state.native;
21
25
  const common = {
22
26
  schemaVersion: 1,
23
- modality: state.modality,
24
27
  runtimeTarget: native.target,
25
28
  kernelVersion: native.buildIdentity,
26
- modelSchemaVersion: EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,
27
- snapshotVersion: EDITABLE_ARTIFACT_SNAPSHOT_VERSION,
28
29
  stateHash: native.stateHash(),
29
30
  snapshotBytes: Uint8Array.from(native.snapshot())
30
31
  };
@@ -35,18 +36,29 @@ function createArtifactSnapshot(artifact) {
35
36
  return Object.freeze({
36
37
  ...common,
37
38
  modality: "spreadsheet",
39
+ modelSchemaVersion: SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
40
+ snapshotVersion: SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
38
41
  coveredCausalFrontierBytes: Uint8Array.from(native.frontier()),
39
42
  operationProtocolVersion: COMMITTED_TRANSACTION_PROTOCOL_VERSION,
40
- crdtStateVersion: EDITABLE_ARTIFACT_SNAPSHOT_VERSION
43
+ crdtStateVersion: SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION
41
44
  });
42
45
  }
43
46
  if (!(native instanceof NativeDocumentSession) && !(native instanceof NativePresentationSession)) {
44
47
  throw new Error("Serialized composite does not own its expected native session");
45
48
  }
46
- return Object.freeze({
49
+ const nativeRevision = safeNativeRevision(native.revision());
50
+ return state.modality === "document" ? Object.freeze({
47
51
  ...common,
48
- modality: state.modality,
49
- nativeRevision: safeNativeRevision(native.revision())
52
+ modality: "document",
53
+ modelSchemaVersion: DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,
54
+ snapshotVersion: DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,
55
+ nativeRevision
56
+ }) : Object.freeze({
57
+ ...common,
58
+ modality: "presentation",
59
+ modelSchemaVersion: PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,
60
+ snapshotVersion: PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,
61
+ nativeRevision
50
62
  });
51
63
  }
52
64
  function safeNativeRevision(value) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/snapshot.ts"],"sourcesContent":["import {\n COMMITTED_TRANSACTION_PROTOCOL_VERSION,\n EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,\n EDITABLE_ARTIFACT_SNAPSHOT_VERSION,\n} from \"@opengeni/contracts/editable-artifact-versions\";\nimport type { Document } from \"./document\";\nimport {\n NativeDocumentSession,\n NativePresentationSession,\n NativeSpreadsheetSession,\n} from \"./native\";\nimport type { Presentation } from \"./presentation\";\nimport { requireCompositeState } from \"./production-composite\";\nimport type { Workbook } from \"./spreadsheet\";\n\ntype ArtifactSnapshotCommon = Readonly<{\n schemaVersion: 1;\n modality: \"spreadsheet\" | \"document\" | \"presentation\";\n runtimeTarget: string;\n kernelVersion: string;\n modelSchemaVersion: 1;\n snapshotVersion: 1;\n stateHash: string;\n snapshotBytes: Uint8Array;\n}>;\n\n/** Exact native-canonical state at one durable artifact boundary. */\nexport type ArtifactSnapshot =\n | (ArtifactSnapshotCommon &\n Readonly<{\n modality: \"spreadsheet\";\n coveredCausalFrontierBytes: Uint8Array;\n operationProtocolVersion: 1;\n crdtStateVersion: 1;\n }>)\n | (ArtifactSnapshotCommon &\n Readonly<{\n modality: \"document\" | \"presentation\";\n nativeRevision: number;\n }>);\n\n/** Capture one immutable native snapshot from an open artifact object. */\nexport function createArtifactSnapshot(\n artifact: Workbook | Document | Presentation,\n): ArtifactSnapshot {\n const state = requireCompositeState(artifact);\n const native = state.native;\n const common = {\n schemaVersion: 1 as const,\n modality: state.modality,\n runtimeTarget: native.target,\n kernelVersion: native.buildIdentity,\n modelSchemaVersion: EDITABLE_ARTIFACT_MODEL_SCHEMA_VERSION,\n snapshotVersion: EDITABLE_ARTIFACT_SNAPSHOT_VERSION,\n stateHash: native.stateHash(),\n snapshotBytes: Uint8Array.from(native.snapshot()),\n };\n if (state.modality === \"spreadsheet\") {\n if (!(native instanceof NativeSpreadsheetSession)) {\n throw new Error(\"Spreadsheet composite does not own a spreadsheet native session\");\n }\n return Object.freeze({\n ...common,\n modality: \"spreadsheet\" as const,\n coveredCausalFrontierBytes: Uint8Array.from(native.frontier()),\n operationProtocolVersion: COMMITTED_TRANSACTION_PROTOCOL_VERSION,\n crdtStateVersion: EDITABLE_ARTIFACT_SNAPSHOT_VERSION,\n });\n }\n if (\n !(native instanceof NativeDocumentSession) &&\n !(native instanceof NativePresentationSession)\n ) {\n throw new Error(\"Serialized composite does not own its expected native session\");\n }\n return Object.freeze({\n ...common,\n modality: state.modality,\n nativeRevision: safeNativeRevision(native.revision()),\n });\n}\n\nfunction safeNativeRevision(value: bigint): number {\n if (value < 0n || value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new RangeError(\"Artifact native revision exceeds the durable range\");\n }\n return Number(value);\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAsCA,SAAS,uBACd,UACkB;AAClB,QAAM,QAAQ,sBAAsB,QAAQ;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,SAAS;AAAA,IACb,eAAe;AAAA,IACf,UAAU,MAAM;AAAA,IAChB,eAAe,OAAO;AAAA,IACtB,eAAe,OAAO;AAAA,IACtB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,WAAW,OAAO,UAAU;AAAA,IAC5B,eAAe,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,EAClD;AACA,MAAI,MAAM,aAAa,eAAe;AACpC,QAAI,EAAE,kBAAkB,2BAA2B;AACjD,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AACA,WAAO,OAAO,OAAO;AAAA,MACnB,GAAG;AAAA,MACH,UAAU;AAAA,MACV,4BAA4B,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,MAC7D,0BAA0B;AAAA,MAC1B,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH;AACA,MACE,EAAE,kBAAkB,0BACpB,EAAE,kBAAkB,4BACpB;AACA,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,SAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,UAAU,MAAM;AAAA,IAChB,gBAAgB,mBAAmB,OAAO,SAAS,CAAC;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,mBAAmB,OAAuB;AACjD,MAAI,QAAQ,MAAM,QAAQ,OAAO,OAAO,gBAAgB,GAAG;AACzD,UAAM,IAAI,WAAW,oDAAoD;AAAA,EAC3E;AACA,SAAO,OAAO,KAAK;AACrB;","names":[]}
1
+ {"version":3,"sources":["../src/snapshot.ts"],"sourcesContent":["import {\n COMMITTED_TRANSACTION_PROTOCOL_VERSION,\n DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,\n DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,\n PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,\n PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,\n SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,\n SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,\n} from \"@opengeni/contracts/editable-artifact-versions\";\nimport type { Document } from \"./document\";\nimport {\n NativeDocumentSession,\n NativePresentationSession,\n NativeSpreadsheetSession,\n} from \"./native\";\nimport type { Presentation } from \"./presentation\";\nimport { requireCompositeState } from \"./production-composite\";\nimport type { Workbook } from \"./spreadsheet\";\n\ntype ArtifactSnapshotCommon = Readonly<{\n schemaVersion: 1;\n runtimeTarget: string;\n kernelVersion: string;\n stateHash: string;\n snapshotBytes: Uint8Array;\n}>;\n\n/** Exact native-canonical state at one durable artifact boundary. */\nexport type ArtifactSnapshot =\n | (ArtifactSnapshotCommon &\n Readonly<{\n modality: \"spreadsheet\";\n modelSchemaVersion: typeof SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION;\n snapshotVersion: typeof SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION;\n coveredCausalFrontierBytes: Uint8Array;\n operationProtocolVersion: typeof COMMITTED_TRANSACTION_PROTOCOL_VERSION;\n crdtStateVersion: typeof SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION;\n }>)\n | (ArtifactSnapshotCommon &\n Readonly<{\n modality: \"document\";\n modelSchemaVersion: typeof DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION;\n snapshotVersion: typeof DOCUMENT_ARTIFACT_SNAPSHOT_VERSION;\n nativeRevision: number;\n }>)\n | (ArtifactSnapshotCommon &\n Readonly<{\n modality: \"presentation\";\n modelSchemaVersion: typeof PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION;\n snapshotVersion: typeof PRESENTATION_ARTIFACT_SNAPSHOT_VERSION;\n nativeRevision: number;\n }>);\n\n/** Capture one immutable native snapshot from an open artifact object. */\nexport function createArtifactSnapshot(\n artifact: Workbook | Document | Presentation,\n): ArtifactSnapshot {\n const state = requireCompositeState(artifact);\n const native = state.native;\n const common = {\n schemaVersion: 1 as const,\n runtimeTarget: native.target,\n kernelVersion: native.buildIdentity,\n stateHash: native.stateHash(),\n snapshotBytes: Uint8Array.from(native.snapshot()),\n };\n if (state.modality === \"spreadsheet\") {\n if (!(native instanceof NativeSpreadsheetSession)) {\n throw new Error(\"Spreadsheet composite does not own a spreadsheet native session\");\n }\n return Object.freeze({\n ...common,\n modality: \"spreadsheet\" as const,\n modelSchemaVersion: SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,\n snapshotVersion: SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,\n coveredCausalFrontierBytes: Uint8Array.from(native.frontier()),\n operationProtocolVersion: COMMITTED_TRANSACTION_PROTOCOL_VERSION,\n crdtStateVersion: SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,\n });\n }\n if (\n !(native instanceof NativeDocumentSession) &&\n !(native instanceof NativePresentationSession)\n ) {\n throw new Error(\"Serialized composite does not own its expected native session\");\n }\n const nativeRevision = safeNativeRevision(native.revision());\n return state.modality === \"document\"\n ? Object.freeze({\n ...common,\n modality: \"document\" as const,\n modelSchemaVersion: DOCUMENT_ARTIFACT_MODEL_SCHEMA_VERSION,\n snapshotVersion: DOCUMENT_ARTIFACT_SNAPSHOT_VERSION,\n nativeRevision,\n })\n : Object.freeze({\n ...common,\n modality: \"presentation\" as const,\n modelSchemaVersion: PRESENTATION_ARTIFACT_MODEL_SCHEMA_VERSION,\n snapshotVersion: PRESENTATION_ARTIFACT_SNAPSHOT_VERSION,\n nativeRevision,\n });\n}\n\nfunction safeNativeRevision(value: bigint): number {\n if (value < 0n || value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new RangeError(\"Artifact native revision exceeds the durable range\");\n }\n return Number(value);\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA8CA,SAAS,uBACd,UACkB;AAClB,QAAM,QAAQ,sBAAsB,QAAQ;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,SAAS;AAAA,IACb,eAAe;AAAA,IACf,eAAe,OAAO;AAAA,IACtB,eAAe,OAAO;AAAA,IACtB,WAAW,OAAO,UAAU;AAAA,IAC5B,eAAe,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,EAClD;AACA,MAAI,MAAM,aAAa,eAAe;AACpC,QAAI,EAAE,kBAAkB,2BAA2B;AACjD,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AACA,WAAO,OAAO,OAAO;AAAA,MACnB,GAAG;AAAA,MACH,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,4BAA4B,WAAW,KAAK,OAAO,SAAS,CAAC;AAAA,MAC7D,0BAA0B;AAAA,MAC1B,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH;AACA,MACE,EAAE,kBAAkB,0BACpB,EAAE,kBAAkB,4BACpB;AACA,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,QAAM,iBAAiB,mBAAmB,OAAO,SAAS,CAAC;AAC3D,SAAO,MAAM,aAAa,aACtB,OAAO,OAAO;AAAA,IACZ,GAAG;AAAA,IACH,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB;AAAA,EACF,CAAC,IACD,OAAO,OAAO;AAAA,IACZ,GAAG;AAAA,IACH,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB;AAAA,EACF,CAAC;AACP;AAEA,SAAS,mBAAmB,OAAuB;AACjD,MAAI,QAAQ,MAAM,QAAQ,OAAO,OAAO,gBAAgB,GAAG;AACzD,UAAM,IAAI,WAAW,oDAAoD;AAAA,EAC3E;AACA,SAAO,OAAO,KAAK;AACrB;","names":[]}
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  SpreadsheetXlsxCodec
3
- } from "./chunk-QZI5POCC.js";
3
+ } from "./chunk-OVXX4G35.js";
4
4
  import "./chunk-J6N7IR44.js";
5
- import "./chunk-XT2EJFCU.js";
5
+ import "./chunk-SYFNJGH5.js";
6
6
  import "./chunk-4FRFNNBM.js";
7
7
  import "./chunk-FGZM4FQ6.js";
8
8
  import "./chunk-72SYDU4O.js";
@@ -26,7 +26,7 @@ import {
26
26
  Worksheet,
27
27
  WorksheetCollection,
28
28
  validateSerializedWorkbook
29
- } from "./chunk-XT2EJFCU.js";
29
+ } from "./chunk-SYFNJGH5.js";
30
30
  import {
31
31
  InvalidSpreadsheetImageError
32
32
  } from "./chunk-4FRFNNBM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/artifact-tool",
3
- "version": "0.2.8",
3
+ "version": "0.3.4-canary.0",
4
4
  "description": "OpenGeni-owned document, spreadsheet, and presentation engine with skill-compatible authoring APIs.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -104,18 +104,18 @@
104
104
  "bench": "bun bench/run.ts",
105
105
  "bench:deep": "bun bench/run.ts --deep",
106
106
  "bench:release": "bun bench/release.ts",
107
- "test:kernel": "cargo test --manifest-path kernel/Cargo.toml",
107
+ "test:kernel": "bun ../../scripts/artifact-kernel-rust.ts cargo test --manifest-path kernel/Cargo.toml",
108
108
  "test:kernel-packages": "bun ../../scripts/test-artifact-kernel-package-consumers.ts",
109
109
  "test:production-native": "bun ../../scripts/run-artifact-native-tests.ts",
110
- "bench:kernel": "cargo bench --manifest-path kernel/Cargo.toml --bench kernel",
110
+ "bench:kernel": "bun ../../scripts/artifact-kernel-rust.ts cargo bench --manifest-path kernel/Cargo.toml --bench kernel",
111
111
  "test:perf": "bun test --timeout 30000 test/perf",
112
- "fuzz:check": "cargo check --manifest-path kernel/fuzz/Cargo.toml",
112
+ "fuzz:check": "bun ../../scripts/artifact-kernel-rust.ts cargo check --manifest-path kernel/fuzz/Cargo.toml",
113
113
  "fuzz:smoke": "bun kernel/fuzz/smoke.ts",
114
114
  "typecheck": "tsc --noEmit",
115
115
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
116
116
  },
117
117
  "dependencies": {
118
- "@opengeni/contracts": "^0.50.0",
118
+ "@opengeni/contracts": "^2.2.0-canary.0",
119
119
  "@resvg/resvg-js": "^2.6.2",
120
120
  "docx": "9.7.1",
121
121
  "exceljs": "^4.4.0",
package/src/kernel.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ArtifactLimitError, UnsupportedArtifactFeatureError } from "./errors";
1
+ import { UnsupportedArtifactFeatureError } from "./errors";
2
2
  import { FileBlob } from "./file-blob";
3
3
 
4
4
  export type ArtifactModality = "spreadsheet" | "presentation" | "document";
@@ -124,402 +124,6 @@ export class ArtifactKernelRegistry {
124
124
  }
125
125
  }
126
126
 
127
- export const ARTIFACT_OPERATION_MAX_BYTES = 1024 * 1024;
128
- export const ARTIFACT_OPERATION_MAX_COMMANDS = 10_000;
129
- export const ARTIFACT_OPERATION_MAX_VECTOR_ACTORS = 1_024;
130
- export const ARTIFACT_OPERATION_MAX_STRING_BYTES = 256 * 1024;
131
- export const ARTIFACT_OPERATION_MAX_JSON_DEPTH = 64;
132
- export const ARTIFACT_OPERATION_MAX_JSON_NODES = 100_000;
133
- const OPERATION_MAGIC = new Uint8Array([0x4f, 0x47, 0x41, 0x52]); // OGAR
134
- const textEncoder = new TextEncoder();
135
- const textDecoder = new TextDecoder("utf-8", { fatal: true });
136
-
137
- /**
138
- * Deterministic codec retained only for historical TypeScript conformance
139
- * fixtures.
140
- *
141
- * @deprecated OGAR duplicates authored identity/causality and must never be
142
- * persisted, submitted, or lowered by a production runtime. Use the canonical
143
- * OGATX001 envelope with an identity-free OGASC001 command payload from
144
- * `@opengeni/contracts/editable-artifacts`.
145
- */
146
- export const ArtifactCommandBatchCodec = {
147
- encode(batch: ArtifactCommandBatch): Uint8Array {
148
- validateBatch(batch);
149
- const writer = new BinaryWriter(ARTIFACT_OPERATION_MAX_BYTES);
150
- writer.bytes(OPERATION_MAGIC);
151
- writer.varint(batch.schemaVersion);
152
- writer.varint(modalityCode(batch.modality));
153
- writer.string(batch.artifactId);
154
- writer.string(batch.transactionId);
155
- writer.string(batch.actorId);
156
- writer.varint(batch.baseSequence);
157
- const vector = Object.entries(batch.baseVector).sort(([left], [right]) =>
158
- left < right ? -1 : left > right ? 1 : 0,
159
- );
160
- writer.varint(vector.length);
161
- for (const [actor, counter] of vector) {
162
- writer.string(actor);
163
- writer.varint(counter);
164
- }
165
- writer.varint(batch.commands.length);
166
- for (const command of batch.commands) {
167
- writer.string(command.code);
168
- writer.string(command.targetId ?? "");
169
- let flags = 0;
170
- if (command.precondition?.objectRevision !== undefined) flags |= 1;
171
- if (command.precondition?.exists !== undefined) flags |= 2;
172
- if (command.payload !== undefined) flags |= 4;
173
- writer.byte(flags);
174
- if ((flags & 1) !== 0) writer.varint(command.precondition!.objectRevision!);
175
- if ((flags & 2) !== 0) writer.byte(command.precondition!.exists ? 1 : 0);
176
- if ((flags & 4) !== 0) writer.string(canonicalJson(command.payload));
177
- }
178
- return writer.finish();
179
- },
180
-
181
- decode(bytes: Uint8Array): ArtifactCommandBatch {
182
- if (bytes.byteLength > ARTIFACT_OPERATION_MAX_BYTES) {
183
- throw new ArtifactLimitError(
184
- "operation bytes",
185
- bytes.byteLength,
186
- ARTIFACT_OPERATION_MAX_BYTES,
187
- );
188
- }
189
- const reader = new BinaryReader(bytes);
190
- const magic = reader.bytes(OPERATION_MAGIC.length);
191
- if (!magic.every((value, index) => value === OPERATION_MAGIC[index])) {
192
- throw new Error("Invalid artifact operation magic");
193
- }
194
- const schemaVersion = reader.varint();
195
- if (schemaVersion !== 1)
196
- throw new Error(`Unsupported artifact operation schema: ${schemaVersion}`);
197
- const modality = modalityFromCode(reader.varint());
198
- const artifactId = reader.string();
199
- const transactionId = reader.string();
200
- const actorId = reader.string();
201
- const baseSequence = reader.varint();
202
- const vectorCount = reader.varint();
203
- if (vectorCount > ARTIFACT_OPERATION_MAX_VECTOR_ACTORS) {
204
- throw new ArtifactLimitError(
205
- "causal vector actors",
206
- vectorCount,
207
- ARTIFACT_OPERATION_MAX_VECTOR_ACTORS,
208
- );
209
- }
210
- const vectorEntries: Array<readonly [string, number]> = [];
211
- let previousActor = "";
212
- for (let index = 0; index < vectorCount; index += 1) {
213
- const actor = reader.string();
214
- if (actor <= previousActor) {
215
- throw new Error("Causal vector actors must be unique and sorted");
216
- }
217
- previousActor = actor;
218
- vectorEntries.push([actor, reader.varint()]);
219
- }
220
- // Object.fromEntries defines data properties instead of invoking the legacy
221
- // `__proto__` setter. Actor identifiers therefore round-trip without
222
- // mutating the vector object's prototype or silently losing an entry.
223
- const baseVector = Object.fromEntries(vectorEntries);
224
- const commandCount = reader.varint();
225
- if (commandCount > ARTIFACT_OPERATION_MAX_COMMANDS) {
226
- throw new ArtifactLimitError(
227
- "operation commands",
228
- commandCount,
229
- ARTIFACT_OPERATION_MAX_COMMANDS,
230
- );
231
- }
232
- const commands: ArtifactCommand[] = [];
233
- for (let index = 0; index < commandCount; index += 1) {
234
- const code = reader.string();
235
- const targetId = reader.string();
236
- const flags = reader.byte();
237
- if ((flags & ~7) !== 0) throw new Error("Unknown artifact command flags");
238
- const objectRevision = (flags & 1) !== 0 ? reader.varint() : undefined;
239
- let exists: boolean | undefined;
240
- if ((flags & 2) !== 0) {
241
- const encodedExists = reader.byte();
242
- if (encodedExists > 1) {
243
- throw new Error("Artifact command boolean uses a non-canonical encoding");
244
- }
245
- exists = encodedExists === 1;
246
- }
247
- const payload = (flags & 4) !== 0 ? parseCanonicalJson(reader.string()) : undefined;
248
- commands.push({
249
- code,
250
- ...(targetId ? { targetId } : {}),
251
- ...(objectRevision !== undefined || exists !== undefined
252
- ? {
253
- precondition: {
254
- ...(objectRevision !== undefined ? { objectRevision } : {}),
255
- ...(exists !== undefined ? { exists } : {}),
256
- },
257
- }
258
- : {}),
259
- ...(payload !== undefined ? { payload } : {}),
260
- });
261
- }
262
- reader.done();
263
- const batch: ArtifactCommandBatch = {
264
- schemaVersion: 1,
265
- artifactId,
266
- modality,
267
- transactionId,
268
- actorId,
269
- baseSequence,
270
- baseVector,
271
- commands,
272
- };
273
- validateBatch(batch);
274
- return batch;
275
- },
276
- };
277
-
278
- function validateBatch(batch: ArtifactCommandBatch): void {
279
- if (batch.schemaVersion !== 1) throw new Error("Artifact operation schema must be 1");
280
- for (const [label, value] of [
281
- ["artifactId", batch.artifactId],
282
- ["transactionId", batch.transactionId],
283
- ["actorId", batch.actorId],
284
- ] as const) {
285
- if (!value || value.length > 512) throw new Error(`${label} must contain 1-512 characters`);
286
- }
287
- assertSafeInteger(batch.baseSequence, "baseSequence");
288
- const vector = Object.entries(batch.baseVector);
289
- if (vector.length > ARTIFACT_OPERATION_MAX_VECTOR_ACTORS) {
290
- throw new ArtifactLimitError(
291
- "causal vector actors",
292
- vector.length,
293
- ARTIFACT_OPERATION_MAX_VECTOR_ACTORS,
294
- );
295
- }
296
- for (const [actor, counter] of vector) {
297
- if (!actor || actor.length > 512)
298
- throw new Error("Causal vector actor must contain 1-512 characters");
299
- assertSafeInteger(counter, `baseVector.${actor}`);
300
- }
301
- if (batch.commands.length > ARTIFACT_OPERATION_MAX_COMMANDS) {
302
- throw new ArtifactLimitError(
303
- "operation commands",
304
- batch.commands.length,
305
- ARTIFACT_OPERATION_MAX_COMMANDS,
306
- );
307
- }
308
- if (batch.commands.length === 0) throw new Error("Artifact command batch must not be empty");
309
- for (const command of batch.commands) {
310
- if (!/^[a-z][a-z0-9_.-]{0,127}$/.test(command.code))
311
- throw new Error(`Invalid artifact command code: ${command.code}`);
312
- if (
313
- command.targetId !== undefined &&
314
- (command.targetId.length === 0 || command.targetId.length > 512)
315
- ) {
316
- throw new Error("Artifact command target id must contain 1-512 characters");
317
- }
318
- if (command.precondition?.objectRevision !== undefined) {
319
- assertSafeInteger(command.precondition.objectRevision, "objectRevision");
320
- }
321
- }
322
- }
323
-
324
127
  function defaultKernelOrder(): readonly ArtifactKernelKind[] {
325
128
  return typeof window === "undefined" ? ["native"] : [];
326
129
  }
327
-
328
- function modalityCode(modality: ArtifactModality): number {
329
- return { spreadsheet: 1, presentation: 2, document: 3 }[modality];
330
- }
331
-
332
- function modalityFromCode(value: number): ArtifactModality {
333
- if (value === 1) return "spreadsheet";
334
- if (value === 2) return "presentation";
335
- if (value === 3) return "document";
336
- throw new Error(`Unknown artifact modality code: ${value}`);
337
- }
338
-
339
- function assertSafeInteger(value: number, label: string): void {
340
- if (!Number.isSafeInteger(value) || value < 0)
341
- throw new Error(`${label} must be a non-negative safe integer`);
342
- }
343
-
344
- function canonicalJson(value: unknown): string {
345
- return JSON.stringify(canonicalValue(value, { nodes: 0 }, 0));
346
- }
347
-
348
- function canonicalValue(value: unknown, state: { nodes: number }, depth: number): unknown {
349
- state.nodes += 1;
350
- if (state.nodes > ARTIFACT_OPERATION_MAX_JSON_NODES) {
351
- throw new ArtifactLimitError(
352
- "operation JSON nodes",
353
- state.nodes,
354
- ARTIFACT_OPERATION_MAX_JSON_NODES,
355
- );
356
- }
357
- if (depth > ARTIFACT_OPERATION_MAX_JSON_DEPTH) {
358
- throw new ArtifactLimitError("operation JSON depth", depth, ARTIFACT_OPERATION_MAX_JSON_DEPTH);
359
- }
360
- if (value === null || typeof value === "string" || typeof value === "boolean") return value;
361
- if (typeof value === "number") {
362
- if (!Number.isFinite(value))
363
- throw new Error("Artifact command JSON cannot contain non-finite numbers");
364
- return Object.is(value, -0) ? 0 : value;
365
- }
366
- if (Array.isArray(value)) {
367
- if (Object.keys(value).length !== value.length || Object.getOwnPropertySymbols(value).length) {
368
- throw new Error("Artifact command payload arrays must be dense JSON arrays");
369
- }
370
- const output: unknown[] = [];
371
- for (let index = 0; index < value.length; index += 1) {
372
- const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
373
- if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
374
- throw new Error("Artifact command payload arrays must contain data properties");
375
- }
376
- output.push(canonicalValue(descriptor.value, state, depth + 1));
377
- }
378
- return output;
379
- }
380
- if (typeof value === "object") {
381
- if (Object.getPrototypeOf(value) !== Object.prototype)
382
- throw new Error("Artifact command payload must be plain JSON");
383
- const record = value as Record<string, unknown>;
384
- const keys = Reflect.ownKeys(record);
385
- if (keys.some((key) => typeof key !== "string")) {
386
- throw new Error("Artifact command payload cannot contain symbol properties");
387
- }
388
- return Object.fromEntries(
389
- (keys as string[]).sort().map((key) => {
390
- const descriptor = Object.getOwnPropertyDescriptor(record, key);
391
- if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
392
- throw new Error("Artifact command payload properties must be enumerable data properties");
393
- }
394
- return [key, canonicalValue(descriptor.value, state, depth + 1)];
395
- }),
396
- );
397
- }
398
- throw new Error(`Artifact command payload contains unsupported ${typeof value}`);
399
- }
400
-
401
- function parseCanonicalJson(value: string): unknown {
402
- const parsed: unknown = JSON.parse(value);
403
- if (canonicalJson(parsed) !== value)
404
- throw new Error("Artifact command payload is not canonical JSON");
405
- return parsed;
406
- }
407
-
408
- class BinaryWriter {
409
- private buffer = new Uint8Array(1_024);
410
- private length = 0;
411
- constructor(private readonly maximum: number) {}
412
-
413
- byte(value: number): void {
414
- this.ensure(1);
415
- this.buffer[this.length++] = value;
416
- }
417
-
418
- bytes(value: Uint8Array): void {
419
- this.ensure(value.byteLength);
420
- this.buffer.set(value, this.length);
421
- this.length += value.byteLength;
422
- }
423
-
424
- varint(value: number): void {
425
- assertSafeInteger(value, "varint");
426
- let remaining = BigInt(value);
427
- do {
428
- let byte = Number(remaining & 0x7fn);
429
- remaining >>= 7n;
430
- if (remaining > 0n) byte |= 0x80;
431
- this.byte(byte);
432
- } while (remaining > 0n);
433
- }
434
-
435
- string(value: string): void {
436
- const bytes = textEncoder.encode(value);
437
- if (bytes.byteLength > ARTIFACT_OPERATION_MAX_STRING_BYTES) {
438
- throw new ArtifactLimitError(
439
- "operation string bytes",
440
- bytes.byteLength,
441
- ARTIFACT_OPERATION_MAX_STRING_BYTES,
442
- );
443
- }
444
- this.varint(bytes.byteLength);
445
- this.bytes(bytes);
446
- }
447
-
448
- finish(): Uint8Array {
449
- return this.buffer.slice(0, this.length);
450
- }
451
-
452
- private ensure(extra: number): void {
453
- const required = this.length + extra;
454
- if (required > this.maximum)
455
- throw new ArtifactLimitError("operation bytes", required, this.maximum);
456
- if (required <= this.buffer.byteLength) return;
457
- let nextSize = this.buffer.byteLength;
458
- while (nextSize < required) nextSize = Math.min(this.maximum, nextSize * 2);
459
- const next = new Uint8Array(nextSize);
460
- next.set(this.buffer);
461
- this.buffer = next;
462
- }
463
- }
464
-
465
- class BinaryReader {
466
- private offset = 0;
467
- constructor(private readonly input: Uint8Array) {}
468
-
469
- byte(): number {
470
- const value = this.input[this.offset];
471
- if (value === undefined) throw new Error("Truncated artifact operation");
472
- this.offset += 1;
473
- return value;
474
- }
475
-
476
- bytes(length: number): Uint8Array {
477
- if (
478
- !Number.isSafeInteger(length) ||
479
- length < 0 ||
480
- this.offset + length > this.input.byteLength
481
- ) {
482
- throw new Error("Truncated artifact operation bytes");
483
- }
484
- const value = this.input.subarray(this.offset, this.offset + length);
485
- this.offset += length;
486
- return value;
487
- }
488
-
489
- varint(): number {
490
- let value = 0n;
491
- let shift = 0n;
492
- for (let index = 0; index < 10; index += 1) {
493
- const byte = this.byte();
494
- value |= BigInt(byte & 0x7f) << shift;
495
- if ((byte & 0x80) === 0) {
496
- if (index > 0 && byte === 0) {
497
- throw new Error("Artifact operation varint is non-canonical");
498
- }
499
- const number = Number(value);
500
- if (!Number.isSafeInteger(number))
501
- throw new Error("Artifact operation varint exceeds safe integer");
502
- return number;
503
- }
504
- shift += 7n;
505
- }
506
- throw new Error("Invalid artifact operation varint");
507
- }
508
-
509
- string(): string {
510
- const length = this.varint();
511
- if (length > ARTIFACT_OPERATION_MAX_STRING_BYTES) {
512
- throw new ArtifactLimitError(
513
- "operation string bytes",
514
- length,
515
- ARTIFACT_OPERATION_MAX_STRING_BYTES,
516
- );
517
- }
518
- return textDecoder.decode(this.bytes(length));
519
- }
520
-
521
- done(): void {
522
- if (this.offset !== this.input.byteLength)
523
- throw new Error("Artifact operation has trailing bytes");
524
- }
525
- }
@@ -13,6 +13,11 @@ import {
13
13
  type SpreadsheetArtifactProjectedCellValue,
14
14
  type SpreadsheetArtifactFormulaError,
15
15
  } from "@opengeni/contracts/editable-artifacts";
16
+ import {
17
+ COMMITTED_TRANSACTION_PROTOCOL_VERSION,
18
+ SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
19
+ SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
20
+ } from "@opengeni/contracts/editable-artifact-versions";
16
21
 
17
22
  import { NativeSpreadsheetSession } from "./native";
18
23
  import { SpreadsheetXlsxCodec } from "./spreadsheet-xlsx-codec";
@@ -46,9 +51,9 @@ export type EditableArtifactNativeMaterializerCapabilities = Readonly<{
46
51
  fontRegistryHash: string;
47
52
  policyHash: string;
48
53
  maxOutputBytes: number;
49
- supportedModelSchemaVersions: readonly [1];
50
- supportedOperationProtocolVersions: readonly [1];
51
- supportedSnapshotProtocolVersions: readonly [1];
54
+ supportedModelSchemaVersions: readonly [typeof SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION];
55
+ supportedOperationProtocolVersions: readonly [typeof COMMITTED_TRANSACTION_PROTOCOL_VERSION];
56
+ supportedSnapshotProtocolVersions: readonly [typeof SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION];
52
57
  }>;
53
58
 
54
59
  type MaterializationManifest = Readonly<{
@@ -467,9 +472,15 @@ export function editableArtifactMaterializerCapabilitiesForRuntime(
467
472
  fontRegistryHash: EMPTY_FONT_REGISTRY_HASH,
468
473
  policyHash: POLICY_HASH,
469
474
  maxOutputBytes: MAX_OUTPUT_BYTES,
470
- supportedModelSchemaVersions: Object.freeze([1] as const),
471
- supportedOperationProtocolVersions: Object.freeze([1] as const),
472
- supportedSnapshotProtocolVersions: Object.freeze([1] as const),
475
+ supportedModelSchemaVersions: Object.freeze([
476
+ SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
477
+ ] as const),
478
+ supportedOperationProtocolVersions: Object.freeze([
479
+ COMMITTED_TRANSACTION_PROTOCOL_VERSION,
480
+ ] as const),
481
+ supportedSnapshotProtocolVersions: Object.freeze([
482
+ SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION,
483
+ ] as const),
473
484
  });
474
485
  }
475
486
 
@@ -478,9 +489,9 @@ function assertManifestCompatibility(
478
489
  capabilities: EditableArtifactNativeMaterializerCapabilities,
479
490
  ): void {
480
491
  if (
481
- manifest.modelSchemaVersion !== 1 ||
482
- manifest.operationProtocolVersion !== 1 ||
483
- manifest.snapshotProtocolVersion !== 1 ||
492
+ manifest.modelSchemaVersion !== SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION ||
493
+ manifest.operationProtocolVersion !== COMMITTED_TRANSACTION_PROTOCOL_VERSION ||
494
+ manifest.snapshotProtocolVersion !== SPREADSHEET_COLLABORATION_SNAPSHOT_VERSION ||
484
495
  manifest.kernelVersion !== capabilities.kernelVersion ||
485
496
  manifest.codecVersion !==
486
497
  (capabilities.codecVersions as Readonly<Record<string, string>>)[manifest.codecId] ||
package/src/native.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  EDITABLE_ARTIFACT_INTENT_VERSION,
3
+ EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION,
3
4
  SPREADSHEET_ARTIFACT_COMMAND_VERSION,
4
5
  assertCanonicalSpreadsheetArtifactCommandBytes,
5
6
  decodeEditableArtifactMutationIntent,
@@ -9,6 +10,7 @@ import {
9
10
  type EditableArtifactMutationIntent,
10
11
  type SpreadsheetArtifactCommandBatch,
11
12
  } from "@opengeni/contracts/editable-artifacts";
13
+ import { SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION } from "@opengeni/contracts/editable-artifact-versions";
12
14
  import {
13
15
  ArtifactCollaborationSession,
14
16
  ArtifactDocumentSession,
@@ -61,7 +63,7 @@ export type NativeSpreadsheetAuthoredTransaction = Readonly<{
61
63
  /** Exact canonical OGATX001 bytes passed to Rust. */
62
64
  intentBytes: Uint8Array;
63
65
  requestHash: string;
64
- /** One whole canonical OGACO001 transaction returned by Rust. */
66
+ /** One whole canonical OGACO002 transaction returned by Rust. */
65
67
  committedTransactionBytes: Uint8Array;
66
68
  }>;
67
69
 
@@ -137,8 +139,8 @@ export class NativeSpreadsheetSession {
137
139
  const intentBytes = encodeEditableArtifactMutationIntent({
138
140
  ...input.intent,
139
141
  envelopeVersion: EDITABLE_ARTIFACT_INTENT_VERSION,
140
- protocolVersion: 1,
141
- modelSchemaVersion: 1,
142
+ protocolVersion: EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION,
143
+ modelSchemaVersion: SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION,
142
144
  commandProtocolVersion: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
143
145
  commandBytes,
144
146
  });
@@ -361,8 +363,8 @@ function assertSpreadsheetIntent(intentBytes: Uint8Array): void {
361
363
  const intent = decodeEditableArtifactMutationIntent(intentBytes);
362
364
  if (
363
365
  intent.envelopeVersion !== EDITABLE_ARTIFACT_INTENT_VERSION ||
364
- intent.protocolVersion !== 1 ||
365
- intent.modelSchemaVersion !== 1 ||
366
+ intent.protocolVersion !== EDITABLE_ARTIFACT_INTENT_PROTOCOL_VERSION ||
367
+ intent.modelSchemaVersion !== SPREADSHEET_ARTIFACT_MODEL_SCHEMA_VERSION ||
366
368
  intent.commandProtocolVersion !== SPREADSHEET_ARTIFACT_COMMAND_VERSION
367
369
  ) {
368
370
  throw new ArtifactRuntimeError(