@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.
- package/config/bun.json +57 -11
- package/config/cloud.json +14 -12
- package/config/local.json +16 -14
- package/config/xpod.json +47 -9
- package/dist/api/matrix/PodMatrixStore.d.ts +4 -7
- package/dist/api/matrix/PodMatrixStore.js +116 -148
- package/dist/api/matrix/PodMatrixStore.js.map +1 -1
- package/dist/api/matrix/types.d.ts +2 -0
- package/dist/api/matrix/types.js.map +1 -1
- package/dist/api/runs/PiAgentRuntimeDriver.d.ts +1 -0
- package/dist/api/runs/PiAgentRuntimeDriver.js +4 -1
- package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
- package/dist/components/components.jsonld +3 -0
- package/dist/components/context.jsonld +71 -32
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -0
- package/dist/http/SubgraphSparqlHttpHandler.js +27 -4
- package/dist/http/SubgraphSparqlHttpHandler.js.map +1 -1
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +4 -0
- package/dist/http/vector/VectorHttpHandler.d.ts +5 -1
- package/dist/http/vector/VectorHttpHandler.js +5 -5
- package/dist/http/vector/VectorHttpHandler.js.map +1 -1
- package/dist/http/vector/VectorHttpHandler.jsonld +40 -28
- package/dist/index.d.ts +5 -2
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/Proxy.d.ts +3 -0
- package/dist/runtime/Proxy.js +31 -7
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/solidfs/LocalSolidFS.js +31 -124
- package/dist/solidfs/LocalSolidFS.js.map +1 -1
- package/dist/solidfs/SolidFsPathUtils.d.ts +13 -0
- package/dist/solidfs/SolidFsPathUtils.js +114 -0
- package/dist/solidfs/SolidFsPathUtils.js.map +1 -0
- package/dist/solidfs/SolidFsSyncJournal.d.ts +117 -0
- package/dist/solidfs/SolidFsSyncJournal.js +553 -0
- package/dist/solidfs/SolidFsSyncJournal.js.map +1 -0
- package/dist/solidfs/index.d.ts +1 -0
- package/dist/solidfs/index.js +1 -0
- package/dist/solidfs/index.js.map +1 -1
- package/dist/solidfs/types.d.ts +1 -0
- package/dist/solidfs/types.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +94 -33
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.d.ts +22 -5
- package/dist/storage/accessors/MixDataAccessor.js +376 -61
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +73 -5
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js +32 -10
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +28 -6
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/SolidRdfDataAccessor.d.ts +45 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js +277 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js.map +1 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.jsonld +161 -0
- package/dist/storage/rdf/Rdf3xIndex.d.ts +122 -0
- package/dist/storage/rdf/Rdf3xIndex.js +2695 -0
- package/dist/storage/rdf/Rdf3xIndex.js.map +1 -0
- package/dist/storage/rdf/Rdf3xIndex.jsonld +528 -0
- package/dist/storage/rdf/Rdf3xSchema.d.ts +20 -0
- package/dist/storage/rdf/Rdf3xSchema.js +65 -0
- package/dist/storage/rdf/Rdf3xSchema.js.map +1 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +10 -4
- package/dist/storage/rdf/RdfLocalQueryEngine.js +607 -127
- package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.d.ts +12 -1
- package/dist/storage/rdf/RdfQuadIndex.js +152 -22
- package/dist/storage/rdf/RdfQuadIndex.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.jsonld +36 -4
- package/dist/storage/rdf/RdfSparqlAdapter.d.ts +20 -2
- package/dist/storage/rdf/RdfSparqlAdapter.js +364 -40
- package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -1
- package/dist/storage/rdf/RdfSparqlAdapter.jsonld +60 -0
- package/dist/storage/rdf/RdfTermDictionary.d.ts +8 -0
- package/dist/storage/rdf/RdfTermDictionary.js +141 -70
- package/dist/storage/rdf/RdfTermDictionary.js.map +1 -1
- package/dist/storage/rdf/RdfTermDictionary.jsonld +24 -0
- package/dist/storage/rdf/RdfTextIndex.js +10 -3
- package/dist/storage/rdf/RdfTextIndex.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.d.ts +15 -6
- package/dist/storage/rdf/SolidRdfEngine.js +218 -25
- package/dist/storage/rdf/SolidRdfEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.jsonld +70 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +11 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.js +60 -47
- package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +9 -5
- package/dist/storage/rdf/index.d.ts +2 -2
- package/dist/storage/rdf/index.js +3 -3
- package/dist/storage/rdf/index.js.map +1 -1
- package/dist/storage/rdf/models-benchmark.d.ts +12 -1
- package/dist/storage/rdf/models-benchmark.js +549 -32
- package/dist/storage/rdf/models-benchmark.js.map +1 -1
- package/dist/storage/rdf/types.d.ts +81 -7
- package/dist/storage/rdf/types.js.map +1 -1
- package/dist/storage/sparql/CompatibilitySparqlEngine.d.ts +36 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js +96 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js.map +1 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.jsonld +123 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.d.ts +35 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js +112 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js.map +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -36
- package/dist/storage/sparql/SubgraphQueryEngine.js +2 -115
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +1 -124
- package/dist/terminal/AclPermissionService.d.ts +2 -1
- package/dist/terminal/AclPermissionService.js +26 -3
- package/dist/terminal/AclPermissionService.js.map +1 -1
- package/dist/terminal/TerminalSessionManager.js +25 -3
- package/dist/terminal/TerminalSessionManager.js.map +1 -1
- package/package.json +1 -1
- package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +0 -55
- package/dist/storage/rdf/Rdf3xTripleIndex.js +0 -1235
- package/dist/storage/rdf/Rdf3xTripleIndex.js.map +0 -1
|
@@ -10,6 +10,7 @@ const arrayify_stream_1 = __importDefault(require("arrayify-stream"));
|
|
|
10
10
|
const n3_1 = require("n3");
|
|
11
11
|
const jsonld_1 = __importDefault(require("jsonld"));
|
|
12
12
|
const rdf_parse_1 = require("rdf-parse");
|
|
13
|
+
const sparqljs_1 = require("sparqljs");
|
|
13
14
|
const community_server_1 = require("@solid/community-server");
|
|
14
15
|
const RdfSparqlAdapter_1 = require("../rdf/RdfSparqlAdapter");
|
|
15
16
|
const RdfContentTypes_1 = require("../rdf/RdfContentTypes");
|
|
@@ -20,7 +21,7 @@ const MetadataRequestContext_1 = require("../MetadataRequestContext");
|
|
|
20
21
|
/**
|
|
21
22
|
* MixDataAccessor - Routes data to appropriate storage based on content type
|
|
22
23
|
*
|
|
23
|
-
* - RDF data (internal/quads) -> structuredDataAccessor (
|
|
24
|
+
* - RDF data (internal/quads) -> structuredDataAccessor (Solid RDF engine by default)
|
|
24
25
|
* - RDF file mirrors (.ttl/.jsonld) -> rdfFileDataAccessor (local FileSystem)
|
|
25
26
|
* - Other data (binary, text, etc.) -> unstructuredDataAccessor (FileSystem, Minio, etc.)
|
|
26
27
|
*
|
|
@@ -179,16 +180,18 @@ class MixDataAccessor {
|
|
|
179
180
|
* Execute SPARQL UPDATE.
|
|
180
181
|
*
|
|
181
182
|
* Supported embedded deltas patch the local RDF authority file first and then
|
|
182
|
-
* rebuild the structured RDF index.
|
|
183
|
-
*
|
|
183
|
+
* rebuild the structured RDF index. The structured accessor decides whether
|
|
184
|
+
* unsupported shapes have an explicitly configured compatibility path.
|
|
184
185
|
*/
|
|
185
186
|
async executeSparqlUpdate(query, baseIri) {
|
|
186
187
|
if (baseIri) {
|
|
187
188
|
const identifier = { path: baseIri };
|
|
188
189
|
if (this.isByLineRdfIdentifier(identifier)) {
|
|
189
190
|
try {
|
|
190
|
-
await this.executeLocalRdfSparqlUpdate(query, identifier);
|
|
191
|
-
|
|
191
|
+
const writtenIdentifiers = await this.executeLocalRdfSparqlUpdate(query, identifier);
|
|
192
|
+
for (const writtenIdentifier of writtenIdentifiers) {
|
|
193
|
+
this.invalidateMetadataCache(writtenIdentifier);
|
|
194
|
+
}
|
|
192
195
|
return;
|
|
193
196
|
}
|
|
194
197
|
catch (error) {
|
|
@@ -210,62 +213,104 @@ class MixDataAccessor {
|
|
|
210
213
|
}
|
|
211
214
|
}
|
|
212
215
|
async executeLocalRdfSparqlUpdate(query, identifier) {
|
|
213
|
-
const
|
|
214
|
-
this.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
216
|
+
const parsed = new sparqljs_1.Parser({ baseIRI: identifier.path }).parse(query);
|
|
217
|
+
const delta = this.rdfSparqlAdapter.compileUpdateDelta(parsed, this.parentContainer(identifier).path, {
|
|
218
|
+
defaultGraph: identifier.path,
|
|
219
|
+
});
|
|
220
|
+
const writableGraphIris = this.localRdfDeltaWriteGraphIris(delta.operations);
|
|
221
|
+
const graphStates = await this.loadLocalRdfDeltaGraphs(delta.operations, writableGraphIris);
|
|
222
|
+
const graphQuads = new Map([...graphStates].map(([graphIri, state]) => [graphIri, state.quads]));
|
|
223
|
+
const nextQuadsByGraph = this.applyLocalRdfDelta(graphQuads, delta.operations, writableGraphIris);
|
|
224
|
+
const patches = writableGraphIris.map((graphIri) => {
|
|
225
|
+
const previous = graphStates.get(graphIri);
|
|
226
|
+
return {
|
|
227
|
+
identifier: { path: graphIri },
|
|
228
|
+
previousQuads: previous?.quads ?? [],
|
|
229
|
+
previousExists: previous?.existed ?? false,
|
|
230
|
+
nextQuads: nextQuadsByGraph.get(graphIri) ?? [],
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
await this.writeLocalRdfAuthorityPatches(patches);
|
|
234
|
+
return patches.map((patch) => patch.identifier);
|
|
235
|
+
}
|
|
236
|
+
applyLocalRdfDelta(graphQuads, operations, writableGraphIris) {
|
|
237
|
+
const writableGraphs = new Set(writableGraphIris);
|
|
238
|
+
const byGraph = new Map();
|
|
239
|
+
for (const [graphIri, quads] of graphQuads) {
|
|
240
|
+
byGraph.set(graphIri, new Map(quads.map((quad) => [this.quadKey(quad), quad])));
|
|
241
|
+
}
|
|
242
|
+
const currentQuads = () => [...byGraph.values()].flatMap((quads) => [...quads.values()]);
|
|
243
|
+
const writableQuads = (graphIri) => {
|
|
244
|
+
let quads = byGraph.get(graphIri);
|
|
245
|
+
if (!quads) {
|
|
246
|
+
quads = new Map();
|
|
247
|
+
byGraph.set(graphIri, quads);
|
|
248
|
+
}
|
|
249
|
+
return quads;
|
|
250
|
+
};
|
|
251
|
+
const deleteQuads = (quads) => {
|
|
252
|
+
for (const quad of quads) {
|
|
253
|
+
const target = writableQuads(this.localRdfWriteGraphIri(quad.graph, writableGraphs));
|
|
254
|
+
target.delete(this.quadKey(quad));
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
const insertQuads = (quads) => {
|
|
258
|
+
for (const quad of quads) {
|
|
259
|
+
const target = writableQuads(this.localRdfWriteGraphIri(quad.graph, writableGraphs));
|
|
260
|
+
target.set(this.quadKey(quad), quad);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
228
263
|
for (const operation of operations) {
|
|
229
264
|
if (operation.type === 'insert') {
|
|
230
|
-
|
|
231
|
-
byKey.set(this.quadKey(quad), quad);
|
|
232
|
-
}
|
|
265
|
+
insertQuads(operation.quads);
|
|
233
266
|
continue;
|
|
234
267
|
}
|
|
235
268
|
if (operation.type === 'delete') {
|
|
236
|
-
|
|
237
|
-
byKey.delete(this.quadKey(quad));
|
|
238
|
-
}
|
|
269
|
+
deleteQuads(operation.quads);
|
|
239
270
|
continue;
|
|
240
271
|
}
|
|
241
272
|
if (operation.type === 'insertDeleteWhere') {
|
|
242
|
-
const rows = this.queryLocalUpdateBindings(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
for (const quad of this.rdfSparqlAdapter.materializeDeleteWhere(operation.inserts, rows)) {
|
|
247
|
-
byKey.set(this.quadKey(quad), quad);
|
|
248
|
-
}
|
|
273
|
+
const rows = this.queryLocalUpdateBindings(currentQuads(), operation.query);
|
|
274
|
+
deleteQuads(this.rdfSparqlAdapter.materializeDeleteWhere(operation.deletes, rows));
|
|
275
|
+
insertQuads(this.rdfSparqlAdapter.materializeDeleteWhere(operation.inserts, rows));
|
|
249
276
|
continue;
|
|
250
277
|
}
|
|
251
278
|
if (operation.type === 'insertWhere') {
|
|
252
|
-
const rows = this.queryLocalUpdateBindings(
|
|
253
|
-
|
|
254
|
-
byKey.set(this.quadKey(quad), quad);
|
|
255
|
-
}
|
|
279
|
+
const rows = this.queryLocalUpdateBindings(currentQuads(), operation.query);
|
|
280
|
+
insertQuads(this.rdfSparqlAdapter.materializeDeleteWhere(operation.inserts, rows));
|
|
256
281
|
continue;
|
|
257
282
|
}
|
|
258
|
-
const rows = this.queryLocalUpdateBindings(
|
|
259
|
-
|
|
260
|
-
|
|
283
|
+
const rows = this.queryLocalUpdateBindings(currentQuads(), operation.query);
|
|
284
|
+
deleteQuads(this.rdfSparqlAdapter.materializeDeleteWhere(operation.template, rows));
|
|
285
|
+
}
|
|
286
|
+
return new Map(writableGraphIris.map((graphIri) => [graphIri, [...(byGraph.get(graphIri)?.values() ?? [])]]));
|
|
287
|
+
}
|
|
288
|
+
async loadLocalRdfDeltaGraphs(operations, writableGraphIris) {
|
|
289
|
+
const graphIris = this.localRdfDeltaGraphIris(operations, writableGraphIris);
|
|
290
|
+
const graphStates = new Map();
|
|
291
|
+
for (const graphIri of graphIris) {
|
|
292
|
+
const graphIdentifier = { path: graphIri };
|
|
293
|
+
if (!this.isByLineRdfIdentifier(graphIdentifier)) {
|
|
294
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports by-line local RDF graph documents');
|
|
261
295
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
296
|
+
const existing = await this.readLocalRdfState(graphIdentifier);
|
|
297
|
+
const graph = n3_1.DataFactory.namedNode(graphIri);
|
|
298
|
+
const quads = existing.text.length > 0
|
|
299
|
+
? await this.parseLocalRdf(graphIdentifier, existing.text, this.localRdfContentType(graphIdentifier))
|
|
300
|
+
.then((items) => items.map((quad) => this.toGraphQuad(quad, graph)))
|
|
301
|
+
: [];
|
|
302
|
+
graphStates.set(graphIri, { quads, existed: existing.existed });
|
|
303
|
+
}
|
|
304
|
+
return graphStates;
|
|
305
|
+
}
|
|
306
|
+
localRdfDeltaGraphIris(operations, writableGraphIris) {
|
|
307
|
+
const graphIris = new Set(writableGraphIris);
|
|
266
308
|
for (const operation of operations) {
|
|
267
309
|
const graphTerms = operation.type === 'deleteWhere'
|
|
268
|
-
?
|
|
310
|
+
? [
|
|
311
|
+
...operation.template.map((item) => item.graph),
|
|
312
|
+
...this.queryGraphTerms(operation.query),
|
|
313
|
+
]
|
|
269
314
|
: operation.type === 'insertDeleteWhere'
|
|
270
315
|
? [
|
|
271
316
|
...operation.deletes.map((item) => item.graph),
|
|
@@ -279,12 +324,64 @@ class MixDataAccessor {
|
|
|
279
324
|
]
|
|
280
325
|
: operation.quads.map((quad) => quad.graph);
|
|
281
326
|
for (const graph of graphTerms) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
327
|
+
this.addNamedGraphIris(graph, graphIris);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return [...graphIris];
|
|
331
|
+
}
|
|
332
|
+
localRdfDeltaWriteGraphIris(operations) {
|
|
333
|
+
const graphIris = new Set();
|
|
334
|
+
for (const operation of operations) {
|
|
335
|
+
if (operation.type === 'deleteWhere') {
|
|
336
|
+
this.addWritableTemplateGraphIris(operation.template.map((item) => item.graph), operation.query, graphIris);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (operation.type === 'insertDeleteWhere') {
|
|
340
|
+
this.addWritableTemplateGraphIris([
|
|
341
|
+
...operation.deletes.map((item) => item.graph),
|
|
342
|
+
...operation.inserts.map((item) => item.graph),
|
|
343
|
+
], operation.query, graphIris);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (operation.type === 'insertWhere') {
|
|
347
|
+
this.addWritableTemplateGraphIris(operation.inserts.map((item) => item.graph), operation.query, graphIris);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const graphTerms = operation.quads.map((quad) => quad.graph);
|
|
351
|
+
for (const graph of graphTerms) {
|
|
352
|
+
this.addWritableNamedGraphIri(graph, graphIris);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (graphIris.size === 0) {
|
|
356
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update requires explicit local RDF graph write targets');
|
|
357
|
+
}
|
|
358
|
+
return [...graphIris];
|
|
359
|
+
}
|
|
360
|
+
addWritableTemplateGraphIris(graphs, query, graphIris) {
|
|
361
|
+
for (const graph of graphs) {
|
|
362
|
+
if (this.isQueryVariable(graph)) {
|
|
363
|
+
this.addWritableGraphVariableIris(query, graph.variable, graphIris);
|
|
364
|
+
continue;
|
|
285
365
|
}
|
|
366
|
+
this.addWritableNamedGraphIri(graph, graphIris);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
addWritableGraphVariableIris(query, variable, graphIris) {
|
|
370
|
+
const values = new Set();
|
|
371
|
+
this.collectGraphVariableFilterIris(query, variable, values);
|
|
372
|
+
if (values.size === 0) {
|
|
373
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports finite GRAPH variable write targets');
|
|
374
|
+
}
|
|
375
|
+
for (const value of values) {
|
|
376
|
+
this.addWritableNamedGraphIri(n3_1.DataFactory.namedNode(value), graphIris);
|
|
286
377
|
}
|
|
287
378
|
}
|
|
379
|
+
localRdfWriteGraphIri(graph, writableGraphs) {
|
|
380
|
+
if (graph.termType !== 'NamedNode' || !writableGraphs.has(graph.value)) {
|
|
381
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update can only write declared local RDF graph documents');
|
|
382
|
+
}
|
|
383
|
+
return graph.value;
|
|
384
|
+
}
|
|
288
385
|
queryLocalUpdateBindings(quads, query) {
|
|
289
386
|
const index = new RdfQuadIndex_1.RdfQuadIndex({ path: ':memory:' });
|
|
290
387
|
index.open();
|
|
@@ -298,33 +395,194 @@ class MixDataAccessor {
|
|
|
298
395
|
}
|
|
299
396
|
}
|
|
300
397
|
queryGraphTerms(query) {
|
|
301
|
-
const
|
|
398
|
+
const graphTerms = [];
|
|
399
|
+
const graphVariables = new Set();
|
|
400
|
+
this.collectQueryGraphTerms(query, graphTerms, graphVariables);
|
|
401
|
+
this.collectGraphVariableFilterTerms(query, graphVariables, graphTerms);
|
|
402
|
+
return graphTerms;
|
|
403
|
+
}
|
|
404
|
+
collectQueryGraphTerms(query, graphTerms, graphVariables) {
|
|
405
|
+
for (const pattern of query.patterns) {
|
|
406
|
+
if (!pattern.graph) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
graphTerms.push(pattern.graph);
|
|
410
|
+
if (this.isQueryVariable(pattern.graph)) {
|
|
411
|
+
graphVariables.add(pattern.graph.variable);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
for (const optional of query.optional ?? []) {
|
|
415
|
+
this.collectQueryGraphTerms(Array.isArray(optional) ? { patterns: optional } : optional, graphTerms, graphVariables);
|
|
416
|
+
}
|
|
417
|
+
for (const union of query.unions ?? []) {
|
|
418
|
+
for (const branch of union.branches) {
|
|
419
|
+
this.collectQueryGraphTerms(branch, graphTerms, graphVariables);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
for (const minus of query.minus ?? []) {
|
|
423
|
+
this.collectQueryGraphTerms(minus, graphTerms, graphVariables);
|
|
424
|
+
}
|
|
425
|
+
for (const exists of query.exists ?? []) {
|
|
426
|
+
this.collectQueryGraphTerms(exists, graphTerms, graphVariables);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
collectGraphVariableFilterTerms(query, graphVariables, graphTerms) {
|
|
430
|
+
for (const filter of query.filters ?? []) {
|
|
431
|
+
if (!graphVariables.has(filter.variable)) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (filter.value && this.isRdfTerm(filter.value)) {
|
|
435
|
+
graphTerms.push(filter.value);
|
|
436
|
+
}
|
|
437
|
+
for (const value of filter.values ?? []) {
|
|
438
|
+
if (this.isRdfTerm(value)) {
|
|
439
|
+
graphTerms.push(value);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
this.collectGraphVariableValueTerms(query.values ?? [], graphVariables, graphTerms);
|
|
444
|
+
for (const optional of query.optional ?? []) {
|
|
445
|
+
if (!Array.isArray(optional)) {
|
|
446
|
+
this.collectGraphVariableFilterTerms(optional, graphVariables, graphTerms);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
for (const union of query.unions ?? []) {
|
|
450
|
+
for (const branch of union.branches) {
|
|
451
|
+
this.collectGraphVariableFilterTerms(branch, graphVariables, graphTerms);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
for (const minus of query.minus ?? []) {
|
|
455
|
+
this.collectGraphVariableFilterTerms(minus, graphVariables, graphTerms);
|
|
456
|
+
}
|
|
457
|
+
for (const exists of query.exists ?? []) {
|
|
458
|
+
this.collectGraphVariableFilterTerms(exists, graphVariables, graphTerms);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
collectGraphVariableFilterIris(query, variable, values) {
|
|
462
|
+
for (const filter of query.filters ?? []) {
|
|
463
|
+
if (filter.variable !== variable) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
if ((filter.operator === '$eq' || filter.operator === '$sameTerm') && filter.value && this.isRdfTerm(filter.value)) {
|
|
467
|
+
this.addGraphFilterValueIri(filter.value, values);
|
|
468
|
+
}
|
|
469
|
+
if (filter.operator === '$in') {
|
|
470
|
+
for (const value of filter.values ?? []) {
|
|
471
|
+
if (this.isRdfTerm(value)) {
|
|
472
|
+
this.addGraphFilterValueIri(value, values);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
this.collectGraphVariableValueIris(query.values ?? [], variable, values);
|
|
302
478
|
for (const optional of query.optional ?? []) {
|
|
303
|
-
|
|
479
|
+
if (!Array.isArray(optional)) {
|
|
480
|
+
this.collectGraphVariableFilterIris(optional, variable, values);
|
|
481
|
+
}
|
|
304
482
|
}
|
|
305
483
|
for (const union of query.unions ?? []) {
|
|
306
484
|
for (const branch of union.branches) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
485
|
+
this.collectGraphVariableFilterIris(branch, variable, values);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
for (const minus of query.minus ?? []) {
|
|
489
|
+
this.collectGraphVariableFilterIris(minus, variable, values);
|
|
490
|
+
}
|
|
491
|
+
for (const exists of query.exists ?? []) {
|
|
492
|
+
this.collectGraphVariableFilterIris(exists, variable, values);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
collectGraphVariableValueTerms(sources, graphVariables, graphTerms) {
|
|
496
|
+
for (const source of sources) {
|
|
497
|
+
for (const variable of source.variables) {
|
|
498
|
+
if (!graphVariables.has(variable)) {
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
for (const row of source.rows) {
|
|
502
|
+
const value = row[variable];
|
|
503
|
+
if (value) {
|
|
504
|
+
graphTerms.push(value);
|
|
505
|
+
}
|
|
310
506
|
}
|
|
311
507
|
}
|
|
312
508
|
}
|
|
313
|
-
return patterns.flatMap((pattern) => pattern.graph ? [pattern.graph] : []);
|
|
314
509
|
}
|
|
315
|
-
|
|
510
|
+
collectGraphVariableValueIris(sources, variable, values) {
|
|
511
|
+
for (const source of sources) {
|
|
512
|
+
if (!source.variables.includes(variable)) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
for (const row of source.rows) {
|
|
516
|
+
const value = row[variable];
|
|
517
|
+
if (value) {
|
|
518
|
+
this.addGraphFilterValueIri(value, values);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
addGraphFilterValueIri(value, values) {
|
|
524
|
+
if (value.termType !== 'NamedNode') {
|
|
525
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update GRAPH variable write targets must be named graph documents');
|
|
526
|
+
}
|
|
527
|
+
values.add(value.value);
|
|
528
|
+
}
|
|
529
|
+
addNamedGraphIris(graph, graphIris) {
|
|
530
|
+
if (this.isRdfTerm(graph)) {
|
|
531
|
+
if (graph.termType !== 'NamedNode') {
|
|
532
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports named graph documents');
|
|
533
|
+
}
|
|
534
|
+
graphIris.add(graph.value);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const values = graph.$in;
|
|
538
|
+
if (Array.isArray(values) && values.every((value) => this.isRdfTerm(value))) {
|
|
539
|
+
for (const value of values) {
|
|
540
|
+
if (value.termType !== 'NamedNode') {
|
|
541
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports named graph documents');
|
|
542
|
+
}
|
|
543
|
+
graphIris.add(value.value);
|
|
544
|
+
}
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
if (this.isQueryVariable(graph)) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports explicit local RDF graph documents');
|
|
551
|
+
}
|
|
552
|
+
addWritableNamedGraphIri(graph, graphIris) {
|
|
553
|
+
if (!this.isRdfTerm(graph) || graph.termType !== 'NamedNode') {
|
|
554
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports explicit local RDF graph write targets');
|
|
555
|
+
}
|
|
556
|
+
if (!this.isByLineRdfIdentifier({ path: graph.value })) {
|
|
557
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports by-line local RDF graph write targets');
|
|
558
|
+
}
|
|
559
|
+
graphIris.add(graph.value);
|
|
560
|
+
}
|
|
561
|
+
isQueryVariable(value) {
|
|
562
|
+
return Boolean(value && typeof value === 'object' && 'variable' in value);
|
|
563
|
+
}
|
|
564
|
+
isRdfTerm(value) {
|
|
565
|
+
return Boolean(value && typeof value === 'object' && 'termType' in value);
|
|
566
|
+
}
|
|
567
|
+
async readLocalRdfState(identifier) {
|
|
316
568
|
try {
|
|
317
|
-
return
|
|
569
|
+
return {
|
|
570
|
+
text: await this.readStreamText(await this.rdfFileDataAccessor.getData(identifier)),
|
|
571
|
+
existed: true,
|
|
572
|
+
};
|
|
318
573
|
}
|
|
319
574
|
catch (error) {
|
|
320
575
|
if (community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
321
576
|
await this.refreshLocalRdfMirror(identifier);
|
|
322
577
|
try {
|
|
323
|
-
return
|
|
578
|
+
return {
|
|
579
|
+
text: await this.readStreamText(await this.rdfFileDataAccessor.getData(identifier)),
|
|
580
|
+
existed: true,
|
|
581
|
+
};
|
|
324
582
|
}
|
|
325
583
|
catch (retryError) {
|
|
326
584
|
if (community_server_1.NotFoundHttpError.isInstance(retryError)) {
|
|
327
|
-
return '';
|
|
585
|
+
return { text: '', existed: false };
|
|
328
586
|
}
|
|
329
587
|
throw retryError;
|
|
330
588
|
}
|
|
@@ -336,6 +594,54 @@ class MixDataAccessor {
|
|
|
336
594
|
await this.ensureRdfFileParentContainers(identifier);
|
|
337
595
|
await this.rdfFileDataAccessor.writeDocument(identifier, (0, community_server_1.guardStream)(stream_1.Readable.from([await this.serializeQuadsForLocalFile(identifier, quads)])), this.createLocalRdfMetadata(identifier, new community_server_1.RepresentationMetadata(identifier)));
|
|
338
596
|
}
|
|
597
|
+
async writeLocalRdfAuthorityPatches(patches) {
|
|
598
|
+
const applied = [];
|
|
599
|
+
try {
|
|
600
|
+
for (const patch of patches) {
|
|
601
|
+
let localAuthorityWritten = false;
|
|
602
|
+
try {
|
|
603
|
+
const authorityQuads = patch.nextQuads.map((quad) => this.toDefaultGraphQuad(quad));
|
|
604
|
+
await this.writeLocalRdfAuthority(patch.identifier, authorityQuads);
|
|
605
|
+
localAuthorityWritten = true;
|
|
606
|
+
await this.writeStructuredRdfIndex(patch.identifier, authorityQuads, new community_server_1.RepresentationMetadata(patch.identifier));
|
|
607
|
+
applied.push(patch);
|
|
608
|
+
}
|
|
609
|
+
catch (error) {
|
|
610
|
+
if (localAuthorityWritten) {
|
|
611
|
+
applied.push(patch);
|
|
612
|
+
}
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
catch (error) {
|
|
618
|
+
await this.rollbackLocalRdfAuthorityPatches(applied);
|
|
619
|
+
throw error;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
async rollbackLocalRdfAuthorityPatches(patches) {
|
|
623
|
+
const failures = [];
|
|
624
|
+
for (const patch of patches.slice().reverse()) {
|
|
625
|
+
try {
|
|
626
|
+
if (patch.previousExists) {
|
|
627
|
+
const authorityQuads = patch.previousQuads.map((quad) => this.toDefaultGraphQuad(quad));
|
|
628
|
+
await this.writeLocalRdfAuthority(patch.identifier, authorityQuads);
|
|
629
|
+
await this.writeStructuredRdfIndex(patch.identifier, authorityQuads, new community_server_1.RepresentationMetadata(patch.identifier));
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
await this.deleteRdfFileResourceIfPresent(patch.identifier);
|
|
633
|
+
await this.deleteLocalRdfIndex(patch.identifier);
|
|
634
|
+
}
|
|
635
|
+
this.invalidateMetadataCache(patch.identifier);
|
|
636
|
+
}
|
|
637
|
+
catch (rollbackError) {
|
|
638
|
+
failures.push(`${patch.identifier.path}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
if (failures.length > 0) {
|
|
642
|
+
this.logger.warn(`Failed to fully roll back local RDF authority patch: ${failures.join('; ')}`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
339
645
|
toDefaultGraphQuad(quad) {
|
|
340
646
|
return n3_1.DataFactory.quad(quad.subject, quad.predicate, quad.object);
|
|
341
647
|
}
|
|
@@ -447,9 +753,18 @@ class MixDataAccessor {
|
|
|
447
753
|
}
|
|
448
754
|
}
|
|
449
755
|
async getExistingLocalRdfMetadata(identifier) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
756
|
+
try {
|
|
757
|
+
const metadata = await this.rdfFileDataAccessor.getMetadata(identifier);
|
|
758
|
+
metadata.contentType = this.localRdfContentType(identifier);
|
|
759
|
+
return metadata;
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
if (community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
763
|
+
throw error;
|
|
764
|
+
}
|
|
765
|
+
this.logger.warn(`Ignoring unreadable local RDF metadata for ${identifier.path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
766
|
+
return this.createLocalRdfMetadata(identifier, new community_server_1.RepresentationMetadata(identifier));
|
|
767
|
+
}
|
|
453
768
|
}
|
|
454
769
|
createLocalRdfMetadata(identifier, metadata) {
|
|
455
770
|
const localMetadata = new community_server_1.RepresentationMetadata(metadata);
|