@_linked/core 2.33.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +26 -0
  3. package/lib/esm/index.d.ts +2 -1
  4. package/lib/esm/index.js +2 -0
  5. package/lib/esm/index.js.map +1 -1
  6. package/lib/esm/live/LiveQueryStore.d.ts +22 -0
  7. package/lib/esm/live/LiveQueryStore.js +86 -19
  8. package/lib/esm/live/LiveQueryStore.js.map +1 -1
  9. package/lib/esm/live/changes.d.ts +9 -1
  10. package/lib/esm/live/changes.js +7 -2
  11. package/lib/esm/live/changes.js.map +1 -1
  12. package/lib/esm/live/keys.d.ts +6 -0
  13. package/lib/esm/live/keys.js +10 -1
  14. package/lib/esm/live/keys.js.map +1 -1
  15. package/lib/esm/live/matcher.d.ts +4 -1
  16. package/lib/esm/live/matcher.js +10 -5
  17. package/lib/esm/live/matcher.js.map +1 -1
  18. package/lib/esm/queries/AskBuilder.d.ts +6 -0
  19. package/lib/esm/queries/AskBuilder.js +14 -0
  20. package/lib/esm/queries/AskBuilder.js.map +1 -1
  21. package/lib/esm/queries/CountBuilder.d.ts +6 -0
  22. package/lib/esm/queries/CountBuilder.js +14 -0
  23. package/lib/esm/queries/CountBuilder.js.map +1 -1
  24. package/lib/esm/queries/CreateBuilder.d.ts +4 -0
  25. package/lib/esm/queries/CreateBuilder.js +15 -1
  26. package/lib/esm/queries/CreateBuilder.js.map +1 -1
  27. package/lib/esm/queries/DeleteBuilder.d.ts +4 -0
  28. package/lib/esm/queries/DeleteBuilder.js +15 -1
  29. package/lib/esm/queries/DeleteBuilder.js.map +1 -1
  30. package/lib/esm/queries/FieldSet.d.ts +10 -0
  31. package/lib/esm/queries/FieldSet.js +85 -18
  32. package/lib/esm/queries/FieldSet.js.map +1 -1
  33. package/lib/esm/queries/IRLower.js +3 -2
  34. package/lib/esm/queries/IRLower.js.map +1 -1
  35. package/lib/esm/queries/IRMutation.js +15 -14
  36. package/lib/esm/queries/IRMutation.js.map +1 -1
  37. package/lib/esm/queries/MutationSerialization.js +2 -2
  38. package/lib/esm/queries/MutationSerialization.js.map +1 -1
  39. package/lib/esm/queries/PropertyPath.js +2 -2
  40. package/lib/esm/queries/PropertyPath.js.map +1 -1
  41. package/lib/esm/queries/QueryBuilder.d.ts +7 -0
  42. package/lib/esm/queries/QueryBuilder.js +40 -3
  43. package/lib/esm/queries/QueryBuilder.js.map +1 -1
  44. package/lib/esm/queries/SelectQuery.js +2 -2
  45. package/lib/esm/queries/SelectQuery.js.map +1 -1
  46. package/lib/esm/queries/UpdateBuilder.d.ts +4 -0
  47. package/lib/esm/queries/UpdateBuilder.js +15 -1
  48. package/lib/esm/queries/UpdateBuilder.js.map +1 -1
  49. package/lib/esm/queries/fromJSON.d.ts +12 -1
  50. package/lib/esm/queries/fromJSON.js +5 -1
  51. package/lib/esm/queries/fromJSON.js.map +1 -1
  52. package/lib/esm/queries/lower.js +12 -5
  53. package/lib/esm/queries/lower.js.map +1 -1
  54. package/lib/esm/queries/queryDependencies.js +14 -10
  55. package/lib/esm/queries/queryDependencies.js.map +1 -1
  56. package/lib/esm/queries/resolveShape.js +14 -2
  57. package/lib/esm/queries/resolveShape.js.map +1 -1
  58. package/lib/esm/shapes/Shape.js +2 -1
  59. package/lib/esm/shapes/Shape.js.map +1 -1
  60. package/lib/esm/shapes/nodeShapeData.js +7 -10
  61. package/lib/esm/shapes/nodeShapeData.js.map +1 -1
  62. package/lib/esm/shapes/registerRuntimeShape.js +3 -1
  63. package/lib/esm/shapes/registerRuntimeShape.js.map +1 -1
  64. package/lib/esm/shapes/syncShapes.d.ts +6 -2
  65. package/lib/esm/shapes/syncShapes.js +16 -9
  66. package/lib/esm/shapes/syncShapes.js.map +1 -1
  67. package/lib/esm/shapes/validation.js +2 -2
  68. package/lib/esm/shapes/validation.js.map +1 -1
  69. package/lib/esm/sparql/irToAlgebra.js +117 -52
  70. package/lib/esm/sparql/irToAlgebra.js.map +1 -1
  71. package/lib/esm/sparql/ownedLinkCheck.js +6 -1
  72. package/lib/esm/sparql/ownedLinkCheck.js.map +1 -1
  73. package/lib/esm/utils/LinkedStorage.d.ts +7 -0
  74. package/lib/esm/utils/LinkedStorage.js +39 -12
  75. package/lib/esm/utils/LinkedStorage.js.map +1 -1
  76. package/lib/esm/utils/ShapeCatalog.d.ts +57 -0
  77. package/lib/esm/utils/ShapeCatalog.js +86 -0
  78. package/lib/esm/utils/ShapeCatalog.js.map +1 -0
  79. package/lib/esm/utils/ShapeClass.d.ts +73 -8
  80. package/lib/esm/utils/ShapeClass.js +245 -66
  81. package/lib/esm/utils/ShapeClass.js.map +1 -1
  82. package/lib/esm/utils/loadStores.d.ts +4 -0
  83. package/lib/esm/utils/loadStores.js +24 -1
  84. package/lib/esm/utils/loadStores.js.map +1 -1
  85. package/lib/esm/utils/registryCache.d.ts +15 -0
  86. package/lib/esm/utils/registryCache.js +50 -0
  87. package/lib/esm/utils/registryCache.js.map +1 -0
  88. package/package.json +1 -1
@@ -2,6 +2,7 @@ import { resolveExpressionRefs, ExistsCondition } from '../expressions/Expressio
2
2
  import { resolveContextId } from './ContextRef.js';
3
3
  import { lowerSelectionPathExpression, projectionKeyFromPath } from './IRProjection.js';
4
4
  import { IRAliasScope } from './IRAliasScope.js';
5
+ import { attachCatalog } from '../utils/ShapeClass.js';
5
6
  /**
6
7
  * Creates a memoized traversal resolver that deduplicates (fromAlias, propertyShapeId)
7
8
  * pairs, generates unique aliases, and accumulates the resulting patterns.
@@ -371,7 +372,7 @@ export const lowerSelectQuery = (canonical) => {
371
372
  }
372
373
  }
373
374
  }
374
- return {
375
+ return attachCatalog({
375
376
  kind: 'select',
376
377
  root,
377
378
  patterns: [...ctx.getPatterns(), ...minusPatterns],
@@ -384,7 +385,7 @@ export const lowerSelectQuery = (canonical) => {
384
385
  subjectIds: canonical.subjectIds,
385
386
  singleResult: canonical.singleResult,
386
387
  resultMap: resultMapEntries,
387
- };
388
+ });
388
389
  };
389
390
  /**
390
391
  * Standalone WHERE lowering — converts a CanonicalWhereExpression to IR expression + patterns.
@@ -1 +1 @@
1
- {"version":3,"file":"IRLower.js","sourceRoot":"","sources":["../../../src/queries/IRLower.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CanonicalDesugaredSelectQuery,\n CanonicalWhereExpression,\n} from './IRCanonicalize.js';\nimport type {\n DesugaredExpressionSelect,\n DesugaredExpressionWhere,\n DesugaredExistsWhere,\n DesugaredSelection,\n DesugaredSelectionPath,\n DesugaredStep,\n DesugaredWhere,\n} from './IRDesugar.js';\nimport {resolveExpressionRefs, ExistsCondition} from '../expressions/ExpressionNode.js';\nimport {resolveContextId} from './ContextRef.js';\nimport type {\n IRExpression,\n IRGraphPattern,\n IROrderByItem,\n IRProjectionItem,\n IRResultMapEntry,\n IRSelectQuery,\n IRShapeScanPattern,\n IRTraversePattern,\n} from './IntermediateRepresentation.js';\nimport {lowerSelectionPathExpression, projectionKeyFromPath} from './IRProjection.js';\nimport {IRAliasScope} from './IRAliasScope.js';\nimport type {PathExpr} from '../paths/PropertyPathExpr.js';\n\n/**\n * Creates a memoized traversal resolver that deduplicates (fromAlias, propertyShapeId)\n * pairs, generates unique aliases, and accumulates the resulting patterns.\n * Used by both select-query lowering and mutation expression resolution.\n */\nexport function createTraversalResolver<P>(\n generateAlias: () => string,\n createPattern: (from: string, to: string, property: string) => P,\n): {resolve: (fromAlias: string, propertyShapeId: string) => string; patterns: P[]} {\n const patterns: P[] = [];\n const seen = new Map<string, string>();\n\n const resolve = (fromAlias: string, propertyShapeId: string): string => {\n const key = `${fromAlias}:${propertyShapeId}`;\n if (seen.has(key)) return seen.get(key)!;\n const toAlias = generateAlias();\n seen.set(key, toAlias);\n patterns.push(createPattern(fromAlias, toAlias, propertyShapeId));\n return toAlias;\n };\n\n return {resolve, patterns};\n}\n\nclass LoweringContext {\n private counter = 0;\n private patterns: IRGraphPattern[] = [];\n private traverseMap = new Map<string, string>();\n private filterMap = new Map<string, IRExpression>();\n private innerPaginationMap = new Map<\n string,\n {limit?: number; offset?: number; orderBy?: import('./IntermediateRepresentation.js').IRInnerOrderBy[]}\n >();\n readonly rootAlias: string;\n\n constructor() {\n this.rootAlias = this.nextAlias();\n }\n\n private nextAlias(): string {\n return `a${this.counter++}`;\n }\n\n getOrCreateTraversal(fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number): string {\n const key = `${fromAlias}:${propertyShapeId}`;\n const existing = this.traverseMap.get(key);\n if (existing) return existing;\n\n const toAlias = this.nextAlias();\n const pattern: IRTraversePattern = {\n kind: 'traverse',\n from: fromAlias,\n to: toAlias,\n property: propertyShapeId,\n };\n if (pathExpr) {\n pattern.pathExpr = pathExpr;\n }\n if (typeof maxCount === 'number') {\n pattern.maxCount = maxCount;\n }\n this.patterns.push(pattern);\n this.traverseMap.set(key, toAlias);\n return toAlias;\n }\n\n generateAlias(): string {\n return this.nextAlias();\n }\n\n /**\n * Attaches an inline where filter to the traverse pattern targeting `toAlias`.\n * The filter will be merged into the pattern when `getPatterns()` is called.\n */\n attachFilter(toAlias: string, filter: IRExpression): void {\n this.filterMap.set(toAlias, filter);\n }\n\n /**\n * Attaches inner LIMIT/OFFSET/ORDER BY (from a nested select) to the traverse\n * pattern targeting `toAlias`. Merged into the pattern in `getPatterns()`.\n */\n attachInnerPagination(\n toAlias: string,\n pagination: {limit?: number; offset?: number; orderBy?: import('./IntermediateRepresentation.js').IRInnerOrderBy[]},\n ): void {\n this.innerPaginationMap.set(toAlias, pagination);\n }\n\n getPatterns(): IRGraphPattern[] {\n return this.patterns.map((p) => {\n if (p.kind !== 'traverse') return p;\n let pattern = p;\n if (this.filterMap.has(p.to)) {\n pattern = {...pattern, filter: this.filterMap.get(p.to)!};\n }\n const pagination = this.innerPaginationMap.get(p.to);\n if (pagination) {\n pattern = {\n ...pattern,\n ...(typeof pagination.limit === 'number' ? {innerLimit: pagination.limit} : {}),\n ...(typeof pagination.offset === 'number' ? {innerOffset: pagination.offset} : {}),\n ...(pagination.orderBy ? {innerOrderBy: pagination.orderBy} : {}),\n };\n }\n return pattern;\n });\n }\n}\n\n/** Minimal interface for alias generation used by lowerWhere and traversal resolvers. */\ntype AliasGenerator = {\n generateAlias(): string;\n};\n\ntype PathLoweringOptions = {\n rootAlias: string;\n resolveTraversal: (fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number) => string;\n};\n\nconst lowerPath = (\n path: DesugaredSelectionPath,\n options: PathLoweringOptions,\n): IRExpression => lowerSelectionPathExpression(path, options);\n\n/**\n * Resolve any `{@ctx}` context references carried in a lowered expression tree —\n * whether it came from a where-clause filter OR a projected (expression-select)\n * value.\n *\n * A context reference (`.equals(getQueryContext('user'))`) is carried through build +\n * the wire as a *name* (`reference_expr.contextName` / `context_property_expr.contextName`),\n * never a baked id. Here — at lowering — it is resolved against the live context map into\n * the concrete IRI; an unresolved one throws `UnresolvedContextError` (SELECT callers\n * short-circuit to null before lowering, so a query is never lowered with an unresolved\n * context in practice). This must be applied to every expression that can reach the SPARQL\n * algebra, not just where-filters.\n */\nconst resolveContextRefs = (expr: IRExpression): IRExpression => {\n switch (expr.kind) {\n case 'reference_expr':\n if (expr.contextName) {\n return {kind: 'reference_expr', value: resolveContextId(expr.contextName, true)!};\n }\n return expr;\n case 'context_property_expr':\n if (expr.contextName) {\n return {kind: 'context_property_expr', contextIri: resolveContextId(expr.contextName, true)!, property: expr.property};\n }\n return expr;\n case 'binary_expr':\n return {...expr, left: resolveContextRefs(expr.left), right: resolveContextRefs(expr.right)};\n case 'in_expr':\n return {\n ...expr,\n value: resolveContextRefs(expr.value),\n source: {list: expr.source.list.map(resolveContextRefs)},\n };\n case 'logical_expr':\n return {...expr, expressions: expr.expressions.map(resolveContextRefs)};\n case 'not_expr':\n return {...expr, expression: resolveContextRefs(expr.expression)};\n case 'function_expr':\n case 'aggregate_expr':\n return {...expr, args: expr.args.map(resolveContextRefs)};\n case 'exists_expr':\n return expr.filter ? {...expr, filter: resolveContextRefs(expr.filter)} : expr;\n default:\n return expr;\n }\n};\n\nconst lowerWhere = (\n where: CanonicalWhereExpression,\n ctx: AliasGenerator,\n options: PathLoweringOptions,\n): IRExpression => {\n switch (where.kind) {\n case 'where_expression': {\n // ExpressionNode-based WHERE — resolve refs and return IRExpression directly\n const exprWhere = where as DesugaredExpressionWhere;\n return resolveContextRefs(resolveExpressionRefs(\n exprWhere.expressionNode.ir,\n exprWhere.expressionNode._refs,\n options.rootAlias,\n options.resolveTraversal,\n ));\n }\n case 'where_exists_condition': {\n // ExistsCondition-based WHERE (from .some()/.every()/.none())\n const existsWhere = where as DesugaredExistsWhere;\n return resolveContextRefs(lowerExistsCondition(existsWhere.existsCondition, ctx, options));\n }\n default:\n const _exhaustive: never = where;\n throw new Error(`Unknown canonical where kind: ${(_exhaustive as {kind: string}).kind}`);\n }\n};\n\n/**\n * Lower an ExistsCondition to IRExistsExpression with proper traversal patterns.\n */\nconst lowerExistsCondition = (\n condition: ExistsCondition,\n ctx: AliasGenerator,\n options: PathLoweringOptions,\n): IRExpression => {\n // Build traversal patterns for the collection path\n const {resolve: existsResolve, patterns: traversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n\n // Walk the path segments to create traversal patterns\n let currentAlias = options.rootAlias;\n for (const segmentId of condition.pathSegmentIds) {\n currentAlias = existsResolve(currentAlias, segmentId);\n }\n\n // Resolve the inner predicate's property refs against the EXISTS scope\n const filter = resolveExpressionRefs(\n condition.predicate.ir,\n condition.predicate._refs,\n currentAlias,\n existsResolve,\n );\n\n let existsExpr: IRExpression = {\n kind: 'exists_expr',\n pattern: traversals.length === 1\n ? traversals[0]\n : {kind: 'join', patterns: traversals},\n filter,\n };\n\n // Wrap in NOT if negated (.none() or outer NOT of .every())\n if (condition.negated) {\n existsExpr = {kind: 'not_expr', expression: existsExpr};\n }\n\n // Handle .and()/.or() chaining\n if (condition.chain.length > 0) {\n let result: IRExpression = existsExpr;\n for (const link of condition.chain) {\n let rightExpr: IRExpression;\n if (link.condition instanceof ExistsCondition) {\n rightExpr = lowerExistsCondition(link.condition, ctx, options);\n } else {\n rightExpr = resolveExpressionRefs(\n link.condition.ir,\n link.condition._refs,\n options.rootAlias,\n options.resolveTraversal,\n );\n }\n result = {\n kind: 'logical_expr',\n operator: link.op,\n expressions: [result, rightExpr],\n };\n }\n return result;\n }\n\n return existsExpr;\n};\n\ntype ProjectionSeed =\n | {\n kind: 'path';\n path: DesugaredSelectionPath;\n key?: string;\n }\n | {\n kind: 'expression';\n expression: IRExpression;\n key: string;\n };\n\nconst combineWithParentPath = (\n parentPath: DesugaredStep[],\n path: DesugaredSelectionPath,\n): DesugaredSelectionPath => ({\n kind: 'selection_path',\n steps: [...parentPath, ...path.steps],\n});\n\n/**\n * Lowers a canonical desugared select query into the final IRSelectQuery.\n * Introduces aliases, graph patterns (shape scans, traversals), and\n * converts selection paths and where-clauses into IR expressions.\n */\nexport const lowerSelectQuery = (\n canonical: CanonicalDesugaredSelectQuery,\n): IRSelectQuery => {\n const ctx = new LoweringContext();\n const pathOptions: PathLoweringOptions = {\n rootAlias: ctx.rootAlias,\n resolveTraversal: (fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number) =>\n ctx.getOrCreateTraversal(fromAlias, propertyShapeId, pathExpr, maxCount),\n };\n\n const root: IRShapeScanPattern = {\n kind: 'shape_scan',\n shape: canonical.shapeId || '',\n alias: ctx.rootAlias,\n };\n\n const aliasAfterPath = (steps: DesugaredStep[]): string => {\n let currentAlias = pathOptions.rootAlias;\n for (const step of steps) {\n if (step.kind === 'property_step') {\n currentAlias = pathOptions.resolveTraversal(currentAlias, step.propertyShapeId, step.pathExpr, step.maxCount);\n }\n }\n return currentAlias;\n };\n\n const collectProjectionSeeds = (\n selection: DesugaredSelection,\n key?: string,\n parentPath: DesugaredStep[] = [],\n ): ProjectionSeed[] => {\n if (selection.kind === 'selection_path') {\n return [{\n kind: 'path',\n path: combineWithParentPath(parentPath, selection),\n key,\n }];\n }\n\n if (selection.kind === 'sub_select') {\n const combinedParentPath = [...parentPath, ...selection.parentPath];\n // Nested-select inner LIMIT/OFFSET/ORDER BY → attach to the root→child\n // traverse (the alias reached by walking combinedParentPath). The serializer\n // wraps that traverse in a SPARQL sub-SELECT. Single-subject is enforced in\n // irToAlgebra; here we only record the intent.\n const hasInnerPagination =\n typeof selection.innerLimit === 'number' ||\n typeof selection.innerOffset === 'number' ||\n (selection.innerOrderBy && selection.innerOrderBy.length > 0);\n if (hasInnerPagination) {\n const childAlias = aliasAfterPath(combinedParentPath);\n ctx.attachInnerPagination(childAlias, {\n limit: selection.innerLimit,\n offset: selection.innerOffset,\n orderBy: selection.innerOrderBy?.map((o) => ({\n property: o.propertyShapeId,\n direction: o.direction,\n })),\n });\n }\n return collectProjectionSeeds(\n selection.selections,\n // The enclosing key identifies the sub-select container. Result-map\n // entries produced inside that container must retain their own property\n // keys. This also covers one-element array selections, which desugaring\n // intentionally collapses to a single selection.\n undefined,\n combinedParentPath,\n );\n }\n\n if (selection.kind === 'custom_object_select') {\n return selection.entries.flatMap((entry) =>\n collectProjectionSeeds(entry.value, entry.key, parentPath),\n );\n }\n\n if (selection.kind === 'multi_selection') {\n return selection.selections.flatMap((nestedSelection) =>\n // A key on the enclosing selection names that selection; it must not\n // replace the individual keys of an array/multi-selection. Each child\n // derives its own key from its terminal property (or carries its own\n // explicit custom key).\n collectProjectionSeeds(nestedSelection, undefined, parentPath),\n );\n }\n\n\n\n if (selection.kind === 'expression_select') {\n const exprSelect = selection as DesugaredExpressionSelect;\n // Resolve property refs AND any {@ctx} context references — a projected\n // expression (e.g. `select(p => ({flag: p.x.equals(getQueryContext('user'))}))`)\n // reaches the SPARQL algebra just like a where-filter, so its context refs\n // must be resolved here too, not only in lowerWhere.\n const resolved = resolveContextRefs(resolveExpressionRefs(\n exprSelect.expressionNode.ir,\n exprSelect.expressionNode._refs,\n aliasAfterPath(parentPath),\n pathOptions.resolveTraversal,\n ));\n return [{\n kind: 'expression',\n key: key || 'expr',\n expression: resolved,\n }];\n }\n\n return [];\n };\n\n const projectionSeeds = canonical.selections.flatMap((selection) =>\n collectProjectionSeeds(selection),\n );\n\n const projectionScope = new IRAliasScope('projection');\n projectionScope.registerAlias(ctx.rootAlias, 'root');\n const projection: IRProjectionItem[] = [];\n const resultMapEntries: IRResultMapEntry[] = [];\n\n // Inline filter handler: when a property step has `.where()`, canonicalize\n // and lower the where predicate, then attach it to the traverse pattern.\n const inlineFilterHandler = (traverseAlias: string, where: DesugaredWhere) => {\n const filterExpr = lowerWhere(where, ctx, {\n rootAlias: traverseAlias,\n resolveTraversal: pathOptions.resolveTraversal,\n });\n ctx.attachFilter(traverseAlias, filterExpr);\n };\n\n for (const seed of projectionSeeds) {\n const key = seed.kind === 'path'\n ? (seed.key || projectionKeyFromPath(seed.path))\n : seed.key;\n const alias = projectionScope.generateAlias(key).alias;\n projection.push({\n alias,\n expression: seed.kind === 'path'\n ? lowerSelectionPathExpression(seed.path, pathOptions, inlineFilterHandler)\n : seed.expression,\n });\n resultMapEntries.push({\n key,\n alias,\n });\n }\n\n const where = canonical.where ? lowerWhere(canonical.where, ctx, pathOptions) : undefined;\n\n const orderBy: IROrderByItem[] | undefined = canonical.sortBy\n ? canonical.sortBy.paths.map((path, i) => ({\n expression: lowerPath(path, pathOptions),\n direction: canonical.sortBy!.directions[i],\n }))\n : undefined;\n\n // Lower MINUS entries → IRMinusPattern objects\n const minusPatterns: IRGraphPattern[] = [];\n if (canonical.minusEntries) {\n for (const entry of canonical.minusEntries) {\n if (entry.shapeId) {\n // Shape exclusion: MINUS { ?a0 a <Shape> }\n minusPatterns.push({\n kind: 'minus',\n pattern: {kind: 'shape_scan', shape: entry.shapeId, alias: ctx.rootAlias},\n });\n } else if (entry.propertyPaths && entry.propertyPaths.length > 0) {\n // Property existence exclusion: MINUS { ?a0 <prop1> ?m0 . ?a0 <prop2> ?m1 . }\n // Supports nested paths: ?a0 <bestFriend> ?m0 . ?m0 <name> ?m1 .\n const traversals: IRTraversePattern[] = [];\n for (const path of entry.propertyPaths) {\n let currentAlias = ctx.rootAlias;\n for (const segment of path) {\n const toAlias = ctx.generateAlias();\n traversals.push({\n kind: 'traverse',\n from: currentAlias,\n to: toAlias,\n property: segment.propertyShapeId,\n });\n currentAlias = toAlias;\n }\n }\n const innerPattern: IRGraphPattern = traversals.length === 1\n ? traversals[0]\n : {kind: 'join', patterns: traversals};\n minusPatterns.push({kind: 'minus', pattern: innerPattern});\n } else if (entry.where) {\n // Condition-based exclusion: MINUS { ?a0 <prop> ?val . FILTER(...) }\n const {resolve: minusResolveTraversal, patterns: minusTraversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n const minusOptions: PathLoweringOptions = {\n rootAlias: ctx.rootAlias,\n resolveTraversal: minusResolveTraversal,\n };\n const filter = lowerWhere(entry.where, ctx, minusOptions);\n const innerPattern: IRGraphPattern = minusTraversals.length === 1\n ? minusTraversals[0]\n : minusTraversals.length > 1\n ? {kind: 'join', patterns: minusTraversals}\n : {kind: 'shape_scan', shape: canonical.shapeId || '', alias: ctx.rootAlias};\n minusPatterns.push({kind: 'minus', pattern: innerPattern, filter});\n }\n }\n }\n\n return {\n kind: 'select',\n root,\n patterns: [...ctx.getPatterns(), ...minusPatterns],\n projection,\n where,\n orderBy,\n limit: canonical.limit,\n offset: canonical.offset,\n subjectId: canonical.subjectId,\n subjectIds: canonical.subjectIds,\n singleResult: canonical.singleResult,\n resultMap: resultMapEntries,\n };\n};\n\n/**\n * Standalone WHERE lowering — converts a CanonicalWhereExpression to IR expression + patterns.\n * Used by mutation builders (DeleteBuilder, UpdateBuilder) that don't go through the select pipeline.\n */\nexport const lowerWhereToIR = (\n where: CanonicalWhereExpression,\n rootAlias: string = 'a0',\n): {where: IRExpression; wherePatterns: IRGraphPattern[]} => {\n let counter = 1; // start at 1 since a0 is the root\n const ctx: AliasGenerator = {\n generateAlias: () => `a${counter++}`,\n };\n\n const {resolve, patterns: traversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n\n const expr = lowerWhere(where, ctx, {rootAlias, resolveTraversal: resolve});\n return {where: expr, wherePatterns: traversals};\n};\n"]}
1
+ {"version":3,"file":"IRLower.js","sourceRoot":"","sources":["../../../src/queries/IRLower.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CanonicalDesugaredSelectQuery,\n CanonicalWhereExpression,\n} from './IRCanonicalize.js';\nimport type {\n DesugaredExpressionSelect,\n DesugaredExpressionWhere,\n DesugaredExistsWhere,\n DesugaredSelection,\n DesugaredSelectionPath,\n DesugaredStep,\n DesugaredWhere,\n} from './IRDesugar.js';\nimport {resolveExpressionRefs, ExistsCondition} from '../expressions/ExpressionNode.js';\nimport {resolveContextId} from './ContextRef.js';\nimport type {\n IRExpression,\n IRGraphPattern,\n IROrderByItem,\n IRProjectionItem,\n IRResultMapEntry,\n IRSelectQuery,\n IRShapeScanPattern,\n IRTraversePattern,\n} from './IntermediateRepresentation.js';\nimport {lowerSelectionPathExpression, projectionKeyFromPath} from './IRProjection.js';\nimport {IRAliasScope} from './IRAliasScope.js';\nimport {attachCatalog} from '../utils/ShapeClass.js';\nimport type {PathExpr} from '../paths/PropertyPathExpr.js';\n\n/**\n * Creates a memoized traversal resolver that deduplicates (fromAlias, propertyShapeId)\n * pairs, generates unique aliases, and accumulates the resulting patterns.\n * Used by both select-query lowering and mutation expression resolution.\n */\nexport function createTraversalResolver<P>(\n generateAlias: () => string,\n createPattern: (from: string, to: string, property: string) => P,\n): {resolve: (fromAlias: string, propertyShapeId: string) => string; patterns: P[]} {\n const patterns: P[] = [];\n const seen = new Map<string, string>();\n\n const resolve = (fromAlias: string, propertyShapeId: string): string => {\n const key = `${fromAlias}:${propertyShapeId}`;\n if (seen.has(key)) return seen.get(key)!;\n const toAlias = generateAlias();\n seen.set(key, toAlias);\n patterns.push(createPattern(fromAlias, toAlias, propertyShapeId));\n return toAlias;\n };\n\n return {resolve, patterns};\n}\n\nclass LoweringContext {\n private counter = 0;\n private patterns: IRGraphPattern[] = [];\n private traverseMap = new Map<string, string>();\n private filterMap = new Map<string, IRExpression>();\n private innerPaginationMap = new Map<\n string,\n {limit?: number; offset?: number; orderBy?: import('./IntermediateRepresentation.js').IRInnerOrderBy[]}\n >();\n readonly rootAlias: string;\n\n constructor() {\n this.rootAlias = this.nextAlias();\n }\n\n private nextAlias(): string {\n return `a${this.counter++}`;\n }\n\n getOrCreateTraversal(fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number): string {\n const key = `${fromAlias}:${propertyShapeId}`;\n const existing = this.traverseMap.get(key);\n if (existing) return existing;\n\n const toAlias = this.nextAlias();\n const pattern: IRTraversePattern = {\n kind: 'traverse',\n from: fromAlias,\n to: toAlias,\n property: propertyShapeId,\n };\n if (pathExpr) {\n pattern.pathExpr = pathExpr;\n }\n if (typeof maxCount === 'number') {\n pattern.maxCount = maxCount;\n }\n this.patterns.push(pattern);\n this.traverseMap.set(key, toAlias);\n return toAlias;\n }\n\n generateAlias(): string {\n return this.nextAlias();\n }\n\n /**\n * Attaches an inline where filter to the traverse pattern targeting `toAlias`.\n * The filter will be merged into the pattern when `getPatterns()` is called.\n */\n attachFilter(toAlias: string, filter: IRExpression): void {\n this.filterMap.set(toAlias, filter);\n }\n\n /**\n * Attaches inner LIMIT/OFFSET/ORDER BY (from a nested select) to the traverse\n * pattern targeting `toAlias`. Merged into the pattern in `getPatterns()`.\n */\n attachInnerPagination(\n toAlias: string,\n pagination: {limit?: number; offset?: number; orderBy?: import('./IntermediateRepresentation.js').IRInnerOrderBy[]},\n ): void {\n this.innerPaginationMap.set(toAlias, pagination);\n }\n\n getPatterns(): IRGraphPattern[] {\n return this.patterns.map((p) => {\n if (p.kind !== 'traverse') return p;\n let pattern = p;\n if (this.filterMap.has(p.to)) {\n pattern = {...pattern, filter: this.filterMap.get(p.to)!};\n }\n const pagination = this.innerPaginationMap.get(p.to);\n if (pagination) {\n pattern = {\n ...pattern,\n ...(typeof pagination.limit === 'number' ? {innerLimit: pagination.limit} : {}),\n ...(typeof pagination.offset === 'number' ? {innerOffset: pagination.offset} : {}),\n ...(pagination.orderBy ? {innerOrderBy: pagination.orderBy} : {}),\n };\n }\n return pattern;\n });\n }\n}\n\n/** Minimal interface for alias generation used by lowerWhere and traversal resolvers. */\ntype AliasGenerator = {\n generateAlias(): string;\n};\n\ntype PathLoweringOptions = {\n rootAlias: string;\n resolveTraversal: (fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number) => string;\n};\n\nconst lowerPath = (\n path: DesugaredSelectionPath,\n options: PathLoweringOptions,\n): IRExpression => lowerSelectionPathExpression(path, options);\n\n/**\n * Resolve any `{@ctx}` context references carried in a lowered expression tree —\n * whether it came from a where-clause filter OR a projected (expression-select)\n * value.\n *\n * A context reference (`.equals(getQueryContext('user'))`) is carried through build +\n * the wire as a *name* (`reference_expr.contextName` / `context_property_expr.contextName`),\n * never a baked id. Here — at lowering — it is resolved against the live context map into\n * the concrete IRI; an unresolved one throws `UnresolvedContextError` (SELECT callers\n * short-circuit to null before lowering, so a query is never lowered with an unresolved\n * context in practice). This must be applied to every expression that can reach the SPARQL\n * algebra, not just where-filters.\n */\nconst resolveContextRefs = (expr: IRExpression): IRExpression => {\n switch (expr.kind) {\n case 'reference_expr':\n if (expr.contextName) {\n return {kind: 'reference_expr', value: resolveContextId(expr.contextName, true)!};\n }\n return expr;\n case 'context_property_expr':\n if (expr.contextName) {\n return {kind: 'context_property_expr', contextIri: resolveContextId(expr.contextName, true)!, property: expr.property};\n }\n return expr;\n case 'binary_expr':\n return {...expr, left: resolveContextRefs(expr.left), right: resolveContextRefs(expr.right)};\n case 'in_expr':\n return {\n ...expr,\n value: resolveContextRefs(expr.value),\n source: {list: expr.source.list.map(resolveContextRefs)},\n };\n case 'logical_expr':\n return {...expr, expressions: expr.expressions.map(resolveContextRefs)};\n case 'not_expr':\n return {...expr, expression: resolveContextRefs(expr.expression)};\n case 'function_expr':\n case 'aggregate_expr':\n return {...expr, args: expr.args.map(resolveContextRefs)};\n case 'exists_expr':\n return expr.filter ? {...expr, filter: resolveContextRefs(expr.filter)} : expr;\n default:\n return expr;\n }\n};\n\nconst lowerWhere = (\n where: CanonicalWhereExpression,\n ctx: AliasGenerator,\n options: PathLoweringOptions,\n): IRExpression => {\n switch (where.kind) {\n case 'where_expression': {\n // ExpressionNode-based WHERE — resolve refs and return IRExpression directly\n const exprWhere = where as DesugaredExpressionWhere;\n return resolveContextRefs(resolveExpressionRefs(\n exprWhere.expressionNode.ir,\n exprWhere.expressionNode._refs,\n options.rootAlias,\n options.resolveTraversal,\n ));\n }\n case 'where_exists_condition': {\n // ExistsCondition-based WHERE (from .some()/.every()/.none())\n const existsWhere = where as DesugaredExistsWhere;\n return resolveContextRefs(lowerExistsCondition(existsWhere.existsCondition, ctx, options));\n }\n default:\n const _exhaustive: never = where;\n throw new Error(`Unknown canonical where kind: ${(_exhaustive as {kind: string}).kind}`);\n }\n};\n\n/**\n * Lower an ExistsCondition to IRExistsExpression with proper traversal patterns.\n */\nconst lowerExistsCondition = (\n condition: ExistsCondition,\n ctx: AliasGenerator,\n options: PathLoweringOptions,\n): IRExpression => {\n // Build traversal patterns for the collection path\n const {resolve: existsResolve, patterns: traversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n\n // Walk the path segments to create traversal patterns\n let currentAlias = options.rootAlias;\n for (const segmentId of condition.pathSegmentIds) {\n currentAlias = existsResolve(currentAlias, segmentId);\n }\n\n // Resolve the inner predicate's property refs against the EXISTS scope\n const filter = resolveExpressionRefs(\n condition.predicate.ir,\n condition.predicate._refs,\n currentAlias,\n existsResolve,\n );\n\n let existsExpr: IRExpression = {\n kind: 'exists_expr',\n pattern: traversals.length === 1\n ? traversals[0]\n : {kind: 'join', patterns: traversals},\n filter,\n };\n\n // Wrap in NOT if negated (.none() or outer NOT of .every())\n if (condition.negated) {\n existsExpr = {kind: 'not_expr', expression: existsExpr};\n }\n\n // Handle .and()/.or() chaining\n if (condition.chain.length > 0) {\n let result: IRExpression = existsExpr;\n for (const link of condition.chain) {\n let rightExpr: IRExpression;\n if (link.condition instanceof ExistsCondition) {\n rightExpr = lowerExistsCondition(link.condition, ctx, options);\n } else {\n rightExpr = resolveExpressionRefs(\n link.condition.ir,\n link.condition._refs,\n options.rootAlias,\n options.resolveTraversal,\n );\n }\n result = {\n kind: 'logical_expr',\n operator: link.op,\n expressions: [result, rightExpr],\n };\n }\n return result;\n }\n\n return existsExpr;\n};\n\ntype ProjectionSeed =\n | {\n kind: 'path';\n path: DesugaredSelectionPath;\n key?: string;\n }\n | {\n kind: 'expression';\n expression: IRExpression;\n key: string;\n };\n\nconst combineWithParentPath = (\n parentPath: DesugaredStep[],\n path: DesugaredSelectionPath,\n): DesugaredSelectionPath => ({\n kind: 'selection_path',\n steps: [...parentPath, ...path.steps],\n});\n\n/**\n * Lowers a canonical desugared select query into the final IRSelectQuery.\n * Introduces aliases, graph patterns (shape scans, traversals), and\n * converts selection paths and where-clauses into IR expressions.\n */\nexport const lowerSelectQuery = (\n canonical: CanonicalDesugaredSelectQuery,\n): IRSelectQuery => {\n const ctx = new LoweringContext();\n const pathOptions: PathLoweringOptions = {\n rootAlias: ctx.rootAlias,\n resolveTraversal: (fromAlias: string, propertyShapeId: string, pathExpr?: PathExpr, maxCount?: number) =>\n ctx.getOrCreateTraversal(fromAlias, propertyShapeId, pathExpr, maxCount),\n };\n\n const root: IRShapeScanPattern = {\n kind: 'shape_scan',\n shape: canonical.shapeId || '',\n alias: ctx.rootAlias,\n };\n\n const aliasAfterPath = (steps: DesugaredStep[]): string => {\n let currentAlias = pathOptions.rootAlias;\n for (const step of steps) {\n if (step.kind === 'property_step') {\n currentAlias = pathOptions.resolveTraversal(currentAlias, step.propertyShapeId, step.pathExpr, step.maxCount);\n }\n }\n return currentAlias;\n };\n\n const collectProjectionSeeds = (\n selection: DesugaredSelection,\n key?: string,\n parentPath: DesugaredStep[] = [],\n ): ProjectionSeed[] => {\n if (selection.kind === 'selection_path') {\n return [{\n kind: 'path',\n path: combineWithParentPath(parentPath, selection),\n key,\n }];\n }\n\n if (selection.kind === 'sub_select') {\n const combinedParentPath = [...parentPath, ...selection.parentPath];\n // Nested-select inner LIMIT/OFFSET/ORDER BY → attach to the root→child\n // traverse (the alias reached by walking combinedParentPath). The serializer\n // wraps that traverse in a SPARQL sub-SELECT. Single-subject is enforced in\n // irToAlgebra; here we only record the intent.\n const hasInnerPagination =\n typeof selection.innerLimit === 'number' ||\n typeof selection.innerOffset === 'number' ||\n (selection.innerOrderBy && selection.innerOrderBy.length > 0);\n if (hasInnerPagination) {\n const childAlias = aliasAfterPath(combinedParentPath);\n ctx.attachInnerPagination(childAlias, {\n limit: selection.innerLimit,\n offset: selection.innerOffset,\n orderBy: selection.innerOrderBy?.map((o) => ({\n property: o.propertyShapeId,\n direction: o.direction,\n })),\n });\n }\n return collectProjectionSeeds(\n selection.selections,\n // The enclosing key identifies the sub-select container. Result-map\n // entries produced inside that container must retain their own property\n // keys. This also covers one-element array selections, which desugaring\n // intentionally collapses to a single selection.\n undefined,\n combinedParentPath,\n );\n }\n\n if (selection.kind === 'custom_object_select') {\n return selection.entries.flatMap((entry) =>\n collectProjectionSeeds(entry.value, entry.key, parentPath),\n );\n }\n\n if (selection.kind === 'multi_selection') {\n return selection.selections.flatMap((nestedSelection) =>\n // A key on the enclosing selection names that selection; it must not\n // replace the individual keys of an array/multi-selection. Each child\n // derives its own key from its terminal property (or carries its own\n // explicit custom key).\n collectProjectionSeeds(nestedSelection, undefined, parentPath),\n );\n }\n\n\n\n if (selection.kind === 'expression_select') {\n const exprSelect = selection as DesugaredExpressionSelect;\n // Resolve property refs AND any {@ctx} context references — a projected\n // expression (e.g. `select(p => ({flag: p.x.equals(getQueryContext('user'))}))`)\n // reaches the SPARQL algebra just like a where-filter, so its context refs\n // must be resolved here too, not only in lowerWhere.\n const resolved = resolveContextRefs(resolveExpressionRefs(\n exprSelect.expressionNode.ir,\n exprSelect.expressionNode._refs,\n aliasAfterPath(parentPath),\n pathOptions.resolveTraversal,\n ));\n return [{\n kind: 'expression',\n key: key || 'expr',\n expression: resolved,\n }];\n }\n\n return [];\n };\n\n const projectionSeeds = canonical.selections.flatMap((selection) =>\n collectProjectionSeeds(selection),\n );\n\n const projectionScope = new IRAliasScope('projection');\n projectionScope.registerAlias(ctx.rootAlias, 'root');\n const projection: IRProjectionItem[] = [];\n const resultMapEntries: IRResultMapEntry[] = [];\n\n // Inline filter handler: when a property step has `.where()`, canonicalize\n // and lower the where predicate, then attach it to the traverse pattern.\n const inlineFilterHandler = (traverseAlias: string, where: DesugaredWhere) => {\n const filterExpr = lowerWhere(where, ctx, {\n rootAlias: traverseAlias,\n resolveTraversal: pathOptions.resolveTraversal,\n });\n ctx.attachFilter(traverseAlias, filterExpr);\n };\n\n for (const seed of projectionSeeds) {\n const key = seed.kind === 'path'\n ? (seed.key || projectionKeyFromPath(seed.path))\n : seed.key;\n const alias = projectionScope.generateAlias(key).alias;\n projection.push({\n alias,\n expression: seed.kind === 'path'\n ? lowerSelectionPathExpression(seed.path, pathOptions, inlineFilterHandler)\n : seed.expression,\n });\n resultMapEntries.push({\n key,\n alias,\n });\n }\n\n const where = canonical.where ? lowerWhere(canonical.where, ctx, pathOptions) : undefined;\n\n const orderBy: IROrderByItem[] | undefined = canonical.sortBy\n ? canonical.sortBy.paths.map((path, i) => ({\n expression: lowerPath(path, pathOptions),\n direction: canonical.sortBy!.directions[i],\n }))\n : undefined;\n\n // Lower MINUS entries → IRMinusPattern objects\n const minusPatterns: IRGraphPattern[] = [];\n if (canonical.minusEntries) {\n for (const entry of canonical.minusEntries) {\n if (entry.shapeId) {\n // Shape exclusion: MINUS { ?a0 a <Shape> }\n minusPatterns.push({\n kind: 'minus',\n pattern: {kind: 'shape_scan', shape: entry.shapeId, alias: ctx.rootAlias},\n });\n } else if (entry.propertyPaths && entry.propertyPaths.length > 0) {\n // Property existence exclusion: MINUS { ?a0 <prop1> ?m0 . ?a0 <prop2> ?m1 . }\n // Supports nested paths: ?a0 <bestFriend> ?m0 . ?m0 <name> ?m1 .\n const traversals: IRTraversePattern[] = [];\n for (const path of entry.propertyPaths) {\n let currentAlias = ctx.rootAlias;\n for (const segment of path) {\n const toAlias = ctx.generateAlias();\n traversals.push({\n kind: 'traverse',\n from: currentAlias,\n to: toAlias,\n property: segment.propertyShapeId,\n });\n currentAlias = toAlias;\n }\n }\n const innerPattern: IRGraphPattern = traversals.length === 1\n ? traversals[0]\n : {kind: 'join', patterns: traversals};\n minusPatterns.push({kind: 'minus', pattern: innerPattern});\n } else if (entry.where) {\n // Condition-based exclusion: MINUS { ?a0 <prop> ?val . FILTER(...) }\n const {resolve: minusResolveTraversal, patterns: minusTraversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n const minusOptions: PathLoweringOptions = {\n rootAlias: ctx.rootAlias,\n resolveTraversal: minusResolveTraversal,\n };\n const filter = lowerWhere(entry.where, ctx, minusOptions);\n const innerPattern: IRGraphPattern = minusTraversals.length === 1\n ? minusTraversals[0]\n : minusTraversals.length > 1\n ? {kind: 'join', patterns: minusTraversals}\n : {kind: 'shape_scan', shape: canonical.shapeId || '', alias: ctx.rootAlias};\n minusPatterns.push({kind: 'minus', pattern: innerPattern, filter});\n }\n }\n }\n\n return attachCatalog<IRSelectQuery>({\n kind: 'select',\n root,\n patterns: [...ctx.getPatterns(), ...minusPatterns],\n projection,\n where,\n orderBy,\n limit: canonical.limit,\n offset: canonical.offset,\n subjectId: canonical.subjectId,\n subjectIds: canonical.subjectIds,\n singleResult: canonical.singleResult,\n resultMap: resultMapEntries,\n });\n};\n\n/**\n * Standalone WHERE lowering — converts a CanonicalWhereExpression to IR expression + patterns.\n * Used by mutation builders (DeleteBuilder, UpdateBuilder) that don't go through the select pipeline.\n */\nexport const lowerWhereToIR = (\n where: CanonicalWhereExpression,\n rootAlias: string = 'a0',\n): {where: IRExpression; wherePatterns: IRGraphPattern[]} => {\n let counter = 1; // start at 1 since a0 is the root\n const ctx: AliasGenerator = {\n generateAlias: () => `a${counter++}`,\n };\n\n const {resolve, patterns: traversals} = createTraversalResolver(\n () => ctx.generateAlias(),\n (from, to, property): IRTraversePattern => ({kind: 'traverse', from, to, property}),\n );\n\n const expr = lowerWhere(where, ctx, {rootAlias, resolveTraversal: resolve});\n return {where: expr, wherePatterns: traversals};\n};\n"]}
@@ -1,6 +1,7 @@
1
1
  import { isSetModificationValue, } from './QueryFactory.js';
2
2
  import { isExpressionNode, resolveExpressionRefs } from '../expressions/ExpressionNode.js';
3
3
  import { createTraversalResolver } from './IRLower.js';
4
+ import { attachCatalog } from '../utils/ShapeClass.js';
4
5
  /**
5
6
  * Throws if any field of an upsert carries an expression. Named per offending property so
6
7
  * the caller is not left decoding an unbound-variable mystery further down the pipeline.
@@ -88,19 +89,19 @@ const toNodeData = (description, collector) => {
88
89
  };
89
90
  /** Builds an IRCreateMutation from a create factory's internal description. */
90
91
  export const buildCanonicalCreateMutationIR = (query) => {
91
- return {
92
+ return attachCatalog({
92
93
  kind: 'create',
93
94
  shape: query.shape.id,
94
95
  data: toNodeData(query.description),
95
- };
96
+ });
96
97
  };
97
98
  /** Builds an IRUpdateMutation from an update factory's internal description. */
98
99
  export const buildCanonicalUpdateMutationIR = (query) => {
99
100
  const collector = createTraversalCollector();
100
101
  const data = toNodeData(query.updates, collector);
101
- return Object.assign({ kind: 'update', shape: query.shape.id, id: query.id, data }, (collector.patterns.length > 0
102
+ return attachCatalog(Object.assign({ kind: 'update', shape: query.shape.id, id: query.id, data }, (collector.patterns.length > 0
102
103
  ? { traversalPatterns: collector.patterns }
103
- : {}));
104
+ : {})));
104
105
  };
105
106
  /**
106
107
  * Builds an IRUpsertMutation — an update that also asserts the node's type, so it is
@@ -116,40 +117,40 @@ export const buildCanonicalUpsertMutationIR = (query) => {
116
117
  assertNoExpressionFields(query.updates, query.shape.id);
117
118
  const collector = createTraversalCollector();
118
119
  const data = toNodeData(query.updates, collector);
119
- return Object.assign({ kind: 'upsert', shape: query.shape.id, id: query.id, data }, (collector.patterns.length > 0
120
+ return attachCatalog(Object.assign({ kind: 'upsert', shape: query.shape.id, id: query.id, data }, (collector.patterns.length > 0
120
121
  ? { traversalPatterns: collector.patterns }
121
- : {}));
122
+ : {})));
122
123
  };
123
124
  /** Builds an IRDeleteMutation from a delete factory's internal description. */
124
125
  export const buildCanonicalDeleteMutationIR = (query) => {
125
- return {
126
+ return attachCatalog({
126
127
  kind: 'delete',
127
128
  shape: query.shape.id,
128
129
  ids: query.ids.map((id) => ({ id: id.id })),
129
- };
130
+ });
130
131
  };
131
132
  /** Builds an IRDeleteAllMutation — delete all instances of a shape type. */
132
133
  export const buildCanonicalDeleteAllMutationIR = (query) => {
133
- return {
134
+ return attachCatalog({
134
135
  kind: 'delete_all',
135
136
  shape: query.shape.id,
136
- };
137
+ });
137
138
  };
138
139
  /** Builds an IRDeleteWhereMutation — delete instances matching a condition. */
139
140
  export const buildCanonicalDeleteWhereMutationIR = (query) => {
140
- return {
141
+ return attachCatalog({
141
142
  kind: 'delete_where',
142
143
  shape: query.shape.id,
143
144
  where: query.where,
144
145
  wherePatterns: query.wherePatterns,
145
- };
146
+ });
146
147
  };
147
148
  /** Builds an IRUpdateWhereMutation — update instances matching a condition or all. */
148
149
  export const buildCanonicalUpdateWhereMutationIR = (query) => {
149
150
  const collector = createTraversalCollector();
150
151
  const data = toNodeData(query.updates, collector);
151
- return Object.assign({ kind: 'update_where', shape: query.shape.id, data, where: query.where, wherePatterns: query.wherePatterns }, (collector.patterns.length > 0
152
+ return attachCatalog(Object.assign({ kind: 'update_where', shape: query.shape.id, data, where: query.where, wherePatterns: query.wherePatterns }, (collector.patterns.length > 0
152
153
  ? { traversalPatterns: collector.patterns }
153
- : {}));
154
+ : {})));
154
155
  };
155
156
  //# sourceMappingURL=IRMutation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IRMutation.js","sourceRoot":"","sources":["../../../src/queries/IRMutation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {NodeShapeData} from '../shapes/SHACL.js';\nimport {\n type NodeDescriptionValue,\n NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {isExpressionNode, resolveExpressionRefs} from '../expressions/ExpressionNode.js';\nimport type {\n IRCreateMutation,\n IRDeleteMutation,\n IRDeleteAllMutation,\n IRDeleteWhereMutation,\n IRUpdateWhereMutation,\n IRFieldValue,\n IRNodeData,\n IRFieldUpdate,\n IRSetModificationValue,\n IRUpdateMutation,\n IRUpsertMutation,\n IRExpression,\n IRGraphPattern,\n IRTraversalPattern,\n} from './IntermediateRepresentation.js';\nimport {createTraversalResolver} from './IRLower.js';\n\ntype CreateMutationInput = {\n shape: NodeShapeData;\n description: NodeDescriptionValue;\n};\n\ntype UpdateMutationInput = {\n id: string;\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n};\n\ntype UpsertMutationInput = {\n id: string;\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n};\n\n/**\n * Throws if any field of an upsert carries an expression. Named per offending property so\n * the caller is not left decoding an unbound-variable mystery further down the pipeline.\n */\nconst assertNoExpressionFields = (\n updates: NodeDescriptionValue,\n shapeId: string,\n): void => {\n for (const field of updates?.fields ?? []) {\n // Mirrors how `toSingleFieldValue` recognises an expression, so the guard cannot\n // drift from the lowering it is protecting.\n if (isExpressionNode(field.val)) {\n throw new Error(\n `upsert does not support expression-valued fields (property \"${field.prop.id}\" of ${shapeId}). ` +\n `An expression reads the node's current value, which does not exist when upsert creates it, ` +\n `and the property would be silently skipped. Pass a concrete value, or use ` +\n `update().for({id}) if the node is known to exist.`,\n );\n }\n }\n};\n\ntype DeleteMutationInput = {\n shape: NodeShapeData;\n ids: NodeReferenceValue[];\n};\n\nconst toNodeReference = (value: NodeReferenceValue): NodeReferenceValue => ({\n id: value.id,\n});\n\nconst toSetModification = (value: SetModificationValue): IRSetModificationValue => {\n return {\n add: value.$add\n ? value.$add.map((item) => toFieldValue(item as unknown as PropUpdateValue))\n : undefined,\n remove: value.$remove ? value.$remove.map((item) => toNodeReference(item)) : undefined,\n };\n};\n\n/** Alias used as the mutation subject for expression ref resolution. */\nconst MUTATION_SUBJECT_ALIAS = '__mutation_subject__';\n\nexport type TraversalCollector = {\n resolve: (fromAlias: string, propertyShapeId: string) => string;\n patterns: IRTraversalPattern[];\n};\n\n/**\n * Create a traversal collector for mutation expressions. Uses `__trav_N__` alias\n * prefixes to avoid collision with query aliases (a0, a1...) and the mutation\n * subject placeholder. Delegates to the shared createTraversalResolver factory.\n */\nexport function createTraversalCollector(): TraversalCollector {\n let counter = 0;\n return createTraversalResolver(\n () => `__trav_${counter++}__`,\n (from, to, property): IRTraversalPattern => ({from, property, to}),\n );\n}\n\nconst toSingleFieldValue = (\n value: SinglePropertyUpdateValue,\n collector?: TraversalCollector,\n): IRFieldValue => {\n if (value === undefined) {\n return undefined;\n }\n\n // ExpressionNode → resolve refs and extract IRExpression\n if (isExpressionNode(value)) {\n return resolveExpressionRefs(\n value.ir,\n value._refs,\n MUTATION_SUBJECT_ALIAS,\n // In mutation context, all property segments are on the subject entity.\n // For single-segment refs (e.g. p.age), the property_expr already has the property as its .property.\n // For multi-segment refs (e.g. p.bestFriend.name), this creates intermediate traversals.\n collector\n ? collector.resolve\n : (_fromAlias, _propertyShapeId) => {\n // No collector provided — multi-segment traversals cannot be resolved.\n return MUTATION_SUBJECT_ALIAS;\n },\n );\n }\n\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value instanceof Date\n ) {\n return value;\n }\n\n if ('id' in (value as NodeReferenceValue)) {\n return toNodeReference(value as NodeReferenceValue);\n }\n\n return toNodeData(value as NodeDescriptionValue);\n};\n\nconst toFieldValue = (\n value: PropUpdateValue,\n collector?: TraversalCollector,\n): IRFieldValue => {\n if (Array.isArray(value)) {\n return value.map((item) => toSingleFieldValue(item, collector));\n }\n\n if (isSetModificationValue(value)) {\n return toSetModification(value);\n }\n\n return toSingleFieldValue(value, collector);\n};\n\nconst toFieldUpdate = (\n field: NodeDescriptionValue['fields'][number],\n collector?: TraversalCollector,\n): IRFieldUpdate => {\n return {\n property: field.prop.id,\n value: toFieldValue(field.val, collector),\n };\n};\n\nconst toNodeData = (\n description: NodeDescriptionValue,\n collector?: TraversalCollector,\n): IRNodeData => {\n return {\n shape: description.shape.id,\n fields: description.fields.map((f) => toFieldUpdate(f, collector)),\n ...(description.__id ? {id: description.__id} : {}),\n };\n};\n\n/** Builds an IRCreateMutation from a create factory's internal description. */\nexport const buildCanonicalCreateMutationIR = (\n query: CreateMutationInput,\n): IRCreateMutation => {\n return {\n kind: 'create',\n shape: query.shape.id,\n data: toNodeData(query.description),\n };\n};\n\n/** Builds an IRUpdateMutation from an update factory's internal description. */\nexport const buildCanonicalUpdateMutationIR = (\n query: UpdateMutationInput,\n): IRUpdateMutation => {\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return {\n kind: 'update',\n shape: query.shape.id,\n id: query.id,\n data,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n };\n};\n\n/**\n * Builds an IRUpsertMutation — an update that also asserts the node's type, so it is\n * correct whether or not the node exists.\n *\n * Rejects expression-valued fields. An expression such as `age: p.age.plus(1)` lowers to\n * a BIND over the node's current value; when the node does not exist that ref is unbound,\n * and SPARQL drops any INSERT triple containing an unbound variable. The write would\n * report success and store nothing for that property — precisely the silent-wrong-write\n * this primitive exists to remove, so it is refused rather than documented.\n */\nexport const buildCanonicalUpsertMutationIR = (\n query: UpsertMutationInput,\n): IRUpsertMutation => {\n assertNoExpressionFields(query.updates, query.shape.id);\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return {\n kind: 'upsert',\n shape: query.shape.id,\n id: query.id,\n data,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n };\n};\n\n/** Builds an IRDeleteMutation from a delete factory's internal description. */\nexport const buildCanonicalDeleteMutationIR = (\n query: DeleteMutationInput,\n): IRDeleteMutation => {\n return {\n kind: 'delete',\n shape: query.shape.id,\n ids: query.ids.map((id) => ({id: id.id})),\n };\n};\n\ntype DeleteAllMutationInput = {\n shape: NodeShapeData;\n};\n\n/** Builds an IRDeleteAllMutation — delete all instances of a shape type. */\nexport const buildCanonicalDeleteAllMutationIR = (\n query: DeleteAllMutationInput,\n): IRDeleteAllMutation => {\n return {\n kind: 'delete_all',\n shape: query.shape.id,\n };\n};\n\ntype DeleteWhereMutationInput = {\n shape: NodeShapeData;\n where: IRExpression;\n wherePatterns: IRGraphPattern[];\n};\n\n/** Builds an IRDeleteWhereMutation — delete instances matching a condition. */\nexport const buildCanonicalDeleteWhereMutationIR = (\n query: DeleteWhereMutationInput,\n): IRDeleteWhereMutation => {\n return {\n kind: 'delete_where',\n shape: query.shape.id,\n where: query.where,\n wherePatterns: query.wherePatterns,\n };\n};\n\ntype UpdateWhereMutationInput = {\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n where?: IRExpression;\n wherePatterns?: IRGraphPattern[];\n};\n\n/** Builds an IRUpdateWhereMutation — update instances matching a condition or all. */\nexport const buildCanonicalUpdateWhereMutationIR = (\n query: UpdateWhereMutationInput,\n): IRUpdateWhereMutation => {\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return {\n kind: 'update_where',\n shape: query.shape.id,\n data,\n where: query.where,\n wherePatterns: query.wherePatterns,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n };\n};\n"]}
1
+ {"version":3,"file":"IRMutation.js","sourceRoot":"","sources":["../../../src/queries/IRMutation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {NodeShapeData} from '../shapes/SHACL.js';\nimport {\n type NodeDescriptionValue,\n NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {isExpressionNode, resolveExpressionRefs} from '../expressions/ExpressionNode.js';\nimport type {\n IRCreateMutation,\n IRDeleteMutation,\n IRDeleteAllMutation,\n IRDeleteWhereMutation,\n IRUpdateWhereMutation,\n IRFieldValue,\n IRNodeData,\n IRFieldUpdate,\n IRSetModificationValue,\n IRUpdateMutation,\n IRUpsertMutation,\n IRExpression,\n IRGraphPattern,\n IRTraversalPattern,\n} from './IntermediateRepresentation.js';\nimport {createTraversalResolver} from './IRLower.js';\nimport {attachCatalog} from '../utils/ShapeClass.js';\n\ntype CreateMutationInput = {\n shape: NodeShapeData;\n description: NodeDescriptionValue;\n};\n\ntype UpdateMutationInput = {\n id: string;\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n};\n\ntype UpsertMutationInput = {\n id: string;\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n};\n\n/**\n * Throws if any field of an upsert carries an expression. Named per offending property so\n * the caller is not left decoding an unbound-variable mystery further down the pipeline.\n */\nconst assertNoExpressionFields = (\n updates: NodeDescriptionValue,\n shapeId: string,\n): void => {\n for (const field of updates?.fields ?? []) {\n // Mirrors how `toSingleFieldValue` recognises an expression, so the guard cannot\n // drift from the lowering it is protecting.\n if (isExpressionNode(field.val)) {\n throw new Error(\n `upsert does not support expression-valued fields (property \"${field.prop.id}\" of ${shapeId}). ` +\n `An expression reads the node's current value, which does not exist when upsert creates it, ` +\n `and the property would be silently skipped. Pass a concrete value, or use ` +\n `update().for({id}) if the node is known to exist.`,\n );\n }\n }\n};\n\ntype DeleteMutationInput = {\n shape: NodeShapeData;\n ids: NodeReferenceValue[];\n};\n\nconst toNodeReference = (value: NodeReferenceValue): NodeReferenceValue => ({\n id: value.id,\n});\n\nconst toSetModification = (value: SetModificationValue): IRSetModificationValue => {\n return {\n add: value.$add\n ? value.$add.map((item) => toFieldValue(item as unknown as PropUpdateValue))\n : undefined,\n remove: value.$remove ? value.$remove.map((item) => toNodeReference(item)) : undefined,\n };\n};\n\n/** Alias used as the mutation subject for expression ref resolution. */\nconst MUTATION_SUBJECT_ALIAS = '__mutation_subject__';\n\nexport type TraversalCollector = {\n resolve: (fromAlias: string, propertyShapeId: string) => string;\n patterns: IRTraversalPattern[];\n};\n\n/**\n * Create a traversal collector for mutation expressions. Uses `__trav_N__` alias\n * prefixes to avoid collision with query aliases (a0, a1...) and the mutation\n * subject placeholder. Delegates to the shared createTraversalResolver factory.\n */\nexport function createTraversalCollector(): TraversalCollector {\n let counter = 0;\n return createTraversalResolver(\n () => `__trav_${counter++}__`,\n (from, to, property): IRTraversalPattern => ({from, property, to}),\n );\n}\n\nconst toSingleFieldValue = (\n value: SinglePropertyUpdateValue,\n collector?: TraversalCollector,\n): IRFieldValue => {\n if (value === undefined) {\n return undefined;\n }\n\n // ExpressionNode → resolve refs and extract IRExpression\n if (isExpressionNode(value)) {\n return resolveExpressionRefs(\n value.ir,\n value._refs,\n MUTATION_SUBJECT_ALIAS,\n // In mutation context, all property segments are on the subject entity.\n // For single-segment refs (e.g. p.age), the property_expr already has the property as its .property.\n // For multi-segment refs (e.g. p.bestFriend.name), this creates intermediate traversals.\n collector\n ? collector.resolve\n : (_fromAlias, _propertyShapeId) => {\n // No collector provided — multi-segment traversals cannot be resolved.\n return MUTATION_SUBJECT_ALIAS;\n },\n );\n }\n\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n value instanceof Date\n ) {\n return value;\n }\n\n if ('id' in (value as NodeReferenceValue)) {\n return toNodeReference(value as NodeReferenceValue);\n }\n\n return toNodeData(value as NodeDescriptionValue);\n};\n\nconst toFieldValue = (\n value: PropUpdateValue,\n collector?: TraversalCollector,\n): IRFieldValue => {\n if (Array.isArray(value)) {\n return value.map((item) => toSingleFieldValue(item, collector));\n }\n\n if (isSetModificationValue(value)) {\n return toSetModification(value);\n }\n\n return toSingleFieldValue(value, collector);\n};\n\nconst toFieldUpdate = (\n field: NodeDescriptionValue['fields'][number],\n collector?: TraversalCollector,\n): IRFieldUpdate => {\n return {\n property: field.prop.id,\n value: toFieldValue(field.val, collector),\n };\n};\n\nconst toNodeData = (\n description: NodeDescriptionValue,\n collector?: TraversalCollector,\n): IRNodeData => {\n return {\n shape: description.shape.id,\n fields: description.fields.map((f) => toFieldUpdate(f, collector)),\n ...(description.__id ? {id: description.__id} : {}),\n };\n};\n\n/** Builds an IRCreateMutation from a create factory's internal description. */\nexport const buildCanonicalCreateMutationIR = (\n query: CreateMutationInput,\n): IRCreateMutation => {\n return attachCatalog({\n kind: 'create',\n shape: query.shape.id,\n data: toNodeData(query.description),\n });\n};\n\n/** Builds an IRUpdateMutation from an update factory's internal description. */\nexport const buildCanonicalUpdateMutationIR = (\n query: UpdateMutationInput,\n): IRUpdateMutation => {\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return attachCatalog({\n kind: 'update',\n shape: query.shape.id,\n id: query.id,\n data,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n });\n};\n\n/**\n * Builds an IRUpsertMutation — an update that also asserts the node's type, so it is\n * correct whether or not the node exists.\n *\n * Rejects expression-valued fields. An expression such as `age: p.age.plus(1)` lowers to\n * a BIND over the node's current value; when the node does not exist that ref is unbound,\n * and SPARQL drops any INSERT triple containing an unbound variable. The write would\n * report success and store nothing for that property — precisely the silent-wrong-write\n * this primitive exists to remove, so it is refused rather than documented.\n */\nexport const buildCanonicalUpsertMutationIR = (\n query: UpsertMutationInput,\n): IRUpsertMutation => {\n assertNoExpressionFields(query.updates, query.shape.id);\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return attachCatalog({\n kind: 'upsert',\n shape: query.shape.id,\n id: query.id,\n data,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n });\n};\n\n/** Builds an IRDeleteMutation from a delete factory's internal description. */\nexport const buildCanonicalDeleteMutationIR = (\n query: DeleteMutationInput,\n): IRDeleteMutation => {\n return attachCatalog({\n kind: 'delete',\n shape: query.shape.id,\n ids: query.ids.map((id) => ({id: id.id})),\n });\n};\n\ntype DeleteAllMutationInput = {\n shape: NodeShapeData;\n};\n\n/** Builds an IRDeleteAllMutation — delete all instances of a shape type. */\nexport const buildCanonicalDeleteAllMutationIR = (\n query: DeleteAllMutationInput,\n): IRDeleteAllMutation => {\n return attachCatalog({\n kind: 'delete_all',\n shape: query.shape.id,\n });\n};\n\ntype DeleteWhereMutationInput = {\n shape: NodeShapeData;\n where: IRExpression;\n wherePatterns: IRGraphPattern[];\n};\n\n/** Builds an IRDeleteWhereMutation — delete instances matching a condition. */\nexport const buildCanonicalDeleteWhereMutationIR = (\n query: DeleteWhereMutationInput,\n): IRDeleteWhereMutation => {\n return attachCatalog({\n kind: 'delete_where',\n shape: query.shape.id,\n where: query.where,\n wherePatterns: query.wherePatterns,\n });\n};\n\ntype UpdateWhereMutationInput = {\n shape: NodeShapeData;\n updates: NodeDescriptionValue;\n where?: IRExpression;\n wherePatterns?: IRGraphPattern[];\n};\n\n/** Builds an IRUpdateWhereMutation — update instances matching a condition or all. */\nexport const buildCanonicalUpdateWhereMutationIR = (\n query: UpdateWhereMutationInput,\n): IRUpdateWhereMutation => {\n const collector = createTraversalCollector();\n const data = toNodeData(query.updates, collector);\n return attachCatalog({\n kind: 'update_where',\n shape: query.shape.id,\n data,\n where: query.where,\n wherePatterns: query.wherePatterns,\n ...(collector.patterns.length > 0\n ? {traversalPatterns: collector.patterns}\n : {}),\n });\n};\n"]}
@@ -24,7 +24,7 @@ import { isSetModificationValue, } from './QueryFactory.js';
24
24
  import { getPropertyShape } from '../shapes/nodeShapeData.js';
25
25
  import { ExpressionNode, isExpressionNode } from '../expressions/ExpressionNode.js';
26
26
  import { PendingQueryContext } from './QueryContext.js';
27
- import { getShapeClass, resolveShapeConstructor } from '../utils/ShapeClass.js';
27
+ import { resolveShapeConstructor, getQueryShapeClass } from '../utils/ShapeClass.js';
28
28
  import { encodeValueExpr, decodeValueExpr, } from './DslJsonExpression.js';
29
29
  /** Reserved node-data keys (not property labels). */
30
30
  const NODE_ID_KEY = '__id';
@@ -36,7 +36,7 @@ const NODE_SHAPE_KEY = '__shape';
36
36
  export function valueShapeOf(prop) {
37
37
  var _a, _b;
38
38
  const id = (_a = prop === null || prop === void 0 ? void 0 : prop.valueShape) === null || _a === void 0 ? void 0 : _a.id;
39
- return id ? (_b = getShapeClass(id)) === null || _b === void 0 ? void 0 : _b.shape : undefined;
39
+ return id ? (_b = getQueryShapeClass(id)) === null || _b === void 0 ? void 0 : _b.shape : undefined;
40
40
  }
41
41
  /** Encode a single (non-array, non-setMod) property value. `prop` gives the nested-node shape. */
42
42
  function encodeSingleValue(value, prop) {
@@ -1 +1 @@
1
- {"version":3,"file":"MutationSerialization.js","sourceRoot":"","sources":["../../../src/queries/MutationSerialization.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n\n/**\n * Lossless JSON (de)serialization for mutations (create / update / delete) — the\n * **IR-free wire codec**. The companion IR side (`decodeNodeData` / `lowerMutationJSON`)\n * lives in `lowerMutationJSON.ts` so this module never pulls the canonical-IR pipeline.\n *\n * The serialization unit is the normalized `NodeDescriptionValue` produced by the\n * IR-free factory base (`MutationQueryFactory.describe()`) — i.e. after `.set()` and\n * after any update-expression callback has been evaluated, but before canonical IR.\n * Property keys are serialized as **labels** (shape-relative, lightweight); decoding\n * resolves them back via the registered shape.\n *\n * Values use the DSL-JSON grammar (documentation/dsl-json.md): a bare scalar is a\n * literal; objects tag the kinds `JSON.stringify` can't represent natively\n * (`{@date}`, `{@id}`, `{@ctx}`, `{@list}`, `{@add,@remove}`, `{@unset}`); and a\n * computed value is an S-expr array via the shared `DslJsonExpression` codec —\n * so the wire carries no IR.\n */\nimport {\n type NodeDescriptionValue,\n type NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {ExpressionNode, isExpressionNode} from '../expressions/ExpressionNode.js';\nimport type {WherePathJSON} from './QueryBuilderSerialization.js';\nimport type {ContextRefJSON} from './ContextRef.js';\nimport {PendingQueryContext} from './QueryContext.js';\nimport {getShapeClass, resolveShapeConstructor} from '../utils/ShapeClass.js';\nimport type {ShapeConstructor} from '../shapes/Shape.js';\nimport type {NodeShapeData, PropertyShapeData} from '../shapes/SHACL.js';\nimport {\n encodeValueExpr,\n decodeValueExpr,\n type DslJsonValue,\n} from './DslJsonExpression.js';\n\n// =============================================================================\n// JSON types\n// =============================================================================\n\n/**\n * A mutation field value in the DSL-JSON grammar. A bare scalar is a literal; objects\n * tag the non-JSON-native kinds (`@`-sigiled); a computed value is an S-expr array (no IR); a\n * nested-node create is a bare path-keyed object ({@link MutationNodeDataJSON}),\n * disambiguated from the tagged forms by having no reserved value-key.\n */\nexport type MutationValueJSON =\n | string\n | number\n | boolean\n | null\n | {'@date': string}\n | {'@id': string}\n | {'@ctx': string}\n | {'@list': MutationValueJSON[]}\n | {'@add'?: MutationValueJSON[]; '@remove'?: string[]}\n | {'@unset': true}\n | MutationNodeDataJSON // nested-node create (bare, path-keyed)\n | DslJsonValue; // computed expression (S-expr) / {@path}\n\n/**\n * A node description in **path-keyed** form: `label → value`, plus two reserved\n * keys — `__id` (a fixed/predefined id) and `__shape` (the concrete shape IRI,\n * emitted only when it differs from the shape inferred from context, e.g. a\n * subclass instance under a superclass-typed relation). Whether a nested node is\n * written as a blank node is not on the wire: the lowering decides it from the\n * property's `sh:nodeKind`.\n */\nexport type MutationNodeDataJSON = {\n [key: string]: MutationValueJSON | undefined;\n};\n\n/** Reserved node-data keys (not property labels). */\nconst NODE_ID_KEY = '__id';\nconst NODE_SHAPE_KEY = '__shape';\n\nexport type CreateMutationJSON = {\n v?: string;\n op: 'create';\n shape: string;\n data: MutationNodeDataJSON;\n};\n\nexport type UpdateMutationJSON = {\n v?: string;\n op: 'update';\n shape: string;\n mode: 'for' | 'forAll' | 'where';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n where?: WherePathJSON;\n data: MutationNodeDataJSON;\n};\n\n/**\n * Create-or-replace against a known id.\n *\n * A distinct `op` rather than `op: 'update'` with a new `mode`. An unaware consumer that\n * received `{op: 'update', mode: 'upsert'}` would fall past its `mode === 'for'` and\n * `mode === 'where'` branches into the update-where path with no where clause — an update\n * applied to *every instance of the shape*. A distinct op instead hits `fromJSON`'s\n * existing `default:` and throws \"Unknown query op\": loud, and safe.\n */\nexport type UpsertMutationJSON = {\n v?: string;\n op: 'upsert';\n shape: string;\n /** Upsert targets one known id; there is no `forAll`/`where` form. */\n mode: 'for';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n data: MutationNodeDataJSON;\n};\n\nexport type DeleteMutationJSON =\n | {v?: string; op: 'delete'; shape: string; mode: 'ids'; ids: (string | ContextRefJSON)[]}\n | {v?: string; op: 'delete'; shape: string; mode: 'all'}\n | {v?: string; op: 'delete'; shape: string; mode: 'where'; where: WherePathJSON};\n\nexport type MutationJSON =\n | CreateMutationJSON\n | UpdateMutationJSON\n | UpsertMutationJSON\n | DeleteMutationJSON;\n\n// =============================================================================\n// Value codec\n// =============================================================================\n\n/** The shape a nested node is expected to have (a property's value shape), if resolvable. */\nexport function valueShapeOf(prop?: PropertyShapeData): NodeShapeData | undefined {\n const id = (prop as unknown as {valueShape?: {id: string}})?.valueShape?.id;\n return id ? getShapeClass(id)?.shape : undefined;\n}\n\n/** Encode a single (non-array, non-setMod) property value. `prop` gives the nested-node shape. */\nfunction encodeSingleValue(\n value: SinglePropertyUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (isExpressionNode(value)) {\n // A computed value is an S-expr (or {@path}) via the shared codec — no IR.\n return encodeValueExpr(value.ir, value._refs) as MutationValueJSON;\n }\n if (value instanceof Date) return {'@date': value.toISOString()};\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n if (value && typeof value === 'object') {\n // Query-context reference — carry the name, resolve at lowering (checked\n // before the generic `.id` branch since a PendingQueryContext has an `.id` getter).\n if (value instanceof PendingQueryContext) {\n return {'@ctx': value.contextName};\n }\n if ('fields' in value) {\n // Nested-node create — bare path-keyed; expected shape = the relation's value shape.\n return encodeNodeData(value as NodeDescriptionValue, valueShapeOf(prop));\n }\n if ('id' in value) return {'@id': (value as NodeReferenceValue).id};\n }\n throw new Error(`Cannot serialize mutation value: ${JSON.stringify(value)}`);\n}\n\n/** Encode any property value, including arrays and set modifications. */\nexport function encodeValue(\n value: PropUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (Array.isArray(value)) {\n return {'@list': value.map((v) => encodeSingleValue(v, prop))};\n }\n if (isSetModificationValue(value)) {\n const mod = value as SetModificationValue;\n const json: {'@add'?: MutationValueJSON[]; '@remove'?: string[]} = {};\n if (mod.$add) json['@add'] = mod.$add.map((v) => encodeValue(v as PropUpdateValue, prop));\n if (mod.$remove) json['@remove'] = mod.$remove.map((r) => r.id);\n return json;\n }\n return encodeSingleValue(value as SinglePropertyUpdateValue, prop);\n}\n\n/**\n * Encode a normalized node description to path-keyed form. `expectedShape` is the\n * shape inferable from context (the envelope, or the parent relation's value shape);\n * `__shape` is emitted only when the concrete shape differs (a subclass instance).\n */\nexport function encodeNodeData(\n desc: NodeDescriptionValue,\n expectedShape?: NodeShapeData,\n): MutationNodeDataJSON {\n const json: MutationNodeDataJSON = {};\n if (desc.__id) json[NODE_ID_KEY] = desc.__id;\n if (!expectedShape || desc.shape.id !== expectedShape.id) {\n json[NODE_SHAPE_KEY] = desc.shape.id;\n }\n for (const f of desc.fields) {\n json[f.prop.label] = encodeValue(f.val, f.prop);\n }\n return json;\n}\n\n// =============================================================================\n// JSON → raw UpdatePartial (for builder rehydration / fromJSON)\n// =============================================================================\n\n// Bound the DSL-JSON decode recursion (rehydration path) against a deeply-nested\n// payload exhausting the stack. Mirrors the cap in lowerMutationJSON.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value back to a raw DSL value (the form `.set()` accepts).\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueToRawInner}.\n */\nfunction decodeValueToRaw(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueToRawInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueToRawInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n // S-expr computed value\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n if (json === null) return null;\n if (typeof json !== 'object') return json; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string);\n // Rehydration path: preserve the live reference so it re-serializes as a\n // `{@ctx}` marker and resolves at the rebuilt builder's own lowering.\n if ('@ctx' in o) return new PendingQueryContext(o['@ctx'] as string);\n if ('@id' in o) return {id: o['@id']};\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n }\n if ('@add' in o || '@remove' in o) {\n // Raw DSL set-modifications use `@add`/`@remove` on the wire.\n const mod: {add?: unknown[]; remove?: {id: string}[]} = {};\n if (o['@add']) mod.add = (o['@add'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n if (o['@remove']) mod.remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod;\n }\n // A computed-path value (`{@path}`) used as a value.\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNestedNodeDataToRaw(o as MutationNodeDataJSON, valueShapeOf(prop) ?? currentShape);\n}\n\n/**\n * Decode a nested node and, when it names its concrete shape (`__shape`), carry that\n * shape as the reserved `shape` key `.set()` accepts on a nested value. Without it the\n * builders validate and lower the value against the property's declared value shape —\n * or none, for a polymorphic slot like `PropertyShape.path` — and reject the fields\n * only the concrete shape has.\n */\n/**\n * The class for a node's `__shape`. Either registry — a project-authored shape exists only\n * as metadata. Throws like `lowerMutationJSON` does, so both decode paths reject an\n * unregistered shape instead of one of them silently validating against another.\n */\nfunction requireNodeShapeClass(shapeId: string): ShapeConstructor {\n const shapeClass = resolveShapeConstructor(shapeId);\n if (!shapeClass) {\n throw new Error(\n `Shape '${shapeId}' is not registered. The receiving side must have the shape registered to decode mutation DSL-JSON.`,\n );\n }\n return shapeClass;\n}\n\nfunction decodeNestedNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape: NodeShapeData | undefined,\n): Record<string, unknown> {\n const obj = decodeNodeDataToRaw(json, shape);\n const shapeId = json[NODE_SHAPE_KEY];\n if (typeof shapeId === 'string') obj.shape = requireNodeShapeClass(shapeId);\n return obj;\n}\n\nfunction requireShapeForExpr(shape: NodeShapeData | undefined): NodeShapeData {\n if (!shape) {\n throw new Error('A shape is required to decode a computed mutation value');\n }\n return shape;\n}\n\n/**\n * Decode path-keyed node data into a raw object the mutation builders' `.set()` accepts.\n * `__id` becomes `id`; `__shape` (if present) overrides the inferred `shape`. Mirrors\n * {@link encodeNodeData}.\n */\nexport function decodeNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): Record<string, unknown> {\n const nodeShape =\n typeof json[NODE_SHAPE_KEY] === 'string'\n ? requireNodeShapeClass(json[NODE_SHAPE_KEY] as string).shape\n : shape;\n const obj: Record<string, unknown> = {};\n if (typeof json[NODE_ID_KEY] === 'string') obj.id = json[NODE_ID_KEY];\n for (const [key, val] of Object.entries(json)) {\n if (key === NODE_ID_KEY || key === NODE_SHAPE_KEY || val === undefined) continue;\n // Skip prototype-polluting keys from untrusted DSL-JSON input.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n const prop = nodeShape ? getPropertyShape(nodeShape, key) : undefined;\n obj[key] = decodeValueToRaw(val as MutationValueJSON, nodeShape, prop);\n }\n return obj;\n}\n"]}
1
+ {"version":3,"file":"MutationSerialization.js","sourceRoot":"","sources":["../../../src/queries/MutationSerialization.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at https://mozilla.org/MPL/2.0/.\n */\n\n/**\n * Lossless JSON (de)serialization for mutations (create / update / delete) — the\n * **IR-free wire codec**. The companion IR side (`decodeNodeData` / `lowerMutationJSON`)\n * lives in `lowerMutationJSON.ts` so this module never pulls the canonical-IR pipeline.\n *\n * The serialization unit is the normalized `NodeDescriptionValue` produced by the\n * IR-free factory base (`MutationQueryFactory.describe()`) — i.e. after `.set()` and\n * after any update-expression callback has been evaluated, but before canonical IR.\n * Property keys are serialized as **labels** (shape-relative, lightweight); decoding\n * resolves them back via the registered shape.\n *\n * Values use the DSL-JSON grammar (documentation/dsl-json.md): a bare scalar is a\n * literal; objects tag the kinds `JSON.stringify` can't represent natively\n * (`{@date}`, `{@id}`, `{@ctx}`, `{@list}`, `{@add,@remove}`, `{@unset}`); and a\n * computed value is an S-expr array via the shared `DslJsonExpression` codec —\n * so the wire carries no IR.\n */\nimport {\n type NodeDescriptionValue,\n type NodeReferenceValue,\n type PropUpdateValue,\n type SetModificationValue,\n type SinglePropertyUpdateValue,\n isSetModificationValue,\n} from './QueryFactory.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {ExpressionNode, isExpressionNode} from '../expressions/ExpressionNode.js';\nimport type {WherePathJSON} from './QueryBuilderSerialization.js';\nimport type {ContextRefJSON} from './ContextRef.js';\nimport {PendingQueryContext} from './QueryContext.js';\nimport {resolveShapeConstructor, getQueryShapeClass} from '../utils/ShapeClass.js';\nimport type {ShapeConstructor} from '../shapes/Shape.js';\nimport type {NodeShapeData, PropertyShapeData} from '../shapes/SHACL.js';\nimport {\n encodeValueExpr,\n decodeValueExpr,\n type DslJsonValue,\n} from './DslJsonExpression.js';\n\n// =============================================================================\n// JSON types\n// =============================================================================\n\n/**\n * A mutation field value in the DSL-JSON grammar. A bare scalar is a literal; objects\n * tag the non-JSON-native kinds (`@`-sigiled); a computed value is an S-expr array (no IR); a\n * nested-node create is a bare path-keyed object ({@link MutationNodeDataJSON}),\n * disambiguated from the tagged forms by having no reserved value-key.\n */\nexport type MutationValueJSON =\n | string\n | number\n | boolean\n | null\n | {'@date': string}\n | {'@id': string}\n | {'@ctx': string}\n | {'@list': MutationValueJSON[]}\n | {'@add'?: MutationValueJSON[]; '@remove'?: string[]}\n | {'@unset': true}\n | MutationNodeDataJSON // nested-node create (bare, path-keyed)\n | DslJsonValue; // computed expression (S-expr) / {@path}\n\n/**\n * A node description in **path-keyed** form: `label → value`, plus two reserved\n * keys — `__id` (a fixed/predefined id) and `__shape` (the concrete shape IRI,\n * emitted only when it differs from the shape inferred from context, e.g. a\n * subclass instance under a superclass-typed relation). Whether a nested node is\n * written as a blank node is not on the wire: the lowering decides it from the\n * property's `sh:nodeKind`.\n */\nexport type MutationNodeDataJSON = {\n [key: string]: MutationValueJSON | undefined;\n};\n\n/** Reserved node-data keys (not property labels). */\nconst NODE_ID_KEY = '__id';\nconst NODE_SHAPE_KEY = '__shape';\n\nexport type CreateMutationJSON = {\n v?: string;\n op: 'create';\n shape: string;\n data: MutationNodeDataJSON;\n};\n\nexport type UpdateMutationJSON = {\n v?: string;\n op: 'update';\n shape: string;\n mode: 'for' | 'forAll' | 'where';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n where?: WherePathJSON;\n data: MutationNodeDataJSON;\n};\n\n/**\n * Create-or-replace against a known id.\n *\n * A distinct `op` rather than `op: 'update'` with a new `mode`. An unaware consumer that\n * received `{op: 'update', mode: 'upsert'}` would fall past its `mode === 'for'` and\n * `mode === 'where'` branches into the update-where path with no where clause — an update\n * applied to *every instance of the shape*. A distinct op instead hits `fromJSON`'s\n * existing `default:` and throws \"Unknown query op\": loud, and safe.\n */\nexport type UpsertMutationJSON = {\n v?: string;\n op: 'upsert';\n shape: string;\n /** Upsert targets one known id; there is no `forAll`/`where` form. */\n mode: 'for';\n /** A node id, or a `{@ctx: name}` context reference resolved at lowering. */\n targetId?: string | ContextRefJSON;\n data: MutationNodeDataJSON;\n};\n\nexport type DeleteMutationJSON =\n | {v?: string; op: 'delete'; shape: string; mode: 'ids'; ids: (string | ContextRefJSON)[]}\n | {v?: string; op: 'delete'; shape: string; mode: 'all'}\n | {v?: string; op: 'delete'; shape: string; mode: 'where'; where: WherePathJSON};\n\nexport type MutationJSON =\n | CreateMutationJSON\n | UpdateMutationJSON\n | UpsertMutationJSON\n | DeleteMutationJSON;\n\n// =============================================================================\n// Value codec\n// =============================================================================\n\n/** The shape a nested node is expected to have (a property's value shape), if resolvable. */\nexport function valueShapeOf(prop?: PropertyShapeData): NodeShapeData | undefined {\n const id = (prop as unknown as {valueShape?: {id: string}})?.valueShape?.id;\n return id ? getQueryShapeClass(id)?.shape : undefined;\n}\n\n/** Encode a single (non-array, non-setMod) property value. `prop` gives the nested-node shape. */\nfunction encodeSingleValue(\n value: SinglePropertyUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (isExpressionNode(value)) {\n // A computed value is an S-expr (or {@path}) via the shared codec — no IR.\n return encodeValueExpr(value.ir, value._refs) as MutationValueJSON;\n }\n if (value instanceof Date) return {'@date': value.toISOString()};\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n if (value && typeof value === 'object') {\n // Query-context reference — carry the name, resolve at lowering (checked\n // before the generic `.id` branch since a PendingQueryContext has an `.id` getter).\n if (value instanceof PendingQueryContext) {\n return {'@ctx': value.contextName};\n }\n if ('fields' in value) {\n // Nested-node create — bare path-keyed; expected shape = the relation's value shape.\n return encodeNodeData(value as NodeDescriptionValue, valueShapeOf(prop));\n }\n if ('id' in value) return {'@id': (value as NodeReferenceValue).id};\n }\n throw new Error(`Cannot serialize mutation value: ${JSON.stringify(value)}`);\n}\n\n/** Encode any property value, including arrays and set modifications. */\nexport function encodeValue(\n value: PropUpdateValue,\n prop?: PropertyShapeData,\n): MutationValueJSON {\n if (value === undefined) return {'@unset': true};\n if (Array.isArray(value)) {\n return {'@list': value.map((v) => encodeSingleValue(v, prop))};\n }\n if (isSetModificationValue(value)) {\n const mod = value as SetModificationValue;\n const json: {'@add'?: MutationValueJSON[]; '@remove'?: string[]} = {};\n if (mod.$add) json['@add'] = mod.$add.map((v) => encodeValue(v as PropUpdateValue, prop));\n if (mod.$remove) json['@remove'] = mod.$remove.map((r) => r.id);\n return json;\n }\n return encodeSingleValue(value as SinglePropertyUpdateValue, prop);\n}\n\n/**\n * Encode a normalized node description to path-keyed form. `expectedShape` is the\n * shape inferable from context (the envelope, or the parent relation's value shape);\n * `__shape` is emitted only when the concrete shape differs (a subclass instance).\n */\nexport function encodeNodeData(\n desc: NodeDescriptionValue,\n expectedShape?: NodeShapeData,\n): MutationNodeDataJSON {\n const json: MutationNodeDataJSON = {};\n if (desc.__id) json[NODE_ID_KEY] = desc.__id;\n if (!expectedShape || desc.shape.id !== expectedShape.id) {\n json[NODE_SHAPE_KEY] = desc.shape.id;\n }\n for (const f of desc.fields) {\n json[f.prop.label] = encodeValue(f.val, f.prop);\n }\n return json;\n}\n\n// =============================================================================\n// JSON → raw UpdatePartial (for builder rehydration / fromJSON)\n// =============================================================================\n\n// Bound the DSL-JSON decode recursion (rehydration path) against a deeply-nested\n// payload exhausting the stack. Mirrors the cap in lowerMutationJSON.\nconst MAX_DECODE_DEPTH = 128;\nlet _decodeDepth = 0;\n\n/**\n * Decode a DSL-JSON value back to a raw DSL value (the form `.set()` accepts).\n * `currentShape` resolves computed `{@path}`/S-expr; `prop` gives a nested node's shape.\n * Depth-guarded wrapper around {@link decodeValueToRawInner}.\n */\nfunction decodeValueToRaw(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n if (++_decodeDepth > MAX_DECODE_DEPTH) {\n _decodeDepth = 0;\n throw new Error('DSL-JSON value nested too deeply');\n }\n try {\n return decodeValueToRawInner(json, currentShape, prop);\n } finally {\n _decodeDepth--;\n }\n}\n\nfunction decodeValueToRawInner(\n json: MutationValueJSON,\n currentShape: NodeShapeData | undefined,\n prop?: PropertyShapeData,\n): unknown {\n // S-expr computed value\n if (Array.isArray(json)) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n if (json === null) return null;\n if (typeof json !== 'object') return json; // bare scalar literal\n const o = json as Record<string, unknown>;\n if ('@unset' in o) return undefined;\n if ('@date' in o) return new Date(o['@date'] as string);\n // Rehydration path: preserve the live reference so it re-serializes as a\n // `{@ctx}` marker and resolves at the rebuilt builder's own lowering.\n if ('@ctx' in o) return new PendingQueryContext(o['@ctx'] as string);\n if ('@id' in o) return {id: o['@id']};\n if ('@list' in o) {\n return (o['@list'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n }\n if ('@add' in o || '@remove' in o) {\n // Raw DSL set-modifications use `@add`/`@remove` on the wire.\n const mod: {add?: unknown[]; remove?: {id: string}[]} = {};\n if (o['@add']) mod.add = (o['@add'] as MutationValueJSON[]).map((i) => decodeValueToRaw(i, currentShape, prop));\n if (o['@remove']) mod.remove = (o['@remove'] as string[]).map((id) => ({id}));\n return mod;\n }\n // A computed-path value (`{@path}`) used as a value.\n if ('@path' in o) {\n const {ir, refs} = decodeValueExpr(json as DslJsonValue, requireShapeForExpr(currentShape));\n return new ExpressionNode(ir, refs);\n }\n // Otherwise: a bare path-keyed nested-node create.\n return decodeNestedNodeDataToRaw(o as MutationNodeDataJSON, valueShapeOf(prop) ?? currentShape);\n}\n\n/**\n * Decode a nested node and, when it names its concrete shape (`__shape`), carry that\n * shape as the reserved `shape` key `.set()` accepts on a nested value. Without it the\n * builders validate and lower the value against the property's declared value shape —\n * or none, for a polymorphic slot like `PropertyShape.path` — and reject the fields\n * only the concrete shape has.\n */\n/**\n * The class for a node's `__shape`. Either registry — a project-authored shape exists only\n * as metadata. Throws like `lowerMutationJSON` does, so both decode paths reject an\n * unregistered shape instead of one of them silently validating against another.\n */\nfunction requireNodeShapeClass(shapeId: string): ShapeConstructor {\n const shapeClass = resolveShapeConstructor(shapeId);\n if (!shapeClass) {\n throw new Error(\n `Shape '${shapeId}' is not registered. The receiving side must have the shape registered to decode mutation DSL-JSON.`,\n );\n }\n return shapeClass;\n}\n\nfunction decodeNestedNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape: NodeShapeData | undefined,\n): Record<string, unknown> {\n const obj = decodeNodeDataToRaw(json, shape);\n const shapeId = json[NODE_SHAPE_KEY];\n if (typeof shapeId === 'string') obj.shape = requireNodeShapeClass(shapeId);\n return obj;\n}\n\nfunction requireShapeForExpr(shape: NodeShapeData | undefined): NodeShapeData {\n if (!shape) {\n throw new Error('A shape is required to decode a computed mutation value');\n }\n return shape;\n}\n\n/**\n * Decode path-keyed node data into a raw object the mutation builders' `.set()` accepts.\n * `__id` becomes `id`; `__shape` (if present) overrides the inferred `shape`. Mirrors\n * {@link encodeNodeData}.\n */\nexport function decodeNodeDataToRaw(\n json: MutationNodeDataJSON,\n shape?: NodeShapeData,\n): Record<string, unknown> {\n const nodeShape =\n typeof json[NODE_SHAPE_KEY] === 'string'\n ? requireNodeShapeClass(json[NODE_SHAPE_KEY] as string).shape\n : shape;\n const obj: Record<string, unknown> = {};\n if (typeof json[NODE_ID_KEY] === 'string') obj.id = json[NODE_ID_KEY];\n for (const [key, val] of Object.entries(json)) {\n if (key === NODE_ID_KEY || key === NODE_SHAPE_KEY || val === undefined) continue;\n // Skip prototype-polluting keys from untrusted DSL-JSON input.\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n const prop = nodeShape ? getPropertyShape(nodeShape, key) : undefined;\n obj[key] = decodeValueToRaw(val as MutationValueJSON, nodeShape, prop);\n }\n return obj;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { getPropertyShape } from '../shapes/nodeShapeData.js';
2
- import { getShapeClass } from '../utils/ShapeClass.js';
2
+ import { getQueryShapeClass } from '../utils/ShapeClass.js';
3
3
  /**
4
4
  * A value object representing a sequence of property traversals from a root shape.
5
5
  *
@@ -66,7 +66,7 @@ export function walkPropertyPath(shape, path) {
66
66
  if (!propertyShape.valueShape) {
67
67
  throw new Error(`Property '${label}' on shape '${currentShape.label || currentShape.id}' has no valueShape; cannot traverse further in path '${path}'`);
68
68
  }
69
- const shapeClass = getShapeClass(propertyShape.valueShape);
69
+ const shapeClass = getQueryShapeClass(propertyShape.valueShape);
70
70
  if (!shapeClass || !shapeClass.shape) {
71
71
  throw new Error(`Cannot resolve valueShape '${propertyShape.valueShape.id}' for property '${label}' in path '${path}'`);
72
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PropertyPath.js","sourceRoot":"","sources":["../../../src/queries/PropertyPath.ts"],"names":[],"mappings":"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","sourcesContent":["import type {PropertyShapeData, NodeShapeData} from '../shapes/SHACL.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {getShapeClass} from '../utils/ShapeClass.js';\n\n/**\n * A value object representing a sequence of property traversals from a root shape.\n *\n * Each segment is a PropertyShapeData representing one hop in the traversal.\n * For example, `friends.name` on PersonShape produces a PropertyPath with\n * two segments: [friendsPropertyShape, namePropertyShape].\n *\n * This is used by FieldSet and QueryBuilder to describe which properties\n * to select/filter, independent of proxy tracing.\n */\nexport class PropertyPath {\n constructor(\n readonly rootShape: NodeShapeData,\n readonly segments: readonly PropertyShapeData[],\n ) {}\n\n /** Append a property traversal hop, returning a new PropertyPath. */\n prop(property: PropertyShapeData): PropertyPath {\n return new PropertyPath(this.rootShape, [...this.segments, property]);\n }\n\n /** The terminal (leaf) property of this path. */\n get terminal(): PropertyShapeData | undefined {\n return this.segments[this.segments.length - 1];\n }\n\n /** The depth (number of hops) of this path. */\n get depth(): number {\n return this.segments.length;\n }\n\n /** String representation using property labels joined by dots. */\n toString(): string {\n return this.segments.map((s) => s.label).join('.');\n }\n\n /** Two PropertyPaths are equal if they have the same root shape and same segment sequence. */\n equals(other: PropertyPath): boolean {\n if (this.rootShape.id !== other.rootShape.id) return false;\n if (this.segments.length !== other.segments.length) return false;\n return this.segments.every((s, i) => s.id === other.segments[i].id);\n }\n}\n\n/**\n * Resolve a dot-separated property path string into a PropertyPath.\n *\n * Walks the shape's property shapes by label, following valueShape references\n * to traverse into nested shapes.\n *\n * Example: `walkPropertyPath(PersonShape, 'friends.name')` resolves\n * [friendsPropertyShape, namePropertyShape].\n *\n * @throws If any segment cannot be resolved.\n */\nexport function walkPropertyPath(shape: NodeShapeData, path: string): PropertyPath {\n const labels = path.split('.');\n const segments: PropertyShapeData[] = [];\n let currentShape = shape;\n\n for (const label of labels) {\n const propertyShape = getPropertyShape(currentShape, label);\n if (!propertyShape) {\n throw new Error(\n `Property '${label}' not found on shape '${currentShape.label || currentShape.id}' while resolving path '${path}'`,\n );\n }\n segments.push(propertyShape);\n\n // If there are more segments to resolve, follow the valueShape\n if (segments.length < labels.length) {\n if (!propertyShape.valueShape) {\n throw new Error(\n `Property '${label}' on shape '${currentShape.label || currentShape.id}' has no valueShape; cannot traverse further in path '${path}'`,\n );\n }\n const shapeClass = getShapeClass(propertyShape.valueShape);\n if (!shapeClass || !shapeClass.shape) {\n throw new Error(\n `Cannot resolve valueShape '${propertyShape.valueShape.id}' for property '${label}' in path '${path}'`,\n );\n }\n currentShape = shapeClass.shape;\n }\n }\n\n return new PropertyPath(shape, segments);\n}\n"]}
1
+ {"version":3,"file":"PropertyPath.js","sourceRoot":"","sources":["../../../src/queries/PropertyPath.ts"],"names":[],"mappings":"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","sourcesContent":["import type {PropertyShapeData, NodeShapeData} from '../shapes/SHACL.js';\nimport {getPropertyShape} from '../shapes/nodeShapeData.js';\nimport {getQueryShapeClass} from '../utils/ShapeClass.js';\n\n/**\n * A value object representing a sequence of property traversals from a root shape.\n *\n * Each segment is a PropertyShapeData representing one hop in the traversal.\n * For example, `friends.name` on PersonShape produces a PropertyPath with\n * two segments: [friendsPropertyShape, namePropertyShape].\n *\n * This is used by FieldSet and QueryBuilder to describe which properties\n * to select/filter, independent of proxy tracing.\n */\nexport class PropertyPath {\n constructor(\n readonly rootShape: NodeShapeData,\n readonly segments: readonly PropertyShapeData[],\n ) {}\n\n /** Append a property traversal hop, returning a new PropertyPath. */\n prop(property: PropertyShapeData): PropertyPath {\n return new PropertyPath(this.rootShape, [...this.segments, property]);\n }\n\n /** The terminal (leaf) property of this path. */\n get terminal(): PropertyShapeData | undefined {\n return this.segments[this.segments.length - 1];\n }\n\n /** The depth (number of hops) of this path. */\n get depth(): number {\n return this.segments.length;\n }\n\n /** String representation using property labels joined by dots. */\n toString(): string {\n return this.segments.map((s) => s.label).join('.');\n }\n\n /** Two PropertyPaths are equal if they have the same root shape and same segment sequence. */\n equals(other: PropertyPath): boolean {\n if (this.rootShape.id !== other.rootShape.id) return false;\n if (this.segments.length !== other.segments.length) return false;\n return this.segments.every((s, i) => s.id === other.segments[i].id);\n }\n}\n\n/**\n * Resolve a dot-separated property path string into a PropertyPath.\n *\n * Walks the shape's property shapes by label, following valueShape references\n * to traverse into nested shapes.\n *\n * Example: `walkPropertyPath(PersonShape, 'friends.name')` resolves\n * [friendsPropertyShape, namePropertyShape].\n *\n * @throws If any segment cannot be resolved.\n */\nexport function walkPropertyPath(shape: NodeShapeData, path: string): PropertyPath {\n const labels = path.split('.');\n const segments: PropertyShapeData[] = [];\n let currentShape = shape;\n\n for (const label of labels) {\n const propertyShape = getPropertyShape(currentShape, label);\n if (!propertyShape) {\n throw new Error(\n `Property '${label}' not found on shape '${currentShape.label || currentShape.id}' while resolving path '${path}'`,\n );\n }\n segments.push(propertyShape);\n\n // If there are more segments to resolve, follow the valueShape\n if (segments.length < labels.length) {\n if (!propertyShape.valueShape) {\n throw new Error(\n `Property '${label}' on shape '${currentShape.label || currentShape.id}' has no valueShape; cannot traverse further in path '${path}'`,\n );\n }\n const shapeClass = getQueryShapeClass(propertyShape.valueShape);\n if (!shapeClass || !shapeClass.shape) {\n throw new Error(\n `Cannot resolve valueShape '${propertyShape.valueShape.id}' for property '${label}' in path '${path}'`,\n );\n }\n currentShape = shapeClass.shape;\n }\n }\n\n return new PropertyPath(shape, segments);\n}\n"]}
@@ -9,6 +9,7 @@ import { FieldSet, type FieldSetFieldJSON } from './FieldSet.js';
9
9
  import { PendingQueryContext } from './QueryContext.js';
10
10
  import { type ContextRefJSON } from './ContextRef.js';
11
11
  import { type WherePathJSON, type SortByPathJSON, type RawMinusEntryJSON } from './QueryBuilderSerialization.js';
12
+ import type { ShapeCatalog } from '../utils/ShapeCatalog.js';
12
13
  import type { LiveListener, LiveQuery, LiveQueryOptions } from '../live/LiveQueryStore.js';
13
14
  /** JSON representation of a SelectBuilder. */
14
15
  export type QueryBuilderJSON = {
@@ -62,6 +63,7 @@ export declare class SelectBuilder<S extends Shape = Shape, R = any, Result = an
62
63
  private readonly _where?;
63
64
  private readonly _sortBy?;
64
65
  private readonly _rawMinusEntries?;
66
+ private readonly _catalog;
65
67
  private constructor();
66
68
  /** Create a shallow clone with overrides. */
67
69
  private clone;
@@ -307,6 +309,11 @@ export declare class SelectBuilder<S extends Shape = Shape, R = any, Result = an
307
309
  readonly __queryKind: "select";
308
310
  /** The shape this query targets — the routing key datasets/`LinkedStorage` use. */
309
311
  get shape(): NodeShapeData;
312
+ /**
313
+ * The catalog this builder resolves shapes in — captured when it was built, kept by
314
+ * every derived builder. Undefined = the global registry. Never serialized.
315
+ */
316
+ get catalog(): ShapeCatalog | undefined;
310
317
  /**
311
318
  * Execute the query and return results.
312
319
  *