@toolproof-core/schema 1.0.9 → 1.0.11
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/artifacts/constants.d.ts +121 -0
- package/dist/generated/artifacts/constants.js +121 -0
- package/dist/generated/artifacts/mappings.d.ts +23 -0
- package/dist/generated/artifacts/mappings.js +23 -0
- package/dist/generated/normalized/Genesis.json +117 -78
- package/dist/generated/resources/Genesis.json +489 -264
- package/dist/generated/schemas/Genesis.json +94 -61
- package/dist/generated/schemas/standalone/Job.json +9 -8
- package/dist/generated/schemas/standalone/RawStrategy.json +86 -110
- package/dist/generated/schemas/standalone/ResourceType.json +4 -4
- package/dist/generated/schemas/standalone/RunnableStrategy.json +115 -139
- package/dist/generated/schemas/standalone/StrategyRun.json +93 -117
- package/dist/generated/types/standalone/Resource_Genesis.d.ts +1 -1
- package/dist/generated/types/standalone/Resource_Job.d.ts +1 -1
- package/dist/generated/types/standalone/Resource_RawStrategy.d.ts +1 -1
- package/dist/generated/types/standalone/Resource_ResourceType.d.ts +1 -1
- package/dist/generated/types/standalone/Resource_RunnableStrategy.d.ts +1 -1
- package/dist/generated/types/types.d.ts +247 -239
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -2
- package/dist/scripts/_lib/config.d.ts +3 -5
- package/dist/scripts/_lib/config.js +8 -14
- package/dist/scripts/generateConstantsAndMappings.d.ts +31 -0
- package/dist/scripts/generateConstantsAndMappings.js +243 -0
- package/dist/scripts/generateDependencies.js +1 -1
- package/dist/scripts/generateStandaloneType.js +2 -1
- package/dist/scripts/generateTerminals.js +2 -2
- package/dist/scripts/generateTypes.js +183 -5
- package/dist/scripts/wrapResourceTypesWithResourceShells.js +7 -3
- package/package.json +9 -10
- package/src/Genesis.json +1873 -1833
- package/src/generated/artifacts/constants.ts +122 -0
- package/src/generated/{dependencies → artifacts}/dependencyMap.json +282 -280
- package/src/generated/artifacts/mappings.ts +24 -0
- package/src/generated/{dependencies → artifacts}/terminals.json +13 -11
- package/src/generated/normalized/Genesis.json +1785 -1746
- package/src/generated/resources/Genesis.json +2833 -2608
- package/src/generated/schemas/Genesis.json +1348 -1315
- package/src/generated/schemas/standalone/Job.json +195 -194
- package/src/generated/schemas/standalone/RawStrategy.json +86 -110
- package/src/generated/schemas/standalone/ResourceType.json +106 -106
- package/src/generated/schemas/standalone/RunnableStrategy.json +645 -669
- package/src/generated/schemas/standalone/StrategyRun.json +913 -937
- package/src/generated/types/standalone/Resource_Genesis.d.ts +3 -3
- package/src/generated/types/standalone/Resource_Job.d.ts +3 -3
- package/src/generated/types/standalone/Resource_RawStrategy.d.ts +3 -3
- package/src/generated/types/standalone/Resource_ResourceType.d.ts +3 -3
- package/src/generated/types/standalone/Resource_RunnableStrategy.d.ts +3 -3
- package/src/generated/types/types.d.ts +717 -709
- package/src/index.ts +77 -70
- package/src/scripts/_lib/config.ts +207 -215
- package/src/scripts/extractSchemasFromResourceTypeShells.ts +261 -261
- package/src/scripts/generateConstantsAndMappings.ts +309 -0
- package/src/scripts/generateDependencies.ts +121 -121
- package/src/scripts/generateSchemaShims.ts +127 -127
- package/src/scripts/generateStandaloneSchema.ts +185 -185
- package/src/scripts/generateStandaloneType.ts +129 -127
- package/src/scripts/generateTerminals.ts +73 -73
- package/src/scripts/generateTypes.ts +733 -531
- package/src/scripts/normalizeAnchorsToPointers.ts +141 -141
- package/src/scripts/wrapResourceTypesWithResourceShells.ts +86 -82
- package/dist/generated/constants/constants.d.ts +0 -60
- package/dist/generated/constants/constants.js +0 -60
- package/dist/scripts/generateConstants.d.ts +0 -12
- package/dist/scripts/generateConstants.js +0 -179
- package/src/generated/constants/constants.ts +0 -61
- package/src/scripts/generateConstants.ts +0 -217
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
export { default as SchemaGenesis } from './generated/schemas/Genesis.js';
|
|
2
|
+
export { default as SchemaResourceType } from './generated/schemas/standalone/ResourceType.js';
|
|
2
3
|
export { default as SchemaJob } from './generated/schemas/standalone/Job.js';
|
|
4
|
+
export { default as SchemaRunnableStrategy } from './generated/schemas/standalone/RunnableStrategy.js';
|
|
3
5
|
export { default as SchemaStrategyRun } from './generated/schemas/standalone/StrategyRun.js';
|
|
4
|
-
export { default as
|
|
5
|
-
export { default as CONSTANTS } from './generated/
|
|
6
|
+
export { default as ResourceGenesis } from './generated/resources/Genesis.js';
|
|
7
|
+
export { default as CONSTANTS } from './generated/artifacts/constants.js';
|
|
8
|
+
export { default as MAPPINGS } from './generated/artifacts/mappings.js';
|
|
6
9
|
export type { Resource_Genesis as Resource_GenesisJson } from './generated/types/standalone/Resource_Genesis.js';
|
|
7
10
|
export type { Resource_ResourceType as Resource_ResourceTypeJson } from './generated/types/standalone/Resource_ResourceType.js';
|
|
8
11
|
export type { Resource_Job as Resource_JobJson } from './generated/types/standalone/Resource_Job.js';
|
|
9
12
|
export type { Resource_RawStrategy as Resource_RawStrategyJson } from './generated/types/standalone/Resource_RawStrategy.js';
|
|
10
13
|
export type { Resource_RunnableStrategy as Resource_RunnableStrategyJson } from './generated/types/standalone/Resource_RunnableStrategy.js';
|
|
11
|
-
export type {
|
|
14
|
+
export type { DocumentationFacetJson, NucleusFacetJson, ResourceTypeIdentityJson, ResourceTypeJson, ResourceRoleIdentityJson, ResourceRoleValueJson, ResourceRoleJson, ConditionalJson, RoleDictJson, RolesJson, RoleBindingsJson, ResourceIdentityJson, JobStepIdentityJson, BranchStepIdentityJson, WhileStepIdentityJson, ForStepIdentityJson, JobStepJson, BranchStepJson, WhileStepJson, ForStepJson, StepKindJson, StepIdentityJson, StepJson, CreationContextJson, ResourceMissingJson, ResourceInputPotentialJson, ResourceOutputPotentialJson, ShellMaterializedBaseJson, ResourceJson, StrategyStateJson, StepsFacetJson, RawStrategyJson, RunnableStrategyIdentityJson, RunnableStrategyStatusJson, RunnableStrategyJson, RunnableStrategyUpdateJson, JobIdentityJson, JobJson, JsonDataJson, StrategyThreadIdentityJson, StrategyThreadDictJson, JobStepSocketJson, TimestampJson, StrategyRunIdentityJson, GoalIdentityJson, GoalJson, ErrorJson, } from './generated/types/types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Re-export JSON schemas via .ts shims to avoid .json re-exports in declarations
|
|
2
2
|
export { default as SchemaGenesis } from './generated/schemas/Genesis.js';
|
|
3
|
+
export { default as SchemaResourceType } from './generated/schemas/standalone/ResourceType.js';
|
|
3
4
|
export { default as SchemaJob } from './generated/schemas/standalone/Job.js';
|
|
5
|
+
export { default as SchemaRunnableStrategy } from './generated/schemas/standalone/RunnableStrategy.js';
|
|
4
6
|
export { default as SchemaStrategyRun } from './generated/schemas/standalone/StrategyRun.js';
|
|
5
|
-
export { default as
|
|
6
|
-
export { default as CONSTANTS } from './generated/
|
|
7
|
+
export { default as ResourceGenesis } from './generated/resources/Genesis.js';
|
|
8
|
+
export { default as CONSTANTS } from './generated/artifacts/constants.js';
|
|
9
|
+
export { default as MAPPINGS } from './generated/artifacts/mappings.js';
|
|
@@ -12,9 +12,8 @@ export declare class SchemaConfig {
|
|
|
12
12
|
private readonly sourceFile;
|
|
13
13
|
private readonly normalizedDir;
|
|
14
14
|
private readonly schemasDir;
|
|
15
|
-
private readonly
|
|
15
|
+
private readonly artifactsDir;
|
|
16
16
|
private readonly resourcesDir;
|
|
17
|
-
private readonly dependencyMapPath;
|
|
18
17
|
private readonly typesSrcDir;
|
|
19
18
|
private readonly typesDistDir;
|
|
20
19
|
private readonly baseUrl;
|
|
@@ -29,8 +28,8 @@ export declare class SchemaConfig {
|
|
|
29
28
|
getNormalizedSourcePath(): string;
|
|
30
29
|
getSchemasDir(): string;
|
|
31
30
|
getSchemaPath(filename: string): string;
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
getArtifactsDir(): string;
|
|
32
|
+
getArtifactsPath(filename: string): string;
|
|
34
33
|
getStandaloneSchemaDir(): string;
|
|
35
34
|
getStandaloneSchemaPath(filename: string): string;
|
|
36
35
|
getTypesSrcDir(): string;
|
|
@@ -42,7 +41,6 @@ export declare class SchemaConfig {
|
|
|
42
41
|
getStandaloneTypeSrcPath(filename: string): string;
|
|
43
42
|
getStandaloneTypeDistPath(filename: string): string;
|
|
44
43
|
getResourcesDir(): string;
|
|
45
|
-
getDependencyMapPath(): string;
|
|
46
44
|
getBaseUrl(): string;
|
|
47
45
|
getVersion(): string;
|
|
48
46
|
getSchemaId(schemaName: string): string;
|
|
@@ -22,13 +22,12 @@ export class SchemaConfig {
|
|
|
22
22
|
this.sourceFile = getEnv('TP_SCHEMA_SOURCE_FILE', 'Genesis.json');
|
|
23
23
|
this.normalizedDir = getEnv('TP_SCHEMA_NORMALIZED_DIR', 'src/generated/normalized');
|
|
24
24
|
this.schemasDir = getEnv('TP_SCHEMA_SCHEMAS_DIR', 'src/generated/schemas');
|
|
25
|
-
this.
|
|
25
|
+
this.artifactsDir = getEnv('TP_SCHEMA_ARTIFACTS_DIR', 'src/generated/artifacts');
|
|
26
26
|
this.resourcesDir = getEnv('TP_SCHEMA_RESOURCES_DIR', 'src/generated/resources');
|
|
27
|
-
this.dependencyMapPath = getEnv('TP_SCHEMA_DEPENDENCY_MAP_PATH', 'src/generated/dependencies/dependencyMap.json');
|
|
28
27
|
this.typesSrcDir = getEnv('TP_SCHEMA_TYPES_SRC_DIR', 'src/generated/types');
|
|
29
28
|
this.typesDistDir = getEnv('TP_SCHEMA_TYPES_DIST_DIR', 'dist/generated/types');
|
|
30
29
|
this.baseUrl = getEnv('TP_SCHEMA_BASE_URL', 'https://schemas.toolproof.com');
|
|
31
|
-
this.version = getEnv('TP_SCHEMA_VERSION', '
|
|
30
|
+
this.version = getEnv('TP_SCHEMA_VERSION', 'v1');
|
|
32
31
|
}
|
|
33
32
|
// Path getters
|
|
34
33
|
getRoot() {
|
|
@@ -67,13 +66,13 @@ export class SchemaConfig {
|
|
|
67
66
|
getSchemaPath(filename) {
|
|
68
67
|
return path.join(this.getSchemasDir(), filename);
|
|
69
68
|
}
|
|
70
|
-
|
|
71
|
-
return path.isAbsolute(this.
|
|
72
|
-
? this.
|
|
73
|
-
: path.join(this.root, this.
|
|
69
|
+
getArtifactsDir() {
|
|
70
|
+
return path.isAbsolute(this.artifactsDir)
|
|
71
|
+
? this.artifactsDir
|
|
72
|
+
: path.join(this.root, this.artifactsDir);
|
|
74
73
|
}
|
|
75
|
-
|
|
76
|
-
return path.join(this.
|
|
74
|
+
getArtifactsPath(filename) {
|
|
75
|
+
return path.join(this.getArtifactsDir(), filename);
|
|
77
76
|
}
|
|
78
77
|
getStandaloneSchemaDir() {
|
|
79
78
|
return path.join(this.getSchemasDir(), 'standalone');
|
|
@@ -114,11 +113,6 @@ export class SchemaConfig {
|
|
|
114
113
|
? this.resourcesDir
|
|
115
114
|
: path.join(this.root, this.resourcesDir);
|
|
116
115
|
}
|
|
117
|
-
getDependencyMapPath() {
|
|
118
|
-
return path.isAbsolute(this.dependencyMapPath)
|
|
119
|
-
? this.dependencyMapPath
|
|
120
|
-
: path.join(this.root, this.dependencyMapPath);
|
|
121
|
-
}
|
|
122
116
|
// Schema URL methods
|
|
123
117
|
getBaseUrl() {
|
|
124
118
|
return this.baseUrl;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type GeneratedConstants = {
|
|
2
|
+
Names: Record<string, string>;
|
|
3
|
+
Enums: Record<string, Record<string, string>>;
|
|
4
|
+
};
|
|
5
|
+
export type GeneratedMappings = {
|
|
6
|
+
IdentityNameToIdentityPrefix: Record<string, string>;
|
|
7
|
+
StepKindToStepIdentityPrefix: Record<string, string>;
|
|
8
|
+
};
|
|
9
|
+
export type DeriveStepKindToStepIdentityPrefixResult = {
|
|
10
|
+
mapping: Record<string, string>;
|
|
11
|
+
missing: Array<{
|
|
12
|
+
stepKind: string;
|
|
13
|
+
identityName: string;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
export declare function extractIdentityPrefixes(schema: unknown): Record<string, string>;
|
|
17
|
+
export declare function extractSubschemaNames(schema: unknown): Record<string, string>;
|
|
18
|
+
export declare function extractEnums(schema: unknown): Record<string, Record<string, string>>;
|
|
19
|
+
export declare function deriveStepKindToStepIdentityPrefix(enums: Record<string, Record<string, string>>, identityNameToIdentityPrefix: Record<string, string>): DeriveStepKindToStepIdentityPrefixResult;
|
|
20
|
+
export declare function extractGeneratedConstantsAndMappings(schema: unknown): {
|
|
21
|
+
CONSTANTS: GeneratedConstants;
|
|
22
|
+
MAPPINGS: GeneratedMappings;
|
|
23
|
+
DIAGNOSTICS: {
|
|
24
|
+
missingStepKindIdentityPrefixes: Array<{
|
|
25
|
+
stepKind: string;
|
|
26
|
+
identityName: string;
|
|
27
|
+
}>;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare function renderConstantsTs(constants: GeneratedConstants): string;
|
|
31
|
+
export declare function renderMappingsTs(mappings: GeneratedMappings): string;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getConfig } from './_lib/config.js';
|
|
4
|
+
// PURE: Convert a string enum member into PascalCase.
|
|
5
|
+
// Examples: 'job' -> 'Job', 'graph_start' -> 'GraphStart'
|
|
6
|
+
function toPascalCase(value) {
|
|
7
|
+
return value
|
|
8
|
+
.split(/[^A-Za-z0-9]+/g)
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
11
|
+
.join('');
|
|
12
|
+
}
|
|
13
|
+
// PURE: Attempt to derive a canonical identity prefix from a canonical identity regex pattern.
|
|
14
|
+
function deriveIdentityPrefixFromPattern(pattern) {
|
|
15
|
+
// Canonical (currently used across schemas): ^PREFIX-.+$
|
|
16
|
+
const match = /^\^([^$]+)\.\+\$$/.exec(pattern);
|
|
17
|
+
if (!match)
|
|
18
|
+
return undefined;
|
|
19
|
+
const prefix = match[1];
|
|
20
|
+
if (!prefix || /[`\n\r]/.test(prefix))
|
|
21
|
+
return undefined;
|
|
22
|
+
return prefix;
|
|
23
|
+
}
|
|
24
|
+
// PURE: Extract all identity prefixes from `$defs/*Identity` string-pattern definitions.
|
|
25
|
+
export function extractIdentityPrefixes(schema) {
|
|
26
|
+
if (!schema || typeof schema !== 'object')
|
|
27
|
+
return {};
|
|
28
|
+
const defs = schema.$defs;
|
|
29
|
+
if (!defs || typeof defs !== 'object')
|
|
30
|
+
return {};
|
|
31
|
+
const defEntries = Object.entries(defs);
|
|
32
|
+
defEntries.sort(([a], [b]) => a.localeCompare(b));
|
|
33
|
+
const out = {};
|
|
34
|
+
for (const [defName, defVal] of defEntries) {
|
|
35
|
+
if (!/Identity$/.test(defName))
|
|
36
|
+
continue;
|
|
37
|
+
if (!defVal || typeof defVal !== 'object' || Array.isArray(defVal))
|
|
38
|
+
continue;
|
|
39
|
+
const v = defVal;
|
|
40
|
+
if (v.type !== 'string')
|
|
41
|
+
continue;
|
|
42
|
+
if (typeof v.pattern !== 'string')
|
|
43
|
+
continue;
|
|
44
|
+
const prefix = deriveIdentityPrefixFromPattern(v.pattern);
|
|
45
|
+
if (!prefix)
|
|
46
|
+
continue;
|
|
47
|
+
out[defName] = prefix;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
// PURE: Extract all subschema names from `$defs/*`.
|
|
52
|
+
// Shape: { JobStep: 'JobStep', StepKind: 'StepKind', ... }
|
|
53
|
+
export function extractSubschemaNames(schema) {
|
|
54
|
+
if (!schema || typeof schema !== 'object')
|
|
55
|
+
return {};
|
|
56
|
+
const defs = schema.$defs;
|
|
57
|
+
if (!defs || typeof defs !== 'object')
|
|
58
|
+
return {};
|
|
59
|
+
const defEntries = Object.entries(defs);
|
|
60
|
+
defEntries.sort(([a], [b]) => a.localeCompare(b));
|
|
61
|
+
const out = {};
|
|
62
|
+
for (const [defName] of defEntries) {
|
|
63
|
+
if (!defName || /[\n\r`]/.test(defName))
|
|
64
|
+
continue;
|
|
65
|
+
out[defName] = defName;
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
// PURE: Extract all string enums from `$defs/*Kind|*Status` definitions.
|
|
70
|
+
// Shape: { StepKind: { job: 'job', ... }, ResourceShellKind: { inputPotential': 'inputPotential', ... } }
|
|
71
|
+
export function extractEnums(schema) {
|
|
72
|
+
if (!schema || typeof schema !== 'object')
|
|
73
|
+
return {};
|
|
74
|
+
const defs = schema.$defs;
|
|
75
|
+
if (!defs || typeof defs !== 'object')
|
|
76
|
+
return {};
|
|
77
|
+
const defEntries = Object.entries(defs);
|
|
78
|
+
defEntries.sort(([a], [b]) => a.localeCompare(b));
|
|
79
|
+
const out = {};
|
|
80
|
+
for (const [defName, defVal] of defEntries) {
|
|
81
|
+
if (!/(Kind|Status)$/.test(defName))
|
|
82
|
+
continue;
|
|
83
|
+
if (!defVal || typeof defVal !== 'object' || Array.isArray(defVal))
|
|
84
|
+
continue;
|
|
85
|
+
const v = defVal;
|
|
86
|
+
if (v.type !== 'string')
|
|
87
|
+
continue;
|
|
88
|
+
if (!Array.isArray(v.enum) || v.enum.length === 0)
|
|
89
|
+
continue;
|
|
90
|
+
if (v.enum.some((x) => typeof x !== 'string'))
|
|
91
|
+
continue;
|
|
92
|
+
const members = {};
|
|
93
|
+
for (const member of v.enum) {
|
|
94
|
+
members[member] = member;
|
|
95
|
+
}
|
|
96
|
+
out[defName] = members;
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
// PURE: Derive a StepKind -> StepIdentityPrefix mapping.
|
|
101
|
+
// Example: { job: 'job' } + IdentityNameToIdentityPrefix['JobStepIdentity']='JOB_STEP-' => { job: 'JOB_STEP-' }
|
|
102
|
+
export function deriveStepKindToStepIdentityPrefix(enums, identityNameToIdentityPrefix) {
|
|
103
|
+
const stepKindEnum = enums.StepKind;
|
|
104
|
+
if (!stepKindEnum || typeof stepKindEnum !== 'object')
|
|
105
|
+
return { mapping: {}, missing: [] };
|
|
106
|
+
const stepKinds = Object.keys(stepKindEnum).sort((a, b) => a.localeCompare(b));
|
|
107
|
+
const mapping = {};
|
|
108
|
+
const missing = [];
|
|
109
|
+
for (const stepKind of stepKinds) {
|
|
110
|
+
const identityName = `${toPascalCase(stepKind)}StepIdentity`;
|
|
111
|
+
const prefix = identityNameToIdentityPrefix[identityName];
|
|
112
|
+
if (!prefix) {
|
|
113
|
+
missing.push({ stepKind, identityName });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
mapping[stepKind] = prefix;
|
|
117
|
+
}
|
|
118
|
+
return { mapping, missing };
|
|
119
|
+
}
|
|
120
|
+
// PURE: Extract generated CONSTANTS + MAPPINGS from a parsed schema.
|
|
121
|
+
export function extractGeneratedConstantsAndMappings(schema) {
|
|
122
|
+
const names = extractSubschemaNames(schema);
|
|
123
|
+
const enums = extractEnums(schema);
|
|
124
|
+
const identityPrefixes = extractIdentityPrefixes(schema);
|
|
125
|
+
const derivedStepKind = deriveStepKindToStepIdentityPrefix(enums, identityPrefixes);
|
|
126
|
+
return {
|
|
127
|
+
CONSTANTS: {
|
|
128
|
+
Names: names,
|
|
129
|
+
Enums: enums,
|
|
130
|
+
},
|
|
131
|
+
MAPPINGS: {
|
|
132
|
+
IdentityNameToIdentityPrefix: identityPrefixes,
|
|
133
|
+
StepKindToStepIdentityPrefix: derivedStepKind.mapping,
|
|
134
|
+
},
|
|
135
|
+
DIAGNOSTICS: {
|
|
136
|
+
missingStepKindIdentityPrefixes: derivedStepKind.missing,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// PURE: Render helpers for TS keys/strings.
|
|
141
|
+
function escapeTsString(value) {
|
|
142
|
+
return value
|
|
143
|
+
.replace(/\\/g, '\\\\')
|
|
144
|
+
.replace(/\r/g, '\\r')
|
|
145
|
+
.replace(/\n/g, '\\n')
|
|
146
|
+
.replace(/\t/g, '\\t')
|
|
147
|
+
.replace(/'/g, "\\'");
|
|
148
|
+
}
|
|
149
|
+
function renderTsStringLiteral(value) {
|
|
150
|
+
return `'${escapeTsString(value)}'`;
|
|
151
|
+
}
|
|
152
|
+
function isValidTsIdentifier(key) {
|
|
153
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
|
|
154
|
+
}
|
|
155
|
+
function renderTsKey(key) {
|
|
156
|
+
return isValidTsIdentifier(key) ? key : renderTsStringLiteral(key);
|
|
157
|
+
}
|
|
158
|
+
// PURE: Render constants TypeScript source.
|
|
159
|
+
export function renderConstantsTs(constants) {
|
|
160
|
+
const nameKeys = Object.keys(constants.Names).sort((a, b) => a.localeCompare(b));
|
|
161
|
+
const enumKeys = Object.keys(constants.Enums).sort((a, b) => a.localeCompare(b));
|
|
162
|
+
const lines = [];
|
|
163
|
+
lines.push('const CONSTANTS = {');
|
|
164
|
+
lines.push(' Names: {');
|
|
165
|
+
for (const key of nameKeys) {
|
|
166
|
+
const value = constants.Names[key] ?? '';
|
|
167
|
+
lines.push(` ${renderTsKey(key)}: ${renderTsStringLiteral(value)},`);
|
|
168
|
+
}
|
|
169
|
+
lines.push(' },');
|
|
170
|
+
lines.push(' Enums: {');
|
|
171
|
+
for (const key of enumKeys) {
|
|
172
|
+
const members = constants.Enums[key] ?? {};
|
|
173
|
+
lines.push(` ${renderTsKey(key)}: {`);
|
|
174
|
+
for (const memberKey of Object.keys(members)) {
|
|
175
|
+
const value = members[memberKey] ?? '';
|
|
176
|
+
lines.push(` ${renderTsKey(memberKey)}: ${renderTsStringLiteral(value)},`);
|
|
177
|
+
}
|
|
178
|
+
lines.push(' },');
|
|
179
|
+
}
|
|
180
|
+
lines.push(' }');
|
|
181
|
+
lines.push('} as const;');
|
|
182
|
+
lines.push('');
|
|
183
|
+
lines.push('export default CONSTANTS;');
|
|
184
|
+
lines.push('');
|
|
185
|
+
return lines.join('\n');
|
|
186
|
+
}
|
|
187
|
+
// PURE: Render mappings TypeScript source.
|
|
188
|
+
export function renderMappingsTs(mappings) {
|
|
189
|
+
const identityKeys = Object.keys(mappings.IdentityNameToIdentityPrefix).sort((a, b) => a.localeCompare(b));
|
|
190
|
+
const stepKindKeys = Object.keys(mappings.StepKindToStepIdentityPrefix).sort((a, b) => a.localeCompare(b));
|
|
191
|
+
const lines = [];
|
|
192
|
+
lines.push('const MAPPINGS = {');
|
|
193
|
+
lines.push(' IdentityNameToIdentityPrefix: {');
|
|
194
|
+
for (const key of identityKeys) {
|
|
195
|
+
const value = mappings.IdentityNameToIdentityPrefix[key] ?? '';
|
|
196
|
+
lines.push(` ${renderTsKey(key)}: ${renderTsStringLiteral(value)},`);
|
|
197
|
+
}
|
|
198
|
+
lines.push(' },');
|
|
199
|
+
lines.push(' StepKindToStepIdentityPrefix: {');
|
|
200
|
+
for (const key of stepKindKeys) {
|
|
201
|
+
const value = mappings.StepKindToStepIdentityPrefix[key] ?? '';
|
|
202
|
+
lines.push(` ${renderTsKey(key)}: ${renderTsStringLiteral(value)},`);
|
|
203
|
+
}
|
|
204
|
+
lines.push(' },');
|
|
205
|
+
lines.push('} as const;');
|
|
206
|
+
lines.push('');
|
|
207
|
+
lines.push('export default MAPPINGS;');
|
|
208
|
+
lines.push('');
|
|
209
|
+
return lines.join('\n');
|
|
210
|
+
}
|
|
211
|
+
// IMPURE: Script entrypoint (config + filesystem I/O + console + process exit code).
|
|
212
|
+
function main() {
|
|
213
|
+
try {
|
|
214
|
+
const config = getConfig();
|
|
215
|
+
const inPath = config.getSchemaPath('Genesis.json');
|
|
216
|
+
const outConstantsPath = config.getArtifactsPath('constants.ts');
|
|
217
|
+
const outMappingsPath = config.getArtifactsPath('mappings.ts');
|
|
218
|
+
if (!fs.existsSync(inPath)) {
|
|
219
|
+
throw new Error(`Genesis schema not found at ${inPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
220
|
+
}
|
|
221
|
+
const raw = fs.readFileSync(inPath, 'utf8');
|
|
222
|
+
const doc = JSON.parse(raw);
|
|
223
|
+
const { CONSTANTS, MAPPINGS, DIAGNOSTICS } = extractGeneratedConstantsAndMappings(doc);
|
|
224
|
+
if (DIAGNOSTICS.missingStepKindIdentityPrefixes.length) {
|
|
225
|
+
const rows = DIAGNOSTICS.missingStepKindIdentityPrefixes
|
|
226
|
+
.map(({ stepKind, identityName }) => `${stepKind} -> ${identityName}`)
|
|
227
|
+
.join(', ');
|
|
228
|
+
throw new Error(`Missing IdentityNameToIdentityPrefix entries required for StepKindToStepIdentityPrefix: ${rows}`);
|
|
229
|
+
}
|
|
230
|
+
const constantsTs = renderConstantsTs(CONSTANTS);
|
|
231
|
+
const mappingsTs = renderMappingsTs(MAPPINGS);
|
|
232
|
+
fs.mkdirSync(path.dirname(outConstantsPath), { recursive: true });
|
|
233
|
+
fs.writeFileSync(outConstantsPath, constantsTs, 'utf8');
|
|
234
|
+
fs.writeFileSync(outMappingsPath, mappingsTs, 'utf8');
|
|
235
|
+
console.log(`Wrote constants to ${outConstantsPath}`);
|
|
236
|
+
console.log(`Wrote mappings to ${outMappingsPath}`);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
console.error(`Error generating constants/mappings: ${error?.message ?? error}`);
|
|
240
|
+
process.exitCode = 1;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
main();
|
|
@@ -88,7 +88,7 @@ function main() {
|
|
|
88
88
|
try {
|
|
89
89
|
const config = getConfig();
|
|
90
90
|
const inPath = config.getSchemaPath("Genesis.json");
|
|
91
|
-
const outPath = config.
|
|
91
|
+
const outPath = config.getArtifactsPath("dependencyMap.json");
|
|
92
92
|
if (!fs.existsSync(inPath)) {
|
|
93
93
|
throw new Error(`Genesis schema not found at ${inPath}. Run extractSchemasFromResourceTypeShells first.`);
|
|
94
94
|
}
|
|
@@ -9,7 +9,8 @@ import { getConfig } from "./_lib/config.js";
|
|
|
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
|
|
12
|
+
const nucleusTypeName = name.endsWith("Json") ? name : `${name}Json`;
|
|
13
|
+
const ts = `import type { ShellMaterializedBaseJson as ShellMaterializedBase, ${nucleusTypeName} as NucleusSchema } from "../types.js";\n` +
|
|
13
14
|
`export type Resource_${name} = ShellMaterializedBase & { nucleus: NucleusSchema };\n`;
|
|
14
15
|
return header + ts;
|
|
15
16
|
}
|
|
@@ -37,8 +37,8 @@ function computeTerminalsInKeyOrder(dependencyMap) {
|
|
|
37
37
|
function main() {
|
|
38
38
|
try {
|
|
39
39
|
const config = getConfig();
|
|
40
|
-
const inPath = config.
|
|
41
|
-
const outPath =
|
|
40
|
+
const inPath = config.getArtifactsPath("dependencyMap.json");
|
|
41
|
+
const outPath = config.getArtifactsPath("terminals.json");
|
|
42
42
|
if (!fs.existsSync(inPath)) {
|
|
43
43
|
throw new Error(`Dependency map not found at ${inPath}. Run generateDependencies first.`);
|
|
44
44
|
}
|
|
@@ -227,6 +227,178 @@ function removeDuplicateUnionEntries(ts) {
|
|
|
227
227
|
function escapeRegExpLiteral(value) {
|
|
228
228
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
229
229
|
}
|
|
230
|
+
// PURE: Rename exported top-level generated declarations to canonical `*Json` names.
|
|
231
|
+
// This makes editor hover/inference prefer `FooJson` because the underlying declared
|
|
232
|
+
// symbol is `FooJson` (not `Foo` with a re-export alias).
|
|
233
|
+
function applyReplacementsOutsideStringsAndComments(text, replaceCodeSegment) {
|
|
234
|
+
const len = text.length;
|
|
235
|
+
let out = '';
|
|
236
|
+
let i = 0;
|
|
237
|
+
let codeStart = 0;
|
|
238
|
+
const flushCode = (end) => {
|
|
239
|
+
if (end > codeStart)
|
|
240
|
+
out += replaceCodeSegment(text.slice(codeStart, end));
|
|
241
|
+
codeStart = end;
|
|
242
|
+
};
|
|
243
|
+
const startsWith = (s) => text.startsWith(s, i);
|
|
244
|
+
while (i < len) {
|
|
245
|
+
// Line comment
|
|
246
|
+
if (startsWith('//')) {
|
|
247
|
+
flushCode(i);
|
|
248
|
+
const start = i;
|
|
249
|
+
i += 2;
|
|
250
|
+
while (i < len && text[i] !== '\n')
|
|
251
|
+
i++;
|
|
252
|
+
if (i < len && text[i] === '\n')
|
|
253
|
+
i++;
|
|
254
|
+
out += text.slice(start, i);
|
|
255
|
+
codeStart = i;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
// Block comment
|
|
259
|
+
if (startsWith('/*')) {
|
|
260
|
+
flushCode(i);
|
|
261
|
+
const start = i;
|
|
262
|
+
i += 2;
|
|
263
|
+
while (i < len && !text.startsWith('*/', i))
|
|
264
|
+
i++;
|
|
265
|
+
if (i < len)
|
|
266
|
+
i += 2;
|
|
267
|
+
out += text.slice(start, i);
|
|
268
|
+
codeStart = i;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const ch = text[i];
|
|
272
|
+
// Single-quoted string
|
|
273
|
+
if (ch === "'") {
|
|
274
|
+
flushCode(i);
|
|
275
|
+
const start = i;
|
|
276
|
+
i++;
|
|
277
|
+
while (i < len) {
|
|
278
|
+
const c = text[i];
|
|
279
|
+
if (c === '\\') {
|
|
280
|
+
i += 2;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
i++;
|
|
284
|
+
if (c === "'")
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
out += text.slice(start, i);
|
|
288
|
+
codeStart = i;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
// Double-quoted string
|
|
292
|
+
if (ch === '"') {
|
|
293
|
+
flushCode(i);
|
|
294
|
+
const start = i;
|
|
295
|
+
i++;
|
|
296
|
+
while (i < len) {
|
|
297
|
+
const c = text[i];
|
|
298
|
+
if (c === '\\') {
|
|
299
|
+
i += 2;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
if (c === '"')
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
out += text.slice(start, i);
|
|
307
|
+
codeStart = i;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
// Template literal (backticks). We conservatively treat the whole template as a string.
|
|
311
|
+
// The generated .d.ts uses these primarily for template-literal *value* types like `TYPE-${string}`
|
|
312
|
+
// and we do not want to rewrite their raw text.
|
|
313
|
+
if (ch === '`') {
|
|
314
|
+
flushCode(i);
|
|
315
|
+
const start = i;
|
|
316
|
+
i++;
|
|
317
|
+
while (i < len) {
|
|
318
|
+
const c = text[i];
|
|
319
|
+
if (c === '\\') {
|
|
320
|
+
i += 2;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
i++;
|
|
324
|
+
if (c === '`')
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
out += text.slice(start, i);
|
|
328
|
+
codeStart = i;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
i++;
|
|
332
|
+
}
|
|
333
|
+
flushCode(len);
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
function renameExportedTopLevelTypesToJson(tsText) {
|
|
337
|
+
// Collect exported type/interface names.
|
|
338
|
+
const exportedDeclRegex = /^export\s+(?:type|interface)\s+([A-Za-z_][A-Za-z0-9_]*)\b/gm;
|
|
339
|
+
const exportedNames = new Set();
|
|
340
|
+
for (let m = exportedDeclRegex.exec(tsText); m; m = exportedDeclRegex.exec(tsText)) {
|
|
341
|
+
exportedNames.add(m[1]);
|
|
342
|
+
}
|
|
343
|
+
const renamePairs = Array.from(exportedNames)
|
|
344
|
+
.filter((name) => !name.endsWith('Json'))
|
|
345
|
+
.map((name) => ({ from: name, to: `${name}Json` }));
|
|
346
|
+
if (!renamePairs.length)
|
|
347
|
+
return tsText;
|
|
348
|
+
// Replace longer names first to reduce any accidental partial-match risk.
|
|
349
|
+
renamePairs.sort((a, b) => b.from.length - a.from.length);
|
|
350
|
+
const replaceCode = (code) => {
|
|
351
|
+
let out = code;
|
|
352
|
+
for (const { from, to } of renamePairs) {
|
|
353
|
+
const re = new RegExp(`\\b${escapeRegExpLiteral(from)}\\b`, 'g');
|
|
354
|
+
out = out.replace(re, to);
|
|
355
|
+
}
|
|
356
|
+
return out;
|
|
357
|
+
};
|
|
358
|
+
return applyReplacementsOutsideStringsAndComments(tsText, replaceCode);
|
|
359
|
+
}
|
|
360
|
+
// PURE: Derive the TS value type for JobStepSocket from Genesis.json.
|
|
361
|
+
// We prefer to match the schema shape:
|
|
362
|
+
// JobStepSocket.additionalProperties.oneOf = [#ResourcePotential, #Resource]
|
|
363
|
+
// so the emitted TS becomes:
|
|
364
|
+
// Record<ResourceRoleIdentity, Resource | ResourcePotential>
|
|
365
|
+
function deriveJobStepSocketValueType(parsedSchema) {
|
|
366
|
+
// NOTE: The generator reads from `src/generated/schemas/Genesis.json`, where `$defs.*`
|
|
367
|
+
// entries are plain JSON-Schema objects.
|
|
368
|
+
// The source-of-truth `src/Genesis.json` uses a wrapper shape:
|
|
369
|
+
// $defs.X = { identity, name, description, nucleusSchema: { ...actual schema... } }
|
|
370
|
+
// Support both.
|
|
371
|
+
const defs = parsedSchema?.$defs ?? parsedSchema?.nucleusSchema?.$defs;
|
|
372
|
+
const def = defs?.JobStepSocket;
|
|
373
|
+
const schemaNode = def?.nucleusSchema ?? def;
|
|
374
|
+
const additionalProperties = schemaNode?.additionalProperties;
|
|
375
|
+
if (!additionalProperties || typeof additionalProperties !== 'object' || Array.isArray(additionalProperties)) {
|
|
376
|
+
return 'Resource';
|
|
377
|
+
}
|
|
378
|
+
const union = additionalProperties.oneOf ??
|
|
379
|
+
additionalProperties.anyOf;
|
|
380
|
+
if (!Array.isArray(union) || union.length === 0) {
|
|
381
|
+
return 'Resource';
|
|
382
|
+
}
|
|
383
|
+
const names = [];
|
|
384
|
+
for (const item of union) {
|
|
385
|
+
const ref = item && typeof item === 'object' ? item.$ref : undefined;
|
|
386
|
+
if (typeof ref !== 'string')
|
|
387
|
+
continue;
|
|
388
|
+
// Accept both internal anchor refs like "#Resource" and JSON Pointer refs like "#/$defs/Resource".
|
|
389
|
+
const m = /^#(?:\/(?:\$defs|definitions)\/)?([A-Za-z_][A-Za-z0-9_]*)$/.exec(ref);
|
|
390
|
+
if (m)
|
|
391
|
+
names.push(m[1]);
|
|
392
|
+
}
|
|
393
|
+
const unique = Array.from(new Set(names));
|
|
394
|
+
if (!unique.length)
|
|
395
|
+
return 'Resource';
|
|
396
|
+
// Preserve an intentional ordering when we recognize the canonical pair.
|
|
397
|
+
if (unique.includes('Resource') && unique.includes('ResourcePotential')) {
|
|
398
|
+
return 'Resource | ResourcePotential';
|
|
399
|
+
}
|
|
400
|
+
return unique.join(' | ');
|
|
401
|
+
}
|
|
230
402
|
// PURE: Fix a known json-schema-to-typescript edge case where a JSON-like recursive value union
|
|
231
403
|
// accidentally includes a direct self-reference (`| JsonData`) instead of the intended array case (`| JsonData[]`).
|
|
232
404
|
function fixJsonDataSelfReference(ts) {
|
|
@@ -306,19 +478,25 @@ function postProcessEmittedTypes(ts, parsedSchema) {
|
|
|
306
478
|
const resourceRoleKeyType = 'ResourceRoleIdentity';
|
|
307
479
|
const jobStepKeyType = 'JobStepIdentity';
|
|
308
480
|
const strategyThreadKeyType = 'StrategyThreadIdentity';
|
|
309
|
-
ts = ts.replace(/export interface
|
|
481
|
+
ts = ts.replace(/export interface RoleDict\s*{[^}]*}/g, `export type RoleDict = Record<${resourceRoleKeyType}, ResourceRoleValue>;`);
|
|
310
482
|
// Normalize StrategyState & related socket maps to identity-keyed Records.
|
|
311
483
|
// These are emitted as `[k: string]` by json-schema-to-typescript but are identity-keyed in practice.
|
|
312
|
-
// Per schema: JobStepSocket: Record<ResourceRoleIdentity, Resource>
|
|
484
|
+
// Per schema: JobStepSocket: Record<ResourceRoleIdentity, Resource | ResourcePotential>
|
|
313
485
|
// StrategyState: Record<JobStepIdentity, JobStepSocket>
|
|
314
|
-
const jobStepSocketValueType =
|
|
486
|
+
const jobStepSocketValueType = deriveJobStepSocketValueType(parsedSchema);
|
|
315
487
|
ts = ts.replace(/export interface JobStepSocket\s*\{\s*\[k:\s*string\]:\s*[^;]+;\s*\}/g, `export type JobStepSocket = Record<${resourceRoleKeyType}, ${jobStepSocketValueType}>;`);
|
|
488
|
+
// If the upstream generator (or earlier passes) already emitted a Record-based alias,
|
|
489
|
+
// force its value type to match the schema-derived union.
|
|
490
|
+
ts = ts.replace(/export\s+type\s+JobStepSocket\s*=\s*Record<\s*ResourceRoleIdentity\s*,\s*[^>]+>\s*;/g, `export type JobStepSocket = Record<${resourceRoleKeyType}, ${jobStepSocketValueType}>;`);
|
|
316
491
|
ts = ts.replace(/export interface StrategyState\s*\{\s*\[k:\s*string\]:\s*JobStepSocket;\s*\}/g, `export type StrategyState = Record<${jobStepKeyType}, JobStepSocket>;`);
|
|
317
492
|
ts = ts.replace(/(strategyStateUpdate\??:\s*)\{\s*\[k:\s*string\]:\s*JobStepSocket;\s*\};/g, `$1Record<${jobStepKeyType}, JobStepSocket>;`);
|
|
318
|
-
// Ensure key constraints for
|
|
493
|
+
// Ensure key constraints for strategyThreadDict are preserved as template-literal identity keys.
|
|
319
494
|
// json-schema-to-typescript emits `[k: string]: StepArray;`, but we want keys to be `StrategyThreadIdentity`.
|
|
320
|
-
ts = ts.replace(/export interface
|
|
495
|
+
ts = ts.replace(/export interface StrategyThreadDict\s*\{\s*\[k:\s*string\]:\s*StepArray;\s*\}/g, `export type StrategyThreadDict = Record<${strategyThreadKeyType}, StepArray>;`);
|
|
321
496
|
ts = fixJsonDataSelfReference(ts);
|
|
497
|
+
// IMPORTANT: do this last so earlier post-processing regexes can target
|
|
498
|
+
// the generator's original names (without `Json` suffixes).
|
|
499
|
+
ts = renameExportedTopLevelTypesToJson(ts);
|
|
322
500
|
return ts;
|
|
323
501
|
}
|
|
324
502
|
// PURE: Add banner + formatting/guards to build the final .d.ts content.
|
|
@@ -22,8 +22,10 @@ function generateResourceShellLogic(genesis) {
|
|
|
22
22
|
resourceRoleHandle: 'ROLE-Genesis',
|
|
23
23
|
jobStepHandle: 'JOB_STEP-Genesis'
|
|
24
24
|
},
|
|
25
|
-
|
|
25
|
+
resourceShellKind: 'materialized',
|
|
26
|
+
version: 1,
|
|
26
27
|
timestamp: genesisTimestamp,
|
|
28
|
+
path: 'https://schemas.toolproof.com/v1/Genesis.json',
|
|
27
29
|
nucleus: {}
|
|
28
30
|
};
|
|
29
31
|
defKeys.forEach((defName) => {
|
|
@@ -33,10 +35,12 @@ function generateResourceShellLogic(genesis) {
|
|
|
33
35
|
resourceTypeHandle: 'TYPE-ResourceType',
|
|
34
36
|
creationContext: {
|
|
35
37
|
resourceRoleHandle: 'ROLE-Genesis',
|
|
36
|
-
jobStepHandle:
|
|
38
|
+
jobStepHandle: 'JOB_STEP-Genesis'
|
|
37
39
|
},
|
|
38
|
-
|
|
40
|
+
resourceShellKind: 'materialized',
|
|
41
|
+
version: 1,
|
|
39
42
|
timestamp: genesisTimestamp,
|
|
43
|
+
path: `https://schemas.toolproof.com/v1/Genesis.json#/$defs/${defName}`,
|
|
40
44
|
nucleus: defValue
|
|
41
45
|
};
|
|
42
46
|
});
|