@toolproof-core/schema 1.0.0 → 1.0.2

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 (83) hide show
  1. package/dist/generated/types/standalone/Resource_Genesis.d.ts +3 -0
  2. package/dist/generated/types/standalone/Resource_Job.d.ts +3 -0
  3. package/dist/generated/types/standalone/Resource_RawStrategy.d.ts +3 -0
  4. package/dist/generated/types/standalone/Resource_ResourceType.d.ts +3 -0
  5. package/dist/generated/types/standalone/Resource_RunnableStrategy.d.ts +3 -0
  6. package/dist/generated/types/types.d.ts +487 -548
  7. package/dist/scripts/_lib/config.d.ts +12 -6
  8. package/dist/scripts/_lib/config.js +33 -15
  9. package/dist/scripts/{extractSchemas.js → extractSchemasFromResourceTypeShells.js} +14 -27
  10. package/dist/scripts/generateDependencies.js +2 -2
  11. package/dist/scripts/generateSchemaShims.js +22 -4
  12. package/dist/scripts/{extractSubSchemaWithDefs.js → generateStandaloneSchema.js} +12 -34
  13. package/dist/scripts/{generateResourceTypeType.js → generateStandaloneType.js} +23 -14
  14. package/dist/scripts/generateTypes.js +1 -1
  15. package/dist/scripts/{rewriteAnchors.js → normalizeAnchorsToPointers.js} +2 -2
  16. package/dist/scripts/{generateResourceShells.js → wrapResourceTypesWithResourceShells.js} +12 -34
  17. package/package.json +15 -14
  18. package/src/Genesis.json +1999 -2042
  19. package/src/generated/{dependencies.json → dependencyMap.json} +207 -214
  20. package/src/generated/{resourceTypes → normalized}/Genesis.json +44 -87
  21. package/src/generated/resources/Genesis.json +415 -478
  22. package/src/generated/schemas/Genesis.json +1026 -1057
  23. package/src/generated/schemas/{Goal.json → standalone/Goal.json} +34 -34
  24. package/src/generated/schemas/{Job.json → standalone/Job.json} +85 -85
  25. package/src/generated/schemas/{RawStrategy.json → standalone/RawStrategy.json} +238 -263
  26. package/src/generated/schemas/{ResourceType.json → standalone/ResourceType.json} +60 -60
  27. package/src/generated/schemas/{RunnableStrategy.json → standalone/RunnableStrategy.json} +296 -321
  28. package/src/generated/schemas/{StrategyRun.json → standalone/StrategyRun.json} +390 -421
  29. package/src/generated/types/standalone/Resource_Genesis.d.ts +3 -0
  30. package/src/generated/types/standalone/Resource_Genesis.js +1 -0
  31. package/src/generated/types/standalone/Resource_Job.d.ts +3 -0
  32. package/src/generated/types/standalone/Resource_Job.js +1 -0
  33. package/src/generated/types/standalone/Resource_RawStrategy.d.ts +3 -0
  34. package/src/generated/types/standalone/Resource_RawStrategy.js +1 -0
  35. package/src/generated/types/standalone/Resource_ResourceType.d.ts +3 -0
  36. package/src/generated/types/standalone/Resource_ResourceType.js +1 -0
  37. package/src/generated/types/standalone/Resource_RunnableStrategy.d.ts +3 -0
  38. package/src/generated/types/standalone/Resource_RunnableStrategy.js +1 -0
  39. package/src/generated/types/types.d.ts +487 -548
  40. package/src/generated/types/types.js +1 -1
  41. package/src/scripts/_lib/config.ts +205 -181
  42. package/src/scripts/extractSchemasFromResourceTypeShells.ts +218 -0
  43. package/src/scripts/generateDependencies.ts +120 -120
  44. package/src/scripts/generateSchemaShims.ts +135 -115
  45. package/src/scripts/{extractSubSchemaWithDefs.ts → generateStandaloneSchema.ts} +175 -196
  46. package/src/scripts/{generateResourceTypeType.ts → generateStandaloneType.ts} +119 -110
  47. package/src/scripts/generateTypes.ts +614 -614
  48. package/src/scripts/{rewriteAnchors.ts → normalizeAnchorsToPointers.ts} +123 -123
  49. package/src/scripts/{generateResourceShells.ts → wrapResourceTypesWithResourceShells.ts} +84 -105
  50. package/dist/generated/types/Resource_Genesis.d.ts +0 -3
  51. package/dist/generated/types/Resource_Job.d.ts +0 -3
  52. package/dist/generated/types/Resource_RawStrategy.d.ts +0 -3
  53. package/dist/generated/types/Resource_ResourceType.d.ts +0 -3
  54. package/dist/generated/types/Resource_RunnableStrategy.d.ts +0 -3
  55. package/src/Roadmap.json +0 -102
  56. package/src/generated/types/Resource_Genesis.d.ts +0 -3
  57. package/src/generated/types/Resource_Genesis.js +0 -1
  58. package/src/generated/types/Resource_Job.d.ts +0 -3
  59. package/src/generated/types/Resource_Job.js +0 -1
  60. package/src/generated/types/Resource_RawStrategy.d.ts +0 -3
  61. package/src/generated/types/Resource_RawStrategy.js +0 -1
  62. package/src/generated/types/Resource_ResourceType.d.ts +0 -3
  63. package/src/generated/types/Resource_ResourceType.js +0 -1
  64. package/src/generated/types/Resource_RunnableStrategy.d.ts +0 -3
  65. package/src/generated/types/Resource_RunnableStrategy.js +0 -1
  66. package/src/scripts/extractSchemas.ts +0 -229
  67. /package/dist/generated/types/{Resource_Genesis.js → standalone/Resource_Genesis.js} +0 -0
  68. /package/dist/generated/types/{Resource_Job.js → standalone/Resource_Job.js} +0 -0
  69. /package/dist/generated/types/{Resource_RawStrategy.js → standalone/Resource_RawStrategy.js} +0 -0
  70. /package/dist/generated/types/{Resource_ResourceType.js → standalone/Resource_ResourceType.js} +0 -0
  71. /package/dist/generated/types/{Resource_RunnableStrategy.js → standalone/Resource_RunnableStrategy.js} +0 -0
  72. /package/dist/scripts/{extractSchemas.d.ts → extractSchemasFromResourceTypeShells.d.ts} +0 -0
  73. /package/dist/scripts/{extractSubSchemaWithDefs.d.ts → generateStandaloneSchema.d.ts} +0 -0
  74. /package/dist/scripts/{generateResourceShells.d.ts → generateStandaloneType.d.ts} +0 -0
  75. /package/dist/scripts/{generateResourceTypeType.d.ts → normalizeAnchorsToPointers.d.ts} +0 -0
  76. /package/dist/scripts/{rewriteAnchors.d.ts → wrapResourceTypesWithResourceShells.d.ts} +0 -0
  77. /package/src/generated/{resourceTypes → normalized}/Genesis.ts +0 -0
  78. /package/src/generated/schemas/{Goal.ts → standalone/Goal.ts} +0 -0
  79. /package/src/generated/schemas/{Job.ts → standalone/Job.ts} +0 -0
  80. /package/src/generated/schemas/{RawStrategy.ts → standalone/RawStrategy.ts} +0 -0
  81. /package/src/generated/schemas/{ResourceType.ts → standalone/ResourceType.ts} +0 -0
  82. /package/src/generated/schemas/{RunnableStrategy.ts → standalone/RunnableStrategy.ts} +0 -0
  83. /package/src/generated/schemas/{StrategyRun.ts → standalone/StrategyRun.ts} +0 -0
@@ -1,196 +1,175 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { getConfig } from './_lib/config.js';
4
-
5
- /**
6
- * Generic extractor: given a subschema name that exists under Genesis.json $defs,
7
- * produce a standalone JSON Schema file that contains that subschema plus an inner $defs
8
- * object holding all direct & transitive local $defs dependencies (by #/$defs/... $ref).
9
- *
10
- * Genesis.json itself is left unchanged.
11
- *
12
- * Usage:
13
- * node ./dist/scripts/extractSubschemaWithDefs.js --name <DefName>
14
- *
15
- * Writes: src/genesis/generated/schemas/<DefName>.json
16
- */
17
- /**
18
- * Pure function to extract a subschema and its dependencies from a genesis object.
19
- * Performs no I/O operations.
20
- *
21
- * @param genesis The root Genesis schema object
22
- * @param name The name of the definition to extract
23
- * @returns The standalone subschema
24
- */
25
- function extractSubSchemaLogic(genesis: any, name: string): any {
26
- const rootDefs: Record<string, any> | undefined = genesis.$defs;
27
- if (!rootDefs || typeof rootDefs !== 'object') {
28
- throw new Error('No $defs object found in Genesis.json');
29
- }
30
-
31
- const target = rootDefs[name];
32
- if (!target) {
33
- throw new Error(`Subschema named '${name}' not found under $defs in Genesis.json`);
34
- }
35
-
36
- // Collect transitive local $defs names referenced by target
37
- const needed = collectLocalDefClosure(target, rootDefs);
38
-
39
- // Build output schema: clone target and attach collected subset as $defs
40
- const targetClone = deepClone(target);
41
- const defsOut: Record<string, any> = {};
42
- for (const defName of needed) {
43
- // Avoid including the target itself inside its own $defs (mirrors previous pattern)
44
- if (defName === name) continue;
45
- const defSchema = rootDefs[defName];
46
- if (defSchema === undefined) {
47
- console.warn(`Warning: referenced def '${defName}' missing in root $defs (skipped).`);
48
- continue;
49
- }
50
- defsOut[defName] = deepClone(defSchema);
51
- }
52
-
53
- // Merge any pre-existing inner $defs of targetClone (if present) giving precedence to collected ones
54
- const existingInner = isObject(targetClone.$defs) ? targetClone.$defs : {};
55
- targetClone.$defs = { ...existingInner, ...defsOut };
56
-
57
- return targetClone;
58
- }
59
-
60
- async function main() {
61
- const config = getConfig();
62
- const { name } = parseArgs(process.argv.slice(2));
63
- if (!name) {
64
- console.error('Missing --name <DefName> argument');
65
- process.exit(1);
66
- }
67
-
68
- const schemasDir = config.getOutputDir();
69
- const genesisPath = path.join(schemasDir, config.getSourceFile());
70
- const outPath = config.getOutputPath(`${name}.json`);
71
-
72
- if (!fs.existsSync(genesisPath)) {
73
- console.error(`Genesis.json not found at ${genesisPath}`);
74
- process.exit(1);
75
- }
76
-
77
- const raw = fs.readFileSync(genesisPath, 'utf-8');
78
- const genesis = JSON.parse(raw);
79
-
80
- try {
81
- // Call the pure logic function
82
- const result = extractSubSchemaLogic(genesis, name);
83
-
84
- // I/O: Write the result
85
- fs.mkdirSync(path.dirname(outPath), { recursive: true });
86
- fs.writeFileSync(outPath, JSON.stringify(result, null, 2) + '\n');
87
- console.log(`Extracted subschema '${name}' -> ${outPath}`);
88
- } catch (error: any) {
89
- console.error(error.message);
90
- process.exit(1);
91
- }
92
- }
93
-
94
- // ---- Helpers ----
95
- function parseArgs(args: string[]): { name?: string } {
96
- let name: string | undefined;
97
- for (let i = 0; i < args.length; i++) {
98
- const a = args[i];
99
- if (a === '--name') {
100
- name = args[i + 1];
101
- i++;
102
- } else if (a.startsWith('--name=')) {
103
- name = a.split('=')[1];
104
- }
105
- }
106
- return { name };
107
- }
108
-
109
- function isObject(v: any): v is Record<string, any> {
110
- return v !== null && typeof v === 'object' && !Array.isArray(v);
111
- }
112
-
113
- function deepClone<T>(v: T): T {
114
- if (Array.isArray(v)) return v.map((x) => deepClone(x)) as any;
115
- if (isObject(v)) {
116
- const out: Record<string, any> = {};
117
- for (const k of Object.keys(v)) out[k] = deepClone((v as any)[k]);
118
- return out as any;
119
- }
120
- return v;
121
- }
122
-
123
- function extractPointerDefName(ref: string): string | null {
124
- // Accept refs like '#/$defs/Name' only (single-level under $defs)
125
- if (!ref || !ref.startsWith('#/')) return null;
126
- const parts = ref.slice(2).split('/'); // remove '#/'
127
- if (parts.length !== 2) return null;
128
- if (parts[0] !== '$defs') return null;
129
- // Decode JSON Pointer tokens for the def name
130
- const name = parts[1].replace(/~1/g, '/').replace(/~0/g, '~');
131
- return name;
132
- }
133
-
134
- function resolveRefToDefName(ref: string, rootDefs: Record<string, any>): string | null {
135
- if (!ref) return null;
136
- // Case 1: JSON Pointer into $defs: '#/$defs/Name'
137
- const byPointer = extractPointerDefName(ref);
138
- if (byPointer) return byPointer;
139
-
140
- // Case 2: Anchor ref: '#Name' -> find a def whose nucleusSchema.$anchor equals 'Name'
141
- if (ref.startsWith('#') && !ref.startsWith('#/')) {
142
- const anchor = ref.slice(1);
143
- if (!anchor) return null;
144
- for (const [defName, defSchema] of Object.entries(rootDefs)) {
145
- if (!defSchema || typeof defSchema !== 'object') continue;
146
- // Flattened Genesis has defs as the extraction schema itself (with $anchor at the top level).
147
- // Unflattened may have { nucleusSchema: { $anchor } } envelopes. Support both.
148
- const topLevelAnchor = (defSchema as any).$anchor;
149
- const nested = (defSchema as any).nucleusSchema;
150
- const nestedAnchor = nested && typeof nested === 'object' ? nested.$anchor : undefined;
151
- const defAnchor = typeof topLevelAnchor === 'string' ? topLevelAnchor : (typeof nestedAnchor === 'string' ? nestedAnchor : undefined);
152
- if (defAnchor === anchor) {
153
- return defName;
154
- }
155
- }
156
- }
157
-
158
- return null;
159
- }
160
-
161
- function collectLocalDefClosure(node: any, rootDefs: Record<string, any>): Set<string> {
162
- const needed = new Set<string>();
163
- const queue: string[] = [];
164
-
165
- function visit(n: any) {
166
- if (Array.isArray(n)) {
167
- for (const item of n) visit(item);
168
- return;
169
- }
170
- if (!isObject(n)) return;
171
- if (typeof n.$ref === 'string') {
172
- const name = resolveRefToDefName(n.$ref, rootDefs);
173
- if (name && !needed.has(name)) {
174
- needed.add(name);
175
- queue.push(name);
176
- }
177
- }
178
- for (const val of Object.values(n)) visit(val);
179
- }
180
-
181
- visit(node);
182
-
183
- while (queue.length > 0) {
184
- const name = queue.shift()!;
185
- const def = rootDefs[name];
186
- if (!def) continue; // Missing def handled earlier
187
- visit(def);
188
- }
189
-
190
- return needed;
191
- }
192
-
193
- main().catch((e) => {
194
- console.error(e);
195
- process.exit(1);
196
- });
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { getConfig } from './_lib/config.js';
4
+
5
+ /**
6
+ * Create a standalone JSON Schema for a single $defs entry under Genesis.json,
7
+ * embedding all direct & transitive local $defs dependencies.
8
+ *
9
+ * Usage:
10
+ * node ./dist/scripts/generateStandaloneSchema.js --name <DefName>
11
+ */
12
+
13
+ /**
14
+ * Pure function to extract a subschema and its dependencies from a flattened genesis schema.
15
+ * Performs no I/O operations.
16
+ */
17
+ function extractStandaloneSubschemaLogic(genesis: any, name: string): any {
18
+ const rootDefs: Record<string, any> | undefined = genesis.$defs;
19
+ if (!rootDefs || typeof rootDefs !== 'object') {
20
+ throw new Error('No $defs object found in Genesis.json');
21
+ }
22
+
23
+ const target = rootDefs[name];
24
+ if (!target) {
25
+ throw new Error(`Subschema named '${name}' not found under $defs in Genesis.json`);
26
+ }
27
+
28
+ const needed = collectLocalDefClosure(target, rootDefs);
29
+
30
+ const targetClone = deepClone(target);
31
+ const defsOut: Record<string, any> = {};
32
+ for (const defName of needed) {
33
+ if (defName === name) continue;
34
+ const defSchema = rootDefs[defName];
35
+ if (defSchema === undefined) {
36
+ console.warn(`Warning: referenced def '${defName}' missing in root $defs (skipped).`);
37
+ continue;
38
+ }
39
+ defsOut[defName] = deepClone(defSchema);
40
+ }
41
+
42
+ const existingInner = isObject(targetClone.$defs) ? targetClone.$defs : {};
43
+ targetClone.$defs = { ...existingInner, ...defsOut };
44
+
45
+ return targetClone;
46
+ }
47
+
48
+ async function main() {
49
+ const config = getConfig();
50
+ const { name } = parseArgs(process.argv.slice(2));
51
+ if (!name) {
52
+ console.error('Missing --name <DefName> argument');
53
+ process.exit(1);
54
+ }
55
+
56
+ const schemasDir = config.getSchemasDir();
57
+ const genesisPath = path.join(schemasDir, config.getSourceFile());
58
+ const outPath = config.getSchemaStandalonePath(`${name}.json`);
59
+
60
+ if (!fs.existsSync(genesisPath)) {
61
+ console.error(`Genesis.json not found at ${genesisPath}. Run extractSchemasFromResourceTypeShells first.`);
62
+ process.exit(1);
63
+ }
64
+
65
+ const raw = fs.readFileSync(genesisPath, 'utf-8');
66
+ const genesis = JSON.parse(raw);
67
+
68
+ try {
69
+ const result = extractStandaloneSubschemaLogic(genesis, name);
70
+
71
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
72
+ fs.writeFileSync(outPath, JSON.stringify(result, null, 2) + '\n');
73
+ console.log(`Created standalone subschema '${name}' -> ${outPath}`);
74
+ } catch (error: any) {
75
+ console.error(error.message);
76
+ process.exit(1);
77
+ }
78
+ }
79
+
80
+ function parseArgs(args: string[]): { name?: string } {
81
+ let name: string | undefined;
82
+ for (let i = 0; i < args.length; i++) {
83
+ const a = args[i];
84
+ if (a === '--name') {
85
+ name = args[i + 1];
86
+ i++;
87
+ } else if (a.startsWith('--name=')) {
88
+ name = a.split('=')[1];
89
+ }
90
+ }
91
+ return { name };
92
+ }
93
+
94
+ function isObject(v: any): v is Record<string, any> {
95
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
96
+ }
97
+
98
+ function deepClone<T>(v: T): T {
99
+ if (Array.isArray(v)) return v.map((x) => deepClone(x)) as any;
100
+ if (isObject(v)) {
101
+ const out: Record<string, any> = {};
102
+ for (const k of Object.keys(v)) out[k] = deepClone((v as any)[k]);
103
+ return out as any;
104
+ }
105
+ return v;
106
+ }
107
+
108
+ function extractPointerDefName(ref: string): string | null {
109
+ if (!ref || !ref.startsWith('#/')) return null;
110
+ const parts = ref.slice(2).split('/');
111
+ if (parts.length !== 2) return null;
112
+ if (parts[0] !== '$defs') return null;
113
+ const name = parts[1].replace(/~1/g, '/').replace(/~0/g, '~');
114
+ return name;
115
+ }
116
+
117
+ function resolveRefToDefName(ref: string, rootDefs: Record<string, any>): string | null {
118
+ if (!ref) return null;
119
+ const byPointer = extractPointerDefName(ref);
120
+ if (byPointer) return byPointer;
121
+
122
+ if (ref.startsWith('#') && !ref.startsWith('#/')) {
123
+ const anchor = ref.slice(1);
124
+ if (!anchor) return null;
125
+ for (const [defName, defSchema] of Object.entries(rootDefs)) {
126
+ if (!defSchema || typeof defSchema !== 'object') continue;
127
+ const topLevelAnchor = (defSchema as any).$anchor;
128
+ const nested = (defSchema as any).nucleusSchema;
129
+ const nestedAnchor = nested && typeof nested === 'object' ? nested.$anchor : undefined;
130
+ const defAnchor = typeof topLevelAnchor === 'string' ? topLevelAnchor : (typeof nestedAnchor === 'string' ? nestedAnchor : undefined);
131
+ if (defAnchor === anchor) {
132
+ return defName;
133
+ }
134
+ }
135
+ }
136
+
137
+ return null;
138
+ }
139
+
140
+ function collectLocalDefClosure(node: any, rootDefs: Record<string, any>): Set<string> {
141
+ const needed = new Set<string>();
142
+ const queue: string[] = [];
143
+
144
+ function visit(n: any) {
145
+ if (Array.isArray(n)) {
146
+ for (const item of n) visit(item);
147
+ return;
148
+ }
149
+ if (!isObject(n)) return;
150
+ if (typeof n.$ref === 'string') {
151
+ const name = resolveRefToDefName(n.$ref, rootDefs);
152
+ if (name && !needed.has(name)) {
153
+ needed.add(name);
154
+ queue.push(name);
155
+ }
156
+ }
157
+ for (const val of Object.values(n)) visit(val);
158
+ }
159
+
160
+ visit(node);
161
+
162
+ while (queue.length > 0) {
163
+ const name = queue.shift()!;
164
+ const def = rootDefs[name];
165
+ if (!def) continue;
166
+ visit(def);
167
+ }
168
+
169
+ return needed;
170
+ }
171
+
172
+ main().catch((e) => {
173
+ console.error(e);
174
+ process.exit(1);
175
+ });
@@ -1,110 +1,119 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { getConfig } from './_lib/config.js';
4
-
5
- /**
6
- * Generate a typed Resource variant where `extractedData` is typed to a specific schema
7
- * extracted under the configured output directory.
8
- *
9
- * Usage: node ./dist/scripts/generateResourceTypeType.js --name Job
10
- */
11
- /**
12
- * Pure function to generate the typed Resource D.TS content.
13
- *
14
- * @param name The name of the schema
15
- * @returns The TypeScript D.TS file content
16
- */
17
- function generateResourceTypeTypeLogic(name: string): string {
18
- const header = '// Auto-generated strict composite type. Do not edit.\n';
19
- const ts =
20
- `import type { ResourceMetaBase, ${name} as ExtractedData } from './types.js';\n` +
21
- `export type Resource_${name} = ResourceMetaBase & { extractedData: ExtractedData };\n`;
22
- return header + ts;
23
- }
24
-
25
- async function main() {
26
- const config = getConfig();
27
- const { name } = parseArgs(process.argv.slice(2));
28
- if (!name) {
29
- console.error('Missing --name <SchemaBasename> argument');
30
- process.exit(1);
31
- }
32
-
33
- const inPath = config.getOutputPath(`${name}.json`);
34
-
35
- if (!fs.existsSync(inPath)) {
36
- console.error(`Schema file not found: ${inPath}`);
37
- process.exit(1);
38
- }
39
-
40
- // Basic validation against the expected shape of nucleusSchema.
41
- const raw = fs.readFileSync(inPath, 'utf8');
42
- let parsed: any = null;
43
- try {
44
- parsed = JSON.parse(raw);
45
- } catch (e) {
46
- console.error(`Failed to parse JSON schema ${inPath}:`, e);
47
- process.exit(1);
48
- }
49
-
50
- // Minimal checks that roughly match the nucleusSchema constraints used elsewhere.
51
- if (parsed.$schema && parsed.$schema !== 'https://json-schema.org/draft/2020-12/schema') {
52
- console.warn(`Warning: schema $schema is '${parsed.$schema}', expected draft 2020-12. Proceeding anyway.`);
53
- }
54
- if (parsed.type && parsed.type !== 'object') {
55
- console.warn(`Warning: nucleusSchema usually has type: 'object' but this schema has type: '${parsed.type}'. Proceeding.`);
56
- }
57
-
58
- const tsContent = generateResourceTypeTypeLogic(name);
59
- const jsContent = 'export {}\n';
60
-
61
- // Output setup
62
- const outName = `Resource_${name}.d.ts`;
63
- const outJsName = `Resource_${name}.js`;
64
-
65
- // Process src output
66
- const outDir = config.getTypesSrcDir();
67
- fs.mkdirSync(outDir, { recursive: true });
68
-
69
- const outPath = config.getTypesSrcPath(outName);
70
- const outJsPath = config.getTypesSrcPath(outJsName);
71
-
72
- fs.writeFileSync(outPath, tsContent, 'utf8');
73
- console.log(`Wrote ${outPath}`);
74
-
75
- if (!fs.existsSync(outJsPath)) {
76
- fs.writeFileSync(outJsPath, jsContent, 'utf8');
77
- console.log(`Wrote ${outJsPath}`);
78
- }
79
-
80
- // Process dist output
81
- const distLibDir = config.getTypesDistDir();
82
- fs.mkdirSync(distLibDir, { recursive: true });
83
-
84
- const distDtsPath = config.getTypesDistPath(outName);
85
- const distJsPath = config.getTypesDistPath(outJsName);
86
-
87
- fs.writeFileSync(distDtsPath, tsContent, 'utf8');
88
- fs.writeFileSync(distJsPath, jsContent, 'utf8');
89
- console.log(`Wrote ${distDtsPath}`);
90
- console.log(`Wrote ${distJsPath}`);
91
- }
92
-
93
- function parseArgs(args: string[]): { name?: string } {
94
- let name: string | undefined;
95
- for (let i = 0; i < args.length; i++) {
96
- const a = args[i];
97
- if (a === '--name') {
98
- name = args[i + 1];
99
- i++;
100
- } else if (a.startsWith('--name=')) {
101
- name = a.split('=')[1];
102
- }
103
- }
104
- return { name };
105
- }
106
-
107
- main().catch((e) => {
108
- console.error(e);
109
- process.exit(1);
110
- });
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { getConfig } from './_lib/config.js';
4
+
5
+ /**
6
+ * Generate a typed Resource variant where `nucleus` is typed to a specific schema
7
+ * extracted under the configured output directory.
8
+ *
9
+ * Usage: node ./dist/scripts/generateStandaloneType.js --name Job
10
+ */
11
+ /**
12
+ * Pure function to generate the typed Resource D.TS content.
13
+ *
14
+ * @param name The name of the schema
15
+ * @returns The TypeScript D.TS file content
16
+ */
17
+ function generateStandaloneTypeLogic(name: string): string {
18
+ const header = '// Auto-generated strict composite type. Do not edit.\n';
19
+ const ts =
20
+ `import type { ShellMaterializedBase, ${name} as NucleusSchema } from '../types.js';\n` +
21
+ `export type Resource_${name} = ShellMaterializedBase & { nucleus: NucleusSchema };\n`;
22
+ return header + ts;
23
+ }
24
+
25
+ async function main() {
26
+ const config = getConfig();
27
+ const { name } = parseArgs(process.argv.slice(2));
28
+ if (!name) {
29
+ console.error('Missing --name <SchemaBasename> argument');
30
+ process.exit(1);
31
+ }
32
+
33
+ const inPath =
34
+ name === 'Genesis'
35
+ ? config.getSchemaPath('Genesis.json')
36
+ : config.getSchemaStandalonePath(`${name}.json`);
37
+
38
+ if (!fs.existsSync(inPath)) {
39
+ if (name === 'Genesis') {
40
+ console.error(`Schema file not found: ${inPath}`);
41
+ console.error('Run extractSchemasFromResourceTypeShells first.');
42
+ } else {
43
+ console.error(`Standalone schema file not found: ${inPath}`);
44
+ console.error(`Run generateStandaloneSchema -- --name ${name} first.`);
45
+ }
46
+ process.exit(1);
47
+ }
48
+
49
+ // Basic validation against the expected shape of nucleusSchema.
50
+ const raw = fs.readFileSync(inPath, 'utf8');
51
+ let parsed: any = null;
52
+ try {
53
+ parsed = JSON.parse(raw);
54
+ } catch (e) {
55
+ console.error(`Failed to parse JSON schema ${inPath}:`, e);
56
+ process.exit(1);
57
+ }
58
+
59
+ // Minimal checks that roughly match the nucleusSchema constraints used elsewhere.
60
+ if (parsed.$schema && parsed.$schema !== 'https://json-schema.org/draft/2020-12/schema') {
61
+ console.warn(`Warning: schema $schema is '${parsed.$schema}', expected draft 2020-12. Proceeding anyway.`);
62
+ }
63
+ if (parsed.type && parsed.type !== 'object') {
64
+ console.warn(`Warning: nucleusSchema usually has type: 'object' but this schema has type: '${parsed.type}'. Proceeding.`);
65
+ }
66
+
67
+ const tsContent = generateStandaloneTypeLogic(name);
68
+ const jsContent = 'export {}\n';
69
+
70
+ // Output setup
71
+ const outName = `Resource_${name}.d.ts`;
72
+ const outJsName = `Resource_${name}.js`;
73
+
74
+ // Process src output
75
+ const outDir = config.getTypesStandaloneSrcDir();
76
+ fs.mkdirSync(outDir, { recursive: true });
77
+
78
+ const outPath = config.getTypesStandaloneSrcPath(outName);
79
+ const outJsPath = config.getTypesStandaloneSrcPath(outJsName);
80
+
81
+ fs.writeFileSync(outPath, tsContent, 'utf8');
82
+ console.log(`Wrote ${outPath}`);
83
+
84
+ if (!fs.existsSync(outJsPath)) {
85
+ fs.writeFileSync(outJsPath, jsContent, 'utf8');
86
+ console.log(`Wrote ${outJsPath}`);
87
+ }
88
+
89
+ // Process dist output
90
+ const distLibDir = config.getTypesStandaloneDistDir();
91
+ fs.mkdirSync(distLibDir, { recursive: true });
92
+
93
+ const distDtsPath = config.getTypesStandaloneDistPath(outName);
94
+ const distJsPath = config.getTypesStandaloneDistPath(outJsName);
95
+
96
+ fs.writeFileSync(distDtsPath, tsContent, 'utf8');
97
+ fs.writeFileSync(distJsPath, jsContent, 'utf8');
98
+ console.log(`Wrote ${distDtsPath}`);
99
+ console.log(`Wrote ${distJsPath}`);
100
+ }
101
+
102
+ function parseArgs(args: string[]): { name?: string } {
103
+ let name: string | undefined;
104
+ for (let i = 0; i < args.length; i++) {
105
+ const a = args[i];
106
+ if (a === '--name') {
107
+ name = args[i + 1];
108
+ i++;
109
+ } else if (a.startsWith('--name=')) {
110
+ name = a.split('=')[1];
111
+ }
112
+ }
113
+ return { name };
114
+ }
115
+
116
+ main().catch((e) => {
117
+ console.error(e);
118
+ process.exit(1);
119
+ });