@toolproof-core/schema 1.0.4 → 1.0.6
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/constants/constants.d.ts +60 -0
- package/dist/generated/constants/constants.js +60 -0
- package/dist/generated/normalized/Genesis.json +0 -261
- package/dist/generated/resources/Genesis.json +0 -299
- package/dist/generated/schemas/Genesis.json +0 -150
- package/dist/generated/schemas/standalone/Goal.json +0 -33
- package/dist/generated/schemas/standalone/Job.json +0 -42
- package/dist/generated/schemas/standalone/RawStrategy.json +0 -46
- package/dist/generated/schemas/standalone/ResourceType.json +0 -34
- package/dist/generated/schemas/standalone/RunnableStrategy.json +0 -51
- package/dist/generated/schemas/standalone/StrategyRun.json +0 -65
- package/dist/generated/{typesTS → types}/standalone/Resource_Genesis.d.ts +1 -1
- package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_Job.d.ts +1 -1
- package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_RawStrategy.d.ts +1 -1
- package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_ResourceType.d.ts +1 -1
- package/dist/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.d.ts +1 -1
- package/dist/generated/{typesTS/typesTS.d.ts → types/types.d.ts} +13 -49
- package/dist/index.d.ts +7 -6
- package/dist/index.js +1 -0
- package/dist/scripts/_lib/config.d.ts +15 -12
- package/dist/scripts/_lib/config.js +34 -27
- package/dist/scripts/generateConstants.d.ts +12 -0
- package/dist/scripts/generateConstants.js +179 -0
- package/dist/scripts/generateSchemaShims.js +2 -2
- package/dist/scripts/generateStandaloneSchema.js +1 -1
- package/dist/scripts/{generateStandaloneTypeTS.js → generateStandaloneType.js} +9 -9
- package/dist/scripts/generateTerminals.js +58 -0
- package/dist/scripts/generateTypes.d.ts +1 -0
- package/dist/scripts/{generateTypesTS.js → generateTypes.js} +11 -11
- package/dist/scripts/normalizeAnchorsToPointers.d.ts +1 -1
- package/dist/scripts/normalizeAnchorsToPointers.js +33 -12
- package/package.json +7 -5
- package/src/Genesis.json +0 -174
- package/src/generated/constants/constants.ts +61 -0
- package/src/generated/dependencies/dependencyMap.json +2 -14
- package/src/generated/dependencies/terminals.json +12 -0
- package/src/generated/normalized/Genesis.json +0 -261
- package/src/generated/resources/Genesis.json +0 -299
- package/src/generated/schemas/Genesis.json +0 -150
- package/src/generated/schemas/standalone/Goal.json +0 -33
- package/src/generated/schemas/standalone/Job.json +0 -42
- package/src/generated/schemas/standalone/RawStrategy.json +0 -46
- package/src/generated/schemas/standalone/ResourceType.json +0 -34
- package/src/generated/schemas/standalone/RunnableStrategy.json +0 -51
- package/src/generated/schemas/standalone/StrategyRun.json +0 -65
- package/src/generated/{typesTS → types}/standalone/Resource_Genesis.d.ts +1 -1
- package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_Job.d.ts +1 -1
- package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_RawStrategy.d.ts +1 -1
- package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_ResourceType.d.ts +1 -1
- package/src/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.d.ts +1 -1
- package/src/generated/{typesTS/typesTS.d.ts → types/types.d.ts} +13 -49
- package/src/index.ts +9 -7
- package/src/scripts/_lib/config.ts +39 -29
- package/src/scripts/generateConstants.ts +217 -0
- package/src/scripts/generateSchemaShims.ts +2 -2
- package/src/scripts/generateStandaloneSchema.ts +1 -1
- package/src/scripts/{generateStandaloneTypeTS.ts → generateStandaloneType.ts} +9 -9
- package/src/scripts/generateTerminals.ts +73 -0
- package/src/scripts/{generateTypesTS.ts → generateTypes.ts} +11 -11
- package/src/scripts/normalizeAnchorsToPointers.ts +38 -12
- /package/dist/generated/{typesTS → types}/standalone/Resource_Genesis.js +0 -0
- /package/dist/generated/{typesTS → types}/standalone/Resource_Job.js +0 -0
- /package/dist/generated/{typesTS → types}/standalone/Resource_RawStrategy.js +0 -0
- /package/dist/generated/{typesTS → types}/standalone/Resource_ResourceType.js +0 -0
- /package/dist/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.js +0 -0
- /package/dist/generated/{typesTS/typesTS.js → types/types.js} +0 -0
- /package/dist/scripts/{generateStandaloneTypeTS.d.ts → generateStandaloneType.d.ts} +0 -0
- /package/dist/scripts/{generateTypesTS.d.ts → generateTerminals.d.ts} +0 -0
- /package/src/generated/{typesTS → types}/standalone/Resource_Genesis.js +0 -0
- /package/src/generated/{typesTS → types}/standalone/Resource_Job.js +0 -0
- /package/src/generated/{typesTS → types}/standalone/Resource_RawStrategy.js +0 -0
- /package/src/generated/{typesTS → types}/standalone/Resource_ResourceType.js +0 -0
- /package/src/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.js +0 -0
- /package/src/generated/{typesTS/typesTS.js → types/types.js} +0 -0
|
@@ -12,10 +12,11 @@ export declare class SchemaConfig {
|
|
|
12
12
|
private readonly sourceFile;
|
|
13
13
|
private readonly normalizedDir;
|
|
14
14
|
private readonly schemasDir;
|
|
15
|
+
private readonly constantsDir;
|
|
15
16
|
private readonly resourcesDir;
|
|
16
17
|
private readonly dependencyMapPath;
|
|
17
|
-
private readonly
|
|
18
|
-
private readonly
|
|
18
|
+
private readonly typesSrcDir;
|
|
19
|
+
private readonly typesDistDir;
|
|
19
20
|
private readonly baseUrl;
|
|
20
21
|
private readonly version;
|
|
21
22
|
constructor();
|
|
@@ -28,16 +29,18 @@ export declare class SchemaConfig {
|
|
|
28
29
|
getNormalizedSourcePath(): string;
|
|
29
30
|
getSchemasDir(): string;
|
|
30
31
|
getSchemaPath(filename: string): string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
getConstantsDir(): string;
|
|
33
|
+
getConstantsPath(filename: string): string;
|
|
34
|
+
getStandaloneSchemaDir(): string;
|
|
35
|
+
getStandaloneSchemaPath(filename: string): string;
|
|
36
|
+
getTypesSrcDir(): string;
|
|
37
|
+
getTypesDistDir(): string;
|
|
38
|
+
getTypesSrcPath(filename: string): string;
|
|
39
|
+
getTypesDistPath(filename: string): string;
|
|
40
|
+
getStandaloneTypeSrcDir(): string;
|
|
41
|
+
getStandaloneTypeDistDir(): string;
|
|
42
|
+
getStandaloneTypeSrcPath(filename: string): string;
|
|
43
|
+
getStandaloneTypeDistPath(filename: string): string;
|
|
41
44
|
getResourcesDir(): string;
|
|
42
45
|
getDependencyMapPath(): string;
|
|
43
46
|
getBaseUrl(): string;
|
|
@@ -20,14 +20,13 @@ 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 normalizeAnchorsToPointers.
|
|
24
|
-
// This should NOT live next to the source-of-truth schemas.
|
|
25
23
|
this.normalizedDir = getEnv('TP_SCHEMA_NORMALIZED_DIR', 'src/generated/normalized');
|
|
26
24
|
this.schemasDir = getEnv('TP_SCHEMA_SCHEMAS_DIR', 'src/generated/schemas');
|
|
25
|
+
this.constantsDir = getEnv('TP_SCHEMA_CONSTANTS_DIR', 'src/generated/constants');
|
|
27
26
|
this.resourcesDir = getEnv('TP_SCHEMA_RESOURCES_DIR', 'src/generated/resources');
|
|
28
27
|
this.dependencyMapPath = getEnv('TP_SCHEMA_DEPENDENCY_MAP_PATH', 'src/generated/dependencies/dependencyMap.json');
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
28
|
+
this.typesSrcDir = getEnv('TP_SCHEMA_TYPES_SRC_DIR', 'src/generated/types');
|
|
29
|
+
this.typesDistDir = getEnv('TP_SCHEMA_TYPES_DIST_DIR', 'dist/generated/types');
|
|
31
30
|
this.baseUrl = getEnv('TP_SCHEMA_BASE_URL', 'https://schemas.toolproof.com');
|
|
32
31
|
this.version = getEnv('TP_SCHEMA_VERSION', 'v0');
|
|
33
32
|
}
|
|
@@ -68,39 +67,47 @@ export class SchemaConfig {
|
|
|
68
67
|
getSchemaPath(filename) {
|
|
69
68
|
return path.join(this.getSchemasDir(), filename);
|
|
70
69
|
}
|
|
71
|
-
|
|
70
|
+
getConstantsDir() {
|
|
71
|
+
return path.isAbsolute(this.constantsDir)
|
|
72
|
+
? this.constantsDir
|
|
73
|
+
: path.join(this.root, this.constantsDir);
|
|
74
|
+
}
|
|
75
|
+
getConstantsPath(filename) {
|
|
76
|
+
return path.join(this.getConstantsDir(), filename);
|
|
77
|
+
}
|
|
78
|
+
getStandaloneSchemaDir() {
|
|
72
79
|
return path.join(this.getSchemasDir(), 'standalone');
|
|
73
80
|
}
|
|
74
|
-
|
|
75
|
-
return path.join(this.
|
|
81
|
+
getStandaloneSchemaPath(filename) {
|
|
82
|
+
return path.join(this.getStandaloneSchemaDir(), filename);
|
|
76
83
|
}
|
|
77
|
-
|
|
78
|
-
return path.isAbsolute(this.
|
|
79
|
-
? this.
|
|
80
|
-
: path.join(this.root, this.
|
|
84
|
+
getTypesSrcDir() {
|
|
85
|
+
return path.isAbsolute(this.typesSrcDir)
|
|
86
|
+
? this.typesSrcDir
|
|
87
|
+
: path.join(this.root, this.typesSrcDir);
|
|
81
88
|
}
|
|
82
|
-
|
|
83
|
-
return path.isAbsolute(this.
|
|
84
|
-
? this.
|
|
85
|
-
: path.join(this.root, this.
|
|
89
|
+
getTypesDistDir() {
|
|
90
|
+
return path.isAbsolute(this.typesDistDir)
|
|
91
|
+
? this.typesDistDir
|
|
92
|
+
: path.join(this.root, this.typesDistDir);
|
|
86
93
|
}
|
|
87
|
-
|
|
88
|
-
return path.join(this.
|
|
94
|
+
getTypesSrcPath(filename) {
|
|
95
|
+
return path.join(this.getTypesSrcDir(), filename);
|
|
89
96
|
}
|
|
90
|
-
|
|
91
|
-
return path.join(this.
|
|
97
|
+
getTypesDistPath(filename) {
|
|
98
|
+
return path.join(this.getTypesDistDir(), filename);
|
|
92
99
|
}
|
|
93
|
-
|
|
94
|
-
return path.join(this.
|
|
100
|
+
getStandaloneTypeSrcDir() {
|
|
101
|
+
return path.join(this.getTypesSrcDir(), 'standalone');
|
|
95
102
|
}
|
|
96
|
-
|
|
97
|
-
return path.join(this.
|
|
103
|
+
getStandaloneTypeDistDir() {
|
|
104
|
+
return path.join(this.getTypesDistDir(), 'standalone');
|
|
98
105
|
}
|
|
99
|
-
|
|
100
|
-
return path.join(this.
|
|
106
|
+
getStandaloneTypeSrcPath(filename) {
|
|
107
|
+
return path.join(this.getStandaloneTypeSrcDir(), filename);
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
return path.join(this.
|
|
109
|
+
getStandaloneTypeDistPath(filename) {
|
|
110
|
+
return path.join(this.getStandaloneTypeDistDir(), filename);
|
|
104
111
|
}
|
|
105
112
|
getResourcesDir() {
|
|
106
113
|
return path.isAbsolute(this.resourcesDir)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type GeneratedConstants = {
|
|
2
|
+
IDENTIFIABLES: {
|
|
3
|
+
PREFIXES: Record<string, string>;
|
|
4
|
+
NAMES: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
ENUMS: Record<string, Record<string, string>>;
|
|
7
|
+
};
|
|
8
|
+
export declare function extractIdentityPrefixes(schema: unknown): Record<string, string>;
|
|
9
|
+
export declare function deriveIdentifiablesFromIdentityPrefixes(identityPrefixes: Record<string, string>): Record<string, string>;
|
|
10
|
+
export declare function extractEnums(schema: unknown): Record<string, Record<string, string>>;
|
|
11
|
+
export declare function extractConstants(schema: unknown): GeneratedConstants;
|
|
12
|
+
export declare function renderConstantsTs(constants: GeneratedConstants): string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getConfig } from './_lib/config.js';
|
|
4
|
+
// PURE: Attempt to derive a canonical identity prefix from a canonical identity regex pattern.
|
|
5
|
+
function deriveIdentityPrefixFromPattern(pattern) {
|
|
6
|
+
// Canonical (currently used across schemas): ^PREFIX-.+$
|
|
7
|
+
const match = /^\^([^$]+)\.\+\$$/.exec(pattern);
|
|
8
|
+
if (!match)
|
|
9
|
+
return undefined;
|
|
10
|
+
const prefix = match[1];
|
|
11
|
+
if (!prefix || /[`\n\r]/.test(prefix))
|
|
12
|
+
return undefined;
|
|
13
|
+
return prefix;
|
|
14
|
+
}
|
|
15
|
+
// PURE: Extract all identity prefixes from `$defs/*Identity` string-pattern definitions.
|
|
16
|
+
export function extractIdentityPrefixes(schema) {
|
|
17
|
+
if (!schema || typeof schema !== 'object')
|
|
18
|
+
return {};
|
|
19
|
+
const defs = schema.$defs;
|
|
20
|
+
if (!defs || typeof defs !== 'object')
|
|
21
|
+
return {};
|
|
22
|
+
const defEntries = Object.entries(defs);
|
|
23
|
+
defEntries.sort(([a], [b]) => a.localeCompare(b));
|
|
24
|
+
const out = {};
|
|
25
|
+
for (const [defName, defVal] of defEntries) {
|
|
26
|
+
if (!/Identity$/.test(defName))
|
|
27
|
+
continue;
|
|
28
|
+
if (!defVal || typeof defVal !== 'object' || Array.isArray(defVal))
|
|
29
|
+
continue;
|
|
30
|
+
const v = defVal;
|
|
31
|
+
if (v.type !== 'string')
|
|
32
|
+
continue;
|
|
33
|
+
if (typeof v.pattern !== 'string')
|
|
34
|
+
continue;
|
|
35
|
+
const prefix = deriveIdentityPrefixFromPattern(v.pattern);
|
|
36
|
+
if (!prefix)
|
|
37
|
+
continue;
|
|
38
|
+
out[defName] = prefix;
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
// PURE: Derive identifiables from extracted Identity def names.
|
|
43
|
+
// Example: { BranchStepIdentity: 'BRANCH_STEP-' } => { BranchStep: 'BranchStep' }
|
|
44
|
+
export function deriveIdentifiablesFromIdentityPrefixes(identityPrefixes) {
|
|
45
|
+
const keys = Object.keys(identityPrefixes).sort((a, b) => a.localeCompare(b));
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const key of keys) {
|
|
48
|
+
if (!key.endsWith('Identity'))
|
|
49
|
+
continue;
|
|
50
|
+
const name = key.slice(0, -'Identity'.length);
|
|
51
|
+
if (!name)
|
|
52
|
+
continue;
|
|
53
|
+
out[name] = name;
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
// PURE: Extract all string enums from `$defs/*Kind|*Status` definitions.
|
|
58
|
+
// Shape: { StepKind: { job: 'job', ... }, ResourceKind: { 'input-potential': 'input-potential', ... } }
|
|
59
|
+
export function extractEnums(schema) {
|
|
60
|
+
if (!schema || typeof schema !== 'object')
|
|
61
|
+
return {};
|
|
62
|
+
const defs = schema.$defs;
|
|
63
|
+
if (!defs || typeof defs !== 'object')
|
|
64
|
+
return {};
|
|
65
|
+
const defEntries = Object.entries(defs);
|
|
66
|
+
defEntries.sort(([a], [b]) => a.localeCompare(b));
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const [defName, defVal] of defEntries) {
|
|
69
|
+
if (!/(Kind|Status)$/.test(defName))
|
|
70
|
+
continue;
|
|
71
|
+
if (!defVal || typeof defVal !== 'object' || Array.isArray(defVal))
|
|
72
|
+
continue;
|
|
73
|
+
const v = defVal;
|
|
74
|
+
if (v.type !== 'string')
|
|
75
|
+
continue;
|
|
76
|
+
if (!Array.isArray(v.enum) || v.enum.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
if (v.enum.some((x) => typeof x !== 'string'))
|
|
79
|
+
continue;
|
|
80
|
+
const members = {};
|
|
81
|
+
for (const member of v.enum) {
|
|
82
|
+
members[member] = member;
|
|
83
|
+
}
|
|
84
|
+
out[defName] = members;
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
// PURE: Extract all generated constants from a parsed schema.
|
|
89
|
+
export function extractConstants(schema) {
|
|
90
|
+
const identityPrefixes = extractIdentityPrefixes(schema);
|
|
91
|
+
const identifiables = deriveIdentifiablesFromIdentityPrefixes(identityPrefixes);
|
|
92
|
+
const enums = extractEnums(schema);
|
|
93
|
+
return {
|
|
94
|
+
IDENTIFIABLES: {
|
|
95
|
+
PREFIXES: identityPrefixes,
|
|
96
|
+
NAMES: identifiables,
|
|
97
|
+
},
|
|
98
|
+
ENUMS: enums,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// PURE: Render helpers for TS keys/strings.
|
|
102
|
+
function escapeTsString(value) {
|
|
103
|
+
return value
|
|
104
|
+
.replace(/\\/g, '\\\\')
|
|
105
|
+
.replace(/\r/g, '\\r')
|
|
106
|
+
.replace(/\n/g, '\\n')
|
|
107
|
+
.replace(/\t/g, '\\t')
|
|
108
|
+
.replace(/'/g, "\\'");
|
|
109
|
+
}
|
|
110
|
+
function renderTsStringLiteral(value) {
|
|
111
|
+
return `'${escapeTsString(value)}'`;
|
|
112
|
+
}
|
|
113
|
+
function isValidTsIdentifier(key) {
|
|
114
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
|
|
115
|
+
}
|
|
116
|
+
function renderTsKey(key) {
|
|
117
|
+
return isValidTsIdentifier(key) ? key : renderTsStringLiteral(key);
|
|
118
|
+
}
|
|
119
|
+
// PURE: Render constants TypeScript source.
|
|
120
|
+
export function renderConstantsTs(constants) {
|
|
121
|
+
const prefixKeys = Object.keys(constants.IDENTIFIABLES.PREFIXES).sort((a, b) => a.localeCompare(b));
|
|
122
|
+
const nameKeys = Object.keys(constants.IDENTIFIABLES.NAMES).sort((a, b) => a.localeCompare(b));
|
|
123
|
+
const enumKeys = Object.keys(constants.ENUMS).sort((a, b) => a.localeCompare(b));
|
|
124
|
+
const lines = [];
|
|
125
|
+
lines.push('const CONSTANTS = {');
|
|
126
|
+
lines.push(' IDENTIFIABLES: {');
|
|
127
|
+
lines.push(' PREFIXES: {');
|
|
128
|
+
for (const key of prefixKeys) {
|
|
129
|
+
const value = constants.IDENTIFIABLES.PREFIXES[key] ?? '';
|
|
130
|
+
lines.push(` ${renderTsKey(key)}: ${renderTsStringLiteral(value)},`);
|
|
131
|
+
}
|
|
132
|
+
lines.push(' },');
|
|
133
|
+
lines.push(' NAMES: {');
|
|
134
|
+
for (const key of nameKeys) {
|
|
135
|
+
const value = constants.IDENTIFIABLES.NAMES[key] ?? '';
|
|
136
|
+
lines.push(` ${renderTsKey(key)}: ${renderTsStringLiteral(value)},`);
|
|
137
|
+
}
|
|
138
|
+
lines.push(' },');
|
|
139
|
+
lines.push(' },');
|
|
140
|
+
lines.push(' ENUMS: {');
|
|
141
|
+
for (const key of enumKeys) {
|
|
142
|
+
const members = constants.ENUMS[key] ?? {};
|
|
143
|
+
lines.push(` ${renderTsKey(key)}: {`);
|
|
144
|
+
for (const memberKey of Object.keys(members)) {
|
|
145
|
+
const value = members[memberKey] ?? '';
|
|
146
|
+
lines.push(` ${renderTsKey(memberKey)}: ${renderTsStringLiteral(value)},`);
|
|
147
|
+
}
|
|
148
|
+
lines.push(' },');
|
|
149
|
+
}
|
|
150
|
+
lines.push(' }');
|
|
151
|
+
lines.push('} as const;');
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push('export default CONSTANTS;');
|
|
154
|
+
lines.push('');
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
157
|
+
// IMPURE: Script entrypoint (config + filesystem I/O + console + process exit code).
|
|
158
|
+
function main() {
|
|
159
|
+
try {
|
|
160
|
+
const config = getConfig();
|
|
161
|
+
const inPath = config.getSchemaPath('Genesis.json');
|
|
162
|
+
const outPath = config.getConstantsPath('constants.ts');
|
|
163
|
+
if (!fs.existsSync(inPath)) {
|
|
164
|
+
throw new Error(`Genesis schema not found at ${inPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
165
|
+
}
|
|
166
|
+
const raw = fs.readFileSync(inPath, 'utf8');
|
|
167
|
+
const doc = JSON.parse(raw);
|
|
168
|
+
const constants = extractConstants(doc);
|
|
169
|
+
const ts = renderConstantsTs(constants);
|
|
170
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
171
|
+
fs.writeFileSync(outPath, ts, 'utf8');
|
|
172
|
+
console.log(`Wrote constants to ${outPath}`);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error(`Error generating constants: ${error?.message ?? error}`);
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
main();
|
|
@@ -10,7 +10,7 @@ import { getConfig } from './_lib/config.js';
|
|
|
10
10
|
*
|
|
11
11
|
* Generates shims for:
|
|
12
12
|
* - schemas dir: config.getSchemasDir() (schema files)
|
|
13
|
-
* - standalone schemas dir: config.
|
|
13
|
+
* - standalone schemas dir: config.getStandaloneSchemaDir() (standalone schema files)
|
|
14
14
|
* - resources dir: config.getResourcesDir() (resource envelope files)
|
|
15
15
|
*
|
|
16
16
|
* Usage: node ./dist/scripts/generateSchemaShims.js
|
|
@@ -34,7 +34,7 @@ function main() {
|
|
|
34
34
|
try {
|
|
35
35
|
const config = getConfig();
|
|
36
36
|
const schemasDir = config.getSchemasDir();
|
|
37
|
-
const standaloneSchemasDir = config.
|
|
37
|
+
const standaloneSchemasDir = config.getStandaloneSchemaDir();
|
|
38
38
|
const resourcesDir = config.getResourcesDir();
|
|
39
39
|
const generatedResourceTypesDir = config.getNormalizedDir();
|
|
40
40
|
let totalCount = 0;
|
|
@@ -154,7 +154,7 @@ async function main() {
|
|
|
154
154
|
}
|
|
155
155
|
const schemasDir = config.getSchemasDir();
|
|
156
156
|
const genesisPath = path.join(schemasDir, config.getSourceFile());
|
|
157
|
-
const outPath = config.
|
|
157
|
+
const outPath = config.getStandaloneSchemaPath(`${name}.json`);
|
|
158
158
|
if (!fs.existsSync(genesisPath)) {
|
|
159
159
|
throw new Error(`Genesis.json not found at ${genesisPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
160
160
|
}
|
|
@@ -4,12 +4,12 @@ import { getConfig } from "./_lib/config.js";
|
|
|
4
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/generateStandaloneTypes.js --name Job
|
|
8
8
|
*/
|
|
9
9
|
// PURE: Generate the content of a standalone Resource type definition file for a given schema name.
|
|
10
10
|
function generateStandaloneTypeLogic(name) {
|
|
11
11
|
const header = "// Auto-generated strict composite type. Do not edit.\n";
|
|
12
|
-
const ts = `import type { ShellMaterializedBase, ${name} as NucleusSchema } from "../
|
|
12
|
+
const ts = `import type { ShellMaterializedBase, ${name} as NucleusSchema } from "../types.js";\n` +
|
|
13
13
|
`export type Resource_${name} = ShellMaterializedBase & { nucleus: NucleusSchema };\n`;
|
|
14
14
|
return header + ts;
|
|
15
15
|
}
|
|
@@ -57,7 +57,7 @@ function main() {
|
|
|
57
57
|
}
|
|
58
58
|
const inPath = name === "Genesis"
|
|
59
59
|
? config.getSchemaPath("Genesis.json")
|
|
60
|
-
: config.
|
|
60
|
+
: config.getStandaloneSchemaPath(`${name}.json`);
|
|
61
61
|
if (!fs.existsSync(inPath)) {
|
|
62
62
|
if (name === "Genesis") {
|
|
63
63
|
console.error(`Schema file not found: ${inPath}`);
|
|
@@ -79,12 +79,12 @@ function main() {
|
|
|
79
79
|
// Output setup
|
|
80
80
|
const outName = `Resource_${name}.d.ts`;
|
|
81
81
|
const outJsName = `Resource_${name}.js`;
|
|
82
|
-
const outDir = config.
|
|
83
|
-
const distLibDir = config.
|
|
82
|
+
const outDir = config.getStandaloneTypeSrcDir();
|
|
83
|
+
const distLibDir = config.getStandaloneTypeDistDir();
|
|
84
84
|
// Process src output
|
|
85
85
|
fs.mkdirSync(outDir, { recursive: true });
|
|
86
|
-
const outPath = config.
|
|
87
|
-
const outJsPath = config.
|
|
86
|
+
const outPath = config.getStandaloneTypeSrcPath(outName);
|
|
87
|
+
const outJsPath = config.getStandaloneTypeSrcPath(outJsName);
|
|
88
88
|
fs.writeFileSync(outPath, tsContent, "utf8");
|
|
89
89
|
console.log(`Wrote ${outPath}`);
|
|
90
90
|
if (!fs.existsSync(outJsPath)) {
|
|
@@ -93,8 +93,8 @@ function main() {
|
|
|
93
93
|
}
|
|
94
94
|
// Process dist output
|
|
95
95
|
fs.mkdirSync(distLibDir, { recursive: true });
|
|
96
|
-
const distDtsPath = config.
|
|
97
|
-
const distJsPath = config.
|
|
96
|
+
const distDtsPath = config.getStandaloneTypeDistPath(outName);
|
|
97
|
+
const distJsPath = config.getStandaloneTypeDistPath(outJsName);
|
|
98
98
|
fs.writeFileSync(distDtsPath, tsContent, "utf8");
|
|
99
99
|
fs.writeFileSync(distJsPath, jsContent, "utf8");
|
|
100
100
|
console.log(`Wrote ${distDtsPath}`);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { getConfig } from "./_lib/config.js";
|
|
4
|
+
// PURE: Validate + normalize a dependency map loaded from JSON.
|
|
5
|
+
function normalizeDependencyMap(value) {
|
|
6
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7
|
+
throw new Error("Invalid dependencyMap.json: expected an object");
|
|
8
|
+
}
|
|
9
|
+
const input = value;
|
|
10
|
+
const out = {};
|
|
11
|
+
// Preserve insertion order from the parsed JSON object.
|
|
12
|
+
for (const [key, rawDeps] of Object.entries(input)) {
|
|
13
|
+
if (rawDeps == null) {
|
|
14
|
+
out[key] = [];
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (!Array.isArray(rawDeps)) {
|
|
18
|
+
throw new Error(`Invalid dependencyMap.json: value for ${key} must be an array`);
|
|
19
|
+
}
|
|
20
|
+
out[key] = rawDeps.filter((d) => typeof d === "string");
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
// PURE: Compute terminals (defs that are not depended-upon by any other def).
|
|
25
|
+
function computeTerminalsInKeyOrder(dependencyMap) {
|
|
26
|
+
const keys = Object.keys(dependencyMap);
|
|
27
|
+
const dependedUpon = new Set();
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
for (const dep of dependencyMap[key] ?? []) {
|
|
30
|
+
dependedUpon.add(dep);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Preserve key order from dependencyMap.json.
|
|
34
|
+
return keys.filter((k) => !dependedUpon.has(k));
|
|
35
|
+
}
|
|
36
|
+
// IMPURE: Script entrypoint (config + filesystem I/O + console + process exit code).
|
|
37
|
+
function main() {
|
|
38
|
+
try {
|
|
39
|
+
const config = getConfig();
|
|
40
|
+
const inPath = config.getDependencyMapPath();
|
|
41
|
+
const outPath = path.join(path.dirname(inPath), "terminals.json");
|
|
42
|
+
if (!fs.existsSync(inPath)) {
|
|
43
|
+
throw new Error(`Dependency map not found at ${inPath}. Run generateDependencies first.`);
|
|
44
|
+
}
|
|
45
|
+
const raw = fs.readFileSync(inPath, "utf8");
|
|
46
|
+
const parsed = JSON.parse(raw);
|
|
47
|
+
const dependencyMap = normalizeDependencyMap(parsed);
|
|
48
|
+
const terminals = computeTerminalsInKeyOrder(dependencyMap);
|
|
49
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
50
|
+
fs.writeFileSync(outPath, JSON.stringify(terminals, null, 4), "utf8");
|
|
51
|
+
console.log(`Wrote terminals to ${outPath}`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error(`Error generating terminals: ${error?.message ?? error}`);
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -322,9 +322,9 @@ function postProcessEmittedTypes(ts, parsedSchema) {
|
|
|
322
322
|
return ts;
|
|
323
323
|
}
|
|
324
324
|
// PURE: Add banner + formatting/guards to build the final .d.ts content.
|
|
325
|
-
function finalizeOutputDts(
|
|
325
|
+
function finalizeOutputDts(emittedType) {
|
|
326
326
|
const banner = '// Auto-generated from JSON schemas. Do not edit.\n';
|
|
327
|
-
let output = banner + '\n' +
|
|
327
|
+
let output = banner + '\n' + emittedType + '\n';
|
|
328
328
|
// Final guard: strip any lingering `[k: string]: unknown;` that might have been
|
|
329
329
|
// reintroduced by later transforms.
|
|
330
330
|
output = output.replace(/^\s*\[k:\s*string\]:\s*unknown;\s*$/gm, '');
|
|
@@ -347,8 +347,8 @@ async function main() {
|
|
|
347
347
|
try {
|
|
348
348
|
const config = getConfig();
|
|
349
349
|
const inputDir = config.getSchemasDir();
|
|
350
|
-
const srcLibTypesDir = config.
|
|
351
|
-
const srcLibOutputPath = config.
|
|
350
|
+
const srcLibTypesDir = config.getTypesSrcDir();
|
|
351
|
+
const srcLibOutputPath = config.getTypesSrcPath('types.d.ts');
|
|
352
352
|
fs.mkdirSync(srcLibTypesDir, { recursive: true });
|
|
353
353
|
const schemaFileName = config.getSourceFile();
|
|
354
354
|
const schemaPath = path.join(inputDir, schemaFileName);
|
|
@@ -389,8 +389,8 @@ async function main() {
|
|
|
389
389
|
console.warn('Failed to write types to src/_lib:', e);
|
|
390
390
|
}
|
|
391
391
|
// Also write a copy into dist so consumers get the generated declarations
|
|
392
|
-
const distLibTypesDir = config.
|
|
393
|
-
const distLibOutputPath = config.
|
|
392
|
+
const distLibTypesDir = config.getTypesDistDir();
|
|
393
|
+
const distLibOutputPath = config.getTypesDistPath('types.d.ts');
|
|
394
394
|
try {
|
|
395
395
|
fs.mkdirSync(distLibTypesDir, { recursive: true });
|
|
396
396
|
fs.writeFileSync(distLibOutputPath, output, 'utf8');
|
|
@@ -400,26 +400,26 @@ async function main() {
|
|
|
400
400
|
// If copying to dist fails, log but don't crash the generator.
|
|
401
401
|
console.warn('Failed to write types to dist:', e);
|
|
402
402
|
}
|
|
403
|
-
// Ensure there is a runtime-resolvable module next to `
|
|
403
|
+
// Ensure there is a runtime-resolvable module next to `types.d.ts`
|
|
404
404
|
// Some consumers and TS NodeNext resolution expect a concrete .js next to .d.ts
|
|
405
405
|
// The file is intentionally empty as all exports are types-only.
|
|
406
406
|
try {
|
|
407
|
-
const srcLibTypesJsPath = config.
|
|
407
|
+
const srcLibTypesJsPath = config.getTypesSrcPath('types.js');
|
|
408
408
|
if (!fs.existsSync(srcLibTypesJsPath)) {
|
|
409
409
|
fs.writeFileSync(srcLibTypesJsPath, 'export {}\n', 'utf8');
|
|
410
410
|
console.log('Wrote', srcLibTypesJsPath);
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
413
|
catch (e) {
|
|
414
|
-
console.warn('Failed to write
|
|
414
|
+
console.warn('Failed to write types.js to src/_lib:', e);
|
|
415
415
|
}
|
|
416
416
|
try {
|
|
417
|
-
const distLibTypesJsPath = config.
|
|
417
|
+
const distLibTypesJsPath = config.getTypesDistPath('types.js');
|
|
418
418
|
fs.writeFileSync(distLibTypesJsPath, 'export {}\n', 'utf8');
|
|
419
419
|
console.log('Wrote', distLibTypesJsPath);
|
|
420
420
|
}
|
|
421
421
|
catch (e) {
|
|
422
|
-
console.warn('Failed to write
|
|
422
|
+
console.warn('Failed to write types.js to dist/_lib:', e);
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
425
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare function stripAnchors<T>(schema: T): T;
|
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { getConfig } from './_lib/config.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
/*
|
|
5
|
+
* Rewrite anchor-style references to JSON Pointer references in Genesis.json.
|
|
6
|
+
* We also strip all $anchor fields from the output since they are no longer needed after rewriting refs.
|
|
7
|
+
*/
|
|
8
|
+
// PURE: Remove all `$anchor` keys from a schema tree without rewriting refs.
|
|
9
|
+
export function stripAnchors(schema) {
|
|
10
|
+
const seen = new WeakMap();
|
|
11
|
+
function walk(node) {
|
|
12
|
+
if (!node || typeof node !== 'object')
|
|
13
|
+
return node;
|
|
14
|
+
const existing = seen.get(node);
|
|
15
|
+
if (existing)
|
|
16
|
+
return existing;
|
|
17
|
+
if (Array.isArray(node)) {
|
|
18
|
+
const out = [];
|
|
19
|
+
seen.set(node, out);
|
|
20
|
+
for (const item of node)
|
|
21
|
+
out.push(walk(item));
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
const out = {};
|
|
25
|
+
seen.set(node, out);
|
|
26
|
+
for (const [key, value] of Object.entries(node)) {
|
|
27
|
+
if (key === '$anchor')
|
|
28
|
+
continue;
|
|
29
|
+
out[key] = walk(value);
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
return walk(schema);
|
|
34
|
+
}
|
|
16
35
|
// PURE: Rewrite anchor-style `$ref` strings (`#Anchor`) into JSON Pointer refs (`#/$defs/DefName`).
|
|
17
36
|
function normalizeAnchorsToPointers(input) {
|
|
18
37
|
if (!input || typeof input !== "object")
|
|
@@ -90,6 +109,8 @@ function main() {
|
|
|
90
109
|
}
|
|
91
110
|
// Rewrite anchors in the nucleusSchema (pure function call)
|
|
92
111
|
genesis.nucleusSchema = normalizeAnchorsToPointers(genesis.nucleusSchema);
|
|
112
|
+
// Strip $anchor fields from the schemas (pure function call)
|
|
113
|
+
genesis.nucleusSchema = stripAnchors(genesis.nucleusSchema);
|
|
93
114
|
// Write normalized version
|
|
94
115
|
fs.mkdirSync(path.dirname(normalizedPath), { recursive: true });
|
|
95
116
|
fs.writeFileSync(normalizedPath, JSON.stringify(genesis, null, 4), 'utf-8');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolproof-core/schema",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "JSON schemas and TypeScript types for ToolProof",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,12 +34,14 @@
|
|
|
34
34
|
"normalizeAnchorsToPointers": "node ./dist/scripts/normalizeAnchorsToPointers.js",
|
|
35
35
|
"extractSchemasFromResourceTypeShells": "node ./dist/scripts/extractSchemasFromResourceTypeShells.js",
|
|
36
36
|
"generateStandaloneSchema": "node ./dist/scripts/generateStandaloneSchema.js",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"generateTypes": "node ./dist/scripts/generateTypes.js",
|
|
38
|
+
"generateStandaloneType": "node ./dist/scripts/generateStandaloneType.js",
|
|
39
39
|
"wrapResourceTypesWithResourceShells": "node ./dist/scripts/wrapResourceTypesWithResourceShells.js",
|
|
40
40
|
"generateSchemaShims": "node ./dist/scripts/generateSchemaShims.js",
|
|
41
41
|
"generateDependencies": "node ./dist/scripts/generateDependencies.js",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
42
|
+
"generateConstants": "node ./dist/scripts/generateConstants.js",
|
|
43
|
+
"generateTerminals": "node ./dist/scripts/generateTerminals.js",
|
|
44
|
+
"generateResourceTypeGenesisType": "node ./dist/scripts/generateStandaloneType.js --name Genesis",
|
|
45
|
+
"update": "rimraf /s /q dist && pnpm run build:scripts && pnpm run normalizeAnchorsToPointers && pnpm run extractSchemasFromResourceTypeShells && pnpm run generateConstants && pnpm run generateStandaloneSchema -- --name Job && pnpm run generateStandaloneSchema -- --name ResourceType && pnpm run generateStandaloneSchema -- --name RawStrategy && pnpm run generateStandaloneSchema -- --name RunnableStrategy && pnpm run generateStandaloneSchema -- --name StrategyRun && pnpm run generateStandaloneSchema -- --name Goal && pnpm run wrapResourceTypesWithResourceShells && pnpm run generateSchemaShims && pnpm run generateTypes && pnpm run generateStandaloneType -- --name Job && pnpm run generateStandaloneType -- --name ResourceType && pnpm run generateStandaloneType -- --name RawStrategy && pnpm run generateStandaloneType -- --name RunnableStrategy && pnpm run generateResourceTypeGenesisType && pnpm run generateDependencies && pnpm run generateTerminals && pnpm run build"
|
|
44
46
|
}
|
|
45
47
|
}
|