@panproto/core 0.7.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/coverage.d.ts +58 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/enrichment.d.ts +146 -0
- package/dist/enrichment.d.ts.map +1 -0
- package/dist/expr.d.ts +145 -0
- package/dist/expr.d.ts.map +1 -0
- package/dist/index.cjs +536 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +536 -0
- package/dist/index.js.map +1 -1
- package/dist/panproto.d.ts +3 -1
- package/dist/panproto.d.ts.map +1 -1
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export { Instance } from './instance.js';
|
|
|
30
30
|
export { IoRegistry, PROTOCOL_CATEGORIES } from './io.js';
|
|
31
31
|
export { FullDiffReport, CompatReport, ValidationResult } from './check.js';
|
|
32
32
|
export type { FullSchemaDiff, CompatReportData, BreakingChange, NonBreakingChange, ConstraintChange, ConstraintDiff, KindChange, SchemaValidationIssue, } from './types.js';
|
|
33
|
+
export { SchemaEnrichment } from './enrichment.js';
|
|
34
|
+
export { ExprBuilder } from './expr.js';
|
|
35
|
+
export { MigrationAnalysis } from './coverage.js';
|
|
36
|
+
export type { ValueKind, SortKind, DirectedEquation, ConflictStrategy, ConflictPolicy, Pattern, Expr, Literal, BuiltinOp, CoverageReport, PartialFailure, PartialReason, OpticKind, EnrichmentSummary, } from './types.js';
|
|
33
37
|
export type { LawCheckResult, ProtocolSpec, EdgeRule, Vertex, Edge, HyperEdge, Constraint, Variant, RecursionPoint, UsageMode, Span, VertexOptions, EdgeOptions, SchemaData, MigrationSpec, LiftResult, GetResult, DiffReport, SchemaChange, Compatibility, ExistenceReport, ExistenceError, WasmModule, WasmExports, InstanceShape, InstanceValidationResult, } from './types.js';
|
|
34
38
|
export { TheoryHandle, TheoryBuilder, createTheory, colimit, checkMorphism, migrateModel, factorizeMorphism, } from './gat.js';
|
|
35
39
|
export type { TheorySpec, TheoryMorphism, Sort, SortParam, GatOperation, Equation, Term, MorphismCheckResult, } from './types.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,SAAS,EACT,UAAU,EACV,OAAO,EACP,cAAc,EACd,SAAS,EACT,IAAI,EACJ,aAAa,EACb,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,SAAS,EACT,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,EACV,WAAW,EACX,aAAa,EACb,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACP,aAAa,EACb,YAAY,EACZ,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,UAAU,EACV,cAAc,EACd,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,IAAI,EACJ,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGhD,OAAO,EACL,aAAa,EACb,SAAS,EACT,qBAAqB,EACrB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,YAAY,EACV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,IAAI,EACJ,OAAO,EACP,SAAS,EACT,cAAc,EACd,cAAc,EACd,aAAa,EACb,SAAS,EACT,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,SAAS,EACT,UAAU,EACV,OAAO,EACP,cAAc,EACd,SAAS,EACT,IAAI,EACJ,aAAa,EACb,WAAW,EACX,UAAU,EACV,aAAa,EACb,UAAU,EACV,SAAS,EACT,UAAU,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,EACV,WAAW,EACX,aAAa,EACb,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACP,aAAa,EACb,YAAY,EACZ,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,UAAU,EACV,cAAc,EACd,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,IAAI,EACJ,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGhD,OAAO,EACL,aAAa,EACb,SAAS,EACT,qBAAqB,EACrB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2057,6 +2057,10 @@ class Panproto {
|
|
|
2057
2057
|
this.#wasm = wasm;
|
|
2058
2058
|
this.#protocols = /* @__PURE__ */ new Map();
|
|
2059
2059
|
}
|
|
2060
|
+
/** The WASM module reference. Internal use only. */
|
|
2061
|
+
get _wasm() {
|
|
2062
|
+
return this.#wasm;
|
|
2063
|
+
}
|
|
2060
2064
|
/**
|
|
2061
2065
|
* Initialize the panproto SDK by loading the WASM module.
|
|
2062
2066
|
*
|
|
@@ -2362,6 +2366,535 @@ class Panproto {
|
|
|
2362
2366
|
this.#protocols.clear();
|
|
2363
2367
|
}
|
|
2364
2368
|
}
|
|
2369
|
+
class SchemaEnrichment {
|
|
2370
|
+
#schema;
|
|
2371
|
+
#defaults;
|
|
2372
|
+
#coercions;
|
|
2373
|
+
#mergers;
|
|
2374
|
+
#policies;
|
|
2375
|
+
constructor(schema, defaults = [], coercions = [], mergers = [], policies = []) {
|
|
2376
|
+
this.#schema = schema;
|
|
2377
|
+
this.#defaults = defaults;
|
|
2378
|
+
this.#coercions = coercions;
|
|
2379
|
+
this.#mergers = mergers;
|
|
2380
|
+
this.#policies = policies;
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* Add a default expression for a vertex.
|
|
2384
|
+
*
|
|
2385
|
+
* The expression is evaluated when forward migration encounters a
|
|
2386
|
+
* missing value at the given vertex.
|
|
2387
|
+
*
|
|
2388
|
+
* @param vertex - The vertex identifier to attach the default to
|
|
2389
|
+
* @param expr - The default expression
|
|
2390
|
+
* @returns A new enrichment with the default added
|
|
2391
|
+
* @throws {@link PanprotoError} if the vertex is not in the schema
|
|
2392
|
+
*/
|
|
2393
|
+
addDefault(vertex, expr) {
|
|
2394
|
+
this.#assertVertex(vertex);
|
|
2395
|
+
if (this.#defaults.some((d) => d.vertex === vertex)) {
|
|
2396
|
+
throw new PanprotoError(
|
|
2397
|
+
`Default already exists for vertex "${vertex}". Remove it first with removeDefault().`
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
return new SchemaEnrichment(
|
|
2401
|
+
this.#schema,
|
|
2402
|
+
[...this.#defaults, { vertex, expr }],
|
|
2403
|
+
this.#coercions,
|
|
2404
|
+
this.#mergers,
|
|
2405
|
+
this.#policies
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Add a coercion function between two value kinds.
|
|
2410
|
+
*
|
|
2411
|
+
* The expression defines how to convert values from `fromKind` to
|
|
2412
|
+
* `toKind`. It receives a single argument (the source value) and
|
|
2413
|
+
* must produce a value of the target kind.
|
|
2414
|
+
*
|
|
2415
|
+
* @param fromKind - Source value kind (e.g., 'int')
|
|
2416
|
+
* @param toKind - Target value kind (e.g., 'float')
|
|
2417
|
+
* @param expr - The coercion expression
|
|
2418
|
+
* @returns A new enrichment with the coercion added
|
|
2419
|
+
* @throws {@link PanprotoError} if a coercion for this pair already exists
|
|
2420
|
+
*/
|
|
2421
|
+
addCoercion(fromKind, toKind, expr) {
|
|
2422
|
+
if (this.#coercions.some((c) => c.from === fromKind && c.to === toKind)) {
|
|
2423
|
+
throw new PanprotoError(
|
|
2424
|
+
`Coercion from "${fromKind}" to "${toKind}" already exists. Remove it first with removeCoercion().`
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
return new SchemaEnrichment(
|
|
2428
|
+
this.#schema,
|
|
2429
|
+
this.#defaults,
|
|
2430
|
+
[...this.#coercions, { from: fromKind, to: toKind, expr }],
|
|
2431
|
+
this.#mergers,
|
|
2432
|
+
this.#policies
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Add a merger expression for a vertex.
|
|
2437
|
+
*
|
|
2438
|
+
* The expression defines how to merge two conflicting values at the
|
|
2439
|
+
* given vertex. It receives two arguments (left and right values)
|
|
2440
|
+
* and must produce a single merged value.
|
|
2441
|
+
*
|
|
2442
|
+
* @param vertex - The vertex identifier to attach the merger to
|
|
2443
|
+
* @param expr - The merger expression
|
|
2444
|
+
* @returns A new enrichment with the merger added
|
|
2445
|
+
* @throws {@link PanprotoError} if the vertex is not in the schema
|
|
2446
|
+
*/
|
|
2447
|
+
addMerger(vertex, expr) {
|
|
2448
|
+
this.#assertVertex(vertex);
|
|
2449
|
+
if (this.#mergers.some((m) => m.vertex === vertex)) {
|
|
2450
|
+
throw new PanprotoError(
|
|
2451
|
+
`Merger already exists for vertex "${vertex}". Remove it first.`
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
return new SchemaEnrichment(
|
|
2455
|
+
this.#schema,
|
|
2456
|
+
this.#defaults,
|
|
2457
|
+
this.#coercions,
|
|
2458
|
+
[...this.#mergers, { vertex, expr }],
|
|
2459
|
+
this.#policies
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Add a conflict resolution policy for a vertex.
|
|
2464
|
+
*
|
|
2465
|
+
* @param vertex - The vertex identifier
|
|
2466
|
+
* @param strategy - The conflict resolution strategy
|
|
2467
|
+
* @returns A new enrichment with the policy added
|
|
2468
|
+
* @throws {@link PanprotoError} if the vertex is not in the schema
|
|
2469
|
+
*/
|
|
2470
|
+
addPolicy(vertex, strategy) {
|
|
2471
|
+
this.#assertVertex(vertex);
|
|
2472
|
+
if (this.#policies.some((p) => p.vertex === vertex)) {
|
|
2473
|
+
throw new PanprotoError(
|
|
2474
|
+
`Policy already exists for vertex "${vertex}". Remove it first.`
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2477
|
+
return new SchemaEnrichment(
|
|
2478
|
+
this.#schema,
|
|
2479
|
+
this.#defaults,
|
|
2480
|
+
this.#coercions,
|
|
2481
|
+
this.#mergers,
|
|
2482
|
+
[...this.#policies, { vertex, strategy }]
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* Remove the default expression for a vertex.
|
|
2487
|
+
*
|
|
2488
|
+
* @param vertex - The vertex identifier
|
|
2489
|
+
* @returns A new enrichment with the default removed
|
|
2490
|
+
* @throws {@link PanprotoError} if no default exists for the vertex
|
|
2491
|
+
*/
|
|
2492
|
+
removeDefault(vertex) {
|
|
2493
|
+
const filtered = this.#defaults.filter((d) => d.vertex !== vertex);
|
|
2494
|
+
if (filtered.length === this.#defaults.length) {
|
|
2495
|
+
throw new PanprotoError(
|
|
2496
|
+
`No default exists for vertex "${vertex}".`
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2499
|
+
return new SchemaEnrichment(
|
|
2500
|
+
this.#schema,
|
|
2501
|
+
filtered,
|
|
2502
|
+
this.#coercions,
|
|
2503
|
+
this.#mergers,
|
|
2504
|
+
this.#policies
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
/**
|
|
2508
|
+
* Remove the coercion function for a value kind pair.
|
|
2509
|
+
*
|
|
2510
|
+
* @param fromKind - Source value kind
|
|
2511
|
+
* @param toKind - Target value kind
|
|
2512
|
+
* @returns A new enrichment with the coercion removed
|
|
2513
|
+
* @throws {@link PanprotoError} if no coercion exists for the pair
|
|
2514
|
+
*/
|
|
2515
|
+
removeCoercion(fromKind, toKind) {
|
|
2516
|
+
const filtered = this.#coercions.filter(
|
|
2517
|
+
(c) => !(c.from === fromKind && c.to === toKind)
|
|
2518
|
+
);
|
|
2519
|
+
if (filtered.length === this.#coercions.length) {
|
|
2520
|
+
throw new PanprotoError(
|
|
2521
|
+
`No coercion exists from "${fromKind}" to "${toKind}".`
|
|
2522
|
+
);
|
|
2523
|
+
}
|
|
2524
|
+
return new SchemaEnrichment(
|
|
2525
|
+
this.#schema,
|
|
2526
|
+
this.#defaults,
|
|
2527
|
+
filtered,
|
|
2528
|
+
this.#mergers,
|
|
2529
|
+
this.#policies
|
|
2530
|
+
);
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* List all enrichments currently attached.
|
|
2534
|
+
*
|
|
2535
|
+
* @returns An enrichment summary with defaults, coercions, mergers, and policies
|
|
2536
|
+
*/
|
|
2537
|
+
listEnrichments() {
|
|
2538
|
+
return {
|
|
2539
|
+
defaults: this.#defaults.map((d) => ({ vertex: d.vertex, expr: d.expr })),
|
|
2540
|
+
coercions: this.#coercions.map((c) => ({ from: c.from, to: c.to, expr: c.expr })),
|
|
2541
|
+
mergers: this.#mergers.map((m) => ({ vertex: m.vertex, expr: m.expr })),
|
|
2542
|
+
policies: this.#policies.map((p) => ({ vertex: p.vertex, strategy: p.strategy }))
|
|
2543
|
+
};
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Build the enriched schema.
|
|
2547
|
+
*
|
|
2548
|
+
* Returns a new `BuiltSchema` with the enrichments recorded in the
|
|
2549
|
+
* schema data. The underlying WASM handle is shared with the original
|
|
2550
|
+
* schema (enrichments are metadata that the SDK tracks client-side).
|
|
2551
|
+
*
|
|
2552
|
+
* @returns A new BuiltSchema with enrichment metadata
|
|
2553
|
+
*/
|
|
2554
|
+
build() {
|
|
2555
|
+
const originalData = this.#schema.data;
|
|
2556
|
+
const enrichedData = {
|
|
2557
|
+
...originalData,
|
|
2558
|
+
constraints: {
|
|
2559
|
+
...originalData.constraints
|
|
2560
|
+
}
|
|
2561
|
+
};
|
|
2562
|
+
const enrichedConstraints = { ...enrichedData.constraints };
|
|
2563
|
+
for (const def of this.#defaults) {
|
|
2564
|
+
const existing = enrichedConstraints[def.vertex] ?? [];
|
|
2565
|
+
enrichedConstraints[def.vertex] = [
|
|
2566
|
+
...existing,
|
|
2567
|
+
{ sort: "__default", value: JSON.stringify(def.expr) }
|
|
2568
|
+
];
|
|
2569
|
+
}
|
|
2570
|
+
for (const coercion of this.#coercions) {
|
|
2571
|
+
const key = `__coercion:${coercion.from}:${coercion.to}`;
|
|
2572
|
+
const existing = enrichedConstraints[key] ?? [];
|
|
2573
|
+
enrichedConstraints[key] = [
|
|
2574
|
+
...existing,
|
|
2575
|
+
{ sort: "__coercion", value: JSON.stringify(coercion.expr) }
|
|
2576
|
+
];
|
|
2577
|
+
}
|
|
2578
|
+
for (const merger of this.#mergers) {
|
|
2579
|
+
const existing = enrichedConstraints[merger.vertex] ?? [];
|
|
2580
|
+
enrichedConstraints[merger.vertex] = [
|
|
2581
|
+
...existing,
|
|
2582
|
+
{ sort: "__merger", value: JSON.stringify(merger.expr) }
|
|
2583
|
+
];
|
|
2584
|
+
}
|
|
2585
|
+
for (const policy of this.#policies) {
|
|
2586
|
+
const existing = enrichedConstraints[policy.vertex] ?? [];
|
|
2587
|
+
enrichedConstraints[policy.vertex] = [
|
|
2588
|
+
...existing,
|
|
2589
|
+
{ sort: "__policy", value: JSON.stringify(policy.strategy) }
|
|
2590
|
+
];
|
|
2591
|
+
}
|
|
2592
|
+
const enrichedSchemaData = {
|
|
2593
|
+
...enrichedData,
|
|
2594
|
+
constraints: enrichedConstraints
|
|
2595
|
+
};
|
|
2596
|
+
return new BuiltSchema(
|
|
2597
|
+
this.#schema._handle,
|
|
2598
|
+
enrichedSchemaData,
|
|
2599
|
+
this.#schema._wasm
|
|
2600
|
+
);
|
|
2601
|
+
}
|
|
2602
|
+
/**
|
|
2603
|
+
* Assert that a vertex exists in the schema.
|
|
2604
|
+
*
|
|
2605
|
+
* @param vertex - The vertex to check
|
|
2606
|
+
* @throws {@link PanprotoError} if the vertex is not found
|
|
2607
|
+
*/
|
|
2608
|
+
#assertVertex(vertex) {
|
|
2609
|
+
if (!(vertex in this.#schema.vertices)) {
|
|
2610
|
+
throw new PanprotoError(
|
|
2611
|
+
`Vertex "${vertex}" not found in schema. Available vertices: ${Object.keys(this.#schema.vertices).join(", ")}`
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
class ExprBuilder {
|
|
2617
|
+
/** This class is not instantiable; all methods are static. */
|
|
2618
|
+
constructor() {
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* Create a variable reference expression.
|
|
2622
|
+
*
|
|
2623
|
+
* @param name - The variable name to reference
|
|
2624
|
+
* @returns A variable expression node
|
|
2625
|
+
*/
|
|
2626
|
+
static var_(name) {
|
|
2627
|
+
return { type: "var", name };
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* Create a literal expression.
|
|
2631
|
+
*
|
|
2632
|
+
* @param value - The literal value
|
|
2633
|
+
* @returns A literal expression node
|
|
2634
|
+
*/
|
|
2635
|
+
static lit(value) {
|
|
2636
|
+
return { type: "lit", value };
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Create a lambda (anonymous function) expression.
|
|
2640
|
+
*
|
|
2641
|
+
* @param param - The parameter name
|
|
2642
|
+
* @param body - The function body expression
|
|
2643
|
+
* @returns A lambda expression node
|
|
2644
|
+
*/
|
|
2645
|
+
static lam(param, body) {
|
|
2646
|
+
return { type: "lam", param, body };
|
|
2647
|
+
}
|
|
2648
|
+
/**
|
|
2649
|
+
* Create a function application expression.
|
|
2650
|
+
*
|
|
2651
|
+
* When multiple arguments are provided, they are applied left-to-right
|
|
2652
|
+
* via currying: `app(f, a, b)` becomes `app(app(f, a), b)`.
|
|
2653
|
+
*
|
|
2654
|
+
* @param func - The function expression
|
|
2655
|
+
* @param args - One or more argument expressions
|
|
2656
|
+
* @returns An application expression node (possibly nested)
|
|
2657
|
+
*/
|
|
2658
|
+
static app(func, ...args) {
|
|
2659
|
+
let result = func;
|
|
2660
|
+
for (const arg of args) {
|
|
2661
|
+
result = { type: "app", func: result, arg };
|
|
2662
|
+
}
|
|
2663
|
+
return result;
|
|
2664
|
+
}
|
|
2665
|
+
/**
|
|
2666
|
+
* Create a let-binding expression.
|
|
2667
|
+
*
|
|
2668
|
+
* Binds `value` to `name` in the scope of `body`.
|
|
2669
|
+
*
|
|
2670
|
+
* @param name - The variable name to bind
|
|
2671
|
+
* @param value - The value expression to bind
|
|
2672
|
+
* @param body - The body expression where the binding is in scope
|
|
2673
|
+
* @returns A let expression node
|
|
2674
|
+
*/
|
|
2675
|
+
static let_(name, value, body) {
|
|
2676
|
+
return { type: "let", name, value, body };
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Create a field access expression.
|
|
2680
|
+
*
|
|
2681
|
+
* @param expr - The record expression to access
|
|
2682
|
+
* @param name - The field name
|
|
2683
|
+
* @returns A field access expression node
|
|
2684
|
+
*/
|
|
2685
|
+
static field(expr, name) {
|
|
2686
|
+
return { type: "field", expr, name };
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* Create a record literal expression.
|
|
2690
|
+
*
|
|
2691
|
+
* @param fields - A mapping of field names to expressions
|
|
2692
|
+
* @returns A record expression node
|
|
2693
|
+
*/
|
|
2694
|
+
static record(fields) {
|
|
2695
|
+
const entries = Object.entries(fields);
|
|
2696
|
+
return { type: "record", fields: entries };
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* Create a list literal expression.
|
|
2700
|
+
*
|
|
2701
|
+
* @param items - The list element expressions
|
|
2702
|
+
* @returns A list expression node
|
|
2703
|
+
*/
|
|
2704
|
+
static list(...items) {
|
|
2705
|
+
return { type: "list", items };
|
|
2706
|
+
}
|
|
2707
|
+
/**
|
|
2708
|
+
* Create a pattern-match expression.
|
|
2709
|
+
*
|
|
2710
|
+
* @param scrutinee - The expression to match against
|
|
2711
|
+
* @param arms - Pattern-expression pairs tried in order
|
|
2712
|
+
* @returns A match expression node
|
|
2713
|
+
*/
|
|
2714
|
+
static match_(scrutinee, arms) {
|
|
2715
|
+
return { type: "match", scrutinee, arms };
|
|
2716
|
+
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Create a builtin operation expression.
|
|
2719
|
+
*
|
|
2720
|
+
* @param op - The builtin operation name
|
|
2721
|
+
* @param args - Argument expressions for the operation
|
|
2722
|
+
* @returns A builtin expression node
|
|
2723
|
+
*/
|
|
2724
|
+
static builtin(op, ...args) {
|
|
2725
|
+
return { type: "builtin", op, args };
|
|
2726
|
+
}
|
|
2727
|
+
/**
|
|
2728
|
+
* Create an index expression for list or record access.
|
|
2729
|
+
*
|
|
2730
|
+
* @param expr - The collection expression
|
|
2731
|
+
* @param index - The index expression
|
|
2732
|
+
* @returns An index expression node
|
|
2733
|
+
*/
|
|
2734
|
+
static index(expr, index) {
|
|
2735
|
+
return { type: "index", expr, index };
|
|
2736
|
+
}
|
|
2737
|
+
// -----------------------------------------------------------------
|
|
2738
|
+
// Convenience arithmetic helpers
|
|
2739
|
+
// -----------------------------------------------------------------
|
|
2740
|
+
/**
|
|
2741
|
+
* Add two expressions.
|
|
2742
|
+
*
|
|
2743
|
+
* @param a - Left operand
|
|
2744
|
+
* @param b - Right operand
|
|
2745
|
+
* @returns A builtin 'Add' expression
|
|
2746
|
+
*/
|
|
2747
|
+
static add(a, b) {
|
|
2748
|
+
return ExprBuilder.builtin("Add", a, b);
|
|
2749
|
+
}
|
|
2750
|
+
/**
|
|
2751
|
+
* Subtract two expressions.
|
|
2752
|
+
*
|
|
2753
|
+
* @param a - Left operand
|
|
2754
|
+
* @param b - Right operand
|
|
2755
|
+
* @returns A builtin 'Sub' expression
|
|
2756
|
+
*/
|
|
2757
|
+
static sub(a, b) {
|
|
2758
|
+
return ExprBuilder.builtin("Sub", a, b);
|
|
2759
|
+
}
|
|
2760
|
+
/**
|
|
2761
|
+
* Multiply two expressions.
|
|
2762
|
+
*
|
|
2763
|
+
* @param a - Left operand
|
|
2764
|
+
* @param b - Right operand
|
|
2765
|
+
* @returns A builtin 'Mul' expression
|
|
2766
|
+
*/
|
|
2767
|
+
static mul(a, b) {
|
|
2768
|
+
return ExprBuilder.builtin("Mul", a, b);
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Concatenate two expressions (strings or lists).
|
|
2772
|
+
*
|
|
2773
|
+
* @param a - Left operand
|
|
2774
|
+
* @param b - Right operand
|
|
2775
|
+
* @returns A builtin 'Concat' expression
|
|
2776
|
+
*/
|
|
2777
|
+
static concat(a, b) {
|
|
2778
|
+
return ExprBuilder.builtin("Concat", a, b);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
function classifyOpticKind(chain, schema, _wasm) {
|
|
2782
|
+
const spec = chain.requirements(schema);
|
|
2783
|
+
const hasDefaults = spec.forwardDefaults.length > 0;
|
|
2784
|
+
const hasCaptured = spec.capturedData.length > 0;
|
|
2785
|
+
if (!hasDefaults && !hasCaptured && spec.kind === "empty") {
|
|
2786
|
+
return "iso";
|
|
2787
|
+
}
|
|
2788
|
+
if (hasDefaults && hasCaptured) {
|
|
2789
|
+
return "affine";
|
|
2790
|
+
}
|
|
2791
|
+
if (hasCaptured) {
|
|
2792
|
+
return "lens";
|
|
2793
|
+
}
|
|
2794
|
+
if (hasDefaults) {
|
|
2795
|
+
return "prism";
|
|
2796
|
+
}
|
|
2797
|
+
return "traversal";
|
|
2798
|
+
}
|
|
2799
|
+
function runDryRun(compiled, instances, srcSchema, _tgtSchema, wasm) {
|
|
2800
|
+
const totalRecords = instances.length;
|
|
2801
|
+
const failed = [];
|
|
2802
|
+
let successful = 0;
|
|
2803
|
+
let recordIndex = 0;
|
|
2804
|
+
for (const record of instances) {
|
|
2805
|
+
try {
|
|
2806
|
+
const inputBytes = packToWasm(record);
|
|
2807
|
+
const instanceBytes = wasm.exports.json_to_instance(
|
|
2808
|
+
srcSchema._handle.id,
|
|
2809
|
+
inputBytes
|
|
2810
|
+
);
|
|
2811
|
+
wasm.exports.lift_record(compiled._handle.id, instanceBytes);
|
|
2812
|
+
successful++;
|
|
2813
|
+
} catch (error) {
|
|
2814
|
+
const reason = categorizeFailure(error);
|
|
2815
|
+
failed.push({ recordId: recordIndex, reason });
|
|
2816
|
+
}
|
|
2817
|
+
recordIndex++;
|
|
2818
|
+
}
|
|
2819
|
+
const coverageRatio = totalRecords > 0 ? successful / totalRecords : 1;
|
|
2820
|
+
return {
|
|
2821
|
+
totalRecords,
|
|
2822
|
+
successful,
|
|
2823
|
+
failed,
|
|
2824
|
+
coverageRatio
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function categorizeFailure(error) {
|
|
2828
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2829
|
+
if (message.includes("constraint") || message.includes("Constraint")) {
|
|
2830
|
+
const constraintMatch = /constraint\s+"?([^"]+)"?\s+violated.*?value\s+"?([^"]*)"?/i.exec(message);
|
|
2831
|
+
return {
|
|
2832
|
+
type: "constraint_violation",
|
|
2833
|
+
constraint: constraintMatch?.[1] ?? "unknown",
|
|
2834
|
+
value: constraintMatch?.[2] ?? "unknown"
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
if (message.includes("required") || message.includes("missing")) {
|
|
2838
|
+
const fieldMatch = /(?:required|missing)\s+(?:field\s+)?"?([^"]+)"?/i.exec(message);
|
|
2839
|
+
return {
|
|
2840
|
+
type: "missing_required_field",
|
|
2841
|
+
field: fieldMatch?.[1] ?? "unknown"
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
if (message.includes("type") && message.includes("mismatch")) {
|
|
2845
|
+
const typeMatch = /expected\s+"?([^"]+)"?\s+got\s+"?([^"]+)"?/i.exec(message);
|
|
2846
|
+
return {
|
|
2847
|
+
type: "type_mismatch",
|
|
2848
|
+
expected: typeMatch?.[1] ?? "unknown",
|
|
2849
|
+
got: typeMatch?.[2] ?? "unknown"
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
return {
|
|
2853
|
+
type: "expr_eval_failed",
|
|
2854
|
+
exprName: "migration",
|
|
2855
|
+
error: message
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
class MigrationAnalysis {
|
|
2859
|
+
#wasm;
|
|
2860
|
+
/**
|
|
2861
|
+
* Create a new migration analysis instance.
|
|
2862
|
+
*
|
|
2863
|
+
* @param panproto - The Panproto instance providing WASM access
|
|
2864
|
+
*/
|
|
2865
|
+
constructor(panproto) {
|
|
2866
|
+
this.#wasm = panproto._wasm;
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Run a dry-run migration and return a coverage report.
|
|
2870
|
+
*
|
|
2871
|
+
* Tests each instance record against the compiled migration without
|
|
2872
|
+
* persisting results, producing detailed failure information for
|
|
2873
|
+
* records that cannot be migrated.
|
|
2874
|
+
*
|
|
2875
|
+
* @param compiled - The compiled migration to test
|
|
2876
|
+
* @param instances - Array of instance records (plain objects)
|
|
2877
|
+
* @param srcSchema - The source schema the instances conform to
|
|
2878
|
+
* @param tgtSchema - The target schema
|
|
2879
|
+
* @returns A coverage report with per-record success/failure data
|
|
2880
|
+
*/
|
|
2881
|
+
dryRun(compiled, instances, srcSchema, tgtSchema) {
|
|
2882
|
+
return runDryRun(compiled, instances, srcSchema, tgtSchema, this.#wasm);
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Classify the optic kind of a protolens chain.
|
|
2886
|
+
*
|
|
2887
|
+
* Determines whether the chain represents an isomorphism, lens, prism,
|
|
2888
|
+
* affine transformation, or traversal based on its complement structure.
|
|
2889
|
+
*
|
|
2890
|
+
* @param chain - The protolens chain to classify
|
|
2891
|
+
* @param schema - The schema to check the chain against
|
|
2892
|
+
* @returns The optic kind classification
|
|
2893
|
+
*/
|
|
2894
|
+
opticKind(chain, schema) {
|
|
2895
|
+
return classifyOpticKind(chain, schema, this.#wasm);
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2365
2898
|
class TheoryHandle {
|
|
2366
2899
|
#handle;
|
|
2367
2900
|
/** @internal Retained for future sort/op inspection methods. */
|
|
@@ -2501,12 +3034,14 @@ export {
|
|
|
2501
3034
|
CompiledMigration,
|
|
2502
3035
|
DataSetHandle,
|
|
2503
3036
|
ExistenceCheckError,
|
|
3037
|
+
ExprBuilder,
|
|
2504
3038
|
FullDiffReport,
|
|
2505
3039
|
GRAPHQL_SPEC,
|
|
2506
3040
|
Instance,
|
|
2507
3041
|
IoRegistry,
|
|
2508
3042
|
JSON_SCHEMA_SPEC,
|
|
2509
3043
|
LensHandle,
|
|
3044
|
+
MigrationAnalysis,
|
|
2510
3045
|
MigrationBuilder,
|
|
2511
3046
|
MigrationError,
|
|
2512
3047
|
PROTOBUF_SPEC,
|
|
@@ -2518,6 +3053,7 @@ export {
|
|
|
2518
3053
|
Repository,
|
|
2519
3054
|
SQL_SPEC,
|
|
2520
3055
|
SchemaBuilder,
|
|
3056
|
+
SchemaEnrichment,
|
|
2521
3057
|
SchemaValidationError,
|
|
2522
3058
|
SymmetricLensHandle,
|
|
2523
3059
|
TheoryBuilder,
|