ldkit 2.6.0 → 2.7.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.
@@ -1,5 +1,5 @@
1
1
  import { dbo, dc, dcterms, foaf, gr, ldkit, owl, rdf, rdfs, schema, sioc, skos, xsd, } from "../namespaces.js";
2
- const NAMESPACES = [
2
+ export const NAMESPACES = [
3
3
  dbo,
4
4
  dc,
5
5
  dcterms,
@@ -14,12 +14,12 @@ const NAMESPACES = [
14
14
  skos,
15
15
  xsd,
16
16
  ];
17
- export function schemaToScript(schemas) {
18
- const printer = new SchemaPrinter();
17
+ export function schemaToScript(schemas, extraNamespaces = [], options = {}) {
18
+ const printer = new SchemaPrinter(extraNamespaces, options);
19
19
  return printer.print(schemas);
20
20
  }
21
21
  class SchemaPrinter {
22
- constructor() {
22
+ constructor(extraNamespaces = [], options = {}) {
23
23
  Object.defineProperty(this, "usedNamespaces", {
24
24
  enumerable: true,
25
25
  configurable: true,
@@ -32,6 +32,68 @@ class SchemaPrinter {
32
32
  writable: true,
33
33
  value: " "
34
34
  });
35
+ // Sorted by IRI length desc so longer prefixes match before shorter ones.
36
+ Object.defineProperty(this, "extraNamespaces", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: void 0
41
+ });
42
+ Object.defineProperty(this, "extraNamespaceTerms", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: new Map()
47
+ });
48
+ Object.defineProperty(this, "shadowedBuiltins", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: void 0
53
+ });
54
+ Object.defineProperty(this, "schemaLocations", {
55
+ enumerable: true,
56
+ configurable: true,
57
+ writable: true,
58
+ value: void 0
59
+ });
60
+ Object.defineProperty(this, "currentFile", {
61
+ enumerable: true,
62
+ configurable: true,
63
+ writable: true,
64
+ value: void 0
65
+ });
66
+ Object.defineProperty(this, "extraNamespaceFiles", {
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true,
70
+ value: void 0
71
+ });
72
+ Object.defineProperty(this, "extraNamespaceTermsOverride", {
73
+ enumerable: true,
74
+ configurable: true,
75
+ writable: true,
76
+ value: void 0
77
+ });
78
+ Object.defineProperty(this, "extraNamespacesImportFrom", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ Object.defineProperty(this, "crossFileImports", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: new Map()
89
+ });
90
+ this.extraNamespaces = [...extraNamespaces].sort((a, b) => b.iri.length - a.iri.length);
91
+ this.shadowedBuiltins = new Set(this.extraNamespaces.map((ns) => ns.prefix));
92
+ this.schemaLocations = options.schemaLocations ?? new Map();
93
+ this.currentFile = options.currentFile;
94
+ this.extraNamespaceFiles = options.extraNamespaceFiles ?? new Map();
95
+ this.extraNamespaceTermsOverride = options.extraNamespaceTermsOverride;
96
+ this.extraNamespacesImportFrom = options.extraNamespacesImportFrom;
35
97
  }
36
98
  print(schemas) {
37
99
  const orderedSchemas = this.orderSchemasByDependencies(schemas);
@@ -41,18 +103,20 @@ class SchemaPrinter {
41
103
  const printedSchema = this.printSchema(schema);
42
104
  printedSchemas.push(printedSchema);
43
105
  }
44
- if (this.usedNamespaces.size > 0) {
45
- printedSchemas.unshift(this.printImports());
106
+ const header = this.printHeader();
107
+ if (header) {
108
+ printedSchemas.unshift(header);
46
109
  }
47
110
  return printedSchemas.join("\n");
48
111
  }
49
112
  orderSchemasByDependencies(schemas) {
50
113
  const orderedSchemas = [];
51
114
  const processedSchemas = new Set();
115
+ const localNames = new Set(schemas.map((s) => s.name));
52
116
  const dependencies = schemas.map((schema) => {
53
117
  return {
54
118
  schemaName: schema.name,
55
- dependencies: this.getSchemaDependencies(schema),
119
+ dependencies: this.getSchemaDependencies(schema).filter((dep) => localNames.has(dep)),
56
120
  };
57
121
  });
58
122
  let unresolved = schemas.length;
@@ -93,9 +157,25 @@ class SchemaPrinter {
93
157
  this.usedNamespaces.add(this.printPrefix(ldkit));
94
158
  return;
95
159
  }
160
+ for (const ns of this.extraNamespaces) {
161
+ if (value.startsWith(ns.iri)) {
162
+ const localPart = value.substring(ns.iri.length);
163
+ let terms = this.extraNamespaceTerms.get(ns.prefix);
164
+ if (!terms) {
165
+ terms = new Set();
166
+ this.extraNamespaceTerms.set(ns.prefix, terms);
167
+ }
168
+ terms.add(localPart);
169
+ return;
170
+ }
171
+ }
96
172
  for (const namespace of NAMESPACES) {
97
173
  if (value.startsWith(namespace.$iri)) {
98
- this.usedNamespaces.add(this.printPrefix(namespace));
174
+ const name = this.printPrefix(namespace);
175
+ if (this.shadowedBuiltins.has(name)) {
176
+ return;
177
+ }
178
+ this.usedNamespaces.add(name);
99
179
  return;
100
180
  }
101
181
  }
@@ -114,11 +194,88 @@ class SchemaPrinter {
114
194
  }
115
195
  }
116
196
  }
117
- printImports() {
118
- const namespacesString = Array.from(this.usedNamespaces)
119
- .toSorted()
120
- .join(", ");
121
- return `import { ${namespacesString} } from "ldkit/namespaces";\n`;
197
+ trackCrossFileRef(schemaRef) {
198
+ if (!this.currentFile)
199
+ return;
200
+ const refFile = this.schemaLocations.get(schemaRef);
201
+ if (!refFile || refFile === this.currentFile)
202
+ return;
203
+ let names = this.crossFileImports.get(refFile);
204
+ if (!names) {
205
+ names = new Set();
206
+ this.crossFileImports.set(refFile, names);
207
+ }
208
+ names.add(schemaRef);
209
+ }
210
+ printHeader() {
211
+ const lines = [];
212
+ const usedPrefixes = new Set(this.extraNamespaces.map((ns) => ns.prefix))
213
+ .intersection(new Set(this.extraNamespaceTerms.keys()));
214
+ const usedExtras = this.extraNamespaces.filter((ns) => usedPrefixes.has(ns.prefix));
215
+ const declaredExtras = [];
216
+ const importedByFile = new Map();
217
+ if (this.extraNamespacesImportFrom !== undefined) {
218
+ if (usedExtras.length > 0) {
219
+ importedByFile.set(this.extraNamespacesImportFrom, new Set(usedExtras.map((ns) => ns.prefix)));
220
+ }
221
+ }
222
+ else {
223
+ for (const ns of usedExtras) {
224
+ const home = this.extraNamespaceFiles.get(ns.prefix);
225
+ if (!home || !this.currentFile || home === this.currentFile) {
226
+ declaredExtras.push(ns);
227
+ continue;
228
+ }
229
+ let names = importedByFile.get(home);
230
+ if (!names) {
231
+ names = new Set();
232
+ importedByFile.set(home, names);
233
+ }
234
+ names.add(ns.prefix);
235
+ }
236
+ }
237
+ if (declaredExtras.length > 0) {
238
+ lines.push(`import { createNamespace } from "ldkit";`);
239
+ }
240
+ if (this.usedNamespaces.size > 0) {
241
+ const namespacesString = Array.from(this.usedNamespaces)
242
+ .toSorted()
243
+ .join(", ");
244
+ lines.push(`import { ${namespacesString} } from "ldkit/namespaces";`);
245
+ }
246
+ const crossFileEntries = [...this.crossFileImports.entries()]
247
+ .toSorted(([a], [b]) => a.localeCompare(b));
248
+ for (const [file, names] of crossFileEntries) {
249
+ const sortedNames = [...names].toSorted().join(", ");
250
+ lines.push(`import { ${sortedNames} } from "./${file}";`);
251
+ }
252
+ const importedExtraEntries = [...importedByFile.entries()]
253
+ .toSorted(([a], [b]) => a.localeCompare(b));
254
+ for (const [file, prefixes] of importedExtraEntries) {
255
+ const sortedPrefixes = [...prefixes].toSorted().join(", ");
256
+ lines.push(`import { ${sortedPrefixes} } from "./${file}";`);
257
+ }
258
+ if (lines.length > 0) {
259
+ lines.push("");
260
+ }
261
+ for (const ns of declaredExtras) {
262
+ const termSet = this.extraNamespaceTermsOverride?.get(ns.prefix) ??
263
+ this.extraNamespaceTerms.get(ns.prefix);
264
+ const terms = Array.from(termSet).toSorted();
265
+ lines.push(`export const ${ns.prefix} = createNamespace(`);
266
+ lines.push(` {`);
267
+ lines.push(` iri: ${JSON.stringify(ns.iri)},`);
268
+ lines.push(` prefix: ${JSON.stringify(`${ns.prefix}:`)},`);
269
+ lines.push(` terms: [`);
270
+ for (const term of terms) {
271
+ lines.push(` ${JSON.stringify(term)},`);
272
+ }
273
+ lines.push(` ],`);
274
+ lines.push(` } as const,`);
275
+ lines.push(`);`);
276
+ lines.push("");
277
+ }
278
+ return lines.join("\n");
122
279
  }
123
280
  printSchema(schema) {
124
281
  const type = this.printType(schema);
@@ -167,6 +324,7 @@ class SchemaPrinter {
167
324
  builder.push(this.indent(subSchema));
168
325
  }
169
326
  else if (prop.schemaRef) {
327
+ this.trackCrossFileRef(prop.schemaRef);
170
328
  builder.push(this.indent(`"@schema": ${prop.schemaRef},`));
171
329
  }
172
330
  const flags = ["optional", "array", "multilang", "inverse"];
@@ -198,13 +356,29 @@ class SchemaPrinter {
198
356
  if (value === "@id") {
199
357
  return `${this.printPrefix(ldkit)}.IRI`;
200
358
  }
359
+ for (const ns of this.extraNamespaces) {
360
+ if (value.startsWith(ns.iri)) {
361
+ const localPart = value.substring(ns.iri.length);
362
+ return this.formatNamespaceAccess(ns.prefix, localPart);
363
+ }
364
+ }
201
365
  for (const namespace of NAMESPACES) {
202
366
  if (value.startsWith(namespace.$iri)) {
203
- return `${this.printPrefix(namespace)}.${value.substring(namespace.$iri.length)}`;
367
+ const name = this.printPrefix(namespace);
368
+ if (this.shadowedBuiltins.has(name)) {
369
+ return `"${value}"`;
370
+ }
371
+ return `${name}.${value.substring(namespace.$iri.length)}`;
204
372
  }
205
373
  }
206
374
  return `"${value}"`;
207
375
  }
376
+ formatNamespaceAccess(prefix, localPart) {
377
+ if (/^[A-Za-z_$]\w*$/.test(localPart)) {
378
+ return `${prefix}.${localPart}`;
379
+ }
380
+ return `${prefix}["${localPart}"]`;
381
+ }
208
382
  printKey(key) {
209
383
  if (key.match(/^[a-zA-Z0-9_]+$/)) {
210
384
  return key;
@@ -0,0 +1,11 @@
1
+ import { type ExtraNamespace, type SchemaSpec } from "./schema_to_script.js";
2
+ export type ShaclConversionResult = {
3
+ schemas: SchemaSpec[];
4
+ extraNamespaces: ExtraNamespace[];
5
+ schemaSourcePrefixes: Map<string, string>;
6
+ };
7
+ export type ShaclConversionOptions = {
8
+ prefixAliases?: Record<string, string>;
9
+ };
10
+ export declare function shaclToSchema(turtle: string, options?: ShaclConversionOptions): ShaclConversionResult;
11
+ //# sourceMappingURL=shacl_to_schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shacl_to_schema.d.ts","sourceRoot":"","sources":["../../src/scripts/shacl_to_schema.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EAGnB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAkE/B,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAGvB"}