@undefineds.co/xpod 0.3.5 → 0.3.14
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/cli.json +1 -1
- package/config/cloud.json +54 -22
- package/config/local.json +56 -12
- package/config/resolver.json +10 -2
- package/config/xpod.base.json +50 -0
- package/config/xpod.json +8 -8
- package/dist/agents/config/resolve.js +10 -10
- package/dist/agents/config/resolve.js.map +1 -1
- package/dist/api/chatkit/index.d.ts +1 -1
- package/dist/api/chatkit/index.js.map +1 -1
- package/dist/api/chatkit/pod-store.d.ts +14 -11
- package/dist/api/chatkit/pod-store.js +114 -78
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
- package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
- package/dist/api/chatkit/service.js +1 -1
- package/dist/api/chatkit/service.js.map +1 -1
- package/dist/api/chatkit/types.d.ts +11 -11
- package/dist/api/chatkit/types.js +3 -3
- package/dist/api/chatkit/types.js.map +1 -1
- package/dist/api/container/cloud.js +0 -8
- package/dist/api/container/cloud.js.map +1 -1
- package/dist/api/container/index.js +2 -1
- package/dist/api/container/index.js.map +1 -1
- package/dist/api/container/local.js +0 -7
- package/dist/api/container/local.js.map +1 -1
- package/dist/api/container/routes.js +3 -17
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +0 -2
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/PodManagementHandler.d.ts +3 -0
- package/dist/api/handlers/PodManagementHandler.js +71 -1
- package/dist/api/handlers/PodManagementHandler.js.map +1 -1
- package/dist/api/handlers/RunHandler.js +5 -5
- package/dist/api/handlers/RunHandler.js.map +1 -1
- package/dist/api/runs/AgentRuntimeTypes.d.ts +7 -8
- package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
- package/dist/api/runs/InngestRunExecutionBackend.d.ts +2 -2
- package/dist/api/runs/ManagedRunWorker.d.ts +1 -1
- package/dist/api/runs/ManagedRunWorker.js +6 -6
- package/dist/api/runs/ManagedRunWorker.js.map +1 -1
- package/dist/api/runs/PiAgentRuntimeDriver.d.ts +16 -1
- package/dist/api/runs/PiAgentRuntimeDriver.js +182 -23
- package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
- package/dist/api/runs/RunStateCenter.d.ts +3 -3
- package/dist/api/runs/RunStateCenter.js +13 -13
- package/dist/api/runs/RunStateCenter.js.map +1 -1
- package/dist/api/runs/store.d.ts +4 -4
- package/dist/api/runs/store.js +2 -2
- package/dist/api/runs/store.js.map +1 -1
- package/dist/api/service/VectorStoreService.d.ts +1 -1
- package/dist/api/service/VectorStoreService.js +16 -16
- package/dist/api/service/VectorStoreService.js.map +1 -1
- package/dist/api/tasks/InngestTaskScheduler.d.ts +4 -4
- package/dist/api/tasks/TaskMaterializer.d.ts +3 -3
- package/dist/api/tasks/TaskMaterializer.js +11 -11
- package/dist/api/tasks/TaskMaterializer.js.map +1 -1
- package/dist/api/tasks/TaskService.d.ts +3 -3
- package/dist/api/tasks/TaskService.js +11 -7
- package/dist/api/tasks/TaskService.js.map +1 -1
- package/dist/api/tasks/store.d.ts +10 -4
- package/dist/api/tasks/store.js +14 -4
- package/dist/api/tasks/store.js.map +1 -1
- package/dist/api/workspace/types.d.ts +3 -3
- package/dist/api/workspace/types.js +6 -6
- package/dist/api/workspace/types.js.map +1 -1
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/start.js +9 -3
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/components/components.jsonld +8 -2
- package/dist/components/context.jsonld +302 -51
- package/dist/http/search/SearchHttpHandler.js +8 -8
- package/dist/http/search/SearchHttpHandler.js.map +1 -1
- package/dist/identity/drizzle/PodLookupRepository.d.ts +11 -1
- package/dist/identity/drizzle/PodLookupRepository.js +95 -4
- package/dist/identity/drizzle/PodLookupRepository.js.map +1 -1
- package/dist/identity/drizzle/db.js +4 -43
- package/dist/identity/drizzle/db.js.map +1 -1
- package/dist/identity/drizzle/schema.pg.d.ts +0 -5
- package/dist/identity/drizzle/schema.pg.js +2 -16
- package/dist/identity/drizzle/schema.pg.js.map +1 -1
- package/dist/identity/drizzle/schema.sqlite.d.ts +19 -176
- package/dist/identity/drizzle/schema.sqlite.js +2 -16
- package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.d.ts +4 -4
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +7 -7
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
- package/dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld +6 -6
- package/dist/identity/oidc/AutoDetectOidcHandler.d.ts +4 -4
- package/dist/identity/oidc/AutoDetectOidcHandler.js +6 -6
- package/dist/identity/oidc/AutoDetectOidcHandler.js.map +1 -1
- package/dist/identity/oidc/AutoDetectOidcHandler.jsonld +6 -6
- package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +37 -0
- package/dist/identity/oidc/ScopedPickWebIdHandler.js +211 -0
- package/dist/identity/oidc/ScopedPickWebIdHandler.js.map +1 -0
- package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +158 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +16 -4
- package/dist/index.js.map +1 -1
- package/dist/main.js +8 -2
- package/dist/main.js.map +1 -1
- package/dist/provision/ProvisionPodCreator.d.ts +3 -4
- package/dist/provision/ProvisionPodCreator.js +8 -13
- package/dist/provision/ProvisionPodCreator.js.map +1 -1
- package/dist/provision/ProvisionPodCreator.jsonld +7 -7
- package/dist/runtime/Proxy.d.ts +0 -1
- package/dist/runtime/Proxy.js +0 -9
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts +1 -0
- package/dist/runtime/bootstrap.js +5 -2
- package/dist/runtime/bootstrap.js.map +1 -1
- package/dist/runtime/css-process.d.ts +12 -4
- package/dist/runtime/css-process.js +61 -14
- package/dist/runtime/css-process.js.map +1 -1
- package/dist/runtime/oidc-issuer.d.ts +3 -2
- package/dist/runtime/oidc-issuer.js +3 -2
- package/dist/runtime/oidc-issuer.js.map +1 -1
- package/dist/runtime/runtime-types.d.ts +1 -0
- package/dist/runtime/runtime-types.js.map +1 -1
- package/dist/solidfs/LocalFirstRdfRepresentationResolver.d.ts +21 -0
- package/dist/solidfs/LocalFirstRdfRepresentationResolver.js +38 -0
- package/dist/solidfs/LocalFirstRdfRepresentationResolver.js.map +1 -0
- package/dist/solidfs/LocalSolidFS.d.ts +18 -0
- package/dist/solidfs/LocalSolidFS.js +539 -0
- package/dist/solidfs/LocalSolidFS.js.map +1 -0
- package/dist/solidfs/PodSolidFsHttpClient.d.ts +16 -0
- package/dist/solidfs/PodSolidFsHttpClient.js +93 -0
- package/dist/solidfs/PodSolidFsHttpClient.js.map +1 -0
- package/dist/solidfs/PodSolidFsHydrator.d.ts +27 -0
- package/dist/solidfs/PodSolidFsHydrator.js +127 -0
- package/dist/solidfs/PodSolidFsHydrator.js.map +1 -0
- package/dist/solidfs/PodSolidFsSyncer.d.ts +21 -0
- package/dist/solidfs/PodSolidFsSyncer.js +78 -0
- package/dist/solidfs/PodSolidFsSyncer.js.map +1 -0
- package/dist/solidfs/RdfIndexSolidFsSyncer.d.ts +22 -0
- package/dist/solidfs/RdfIndexSolidFsSyncer.js +131 -0
- package/dist/solidfs/RdfIndexSolidFsSyncer.js.map +1 -0
- package/dist/solidfs/index.d.ts +7 -0
- package/dist/solidfs/index.js +24 -0
- package/dist/solidfs/index.js.map +1 -0
- package/dist/solidfs/types.d.ts +131 -0
- package/dist/solidfs/types.js +19 -0
- package/dist/solidfs/types.js.map +1 -0
- package/dist/storage/RepresentationPartialConvertingStore.js +6 -13
- package/dist/storage/RepresentationPartialConvertingStore.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.d.ts +4 -0
- package/dist/storage/SparqlUpdateResourceStore.js +13 -0
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.jsonld +26 -0
- package/dist/storage/accessors/MinioDataAccessor.d.ts +2 -0
- package/dist/storage/accessors/MinioDataAccessor.js +13 -7
- package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MinioDataAccessor.jsonld +8 -0
- package/dist/storage/accessors/MixDataAccessor.d.ts +85 -4
- package/dist/storage/accessors/MixDataAccessor.js +511 -16
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +176 -1
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.d.ts +7 -0
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +72 -4
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.jsonld +24 -0
- package/dist/storage/quint/BaseQuintStore.d.ts +3 -0
- package/dist/storage/quint/BaseQuintStore.js +51 -27
- package/dist/storage/quint/BaseQuintStore.js.map +1 -1
- package/dist/storage/quint/PgQuintStore.d.ts +1 -0
- package/dist/storage/quint/PgQuintStore.js +50 -32
- package/dist/storage/quint/PgQuintStore.js.map +1 -1
- package/dist/storage/quint/PgQuintStore.jsonld +4 -3
- package/dist/storage/quint/SqliteQuintStore.d.ts +5 -0
- package/dist/storage/quint/SqliteQuintStore.js +100 -0
- package/dist/storage/quint/SqliteQuintStore.js.map +1 -1
- package/dist/storage/quint/SqliteQuintStore.jsonld +20 -0
- package/dist/storage/quint/types.d.ts +16 -0
- package/dist/storage/quint/types.js.map +1 -1
- package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +55 -0
- package/dist/storage/rdf/Rdf3xTripleIndex.js +1235 -0
- package/dist/storage/rdf/Rdf3xTripleIndex.js.map +1 -0
- package/dist/storage/rdf/RdfContentTypes.d.ts +9 -0
- package/dist/storage/rdf/RdfContentTypes.js +79 -0
- package/dist/storage/rdf/RdfContentTypes.js.map +1 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +76 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.js +2636 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -0
- package/dist/storage/rdf/RdfQuadIndex.d.ts +98 -0
- package/dist/storage/rdf/RdfQuadIndex.js +1840 -0
- package/dist/storage/rdf/RdfQuadIndex.js.map +1 -0
- package/dist/storage/rdf/RdfQuadIndex.jsonld +416 -0
- package/dist/storage/rdf/RdfShadowComparator.d.ts +12 -0
- package/dist/storage/rdf/RdfShadowComparator.js +47 -0
- package/dist/storage/rdf/RdfShadowComparator.js.map +1 -0
- package/dist/storage/rdf/RdfSparqlAdapter.d.ts +147 -0
- package/dist/storage/rdf/RdfSparqlAdapter.js +2420 -0
- package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -0
- package/dist/storage/rdf/RdfSparqlAdapter.jsonld +414 -0
- package/dist/storage/rdf/RdfTermDictionary.d.ts +27 -0
- package/dist/storage/rdf/RdfTermDictionary.js +352 -0
- package/dist/storage/rdf/RdfTermDictionary.js.map +1 -0
- package/dist/storage/rdf/RdfTermDictionary.jsonld +114 -0
- package/dist/storage/rdf/RdfTermSemantics.d.ts +6 -0
- package/dist/storage/rdf/RdfTermSemantics.js +40 -0
- package/dist/storage/rdf/RdfTermSemantics.js.map +1 -0
- package/dist/storage/rdf/RdfTextIndex.d.ts +23 -0
- package/dist/storage/rdf/RdfTextIndex.js +569 -0
- package/dist/storage/rdf/RdfTextIndex.js.map +1 -0
- package/dist/storage/rdf/RdfVectorIndex.d.ts +22 -0
- package/dist/storage/rdf/RdfVectorIndex.js +631 -0
- package/dist/storage/rdf/RdfVectorIndex.js.map +1 -0
- package/dist/storage/rdf/RdfXmlSerializer.d.ts +2 -0
- package/dist/storage/rdf/RdfXmlSerializer.js +123 -0
- package/dist/storage/rdf/RdfXmlSerializer.js.map +1 -0
- package/dist/storage/rdf/ShadowRdfQuintStore.d.ts +58 -0
- package/dist/storage/rdf/ShadowRdfQuintStore.js +202 -0
- package/dist/storage/rdf/ShadowRdfQuintStore.js.map +1 -0
- package/dist/storage/rdf/ShadowRdfQuintStore.jsonld +308 -0
- package/dist/storage/rdf/SolidRdfEngine.d.ts +51 -0
- package/dist/storage/rdf/SolidRdfEngine.js +264 -0
- package/dist/storage/rdf/SolidRdfEngine.js.map +1 -0
- package/dist/storage/rdf/SolidRdfEngine.jsonld +338 -0
- package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +92 -0
- package/dist/storage/rdf/SolidRdfSparqlEngine.js +477 -0
- package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -0
- package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +257 -0
- package/dist/storage/rdf/index.d.ts +15 -0
- package/dist/storage/rdf/index.js +61 -0
- package/dist/storage/rdf/index.js.map +1 -0
- package/dist/storage/rdf/models-benchmark.d.ts +260 -0
- package/dist/storage/rdf/models-benchmark.js +1405 -0
- package/dist/storage/rdf/models-benchmark.js.map +1 -0
- package/dist/storage/rdf/types.d.ts +726 -0
- package/dist/storage/rdf/types.js +3 -0
- package/dist/storage/rdf/types.js.map +1 -0
- package/dist/storage/rdf/types.jsonld +316 -0
- package/dist/storage/vector/VectorIndexingListener.d.ts +5 -5
- package/dist/storage/vector/VectorIndexingListener.js +19 -19
- package/dist/storage/vector/VectorIndexingListener.js.map +1 -1
- package/package.json +3 -2
- package/templates/pod/acp/.acr.hbs +39 -0
- package/templates/pod/acp/README.acr +18 -0
- package/templates/pod/acp/profile/card.acr +22 -0
- package/templates/pod/base/README$.md.hbs +27 -0
- package/templates/pod/base/profile/card$.ttl.hbs +13 -0
- package/templates/pod/wac/.acl.hbs +26 -0
- package/templates/pod/wac/README.acl.hbs +14 -0
- package/templates/pod/wac/profile/card.acl.hbs +19 -0
- package/dist/api/handlers/WebIdProfileHandler.d.ts +0 -16
- package/dist/api/handlers/WebIdProfileHandler.js +0 -423
- package/dist/api/handlers/WebIdProfileHandler.js.map +0 -1
- package/dist/identity/drizzle/WebIdProfileRepository.d.ts +0 -63
- package/dist/identity/drizzle/WebIdProfileRepository.js +0 -168
- package/dist/identity/drizzle/WebIdProfileRepository.js.map +0 -1
- package/dist/identity/drizzle/WebIdProfileRepository.jsonld +0 -112
- package/dist/storage/quint/BaseQuintStore.jsonld +0 -257
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.MixDataAccessor = void 0;
|
|
7
|
+
const stream_1 = require("stream");
|
|
4
8
|
const global_logger_factory_1 = require("global-logger-factory");
|
|
9
|
+
const arrayify_stream_1 = __importDefault(require("arrayify-stream"));
|
|
10
|
+
const n3_1 = require("n3");
|
|
11
|
+
const jsonld_1 = __importDefault(require("jsonld"));
|
|
12
|
+
const rdf_parse_1 = require("rdf-parse");
|
|
5
13
|
const community_server_1 = require("@solid/community-server");
|
|
14
|
+
const RdfSparqlAdapter_1 = require("../rdf/RdfSparqlAdapter");
|
|
15
|
+
const RdfContentTypes_1 = require("../rdf/RdfContentTypes");
|
|
16
|
+
const RdfQuadIndex_1 = require("../rdf/RdfQuadIndex");
|
|
17
|
+
const RdfXmlSerializer_1 = require("../rdf/RdfXmlSerializer");
|
|
18
|
+
const SolidRdfEngine_1 = require("../rdf/SolidRdfEngine");
|
|
6
19
|
const MetadataRequestContext_1 = require("../MetadataRequestContext");
|
|
7
20
|
/**
|
|
8
21
|
* MixDataAccessor - Routes data to appropriate storage based on content type
|
|
9
22
|
*
|
|
10
23
|
* - RDF data (internal/quads) -> structuredDataAccessor (Quadstore or QuintStore)
|
|
24
|
+
* - RDF file mirrors (.ttl/.jsonld) -> rdfFileDataAccessor (local FileSystem)
|
|
11
25
|
* - Other data (binary, text, etc.) -> unstructuredDataAccessor (FileSystem, Minio, etc.)
|
|
12
26
|
*
|
|
13
27
|
* This uses composition instead of inheritance, allowing any DataAccessor
|
|
14
28
|
* to be used as the RDF storage backend.
|
|
15
29
|
*/
|
|
16
30
|
class MixDataAccessor {
|
|
17
|
-
constructor(structuredDataAccessor, unstructuredDataAccessor, presignedRedirectEnabled = false, mirrorContainersToUnstructured = true) {
|
|
31
|
+
constructor(structuredDataAccessor, unstructuredDataAccessor, presignedRedirectEnabled = false, mirrorContainersToUnstructured = true, rdfFileDataAccessor = unstructuredDataAccessor) {
|
|
18
32
|
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
33
|
+
this.rdfSparqlAdapter = new RdfSparqlAdapter_1.RdfSparqlAdapter();
|
|
19
34
|
this.structuredDataAccessor = structuredDataAccessor;
|
|
20
35
|
this.unstructuredDataAccessor = unstructuredDataAccessor;
|
|
36
|
+
this.rdfFileDataAccessor = rdfFileDataAccessor;
|
|
21
37
|
this.presignedRedirectEnabled = presignedRedirectEnabled;
|
|
22
38
|
this.mirrorContainersToUnstructured = mirrorContainersToUnstructured;
|
|
23
39
|
}
|
|
@@ -50,6 +66,51 @@ class MixDataAccessor {
|
|
|
50
66
|
}
|
|
51
67
|
return await this.structuredDataAccessor.getData(identifier);
|
|
52
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Read the local RDF file mirror used by SolidFS/local-first HTTP reads.
|
|
71
|
+
*
|
|
72
|
+
* `getData()` intentionally keeps returning the structured quad stream for
|
|
73
|
+
* CSS internals. This method is the explicit file-content path for callers
|
|
74
|
+
* that need a real Turtle/JSON-LD byte stream.
|
|
75
|
+
*/
|
|
76
|
+
async getLocalRdfDocument(identifier) {
|
|
77
|
+
if ((0, community_server_1.isContainerIdentifier)(identifier)) {
|
|
78
|
+
throw new community_server_1.NotFoundHttpError();
|
|
79
|
+
}
|
|
80
|
+
if (this.isByLineRdfIdentifier(identifier)) {
|
|
81
|
+
try {
|
|
82
|
+
return {
|
|
83
|
+
data: await this.rdfFileDataAccessor.getData(identifier),
|
|
84
|
+
metadata: await this.getExistingLocalRdfMetadata(identifier),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (!community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const metadata = await this.getMetadata(identifier);
|
|
94
|
+
if (!this.isLocalMirroredRdf(identifier, metadata)) {
|
|
95
|
+
throw new community_server_1.NotFoundHttpError();
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
return {
|
|
99
|
+
data: await this.rdfFileDataAccessor.getData(identifier),
|
|
100
|
+
metadata: await this.getLocalRdfMetadata(identifier, metadata),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (!community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
await this.refreshLocalRdfMirror(identifier);
|
|
109
|
+
return {
|
|
110
|
+
data: await this.rdfFileDataAccessor.getData(identifier),
|
|
111
|
+
metadata: await this.getLocalRdfMetadata(identifier, metadata),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
53
114
|
async getMetadata(identifier) {
|
|
54
115
|
const cache = MetadataRequestContext_1.metadataRequestContext.getStore()?.metadataCache;
|
|
55
116
|
const cacheKey = identifier.path;
|
|
@@ -92,7 +153,7 @@ class MixDataAccessor {
|
|
|
92
153
|
this.invalidateMetadataCache(identifier);
|
|
93
154
|
return;
|
|
94
155
|
}
|
|
95
|
-
await this.
|
|
156
|
+
await this.writeRdfDocument(identifier, data, metadata);
|
|
96
157
|
this.invalidateMetadataCache(identifier);
|
|
97
158
|
}
|
|
98
159
|
async writeMetadata(identifier, metadata) {
|
|
@@ -102,32 +163,388 @@ class MixDataAccessor {
|
|
|
102
163
|
}
|
|
103
164
|
async deleteResource(identifier) {
|
|
104
165
|
const metadata = await this.getMetadata(identifier);
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (error.code !== 'ENOENT' && error.code !== 'ENOTDIR') {
|
|
113
|
-
throw error;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
166
|
+
// RDF by-line resources are mirrored to local file storage so shell tools
|
|
167
|
+
// can operate on real files; remove that mirror together with the index.
|
|
168
|
+
if (this.isLocalMirroredRdf(identifier, metadata)) {
|
|
169
|
+
await this.deleteRdfFileResourceIfPresent(identifier);
|
|
170
|
+
}
|
|
171
|
+
else if (this.isUnstructured(metadata)) {
|
|
172
|
+
await this.deleteUnstructuredResourceIfPresent(identifier);
|
|
116
173
|
}
|
|
117
174
|
// Always delete from structured storage (contains metadata)
|
|
118
175
|
await this.structuredDataAccessor.deleteResource(identifier);
|
|
119
176
|
this.invalidateMetadataCache(identifier);
|
|
120
177
|
}
|
|
121
178
|
/**
|
|
122
|
-
* Execute SPARQL UPDATE
|
|
123
|
-
*
|
|
179
|
+
* Execute SPARQL UPDATE.
|
|
180
|
+
*
|
|
181
|
+
* Supported embedded deltas patch the local RDF authority file first and then
|
|
182
|
+
* rebuild the structured RDF index. Unsupported shapes keep using the
|
|
183
|
+
* compatibility accessor until the embedded engine covers them.
|
|
124
184
|
*/
|
|
125
185
|
async executeSparqlUpdate(query, baseIri) {
|
|
186
|
+
if (baseIri) {
|
|
187
|
+
const identifier = { path: baseIri };
|
|
188
|
+
if (this.isByLineRdfIdentifier(identifier)) {
|
|
189
|
+
try {
|
|
190
|
+
await this.executeLocalRdfSparqlUpdate(query, identifier);
|
|
191
|
+
this.invalidateMetadataCache(identifier);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (!(error instanceof RdfSparqlAdapter_1.UnsupportedSparqlQueryError)) {
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
126
201
|
const accessor = this.structuredDataAccessor;
|
|
127
202
|
if (typeof accessor.executeSparqlUpdate !== 'function') {
|
|
128
203
|
throw new Error('Structured data accessor does not support SPARQL UPDATE');
|
|
129
204
|
}
|
|
130
|
-
|
|
205
|
+
await accessor.executeSparqlUpdate(query, baseIri);
|
|
206
|
+
if (baseIri) {
|
|
207
|
+
const identifier = { path: baseIri };
|
|
208
|
+
await this.refreshLocalRdfMirror(identifier);
|
|
209
|
+
this.invalidateMetadataCache(identifier);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async executeLocalRdfSparqlUpdate(query, identifier) {
|
|
213
|
+
const delta = this.rdfSparqlAdapter.compileUpdateDelta(query, identifier.path);
|
|
214
|
+
this.assertLocalRdfDeltaTargetsGraph(delta.operations, identifier.path);
|
|
215
|
+
const existingText = await this.readLocalRdfTextOrEmpty(identifier);
|
|
216
|
+
const graph = n3_1.DataFactory.namedNode(identifier.path);
|
|
217
|
+
const existingQuads = existingText.length > 0
|
|
218
|
+
? await this.parseLocalRdf(identifier, existingText, this.localRdfContentType(identifier))
|
|
219
|
+
.then((quads) => quads.map((quad) => this.toGraphQuad(quad, graph)))
|
|
220
|
+
: [];
|
|
221
|
+
const nextQuads = this.applyLocalRdfDelta(existingQuads, delta.operations);
|
|
222
|
+
const authorityQuads = nextQuads.map((quad) => this.toDefaultGraphQuad(quad));
|
|
223
|
+
await this.writeLocalRdfAuthority(identifier, authorityQuads);
|
|
224
|
+
await this.writeStructuredRdfIndex(identifier, authorityQuads, new community_server_1.RepresentationMetadata(identifier));
|
|
225
|
+
}
|
|
226
|
+
applyLocalRdfDelta(quads, operations) {
|
|
227
|
+
const byKey = new Map(quads.map((quad) => [this.quadKey(quad), quad]));
|
|
228
|
+
for (const operation of operations) {
|
|
229
|
+
if (operation.type === 'insert') {
|
|
230
|
+
for (const quad of operation.quads) {
|
|
231
|
+
byKey.set(this.quadKey(quad), quad);
|
|
232
|
+
}
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (operation.type === 'delete') {
|
|
236
|
+
for (const quad of operation.quads) {
|
|
237
|
+
byKey.delete(this.quadKey(quad));
|
|
238
|
+
}
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (operation.type === 'insertDeleteWhere') {
|
|
242
|
+
const rows = this.queryLocalUpdateBindings([...byKey.values()], operation.query);
|
|
243
|
+
for (const quad of this.rdfSparqlAdapter.materializeDeleteWhere(operation.deletes, rows)) {
|
|
244
|
+
byKey.delete(this.quadKey(quad));
|
|
245
|
+
}
|
|
246
|
+
for (const quad of this.rdfSparqlAdapter.materializeDeleteWhere(operation.inserts, rows)) {
|
|
247
|
+
byKey.set(this.quadKey(quad), quad);
|
|
248
|
+
}
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (operation.type === 'insertWhere') {
|
|
252
|
+
const rows = this.queryLocalUpdateBindings([...byKey.values()], operation.query);
|
|
253
|
+
for (const quad of this.rdfSparqlAdapter.materializeDeleteWhere(operation.inserts, rows)) {
|
|
254
|
+
byKey.set(this.quadKey(quad), quad);
|
|
255
|
+
}
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const rows = this.queryLocalUpdateBindings([...byKey.values()], operation.query);
|
|
259
|
+
for (const quad of this.rdfSparqlAdapter.materializeDeleteWhere(operation.template, rows)) {
|
|
260
|
+
byKey.delete(this.quadKey(quad));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return [...byKey.values()];
|
|
264
|
+
}
|
|
265
|
+
assertLocalRdfDeltaTargetsGraph(operations, graphIri) {
|
|
266
|
+
for (const operation of operations) {
|
|
267
|
+
const graphTerms = operation.type === 'deleteWhere'
|
|
268
|
+
? operation.template.map((item) => item.graph)
|
|
269
|
+
: operation.type === 'insertDeleteWhere'
|
|
270
|
+
? [
|
|
271
|
+
...operation.deletes.map((item) => item.graph),
|
|
272
|
+
...operation.inserts.map((item) => item.graph),
|
|
273
|
+
...this.queryGraphTerms(operation.query),
|
|
274
|
+
]
|
|
275
|
+
: operation.type === 'insertWhere'
|
|
276
|
+
? [
|
|
277
|
+
...operation.inserts.map((item) => item.graph),
|
|
278
|
+
...this.queryGraphTerms(operation.query),
|
|
279
|
+
]
|
|
280
|
+
: operation.quads.map((quad) => quad.graph);
|
|
281
|
+
for (const graph of graphTerms) {
|
|
282
|
+
if (!('termType' in graph) || graph.termType !== 'NamedNode' || graph.value !== graphIri) {
|
|
283
|
+
throw new RdfSparqlAdapter_1.UnsupportedSparqlQueryError('Embedded local RDF update only supports the target document graph');
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
queryLocalUpdateBindings(quads, query) {
|
|
289
|
+
const index = new RdfQuadIndex_1.RdfQuadIndex({ path: ':memory:' });
|
|
290
|
+
index.open();
|
|
291
|
+
try {
|
|
292
|
+
const engine = new SolidRdfEngine_1.SolidRdfEngine({ index });
|
|
293
|
+
engine.put(quads);
|
|
294
|
+
return engine.query(query).bindings;
|
|
295
|
+
}
|
|
296
|
+
finally {
|
|
297
|
+
index.close();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
queryGraphTerms(query) {
|
|
301
|
+
const patterns = [...query.patterns];
|
|
302
|
+
for (const optional of query.optional ?? []) {
|
|
303
|
+
patterns.push(...(Array.isArray(optional) ? optional : optional.patterns));
|
|
304
|
+
}
|
|
305
|
+
for (const union of query.unions ?? []) {
|
|
306
|
+
for (const branch of union.branches) {
|
|
307
|
+
patterns.push(...branch.patterns);
|
|
308
|
+
for (const optional of branch.optional ?? []) {
|
|
309
|
+
patterns.push(...(Array.isArray(optional) ? optional : optional.patterns));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return patterns.flatMap((pattern) => pattern.graph ? [pattern.graph] : []);
|
|
314
|
+
}
|
|
315
|
+
async readLocalRdfTextOrEmpty(identifier) {
|
|
316
|
+
try {
|
|
317
|
+
return await this.readStreamText(await this.rdfFileDataAccessor.getData(identifier));
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
321
|
+
await this.refreshLocalRdfMirror(identifier);
|
|
322
|
+
try {
|
|
323
|
+
return await this.readStreamText(await this.rdfFileDataAccessor.getData(identifier));
|
|
324
|
+
}
|
|
325
|
+
catch (retryError) {
|
|
326
|
+
if (community_server_1.NotFoundHttpError.isInstance(retryError)) {
|
|
327
|
+
return '';
|
|
328
|
+
}
|
|
329
|
+
throw retryError;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
throw error;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
async writeLocalRdfAuthority(identifier, quads) {
|
|
336
|
+
await this.ensureRdfFileParentContainers(identifier);
|
|
337
|
+
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
|
+
}
|
|
339
|
+
toDefaultGraphQuad(quad) {
|
|
340
|
+
return n3_1.DataFactory.quad(quad.subject, quad.predicate, quad.object);
|
|
341
|
+
}
|
|
342
|
+
toGraphQuad(quad, graph) {
|
|
343
|
+
return n3_1.DataFactory.quad(quad.subject, quad.predicate, quad.object, graph);
|
|
344
|
+
}
|
|
345
|
+
quadKey(quad) {
|
|
346
|
+
return [quad.graph, quad.subject, quad.predicate, quad.object]
|
|
347
|
+
.map((term) => (0, n3_1.termToId)(term))
|
|
348
|
+
.join('\u001f');
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Rebuild the structured RDF index from an already-written local RDF file.
|
|
352
|
+
*
|
|
353
|
+
* SolidFS uses this after tools edit `.ttl`/`.jsonld` files directly. The
|
|
354
|
+
* local file remains the content authority; the structured accessor is only
|
|
355
|
+
* refreshed as query/index state.
|
|
356
|
+
*/
|
|
357
|
+
async syncLocalRdfDocument(identifier, data, contentType, options) {
|
|
358
|
+
if (!this.isRdfDocumentIdentifier(identifier)) {
|
|
359
|
+
throw new Error(`Cannot sync non RDF document into RDF index: ${identifier.path}`);
|
|
360
|
+
}
|
|
361
|
+
const source = data ?? await this.rdfFileDataAccessor.getData(identifier);
|
|
362
|
+
const localContentType = contentType ?? this.localRdfContentType(identifier);
|
|
363
|
+
const text = await this.readStreamText(source);
|
|
364
|
+
if (data) {
|
|
365
|
+
await this.ensureRdfFileParentContainers(identifier);
|
|
366
|
+
await this.rdfFileDataAccessor.writeDocument(identifier, (0, community_server_1.guardStream)(stream_1.Readable.from([text])), this.createLocalRdfMetadata(identifier, new community_server_1.RepresentationMetadata(identifier)));
|
|
367
|
+
}
|
|
368
|
+
const quads = await this.parseLocalRdf(identifier, text, localContentType);
|
|
369
|
+
await this.writeStructuredRdfIndex(identifier, quads, new community_server_1.RepresentationMetadata(identifier), {
|
|
370
|
+
...options,
|
|
371
|
+
contentType: localContentType,
|
|
372
|
+
});
|
|
373
|
+
this.invalidateMetadataCache(identifier);
|
|
374
|
+
}
|
|
375
|
+
async deleteLocalRdfIndex(identifier) {
|
|
376
|
+
try {
|
|
377
|
+
const sourceScopedAccessor = this.sourceScopedStructuredAccessor();
|
|
378
|
+
if (sourceScopedAccessor) {
|
|
379
|
+
await sourceScopedAccessor.deleteRdfSourceDocument(identifier);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
await this.structuredDataAccessor.deleteResource(identifier);
|
|
383
|
+
}
|
|
384
|
+
this.invalidateMetadataCache(identifier);
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
if (!community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
async writeRdfDocument(identifier, data, metadata) {
|
|
393
|
+
const quads = await (0, arrayify_stream_1.default)(data);
|
|
394
|
+
const structuredMetadata = new community_server_1.RepresentationMetadata(metadata);
|
|
395
|
+
(0, community_server_1.addResourceMetadata)(structuredMetadata, false);
|
|
396
|
+
(0, community_server_1.updateModifiedDate)(structuredMetadata);
|
|
397
|
+
await this.ensureRdfFileParentContainers(identifier);
|
|
398
|
+
await this.rdfFileDataAccessor.writeDocument(identifier, (0, community_server_1.guardStream)(stream_1.Readable.from([await this.serializeQuadsForLocalFile(identifier, quads)])), this.createLocalRdfMetadata(identifier, metadata));
|
|
399
|
+
try {
|
|
400
|
+
await this.writeStructuredRdfIndex(identifier, quads, structuredMetadata);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
await this.deleteRdfFileResourceIfPresent(identifier);
|
|
404
|
+
throw error;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async writeStructuredRdfIndex(identifier, quads, metadata, options = {}) {
|
|
408
|
+
const structuredMetadata = new community_server_1.RepresentationMetadata(metadata);
|
|
409
|
+
(0, community_server_1.addResourceMetadata)(structuredMetadata, false);
|
|
410
|
+
(0, community_server_1.updateModifiedDate)(structuredMetadata);
|
|
411
|
+
const sourceScopedAccessor = this.sourceScopedStructuredAccessor();
|
|
412
|
+
if (sourceScopedAccessor) {
|
|
413
|
+
await sourceScopedAccessor.writeRdfSourceDocument(identifier, quads, structuredMetadata, this.rdfSourceInput(identifier, options));
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
await this.structuredDataAccessor.writeDocument(identifier, (0, community_server_1.guardStream)(stream_1.Readable.from(quads)), structuredMetadata);
|
|
417
|
+
}
|
|
418
|
+
async refreshLocalRdfMirror(identifier) {
|
|
419
|
+
let metadata;
|
|
420
|
+
let quads;
|
|
421
|
+
try {
|
|
422
|
+
metadata = await this.structuredDataAccessor.getMetadata(identifier);
|
|
423
|
+
if (!this.isLocalMirroredRdf(identifier, metadata)) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
quads = await (0, arrayify_stream_1.default)(await this.structuredDataAccessor.getData(identifier));
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
if (community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
430
|
+
await this.deleteRdfFileResourceIfPresent(identifier);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
await this.ensureRdfFileParentContainers(identifier);
|
|
436
|
+
await this.rdfFileDataAccessor.writeDocument(identifier, (0, community_server_1.guardStream)(stream_1.Readable.from([await this.serializeQuadsForLocalFile(identifier, quads)])), this.createLocalRdfMetadata(identifier, metadata));
|
|
437
|
+
}
|
|
438
|
+
async getLocalRdfMetadata(identifier, sourceMetadata) {
|
|
439
|
+
try {
|
|
440
|
+
return await this.getExistingLocalRdfMetadata(identifier);
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
if (!community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
444
|
+
throw error;
|
|
445
|
+
}
|
|
446
|
+
return this.createLocalRdfMetadata(identifier, sourceMetadata);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async getExistingLocalRdfMetadata(identifier) {
|
|
450
|
+
const metadata = await this.rdfFileDataAccessor.getMetadata(identifier);
|
|
451
|
+
metadata.contentType = this.localRdfContentType(identifier);
|
|
452
|
+
return metadata;
|
|
453
|
+
}
|
|
454
|
+
createLocalRdfMetadata(identifier, metadata) {
|
|
455
|
+
const localMetadata = new community_server_1.RepresentationMetadata(metadata);
|
|
456
|
+
localMetadata.contentType = this.localRdfContentType(identifier);
|
|
457
|
+
return localMetadata;
|
|
458
|
+
}
|
|
459
|
+
localRdfContentType(identifier) {
|
|
460
|
+
return (0, RdfContentTypes_1.rdfContentTypeForPath)(identifier.path) ?? 'text/turtle';
|
|
461
|
+
}
|
|
462
|
+
sourceScopedStructuredAccessor() {
|
|
463
|
+
const accessor = this.structuredDataAccessor;
|
|
464
|
+
if (typeof accessor.writeRdfSourceDocument === 'function'
|
|
465
|
+
&& typeof accessor.deleteRdfSourceDocument === 'function') {
|
|
466
|
+
return accessor;
|
|
467
|
+
}
|
|
468
|
+
return undefined;
|
|
469
|
+
}
|
|
470
|
+
rdfSourceInput(identifier, options) {
|
|
471
|
+
const workspace = options.workspace ?? this.parentContainer(identifier).path;
|
|
472
|
+
return {
|
|
473
|
+
source: options.source ?? identifier.path,
|
|
474
|
+
workspace,
|
|
475
|
+
localPath: options.localPath ?? this.relativePathFromWorkspace(identifier.path, workspace),
|
|
476
|
+
contentType: options.contentType ?? this.localRdfContentType(identifier),
|
|
477
|
+
sourceVersion: options.sourceVersion,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
relativePathFromWorkspace(identifierPath, workspaceValue) {
|
|
481
|
+
try {
|
|
482
|
+
const resource = new URL(identifierPath);
|
|
483
|
+
const workspace = new URL(workspaceValue.endsWith('/') ? workspaceValue : `${workspaceValue}/`);
|
|
484
|
+
if (resource.origin !== workspace.origin || !resource.pathname.startsWith(workspace.pathname)) {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
return decodeURIComponent(resource.pathname.slice(workspace.pathname.length));
|
|
488
|
+
}
|
|
489
|
+
catch {
|
|
490
|
+
return undefined;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
isByLineRdfIdentifier(identifier) {
|
|
494
|
+
return (0, RdfContentTypes_1.isLineAddressableRdfPath)(identifier.path);
|
|
495
|
+
}
|
|
496
|
+
isRdfDocumentIdentifier(identifier) {
|
|
497
|
+
return (0, RdfContentTypes_1.isRdfDocumentPath)(identifier.path);
|
|
498
|
+
}
|
|
499
|
+
isLocalMirroredRdf(identifier, metadata) {
|
|
500
|
+
return metadata.contentType === community_server_1.INTERNAL_QUADS || this.isRdfDocumentIdentifier(identifier);
|
|
501
|
+
}
|
|
502
|
+
async serializeQuadsForLocalFile(identifier, quads) {
|
|
503
|
+
if (this.localRdfContentType(identifier) === 'application/ld+json') {
|
|
504
|
+
const nquads = await this.serializeNQuads(quads);
|
|
505
|
+
const document = await jsonld_1.default.fromRDF(nquads, { format: 'application/n-quads' });
|
|
506
|
+
return `${JSON.stringify(document, null, 2)}\n`;
|
|
507
|
+
}
|
|
508
|
+
if (this.localRdfContentType(identifier) === 'application/rdf+xml') {
|
|
509
|
+
return (0, RdfXmlSerializer_1.serializeRdfXml)(quads);
|
|
510
|
+
}
|
|
511
|
+
const writer = new n3_1.Writer({ format: this.localRdfContentType(identifier) });
|
|
512
|
+
return writer.quadsToString(quads);
|
|
513
|
+
}
|
|
514
|
+
async serializeNQuads(quads) {
|
|
515
|
+
return new Promise((resolve, reject) => {
|
|
516
|
+
const writer = new n3_1.Writer({ format: 'application/n-quads' });
|
|
517
|
+
writer.addQuads(quads);
|
|
518
|
+
writer.end((error, result) => {
|
|
519
|
+
if (error) {
|
|
520
|
+
reject(error);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
resolve(result);
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
async parseLocalRdf(identifier, text, contentType) {
|
|
528
|
+
if (contentType === 'application/ld+json') {
|
|
529
|
+
const nquads = await jsonld_1.default.toRDF(JSON.parse(text), {
|
|
530
|
+
base: identifier.path,
|
|
531
|
+
format: 'application/n-quads',
|
|
532
|
+
});
|
|
533
|
+
return new n3_1.Parser({ format: 'application/n-quads', baseIRI: identifier.path }).parse(nquads);
|
|
534
|
+
}
|
|
535
|
+
if (contentType === 'application/rdf+xml') {
|
|
536
|
+
return (0, arrayify_stream_1.default)(rdf_parse_1.rdfParser.parse(stream_1.Readable.from([text]), {
|
|
537
|
+
contentType,
|
|
538
|
+
baseIRI: identifier.path,
|
|
539
|
+
}));
|
|
540
|
+
}
|
|
541
|
+
return new n3_1.Parser({ format: contentType, baseIRI: identifier.path }).parse(text);
|
|
542
|
+
}
|
|
543
|
+
async readStreamText(data) {
|
|
544
|
+
const chunks = await (0, arrayify_stream_1.default)(data);
|
|
545
|
+
return chunks
|
|
546
|
+
.map((chunk) => typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8'))
|
|
547
|
+
.join('');
|
|
131
548
|
}
|
|
132
549
|
/**
|
|
133
550
|
* Write unstructured document: store data in unstructured accessor,
|
|
@@ -162,6 +579,84 @@ class MixDataAccessor {
|
|
|
162
579
|
throw error;
|
|
163
580
|
}
|
|
164
581
|
}
|
|
582
|
+
async deleteUnstructuredResourceIfPresent(identifier) {
|
|
583
|
+
try {
|
|
584
|
+
await this.unstructuredDataAccessor.deleteResource(identifier);
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
if (error?.code !== 'ENOENT' && error?.code !== 'ENOTDIR' && !community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
async deleteRdfFileResourceIfPresent(identifier) {
|
|
593
|
+
try {
|
|
594
|
+
await this.rdfFileDataAccessor.deleteResource(identifier);
|
|
595
|
+
}
|
|
596
|
+
catch (error) {
|
|
597
|
+
if (error?.code !== 'ENOENT' && error?.code !== 'ENOTDIR' && !community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async ensureUnstructuredParentContainers(identifier) {
|
|
603
|
+
await this.ensureParentContainers(identifier, this.unstructuredDataAccessor);
|
|
604
|
+
}
|
|
605
|
+
async ensureRdfFileParentContainers(identifier) {
|
|
606
|
+
await this.ensureParentContainers(identifier, this.rdfFileDataAccessor);
|
|
607
|
+
}
|
|
608
|
+
async ensureParentContainers(identifier, accessor) {
|
|
609
|
+
const containers = [];
|
|
610
|
+
let current = this.parentContainer(identifier);
|
|
611
|
+
while (!this.sameIdentifier(current, identifier)) {
|
|
612
|
+
containers.push(current);
|
|
613
|
+
const next = this.parentContainer(current);
|
|
614
|
+
if (this.sameIdentifier(next, current)) {
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
current = next;
|
|
618
|
+
}
|
|
619
|
+
for (const container of containers.reverse()) {
|
|
620
|
+
await this.writeContainerIfMissing(accessor, container);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
async writeContainerIfMissing(accessor, identifier) {
|
|
624
|
+
try {
|
|
625
|
+
await accessor.getMetadata(identifier);
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
catch (error) {
|
|
629
|
+
if (!community_server_1.NotFoundHttpError.isInstance(error)) {
|
|
630
|
+
throw error;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
await accessor.writeContainer(identifier, new community_server_1.RepresentationMetadata(identifier));
|
|
634
|
+
}
|
|
635
|
+
sameIdentifier(left, right) {
|
|
636
|
+
return left.path === right.path;
|
|
637
|
+
}
|
|
638
|
+
parentContainer(identifier) {
|
|
639
|
+
try {
|
|
640
|
+
const url = new URL(identifier.path);
|
|
641
|
+
if (url.pathname === '/' || url.pathname === '') {
|
|
642
|
+
return { path: url.href.endsWith('/') ? url.href : `${url.href}/` };
|
|
643
|
+
}
|
|
644
|
+
const segments = url.pathname.replace(/\/+$/u, '').split('/');
|
|
645
|
+
segments.pop();
|
|
646
|
+
url.pathname = `${segments.join('/') || '/'}`.replace(/\/?$/u, '/');
|
|
647
|
+
url.search = '';
|
|
648
|
+
url.hash = '';
|
|
649
|
+
return { path: url.href };
|
|
650
|
+
}
|
|
651
|
+
catch {
|
|
652
|
+
const trimmed = identifier.path.replace(/\/+$/u, '');
|
|
653
|
+
const slashIndex = trimmed.lastIndexOf('/');
|
|
654
|
+
if (slashIndex < 0) {
|
|
655
|
+
return identifier;
|
|
656
|
+
}
|
|
657
|
+
return { path: `${trimmed.slice(0, slashIndex + 1)}` };
|
|
658
|
+
}
|
|
659
|
+
}
|
|
165
660
|
invalidateMetadataCache(identifier) {
|
|
166
661
|
const cache = MetadataRequestContext_1.metadataRequestContext.getStore()?.metadataCache;
|
|
167
662
|
if (!cache) {
|