@undefineds.co/xpod 0.3.18 → 0.3.23

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 (115) hide show
  1. package/config/bun.json +57 -11
  2. package/config/cloud.json +14 -12
  3. package/config/local.json +16 -14
  4. package/config/xpod.json +47 -9
  5. package/dist/api/matrix/PodMatrixStore.d.ts +4 -7
  6. package/dist/api/matrix/PodMatrixStore.js +116 -148
  7. package/dist/api/matrix/PodMatrixStore.js.map +1 -1
  8. package/dist/api/matrix/types.d.ts +2 -0
  9. package/dist/api/matrix/types.js.map +1 -1
  10. package/dist/api/runs/PiAgentRuntimeDriver.d.ts +1 -0
  11. package/dist/api/runs/PiAgentRuntimeDriver.js +4 -1
  12. package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
  13. package/dist/components/components.jsonld +3 -0
  14. package/dist/components/context.jsonld +71 -32
  15. package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -0
  16. package/dist/http/SubgraphSparqlHttpHandler.js +27 -4
  17. package/dist/http/SubgraphSparqlHttpHandler.js.map +1 -1
  18. package/dist/http/SubgraphSparqlHttpHandler.jsonld +4 -0
  19. package/dist/http/vector/VectorHttpHandler.d.ts +5 -1
  20. package/dist/http/vector/VectorHttpHandler.js +5 -5
  21. package/dist/http/vector/VectorHttpHandler.js.map +1 -1
  22. package/dist/http/vector/VectorHttpHandler.jsonld +40 -28
  23. package/dist/index.d.ts +5 -2
  24. package/dist/index.js +9 -4
  25. package/dist/index.js.map +1 -1
  26. package/dist/runtime/Proxy.d.ts +3 -0
  27. package/dist/runtime/Proxy.js +31 -7
  28. package/dist/runtime/Proxy.js.map +1 -1
  29. package/dist/solidfs/LocalSolidFS.js +31 -124
  30. package/dist/solidfs/LocalSolidFS.js.map +1 -1
  31. package/dist/solidfs/SolidFsPathUtils.d.ts +13 -0
  32. package/dist/solidfs/SolidFsPathUtils.js +114 -0
  33. package/dist/solidfs/SolidFsPathUtils.js.map +1 -0
  34. package/dist/solidfs/SolidFsSyncJournal.d.ts +117 -0
  35. package/dist/solidfs/SolidFsSyncJournal.js +553 -0
  36. package/dist/solidfs/SolidFsSyncJournal.js.map +1 -0
  37. package/dist/solidfs/index.d.ts +1 -0
  38. package/dist/solidfs/index.js +1 -0
  39. package/dist/solidfs/index.js.map +1 -1
  40. package/dist/solidfs/types.d.ts +1 -0
  41. package/dist/solidfs/types.js.map +1 -1
  42. package/dist/storage/SparqlUpdateResourceStore.js +94 -33
  43. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  44. package/dist/storage/accessors/MixDataAccessor.d.ts +22 -5
  45. package/dist/storage/accessors/MixDataAccessor.js +376 -61
  46. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  47. package/dist/storage/accessors/MixDataAccessor.jsonld +73 -5
  48. package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js +32 -10
  49. package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js.map +1 -1
  50. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +28 -6
  51. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
  52. package/dist/storage/accessors/SolidRdfDataAccessor.d.ts +45 -0
  53. package/dist/storage/accessors/SolidRdfDataAccessor.js +277 -0
  54. package/dist/storage/accessors/SolidRdfDataAccessor.js.map +1 -0
  55. package/dist/storage/accessors/SolidRdfDataAccessor.jsonld +161 -0
  56. package/dist/storage/rdf/Rdf3xIndex.d.ts +122 -0
  57. package/dist/storage/rdf/Rdf3xIndex.js +2695 -0
  58. package/dist/storage/rdf/Rdf3xIndex.js.map +1 -0
  59. package/dist/storage/rdf/Rdf3xIndex.jsonld +528 -0
  60. package/dist/storage/rdf/Rdf3xSchema.d.ts +20 -0
  61. package/dist/storage/rdf/Rdf3xSchema.js +65 -0
  62. package/dist/storage/rdf/Rdf3xSchema.js.map +1 -0
  63. package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +10 -4
  64. package/dist/storage/rdf/RdfLocalQueryEngine.js +607 -127
  65. package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -1
  66. package/dist/storage/rdf/RdfQuadIndex.d.ts +12 -1
  67. package/dist/storage/rdf/RdfQuadIndex.js +152 -22
  68. package/dist/storage/rdf/RdfQuadIndex.js.map +1 -1
  69. package/dist/storage/rdf/RdfQuadIndex.jsonld +36 -4
  70. package/dist/storage/rdf/RdfSparqlAdapter.d.ts +20 -2
  71. package/dist/storage/rdf/RdfSparqlAdapter.js +364 -40
  72. package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -1
  73. package/dist/storage/rdf/RdfSparqlAdapter.jsonld +60 -0
  74. package/dist/storage/rdf/RdfTermDictionary.d.ts +8 -0
  75. package/dist/storage/rdf/RdfTermDictionary.js +141 -70
  76. package/dist/storage/rdf/RdfTermDictionary.js.map +1 -1
  77. package/dist/storage/rdf/RdfTermDictionary.jsonld +24 -0
  78. package/dist/storage/rdf/RdfTextIndex.js +10 -3
  79. package/dist/storage/rdf/RdfTextIndex.js.map +1 -1
  80. package/dist/storage/rdf/SolidRdfEngine.d.ts +15 -6
  81. package/dist/storage/rdf/SolidRdfEngine.js +218 -25
  82. package/dist/storage/rdf/SolidRdfEngine.js.map +1 -1
  83. package/dist/storage/rdf/SolidRdfEngine.jsonld +70 -7
  84. package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +11 -7
  85. package/dist/storage/rdf/SolidRdfSparqlEngine.js +60 -47
  86. package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -1
  87. package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +9 -5
  88. package/dist/storage/rdf/index.d.ts +2 -2
  89. package/dist/storage/rdf/index.js +3 -3
  90. package/dist/storage/rdf/index.js.map +1 -1
  91. package/dist/storage/rdf/models-benchmark.d.ts +12 -1
  92. package/dist/storage/rdf/models-benchmark.js +549 -32
  93. package/dist/storage/rdf/models-benchmark.js.map +1 -1
  94. package/dist/storage/rdf/types.d.ts +81 -7
  95. package/dist/storage/rdf/types.js.map +1 -1
  96. package/dist/storage/sparql/CompatibilitySparqlEngine.d.ts +36 -0
  97. package/dist/storage/sparql/CompatibilitySparqlEngine.js +96 -0
  98. package/dist/storage/sparql/CompatibilitySparqlEngine.js.map +1 -0
  99. package/dist/storage/sparql/CompatibilitySparqlEngine.jsonld +123 -0
  100. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.d.ts +35 -0
  101. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js +112 -0
  102. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js.map +1 -0
  103. package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -36
  104. package/dist/storage/sparql/SubgraphQueryEngine.js +2 -115
  105. package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
  106. package/dist/storage/sparql/SubgraphQueryEngine.jsonld +1 -124
  107. package/dist/terminal/AclPermissionService.d.ts +2 -1
  108. package/dist/terminal/AclPermissionService.js +26 -3
  109. package/dist/terminal/AclPermissionService.js.map +1 -1
  110. package/dist/terminal/TerminalSessionManager.js +25 -3
  111. package/dist/terminal/TerminalSessionManager.js.map +1 -1
  112. package/package.json +1 -1
  113. package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +0 -55
  114. package/dist/storage/rdf/Rdf3xTripleIndex.js +0 -1235
  115. package/dist/storage/rdf/Rdf3xTripleIndex.js.map +0 -1
@@ -68,13 +68,14 @@ class RdfSparqlAdapter {
68
68
  describeTargets,
69
69
  };
70
70
  }
71
- compileUpdateDelta(query, basePath) {
71
+ compileUpdateDelta(query, basePath, options = {}) {
72
72
  const parsed = typeof query === 'string'
73
73
  ? new sparqljs_1.Parser({ baseIRI: basePath }).parse(query)
74
74
  : query;
75
75
  if (parsed.type !== 'update') {
76
76
  throw new UnsupportedSparqlQueryError('Only SPARQL UPDATE can compile into update delta');
77
77
  }
78
+ const defaultGraph = this.compileUpdateDefaultGraph(options.defaultGraph, basePath);
78
79
  const operations = [];
79
80
  for (const update of parsed.updates) {
80
81
  if (!('updateType' in update)) {
@@ -87,7 +88,7 @@ class RdfSparqlAdapter {
87
88
  }
88
89
  operations.push({
89
90
  type: 'insert',
90
- quads: this.compileUpdateGraphQuads(update.insert, basePath),
91
+ quads: this.compileUpdateGraphQuads(update.insert, basePath, defaultGraph),
91
92
  });
92
93
  break;
93
94
  case 'delete':
@@ -96,17 +97,17 @@ class RdfSparqlAdapter {
96
97
  }
97
98
  operations.push({
98
99
  type: 'delete',
99
- quads: this.compileUpdateGraphQuads(update.delete, basePath),
100
+ quads: this.compileUpdateGraphQuads(update.delete, basePath, defaultGraph),
100
101
  });
101
102
  break;
102
103
  case 'deletewhere':
103
104
  if (update.graph) {
104
105
  throw new UnsupportedSparqlQueryError('SPARQL UPDATE WITH/default graph scope fallback to compatibility engine');
105
106
  }
106
- operations.push(this.compileDeleteWhere(update.delete, basePath));
107
+ operations.push(this.compileDeleteWhere(update.delete, basePath, defaultGraph));
107
108
  break;
108
109
  case 'insertdelete':
109
- operations.push(this.compileInsertDeleteWhere(update, basePath));
110
+ operations.push(this.compileInsertDeleteWhere(update, basePath, defaultGraph));
110
111
  break;
111
112
  default:
112
113
  throw new UnsupportedSparqlQueryError('Unsupported SPARQL UPDATE operation fallback to compatibility engine');
@@ -136,15 +137,15 @@ class RdfSparqlAdapter {
136
137
  }
137
138
  return { operations, inserts, deletes };
138
139
  }
139
- compileDeleteWhere(items, basePath) {
140
- const template = this.compileGraphQuadsTemplate(items, basePath, 'DELETE WHERE');
140
+ compileDeleteWhere(items, basePath, defaultGraph) {
141
+ const template = this.compileGraphQuadsTemplate(items, basePath, 'DELETE WHERE', defaultGraph);
141
142
  return {
142
143
  type: 'deleteWhere',
143
144
  query: this.queryFromUpdateTemplate(template, 'DELETE WHERE'),
144
145
  template,
145
146
  };
146
147
  }
147
- compileInsertDeleteWhere(update, basePath) {
148
+ compileInsertDeleteWhere(update, basePath, defaultGraph) {
148
149
  const hasInsertTemplate = (update.insert?.length ?? 0) > 0;
149
150
  const hasDeleteTemplate = (update.delete?.length ?? 0) > 0;
150
151
  if (!hasInsertTemplate && !hasDeleteTemplate) {
@@ -155,7 +156,7 @@ class RdfSparqlAdapter {
155
156
  : hasInsertTemplate
156
157
  ? 'INSERT WHERE'
157
158
  : 'DELETE WHERE';
158
- const withGraph = this.compileWithGraph(update.graph, basePath, label);
159
+ const withGraph = this.compileWithGraph(update.graph, basePath, label) ?? defaultGraph;
159
160
  const using = this.compileUsingDatasetScope(update.using, basePath, label);
160
161
  const queryDefaultGraph = using.hasUsing
161
162
  ? using.defaultGraph ?? this.impossibleGraph(basePath)
@@ -167,14 +168,15 @@ class RdfSparqlAdapter {
167
168
  defaultGraph: queryDefaultGraph,
168
169
  namedGraph: queryNamedGraph,
169
170
  });
171
+ const graphVariables = this.safeUpdateTemplateGraphVariables(query);
170
172
  const inserts = hasInsertTemplate
171
- ? this.compileGraphQuadsTemplate(update.insert ?? [], basePath, 'INSERT template', withGraph)
173
+ ? this.compileGraphQuadsTemplate(update.insert ?? [], basePath, 'INSERT template', withGraph, { graphVariables })
172
174
  : [];
173
175
  if (hasInsertTemplate && inserts.length === 0) {
174
176
  throw new UnsupportedSparqlQueryError(`${label} without INSERT template fallback to compatibility engine`);
175
177
  }
176
178
  const deletes = hasDeleteTemplate
177
- ? this.compileGraphQuadsTemplate(update.delete ?? [], basePath, 'DELETE template', withGraph)
179
+ ? this.compileGraphQuadsTemplate(update.delete ?? [], basePath, 'DELETE template', withGraph, { graphVariables })
178
180
  : [];
179
181
  if (hasDeleteTemplate && deletes.length === 0) {
180
182
  throw new UnsupportedSparqlQueryError(`${label} without DELETE template fallback to compatibility engine`);
@@ -230,7 +232,9 @@ class RdfSparqlAdapter {
230
232
  }
231
233
  compileQueryDatasetScope(from, basePath) {
232
234
  if (!from) {
233
- return {};
235
+ return {
236
+ defaultGraph: this.compileImplicitQueryDefaultGraph(basePath),
237
+ };
234
238
  }
235
239
  const defaultGraphs = from.default ?? [];
236
240
  const namedGraphs = from.named ?? [];
@@ -239,12 +243,15 @@ class RdfSparqlAdapter {
239
243
  ? this.compileQueryDatasetGraphs(defaultGraphs, basePath, 'FROM')
240
244
  : namedGraphs.length > 0
241
245
  ? this.impossibleGraph(basePath)
242
- : undefined,
246
+ : this.compileImplicitQueryDefaultGraph(basePath),
243
247
  namedGraph: namedGraphs.length > 0
244
248
  ? this.compileQueryDatasetGraphs(namedGraphs, basePath, 'FROM NAMED')
245
249
  : undefined,
246
250
  };
247
251
  }
252
+ compileImplicitQueryDefaultGraph(basePath) {
253
+ return implicitQueryDefaultGraph(basePath);
254
+ }
248
255
  compileQueryDatasetGraphs(graphs, basePath, clause) {
249
256
  const compiledGraphs = graphs.map((graph) => {
250
257
  const compiled = this.compileGraphTerm(graph, basePath);
@@ -287,6 +294,7 @@ class RdfSparqlAdapter {
287
294
  state.assertBindVariablesSafe();
288
295
  state.assertValuesVariablesBoundByRequiredPatterns();
289
296
  state.assertDependentGroupsShareRequiredVariables();
297
+ this.assertFiniteUpdateGraphVariables(state.query, basePath, label);
290
298
  if (state.query.patterns.length === 0 && (state.query.unions?.length ?? 0) === 0) {
291
299
  throw new UnsupportedSparqlQueryError(`${label} without required graph BGP patterns fallback to compatibility engine`);
292
300
  }
@@ -307,24 +315,32 @@ class RdfSparqlAdapter {
307
315
  filters: [],
308
316
  };
309
317
  }
310
- compileGraphQuadsTemplate(items, basePath, label, defaultGraph) {
318
+ compileGraphQuadsTemplate(items, basePath, label, defaultGraph, options = {}) {
311
319
  const template = [];
312
320
  for (const item of items) {
313
321
  let graph = defaultGraph;
314
322
  if (item.type === 'graph') {
315
- if (item.name.termType !== 'NamedNode') {
323
+ if (item.name.termType === 'Variable') {
324
+ if (!options.graphVariables?.has(item.name.value)) {
325
+ throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
326
+ }
327
+ graph = (0, RdfLocalQueryEngine_1.variable)(item.name.value);
328
+ }
329
+ else if (item.name.termType !== 'NamedNode') {
316
330
  throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
317
331
  }
318
- graph = this.compileGraphTerm(item.name, basePath) ?? undefined;
332
+ else {
333
+ graph = this.compileGraphTerm(item.name, basePath) ?? undefined;
334
+ }
319
335
  }
320
336
  else if (!graph) {
321
337
  throw new UnsupportedSparqlQueryError(`${label} default graph fallback to compatibility engine`);
322
338
  }
323
- if (!graph || graph === null || isCompiledVariable(graph)) {
339
+ if (!graph || graph === null) {
324
340
  throw new UnsupportedSparqlQueryError(`${label} graph outside basePath fallback to compatibility engine`);
325
341
  }
326
342
  const state = new CompileState(basePath);
327
- for (const triple of item.triples) {
343
+ for (const triple of this.updateTemplateTriples(item)) {
328
344
  if (!isSimpleTerm(triple.predicate)) {
329
345
  throw new UnsupportedSparqlQueryError(`${label} property path templates fallback to compatibility engine`);
330
346
  }
@@ -344,6 +360,75 @@ class RdfSparqlAdapter {
344
360
  }
345
361
  return template;
346
362
  }
363
+ safeUpdateTemplateGraphVariables(query) {
364
+ const graphVariables = new Set();
365
+ this.collectQueryGraphVariables(query, graphVariables);
366
+ if (graphVariables.size === 0) {
367
+ return graphVariables;
368
+ }
369
+ const constrainedVariables = new Set();
370
+ this.collectFiniteGraphFilterVariables(query, graphVariables, constrainedVariables);
371
+ return constrainedVariables;
372
+ }
373
+ collectQueryGraphVariables(query, graphVariables) {
374
+ for (const pattern of query.patterns) {
375
+ if (pattern.graph && isCompiledVariable(pattern.graph)) {
376
+ graphVariables.add(pattern.graph.variable);
377
+ }
378
+ }
379
+ for (const optional of query.optional ?? []) {
380
+ this.collectQueryGraphVariables(Array.isArray(optional) ? { patterns: optional } : optional, graphVariables);
381
+ }
382
+ for (const union of query.unions ?? []) {
383
+ for (const branch of union.branches) {
384
+ this.collectQueryGraphVariables(branch, graphVariables);
385
+ }
386
+ }
387
+ for (const minus of query.minus ?? []) {
388
+ this.collectQueryGraphVariables(minus, graphVariables);
389
+ }
390
+ for (const exists of query.exists ?? []) {
391
+ this.collectQueryGraphVariables(exists, graphVariables);
392
+ }
393
+ }
394
+ collectFiniteGraphFilterVariables(query, graphVariables, constrainedVariables) {
395
+ this.collectFiniteGraphValueVariables(query.values ?? [], graphVariables, constrainedVariables, (value) => (this.isNamedNodeFilterValue(value)));
396
+ for (const filter of query.filters ?? []) {
397
+ if (!graphVariables.has(filter.variable)) {
398
+ continue;
399
+ }
400
+ const values = filter.values ?? (filter.value ? [filter.value] : []);
401
+ if ((filter.operator === '$eq' || filter.operator === '$sameTerm' || filter.operator === '$in')
402
+ && values.length > 0
403
+ && values.every((value) => this.isNamedNodeFilterValue(value))) {
404
+ constrainedVariables.add(filter.variable);
405
+ }
406
+ }
407
+ for (const optional of query.optional ?? []) {
408
+ this.collectFiniteGraphFilterVariables(Array.isArray(optional) ? { patterns: optional } : optional, graphVariables, constrainedVariables);
409
+ }
410
+ for (const union of query.unions ?? []) {
411
+ for (const branch of union.branches) {
412
+ this.collectFiniteGraphFilterVariables(branch, graphVariables, constrainedVariables);
413
+ }
414
+ }
415
+ for (const minus of query.minus ?? []) {
416
+ this.collectFiniteGraphFilterVariables(minus, graphVariables, constrainedVariables);
417
+ }
418
+ for (const exists of query.exists ?? []) {
419
+ this.collectFiniteGraphFilterVariables(exists, graphVariables, constrainedVariables);
420
+ }
421
+ }
422
+ isNamedNodeFilterValue(value) {
423
+ return Boolean(value && typeof value === 'object' && 'termType' in value && value.termType === 'NamedNode');
424
+ }
425
+ updateTemplateTriples(item) {
426
+ if ('triples' in item && Array.isArray(item.triples)) {
427
+ return item.triples;
428
+ }
429
+ const patterns = item.patterns ?? [];
430
+ return patterns.flatMap((pattern) => pattern.type === 'bgp' ? pattern.triples : []);
431
+ }
347
432
  assertSafeUpdateTemplatePattern(pattern, label) {
348
433
  const terms = [pattern.subject, pattern.predicate, pattern.object];
349
434
  if (terms.some((term) => term && 'termType' in term && term.termType === 'BlankNode')) {
@@ -358,9 +443,6 @@ class RdfSparqlAdapter {
358
443
  switch (pattern.type) {
359
444
  case 'graph':
360
445
  if (pattern.name.termType === 'Variable') {
361
- if (!namedGraph) {
362
- throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
363
- }
364
446
  }
365
447
  else if (pattern.name.termType !== 'NamedNode') {
366
448
  throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
@@ -395,11 +477,76 @@ class RdfSparqlAdapter {
395
477
  }
396
478
  }
397
479
  }
398
- compileUpdateGraphQuads(items, basePath) {
480
+ assertFiniteUpdateGraphVariables(query, basePath, label) {
481
+ const unboundedVariables = new Set();
482
+ this.collectUnboundedUpdateGraphVariables(query, basePath, new Set(), unboundedVariables);
483
+ if (unboundedVariables.size > 0) {
484
+ throw new UnsupportedSparqlQueryError(`${label} GRAPH variables require finite named graph filters fallback to compatibility engine`);
485
+ }
486
+ }
487
+ collectUnboundedUpdateGraphVariables(query, basePath, inheritedFiniteVariables, unboundedVariables) {
488
+ const finiteVariables = new Set(inheritedFiniteVariables);
489
+ this.collectFiniteGraphValueVariables(query.values ?? [], undefined, finiteVariables, (value) => (this.isBasePathNamedNodeFilterValue(value, basePath)));
490
+ this.collectFiniteGraphFilterVariablesFromFilters(query.filters ?? [], finiteVariables, basePath);
491
+ for (const pattern of query.patterns) {
492
+ if (pattern.graph && isCompiledVariable(pattern.graph) && !finiteVariables.has(pattern.graph.variable)) {
493
+ unboundedVariables.add(pattern.graph.variable);
494
+ }
495
+ }
496
+ for (const optional of query.optional ?? []) {
497
+ this.collectUnboundedUpdateGraphVariables(Array.isArray(optional) ? { patterns: optional } : optional, basePath, finiteVariables, unboundedVariables);
498
+ }
499
+ for (const union of query.unions ?? []) {
500
+ for (const branch of union.branches) {
501
+ this.collectUnboundedUpdateGraphVariables(branch, basePath, finiteVariables, unboundedVariables);
502
+ }
503
+ }
504
+ for (const minus of query.minus ?? []) {
505
+ this.collectUnboundedUpdateGraphVariables(minus, basePath, finiteVariables, unboundedVariables);
506
+ }
507
+ for (const exists of query.exists ?? []) {
508
+ this.collectUnboundedUpdateGraphVariables(exists, basePath, finiteVariables, unboundedVariables);
509
+ }
510
+ }
511
+ collectFiniteGraphFilterVariablesFromFilters(filters, finiteVariables, basePath) {
512
+ for (const filter of filters) {
513
+ const values = filter.values ?? (filter.value ? [filter.value] : []);
514
+ if ((filter.operator === '$eq' || filter.operator === '$sameTerm' || filter.operator === '$in')
515
+ && values.length > 0
516
+ && values.every((value) => this.isBasePathNamedNodeFilterValue(value, basePath))) {
517
+ finiteVariables.add(filter.variable);
518
+ }
519
+ }
520
+ }
521
+ isBasePathNamedNodeFilterValue(value, basePath) {
522
+ return this.isNamedNodeFilterValue(value) && value.value.startsWith(basePath);
523
+ }
524
+ collectFiniteGraphValueVariables(sources, graphVariables, finiteVariables, isSafeValue) {
525
+ for (const source of sources) {
526
+ if (source.rows.length === 0) {
527
+ continue;
528
+ }
529
+ for (const variable of source.variables) {
530
+ if (graphVariables && !graphVariables.has(variable)) {
531
+ continue;
532
+ }
533
+ if (source.rows.every((row) => isSafeValue(row[variable]))) {
534
+ finiteVariables.add(variable);
535
+ }
536
+ }
537
+ }
538
+ }
539
+ compileUpdateGraphQuads(items, basePath, defaultGraph) {
399
540
  const quads = [];
400
541
  for (const item of items) {
401
542
  if (item.type !== 'graph') {
402
- throw new UnsupportedSparqlQueryError('SPARQL UPDATE default graph fallback to compatibility engine');
543
+ if (!defaultGraph) {
544
+ throw new UnsupportedSparqlQueryError('SPARQL UPDATE default graph fallback to compatibility engine');
545
+ }
546
+ for (const triple of item.triples) {
547
+ quads.push(this.compileUpdateTriple(triple, defaultGraph));
548
+ }
549
+ continue;
403
550
  }
404
551
  if (item.name.termType !== 'NamedNode') {
405
552
  throw new UnsupportedSparqlQueryError('SPARQL UPDATE GRAPH variables fallback to compatibility engine');
@@ -407,12 +554,24 @@ class RdfSparqlAdapter {
407
554
  if (!item.name.value.startsWith(basePath)) {
408
555
  throw new UnsupportedSparqlQueryError('SPARQL UPDATE graph outside basePath fallback to compatibility engine');
409
556
  }
410
- for (const triple of item.triples) {
557
+ for (const triple of this.updateTemplateTriples(item)) {
411
558
  quads.push(this.compileUpdateTriple(triple, item.name));
412
559
  }
413
560
  }
414
561
  return quads;
415
562
  }
563
+ compileUpdateDefaultGraph(defaultGraph, basePath) {
564
+ if (!defaultGraph) {
565
+ return undefined;
566
+ }
567
+ const graph = typeof defaultGraph === 'string'
568
+ ? n3_1.DataFactory.namedNode(defaultGraph)
569
+ : defaultGraph;
570
+ if (basePath && !graph.value.startsWith(basePath)) {
571
+ throw new UnsupportedSparqlQueryError('SPARQL UPDATE default graph outside basePath fallback to compatibility engine');
572
+ }
573
+ return graph;
574
+ }
416
575
  compileUpdateTriple(triple, graph) {
417
576
  const subject = this.compileUpdateNamedNode(triple.subject, 'subject');
418
577
  const predicate = this.compileUpdateNamedNode(triple.predicate, 'predicate');
@@ -523,15 +682,13 @@ class RdfSparqlAdapter {
523
682
  this.compilePatterns(this.unionBranchPatterns(branch), graph, branchState, false, namedGraphScope);
524
683
  branchState.assertBindVariablesSafe();
525
684
  branchState.assertValuesVariablesBoundByRequiredPatterns();
526
- if (branchState.query.unions?.length) {
527
- throw new UnsupportedSparqlQueryError('Nested UNION fallback to compatibility engine');
528
- }
529
- if (branchState.query.patterns.length === 0) {
685
+ if (branchState.query.patterns.length === 0 && (branchState.query.unions?.length ?? 0) === 0) {
530
686
  throw new UnsupportedSparqlQueryError('UNION branch without required BGP fallback to compatibility engine');
531
687
  }
532
688
  return [{
533
689
  patterns: branchState.query.patterns,
534
690
  ...(branchState.query.values?.length ? { values: branchState.query.values } : {}),
691
+ ...(branchState.query.unions?.length ? { unions: branchState.query.unions } : {}),
535
692
  ...(branchState.query.optional?.length ? { optional: branchState.query.optional } : {}),
536
693
  ...(branchState.query.binds?.length ? { binds: branchState.query.binds } : {}),
537
694
  ...(branchState.query.filters?.length ? { filters: branchState.query.filters } : {}),
@@ -623,22 +780,22 @@ class RdfSparqlAdapter {
623
780
  return;
624
781
  }
625
782
  if (pattern.name.termType === 'Variable') {
626
- if (optional) {
627
- throw new UnsupportedSparqlQueryError('OPTIONAL GRAPH variable scope fallback to compatibility engine');
628
- }
629
- if (namedGraphScope) {
630
- state.query.filters?.push({
783
+ const graphScopeFilter = namedGraphScope
784
+ ? {
631
785
  variable: pattern.name.value,
632
786
  operator: '$in',
633
787
  values: this.graphScopeFilterValues(namedGraphScope),
634
- });
635
- }
636
- else {
637
- state.query.filters?.push({
788
+ }
789
+ : {
638
790
  variable: pattern.name.value,
639
791
  operator: '$startsWith',
640
792
  value: state.basePath,
641
- });
793
+ };
794
+ if (optional) {
795
+ state.addOptionalFilters([graphScopeFilter]);
796
+ }
797
+ else {
798
+ state.query.filters?.push(graphScopeFilter);
642
799
  }
643
800
  }
644
801
  this.compilePatterns(pattern.patterns, graph, state, optional, namedGraphScope);
@@ -730,6 +887,20 @@ class RdfSparqlAdapter {
730
887
  expression: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
731
888
  };
732
889
  }
890
+ if (operator === 'coalesce') {
891
+ return {
892
+ type: 'coalesce',
893
+ expressions: normalized.args.map((arg) => (this.compileBindExpression(this.expressionArg(arg), basePath))),
894
+ };
895
+ }
896
+ if (operator === 'if') {
897
+ return {
898
+ type: 'if',
899
+ condition: this.compileFilter(this.expressionArg(normalized.args[0])),
900
+ then: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
901
+ else: this.compileBindExpression(this.expressionArg(normalized.args[2]), basePath),
902
+ };
903
+ }
733
904
  if (operator === 'substr' || operator === 'substring') {
734
905
  return {
735
906
  type: 'substring',
@@ -753,6 +924,20 @@ class RdfSparqlAdapter {
753
924
  base: basePath,
754
925
  };
755
926
  }
927
+ if (operator === 'strdt') {
928
+ return {
929
+ type: 'strdt',
930
+ lexical: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
931
+ datatype: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
932
+ };
933
+ }
934
+ if (operator === 'strlang') {
935
+ return {
936
+ type: 'strlang',
937
+ lexical: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
938
+ language: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
939
+ };
940
+ }
756
941
  throw new UnsupportedSparqlQueryError(`${label} ${operator} fallback to compatibility engine`);
757
942
  }
758
943
  compileTriple(triple, graph, state) {
@@ -1014,6 +1199,7 @@ class RdfSparqlAdapter {
1014
1199
  }
1015
1200
  const variables = [];
1016
1201
  const visibleVariables = visibleSelectVariables(query);
1202
+ state.setVisibleSolutionVariables(visibleVariables);
1017
1203
  for (const variable of query.variables) {
1018
1204
  if (isSelectVariableTerm(variable)) {
1019
1205
  variables.push(variable.value);
@@ -1065,6 +1251,9 @@ class RdfSparqlAdapter {
1065
1251
  as,
1066
1252
  variable,
1067
1253
  distinct: aggregate.distinct,
1254
+ ...(type === 'count' && aggregate.distinct && !variable
1255
+ ? { distinctVariables: state.visibleSolutionVariables }
1256
+ : {}),
1068
1257
  };
1069
1258
  }
1070
1259
  aggregateType(aggregation) {
@@ -1204,6 +1393,9 @@ class RdfSparqlAdapter {
1204
1393
  as: state.nextHavingAggregateVariable(),
1205
1394
  variable,
1206
1395
  distinct: expression.distinct,
1396
+ ...(type === 'count' && expression.distinct && !variable
1397
+ ? { distinctVariables: state.visibleSolutionVariables }
1398
+ : {}),
1207
1399
  };
1208
1400
  localQuery.aggregates = [...(localQuery.aggregates ?? []), hiddenAggregate];
1209
1401
  return hiddenAggregate.as;
@@ -1317,6 +1509,10 @@ class RdfSparqlAdapter {
1317
1509
  if (!Array.isArray(values)) {
1318
1510
  throw new UnsupportedSparqlQueryError('FILTER IN tuple fallback to compatibility engine');
1319
1511
  }
1512
+ const functionFilter = this.compileFunctionInFilter(this.expressionArg(expression.args[0]), values, operator === 'notin');
1513
+ if (functionFilter) {
1514
+ return [functionFilter];
1515
+ }
1320
1516
  const operand = this.stringOperandVariable(this.expressionArg(expression.args[0]));
1321
1517
  return [{
1322
1518
  variable: operand.variable,
@@ -1578,6 +1774,31 @@ class RdfSparqlAdapter {
1578
1774
  }
1579
1775
  return null;
1580
1776
  }
1777
+ compileFunctionInFilter(functionExpression, values, negated) {
1778
+ if (!isOperationExpression(functionExpression)) {
1779
+ return null;
1780
+ }
1781
+ const functionOperator = functionExpression.operator.toLowerCase();
1782
+ if (functionOperator === 'lang') {
1783
+ return {
1784
+ variable: this.expressionVariable(this.expressionArg(functionExpression.args[0])),
1785
+ operator: negated ? '$notLangIn' : '$langIn',
1786
+ values: values.map((value) => this.literalString(value)),
1787
+ };
1788
+ }
1789
+ if (functionOperator === 'datatype') {
1790
+ const datatypeValues = values.map((value) => this.filterValue(value));
1791
+ if (datatypeValues.some((value) => !isNamedNodeTerm(value))) {
1792
+ throw new UnsupportedSparqlQueryError('DATATYPE FILTER values must be IRIs locally');
1793
+ }
1794
+ return {
1795
+ variable: this.expressionVariable(this.expressionArg(functionExpression.args[0])),
1796
+ operator: negated ? '$notDatatypeIn' : '$datatypeIn',
1797
+ values: datatypeValues,
1798
+ };
1799
+ }
1800
+ return null;
1801
+ }
1581
1802
  stringLengthVariableOrUndefined(expression) {
1582
1803
  const normalized = this.normalizeFunctionCallExpression(expression);
1583
1804
  if (!isOperationExpression(normalized) || normalized.operator.toLowerCase() !== 'strlen') {
@@ -1686,6 +1907,17 @@ class RdfSparqlAdapter {
1686
1907
  value: false,
1687
1908
  }];
1688
1909
  }
1910
+ const termTest = this.compileTermTestFilter(operator, expression);
1911
+ if (termTest) {
1912
+ return [this.negateTermTestFilter(termTest)];
1913
+ }
1914
+ if (operator === 'langmatches') {
1915
+ const filter = this.compileLangMatchesFilter(expression);
1916
+ return [{
1917
+ ...filter,
1918
+ operator: '$notLangMatches',
1919
+ }];
1920
+ }
1689
1921
  if (operator === '||') {
1690
1922
  const filter = this.compileOrFilter(expression);
1691
1923
  return [{
@@ -1702,6 +1934,10 @@ class RdfSparqlAdapter {
1702
1934
  if (!Array.isArray(values)) {
1703
1935
  throw new UnsupportedSparqlQueryError('FILTER negated IN tuple fallback to compatibility engine');
1704
1936
  }
1937
+ const functionFilter = this.compileFunctionInFilter(this.expressionArg(expression.args[0]), values, operator === 'in');
1938
+ if (functionFilter) {
1939
+ return [functionFilter];
1940
+ }
1705
1941
  const operand = this.stringOperandVariable(this.expressionArg(expression.args[0]));
1706
1942
  return [{
1707
1943
  variable: operand.variable,
@@ -1710,6 +1946,18 @@ class RdfSparqlAdapter {
1710
1946
  values: values.map((value) => this.filterValue(value)),
1711
1947
  }];
1712
1948
  }
1949
+ const stringOperator = this.stringFilter(operator);
1950
+ if (stringOperator) {
1951
+ const [left, right, flags] = expression.args;
1952
+ const leftOperand = this.stringOperandVariable(this.expressionArg(left));
1953
+ return [{
1954
+ variable: leftOperand.variable,
1955
+ operator: this.negatedStringFilter(stringOperator),
1956
+ operand: leftOperand.operand,
1957
+ value: this.literalString(this.expressionArg(right)),
1958
+ flags: operator === 'regex' && flags ? this.literalString(this.expressionArg(flags)) : undefined,
1959
+ }];
1960
+ }
1713
1961
  throw new UnsupportedSparqlQueryError(`FILTER !${operator} fallback to compatibility engine`);
1714
1962
  }
1715
1963
  expressionArg(value) {
@@ -1806,6 +2054,36 @@ class RdfSparqlAdapter {
1806
2054
  return null;
1807
2055
  }
1808
2056
  }
2057
+ negatedStringFilter(operator) {
2058
+ switch (operator) {
2059
+ case '$startsWith':
2060
+ return '$notStartsWith';
2061
+ case '$contains':
2062
+ return '$notContains';
2063
+ case '$endsWith':
2064
+ return '$notEndsWith';
2065
+ case '$regex':
2066
+ return '$notRegex';
2067
+ default:
2068
+ throw new UnsupportedSparqlQueryError(`FILTER !${operator} fallback to compatibility engine`);
2069
+ }
2070
+ }
2071
+ negateTermTestFilter(filter) {
2072
+ switch (filter.operator) {
2073
+ case '$termType':
2074
+ return {
2075
+ ...filter,
2076
+ operator: '$notTermType',
2077
+ };
2078
+ case '$sameTerm':
2079
+ return {
2080
+ ...filter,
2081
+ operator: '$notSameTerm',
2082
+ };
2083
+ default:
2084
+ throw new UnsupportedSparqlQueryError(`FILTER !${filter.operator} fallback to compatibility engine`);
2085
+ }
2086
+ }
1809
2087
  normalizeFunctionCallExpression(expression) {
1810
2088
  if (!isFunctionCallExpression(expression)) {
1811
2089
  return expression;
@@ -1875,6 +2153,9 @@ class CompileState {
1875
2153
  this.orderVariableIndex = 0;
1876
2154
  this.havingAggregateVariableIndex = 0;
1877
2155
  }
2156
+ setVisibleSolutionVariables(variables) {
2157
+ this.visibleSolutionVariables = variables;
2158
+ }
1878
2159
  addPattern(pattern, optional) {
1879
2160
  if (optional) {
1880
2161
  this.currentOptionalFrame().patterns.push(this.scopePattern(pattern));
@@ -2012,6 +2293,9 @@ class CompileState {
2012
2293
  for (const variableName of variablesInPatterns(branch.patterns)) {
2013
2294
  bound.add(variableName);
2014
2295
  }
2296
+ for (const variableName of variablesInUnionGroups(branch.unions ?? [])) {
2297
+ bound.add(variableName);
2298
+ }
2015
2299
  for (const bind of branch.binds ?? []) {
2016
2300
  for (const dependency of variablesInBindExpression(bind.expression)) {
2017
2301
  if (!bound.has(dependency)) {
@@ -2061,7 +2345,7 @@ class CompileState {
2061
2345
  return queryBindsVariableInRequiredShape(this.query, variableName);
2062
2346
  }
2063
2347
  scopePattern(pattern) {
2064
- return pattern.graph ? pattern : { ...pattern, graph: { $startsWith: this.basePath } };
2348
+ return pattern.graph ? pattern : { ...pattern, graph: implicitQueryDefaultGraph(this.basePath) };
2065
2349
  }
2066
2350
  currentOptionalFrame() {
2067
2351
  const frame = this.peekOptionalFrame();
@@ -2074,6 +2358,11 @@ class CompileState {
2074
2358
  return this.optionalStack[this.optionalStack.length - 1];
2075
2359
  }
2076
2360
  }
2361
+ function implicitQueryDefaultGraph(basePath) {
2362
+ return basePath.endsWith('/')
2363
+ ? { $startsWith: basePath }
2364
+ : n3_1.DataFactory.namedNode(basePath);
2365
+ }
2077
2366
  function isVariableTerm(value) {
2078
2367
  return Boolean(value && 'termType' in value && value.termType === 'Variable');
2079
2368
  }
@@ -2284,6 +2573,7 @@ function variablesInUnionGroups(unions) {
2284
2573
  return unique(unions.flatMap((unionGroup) => (unionGroup.branches.flatMap((branch) => [
2285
2574
  ...variablesInPatterns(branch.patterns),
2286
2575
  ...variablesInValuesSources(branch.values ?? []),
2576
+ ...variablesInUnionGroups(branch.unions ?? []),
2287
2577
  ...((branch.binds ?? []).map((bind) => bind.variable)),
2288
2578
  ]))));
2289
2579
  }
@@ -2326,6 +2616,14 @@ function variablesInBindExpression(expression) {
2326
2616
  case 'lowerCase':
2327
2617
  case 'upperCase':
2328
2618
  return variablesInBindExpression(expression.expression);
2619
+ case 'coalesce':
2620
+ return unique(expression.expressions.flatMap((item) => variablesInBindExpression(item)));
2621
+ case 'if':
2622
+ return unique([
2623
+ ...variablesInFilters(expression.condition),
2624
+ ...variablesInBindExpression(expression.then),
2625
+ ...variablesInBindExpression(expression.else),
2626
+ ]);
2329
2627
  case 'substring':
2330
2628
  return unique([
2331
2629
  ...variablesInBindExpression(expression.expression),
@@ -2336,12 +2634,28 @@ function variablesInBindExpression(expression) {
2336
2634
  return unique(expression.expressions.flatMap((item) => variablesInBindExpression(item)));
2337
2635
  case 'iri':
2338
2636
  return variablesInBindExpression(expression.expression);
2637
+ case 'strdt':
2638
+ return unique([
2639
+ ...variablesInBindExpression(expression.lexical),
2640
+ ...variablesInBindExpression(expression.datatype),
2641
+ ]);
2642
+ case 'strlang':
2643
+ return unique([
2644
+ ...variablesInBindExpression(expression.lexical),
2645
+ ...variablesInBindExpression(expression.language),
2646
+ ]);
2339
2647
  default: {
2340
2648
  const exhaustive = expression;
2341
2649
  return exhaustive;
2342
2650
  }
2343
2651
  }
2344
2652
  }
2653
+ function variablesInFilters(filters) {
2654
+ return unique(filters.flatMap((filter) => [
2655
+ filter.variable,
2656
+ filter.variable2,
2657
+ ].filter((value) => Boolean(value))));
2658
+ }
2345
2659
  function assertOptionalBindVariablesSafe(rawOptionalGroup, outerBound) {
2346
2660
  const optionalGroup = normalizeOptionalGroupForAdapter(rawOptionalGroup);
2347
2661
  const optionalBound = new Set(outerBound);
@@ -2360,6 +2674,9 @@ function assertOptionalBindVariablesSafe(rawOptionalGroup, outerBound) {
2360
2674
  for (const variableName of variablesInValuesSources(branch.values ?? [])) {
2361
2675
  branchBound.add(variableName);
2362
2676
  }
2677
+ for (const variableName of variablesInUnionGroups(branch.unions ?? [])) {
2678
+ branchBound.add(variableName);
2679
+ }
2363
2680
  for (const bind of branch.binds ?? []) {
2364
2681
  assertBindDependenciesBound(bind, branchBound);
2365
2682
  branchBound.add(bind.variable);
@@ -2412,7 +2729,14 @@ function queryBindsVariableInRequiredShape(query, variableName) {
2412
2729
  if ((query.unions?.length ?? 0) === 0) {
2413
2730
  return false;
2414
2731
  }
2415
- return (query.unions ?? []).every((group) => (group.branches.every((branch) => patternsBindVariable(branch.patterns, variableName))));
2732
+ return (query.unions ?? []).every((group) => (group.branches.every((branch) => unionBranchBindsVariable(branch, variableName))));
2733
+ }
2734
+ function unionBranchBindsVariable(branch, variableName) {
2735
+ if (patternsBindVariable(branch.patterns, variableName)) {
2736
+ return true;
2737
+ }
2738
+ const unions = branch.unions ?? [];
2739
+ return unions.length > 0 && unions.every((group) => (group.branches.every((nestedBranch) => unionBranchBindsVariable(nestedBranch, variableName))));
2416
2740
  }
2417
2741
  function normalizeOptionalGroupForAdapter(group) {
2418
2742
  return Array.isArray(group) ? { patterns: group } : group;