@panproto/core 0.3.0 → 0.5.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.
- package/dist/check.d.ts +64 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/gat.d.ts +99 -0
- package/dist/gat.d.ts.map +1 -0
- package/dist/index.cjs +1092 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1093 -21
- package/dist/index.js.map +1 -1
- package/dist/instance.d.ts +42 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/io.d.ts +65 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/lens.d.ts +74 -9
- package/dist/lens.d.ts.map +1 -1
- package/dist/migration.d.ts +11 -0
- package/dist/migration.d.ts.map +1 -1
- package/dist/panproto.d.ts +67 -0
- package/dist/panproto.d.ts.map +1 -1
- package/dist/protocol.d.ts +27 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/schema.d.ts +8 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/types.d.ts +203 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vcs.d.ts +111 -0
- package/dist/vcs.d.ts.map +1 -0
- package/dist/wasm.d.ts +38 -0
- package/dist/wasm.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,48 @@ async function loadWasm(input) {
|
|
|
52
52
|
put_record: glue.put_record,
|
|
53
53
|
compose_migrations: glue.compose_migrations,
|
|
54
54
|
diff_schemas: glue.diff_schemas,
|
|
55
|
-
free_handle: glue.free_handle
|
|
55
|
+
free_handle: glue.free_handle,
|
|
56
|
+
diff_schemas_full: glue.diff_schemas_full,
|
|
57
|
+
classify_diff: glue.classify_diff,
|
|
58
|
+
report_text: glue.report_text,
|
|
59
|
+
report_json: glue.report_json,
|
|
60
|
+
normalize_schema: glue.normalize_schema,
|
|
61
|
+
validate_schema: glue.validate_schema,
|
|
62
|
+
register_io_protocols: glue.register_io_protocols,
|
|
63
|
+
list_io_protocols: glue.list_io_protocols,
|
|
64
|
+
parse_instance: glue.parse_instance,
|
|
65
|
+
emit_instance: glue.emit_instance,
|
|
66
|
+
validate_instance: glue.validate_instance,
|
|
67
|
+
instance_to_json: glue.instance_to_json,
|
|
68
|
+
json_to_instance: glue.json_to_instance,
|
|
69
|
+
instance_element_count: glue.instance_element_count,
|
|
70
|
+
lens_from_combinators: glue.lens_from_combinators,
|
|
71
|
+
check_lens_laws: glue.check_lens_laws,
|
|
72
|
+
check_get_put: glue.check_get_put,
|
|
73
|
+
check_put_get: glue.check_put_get,
|
|
74
|
+
invert_migration: glue.invert_migration,
|
|
75
|
+
compose_lenses: glue.compose_lenses,
|
|
76
|
+
// Phase 4
|
|
77
|
+
list_builtin_protocols: glue.list_builtin_protocols,
|
|
78
|
+
get_builtin_protocol: glue.get_builtin_protocol,
|
|
79
|
+
// Phase 5
|
|
80
|
+
create_theory: glue.create_theory,
|
|
81
|
+
colimit_theories: glue.colimit_theories,
|
|
82
|
+
check_morphism: glue.check_morphism,
|
|
83
|
+
migrate_model: glue.migrate_model,
|
|
84
|
+
// Phase 6
|
|
85
|
+
vcs_init: glue.vcs_init,
|
|
86
|
+
vcs_add: glue.vcs_add,
|
|
87
|
+
vcs_commit: glue.vcs_commit,
|
|
88
|
+
vcs_log: glue.vcs_log,
|
|
89
|
+
vcs_status: glue.vcs_status,
|
|
90
|
+
vcs_diff: glue.vcs_diff,
|
|
91
|
+
vcs_branch: glue.vcs_branch,
|
|
92
|
+
vcs_checkout: glue.vcs_checkout,
|
|
93
|
+
vcs_merge: glue.vcs_merge,
|
|
94
|
+
vcs_stash: glue.vcs_stash,
|
|
95
|
+
vcs_stash_pop: glue.vcs_stash_pop,
|
|
96
|
+
vcs_blame: glue.vcs_blame
|
|
56
97
|
};
|
|
57
98
|
const memory = initOutput.memory;
|
|
58
99
|
if (!memory) {
|
|
@@ -119,6 +160,280 @@ function packSchemaOps(ops) {
|
|
|
119
160
|
function packMigrationMapping(mapping) {
|
|
120
161
|
return msgpack.encode(mapping);
|
|
121
162
|
}
|
|
163
|
+
function renameField(oldName, newName) {
|
|
164
|
+
return { type: "rename-field", old: oldName, new: newName };
|
|
165
|
+
}
|
|
166
|
+
function addField(name, vertexKind, defaultValue) {
|
|
167
|
+
return { type: "add-field", name, vertexKind, default: defaultValue };
|
|
168
|
+
}
|
|
169
|
+
function removeField(name) {
|
|
170
|
+
return { type: "remove-field", name };
|
|
171
|
+
}
|
|
172
|
+
function wrapInObject(fieldName) {
|
|
173
|
+
return { type: "wrap-in-object", fieldName };
|
|
174
|
+
}
|
|
175
|
+
function hoistField(host, field) {
|
|
176
|
+
return { type: "hoist-field", host, field };
|
|
177
|
+
}
|
|
178
|
+
function coerceType(fromKind, toKind) {
|
|
179
|
+
return { type: "coerce-type", fromKind, toKind };
|
|
180
|
+
}
|
|
181
|
+
function compose(first, second) {
|
|
182
|
+
return { type: "compose", first, second };
|
|
183
|
+
}
|
|
184
|
+
function pipeline(combinators) {
|
|
185
|
+
const [first, ...rest] = combinators;
|
|
186
|
+
return rest.reduce((acc, c) => compose(acc, c), first);
|
|
187
|
+
}
|
|
188
|
+
class LensHandle {
|
|
189
|
+
#handle;
|
|
190
|
+
#wasm;
|
|
191
|
+
constructor(handle, wasm) {
|
|
192
|
+
this.#handle = handle;
|
|
193
|
+
this.#wasm = wasm;
|
|
194
|
+
}
|
|
195
|
+
/** The underlying WASM handle. Internal use only. */
|
|
196
|
+
get _handle() {
|
|
197
|
+
return this.#handle;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Forward projection: extract the view from a record.
|
|
201
|
+
*
|
|
202
|
+
* @param record - MessagePack-encoded input record
|
|
203
|
+
* @returns The projected view and opaque complement bytes
|
|
204
|
+
* @throws {@link WasmError} if the WASM call fails
|
|
205
|
+
*/
|
|
206
|
+
get(record) {
|
|
207
|
+
try {
|
|
208
|
+
const outputBytes = this.#wasm.exports.get_record(
|
|
209
|
+
this.#handle.id,
|
|
210
|
+
record
|
|
211
|
+
);
|
|
212
|
+
const result = unpackFromWasm(outputBytes);
|
|
213
|
+
return {
|
|
214
|
+
view: result.view,
|
|
215
|
+
complement: result.complement instanceof Uint8Array ? result.complement : new Uint8Array(result.complement)
|
|
216
|
+
};
|
|
217
|
+
} catch (error) {
|
|
218
|
+
throw new WasmError(
|
|
219
|
+
`get_record failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
220
|
+
{ cause: error }
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Backward put: restore a full record from a modified view and complement.
|
|
226
|
+
*
|
|
227
|
+
* @param view - MessagePack-encoded (possibly modified) projected view
|
|
228
|
+
* @param complement - The complement from a prior `get()` call
|
|
229
|
+
* @returns The restored full record
|
|
230
|
+
* @throws {@link WasmError} if the WASM call fails
|
|
231
|
+
*/
|
|
232
|
+
put(view, complement) {
|
|
233
|
+
try {
|
|
234
|
+
const outputBytes = this.#wasm.exports.put_record(
|
|
235
|
+
this.#handle.id,
|
|
236
|
+
view,
|
|
237
|
+
complement
|
|
238
|
+
);
|
|
239
|
+
const data = unpackFromWasm(outputBytes);
|
|
240
|
+
return { data };
|
|
241
|
+
} catch (error) {
|
|
242
|
+
throw new WasmError(
|
|
243
|
+
`put_record failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
244
|
+
{ cause: error }
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Check both GetPut and PutGet lens laws for an instance.
|
|
250
|
+
*
|
|
251
|
+
* @param instance - MessagePack-encoded instance data
|
|
252
|
+
* @returns Whether both laws hold and any violation message
|
|
253
|
+
* @throws {@link WasmError} if the WASM call fails
|
|
254
|
+
*/
|
|
255
|
+
checkLaws(instance) {
|
|
256
|
+
try {
|
|
257
|
+
const resultBytes = this.#wasm.exports.check_lens_laws(
|
|
258
|
+
this.#handle.id,
|
|
259
|
+
instance
|
|
260
|
+
);
|
|
261
|
+
return unpackFromWasm(resultBytes);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
throw new WasmError(
|
|
264
|
+
`check_lens_laws failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
265
|
+
{ cause: error }
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Check the GetPut lens law for an instance.
|
|
271
|
+
*
|
|
272
|
+
* @param instance - MessagePack-encoded instance data
|
|
273
|
+
* @returns Whether the law holds and any violation message
|
|
274
|
+
* @throws {@link WasmError} if the WASM call fails
|
|
275
|
+
*/
|
|
276
|
+
checkGetPut(instance) {
|
|
277
|
+
try {
|
|
278
|
+
const resultBytes = this.#wasm.exports.check_get_put(
|
|
279
|
+
this.#handle.id,
|
|
280
|
+
instance
|
|
281
|
+
);
|
|
282
|
+
return unpackFromWasm(resultBytes);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
throw new WasmError(
|
|
285
|
+
`check_get_put failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
286
|
+
{ cause: error }
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Check the PutGet lens law for an instance.
|
|
292
|
+
*
|
|
293
|
+
* @param instance - MessagePack-encoded instance data
|
|
294
|
+
* @returns Whether the law holds and any violation message
|
|
295
|
+
* @throws {@link WasmError} if the WASM call fails
|
|
296
|
+
*/
|
|
297
|
+
checkPutGet(instance) {
|
|
298
|
+
try {
|
|
299
|
+
const resultBytes = this.#wasm.exports.check_put_get(
|
|
300
|
+
this.#handle.id,
|
|
301
|
+
instance
|
|
302
|
+
);
|
|
303
|
+
return unpackFromWasm(resultBytes);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
throw new WasmError(
|
|
306
|
+
`check_put_get failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
307
|
+
{ cause: error }
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/** Release the underlying WASM resource. */
|
|
312
|
+
[Symbol.dispose]() {
|
|
313
|
+
this.#handle[Symbol.dispose]();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function fromCombinators(schema, protocol, wasm, ...combinators) {
|
|
317
|
+
const wireCombs = combinators.map(combinatorToWire);
|
|
318
|
+
const combBytes = packToWasm(wireCombs);
|
|
319
|
+
try {
|
|
320
|
+
const rawHandle = wasm.exports.lens_from_combinators(
|
|
321
|
+
schema._handle.id,
|
|
322
|
+
protocol._handle.id,
|
|
323
|
+
combBytes
|
|
324
|
+
);
|
|
325
|
+
const handle = createHandle(rawHandle, wasm);
|
|
326
|
+
return new LensHandle(handle, wasm);
|
|
327
|
+
} catch (error) {
|
|
328
|
+
throw new WasmError(
|
|
329
|
+
`lens_from_combinators failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
330
|
+
{ cause: error }
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function combinatorToWire(combinator) {
|
|
335
|
+
switch (combinator.type) {
|
|
336
|
+
case "rename-field":
|
|
337
|
+
return { RenameField: { old: combinator.old, new: combinator.new } };
|
|
338
|
+
case "add-field":
|
|
339
|
+
return { AddField: { name: combinator.name, vertex_kind: combinator.vertexKind, default: combinator.default } };
|
|
340
|
+
case "remove-field":
|
|
341
|
+
return { RemoveField: { name: combinator.name } };
|
|
342
|
+
case "wrap-in-object":
|
|
343
|
+
return { WrapInObject: { field_name: combinator.fieldName } };
|
|
344
|
+
case "hoist-field":
|
|
345
|
+
return { HoistField: { host: combinator.host, field: combinator.field } };
|
|
346
|
+
case "coerce-type":
|
|
347
|
+
return { CoerceType: { from_kind: combinator.fromKind, to_kind: combinator.toKind } };
|
|
348
|
+
case "compose":
|
|
349
|
+
return { Compose: [combinatorToWire(combinator.first), combinatorToWire(combinator.second)] };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
class FullDiffReport {
|
|
353
|
+
/** The raw diff data. */
|
|
354
|
+
data;
|
|
355
|
+
/** @internal */
|
|
356
|
+
_reportBytes;
|
|
357
|
+
/** @internal */
|
|
358
|
+
_wasm;
|
|
359
|
+
/** @internal */
|
|
360
|
+
constructor(data, reportBytes, wasm) {
|
|
361
|
+
this.data = data;
|
|
362
|
+
this._reportBytes = reportBytes;
|
|
363
|
+
this._wasm = wasm;
|
|
364
|
+
}
|
|
365
|
+
/** Whether there are any changes at all. */
|
|
366
|
+
get hasChanges() {
|
|
367
|
+
const d = this.data;
|
|
368
|
+
return d.added_vertices.length > 0 || d.removed_vertices.length > 0 || d.kind_changes.length > 0 || d.added_edges.length > 0 || d.removed_edges.length > 0 || Object.keys(d.modified_constraints).length > 0 || d.added_hyper_edges.length > 0 || d.removed_hyper_edges.length > 0 || d.modified_hyper_edges.length > 0 || Object.keys(d.added_required).length > 0 || Object.keys(d.removed_required).length > 0 || Object.keys(d.added_nsids).length > 0 || d.removed_nsids.length > 0 || d.changed_nsids.length > 0 || d.added_variants.length > 0 || d.removed_variants.length > 0 || d.modified_variants.length > 0 || d.order_changes.length > 0 || d.added_recursion_points.length > 0 || d.removed_recursion_points.length > 0 || d.modified_recursion_points.length > 0 || d.usage_mode_changes.length > 0 || d.added_spans.length > 0 || d.removed_spans.length > 0 || d.modified_spans.length > 0 || d.nominal_changes.length > 0;
|
|
369
|
+
}
|
|
370
|
+
/** Classify the diff against a protocol, producing a compatibility report. */
|
|
371
|
+
classify(protocol) {
|
|
372
|
+
const rawBytes = this._wasm.exports.classify_diff(
|
|
373
|
+
protocol._handle.id,
|
|
374
|
+
this._reportBytes
|
|
375
|
+
);
|
|
376
|
+
const data = unpackFromWasm(rawBytes);
|
|
377
|
+
return new CompatReport(data, rawBytes, this._wasm);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
class CompatReport {
|
|
381
|
+
/** The raw report data. */
|
|
382
|
+
data;
|
|
383
|
+
/** @internal */
|
|
384
|
+
_rawBytes;
|
|
385
|
+
/** @internal */
|
|
386
|
+
_wasm;
|
|
387
|
+
/** @internal */
|
|
388
|
+
constructor(data, rawBytes, wasm) {
|
|
389
|
+
this.data = data;
|
|
390
|
+
this._rawBytes = rawBytes;
|
|
391
|
+
this._wasm = wasm;
|
|
392
|
+
}
|
|
393
|
+
/** List of breaking changes. */
|
|
394
|
+
get breakingChanges() {
|
|
395
|
+
return this.data.breaking;
|
|
396
|
+
}
|
|
397
|
+
/** List of non-breaking changes. */
|
|
398
|
+
get nonBreakingChanges() {
|
|
399
|
+
return this.data.non_breaking;
|
|
400
|
+
}
|
|
401
|
+
/** Whether the changes are fully compatible (no breaking changes). */
|
|
402
|
+
get isCompatible() {
|
|
403
|
+
return this.data.compatible;
|
|
404
|
+
}
|
|
405
|
+
/** Whether there are any breaking changes. */
|
|
406
|
+
get isBreaking() {
|
|
407
|
+
return !this.data.compatible;
|
|
408
|
+
}
|
|
409
|
+
/** Whether the changes are backward-compatible (additions only, no removals). */
|
|
410
|
+
get isBackwardCompatible() {
|
|
411
|
+
return this.data.compatible;
|
|
412
|
+
}
|
|
413
|
+
/** Render as human-readable text. */
|
|
414
|
+
toText() {
|
|
415
|
+
return this._wasm.exports.report_text(this._rawBytes);
|
|
416
|
+
}
|
|
417
|
+
/** Render as a JSON string. */
|
|
418
|
+
toJson() {
|
|
419
|
+
return this._wasm.exports.report_json(this._rawBytes);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
class ValidationResult {
|
|
423
|
+
/** The list of validation issues found. */
|
|
424
|
+
issues;
|
|
425
|
+
constructor(issues) {
|
|
426
|
+
this.issues = issues;
|
|
427
|
+
}
|
|
428
|
+
/** Whether the schema is valid (no issues found). */
|
|
429
|
+
get isValid() {
|
|
430
|
+
return this.issues.length === 0;
|
|
431
|
+
}
|
|
432
|
+
/** The number of validation issues. */
|
|
433
|
+
get errorCount() {
|
|
434
|
+
return this.issues.length;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
122
437
|
class SchemaBuilder {
|
|
123
438
|
#protocolName;
|
|
124
439
|
#protocolHandle;
|
|
@@ -397,6 +712,25 @@ class BuiltSchema {
|
|
|
397
712
|
get edges() {
|
|
398
713
|
return this.#data.edges;
|
|
399
714
|
}
|
|
715
|
+
/** @internal Create from raw handle (used by normalize). */
|
|
716
|
+
static _fromHandle(handle, data, _protocol, wasm) {
|
|
717
|
+
const wasmHandle = createHandle(handle, wasm);
|
|
718
|
+
return new BuiltSchema(wasmHandle, data, wasm);
|
|
719
|
+
}
|
|
720
|
+
/** Normalize this schema by collapsing reference chains. Returns a new BuiltSchema. */
|
|
721
|
+
normalize() {
|
|
722
|
+
const handle = this.#wasm.exports.normalize_schema(this.#handle.id);
|
|
723
|
+
return BuiltSchema._fromHandle(handle, this.#data, this.#data.protocol, this.#wasm);
|
|
724
|
+
}
|
|
725
|
+
/** Validate this schema against a protocol's rules. */
|
|
726
|
+
validate(protocol) {
|
|
727
|
+
const bytes = this.#wasm.exports.validate_schema(
|
|
728
|
+
this.#handle.id,
|
|
729
|
+
protocol._handle.id
|
|
730
|
+
);
|
|
731
|
+
const issues = unpackFromWasm(bytes);
|
|
732
|
+
return new ValidationResult(issues);
|
|
733
|
+
}
|
|
400
734
|
/** Release the WASM-side schema resource. */
|
|
401
735
|
[Symbol.dispose]() {
|
|
402
736
|
this.#handle[Symbol.dispose]();
|
|
@@ -419,6 +753,18 @@ class Protocol {
|
|
|
419
753
|
get spec() {
|
|
420
754
|
return this.#spec;
|
|
421
755
|
}
|
|
756
|
+
/** The edge rules for this protocol. */
|
|
757
|
+
get edgeRules() {
|
|
758
|
+
return this.#spec.edgeRules;
|
|
759
|
+
}
|
|
760
|
+
/** The constraint sorts for this protocol. */
|
|
761
|
+
get constraintSorts() {
|
|
762
|
+
return this.#spec.constraintSorts;
|
|
763
|
+
}
|
|
764
|
+
/** The object kinds for this protocol. */
|
|
765
|
+
get objectKinds() {
|
|
766
|
+
return this.#spec.objKinds;
|
|
767
|
+
}
|
|
422
768
|
/** The WASM handle. Internal use only. */
|
|
423
769
|
get _handle() {
|
|
424
770
|
return this.#handle;
|
|
@@ -559,6 +905,34 @@ const BUILTIN_PROTOCOLS = /* @__PURE__ */ new Map([
|
|
|
559
905
|
["graphql", GRAPHQL_SPEC],
|
|
560
906
|
["json-schema", JSON_SCHEMA_SPEC]
|
|
561
907
|
]);
|
|
908
|
+
let _protocolNamesCache = null;
|
|
909
|
+
function getProtocolNames(wasm) {
|
|
910
|
+
if (_protocolNamesCache !== null) return _protocolNamesCache;
|
|
911
|
+
const bytes = wasm.exports.list_builtin_protocols();
|
|
912
|
+
_protocolNamesCache = unpackFromWasm(bytes);
|
|
913
|
+
return _protocolNamesCache;
|
|
914
|
+
}
|
|
915
|
+
function getBuiltinProtocol(name, wasm) {
|
|
916
|
+
try {
|
|
917
|
+
const nameBytes = new TextEncoder().encode(name);
|
|
918
|
+
const bytes = wasm.exports.get_builtin_protocol(nameBytes);
|
|
919
|
+
const wire = unpackFromWasm(bytes);
|
|
920
|
+
return {
|
|
921
|
+
name: wire.name,
|
|
922
|
+
schemaTheory: wire.schema_theory,
|
|
923
|
+
instanceTheory: wire.instance_theory,
|
|
924
|
+
edgeRules: wire.edge_rules.map((r) => ({
|
|
925
|
+
edgeKind: r.edge_kind,
|
|
926
|
+
srcKinds: r.src_kinds,
|
|
927
|
+
tgtKinds: r.tgt_kinds
|
|
928
|
+
})),
|
|
929
|
+
objKinds: wire.obj_kinds,
|
|
930
|
+
constraintSorts: wire.constraint_sorts
|
|
931
|
+
};
|
|
932
|
+
} catch {
|
|
933
|
+
return void 0;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
562
936
|
class MigrationBuilder {
|
|
563
937
|
#src;
|
|
564
938
|
#tgt;
|
|
@@ -643,6 +1017,50 @@ class MigrationBuilder {
|
|
|
643
1017
|
resolvers: [...this.#resolvers]
|
|
644
1018
|
};
|
|
645
1019
|
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Invert a bijective migration.
|
|
1022
|
+
*
|
|
1023
|
+
* Serializes the current mapping to MessagePack and calls the
|
|
1024
|
+
* `invert_migration` WASM entry point. Returns a new MigrationSpec
|
|
1025
|
+
* representing the inverted migration.
|
|
1026
|
+
*
|
|
1027
|
+
* @returns The inverted migration specification
|
|
1028
|
+
* @throws {@link MigrationError} if the migration is not bijective or inversion fails
|
|
1029
|
+
*/
|
|
1030
|
+
invert() {
|
|
1031
|
+
const edgeMap = new Map(
|
|
1032
|
+
this.#edgeMap.map(([src, tgt]) => [
|
|
1033
|
+
{ src: src.src, tgt: src.tgt, kind: src.kind, name: src.name ?? null },
|
|
1034
|
+
{ src: tgt.src, tgt: tgt.tgt, kind: tgt.kind, name: tgt.name ?? null }
|
|
1035
|
+
])
|
|
1036
|
+
);
|
|
1037
|
+
const resolver = new Map(
|
|
1038
|
+
this.#resolvers.map(([[s, t], e]) => [
|
|
1039
|
+
[s, t],
|
|
1040
|
+
{ src: e.src, tgt: e.tgt, kind: e.kind, name: e.name ?? null }
|
|
1041
|
+
])
|
|
1042
|
+
);
|
|
1043
|
+
const mapping = packMigrationMapping({
|
|
1044
|
+
vertex_map: Object.fromEntries(this.#vertexMap),
|
|
1045
|
+
edge_map: edgeMap,
|
|
1046
|
+
hyper_edge_map: {},
|
|
1047
|
+
label_map: /* @__PURE__ */ new Map(),
|
|
1048
|
+
resolver
|
|
1049
|
+
});
|
|
1050
|
+
try {
|
|
1051
|
+
const resultBytes = this.#wasm.exports.invert_migration(
|
|
1052
|
+
mapping,
|
|
1053
|
+
this.#src._handle.id,
|
|
1054
|
+
this.#tgt._handle.id
|
|
1055
|
+
);
|
|
1056
|
+
return unpackFromWasm(resultBytes);
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
throw new MigrationError(
|
|
1059
|
+
`Failed to invert migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
1060
|
+
{ cause: error }
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
646
1064
|
/**
|
|
647
1065
|
* Compile the migration for fast per-record application.
|
|
648
1066
|
*
|
|
@@ -843,6 +1261,433 @@ function composeMigrations(m1, m2, wasm) {
|
|
|
843
1261
|
);
|
|
844
1262
|
}
|
|
845
1263
|
}
|
|
1264
|
+
class Instance {
|
|
1265
|
+
/** Raw MsgPack-encoded instance bytes (for passing back to WASM). */
|
|
1266
|
+
_bytes;
|
|
1267
|
+
/** The schema this instance conforms to. */
|
|
1268
|
+
_schema;
|
|
1269
|
+
/** @internal */
|
|
1270
|
+
_wasm;
|
|
1271
|
+
constructor(bytes, schema, wasm) {
|
|
1272
|
+
this._bytes = bytes;
|
|
1273
|
+
this._schema = schema;
|
|
1274
|
+
this._wasm = wasm;
|
|
1275
|
+
}
|
|
1276
|
+
/** Convert this instance to JSON bytes. */
|
|
1277
|
+
toJson() {
|
|
1278
|
+
return this._wasm.exports.instance_to_json(
|
|
1279
|
+
this._schema._handle.id,
|
|
1280
|
+
this._bytes
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
/** Validate this instance against its schema. */
|
|
1284
|
+
validate() {
|
|
1285
|
+
const resultBytes = this._wasm.exports.validate_instance(
|
|
1286
|
+
this._schema._handle.id,
|
|
1287
|
+
this._bytes
|
|
1288
|
+
);
|
|
1289
|
+
const errors = unpackFromWasm(resultBytes);
|
|
1290
|
+
return {
|
|
1291
|
+
isValid: errors.length === 0,
|
|
1292
|
+
errors
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
/** Get the number of elements in this instance. */
|
|
1296
|
+
get elementCount() {
|
|
1297
|
+
return this._wasm.exports.instance_element_count(this._bytes);
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Create an Instance from JSON input.
|
|
1301
|
+
*
|
|
1302
|
+
* @param schema - The schema the JSON data conforms to
|
|
1303
|
+
* @param json - JSON bytes
|
|
1304
|
+
* @param wasm - The WASM module
|
|
1305
|
+
* @returns A new Instance
|
|
1306
|
+
*/
|
|
1307
|
+
static fromJson(schema, json, wasm) {
|
|
1308
|
+
const bytes = wasm.exports.json_to_instance(schema._handle.id, json);
|
|
1309
|
+
return new Instance(bytes, schema, wasm);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
const PROTOCOL_CATEGORIES = {
|
|
1313
|
+
annotation: [
|
|
1314
|
+
"brat",
|
|
1315
|
+
"conllu",
|
|
1316
|
+
"naf",
|
|
1317
|
+
"uima",
|
|
1318
|
+
"folia",
|
|
1319
|
+
"tei",
|
|
1320
|
+
"timeml",
|
|
1321
|
+
"elan",
|
|
1322
|
+
"iso_space",
|
|
1323
|
+
"paula",
|
|
1324
|
+
"laf_graf",
|
|
1325
|
+
"decomp",
|
|
1326
|
+
"ucca",
|
|
1327
|
+
"fovea",
|
|
1328
|
+
"bead",
|
|
1329
|
+
"web_annotation",
|
|
1330
|
+
"amr",
|
|
1331
|
+
"concrete",
|
|
1332
|
+
"nif"
|
|
1333
|
+
],
|
|
1334
|
+
api: ["graphql", "openapi", "asyncapi", "jsonapi", "raml"],
|
|
1335
|
+
config: ["cloudformation", "ansible", "k8s_crd", "hcl"],
|
|
1336
|
+
data_schema: [
|
|
1337
|
+
"json_schema",
|
|
1338
|
+
"yaml_schema",
|
|
1339
|
+
"toml_schema",
|
|
1340
|
+
"cddl",
|
|
1341
|
+
"bson",
|
|
1342
|
+
"csv_table",
|
|
1343
|
+
"ini_schema"
|
|
1344
|
+
],
|
|
1345
|
+
data_science: ["dataframe", "parquet", "arrow"],
|
|
1346
|
+
database: ["mongodb", "dynamodb", "cassandra", "neo4j", "sql", "redis"],
|
|
1347
|
+
domain: ["geojson", "fhir", "rss_atom", "vcard_ical", "swift_mt", "edi_x12"],
|
|
1348
|
+
serialization: [
|
|
1349
|
+
"protobuf",
|
|
1350
|
+
"avro",
|
|
1351
|
+
"thrift",
|
|
1352
|
+
"capnproto",
|
|
1353
|
+
"flatbuffers",
|
|
1354
|
+
"asn1",
|
|
1355
|
+
"bond",
|
|
1356
|
+
"msgpack_schema"
|
|
1357
|
+
],
|
|
1358
|
+
type_system: [
|
|
1359
|
+
"typescript",
|
|
1360
|
+
"python",
|
|
1361
|
+
"rust_serde",
|
|
1362
|
+
"java",
|
|
1363
|
+
"go_struct",
|
|
1364
|
+
"kotlin",
|
|
1365
|
+
"csharp",
|
|
1366
|
+
"swift"
|
|
1367
|
+
],
|
|
1368
|
+
web_document: [
|
|
1369
|
+
"atproto",
|
|
1370
|
+
"jsx",
|
|
1371
|
+
"vue",
|
|
1372
|
+
"svelte",
|
|
1373
|
+
"css",
|
|
1374
|
+
"html",
|
|
1375
|
+
"markdown",
|
|
1376
|
+
"xml_xsd",
|
|
1377
|
+
"docx",
|
|
1378
|
+
"odf"
|
|
1379
|
+
]
|
|
1380
|
+
};
|
|
1381
|
+
const encoder$1 = new TextEncoder();
|
|
1382
|
+
class IoRegistry {
|
|
1383
|
+
_handle;
|
|
1384
|
+
_wasm;
|
|
1385
|
+
_protocolsCache = null;
|
|
1386
|
+
constructor(handle, wasm) {
|
|
1387
|
+
this._handle = handle;
|
|
1388
|
+
this._wasm = wasm;
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* List all registered protocol names.
|
|
1392
|
+
*
|
|
1393
|
+
* The result is cached after the first call.
|
|
1394
|
+
*/
|
|
1395
|
+
get protocols() {
|
|
1396
|
+
if (this._protocolsCache === null) {
|
|
1397
|
+
const bytes = this._wasm.exports.list_io_protocols(this._handle.id);
|
|
1398
|
+
this._protocolsCache = unpackFromWasm(bytes);
|
|
1399
|
+
}
|
|
1400
|
+
return this._protocolsCache;
|
|
1401
|
+
}
|
|
1402
|
+
/** Protocol names organized by category. */
|
|
1403
|
+
get categories() {
|
|
1404
|
+
return PROTOCOL_CATEGORIES;
|
|
1405
|
+
}
|
|
1406
|
+
/** Check if a protocol is registered. */
|
|
1407
|
+
hasProtocol(name) {
|
|
1408
|
+
return this.protocols.includes(name);
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Parse raw format bytes into an Instance.
|
|
1412
|
+
*
|
|
1413
|
+
* @param protocolName - The protocol codec name (e.g., 'graphql', 'protobuf')
|
|
1414
|
+
* @param schema - The schema the data conforms to
|
|
1415
|
+
* @param input - Raw format bytes to parse
|
|
1416
|
+
* @returns A new Instance wrapping the parsed data
|
|
1417
|
+
* @throws {@link PanprotoError} if the protocol is not registered or parsing fails
|
|
1418
|
+
*/
|
|
1419
|
+
parse(protocolName, schema, input) {
|
|
1420
|
+
const nameBytes = encoder$1.encode(protocolName);
|
|
1421
|
+
const resultBytes = this._wasm.exports.parse_instance(
|
|
1422
|
+
this._handle.id,
|
|
1423
|
+
nameBytes,
|
|
1424
|
+
schema._handle.id,
|
|
1425
|
+
input
|
|
1426
|
+
);
|
|
1427
|
+
return new Instance(resultBytes, schema, this._wasm);
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Emit an Instance to raw format bytes.
|
|
1431
|
+
*
|
|
1432
|
+
* @param protocolName - The protocol codec name (e.g., 'graphql', 'protobuf')
|
|
1433
|
+
* @param schema - The schema the instance conforms to
|
|
1434
|
+
* @param instance - The instance to emit
|
|
1435
|
+
* @returns Raw format bytes
|
|
1436
|
+
* @throws {@link PanprotoError} if the protocol is not registered or emission fails
|
|
1437
|
+
*/
|
|
1438
|
+
emit(protocolName, schema, instance) {
|
|
1439
|
+
const nameBytes = encoder$1.encode(protocolName);
|
|
1440
|
+
return this._wasm.exports.emit_instance(
|
|
1441
|
+
this._handle.id,
|
|
1442
|
+
nameBytes,
|
|
1443
|
+
schema._handle.id,
|
|
1444
|
+
instance._bytes
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
/** Release the WASM-side IoRegistry resource. */
|
|
1448
|
+
[Symbol.dispose]() {
|
|
1449
|
+
this._handle[Symbol.dispose]();
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
const encoder = new TextEncoder();
|
|
1453
|
+
class Repository {
|
|
1454
|
+
#handle;
|
|
1455
|
+
#wasm;
|
|
1456
|
+
#protocolName;
|
|
1457
|
+
constructor(handle, protocolName, wasm) {
|
|
1458
|
+
this.#handle = handle;
|
|
1459
|
+
this.#protocolName = protocolName;
|
|
1460
|
+
this.#wasm = wasm;
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Initialize a new in-memory repository.
|
|
1464
|
+
*
|
|
1465
|
+
* @param protocolName - The protocol this repository tracks
|
|
1466
|
+
* @param wasm - The WASM module
|
|
1467
|
+
* @returns A new disposable Repository
|
|
1468
|
+
*/
|
|
1469
|
+
static init(protocolName, wasm) {
|
|
1470
|
+
const nameBytes = encoder.encode(protocolName);
|
|
1471
|
+
const rawHandle = wasm.exports.vcs_init(nameBytes);
|
|
1472
|
+
const handle = createHandle(rawHandle, wasm);
|
|
1473
|
+
return new Repository(handle, protocolName, wasm);
|
|
1474
|
+
}
|
|
1475
|
+
/** The protocol name this repository tracks. */
|
|
1476
|
+
get protocolName() {
|
|
1477
|
+
return this.#protocolName;
|
|
1478
|
+
}
|
|
1479
|
+
/** The underlying WASM handle. Internal use only. */
|
|
1480
|
+
get _handle() {
|
|
1481
|
+
return this.#handle;
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Stage a schema for the next commit.
|
|
1485
|
+
*
|
|
1486
|
+
* @param schema - The built schema to stage
|
|
1487
|
+
* @returns An object with the schema's object ID
|
|
1488
|
+
*/
|
|
1489
|
+
add(schema) {
|
|
1490
|
+
try {
|
|
1491
|
+
const resultBytes = this.#wasm.exports.vcs_add(
|
|
1492
|
+
this.#handle.id,
|
|
1493
|
+
schema._handle.id
|
|
1494
|
+
);
|
|
1495
|
+
const result = unpackFromWasm(resultBytes);
|
|
1496
|
+
return { schemaId: result.schema_id };
|
|
1497
|
+
} catch (error) {
|
|
1498
|
+
throw new WasmError(
|
|
1499
|
+
`vcs_add failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1500
|
+
{ cause: error }
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Create a commit from the current staging area.
|
|
1506
|
+
*
|
|
1507
|
+
* @param message - The commit message
|
|
1508
|
+
* @param author - The commit author
|
|
1509
|
+
* @returns The commit result
|
|
1510
|
+
*/
|
|
1511
|
+
commit(message, author) {
|
|
1512
|
+
try {
|
|
1513
|
+
return this.#wasm.exports.vcs_commit(
|
|
1514
|
+
this.#handle.id,
|
|
1515
|
+
encoder.encode(message),
|
|
1516
|
+
encoder.encode(author)
|
|
1517
|
+
);
|
|
1518
|
+
} catch (error) {
|
|
1519
|
+
throw new WasmError(
|
|
1520
|
+
`vcs_commit failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1521
|
+
{ cause: error }
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Walk the commit log from HEAD.
|
|
1527
|
+
*
|
|
1528
|
+
* @param count - Maximum number of log entries to return (default: 50)
|
|
1529
|
+
* @returns Array of commit log entries
|
|
1530
|
+
*/
|
|
1531
|
+
log(count = 50) {
|
|
1532
|
+
try {
|
|
1533
|
+
const resultBytes = this.#wasm.exports.vcs_log(this.#handle.id, count);
|
|
1534
|
+
return unpackFromWasm(resultBytes);
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
throw new WasmError(
|
|
1537
|
+
`vcs_log failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1538
|
+
{ cause: error }
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Get the repository status.
|
|
1544
|
+
*
|
|
1545
|
+
* @returns Current branch and HEAD commit info
|
|
1546
|
+
*/
|
|
1547
|
+
status() {
|
|
1548
|
+
try {
|
|
1549
|
+
const resultBytes = this.#wasm.exports.vcs_status(this.#handle.id);
|
|
1550
|
+
return unpackFromWasm(resultBytes);
|
|
1551
|
+
} catch (error) {
|
|
1552
|
+
throw new WasmError(
|
|
1553
|
+
`vcs_status failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1554
|
+
{ cause: error }
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Get diff information for the repository.
|
|
1560
|
+
*
|
|
1561
|
+
* @returns Diff result with branch info
|
|
1562
|
+
*/
|
|
1563
|
+
diff() {
|
|
1564
|
+
try {
|
|
1565
|
+
const resultBytes = this.#wasm.exports.vcs_diff(this.#handle.id);
|
|
1566
|
+
return unpackFromWasm(resultBytes);
|
|
1567
|
+
} catch (error) {
|
|
1568
|
+
throw new WasmError(
|
|
1569
|
+
`vcs_diff failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1570
|
+
{ cause: error }
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Create a new branch at the current HEAD.
|
|
1576
|
+
*
|
|
1577
|
+
* @param name - The branch name
|
|
1578
|
+
* @returns Operation result
|
|
1579
|
+
*/
|
|
1580
|
+
branch(name) {
|
|
1581
|
+
try {
|
|
1582
|
+
const resultBytes = this.#wasm.exports.vcs_branch(
|
|
1583
|
+
this.#handle.id,
|
|
1584
|
+
encoder.encode(name)
|
|
1585
|
+
);
|
|
1586
|
+
return unpackFromWasm(resultBytes);
|
|
1587
|
+
} catch (error) {
|
|
1588
|
+
throw new WasmError(
|
|
1589
|
+
`vcs_branch failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1590
|
+
{ cause: error }
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Checkout a branch.
|
|
1596
|
+
*
|
|
1597
|
+
* @param target - The branch name to checkout
|
|
1598
|
+
* @returns Operation result
|
|
1599
|
+
*/
|
|
1600
|
+
checkout(target) {
|
|
1601
|
+
try {
|
|
1602
|
+
const resultBytes = this.#wasm.exports.vcs_checkout(
|
|
1603
|
+
this.#handle.id,
|
|
1604
|
+
encoder.encode(target)
|
|
1605
|
+
);
|
|
1606
|
+
return unpackFromWasm(resultBytes);
|
|
1607
|
+
} catch (error) {
|
|
1608
|
+
throw new WasmError(
|
|
1609
|
+
`vcs_checkout failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1610
|
+
{ cause: error }
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Merge a branch into the current branch.
|
|
1616
|
+
*
|
|
1617
|
+
* @param branchName - The branch to merge
|
|
1618
|
+
* @returns Operation result
|
|
1619
|
+
*/
|
|
1620
|
+
merge(branchName) {
|
|
1621
|
+
try {
|
|
1622
|
+
const resultBytes = this.#wasm.exports.vcs_merge(
|
|
1623
|
+
this.#handle.id,
|
|
1624
|
+
encoder.encode(branchName)
|
|
1625
|
+
);
|
|
1626
|
+
return unpackFromWasm(resultBytes);
|
|
1627
|
+
} catch (error) {
|
|
1628
|
+
throw new WasmError(
|
|
1629
|
+
`vcs_merge failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1630
|
+
{ cause: error }
|
|
1631
|
+
);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
/**
|
|
1635
|
+
* Stash the current working state.
|
|
1636
|
+
*
|
|
1637
|
+
* @returns Operation result
|
|
1638
|
+
*/
|
|
1639
|
+
stash() {
|
|
1640
|
+
try {
|
|
1641
|
+
const resultBytes = this.#wasm.exports.vcs_stash(this.#handle.id);
|
|
1642
|
+
return unpackFromWasm(resultBytes);
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
throw new WasmError(
|
|
1645
|
+
`vcs_stash failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1646
|
+
{ cause: error }
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
/**
|
|
1651
|
+
* Pop the most recent stash entry.
|
|
1652
|
+
*
|
|
1653
|
+
* @returns Operation result
|
|
1654
|
+
*/
|
|
1655
|
+
stashPop() {
|
|
1656
|
+
try {
|
|
1657
|
+
const resultBytes = this.#wasm.exports.vcs_stash_pop(this.#handle.id);
|
|
1658
|
+
return unpackFromWasm(resultBytes);
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
throw new WasmError(
|
|
1661
|
+
`vcs_stash_pop failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1662
|
+
{ cause: error }
|
|
1663
|
+
);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Find which commit introduced a vertex.
|
|
1668
|
+
*
|
|
1669
|
+
* @param vertexId - The vertex ID to blame
|
|
1670
|
+
* @returns Blame result with commit info
|
|
1671
|
+
*/
|
|
1672
|
+
blame(vertexId) {
|
|
1673
|
+
try {
|
|
1674
|
+
const resultBytes = this.#wasm.exports.vcs_blame(
|
|
1675
|
+
this.#handle.id,
|
|
1676
|
+
encoder.encode(vertexId)
|
|
1677
|
+
);
|
|
1678
|
+
return unpackFromWasm(resultBytes);
|
|
1679
|
+
} catch (error) {
|
|
1680
|
+
throw new WasmError(
|
|
1681
|
+
`vcs_blame failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1682
|
+
{ cause: error }
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
/** Release the WASM-side repository resource. */
|
|
1687
|
+
[Symbol.dispose]() {
|
|
1688
|
+
this.#handle[Symbol.dispose]();
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
846
1691
|
class Panproto {
|
|
847
1692
|
#wasm;
|
|
848
1693
|
#protocols;
|
|
@@ -883,6 +1728,12 @@ class Panproto {
|
|
|
883
1728
|
this.#protocols.set(name, proto);
|
|
884
1729
|
return proto;
|
|
885
1730
|
}
|
|
1731
|
+
const wasmSpec = getBuiltinProtocol(name, this.#wasm);
|
|
1732
|
+
if (wasmSpec) {
|
|
1733
|
+
const proto = defineProtocol(wasmSpec, this.#wasm);
|
|
1734
|
+
this.#protocols.set(name, proto);
|
|
1735
|
+
return proto;
|
|
1736
|
+
}
|
|
886
1737
|
throw new PanprotoError(
|
|
887
1738
|
`Protocol "${name}" not found. Register it with defineProtocol() first.`
|
|
888
1739
|
);
|
|
@@ -943,6 +1794,31 @@ class Panproto {
|
|
|
943
1794
|
compose(m1, m2) {
|
|
944
1795
|
return composeMigrations(m1, m2, this.#wasm);
|
|
945
1796
|
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Compose two lenses into a single lens.
|
|
1799
|
+
*
|
|
1800
|
+
* The resulting lens is equivalent to applying `l1` then `l2`.
|
|
1801
|
+
*
|
|
1802
|
+
* @param l1 - First lens (applied first)
|
|
1803
|
+
* @param l2 - Second lens (applied second)
|
|
1804
|
+
* @returns A new LensHandle representing the composition
|
|
1805
|
+
* @throws {@link import('./types.js').WasmError} if composition fails
|
|
1806
|
+
*/
|
|
1807
|
+
composeLenses(l1, l2) {
|
|
1808
|
+
try {
|
|
1809
|
+
const rawHandle = this.#wasm.exports.compose_lenses(
|
|
1810
|
+
l1._handle.id,
|
|
1811
|
+
l2._handle.id
|
|
1812
|
+
);
|
|
1813
|
+
const handle = createHandle(rawHandle, this.#wasm);
|
|
1814
|
+
return new LensHandle(handle, this.#wasm);
|
|
1815
|
+
} catch (error) {
|
|
1816
|
+
throw new WasmError(
|
|
1817
|
+
`compose_lenses failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1818
|
+
{ cause: error }
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
946
1822
|
/**
|
|
947
1823
|
* Diff two schemas and produce a compatibility report.
|
|
948
1824
|
*
|
|
@@ -957,6 +1833,90 @@ class Panproto {
|
|
|
957
1833
|
);
|
|
958
1834
|
return unpackFromWasm(resultBytes);
|
|
959
1835
|
}
|
|
1836
|
+
/** Diff two schemas using the full panproto-check engine (20+ change categories). */
|
|
1837
|
+
diffFull(oldSchema, newSchema) {
|
|
1838
|
+
const bytes = this.#wasm.exports.diff_schemas_full(
|
|
1839
|
+
oldSchema._handle.id,
|
|
1840
|
+
newSchema._handle.id
|
|
1841
|
+
);
|
|
1842
|
+
const data = unpackFromWasm(bytes);
|
|
1843
|
+
return new FullDiffReport(data, bytes, this.#wasm);
|
|
1844
|
+
}
|
|
1845
|
+
/** Normalize a schema by collapsing reference chains. Returns a new BuiltSchema. */
|
|
1846
|
+
normalize(schema) {
|
|
1847
|
+
const handle = this.#wasm.exports.normalize_schema(schema._handle.id);
|
|
1848
|
+
return BuiltSchema._fromHandle(handle, schema.data, schema.protocol, this.#wasm);
|
|
1849
|
+
}
|
|
1850
|
+
/** Validate a schema against its protocol's rules. */
|
|
1851
|
+
validateSchema(schema, protocol) {
|
|
1852
|
+
const bytes = this.#wasm.exports.validate_schema(
|
|
1853
|
+
schema._handle.id,
|
|
1854
|
+
protocol._handle.id
|
|
1855
|
+
);
|
|
1856
|
+
const issues = unpackFromWasm(bytes);
|
|
1857
|
+
return new ValidationResult(issues);
|
|
1858
|
+
}
|
|
1859
|
+
/**
|
|
1860
|
+
* Create an I/O protocol registry for parsing and emitting instances.
|
|
1861
|
+
*
|
|
1862
|
+
* The returned registry wraps all 77 built-in protocol codecs and
|
|
1863
|
+
* implements `Disposable` for automatic cleanup.
|
|
1864
|
+
*
|
|
1865
|
+
* @returns A new IoRegistry
|
|
1866
|
+
*/
|
|
1867
|
+
io() {
|
|
1868
|
+
const rawHandle = this.#wasm.exports.register_io_protocols();
|
|
1869
|
+
const handle = createHandle(rawHandle, this.#wasm);
|
|
1870
|
+
return new IoRegistry(handle, this.#wasm);
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Parse JSON bytes into an Instance.
|
|
1874
|
+
*
|
|
1875
|
+
* Convenience method that wraps `json_to_instance`.
|
|
1876
|
+
*
|
|
1877
|
+
* @param schema - The schema the JSON data conforms to
|
|
1878
|
+
* @param json - JSON bytes or a JSON string
|
|
1879
|
+
* @returns A new Instance
|
|
1880
|
+
*/
|
|
1881
|
+
parseJson(schema, json) {
|
|
1882
|
+
const jsonBytes = typeof json === "string" ? new TextEncoder().encode(json) : json;
|
|
1883
|
+
return Instance.fromJson(schema, jsonBytes, this.#wasm);
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Convert an Instance to JSON bytes.
|
|
1887
|
+
*
|
|
1888
|
+
* Convenience method that wraps `instance_to_json`.
|
|
1889
|
+
*
|
|
1890
|
+
* @param schema - The schema the instance conforms to
|
|
1891
|
+
* @param instance - The instance to convert
|
|
1892
|
+
* @returns JSON bytes
|
|
1893
|
+
*/
|
|
1894
|
+
toJson(schema, instance) {
|
|
1895
|
+
return this.#wasm.exports.instance_to_json(
|
|
1896
|
+
schema._handle.id,
|
|
1897
|
+
instance._bytes
|
|
1898
|
+
);
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* List all built-in protocol names.
|
|
1902
|
+
*
|
|
1903
|
+
* Returns the names of all 76 built-in protocols supported by the
|
|
1904
|
+
* WASM layer.
|
|
1905
|
+
*
|
|
1906
|
+
* @returns Array of protocol name strings
|
|
1907
|
+
*/
|
|
1908
|
+
listProtocols() {
|
|
1909
|
+
return [...getProtocolNames(this.#wasm)];
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Initialize an in-memory VCS repository.
|
|
1913
|
+
*
|
|
1914
|
+
* @param protocolName - The protocol name for this repository
|
|
1915
|
+
* @returns A disposable VCS Repository
|
|
1916
|
+
*/
|
|
1917
|
+
initRepo(protocolName) {
|
|
1918
|
+
return Repository.init(protocolName, this.#wasm);
|
|
1919
|
+
}
|
|
960
1920
|
/**
|
|
961
1921
|
* Release all WASM resources held by this instance.
|
|
962
1922
|
*
|
|
@@ -970,52 +1930,164 @@ class Panproto {
|
|
|
970
1930
|
this.#protocols.clear();
|
|
971
1931
|
}
|
|
972
1932
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1933
|
+
class TheoryHandle {
|
|
1934
|
+
#handle;
|
|
1935
|
+
/** @internal Retained for future sort/op inspection methods. */
|
|
1936
|
+
_wasm;
|
|
1937
|
+
constructor(handle, wasm) {
|
|
1938
|
+
this.#handle = handle;
|
|
1939
|
+
this._wasm = wasm;
|
|
1940
|
+
}
|
|
1941
|
+
/** The WASM handle. Internal use only. */
|
|
1942
|
+
get _handle() {
|
|
1943
|
+
return this.#handle;
|
|
1944
|
+
}
|
|
1945
|
+
/** Release the WASM-side theory resource. */
|
|
1946
|
+
[Symbol.dispose]() {
|
|
1947
|
+
this.#handle[Symbol.dispose]();
|
|
1948
|
+
}
|
|
981
1949
|
}
|
|
982
|
-
|
|
983
|
-
|
|
1950
|
+
class TheoryBuilder {
|
|
1951
|
+
#name;
|
|
1952
|
+
#extends;
|
|
1953
|
+
#sorts;
|
|
1954
|
+
#ops;
|
|
1955
|
+
#eqs;
|
|
1956
|
+
constructor(name) {
|
|
1957
|
+
this.#name = name;
|
|
1958
|
+
this.#extends = [];
|
|
1959
|
+
this.#sorts = [];
|
|
1960
|
+
this.#ops = [];
|
|
1961
|
+
this.#eqs = [];
|
|
1962
|
+
}
|
|
1963
|
+
/** Declare that this theory extends a parent theory. */
|
|
1964
|
+
extends(parentName) {
|
|
1965
|
+
this.#extends.push(parentName);
|
|
1966
|
+
return this;
|
|
1967
|
+
}
|
|
1968
|
+
/** Add a simple sort (no parameters). */
|
|
1969
|
+
sort(name) {
|
|
1970
|
+
this.#sorts.push({ name, params: [] });
|
|
1971
|
+
return this;
|
|
1972
|
+
}
|
|
1973
|
+
/** Add a dependent sort with parameters. */
|
|
1974
|
+
dependentSort(name, params) {
|
|
1975
|
+
this.#sorts.push({ name, params });
|
|
1976
|
+
return this;
|
|
1977
|
+
}
|
|
1978
|
+
/** Add an operation. */
|
|
1979
|
+
op(name, inputs, output) {
|
|
1980
|
+
this.#ops.push({ name, inputs, output });
|
|
1981
|
+
return this;
|
|
1982
|
+
}
|
|
1983
|
+
/** Add an equation (axiom). */
|
|
1984
|
+
eq(name, lhs, rhs) {
|
|
1985
|
+
this.#eqs.push({ name, lhs, rhs });
|
|
1986
|
+
return this;
|
|
1987
|
+
}
|
|
1988
|
+
/** Get the theory specification. */
|
|
1989
|
+
toSpec() {
|
|
1990
|
+
return {
|
|
1991
|
+
name: this.#name,
|
|
1992
|
+
extends: this.#extends,
|
|
1993
|
+
sorts: this.#sorts,
|
|
1994
|
+
ops: this.#ops,
|
|
1995
|
+
eqs: this.#eqs
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1999
|
+
* Build the theory and register it in WASM.
|
|
2000
|
+
*
|
|
2001
|
+
* @param wasm - The WASM module
|
|
2002
|
+
* @returns A disposable TheoryHandle
|
|
2003
|
+
* @throws {@link PanprotoError} if the WASM call fails
|
|
2004
|
+
*/
|
|
2005
|
+
build(wasm) {
|
|
2006
|
+
return createTheory(this.toSpec(), wasm);
|
|
2007
|
+
}
|
|
984
2008
|
}
|
|
985
|
-
function
|
|
986
|
-
|
|
2009
|
+
function createTheory(spec, wasm) {
|
|
2010
|
+
try {
|
|
2011
|
+
const bytes = packToWasm(spec);
|
|
2012
|
+
const rawHandle = wasm.exports.create_theory(bytes);
|
|
2013
|
+
const handle = createHandle(rawHandle, wasm);
|
|
2014
|
+
return new TheoryHandle(handle, wasm);
|
|
2015
|
+
} catch (error) {
|
|
2016
|
+
throw new PanprotoError(
|
|
2017
|
+
`Failed to create theory "${spec.name}": ${error instanceof Error ? error.message : String(error)}`,
|
|
2018
|
+
{ cause: error }
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
987
2021
|
}
|
|
988
|
-
function
|
|
989
|
-
|
|
2022
|
+
function colimit(t1, t2, shared, wasm) {
|
|
2023
|
+
try {
|
|
2024
|
+
const rawHandle = wasm.exports.colimit_theories(
|
|
2025
|
+
t1._handle.id,
|
|
2026
|
+
t2._handle.id,
|
|
2027
|
+
shared._handle.id
|
|
2028
|
+
);
|
|
2029
|
+
const handle = createHandle(rawHandle, wasm);
|
|
2030
|
+
return new TheoryHandle(handle, wasm);
|
|
2031
|
+
} catch (error) {
|
|
2032
|
+
throw new WasmError(
|
|
2033
|
+
`colimit_theories failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
2034
|
+
{ cause: error }
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
990
2037
|
}
|
|
991
|
-
function
|
|
992
|
-
|
|
2038
|
+
function checkMorphism(morphism, domain, codomain, wasm) {
|
|
2039
|
+
const morphBytes = packToWasm(morphism);
|
|
2040
|
+
const resultBytes = wasm.exports.check_morphism(
|
|
2041
|
+
morphBytes,
|
|
2042
|
+
domain._handle.id,
|
|
2043
|
+
codomain._handle.id
|
|
2044
|
+
);
|
|
2045
|
+
return unpackFromWasm(resultBytes);
|
|
993
2046
|
}
|
|
994
|
-
function
|
|
995
|
-
const
|
|
996
|
-
|
|
2047
|
+
function migrateModel(sortInterp, morphism, wasm) {
|
|
2048
|
+
const modelBytes = packToWasm(sortInterp);
|
|
2049
|
+
const morphBytes = packToWasm(morphism);
|
|
2050
|
+
const resultBytes = wasm.exports.migrate_model(modelBytes, morphBytes);
|
|
2051
|
+
return unpackFromWasm(resultBytes);
|
|
997
2052
|
}
|
|
998
2053
|
exports.ATPROTO_SPEC = ATPROTO_SPEC;
|
|
999
2054
|
exports.BUILTIN_PROTOCOLS = BUILTIN_PROTOCOLS;
|
|
1000
2055
|
exports.BuiltSchema = BuiltSchema;
|
|
2056
|
+
exports.CompatReport = CompatReport;
|
|
1001
2057
|
exports.CompiledMigration = CompiledMigration;
|
|
1002
2058
|
exports.ExistenceCheckError = ExistenceCheckError;
|
|
2059
|
+
exports.FullDiffReport = FullDiffReport;
|
|
1003
2060
|
exports.GRAPHQL_SPEC = GRAPHQL_SPEC;
|
|
2061
|
+
exports.Instance = Instance;
|
|
2062
|
+
exports.IoRegistry = IoRegistry;
|
|
1004
2063
|
exports.JSON_SCHEMA_SPEC = JSON_SCHEMA_SPEC;
|
|
2064
|
+
exports.LensHandle = LensHandle;
|
|
1005
2065
|
exports.MigrationBuilder = MigrationBuilder;
|
|
1006
2066
|
exports.MigrationError = MigrationError;
|
|
1007
2067
|
exports.PROTOBUF_SPEC = PROTOBUF_SPEC;
|
|
2068
|
+
exports.PROTOCOL_CATEGORIES = PROTOCOL_CATEGORIES;
|
|
1008
2069
|
exports.Panproto = Panproto;
|
|
1009
2070
|
exports.PanprotoError = PanprotoError;
|
|
1010
2071
|
exports.Protocol = Protocol;
|
|
2072
|
+
exports.Repository = Repository;
|
|
1011
2073
|
exports.SQL_SPEC = SQL_SPEC;
|
|
1012
2074
|
exports.SchemaBuilder = SchemaBuilder;
|
|
1013
2075
|
exports.SchemaValidationError = SchemaValidationError;
|
|
2076
|
+
exports.TheoryBuilder = TheoryBuilder;
|
|
2077
|
+
exports.TheoryHandle = TheoryHandle;
|
|
2078
|
+
exports.ValidationResult = ValidationResult;
|
|
1014
2079
|
exports.WasmError = WasmError;
|
|
1015
2080
|
exports.addField = addField;
|
|
2081
|
+
exports.checkMorphism = checkMorphism;
|
|
1016
2082
|
exports.coerceType = coerceType;
|
|
2083
|
+
exports.colimit = colimit;
|
|
1017
2084
|
exports.compose = compose;
|
|
2085
|
+
exports.createTheory = createTheory;
|
|
2086
|
+
exports.fromCombinators = fromCombinators;
|
|
2087
|
+
exports.getBuiltinProtocol = getBuiltinProtocol;
|
|
2088
|
+
exports.getProtocolNames = getProtocolNames;
|
|
1018
2089
|
exports.hoistField = hoistField;
|
|
2090
|
+
exports.migrateModel = migrateModel;
|
|
1019
2091
|
exports.pipeline = pipeline;
|
|
1020
2092
|
exports.removeField = removeField;
|
|
1021
2093
|
exports.renameField = renameField;
|