@twin.org/ts-to-jsonld-context 0.0.3-next.6 → 0.0.3-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -116
- package/dist/es/cli.js +1 -1
- package/dist/es/cli.js.map +1 -1
- package/dist/es/commands/tsToJsonLdContext.js +73 -39
- package/dist/es/commands/tsToJsonLdContext.js.map +1 -1
- package/dist/es/models/IJsonLdProps.js.map +1 -1
- package/dist/locales/en.json +2 -1
- package/dist/types/models/IJsonLdProps.d.ts +5 -2
- package/docs/changelog.md +14 -0
- package/docs/examples.md +152 -0
- package/locales/en.json +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,122 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
This tool is used to convert TypeScript definitions to JSON-LD Contexts.
|
|
4
4
|
|
|
5
|
-
Reads the comments from the model properties to generate the definitions.
|
|
6
|
-
|
|
7
|
-
## Types
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
/**
|
|
11
|
-
* The index of the entry.
|
|
12
|
-
* json-ld type:schema:Integer
|
|
13
|
-
*/
|
|
14
|
-
index: number;
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
will produce
|
|
18
|
-
|
|
19
|
-
```json
|
|
20
|
-
"index": {
|
|
21
|
-
"@id": "twin-ais:index",
|
|
22
|
-
"@type": "schema:Integer"
|
|
23
|
-
},
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
/**
|
|
28
|
-
* The object to associate with the entry as JSON-LD.
|
|
29
|
-
* json-ld type:json
|
|
30
|
-
*/
|
|
31
|
-
entryObject: IJsonLdNodeObject;
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
will produce
|
|
35
|
-
|
|
36
|
-
```json
|
|
37
|
-
"entryObject": {
|
|
38
|
-
"@id": "twin-ais:entryObject",
|
|
39
|
-
"@type": "@json"
|
|
40
|
-
},
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Namespace
|
|
44
|
-
|
|
45
|
-
If the property refers to an external namespace defined in the config, property is not included in the output:
|
|
46
|
-
|
|
47
|
-
```ts
|
|
48
|
-
/**
|
|
49
|
-
* The identity of the user which added the entry to the stream.
|
|
50
|
-
* json-ld namespace:twin-common
|
|
51
|
-
*/
|
|
52
|
-
userIdentity?: string;
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Containers
|
|
56
|
-
|
|
57
|
-
For a container type:
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
/**
|
|
61
|
-
* Entries in the stream.
|
|
62
|
-
* json-ld container:set
|
|
63
|
-
*/
|
|
64
|
-
entries?: IAuditableItemStreamEntry[];
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
produces
|
|
68
|
-
|
|
69
|
-
```json
|
|
70
|
-
"entries": {
|
|
71
|
-
"@id": "twin-ais:entries",
|
|
72
|
-
"@container": "@set"
|
|
73
|
-
},
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Plain ID Mapping
|
|
77
|
-
|
|
78
|
-
For a plain id mapping:
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
/**
|
|
82
|
-
* Entries in the stream.
|
|
83
|
-
* json-ld id
|
|
84
|
-
*/
|
|
85
|
-
foo: unknown;
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
produces
|
|
89
|
-
|
|
90
|
-
```json
|
|
91
|
-
"foo": {
|
|
92
|
-
"@id": "twin-ais:foo"
|
|
93
|
-
},
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Example Config
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"prefix": "twin-ais",
|
|
101
|
-
"contextUrl": "https://schema.twindev.org/ais/",
|
|
102
|
-
"additionalContextUrls": {
|
|
103
|
-
"twin-common": "https://schema.twindev.org/common/",
|
|
104
|
-
"twin-immutable-proof": "https://schema.twindev.org/immutable-proof/",
|
|
105
|
-
"schema": "http://schema.org/"
|
|
106
|
-
},
|
|
107
|
-
"fixedMappings": {
|
|
108
|
-
"id": "@id",
|
|
109
|
-
"type": "@type"
|
|
110
|
-
},
|
|
111
|
-
"types": [
|
|
112
|
-
"./src/models/IAuditableItemStream.ts",
|
|
113
|
-
"./src/models/IAuditableItemStreamList.ts",
|
|
114
|
-
"./src/models/IAuditableItemStreamEntry.ts",
|
|
115
|
-
"./src/models/IAuditableItemStreamEntryList.ts",
|
|
116
|
-
"./src/models/IAuditableItemStreamEntryObjectList.ts"
|
|
117
|
-
]
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
5
|
## Installation
|
|
122
6
|
|
|
123
7
|
```shell
|
package/dist/es/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ export class CLI extends CLIBase {
|
|
|
20
20
|
return this.execute({
|
|
21
21
|
title: "TWIN TypeScript To JSON-LD Context",
|
|
22
22
|
appName: "ts-to-jsonld-context",
|
|
23
|
-
version: "0.0.3-next.
|
|
23
|
+
version: "0.0.3-next.7", // x-release-please-version
|
|
24
24
|
icon: "⚙️ ",
|
|
25
25
|
supportsEnvFiles: false,
|
|
26
26
|
overrideOutputWidth: options?.overrideOutputWidth
|
package/dist/es/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAEhF;;GAEG;AACH,MAAM,OAAO,GAAI,SAAQ,OAAO;IAC/B;;;;;;;OAOG;IACI,KAAK,CAAC,GAAG,CACf,IAAc,EACd,gBAAyB,EACzB,OAA0C;QAE1C,OAAO,IAAI,CAAC,OAAO,CAClB;YACC,KAAK,EAAE,oCAAoC;YAC3C,OAAO,EAAE,sBAAsB;YAC/B,OAAO,EAAE,cAAc,EAAE,2BAA2B;YACpD,IAAI,EAAE,KAAK;YACX,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;SACjD,EACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EACzF,IAAI,CACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,OAAgB;QACvC,6BAA6B,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACD","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { CLIBase } from \"@twin.org/cli-core\";\nimport type { Command } from \"commander\";\nimport { buildCommandTsToJsonLdContext } from \"./commands/tsToJsonLdContext.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport class CLI extends CLIBase {\n\t/**\n\t * Run the app.\n\t * @param argv The process arguments.\n\t * @param localesDirectory The directory for the locales, default to relative to the script.\n\t * @param options Additional options.\n\t * @param options.overrideOutputWidth Override the output width.\n\t * @returns The exit code.\n\t */\n\tpublic async run(\n\t\targv: string[],\n\t\tlocalesDirectory?: string,\n\t\toptions?: { overrideOutputWidth?: number }\n\t): Promise<number> {\n\t\treturn this.execute(\n\t\t\t{\n\t\t\t\ttitle: \"TWIN TypeScript To JSON-LD Context\",\n\t\t\t\tappName: \"ts-to-jsonld-context\",\n\t\t\t\tversion: \"0.0.3-next.
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAEhF;;GAEG;AACH,MAAM,OAAO,GAAI,SAAQ,OAAO;IAC/B;;;;;;;OAOG;IACI,KAAK,CAAC,GAAG,CACf,IAAc,EACd,gBAAyB,EACzB,OAA0C;QAE1C,OAAO,IAAI,CAAC,OAAO,CAClB;YACC,KAAK,EAAE,oCAAoC;YAC3C,OAAO,EAAE,sBAAsB;YAC/B,OAAO,EAAE,cAAc,EAAE,2BAA2B;YACpD,IAAI,EAAE,KAAK;YACX,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;SACjD,EACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EACzF,IAAI,CACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,OAAgB;QACvC,6BAA6B,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACD","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { CLIBase } from \"@twin.org/cli-core\";\nimport type { Command } from \"commander\";\nimport { buildCommandTsToJsonLdContext } from \"./commands/tsToJsonLdContext.js\";\n\n/**\n * The main entry point for the CLI.\n */\nexport class CLI extends CLIBase {\n\t/**\n\t * Run the app.\n\t * @param argv The process arguments.\n\t * @param localesDirectory The directory for the locales, default to relative to the script.\n\t * @param options Additional options.\n\t * @param options.overrideOutputWidth Override the output width.\n\t * @returns The exit code.\n\t */\n\tpublic async run(\n\t\targv: string[],\n\t\tlocalesDirectory?: string,\n\t\toptions?: { overrideOutputWidth?: number }\n\t): Promise<number> {\n\t\treturn this.execute(\n\t\t\t{\n\t\t\t\ttitle: \"TWIN TypeScript To JSON-LD Context\",\n\t\t\t\tappName: \"ts-to-jsonld-context\",\n\t\t\t\tversion: \"0.0.3-next.7\", // x-release-please-version\n\t\t\t\ticon: \"⚙️ \",\n\t\t\t\tsupportsEnvFiles: false,\n\t\t\t\toverrideOutputWidth: options?.overrideOutputWidth\n\t\t\t},\n\t\t\tlocalesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), \"../locales\"),\n\t\t\targv\n\t\t);\n\t}\n\n\t/**\n\t * Configure any options or actions at the root program level.\n\t * @param program The root program command.\n\t */\n\tprotected configureRoot(program: Command): void {\n\t\tbuildCommandTsToJsonLdContext(program);\n\t}\n}\n"]}
|
|
@@ -75,13 +75,25 @@ export async function tsToJsonLdContext(config, outputFile) {
|
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
77
|
finalObject["@context"][config.prefix] = config.contextUrl;
|
|
78
|
+
const usedNamespaces = ObjectHelper.clone(context.namespaces);
|
|
79
|
+
const idx = usedNamespaces.indexOf(config.prefix);
|
|
80
|
+
if (idx !== -1) {
|
|
81
|
+
usedNamespaces.splice(idx, 1);
|
|
82
|
+
}
|
|
78
83
|
if (Is.objectValue(config.additionalContextUrls)) {
|
|
79
84
|
for (const [key, value] of Object.entries(config.additionalContextUrls)) {
|
|
80
85
|
if (context.namespaces.includes(key)) {
|
|
81
86
|
finalObject["@context"][key] = value;
|
|
87
|
+
const idx2 = usedNamespaces.indexOf(key);
|
|
88
|
+
usedNamespaces.splice(idx2, 1);
|
|
82
89
|
}
|
|
83
90
|
}
|
|
84
91
|
}
|
|
92
|
+
if (usedNamespaces.length > 0) {
|
|
93
|
+
throw new GeneralError("commands", "commands.ts-to-jsonld-context.namespaceNotInConfig", {
|
|
94
|
+
namespaces: usedNamespaces.join(", ")
|
|
95
|
+
});
|
|
96
|
+
}
|
|
85
97
|
if (Is.objectValue(config.fixedMappings)) {
|
|
86
98
|
for (const [key, value] of Object.entries(config.fixedMappings)) {
|
|
87
99
|
finalObject["@context"][key] = value;
|
|
@@ -129,33 +141,41 @@ function visit(config, node, sourceFile, context, program, processedTypes) {
|
|
|
129
141
|
propertyName
|
|
130
142
|
});
|
|
131
143
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
const contextInfo = {};
|
|
145
|
+
const usedNamespaces = [];
|
|
146
|
+
if (Is.objectValue(jsonLdProps.propertyId)) {
|
|
147
|
+
usedNamespaces.push(jsonLdProps.propertyId.namespace);
|
|
148
|
+
contextInfo["@id"] =
|
|
149
|
+
`${jsonLdProps.propertyId.namespace ?? config.prefix}:${jsonLdProps.propertyId.id}`;
|
|
150
|
+
}
|
|
151
|
+
else if (Is.object(jsonLdProps.propertyId)) {
|
|
152
|
+
contextInfo["@id"] = `${config.prefix}:${propertyName}`;
|
|
135
153
|
}
|
|
154
|
+
usedNamespaces.push(jsonLdProps.namespace);
|
|
136
155
|
if (Is.objectValue(jsonLdProps.propertyType)) {
|
|
137
156
|
let fullType = jsonLdProps.propertyType.type === "json" ? "@json" : jsonLdProps.propertyType.type;
|
|
138
157
|
if (Is.stringValue(jsonLdProps.propertyType.namespace)) {
|
|
139
158
|
fullType = `${jsonLdProps.propertyType.namespace}:${jsonLdProps.propertyType.type}`;
|
|
140
|
-
|
|
141
|
-
context.namespaces.push(jsonLdProps.propertyType.namespace);
|
|
142
|
-
}
|
|
159
|
+
usedNamespaces.push(jsonLdProps.propertyType.namespace);
|
|
143
160
|
}
|
|
144
|
-
|
|
145
|
-
"@id"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
else if (Is.boolean(jsonLdProps.idOnly)) {
|
|
150
|
-
context.properties[propertyName] = {
|
|
151
|
-
"@id": `${config.prefix}:${propertyName}`
|
|
152
|
-
};
|
|
161
|
+
if (!Is.stringValue(contextInfo["@id"])) {
|
|
162
|
+
contextInfo["@id"] = `${config.prefix}:${propertyName}`;
|
|
163
|
+
}
|
|
164
|
+
contextInfo["@type"] = fullType;
|
|
153
165
|
}
|
|
154
166
|
if (Is.stringValue(jsonLdProps.container)) {
|
|
155
|
-
|
|
156
|
-
"@id"
|
|
157
|
-
|
|
158
|
-
}
|
|
167
|
+
if (!Is.stringValue(contextInfo["@id"])) {
|
|
168
|
+
contextInfo["@id"] = `${config.prefix}:${propertyName}`;
|
|
169
|
+
}
|
|
170
|
+
contextInfo["@container"] = `@${jsonLdProps.container}`;
|
|
171
|
+
}
|
|
172
|
+
if (Is.objectValue(contextInfo)) {
|
|
173
|
+
context.properties[propertyName] = contextInfo;
|
|
174
|
+
}
|
|
175
|
+
for (const ns of usedNamespaces) {
|
|
176
|
+
if (Is.stringValue(ns) && !context.namespaces.includes(ns)) {
|
|
177
|
+
context.namespaces.push(ns);
|
|
178
|
+
}
|
|
159
179
|
}
|
|
160
180
|
CLIDisplay.value(I18n.formatMessage("commands.ts-to-jsonld-context.labels.property"), propertyName, 1);
|
|
161
181
|
}
|
|
@@ -229,34 +249,48 @@ function extractComments(member) {
|
|
|
229
249
|
function extractJsonLdProps(comments) {
|
|
230
250
|
const jsonLdProps = {};
|
|
231
251
|
for (const comment of comments) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
jsonLdProps.idOnly = true;
|
|
252
|
+
if (/^json-ld id$/.exec(comment)) {
|
|
253
|
+
jsonLdProps.propertyId = {};
|
|
235
254
|
}
|
|
236
255
|
else {
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
239
|
-
jsonLdProps.
|
|
256
|
+
const idWithNamespaceAndType = /^json-ld id:(.*):(.*)$/.exec(comment);
|
|
257
|
+
if (idWithNamespaceAndType) {
|
|
258
|
+
jsonLdProps.propertyId = {
|
|
259
|
+
namespace: idWithNamespaceAndType[1],
|
|
260
|
+
id: idWithNamespaceAndType[2]
|
|
261
|
+
};
|
|
240
262
|
}
|
|
241
263
|
else {
|
|
242
|
-
const
|
|
243
|
-
if (
|
|
244
|
-
jsonLdProps.
|
|
264
|
+
const idMatch = /^json-ld id:(.*)$/.exec(comment);
|
|
265
|
+
if (idMatch) {
|
|
266
|
+
jsonLdProps.propertyId = { id: idMatch[1] };
|
|
245
267
|
}
|
|
246
268
|
else {
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
jsonLdProps.
|
|
250
|
-
namespace: typeMatch[1],
|
|
251
|
-
type: typeMatch[2]
|
|
252
|
-
};
|
|
269
|
+
const namespaceMatch = /^json-ld namespace:(.*)/.exec(comment);
|
|
270
|
+
if (namespaceMatch) {
|
|
271
|
+
jsonLdProps.namespace = namespaceMatch[1];
|
|
253
272
|
}
|
|
254
273
|
else {
|
|
255
|
-
const
|
|
256
|
-
if (
|
|
257
|
-
jsonLdProps.
|
|
258
|
-
|
|
259
|
-
|
|
274
|
+
const containerMatch = /^json-ld container:(.*)$/.exec(comment);
|
|
275
|
+
if (containerMatch) {
|
|
276
|
+
jsonLdProps.container = containerMatch[1];
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
const typeMatch = /^json-ld type:(.*):(.*)$/.exec(comment);
|
|
280
|
+
if (typeMatch) {
|
|
281
|
+
jsonLdProps.propertyType = {
|
|
282
|
+
namespace: typeMatch[1],
|
|
283
|
+
type: typeMatch[2]
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
const typeMatch2 = /^json-ld type:(.*)$/.exec(comment);
|
|
288
|
+
if (typeMatch2) {
|
|
289
|
+
jsonLdProps.propertyType = {
|
|
290
|
+
type: typeMatch2[1]
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
260
294
|
}
|
|
261
295
|
}
|
|
262
296
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsToJsonLdContext.js","sourceRoot":"","sources":["../../../src/commands/tsToJsonLdContext.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { GeneralError, I18n, Is, ObjectHelper, StringHelper } from \"@twin.org/core\";\nimport type { Command } from \"commander\";\nimport ts from \"typescript\";\nimport type { IJsonLdProps } from \"../models/IJsonLdProps.js\";\nimport type { ITsToJsonLdContextConfig } from \"../models/ITsToJsonLdContextConfig.js\";\n\n/**\n * Build the root command to be consumed by the CLI.\n * @param program The command to build on.\n */\nexport function buildCommandTsToJsonLdContext(program: Command): void {\n\tprogram\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.config.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.config.description\")\n\t\t)\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.output-file.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.output-file.description\")\n\t\t)\n\t\t.action(async (config, outputFile, opts) => {\n\t\t\tawait actionCommandTsToJsonLdContext(config, outputFile, opts);\n\t\t});\n}\n\n/**\n * Action the root command.\n * @param configFile The optional configuration file.\n * @param outputFile The output file for the schema.\n * @param opts The options for the command.\n */\nexport async function actionCommandTsToJsonLdContext(\n\tconfigFile: string,\n\toutputFile: string,\n\topts: unknown\n): Promise<void> {\n\tlet config: ITsToJsonLdContextConfig | undefined;\n\n\tconst fullConfigFile = path.resolve(configFile);\n\tconst fullOutputFile = path.resolve(outputFile);\n\n\tCLIDisplay.value(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.configJson\"),\n\t\tfullConfigFile\n\t);\n\tCLIDisplay.value(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.outputFile\"),\n\t\tfullOutputFile\n\t);\n\tCLIDisplay.break();\n\n\ttry {\n\t\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-jsonld-context.progress.loadingConfigJson\"));\n\t\tCLIDisplay.break();\n\n\t\tconfig = await CLIUtils.readJsonFile<ITsToJsonLdContextConfig>(fullConfigFile);\n\t} catch (err) {\n\t\tthrow new GeneralError(\n\t\t\t\"commands\",\n\t\t\t\"commands.ts-to-jsonld-context.configFailed\",\n\t\t\tundefined,\n\t\t\terr\n\t\t);\n\t}\n\n\tif (Is.empty(config)) {\n\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-jsonld-context.configFailed\");\n\t}\n\n\tCLIDisplay.break();\n\n\tawait tsToJsonLdContext(config ?? {}, fullOutputFile);\n\n\tCLIDisplay.break();\n\tCLIDisplay.done();\n}\n\n/**\n * Convert the TypeScript definitions to JSON-LD Contexts.\n * @param config The configuration for the app.\n * @param outputFile The output file for the schema.\n */\nexport async function tsToJsonLdContext(\n\tconfig: ITsToJsonLdContextConfig,\n\toutputFile: string\n): Promise<void> {\n\tconst program = ts.createProgram(config.types, {});\n\tconst context: { types: string[]; namespaces: string[]; properties: { [id: string]: unknown } } =\n\t\t{\n\t\t\ttypes: [],\n\t\t\tnamespaces: [],\n\t\t\tproperties: {}\n\t\t};\n\n\tconst processedTypes: { [typeName: string]: IJsonLdProps } = {};\n\n\t// Walk the AST for each source file\n\tfor (const sourceFile of program.getSourceFiles()) {\n\t\tconst resolvedFilename = path.resolve(sourceFile.fileName);\n\t\tif (config.types.some(file => resolvedFilename.endsWith(path.resolve(file)))) {\n\t\t\tCLIDisplay.task(\"Processing\", resolvedFilename);\n\n\t\t\tvisit(config, sourceFile, sourceFile, context, program, processedTypes);\n\t\t\tCLIDisplay.break();\n\t\t}\n\t}\n\n\tconst finalObject: {\n\t\t\"@context\": { [key: string]: unknown; \"@version\": number; \"@protected\": boolean };\n\t} = {\n\t\t\"@context\": {\n\t\t\t\"@version\": 1.1,\n\t\t\t\"@protected\": true\n\t\t}\n\t};\n\n\tfinalObject[\"@context\"][config.prefix] = config.contextUrl;\n\n\tif (Is.objectValue(config.additionalContextUrls)) {\n\t\tfor (const [key, value] of Object.entries(config.additionalContextUrls)) {\n\t\t\tif (context.namespaces.includes(key)) {\n\t\t\t\tfinalObject[\"@context\"][key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Is.objectValue(config.fixedMappings)) {\n\t\tfor (const [key, value] of Object.entries(config.fixedMappings)) {\n\t\t\tfinalObject[\"@context\"][key] = value;\n\t\t}\n\t}\n\n\tfor (const typeName of context.types) {\n\t\tconst noPrefixType = StringHelper.stripPrefix(typeName);\n\t\tfinalObject[\"@context\"][noPrefixType] = `${config.prefix}:${noPrefixType}`;\n\t}\n\n\tfor (const [propertyName, propertyValue] of Object.entries(context.properties).sort((a, b) =>\n\t\ta[0].localeCompare(b[0])\n\t)) {\n\t\tfinalObject[\"@context\"][propertyName] = propertyValue;\n\t}\n\n\tCLIDisplay.break();\n\tCLIDisplay.task(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.writingOutputFile\"),\n\t\toutputFile\n\t);\n\tawait writeFile(outputFile, `${JSON.stringify(finalObject, null, 2)}\\n`);\n}\n\n/**\n * Visit a node in the AST.\n * @param config The configuration for the app.\n * @param node The node to visit.\n * @param sourceFile The source file being processed.\n * @param context The JSON-LD context being built.\n * @param context.types The types collected in the context.\n * @param context.namespaces The namespaces collected in the context.\n * @param context.properties The properties collected in the context.\n * @param program The TypeScript program for resolving inherited interfaces.\n * @param processedTypes The types that have already been processed.\n */\nfunction visit(\n\tconfig: ITsToJsonLdContextConfig,\n\tnode: ts.Node,\n\tsourceFile: ts.SourceFile,\n\tcontext: { types: string[]; namespaces: string[]; properties: { [id: string]: unknown } },\n\tprogram: ts.Program,\n\tprocessedTypes: { [typeName: string]: IJsonLdProps }\n): void {\n\tlet jsonLdProps: IJsonLdProps = {};\n\n\t// Handle different node types\n\tif (ts.isInterfaceDeclaration(node)) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.model\"),\n\t\t\tnode.name.text\n\t\t);\n\t\tcontext.types.push(node.name.text);\n\n\t\tif (Is.array(node.members)) {\n\t\t\tnode.members.forEach(member => {\n\t\t\t\tif (ts.isPropertySignature(member)) {\n\t\t\t\t\tconst propertyName = member.name?.getText(sourceFile).replace(/[\"']/g, \"\");\n\n\t\t\t\t\tif (Is.stringValue(propertyName)) {\n\t\t\t\t\t\tconst jsDocComments: string[] = extractComments(member);\n\n\t\t\t\t\t\tjsonLdProps = extractJsonLdProps(jsDocComments);\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t![\"@context\", \"type\", \"id\"].includes(propertyName) &&\n\t\t\t\t\t\t\t!Is.objectValue(jsonLdProps)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-jsonld-context.noJsonLdProps\", {\n\t\t\t\t\t\t\t\tpropertyName\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tIs.stringValue(jsonLdProps.namespace) &&\n\t\t\t\t\t\t\t!context.namespaces.includes(jsonLdProps.namespace)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcontext.namespaces.push(jsonLdProps.namespace);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Is.objectValue(jsonLdProps.propertyType)) {\n\t\t\t\t\t\t\tlet fullType =\n\t\t\t\t\t\t\t\tjsonLdProps.propertyType.type === \"json\" ? \"@json\" : jsonLdProps.propertyType.type;\n\t\t\t\t\t\t\tif (Is.stringValue(jsonLdProps.propertyType.namespace)) {\n\t\t\t\t\t\t\t\tfullType = `${jsonLdProps.propertyType.namespace}:${jsonLdProps.propertyType.type}`;\n\n\t\t\t\t\t\t\t\tif (!context.namespaces.includes(jsonLdProps.propertyType.namespace)) {\n\t\t\t\t\t\t\t\t\tcontext.namespaces.push(jsonLdProps.propertyType.namespace);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcontext.properties[propertyName] = {\n\t\t\t\t\t\t\t\t\"@id\": `${config.prefix}:${propertyName}`,\n\t\t\t\t\t\t\t\t\"@type\": fullType\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (Is.boolean(jsonLdProps.idOnly)) {\n\t\t\t\t\t\t\tcontext.properties[propertyName] = {\n\t\t\t\t\t\t\t\t\"@id\": `${config.prefix}:${propertyName}`\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Is.stringValue(jsonLdProps.container)) {\n\t\t\t\t\t\t\tcontext.properties[propertyName] = {\n\t\t\t\t\t\t\t\t\"@id\": `${config.prefix}:${propertyName}`,\n\t\t\t\t\t\t\t\t\"@container\": `@${jsonLdProps.container}`\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tCLIDisplay.value(\n\t\t\t\t\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.property\"),\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t\t1\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tprocessedTypes[node.name.text] = jsonLdProps;\n\n\t\tif (node.heritageClauses) {\n\t\t\tfor (const clause of node.heritageClauses) {\n\t\t\t\tif (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n\t\t\t\t\tfor (const type of clause.types) {\n\t\t\t\t\t\tconst inheritedInterfaceName = extractBaseInterfaceName(type, sourceFile);\n\n\t\t\t\t\t\tif (!processedTypes[inheritedInterfaceName]) {\n\t\t\t\t\t\t\tconst result = findInterfaceByName(inheritedInterfaceName, program);\n\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\tvisit(\n\t\t\t\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t\t\t\tresult.interfaceDeclaration,\n\t\t\t\t\t\t\t\t\tresult.sourceFile,\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tprogram,\n\t\t\t\t\t\t\t\t\tprocessedTypes\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tts.forEachChild(node, child =>\n\t\tvisit(config, child, sourceFile, context, program, processedTypes)\n\t);\n}\n\n/**\n * Find an interface by name in the program.\n * @param interfaceName The name of the interface to find.\n * @param program The TypeScript program.\n * @returns The found interface declaration with its source file or undefined.\n */\nfunction findInterfaceByName(\n\tinterfaceName: string,\n\tprogram: ts.Program\n): { interfaceDeclaration: ts.InterfaceDeclaration; sourceFile: ts.SourceFile } | undefined {\n\tfor (const sourceFile of program.getSourceFiles()) {\n\t\tlet foundInterface: ts.InterfaceDeclaration | undefined;\n\n\t\tts.forEachChild(sourceFile, node => {\n\t\t\tif (ts.isInterfaceDeclaration(node) && node.name.text === interfaceName) {\n\t\t\t\tfoundInterface = node;\n\t\t\t}\n\t\t});\n\n\t\tif (foundInterface) {\n\t\t\treturn { interfaceDeclaration: foundInterface, sourceFile };\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Extract JSDoc comments from a property signature.\n * @param member The property signature member.\n * @returns The extracted comments.\n */\nfunction extractComments(member: ts.Node): string[] {\n\tconst jsDocComments: string[] = [];\n\tconst jsDocs = ObjectHelper.propertyGet<ts.JSDoc[] | undefined>(member, \"jsDoc\");\n\n\tif (Is.arrayValue(jsDocs)) {\n\t\tfor (const doc of jsDocs) {\n\t\t\tif (Is.string(doc.comment)) {\n\t\t\t\tjsDocComments.push(...doc.comment.split(\"\\n\").map(part => part.trim()));\n\t\t\t} else if (Is.arrayValue<string>(doc.comment)) {\n\t\t\t\tjsDocComments.push(...doc.comment.map(part => part.text));\n\t\t\t}\n\t\t}\n\t}\n\treturn jsDocComments;\n}\n\n/**\n * Extract JSON-LD properties from comments.\n * @param comments The comments to extract from.\n * @returns The extracted JSON-LD properties.\n */\nfunction extractJsonLdProps(comments: string[]): IJsonLdProps {\n\tconst jsonLdProps: IJsonLdProps = {};\n\n\tfor (const comment of comments) {\n\t\tconst idMatch = /json-ld id/.exec(comment);\n\t\tif (idMatch) {\n\t\t\tjsonLdProps.idOnly = true;\n\t\t} else {\n\t\t\tconst namespaceMatch = /json-ld namespace:(.*)/.exec(comment);\n\t\t\tif (namespaceMatch) {\n\t\t\t\tjsonLdProps.namespace = namespaceMatch[1];\n\t\t\t} else {\n\t\t\t\tconst containerMatch = /json-ld container:(.*)/.exec(comment);\n\t\t\t\tif (containerMatch) {\n\t\t\t\t\tjsonLdProps.container = containerMatch[1];\n\t\t\t\t} else {\n\t\t\t\t\tconst typeMatch = /json-ld type:(.*):(.*)/.exec(comment);\n\t\t\t\t\tif (typeMatch) {\n\t\t\t\t\t\tjsonLdProps.propertyType = {\n\t\t\t\t\t\t\tnamespace: typeMatch[1],\n\t\t\t\t\t\t\ttype: typeMatch[2]\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst typeMatch2 = /json-ld type:(.*)/.exec(comment);\n\t\t\t\t\t\tif (typeMatch2) {\n\t\t\t\t\t\t\tjsonLdProps.propertyType = {\n\t\t\t\t\t\t\t\ttype: typeMatch2[1]\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn jsonLdProps;\n}\n\n/**\n * Extract the base interface name from a type reference using the AST.\n * Handles utility types like Omit<InterfaceName, \"deleted\"> by extracting the first type argument.\n * @param type The type reference expression node.\n * @param sourceFile The source file for extracting text.\n * @returns The base interface name.\n */\nfunction extractBaseInterfaceName(type: ts.TypeReferenceType, sourceFile: ts.SourceFile): string {\n\t// Check if it's an expression with type arguments (e.g., Omit<Interface, \"deleted\">)\n\tif (\n\t\tts.isExpressionWithTypeArguments(type) &&\n\t\ttype.typeArguments &&\n\t\ttype.typeArguments.length > 0\n\t) {\n\t\t// Extract the first type argument which should be the interface name\n\t\tconst firstTypeArg = type.typeArguments[0];\n\t\treturn firstTypeArg.getText(sourceFile);\n\t}\n\n\t// Otherwise, treat the whole expression as the interface name\n\treturn type.getText(sourceFile);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tsToJsonLdContext.js","sourceRoot":"","sources":["../../../src/commands/tsToJsonLdContext.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { GeneralError, I18n, Is, ObjectHelper, StringHelper } from \"@twin.org/core\";\nimport type { Command } from \"commander\";\nimport ts from \"typescript\";\nimport type { IJsonLdProps } from \"../models/IJsonLdProps.js\";\nimport type { ITsToJsonLdContextConfig } from \"../models/ITsToJsonLdContextConfig.js\";\n\n/**\n * Build the root command to be consumed by the CLI.\n * @param program The command to build on.\n */\nexport function buildCommandTsToJsonLdContext(program: Command): void {\n\tprogram\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.config.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.config.description\")\n\t\t)\n\t\t.argument(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.output-file.param\"),\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.options.output-file.description\")\n\t\t)\n\t\t.action(async (config, outputFile, opts) => {\n\t\t\tawait actionCommandTsToJsonLdContext(config, outputFile, opts);\n\t\t});\n}\n\n/**\n * Action the root command.\n * @param configFile The optional configuration file.\n * @param outputFile The output file for the schema.\n * @param opts The options for the command.\n */\nexport async function actionCommandTsToJsonLdContext(\n\tconfigFile: string,\n\toutputFile: string,\n\topts: unknown\n): Promise<void> {\n\tlet config: ITsToJsonLdContextConfig | undefined;\n\n\tconst fullConfigFile = path.resolve(configFile);\n\tconst fullOutputFile = path.resolve(outputFile);\n\n\tCLIDisplay.value(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.configJson\"),\n\t\tfullConfigFile\n\t);\n\tCLIDisplay.value(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.outputFile\"),\n\t\tfullOutputFile\n\t);\n\tCLIDisplay.break();\n\n\ttry {\n\t\tCLIDisplay.task(I18n.formatMessage(\"commands.ts-to-jsonld-context.progress.loadingConfigJson\"));\n\t\tCLIDisplay.break();\n\n\t\tconfig = await CLIUtils.readJsonFile<ITsToJsonLdContextConfig>(fullConfigFile);\n\t} catch (err) {\n\t\tthrow new GeneralError(\n\t\t\t\"commands\",\n\t\t\t\"commands.ts-to-jsonld-context.configFailed\",\n\t\t\tundefined,\n\t\t\terr\n\t\t);\n\t}\n\n\tif (Is.empty(config)) {\n\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-jsonld-context.configFailed\");\n\t}\n\n\tCLIDisplay.break();\n\n\tawait tsToJsonLdContext(config ?? {}, fullOutputFile);\n\n\tCLIDisplay.break();\n\tCLIDisplay.done();\n}\n\n/**\n * Convert the TypeScript definitions to JSON-LD Contexts.\n * @param config The configuration for the app.\n * @param outputFile The output file for the schema.\n */\nexport async function tsToJsonLdContext(\n\tconfig: ITsToJsonLdContextConfig,\n\toutputFile: string\n): Promise<void> {\n\tconst program = ts.createProgram(config.types, {});\n\tconst context: { types: string[]; namespaces: string[]; properties: { [id: string]: unknown } } =\n\t\t{\n\t\t\ttypes: [],\n\t\t\tnamespaces: [],\n\t\t\tproperties: {}\n\t\t};\n\n\tconst processedTypes: { [typeName: string]: IJsonLdProps } = {};\n\n\t// Walk the AST for each source file\n\tfor (const sourceFile of program.getSourceFiles()) {\n\t\tconst resolvedFilename = path.resolve(sourceFile.fileName);\n\t\tif (config.types.some(file => resolvedFilename.endsWith(path.resolve(file)))) {\n\t\t\tCLIDisplay.task(\"Processing\", resolvedFilename);\n\n\t\t\tvisit(config, sourceFile, sourceFile, context, program, processedTypes);\n\t\t\tCLIDisplay.break();\n\t\t}\n\t}\n\n\tconst finalObject: {\n\t\t\"@context\": { [key: string]: unknown; \"@version\": number; \"@protected\": boolean };\n\t} = {\n\t\t\"@context\": {\n\t\t\t\"@version\": 1.1,\n\t\t\t\"@protected\": true\n\t\t}\n\t};\n\n\tfinalObject[\"@context\"][config.prefix] = config.contextUrl;\n\n\tconst usedNamespaces: string[] = ObjectHelper.clone(context.namespaces);\n\tconst idx = usedNamespaces.indexOf(config.prefix);\n\tif (idx !== -1) {\n\t\tusedNamespaces.splice(idx, 1);\n\t}\n\n\tif (Is.objectValue(config.additionalContextUrls)) {\n\t\tfor (const [key, value] of Object.entries(config.additionalContextUrls)) {\n\t\t\tif (context.namespaces.includes(key)) {\n\t\t\t\tfinalObject[\"@context\"][key] = value;\n\t\t\t\tconst idx2 = usedNamespaces.indexOf(key);\n\t\t\t\tusedNamespaces.splice(idx2, 1);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (usedNamespaces.length > 0) {\n\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-jsonld-context.namespaceNotInConfig\", {\n\t\t\tnamespaces: usedNamespaces.join(\", \")\n\t\t});\n\t}\n\n\tif (Is.objectValue(config.fixedMappings)) {\n\t\tfor (const [key, value] of Object.entries(config.fixedMappings)) {\n\t\t\tfinalObject[\"@context\"][key] = value;\n\t\t}\n\t}\n\n\tfor (const typeName of context.types) {\n\t\tconst noPrefixType = StringHelper.stripPrefix(typeName);\n\t\tfinalObject[\"@context\"][noPrefixType] = `${config.prefix}:${noPrefixType}`;\n\t}\n\n\tfor (const [propertyName, propertyValue] of Object.entries(context.properties).sort((a, b) =>\n\t\ta[0].localeCompare(b[0])\n\t)) {\n\t\tfinalObject[\"@context\"][propertyName] = propertyValue;\n\t}\n\n\tCLIDisplay.break();\n\tCLIDisplay.task(\n\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.writingOutputFile\"),\n\t\toutputFile\n\t);\n\tawait writeFile(outputFile, `${JSON.stringify(finalObject, null, 2)}\\n`);\n}\n\n/**\n * Visit a node in the AST.\n * @param config The configuration for the app.\n * @param node The node to visit.\n * @param sourceFile The source file being processed.\n * @param context The JSON-LD context being built.\n * @param context.types The types collected in the context.\n * @param context.namespaces The namespaces collected in the context.\n * @param context.properties The properties collected in the context.\n * @param program The TypeScript program for resolving inherited interfaces.\n * @param processedTypes The types that have already been processed.\n */\nfunction visit(\n\tconfig: ITsToJsonLdContextConfig,\n\tnode: ts.Node,\n\tsourceFile: ts.SourceFile,\n\tcontext: { types: string[]; namespaces: string[]; properties: { [id: string]: unknown } },\n\tprogram: ts.Program,\n\tprocessedTypes: { [typeName: string]: IJsonLdProps }\n): void {\n\tlet jsonLdProps: IJsonLdProps = {};\n\n\t// Handle different node types\n\tif (ts.isInterfaceDeclaration(node)) {\n\t\tCLIDisplay.value(\n\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.model\"),\n\t\t\tnode.name.text\n\t\t);\n\t\tcontext.types.push(node.name.text);\n\n\t\tif (Is.array(node.members)) {\n\t\t\tnode.members.forEach(member => {\n\t\t\t\tif (ts.isPropertySignature(member)) {\n\t\t\t\t\tconst propertyName = member.name?.getText(sourceFile).replace(/[\"']/g, \"\");\n\n\t\t\t\t\tif (Is.stringValue(propertyName)) {\n\t\t\t\t\t\tconst jsDocComments: string[] = extractComments(member);\n\n\t\t\t\t\t\tjsonLdProps = extractJsonLdProps(jsDocComments);\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t![\"@context\", \"type\", \"id\"].includes(propertyName) &&\n\t\t\t\t\t\t\t!Is.objectValue(jsonLdProps)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new GeneralError(\"commands\", \"commands.ts-to-jsonld-context.noJsonLdProps\", {\n\t\t\t\t\t\t\t\tpropertyName\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst contextInfo: {\n\t\t\t\t\t\t\t\"@id\"?: string;\n\t\t\t\t\t\t\t\"@type\"?: string;\n\t\t\t\t\t\t\t\"@container\"?: string;\n\t\t\t\t\t\t} = {};\n\n\t\t\t\t\t\tconst usedNamespaces: (string | undefined)[] = [];\n\n\t\t\t\t\t\tif (Is.objectValue(jsonLdProps.propertyId)) {\n\t\t\t\t\t\t\tusedNamespaces.push(jsonLdProps.propertyId.namespace);\n\t\t\t\t\t\t\tcontextInfo[\"@id\"] =\n\t\t\t\t\t\t\t\t`${jsonLdProps.propertyId.namespace ?? config.prefix}:${jsonLdProps.propertyId.id}`;\n\t\t\t\t\t\t} else if (Is.object(jsonLdProps.propertyId)) {\n\t\t\t\t\t\t\tcontextInfo[\"@id\"] = `${config.prefix}:${propertyName}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tusedNamespaces.push(jsonLdProps.namespace);\n\n\t\t\t\t\t\tif (Is.objectValue(jsonLdProps.propertyType)) {\n\t\t\t\t\t\t\tlet fullType =\n\t\t\t\t\t\t\t\tjsonLdProps.propertyType.type === \"json\" ? \"@json\" : jsonLdProps.propertyType.type;\n\n\t\t\t\t\t\t\tif (Is.stringValue(jsonLdProps.propertyType.namespace)) {\n\t\t\t\t\t\t\t\tfullType = `${jsonLdProps.propertyType.namespace}:${jsonLdProps.propertyType.type}`;\n\n\t\t\t\t\t\t\t\tusedNamespaces.push(jsonLdProps.propertyType.namespace);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!Is.stringValue(contextInfo[\"@id\"])) {\n\t\t\t\t\t\t\t\tcontextInfo[\"@id\"] = `${config.prefix}:${propertyName}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontextInfo[\"@type\"] = fullType;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Is.stringValue(jsonLdProps.container)) {\n\t\t\t\t\t\t\tif (!Is.stringValue(contextInfo[\"@id\"])) {\n\t\t\t\t\t\t\t\tcontextInfo[\"@id\"] = `${config.prefix}:${propertyName}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontextInfo[\"@container\"] = `@${jsonLdProps.container}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (Is.objectValue(contextInfo)) {\n\t\t\t\t\t\t\tcontext.properties[propertyName] = contextInfo;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (const ns of usedNamespaces) {\n\t\t\t\t\t\t\tif (Is.stringValue(ns) && !context.namespaces.includes(ns)) {\n\t\t\t\t\t\t\t\tcontext.namespaces.push(ns);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tCLIDisplay.value(\n\t\t\t\t\t\t\tI18n.formatMessage(\"commands.ts-to-jsonld-context.labels.property\"),\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t\t1\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tprocessedTypes[node.name.text] = jsonLdProps;\n\n\t\tif (node.heritageClauses) {\n\t\t\tfor (const clause of node.heritageClauses) {\n\t\t\t\tif (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n\t\t\t\t\tfor (const type of clause.types) {\n\t\t\t\t\t\tconst inheritedInterfaceName = extractBaseInterfaceName(type, sourceFile);\n\n\t\t\t\t\t\tif (!processedTypes[inheritedInterfaceName]) {\n\t\t\t\t\t\t\tconst result = findInterfaceByName(inheritedInterfaceName, program);\n\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\tvisit(\n\t\t\t\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t\t\t\tresult.interfaceDeclaration,\n\t\t\t\t\t\t\t\t\tresult.sourceFile,\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tprogram,\n\t\t\t\t\t\t\t\t\tprocessedTypes\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tts.forEachChild(node, child =>\n\t\tvisit(config, child, sourceFile, context, program, processedTypes)\n\t);\n}\n\n/**\n * Find an interface by name in the program.\n * @param interfaceName The name of the interface to find.\n * @param program The TypeScript program.\n * @returns The found interface declaration with its source file or undefined.\n */\nfunction findInterfaceByName(\n\tinterfaceName: string,\n\tprogram: ts.Program\n): { interfaceDeclaration: ts.InterfaceDeclaration; sourceFile: ts.SourceFile } | undefined {\n\tfor (const sourceFile of program.getSourceFiles()) {\n\t\tlet foundInterface: ts.InterfaceDeclaration | undefined;\n\n\t\tts.forEachChild(sourceFile, node => {\n\t\t\tif (ts.isInterfaceDeclaration(node) && node.name.text === interfaceName) {\n\t\t\t\tfoundInterface = node;\n\t\t\t}\n\t\t});\n\n\t\tif (foundInterface) {\n\t\t\treturn { interfaceDeclaration: foundInterface, sourceFile };\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Extract JSDoc comments from a property signature.\n * @param member The property signature member.\n * @returns The extracted comments.\n */\nfunction extractComments(member: ts.Node): string[] {\n\tconst jsDocComments: string[] = [];\n\tconst jsDocs = ObjectHelper.propertyGet<ts.JSDoc[] | undefined>(member, \"jsDoc\");\n\n\tif (Is.arrayValue(jsDocs)) {\n\t\tfor (const doc of jsDocs) {\n\t\t\tif (Is.string(doc.comment)) {\n\t\t\t\tjsDocComments.push(...doc.comment.split(\"\\n\").map(part => part.trim()));\n\t\t\t} else if (Is.arrayValue<string>(doc.comment)) {\n\t\t\t\tjsDocComments.push(...doc.comment.map(part => part.text));\n\t\t\t}\n\t\t}\n\t}\n\treturn jsDocComments;\n}\n\n/**\n * Extract JSON-LD properties from comments.\n * @param comments The comments to extract from.\n * @returns The extracted JSON-LD properties.\n */\nfunction extractJsonLdProps(comments: string[]): IJsonLdProps {\n\tconst jsonLdProps: IJsonLdProps = {};\n\n\tfor (const comment of comments) {\n\t\tif (/^json-ld id$/.exec(comment)) {\n\t\t\tjsonLdProps.propertyId = {};\n\t\t} else {\n\t\t\tconst idWithNamespaceAndType = /^json-ld id:(.*):(.*)$/.exec(comment);\n\t\t\tif (idWithNamespaceAndType) {\n\t\t\t\tjsonLdProps.propertyId = {\n\t\t\t\t\tnamespace: idWithNamespaceAndType[1],\n\t\t\t\t\tid: idWithNamespaceAndType[2]\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tconst idMatch = /^json-ld id:(.*)$/.exec(comment);\n\t\t\t\tif (idMatch) {\n\t\t\t\t\tjsonLdProps.propertyId = { id: idMatch[1] };\n\t\t\t\t} else {\n\t\t\t\t\tconst namespaceMatch = /^json-ld namespace:(.*)/.exec(comment);\n\t\t\t\t\tif (namespaceMatch) {\n\t\t\t\t\t\tjsonLdProps.namespace = namespaceMatch[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst containerMatch = /^json-ld container:(.*)$/.exec(comment);\n\t\t\t\t\t\tif (containerMatch) {\n\t\t\t\t\t\t\tjsonLdProps.container = containerMatch[1];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst typeMatch = /^json-ld type:(.*):(.*)$/.exec(comment);\n\t\t\t\t\t\t\tif (typeMatch) {\n\t\t\t\t\t\t\t\tjsonLdProps.propertyType = {\n\t\t\t\t\t\t\t\t\tnamespace: typeMatch[1],\n\t\t\t\t\t\t\t\t\ttype: typeMatch[2]\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst typeMatch2 = /^json-ld type:(.*)$/.exec(comment);\n\t\t\t\t\t\t\t\tif (typeMatch2) {\n\t\t\t\t\t\t\t\t\tjsonLdProps.propertyType = {\n\t\t\t\t\t\t\t\t\t\ttype: typeMatch2[1]\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn jsonLdProps;\n}\n\n/**\n * Extract the base interface name from a type reference using the AST.\n * Handles utility types like Omit<InterfaceName, \"deleted\"> by extracting the first type argument.\n * @param type The type reference expression node.\n * @param sourceFile The source file for extracting text.\n * @returns The base interface name.\n */\nfunction extractBaseInterfaceName(type: ts.TypeReferenceType, sourceFile: ts.SourceFile): string {\n\t// Check if it's an expression with type arguments (e.g., Omit<Interface, \"deleted\">)\n\tif (\n\t\tts.isExpressionWithTypeArguments(type) &&\n\t\ttype.typeArguments &&\n\t\ttype.typeArguments.length > 0\n\t) {\n\t\t// Extract the first type argument which should be the interface name\n\t\tconst firstTypeArg = type.typeArguments[0];\n\t\treturn firstTypeArg.getText(sourceFile);\n\t}\n\n\t// Otherwise, treat the whole expression as the interface name\n\treturn type.getText(sourceFile);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IJsonLdProps.js","sourceRoot":"","sources":["../../../src/models/IJsonLdProps.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * JSON-LD property metadata.\n */\nexport interface IJsonLdProps {\n\t/**\n\t *
|
|
1
|
+
{"version":3,"file":"IJsonLdProps.js","sourceRoot":"","sources":["../../../src/models/IJsonLdProps.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * JSON-LD property metadata.\n */\nexport interface IJsonLdProps {\n\t/**\n\t * The id of the property.\n\t */\n\tpropertyId?: {\n\t\tnamespace?: string;\n\t\tid?: string;\n\t};\n\n\t/**\n\t * The namespace of the property.\n\t */\n\tnamespace?: string;\n\n\t/**\n\t * The type information of the property.\n\t */\n\tpropertyType?: {\n\t\tnamespace?: string;\n\t\ttype?: string;\n\t};\n\n\t/**\n\t * The container type of the property.\n\t */\n\tcontainer?: string;\n}\n"]}
|
package/dist/locales/en.json
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"ts-to-jsonld-context": {
|
|
13
13
|
"configFailed": "Configuration failed to load.",
|
|
14
|
-
"noJsonLdProps": "No JSON-LD properties found for property \"{propertyName}\"."
|
|
14
|
+
"noJsonLdProps": "No JSON-LD properties found for property \"{propertyName}\".",
|
|
15
|
+
"namespaceNotInConfig": "The following namespaces were used in the models but not defined in the configuration file: {namespaces}."
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
18
|
"validation": {
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.7](https://github.com/twinfoundation/tools/compare/ts-to-jsonld-context-v0.0.3-next.6...ts-to-jsonld-context-v0.0.3-next.7) (2026-02-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* support id definition for properties, including ids coming from external LD Contexts ([#69](https://github.com/twinfoundation/tools/issues/69)) ([7afbb81](https://github.com/twinfoundation/tools/commit/7afbb810f5a9e88163fc3ec05fd4957e60c0ca22))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/tools-core bumped from 0.0.3-next.6 to 0.0.3-next.7
|
|
16
|
+
|
|
3
17
|
## [0.0.3-next.6](https://github.com/twinfoundation/tools/compare/ts-to-jsonld-context-v0.0.3-next.5...ts-to-jsonld-context-v0.0.3-next.6) (2026-01-28)
|
|
4
18
|
|
|
5
19
|
|
package/docs/examples.md
CHANGED
|
@@ -13,3 +13,155 @@ You can then run the tool from the command line e.g.
|
|
|
13
13
|
```shell
|
|
14
14
|
ts-to-jsonld-context
|
|
15
15
|
```
|
|
16
|
+
|
|
17
|
+
Reads the comments from the model properties to generate the definitions.
|
|
18
|
+
|
|
19
|
+
## Types
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
/**
|
|
23
|
+
* The index of the entry.
|
|
24
|
+
* json-ld type:schema:Integer
|
|
25
|
+
*/
|
|
26
|
+
index: number;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
will produce
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
"index": {
|
|
33
|
+
"@id": "twin-ais:index",
|
|
34
|
+
"@type": "schema:Integer"
|
|
35
|
+
},
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
/**
|
|
40
|
+
* The object to associate with the entry as JSON-LD.
|
|
41
|
+
* json-ld type:json
|
|
42
|
+
*/
|
|
43
|
+
entryObject: IJsonLdNodeObject;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
will produce
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
"entryObject": {
|
|
50
|
+
"@id": "twin-ais:entryObject",
|
|
51
|
+
"@type": "@json"
|
|
52
|
+
},
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Namespace
|
|
56
|
+
|
|
57
|
+
If the property refers to an external namespace defined in the config, property is not included in the output:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
/**
|
|
61
|
+
* The identity of the user which added the entry to the stream.
|
|
62
|
+
* json-ld namespace:twin-common
|
|
63
|
+
*/
|
|
64
|
+
userIdentity?: string;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Containers
|
|
68
|
+
|
|
69
|
+
For a container type:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
/**
|
|
73
|
+
* Entries in the stream.
|
|
74
|
+
* json-ld container:set
|
|
75
|
+
*/
|
|
76
|
+
entries?: IAuditableItemStreamEntry[];
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
produces
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
"entries": {
|
|
83
|
+
"@id": "twin-ais:entries",
|
|
84
|
+
"@container": "@set"
|
|
85
|
+
},
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## IDs
|
|
89
|
+
|
|
90
|
+
For a plain id mapping:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
/**
|
|
94
|
+
* Entries in the stream.
|
|
95
|
+
* json-ld id
|
|
96
|
+
*/
|
|
97
|
+
foo: unknown;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
produces
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
"foo": {
|
|
104
|
+
"@id": "twin-ais:foo"
|
|
105
|
+
},
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For an id with name:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
/**
|
|
112
|
+
* Entries in the stream.
|
|
113
|
+
* json-ld id:bar
|
|
114
|
+
*/
|
|
115
|
+
foo: unknown;
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
produces
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
"foo": {
|
|
122
|
+
"@id": "twin-ais:bar"
|
|
123
|
+
},
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For an id with namespace and name:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
/**
|
|
130
|
+
* Entries in the stream.
|
|
131
|
+
* json-ld id:dee:bar
|
|
132
|
+
*/
|
|
133
|
+
foo: unknown;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
produces
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
"foo": {
|
|
140
|
+
"@id": "dee:bar"
|
|
141
|
+
},
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Example Config
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"prefix": "twin-ais",
|
|
149
|
+
"contextUrl": "https://schema.twindev.org/ais/",
|
|
150
|
+
"additionalContextUrls": {
|
|
151
|
+
"twin-common": "https://schema.twindev.org/common/",
|
|
152
|
+
"twin-immutable-proof": "https://schema.twindev.org/immutable-proof/",
|
|
153
|
+
"schema": "http://schema.org/"
|
|
154
|
+
},
|
|
155
|
+
"fixedMappings": {
|
|
156
|
+
"id": "@id",
|
|
157
|
+
"type": "@type"
|
|
158
|
+
},
|
|
159
|
+
"types": [
|
|
160
|
+
"./src/models/IAuditableItemStream.ts",
|
|
161
|
+
"./src/models/IAuditableItemStreamList.ts",
|
|
162
|
+
"./src/models/IAuditableItemStreamEntry.ts",
|
|
163
|
+
"./src/models/IAuditableItemStreamEntryList.ts",
|
|
164
|
+
"./src/models/IAuditableItemStreamEntryObjectList.ts"
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
```
|
package/locales/en.json
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
"commands": {
|
|
4
4
|
"ts-to-jsonld-context": {
|
|
5
5
|
"configFailed": "Configuration failed to load.",
|
|
6
|
-
"noJsonLdProps": "No JSON-LD properties found for property \"{propertyName}\"."
|
|
6
|
+
"noJsonLdProps": "No JSON-LD properties found for property \"{propertyName}\".",
|
|
7
|
+
"namespaceNotInConfig": "The following namespaces were used in the models but not defined in the configuration file: {namespaces}."
|
|
7
8
|
}
|
|
8
9
|
}
|
|
9
10
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/ts-to-jsonld-context",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.7",
|
|
4
4
|
"description": "Tool to convert TypeScript definitions to JSON-LD contexts",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@twin.org/cli-core": "next",
|
|
18
18
|
"@twin.org/core": "next",
|
|
19
19
|
"@twin.org/nameof": "next",
|
|
20
|
-
"@twin.org/tools-core": "0.0.3-next.
|
|
20
|
+
"@twin.org/tools-core": "0.0.3-next.7",
|
|
21
21
|
"commander": "14.0.2",
|
|
22
22
|
"glob": "11.0.3",
|
|
23
23
|
"typescript": "5.9.3"
|