@undefineds.co/xpod 0.3.6 → 0.3.15

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 (249) hide show
  1. package/config/cli.json +1 -1
  2. package/config/cloud.json +54 -22
  3. package/config/local.json +56 -12
  4. package/config/resolver.json +10 -2
  5. package/config/xpod.base.json +50 -0
  6. package/config/xpod.json +8 -8
  7. package/dist/agents/config/resolve.js +10 -10
  8. package/dist/agents/config/resolve.js.map +1 -1
  9. package/dist/api/chatkit/index.d.ts +1 -1
  10. package/dist/api/chatkit/index.js.map +1 -1
  11. package/dist/api/chatkit/pod-store.d.ts +14 -11
  12. package/dist/api/chatkit/pod-store.js +114 -78
  13. package/dist/api/chatkit/pod-store.js.map +1 -1
  14. package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
  15. package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
  16. package/dist/api/chatkit/service.js +1 -1
  17. package/dist/api/chatkit/service.js.map +1 -1
  18. package/dist/api/chatkit/types.d.ts +11 -11
  19. package/dist/api/chatkit/types.js +3 -3
  20. package/dist/api/chatkit/types.js.map +1 -1
  21. package/dist/api/container/cloud.js +0 -8
  22. package/dist/api/container/cloud.js.map +1 -1
  23. package/dist/api/container/index.js +2 -1
  24. package/dist/api/container/index.js.map +1 -1
  25. package/dist/api/container/local.js +0 -7
  26. package/dist/api/container/local.js.map +1 -1
  27. package/dist/api/container/routes.js +3 -17
  28. package/dist/api/container/routes.js.map +1 -1
  29. package/dist/api/container/types.d.ts +0 -2
  30. package/dist/api/container/types.js.map +1 -1
  31. package/dist/api/handlers/PodManagementHandler.d.ts +3 -0
  32. package/dist/api/handlers/PodManagementHandler.js +71 -1
  33. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  34. package/dist/api/handlers/RunHandler.js +5 -5
  35. package/dist/api/handlers/RunHandler.js.map +1 -1
  36. package/dist/api/runs/AgentRuntimeTypes.d.ts +7 -8
  37. package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
  38. package/dist/api/runs/InngestRunExecutionBackend.d.ts +2 -2
  39. package/dist/api/runs/ManagedRunWorker.d.ts +1 -1
  40. package/dist/api/runs/ManagedRunWorker.js +6 -6
  41. package/dist/api/runs/ManagedRunWorker.js.map +1 -1
  42. package/dist/api/runs/PiAgentRuntimeDriver.d.ts +16 -1
  43. package/dist/api/runs/PiAgentRuntimeDriver.js +182 -23
  44. package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
  45. package/dist/api/runs/RunStateCenter.d.ts +3 -3
  46. package/dist/api/runs/RunStateCenter.js +13 -13
  47. package/dist/api/runs/RunStateCenter.js.map +1 -1
  48. package/dist/api/runs/store.d.ts +4 -4
  49. package/dist/api/runs/store.js +2 -2
  50. package/dist/api/runs/store.js.map +1 -1
  51. package/dist/api/service/VectorStoreService.d.ts +1 -1
  52. package/dist/api/service/VectorStoreService.js +16 -16
  53. package/dist/api/service/VectorStoreService.js.map +1 -1
  54. package/dist/api/tasks/InngestTaskScheduler.d.ts +4 -4
  55. package/dist/api/tasks/TaskMaterializer.d.ts +3 -3
  56. package/dist/api/tasks/TaskMaterializer.js +11 -11
  57. package/dist/api/tasks/TaskMaterializer.js.map +1 -1
  58. package/dist/api/tasks/TaskService.d.ts +3 -3
  59. package/dist/api/tasks/TaskService.js +11 -7
  60. package/dist/api/tasks/TaskService.js.map +1 -1
  61. package/dist/api/tasks/store.d.ts +10 -4
  62. package/dist/api/tasks/store.js +14 -4
  63. package/dist/api/tasks/store.js.map +1 -1
  64. package/dist/api/workspace/types.d.ts +3 -3
  65. package/dist/api/workspace/types.js +6 -6
  66. package/dist/api/workspace/types.js.map +1 -1
  67. package/dist/cli/commands/config.js +2 -2
  68. package/dist/cli/commands/config.js.map +1 -1
  69. package/dist/cli/commands/start.js +9 -3
  70. package/dist/cli/commands/start.js.map +1 -1
  71. package/dist/components/components.jsonld +8 -2
  72. package/dist/components/context.jsonld +308 -51
  73. package/dist/http/search/SearchHttpHandler.js +8 -8
  74. package/dist/http/search/SearchHttpHandler.js.map +1 -1
  75. package/dist/identity/drizzle/PodLookupRepository.d.ts +11 -1
  76. package/dist/identity/drizzle/PodLookupRepository.js +95 -4
  77. package/dist/identity/drizzle/PodLookupRepository.js.map +1 -1
  78. package/dist/identity/drizzle/db.js +4 -43
  79. package/dist/identity/drizzle/db.js.map +1 -1
  80. package/dist/identity/drizzle/schema.pg.d.ts +0 -5
  81. package/dist/identity/drizzle/schema.pg.js +2 -16
  82. package/dist/identity/drizzle/schema.pg.js.map +1 -1
  83. package/dist/identity/drizzle/schema.sqlite.d.ts +19 -176
  84. package/dist/identity/drizzle/schema.sqlite.js +2 -16
  85. package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
  86. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.d.ts +4 -4
  87. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +7 -7
  88. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
  89. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld +6 -6
  90. package/dist/identity/oidc/AutoDetectOidcHandler.d.ts +4 -4
  91. package/dist/identity/oidc/AutoDetectOidcHandler.js +6 -6
  92. package/dist/identity/oidc/AutoDetectOidcHandler.js.map +1 -1
  93. package/dist/identity/oidc/AutoDetectOidcHandler.jsonld +6 -6
  94. package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +37 -0
  95. package/dist/identity/oidc/ScopedPickWebIdHandler.js +211 -0
  96. package/dist/identity/oidc/ScopedPickWebIdHandler.js.map +1 -0
  97. package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +158 -0
  98. package/dist/index.d.ts +12 -2
  99. package/dist/index.js +16 -4
  100. package/dist/index.js.map +1 -1
  101. package/dist/main.js +8 -2
  102. package/dist/main.js.map +1 -1
  103. package/dist/provision/ProvisionPodCreator.d.ts +3 -4
  104. package/dist/provision/ProvisionPodCreator.js +8 -13
  105. package/dist/provision/ProvisionPodCreator.js.map +1 -1
  106. package/dist/provision/ProvisionPodCreator.jsonld +7 -7
  107. package/dist/runtime/Proxy.d.ts +0 -1
  108. package/dist/runtime/Proxy.js +0 -9
  109. package/dist/runtime/Proxy.js.map +1 -1
  110. package/dist/runtime/bootstrap.d.ts +1 -0
  111. package/dist/runtime/bootstrap.js +5 -2
  112. package/dist/runtime/bootstrap.js.map +1 -1
  113. package/dist/runtime/css-process.d.ts +12 -4
  114. package/dist/runtime/css-process.js +61 -14
  115. package/dist/runtime/css-process.js.map +1 -1
  116. package/dist/runtime/oidc-issuer.d.ts +3 -2
  117. package/dist/runtime/oidc-issuer.js +3 -2
  118. package/dist/runtime/oidc-issuer.js.map +1 -1
  119. package/dist/runtime/runtime-types.d.ts +1 -0
  120. package/dist/runtime/runtime-types.js.map +1 -1
  121. package/dist/solidfs/LocalFirstRdfRepresentationResolver.d.ts +21 -0
  122. package/dist/solidfs/LocalFirstRdfRepresentationResolver.js +38 -0
  123. package/dist/solidfs/LocalFirstRdfRepresentationResolver.js.map +1 -0
  124. package/dist/solidfs/LocalSolidFS.d.ts +18 -0
  125. package/dist/solidfs/LocalSolidFS.js +539 -0
  126. package/dist/solidfs/LocalSolidFS.js.map +1 -0
  127. package/dist/solidfs/PodSolidFsHttpClient.d.ts +16 -0
  128. package/dist/solidfs/PodSolidFsHttpClient.js +93 -0
  129. package/dist/solidfs/PodSolidFsHttpClient.js.map +1 -0
  130. package/dist/solidfs/PodSolidFsHydrator.d.ts +27 -0
  131. package/dist/solidfs/PodSolidFsHydrator.js +127 -0
  132. package/dist/solidfs/PodSolidFsHydrator.js.map +1 -0
  133. package/dist/solidfs/PodSolidFsSyncer.d.ts +21 -0
  134. package/dist/solidfs/PodSolidFsSyncer.js +78 -0
  135. package/dist/solidfs/PodSolidFsSyncer.js.map +1 -0
  136. package/dist/solidfs/RdfIndexSolidFsSyncer.d.ts +22 -0
  137. package/dist/solidfs/RdfIndexSolidFsSyncer.js +131 -0
  138. package/dist/solidfs/RdfIndexSolidFsSyncer.js.map +1 -0
  139. package/dist/solidfs/index.d.ts +7 -0
  140. package/dist/solidfs/index.js +24 -0
  141. package/dist/solidfs/index.js.map +1 -0
  142. package/dist/solidfs/types.d.ts +131 -0
  143. package/dist/solidfs/types.js +19 -0
  144. package/dist/solidfs/types.js.map +1 -0
  145. package/dist/storage/RepresentationPartialConvertingStore.js +6 -13
  146. package/dist/storage/RepresentationPartialConvertingStore.js.map +1 -1
  147. package/dist/storage/SparqlUpdateResourceStore.d.ts +4 -0
  148. package/dist/storage/SparqlUpdateResourceStore.js +13 -0
  149. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  150. package/dist/storage/SparqlUpdateResourceStore.jsonld +26 -0
  151. package/dist/storage/accessors/MixDataAccessor.d.ts +85 -4
  152. package/dist/storage/accessors/MixDataAccessor.js +511 -16
  153. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  154. package/dist/storage/accessors/MixDataAccessor.jsonld +176 -1
  155. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.d.ts +7 -0
  156. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +72 -4
  157. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
  158. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.jsonld +24 -0
  159. package/dist/storage/quint/BaseQuintStore.d.ts +3 -0
  160. package/dist/storage/quint/BaseQuintStore.js +51 -27
  161. package/dist/storage/quint/BaseQuintStore.js.map +1 -1
  162. package/dist/storage/quint/PgQuintStore.d.ts +1 -0
  163. package/dist/storage/quint/PgQuintStore.js +50 -32
  164. package/dist/storage/quint/PgQuintStore.js.map +1 -1
  165. package/dist/storage/quint/PgQuintStore.jsonld +4 -3
  166. package/dist/storage/quint/SqliteQuintStore.d.ts +5 -0
  167. package/dist/storage/quint/SqliteQuintStore.js +100 -0
  168. package/dist/storage/quint/SqliteQuintStore.js.map +1 -1
  169. package/dist/storage/quint/SqliteQuintStore.jsonld +20 -0
  170. package/dist/storage/quint/types.d.ts +16 -0
  171. package/dist/storage/quint/types.js.map +1 -1
  172. package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +55 -0
  173. package/dist/storage/rdf/Rdf3xTripleIndex.js +1235 -0
  174. package/dist/storage/rdf/Rdf3xTripleIndex.js.map +1 -0
  175. package/dist/storage/rdf/RdfContentTypes.d.ts +9 -0
  176. package/dist/storage/rdf/RdfContentTypes.js +79 -0
  177. package/dist/storage/rdf/RdfContentTypes.js.map +1 -0
  178. package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +79 -0
  179. package/dist/storage/rdf/RdfLocalQueryEngine.js +2705 -0
  180. package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -0
  181. package/dist/storage/rdf/RdfQuadIndex.d.ts +98 -0
  182. package/dist/storage/rdf/RdfQuadIndex.js +1840 -0
  183. package/dist/storage/rdf/RdfQuadIndex.js.map +1 -0
  184. package/dist/storage/rdf/RdfQuadIndex.jsonld +416 -0
  185. package/dist/storage/rdf/RdfShadowComparator.d.ts +12 -0
  186. package/dist/storage/rdf/RdfShadowComparator.js +47 -0
  187. package/dist/storage/rdf/RdfShadowComparator.js.map +1 -0
  188. package/dist/storage/rdf/RdfSparqlAdapter.d.ts +147 -0
  189. package/dist/storage/rdf/RdfSparqlAdapter.js +2420 -0
  190. package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -0
  191. package/dist/storage/rdf/RdfSparqlAdapter.jsonld +414 -0
  192. package/dist/storage/rdf/RdfTermDictionary.d.ts +27 -0
  193. package/dist/storage/rdf/RdfTermDictionary.js +352 -0
  194. package/dist/storage/rdf/RdfTermDictionary.js.map +1 -0
  195. package/dist/storage/rdf/RdfTermDictionary.jsonld +114 -0
  196. package/dist/storage/rdf/RdfTermSemantics.d.ts +6 -0
  197. package/dist/storage/rdf/RdfTermSemantics.js +40 -0
  198. package/dist/storage/rdf/RdfTermSemantics.js.map +1 -0
  199. package/dist/storage/rdf/RdfTextIndex.d.ts +23 -0
  200. package/dist/storage/rdf/RdfTextIndex.js +569 -0
  201. package/dist/storage/rdf/RdfTextIndex.js.map +1 -0
  202. package/dist/storage/rdf/RdfVectorIndex.d.ts +22 -0
  203. package/dist/storage/rdf/RdfVectorIndex.js +631 -0
  204. package/dist/storage/rdf/RdfVectorIndex.js.map +1 -0
  205. package/dist/storage/rdf/RdfXmlSerializer.d.ts +2 -0
  206. package/dist/storage/rdf/RdfXmlSerializer.js +123 -0
  207. package/dist/storage/rdf/RdfXmlSerializer.js.map +1 -0
  208. package/dist/storage/rdf/ShadowRdfQuintStore.d.ts +58 -0
  209. package/dist/storage/rdf/ShadowRdfQuintStore.js +202 -0
  210. package/dist/storage/rdf/ShadowRdfQuintStore.js.map +1 -0
  211. package/dist/storage/rdf/ShadowRdfQuintStore.jsonld +308 -0
  212. package/dist/storage/rdf/SolidRdfEngine.d.ts +56 -0
  213. package/dist/storage/rdf/SolidRdfEngine.js +292 -0
  214. package/dist/storage/rdf/SolidRdfEngine.js.map +1 -0
  215. package/dist/storage/rdf/SolidRdfEngine.jsonld +372 -0
  216. package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +92 -0
  217. package/dist/storage/rdf/SolidRdfSparqlEngine.js +477 -0
  218. package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -0
  219. package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +257 -0
  220. package/dist/storage/rdf/index.d.ts +15 -0
  221. package/dist/storage/rdf/index.js +61 -0
  222. package/dist/storage/rdf/index.js.map +1 -0
  223. package/dist/storage/rdf/models-benchmark.d.ts +260 -0
  224. package/dist/storage/rdf/models-benchmark.js +1405 -0
  225. package/dist/storage/rdf/models-benchmark.js.map +1 -0
  226. package/dist/storage/rdf/types.d.ts +726 -0
  227. package/dist/storage/rdf/types.js +3 -0
  228. package/dist/storage/rdf/types.js.map +1 -0
  229. package/dist/storage/rdf/types.jsonld +316 -0
  230. package/dist/storage/vector/VectorIndexingListener.d.ts +5 -5
  231. package/dist/storage/vector/VectorIndexingListener.js +19 -19
  232. package/dist/storage/vector/VectorIndexingListener.js.map +1 -1
  233. package/package.json +3 -2
  234. package/templates/pod/acp/.acr.hbs +39 -0
  235. package/templates/pod/acp/README.acr +18 -0
  236. package/templates/pod/acp/profile/card.acr +22 -0
  237. package/templates/pod/base/README$.md.hbs +27 -0
  238. package/templates/pod/base/profile/card$.ttl.hbs +13 -0
  239. package/templates/pod/wac/.acl.hbs +26 -0
  240. package/templates/pod/wac/README.acl.hbs +14 -0
  241. package/templates/pod/wac/profile/card.acl.hbs +19 -0
  242. package/dist/api/handlers/WebIdProfileHandler.d.ts +0 -16
  243. package/dist/api/handlers/WebIdProfileHandler.js +0 -423
  244. package/dist/api/handlers/WebIdProfileHandler.js.map +0 -1
  245. package/dist/identity/drizzle/WebIdProfileRepository.d.ts +0 -63
  246. package/dist/identity/drizzle/WebIdProfileRepository.js +0 -168
  247. package/dist/identity/drizzle/WebIdProfileRepository.js.map +0 -1
  248. package/dist/identity/drizzle/WebIdProfileRepository.jsonld +0 -112
  249. package/dist/storage/quint/BaseQuintStore.jsonld +0 -257
@@ -0,0 +1,131 @@
1
+ export type SolidFsProjection = 'direct' | 'copy' | 'hydrated-object';
2
+ export type SolidFsEntrySource = 'filesystem' | 'pod-http' | 'object';
3
+ export type SolidFsEntryState = 'clean' | 'dirty' | 'committed' | 'conflict';
4
+ export type SolidFsChangeType = 'created' | 'updated' | 'deleted';
5
+ export interface SolidFsRunRef {
6
+ id?: string;
7
+ workspace?: string;
8
+ }
9
+ export interface SolidFsPrepareInput {
10
+ run?: SolidFsRunRef;
11
+ workspace: string;
12
+ /**
13
+ * Adapter-provided local source path for workspaces that are resolved by
14
+ * the runner before SolidFS materializes them, such as Pod HTTPS containers.
15
+ */
16
+ sourcePath?: string;
17
+ projection?: SolidFsProjection;
18
+ /**
19
+ * Opaque request/runtime context used by adapter syncers. SolidFS itself must
20
+ * not inspect or persist this value because it can contain credentials.
21
+ */
22
+ context?: unknown;
23
+ }
24
+ export interface SolidFsManifestEntry {
25
+ path: string;
26
+ resource?: string;
27
+ source: SolidFsEntrySource;
28
+ sourcePath: string;
29
+ contentType?: string;
30
+ projection: SolidFsProjection;
31
+ /**
32
+ * Opaque authority-side version token, such as an ETag, object version, RDF
33
+ * revision, or filesystem hash. For local filesystem projections this can be
34
+ * the same value used for dirty detection.
35
+ */
36
+ sourceVersion?: string;
37
+ /**
38
+ * Local working-copy version captured when the entry was materialized. This
39
+ * lets hydrated objects keep an authority ETag in sourceVersion while still
40
+ * detecting local edits by hashing the working file.
41
+ */
42
+ workingVersion?: string;
43
+ lastAccessedAt?: number;
44
+ state: SolidFsEntryState;
45
+ }
46
+ export interface SolidFsChange {
47
+ path: string;
48
+ resource?: string;
49
+ source: SolidFsEntrySource;
50
+ sourcePath: string;
51
+ contentType?: string;
52
+ projection: SolidFsProjection;
53
+ type: SolidFsChangeType;
54
+ sourceVersion?: string;
55
+ }
56
+ export interface SolidFsManifest {
57
+ workspace: string;
58
+ cwd: string;
59
+ projection: SolidFsProjection;
60
+ entries: SolidFsManifestEntry[];
61
+ changes?: SolidFsChange[];
62
+ }
63
+ export interface SolidFsConflict {
64
+ path: string;
65
+ sourcePath: string;
66
+ expectedVersion?: string;
67
+ actualVersion?: string;
68
+ message: string;
69
+ }
70
+ export declare class SolidFsConflictError extends Error {
71
+ readonly conflicts: SolidFsConflict[];
72
+ constructor(conflicts: SolidFsConflict[]);
73
+ }
74
+ export declare class SolidFsNotFoundError extends Error {
75
+ constructor(message: string);
76
+ }
77
+ export interface MaterializedWorkspace {
78
+ cwd: string;
79
+ manifest: SolidFsManifest;
80
+ /**
81
+ * Materialize one object-backed resource into the real cwd. Implementations
82
+ * without object hydration support can leave this undefined.
83
+ */
84
+ hydrate?(relativePath: string): Promise<SolidFsManifestEntry>;
85
+ /**
86
+ * Remove clean hydrated working copies that are no longer needed. Dirty files
87
+ * must never be pruned.
88
+ */
89
+ prune?(options?: SolidFsPruneOptions): Promise<SolidFsManifest>;
90
+ commit(): Promise<SolidFsManifest>;
91
+ rollback(): Promise<void>;
92
+ }
93
+ export interface SolidFS {
94
+ prepare(input: SolidFsPrepareInput): Promise<MaterializedWorkspace>;
95
+ }
96
+ export interface SolidFsSyncer {
97
+ shouldTrack?(input: SolidFsPrepareInput): boolean;
98
+ shouldTrackPath?(relativePath: string): boolean;
99
+ sync(change: SolidFsChange, workspace: SolidFsManifest, context?: unknown): Promise<void>;
100
+ }
101
+ export interface SolidFsHydrateInput {
102
+ path: string;
103
+ targetPath: string;
104
+ workspace: SolidFsManifest;
105
+ context?: unknown;
106
+ }
107
+ export interface SolidFsHydrateResult {
108
+ contentType?: string;
109
+ sourceVersion?: string;
110
+ }
111
+ export interface SolidFsCommitHydratedInput {
112
+ change: SolidFsChange;
113
+ workspace: SolidFsManifest;
114
+ context?: unknown;
115
+ }
116
+ export interface SolidFsCommitHydratedResult {
117
+ sourceVersion?: string;
118
+ }
119
+ export interface SolidFsHydrator {
120
+ hydrate(input: SolidFsHydrateInput): Promise<SolidFsHydrateResult | void>;
121
+ commit(input: SolidFsCommitHydratedInput): Promise<SolidFsCommitHydratedResult | void>;
122
+ delete?(input: SolidFsCommitHydratedInput): Promise<void>;
123
+ }
124
+ export interface SolidFsPruneOptions {
125
+ /**
126
+ * Prune clean hydrated files not accessed for at least this many ms.
127
+ * Defaults to 0, meaning any clean hydrated file is eligible.
128
+ */
129
+ olderThanMs?: number;
130
+ now?: number;
131
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SolidFsNotFoundError = exports.SolidFsConflictError = void 0;
4
+ class SolidFsConflictError extends Error {
5
+ constructor(conflicts) {
6
+ super(`SolidFS commit conflict: ${conflicts.map((conflict) => conflict.path).join(', ')}`);
7
+ this.name = 'SolidFsConflictError';
8
+ this.conflicts = conflicts;
9
+ }
10
+ }
11
+ exports.SolidFsConflictError = SolidFsConflictError;
12
+ class SolidFsNotFoundError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = 'SolidFsNotFoundError';
16
+ }
17
+ }
18
+ exports.SolidFsNotFoundError = SolidFsNotFoundError;
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/solidfs/types.ts"],"names":[],"mappings":";;;AA6EA,MAAa,oBAAqB,SAAQ,KAAK;IAG7C,YAAmB,SAA4B;QAC7C,KAAK,CAAC,4BAA4B,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AARD,oDAQC;AAED,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAmB,OAAe;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AALD,oDAKC","sourcesContent":["export type SolidFsProjection = 'direct' | 'copy' | 'hydrated-object';\nexport type SolidFsEntrySource = 'filesystem' | 'pod-http' | 'object';\n\nexport type SolidFsEntryState = 'clean' | 'dirty' | 'committed' | 'conflict';\nexport type SolidFsChangeType = 'created' | 'updated' | 'deleted';\n\nexport interface SolidFsRunRef {\n id?: string;\n workspace?: string;\n}\n\nexport interface SolidFsPrepareInput {\n run?: SolidFsRunRef;\n workspace: string;\n /**\n * Adapter-provided local source path for workspaces that are resolved by\n * the runner before SolidFS materializes them, such as Pod HTTPS containers.\n */\n sourcePath?: string;\n projection?: SolidFsProjection;\n /**\n * Opaque request/runtime context used by adapter syncers. SolidFS itself must\n * not inspect or persist this value because it can contain credentials.\n */\n context?: unknown;\n}\n\nexport interface SolidFsManifestEntry {\n path: string;\n resource?: string;\n source: SolidFsEntrySource;\n sourcePath: string;\n contentType?: string;\n projection: SolidFsProjection;\n /**\n * Opaque authority-side version token, such as an ETag, object version, RDF\n * revision, or filesystem hash. For local filesystem projections this can be\n * the same value used for dirty detection.\n */\n sourceVersion?: string;\n /**\n * Local working-copy version captured when the entry was materialized. This\n * lets hydrated objects keep an authority ETag in sourceVersion while still\n * detecting local edits by hashing the working file.\n */\n workingVersion?: string;\n lastAccessedAt?: number;\n state: SolidFsEntryState;\n}\n\nexport interface SolidFsChange {\n path: string;\n resource?: string;\n source: SolidFsEntrySource;\n sourcePath: string;\n contentType?: string;\n projection: SolidFsProjection;\n type: SolidFsChangeType;\n sourceVersion?: string;\n}\n\nexport interface SolidFsManifest {\n workspace: string;\n cwd: string;\n projection: SolidFsProjection;\n entries: SolidFsManifestEntry[];\n changes?: SolidFsChange[];\n}\n\nexport interface SolidFsConflict {\n path: string;\n sourcePath: string;\n expectedVersion?: string;\n actualVersion?: string;\n message: string;\n}\n\nexport class SolidFsConflictError extends Error {\n public readonly conflicts: SolidFsConflict[];\n\n public constructor(conflicts: SolidFsConflict[]) {\n super(`SolidFS commit conflict: ${conflicts.map((conflict) => conflict.path).join(', ')}`);\n this.name = 'SolidFsConflictError';\n this.conflicts = conflicts;\n }\n}\n\nexport class SolidFsNotFoundError extends Error {\n public constructor(message: string) {\n super(message);\n this.name = 'SolidFsNotFoundError';\n }\n}\n\nexport interface MaterializedWorkspace {\n cwd: string;\n manifest: SolidFsManifest;\n /**\n * Materialize one object-backed resource into the real cwd. Implementations\n * without object hydration support can leave this undefined.\n */\n hydrate?(relativePath: string): Promise<SolidFsManifestEntry>;\n /**\n * Remove clean hydrated working copies that are no longer needed. Dirty files\n * must never be pruned.\n */\n prune?(options?: SolidFsPruneOptions): Promise<SolidFsManifest>;\n commit(): Promise<SolidFsManifest>;\n rollback(): Promise<void>;\n}\n\nexport interface SolidFS {\n prepare(input: SolidFsPrepareInput): Promise<MaterializedWorkspace>;\n}\n\nexport interface SolidFsSyncer {\n shouldTrack?(input: SolidFsPrepareInput): boolean;\n shouldTrackPath?(relativePath: string): boolean;\n sync(change: SolidFsChange, workspace: SolidFsManifest, context?: unknown): Promise<void>;\n}\n\nexport interface SolidFsHydrateInput {\n path: string;\n targetPath: string;\n workspace: SolidFsManifest;\n context?: unknown;\n}\n\nexport interface SolidFsHydrateResult {\n contentType?: string;\n sourceVersion?: string;\n}\n\nexport interface SolidFsCommitHydratedInput {\n change: SolidFsChange;\n workspace: SolidFsManifest;\n context?: unknown;\n}\n\nexport interface SolidFsCommitHydratedResult {\n sourceVersion?: string;\n}\n\nexport interface SolidFsHydrator {\n hydrate(input: SolidFsHydrateInput): Promise<SolidFsHydrateResult | void>;\n commit(input: SolidFsCommitHydratedInput): Promise<SolidFsCommitHydratedResult | void>;\n delete?(input: SolidFsCommitHydratedInput): Promise<void>;\n}\n\nexport interface SolidFsPruneOptions {\n /**\n * Prune clean hydrated files not accessed for at least this many ms.\n * Defaults to 0, meaning any clean hydrated file is eligible.\n */\n olderThanMs?: number;\n now?: number;\n}\n"]}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RepresentationPartialConvertingStore = void 0;
4
4
  const global_logger_factory_1 = require("global-logger-factory");
5
5
  const community_server_1 = require("@solid/community-server");
6
+ const RdfContentTypes_1 = require("./rdf/RdfContentTypes");
6
7
  /**
7
8
  * A store that converts representations based on their content type.
8
9
  */
@@ -26,19 +27,11 @@ class RepresentationPartialConvertingStore extends community_server_1.Passthroug
26
27
  }
27
28
  const contentType = representation.metadata.contentType;
28
29
  const preferencesType = Object.keys(preferences.type || {})[0];
29
- // Whitelist: Only allow conversion for known, pure RDF formats.
30
- // Everything else (HTML, Markdown, Images, random XML/JSON) is treated as a file.
31
- const SAFE_RDF_TYPES = new Set([
32
- 'text/turtle',
33
- 'application/ld+json',
34
- 'application/n-triples',
35
- 'application/n-quads',
36
- 'application/trig',
37
- 'text/n3',
38
- 'application/rdf+xml',
39
- community_server_1.INTERNAL_QUADS // Necessary for GET requests to convert internal quads back to public formats
40
- ]);
41
- if (!SAFE_RDF_TYPES.has(contentType)) {
30
+ if (preferences.type?.[contentType]) {
31
+ this.logger.debug(`Not converting ${identifier.path}: ${contentType} already satisfies preferences`);
32
+ return false;
33
+ }
34
+ if (contentType !== community_server_1.INTERNAL_QUADS && !(0, RdfContentTypes_1.isSafeRdfDocumentContentType)(contentType)) {
42
35
  this.logger.debug(`Not converting ${identifier.path}: ${contentType} is not in RDF whitelist`);
43
36
  return false;
44
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RepresentationPartialConvertingStore.js","sourceRoot":"","sources":["../../src/storage/RepresentationPartialConvertingStore.ts"],"names":[],"mappings":"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","sourcesContent":["import rdfParser from 'rdf-parse';\nimport { getLoggerFor } from 'global-logger-factory';\n\nimport {\n PassthroughStore,\n PassthroughConverter,\n AuxiliaryStrategy,\n ResourceStore,\n RepresentationConverter,\n RepresentationPreferences,\n ResourceIdentifier,\n Representation,\n RepresentationConverterArgs,\n Conditions,\n \n ChangeMap,\n INTERNAL_QUADS,\n APPLICATION_JSON,\n} from \"@solid/community-server\"\n\ninterface RepresentationPartialConvertingStoreOptions {\n outConverter?: RepresentationConverter\n inConverter?: RepresentationConverter\n inPreferences?: RepresentationPreferences\n}\n\n/**\n * A store that converts representations based on their content type.\n */\nexport class RepresentationPartialConvertingStore<T extends ResourceStore = ResourceStore> extends PassthroughStore<T> {\n protected readonly logger = getLoggerFor(this)\n\n private readonly metadataStrategy: AuxiliaryStrategy\n private readonly inConverter: RepresentationConverter\n private readonly outConverter: RepresentationConverter\n private readonly inPreferences: RepresentationPreferences\n \n constructor(\n source: T,\n metadataStrategy: AuxiliaryStrategy,\n options: RepresentationPartialConvertingStoreOptions,\n ) {\n super(source)\n this.metadataStrategy = metadataStrategy\n this.inConverter = options.inConverter ?? new PassthroughConverter();\n this.outConverter = options.outConverter ?? new PassthroughConverter();\n this.inPreferences = options.inPreferences ?? {};\n\n const inConverterClass = this.inConverter.constructor.name;\n const outConverterClass = this.outConverter.constructor.name;\n this.logger.debug(\n `Initializing with inConverter: ${inConverterClass}, \n outConverter: ${outConverterClass}, \n inPreferences: ${JSON.stringify(this.inPreferences)}`);\n }\n\n private async shouldConvert(\n identifier: ResourceIdentifier,\n representation: Representation,\n preferences: RepresentationPreferences,\n ) {\n if (representation.metadata.contentType === undefined) {\n return false\n }\n\n const contentType = representation.metadata.contentType;\n const preferencesType = Object.keys(preferences.type || {})[0];\n\n // Whitelist: Only allow conversion for known, pure RDF formats.\n // Everything else (HTML, Markdown, Images, random XML/JSON) is treated as a file.\n const SAFE_RDF_TYPES = new Set([\n 'text/turtle',\n 'application/ld+json',\n 'application/n-triples',\n 'application/n-quads',\n 'application/trig',\n 'text/n3',\n 'application/rdf+xml',\n INTERNAL_QUADS // Necessary for GET requests to convert internal quads back to public formats\n ]);\n\n if (!SAFE_RDF_TYPES.has(contentType)) {\n this.logger.debug(`Not converting ${identifier.path}: ${contentType} is not in RDF whitelist`);\n return false;\n }\n\n try {\n await this.inConverter.canHandle({ identifier, representation, preferences });\n this.logger.debug(\n `Converting ${identifier.path}: ${contentType} to ${preferencesType}`,\n );\n return true;\n } catch (error) {\n this.logger.debug(`Not converting ${identifier.path}: ${contentType} to ${preferencesType}. Error: ${error}`);\n return false;\n }\n }\n\n public override async getRepresentation(\n identifier: ResourceIdentifier,\n preferences: RepresentationPreferences,\n conditions?: Conditions,\n ): Promise<Representation> {\n let representation = await super.getRepresentation(identifier, preferences, conditions);\n if (await this.shouldConvert(identifier, representation, preferences)) {\n representation = await this.outConverter.handleSafe({ identifier, representation, preferences });\n }\n return representation;\n }\n\n public override async addResource(\n identifier: ResourceIdentifier,\n representation: Representation,\n conditions?: Conditions,\n ): Promise<ChangeMap> {\n // In case of containers, no content-type is required and the representation is not used.\n try {\n if (await this.shouldConvert(identifier, representation, this.inPreferences)) {\n // We can potentially run into problems here if we convert a turtle document where the base IRI is required,\n // since we don't know the resource IRI yet at this point.\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: this.inPreferences },\n );\n }\n } catch (error) {\n this.logger.warn(`Conversion skipped for ${identifier.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n return this.source.addResource(identifier, representation, conditions);\n }\n\n public override async setRepresentation(\n identifier: ResourceIdentifier,\n representation: Representation,\n conditions?: Conditions,\n ): Promise<ChangeMap> {\n try {\n // When it is a metadata resource, convert it to Quads as those are expected in the later stores\n if (this.metadataStrategy.isAuxiliaryIdentifier(identifier)) {\n this.logger.debug(`Converting metadata resource ${identifier.path} to ${INTERNAL_QUADS}`);\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: { type: { [INTERNAL_QUADS]: 1 }}},\n );\n } else if (await this.shouldConvert(identifier, representation, this.inPreferences)) {\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: this.inPreferences },\n );\n }\n } catch (error) {\n this.logger.warn(`Conversion skipped for ${identifier.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n return this.source.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
1
+ {"version":3,"file":"RepresentationPartialConvertingStore.js","sourceRoot":"","sources":["../../src/storage/RepresentationPartialConvertingStore.ts"],"names":[],"mappings":"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","sourcesContent":["import rdfParser from 'rdf-parse';\nimport { getLoggerFor } from 'global-logger-factory';\n\nimport {\n PassthroughStore,\n PassthroughConverter,\n AuxiliaryStrategy,\n ResourceStore,\n RepresentationConverter,\n RepresentationPreferences,\n ResourceIdentifier,\n Representation,\n RepresentationConverterArgs,\n Conditions,\n \n ChangeMap,\n INTERNAL_QUADS,\n APPLICATION_JSON,\n} from \"@solid/community-server\"\nimport { isSafeRdfDocumentContentType } from './rdf/RdfContentTypes'\n\ninterface RepresentationPartialConvertingStoreOptions {\n outConverter?: RepresentationConverter\n inConverter?: RepresentationConverter\n inPreferences?: RepresentationPreferences\n}\n\n/**\n * A store that converts representations based on their content type.\n */\nexport class RepresentationPartialConvertingStore<T extends ResourceStore = ResourceStore> extends PassthroughStore<T> {\n protected readonly logger = getLoggerFor(this)\n\n private readonly metadataStrategy: AuxiliaryStrategy\n private readonly inConverter: RepresentationConverter\n private readonly outConverter: RepresentationConverter\n private readonly inPreferences: RepresentationPreferences\n \n constructor(\n source: T,\n metadataStrategy: AuxiliaryStrategy,\n options: RepresentationPartialConvertingStoreOptions,\n ) {\n super(source)\n this.metadataStrategy = metadataStrategy\n this.inConverter = options.inConverter ?? new PassthroughConverter();\n this.outConverter = options.outConverter ?? new PassthroughConverter();\n this.inPreferences = options.inPreferences ?? {};\n\n const inConverterClass = this.inConverter.constructor.name;\n const outConverterClass = this.outConverter.constructor.name;\n this.logger.debug(\n `Initializing with inConverter: ${inConverterClass}, \n outConverter: ${outConverterClass}, \n inPreferences: ${JSON.stringify(this.inPreferences)}`);\n }\n\n private async shouldConvert(\n identifier: ResourceIdentifier,\n representation: Representation,\n preferences: RepresentationPreferences,\n ) {\n if (representation.metadata.contentType === undefined) {\n return false\n }\n\n const contentType = representation.metadata.contentType;\n const preferencesType = Object.keys(preferences.type || {})[0];\n\n if (preferences.type?.[contentType]) {\n this.logger.debug(`Not converting ${identifier.path}: ${contentType} already satisfies preferences`);\n return false;\n }\n\n if (contentType !== INTERNAL_QUADS && !isSafeRdfDocumentContentType(contentType)) {\n this.logger.debug(`Not converting ${identifier.path}: ${contentType} is not in RDF whitelist`);\n return false;\n }\n\n try {\n await this.inConverter.canHandle({ identifier, representation, preferences });\n this.logger.debug(\n `Converting ${identifier.path}: ${contentType} to ${preferencesType}`,\n );\n return true;\n } catch (error) {\n this.logger.debug(`Not converting ${identifier.path}: ${contentType} to ${preferencesType}. Error: ${error}`);\n return false;\n }\n }\n\n public override async getRepresentation(\n identifier: ResourceIdentifier,\n preferences: RepresentationPreferences,\n conditions?: Conditions,\n ): Promise<Representation> {\n let representation = await super.getRepresentation(identifier, preferences, conditions);\n if (await this.shouldConvert(identifier, representation, preferences)) {\n representation = await this.outConverter.handleSafe({ identifier, representation, preferences });\n }\n return representation;\n }\n\n public override async addResource(\n identifier: ResourceIdentifier,\n representation: Representation,\n conditions?: Conditions,\n ): Promise<ChangeMap> {\n // In case of containers, no content-type is required and the representation is not used.\n try {\n if (await this.shouldConvert(identifier, representation, this.inPreferences)) {\n // We can potentially run into problems here if we convert a turtle document where the base IRI is required,\n // since we don't know the resource IRI yet at this point.\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: this.inPreferences },\n );\n }\n } catch (error) {\n this.logger.warn(`Conversion skipped for ${identifier.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n return this.source.addResource(identifier, representation, conditions);\n }\n\n public override async setRepresentation(\n identifier: ResourceIdentifier,\n representation: Representation,\n conditions?: Conditions,\n ): Promise<ChangeMap> {\n try {\n // When it is a metadata resource, convert it to Quads as those are expected in the later stores\n if (this.metadataStrategy.isAuxiliaryIdentifier(identifier)) {\n this.logger.debug(`Converting metadata resource ${identifier.path} to ${INTERNAL_QUADS}`);\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: { type: { [INTERNAL_QUADS]: 1 }}},\n );\n } else if (await this.shouldConvert(identifier, representation, this.inPreferences)) {\n representation = await this.inConverter.handleSafe(\n { identifier, representation, preferences: this.inPreferences },\n );\n }\n } catch (error) {\n this.logger.warn(`Conversion skipped for ${identifier.path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n return this.source.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
@@ -1,9 +1,11 @@
1
1
  import { DataAccessorBasedStore, type ChangeMap, type ResourceIdentifier, type Patch, type Conditions, type DataAccessor, type IdentifierStrategy, type AuxiliaryStrategy, type Representation } from '@solid/community-server';
2
+ import { type LocalFirstRdfRepresentationResolverLike } from '../solidfs/LocalFirstRdfRepresentationResolver';
2
3
  export interface SparqlUpdateResourceStoreOptions {
3
4
  accessor: DataAccessor;
4
5
  identifierStrategy: IdentifierStrategy;
5
6
  auxiliaryStrategy: AuxiliaryStrategy;
6
7
  metadataStrategy: AuxiliaryStrategy;
8
+ localFirstRdfRepresentationResolver?: LocalFirstRdfRepresentationResolverLike;
7
9
  }
8
10
  /**
9
11
  * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE
@@ -12,8 +14,10 @@ export interface SparqlUpdateResourceStoreOptions {
12
14
  export declare class SparqlUpdateResourceStore extends DataAccessorBasedStore {
13
15
  private readonly generator;
14
16
  private readonly parser;
17
+ private readonly localFirstRdfRepresentationResolver;
15
18
  protected readonly logger: import("global-logger-factory").Logger<unknown>;
16
19
  constructor(options: SparqlUpdateResourceStoreOptions);
20
+ getRepresentation(identifier: ResourceIdentifier): Promise<Representation>;
17
21
  modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<ChangeMap>;
18
22
  /**
19
23
  * 只处理 SPARQL UPDATE (application/sparql-update)。
@@ -6,6 +6,7 @@ const sparqljs_1 = require("sparqljs");
6
6
  const community_server_1 = require("@solid/community-server");
7
7
  const StreamUtil_1 = require("@solid/community-server/dist/util/StreamUtil");
8
8
  const global_logger_factory_1 = require("global-logger-factory");
9
+ const LocalFirstRdfRepresentationResolver_1 = require("../solidfs/LocalFirstRdfRepresentationResolver");
9
10
  /**
10
11
  * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE
11
12
  * when the underlying DataAccessor supports it.
@@ -16,10 +17,22 @@ class SparqlUpdateResourceStore extends community_server_1.DataAccessorBasedStor
16
17
  this.generator = new sparqljs_1.Generator();
17
18
  this.parser = new sparqljs_1.Parser();
18
19
  this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
20
+ this.localFirstRdfRepresentationResolver = options.localFirstRdfRepresentationResolver ??
21
+ new LocalFirstRdfRepresentationResolver_1.LocalFirstRdfRepresentationResolver({
22
+ accessor: options.accessor,
23
+ metadataStrategy: options.metadataStrategy,
24
+ });
19
25
  // Check if identifierStrategy has baseUrl property (SingleRootIdentifierStrategy)
20
26
  const strategy = options.identifierStrategy;
21
27
  this.logger.info(`SparqlUpdateResourceStore initialized with identifierStrategy: ${options.identifierStrategy.constructor.name}, baseUrl: ${strategy.baseUrl ?? 'N/A'}`);
22
28
  }
29
+ async getRepresentation(identifier) {
30
+ const localRepresentation = await this.localFirstRdfRepresentationResolver.resolve(identifier);
31
+ if (localRepresentation) {
32
+ return localRepresentation;
33
+ }
34
+ return super.getRepresentation(identifier);
35
+ }
23
36
  // @ts-expect-error Upstream signature returns never; we return ChangeMap for successful PATCH.
24
37
  async modifyResource(identifier, patch, conditions) {
25
38
  this.logger.debug(`SparqlUpdateResourceStore.modifyResource called for ${identifier.path}`);
@@ -1 +1 @@
1
- {"version":3,"file":"SparqlUpdateResourceStore.js","sourceRoot":"","sources":["../../src/storage/SparqlUpdateResourceStore.ts"],"names":[],"mappings":";;;AAAA,2BAAiC;AACjC,uCAAoJ;AACpJ,8DAgBiC;AAEjC,6EAAgF;AAChF,iEAAqD;AASrD;;;GAGG;AACH,MAAa,yBAA0B,SAAQ,yCAAsB;IAKnE,YAAmB,OAAyC;QAC1D,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAL1F,cAAS,GAAG,IAAI,oBAAe,EAAE,CAAC;QAClC,WAAM,GAAG,IAAI,iBAAY,EAAE,CAAC;QACjB,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAItD,kFAAkF;QAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAqD,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kEAAkE,OAAO,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,cAAc,QAAQ,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;IAC3K,CAAC;IAED,+FAA+F;IAC/E,KAAK,CAAC,cAAc,CAAC,UAA8B,EAAE,KAAY,EAAE,UAAuB;QACxG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uDAAuD,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,OAAQ,KAA2B,CAAC,OAAO,KAAK,QAAQ,2BAA2B,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;QAE1J,MAAM,QAAQ,GAAI,IAAyC,CAAC,QAAmB,CAAC;QAChF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,MAAM,IAAI,0CAAuB,CAAC,8CAA8C,CAAC,CAAC;QACpF,CAAC;QAED,kDAAkD;QAClD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,QAA4C,CAAC;YACjD,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACpD,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,oCAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YACD,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,UAAU,CAAC,IAAI,+BAA+B,CAAC,CAAC;YAC3G,MAAM,IAAI,0CAAuB,CAAC,iDAAiD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QAElE,0EAA0E;QAC1E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,yCAAsB,CAAC,UAAU,EAAE,EAAE,CAAC,2BAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC1G,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,cAAc,CAAC,KAAY,EAAE,UAA8B;QACvE,kDAAkD;QAClD,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAA,6BAAgB,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,UAAkB,EAAE,UAA8B;QACxE,MAAM,KAAK,GAAG,gBAAW,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,kBAAkB,GAAI,IAAsG,CAAC,kBAAkB,CAAC;QAEtJ,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAAQ,EAAE;YAClD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAA8C,CAAC;YAC5D,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;gBAChH,MAAM,IAAI,sCAAmB,CAAC,SAAS,IAAI,CAAC,KAAK,8CAA8C,CAAC,CAAC;YACnG,CAAC;QACH,CAAC,CAAC;QACF,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE;YAChD,MAAM,MAAM,GAAG,gCAAgC,CAAC;YAChD,MAAM,GAAG,GAAG,gCAAgC,CAAC;YAC7C,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,KAAa,EAAU,EAAE,CACtE,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,aAAa,KAAK,CAAC,KAAK,OAAO,IAAI,MAAM,CAAC,CAAC;YAC5F,IAAI,GAAG,GAAG,IAAI,CAAC;YACf,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;YAC5C,CAAC;YACD,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,WAAW,GAAG,KAAK,EAAS,EAAE;YACrE,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAW,EAAO,EAAE,CAAC,CAAC;gBACxC,GAAG,MAAM;gBACT,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;aAChG,CAAC,CAAC,CAAC;QACN,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,CAAC,OAAY,EAAO,EAAE;YAC3C,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC3B,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAChC,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,OAAO,CAAC,CAAC,+CAA+C;YACjE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC5B,OAAO,OAAO,CAAC,CAAC,6CAA6C;YAC/D,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,OAAO,CAAC,CAAC,+CAA+C;YACjE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,CAAC,KAAa,EAA4B,EAAE;YAC/D,IAAI,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAc,EAAE;gBACzC,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC9B,OAAO;wBACL,GAAG,IAAI;wBACP,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;wBACxB,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;qBAC1D,CAAC;gBACJ,CAAC;gBACD,sBAAsB;gBACtB,OAAO;oBACL,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,KAAK;oBACX,OAAO,EAAE,cAAc,CAAC,CAAE,IAAI,CAAE,EAAE,KAAK,CAAC;iBACzC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,qDAAqD,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAC;YAExE,qEAAqE;YACrE,IAAK,MAAc,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,UAAU,CAAC,IAAI,iDAAiD,CAAC,CAAC;gBACjI,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,GAAwB,EAAS,EAAE,CAC9D,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAS,EAAE;gBACxB,MAAM,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;gBACxB,IAAI,CAAC,OAAO;oBAAE,OAAO,EAAE,CAAC;gBACxB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,KAAU,EAAS,EAAE,CAC3C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;gBACzD,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YACP,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAgB,EAAE,QAAQ,CAAC,CAAC;YACjE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAgB,EAAE,QAAQ,CAAC,CAAC;YACjE,MAAM,YAAY,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAW,EAAE,CACjF,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,KAAK,UAAU,CAAC,CAAC;YAEjH,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAO,EAAW,EAAE,CAC1D,CAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,CAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;gBAC9E,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;gBACpC,CAAC,YAAY,CAAC,CAAC;YAEjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,SAAS,kBAAkB,YAAY,mBAAmB,aAAa,CAAC,MAAM,mBAAmB,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1K,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEjH,IAAI,SAAS,IAAI,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjE,MAAM,YAAY,GAAG,CAAC,IAAS,EAAU,EAAE;oBACzC,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;wBAClC,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;oBAC3B,CAAC;oBACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;wBAChC,8CAA8C;wBAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;wBAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wBAE3E,IAAI,OAAe,CAAC;wBACpB,IAAI,eAAe,GAAG,KAAK,CAAC;wBAE5B,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;4BAC7B,+DAA+D;4BAC/D,eAAe,GAAG,IAAI,CAAC;4BACvB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;4BACrB,gCAAgC;4BAChC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;4BAC9C,2DAA2D;4BAC3D,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gCAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gCACnC,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gCACnD,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gCAC7E,CAAC;4BACH,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,sCAAsC;4BACtC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;wBACnE,CAAC;wBAED,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;wBAE5C,qCAAqC;wBACrC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;4BAClB,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACvD,CAAC;wBACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,yCAAyC,EAAE,CAAC;4BACvF,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC;wBAChE,CAAC;wBACD,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC;oBACtC,CAAC;oBACD,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;wBAClC,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC3B,CAAC;oBACD,kCAAkC;oBAClC,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;gBAC3B,CAAC,CAAC;gBACF,MAAM,WAAW,GAAG,CAAC,OAAc,EAAU,EAAE,CAC7C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAU,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC9H,IAAI,KAAK,GAAa,EAAE,CAAC;gBACzB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,KAAK,OAAO,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACzF,CAAC;gBACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,KAAK,OAAO,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACzF,CAAC;gBACD,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,UAAU,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC,CAAC;gBAC5F,OAAO,gBAAgB,CAAC;YAC1B,CAAC;YAED,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAO,EAAmB,EAAE;gBAC/D,QAAQ,EAAE,CAAC,UAAU,EAAE,CAAC;oBACtB,KAAK,cAAc,CAAC;oBACpB,KAAK,cAAc;wBACjB,OAAO;4BACL,GAAG,EAAE;4BACL,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC;4BAC/B,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC;4BAC/B,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,EAAE;yBACzH,CAAC;oBACJ,KAAK,QAAQ,CAAC;oBACd,KAAK,QAAQ,CAAC,CAAC,CAAC;wBACd,MAAM,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAClD,MAAM,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAClD,OAAO;4BACL,UAAU,EAAE,cAAc;4BAC1B,MAAM,EAAE,WAAW;4BACnB,MAAM,EAAE,WAAW;4BACnB,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,EAAE;yBACzH,CAAC;oBACJ,CAAC;oBACD;wBACE,OAAO,EAAE,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,UAAU,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC,CAAC;YACtF,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,sCAAsC,UAAU,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;YAC/E,OAAO,CAAC,GAAG,CAAC,gCAAgC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACxE,MAAM,cAAc,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,sCAAsC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAClF,OAAO,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,KAAY;QACtC,OAAO,OAAQ,KAA2B,CAAC,OAAO,KAAK,QAAQ,CAAC;IAClE,CAAC;IAEO,eAAe,CAAC,QAAiB;QAIvC,OAAO,OAAO,QAAQ,KAAK,QAAQ;YACjC,QAAQ,KAAK,IAAI;YACjB,OAAQ,QAA8C,CAAC,mBAAmB,KAAK,UAAU;YACzF,OAAQ,QAAsC,CAAC,WAAW,KAAK,UAAU,CAAC;IAC9E,CAAC;IAEe,KAAK,CAAC,iBAAiB,CAAC,UAA8B,EAAE,cAA8B,EAAE,UAAuB;QAC7H,OAAO,KAAK,CAAC,iBAAiB,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACzE,CAAC;CACF;AApTD,8DAoTC","sourcesContent":["import { DataFactory } from 'n3';\nimport { Generator as SparqlGenerator, Parser as SparqlParser, type GraphQuads, type UpdateOperation, type Update as SparqlUpdate } from 'sparqljs';\nimport {\n DataAccessorBasedStore,\n type ChangeMap,\n type ResourceIdentifier,\n type Patch,\n NotImplementedHttpError,\n type Conditions,\n NotFoundHttpError,\n RepresentationMetadata,\n AS,\n SOLID_AS,\n BadRequestHttpError,\n type DataAccessor,\n type IdentifierStrategy,\n type AuxiliaryStrategy,\n type Representation,\n} from '@solid/community-server';\nimport type { SparqlUpdatePatch } from '@solid/community-server';\nimport { readableToString } from '@solid/community-server/dist/util/StreamUtil';\nimport { getLoggerFor } from 'global-logger-factory';\n\nexport interface SparqlUpdateResourceStoreOptions {\n accessor: DataAccessor;\n identifierStrategy: IdentifierStrategy;\n auxiliaryStrategy: AuxiliaryStrategy;\n metadataStrategy: AuxiliaryStrategy;\n}\n\n/**\n * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE\n * when the underlying DataAccessor supports it.\n */\nexport class SparqlUpdateResourceStore extends DataAccessorBasedStore {\n private readonly generator = new SparqlGenerator();\n private readonly parser = new SparqlParser();\n protected override readonly logger = getLoggerFor(this);\n\n public constructor(options: SparqlUpdateResourceStoreOptions) {\n super(options.accessor, options.identifierStrategy, options.auxiliaryStrategy, options.metadataStrategy);\n // Check if identifierStrategy has baseUrl property (SingleRootIdentifierStrategy)\n const strategy = options.identifierStrategy as unknown as { baseUrl?: string };\n this.logger.info(`SparqlUpdateResourceStore initialized with identifierStrategy: ${options.identifierStrategy.constructor.name}, baseUrl: ${strategy.baseUrl ?? 'N/A'}`);\n }\n\n // @ts-expect-error Upstream signature returns never; we return ChangeMap for successful PATCH.\n public override async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<ChangeMap> {\n this.logger.debug(`SparqlUpdateResourceStore.modifyResource called for ${identifier.path}`);\n this.logger.debug(`Patch has algebra: ${typeof (patch as SparqlUpdatePatch).algebra === 'object'}, metadata.contentType: ${patch.metadata?.contentType}`);\n\n const accessor = (this as unknown as { accessor: unknown }).accessor as unknown;\n if (!this.isSparqlCapable(accessor)) {\n this.logger.debug('Accessor is not SPARQL capable');\n throw new NotImplementedHttpError('SPARQL UPDATE not supported by this accessor');\n }\n\n // Keep the default condition validation semantics\n if (conditions) {\n let metadata: RepresentationMetadata | undefined;\n try {\n metadata = await accessor.getMetadata(identifier);\n } catch (error: unknown) {\n if (!NotFoundHttpError.isInstance(error)) {\n throw error;\n }\n }\n this.validateConditions(conditions, metadata);\n }\n\n const sparqlUpdate = await this.toSparqlUpdate(patch, identifier);\n if (!sparqlUpdate) {\n this.logger.debug(`toSparqlUpdate returned undefined for ${identifier.path}, falling back to CSS handler`);\n throw new NotImplementedHttpError('Unsupported PATCH payload for SPARQL conversion');\n }\n\n this.logger.debug(`Applying SPARQL PATCH to ${identifier.path}: ${sparqlUpdate}`);\n await accessor.executeSparqlUpdate(sparqlUpdate, identifier.path);\n\n // PATCH does not affect containment; mark the target resource as updated.\n const changes = new Map() as ChangeMap;\n changes.set(identifier, new RepresentationMetadata(identifier, { [SOLID_AS.activity]: AS.terms.Update }));\n return changes;\n }\n\n /**\n * 只处理 SPARQL UPDATE (application/sparql-update)。\n * N3 Patch 和其他类型返回 undefined,让 CSS PatchingStore 回退到 get-patch-set 逻辑。\n */\n private async toSparqlUpdate(patch: Patch, identifier: ResourceIdentifier): Promise<string | undefined> {\n // 只处理 SPARQL UPDATE,其他类型(包括 N3 Patch)回退到 CSS 默认处理\n if (!this.isSparqlUpdatePatch(patch)) {\n return undefined;\n }\n\n const updateText = await readableToString(patch.data);\n return this.normalizeGraphs(updateText, identifier);\n }\n\n /**\n * Ensure SPARQL UPDATE targets the resource graph (CSS stores documents in named graphs).\n */\n private normalizeGraphs(updateText: string, identifier: ResourceIdentifier): string | undefined {\n const graph = DataFactory.namedNode(identifier.path);\n const identifierStrategy = (this as unknown as { identifierStrategy: { supportsIdentifier: (id: ResourceIdentifier) => boolean }}).identifierStrategy;\n\n const assertGraphAllowed = (value: unknown): void => {\n if (!value || typeof value !== 'object') {\n return;\n }\n const term = value as { termType?: string; value?: string };\n if (term.termType === 'NamedNode' && term.value && !identifierStrategy.supportsIdentifier({ path: term.value })) {\n throw new BadRequestHttpError(`GRAPH ${term.value} is outside the configured identifier space.`);\n }\n };\n const wrapDefaultGraph = (text: string): string => {\n const insert = /INSERT\\s+DATA\\s*{\\s*([^}]*)}/is;\n const del = /DELETE\\s+DATA\\s*{\\s*([^}]*)}/is;\n const rewrite = (regex: RegExp, label: string, input: string): string =>\n input.replace(regex, (_match, body) => `${label} { GRAPH <${graph.value}> { ${body} } }`);\n let out = text;\n if (insert.test(out)) {\n out = rewrite(insert, 'INSERT DATA', out);\n }\n if (del.test(out)) {\n out = rewrite(del, 'DELETE DATA', out);\n }\n return out;\n };\n\n const rewriteTriples = (triples?: any[], targetGraph = graph): any[] => {\n if (!triples) return [];\n return triples.map((triple: any): any => ({\n ...triple,\n graph: (!triple.graph || triple.graph.termType === 'DefaultGraph') ? targetGraph : triple.graph,\n }));\n };\n\n const rewritePattern = (pattern: any): any => {\n if (pattern.type === 'bgp') {\n return { ...pattern, triples: rewriteTriples(pattern.triples) };\n }\n if (pattern.type === 'graph') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'group') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'optional') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'union') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'minus') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'filter') {\n return pattern; // FILTER doesn't contain triples, pass through\n }\n if (pattern.type === 'bind') {\n return pattern; // BIND doesn't contain triples, pass through\n }\n if (pattern.type === 'values') {\n return pattern; // VALUES doesn't contain triples, pass through\n }\n if (pattern.type === 'service') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n return pattern;\n };\n\n const toGraphQuads = (items?: any[]): GraphQuads[] | undefined => {\n if (!items) return items;\n return items.map((item: any): GraphQuads => {\n if (item?.type === 'graph') {\n assertGraphAllowed(item.name);\n return {\n ...item,\n name: item.name ?? graph,\n triples: rewriteTriples(item.triples, item.name ?? graph),\n };\n }\n // Treat as plain quad\n return {\n type: 'graph',\n name: graph,\n triples: rewriteTriples([ item ], graph),\n };\n });\n };\n\n try {\n console.log(`[normalizeGraphs] Input SPARQL (first 500 chars): ${updateText.slice(0, 500)}`);\n const parsed = this.parser.parse(updateText) as unknown as SparqlUpdate;\n\n // Explicitly reject SPARQL Queries (SELECT, ASK, CONSTRUCT) in PATCH\n if ((parsed as any).type === 'query') {\n this.logger.warn(`Received SPARQL Query in PATCH request for ${identifier.path}. SPARQL PATCH only supports UPDATE operations.`);\n return undefined;\n }\n\n const collect = (ops: any[], key: 'delete' | 'insert'): any[] =>\n ops.flatMap((op): any[] => {\n const entries = op[key];\n if (!entries) return [];\n if (Array.isArray(entries)) {\n return entries.flatMap((entry: any): any[] =>\n entry.triples ? entry.triples : (entry.quads ?? []));\n }\n return [];\n });\n const deleteTriples = collect(parsed.updates as any[], 'delete');\n const insertTriples = collect(parsed.updates as any[], 'insert');\n const hasVariables = [...deleteTriples, ...insertTriples].some((t: any): boolean =>\n t.subject?.termType === 'Variable' || t.predicate?.termType === 'Variable' || t.object?.termType === 'Variable');\n\n const simpleOps = parsed.updates.every((op: any): boolean =>\n [ 'delete', 'insert', 'insertdelete', 'deleteinsert' ].includes(op.updateType) &&\n (!op.where || op.where.length === 0) &&\n !hasVariables);\n\n this.logger.debug(`[normalizeGraphs] simpleOps=${simpleOps}, hasVariables=${hasVariables}, deleteTriples=${deleteTriples.length}, insertTriples=${insertTriples.length}`);\n this.logger.debug(`[normalizeGraphs] updateTypes: ${parsed.updates.map((op: any) => op.updateType).join(', ')}`);\n\n if (simpleOps && deleteTriples.length + insertTriples.length > 0) {\n const termToString = (term: any): string => {\n if (term.termType === 'NamedNode') {\n return `<${term.value}>`;\n }\n if (term.termType === 'Literal') {\n // Escape special characters in literal values\n const hasQuotes = term.value.includes('\"');\n const hasNewlines = term.value.includes('\\n') || term.value.includes('\\r');\n\n let escaped: string;\n let useTripleQuotes = false;\n\n if (hasQuotes || hasNewlines) {\n // Use triple-quoted strings for values with quotes or newlines\n useTripleQuotes = true;\n escaped = term.value;\n // Escape triple-quote sequences\n escaped = escaped.replace(/\"\"\"/g, '\"\\\\\"\\\\\"\"');\n // Escape trailing quotes to avoid \"\"\"content\"\"\"\" sequences\n if (escaped.endsWith('\"')) {\n const match = escaped.match(/\"*$/);\n const trailingQuotes = match ? match[0].length : 0;\n if (trailingQuotes > 0) {\n escaped = escaped.slice(0, -trailingQuotes) + '\\\\\"'.repeat(trailingQuotes);\n }\n }\n } else {\n // Regular escaping for simple strings\n escaped = term.value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n const quote = useTripleQuotes ? '\"\"\"' : '\"';\n\n // Handle language tags and datatypes\n if (term.language) {\n return `${quote}${escaped}${quote}@${term.language}`;\n }\n if (term.datatype && term.datatype.value !== 'http://www.w3.org/2001/XMLSchema#string') {\n return `${quote}${escaped}${quote}^^<${term.datatype.value}>`;\n }\n return `${quote}${escaped}${quote}`;\n }\n if (term.termType === 'BlankNode') {\n return `_:${term.value}`;\n }\n // Fallback for unknown term types\n return `<${term.value}>`;\n };\n const toTripleStr = (triples: any[]): string =>\n triples.map((t): string => `${termToString(t.subject)} ${termToString(t.predicate)} ${termToString(t.object)} .`).join(' ');\n let parts: string[] = [];\n if (deleteTriples.length > 0) {\n parts.push(`DELETE DATA { GRAPH <${graph.value}> { ${toTripleStr(deleteTriples)} } }`);\n }\n if (insertTriples.length > 0) {\n parts.push(`INSERT DATA { GRAPH <${graph.value}> { ${toTripleStr(insertTriples)} } }`);\n }\n const normalizedSimple = parts.join(';\\n');\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalizedSimple}`);\n return normalizedSimple;\n }\n\n parsed.updates = parsed.updates.map((op: any): UpdateOperation => {\n switch (op.updateType) {\n case 'deleteinsert':\n case 'insertdelete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n insert: toGraphQuads(op.insert),\n where: op.where && op.where.length > 0 ? [ { type: 'graph', name: graph, patterns: op.where.map(rewritePattern) } ] : [],\n };\n case 'delete':\n case 'insert': {\n const deleteQuads = toGraphQuads(op.delete) ?? [];\n const insertQuads = toGraphQuads(op.insert) ?? [];\n return {\n updateType: 'insertdelete',\n delete: deleteQuads,\n insert: insertQuads,\n where: op.where && op.where.length > 0 ? [ { type: 'graph', name: graph, patterns: op.where.map(rewritePattern) } ] : [],\n };\n }\n default:\n return op;\n }\n });\n const normalized = this.generator.stringify(parsed);\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalized}`);\n return normalized;\n } catch (error: unknown) {\n console.log(`[normalizeGraphs] Parse FAILED for ${identifier.path}: ${error}`);\n console.log(`[normalizeGraphs] Input was: ${updateText.slice(0, 300)}`);\n const fallbackResult = wrapDefaultGraph(updateText);\n console.log(`[normalizeGraphs] Fallback result: ${fallbackResult.slice(0, 300)}`);\n return fallbackResult;\n }\n }\n\n private isSparqlUpdatePatch(patch: Patch): patch is SparqlUpdatePatch {\n return typeof (patch as SparqlUpdatePatch).algebra === 'object';\n }\n\n private isSparqlCapable(accessor: unknown): accessor is {\n executeSparqlUpdate: (query: string, baseIri?: string) => Promise<void>;\n getMetadata: (identifier: ResourceIdentifier) => Promise<RepresentationMetadata>;\n } {\n return typeof accessor === 'object' &&\n accessor !== null &&\n typeof (accessor as { executeSparqlUpdate?: unknown }).executeSparqlUpdate === 'function' &&\n typeof (accessor as { getMetadata?: unknown }).getMetadata === 'function';\n }\n\n public override async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ChangeMap> {\n return super.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
1
+ {"version":3,"file":"SparqlUpdateResourceStore.js","sourceRoot":"","sources":["../../src/storage/SparqlUpdateResourceStore.ts"],"names":[],"mappings":";;;AAAA,2BAAiC;AACjC,uCAAoJ;AACpJ,8DAgBiC;AAEjC,6EAAgF;AAChF,iEAAqD;AACrD,wGAGwD;AAUxD;;;GAGG;AACH,MAAa,yBAA0B,SAAQ,yCAAsB;IAMnE,YAAmB,OAAyC;QAC1D,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAN1F,cAAS,GAAG,IAAI,oBAAe,EAAE,CAAC;QAClC,WAAM,GAAG,IAAI,iBAAY,EAAE,CAAC;QAEjB,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAItD,IAAI,CAAC,mCAAmC,GAAG,OAAO,CAAC,mCAAmC;YACpF,IAAI,yEAAmC,CAAC;gBACtC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;aAC3C,CAAC,CAAC;QACL,kFAAkF;QAClF,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAqD,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kEAAkE,OAAO,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,cAAc,QAAQ,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;IAC3K,CAAC;IAEe,KAAK,CAAC,iBAAiB,CAAC,UAA8B;QACpE,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,mCAAmC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC/F,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QAED,OAAO,KAAK,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAED,+FAA+F;IAC/E,KAAK,CAAC,cAAc,CAAC,UAA8B,EAAE,KAAY,EAAE,UAAuB;QACxG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uDAAuD,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,OAAQ,KAA2B,CAAC,OAAO,KAAK,QAAQ,2BAA2B,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;QAE1J,MAAM,QAAQ,GAAI,IAAyC,CAAC,QAAmB,CAAC;QAChF,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,MAAM,IAAI,0CAAuB,CAAC,8CAA8C,CAAC,CAAC;QACpF,CAAC;QAED,kDAAkD;QAClD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,QAA4C,CAAC;YACjD,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACpD,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,oCAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YACD,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,UAAU,CAAC,IAAI,+BAA+B,CAAC,CAAC;YAC3G,MAAM,IAAI,0CAAuB,CAAC,iDAAiD,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,UAAU,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QAElE,0EAA0E;QAC1E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,yCAAsB,CAAC,UAAU,EAAE,EAAE,CAAC,2BAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC1G,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,cAAc,CAAC,KAAY,EAAE,UAA8B;QACvE,kDAAkD;QAClD,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAA,6BAAgB,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,UAAkB,EAAE,UAA8B;QACxE,MAAM,KAAK,GAAG,gBAAW,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,kBAAkB,GAAI,IAAsG,CAAC,kBAAkB,CAAC;QAEtJ,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAAQ,EAAE;YAClD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAA8C,CAAC;YAC5D,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;gBAChH,MAAM,IAAI,sCAAmB,CAAC,SAAS,IAAI,CAAC,KAAK,8CAA8C,CAAC,CAAC;YACnG,CAAC;QACH,CAAC,CAAC;QACF,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE;YAChD,MAAM,MAAM,GAAG,gCAAgC,CAAC;YAChD,MAAM,GAAG,GAAG,gCAAgC,CAAC;YAC7C,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,KAAa,EAAU,EAAE,CACtE,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,aAAa,KAAK,CAAC,KAAK,OAAO,IAAI,MAAM,CAAC,CAAC;YAC5F,IAAI,GAAG,GAAG,IAAI,CAAC;YACf,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;YAC5C,CAAC;YACD,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClB,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,WAAW,GAAG,KAAK,EAAS,EAAE;YACrE,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAW,EAAO,EAAE,CAAC,CAAC;gBACxC,GAAG,MAAM;gBACT,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;aAChG,CAAC,CAAC,CAAC;QACN,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,CAAC,OAAY,EAAO,EAAE;YAC3C,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC3B,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAChC,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,OAAO,CAAC,CAAC,+CAA+C;YACjE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC5B,OAAO,OAAO,CAAC,CAAC,6CAA6C;YAC/D,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,OAAO,CAAC,CAAC,+CAA+C;YACjE,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC/E,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,CAAC,KAAa,EAA4B,EAAE;YAC/D,IAAI,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAc,EAAE;gBACzC,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC9B,OAAO;wBACL,GAAG,IAAI;wBACP,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;wBACxB,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;qBAC1D,CAAC;gBACJ,CAAC;gBACD,sBAAsB;gBACtB,OAAO;oBACL,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,KAAK;oBACX,OAAO,EAAE,cAAc,CAAC,CAAE,IAAI,CAAE,EAAE,KAAK,CAAC;iBACzC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,qDAAqD,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAC;YAExE,qEAAqE;YACrE,IAAK,MAAc,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,UAAU,CAAC,IAAI,iDAAiD,CAAC,CAAC;gBACjI,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,GAAwB,EAAS,EAAE,CAC9D,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAS,EAAE;gBACxB,MAAM,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;gBACxB,IAAI,CAAC,OAAO;oBAAE,OAAO,EAAE,CAAC;gBACxB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,KAAU,EAAS,EAAE,CAC3C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;gBACzD,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YACP,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAgB,EAAE,QAAQ,CAAC,CAAC;YACjE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAgB,EAAE,QAAQ,CAAC,CAAC;YACjE,MAAM,YAAY,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAW,EAAE,CACjF,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,KAAK,UAAU,CAAC,CAAC;YAEjH,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAO,EAAW,EAAE,CAC1D,CAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,CAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;gBAC9E,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;gBACpC,CAAC,YAAY,CAAC,CAAC;YAEjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,SAAS,kBAAkB,YAAY,mBAAmB,aAAa,CAAC,MAAM,mBAAmB,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1K,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEjH,IAAI,SAAS,IAAI,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjE,MAAM,YAAY,GAAG,CAAC,IAAS,EAAU,EAAE;oBACzC,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;wBAClC,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;oBAC3B,CAAC;oBACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;wBAChC,8CAA8C;wBAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;wBAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wBAE3E,IAAI,OAAe,CAAC;wBACpB,IAAI,eAAe,GAAG,KAAK,CAAC;wBAE5B,IAAI,SAAS,IAAI,WAAW,EAAE,CAAC;4BAC7B,+DAA+D;4BAC/D,eAAe,GAAG,IAAI,CAAC;4BACvB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;4BACrB,gCAAgC;4BAChC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;4BAC9C,2DAA2D;4BAC3D,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gCAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gCACnC,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gCACnD,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gCAC7E,CAAC;4BACH,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,sCAAsC;4BACtC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;wBACnE,CAAC;wBAED,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;wBAE5C,qCAAqC;wBACrC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;4BAClB,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;wBACvD,CAAC;wBACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,yCAAyC,EAAE,CAAC;4BACvF,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,CAAC;wBAChE,CAAC;wBACD,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC;oBACtC,CAAC;oBACD,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;wBAClC,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC3B,CAAC;oBACD,kCAAkC;oBAClC,OAAO,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;gBAC3B,CAAC,CAAC;gBACF,MAAM,WAAW,GAAG,CAAC,OAAc,EAAU,EAAE,CAC7C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAU,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC9H,IAAI,KAAK,GAAa,EAAE,CAAC;gBACzB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,KAAK,OAAO,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACzF,CAAC;gBACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,KAAK,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,KAAK,OAAO,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;gBACzF,CAAC;gBACD,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,UAAU,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC,CAAC;gBAC5F,OAAO,gBAAgB,CAAC;YAC1B,CAAC;YAED,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAO,EAAmB,EAAE;gBAC/D,QAAQ,EAAE,CAAC,UAAU,EAAE,CAAC;oBACtB,KAAK,cAAc,CAAC;oBACpB,KAAK,cAAc;wBACjB,OAAO;4BACL,GAAG,EAAE;4BACL,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC;4BAC/B,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC;4BAC/B,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,EAAE;yBACzH,CAAC;oBACJ,KAAK,QAAQ,CAAC;oBACd,KAAK,QAAQ,CAAC,CAAC,CAAC;wBACd,MAAM,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAClD,MAAM,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAClD,OAAO;4BACL,UAAU,EAAE,cAAc;4BAC1B,MAAM,EAAE,WAAW;4BACnB,MAAM,EAAE,WAAW;4BACnB,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC,EAAE;yBACzH,CAAC;oBACJ,CAAC;oBACD;wBACE,OAAO,EAAE,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gCAAgC,UAAU,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC,CAAC;YACtF,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,sCAAsC,UAAU,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC;YAC/E,OAAO,CAAC,GAAG,CAAC,gCAAgC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACxE,MAAM,cAAc,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,sCAAsC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAClF,OAAO,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,KAAY;QACtC,OAAO,OAAQ,KAA2B,CAAC,OAAO,KAAK,QAAQ,CAAC;IAClE,CAAC;IAEO,eAAe,CAAC,QAAiB;QAIvC,OAAO,OAAO,QAAQ,KAAK,QAAQ;YACjC,QAAQ,KAAK,IAAI;YACjB,OAAQ,QAA8C,CAAC,mBAAmB,KAAK,UAAU;YACzF,OAAQ,QAAsC,CAAC,WAAW,KAAK,UAAU,CAAC;IAC9E,CAAC;IAEe,KAAK,CAAC,iBAAiB,CAAC,UAA8B,EAAE,cAA8B,EAAE,UAAuB;QAC7H,OAAO,KAAK,CAAC,iBAAiB,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACzE,CAAC;CACF;AAnUD,8DAmUC","sourcesContent":["import { DataFactory } from 'n3';\nimport { Generator as SparqlGenerator, Parser as SparqlParser, type GraphQuads, type UpdateOperation, type Update as SparqlUpdate } from 'sparqljs';\nimport {\n DataAccessorBasedStore,\n type ChangeMap,\n type ResourceIdentifier,\n type Patch,\n NotImplementedHttpError,\n type Conditions,\n NotFoundHttpError,\n RepresentationMetadata,\n AS,\n SOLID_AS,\n BadRequestHttpError,\n type DataAccessor,\n type IdentifierStrategy,\n type AuxiliaryStrategy,\n type Representation,\n} from '@solid/community-server';\nimport type { SparqlUpdatePatch } from '@solid/community-server';\nimport { readableToString } from '@solid/community-server/dist/util/StreamUtil';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n LocalFirstRdfRepresentationResolver,\n type LocalFirstRdfRepresentationResolverLike,\n} from '../solidfs/LocalFirstRdfRepresentationResolver';\n\nexport interface SparqlUpdateResourceStoreOptions {\n accessor: DataAccessor;\n identifierStrategy: IdentifierStrategy;\n auxiliaryStrategy: AuxiliaryStrategy;\n metadataStrategy: AuxiliaryStrategy;\n localFirstRdfRepresentationResolver?: LocalFirstRdfRepresentationResolverLike;\n}\n\n/**\n * ResourceStore that short-circuits PATCH into direct SPARQL UPDATE\n * when the underlying DataAccessor supports it.\n */\nexport class SparqlUpdateResourceStore extends DataAccessorBasedStore {\n private readonly generator = new SparqlGenerator();\n private readonly parser = new SparqlParser();\n private readonly localFirstRdfRepresentationResolver: LocalFirstRdfRepresentationResolverLike;\n protected override readonly logger = getLoggerFor(this);\n\n public constructor(options: SparqlUpdateResourceStoreOptions) {\n super(options.accessor, options.identifierStrategy, options.auxiliaryStrategy, options.metadataStrategy);\n this.localFirstRdfRepresentationResolver = options.localFirstRdfRepresentationResolver ??\n new LocalFirstRdfRepresentationResolver({\n accessor: options.accessor,\n metadataStrategy: options.metadataStrategy,\n });\n // Check if identifierStrategy has baseUrl property (SingleRootIdentifierStrategy)\n const strategy = options.identifierStrategy as unknown as { baseUrl?: string };\n this.logger.info(`SparqlUpdateResourceStore initialized with identifierStrategy: ${options.identifierStrategy.constructor.name}, baseUrl: ${strategy.baseUrl ?? 'N/A'}`);\n }\n\n public override async getRepresentation(identifier: ResourceIdentifier): Promise<Representation> {\n const localRepresentation = await this.localFirstRdfRepresentationResolver.resolve(identifier);\n if (localRepresentation) {\n return localRepresentation;\n }\n\n return super.getRepresentation(identifier);\n }\n\n // @ts-expect-error Upstream signature returns never; we return ChangeMap for successful PATCH.\n public override async modifyResource(identifier: ResourceIdentifier, patch: Patch, conditions?: Conditions): Promise<ChangeMap> {\n this.logger.debug(`SparqlUpdateResourceStore.modifyResource called for ${identifier.path}`);\n this.logger.debug(`Patch has algebra: ${typeof (patch as SparqlUpdatePatch).algebra === 'object'}, metadata.contentType: ${patch.metadata?.contentType}`);\n\n const accessor = (this as unknown as { accessor: unknown }).accessor as unknown;\n if (!this.isSparqlCapable(accessor)) {\n this.logger.debug('Accessor is not SPARQL capable');\n throw new NotImplementedHttpError('SPARQL UPDATE not supported by this accessor');\n }\n\n // Keep the default condition validation semantics\n if (conditions) {\n let metadata: RepresentationMetadata | undefined;\n try {\n metadata = await accessor.getMetadata(identifier);\n } catch (error: unknown) {\n if (!NotFoundHttpError.isInstance(error)) {\n throw error;\n }\n }\n this.validateConditions(conditions, metadata);\n }\n\n const sparqlUpdate = await this.toSparqlUpdate(patch, identifier);\n if (!sparqlUpdate) {\n this.logger.debug(`toSparqlUpdate returned undefined for ${identifier.path}, falling back to CSS handler`);\n throw new NotImplementedHttpError('Unsupported PATCH payload for SPARQL conversion');\n }\n\n this.logger.debug(`Applying SPARQL PATCH to ${identifier.path}: ${sparqlUpdate}`);\n await accessor.executeSparqlUpdate(sparqlUpdate, identifier.path);\n\n // PATCH does not affect containment; mark the target resource as updated.\n const changes = new Map() as ChangeMap;\n changes.set(identifier, new RepresentationMetadata(identifier, { [SOLID_AS.activity]: AS.terms.Update }));\n return changes;\n }\n\n /**\n * 只处理 SPARQL UPDATE (application/sparql-update)。\n * N3 Patch 和其他类型返回 undefined,让 CSS PatchingStore 回退到 get-patch-set 逻辑。\n */\n private async toSparqlUpdate(patch: Patch, identifier: ResourceIdentifier): Promise<string | undefined> {\n // 只处理 SPARQL UPDATE,其他类型(包括 N3 Patch)回退到 CSS 默认处理\n if (!this.isSparqlUpdatePatch(patch)) {\n return undefined;\n }\n\n const updateText = await readableToString(patch.data);\n return this.normalizeGraphs(updateText, identifier);\n }\n\n /**\n * Ensure SPARQL UPDATE targets the resource graph (CSS stores documents in named graphs).\n */\n private normalizeGraphs(updateText: string, identifier: ResourceIdentifier): string | undefined {\n const graph = DataFactory.namedNode(identifier.path);\n const identifierStrategy = (this as unknown as { identifierStrategy: { supportsIdentifier: (id: ResourceIdentifier) => boolean }}).identifierStrategy;\n\n const assertGraphAllowed = (value: unknown): void => {\n if (!value || typeof value !== 'object') {\n return;\n }\n const term = value as { termType?: string; value?: string };\n if (term.termType === 'NamedNode' && term.value && !identifierStrategy.supportsIdentifier({ path: term.value })) {\n throw new BadRequestHttpError(`GRAPH ${term.value} is outside the configured identifier space.`);\n }\n };\n const wrapDefaultGraph = (text: string): string => {\n const insert = /INSERT\\s+DATA\\s*{\\s*([^}]*)}/is;\n const del = /DELETE\\s+DATA\\s*{\\s*([^}]*)}/is;\n const rewrite = (regex: RegExp, label: string, input: string): string =>\n input.replace(regex, (_match, body) => `${label} { GRAPH <${graph.value}> { ${body} } }`);\n let out = text;\n if (insert.test(out)) {\n out = rewrite(insert, 'INSERT DATA', out);\n }\n if (del.test(out)) {\n out = rewrite(del, 'DELETE DATA', out);\n }\n return out;\n };\n\n const rewriteTriples = (triples?: any[], targetGraph = graph): any[] => {\n if (!triples) return [];\n return triples.map((triple: any): any => ({\n ...triple,\n graph: (!triple.graph || triple.graph.termType === 'DefaultGraph') ? targetGraph : triple.graph,\n }));\n };\n\n const rewritePattern = (pattern: any): any => {\n if (pattern.type === 'bgp') {\n return { ...pattern, triples: rewriteTriples(pattern.triples) };\n }\n if (pattern.type === 'graph') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'group') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'optional') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'union') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'minus') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n if (pattern.type === 'filter') {\n return pattern; // FILTER doesn't contain triples, pass through\n }\n if (pattern.type === 'bind') {\n return pattern; // BIND doesn't contain triples, pass through\n }\n if (pattern.type === 'values') {\n return pattern; // VALUES doesn't contain triples, pass through\n }\n if (pattern.type === 'service') {\n return { ...pattern, patterns: pattern.patterns?.map(rewritePattern) ?? [] };\n }\n return pattern;\n };\n\n const toGraphQuads = (items?: any[]): GraphQuads[] | undefined => {\n if (!items) return items;\n return items.map((item: any): GraphQuads => {\n if (item?.type === 'graph') {\n assertGraphAllowed(item.name);\n return {\n ...item,\n name: item.name ?? graph,\n triples: rewriteTriples(item.triples, item.name ?? graph),\n };\n }\n // Treat as plain quad\n return {\n type: 'graph',\n name: graph,\n triples: rewriteTriples([ item ], graph),\n };\n });\n };\n\n try {\n console.log(`[normalizeGraphs] Input SPARQL (first 500 chars): ${updateText.slice(0, 500)}`);\n const parsed = this.parser.parse(updateText) as unknown as SparqlUpdate;\n\n // Explicitly reject SPARQL Queries (SELECT, ASK, CONSTRUCT) in PATCH\n if ((parsed as any).type === 'query') {\n this.logger.warn(`Received SPARQL Query in PATCH request for ${identifier.path}. SPARQL PATCH only supports UPDATE operations.`);\n return undefined;\n }\n\n const collect = (ops: any[], key: 'delete' | 'insert'): any[] =>\n ops.flatMap((op): any[] => {\n const entries = op[key];\n if (!entries) return [];\n if (Array.isArray(entries)) {\n return entries.flatMap((entry: any): any[] =>\n entry.triples ? entry.triples : (entry.quads ?? []));\n }\n return [];\n });\n const deleteTriples = collect(parsed.updates as any[], 'delete');\n const insertTriples = collect(parsed.updates as any[], 'insert');\n const hasVariables = [...deleteTriples, ...insertTriples].some((t: any): boolean =>\n t.subject?.termType === 'Variable' || t.predicate?.termType === 'Variable' || t.object?.termType === 'Variable');\n\n const simpleOps = parsed.updates.every((op: any): boolean =>\n [ 'delete', 'insert', 'insertdelete', 'deleteinsert' ].includes(op.updateType) &&\n (!op.where || op.where.length === 0) &&\n !hasVariables);\n\n this.logger.debug(`[normalizeGraphs] simpleOps=${simpleOps}, hasVariables=${hasVariables}, deleteTriples=${deleteTriples.length}, insertTriples=${insertTriples.length}`);\n this.logger.debug(`[normalizeGraphs] updateTypes: ${parsed.updates.map((op: any) => op.updateType).join(', ')}`);\n\n if (simpleOps && deleteTriples.length + insertTriples.length > 0) {\n const termToString = (term: any): string => {\n if (term.termType === 'NamedNode') {\n return `<${term.value}>`;\n }\n if (term.termType === 'Literal') {\n // Escape special characters in literal values\n const hasQuotes = term.value.includes('\"');\n const hasNewlines = term.value.includes('\\n') || term.value.includes('\\r');\n\n let escaped: string;\n let useTripleQuotes = false;\n\n if (hasQuotes || hasNewlines) {\n // Use triple-quoted strings for values with quotes or newlines\n useTripleQuotes = true;\n escaped = term.value;\n // Escape triple-quote sequences\n escaped = escaped.replace(/\"\"\"/g, '\"\\\\\"\\\\\"\"');\n // Escape trailing quotes to avoid \"\"\"content\"\"\"\" sequences\n if (escaped.endsWith('\"')) {\n const match = escaped.match(/\"*$/);\n const trailingQuotes = match ? match[0].length : 0;\n if (trailingQuotes > 0) {\n escaped = escaped.slice(0, -trailingQuotes) + '\\\\\"'.repeat(trailingQuotes);\n }\n }\n } else {\n // Regular escaping for simple strings\n escaped = term.value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n }\n\n const quote = useTripleQuotes ? '\"\"\"' : '\"';\n\n // Handle language tags and datatypes\n if (term.language) {\n return `${quote}${escaped}${quote}@${term.language}`;\n }\n if (term.datatype && term.datatype.value !== 'http://www.w3.org/2001/XMLSchema#string') {\n return `${quote}${escaped}${quote}^^<${term.datatype.value}>`;\n }\n return `${quote}${escaped}${quote}`;\n }\n if (term.termType === 'BlankNode') {\n return `_:${term.value}`;\n }\n // Fallback for unknown term types\n return `<${term.value}>`;\n };\n const toTripleStr = (triples: any[]): string =>\n triples.map((t): string => `${termToString(t.subject)} ${termToString(t.predicate)} ${termToString(t.object)} .`).join(' ');\n let parts: string[] = [];\n if (deleteTriples.length > 0) {\n parts.push(`DELETE DATA { GRAPH <${graph.value}> { ${toTripleStr(deleteTriples)} } }`);\n }\n if (insertTriples.length > 0) {\n parts.push(`INSERT DATA { GRAPH <${graph.value}> { ${toTripleStr(insertTriples)} } }`);\n }\n const normalizedSimple = parts.join(';\\n');\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalizedSimple}`);\n return normalizedSimple;\n }\n\n parsed.updates = parsed.updates.map((op: any): UpdateOperation => {\n switch (op.updateType) {\n case 'deleteinsert':\n case 'insertdelete':\n return {\n ...op,\n delete: toGraphQuads(op.delete),\n insert: toGraphQuads(op.insert),\n where: op.where && op.where.length > 0 ? [ { type: 'graph', name: graph, patterns: op.where.map(rewritePattern) } ] : [],\n };\n case 'delete':\n case 'insert': {\n const deleteQuads = toGraphQuads(op.delete) ?? [];\n const insertQuads = toGraphQuads(op.insert) ?? [];\n return {\n updateType: 'insertdelete',\n delete: deleteQuads,\n insert: insertQuads,\n where: op.where && op.where.length > 0 ? [ { type: 'graph', name: graph, patterns: op.where.map(rewritePattern) } ] : [],\n };\n }\n default:\n return op;\n }\n });\n const normalized = this.generator.stringify(parsed);\n this.logger.verbose(`Normalized SPARQL UPDATE for ${identifier.path}: ${normalized}`);\n return normalized;\n } catch (error: unknown) {\n console.log(`[normalizeGraphs] Parse FAILED for ${identifier.path}: ${error}`);\n console.log(`[normalizeGraphs] Input was: ${updateText.slice(0, 300)}`);\n const fallbackResult = wrapDefaultGraph(updateText);\n console.log(`[normalizeGraphs] Fallback result: ${fallbackResult.slice(0, 300)}`);\n return fallbackResult;\n }\n }\n\n private isSparqlUpdatePatch(patch: Patch): patch is SparqlUpdatePatch {\n return typeof (patch as SparqlUpdatePatch).algebra === 'object';\n }\n\n private isSparqlCapable(accessor: unknown): accessor is {\n executeSparqlUpdate: (query: string, baseIri?: string) => Promise<void>;\n getMetadata: (identifier: ResourceIdentifier) => Promise<RepresentationMetadata>;\n } {\n return typeof accessor === 'object' &&\n accessor !== null &&\n typeof (accessor as { executeSparqlUpdate?: unknown }).executeSparqlUpdate === 'function' &&\n typeof (accessor as { getMetadata?: unknown }).getMetadata === 'function';\n }\n\n public override async setRepresentation(identifier: ResourceIdentifier, representation: Representation, conditions?: Conditions): Promise<ChangeMap> {\n return super.setRepresentation(identifier, representation, conditions);\n }\n}\n"]}
@@ -29,6 +29,18 @@
29
29
  {
30
30
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore_options_metadataStrategy",
31
31
  "range": "css:dist/http/auxiliary/AuxiliaryStrategy.jsonld#AuxiliaryStrategy"
32
+ },
33
+ {
34
+ "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore_options_localFirstRdfRepresentationResolver",
35
+ "range": {
36
+ "@type": "ParameterRangeUnion",
37
+ "parameterRangeElements": [
38
+ "undefineds:dist/solidfs/LocalFirstRdfRepresentationResolver.jsonld#LocalFirstRdfRepresentationResolverLike",
39
+ {
40
+ "@type": "ParameterRangeUndefined"
41
+ }
42
+ ]
43
+ }
32
44
  }
33
45
  ],
34
46
  "memberFields": [
@@ -40,6 +52,10 @@
40
52
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_parser",
41
53
  "memberFieldName": "parser"
42
54
  },
55
+ {
56
+ "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_localFirstRdfRepresentationResolver",
57
+ "memberFieldName": "localFirstRdfRepresentationResolver"
58
+ },
43
59
  {
44
60
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_logger",
45
61
  "memberFieldName": "logger",
@@ -51,6 +67,10 @@
51
67
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_constructor",
52
68
  "memberFieldName": "constructor"
53
69
  },
70
+ {
71
+ "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_getRepresentation",
72
+ "memberFieldName": "getRepresentation"
73
+ },
54
74
  {
55
75
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore__member_modifyResource",
56
76
  "memberFieldName": "modifyResource"
@@ -103,6 +123,12 @@
103
123
  "value": {
104
124
  "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore_options_metadataStrategy"
105
125
  }
126
+ },
127
+ {
128
+ "keyRaw": "localFirstRdfRepresentationResolver",
129
+ "value": {
130
+ "@id": "undefineds:dist/storage/SparqlUpdateResourceStore.jsonld#SparqlUpdateResourceStore_options_localFirstRdfRepresentationResolver"
131
+ }
106
132
  }
107
133
  ]
108
134
  }
@@ -1,10 +1,34 @@
1
- import type { Readable } from 'stream';
1
+ import { Readable } from 'stream';
2
+ import type { Quad } from '@rdfjs/types';
2
3
  import { RepresentationMetadata } from '@solid/community-server';
3
4
  import type { Representation, ResourceIdentifier, Guarded, DataAccessor } from '@solid/community-server';
5
+ import type { RdfSourceInput } from '../rdf/types';
6
+ export interface LocalRdfDocument {
7
+ data: Guarded<Readable>;
8
+ metadata: RepresentationMetadata;
9
+ }
10
+ export interface LocalRdfReadableAccessor {
11
+ getLocalRdfDocument(identifier: ResourceIdentifier): Promise<LocalRdfDocument>;
12
+ }
13
+ export interface LocalRdfIndexAccessor {
14
+ syncLocalRdfDocument(identifier: ResourceIdentifier, data?: Guarded<Readable>, contentType?: string, options?: LocalRdfSyncOptions): Promise<void>;
15
+ deleteLocalRdfIndex(identifier: ResourceIdentifier): Promise<void>;
16
+ }
17
+ export interface LocalRdfSyncOptions {
18
+ source?: string;
19
+ workspace?: string;
20
+ localPath?: string;
21
+ sourceVersion?: string;
22
+ }
23
+ export interface SourceScopedStructuredRdfAccessor {
24
+ writeRdfSourceDocument(identifier: ResourceIdentifier, quads: Quad[], metadata: RepresentationMetadata, source: RdfSourceInput): Promise<void>;
25
+ deleteRdfSourceDocument(identifier: ResourceIdentifier): Promise<void>;
26
+ }
4
27
  /**
5
28
  * MixDataAccessor - Routes data to appropriate storage based on content type
6
29
  *
7
30
  * - RDF data (internal/quads) -> structuredDataAccessor (Quadstore or QuintStore)
31
+ * - RDF file mirrors (.ttl/.jsonld) -> rdfFileDataAccessor (local FileSystem)
8
32
  * - Other data (binary, text, etc.) -> unstructuredDataAccessor (FileSystem, Minio, etc.)
9
33
  *
10
34
  * This uses composition instead of inheritance, allowing any DataAccessor
@@ -12,11 +36,13 @@ import type { Representation, ResourceIdentifier, Guarded, DataAccessor } from '
12
36
  */
13
37
  export declare class MixDataAccessor implements DataAccessor {
14
38
  protected readonly logger: import("global-logger-factory").Logger<unknown>;
39
+ private readonly rdfSparqlAdapter;
15
40
  private readonly structuredDataAccessor;
16
41
  private readonly unstructuredDataAccessor;
42
+ private readonly rdfFileDataAccessor;
17
43
  private readonly presignedRedirectEnabled;
18
44
  private readonly mirrorContainersToUnstructured;
19
- constructor(structuredDataAccessor: DataAccessor, unstructuredDataAccessor: DataAccessor, presignedRedirectEnabled?: boolean, mirrorContainersToUnstructured?: boolean);
45
+ constructor(structuredDataAccessor: DataAccessor, unstructuredDataAccessor: DataAccessor, presignedRedirectEnabled?: boolean, mirrorContainersToUnstructured?: boolean, rdfFileDataAccessor?: DataAccessor);
20
46
  /**
21
47
  * This accessor supports all types of data.
22
48
  */
@@ -26,6 +52,14 @@ export declare class MixDataAccessor implements DataAccessor {
26
52
  */
27
53
  private isUnstructured;
28
54
  getData(identifier: ResourceIdentifier): Promise<Guarded<Readable>>;
55
+ /**
56
+ * Read the local RDF file mirror used by SolidFS/local-first HTTP reads.
57
+ *
58
+ * `getData()` intentionally keeps returning the structured quad stream for
59
+ * CSS internals. This method is the explicit file-content path for callers
60
+ * that need a real Turtle/JSON-LD byte stream.
61
+ */
62
+ getLocalRdfDocument(identifier: ResourceIdentifier): Promise<LocalRdfDocument>;
29
63
  getMetadata(identifier: ResourceIdentifier): Promise<RepresentationMetadata>;
30
64
  getChildren(identifier: ResourceIdentifier): AsyncIterableIterator<RepresentationMetadata>;
31
65
  writeContainer(identifier: ResourceIdentifier, metadata: RepresentationMetadata): Promise<void>;
@@ -33,14 +67,61 @@ export declare class MixDataAccessor implements DataAccessor {
33
67
  writeMetadata(identifier: ResourceIdentifier, metadata: RepresentationMetadata): Promise<void>;
34
68
  deleteResource(identifier: ResourceIdentifier): Promise<void>;
35
69
  /**
36
- * Execute SPARQL UPDATE on structured data accessor.
37
- * Delegates to the underlying structuredDataAccessor if it supports SPARQL.
70
+ * Execute SPARQL UPDATE.
71
+ *
72
+ * Supported embedded deltas patch the local RDF authority file first and then
73
+ * rebuild the structured RDF index. Unsupported shapes keep using the
74
+ * compatibility accessor until the embedded engine covers them.
38
75
  */
39
76
  executeSparqlUpdate(query: string, baseIri?: string): Promise<void>;
77
+ private executeLocalRdfSparqlUpdate;
78
+ private applyLocalRdfDelta;
79
+ private assertLocalRdfDeltaTargetsGraph;
80
+ private queryLocalUpdateBindings;
81
+ private queryGraphTerms;
82
+ private readLocalRdfTextOrEmpty;
83
+ private writeLocalRdfAuthority;
84
+ private toDefaultGraphQuad;
85
+ private toGraphQuad;
86
+ private quadKey;
87
+ /**
88
+ * Rebuild the structured RDF index from an already-written local RDF file.
89
+ *
90
+ * SolidFS uses this after tools edit `.ttl`/`.jsonld` files directly. The
91
+ * local file remains the content authority; the structured accessor is only
92
+ * refreshed as query/index state.
93
+ */
94
+ syncLocalRdfDocument(identifier: ResourceIdentifier, data?: Guarded<Readable>, contentType?: string, options?: LocalRdfSyncOptions): Promise<void>;
95
+ deleteLocalRdfIndex(identifier: ResourceIdentifier): Promise<void>;
96
+ private writeRdfDocument;
97
+ private writeStructuredRdfIndex;
98
+ private refreshLocalRdfMirror;
99
+ private getLocalRdfMetadata;
100
+ private getExistingLocalRdfMetadata;
101
+ private createLocalRdfMetadata;
102
+ private localRdfContentType;
103
+ private sourceScopedStructuredAccessor;
104
+ private rdfSourceInput;
105
+ private relativePathFromWorkspace;
106
+ private isByLineRdfIdentifier;
107
+ private isRdfDocumentIdentifier;
108
+ private isLocalMirroredRdf;
109
+ private serializeQuadsForLocalFile;
110
+ private serializeNQuads;
111
+ private parseLocalRdf;
112
+ private readStreamText;
40
113
  /**
41
114
  * Write unstructured document: store data in unstructured accessor,
42
115
  * then save metadata in structured accessor.
43
116
  */
44
117
  private writeUnstructuredDocument;
118
+ private deleteUnstructuredResourceIfPresent;
119
+ private deleteRdfFileResourceIfPresent;
120
+ private ensureUnstructuredParentContainers;
121
+ private ensureRdfFileParentContainers;
122
+ private ensureParentContainers;
123
+ private writeContainerIfMissing;
124
+ private sameIdentifier;
125
+ private parentContainer;
45
126
  private invalidateMetadataCache;
46
127
  }