@nyrra/prismantix-cli 0.0.4-next.20 → 0.0.4-next.22

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 (54) hide show
  1. package/README.md +14 -0
  2. package/dist/commands/foundry/import.d.ts +17 -0
  3. package/dist/commands/foundry/import.d.ts.map +1 -0
  4. package/dist/commands/foundry/import.js +94 -0
  5. package/dist/constants.d.ts +1 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +1 -0
  8. package/dist/foundry-import/actions.d.ts +3 -0
  9. package/dist/foundry-import/actions.d.ts.map +1 -0
  10. package/dist/foundry-import/actions.js +37 -0
  11. package/dist/foundry-import/convert.d.ts +3 -0
  12. package/dist/foundry-import/convert.d.ts.map +1 -0
  13. package/dist/foundry-import/convert.js +47 -0
  14. package/dist/foundry-import/emit.d.ts +3 -0
  15. package/dist/foundry-import/emit.d.ts.map +1 -0
  16. package/dist/foundry-import/emit.js +263 -0
  17. package/dist/foundry-import/interfaces.d.ts +3 -0
  18. package/dist/foundry-import/interfaces.d.ts.map +1 -0
  19. package/dist/foundry-import/interfaces.js +43 -0
  20. package/dist/foundry-import/names.d.ts +10 -0
  21. package/dist/foundry-import/names.d.ts.map +1 -0
  22. package/dist/foundry-import/names.js +83 -0
  23. package/dist/foundry-import/objects.d.ts +9 -0
  24. package/dist/foundry-import/objects.d.ts.map +1 -0
  25. package/dist/foundry-import/objects.js +128 -0
  26. package/dist/foundry-import/parse.d.ts +3 -0
  27. package/dist/foundry-import/parse.d.ts.map +1 -0
  28. package/dist/foundry-import/parse.js +28 -0
  29. package/dist/foundry-import/properties.d.ts +4 -0
  30. package/dist/foundry-import/properties.d.ts.map +1 -0
  31. package/dist/foundry-import/properties.js +83 -0
  32. package/dist/foundry-import/property-types.d.ts +7 -0
  33. package/dist/foundry-import/property-types.d.ts.map +1 -0
  34. package/dist/foundry-import/property-types.js +77 -0
  35. package/dist/foundry-import/relations.d.ts +11 -0
  36. package/dist/foundry-import/relations.d.ts.map +1 -0
  37. package/dist/foundry-import/relations.js +204 -0
  38. package/dist/foundry-import/types.d.ts +335 -0
  39. package/dist/foundry-import/types.d.ts.map +1 -0
  40. package/dist/foundry-import/types.js +1 -0
  41. package/dist/foundry-import/utils.d.ts +13 -0
  42. package/dist/foundry-import/utils.d.ts.map +1 -0
  43. package/dist/foundry-import/utils.js +82 -0
  44. package/dist/foundry-import/validate.d.ts +8 -0
  45. package/dist/foundry-import/validate.d.ts.map +1 -0
  46. package/dist/foundry-import/validate.js +117 -0
  47. package/dist/foundry-import/workflow.d.ts +3 -0
  48. package/dist/foundry-import/workflow.d.ts.map +1 -0
  49. package/dist/foundry-import/workflow.js +104 -0
  50. package/dist/foundry-import.d.ts +3 -0
  51. package/dist/foundry-import.d.ts.map +1 -0
  52. package/dist/foundry-import.js +1 -0
  53. package/oclif.manifest.json +62 -1
  54. package/package.json +6 -3
package/README.md CHANGED
@@ -40,3 +40,17 @@ npx -y @nyrra/prismantix-cli download \
40
40
  ```
41
41
 
42
42
  `--json` keeps stdout machine-readable. Progress and errors are written to stderr, and the API key is never printed.
43
+
44
+ ## Foundry Ontology Import
45
+
46
+ Convert a downloaded Foundry ontology export JSON into best-effort Ontology-as-Code source:
47
+
48
+ ```sh
49
+ npx -y @nyrra/prismantix-cli foundry import \
50
+ --input ./ontology-export.json \
51
+ --output ./foundry-oac \
52
+ --ontology-name devcon \
53
+ --json
54
+ ```
55
+
56
+ The command writes generated `.mts` files plus `diagnostics.json` and `diagnostics.md`. The emitted source targets upstream `@osdk/maker` OAC, not PrismantiX's local `@nyrra/maker` DSL. Dotted or hyphenated Foundry API names are normalized into maker-compatible identifiers and reported in diagnostics.
@@ -0,0 +1,17 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class FoundryImport extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ "ontology-name": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ validate: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ private fail;
14
+ private printProgress;
15
+ private printSummary;
16
+ }
17
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/commands/foundry/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAQ7C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,OAAO;IACjD,OAAgB,WAAW,SACyD;IAEpF,OAAgB,QAAQ,WAGtB;IAEF,OAAgB,KAAK;;;;;;MAmBnB;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BjC,OAAO,CAAC,IAAI;IAeZ,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,YAAY;CAqBpB"}
@@ -0,0 +1,94 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import { toCliUserError } from "../../errors.js";
3
+ import { runFoundryImportWorkflow, } from "../../foundry-import.js";
4
+ export default class FoundryImport extends Command {
5
+ static description = "Convert a Foundry ontology export JSON into best-effort Ontology-as-Code source.";
6
+ static examples = [
7
+ "<%= config.bin %> foundry import --input ontology.json --output ./oac",
8
+ "<%= config.bin %> foundry import --input ontology.json --ontology-name devcon --json",
9
+ ];
10
+ static flags = {
11
+ input: Flags.string({
12
+ description: "Foundry ontology export JSON file.",
13
+ env: "PRISMANTIX_FOUNDRY_EXPORT",
14
+ }),
15
+ json: Flags.boolean({
16
+ description: "Print machine-readable JSON to stdout.",
17
+ }),
18
+ "ontology-name": Flags.string({
19
+ description: "Name to write into generated source file headers.",
20
+ }),
21
+ output: Flags.string({
22
+ description: "Output directory.",
23
+ env: "PRISMANTIX_OUTPUT_DIR",
24
+ }),
25
+ validate: Flags.boolean({
26
+ description: "Compile generated source and run upstream @osdk/maker OntologyIr conversion.",
27
+ }),
28
+ };
29
+ async run() {
30
+ const { flags } = await this.parse(FoundryImport);
31
+ try {
32
+ const result = await runFoundryImportWorkflow({
33
+ input: flags.input,
34
+ ontologyName: flags["ontology-name"],
35
+ outputDir: flags.output,
36
+ validate: flags.validate,
37
+ }, {
38
+ onEvent: (event) => this.printProgress(event),
39
+ });
40
+ if (flags.json) {
41
+ this.log(JSON.stringify(result, null, 2));
42
+ return;
43
+ }
44
+ this.printSummary(result);
45
+ }
46
+ catch (error) {
47
+ this.fail(toCliUserError(error), flags.json);
48
+ }
49
+ }
50
+ fail(error, json) {
51
+ if (json) {
52
+ this.logToStderr(JSON.stringify({
53
+ code: error.code,
54
+ error: error.message,
55
+ ok: false,
56
+ }));
57
+ this.exit(error.exitCode);
58
+ }
59
+ this.error(error.message, { code: error.code, exit: error.exitCode });
60
+ }
61
+ printProgress(event) {
62
+ this.logToStderr(progressMessage(event));
63
+ }
64
+ printSummary(result) {
65
+ this.log(`Imported Foundry ontology ${result.ontologyName}`);
66
+ this.log(`Input: ${result.inputPath}`);
67
+ this.log(`Output: ${result.outputDir}`);
68
+ this.log(`Files: ${result.files.length}`);
69
+ this.log(`Objects: ${result.counts.objects}; relations: ${result.counts.relations}; actions: ${result.counts.actions}; interfaces: ${result.counts.interfaces}; shared properties: ${result.counts.sharedProperties}; type groups: ${result.counts.typeGroups}`);
70
+ this.log(`Diagnostics: ${result.diagnostics.total} total, ${result.diagnostics.warnings + result.diagnostics.errors} warnings/errors, ${result.diagnostics.info} info.`);
71
+ if (result.validation) {
72
+ this.log(`Validation: ${result.validation.makerPackage} ${result.validation.makerVersion} produced OntologyIr (${result.validation.ontologyIrBytes} bytes).`);
73
+ }
74
+ for (const file of result.files) {
75
+ this.log(`- ${file.relativePath}: ${file.path}`);
76
+ }
77
+ }
78
+ }
79
+ function progressMessage(event) {
80
+ if (event.type === "read") {
81
+ return `Reading Foundry export ${event.inputPath}.`;
82
+ }
83
+ return completionProgressMessage(event);
84
+ }
85
+ function completionProgressMessage(event) {
86
+ switch (event.type) {
87
+ case "converted":
88
+ return `Converted ${event.counts.objects} objects, ${event.counts.relations} relations, ${event.counts.actions} actions, ${event.counts.interfaces} interfaces, and ${event.counts.sharedProperties} shared properties.`;
89
+ case "validated":
90
+ return `Validated generated OAC with ${event.validation.makerPackage} ${event.validation.makerVersion}.`;
91
+ case "write-file":
92
+ return `Wrote ${event.file.relativePath}.`;
93
+ }
94
+ }
@@ -1,4 +1,5 @@
1
1
  export declare const DEFAULT_API_BASE_URL = "https://api.prismantix.com";
2
+ export declare const DEFAULT_FOUNDRY_IMPORT_OUTPUT_ROOT = "prismantix-foundry-imports";
2
3
  export declare const DEFAULT_OUTPUT_ROOT = "prismantix-exports";
3
4
  export declare const DEFAULT_POLL_INTERVAL_MS = 1000;
4
5
  export declare const DEFAULT_TIMEOUT_MS = 120000;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,+BAA+B,CAAC;AACjE,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AACxD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,kBAAkB,SAAU,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,+BAA+B,CAAC;AACjE,eAAO,MAAM,kCAAkC,+BAA+B,CAAC;AAC/E,eAAO,MAAM,mBAAmB,uBAAuB,CAAC;AACxD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,kBAAkB,SAAU,CAAC"}
package/dist/constants.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export const DEFAULT_API_BASE_URL = "https://api.prismantix.com";
2
+ export const DEFAULT_FOUNDRY_IMPORT_OUTPUT_ROOT = "prismantix-foundry-imports";
2
3
  export const DEFAULT_OUTPUT_ROOT = "prismantix-exports";
3
4
  export const DEFAULT_POLL_INTERVAL_MS = 1000;
4
5
  export const DEFAULT_TIMEOUT_MS = 120_000;
@@ -0,0 +1,3 @@
1
+ import type { ConversionDiagnostic, FoundryActionType, NormalizedAction } from "./types.js";
2
+ export declare function normalizeAction(action: FoundryActionType, actionIndex: number, nameAllocator: (name: string) => string, diagnostics: ConversionDiagnostic[]): NormalizedAction;
3
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/foundry-import/actions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,eAAe,CAC9B,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACvC,WAAW,EAAE,oBAAoB,EAAE,GACjC,gBAAgB,CAclB"}
@@ -0,0 +1,37 @@
1
+ import { addSanitizationDiagnostic, sanitizeApiName } from "./names.js";
2
+ import { displayNameFor, normalizeStatus, requiredString } from "./utils.js";
3
+ export function normalizeAction(action, actionIndex, nameAllocator, diagnostics) {
4
+ const apiName = normalizeActionApiName(action, actionIndex, nameAllocator, diagnostics);
5
+ return {
6
+ apiName,
7
+ displayName: actionDisplayName(action, apiName.sanitized),
8
+ parameterCount: parameterCount(actionFormContent(action)),
9
+ ruleTypes: actionRuleTypes(action),
10
+ status: actionStatus(action),
11
+ };
12
+ }
13
+ function normalizeActionApiName(action, actionIndex, nameAllocator, diagnostics) {
14
+ const path = `$.actionTypes[${actionIndex}].metadata.apiName`;
15
+ const original = requiredString(action.metadata?.apiName, path, diagnostics, `action${actionIndex + 1}`);
16
+ const sanitized = nameAllocator(sanitizeApiName(original, "api"));
17
+ addSanitizationDiagnostic(diagnostics, path, original, sanitized);
18
+ return { original, sanitized };
19
+ }
20
+ function parameterCount(formContent) {
21
+ return formContent.filter((content) => content.type === "parameter").length;
22
+ }
23
+ function actionDisplayName(action, fallback) {
24
+ return displayNameFor(action.metadata?.displayMetadata, fallback);
25
+ }
26
+ function actionFormContent(action) {
27
+ return action.metadata?.formContentInOrder ?? [];
28
+ }
29
+ function actionRuleTypes(action) {
30
+ return actionRules(action).map((rule) => rule.type ?? "unknown");
31
+ }
32
+ function actionRules(action) {
33
+ return action.actionTypeLogic?.logic?.rules ?? [];
34
+ }
35
+ function actionStatus(action) {
36
+ return normalizeStatus(action.metadata?.status);
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { ConversionResult } from "./types.js";
2
+ export declare function convertFoundryV2Export(input: unknown): ConversionResult;
3
+ //# sourceMappingURL=convert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/foundry-import/convert.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEX,gBAAgB,EAIhB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAqDvE"}
@@ -0,0 +1,47 @@
1
+ import { normalizeAction } from "./actions.js";
2
+ import { normalizeInterface } from "./interfaces.js";
3
+ import { createNameAllocator } from "./names.js";
4
+ import { normalizeObject } from "./objects.js";
5
+ import { parseFoundryV2Export } from "./parse.js";
6
+ import { normalizeSharedProperty } from "./properties.js";
7
+ import { normalizeRelation } from "./relations.js";
8
+ import { displayNameFor } from "./utils.js";
9
+ export function convertFoundryV2Export(input) {
10
+ const diagnostics = [];
11
+ const foundryExport = parseFoundryV2Export(input, diagnostics);
12
+ const objectNameAllocator = createNameAllocator();
13
+ const generalNameAllocator = createNameAllocator();
14
+ const relationNameAllocator = createNameAllocator();
15
+ const variableNameAllocator = createNameAllocator();
16
+ const objects = foundryExport.objectTypes.map((objectType, objectIndex) => normalizeObject(objectType, objectIndex, {
17
+ diagnostics,
18
+ objectNameAllocator,
19
+ variableNameAllocator,
20
+ }));
21
+ const objectsByRid = indexObjectsByRid(objects);
22
+ return {
23
+ actions: foundryExport.actionTypes.map((action, actionIndex) => normalizeAction(action, actionIndex, generalNameAllocator, diagnostics)),
24
+ diagnostics,
25
+ interfaces: foundryExport.interfaces.map((interfaceType, interfaceIndex) => normalizeInterface(interfaceType, interfaceIndex, generalNameAllocator, variableNameAllocator, diagnostics)),
26
+ objects,
27
+ relations: foundryExport.relations.flatMap((relation, relationIndex) => normalizeRelation(relation, relationIndex, objectsByRid, relationNameAllocator, variableNameAllocator, diagnostics)),
28
+ sharedProperties: foundryExport.sharedProperties.map((sharedProperty, sharedPropertyIndex) => normalizeSharedProperty(sharedProperty, sharedPropertyIndex, generalNameAllocator, variableNameAllocator, diagnostics)),
29
+ sourceVersion: foundryExport.version,
30
+ typeGroups: foundryExport.typeGroups.map(normalizeTypeGroup),
31
+ };
32
+ }
33
+ function indexObjectsByRid(objects) {
34
+ const objectsByRid = new Map();
35
+ for (const object of objects) {
36
+ if (object.rid) {
37
+ objectsByRid.set(object.rid, object);
38
+ }
39
+ }
40
+ return objectsByRid;
41
+ }
42
+ function normalizeTypeGroup(typeGroup) {
43
+ return {
44
+ displayName: displayNameFor(typeGroup.displayMetadata, typeGroup.rid ?? "Type Group"),
45
+ rid: typeGroup.rid,
46
+ };
47
+ }
@@ -0,0 +1,3 @@
1
+ import type { ConversionResult, EmitOptions, EmittedFile } from "./types.js";
2
+ export declare function emitFoundryImportFiles(result: ConversionResult, options?: EmitOptions): readonly EmittedFile[];
3
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/foundry-import/emit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEX,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,MAAM,YAAY,CAAC;AAGpB,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,WAAgB,GACvB,SAAS,WAAW,EAAE,CAoBxB"}
@@ -0,0 +1,263 @@
1
+ import { entityComment, safePropertyKey } from "./names.js";
2
+ import { isRaw, raw } from "./relations.js";
3
+ import { isRecord } from "./utils.js";
4
+ export function emitFoundryImportFiles(result, options = {}) {
5
+ const ontologyName = options.ontologyName ?? "ImportedFoundryOntology";
6
+ return [
7
+ emitIndex(ontologyName),
8
+ emitOntologyEntrypoint(ontologyName),
9
+ { path: "objects.mts", content: emitObjects(result, ontologyName) },
10
+ { path: "relations.mts", content: emitRelations(result, ontologyName) },
11
+ {
12
+ path: "sharedProperties.mts",
13
+ content: emitSharedProperties(result, ontologyName),
14
+ },
15
+ { path: "interfaces.mts", content: emitInterfaces(result, ontologyName) },
16
+ { path: "actions.mts", content: emitActions(result, ontologyName) },
17
+ { path: "typeGroups.mts", content: emitTypeGroups(result, ontologyName) },
18
+ {
19
+ path: "diagnostics.json",
20
+ content: `${JSON.stringify(result.diagnostics, null, 2)}\n`,
21
+ },
22
+ { path: "diagnostics.md", content: emitDiagnosticsMarkdown(result) },
23
+ ];
24
+ }
25
+ function emitIndex(ontologyName) {
26
+ return {
27
+ path: "index.mts",
28
+ content: [
29
+ header(ontologyName),
30
+ `export { ACTIONS } from "./actions.mjs";`,
31
+ `export { INTERFACES } from "./interfaces.mjs";`,
32
+ `export { OBJECTS } from "./objects.mjs";`,
33
+ `export { RELATIONS } from "./relations.mjs";`,
34
+ `export { SHARED_PROPERTIES } from "./sharedProperties.mjs";`,
35
+ `export { TYPE_GROUPS } from "./typeGroups.mjs";`,
36
+ "",
37
+ ].join("\n"),
38
+ };
39
+ }
40
+ function emitOntologyEntrypoint(ontologyName) {
41
+ return {
42
+ path: "ontology.mts",
43
+ content: [
44
+ header(ontologyName),
45
+ `import "./sharedProperties.mjs";`,
46
+ `import "./interfaces.mjs";`,
47
+ `import "./objects.mjs";`,
48
+ `import "./relations.mjs";`,
49
+ "",
50
+ ].join("\n"),
51
+ };
52
+ }
53
+ function emitObjects(result, ontologyName) {
54
+ const body = result.objects.map(emitObject).join("\n\n");
55
+ return [
56
+ header(ontologyName),
57
+ `import { defineObject } from "@osdk/maker";`,
58
+ "",
59
+ body,
60
+ "",
61
+ `export const OBJECTS = [${result.objects.map((object) => object.variableName).join(", ")}] as const;`,
62
+ "",
63
+ ].join("\n");
64
+ }
65
+ function emitObject(object) {
66
+ const properties = object.properties.map(emitObjectProperty).join(",\n");
67
+ return [
68
+ entityComment(object.apiName, object.rid),
69
+ `export const ${object.variableName} = defineObject(${objectLiteral({
70
+ apiName: object.apiName.sanitized,
71
+ description: object.description,
72
+ displayName: object.displayName,
73
+ pluralDisplayName: object.pluralDisplayName,
74
+ primaryKeyPropertyApiName: object.primaryKeyPropertyApiName,
75
+ properties: raw(`{\n${properties}\n\t}`),
76
+ status: object.status,
77
+ titlePropertyApiName: object.titlePropertyApiName,
78
+ }, 0)});`,
79
+ ].join("\n");
80
+ }
81
+ function emitObjectProperty(property) {
82
+ return `\t\t${safePropertyKey(property.apiName.sanitized)}: ${objectLiteral({
83
+ array: property.array || undefined,
84
+ description: property.description,
85
+ displayName: property.displayName,
86
+ editOnly: property.editOnly || undefined,
87
+ indexedForSearch: property.indexedForSearch || undefined,
88
+ nullability: property.nullability,
89
+ type: property.type,
90
+ visibility: property.visibility,
91
+ }, 2)}`;
92
+ }
93
+ function emitRelations(result, ontologyName) {
94
+ const body = result.relations.map(emitRelation).join("\n\n");
95
+ return [
96
+ header(ontologyName),
97
+ `import { defineLink } from "@osdk/maker";`,
98
+ ...relationObjectImports(result),
99
+ "",
100
+ body,
101
+ "",
102
+ `export const RELATIONS = [${result.relations.map((relation) => relation.variableName).join(", ")}] as const;`,
103
+ "",
104
+ ].join("\n");
105
+ }
106
+ function relationObjectImports(result) {
107
+ const objectNames = result.objects.map((object) => object.variableName);
108
+ return objectNames.length === 0
109
+ ? []
110
+ : [`import { ${objectNames.join(", ")} } from "./objects.mjs";`];
111
+ }
112
+ function emitRelation(relation) {
113
+ return [
114
+ entityComment(relation.apiName, relation.rid),
115
+ `export const ${relation.variableName} = defineLink(${objectLiteral(relation.definition, 0)});`,
116
+ ].join("\n");
117
+ }
118
+ function emitSharedProperties(result, ontologyName) {
119
+ const body = result.sharedProperties.map(emitSharedProperty).join("\n\n");
120
+ return [
121
+ header(ontologyName),
122
+ `import { defineSharedPropertyType } from "@osdk/maker";`,
123
+ "",
124
+ body,
125
+ "",
126
+ `export const SHARED_PROPERTIES = [${result.sharedProperties.map((property) => property.variableName).join(", ")}] as const;`,
127
+ "",
128
+ ].join("\n");
129
+ }
130
+ function emitSharedProperty(property) {
131
+ return [
132
+ entityComment(property.apiName, property.rid),
133
+ `export const ${property.variableName} = defineSharedPropertyType(${objectLiteral({
134
+ apiName: property.apiName.sanitized,
135
+ array: property.array || undefined,
136
+ description: property.description,
137
+ displayName: property.displayName,
138
+ nullability: property.nullability,
139
+ type: property.type,
140
+ visibility: property.visibility,
141
+ }, 0)});`,
142
+ ].join("\n");
143
+ }
144
+ function emitInterfaces(result, ontologyName) {
145
+ const body = result.interfaces.map(emitInterface).join("\n\n");
146
+ return [
147
+ header(ontologyName),
148
+ `import { defineInterface } from "@osdk/maker";`,
149
+ "",
150
+ body,
151
+ "",
152
+ `export const INTERFACES = [${result.interfaces.map((interfaceType) => interfaceType.variableName).join(", ")}] as const;`,
153
+ "",
154
+ ].join("\n");
155
+ }
156
+ function emitInterface(interfaceType) {
157
+ return [
158
+ entityComment(interfaceType.apiName, interfaceType.rid),
159
+ `export const ${interfaceType.variableName} = defineInterface(${objectLiteral({
160
+ apiName: interfaceType.apiName.sanitized,
161
+ description: interfaceType.description,
162
+ displayName: interfaceType.displayName,
163
+ searchable: interfaceType.searchable,
164
+ status: interfaceType.status
165
+ ? { type: interfaceType.status }
166
+ : undefined,
167
+ }, 0)});`,
168
+ ].join("\n");
169
+ }
170
+ function emitActions(result, ontologyName) {
171
+ return [
172
+ header(ontologyName),
173
+ "// Action forms and logic are summarized here. Full action-rule reconstruction is intentionally deferred.",
174
+ `export const ACTIONS = ${objectLiteral(result.actions, 0)} as const;`,
175
+ "",
176
+ ].join("\n");
177
+ }
178
+ function emitTypeGroups(result, ontologyName) {
179
+ return [
180
+ header(ontologyName),
181
+ "// Type groups are not an upstream maker construct in this first pass.",
182
+ `export const TYPE_GROUPS = ${objectLiteral(result.typeGroups, 0)} as const;`,
183
+ "",
184
+ ].join("\n");
185
+ }
186
+ function emitDiagnosticsMarkdown(result) {
187
+ return [
188
+ "# Foundry Import Diagnostics",
189
+ "",
190
+ `Source version: ${result.sourceVersion}`,
191
+ "",
192
+ "## Counts",
193
+ "",
194
+ `- Objects: ${result.objects.length}`,
195
+ `- Relations: ${result.relations.length}`,
196
+ `- Actions: ${result.actions.length}`,
197
+ `- Interfaces: ${result.interfaces.length}`,
198
+ `- Shared properties: ${result.sharedProperties.length}`,
199
+ `- Type groups: ${result.typeGroups.length}`,
200
+ "",
201
+ "## Diagnostic Summary",
202
+ "",
203
+ diagnosticSummary(result.diagnostics),
204
+ "",
205
+ "## Details",
206
+ "",
207
+ diagnosticDetails(result.diagnostics),
208
+ "",
209
+ ].join("\n");
210
+ }
211
+ function diagnosticSummary(diagnostics) {
212
+ const counts = new Map();
213
+ for (const diagnostic of diagnostics) {
214
+ counts.set(diagnostic.code, (counts.get(diagnostic.code) ?? 0) + 1);
215
+ }
216
+ const lines = Array.from(counts.entries())
217
+ .sort(([left], [right]) => left.localeCompare(right))
218
+ .map(([code, count]) => `- ${code}: ${count}`);
219
+ return markdownLines(lines, "- No diagnostics.");
220
+ }
221
+ function diagnosticDetails(diagnostics) {
222
+ return markdownLines(diagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code} at \`${diagnostic.path}\`: ${diagnostic.message}`), "- No diagnostics.");
223
+ }
224
+ function markdownLines(lines, fallback) {
225
+ return lines.length === 0 ? fallback : lines.join("\n");
226
+ }
227
+ function objectLiteral(value, indentLevel) {
228
+ if (isRaw(value)) {
229
+ return value.value;
230
+ }
231
+ if (Array.isArray(value)) {
232
+ return arrayLiteral(value, indentLevel);
233
+ }
234
+ if (isRecord(value)) {
235
+ return recordLiteral(value, indentLevel);
236
+ }
237
+ return JSON.stringify(value);
238
+ }
239
+ function arrayLiteral(value, indentLevel) {
240
+ if (value.length === 0) {
241
+ return "[]";
242
+ }
243
+ const indent = "\t".repeat(indentLevel);
244
+ const innerIndent = "\t".repeat(indentLevel + 1);
245
+ return `[\n${value.map((item) => `${innerIndent}${objectLiteral(item, indentLevel + 1)}`).join(",\n")}\n${indent}]`;
246
+ }
247
+ function recordLiteral(value, indentLevel) {
248
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== undefined);
249
+ if (entries.length === 0) {
250
+ return "{}";
251
+ }
252
+ const indent = "\t".repeat(indentLevel);
253
+ const innerIndent = "\t".repeat(indentLevel + 1);
254
+ return `{\n${entries
255
+ .map(([key, entryValue]) => `${innerIndent}${safePropertyKey(key)}: ${objectLiteral(entryValue, indentLevel + 1)}`)
256
+ .join(",\n")}\n${indent}}`;
257
+ }
258
+ function header(ontologyName) {
259
+ return [
260
+ `// Generated by @nyrra/prismantix-cli foundry import.`,
261
+ `// Source ontology: ${ontologyName}. Review diagnostics before treating this as hand-authored OAC.`,
262
+ ].join("\n");
263
+ }
@@ -0,0 +1,3 @@
1
+ import type { ConversionDiagnostic, FoundryInterface, NormalizedInterface } from "./types.js";
2
+ export declare function normalizeInterface(interfaceType: FoundryInterface, interfaceIndex: number, nameAllocator: (name: string) => string, variableNameAllocator: (name: string) => string, diagnostics: ConversionDiagnostic[]): NormalizedInterface;
3
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/foundry-import/interfaces.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACX,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,MAAM,YAAY,CAAC;AAQpB,wBAAgB,kBAAkB,CACjC,aAAa,EAAE,gBAAgB,EAC/B,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACvC,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAC/C,WAAW,EAAE,oBAAoB,EAAE,GACjC,mBAAmB,CAsCrB"}
@@ -0,0 +1,43 @@
1
+ import { addSanitizationDiagnostic, sanitizeApiName, toPascalCase, } from "./names.js";
2
+ import { displayNameFor, normalizeDescription, normalizeStatus, requiredString, } from "./utils.js";
3
+ export function normalizeInterface(interfaceType, interfaceIndex, nameAllocator, variableNameAllocator, diagnostics) {
4
+ const originalApiName = requiredString(interfaceType.apiName, `$.interfaces[${interfaceIndex}].apiName`, diagnostics, `Interface${interfaceIndex + 1}`);
5
+ const sanitizedApiName = nameAllocator(sanitizeApiName(originalApiName, "api"));
6
+ addSanitizationDiagnostic(diagnostics, `$.interfaces[${interfaceIndex}].apiName`, originalApiName, sanitizedApiName);
7
+ addInterfaceDiagnostics(interfaceType, interfaceIndex, originalApiName, diagnostics);
8
+ return {
9
+ apiName: { original: originalApiName, sanitized: sanitizedApiName },
10
+ description: normalizeDescription(interfaceType.displayMetadata?.description),
11
+ displayName: displayNameFor(interfaceType.displayMetadata, sanitizedApiName),
12
+ rid: interfaceType.rid,
13
+ searchable: interfaceType.searchable ?? false,
14
+ status: normalizeStatus(interfaceType.status),
15
+ variableName: variableNameAllocator(`${toPascalCase(sanitizedApiName)}Interface`),
16
+ };
17
+ }
18
+ function addInterfaceDiagnostics(interfaceType, interfaceIndex, apiName, diagnostics) {
19
+ addInterfaceLinksDiagnostic(interfaceType, interfaceIndex, apiName, diagnostics);
20
+ addInterfacePropertiesDiagnostic(interfaceType, interfaceIndex, apiName, diagnostics);
21
+ }
22
+ function addInterfaceLinksDiagnostic(interfaceType, interfaceIndex, apiName, diagnostics) {
23
+ if ((interfaceType.links?.length ?? 0) === 0) {
24
+ return;
25
+ }
26
+ diagnostics.push({
27
+ code: "unsupported.interfaceLinks",
28
+ message: `Interface ${apiName} has interface links; emitted interface shell only.`,
29
+ path: `$.interfaces[${interfaceIndex}].links`,
30
+ severity: "warning",
31
+ });
32
+ }
33
+ function addInterfacePropertiesDiagnostic(interfaceType, interfaceIndex, apiName, diagnostics) {
34
+ if ((interfaceType.properties?.length ?? 0) === 0) {
35
+ return;
36
+ }
37
+ diagnostics.push({
38
+ code: "partial.interfaceProperties",
39
+ message: `Interface ${apiName} has properties; emitted interface shell only in this first pass.`,
40
+ path: `$.interfaces[${interfaceIndex}].properties`,
41
+ severity: "warning",
42
+ });
43
+ }
@@ -0,0 +1,10 @@
1
+ import type { ConversionDiagnostic, NamePair } from "./types.js";
2
+ type ApiNameMode = "api" | "object";
3
+ export declare function addSanitizationDiagnostic(diagnostics: ConversionDiagnostic[], path: string, original: string, sanitized: string): void;
4
+ export declare function sanitizeApiName(name: string, mode: ApiNameMode): string;
5
+ export declare function createNameAllocator(): (name: string) => string;
6
+ export declare function entityComment(name: NamePair, rid: string | undefined): string;
7
+ export declare function safePropertyKey(key: string): string;
8
+ export declare function toPascalCase(value: string): string;
9
+ export {};
10
+ //# sourceMappingURL=names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/foundry-import/names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgBjE,KAAK,WAAW,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEpC,wBAAgB,yBAAyB,CACxC,WAAW,EAAE,oBAAoB,EAAE,EACnC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GACf,IAAI,CAUN;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAMvE;AAED,wBAAgB,mBAAmB,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAO9D;AAQD,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAI7E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlD"}