@panproto/core 0.6.0 → 0.8.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/index.cjs CHANGED
@@ -71,7 +71,21 @@ async function loadWasm(input) {
71
71
  get_json: glue.get_json,
72
72
  put_json: glue.put_json,
73
73
  instance_element_count: glue.instance_element_count,
74
- lens_from_combinators: glue.lens_from_combinators,
74
+ auto_generate_protolens: glue.auto_generate_protolens,
75
+ instantiate_protolens: glue.instantiate_protolens,
76
+ protolens_complement_spec: glue.protolens_complement_spec,
77
+ protolens_from_diff: glue.protolens_from_diff,
78
+ protolens_compose: glue.protolens_compose,
79
+ protolens_chain_to_json: glue.protolens_chain_to_json,
80
+ factorize_morphism: glue.factorize_morphism,
81
+ symmetric_lens_from_schemas: glue.symmetric_lens_from_schemas,
82
+ symmetric_lens_sync: glue.symmetric_lens_sync,
83
+ apply_protolens_step: glue.apply_protolens_step,
84
+ protolens_from_json: glue.protolens_from_json,
85
+ protolens_fuse: glue.protolens_fuse,
86
+ protolens_lift: glue.protolens_lift,
87
+ protolens_check_applicability: glue.protolens_check_applicability,
88
+ protolens_fleet: glue.protolens_fleet,
75
89
  check_lens_laws: glue.check_lens_laws,
76
90
  check_get_put: glue.check_get_put,
77
91
  check_put_get: glue.check_put_get,
@@ -97,7 +111,16 @@ async function loadWasm(input) {
97
111
  vcs_merge: glue.vcs_merge,
98
112
  vcs_stash: glue.vcs_stash,
99
113
  vcs_stash_pop: glue.vcs_stash_pop,
100
- vcs_blame: glue.vcs_blame
114
+ vcs_blame: glue.vcs_blame,
115
+ // Phase 7: Data versioning
116
+ store_dataset: glue.store_dataset,
117
+ get_dataset: glue.get_dataset,
118
+ migrate_dataset_forward: glue.migrate_dataset_forward,
119
+ migrate_dataset_backward: glue.migrate_dataset_backward,
120
+ check_dataset_staleness: glue.check_dataset_staleness,
121
+ store_protocol_definition: glue.store_protocol_definition,
122
+ get_protocol_definition: glue.get_protocol_definition,
123
+ get_migration_complement: glue.get_migration_complement
101
124
  };
102
125
  const memory = initOutput.memory;
103
126
  if (!memory) {
@@ -171,30 +194,212 @@ function packMigrationMapping(mapping) {
171
194
  hyper_resolver: []
172
195
  });
173
196
  }
174
- function renameField(oldName, newName) {
175
- return { type: "rename-field", old: oldName, new: newName };
176
- }
177
- function addField(name, vertexKind, defaultValue) {
178
- return { type: "add-field", name, vertexKind, default: defaultValue };
179
- }
180
- function removeField(name) {
181
- return { type: "remove-field", name };
182
- }
183
- function wrapInObject(fieldName) {
184
- return { type: "wrap-in-object", fieldName };
185
- }
186
- function hoistField(host, field) {
187
- return { type: "hoist-field", host, field };
188
- }
189
- function coerceType(fromKind, toKind) {
190
- return { type: "coerce-type", fromKind, toKind };
191
- }
192
- function compose(first, second) {
193
- return { type: "compose", first, second };
194
- }
195
- function pipeline(combinators) {
196
- const [first, ...rest] = combinators;
197
- return rest.reduce((acc, c) => compose(acc, c), first);
197
+ class ProtolensChainHandle {
198
+ #handle;
199
+ #wasm;
200
+ constructor(handle, wasm) {
201
+ this.#handle = handle;
202
+ this.#wasm = wasm;
203
+ }
204
+ /** The underlying WASM handle. Internal use only. */
205
+ get _handle() {
206
+ return this.#handle;
207
+ }
208
+ /**
209
+ * Auto-generate a protolens chain between two schemas.
210
+ *
211
+ * @param schema1 - The source schema
212
+ * @param schema2 - The target schema
213
+ * @param wasm - The WASM module
214
+ * @returns A ProtolensChainHandle wrapping the generated chain
215
+ * @throws {@link WasmError} if the WASM call fails
216
+ */
217
+ static autoGenerate(schema1, schema2, wasm) {
218
+ try {
219
+ const rawHandle = wasm.exports.auto_generate_protolens(schema1._handle.id, schema2._handle.id);
220
+ return new ProtolensChainHandle(createHandle(rawHandle, wasm), wasm);
221
+ } catch (error) {
222
+ throw new WasmError(
223
+ `auto_generate_protolens failed: ${error instanceof Error ? error.message : String(error)}`,
224
+ { cause: error }
225
+ );
226
+ }
227
+ }
228
+ /**
229
+ * Instantiate this protolens chain against a concrete schema.
230
+ *
231
+ * @param schema - The schema to instantiate against
232
+ * @returns A LensHandle for the instantiated lens
233
+ * @throws {@link WasmError} if the WASM call fails
234
+ */
235
+ instantiate(schema) {
236
+ try {
237
+ const rawHandle = this.#wasm.exports.instantiate_protolens(this.#handle.id, schema._handle.id);
238
+ return new LensHandle(createHandle(rawHandle, this.#wasm), this.#wasm);
239
+ } catch (error) {
240
+ throw new WasmError(
241
+ `instantiate_protolens failed: ${error instanceof Error ? error.message : String(error)}`,
242
+ { cause: error }
243
+ );
244
+ }
245
+ }
246
+ /**
247
+ * Get the complement specification for instantiation against a schema.
248
+ *
249
+ * @param schema - The schema to check requirements against
250
+ * @returns The complement spec describing defaults and captured data
251
+ * @throws {@link WasmError} if the WASM call fails
252
+ */
253
+ requirements(schema) {
254
+ try {
255
+ const bytes = this.#wasm.exports.protolens_complement_spec(this.#handle.id, schema._handle.id);
256
+ return unpackFromWasm(bytes);
257
+ } catch (error) {
258
+ throw new WasmError(
259
+ `protolens_complement_spec failed: ${error instanceof Error ? error.message : String(error)}`,
260
+ { cause: error }
261
+ );
262
+ }
263
+ }
264
+ /**
265
+ * Compose this chain with another protolens chain.
266
+ *
267
+ * @param other - The chain to compose with (applied second)
268
+ * @returns A new ProtolensChainHandle for the composed chain
269
+ * @throws {@link WasmError} if the WASM call fails
270
+ */
271
+ compose(other) {
272
+ try {
273
+ const rawHandle = this.#wasm.exports.protolens_compose(this.#handle.id, other.#handle.id);
274
+ return new ProtolensChainHandle(createHandle(rawHandle, this.#wasm), this.#wasm);
275
+ } catch (error) {
276
+ throw new WasmError(
277
+ `protolens_compose failed: ${error instanceof Error ? error.message : String(error)}`,
278
+ { cause: error }
279
+ );
280
+ }
281
+ }
282
+ /**
283
+ * Serialize this chain to a JSON string.
284
+ *
285
+ * @returns A JSON representation of the chain
286
+ * @throws {@link WasmError} if the WASM call fails
287
+ */
288
+ toJson() {
289
+ try {
290
+ const bytes = this.#wasm.exports.protolens_chain_to_json(this.#handle.id);
291
+ return new TextDecoder().decode(bytes);
292
+ } catch (error) {
293
+ throw new WasmError(
294
+ `protolens_chain_to_json failed: ${error instanceof Error ? error.message : String(error)}`,
295
+ { cause: error }
296
+ );
297
+ }
298
+ }
299
+ /**
300
+ * Deserialize a protolens chain from JSON via WASM.
301
+ *
302
+ * @param json - JSON string representing a protolens chain
303
+ * @param wasm - The WASM module
304
+ * @returns A ProtolensChainHandle wrapping the deserialized chain
305
+ * @throws {@link WasmError} if the WASM call fails or JSON is invalid
306
+ */
307
+ static fromJson(json, wasm) {
308
+ try {
309
+ const jsonBytes = new TextEncoder().encode(json);
310
+ const rawHandle = wasm.exports.protolens_from_json(jsonBytes);
311
+ return new ProtolensChainHandle(createHandle(rawHandle, wasm), wasm);
312
+ } catch (error) {
313
+ throw new WasmError(
314
+ `protolens_from_json failed: ${error instanceof Error ? error.message : String(error)}`,
315
+ { cause: error }
316
+ );
317
+ }
318
+ }
319
+ /**
320
+ * Fuse this chain into a single protolens step.
321
+ *
322
+ * Composes all steps into a single step with a composite complement,
323
+ * avoiding intermediate schema materialization.
324
+ *
325
+ * @returns A new ProtolensChainHandle containing the fused step
326
+ * @throws {@link WasmError} if the WASM call fails
327
+ */
328
+ fuse() {
329
+ try {
330
+ const rawHandle = this.#wasm.exports.protolens_fuse(this.#handle.id);
331
+ return new ProtolensChainHandle(createHandle(rawHandle, this.#wasm), this.#wasm);
332
+ } catch (error) {
333
+ throw new WasmError(
334
+ `protolens_fuse failed: ${error instanceof Error ? error.message : String(error)}`,
335
+ { cause: error }
336
+ );
337
+ }
338
+ }
339
+ /**
340
+ * Check whether this chain can be instantiated at a given schema.
341
+ *
342
+ * @param schema - The schema to check against
343
+ * @returns An object with `applicable` boolean and `reasons` array
344
+ * @throws {@link WasmError} if the WASM call fails
345
+ */
346
+ checkApplicability(schema) {
347
+ try {
348
+ const bytes = this.#wasm.exports.protolens_check_applicability(this.#handle.id, schema._handle.id);
349
+ return unpackFromWasm(bytes);
350
+ } catch (error) {
351
+ throw new WasmError(
352
+ `protolens_check_applicability failed: ${error instanceof Error ? error.message : String(error)}`,
353
+ { cause: error }
354
+ );
355
+ }
356
+ }
357
+ /**
358
+ * Lift this chain along a theory morphism.
359
+ *
360
+ * Given a morphism between theories, produces a new chain that operates
361
+ * on schemas of the codomain theory instead of the domain theory.
362
+ *
363
+ * @param morphismBytes - MessagePack-encoded theory morphism
364
+ * @returns A new ProtolensChainHandle for the lifted chain
365
+ * @throws {@link WasmError} if the WASM call fails
366
+ */
367
+ lift(morphismBytes) {
368
+ try {
369
+ const rawHandle = this.#wasm.exports.protolens_lift(this.#handle.id, morphismBytes);
370
+ return new ProtolensChainHandle(createHandle(rawHandle, this.#wasm), this.#wasm);
371
+ } catch (error) {
372
+ throw new WasmError(
373
+ `protolens_lift failed: ${error instanceof Error ? error.message : String(error)}`,
374
+ { cause: error }
375
+ );
376
+ }
377
+ }
378
+ /**
379
+ * Apply this chain to a fleet of schemas.
380
+ *
381
+ * Checks applicability and instantiates the chain against each schema.
382
+ *
383
+ * @param schemas - Array of schema handles to apply the chain to
384
+ * @returns Fleet result with applied/skipped schema names and reasons
385
+ * @throws {@link WasmError} if the WASM call fails
386
+ */
387
+ applyToFleet(schemas) {
388
+ try {
389
+ const handles = new Uint32Array(schemas.map((s) => s._handle.id));
390
+ const bytes = this.#wasm.exports.protolens_fleet(this.#handle.id, handles);
391
+ return unpackFromWasm(bytes);
392
+ } catch (error) {
393
+ throw new WasmError(
394
+ `protolens_fleet failed: ${error instanceof Error ? error.message : String(error)}`,
395
+ { cause: error }
396
+ );
397
+ }
398
+ }
399
+ /** Release the underlying WASM resource. */
400
+ [Symbol.dispose]() {
401
+ this.#handle[Symbol.dispose]();
402
+ }
198
403
  }
199
404
  class LensHandle {
200
405
  #handle;
@@ -207,6 +412,53 @@ class LensHandle {
207
412
  get _handle() {
208
413
  return this.#handle;
209
414
  }
415
+ /**
416
+ * Auto-generate a lens between two schemas.
417
+ *
418
+ * Generates a protolens chain and immediately instantiates it.
419
+ *
420
+ * @param schema1 - The source schema
421
+ * @param schema2 - The target schema
422
+ * @param wasm - The WASM module
423
+ * @returns A LensHandle wrapping the generated lens
424
+ * @throws {@link WasmError} if the WASM call fails
425
+ */
426
+ static autoGenerate(schema1, schema2, wasm) {
427
+ try {
428
+ const rawHandle = wasm.exports.auto_generate_protolens(schema1._handle.id, schema2._handle.id);
429
+ const chainHandle = createHandle(rawHandle, wasm);
430
+ const lensRaw = wasm.exports.instantiate_protolens(chainHandle.id, schema1._handle.id);
431
+ chainHandle[Symbol.dispose]();
432
+ const handle = createHandle(lensRaw, wasm);
433
+ return new LensHandle(handle, wasm);
434
+ } catch (error) {
435
+ throw new WasmError(
436
+ `autoGenerate failed: ${error instanceof Error ? error.message : String(error)}`,
437
+ { cause: error }
438
+ );
439
+ }
440
+ }
441
+ /**
442
+ * Create a lens by instantiating a protolens chain against a schema.
443
+ *
444
+ * @param chain - The protolens chain to instantiate
445
+ * @param schema - The schema to instantiate against
446
+ * @param wasm - The WASM module
447
+ * @returns A LensHandle wrapping the instantiated lens
448
+ * @throws {@link WasmError} if the WASM call fails
449
+ */
450
+ static fromChain(chain, schema, wasm) {
451
+ try {
452
+ const rawHandle = wasm.exports.instantiate_protolens(chain._handle.id, schema._handle.id);
453
+ const handle = createHandle(rawHandle, wasm);
454
+ return new LensHandle(handle, wasm);
455
+ } catch (error) {
456
+ throw new WasmError(
457
+ `fromChain failed: ${error instanceof Error ? error.message : String(error)}`,
458
+ { cause: error }
459
+ );
460
+ }
461
+ }
210
462
  /**
211
463
  * Forward projection: extract the view from a record.
212
464
  *
@@ -324,40 +576,74 @@ class LensHandle {
324
576
  this.#handle[Symbol.dispose]();
325
577
  }
326
578
  }
327
- function fromCombinators(schema, protocol, wasm, ...combinators) {
328
- const wireCombs = combinators.map(combinatorToWire);
329
- const combBytes = packToWasm(wireCombs);
330
- try {
331
- const rawHandle = wasm.exports.lens_from_combinators(
332
- schema._handle.id,
333
- protocol._handle.id,
334
- combBytes
335
- );
336
- const handle = createHandle(rawHandle, wasm);
337
- return new LensHandle(handle, wasm);
338
- } catch (error) {
339
- throw new WasmError(
340
- `lens_from_combinators failed: ${error instanceof Error ? error.message : String(error)}`,
341
- { cause: error }
342
- );
579
+ class SymmetricLensHandle {
580
+ #handle;
581
+ #wasm;
582
+ constructor(handle, wasm) {
583
+ this.#handle = handle;
584
+ this.#wasm = wasm;
343
585
  }
344
- }
345
- function combinatorToWire(combinator) {
346
- switch (combinator.type) {
347
- case "rename-field":
348
- return { RenameField: { old: combinator.old, new: combinator.new } };
349
- case "add-field":
350
- return { AddField: { name: combinator.name, vertex_kind: combinator.vertexKind, default: combinator.default } };
351
- case "remove-field":
352
- return { RemoveField: { name: combinator.name } };
353
- case "wrap-in-object":
354
- return { WrapInObject: { field_name: combinator.fieldName } };
355
- case "hoist-field":
356
- return { HoistField: { host: combinator.host, field: combinator.field } };
357
- case "coerce-type":
358
- return { CoerceType: { from_kind: combinator.fromKind, to_kind: combinator.toKind } };
359
- case "compose":
360
- return { Compose: [combinatorToWire(combinator.first), combinatorToWire(combinator.second)] };
586
+ /**
587
+ * Create a symmetric lens between two schemas.
588
+ *
589
+ * @param schema1 - The left schema
590
+ * @param schema2 - The right schema
591
+ * @param wasm - The WASM module
592
+ * @returns A SymmetricLensHandle for bidirectional sync
593
+ * @throws {@link WasmError} if the WASM call fails
594
+ */
595
+ static fromSchemas(schema1, schema2, wasm) {
596
+ try {
597
+ const rawHandle = wasm.exports.symmetric_lens_from_schemas(schema1._handle.id, schema2._handle.id);
598
+ return new SymmetricLensHandle(createHandle(rawHandle, wasm), wasm);
599
+ } catch (error) {
600
+ throw new WasmError(
601
+ `symmetric_lens_from_schemas failed: ${error instanceof Error ? error.message : String(error)}`,
602
+ { cause: error }
603
+ );
604
+ }
605
+ }
606
+ /**
607
+ * Synchronize left view to right view.
608
+ *
609
+ * @param leftView - MessagePack-encoded left view data
610
+ * @param leftComplement - Opaque complement bytes from a prior sync
611
+ * @returns The synchronized right view and updated complement
612
+ * @throws {@link WasmError} if the WASM call fails
613
+ */
614
+ syncLeftToRight(leftView, leftComplement) {
615
+ try {
616
+ const bytes = this.#wasm.exports.symmetric_lens_sync(this.#handle.id, leftView, leftComplement, 0);
617
+ return unpackFromWasm(bytes);
618
+ } catch (error) {
619
+ throw new WasmError(
620
+ `symmetric_lens_sync (left-to-right) failed: ${error instanceof Error ? error.message : String(error)}`,
621
+ { cause: error }
622
+ );
623
+ }
624
+ }
625
+ /**
626
+ * Synchronize right view to left view.
627
+ *
628
+ * @param rightView - MessagePack-encoded right view data
629
+ * @param rightComplement - Opaque complement bytes from a prior sync
630
+ * @returns The synchronized left view and updated complement
631
+ * @throws {@link WasmError} if the WASM call fails
632
+ */
633
+ syncRightToLeft(rightView, rightComplement) {
634
+ try {
635
+ const bytes = this.#wasm.exports.symmetric_lens_sync(this.#handle.id, rightView, rightComplement, 1);
636
+ return unpackFromWasm(bytes);
637
+ } catch (error) {
638
+ throw new WasmError(
639
+ `symmetric_lens_sync (right-to-left) failed: ${error instanceof Error ? error.message : String(error)}`,
640
+ { cause: error }
641
+ );
642
+ }
643
+ }
644
+ /** Release the underlying WASM resource. */
645
+ [Symbol.dispose]() {
646
+ this.#handle[Symbol.dispose]();
361
647
  }
362
648
  }
363
649
  class FullDiffReport {
@@ -1703,6 +1989,70 @@ class Repository {
1703
1989
  this.#handle[Symbol.dispose]();
1704
1990
  }
1705
1991
  }
1992
+ class DataSetHandle {
1993
+ #handle;
1994
+ #wasm;
1995
+ constructor(handle, wasm) {
1996
+ this.#handle = handle;
1997
+ this.#wasm = wasm;
1998
+ }
1999
+ /** The WASM handle for this data set. Internal use only. */
2000
+ get _handle() {
2001
+ return this.#handle;
2002
+ }
2003
+ /** Store a data set from a JavaScript object, bound to a schema. */
2004
+ static fromData(data, schema, wasm) {
2005
+ const jsonBytes = new TextEncoder().encode(JSON.stringify(data));
2006
+ const rawHandle = wasm.exports.store_dataset(schema._handle.id, jsonBytes);
2007
+ return new DataSetHandle(createHandle(rawHandle, wasm), wasm);
2008
+ }
2009
+ /** Retrieve the data as MessagePack-encoded bytes. */
2010
+ getData() {
2011
+ const bytes = this.#wasm.exports.get_dataset(this.#handle.id);
2012
+ return unpackFromWasm(bytes);
2013
+ }
2014
+ /** Migrate this data set forward to a new schema. */
2015
+ migrateForward(srcSchema, tgtSchema) {
2016
+ const bytes = this.#wasm.exports.migrate_dataset_forward(
2017
+ this.#handle.id,
2018
+ srcSchema._handle.id,
2019
+ tgtSchema._handle.id
2020
+ );
2021
+ const result = unpackFromWasm(bytes);
2022
+ const complementBytes = this.#wasm.exports.get_dataset(result.complement_handle);
2023
+ this.#wasm.exports.free_handle(result.complement_handle);
2024
+ return {
2025
+ data: new DataSetHandle(createHandle(result.data_handle, this.#wasm), this.#wasm),
2026
+ complement: new Uint8Array(complementBytes)
2027
+ };
2028
+ }
2029
+ /** Migrate this data set backward using a complement. */
2030
+ migrateBackward(complement, srcSchema, tgtSchema) {
2031
+ const rawHandle = this.#wasm.exports.migrate_dataset_backward(
2032
+ this.#handle.id,
2033
+ complement,
2034
+ srcSchema._handle.id,
2035
+ tgtSchema._handle.id
2036
+ );
2037
+ return new DataSetHandle(createHandle(rawHandle, this.#wasm), this.#wasm);
2038
+ }
2039
+ /** Check if this data set is stale relative to a schema. */
2040
+ isStale(schema) {
2041
+ const bytes = this.#wasm.exports.check_dataset_staleness(
2042
+ this.#handle.id,
2043
+ schema._handle.id
2044
+ );
2045
+ const raw = unpackFromWasm(bytes);
2046
+ return {
2047
+ stale: raw.stale,
2048
+ dataSchemaId: raw.data_schema_id,
2049
+ targetSchemaId: raw.target_schema_id
2050
+ };
2051
+ }
2052
+ [Symbol.dispose]() {
2053
+ this.#handle[Symbol.dispose]();
2054
+ }
2055
+ }
1706
2056
  class Panproto {
1707
2057
  #wasm;
1708
2058
  #protocols;
@@ -1710,6 +2060,10 @@ class Panproto {
1710
2060
  this.#wasm = wasm;
1711
2061
  this.#protocols = /* @__PURE__ */ new Map();
1712
2062
  }
2063
+ /** The WASM module reference. Internal use only. */
2064
+ get _wasm() {
2065
+ return this.#wasm;
2066
+ }
1713
2067
  /**
1714
2068
  * Initialize the panproto SDK by loading the WASM module.
1715
2069
  *
@@ -1932,6 +2286,76 @@ class Panproto {
1932
2286
  initRepo(protocolName) {
1933
2287
  return Repository.init(protocolName, this.#wasm);
1934
2288
  }
2289
+ /**
2290
+ * Convert data from one schema to another using an auto-generated lens.
2291
+ *
2292
+ * This is a convenience method that generates a protolens, applies the
2293
+ * forward projection, and disposes the lens automatically.
2294
+ *
2295
+ * @param data - The input data (Uint8Array of MessagePack, or a plain object)
2296
+ * @param opts - Conversion options specifying source and target schemas
2297
+ * @returns The converted data
2298
+ * @throws {@link WasmError} if lens generation or conversion fails
2299
+ */
2300
+ async convert(data, opts) {
2301
+ const lens = LensHandle.autoGenerate(opts.from, opts.to, this.#wasm);
2302
+ try {
2303
+ const input = data instanceof Uint8Array ? data : packToWasm(data);
2304
+ const result = lens.get(input);
2305
+ return result.view;
2306
+ } finally {
2307
+ lens[Symbol.dispose]();
2308
+ }
2309
+ }
2310
+ /**
2311
+ * Create an auto-generated lens between two schemas.
2312
+ *
2313
+ * @param from - The source schema
2314
+ * @param to - The target schema
2315
+ * @returns A LensHandle for the generated lens
2316
+ * @throws {@link WasmError} if lens generation fails
2317
+ */
2318
+ lens(from, to) {
2319
+ return LensHandle.autoGenerate(from, to, this.#wasm);
2320
+ }
2321
+ /**
2322
+ * Create a protolens chain between two schemas.
2323
+ *
2324
+ * The returned chain is schema-independent and can be instantiated
2325
+ * against different concrete schemas.
2326
+ *
2327
+ * @param from - The source schema
2328
+ * @param to - The target schema
2329
+ * @returns A ProtolensChainHandle for the generated chain
2330
+ * @throws {@link WasmError} if chain generation fails
2331
+ */
2332
+ protolensChain(from, to) {
2333
+ return ProtolensChainHandle.autoGenerate(from, to, this.#wasm);
2334
+ }
2335
+ /**
2336
+ * Store and track a data set against a schema.
2337
+ *
2338
+ * @param data - The data to store (array of records or a single object)
2339
+ * @param schema - The schema this data conforms to
2340
+ * @returns A disposable DataSetHandle
2341
+ */
2342
+ dataSet(data, schema) {
2343
+ return DataSetHandle.fromData(data, schema, this.#wasm);
2344
+ }
2345
+ /**
2346
+ * Migrate data forward between two schemas.
2347
+ *
2348
+ * Auto-generates a lens and migrates each record, returning the
2349
+ * migrated data and a complement for backward migration.
2350
+ *
2351
+ * @param data - The data set to migrate
2352
+ * @param from - The source schema
2353
+ * @param to - The target schema
2354
+ * @returns The migration result with new data and complement
2355
+ */
2356
+ migrateData(data, from, to) {
2357
+ return data.migrateForward(from, to);
2358
+ }
1935
2359
  /**
1936
2360
  * Release all WASM resources held by this instance.
1937
2361
  *
@@ -1945,6 +2369,535 @@ class Panproto {
1945
2369
  this.#protocols.clear();
1946
2370
  }
1947
2371
  }
2372
+ class SchemaEnrichment {
2373
+ #schema;
2374
+ #defaults;
2375
+ #coercions;
2376
+ #mergers;
2377
+ #policies;
2378
+ constructor(schema, defaults = [], coercions = [], mergers = [], policies = []) {
2379
+ this.#schema = schema;
2380
+ this.#defaults = defaults;
2381
+ this.#coercions = coercions;
2382
+ this.#mergers = mergers;
2383
+ this.#policies = policies;
2384
+ }
2385
+ /**
2386
+ * Add a default expression for a vertex.
2387
+ *
2388
+ * The expression is evaluated when forward migration encounters a
2389
+ * missing value at the given vertex.
2390
+ *
2391
+ * @param vertex - The vertex identifier to attach the default to
2392
+ * @param expr - The default expression
2393
+ * @returns A new enrichment with the default added
2394
+ * @throws {@link PanprotoError} if the vertex is not in the schema
2395
+ */
2396
+ addDefault(vertex, expr) {
2397
+ this.#assertVertex(vertex);
2398
+ if (this.#defaults.some((d) => d.vertex === vertex)) {
2399
+ throw new PanprotoError(
2400
+ `Default already exists for vertex "${vertex}". Remove it first with removeDefault().`
2401
+ );
2402
+ }
2403
+ return new SchemaEnrichment(
2404
+ this.#schema,
2405
+ [...this.#defaults, { vertex, expr }],
2406
+ this.#coercions,
2407
+ this.#mergers,
2408
+ this.#policies
2409
+ );
2410
+ }
2411
+ /**
2412
+ * Add a coercion function between two value kinds.
2413
+ *
2414
+ * The expression defines how to convert values from `fromKind` to
2415
+ * `toKind`. It receives a single argument (the source value) and
2416
+ * must produce a value of the target kind.
2417
+ *
2418
+ * @param fromKind - Source value kind (e.g., 'int')
2419
+ * @param toKind - Target value kind (e.g., 'float')
2420
+ * @param expr - The coercion expression
2421
+ * @returns A new enrichment with the coercion added
2422
+ * @throws {@link PanprotoError} if a coercion for this pair already exists
2423
+ */
2424
+ addCoercion(fromKind, toKind, expr) {
2425
+ if (this.#coercions.some((c) => c.from === fromKind && c.to === toKind)) {
2426
+ throw new PanprotoError(
2427
+ `Coercion from "${fromKind}" to "${toKind}" already exists. Remove it first with removeCoercion().`
2428
+ );
2429
+ }
2430
+ return new SchemaEnrichment(
2431
+ this.#schema,
2432
+ this.#defaults,
2433
+ [...this.#coercions, { from: fromKind, to: toKind, expr }],
2434
+ this.#mergers,
2435
+ this.#policies
2436
+ );
2437
+ }
2438
+ /**
2439
+ * Add a merger expression for a vertex.
2440
+ *
2441
+ * The expression defines how to merge two conflicting values at the
2442
+ * given vertex. It receives two arguments (left and right values)
2443
+ * and must produce a single merged value.
2444
+ *
2445
+ * @param vertex - The vertex identifier to attach the merger to
2446
+ * @param expr - The merger expression
2447
+ * @returns A new enrichment with the merger added
2448
+ * @throws {@link PanprotoError} if the vertex is not in the schema
2449
+ */
2450
+ addMerger(vertex, expr) {
2451
+ this.#assertVertex(vertex);
2452
+ if (this.#mergers.some((m) => m.vertex === vertex)) {
2453
+ throw new PanprotoError(
2454
+ `Merger already exists for vertex "${vertex}". Remove it first.`
2455
+ );
2456
+ }
2457
+ return new SchemaEnrichment(
2458
+ this.#schema,
2459
+ this.#defaults,
2460
+ this.#coercions,
2461
+ [...this.#mergers, { vertex, expr }],
2462
+ this.#policies
2463
+ );
2464
+ }
2465
+ /**
2466
+ * Add a conflict resolution policy for a vertex.
2467
+ *
2468
+ * @param vertex - The vertex identifier
2469
+ * @param strategy - The conflict resolution strategy
2470
+ * @returns A new enrichment with the policy added
2471
+ * @throws {@link PanprotoError} if the vertex is not in the schema
2472
+ */
2473
+ addPolicy(vertex, strategy) {
2474
+ this.#assertVertex(vertex);
2475
+ if (this.#policies.some((p) => p.vertex === vertex)) {
2476
+ throw new PanprotoError(
2477
+ `Policy already exists for vertex "${vertex}". Remove it first.`
2478
+ );
2479
+ }
2480
+ return new SchemaEnrichment(
2481
+ this.#schema,
2482
+ this.#defaults,
2483
+ this.#coercions,
2484
+ this.#mergers,
2485
+ [...this.#policies, { vertex, strategy }]
2486
+ );
2487
+ }
2488
+ /**
2489
+ * Remove the default expression for a vertex.
2490
+ *
2491
+ * @param vertex - The vertex identifier
2492
+ * @returns A new enrichment with the default removed
2493
+ * @throws {@link PanprotoError} if no default exists for the vertex
2494
+ */
2495
+ removeDefault(vertex) {
2496
+ const filtered = this.#defaults.filter((d) => d.vertex !== vertex);
2497
+ if (filtered.length === this.#defaults.length) {
2498
+ throw new PanprotoError(
2499
+ `No default exists for vertex "${vertex}".`
2500
+ );
2501
+ }
2502
+ return new SchemaEnrichment(
2503
+ this.#schema,
2504
+ filtered,
2505
+ this.#coercions,
2506
+ this.#mergers,
2507
+ this.#policies
2508
+ );
2509
+ }
2510
+ /**
2511
+ * Remove the coercion function for a value kind pair.
2512
+ *
2513
+ * @param fromKind - Source value kind
2514
+ * @param toKind - Target value kind
2515
+ * @returns A new enrichment with the coercion removed
2516
+ * @throws {@link PanprotoError} if no coercion exists for the pair
2517
+ */
2518
+ removeCoercion(fromKind, toKind) {
2519
+ const filtered = this.#coercions.filter(
2520
+ (c) => !(c.from === fromKind && c.to === toKind)
2521
+ );
2522
+ if (filtered.length === this.#coercions.length) {
2523
+ throw new PanprotoError(
2524
+ `No coercion exists from "${fromKind}" to "${toKind}".`
2525
+ );
2526
+ }
2527
+ return new SchemaEnrichment(
2528
+ this.#schema,
2529
+ this.#defaults,
2530
+ filtered,
2531
+ this.#mergers,
2532
+ this.#policies
2533
+ );
2534
+ }
2535
+ /**
2536
+ * List all enrichments currently attached.
2537
+ *
2538
+ * @returns An enrichment summary with defaults, coercions, mergers, and policies
2539
+ */
2540
+ listEnrichments() {
2541
+ return {
2542
+ defaults: this.#defaults.map((d) => ({ vertex: d.vertex, expr: d.expr })),
2543
+ coercions: this.#coercions.map((c) => ({ from: c.from, to: c.to, expr: c.expr })),
2544
+ mergers: this.#mergers.map((m) => ({ vertex: m.vertex, expr: m.expr })),
2545
+ policies: this.#policies.map((p) => ({ vertex: p.vertex, strategy: p.strategy }))
2546
+ };
2547
+ }
2548
+ /**
2549
+ * Build the enriched schema.
2550
+ *
2551
+ * Returns a new `BuiltSchema` with the enrichments recorded in the
2552
+ * schema data. The underlying WASM handle is shared with the original
2553
+ * schema (enrichments are metadata that the SDK tracks client-side).
2554
+ *
2555
+ * @returns A new BuiltSchema with enrichment metadata
2556
+ */
2557
+ build() {
2558
+ const originalData = this.#schema.data;
2559
+ const enrichedData = {
2560
+ ...originalData,
2561
+ constraints: {
2562
+ ...originalData.constraints
2563
+ }
2564
+ };
2565
+ const enrichedConstraints = { ...enrichedData.constraints };
2566
+ for (const def of this.#defaults) {
2567
+ const existing = enrichedConstraints[def.vertex] ?? [];
2568
+ enrichedConstraints[def.vertex] = [
2569
+ ...existing,
2570
+ { sort: "__default", value: JSON.stringify(def.expr) }
2571
+ ];
2572
+ }
2573
+ for (const coercion of this.#coercions) {
2574
+ const key = `__coercion:${coercion.from}:${coercion.to}`;
2575
+ const existing = enrichedConstraints[key] ?? [];
2576
+ enrichedConstraints[key] = [
2577
+ ...existing,
2578
+ { sort: "__coercion", value: JSON.stringify(coercion.expr) }
2579
+ ];
2580
+ }
2581
+ for (const merger of this.#mergers) {
2582
+ const existing = enrichedConstraints[merger.vertex] ?? [];
2583
+ enrichedConstraints[merger.vertex] = [
2584
+ ...existing,
2585
+ { sort: "__merger", value: JSON.stringify(merger.expr) }
2586
+ ];
2587
+ }
2588
+ for (const policy of this.#policies) {
2589
+ const existing = enrichedConstraints[policy.vertex] ?? [];
2590
+ enrichedConstraints[policy.vertex] = [
2591
+ ...existing,
2592
+ { sort: "__policy", value: JSON.stringify(policy.strategy) }
2593
+ ];
2594
+ }
2595
+ const enrichedSchemaData = {
2596
+ ...enrichedData,
2597
+ constraints: enrichedConstraints
2598
+ };
2599
+ return new BuiltSchema(
2600
+ this.#schema._handle,
2601
+ enrichedSchemaData,
2602
+ this.#schema._wasm
2603
+ );
2604
+ }
2605
+ /**
2606
+ * Assert that a vertex exists in the schema.
2607
+ *
2608
+ * @param vertex - The vertex to check
2609
+ * @throws {@link PanprotoError} if the vertex is not found
2610
+ */
2611
+ #assertVertex(vertex) {
2612
+ if (!(vertex in this.#schema.vertices)) {
2613
+ throw new PanprotoError(
2614
+ `Vertex "${vertex}" not found in schema. Available vertices: ${Object.keys(this.#schema.vertices).join(", ")}`
2615
+ );
2616
+ }
2617
+ }
2618
+ }
2619
+ class ExprBuilder {
2620
+ /** This class is not instantiable; all methods are static. */
2621
+ constructor() {
2622
+ }
2623
+ /**
2624
+ * Create a variable reference expression.
2625
+ *
2626
+ * @param name - The variable name to reference
2627
+ * @returns A variable expression node
2628
+ */
2629
+ static var_(name) {
2630
+ return { type: "var", name };
2631
+ }
2632
+ /**
2633
+ * Create a literal expression.
2634
+ *
2635
+ * @param value - The literal value
2636
+ * @returns A literal expression node
2637
+ */
2638
+ static lit(value) {
2639
+ return { type: "lit", value };
2640
+ }
2641
+ /**
2642
+ * Create a lambda (anonymous function) expression.
2643
+ *
2644
+ * @param param - The parameter name
2645
+ * @param body - The function body expression
2646
+ * @returns A lambda expression node
2647
+ */
2648
+ static lam(param, body) {
2649
+ return { type: "lam", param, body };
2650
+ }
2651
+ /**
2652
+ * Create a function application expression.
2653
+ *
2654
+ * When multiple arguments are provided, they are applied left-to-right
2655
+ * via currying: `app(f, a, b)` becomes `app(app(f, a), b)`.
2656
+ *
2657
+ * @param func - The function expression
2658
+ * @param args - One or more argument expressions
2659
+ * @returns An application expression node (possibly nested)
2660
+ */
2661
+ static app(func, ...args) {
2662
+ let result = func;
2663
+ for (const arg of args) {
2664
+ result = { type: "app", func: result, arg };
2665
+ }
2666
+ return result;
2667
+ }
2668
+ /**
2669
+ * Create a let-binding expression.
2670
+ *
2671
+ * Binds `value` to `name` in the scope of `body`.
2672
+ *
2673
+ * @param name - The variable name to bind
2674
+ * @param value - The value expression to bind
2675
+ * @param body - The body expression where the binding is in scope
2676
+ * @returns A let expression node
2677
+ */
2678
+ static let_(name, value, body) {
2679
+ return { type: "let", name, value, body };
2680
+ }
2681
+ /**
2682
+ * Create a field access expression.
2683
+ *
2684
+ * @param expr - The record expression to access
2685
+ * @param name - The field name
2686
+ * @returns A field access expression node
2687
+ */
2688
+ static field(expr, name) {
2689
+ return { type: "field", expr, name };
2690
+ }
2691
+ /**
2692
+ * Create a record literal expression.
2693
+ *
2694
+ * @param fields - A mapping of field names to expressions
2695
+ * @returns A record expression node
2696
+ */
2697
+ static record(fields) {
2698
+ const entries = Object.entries(fields);
2699
+ return { type: "record", fields: entries };
2700
+ }
2701
+ /**
2702
+ * Create a list literal expression.
2703
+ *
2704
+ * @param items - The list element expressions
2705
+ * @returns A list expression node
2706
+ */
2707
+ static list(...items) {
2708
+ return { type: "list", items };
2709
+ }
2710
+ /**
2711
+ * Create a pattern-match expression.
2712
+ *
2713
+ * @param scrutinee - The expression to match against
2714
+ * @param arms - Pattern-expression pairs tried in order
2715
+ * @returns A match expression node
2716
+ */
2717
+ static match_(scrutinee, arms) {
2718
+ return { type: "match", scrutinee, arms };
2719
+ }
2720
+ /**
2721
+ * Create a builtin operation expression.
2722
+ *
2723
+ * @param op - The builtin operation name
2724
+ * @param args - Argument expressions for the operation
2725
+ * @returns A builtin expression node
2726
+ */
2727
+ static builtin(op, ...args) {
2728
+ return { type: "builtin", op, args };
2729
+ }
2730
+ /**
2731
+ * Create an index expression for list or record access.
2732
+ *
2733
+ * @param expr - The collection expression
2734
+ * @param index - The index expression
2735
+ * @returns An index expression node
2736
+ */
2737
+ static index(expr, index) {
2738
+ return { type: "index", expr, index };
2739
+ }
2740
+ // -----------------------------------------------------------------
2741
+ // Convenience arithmetic helpers
2742
+ // -----------------------------------------------------------------
2743
+ /**
2744
+ * Add two expressions.
2745
+ *
2746
+ * @param a - Left operand
2747
+ * @param b - Right operand
2748
+ * @returns A builtin 'Add' expression
2749
+ */
2750
+ static add(a, b) {
2751
+ return ExprBuilder.builtin("Add", a, b);
2752
+ }
2753
+ /**
2754
+ * Subtract two expressions.
2755
+ *
2756
+ * @param a - Left operand
2757
+ * @param b - Right operand
2758
+ * @returns A builtin 'Sub' expression
2759
+ */
2760
+ static sub(a, b) {
2761
+ return ExprBuilder.builtin("Sub", a, b);
2762
+ }
2763
+ /**
2764
+ * Multiply two expressions.
2765
+ *
2766
+ * @param a - Left operand
2767
+ * @param b - Right operand
2768
+ * @returns A builtin 'Mul' expression
2769
+ */
2770
+ static mul(a, b) {
2771
+ return ExprBuilder.builtin("Mul", a, b);
2772
+ }
2773
+ /**
2774
+ * Concatenate two expressions (strings or lists).
2775
+ *
2776
+ * @param a - Left operand
2777
+ * @param b - Right operand
2778
+ * @returns A builtin 'Concat' expression
2779
+ */
2780
+ static concat(a, b) {
2781
+ return ExprBuilder.builtin("Concat", a, b);
2782
+ }
2783
+ }
2784
+ function classifyOpticKind(chain, schema, _wasm) {
2785
+ const spec = chain.requirements(schema);
2786
+ const hasDefaults = spec.forwardDefaults.length > 0;
2787
+ const hasCaptured = spec.capturedData.length > 0;
2788
+ if (!hasDefaults && !hasCaptured && spec.kind === "empty") {
2789
+ return "iso";
2790
+ }
2791
+ if (hasDefaults && hasCaptured) {
2792
+ return "affine";
2793
+ }
2794
+ if (hasCaptured) {
2795
+ return "lens";
2796
+ }
2797
+ if (hasDefaults) {
2798
+ return "prism";
2799
+ }
2800
+ return "traversal";
2801
+ }
2802
+ function runDryRun(compiled, instances, srcSchema, _tgtSchema, wasm) {
2803
+ const totalRecords = instances.length;
2804
+ const failed = [];
2805
+ let successful = 0;
2806
+ let recordIndex = 0;
2807
+ for (const record of instances) {
2808
+ try {
2809
+ const inputBytes = packToWasm(record);
2810
+ const instanceBytes = wasm.exports.json_to_instance(
2811
+ srcSchema._handle.id,
2812
+ inputBytes
2813
+ );
2814
+ wasm.exports.lift_record(compiled._handle.id, instanceBytes);
2815
+ successful++;
2816
+ } catch (error) {
2817
+ const reason = categorizeFailure(error);
2818
+ failed.push({ recordId: recordIndex, reason });
2819
+ }
2820
+ recordIndex++;
2821
+ }
2822
+ const coverageRatio = totalRecords > 0 ? successful / totalRecords : 1;
2823
+ return {
2824
+ totalRecords,
2825
+ successful,
2826
+ failed,
2827
+ coverageRatio
2828
+ };
2829
+ }
2830
+ function categorizeFailure(error) {
2831
+ const message = error instanceof Error ? error.message : String(error);
2832
+ if (message.includes("constraint") || message.includes("Constraint")) {
2833
+ const constraintMatch = /constraint\s+"?([^"]+)"?\s+violated.*?value\s+"?([^"]*)"?/i.exec(message);
2834
+ return {
2835
+ type: "constraint_violation",
2836
+ constraint: constraintMatch?.[1] ?? "unknown",
2837
+ value: constraintMatch?.[2] ?? "unknown"
2838
+ };
2839
+ }
2840
+ if (message.includes("required") || message.includes("missing")) {
2841
+ const fieldMatch = /(?:required|missing)\s+(?:field\s+)?"?([^"]+)"?/i.exec(message);
2842
+ return {
2843
+ type: "missing_required_field",
2844
+ field: fieldMatch?.[1] ?? "unknown"
2845
+ };
2846
+ }
2847
+ if (message.includes("type") && message.includes("mismatch")) {
2848
+ const typeMatch = /expected\s+"?([^"]+)"?\s+got\s+"?([^"]+)"?/i.exec(message);
2849
+ return {
2850
+ type: "type_mismatch",
2851
+ expected: typeMatch?.[1] ?? "unknown",
2852
+ got: typeMatch?.[2] ?? "unknown"
2853
+ };
2854
+ }
2855
+ return {
2856
+ type: "expr_eval_failed",
2857
+ exprName: "migration",
2858
+ error: message
2859
+ };
2860
+ }
2861
+ class MigrationAnalysis {
2862
+ #wasm;
2863
+ /**
2864
+ * Create a new migration analysis instance.
2865
+ *
2866
+ * @param panproto - The Panproto instance providing WASM access
2867
+ */
2868
+ constructor(panproto) {
2869
+ this.#wasm = panproto._wasm;
2870
+ }
2871
+ /**
2872
+ * Run a dry-run migration and return a coverage report.
2873
+ *
2874
+ * Tests each instance record against the compiled migration without
2875
+ * persisting results, producing detailed failure information for
2876
+ * records that cannot be migrated.
2877
+ *
2878
+ * @param compiled - The compiled migration to test
2879
+ * @param instances - Array of instance records (plain objects)
2880
+ * @param srcSchema - The source schema the instances conform to
2881
+ * @param tgtSchema - The target schema
2882
+ * @returns A coverage report with per-record success/failure data
2883
+ */
2884
+ dryRun(compiled, instances, srcSchema, tgtSchema) {
2885
+ return runDryRun(compiled, instances, srcSchema, tgtSchema, this.#wasm);
2886
+ }
2887
+ /**
2888
+ * Classify the optic kind of a protolens chain.
2889
+ *
2890
+ * Determines whether the chain represents an isomorphism, lens, prism,
2891
+ * affine transformation, or traversal based on its complement structure.
2892
+ *
2893
+ * @param chain - The protolens chain to classify
2894
+ * @param schema - The schema to check the chain against
2895
+ * @returns The optic kind classification
2896
+ */
2897
+ opticKind(chain, schema) {
2898
+ return classifyOpticKind(chain, schema, this.#wasm);
2899
+ }
2900
+ }
1948
2901
  class TheoryHandle {
1949
2902
  #handle;
1950
2903
  /** @internal Retained for future sort/op inspection methods. */
@@ -2065,18 +3018,32 @@ function migrateModel(sortInterp, morphism, wasm) {
2065
3018
  const resultBytes = wasm.exports.migrate_model(modelBytes, morphBytes);
2066
3019
  return unpackFromWasm(resultBytes);
2067
3020
  }
3021
+ function factorizeMorphism(morphismBytes, domain, codomain, wasm) {
3022
+ try {
3023
+ const bytes = wasm.exports.factorize_morphism(morphismBytes, domain._handle.id, codomain._handle.id);
3024
+ return unpackFromWasm(bytes);
3025
+ } catch (error) {
3026
+ throw new WasmError(
3027
+ `factorize_morphism failed: ${error instanceof Error ? error.message : String(error)}`,
3028
+ { cause: error }
3029
+ );
3030
+ }
3031
+ }
2068
3032
  exports.ATPROTO_SPEC = ATPROTO_SPEC;
2069
3033
  exports.BUILTIN_PROTOCOLS = BUILTIN_PROTOCOLS;
2070
3034
  exports.BuiltSchema = BuiltSchema;
2071
3035
  exports.CompatReport = CompatReport;
2072
3036
  exports.CompiledMigration = CompiledMigration;
3037
+ exports.DataSetHandle = DataSetHandle;
2073
3038
  exports.ExistenceCheckError = ExistenceCheckError;
3039
+ exports.ExprBuilder = ExprBuilder;
2074
3040
  exports.FullDiffReport = FullDiffReport;
2075
3041
  exports.GRAPHQL_SPEC = GRAPHQL_SPEC;
2076
3042
  exports.Instance = Instance;
2077
3043
  exports.IoRegistry = IoRegistry;
2078
3044
  exports.JSON_SCHEMA_SPEC = JSON_SCHEMA_SPEC;
2079
3045
  exports.LensHandle = LensHandle;
3046
+ exports.MigrationAnalysis = MigrationAnalysis;
2080
3047
  exports.MigrationBuilder = MigrationBuilder;
2081
3048
  exports.MigrationError = MigrationError;
2082
3049
  exports.PROTOBUF_SPEC = PROTOBUF_SPEC;
@@ -2084,27 +3051,22 @@ exports.PROTOCOL_CATEGORIES = PROTOCOL_CATEGORIES;
2084
3051
  exports.Panproto = Panproto;
2085
3052
  exports.PanprotoError = PanprotoError;
2086
3053
  exports.Protocol = Protocol;
3054
+ exports.ProtolensChainHandle = ProtolensChainHandle;
2087
3055
  exports.Repository = Repository;
2088
3056
  exports.SQL_SPEC = SQL_SPEC;
2089
3057
  exports.SchemaBuilder = SchemaBuilder;
3058
+ exports.SchemaEnrichment = SchemaEnrichment;
2090
3059
  exports.SchemaValidationError = SchemaValidationError;
3060
+ exports.SymmetricLensHandle = SymmetricLensHandle;
2091
3061
  exports.TheoryBuilder = TheoryBuilder;
2092
3062
  exports.TheoryHandle = TheoryHandle;
2093
3063
  exports.ValidationResult = ValidationResult;
2094
3064
  exports.WasmError = WasmError;
2095
- exports.addField = addField;
2096
3065
  exports.checkMorphism = checkMorphism;
2097
- exports.coerceType = coerceType;
2098
3066
  exports.colimit = colimit;
2099
- exports.compose = compose;
2100
3067
  exports.createTheory = createTheory;
2101
- exports.fromCombinators = fromCombinators;
3068
+ exports.factorizeMorphism = factorizeMorphism;
2102
3069
  exports.getBuiltinProtocol = getBuiltinProtocol;
2103
3070
  exports.getProtocolNames = getProtocolNames;
2104
- exports.hoistField = hoistField;
2105
3071
  exports.migrateModel = migrateModel;
2106
- exports.pipeline = pipeline;
2107
- exports.removeField = removeField;
2108
- exports.renameField = renameField;
2109
- exports.wrapInObject = wrapInObject;
2110
3072
  //# sourceMappingURL=index.cjs.map