@_linked/core 2.6.0-next.20260509053822 → 2.6.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 (65) hide show
  1. package/CHANGELOG.md +54 -4
  2. package/README.md +36 -0
  3. package/lib/cjs/queries/queryDispatch.js +1 -1
  4. package/lib/cjs/queries/queryDispatch.js.map +1 -1
  5. package/lib/cjs/shapes/SHACL.d.ts +13 -0
  6. package/lib/cjs/shapes/SHACL.js +53 -5
  7. package/lib/cjs/shapes/SHACL.js.map +1 -1
  8. package/lib/cjs/sparql/{SparqlStore.d.ts → SparqlDataset.d.ts} +6 -5
  9. package/lib/cjs/sparql/{SparqlStore.js → SparqlDataset.js} +9 -8
  10. package/lib/cjs/sparql/SparqlDataset.js.map +1 -0
  11. package/lib/cjs/sparql/index.d.ts +1 -1
  12. package/lib/cjs/sparql/index.js +5 -4
  13. package/lib/cjs/sparql/index.js.map +1 -1
  14. package/lib/cjs/sparql/irToAlgebra.js +237 -41
  15. package/lib/cjs/sparql/irToAlgebra.js.map +1 -1
  16. package/lib/cjs/test-helpers/FusekiStore.d.ts +4 -4
  17. package/lib/cjs/test-helpers/FusekiStore.js +4 -4
  18. package/lib/cjs/test-helpers/FusekiStore.js.map +1 -1
  19. package/lib/cjs/test-helpers/fuseki-test-store.js +3 -0
  20. package/lib/cjs/test-helpers/fuseki-test-store.js.map +1 -1
  21. package/lib/cjs/utils/LinkedFileStorage.d.ts +3 -3
  22. package/lib/cjs/utils/LinkedFileStorage.js +21 -13
  23. package/lib/cjs/utils/LinkedFileStorage.js.map +1 -1
  24. package/lib/cjs/utils/LinkedStorage.d.ts +25 -9
  25. package/lib/cjs/utils/LinkedStorage.js +63 -44
  26. package/lib/cjs/utils/LinkedStorage.js.map +1 -1
  27. package/lib/cjs/utils/loadStores.d.ts +34 -0
  28. package/lib/cjs/utils/loadStores.js +101 -0
  29. package/lib/cjs/utils/loadStores.js.map +1 -0
  30. package/lib/cjs/utils/parseDatasetsConfig.d.ts +49 -0
  31. package/lib/cjs/utils/parseDatasetsConfig.js +110 -0
  32. package/lib/cjs/utils/parseDatasetsConfig.js.map +1 -0
  33. package/lib/esm/queries/queryDispatch.js +1 -1
  34. package/lib/esm/queries/queryDispatch.js.map +1 -1
  35. package/lib/esm/shapes/SHACL.d.ts +13 -0
  36. package/lib/esm/shapes/SHACL.js +53 -5
  37. package/lib/esm/shapes/SHACL.js.map +1 -1
  38. package/lib/esm/sparql/{SparqlStore.d.ts → SparqlDataset.d.ts} +6 -5
  39. package/lib/esm/sparql/{SparqlStore.js → SparqlDataset.js} +8 -6
  40. package/lib/esm/sparql/SparqlDataset.js.map +1 -0
  41. package/lib/esm/sparql/index.d.ts +1 -1
  42. package/lib/esm/sparql/index.js +2 -2
  43. package/lib/esm/sparql/index.js.map +1 -1
  44. package/lib/esm/sparql/irToAlgebra.js +237 -41
  45. package/lib/esm/sparql/irToAlgebra.js.map +1 -1
  46. package/lib/esm/test-helpers/FusekiStore.d.ts +4 -4
  47. package/lib/esm/test-helpers/FusekiStore.js +4 -4
  48. package/lib/esm/test-helpers/FusekiStore.js.map +1 -1
  49. package/lib/esm/test-helpers/fuseki-test-store.js +3 -0
  50. package/lib/esm/test-helpers/fuseki-test-store.js.map +1 -1
  51. package/lib/esm/utils/LinkedFileStorage.d.ts +3 -3
  52. package/lib/esm/utils/LinkedFileStorage.js +21 -13
  53. package/lib/esm/utils/LinkedFileStorage.js.map +1 -1
  54. package/lib/esm/utils/LinkedStorage.d.ts +25 -9
  55. package/lib/esm/utils/LinkedStorage.js +63 -44
  56. package/lib/esm/utils/LinkedStorage.js.map +1 -1
  57. package/lib/esm/utils/loadStores.d.ts +34 -0
  58. package/lib/esm/utils/loadStores.js +65 -0
  59. package/lib/esm/utils/loadStores.js.map +1 -0
  60. package/lib/esm/utils/parseDatasetsConfig.d.ts +49 -0
  61. package/lib/esm/utils/parseDatasetsConfig.js +107 -0
  62. package/lib/esm/utils/parseDatasetsConfig.js.map +1 -0
  63. package/package.json +1 -1
  64. package/lib/cjs/sparql/SparqlStore.js.map +0 -1
  65. package/lib/esm/sparql/SparqlStore.js.map +0 -1
@@ -5,18 +5,30 @@ const CoreMap_js_1 = require("../collections/CoreMap.js");
5
5
  const CoreSet_js_1 = require("../collections/CoreSet.js");
6
6
  const queryDispatch_js_1 = require("../queries/queryDispatch.js");
7
7
  const ShapeClass_js_1 = require("./ShapeClass.js");
8
+ /**
9
+ * Primary routing layer (arch-04 §The IDataset abstraction).
10
+ *
11
+ * Resolves an incoming Linked Query to the IDataset that should handle it,
12
+ * based on the query's target shape. Composite IDatasets (gateways, routers,
13
+ * forwarders, resolvers) plug in here just like storage IDatasets do.
14
+ *
15
+ * The "Dataset" naming aligns with the IDataset contract. Earlier "Store"
16
+ * names were renamed in phase-1 — see docs/plans/002-phase-1-create-user-project-flow.md.
17
+ */
8
18
  class LinkedStorage {
9
19
  static isInitialised() {
10
- return !!this.defaultStore;
20
+ return !!this.defaultDataset;
11
21
  }
12
- static getDefaultStore() {
13
- return this.defaultStore;
22
+ /** The catch-all IDataset for shapes with no explicit mapping. */
23
+ static getDefaultDataset() {
24
+ return this.defaultDataset;
14
25
  }
15
- static setDefaultStore(store) {
26
+ /** Set the default IDataset (catch-all for shapes with no explicit mapping). */
27
+ static setDefaultDataset(dataset) {
16
28
  var _a;
17
- this.defaultStore = store;
18
- if ((_a = this.defaultStore) === null || _a === void 0 ? void 0 : _a.init) {
19
- this.defaultStore.init();
29
+ this.defaultDataset = dataset;
30
+ if ((_a = this.defaultDataset) === null || _a === void 0 ? void 0 : _a.init) {
31
+ this.defaultDataset.init();
20
32
  }
21
33
  (0, queryDispatch_js_1.setQueryDispatch)({
22
34
  selectQuery: (q) => this.selectQuery(q),
@@ -25,79 +37,86 @@ class LinkedStorage {
25
37
  deleteQuery: (q) => this.deleteQuery(q),
26
38
  });
27
39
  }
28
- static setStoreForShapes(store, ...shapeClasses) {
40
+ /** Pin one or more shape classes to a specific IDataset implementer. */
41
+ static setDatasetForShapes(dataset, ...shapeClasses) {
29
42
  shapeClasses.forEach((shapeClass) => {
30
- this.shapeToStore.set(shapeClass, store);
43
+ this.shapeToDataset.set(shapeClass, dataset);
31
44
  });
32
45
  }
33
- static getStores() {
34
- const stores = new CoreSet_js_1.CoreSet();
35
- if (this.defaultStore) {
36
- stores.add(this.defaultStore);
46
+ /** Every IDataset known to the primary router (default + all pinned). */
47
+ static getDatasets() {
48
+ const datasets = new CoreSet_js_1.CoreSet();
49
+ if (this.defaultDataset) {
50
+ datasets.add(this.defaultDataset);
37
51
  }
38
- this.shapeToStore.forEach((store) => stores.add(store));
39
- return stores;
52
+ this.shapeToDataset.forEach((dataset) => datasets.add(dataset));
53
+ return datasets;
40
54
  }
41
- static getShapeToStoreMap() {
42
- return this.shapeToStore;
55
+ /** Read-only view of the shape→IDataset map. */
56
+ static getShapeToDatasetMap() {
57
+ return this.shapeToDataset;
43
58
  }
44
- static getStoreForShapeClass(shapeClass) {
59
+ /** Resolve the IDataset for a given shape class. Walks the prototype chain. */
60
+ static getDatasetForShapeClass(shapeClass) {
45
61
  let current = shapeClass !== null && shapeClass !== void 0 ? shapeClass : null;
46
62
  while (typeof current === 'function') {
47
- const store = this.shapeToStore.get(current);
48
- if (store) {
49
- return store;
63
+ const dataset = this.shapeToDataset.get(current);
64
+ if (dataset) {
65
+ return dataset;
50
66
  }
51
67
  const parent = Object.getPrototypeOf(current);
52
68
  if (parent === Function.prototype || parent === null)
53
69
  break;
54
70
  current = parent;
55
71
  }
56
- return this.defaultStore;
72
+ return this.defaultDataset;
57
73
  }
58
- static resolveStoreForQueryShape(shape) {
74
+ static resolveDatasetForQueryShape(shape) {
59
75
  if (!shape) {
60
- return this.defaultStore;
76
+ return this.defaultDataset;
61
77
  }
62
78
  if (typeof shape === 'function') {
63
- return this.getStoreForShapeClass(shape);
79
+ return this.getDatasetForShapeClass(shape);
64
80
  }
65
81
  if (typeof shape === 'string') {
66
82
  const shapeClass = (0, ShapeClass_js_1.getShapeClass)(shape);
67
- return this.getStoreForShapeClass(shapeClass);
83
+ return this.getDatasetForShapeClass(shapeClass);
68
84
  }
69
- return this.defaultStore;
85
+ return this.defaultDataset;
70
86
  }
71
87
  static selectQuery(query) {
72
88
  var _a;
73
- const store = this.resolveStoreForQueryShape((_a = query === null || query === void 0 ? void 0 : query.root) === null || _a === void 0 ? void 0 : _a.shape);
74
- if (!(store === null || store === void 0 ? void 0 : store.selectQuery)) {
75
- return Promise.reject(new Error('No query store configured. Call LinkedStorage.setDefaultStore().'));
89
+ if (!(query === null || query === void 0 ? void 0 : query.root)) {
90
+ return Promise.reject(new Error(`Invalid select query passed to LinkedStorage.selectQuery(): missing root. Payload: ${query ? JSON.stringify(query) : 'undefined'}`));
76
91
  }
77
- return store.selectQuery(query);
92
+ const dataset = this.resolveDatasetForQueryShape((_a = query === null || query === void 0 ? void 0 : query.root) === null || _a === void 0 ? void 0 : _a.shape);
93
+ if (!(dataset === null || dataset === void 0 ? void 0 : dataset.selectQuery)) {
94
+ return Promise.reject(new Error('No query dataset configured. Call LinkedStorage.setDefaultDataset().'));
95
+ }
96
+ return dataset.selectQuery(query);
78
97
  }
79
98
  static updateQuery(query) {
80
- const store = this.resolveStoreForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
81
- if (!(store === null || store === void 0 ? void 0 : store.updateQuery)) {
82
- return Promise.reject(new Error('No update handler configured on the query store.'));
99
+ const dataset = this.resolveDatasetForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
100
+ if (!(dataset === null || dataset === void 0 ? void 0 : dataset.updateQuery)) {
101
+ return Promise.reject(new Error('No update handler configured on the query dataset.'));
83
102
  }
84
- return store.updateQuery(query);
103
+ return dataset.updateQuery(query);
85
104
  }
86
105
  static createQuery(query) {
87
- const store = this.resolveStoreForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
88
- if (!(store === null || store === void 0 ? void 0 : store.createQuery)) {
89
- return Promise.reject(new Error('No create handler configured on the query store.'));
106
+ const dataset = this.resolveDatasetForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
107
+ if (!(dataset === null || dataset === void 0 ? void 0 : dataset.createQuery)) {
108
+ return Promise.reject(new Error('No create handler configured on the query dataset.'));
90
109
  }
91
- return store.createQuery(query);
110
+ return dataset.createQuery(query);
92
111
  }
93
112
  static deleteQuery(query) {
94
- const store = this.resolveStoreForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
95
- if (!(store === null || store === void 0 ? void 0 : store.deleteQuery)) {
96
- return Promise.reject(new Error('No delete handler configured on the query store.'));
113
+ const dataset = this.resolveDatasetForQueryShape(query === null || query === void 0 ? void 0 : query.shape);
114
+ if (!(dataset === null || dataset === void 0 ? void 0 : dataset.deleteQuery)) {
115
+ return Promise.reject(new Error('No delete handler configured on the query dataset.'));
97
116
  }
98
- return store.deleteQuery(query);
117
+ return dataset.deleteQuery(query);
99
118
  }
100
119
  }
101
120
  exports.LinkedStorage = LinkedStorage;
102
- LinkedStorage.shapeToStore = new CoreMap_js_1.CoreMap();
121
+ LinkedStorage.shapeToDataset = new CoreMap_js_1.CoreMap();
103
122
  //# sourceMappingURL=LinkedStorage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkedStorage.js","sourceRoot":"","sources":["../../../src/utils/LinkedStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LinkedStorage.js","sourceRoot":"","sources":["../../../src/utils/LinkedStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { DatasetsConfig } from './parseDatasetsConfig.js';
2
+ /**
3
+ * Dynamically imports each alias's `store` (an npm specifier) and
4
+ * instantiates the resolved class with the entry's `config` verbatim —
5
+ * `new StoreClass(entry.config)`. Returns alias → store.
6
+ *
7
+ * Convention: the last segment of the `store` path is the named export
8
+ * to use (e.g. `@_linked/fuseki/shapes/FusekiStore` → `FusekiStore`).
9
+ * Falls back to the module's `default` export if the named export is
10
+ * absent. Each store class must accept a single config-object argument.
11
+ *
12
+ * Async + uses runtime dynamic import; works in Node where the module
13
+ * specifier can be resolved at runtime. Frontends should instead
14
+ * import each store class explicitly in their storage-config file and
15
+ * instantiate per alias by hand (webpack can't bundle
16
+ * `import(variableString)`).
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import rawConfig from './linked.backend.datasets.json' assert { type: 'json' };
21
+ * import { parseDatasetsConfig } from '@_linked/core/utils/parseDatasetsConfig';
22
+ * import { loadStores } from '@_linked/core/utils/loadStores';
23
+ * import { LinkedStorage } from '@_linked/core/utils/LinkedStorage';
24
+ *
25
+ * const config = parseDatasetsConfig(rawConfig, process.env);
26
+ * const stores = await loadStores(config);
27
+ * LinkedStorage.setDefaultDataset(stores.appData);
28
+ * ```
29
+ *
30
+ * @param config Parsed config from {@link parseDatasetsConfig}.
31
+ * @returns Map of alias → constructed store instance.
32
+ * @throws If a `store` path can't be resolved to a class export.
33
+ */
34
+ export declare function loadStores<T = unknown>(config: DatasetsConfig): Promise<Record<string, T>>;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ // Backend-side store loader. Lives in its own file so that frontend
3
+ // bundlers (webpack) consuming parseDatasetsConfig don't pull in the
4
+ // dynamic-import code below — webpack flags `import(variableString)` as
5
+ // a critical dependency when it can't analyse the target statically.
6
+ //
7
+ // Backends import this directly; frontends never do.
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
42
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
43
+ return new (P || (P = Promise))(function (resolve, reject) {
44
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
45
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
46
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
47
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
48
+ });
49
+ };
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.loadStores = loadStores;
52
+ /**
53
+ * Dynamically imports each alias's `store` (an npm specifier) and
54
+ * instantiates the resolved class with the entry's `config` verbatim —
55
+ * `new StoreClass(entry.config)`. Returns alias → store.
56
+ *
57
+ * Convention: the last segment of the `store` path is the named export
58
+ * to use (e.g. `@_linked/fuseki/shapes/FusekiStore` → `FusekiStore`).
59
+ * Falls back to the module's `default` export if the named export is
60
+ * absent. Each store class must accept a single config-object argument.
61
+ *
62
+ * Async + uses runtime dynamic import; works in Node where the module
63
+ * specifier can be resolved at runtime. Frontends should instead
64
+ * import each store class explicitly in their storage-config file and
65
+ * instantiate per alias by hand (webpack can't bundle
66
+ * `import(variableString)`).
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import rawConfig from './linked.backend.datasets.json' assert { type: 'json' };
71
+ * import { parseDatasetsConfig } from '@_linked/core/utils/parseDatasetsConfig';
72
+ * import { loadStores } from '@_linked/core/utils/loadStores';
73
+ * import { LinkedStorage } from '@_linked/core/utils/LinkedStorage';
74
+ *
75
+ * const config = parseDatasetsConfig(rawConfig, process.env);
76
+ * const stores = await loadStores(config);
77
+ * LinkedStorage.setDefaultDataset(stores.appData);
78
+ * ```
79
+ *
80
+ * @param config Parsed config from {@link parseDatasetsConfig}.
81
+ * @returns Map of alias → constructed store instance.
82
+ * @throws If a `store` path can't be resolved to a class export.
83
+ */
84
+ function loadStores(config) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ var _a;
87
+ const stores = {};
88
+ for (const [alias, entry] of Object.entries(config.datasets)) {
89
+ const mod = yield Promise.resolve(`${entry.store}`).then(s => __importStar(require(s)));
90
+ const exportName = entry.store.split('/').pop();
91
+ const StoreClass = (_a = (mod && mod[exportName])) !== null && _a !== void 0 ? _a : (mod && mod.default);
92
+ if (typeof StoreClass !== 'function') {
93
+ throw new Error(`loadStores: could not resolve a class export from "${entry.store}" for alias "${alias}". ` +
94
+ `Expected a named export "${exportName}" or a default export that is a class.`);
95
+ }
96
+ stores[alias] = new StoreClass(entry.config);
97
+ }
98
+ return stores;
99
+ });
100
+ }
101
+ //# sourceMappingURL=loadStores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadStores.js","sourceRoot":"","sources":["../../../src/utils/loadStores.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,qEAAqE;AACrE,wEAAwE;AACxE,qEAAqE;AACrE,EAAE;AACF,qDAAqD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCrD,gCAmBC;AAnDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAsB,UAAU,CAC9B,MAAsB;;;QAEtB,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,yBAAa,KAAK,CAAC,KAAK,uCAAC,CAAC;YACtC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC;YACjD,MAAM,UAAU,GACd,MAAA,CAAC,GAAG,IAAK,GAA+B,CAAC,UAAU,CAAC,CAAC,mCACrD,CAAC,GAAG,IAAK,GAA2B,CAAC,OAAO,CAAC,CAAC;YAChD,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;gBACrC,MAAM,IAAI,KAAK,CACb,sDAAsD,KAAK,CAAC,KAAK,gBAAgB,KAAK,KAAK;oBACzF,4BAA4B,UAAU,wCAAwC,CACjF,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,GAAG,IAAK,UAAsC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CAAA"}
@@ -0,0 +1,49 @@
1
+ /** One entry under `datasets`. Keyed by alias name in the parent object. */
2
+ export interface DatasetEntry {
3
+ /** npm import path to the IDataset class — e.g. "@_linked/fuseki/shapes/FusekiStore". */
4
+ store: string;
5
+ /** Constructor argument forwarded to the store class. Shape is store-specific. */
6
+ config: Record<string, unknown>;
7
+ }
8
+ /** Top-level structure of linked.{backend,frontend}.datasets.json. */
9
+ export interface DatasetsConfig {
10
+ /** Alias → store entry. */
11
+ datasets: Record<string, DatasetEntry>;
12
+ /** Reserved for future top-level sections (fileStorage, services, etc.). */
13
+ [section: string]: unknown;
14
+ }
15
+ /**
16
+ * Parse + env-resolve a raw datasets config object.
17
+ *
18
+ * - Requires a top-level `datasets` object (other top-level sections are passed
19
+ * through unchanged for future extension).
20
+ * - Resolves `${VAR}` and `${VAR:-default}` placeholders against `env` recursively
21
+ * across all string leaves.
22
+ * - Strips keys starting with `_` (treated as comments / `_note` fields).
23
+ * - Throws on a referenced env var with no default that is unset or empty.
24
+ *
25
+ * Pure + browser-safe — no file I/O, no dynamic imports. Use this on both
26
+ * backend and frontend. The companion `loadStores` (separate file) does the
27
+ * runtime dynamic-import dispatch for the backend.
28
+ *
29
+ * @example Backend
30
+ * ```ts
31
+ * import rawConfig from './linked.backend.datasets.json' assert { type: 'json' };
32
+ * const config = parseDatasetsConfig(rawConfig, process.env);
33
+ * ```
34
+ *
35
+ * @example Frontend
36
+ * ```ts
37
+ * import rawConfig from './linked.frontend.datasets.json' assert { type: 'json' };
38
+ * // No runtime env in the browser; pass empty {}
39
+ * const config = parseDatasetsConfig(rawConfig, {});
40
+ * const appData = new BackendAPIStore(config.datasets.appData.config);
41
+ * ```
42
+ *
43
+ * @param raw Parsed JSON object (or anything object-shaped). Throws otherwise.
44
+ * @param env Env map. Defaults to {} (no interpolation).
45
+ * @returns Typed, env-resolved {@link DatasetsConfig}.
46
+ * @throws On missing/malformed `datasets`, on malformed alias entry, or
47
+ * on an unresolved `${VAR}` with no default.
48
+ */
49
+ export declare function parseDatasetsConfig(raw: unknown, env?: Record<string, string | undefined>): DatasetsConfig;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ // Pure parser + dispatcher for linked.{backend,frontend}.datasets.json.
3
+ //
4
+ // Per the spec in docs/backlog/016-ejection-export-flow.md:
5
+ //
6
+ // {
7
+ // "datasets": {
8
+ // "<alias>": {
9
+ // "store": "<npm-import-path>",
10
+ // "config": { /* passed verbatim to the store's constructor */ }
11
+ // }
12
+ // }
13
+ // }
14
+ //
15
+ // `store` is an npm import path string (e.g. "@_linked/fuseki/shapes/FusekiStore").
16
+ // `config` is the store class's own concern — the runtime never inspects it.
17
+ // `${VAR}` / `${VAR:-default}` placeholders inside string values are resolved
18
+ // against an env map at parse time.
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.parseDatasetsConfig = parseDatasetsConfig;
21
+ /**
22
+ * Parse + env-resolve a raw datasets config object.
23
+ *
24
+ * - Requires a top-level `datasets` object (other top-level sections are passed
25
+ * through unchanged for future extension).
26
+ * - Resolves `${VAR}` and `${VAR:-default}` placeholders against `env` recursively
27
+ * across all string leaves.
28
+ * - Strips keys starting with `_` (treated as comments / `_note` fields).
29
+ * - Throws on a referenced env var with no default that is unset or empty.
30
+ *
31
+ * Pure + browser-safe — no file I/O, no dynamic imports. Use this on both
32
+ * backend and frontend. The companion `loadStores` (separate file) does the
33
+ * runtime dynamic-import dispatch for the backend.
34
+ *
35
+ * @example Backend
36
+ * ```ts
37
+ * import rawConfig from './linked.backend.datasets.json' assert { type: 'json' };
38
+ * const config = parseDatasetsConfig(rawConfig, process.env);
39
+ * ```
40
+ *
41
+ * @example Frontend
42
+ * ```ts
43
+ * import rawConfig from './linked.frontend.datasets.json' assert { type: 'json' };
44
+ * // No runtime env in the browser; pass empty {}
45
+ * const config = parseDatasetsConfig(rawConfig, {});
46
+ * const appData = new BackendAPIStore(config.datasets.appData.config);
47
+ * ```
48
+ *
49
+ * @param raw Parsed JSON object (or anything object-shaped). Throws otherwise.
50
+ * @param env Env map. Defaults to {} (no interpolation).
51
+ * @returns Typed, env-resolved {@link DatasetsConfig}.
52
+ * @throws On missing/malformed `datasets`, on malformed alias entry, or
53
+ * on an unresolved `${VAR}` with no default.
54
+ */
55
+ function parseDatasetsConfig(raw, env = {}) {
56
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
57
+ throw new Error('Invalid datasets config: expected a top-level JSON object');
58
+ }
59
+ const resolved = resolveInterpolations(raw, env);
60
+ const datasets = resolved.datasets;
61
+ if (!datasets || typeof datasets !== 'object' || Array.isArray(datasets)) {
62
+ throw new Error('Invalid datasets config: missing or malformed "datasets" section');
63
+ }
64
+ for (const [alias, entry] of Object.entries(datasets)) {
65
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
66
+ throw new Error(`Invalid datasets config: alias "${alias}" must be an object`);
67
+ }
68
+ const e = entry;
69
+ if (typeof e.store !== 'string' || !e.store) {
70
+ throw new Error(`Invalid datasets config: alias "${alias}" is missing a string "store" (npm import path)`);
71
+ }
72
+ if (e.config !== undefined && (typeof e.config !== 'object' || Array.isArray(e.config))) {
73
+ throw new Error(`Invalid datasets config: alias "${alias}" "config" must be an object if present`);
74
+ }
75
+ if (e.config === undefined)
76
+ e.config = {};
77
+ }
78
+ return resolved;
79
+ }
80
+ function resolveInterpolations(value, env) {
81
+ if (typeof value === 'string')
82
+ return resolveString(value, env);
83
+ if (Array.isArray(value)) {
84
+ return value.map((v) => resolveInterpolations(v, env));
85
+ }
86
+ if (value && typeof value === 'object') {
87
+ const out = {};
88
+ for (const key of Object.keys(value)) {
89
+ if (key.startsWith('_'))
90
+ continue; // _note, _comment, ...
91
+ out[key] = resolveInterpolations(value[key], env);
92
+ }
93
+ return out;
94
+ }
95
+ return value;
96
+ }
97
+ // Matches ${VAR} or ${VAR:-default}. VAR is uppercase alphanum + underscore.
98
+ // Default text may contain anything except `}`.
99
+ const INTERP_RE = /\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g;
100
+ function resolveString(input, env) {
101
+ return input.replace(INTERP_RE, (_full, varName, defaultValue) => {
102
+ const v = env[varName];
103
+ if (v !== undefined && v !== '')
104
+ return v;
105
+ if (defaultValue !== undefined)
106
+ return defaultValue;
107
+ throw new Error(`Required env var "${varName}" is not set and has no default (referenced in datasets config)`);
108
+ });
109
+ }
110
+ //# sourceMappingURL=parseDatasetsConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseDatasetsConfig.js","sourceRoot":"","sources":["../../../src/utils/parseDatasetsConfig.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ export function setQueryDispatch(d) {
4
4
  }
5
5
  export function getQueryDispatch() {
6
6
  if (!dispatch) {
7
- throw new Error('No query dispatch configured. Call LinkedStorage.setDefaultStore() first.');
7
+ throw new Error('No query dispatch configured. Call LinkedStorage.setDefaultDataset() first.');
8
8
  }
9
9
  return dispatch;
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"queryDispatch.js","sourceRoot":"","sources":["../../../src/queries/queryDispatch.ts"],"names":[],"mappings":"AAoBA,IAAI,QAAQ,GAAyB,IAAI,CAAC;AAE1C,MAAM,UAAU,gBAAgB,CAAC,CAAgB;IAC/C,QAAQ,GAAG,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"queryDispatch.js","sourceRoot":"","sources":["../../../src/queries/queryDispatch.ts"],"names":[],"mappings":"AAoBA,IAAI,QAAQ,GAAyB,IAAI,CAAC;AAE1C,MAAM,UAAU,gBAAgB,CAAC,CAAgB;IAC/C,QAAQ,GAAG,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -175,6 +175,19 @@ export interface ParameterConfig {
175
175
  }
176
176
  export declare class NodeShape extends Shape {
177
177
  static targetClass: NodeReferenceValue;
178
+ /** One-time keys for missing/invalid `propertyShapes` on superclass static `shape`. */
179
+ private static readonly _warnedMissingPropertyShapesKeys;
180
+ /**
181
+ * Returns `propertyShapes` when it is a real array; otherwise `[]` and logs once per
182
+ * `(ownerClassName, shapeId)` — common when a superclass `static shape` is a plain object
183
+ * or came from another `@_linked/core` copy without field initializers.
184
+ *
185
+ * Label for logs / dedupe keys when walking the shape class chain.
186
+ * Prefer `class.name` (almost always set for `class X {}`); if missing, use the static
187
+ * shape's `id` so diagnostics stay useful without vague "(anonymous)".
188
+ */
189
+ private static shapeOwnerLabel;
190
+ private static listPropertyShapesSafe;
178
191
  private _label?;
179
192
  description?: string;
180
193
  targetClass?: NodeReferenceValue;
@@ -36,6 +36,44 @@ const EXPLICIT_NODE_KIND_SYMBOL = Symbol('explicitNodeKind');
36
36
  const EXPLICIT_MIN_COUNT_SYMBOL = Symbol('explicitMinCount');
37
37
  const EXPLICIT_MAX_COUNT_SYMBOL = Symbol('explicitMaxCount');
38
38
  export class NodeShape extends Shape {
39
+ /**
40
+ * Returns `propertyShapes` when it is a real array; otherwise `[]` and logs once per
41
+ * `(ownerClassName, shapeId)` — common when a superclass `static shape` is a plain object
42
+ * or came from another `@_linked/core` copy without field initializers.
43
+ *
44
+ * Label for logs / dedupe keys when walking the shape class chain.
45
+ * Prefer `class.name` (almost always set for `class X {}`); if missing, use the static
46
+ * shape's `id` so diagnostics stay useful without vague "(anonymous)".
47
+ */
48
+ static shapeOwnerLabel(shapeClass, nodeShape) {
49
+ var _a;
50
+ const n = (_a = shapeClass.name) === null || _a === void 0 ? void 0 : _a.trim();
51
+ if (n) {
52
+ return n;
53
+ }
54
+ const sid = nodeShape.id;
55
+ if (sid) {
56
+ return `<shape ${sid}>`;
57
+ }
58
+ return '(unknown-class)';
59
+ }
60
+ static listPropertyShapesSafe(nodeShape, ownerClassName, context) {
61
+ var _a;
62
+ const raw = nodeShape
63
+ .propertyShapes;
64
+ if (Array.isArray(raw)) {
65
+ return raw;
66
+ }
67
+ const id = (_a = nodeShape.id) !== null && _a !== void 0 ? _a : '';
68
+ const key = `${ownerClassName}:${String(id)}`;
69
+ if (!NodeShape._warnedMissingPropertyShapesKeys.has(key)) {
70
+ NodeShape._warnedMissingPropertyShapesKeys.add(key);
71
+ console.warn(`[@_linked/core] '${ownerClassName}' static shape has missing or invalid propertyShapes ` +
72
+ `(${context}). Treating as []. Often caused by duplicate @linked/core installs or a ` +
73
+ `non-normalized static shape on a superclass.`);
74
+ }
75
+ return [];
76
+ }
39
77
  constructor(node) {
40
78
  super(node);
41
79
  this.propertyShapes = [];
@@ -58,15 +96,19 @@ export class NodeShape extends Shape {
58
96
  }
59
97
  getPropertyShapes(includeSuperClasses = false) {
60
98
  if (!includeSuperClasses) {
61
- return [...this.propertyShapes];
99
+ const own = this
100
+ .propertyShapes;
101
+ return Array.isArray(own) ? [...own] : [];
62
102
  }
63
103
  const res = [];
64
104
  let shapeClass = getShapeClass(this.id);
65
105
  if (!shapeClass) {
66
- return [...this.propertyShapes];
106
+ const own = this
107
+ .propertyShapes;
108
+ return Array.isArray(own) ? [...own] : [];
67
109
  }
68
110
  while (shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.shape) {
69
- res.push(...shapeClass.shape.propertyShapes);
111
+ res.push(...NodeShape.listPropertyShapesSafe(shapeClass.shape, NodeShape.shapeOwnerLabel(shapeClass, shapeClass.shape), 'getPropertyShapes(includeSuperClasses=true)'));
70
112
  // Stop at Shape base class. Cast needed: ShapeConstructor (concrete new) vs
71
113
  // typeof Shape (abstract new) are structurally incompatible for ===.
72
114
  if (shapeClass === Shape) {
@@ -91,10 +133,14 @@ export class NodeShape extends Shape {
91
133
  let shapeClass = getShapeClass(this.id);
92
134
  let res;
93
135
  if (!shapeClass) {
94
- return this.propertyShapes.find((shape) => shape.label === label);
136
+ const own = this
137
+ .propertyShapes;
138
+ return Array.isArray(own)
139
+ ? own.find((shape) => shape.label === label)
140
+ : undefined;
95
141
  }
96
142
  while (!res && (shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.shape)) {
97
- res = shapeClass.shape.propertyShapes.find((shape) => shape.label === label);
143
+ res = NodeShape.listPropertyShapesSafe(shapeClass.shape, NodeShape.shapeOwnerLabel(shapeClass, shapeClass.shape), 'getPropertyShape').find((shape) => shape.label === label);
98
144
  if (checkSubShapes) {
99
145
  if (shapeClass === Shape) {
100
146
  break;
@@ -115,6 +161,8 @@ export class NodeShape extends Shape {
115
161
  }
116
162
  }
117
163
  NodeShape.targetClass = shacl.NodeShape;
164
+ /** One-time keys for missing/invalid `propertyShapes` on superclass static `shape`. */
165
+ NodeShape._warnedMissingPropertyShapesKeys = new Set();
118
166
  export class PropertyShape extends Shape {
119
167
  constructor() {
120
168
  super();