@matdata/yasgui 5.10.0 → 5.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +6 -2
  2. package/build/ts/src/PersistentConfig.d.ts +10 -0
  3. package/build/ts/src/PersistentConfig.js +40 -0
  4. package/build/ts/src/PersistentConfig.js.map +1 -1
  5. package/build/ts/src/Tab.d.ts +17 -0
  6. package/build/ts/src/Tab.js +372 -15
  7. package/build/ts/src/Tab.js.map +1 -1
  8. package/build/ts/src/TabContextMenu.d.ts +1 -0
  9. package/build/ts/src/TabContextMenu.js +17 -0
  10. package/build/ts/src/TabContextMenu.js.map +1 -1
  11. package/build/ts/src/TabElements.d.ts +3 -0
  12. package/build/ts/src/TabElements.js +97 -28
  13. package/build/ts/src/TabElements.js.map +1 -1
  14. package/build/ts/src/TabSettingsModal.d.ts +2 -0
  15. package/build/ts/src/TabSettingsModal.js +44 -19
  16. package/build/ts/src/TabSettingsModal.js.map +1 -1
  17. package/build/ts/src/index.d.ts +3 -0
  18. package/build/ts/src/index.js +4 -0
  19. package/build/ts/src/index.js.map +1 -1
  20. package/build/ts/src/queryManagement/QueryBrowser.d.ts +64 -0
  21. package/build/ts/src/queryManagement/QueryBrowser.js +914 -0
  22. package/build/ts/src/queryManagement/QueryBrowser.js.map +1 -0
  23. package/build/ts/src/queryManagement/SaveManagedQueryModal.d.ts +55 -0
  24. package/build/ts/src/queryManagement/SaveManagedQueryModal.js +451 -0
  25. package/build/ts/src/queryManagement/SaveManagedQueryModal.js.map +1 -0
  26. package/build/ts/src/queryManagement/WorkspaceSettingsForm.d.ts +16 -0
  27. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js +452 -0
  28. package/build/ts/src/queryManagement/WorkspaceSettingsForm.js.map +1 -0
  29. package/build/ts/src/queryManagement/backends/BaseGitProviderClient.d.ts +19 -0
  30. package/build/ts/src/queryManagement/backends/BaseGitProviderClient.js +77 -0
  31. package/build/ts/src/queryManagement/backends/BaseGitProviderClient.js.map +1 -0
  32. package/build/ts/src/queryManagement/backends/BitbucketProviderClient.d.ts +16 -0
  33. package/build/ts/src/queryManagement/backends/BitbucketProviderClient.js +269 -0
  34. package/build/ts/src/queryManagement/backends/BitbucketProviderClient.js.map +1 -0
  35. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.d.ts +26 -0
  36. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js +93 -0
  37. package/build/ts/src/queryManagement/backends/GitWorkspaceBackend.js.map +1 -0
  38. package/build/ts/src/queryManagement/backends/GiteaProviderClient.d.ts +14 -0
  39. package/build/ts/src/queryManagement/backends/GiteaProviderClient.js +244 -0
  40. package/build/ts/src/queryManagement/backends/GiteaProviderClient.js.map +1 -0
  41. package/build/ts/src/queryManagement/backends/GithubProviderClient.d.ts +14 -0
  42. package/build/ts/src/queryManagement/backends/GithubProviderClient.js +252 -0
  43. package/build/ts/src/queryManagement/backends/GithubProviderClient.js.map +1 -0
  44. package/build/ts/src/queryManagement/backends/GitlabProviderClient.d.ts +16 -0
  45. package/build/ts/src/queryManagement/backends/GitlabProviderClient.js +246 -0
  46. package/build/ts/src/queryManagement/backends/GitlabProviderClient.js.map +1 -0
  47. package/build/ts/src/queryManagement/backends/InMemoryWorkspaceBackend.d.ts +21 -0
  48. package/build/ts/src/queryManagement/backends/InMemoryWorkspaceBackend.js +175 -0
  49. package/build/ts/src/queryManagement/backends/InMemoryWorkspaceBackend.js.map +1 -0
  50. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.d.ts +28 -0
  51. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js +687 -0
  52. package/build/ts/src/queryManagement/backends/SparqlWorkspaceBackend.js.map +1 -0
  53. package/build/ts/src/queryManagement/backends/WorkspaceBackend.d.ts +15 -0
  54. package/build/ts/src/queryManagement/backends/WorkspaceBackend.js +2 -0
  55. package/build/ts/src/queryManagement/backends/WorkspaceBackend.js.map +1 -0
  56. package/build/ts/src/queryManagement/backends/errors.d.ts +7 -0
  57. package/build/ts/src/queryManagement/backends/errors.js +18 -0
  58. package/build/ts/src/queryManagement/backends/errors.js.map +1 -0
  59. package/build/ts/src/queryManagement/backends/getWorkspaceBackend.d.ts +8 -0
  60. package/build/ts/src/queryManagement/backends/getWorkspaceBackend.js +114 -0
  61. package/build/ts/src/queryManagement/backends/getWorkspaceBackend.js.map +1 -0
  62. package/build/ts/src/queryManagement/backends/gitRemote.d.ts +5 -0
  63. package/build/ts/src/queryManagement/backends/gitRemote.js +40 -0
  64. package/build/ts/src/queryManagement/backends/gitRemote.js.map +1 -0
  65. package/build/ts/src/queryManagement/browserFilter.d.ts +2 -0
  66. package/build/ts/src/queryManagement/browserFilter.js +7 -0
  67. package/build/ts/src/queryManagement/browserFilter.js.map +1 -0
  68. package/build/ts/src/queryManagement/index.d.ts +13 -0
  69. package/build/ts/src/queryManagement/index.js +14 -0
  70. package/build/ts/src/queryManagement/index.js.map +1 -0
  71. package/build/ts/src/queryManagement/normalizeQueryFilename.d.ts +1 -0
  72. package/build/ts/src/queryManagement/normalizeQueryFilename.js +10 -0
  73. package/build/ts/src/queryManagement/normalizeQueryFilename.js.map +1 -0
  74. package/build/ts/src/queryManagement/openManagedQuery.d.ts +15 -0
  75. package/build/ts/src/queryManagement/openManagedQuery.js +27 -0
  76. package/build/ts/src/queryManagement/openManagedQuery.js.map +1 -0
  77. package/build/ts/src/queryManagement/saveManagedQuery.d.ts +20 -0
  78. package/build/ts/src/queryManagement/saveManagedQuery.js +109 -0
  79. package/build/ts/src/queryManagement/saveManagedQuery.js.map +1 -0
  80. package/build/ts/src/queryManagement/textHash.d.ts +2 -0
  81. package/build/ts/src/queryManagement/textHash.js +13 -0
  82. package/build/ts/src/queryManagement/textHash.js.map +1 -0
  83. package/build/ts/src/queryManagement/types.d.ts +76 -0
  84. package/build/ts/src/queryManagement/types.js +2 -0
  85. package/build/ts/src/queryManagement/types.js.map +1 -0
  86. package/build/ts/src/queryManagement/validateWorkspaceConfig.d.ts +6 -0
  87. package/build/ts/src/queryManagement/validateWorkspaceConfig.js +33 -0
  88. package/build/ts/src/queryManagement/validateWorkspaceConfig.js.map +1 -0
  89. package/build/ts/src/version.d.ts +1 -1
  90. package/build/ts/src/version.js +1 -1
  91. package/build/yasgui.min.css +10 -1
  92. package/build/yasgui.min.css.map +3 -3
  93. package/build/yasgui.min.js +398 -172
  94. package/build/yasgui.min.js.map +4 -4
  95. package/package.json +1 -1
  96. package/src/PersistentConfig.ts +61 -0
  97. package/src/Tab.ts +431 -20
  98. package/src/TabContextMenu.ts +10 -0
  99. package/src/TabElements.scss +46 -7
  100. package/src/TabElements.ts +95 -27
  101. package/src/TabSettingsModal.scss +102 -5
  102. package/src/TabSettingsModal.ts +48 -25
  103. package/src/endpointSelect.scss +2 -3
  104. package/src/index.scss +4 -0
  105. package/src/index.ts +7 -0
  106. package/src/queryManagement/QueryBrowser.scss +418 -0
  107. package/src/queryManagement/QueryBrowser.ts +1079 -0
  108. package/src/queryManagement/SaveManagedQueryModal.scss +245 -0
  109. package/src/queryManagement/SaveManagedQueryModal.ts +554 -0
  110. package/src/queryManagement/WorkspaceSettingsForm.ts +546 -0
  111. package/src/queryManagement/backends/BaseGitProviderClient.ts +124 -0
  112. package/src/queryManagement/backends/BitbucketProviderClient.ts +403 -0
  113. package/src/queryManagement/backends/GitWorkspaceBackend.ts +96 -0
  114. package/src/queryManagement/backends/GiteaProviderClient.ts +316 -0
  115. package/src/queryManagement/backends/GithubProviderClient.ts +319 -0
  116. package/src/queryManagement/backends/GitlabProviderClient.ts +327 -0
  117. package/src/queryManagement/backends/InMemoryWorkspaceBackend.ts +175 -0
  118. package/src/queryManagement/backends/SparqlWorkspaceBackend.ts +729 -0
  119. package/src/queryManagement/backends/WorkspaceBackend.ts +41 -0
  120. package/src/queryManagement/backends/errors.ts +28 -0
  121. package/src/queryManagement/backends/getWorkspaceBackend.ts +132 -0
  122. package/src/queryManagement/backends/gitRemote.ts +54 -0
  123. package/src/queryManagement/browserFilter.ts +8 -0
  124. package/src/queryManagement/index.ts +15 -0
  125. package/src/queryManagement/normalizeQueryFilename.ts +8 -0
  126. package/src/queryManagement/openManagedQuery.ts +31 -0
  127. package/src/queryManagement/saveManagedQuery.ts +135 -0
  128. package/src/queryManagement/textHash.ts +15 -0
  129. package/src/queryManagement/types.ts +85 -0
  130. package/src/queryManagement/validateWorkspaceConfig.ts +40 -0
  131. package/src/tab.scss +4 -14
  132. package/src/themes.scss +14 -23
  133. package/src/version.ts +1 -1
@@ -0,0 +1,687 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { normalizeQueryText } from "../textHash";
11
+ import { WorkspaceBackendError } from "./errors";
12
+ function stripTrailingSlash(value) {
13
+ return value.replace(/\/+$/, "");
14
+ }
15
+ function splitPath(path) {
16
+ return path.split("/").filter(Boolean);
17
+ }
18
+ function nowIso() {
19
+ return new Date().toISOString();
20
+ }
21
+ function sparqlStringLiteral(value) {
22
+ const escaped = value
23
+ .replace(/\\/g, "\\\\")
24
+ .replace(/\r/g, "\\r")
25
+ .replace(/\n/g, "\\n")
26
+ .replace(/\t/g, "\\t")
27
+ .replace(/\"/g, '\\"');
28
+ return `"${escaped}"`;
29
+ }
30
+ function iri(iriValue) {
31
+ const trimmed = iriValue.trim();
32
+ if (!trimmed)
33
+ throw new Error("IRI is required");
34
+ return `<${trimmed.replace(/>/g, "%3E")}>`;
35
+ }
36
+ function uuidV4() {
37
+ const cryptoObj = globalThis.crypto;
38
+ if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.randomUUID)
39
+ return cryptoObj.randomUUID();
40
+ const rnds = new Uint8Array(16);
41
+ if (cryptoObj === null || cryptoObj === void 0 ? void 0 : cryptoObj.getRandomValues) {
42
+ cryptoObj.getRandomValues(rnds);
43
+ }
44
+ else {
45
+ for (let i = 0; i < rnds.length; i++)
46
+ rnds[i] = Math.floor(Math.random() * 256);
47
+ }
48
+ rnds[6] = (rnds[6] & 0x0f) | 0x40;
49
+ rnds[8] = (rnds[8] & 0x3f) | 0x80;
50
+ const hex = Array.from(rnds, (b) => b.toString(16).padStart(2, "0")).join("");
51
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
52
+ }
53
+ function mintManagedQueryVersionIri(workspaceIri) {
54
+ return `${workspaceIri.trim()}_mq_v_${uuidV4()}`;
55
+ }
56
+ function isIriLike(value) {
57
+ return /^[a-z][a-z0-9+.-]*:/i.test(value.trim());
58
+ }
59
+ function mintFolderIri(workspaceIri, folderPath) {
60
+ const base = stripTrailingSlash(workspaceIri);
61
+ return `${base}/folder/${encodeURIComponent(folderPath)}`;
62
+ }
63
+ function tryParseFolderPathFromFolderIri(workspaceIri, folderIri) {
64
+ const base = stripTrailingSlash(workspaceIri);
65
+ const prefix = `${base}/folder/`;
66
+ if (!folderIri.startsWith(prefix))
67
+ return undefined;
68
+ const encoded = folderIri.slice(prefix.length);
69
+ try {
70
+ return decodeURIComponent(encoded);
71
+ }
72
+ catch (_a) {
73
+ return undefined;
74
+ }
75
+ }
76
+ function mapHttpError(status, message) {
77
+ if (status === 401)
78
+ return new WorkspaceBackendError("AUTH_FAILED", message || "Authentication failed");
79
+ if (status === 403)
80
+ return new WorkspaceBackendError("FORBIDDEN", message || "Forbidden");
81
+ if (status === 404)
82
+ return new WorkspaceBackendError("NOT_FOUND", message || "Not found");
83
+ if (status === 409)
84
+ return new WorkspaceBackendError("CONFLICT", message || "Conflict");
85
+ if (status === 429)
86
+ return new WorkspaceBackendError("RATE_LIMITED", message || "Rate limited");
87
+ if (status >= 500)
88
+ return new WorkspaceBackendError("NETWORK_ERROR", message || "Server error");
89
+ return new WorkspaceBackendError("UNKNOWN", message || `HTTP ${status}`);
90
+ }
91
+ export default class SparqlWorkspaceBackend {
92
+ constructor(config, options) {
93
+ this.config = config;
94
+ this.options = options;
95
+ this.type = "sparql";
96
+ }
97
+ resolveAuthHeaders() {
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ var _a, _b, _c;
100
+ try {
101
+ const dynamic = yield ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.getAuthHeaders) === null || _b === void 0 ? void 0 : _b.call(_a));
102
+ if (dynamic)
103
+ return dynamic;
104
+ }
105
+ catch (e) {
106
+ console.error("Failed to resolve SPARQL auth headers", e);
107
+ }
108
+ return ((_c = this.options) === null || _c === void 0 ? void 0 : _c.authHeaders) || {};
109
+ });
110
+ }
111
+ sparqlQuery(query) {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ const body = new URLSearchParams();
114
+ body.set("query", query);
115
+ if (this.config.defaultGraph)
116
+ body.set("default-graph-uri", this.config.defaultGraph);
117
+ const authHeaders = yield this.resolveAuthHeaders();
118
+ let res;
119
+ try {
120
+ res = yield fetch(this.config.endpoint, {
121
+ method: "POST",
122
+ headers: Object.assign({ Accept: "application/sparql-results+json", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" }, authHeaders),
123
+ body: body.toString(),
124
+ });
125
+ }
126
+ catch (e) {
127
+ throw new WorkspaceBackendError("NETWORK_ERROR", e instanceof Error ? e.message : String(e));
128
+ }
129
+ if (!res.ok) {
130
+ const text = yield res.text().catch(() => "");
131
+ throw mapHttpError(res.status, text || `SPARQL endpoint responded with ${res.status}`);
132
+ }
133
+ try {
134
+ return (yield res.json());
135
+ }
136
+ catch (e) {
137
+ throw new WorkspaceBackendError("UNKNOWN", e instanceof Error ? e.message : "Invalid SPARQL JSON response");
138
+ }
139
+ });
140
+ }
141
+ sparqlUpdate(update) {
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ const body = new URLSearchParams();
144
+ body.set("update", update);
145
+ if (this.config.defaultGraph)
146
+ body.set("default-graph-uri", this.config.defaultGraph);
147
+ const authHeaders = yield this.resolveAuthHeaders();
148
+ let res;
149
+ try {
150
+ res = yield fetch(this.config.endpoint, {
151
+ method: "POST",
152
+ headers: Object.assign({ Accept: "application/sparql-results+json, */*", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" }, authHeaders),
153
+ body: body.toString(),
154
+ });
155
+ }
156
+ catch (e) {
157
+ throw new WorkspaceBackendError("NETWORK_ERROR", e instanceof Error ? e.message : String(e));
158
+ }
159
+ if (!res.ok) {
160
+ const text = yield res.text().catch(() => "");
161
+ throw mapHttpError(res.status, text || `SPARQL endpoint responded with ${res.status}`);
162
+ }
163
+ });
164
+ }
165
+ getBindings(results) {
166
+ var _a;
167
+ return ((_a = results === null || results === void 0 ? void 0 : results.results) === null || _a === void 0 ? void 0 : _a.bindings) || [];
168
+ }
169
+ folderIriFromId(folderId) {
170
+ if (!folderId)
171
+ return this.config.workspaceIri;
172
+ return mintFolderIri(this.config.workspaceIri, folderId);
173
+ }
174
+ resolveManagedQueryIri(queryIdOrIri) {
175
+ const trimmed = queryIdOrIri.trim();
176
+ if (!trimmed)
177
+ throw new WorkspaceBackendError("UNKNOWN", "Query ID is required");
178
+ if (isIriLike(trimmed))
179
+ return trimmed;
180
+ throw new WorkspaceBackendError("UNKNOWN", "SPARQL managed query IDs must be IRIs");
181
+ }
182
+ validateAccess() {
183
+ return __awaiter(this, void 0, void 0, function* () {
184
+ yield this.sparqlQuery(`SELECT (1 AS ?ok) WHERE {} LIMIT 1`);
185
+ });
186
+ }
187
+ listFolder(folderId) {
188
+ return __awaiter(this, void 0, void 0, function* () {
189
+ var _a, _b, _c, _d, _e;
190
+ const workspaceIri = this.config.workspaceIri;
191
+ const containerIri = this.folderIriFromId(folderId);
192
+ const folderFilter = folderId ? `?folder skos:broader ${iri(containerIri)} .` : `FILTER(!BOUND(?parent))`;
193
+ const foldersQuery = `
194
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
195
+ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
196
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
197
+
198
+ SELECT ?folder ?label ?parent WHERE {
199
+ ?folder a yasgui:WorkspaceFolder ;
200
+ skos:inScheme ${iri(workspaceIri)} ;
201
+ rdfs:label ?label .
202
+ OPTIONAL { ?folder skos:broader ?parent }
203
+ ${folderFilter}
204
+ }
205
+ ORDER BY LCASE(STR(?label))`;
206
+ const queriesQuery = `
207
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
208
+ PREFIX dcterms: <http://purl.org/dc/terms/>
209
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
210
+
211
+ SELECT ?mq ?label WHERE {
212
+ ?mq a yasgui:ManagedQuery ;
213
+ rdfs:label ?label ;
214
+ dcterms:isPartOf ${iri(containerIri)} .
215
+ }
216
+ ORDER BY LCASE(STR(?label))`;
217
+ const [foldersRes, queriesRes] = yield Promise.all([
218
+ this.sparqlQuery(foldersQuery),
219
+ this.sparqlQuery(queriesQuery),
220
+ ]);
221
+ const folders = [];
222
+ for (const row of this.getBindings(foldersRes)) {
223
+ const folder = (_a = row.folder) === null || _a === void 0 ? void 0 : _a.value;
224
+ const label = (_b = row.label) === null || _b === void 0 ? void 0 : _b.value;
225
+ if (!folder || !label)
226
+ continue;
227
+ const folderPath = tryParseFolderPathFromFolderIri(workspaceIri, folder) || label;
228
+ const parentIri = (_c = row.parent) === null || _c === void 0 ? void 0 : _c.value;
229
+ const parentPath = parentIri ? tryParseFolderPathFromFolderIri(workspaceIri, parentIri) : undefined;
230
+ folders.push({
231
+ kind: "folder",
232
+ id: folderPath,
233
+ label,
234
+ parentId: parentPath,
235
+ });
236
+ }
237
+ const queries = [];
238
+ for (const row of this.getBindings(queriesRes)) {
239
+ const mqIri = (_d = row.mq) === null || _d === void 0 ? void 0 : _d.value;
240
+ const label = (_e = row.label) === null || _e === void 0 ? void 0 : _e.value;
241
+ if (!mqIri || !label)
242
+ continue;
243
+ queries.push({
244
+ kind: "query",
245
+ id: mqIri,
246
+ label,
247
+ parentId: folderId || undefined,
248
+ });
249
+ }
250
+ const out = [...folders, ...queries];
251
+ out.sort((a, b) => a.label.localeCompare(b.label));
252
+ return out;
253
+ });
254
+ }
255
+ searchByName(query) {
256
+ return __awaiter(this, void 0, void 0, function* () {
257
+ var _a, _b, _c;
258
+ const q = query.trim();
259
+ if (!q)
260
+ return [];
261
+ const workspaceIri = this.config.workspaceIri;
262
+ const queryText = `
263
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
264
+ PREFIX dcterms: <http://purl.org/dc/terms/>
265
+ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
266
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
267
+
268
+ SELECT ?mq ?label ?container WHERE {
269
+ ?mq a yasgui:ManagedQuery ;
270
+ rdfs:label ?label ;
271
+ dcterms:isPartOf ?container .
272
+
273
+ {
274
+ FILTER(?container = ${iri(workspaceIri)})
275
+ } UNION {
276
+ ?container a yasgui:WorkspaceFolder ; skos:inScheme ${iri(workspaceIri)} .
277
+ }
278
+
279
+ FILTER(CONTAINS(LCASE(STR(?label)), LCASE(${sparqlStringLiteral(q)})))
280
+ }
281
+ ORDER BY LCASE(STR(?label))`;
282
+ const res = yield this.sparqlQuery(queryText);
283
+ const hits = [];
284
+ for (const row of this.getBindings(res)) {
285
+ const mqIri = (_a = row.mq) === null || _a === void 0 ? void 0 : _a.value;
286
+ const label = (_b = row.label) === null || _b === void 0 ? void 0 : _b.value;
287
+ const container = (_c = row.container) === null || _c === void 0 ? void 0 : _c.value;
288
+ if (!mqIri || !label || !container)
289
+ continue;
290
+ const parentId = container === workspaceIri ? undefined : tryParseFolderPathFromFolderIri(workspaceIri, container) || undefined;
291
+ hits.push({ kind: "query", id: mqIri, label, parentId });
292
+ }
293
+ hits.sort((a, b) => a.label.localeCompare(b.label));
294
+ return hits;
295
+ });
296
+ }
297
+ readQuery(queryId) {
298
+ return __awaiter(this, void 0, void 0, function* () {
299
+ var _a, _b, _c, _d;
300
+ const mqIri = this.resolveManagedQueryIri(queryId);
301
+ const query = `
302
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
303
+ PREFIX dcterms: <http://purl.org/dc/terms/>
304
+ PREFIX prov: <http://www.w3.org/ns/prov#>
305
+ PREFIX spin: <http://spinrdf.org/spin#>
306
+ PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>
307
+
308
+ SELECT ?version ?created ?text ?endpoint ?description WHERE {
309
+ ?version a yasgui:ManagedQueryVersion ;
310
+ dcterms:isVersionOf ${iri(mqIri)} ;
311
+ dcterms:created ?created ;
312
+ spin:text ?text .
313
+
314
+ OPTIONAL { ?version dcterms:description ?description }
315
+
316
+ OPTIONAL {
317
+ ?version prov:used ?svc .
318
+ ?svc a sd:Service ;
319
+ sd:endpoint ?endpoint .
320
+ }
321
+
322
+ }
323
+ ORDER BY DESC(?created)
324
+ LIMIT 1`;
325
+ const res = yield this.sparqlQuery(query);
326
+ const row = this.getBindings(res)[0];
327
+ if (!row)
328
+ throw new WorkspaceBackendError("NOT_FOUND", "Query not found");
329
+ const text = (_a = row.text) === null || _a === void 0 ? void 0 : _a.value;
330
+ const version = (_b = row.version) === null || _b === void 0 ? void 0 : _b.value;
331
+ const endpoint = (_c = row.endpoint) === null || _c === void 0 ? void 0 : _c.value;
332
+ const description = (_d = row.description) === null || _d === void 0 ? void 0 : _d.value;
333
+ if (!text || !version)
334
+ throw new WorkspaceBackendError("NOT_FOUND", "Query not found");
335
+ return {
336
+ queryText: text,
337
+ versionTag: version,
338
+ associatedEndpoint: endpoint,
339
+ description,
340
+ };
341
+ });
342
+ }
343
+ renameQuery(queryId, newLabel) {
344
+ return __awaiter(this, void 0, void 0, function* () {
345
+ var _a;
346
+ const label = newLabel.trim();
347
+ if (!label)
348
+ throw new WorkspaceBackendError("UNKNOWN", "New name is required");
349
+ const mqIriValue = this.resolveManagedQueryIri(queryId);
350
+ const containerIriValue = yield (() => __awaiter(this, void 0, void 0, function* () {
351
+ var _a;
352
+ const q = `
353
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
354
+ PREFIX dcterms: <http://purl.org/dc/terms/>
355
+
356
+ SELECT ?container WHERE {
357
+ ${iri(mqIriValue)} a yasgui:ManagedQuery ;
358
+ dcterms:isPartOf ?container .
359
+ }
360
+ LIMIT 1`;
361
+ const res = yield this.sparqlQuery(q);
362
+ const row = this.getBindings(res)[0];
363
+ const container = (_a = row === null || row === void 0 ? void 0 : row.container) === null || _a === void 0 ? void 0 : _a.value;
364
+ if (!container)
365
+ throw new WorkspaceBackendError("NOT_FOUND", "Query not found");
366
+ return container;
367
+ }))();
368
+ {
369
+ const dupCheck = `
370
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
371
+ PREFIX dcterms: <http://purl.org/dc/terms/>
372
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
373
+
374
+ SELECT ?mq WHERE {
375
+ ?mq a yasgui:ManagedQuery ;
376
+ dcterms:isPartOf ${iri(containerIriValue)} ;
377
+ rdfs:label ?lbl .
378
+ FILTER(LCASE(STR(?lbl)) = LCASE(${sparqlStringLiteral(label)}))
379
+ FILTER(?mq != ${iri(mqIriValue)})
380
+ }
381
+ LIMIT 1`;
382
+ const res = yield this.sparqlQuery(dupCheck);
383
+ const row = this.getBindings(res)[0];
384
+ if ((_a = row === null || row === void 0 ? void 0 : row.mq) === null || _a === void 0 ? void 0 : _a.value) {
385
+ throw new WorkspaceBackendError("CONFLICT", `A query named '${label}' already exists in this folder. Please choose a different name.`);
386
+ }
387
+ }
388
+ const mqIri = mqIriValue;
389
+ const update = `
390
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
391
+
392
+ DELETE { ${iri(mqIri)} rdfs:label ?oldLabel . }
393
+ INSERT { ${iri(mqIri)} rdfs:label ${sparqlStringLiteral(label)} . }
394
+ WHERE { OPTIONAL { ${iri(mqIri)} rdfs:label ?oldLabel . } }
395
+ `;
396
+ yield this.sparqlUpdate(update);
397
+ });
398
+ }
399
+ deleteQuery(queryId) {
400
+ return __awaiter(this, void 0, void 0, function* () {
401
+ const mqIri = this.resolveManagedQueryIri(queryId);
402
+ const update = `
403
+ PREFIX dcterms: <http://purl.org/dc/terms/>
404
+
405
+ DELETE {
406
+ ${iri(mqIri)} ?p ?o .
407
+ ?s ?pp ${iri(mqIri)} .
408
+ ?v ?vp ?vo .
409
+ ?sv ?svP ?v .
410
+ }
411
+ WHERE {
412
+ OPTIONAL { ${iri(mqIri)} ?p ?o . }
413
+ OPTIONAL { ?s ?pp ${iri(mqIri)} . }
414
+ OPTIONAL {
415
+ ?v dcterms:isVersionOf ${iri(mqIri)} .
416
+ OPTIONAL { ?v ?vp ?vo . }
417
+ OPTIONAL { ?sv ?svP ?v . }
418
+ }
419
+ }
420
+ `;
421
+ yield this.sparqlUpdate(update);
422
+ });
423
+ }
424
+ renameFolder(folderId, newLabel) {
425
+ return __awaiter(this, void 0, void 0, function* () {
426
+ const label = newLabel.trim();
427
+ if (!label)
428
+ throw new WorkspaceBackendError("UNKNOWN", "New name is required");
429
+ const folderIriValue = mintFolderIri(this.config.workspaceIri, folderId);
430
+ const update = `
431
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
432
+
433
+ DELETE { ${iri(folderIriValue)} rdfs:label ?oldLabel . }
434
+ INSERT { ${iri(folderIriValue)} rdfs:label ${sparqlStringLiteral(label)} . }
435
+ WHERE { OPTIONAL { ${iri(folderIriValue)} rdfs:label ?oldLabel . } }
436
+ `;
437
+ yield this.sparqlUpdate(update);
438
+ });
439
+ }
440
+ deleteFolder(folderId) {
441
+ return __awaiter(this, void 0, void 0, function* () {
442
+ const workspaceIri = this.config.workspaceIri;
443
+ const rootFolderIri = mintFolderIri(workspaceIri, folderId);
444
+ const update = `
445
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
446
+ PREFIX dcterms: <http://purl.org/dc/terms/>
447
+ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
448
+
449
+ DELETE {
450
+ ?folder ?fp ?fo .
451
+ ?sf ?sfp ?folder .
452
+
453
+ ?mq ?mp ?mo .
454
+ ?sm ?smp ?mq .
455
+
456
+ ?v ?vp ?vo .
457
+ ?sv ?svP ?v .
458
+ }
459
+ WHERE {
460
+ {
461
+ SELECT DISTINCT ?folder WHERE {
462
+ ?folder a yasgui:WorkspaceFolder ;
463
+ skos:inScheme ${iri(workspaceIri)} .
464
+ ?folder (skos:broader)* ${iri(rootFolderIri)} .
465
+ }
466
+ }
467
+
468
+ OPTIONAL { ?folder ?fp ?fo . }
469
+ OPTIONAL { ?sf ?sfp ?folder . }
470
+
471
+ OPTIONAL {
472
+ ?mq a yasgui:ManagedQuery ;
473
+ dcterms:isPartOf ?folder .
474
+ OPTIONAL { ?mq ?mp ?mo . }
475
+ OPTIONAL { ?sm ?smp ?mq . }
476
+
477
+ OPTIONAL {
478
+ ?v dcterms:isVersionOf ?mq .
479
+ OPTIONAL { ?v ?vp ?vo . }
480
+ OPTIONAL { ?sv ?svP ?v . }
481
+ }
482
+ }
483
+ }
484
+ `;
485
+ yield this.sparqlUpdate(update);
486
+ });
487
+ }
488
+ writeQuery(queryId, queryText, options) {
489
+ return __awaiter(this, void 0, void 0, function* () {
490
+ var _a, _b, _c, _d, _e;
491
+ const workspaceIri = this.config.workspaceIri;
492
+ const mqIriValue = this.resolveManagedQueryIri(queryId);
493
+ let folderPath = ((options === null || options === void 0 ? void 0 : options.folderId) || "").trim();
494
+ let label = ((options === null || options === void 0 ? void 0 : options.label) || "").trim();
495
+ if (!label) {
496
+ const q = `
497
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
498
+ PREFIX dcterms: <http://purl.org/dc/terms/>
499
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
500
+
501
+ SELECT ?label ?container WHERE {
502
+ ${iri(mqIriValue)} a yasgui:ManagedQuery ;
503
+ rdfs:label ?label ;
504
+ dcterms:isPartOf ?container .
505
+ }
506
+ LIMIT 1`;
507
+ const res = yield this.sparqlQuery(q);
508
+ const row = this.getBindings(res)[0];
509
+ const fetchedLabel = (_a = row === null || row === void 0 ? void 0 : row.label) === null || _a === void 0 ? void 0 : _a.value;
510
+ const container = (_b = row === null || row === void 0 ? void 0 : row.container) === null || _b === void 0 ? void 0 : _b.value;
511
+ if (!fetchedLabel || !container)
512
+ throw new WorkspaceBackendError("NOT_FOUND", "Query not found");
513
+ label = fetchedLabel;
514
+ if (!folderPath && container !== workspaceIri) {
515
+ folderPath = tryParseFolderPathFromFolderIri(workspaceIri, container) || "";
516
+ }
517
+ }
518
+ if (!label.trim())
519
+ throw new WorkspaceBackendError("UNKNOWN", "Query name is required");
520
+ const containerIriValue = folderPath ? mintFolderIri(workspaceIri, folderPath) : workspaceIri;
521
+ {
522
+ const dupCheck = `
523
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
524
+ PREFIX dcterms: <http://purl.org/dc/terms/>
525
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
526
+
527
+ SELECT ?mq WHERE {
528
+ ?mq a yasgui:ManagedQuery ;
529
+ dcterms:isPartOf ${iri(containerIriValue)} ;
530
+ rdfs:label ?lbl .
531
+ FILTER(LCASE(STR(?lbl)) = LCASE(${sparqlStringLiteral(label)}))
532
+ FILTER(?mq != ${iri(mqIriValue)})
533
+ }
534
+ LIMIT 1`;
535
+ const res = yield this.sparqlQuery(dupCheck);
536
+ const row = this.getBindings(res)[0];
537
+ if ((_c = row === null || row === void 0 ? void 0 : row.mq) === null || _c === void 0 ? void 0 : _c.value) {
538
+ throw new WorkspaceBackendError("CONFLICT", `A query named '${label}' already exists in this folder. Please choose a different name.`);
539
+ }
540
+ }
541
+ if (options === null || options === void 0 ? void 0 : options.expectedVersionTag) {
542
+ try {
543
+ const current = yield this.readQuery(queryId);
544
+ if (current.versionTag && current.versionTag !== options.expectedVersionTag) {
545
+ throw new WorkspaceBackendError("CONFLICT", "Version tag mismatch");
546
+ }
547
+ }
548
+ catch (e) {
549
+ const err = e;
550
+ if ((err === null || err === void 0 ? void 0 : err.code) && err.code !== "NOT_FOUND")
551
+ throw e;
552
+ }
553
+ }
554
+ try {
555
+ const current = yield this.readQuery(queryId);
556
+ if (normalizeQueryText(current.queryText) === normalizeQueryText(queryText)) {
557
+ return;
558
+ }
559
+ }
560
+ catch (e) {
561
+ const err = e;
562
+ if ((err === null || err === void 0 ? void 0 : err.code) && err.code !== "NOT_FOUND")
563
+ throw e;
564
+ }
565
+ const versionIriValue = mintManagedQueryVersionIri(workspaceIri);
566
+ const createdAt = nowIso();
567
+ const description = (_d = options === null || options === void 0 ? void 0 : options.message) === null || _d === void 0 ? void 0 : _d.trim();
568
+ const associatedEndpoint = (_e = options === null || options === void 0 ? void 0 : options.associatedEndpoint) === null || _e === void 0 ? void 0 : _e.trim();
569
+ const folderTriples = [];
570
+ if (folderPath) {
571
+ const parts = splitPath(folderPath);
572
+ for (let i = 0; i < parts.length; i++) {
573
+ const subPath = parts.slice(0, i + 1).join("/");
574
+ const folderIriValue = mintFolderIri(workspaceIri, subPath);
575
+ const folderLabel = parts[i];
576
+ folderTriples.push(`${iri(folderIriValue)} a <https://matdata.eu/ns/yasgui#WorkspaceFolder> ;`);
577
+ folderTriples.push(` <http://www.w3.org/2004/02/skos/core#inScheme> ${iri(workspaceIri)} ;`);
578
+ folderTriples.push(` <http://www.w3.org/2000/01/rdf-schema#label> ${sparqlStringLiteral(folderLabel)} .`);
579
+ if (i > 0) {
580
+ const parentPath = parts.slice(0, i).join("/");
581
+ const parentIri = mintFolderIri(workspaceIri, parentPath);
582
+ folderTriples.push(`${iri(folderIriValue)} <http://www.w3.org/2004/02/skos/core#broader> ${iri(parentIri)} .`);
583
+ }
584
+ }
585
+ }
586
+ const update = `
587
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
588
+ PREFIX dcterms: <http://purl.org/dc/terms/>
589
+ PREFIX prov: <http://www.w3.org/ns/prov#>
590
+ PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>
591
+ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
592
+ PREFIX spin: <http://spinrdf.org/spin#>
593
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
594
+
595
+ INSERT DATA {
596
+ ${iri(workspaceIri)} a yasgui:Workspace .
597
+
598
+ ${folderTriples.join("\n ")}
599
+
600
+ ${iri(mqIriValue)} a yasgui:ManagedQuery ;
601
+ rdfs:label ${sparqlStringLiteral(label)} ;
602
+ dcterms:isPartOf ${iri(containerIriValue)} .
603
+
604
+ ${iri(versionIriValue)} a yasgui:ManagedQueryVersion ;
605
+ dcterms:isVersionOf ${iri(mqIriValue)} ;
606
+ dcterms:created ${sparqlStringLiteral(createdAt)}^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
607
+ spin:text ${sparqlStringLiteral(queryText)}${description ? `;\n dcterms:description ${sparqlStringLiteral(description)}` : ""}${associatedEndpoint ? `;\n prov:used _:svc` : ""} .
608
+
609
+ ${associatedEndpoint ? `_:svc a sd:Service ;\n sd:endpoint ${iri(associatedEndpoint)} .` : ""}
610
+ }`;
611
+ yield this.sparqlUpdate(update);
612
+ });
613
+ }
614
+ listVersions(queryId) {
615
+ return __awaiter(this, void 0, void 0, function* () {
616
+ var _a, _b, _c, _d;
617
+ const mqIri = this.resolveManagedQueryIri(queryId);
618
+ const query = `
619
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
620
+ PREFIX dcterms: <http://purl.org/dc/terms/>
621
+
622
+ SELECT ?version ?created ?creator ?message WHERE {
623
+ ?version a yasgui:ManagedQueryVersion ;
624
+ dcterms:isVersionOf ${iri(mqIri)} ;
625
+ dcterms:created ?created .
626
+ OPTIONAL { ?version dcterms:creator ?creator }
627
+ OPTIONAL { ?version dcterms:description ?message }
628
+ }
629
+ ORDER BY DESC(?created)`;
630
+ const res = yield this.sparqlQuery(query);
631
+ const versions = [];
632
+ for (const row of this.getBindings(res)) {
633
+ const version = (_a = row.version) === null || _a === void 0 ? void 0 : _a.value;
634
+ const createdAt = (_b = row.created) === null || _b === void 0 ? void 0 : _b.value;
635
+ if (!version || !createdAt)
636
+ continue;
637
+ versions.push({
638
+ id: version,
639
+ createdAt,
640
+ author: (_c = row.creator) === null || _c === void 0 ? void 0 : _c.value,
641
+ message: (_d = row.message) === null || _d === void 0 ? void 0 : _d.value,
642
+ });
643
+ }
644
+ return versions;
645
+ });
646
+ }
647
+ readVersion(queryId, versionId) {
648
+ return __awaiter(this, void 0, void 0, function* () {
649
+ var _a, _b, _c;
650
+ const mqIri = this.resolveManagedQueryIri(queryId);
651
+ const query = `
652
+ PREFIX yasgui: <https://matdata.eu/ns/yasgui#>
653
+ PREFIX dcterms: <http://purl.org/dc/terms/>
654
+ PREFIX prov: <http://www.w3.org/ns/prov#>
655
+ PREFIX spin: <http://spinrdf.org/spin#>
656
+ PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>
657
+
658
+ SELECT ?text ?endpoint ?description WHERE {
659
+ ${iri(versionId)} a yasgui:ManagedQueryVersion ;
660
+ dcterms:isVersionOf ${iri(mqIri)} ;
661
+ spin:text ?text .
662
+
663
+ OPTIONAL { ${iri(versionId)} dcterms:description ?description }
664
+ OPTIONAL {
665
+ ${iri(versionId)} prov:used ?svc .
666
+ ?svc a sd:Service ;
667
+ sd:endpoint ?endpoint .
668
+ }
669
+ }
670
+ LIMIT 1`;
671
+ const res = yield this.sparqlQuery(query);
672
+ const row = this.getBindings(res)[0];
673
+ if (!row)
674
+ throw new WorkspaceBackendError("NOT_FOUND", "Version not found");
675
+ const text = (_a = row.text) === null || _a === void 0 ? void 0 : _a.value;
676
+ if (!text)
677
+ throw new WorkspaceBackendError("NOT_FOUND", "Version not found");
678
+ return {
679
+ queryText: text,
680
+ versionTag: versionId,
681
+ associatedEndpoint: (_b = row.endpoint) === null || _b === void 0 ? void 0 : _b.value,
682
+ description: (_c = row.description) === null || _c === void 0 ? void 0 : _c.value,
683
+ };
684
+ });
685
+ }
686
+ }
687
+ //# sourceMappingURL=SparqlWorkspaceBackend.js.map