@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.
- package/dist/generated/types/standalone/Resource_Genesis.d.ts +3 -0
- package/dist/generated/types/standalone/Resource_Job.d.ts +3 -0
- package/dist/generated/types/standalone/Resource_RawStrategy.d.ts +3 -0
- package/dist/generated/types/standalone/Resource_ResourceType.d.ts +3 -0
- package/dist/generated/types/standalone/Resource_RunnableStrategy.d.ts +3 -0
- package/dist/generated/types/types.d.ts +487 -548
- package/dist/scripts/_lib/config.d.ts +12 -6
- package/dist/scripts/_lib/config.js +33 -15
- package/dist/scripts/{extractSchemas.js → extractSchemasFromResourceTypeShells.js} +14 -27
- package/dist/scripts/generateDependencies.js +2 -2
- package/dist/scripts/generateSchemaShims.js +22 -4
- package/dist/scripts/{extractSubSchemaWithDefs.js → generateStandaloneSchema.js} +12 -34
- package/dist/scripts/{generateResourceTypeType.js → generateStandaloneType.js} +23 -14
- package/dist/scripts/generateTypes.js +1 -1
- package/dist/scripts/{rewriteAnchors.js → normalizeAnchorsToPointers.js} +2 -2
- package/dist/scripts/{generateResourceShells.js → wrapResourceTypesWithResourceShells.js} +12 -34
- package/package.json +15 -14
- package/src/Genesis.json +1999 -2042
- package/src/generated/{dependencies.json → dependencyMap.json} +207 -214
- package/src/generated/{resourceTypes → normalized}/Genesis.json +44 -87
- package/src/generated/resources/Genesis.json +415 -478
- package/src/generated/schemas/Genesis.json +1026 -1057
- package/src/generated/schemas/{Goal.json → standalone/Goal.json} +34 -34
- package/src/generated/schemas/{Job.json → standalone/Job.json} +85 -85
- package/src/generated/schemas/{RawStrategy.json → standalone/RawStrategy.json} +238 -263
- package/src/generated/schemas/{ResourceType.json → standalone/ResourceType.json} +60 -60
- package/src/generated/schemas/{RunnableStrategy.json → standalone/RunnableStrategy.json} +296 -321
- package/src/generated/schemas/{StrategyRun.json → standalone/StrategyRun.json} +390 -421
- package/src/generated/types/standalone/Resource_Genesis.d.ts +3 -0
- package/src/generated/types/standalone/Resource_Genesis.js +1 -0
- package/src/generated/types/standalone/Resource_Job.d.ts +3 -0
- package/src/generated/types/standalone/Resource_Job.js +1 -0
- package/src/generated/types/standalone/Resource_RawStrategy.d.ts +3 -0
- package/src/generated/types/standalone/Resource_RawStrategy.js +1 -0
- package/src/generated/types/standalone/Resource_ResourceType.d.ts +3 -0
- package/src/generated/types/standalone/Resource_ResourceType.js +1 -0
- package/src/generated/types/standalone/Resource_RunnableStrategy.d.ts +3 -0
- package/src/generated/types/standalone/Resource_RunnableStrategy.js +1 -0
- package/src/generated/types/types.d.ts +487 -548
- package/src/generated/types/types.js +1 -1
- package/src/scripts/_lib/config.ts +205 -181
- package/src/scripts/extractSchemasFromResourceTypeShells.ts +218 -0
- package/src/scripts/generateDependencies.ts +120 -120
- package/src/scripts/generateSchemaShims.ts +135 -115
- package/src/scripts/{extractSubSchemaWithDefs.ts → generateStandaloneSchema.ts} +175 -196
- package/src/scripts/{generateResourceTypeType.ts → generateStandaloneType.ts} +119 -110
- package/src/scripts/generateTypes.ts +614 -614
- package/src/scripts/{rewriteAnchors.ts → normalizeAnchorsToPointers.ts} +123 -123
- package/src/scripts/{generateResourceShells.ts → wrapResourceTypesWithResourceShells.ts} +84 -105
- package/dist/generated/types/Resource_Genesis.d.ts +0 -3
- package/dist/generated/types/Resource_Job.d.ts +0 -3
- package/dist/generated/types/Resource_RawStrategy.d.ts +0 -3
- package/dist/generated/types/Resource_ResourceType.d.ts +0 -3
- package/dist/generated/types/Resource_RunnableStrategy.d.ts +0 -3
- package/src/Roadmap.json +0 -102
- package/src/generated/types/Resource_Genesis.d.ts +0 -3
- package/src/generated/types/Resource_Genesis.js +0 -1
- package/src/generated/types/Resource_Job.d.ts +0 -3
- package/src/generated/types/Resource_Job.js +0 -1
- package/src/generated/types/Resource_RawStrategy.d.ts +0 -3
- package/src/generated/types/Resource_RawStrategy.js +0 -1
- package/src/generated/types/Resource_ResourceType.d.ts +0 -3
- package/src/generated/types/Resource_ResourceType.js +0 -1
- package/src/generated/types/Resource_RunnableStrategy.d.ts +0 -3
- package/src/generated/types/Resource_RunnableStrategy.js +0 -1
- package/src/scripts/extractSchemas.ts +0 -229
- /package/dist/generated/types/{Resource_Genesis.js → standalone/Resource_Genesis.js} +0 -0
- /package/dist/generated/types/{Resource_Job.js → standalone/Resource_Job.js} +0 -0
- /package/dist/generated/types/{Resource_RawStrategy.js → standalone/Resource_RawStrategy.js} +0 -0
- /package/dist/generated/types/{Resource_ResourceType.js → standalone/Resource_ResourceType.js} +0 -0
- /package/dist/generated/types/{Resource_RunnableStrategy.js → standalone/Resource_RunnableStrategy.js} +0 -0
- /package/dist/scripts/{extractSchemas.d.ts → extractSchemasFromResourceTypeShells.d.ts} +0 -0
- /package/dist/scripts/{extractSubSchemaWithDefs.d.ts → generateStandaloneSchema.d.ts} +0 -0
- /package/dist/scripts/{generateResourceShells.d.ts → generateStandaloneType.d.ts} +0 -0
- /package/dist/scripts/{generateResourceTypeType.d.ts → normalizeAnchorsToPointers.d.ts} +0 -0
- /package/dist/scripts/{rewriteAnchors.d.ts → wrapResourceTypesWithResourceShells.d.ts} +0 -0
- /package/src/generated/{resourceTypes → normalized}/Genesis.ts +0 -0
- /package/src/generated/schemas/{Goal.ts → standalone/Goal.ts} +0 -0
- /package/src/generated/schemas/{Job.ts → standalone/Job.ts} +0 -0
- /package/src/generated/schemas/{RawStrategy.ts → standalone/RawStrategy.ts} +0 -0
- /package/src/generated/schemas/{ResourceType.ts → standalone/ResourceType.ts} +0 -0
- /package/src/generated/schemas/{RunnableStrategy.ts → standalone/RunnableStrategy.ts} +0 -0
- /package/src/generated/schemas/{StrategyRun.ts → standalone/StrategyRun.ts} +0 -0
|
@@ -11,11 +11,11 @@ export declare class SchemaConfig {
|
|
|
11
11
|
private readonly sourceDir;
|
|
12
12
|
private readonly sourceFile;
|
|
13
13
|
private readonly normalizedDir;
|
|
14
|
-
private readonly
|
|
14
|
+
private readonly schemasDir;
|
|
15
|
+
private readonly resourcesDir;
|
|
16
|
+
private readonly dependencyMapPath;
|
|
15
17
|
private readonly typesSrcDir;
|
|
16
18
|
private readonly typesDistDir;
|
|
17
|
-
private readonly generatedResourcesDir;
|
|
18
|
-
private readonly dependencyMapPath;
|
|
19
19
|
private readonly baseUrl;
|
|
20
20
|
private readonly version;
|
|
21
21
|
constructor();
|
|
@@ -26,13 +26,19 @@ export declare class SchemaConfig {
|
|
|
26
26
|
getNormalizedDir(): string;
|
|
27
27
|
getNormalizedSourceFile(): string;
|
|
28
28
|
getNormalizedSourcePath(): string;
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
getSchemasDir(): string;
|
|
30
|
+
getSchemaPath(filename: string): string;
|
|
31
|
+
getSchemasStandaloneDir(): string;
|
|
32
|
+
getSchemaStandalonePath(filename: string): string;
|
|
31
33
|
getTypesSrcDir(): string;
|
|
32
34
|
getTypesDistDir(): string;
|
|
33
35
|
getTypesSrcPath(filename: string): string;
|
|
34
36
|
getTypesDistPath(filename: string): string;
|
|
35
|
-
|
|
37
|
+
getTypesStandaloneSrcDir(): string;
|
|
38
|
+
getTypesStandaloneDistDir(): string;
|
|
39
|
+
getTypesStandaloneSrcPath(filename: string): string;
|
|
40
|
+
getTypesStandaloneDistPath(filename: string): string;
|
|
41
|
+
getResourcesDir(): string;
|
|
36
42
|
getDependencyMapPath(): string;
|
|
37
43
|
getBaseUrl(): string;
|
|
38
44
|
getVersion(): string;
|
|
@@ -20,14 +20,14 @@ export class SchemaConfig {
|
|
|
20
20
|
this.root = getEnv('TP_SCHEMA_ROOT', process.cwd());
|
|
21
21
|
this.sourceDir = getEnv('TP_SCHEMA_SOURCE_DIR', 'src/');
|
|
22
22
|
this.sourceFile = getEnv('TP_SCHEMA_SOURCE_FILE', 'Genesis.json');
|
|
23
|
-
// Intermediate, generated artifact produced by
|
|
23
|
+
// Intermediate, generated artifact produced by normalizeAnchorsToPointers.
|
|
24
24
|
// This should NOT live next to the source-of-truth schemas.
|
|
25
|
-
this.normalizedDir = getEnv('TP_SCHEMA_NORMALIZED_DIR', 'src/generated/
|
|
26
|
-
this.
|
|
25
|
+
this.normalizedDir = getEnv('TP_SCHEMA_NORMALIZED_DIR', 'src/generated/normalized');
|
|
26
|
+
this.schemasDir = getEnv('TP_SCHEMA_SCHEMAS_DIR', 'src/generated/schemas');
|
|
27
|
+
this.resourcesDir = getEnv('TP_SCHEMA_RESOURCES_DIR', 'src/generated/resources');
|
|
28
|
+
this.dependencyMapPath = getEnv('TP_SCHEMA_DEPENDENCY_MAP_PATH', 'src/generated/dependencyMap.json');
|
|
27
29
|
this.typesSrcDir = getEnv('TP_SCHEMA_TYPES_SRC_DIR', 'src/generated/types');
|
|
28
30
|
this.typesDistDir = getEnv('TP_SCHEMA_TYPES_DIST_DIR', 'dist/generated/types');
|
|
29
|
-
this.generatedResourcesDir = getEnv('TP_SCHEMA_RESOURCES_DIR', 'src/generated/resources');
|
|
30
|
-
this.dependencyMapPath = getEnv('TP_SCHEMA_DEPENDENCY_MAP_PATH', 'src/generated/dependencies.json');
|
|
31
31
|
this.baseUrl = getEnv('TP_SCHEMA_BASE_URL', 'https://schemas.toolproof.com');
|
|
32
32
|
this.version = getEnv('TP_SCHEMA_VERSION', 'v0');
|
|
33
33
|
}
|
|
@@ -60,13 +60,19 @@ export class SchemaConfig {
|
|
|
60
60
|
getNormalizedSourcePath() {
|
|
61
61
|
return path.join(this.getNormalizedDir(), this.getNormalizedSourceFile());
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
return path.isAbsolute(this.
|
|
65
|
-
? this.
|
|
66
|
-
: path.join(this.root, this.
|
|
63
|
+
getSchemasDir() {
|
|
64
|
+
return path.isAbsolute(this.schemasDir)
|
|
65
|
+
? this.schemasDir
|
|
66
|
+
: path.join(this.root, this.schemasDir);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
return path.join(this.
|
|
68
|
+
getSchemaPath(filename) {
|
|
69
|
+
return path.join(this.getSchemasDir(), filename);
|
|
70
|
+
}
|
|
71
|
+
getSchemasStandaloneDir() {
|
|
72
|
+
return path.join(this.getSchemasDir(), 'standalone');
|
|
73
|
+
}
|
|
74
|
+
getSchemaStandalonePath(filename) {
|
|
75
|
+
return path.join(this.getSchemasStandaloneDir(), filename);
|
|
70
76
|
}
|
|
71
77
|
getTypesSrcDir() {
|
|
72
78
|
return path.isAbsolute(this.typesSrcDir)
|
|
@@ -84,10 +90,22 @@ export class SchemaConfig {
|
|
|
84
90
|
getTypesDistPath(filename) {
|
|
85
91
|
return path.join(this.getTypesDistDir(), filename);
|
|
86
92
|
}
|
|
87
|
-
|
|
88
|
-
return path.
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
getTypesStandaloneSrcDir() {
|
|
94
|
+
return path.join(this.getTypesSrcDir(), 'standalone');
|
|
95
|
+
}
|
|
96
|
+
getTypesStandaloneDistDir() {
|
|
97
|
+
return path.join(this.getTypesDistDir(), 'standalone');
|
|
98
|
+
}
|
|
99
|
+
getTypesStandaloneSrcPath(filename) {
|
|
100
|
+
return path.join(this.getTypesStandaloneSrcDir(), filename);
|
|
101
|
+
}
|
|
102
|
+
getTypesStandaloneDistPath(filename) {
|
|
103
|
+
return path.join(this.getTypesStandaloneDistDir(), filename);
|
|
104
|
+
}
|
|
105
|
+
getResourcesDir() {
|
|
106
|
+
return path.isAbsolute(this.resourcesDir)
|
|
107
|
+
? this.resourcesDir
|
|
108
|
+
: path.join(this.root, this.resourcesDir);
|
|
91
109
|
}
|
|
92
110
|
getDependencyMapPath() {
|
|
93
111
|
return path.isAbsolute(this.dependencyMapPath)
|
|
@@ -29,7 +29,7 @@ function parseArgs() {
|
|
|
29
29
|
inPath = config.getNormalizedSourcePath();
|
|
30
30
|
}
|
|
31
31
|
if (!outPath) {
|
|
32
|
-
outPath = config.
|
|
32
|
+
outPath = config.getSchemaPath(config.getSourceFile());
|
|
33
33
|
}
|
|
34
34
|
if (!topLevelId) {
|
|
35
35
|
topLevelId = config.getSchemaId('Genesis');
|
|
@@ -60,10 +60,11 @@ function parseArgs() {
|
|
|
60
60
|
}
|
|
61
61
|
return { inPath, outPath, topLevelId };
|
|
62
62
|
}
|
|
63
|
-
//
|
|
64
|
-
|
|
63
|
+
// ATTENTION: we don't want heuristic behavior.
|
|
64
|
+
// Heuristic: determine if a node is a Type shell
|
|
65
|
+
function isTypeShell(node) {
|
|
65
66
|
return (node && typeof node === "object" && !Array.isArray(node) &&
|
|
66
|
-
// Treat any object that has an 'nucleusSchema' AND 'identity' as a Type
|
|
67
|
+
// Treat any object that has an 'nucleusSchema' AND 'identity' as a Type shell
|
|
67
68
|
// This prevents false positives where 'nucleusSchema' is just a regular schema property
|
|
68
69
|
node.nucleusSchema && typeof node.nucleusSchema === "object" &&
|
|
69
70
|
node.identity && typeof node.identity === "string");
|
|
@@ -91,7 +92,7 @@ function mergeDefs(target, source, label) {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
|
-
// Deeply traverse an object replacing any Type
|
|
95
|
+
// Deeply traverse an object replacing any Type shell with its nucleusSchema,
|
|
95
96
|
// and hoist its inner $defs to topDefs. Prevent infinite recursion with a visited set.
|
|
96
97
|
function unwrapTypes(node, topDefs, labelPath = [], visited = new Set()) {
|
|
97
98
|
if (node && typeof node === "object") {
|
|
@@ -99,12 +100,12 @@ function unwrapTypes(node, topDefs, labelPath = [], visited = new Set()) {
|
|
|
99
100
|
return node; // avoid cycles
|
|
100
101
|
visited.add(node);
|
|
101
102
|
}
|
|
102
|
-
if (
|
|
103
|
+
if (isTypeShell(node)) {
|
|
103
104
|
const env = node;
|
|
104
105
|
const inner = env.nucleusSchema;
|
|
105
106
|
// Hoist inner $defs before stripping
|
|
106
107
|
mergeDefs(topDefs, inner, labelPath.join("_"));
|
|
107
|
-
// Return the inner schema itself, after also unwrapping any nested
|
|
108
|
+
// Return the inner schema itself, after also unwrapping any nested shells it may contain
|
|
108
109
|
const unwrappedInner = unwrapTypes(inner, topDefs, labelPath.concat([String(env.identity || "env")]), visited);
|
|
109
110
|
return unwrappedInner;
|
|
110
111
|
}
|
|
@@ -115,7 +116,7 @@ function unwrapTypes(node, topDefs, labelPath = [], visited = new Set()) {
|
|
|
115
116
|
const out = {};
|
|
116
117
|
for (const [k, v] of Object.entries(node)) {
|
|
117
118
|
if (k === "$defs" && v && typeof v === "object" && !Array.isArray(v)) {
|
|
118
|
-
// Process nested $defs: unwrap each entry value if it's a Type
|
|
119
|
+
// Process nested $defs: unwrap each entry value if it's a Type shell
|
|
119
120
|
const defsOut = {};
|
|
120
121
|
for (const [dk, dv] of Object.entries(v)) {
|
|
121
122
|
const unwrapped = unwrapTypes(dv, topDefs, labelPath.concat(["$defs", dk]), visited);
|
|
@@ -140,10 +141,11 @@ function extractSchemaLogic(doc, topLevelId) {
|
|
|
140
141
|
throw new Error("Input must be a Type JSON with an nucleusSchema at the top level");
|
|
141
142
|
}
|
|
142
143
|
const topSchema = doc.nucleusSchema;
|
|
144
|
+
// Collect $defs so that any '#/$defs/...' pointers can be resolved from the root.
|
|
143
145
|
const outDefs = {};
|
|
144
146
|
// Seed with top-level $defs (if any) before unwrapping
|
|
145
147
|
mergeDefs(outDefs, topSchema, "top");
|
|
146
|
-
// Unwrap the entire top schema tree so that any nested Type
|
|
148
|
+
// Unwrap the entire top schema tree so that any nested Type shells become raw schemas
|
|
147
149
|
const flattened = unwrapTypes(topSchema, outDefs, ["nucleusSchema"]);
|
|
148
150
|
// Assemble output: force $schema, optionally set $id, hoist collected $defs
|
|
149
151
|
let base;
|
|
@@ -166,7 +168,7 @@ function extractSchemaLogic(doc, topLevelId) {
|
|
|
166
168
|
if (!output.$id) {
|
|
167
169
|
throw new Error("Flattened schema must define $id. Provide it via CLI --id or include $id in the source nucleusSchema.");
|
|
168
170
|
}
|
|
169
|
-
//
|
|
171
|
+
// Hoist collected defs into output.$defs, taking care not to clobber any existing
|
|
170
172
|
if (!("$defs" in output))
|
|
171
173
|
output.$defs = {};
|
|
172
174
|
const finalDefs = output.$defs || {};
|
|
@@ -175,8 +177,8 @@ function extractSchemaLogic(doc, topLevelId) {
|
|
|
175
177
|
finalDefs[k] = v;
|
|
176
178
|
}
|
|
177
179
|
output.$defs = finalDefs;
|
|
178
|
-
//
|
|
179
|
-
return
|
|
180
|
+
// Preserve natural key ordering (do not reorder for readability)
|
|
181
|
+
return output;
|
|
180
182
|
}
|
|
181
183
|
function main() {
|
|
182
184
|
const { inPath, outPath, topLevelId } = parseArgs();
|
|
@@ -192,19 +194,4 @@ function main() {
|
|
|
192
194
|
fs.writeFileSync(outPath, JSON.stringify(ordered, null, 4), "utf8");
|
|
193
195
|
console.log(`Wrote flattened schema to ${outPath}`);
|
|
194
196
|
}
|
|
195
|
-
function orderKeys(obj, preferred) {
|
|
196
|
-
if (Array.isArray(obj))
|
|
197
|
-
return obj.map((v) => orderKeys(v, preferred));
|
|
198
|
-
if (!obj || typeof obj !== "object")
|
|
199
|
-
return obj;
|
|
200
|
-
const keys = Object.keys(obj);
|
|
201
|
-
const sorted = [
|
|
202
|
-
...preferred.filter((k) => keys.includes(k)),
|
|
203
|
-
...keys.filter((k) => !preferred.includes(k)).sort()
|
|
204
|
-
];
|
|
205
|
-
const out = {};
|
|
206
|
-
for (const k of sorted)
|
|
207
|
-
out[k] = orderKeys(obj[k], preferred);
|
|
208
|
-
return out;
|
|
209
|
-
}
|
|
210
197
|
main();
|
|
@@ -81,10 +81,10 @@ function generateDependencyMapLogic(doc) {
|
|
|
81
81
|
}
|
|
82
82
|
async function main() {
|
|
83
83
|
const config = getConfig();
|
|
84
|
-
const inPath = config.
|
|
84
|
+
const inPath = config.getSchemaPath("Genesis.json");
|
|
85
85
|
const outPath = config.getDependencyMapPath();
|
|
86
86
|
if (!fs.existsSync(inPath)) {
|
|
87
|
-
console.error(`Genesis schema not found at ${inPath}. Run
|
|
87
|
+
console.error(`Genesis schema not found at ${inPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
88
88
|
process.exit(1);
|
|
89
89
|
}
|
|
90
90
|
try {
|
|
@@ -9,8 +9,9 @@ import { getConfig } from './_lib/config.js';
|
|
|
9
9
|
* and type inference when importing schemas in TypeScript.
|
|
10
10
|
*
|
|
11
11
|
* Generates shims for:
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
12
|
+
* - schemas dir: config.getSchemasDir() (schema files)
|
|
13
|
+
* - standalone schemas dir: config.getSchemasStandaloneDir() (standalone schema files)
|
|
14
|
+
* - resources dir: config.getResourcesDir() (resource envelope files)
|
|
14
15
|
*
|
|
15
16
|
* Usage: node ./dist/scripts/generateSchemaShims.js
|
|
16
17
|
*/
|
|
@@ -42,8 +43,9 @@ function getShimsForFiles(jsonFiles, variableName) {
|
|
|
42
43
|
}
|
|
43
44
|
async function main() {
|
|
44
45
|
const config = getConfig();
|
|
45
|
-
const schemasDir = config.
|
|
46
|
-
const
|
|
46
|
+
const schemasDir = config.getSchemasDir();
|
|
47
|
+
const standaloneSchemasDir = config.getSchemasStandaloneDir();
|
|
48
|
+
const resourcesDir = config.getResourcesDir();
|
|
47
49
|
const generatedResourceTypesDir = config.getNormalizedDir();
|
|
48
50
|
let totalCount = 0;
|
|
49
51
|
// Process schemas directory
|
|
@@ -62,6 +64,22 @@ async function main() {
|
|
|
62
64
|
else {
|
|
63
65
|
console.warn(`Schemas directory not found at ${schemasDir}`);
|
|
64
66
|
}
|
|
67
|
+
// Process standalone schemas directory
|
|
68
|
+
if (fs.existsSync(standaloneSchemasDir)) {
|
|
69
|
+
const files = fs.readdirSync(standaloneSchemasDir);
|
|
70
|
+
const jsonFiles = files.filter(f => f.endsWith('.json') && !f.startsWith('.'));
|
|
71
|
+
const shims = getShimsForFiles(jsonFiles, 'schema');
|
|
72
|
+
for (const [tsFile, content] of Object.entries(shims)) {
|
|
73
|
+
const tsPath = path.join(standaloneSchemasDir, tsFile);
|
|
74
|
+
fs.writeFileSync(tsPath, content, 'utf-8');
|
|
75
|
+
console.log(`Generated ${tsFile} in ${standaloneSchemasDir}`);
|
|
76
|
+
totalCount++;
|
|
77
|
+
}
|
|
78
|
+
console.log(`Generated ${jsonFiles.length} TypeScript standalone schema shims in ${standaloneSchemasDir}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Standalone schemas are optional
|
|
82
|
+
}
|
|
65
83
|
// Process resources directory
|
|
66
84
|
if (fs.existsSync(resourcesDir)) {
|
|
67
85
|
const files = fs.readdirSync(resourcesDir);
|
|
@@ -2,26 +2,17 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { getConfig } from './_lib/config.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* object holding all direct & transitive local $defs dependencies (by #/$defs/... $ref).
|
|
8
|
-
*
|
|
9
|
-
* Genesis.json itself is left unchanged.
|
|
5
|
+
* Create a standalone JSON Schema for a single $defs entry under Genesis.json,
|
|
6
|
+
* embedding all direct & transitive local $defs dependencies.
|
|
10
7
|
*
|
|
11
8
|
* Usage:
|
|
12
|
-
* node ./dist/scripts/
|
|
13
|
-
*
|
|
14
|
-
* Writes: src/genesis/generated/schemas/<DefName>.json
|
|
9
|
+
* node ./dist/scripts/generateStandaloneSchema.js --name <DefName>
|
|
15
10
|
*/
|
|
16
11
|
/**
|
|
17
|
-
* Pure function to extract a subschema and its dependencies from a genesis
|
|
12
|
+
* Pure function to extract a subschema and its dependencies from a flattened genesis schema.
|
|
18
13
|
* Performs no I/O operations.
|
|
19
|
-
*
|
|
20
|
-
* @param genesis The root Genesis schema object
|
|
21
|
-
* @param name The name of the definition to extract
|
|
22
|
-
* @returns The standalone subschema
|
|
23
14
|
*/
|
|
24
|
-
function
|
|
15
|
+
function extractStandaloneSubschemaLogic(genesis, name) {
|
|
25
16
|
const rootDefs = genesis.$defs;
|
|
26
17
|
if (!rootDefs || typeof rootDefs !== 'object') {
|
|
27
18
|
throw new Error('No $defs object found in Genesis.json');
|
|
@@ -30,13 +21,10 @@ function extractSubSchemaLogic(genesis, name) {
|
|
|
30
21
|
if (!target) {
|
|
31
22
|
throw new Error(`Subschema named '${name}' not found under $defs in Genesis.json`);
|
|
32
23
|
}
|
|
33
|
-
// Collect transitive local $defs names referenced by target
|
|
34
24
|
const needed = collectLocalDefClosure(target, rootDefs);
|
|
35
|
-
// Build output schema: clone target and attach collected subset as $defs
|
|
36
25
|
const targetClone = deepClone(target);
|
|
37
26
|
const defsOut = {};
|
|
38
27
|
for (const defName of needed) {
|
|
39
|
-
// Avoid including the target itself inside its own $defs (mirrors previous pattern)
|
|
40
28
|
if (defName === name)
|
|
41
29
|
continue;
|
|
42
30
|
const defSchema = rootDefs[defName];
|
|
@@ -46,7 +34,6 @@ function extractSubSchemaLogic(genesis, name) {
|
|
|
46
34
|
}
|
|
47
35
|
defsOut[defName] = deepClone(defSchema);
|
|
48
36
|
}
|
|
49
|
-
// Merge any pre-existing inner $defs of targetClone (if present) giving precedence to collected ones
|
|
50
37
|
const existingInner = isObject(targetClone.$defs) ? targetClone.$defs : {};
|
|
51
38
|
targetClone.$defs = { ...existingInner, ...defsOut };
|
|
52
39
|
return targetClone;
|
|
@@ -58,29 +45,26 @@ async function main() {
|
|
|
58
45
|
console.error('Missing --name <DefName> argument');
|
|
59
46
|
process.exit(1);
|
|
60
47
|
}
|
|
61
|
-
const schemasDir = config.
|
|
48
|
+
const schemasDir = config.getSchemasDir();
|
|
62
49
|
const genesisPath = path.join(schemasDir, config.getSourceFile());
|
|
63
|
-
const outPath = config.
|
|
50
|
+
const outPath = config.getSchemaStandalonePath(`${name}.json`);
|
|
64
51
|
if (!fs.existsSync(genesisPath)) {
|
|
65
|
-
console.error(`Genesis.json not found at ${genesisPath}
|
|
52
|
+
console.error(`Genesis.json not found at ${genesisPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
66
53
|
process.exit(1);
|
|
67
54
|
}
|
|
68
55
|
const raw = fs.readFileSync(genesisPath, 'utf-8');
|
|
69
56
|
const genesis = JSON.parse(raw);
|
|
70
57
|
try {
|
|
71
|
-
|
|
72
|
-
const result = extractSubSchemaLogic(genesis, name);
|
|
73
|
-
// I/O: Write the result
|
|
58
|
+
const result = extractStandaloneSubschemaLogic(genesis, name);
|
|
74
59
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
75
60
|
fs.writeFileSync(outPath, JSON.stringify(result, null, 2) + '\n');
|
|
76
|
-
console.log(`
|
|
61
|
+
console.log(`Created standalone subschema '${name}' -> ${outPath}`);
|
|
77
62
|
}
|
|
78
63
|
catch (error) {
|
|
79
64
|
console.error(error.message);
|
|
80
65
|
process.exit(1);
|
|
81
66
|
}
|
|
82
67
|
}
|
|
83
|
-
// ---- Helpers ----
|
|
84
68
|
function parseArgs(args) {
|
|
85
69
|
let name;
|
|
86
70
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -110,26 +94,22 @@ function deepClone(v) {
|
|
|
110
94
|
return v;
|
|
111
95
|
}
|
|
112
96
|
function extractPointerDefName(ref) {
|
|
113
|
-
// Accept refs like '#/$defs/Name' only (single-level under $defs)
|
|
114
97
|
if (!ref || !ref.startsWith('#/'))
|
|
115
98
|
return null;
|
|
116
|
-
const parts = ref.slice(2).split('/');
|
|
99
|
+
const parts = ref.slice(2).split('/');
|
|
117
100
|
if (parts.length !== 2)
|
|
118
101
|
return null;
|
|
119
102
|
if (parts[0] !== '$defs')
|
|
120
103
|
return null;
|
|
121
|
-
// Decode JSON Pointer tokens for the def name
|
|
122
104
|
const name = parts[1].replace(/~1/g, '/').replace(/~0/g, '~');
|
|
123
105
|
return name;
|
|
124
106
|
}
|
|
125
107
|
function resolveRefToDefName(ref, rootDefs) {
|
|
126
108
|
if (!ref)
|
|
127
109
|
return null;
|
|
128
|
-
// Case 1: JSON Pointer into $defs: '#/$defs/Name'
|
|
129
110
|
const byPointer = extractPointerDefName(ref);
|
|
130
111
|
if (byPointer)
|
|
131
112
|
return byPointer;
|
|
132
|
-
// Case 2: Anchor ref: '#Name' -> find a def whose nucleusSchema.$anchor equals 'Name'
|
|
133
113
|
if (ref.startsWith('#') && !ref.startsWith('#/')) {
|
|
134
114
|
const anchor = ref.slice(1);
|
|
135
115
|
if (!anchor)
|
|
@@ -137,8 +117,6 @@ function resolveRefToDefName(ref, rootDefs) {
|
|
|
137
117
|
for (const [defName, defSchema] of Object.entries(rootDefs)) {
|
|
138
118
|
if (!defSchema || typeof defSchema !== 'object')
|
|
139
119
|
continue;
|
|
140
|
-
// Flattened Genesis has defs as the extraction schema itself (with $anchor at the top level).
|
|
141
|
-
// Unflattened may have { nucleusSchema: { $anchor } } envelopes. Support both.
|
|
142
120
|
const topLevelAnchor = defSchema.$anchor;
|
|
143
121
|
const nested = defSchema.nucleusSchema;
|
|
144
122
|
const nestedAnchor = nested && typeof nested === 'object' ? nested.$anchor : undefined;
|
|
@@ -176,7 +154,7 @@ function collectLocalDefClosure(node, rootDefs) {
|
|
|
176
154
|
const name = queue.shift();
|
|
177
155
|
const def = rootDefs[name];
|
|
178
156
|
if (!def)
|
|
179
|
-
continue;
|
|
157
|
+
continue;
|
|
180
158
|
visit(def);
|
|
181
159
|
}
|
|
182
160
|
return needed;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { getConfig } from './_lib/config.js';
|
|
3
3
|
/**
|
|
4
|
-
* Generate a typed Resource variant where `
|
|
4
|
+
* Generate a typed Resource variant where `nucleus` is typed to a specific schema
|
|
5
5
|
* extracted under the configured output directory.
|
|
6
6
|
*
|
|
7
|
-
* Usage: node ./dist/scripts/
|
|
7
|
+
* Usage: node ./dist/scripts/generateStandaloneType.js --name Job
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Pure function to generate the typed Resource D.TS content.
|
|
@@ -12,10 +12,10 @@ import { getConfig } from './_lib/config.js';
|
|
|
12
12
|
* @param name The name of the schema
|
|
13
13
|
* @returns The TypeScript D.TS file content
|
|
14
14
|
*/
|
|
15
|
-
function
|
|
15
|
+
function generateStandaloneTypeLogic(name) {
|
|
16
16
|
const header = '// Auto-generated strict composite type. Do not edit.\n';
|
|
17
|
-
const ts = `import type {
|
|
18
|
-
`export type Resource_${name} =
|
|
17
|
+
const ts = `import type { ShellMaterializedBase, ${name} as NucleusSchema } from '../types.js';\n` +
|
|
18
|
+
`export type Resource_${name} = ShellMaterializedBase & { nucleus: NucleusSchema };\n`;
|
|
19
19
|
return header + ts;
|
|
20
20
|
}
|
|
21
21
|
async function main() {
|
|
@@ -25,9 +25,18 @@ async function main() {
|
|
|
25
25
|
console.error('Missing --name <SchemaBasename> argument');
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
|
-
const inPath =
|
|
28
|
+
const inPath = name === 'Genesis'
|
|
29
|
+
? config.getSchemaPath('Genesis.json')
|
|
30
|
+
: config.getSchemaStandalonePath(`${name}.json`);
|
|
29
31
|
if (!fs.existsSync(inPath)) {
|
|
30
|
-
|
|
32
|
+
if (name === 'Genesis') {
|
|
33
|
+
console.error(`Schema file not found: ${inPath}`);
|
|
34
|
+
console.error('Run extractSchemasFromResourceTypeShells first.');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.error(`Standalone schema file not found: ${inPath}`);
|
|
38
|
+
console.error(`Run generateStandaloneSchema -- --name ${name} first.`);
|
|
39
|
+
}
|
|
31
40
|
process.exit(1);
|
|
32
41
|
}
|
|
33
42
|
// Basic validation against the expected shape of nucleusSchema.
|
|
@@ -47,16 +56,16 @@ async function main() {
|
|
|
47
56
|
if (parsed.type && parsed.type !== 'object') {
|
|
48
57
|
console.warn(`Warning: nucleusSchema usually has type: 'object' but this schema has type: '${parsed.type}'. Proceeding.`);
|
|
49
58
|
}
|
|
50
|
-
const tsContent =
|
|
59
|
+
const tsContent = generateStandaloneTypeLogic(name);
|
|
51
60
|
const jsContent = 'export {}\n';
|
|
52
61
|
// Output setup
|
|
53
62
|
const outName = `Resource_${name}.d.ts`;
|
|
54
63
|
const outJsName = `Resource_${name}.js`;
|
|
55
64
|
// Process src output
|
|
56
|
-
const outDir = config.
|
|
65
|
+
const outDir = config.getTypesStandaloneSrcDir();
|
|
57
66
|
fs.mkdirSync(outDir, { recursive: true });
|
|
58
|
-
const outPath = config.
|
|
59
|
-
const outJsPath = config.
|
|
67
|
+
const outPath = config.getTypesStandaloneSrcPath(outName);
|
|
68
|
+
const outJsPath = config.getTypesStandaloneSrcPath(outJsName);
|
|
60
69
|
fs.writeFileSync(outPath, tsContent, 'utf8');
|
|
61
70
|
console.log(`Wrote ${outPath}`);
|
|
62
71
|
if (!fs.existsSync(outJsPath)) {
|
|
@@ -64,10 +73,10 @@ async function main() {
|
|
|
64
73
|
console.log(`Wrote ${outJsPath}`);
|
|
65
74
|
}
|
|
66
75
|
// Process dist output
|
|
67
|
-
const distLibDir = config.
|
|
76
|
+
const distLibDir = config.getTypesStandaloneDistDir();
|
|
68
77
|
fs.mkdirSync(distLibDir, { recursive: true });
|
|
69
|
-
const distDtsPath = config.
|
|
70
|
-
const distJsPath = config.
|
|
78
|
+
const distDtsPath = config.getTypesStandaloneDistPath(outName);
|
|
79
|
+
const distJsPath = config.getTypesStandaloneDistPath(outJsName);
|
|
71
80
|
fs.writeFileSync(distDtsPath, tsContent, 'utf8');
|
|
72
81
|
fs.writeFileSync(distJsPath, jsContent, 'utf8');
|
|
73
82
|
console.log(`Wrote ${distDtsPath}`);
|
|
@@ -4,7 +4,7 @@ import { compileFromFile } from 'json-schema-to-typescript';
|
|
|
4
4
|
import { getConfig } from './_lib/config.js';
|
|
5
5
|
const config = getConfig();
|
|
6
6
|
const projectRoot = config.getRoot();
|
|
7
|
-
const inputDir = config.
|
|
7
|
+
const inputDir = config.getSchemasDir();
|
|
8
8
|
// We emit under src/genesis/generated/types and dist/genesis/generated/types
|
|
9
9
|
const srcLibTypesDir = config.getTypesSrcDir();
|
|
10
10
|
const srcLibOutputPath = config.getTypesSrcPath('types.d.ts');
|
|
@@ -9,7 +9,7 @@ import { getConfig } from './_lib/config.js';
|
|
|
9
9
|
* @param input The schema object to process
|
|
10
10
|
* @returns A new schema object with rewritten references
|
|
11
11
|
*/
|
|
12
|
-
function
|
|
12
|
+
function normalizeAnchorsToPointersToPointers(input) {
|
|
13
13
|
if (!input || typeof input !== "object")
|
|
14
14
|
return input;
|
|
15
15
|
// Deep clone the input to ensure the function is pure (no side effects on input)
|
|
@@ -84,7 +84,7 @@ async function main() {
|
|
|
84
84
|
process.exit(1);
|
|
85
85
|
}
|
|
86
86
|
// Rewrite anchors in the nucleusSchema (pure function call)
|
|
87
|
-
genesis.nucleusSchema =
|
|
87
|
+
genesis.nucleusSchema = normalizeAnchorsToPointersToPointers(genesis.nucleusSchema);
|
|
88
88
|
// Write normalized version
|
|
89
89
|
fs.mkdirSync(path.dirname(normalizedPath), { recursive: true });
|
|
90
90
|
fs.writeFileSync(normalizedPath, JSON.stringify(genesis, null, 4), 'utf-8');
|
|
@@ -2,69 +2,49 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { getConfig } from './_lib/config.js';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* This script wraps each ResourceType definition (from $defs) with a Resource envelope
|
|
5
|
+
* Wrap each ResourceType definition (from Genesis.nucleusSchema.$defs) with a Resource shell
|
|
8
6
|
* that conforms to the Resource.nucleusSchema pattern defined in Genesis.json.
|
|
9
|
-
*
|
|
10
|
-
* For the top-level Genesis ResourceType, extractedData is set to {} to avoid
|
|
11
|
-
* duplicating the entire $defs object.
|
|
12
|
-
*
|
|
13
|
-
* Resource identities follow the pattern RESOURCE-{Name} where Name is the key
|
|
14
|
-
* from the $defs object. Genesis itself uses RESOURCE-Genesis.
|
|
15
|
-
*
|
|
16
|
-
* Usage: node ./dist/scripts/generateResourceEnvelopes.js
|
|
17
7
|
*/
|
|
18
|
-
|
|
19
|
-
* Pure function to generate resource envelopes from a Genesis schema.
|
|
20
|
-
*
|
|
21
|
-
* @param genesis The Genesis schema object
|
|
22
|
-
* @returns A record mapping resource names to their envelopes
|
|
23
|
-
*/
|
|
24
|
-
function generateResourceEnvelopesLogic(genesis) {
|
|
8
|
+
function generateResourceShellLogic(genesis) {
|
|
25
9
|
if (!genesis.nucleusSchema || !genesis.nucleusSchema.$defs) {
|
|
26
10
|
throw new Error('Genesis.json must have nucleusSchema.$defs');
|
|
27
11
|
}
|
|
28
12
|
const defs = genesis.nucleusSchema.$defs;
|
|
29
13
|
const defKeys = Object.keys(defs);
|
|
30
|
-
// Generate Resource envelopes
|
|
31
14
|
const resources = {};
|
|
32
15
|
// Genesis timestamp: 2025-11-30T00:00:00.000Z marks the genesis of ToolProof
|
|
33
16
|
const genesisTimestamp = '2025-11-30T00:00:00.000Z';
|
|
34
|
-
// First entry is Genesis itself with empty extractedData
|
|
35
17
|
resources['Genesis'] = {
|
|
36
18
|
identity: 'RESOURCE-Genesis',
|
|
37
|
-
|
|
19
|
+
resourceTypeHandle: 'TYPE-ResourceType',
|
|
38
20
|
creationContext: {
|
|
39
|
-
|
|
40
|
-
|
|
21
|
+
resourceRoleHandle: 'ROLE-Genesis',
|
|
22
|
+
jobStepHandle: 'JOB_STEP-Genesis'
|
|
41
23
|
},
|
|
42
24
|
kind: 'materialized',
|
|
43
25
|
timestamp: genesisTimestamp,
|
|
44
|
-
|
|
26
|
+
nucleus: {}
|
|
45
27
|
};
|
|
46
|
-
// Generate resources for all other $defs
|
|
47
28
|
defKeys.forEach((defName) => {
|
|
48
29
|
const defValue = defs[defName];
|
|
49
30
|
resources[defName] = {
|
|
50
31
|
identity: `RESOURCE-${defName}`,
|
|
51
|
-
|
|
32
|
+
resourceTypeHandle: 'TYPE-ResourceType',
|
|
52
33
|
creationContext: {
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
resourceRoleHandle: 'ROLE-Genesis',
|
|
35
|
+
jobStepHandle: `JOB_STEP-${defName}`
|
|
55
36
|
},
|
|
56
37
|
kind: 'materialized',
|
|
57
38
|
timestamp: genesisTimestamp,
|
|
58
|
-
|
|
39
|
+
nucleus: defValue
|
|
59
40
|
};
|
|
60
41
|
});
|
|
61
42
|
return resources;
|
|
62
43
|
}
|
|
63
44
|
async function main() {
|
|
64
45
|
const config = getConfig();
|
|
65
|
-
// Use normalized version with anchor refs rewritten to pointers
|
|
66
46
|
const genesisSourcePath = config.getNormalizedSourcePath();
|
|
67
|
-
const outputPath = path.join(config.
|
|
47
|
+
const outputPath = path.join(config.getResourcesDir(), 'Genesis.json');
|
|
68
48
|
if (!fs.existsSync(genesisSourcePath)) {
|
|
69
49
|
console.error(`Genesis source file not found at ${genesisSourcePath}`);
|
|
70
50
|
process.exit(1);
|
|
@@ -72,11 +52,9 @@ async function main() {
|
|
|
72
52
|
const raw = fs.readFileSync(genesisSourcePath, 'utf-8');
|
|
73
53
|
const genesis = JSON.parse(raw);
|
|
74
54
|
try {
|
|
75
|
-
const resources =
|
|
76
|
-
// Ensure output directory exists
|
|
55
|
+
const resources = generateResourceShellLogic(genesis);
|
|
77
56
|
const outputDir = path.dirname(outputPath);
|
|
78
57
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
79
|
-
// Write the generated resources file
|
|
80
58
|
fs.writeFileSync(outputPath, JSON.stringify(resources, null, 4) + '\n', 'utf-8');
|
|
81
59
|
console.log(`Generated ${Object.keys(resources).length} Resource envelopes -> ${outputPath}`);
|
|
82
60
|
}
|