@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.
Files changed (74) hide show
  1. package/dist/generated/constants/constants.d.ts +60 -0
  2. package/dist/generated/constants/constants.js +60 -0
  3. package/dist/generated/normalized/Genesis.json +0 -261
  4. package/dist/generated/resources/Genesis.json +0 -299
  5. package/dist/generated/schemas/Genesis.json +0 -150
  6. package/dist/generated/schemas/standalone/Goal.json +0 -33
  7. package/dist/generated/schemas/standalone/Job.json +0 -42
  8. package/dist/generated/schemas/standalone/RawStrategy.json +0 -46
  9. package/dist/generated/schemas/standalone/ResourceType.json +0 -34
  10. package/dist/generated/schemas/standalone/RunnableStrategy.json +0 -51
  11. package/dist/generated/schemas/standalone/StrategyRun.json +0 -65
  12. package/dist/generated/{typesTS → types}/standalone/Resource_Genesis.d.ts +1 -1
  13. package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_Job.d.ts +1 -1
  14. package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_RawStrategy.d.ts +1 -1
  15. package/{src/generated/typesTS → dist/generated/types}/standalone/Resource_ResourceType.d.ts +1 -1
  16. package/dist/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.d.ts +1 -1
  17. package/dist/generated/{typesTS/typesTS.d.ts → types/types.d.ts} +13 -49
  18. package/dist/index.d.ts +7 -6
  19. package/dist/index.js +1 -0
  20. package/dist/scripts/_lib/config.d.ts +15 -12
  21. package/dist/scripts/_lib/config.js +34 -27
  22. package/dist/scripts/generateConstants.d.ts +12 -0
  23. package/dist/scripts/generateConstants.js +179 -0
  24. package/dist/scripts/generateSchemaShims.js +2 -2
  25. package/dist/scripts/generateStandaloneSchema.js +1 -1
  26. package/dist/scripts/{generateStandaloneTypeTS.js → generateStandaloneType.js} +9 -9
  27. package/dist/scripts/generateTerminals.js +58 -0
  28. package/dist/scripts/generateTypes.d.ts +1 -0
  29. package/dist/scripts/{generateTypesTS.js → generateTypes.js} +11 -11
  30. package/dist/scripts/normalizeAnchorsToPointers.d.ts +1 -1
  31. package/dist/scripts/normalizeAnchorsToPointers.js +33 -12
  32. package/package.json +7 -5
  33. package/src/Genesis.json +0 -174
  34. package/src/generated/constants/constants.ts +61 -0
  35. package/src/generated/dependencies/dependencyMap.json +2 -14
  36. package/src/generated/dependencies/terminals.json +12 -0
  37. package/src/generated/normalized/Genesis.json +0 -261
  38. package/src/generated/resources/Genesis.json +0 -299
  39. package/src/generated/schemas/Genesis.json +0 -150
  40. package/src/generated/schemas/standalone/Goal.json +0 -33
  41. package/src/generated/schemas/standalone/Job.json +0 -42
  42. package/src/generated/schemas/standalone/RawStrategy.json +0 -46
  43. package/src/generated/schemas/standalone/ResourceType.json +0 -34
  44. package/src/generated/schemas/standalone/RunnableStrategy.json +0 -51
  45. package/src/generated/schemas/standalone/StrategyRun.json +0 -65
  46. package/src/generated/{typesTS → types}/standalone/Resource_Genesis.d.ts +1 -1
  47. package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_Job.d.ts +1 -1
  48. package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_RawStrategy.d.ts +1 -1
  49. package/{dist/generated/typesTS → src/generated/types}/standalone/Resource_ResourceType.d.ts +1 -1
  50. package/src/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.d.ts +1 -1
  51. package/src/generated/{typesTS/typesTS.d.ts → types/types.d.ts} +13 -49
  52. package/src/index.ts +9 -7
  53. package/src/scripts/_lib/config.ts +39 -29
  54. package/src/scripts/generateConstants.ts +217 -0
  55. package/src/scripts/generateSchemaShims.ts +2 -2
  56. package/src/scripts/generateStandaloneSchema.ts +1 -1
  57. package/src/scripts/{generateStandaloneTypeTS.ts → generateStandaloneType.ts} +9 -9
  58. package/src/scripts/generateTerminals.ts +73 -0
  59. package/src/scripts/{generateTypesTS.ts → generateTypes.ts} +11 -11
  60. package/src/scripts/normalizeAnchorsToPointers.ts +38 -12
  61. /package/dist/generated/{typesTS → types}/standalone/Resource_Genesis.js +0 -0
  62. /package/dist/generated/{typesTS → types}/standalone/Resource_Job.js +0 -0
  63. /package/dist/generated/{typesTS → types}/standalone/Resource_RawStrategy.js +0 -0
  64. /package/dist/generated/{typesTS → types}/standalone/Resource_ResourceType.js +0 -0
  65. /package/dist/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.js +0 -0
  66. /package/dist/generated/{typesTS/typesTS.js → types/types.js} +0 -0
  67. /package/dist/scripts/{generateStandaloneTypeTS.d.ts → generateStandaloneType.d.ts} +0 -0
  68. /package/dist/scripts/{generateTypesTS.d.ts → generateTerminals.d.ts} +0 -0
  69. /package/src/generated/{typesTS → types}/standalone/Resource_Genesis.js +0 -0
  70. /package/src/generated/{typesTS → types}/standalone/Resource_Job.js +0 -0
  71. /package/src/generated/{typesTS → types}/standalone/Resource_RawStrategy.js +0 -0
  72. /package/src/generated/{typesTS → types}/standalone/Resource_ResourceType.js +0 -0
  73. /package/src/generated/{typesTS → types}/standalone/Resource_RunnableStrategy.js +0 -0
  74. /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 typesTsSrcDir;
18
- private readonly typesTsDistDir;
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
- getSchemasStandaloneDir(): string;
32
- getSchemaStandalonePath(filename: string): string;
33
- getTypesTsSrcDir(): string;
34
- getTypesTsDistDir(): string;
35
- getTypesTsSrcPath(filename: string): string;
36
- getTypesTsDistPath(filename: string): string;
37
- getStandaloneTypeTsSrcDir(): string;
38
- getStandaloneTypeTsDistDir(): string;
39
- getStandaloneTypeTsSrcPath(filename: string): string;
40
- getStandaloneTypeTsDistPath(filename: string): string;
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.typesTsSrcDir = getEnv('TP_SCHEMA_TYPES_TS_SRC_DIR', 'src/generated/typesTS');
30
- this.typesTsDistDir = getEnv('TP_SCHEMA_TYPES_TS_DIST_DIR', 'dist/generated/typesTS');
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
- getSchemasStandaloneDir() {
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
- getSchemaStandalonePath(filename) {
75
- return path.join(this.getSchemasStandaloneDir(), filename);
81
+ getStandaloneSchemaPath(filename) {
82
+ return path.join(this.getStandaloneSchemaDir(), filename);
76
83
  }
77
- getTypesTsSrcDir() {
78
- return path.isAbsolute(this.typesTsSrcDir)
79
- ? this.typesTsSrcDir
80
- : path.join(this.root, this.typesTsSrcDir);
84
+ getTypesSrcDir() {
85
+ return path.isAbsolute(this.typesSrcDir)
86
+ ? this.typesSrcDir
87
+ : path.join(this.root, this.typesSrcDir);
81
88
  }
82
- getTypesTsDistDir() {
83
- return path.isAbsolute(this.typesTsDistDir)
84
- ? this.typesTsDistDir
85
- : path.join(this.root, this.typesTsDistDir);
89
+ getTypesDistDir() {
90
+ return path.isAbsolute(this.typesDistDir)
91
+ ? this.typesDistDir
92
+ : path.join(this.root, this.typesDistDir);
86
93
  }
87
- getTypesTsSrcPath(filename) {
88
- return path.join(this.getTypesTsSrcDir(), filename);
94
+ getTypesSrcPath(filename) {
95
+ return path.join(this.getTypesSrcDir(), filename);
89
96
  }
90
- getTypesTsDistPath(filename) {
91
- return path.join(this.getTypesTsDistDir(), filename);
97
+ getTypesDistPath(filename) {
98
+ return path.join(this.getTypesDistDir(), filename);
92
99
  }
93
- getStandaloneTypeTsSrcDir() {
94
- return path.join(this.getTypesTsSrcDir(), 'standalone');
100
+ getStandaloneTypeSrcDir() {
101
+ return path.join(this.getTypesSrcDir(), 'standalone');
95
102
  }
96
- getStandaloneTypeTsDistDir() {
97
- return path.join(this.getTypesTsDistDir(), 'standalone');
103
+ getStandaloneTypeDistDir() {
104
+ return path.join(this.getTypesDistDir(), 'standalone');
98
105
  }
99
- getStandaloneTypeTsSrcPath(filename) {
100
- return path.join(this.getStandaloneTypeTsSrcDir(), filename);
106
+ getStandaloneTypeSrcPath(filename) {
107
+ return path.join(this.getStandaloneTypeSrcDir(), filename);
101
108
  }
102
- getStandaloneTypeTsDistPath(filename) {
103
- return path.join(this.getStandaloneTypeTsDistDir(), filename);
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.getSchemasStandaloneDir() (standalone schema files)
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.getSchemasStandaloneDir();
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.getSchemaStandalonePath(`${name}.json`);
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/generateStandaloneType.js --name Job
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 "../typesTS.js";\n` +
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.getSchemaStandalonePath(`${name}.json`);
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.getStandaloneTypeTsSrcDir();
83
- const distLibDir = config.getStandaloneTypeTsDistDir();
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.getStandaloneTypeTsSrcPath(outName);
87
- const outJsPath = config.getStandaloneTypeTsSrcPath(outJsName);
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.getStandaloneTypeTsDistPath(outName);
97
- const distJsPath = config.getStandaloneTypeTsDistPath(outJsName);
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(emittedTypesTs) {
325
+ function finalizeOutputDts(emittedType) {
326
326
  const banner = '// Auto-generated from JSON schemas. Do not edit.\n';
327
- let output = banner + '\n' + emittedTypesTs + '\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.getTypesTsSrcDir();
351
- const srcLibOutputPath = config.getTypesTsSrcPath('typesTS.d.ts');
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.getTypesTsDistDir();
393
- const distLibOutputPath = config.getTypesTsDistPath('typesTS.d.ts');
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 `typesTS.d.ts`
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.getTypesTsSrcPath('typesTS.js');
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 typesTS.js to src/_lib:', e);
414
+ console.warn('Failed to write types.js to src/_lib:', e);
415
415
  }
416
416
  try {
417
- const distLibTypesJsPath = config.getTypesTsDistPath('typesTS.js');
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 typesTS.js to dist/_lib:', e);
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
- * Rewrite anchor-style references to JSON Pointer references in Genesis.json
6
- *
7
- * Converts #AnchorName to #/$defs/AnchorName for compatibility with strict
8
- * JSON Schema validators and downstream tooling. This normalization step runs
9
- * before both schema extraction and resource envelope generation.
10
- *
11
- * The rewritten file is saved under src/genesis/generated/resourceTypes/Genesis.json
12
- * for use by other scripts.
13
- *
14
- * Usage: node ./dist/scripts/normalizeAnchorsToPointers.js
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.4",
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
- "generateTypesTS": "node ./dist/scripts/generateTypesTS.js",
38
- "generateStandaloneTypeTS": "node ./dist/scripts/generateStandaloneTypeTS.js",
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
- "generateResourceTypeGenesisType": "node ./dist/scripts/generateStandaloneTypeTS.js --name Genesis",
43
- "update": "rimraf /s /q dist && pnpm run build:scripts && pnpm run normalizeAnchorsToPointers && pnpm run extractSchemasFromResourceTypeShells && 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 generateTypesTS && pnpm run generateStandaloneTypeTS -- --name Job && pnpm run generateStandaloneTypeTS -- --name ResourceType && pnpm run generateStandaloneTypeTS -- --name RawStrategy && pnpm run generateStandaloneTypeTS -- --name RunnableStrategy && pnpm run generateResourceTypeGenesisType && pnpm run generateDependencies && pnpm run build"
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
  }