@_linked/core 2.28.4 → 2.30.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 (59) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +131 -1
  3. package/lib/esm/index.d.ts +1 -0
  4. package/lib/esm/index.js +1 -0
  5. package/lib/esm/index.js.map +1 -1
  6. package/lib/esm/ontologies/linked-core.d.ts +2 -0
  7. package/lib/esm/ontologies/linked-core.js +10 -0
  8. package/lib/esm/ontologies/linked-core.js.map +1 -1
  9. package/lib/esm/ontologies/shacl.d.ts +1 -0
  10. package/lib/esm/ontologies/shacl.js +2 -0
  11. package/lib/esm/ontologies/shacl.js.map +1 -1
  12. package/lib/esm/queries/IRMutation.js +1 -1
  13. package/lib/esm/queries/IRMutation.js.map +1 -1
  14. package/lib/esm/queries/IntermediateRepresentation.d.ts +5 -0
  15. package/lib/esm/queries/IntermediateRepresentation.js.map +1 -1
  16. package/lib/esm/queries/MutationQuery.js +15 -0
  17. package/lib/esm/queries/MutationQuery.js.map +1 -1
  18. package/lib/esm/queries/MutationSerialization.d.ts +5 -4
  19. package/lib/esm/queries/MutationSerialization.js +9 -1
  20. package/lib/esm/queries/MutationSerialization.js.map +1 -1
  21. package/lib/esm/queries/QueryFactory.d.ts +6 -0
  22. package/lib/esm/queries/QueryFactory.js.map +1 -1
  23. package/lib/esm/queries/SelectQuery.js +3 -1
  24. package/lib/esm/queries/SelectQuery.js.map +1 -1
  25. package/lib/esm/queries/lowerMutationJSON.js +6 -1
  26. package/lib/esm/queries/lowerMutationJSON.js.map +1 -1
  27. package/lib/esm/shapes/List.d.ts +1 -0
  28. package/lib/esm/shapes/List.js.map +1 -1
  29. package/lib/esm/shapes/PathNode.d.ts +5 -2
  30. package/lib/esm/shapes/PathNode.js +5 -2
  31. package/lib/esm/shapes/PathNode.js.map +1 -1
  32. package/lib/esm/shapes/SHACL.d.ts +15 -2
  33. package/lib/esm/shapes/SHACL.js.map +1 -1
  34. package/lib/esm/shapes/serializePathToNodeData.d.ts +17 -5
  35. package/lib/esm/shapes/serializePathToNodeData.js +41 -27
  36. package/lib/esm/shapes/serializePathToNodeData.js.map +1 -1
  37. package/lib/esm/shapes/singleOwnerConstraint.d.ts +27 -0
  38. package/lib/esm/shapes/singleOwnerConstraint.js +89 -0
  39. package/lib/esm/shapes/singleOwnerConstraint.js.map +1 -0
  40. package/lib/esm/shapes/syncShapes.js +49 -10
  41. package/lib/esm/shapes/syncShapes.js.map +1 -1
  42. package/lib/esm/shapes/validation.js +2 -2
  43. package/lib/esm/shapes/validation.js.map +1 -1
  44. package/lib/esm/sparql/SparqlAlgebra.d.ts +5 -0
  45. package/lib/esm/sparql/SparqlAlgebra.js.map +1 -1
  46. package/lib/esm/sparql/SparqlDataset.d.ts +9 -1
  47. package/lib/esm/sparql/SparqlDataset.js +19 -0
  48. package/lib/esm/sparql/SparqlDataset.js.map +1 -1
  49. package/lib/esm/sparql/algebraToString.js +2 -0
  50. package/lib/esm/sparql/algebraToString.js.map +1 -1
  51. package/lib/esm/sparql/irToAlgebra.d.ts +34 -6
  52. package/lib/esm/sparql/irToAlgebra.js +384 -59
  53. package/lib/esm/sparql/irToAlgebra.js.map +1 -1
  54. package/lib/esm/sparql/ownedLinkCheck.d.ts +50 -0
  55. package/lib/esm/sparql/ownedLinkCheck.js +142 -0
  56. package/lib/esm/sparql/ownedLinkCheck.js.map +1 -0
  57. package/lib/esm/utils/Package.js +8 -0
  58. package/lib/esm/utils/Package.js.map +1 -1
  59. package/package.json +2 -2
@@ -11,6 +11,7 @@ import { selectToSparql, askToSparql, countToSparql, createToSparql, updateToSpa
11
11
  import { mapSparqlSelectResult, mapSparqlAskResult, mapSparqlCountResult, mapSparqlCreateResult, mapSparqlUpdateResult, isSparqlSelectResults, } from './resultMapping.js';
12
12
  import { generateEntityUri } from './sparqlUtils.js';
13
13
  import { lower } from '../queries/lower.js';
14
+ import { assertOwnedLinkTypes, collectOwnedLinks, ownedLinkTypesFromResults, ownedLinkTypesQuery, } from './ownedLinkCheck.js';
14
15
  /**
15
16
  * Abstract base class for SPARQL-backed datasets.
16
17
  *
@@ -84,6 +85,7 @@ export class SparqlDataset {
84
85
  const ir = lower(query);
85
86
  const uri = ir.data.id || generateEntityUri(ir.data.shape, this.options);
86
87
  ir.data.id = uri;
88
+ yield this.checkOwnedLinks(ir);
87
89
  const sparql = createToSparql(ir, this.options);
88
90
  yield this.executeSparqlUpdate(sparql);
89
91
  return mapSparqlCreateResult(uri, ir);
@@ -92,6 +94,7 @@ export class SparqlDataset {
92
94
  updateQuery(query) {
93
95
  return __awaiter(this, void 0, void 0, function* () {
94
96
  const ir = lower(query);
97
+ yield this.checkOwnedLinks(ir);
95
98
  if (ir.kind === 'update_where') {
96
99
  const sparql = updateWhereToSparql(ir, this.options);
97
100
  yield this.executeSparqlUpdate(sparql);
@@ -104,6 +107,22 @@ export class SparqlDataset {
104
107
  return mapSparqlUpdateResult(ir);
105
108
  });
106
109
  }
110
+ /**
111
+ * Refuse a mutation that links a node of the wrong class into a `contains` property
112
+ * (see `ownedLinkCheck.ts`). An owner deletes what it contains, so a Person linked into
113
+ * an ImageObject slot would be deleted with its owner. Runs before the update is sent, so
114
+ * a refused mutation writes nothing. With no such link no query is sent; otherwise one
115
+ * SELECT covers every linked id.
116
+ */
117
+ checkOwnedLinks(ir) {
118
+ return __awaiter(this, void 0, void 0, function* () {
119
+ const links = collectOwnedLinks(ir);
120
+ if (links.length === 0)
121
+ return;
122
+ const json = yield this.executeSparqlSelect(ownedLinkTypesQuery(links.map((link) => link.id)));
123
+ assertOwnedLinkTypes(links, ownedLinkTypesFromResults(json));
124
+ });
125
+ }
107
126
  deleteQuery(query) {
108
127
  return __awaiter(this, void 0, void 0, function* () {
109
128
  const ir = lower(query);
@@ -1 +1 @@
1
- {"version":3,"file":"SparqlDataset.js","sourceRoot":"","sources":["../../../src/sparql/SparqlDataset.ts"],"names":[],"mappings":"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","sourcesContent":["import type {IDataset} from '../interfaces/IDataset.js';\nimport type {SelectQuery} from '../queries/SelectQuery.js';\nimport type {AskQuery} from '../queries/AskQuery.js';\nimport type {CountQuery} from '../queries/CountQuery.js';\nimport type {CreateQuery} from '../queries/CreateQuery.js';\nimport type {UpdateQuery} from '../queries/UpdateQuery.js';\nimport type {DeleteQuery, DeleteResponse} from '../queries/DeleteQuery.js';\nimport type {\n IRSelectQuery,\n IRCountQuery,\n SelectResult,\n CreateResult,\n UpdateResult,\n} from '../queries/IntermediateRepresentation.js';\nimport type {SparqlQueryResults} from './resultMapping.js';\nimport {\n selectToSparql,\n askToSparql,\n countToSparql,\n createToSparql,\n updateToSparql,\n upsertToSparql,\n updateWhereToSparql,\n deleteToSparql,\n deleteAllToSparql,\n deleteWhereToSparql,\n} from './irToAlgebra.js';\nimport {\n mapSparqlSelectResult,\n mapSparqlAskResult,\n mapSparqlCountResult,\n mapSparqlCreateResult,\n mapSparqlUpdateResult,\n isSparqlSelectResults,\n} from './resultMapping.js';\nimport {generateEntityUri, type SparqlOptions} from './sparqlUtils.js';\nimport {lower} from '../queries/lower.js';\n\n/**\n * Abstract base class for SPARQL-backed datasets.\n *\n * Handles the full pipeline: IR query → SPARQL string → execute → map results.\n * Subclasses only need to implement the two transport methods:\n * - `executeSparqlSelect` — send a SPARQL SELECT and return JSON results\n * - `executeSparqlUpdate` — send a SPARQL UPDATE (INSERT DATA / DELETE..INSERT / etc.)\n *\n * Example subclass (Fuseki):\n * ```ts\n * class FusekiDataset extends SparqlDataset {\n * constructor(baseUrl: string, dataset: string) {\n * super({ dataRoot: 'http://data.example.org' });\n * this.queryEndpoint = `${baseUrl}/${dataset}/sparql`;\n * this.updateEndpoint = `${baseUrl}/${dataset}/update`;\n * }\n * protected async executeSparqlSelect(sparql: string) {\n * const res = await fetch(this.queryEndpoint, { ... });\n * return res.json();\n * }\n * protected async executeSparqlUpdate(sparql: string) {\n * await fetch(this.updateEndpoint, { ... });\n * }\n * }\n * ```\n */\nexport abstract class SparqlDataset implements IDataset {\n protected options?: SparqlOptions;\n\n constructor(options?: SparqlOptions) {\n this.options = options;\n }\n\n /**\n * Send a SPARQL SELECT/ASK/CONSTRUCT query and return the parsed\n * SPARQL JSON Results (application/sparql-results+json).\n *\n * The return type is the union of both response shapes a query endpoint can\n * produce: a SELECT result set (`results.bindings`) or an ASK answer\n * (`boolean`). A subclass may still declare the narrower `SparqlJsonResults` —\n * a return type is covariant, so existing implementations stay valid.\n */\n protected abstract executeSparqlSelect(\n sparql: string,\n ): Promise<SparqlQueryResults>;\n\n /**\n * Send a SPARQL UPDATE request (INSERT DATA, DELETE/INSERT, etc.).\n * No return value — the update is fire-and-forget at the SPARQL level.\n */\n protected abstract executeSparqlUpdate(sparql: string): Promise<void>;\n\n /**\n * Answer a select query — **and a count, which is a select.**\n *\n * A count is not a distinct query form the way an ask is. An ask really is\n * `ASK WHERE { … }` and needs its own method; a count is\n * `SELECT (COUNT(DISTINCT ?a0) AS ?count) WHERE { … }` — the same query form, the\n * same transport (`executeSparqlSelect`), the same result-set response, differing\n * only in its projection. `countToAlgebra` says so itself: it builds its plan by\n * calling `selectToAlgebra` and swapping the projection, and yields\n * `{type: 'select'}`.\n *\n * So a count rides this channel rather than a method of its own. That is not\n * tidiness: it is what lets a count reach a store through every router that\n * already forwards a select — `LinkedStorage.selectQuery`, a backend API store —\n * with no per-kind plumbing to add in each of them, and no optional `IDataset`\n * member that a third-party store silently lacks.\n *\n * The branch is on the LOWERED IR, as `updateQuery` and `deleteQuery` branch on\n * theirs: `lower()` is the one place that knows a count from a select, and a\n * rehydrated envelope (`fromJSON`) arrives here as a builder like any other.\n *\n * A count carries only a pattern, so there is nothing to normalise away on that\n * path: no projection, no ordering, and in particular no `LIMIT`/`OFFSET`, which\n * the builder dropped before the query ever reached the IR. Errors reject; a count\n * failure is never reported as `0`.\n */\n selectQuery(query: SelectQuery): Promise<SelectResult>;\n selectQuery(query: CountQuery): Promise<number>;\n async selectQuery(\n query: SelectQuery | CountQuery,\n ): Promise<SelectResult | number> {\n // Cast once for the call rather than lowering in each branch: `lower` is\n // overloaded per query kind and cannot resolve a union, and lowering twice\n // would be the thing this method most needs not to do.\n const ir = lower(query as SelectQuery) as IRSelectQuery | IRCountQuery;\n if (ir.kind === 'count') {\n const sparql = countToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n // `mapSparqlCountResult` is strict in the same way the guard below is: it\n // refuses an ASK response, an empty result set and a non-integer binding\n // rather than answering `0`.\n return mapSparqlCountResult(json, ir);\n }\n const sparql = selectToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n if (!isSparqlSelectResults(json)) {\n throw new Error(\n 'Expected a SPARQL SELECT result set, got an ASK response. The endpoint ' +\n 'did not answer the SELECT query that was sent.',\n );\n }\n return mapSparqlSelectResult(json, ir);\n }\n\n /**\n * Answer an ask query — emitted as `ASK WHERE { … }`.\n *\n * An {@link AskQuery} carries only a pattern, so there is nothing to normalise\n * away here. A query with no shape lowers to `ASK { <iri> ?p ?o }` — existence\n * of the node under any type or none. Errors reject; never reported as `false`.\n */\n async askQuery(query: AskQuery): Promise<boolean> {\n const ir = lower(query);\n const sparql = askToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n return mapSparqlAskResult(json);\n }\n\n async createQuery(query: CreateQuery): Promise<CreateResult> {\n const ir = lower(query);\n const uri = ir.data.id || generateEntityUri(ir.data.shape, this.options);\n ir.data.id = uri;\n const sparql = createToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return mapSparqlCreateResult(uri, ir);\n }\n\n async updateQuery(query: UpdateQuery): Promise<UpdateResult> {\n const ir = lower(query);\n if (ir.kind === 'update_where') {\n const sparql = updateWhereToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {id: ''} as UpdateResult;\n }\n const sparql =\n ir.kind === 'upsert'\n ? upsertToSparql(ir, this.options)\n : updateToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return mapSparqlUpdateResult(ir);\n }\n\n async deleteQuery(query: DeleteQuery): Promise<DeleteResponse> {\n const ir = lower(query);\n if (ir.kind === 'delete_all') {\n const sparql = deleteAllToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {deleted: [], count: 0};\n }\n if (ir.kind === 'delete_where') {\n const sparql = deleteWhereToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {deleted: [], count: 0};\n }\n const sparql = deleteToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {\n deleted: ir.ids,\n count: ir.ids.length,\n };\n }\n\n /**\n * Execute a raw SPARQL query string directly against the dataset.\n * Defaults to SELECT; pass `'update'` for INSERT/DELETE operations.\n */\n async rawQuery(\n sparql: string,\n mode?: 'query' | 'update',\n ): Promise<SparqlQueryResults | void> {\n if (mode === 'update') {\n return this.executeSparqlUpdate(sparql);\n }\n return this.executeSparqlSelect(sparql);\n }\n}\n\n// Backwards-compatibility re-export — remove once all consumers are updated.\nexport {SparqlDataset as SparqlStore};\n"]}
1
+ {"version":3,"file":"SparqlDataset.js","sourceRoot":"","sources":["../../../src/sparql/SparqlDataset.ts"],"names":[],"mappings":"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","sourcesContent":["import type {IDataset} from '../interfaces/IDataset.js';\nimport type {SelectQuery} from '../queries/SelectQuery.js';\nimport type {AskQuery} from '../queries/AskQuery.js';\nimport type {CountQuery} from '../queries/CountQuery.js';\nimport type {CreateQuery} from '../queries/CreateQuery.js';\nimport type {UpdateQuery} from '../queries/UpdateQuery.js';\nimport type {DeleteQuery, DeleteResponse} from '../queries/DeleteQuery.js';\nimport type {\n IRSelectQuery,\n IRCountQuery,\n IRCreateMutation,\n IRUpdateMutation,\n IRUpdateWhereMutation,\n IRUpsertMutation,\n SelectResult,\n CreateResult,\n UpdateResult,\n} from '../queries/IntermediateRepresentation.js';\nimport type {SparqlQueryResults} from './resultMapping.js';\nimport {\n selectToSparql,\n askToSparql,\n countToSparql,\n createToSparql,\n updateToSparql,\n upsertToSparql,\n updateWhereToSparql,\n deleteToSparql,\n deleteAllToSparql,\n deleteWhereToSparql,\n} from './irToAlgebra.js';\nimport {\n mapSparqlSelectResult,\n mapSparqlAskResult,\n mapSparqlCountResult,\n mapSparqlCreateResult,\n mapSparqlUpdateResult,\n isSparqlSelectResults,\n} from './resultMapping.js';\nimport {generateEntityUri, type SparqlOptions} from './sparqlUtils.js';\nimport {lower} from '../queries/lower.js';\nimport {\n assertOwnedLinkTypes,\n collectOwnedLinks,\n ownedLinkTypesFromResults,\n ownedLinkTypesQuery,\n} from './ownedLinkCheck.js';\n\n/**\n * Abstract base class for SPARQL-backed datasets.\n *\n * Handles the full pipeline: IR query → SPARQL string → execute → map results.\n * Subclasses only need to implement the two transport methods:\n * - `executeSparqlSelect` — send a SPARQL SELECT and return JSON results\n * - `executeSparqlUpdate` — send a SPARQL UPDATE (INSERT DATA / DELETE..INSERT / etc.)\n *\n * Example subclass (Fuseki):\n * ```ts\n * class FusekiDataset extends SparqlDataset {\n * constructor(baseUrl: string, dataset: string) {\n * super({ dataRoot: 'http://data.example.org' });\n * this.queryEndpoint = `${baseUrl}/${dataset}/sparql`;\n * this.updateEndpoint = `${baseUrl}/${dataset}/update`;\n * }\n * protected async executeSparqlSelect(sparql: string) {\n * const res = await fetch(this.queryEndpoint, { ... });\n * return res.json();\n * }\n * protected async executeSparqlUpdate(sparql: string) {\n * await fetch(this.updateEndpoint, { ... });\n * }\n * }\n * ```\n */\nexport abstract class SparqlDataset implements IDataset {\n protected options?: SparqlOptions;\n\n constructor(options?: SparqlOptions) {\n this.options = options;\n }\n\n /**\n * Send a SPARQL SELECT/ASK/CONSTRUCT query and return the parsed\n * SPARQL JSON Results (application/sparql-results+json).\n *\n * The return type is the union of both response shapes a query endpoint can\n * produce: a SELECT result set (`results.bindings`) or an ASK answer\n * (`boolean`). A subclass may still declare the narrower `SparqlJsonResults` —\n * a return type is covariant, so existing implementations stay valid.\n */\n protected abstract executeSparqlSelect(\n sparql: string,\n ): Promise<SparqlQueryResults>;\n\n /**\n * Send a SPARQL UPDATE request (INSERT DATA, DELETE/INSERT, etc.).\n * No return value — the update is fire-and-forget at the SPARQL level.\n */\n protected abstract executeSparqlUpdate(sparql: string): Promise<void>;\n\n /**\n * Answer a select query — **and a count, which is a select.**\n *\n * A count is not a distinct query form the way an ask is. An ask really is\n * `ASK WHERE { … }` and needs its own method; a count is\n * `SELECT (COUNT(DISTINCT ?a0) AS ?count) WHERE { … }` — the same query form, the\n * same transport (`executeSparqlSelect`), the same result-set response, differing\n * only in its projection. `countToAlgebra` says so itself: it builds its plan by\n * calling `selectToAlgebra` and swapping the projection, and yields\n * `{type: 'select'}`.\n *\n * So a count rides this channel rather than a method of its own. That is not\n * tidiness: it is what lets a count reach a store through every router that\n * already forwards a select — `LinkedStorage.selectQuery`, a backend API store —\n * with no per-kind plumbing to add in each of them, and no optional `IDataset`\n * member that a third-party store silently lacks.\n *\n * The branch is on the LOWERED IR, as `updateQuery` and `deleteQuery` branch on\n * theirs: `lower()` is the one place that knows a count from a select, and a\n * rehydrated envelope (`fromJSON`) arrives here as a builder like any other.\n *\n * A count carries only a pattern, so there is nothing to normalise away on that\n * path: no projection, no ordering, and in particular no `LIMIT`/`OFFSET`, which\n * the builder dropped before the query ever reached the IR. Errors reject; a count\n * failure is never reported as `0`.\n */\n selectQuery(query: SelectQuery): Promise<SelectResult>;\n selectQuery(query: CountQuery): Promise<number>;\n async selectQuery(\n query: SelectQuery | CountQuery,\n ): Promise<SelectResult | number> {\n // Cast once for the call rather than lowering in each branch: `lower` is\n // overloaded per query kind and cannot resolve a union, and lowering twice\n // would be the thing this method most needs not to do.\n const ir = lower(query as SelectQuery) as IRSelectQuery | IRCountQuery;\n if (ir.kind === 'count') {\n const sparql = countToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n // `mapSparqlCountResult` is strict in the same way the guard below is: it\n // refuses an ASK response, an empty result set and a non-integer binding\n // rather than answering `0`.\n return mapSparqlCountResult(json, ir);\n }\n const sparql = selectToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n if (!isSparqlSelectResults(json)) {\n throw new Error(\n 'Expected a SPARQL SELECT result set, got an ASK response. The endpoint ' +\n 'did not answer the SELECT query that was sent.',\n );\n }\n return mapSparqlSelectResult(json, ir);\n }\n\n /**\n * Answer an ask query — emitted as `ASK WHERE { … }`.\n *\n * An {@link AskQuery} carries only a pattern, so there is nothing to normalise\n * away here. A query with no shape lowers to `ASK { <iri> ?p ?o }` — existence\n * of the node under any type or none. Errors reject; never reported as `false`.\n */\n async askQuery(query: AskQuery): Promise<boolean> {\n const ir = lower(query);\n const sparql = askToSparql(ir, this.options);\n const json = await this.executeSparqlSelect(sparql);\n return mapSparqlAskResult(json);\n }\n\n async createQuery(query: CreateQuery): Promise<CreateResult> {\n const ir = lower(query);\n const uri = ir.data.id || generateEntityUri(ir.data.shape, this.options);\n ir.data.id = uri;\n await this.checkOwnedLinks(ir);\n const sparql = createToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return mapSparqlCreateResult(uri, ir);\n }\n\n async updateQuery(query: UpdateQuery): Promise<UpdateResult> {\n const ir = lower(query);\n await this.checkOwnedLinks(ir);\n if (ir.kind === 'update_where') {\n const sparql = updateWhereToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {id: ''} as UpdateResult;\n }\n const sparql =\n ir.kind === 'upsert'\n ? upsertToSparql(ir, this.options)\n : updateToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return mapSparqlUpdateResult(ir);\n }\n\n /**\n * Refuse a mutation that links a node of the wrong class into a `contains` property\n * (see `ownedLinkCheck.ts`). An owner deletes what it contains, so a Person linked into\n * an ImageObject slot would be deleted with its owner. Runs before the update is sent, so\n * a refused mutation writes nothing. With no such link no query is sent; otherwise one\n * SELECT covers every linked id.\n */\n protected async checkOwnedLinks(\n ir: IRCreateMutation | IRUpdateMutation | IRUpsertMutation | IRUpdateWhereMutation,\n ): Promise<void> {\n const links = collectOwnedLinks(ir);\n if (links.length === 0) return;\n const json = await this.executeSparqlSelect(\n ownedLinkTypesQuery(links.map((link) => link.id)),\n );\n assertOwnedLinkTypes(links, ownedLinkTypesFromResults(json));\n }\n\n async deleteQuery(query: DeleteQuery): Promise<DeleteResponse> {\n const ir = lower(query);\n if (ir.kind === 'delete_all') {\n const sparql = deleteAllToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {deleted: [], count: 0};\n }\n if (ir.kind === 'delete_where') {\n const sparql = deleteWhereToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {deleted: [], count: 0};\n }\n const sparql = deleteToSparql(ir, this.options);\n await this.executeSparqlUpdate(sparql);\n return {\n deleted: ir.ids,\n count: ir.ids.length,\n };\n }\n\n /**\n * Execute a raw SPARQL query string directly against the dataset.\n * Defaults to SELECT; pass `'update'` for INSERT/DELETE operations.\n */\n async rawQuery(\n sparql: string,\n mode?: 'query' | 'update',\n ): Promise<SparqlQueryResults | void> {\n if (mode === 'update') {\n return this.executeSparqlUpdate(sparql);\n }\n return this.executeSparqlSelect(sparql);\n }\n}\n\n// Backwards-compatibility re-export — remove once all consumers are updated.\nexport {SparqlDataset as SparqlStore};\n"]}
@@ -13,6 +13,8 @@ export function serializeTerm(term, collector) {
13
13
  if (collector)
14
14
  collectUri(collector, term.value);
15
15
  return formatUri(term.value);
16
+ case 'blank':
17
+ return `_:${sanitizeVarName(term.label)}`;
16
18
  case 'literal': {
17
19
  if (term.language) {
18
20
  return `"${escapeSparqlString(term.value)}"@${term.language}`;
@@ -1 +1 @@
1
- {"version":3,"file":"algebraToString.js","sourceRoot":"","sources":["../../../src/sparql/algebraToString.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SparqlAlgebraNode,\n SparqlExpression,\n SparqlTerm,\n SparqlTriple,\n SparqlSelectPlan,\n SparqlAskPlan,\n SparqlInsertDataPlan,\n SparqlDeleteInsertPlan,\n SparqlDeleteWherePlan,\n} from './SparqlAlgebra.js';\nimport {\n type SparqlOptions,\n formatUri,\n formatLiteral,\n escapeSparqlString,\n collectPrefixes,\n assertSafeCallName,\n sanitizeVarName,\n} from './sparqlUtils.js';\n\n// ---------------------------------------------------------------------------\n// URI collector — gathers all IRIs encountered during serialization so that\n// the prefix block can be built afterwards.\n// ---------------------------------------------------------------------------\n\ntype UriCollector = {uris: Set<string>};\n\nfunction collectUri(collector: UriCollector, uri: string): void {\n collector.uris.add(uri);\n}\n\n// ---------------------------------------------------------------------------\n// Term serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeTerm(\n term: SparqlTerm,\n collector?: UriCollector,\n): string {\n switch (term.kind) {\n case 'variable':\n return `?${sanitizeVarName(term.name)}`;\n case 'iri':\n if (collector) collectUri(collector, term.value);\n return formatUri(term.value);\n case 'literal': {\n if (term.language) {\n return `\"${escapeSparqlString(term.value)}\"@${term.language}`;\n }\n if (term.datatype) {\n if (collector) collectUri(collector, term.datatype);\n }\n return formatLiteral(term.value, term.datatype);\n }\n case 'path':\n if (collector && term.uris) {\n for (const uri of term.uris) collectUri(collector, uri);\n }\n return term.value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Triple serialization\n// ---------------------------------------------------------------------------\n\nfunction serializeTriple(\n triple: SparqlTriple,\n collector?: UriCollector,\n): string {\n const s = serializeTerm(triple.subject, collector);\n const p = serializeTerm(triple.predicate, collector);\n const o = serializeTerm(triple.object, collector);\n return `${s} ${p} ${o}`;\n}\n\nfunction serializeTriples(\n triples: SparqlTriple[],\n collector?: UriCollector,\n): string {\n return triples\n .map((t) => serializeTriple(t, collector) + ' .')\n .join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Expression serialization\n// ---------------------------------------------------------------------------\n\n// SPARQL binary-operator precedence (higher binds tighter): multiplicative >\n// additive > relational. Used to parenthesize nested `binary_expr` operands so\n// arithmetic groups correctly (`(a+b)*c`, not `a+b*c`) and relational chains\n// (`a=b=c`, a non-associative syntax error) get parenthesized.\nconst RELATIONAL_OPS = new Set(['=', '!=', '<', '>', '<=', '>=']);\nfunction binaryPrecedence(op: string): number {\n if (op === '*' || op === '/') return 3;\n if (op === '+' || op === '-') return 2;\n if (RELATIONAL_OPS.has(op)) return 1;\n return 0;\n}\n\n/**\n * Serialize a `binary_expr` operand, wrapping it in parens when omitting them\n * would change how SPARQL parses the expression.\n */\nfunction wrapBinaryOperand(\n operand: SparqlExpression,\n parentOp: string,\n side: 'left' | 'right',\n collector?: UriCollector,\n): string {\n const s = serializeExpression(operand, collector);\n // Logical (&&/||) binds looser than any binary operator → always parenthesize.\n if (operand.kind === 'logical_expr') return `(${s})`;\n if (operand.kind !== 'binary_expr') return s;\n const parentIsRel = RELATIONAL_OPS.has(parentOp);\n const childIsRel = RELATIONAL_OPS.has(operand.op);\n // Relational is non-associative in SPARQL: any relational-in-relational needs parens.\n if (parentIsRel && childIsRel) return `(${s})`;\n const pc = binaryPrecedence(operand.op);\n const pp = binaryPrecedence(parentOp);\n const needs = side === 'left' ? pc < pp : pc <= pp;\n return needs ? `(${s})` : s;\n}\n\nexport function serializeExpression(\n expr: SparqlExpression,\n collector?: UriCollector,\n): string {\n switch (expr.kind) {\n case 'variable_expr':\n return `?${sanitizeVarName(expr.name)}`;\n\n case 'iri_expr':\n if (collector) collectUri(collector, expr.value);\n return formatUri(expr.value);\n\n case 'literal_expr': {\n if (expr.datatype && collector) collectUri(collector, expr.datatype);\n return formatLiteral(expr.value, expr.datatype);\n }\n\n case 'binary_expr': {\n const left = wrapBinaryOperand(expr.left, expr.op, 'left', collector);\n const right = wrapBinaryOperand(expr.right, expr.op, 'right', collector);\n return `${left} ${expr.op} ${right}`;\n }\n\n case 'logical_expr': {\n const op = expr.op === 'and' ? '&&' : '||';\n const parts = expr.exprs.map((e) => {\n const s = serializeExpression(e, collector);\n // Parenthesize OR children inside AND (AND binds tighter than OR)\n if (expr.op === 'and' && e.kind === 'logical_expr' && e.op === 'or') {\n return `(${s})`;\n }\n return s;\n });\n return parts.join(` ${op} `);\n }\n\n case 'not_expr':\n return `!(${serializeExpression(expr.inner, collector)})`;\n\n case 'function_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n return `${expr.name}(${args})`;\n }\n\n case 'aggregate_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n const distinctPrefix = expr.distinct ? 'DISTINCT ' : '';\n // Uppercased here rather than in the IR: this one line covers COUNT/SUM/AVG/\n // MIN/MAX and any aggregate added later, while the IR keeps carrying a plain\n // lowercase name (`'count'`) that other consumers can match on without\n // case-folding. It also puts the aggregate in the same voice as every other\n // keyword this file emits (SELECT, DISTINCT, GROUP BY, HAVING, …).\n // `function_expr` is deliberately left alone: its names arrive already in\n // their correct SPARQL spelling, which is not uniformly uppercase (`isBlank`,\n // `isIRI`), so case-folding there would corrupt them.\n return `${expr.name.toUpperCase()}(${distinctPrefix}${args})`;\n }\n\n case 'exists_expr': {\n const inner = serializeAlgebraNode(expr.pattern, collector);\n const prefix = expr.negated ? 'NOT EXISTS' : 'EXISTS';\n return `${prefix} {\\n${indent(inner)}\\n}`;\n }\n\n case 'bound_expr':\n return `BOUND(?${sanitizeVarName(expr.variable)})`;\n\n case 'in_expr': {\n // Empty list: `IN ()` matches nothing, `NOT IN ()` matches everything —\n // fold to a boolean constant rather than emit an empty parenthesis list.\n if (expr.list.length === 0) return expr.negated ? 'true' : 'false';\n const val = serializeExpression(expr.value, collector);\n const items = expr.list.map((e) => serializeExpression(e, collector)).join(', ');\n return `${val} ${expr.negated ? 'NOT IN' : 'IN'} (${items})`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Algebra node serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeAlgebraNode(\n node: SparqlAlgebraNode,\n collector?: UriCollector,\n): string {\n switch (node.type) {\n case 'bgp':\n return serializeTriples(node.triples, collector);\n\n case 'join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\n${right}`;\n }\n\n case 'left_join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n let optionalBlock = `OPTIONAL {\\n${indent(right)}\\n}`;\n if (node.condition) {\n const cond = serializeExpression(node.condition, collector);\n // OPTIONAL with filter: OPTIONAL { pattern FILTER(cond) }\n // Re-build to include filter inside the OPTIONAL block\n optionalBlock = `OPTIONAL {\\n${indent(right)}\\n FILTER(${cond})\\n}`;\n }\n // If left side is empty (e.g. UPDATE WHERE with all-OPTIONAL triples),\n // omit the empty prefix to avoid blank lines\n return left ? `${left}\\n${optionalBlock}` : optionalBlock;\n }\n\n case 'filter': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nFILTER(${expr})`;\n }\n\n case 'union': {\n // UNION is associative: write a left-nested chain flat, {a} UNION {b} UNION {c},\n // instead of nesting every earlier branch one group deeper.\n const branches: SparqlAlgebraNode[] = [node.right];\n let head: SparqlAlgebraNode = node.left;\n while (head.type === 'union') {\n branches.unshift(head.right);\n head = head.left;\n }\n branches.unshift(head);\n return branches\n .map((branch) => `{\\n${indent(serializeAlgebraNode(branch, collector))}\\n}`)\n .join('\\nUNION\\n');\n }\n\n case 'minus': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\nMINUS {\\n${indent(right)}\\n}`;\n }\n\n case 'extend': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nBIND(${expr} AS ?${sanitizeVarName(node.variable)})`;\n }\n\n case 'graph': {\n if (collector) collectUri(collector, node.iri);\n const inner = serializeAlgebraNode(node.inner, collector);\n return `GRAPH ${formatUri(node.iri)} {\\n${indent(inner)}\\n}`;\n }\n\n case 'values': {\n const values = node.iris\n .map((iri) => {\n if (collector) collectUri(collector, iri);\n return formatUri(iri);\n })\n .join(' ');\n return `VALUES ?${sanitizeVarName(node.variable)} { ${values} }`;\n }\n\n case 'subselect': {\n const innerBody = serializeAlgebraNode(node.inner, collector);\n const projection = node.projection.map((v) => `?${sanitizeVarName(v)}`).join(' ');\n const lines: string[] = [`SELECT ${projection} WHERE {`];\n lines.push(indent(innerBody));\n lines.push('}');\n const trailing: string[] = [];\n if (node.orderBy && node.orderBy.length > 0) {\n const orderParts = node.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n trailing.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n if (node.limit !== undefined) {\n trailing.push(`LIMIT ${node.limit}`);\n }\n if (node.offset !== undefined) {\n trailing.push(`OFFSET ${node.offset}`);\n }\n const subSelectStr = trailing.length > 0\n ? `${lines.join('\\n')} ${trailing.join(' ')}`\n : lines.join('\\n');\n return `{\\n${indent(subSelectStr)}\\n}`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction indent(text: string, level: number = 1): string {\n const prefix = ' '.repeat(level);\n return text\n .split('\\n')\n .map((line) => prefix + line)\n .join('\\n');\n}\n\nfunction buildPrefixBlock(usedUris: Set<string>): string {\n const prefixes = collectPrefixes([...usedUris]);\n const lines = Object.entries(prefixes)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([prefix, uri]) => `PREFIX ${prefix}: <${uri}>`);\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Top-level plan serializers\n// ---------------------------------------------------------------------------\n\nexport function selectPlanToSparql(\n plan: SparqlSelectPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build SELECT line\n const projectionParts = plan.projection.map((item) => {\n if (item.kind === 'variable') {\n return `?${sanitizeVarName(item.name)}`;\n } else {\n // aggregate or expression projection: (expr AS ?alias)\n const expr = serializeExpression(item.expression, collector);\n return `(${expr} AS ?${sanitizeVarName(item.alias)})`;\n }\n });\n\n const distinctStr = plan.distinct ? 'DISTINCT ' : '';\n const selectLine = `SELECT ${distinctStr}${projectionParts.join(' ')}`;\n\n // 3. Build WHERE block\n const whereBlock = `WHERE {\\n${indent(body)}\\n}`;\n\n // 4. Build trailing clauses\n const clauses: string[] = [];\n\n if (plan.groupBy && plan.groupBy.length > 0) {\n clauses.push(\n `GROUP BY ${plan.groupBy.map((v) => `?${sanitizeVarName(v)}`).join(' ')}`,\n );\n }\n\n if (plan.having) {\n const havingExpr = serializeExpression(plan.having, collector);\n clauses.push(`HAVING(${havingExpr})`);\n }\n\n if (plan.orderBy && plan.orderBy.length > 0) {\n const orderParts = plan.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n clauses.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n\n if (plan.limit !== undefined) {\n clauses.push(`LIMIT ${plan.limit}`);\n }\n\n if (plan.offset !== undefined) {\n clauses.push(`OFFSET ${plan.offset}`);\n }\n\n // 5. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 6. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(selectLine);\n parts.push(whereBlock);\n parts.push(...clauses);\n\n return parts.join('\\n');\n}\n\n/**\n * Serializes a {@link SparqlAskPlan} to `ASK WHERE { … }`.\n *\n * The same WHERE body as {@link selectPlanToSparql}, with the projection line and\n * every solution modifier removed — `ASK` accepts none of them.\n */\nexport function askPlanToSparql(\n plan: SparqlAskPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body (collects the URIs the prefix block is built from)\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 3. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(`ASK WHERE {\\n${indent(body)}\\n}`);\n\n return parts.join('\\n');\n}\n\nexport function insertDataPlanToSparql(\n plan: SparqlInsertDataPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n let triplesStr: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n const innerTriples = serializeTriples(plan.triples, collector);\n triplesStr = `GRAPH ${formatUri(plan.graph)} {\\n${indent(innerTriples)}\\n}`;\n } else {\n triplesStr = serializeTriples(plan.triples, collector);\n }\n\n const body = `INSERT DATA {\\n${indent(triplesStr)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(body);\n return parts.join('\\n');\n}\n\nexport function deleteInsertPlanToSparql(\n plan: SparqlDeleteInsertPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // DELETE block\n const deleteTriples = serializeTriples(plan.deletePatterns, collector);\n const deletePart = `DELETE {\\n${indent(deleteTriples)}\\n}`;\n\n // INSERT block (may be empty)\n let insertPart = '';\n if (plan.insertPatterns.length > 0) {\n const insertTriples = serializeTriples(plan.insertPatterns, collector);\n insertPart = `INSERT {\\n${indent(insertTriples)}\\n}\\n`;\n }\n\n // WHERE block\n const whereBody = serializeAlgebraNode(plan.whereAlgebra, collector);\n const wherePart = `WHERE {\\n${indent(whereBody)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(deletePart);\n if (insertPart) parts.push(insertPart.trimEnd());\n parts.push(wherePart);\n return parts.join('\\n');\n}\n\nexport function deleteWherePlanToSparql(\n plan: SparqlDeleteWherePlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n const body = serializeAlgebraNode(plan.patterns, collector);\n\n let content: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n content = `GRAPH ${formatUri(plan.graph)} {\\n${indent(body)}\\n}`;\n } else {\n content = body;\n }\n\n const result = `DELETE WHERE {\\n${indent(content)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(result);\n return parts.join('\\n');\n}\n"]}
1
+ {"version":3,"file":"algebraToString.js","sourceRoot":"","sources":["../../../src/sparql/algebraToString.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SparqlAlgebraNode,\n SparqlExpression,\n SparqlTerm,\n SparqlTriple,\n SparqlSelectPlan,\n SparqlAskPlan,\n SparqlInsertDataPlan,\n SparqlDeleteInsertPlan,\n SparqlDeleteWherePlan,\n} from './SparqlAlgebra.js';\nimport {\n type SparqlOptions,\n formatUri,\n formatLiteral,\n escapeSparqlString,\n collectPrefixes,\n assertSafeCallName,\n sanitizeVarName,\n} from './sparqlUtils.js';\n\n// ---------------------------------------------------------------------------\n// URI collector — gathers all IRIs encountered during serialization so that\n// the prefix block can be built afterwards.\n// ---------------------------------------------------------------------------\n\ntype UriCollector = {uris: Set<string>};\n\nfunction collectUri(collector: UriCollector, uri: string): void {\n collector.uris.add(uri);\n}\n\n// ---------------------------------------------------------------------------\n// Term serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeTerm(\n term: SparqlTerm,\n collector?: UriCollector,\n): string {\n switch (term.kind) {\n case 'variable':\n return `?${sanitizeVarName(term.name)}`;\n case 'iri':\n if (collector) collectUri(collector, term.value);\n return formatUri(term.value);\n case 'blank':\n return `_:${sanitizeVarName(term.label)}`;\n case 'literal': {\n if (term.language) {\n return `\"${escapeSparqlString(term.value)}\"@${term.language}`;\n }\n if (term.datatype) {\n if (collector) collectUri(collector, term.datatype);\n }\n return formatLiteral(term.value, term.datatype);\n }\n case 'path':\n if (collector && term.uris) {\n for (const uri of term.uris) collectUri(collector, uri);\n }\n return term.value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Triple serialization\n// ---------------------------------------------------------------------------\n\nfunction serializeTriple(\n triple: SparqlTriple,\n collector?: UriCollector,\n): string {\n const s = serializeTerm(triple.subject, collector);\n const p = serializeTerm(triple.predicate, collector);\n const o = serializeTerm(triple.object, collector);\n return `${s} ${p} ${o}`;\n}\n\nfunction serializeTriples(\n triples: SparqlTriple[],\n collector?: UriCollector,\n): string {\n return triples\n .map((t) => serializeTriple(t, collector) + ' .')\n .join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Expression serialization\n// ---------------------------------------------------------------------------\n\n// SPARQL binary-operator precedence (higher binds tighter): multiplicative >\n// additive > relational. Used to parenthesize nested `binary_expr` operands so\n// arithmetic groups correctly (`(a+b)*c`, not `a+b*c`) and relational chains\n// (`a=b=c`, a non-associative syntax error) get parenthesized.\nconst RELATIONAL_OPS = new Set(['=', '!=', '<', '>', '<=', '>=']);\nfunction binaryPrecedence(op: string): number {\n if (op === '*' || op === '/') return 3;\n if (op === '+' || op === '-') return 2;\n if (RELATIONAL_OPS.has(op)) return 1;\n return 0;\n}\n\n/**\n * Serialize a `binary_expr` operand, wrapping it in parens when omitting them\n * would change how SPARQL parses the expression.\n */\nfunction wrapBinaryOperand(\n operand: SparqlExpression,\n parentOp: string,\n side: 'left' | 'right',\n collector?: UriCollector,\n): string {\n const s = serializeExpression(operand, collector);\n // Logical (&&/||) binds looser than any binary operator → always parenthesize.\n if (operand.kind === 'logical_expr') return `(${s})`;\n if (operand.kind !== 'binary_expr') return s;\n const parentIsRel = RELATIONAL_OPS.has(parentOp);\n const childIsRel = RELATIONAL_OPS.has(operand.op);\n // Relational is non-associative in SPARQL: any relational-in-relational needs parens.\n if (parentIsRel && childIsRel) return `(${s})`;\n const pc = binaryPrecedence(operand.op);\n const pp = binaryPrecedence(parentOp);\n const needs = side === 'left' ? pc < pp : pc <= pp;\n return needs ? `(${s})` : s;\n}\n\nexport function serializeExpression(\n expr: SparqlExpression,\n collector?: UriCollector,\n): string {\n switch (expr.kind) {\n case 'variable_expr':\n return `?${sanitizeVarName(expr.name)}`;\n\n case 'iri_expr':\n if (collector) collectUri(collector, expr.value);\n return formatUri(expr.value);\n\n case 'literal_expr': {\n if (expr.datatype && collector) collectUri(collector, expr.datatype);\n return formatLiteral(expr.value, expr.datatype);\n }\n\n case 'binary_expr': {\n const left = wrapBinaryOperand(expr.left, expr.op, 'left', collector);\n const right = wrapBinaryOperand(expr.right, expr.op, 'right', collector);\n return `${left} ${expr.op} ${right}`;\n }\n\n case 'logical_expr': {\n const op = expr.op === 'and' ? '&&' : '||';\n const parts = expr.exprs.map((e) => {\n const s = serializeExpression(e, collector);\n // Parenthesize OR children inside AND (AND binds tighter than OR)\n if (expr.op === 'and' && e.kind === 'logical_expr' && e.op === 'or') {\n return `(${s})`;\n }\n return s;\n });\n return parts.join(` ${op} `);\n }\n\n case 'not_expr':\n return `!(${serializeExpression(expr.inner, collector)})`;\n\n case 'function_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n return `${expr.name}(${args})`;\n }\n\n case 'aggregate_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n const distinctPrefix = expr.distinct ? 'DISTINCT ' : '';\n // Uppercased here rather than in the IR: this one line covers COUNT/SUM/AVG/\n // MIN/MAX and any aggregate added later, while the IR keeps carrying a plain\n // lowercase name (`'count'`) that other consumers can match on without\n // case-folding. It also puts the aggregate in the same voice as every other\n // keyword this file emits (SELECT, DISTINCT, GROUP BY, HAVING, …).\n // `function_expr` is deliberately left alone: its names arrive already in\n // their correct SPARQL spelling, which is not uniformly uppercase (`isBlank`,\n // `isIRI`), so case-folding there would corrupt them.\n return `${expr.name.toUpperCase()}(${distinctPrefix}${args})`;\n }\n\n case 'exists_expr': {\n const inner = serializeAlgebraNode(expr.pattern, collector);\n const prefix = expr.negated ? 'NOT EXISTS' : 'EXISTS';\n return `${prefix} {\\n${indent(inner)}\\n}`;\n }\n\n case 'bound_expr':\n return `BOUND(?${sanitizeVarName(expr.variable)})`;\n\n case 'in_expr': {\n // Empty list: `IN ()` matches nothing, `NOT IN ()` matches everything —\n // fold to a boolean constant rather than emit an empty parenthesis list.\n if (expr.list.length === 0) return expr.negated ? 'true' : 'false';\n const val = serializeExpression(expr.value, collector);\n const items = expr.list.map((e) => serializeExpression(e, collector)).join(', ');\n return `${val} ${expr.negated ? 'NOT IN' : 'IN'} (${items})`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Algebra node serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeAlgebraNode(\n node: SparqlAlgebraNode,\n collector?: UriCollector,\n): string {\n switch (node.type) {\n case 'bgp':\n return serializeTriples(node.triples, collector);\n\n case 'join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\n${right}`;\n }\n\n case 'left_join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n let optionalBlock = `OPTIONAL {\\n${indent(right)}\\n}`;\n if (node.condition) {\n const cond = serializeExpression(node.condition, collector);\n // OPTIONAL with filter: OPTIONAL { pattern FILTER(cond) }\n // Re-build to include filter inside the OPTIONAL block\n optionalBlock = `OPTIONAL {\\n${indent(right)}\\n FILTER(${cond})\\n}`;\n }\n // If left side is empty (e.g. UPDATE WHERE with all-OPTIONAL triples),\n // omit the empty prefix to avoid blank lines\n return left ? `${left}\\n${optionalBlock}` : optionalBlock;\n }\n\n case 'filter': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nFILTER(${expr})`;\n }\n\n case 'union': {\n // UNION is associative: write a left-nested chain flat, {a} UNION {b} UNION {c},\n // instead of nesting every earlier branch one group deeper.\n const branches: SparqlAlgebraNode[] = [node.right];\n let head: SparqlAlgebraNode = node.left;\n while (head.type === 'union') {\n branches.unshift(head.right);\n head = head.left;\n }\n branches.unshift(head);\n return branches\n .map((branch) => `{\\n${indent(serializeAlgebraNode(branch, collector))}\\n}`)\n .join('\\nUNION\\n');\n }\n\n case 'minus': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\nMINUS {\\n${indent(right)}\\n}`;\n }\n\n case 'extend': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nBIND(${expr} AS ?${sanitizeVarName(node.variable)})`;\n }\n\n case 'graph': {\n if (collector) collectUri(collector, node.iri);\n const inner = serializeAlgebraNode(node.inner, collector);\n return `GRAPH ${formatUri(node.iri)} {\\n${indent(inner)}\\n}`;\n }\n\n case 'values': {\n const values = node.iris\n .map((iri) => {\n if (collector) collectUri(collector, iri);\n return formatUri(iri);\n })\n .join(' ');\n return `VALUES ?${sanitizeVarName(node.variable)} { ${values} }`;\n }\n\n case 'subselect': {\n const innerBody = serializeAlgebraNode(node.inner, collector);\n const projection = node.projection.map((v) => `?${sanitizeVarName(v)}`).join(' ');\n const lines: string[] = [`SELECT ${projection} WHERE {`];\n lines.push(indent(innerBody));\n lines.push('}');\n const trailing: string[] = [];\n if (node.orderBy && node.orderBy.length > 0) {\n const orderParts = node.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n trailing.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n if (node.limit !== undefined) {\n trailing.push(`LIMIT ${node.limit}`);\n }\n if (node.offset !== undefined) {\n trailing.push(`OFFSET ${node.offset}`);\n }\n const subSelectStr = trailing.length > 0\n ? `${lines.join('\\n')} ${trailing.join(' ')}`\n : lines.join('\\n');\n return `{\\n${indent(subSelectStr)}\\n}`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction indent(text: string, level: number = 1): string {\n const prefix = ' '.repeat(level);\n return text\n .split('\\n')\n .map((line) => prefix + line)\n .join('\\n');\n}\n\nfunction buildPrefixBlock(usedUris: Set<string>): string {\n const prefixes = collectPrefixes([...usedUris]);\n const lines = Object.entries(prefixes)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([prefix, uri]) => `PREFIX ${prefix}: <${uri}>`);\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Top-level plan serializers\n// ---------------------------------------------------------------------------\n\nexport function selectPlanToSparql(\n plan: SparqlSelectPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build SELECT line\n const projectionParts = plan.projection.map((item) => {\n if (item.kind === 'variable') {\n return `?${sanitizeVarName(item.name)}`;\n } else {\n // aggregate or expression projection: (expr AS ?alias)\n const expr = serializeExpression(item.expression, collector);\n return `(${expr} AS ?${sanitizeVarName(item.alias)})`;\n }\n });\n\n const distinctStr = plan.distinct ? 'DISTINCT ' : '';\n const selectLine = `SELECT ${distinctStr}${projectionParts.join(' ')}`;\n\n // 3. Build WHERE block\n const whereBlock = `WHERE {\\n${indent(body)}\\n}`;\n\n // 4. Build trailing clauses\n const clauses: string[] = [];\n\n if (plan.groupBy && plan.groupBy.length > 0) {\n clauses.push(\n `GROUP BY ${plan.groupBy.map((v) => `?${sanitizeVarName(v)}`).join(' ')}`,\n );\n }\n\n if (plan.having) {\n const havingExpr = serializeExpression(plan.having, collector);\n clauses.push(`HAVING(${havingExpr})`);\n }\n\n if (plan.orderBy && plan.orderBy.length > 0) {\n const orderParts = plan.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n clauses.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n\n if (plan.limit !== undefined) {\n clauses.push(`LIMIT ${plan.limit}`);\n }\n\n if (plan.offset !== undefined) {\n clauses.push(`OFFSET ${plan.offset}`);\n }\n\n // 5. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 6. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(selectLine);\n parts.push(whereBlock);\n parts.push(...clauses);\n\n return parts.join('\\n');\n}\n\n/**\n * Serializes a {@link SparqlAskPlan} to `ASK WHERE { … }`.\n *\n * The same WHERE body as {@link selectPlanToSparql}, with the projection line and\n * every solution modifier removed — `ASK` accepts none of them.\n */\nexport function askPlanToSparql(\n plan: SparqlAskPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body (collects the URIs the prefix block is built from)\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 3. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(`ASK WHERE {\\n${indent(body)}\\n}`);\n\n return parts.join('\\n');\n}\n\nexport function insertDataPlanToSparql(\n plan: SparqlInsertDataPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n let triplesStr: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n const innerTriples = serializeTriples(plan.triples, collector);\n triplesStr = `GRAPH ${formatUri(plan.graph)} {\\n${indent(innerTriples)}\\n}`;\n } else {\n triplesStr = serializeTriples(plan.triples, collector);\n }\n\n const body = `INSERT DATA {\\n${indent(triplesStr)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(body);\n return parts.join('\\n');\n}\n\nexport function deleteInsertPlanToSparql(\n plan: SparqlDeleteInsertPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // DELETE block\n const deleteTriples = serializeTriples(plan.deletePatterns, collector);\n const deletePart = `DELETE {\\n${indent(deleteTriples)}\\n}`;\n\n // INSERT block (may be empty)\n let insertPart = '';\n if (plan.insertPatterns.length > 0) {\n const insertTriples = serializeTriples(plan.insertPatterns, collector);\n insertPart = `INSERT {\\n${indent(insertTriples)}\\n}\\n`;\n }\n\n // WHERE block\n const whereBody = serializeAlgebraNode(plan.whereAlgebra, collector);\n const wherePart = `WHERE {\\n${indent(whereBody)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(deletePart);\n if (insertPart) parts.push(insertPart.trimEnd());\n parts.push(wherePart);\n return parts.join('\\n');\n}\n\nexport function deleteWherePlanToSparql(\n plan: SparqlDeleteWherePlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n const body = serializeAlgebraNode(plan.patterns, collector);\n\n let content: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n content = `GRAPH ${formatUri(plan.graph)} {\\n${indent(body)}\\n}`;\n } else {\n content = body;\n }\n\n const result = `DELETE WHERE {\\n${indent(content)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(result);\n return parts.join('\\n');\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { IRSelectQuery, IRAskQuery, IRCountQuery, IRCreateMutation, IRUpdateMutation, IRUpsertMutation, IRDeleteMutation, IRDeleteAllMutation, IRDeleteWhereMutation, IRUpdateWhereMutation } from '../queries/IntermediateRepresentation.js';
2
+ import type { NodeReferenceValue } from '../utils/NodeReference.js';
2
3
  import type { SparqlSelectPlan, SparqlAskPlan, SparqlInsertDataPlan, SparqlDeleteInsertPlan, SparqlAlgebraNode, SparqlTriple, SparqlTerm } from './SparqlAlgebra.js';
3
4
  import { type SparqlOptions } from './sparqlUtils.js';
4
5
  /**
@@ -9,6 +10,8 @@ export declare function selectToAlgebra(query: IRSelectQuery, _options?: SparqlO
9
10
  * Converts an IRCreateMutation to a SparqlInsertDataPlan.
10
11
  */
11
12
  export declare function createToAlgebra(query: IRCreateMutation, options?: SparqlOptions): SparqlInsertDataPlan;
13
+ /** A bare `{id}` reference: a link to an existing node, not a nested create. */
14
+ export declare function isBareNodeReference(value: unknown): value is NodeReferenceValue;
12
15
  /**
13
16
  * Converts an IRUpdateMutation to a SparqlDeleteInsertPlan.
14
17
  */
@@ -23,6 +26,11 @@ export declare function updateToAlgebra(query: IRUpdateMutation, options?: Sparq
23
26
  * needs no guard.
24
27
  */
25
28
  export declare function upsertToAlgebra(query: IRUpsertMutation, options?: SparqlOptions): SparqlDeleteInsertPlan;
29
+ /** Gather contains-predicate IRIs and dependent targetClass IRIs from the registry. */
30
+ export declare function collectContainment(): {
31
+ containsPreds: string[];
32
+ dependentTypes: string[];
33
+ };
26
34
  /**
27
35
  * Build DELETE patterns + WHERE OPTIONAL blocks that cascade-delete the owned subtree
28
36
  * reachable from `rootTerm` via `contains` edges. `varPrefix` keeps generated variables
@@ -30,8 +38,10 @@ export declare function upsertToAlgebra(query: IRUpsertMutation, options?: Sparq
30
38
  *
31
39
  * `anchor`, when given, leads every block: the triple that binds a variable root, so
32
40
  * each block stays correct on its own (as a UNION branch) when no such root exists.
41
+ * `onlyTypes`, when given, restricts the blocks to those dependent types (a subject delete
42
+ * passes the types its shape can reach); by default every registered dependent type gets one.
33
43
  */
34
- export declare function buildOwnedCascade(rootTerm: SparqlTerm, varPrefix: string, anchor?: SparqlTriple): {
44
+ export declare function buildOwnedCascade(rootTerm: SparqlTerm, varPrefix: string, anchor?: SparqlTriple, keep?: SparqlTerm[], onlyTypes?: string[]): {
35
45
  deletePatterns: SparqlTriple[];
36
46
  whereOptionals: SparqlAlgebraNode[];
37
47
  };
@@ -43,12 +53,21 @@ export declare function buildOwnedCascade(rootTerm: SparqlTerm, varPrefix: strin
43
53
  * does NOT require the child shape to be `dependent`: ownership via the edge is sufficient.
44
54
  * Owned descendants *below* the old node are cascaded separately by `buildOwnedCascade`.
45
55
  *
56
+ * Callers use it only for a property that declares a value shape. A shape-less `contains`
57
+ * slot (like `sh:path`) may hold a shared IRI, so its old value is left to
58
+ * `buildOwnedCascade`, which deletes it only when it is dependent-typed.
59
+ *
46
60
  * The owning edge `<subject> <prop> ?old` is re-asserted INSIDE the WHERE group so `?old`
47
61
  * is bound there: when no old value exists the group matches nothing and the DELETE is a
48
62
  * no-op, rather than an unbound `?old` matching (and deleting) the whole graph. When
49
63
  * `oldTerm` is a concrete IRI (set-remove), the guard just confirms the link still holds.
64
+ *
65
+ * `keep` lists the bare `{id}`s the mutation writes again (a re-sent current value, the
66
+ * retained ids of an array overwrite). With a variable `oldTerm` the block is wrapped in
67
+ * `FILTER(?old NOT IN (…))`, so a kept value is not deleted; its edge is deleted and
68
+ * re-inserted, a no-op. A nested create carrying an id is never kept: it rewrites that node.
50
69
  */
51
- export declare function buildOwnedSelfDelete(subjectTerm: SparqlTerm, propertyTerm: SparqlTerm, oldTerm: SparqlTerm, varPrefix: string): {
70
+ export declare function buildOwnedSelfDelete(subjectTerm: SparqlTerm, propertyTerm: SparqlTerm, oldTerm: SparqlTerm, varPrefix: string, keep?: SparqlTerm[]): {
52
71
  deletePatterns: SparqlTriple[];
53
72
  whereOptionals: SparqlAlgebraNode[];
54
73
  };
@@ -57,7 +76,12 @@ export declare function buildOwnedSelfDelete(subjectTerm: SparqlTerm, propertyTe
57
76
  *
58
77
  * The WHERE is the type guard of every id, joined with ONE UNION of independent
59
78
  * blocks: per id its own triples, its incoming references and, for a shape that
60
- * owns something, one block per dependent type of its owned subtree.
79
+ * owns something, one block per immediately-owned child (`<s> <p> ?dN . ?dN ?dN_p ?dN_o`,
80
+ * for each of the shape's own and inherited `contains` properties with a value shape and
81
+ * a simple path) and one block per dependent type its owned subtree can reach
82
+ * (`reachableDependentTypes`; none for a shape that owns only non-dependent values). The
83
+ * bulk deletes (`deleteAllToAlgebra`, `deleteWhereToAlgebra`) add the same owned blocks,
84
+ * rooted at the subject variable (see `bulkDeleteUnion`).
61
85
  *
62
86
  * The blocks must not be chained as OPTIONALs. A chain of OPTIONALs is a join, so
63
87
  * the solutions multiply: own triples x incoming references x owned triples of each
@@ -75,14 +99,18 @@ export declare function deleteToAlgebra(query: IRDeleteMutation, _options?: Spar
75
99
  /**
76
100
  * Converts an IRDeleteAllMutation to a SparqlDeleteInsertPlan.
77
101
  *
78
- * Generates DELETE { ?a0 ?p ?o . [blank node wildcards] }
79
- * WHERE { ?a0 a <Shape> . ?a0 ?p ?o . OPTIONAL { [blank node traversals] } }
102
+ * Generates DELETE { ?a0 ?p ?o . [blank-node and owned-cleanup wildcards] }
103
+ * WHERE { ?a0 a <Shape> . { ?a0 ?p ?o } UNION [one block per blank node,
104
+ * owned child and dependent type] }
105
+ * (see `bulkDeleteUnion`). Unlike a delete by id, incoming references are not deleted.
80
106
  */
81
107
  export declare function deleteAllToAlgebra(query: IRDeleteAllMutation, _options?: SparqlOptions): SparqlDeleteInsertPlan;
82
108
  /**
83
109
  * Converts an IRDeleteWhereMutation to a SparqlDeleteInsertPlan.
84
110
  *
85
- * Like deleteAllToAlgebra but adds filter conditions from the where clause.
111
+ * Like deleteAllToAlgebra but adds filter conditions from the where clause. The cleanup
112
+ * UNION (blank nodes, owned children, dependent cascade) is joined with the filtered match,
113
+ * so only the matched subjects' children are deleted.
86
114
  */
87
115
  export declare function deleteWhereToAlgebra(query: IRDeleteWhereMutation, _options?: SparqlOptions): SparqlDeleteInsertPlan;
88
116
  /**