@specverse/engines 6.5.4 → 6.7.8
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/libs/instance-factories/applications/templates/generic/backend-package-json-generator.js +26 -10
- package/dist/libs/instance-factories/controllers/templates/fastify/server-generator.js +1 -1
- package/dist/libs/instance-factories/services/mongodb-native-services.yaml +84 -0
- package/dist/libs/instance-factories/services/templates/mongodb-native/client-generator.js +43 -0
- package/dist/libs/instance-factories/services/templates/mongodb-native/controller-generator.js +252 -0
- package/dist/libs/instance-factories/services/templates/mongodb-native/service-generator.js +64 -0
- package/dist/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.js +167 -26
- package/dist/realize/library/library.d.ts.map +1 -1
- package/dist/realize/library/library.js +11 -0
- package/dist/realize/library/library.js.map +1 -1
- package/libs/instance-factories/applications/templates/generic/backend-package-json-generator.ts +48 -12
- package/libs/instance-factories/controllers/templates/fastify/server-generator.ts +1 -1
- package/libs/instance-factories/services/mongodb-native-services.yaml +84 -0
- package/libs/instance-factories/services/templates/mongodb-native/__tests__/controller-generator.test.ts +113 -0
- package/libs/instance-factories/services/templates/mongodb-native/client-generator.ts +51 -0
- package/libs/instance-factories/services/templates/mongodb-native/controller-generator.ts +319 -0
- package/libs/instance-factories/services/templates/mongodb-native/service-generator.ts +83 -0
- package/libs/instance-factories/services/templates/prisma/ai-behaviors-generator.ts +231 -36
- package/package.json +4 -5
|
@@ -46,6 +46,85 @@ async function validateTypeScript(code: string): Promise<string | null> {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Type-check the generated body in isolation using the TypeScript compiler
|
|
51
|
+
* API. Returns null if clean, or a concise error string suitable for
|
|
52
|
+
* passing back to the LLM as a fix-up hint. Skipped silently if the `typescript`
|
|
53
|
+
* package isn't installed (the realize pipeline still runs full tsc against
|
|
54
|
+
* the realized output downstream — this is a faster, generator-side filter
|
|
55
|
+
* to catch the most common LLM mistakes before they hit the user).
|
|
56
|
+
*
|
|
57
|
+
* Why bother: the LLM regularly emits patterns that are valid syntax but
|
|
58
|
+
* fail strict tsc — RegExp index access (`m[1]` is `string | undefined`),
|
|
59
|
+
* unused locals, undefined references. Reprompting with the tsc error
|
|
60
|
+
* lets the LLM self-correct without burning a per-step retry.
|
|
61
|
+
*/
|
|
62
|
+
async function validateTypeScriptTypes(code: string): Promise<string | null> {
|
|
63
|
+
let ts: any;
|
|
64
|
+
try {
|
|
65
|
+
ts = await import('typescript');
|
|
66
|
+
if (ts.default) ts = ts.default;
|
|
67
|
+
} catch {
|
|
68
|
+
return null; // typescript not available — skip
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const fileName = 'aiBehavior.ts';
|
|
72
|
+
const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2022, true);
|
|
73
|
+
// Mirror the strict shape used by the realized backend's tsconfig so
|
|
74
|
+
// a body that passes here also passes downstream. Failing to match the
|
|
75
|
+
// realized strictness means we'd ship code that fails user-side tsc
|
|
76
|
+
// (defeating the whole point of generator-side validation).
|
|
77
|
+
const compilerOptions: any = {
|
|
78
|
+
target: ts.ScriptTarget.ES2022,
|
|
79
|
+
module: ts.ModuleKind.ESNext,
|
|
80
|
+
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
81
|
+
strict: true,
|
|
82
|
+
noImplicitAny: false, // body uses `any` extensively for inputs
|
|
83
|
+
noUnusedLocals: true,
|
|
84
|
+
noUnusedParameters: true,
|
|
85
|
+
noImplicitReturns: true,
|
|
86
|
+
noUncheckedIndexedAccess: true,
|
|
87
|
+
noFallthroughCasesInSwitch: true,
|
|
88
|
+
noEmit: true,
|
|
89
|
+
skipLibCheck: true,
|
|
90
|
+
types: [],
|
|
91
|
+
// Without `lib`, tsc can't resolve Promise / Array / RegExp etc., and
|
|
92
|
+
// every body fails the basic-types check before it even gets to the
|
|
93
|
+
// strict-null-check rules we actually want to validate.
|
|
94
|
+
lib: ['lib.es2022.d.ts'],
|
|
95
|
+
};
|
|
96
|
+
const defaultHost = ts.createCompilerHost(compilerOptions);
|
|
97
|
+
const host: any = {
|
|
98
|
+
...defaultHost,
|
|
99
|
+
getSourceFile: (n: string, target: any) => {
|
|
100
|
+
if (n === fileName) return sourceFile;
|
|
101
|
+
return defaultHost.getSourceFile(n, target);
|
|
102
|
+
},
|
|
103
|
+
writeFile: () => {},
|
|
104
|
+
fileExists: (n: string) => n === fileName || defaultHost.fileExists(n),
|
|
105
|
+
readFile: (n: string) => (n === fileName ? code : defaultHost.readFile(n)),
|
|
106
|
+
};
|
|
107
|
+
const program = ts.createProgram([fileName], compilerOptions, host);
|
|
108
|
+
const diagnostics = [
|
|
109
|
+
...program.getSyntacticDiagnostics(sourceFile),
|
|
110
|
+
...program.getSemanticDiagnostics(sourceFile),
|
|
111
|
+
];
|
|
112
|
+
if (diagnostics.length === 0) return null;
|
|
113
|
+
const formatted = diagnostics.slice(0, 5).map((d: any) => {
|
|
114
|
+
const msg = ts.flattenDiagnosticMessageText(d.messageText, '\n');
|
|
115
|
+
const pos = d.file && d.start !== undefined
|
|
116
|
+
? d.file.getLineAndCharacterOfPosition(d.start)
|
|
117
|
+
: null;
|
|
118
|
+
return pos
|
|
119
|
+
? `line ${pos.line + 1}, col ${pos.character + 1}: ${msg}`
|
|
120
|
+
: msg;
|
|
121
|
+
});
|
|
122
|
+
return formatted.join('; ');
|
|
123
|
+
} catch {
|
|
124
|
+
return null; // never let validation crash the generator
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
49
128
|
/**
|
|
50
129
|
* AI output cache — avoids re-calling Claude for unchanged steps.
|
|
51
130
|
*
|
|
@@ -56,7 +135,7 @@ async function validateTypeScript(code: string): Promise<string | null> {
|
|
|
56
135
|
* produces a new hash. The prompt version is part of the hash so
|
|
57
136
|
* prompt upgrades also invalidate.
|
|
58
137
|
*/
|
|
59
|
-
const PROMPT_VERSION = '9.
|
|
138
|
+
const PROMPT_VERSION = '9.2.0';
|
|
60
139
|
|
|
61
140
|
function cacheKey(step: string, modelName: string, operationName: string, functionName: string, inputs: string[]): string {
|
|
62
141
|
const payload = JSON.stringify({ step, modelName, operationName, functionName, inputs: [...inputs].sort(), v: PROMPT_VERSION });
|
|
@@ -229,15 +308,76 @@ export async function generateAiBehaviorsFile(opts: {
|
|
|
229
308
|
let cacheHits = 0;
|
|
230
309
|
let cacheMisses = 0;
|
|
231
310
|
for (const { functionName, step, operationName, parameterNames, inputs, returns, modelName } of unmatchedFunctions) {
|
|
232
|
-
// Pure function signature
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
311
|
+
// Pure function signature + destructure are built AFTER the body so we
|
|
312
|
+
// can match what the LLM actually references — strict tsc's
|
|
313
|
+
// noUnusedLocals / noUnusedParameters fire on every input the body
|
|
314
|
+
// didn't touch. We tolerate underuse rather than re-prompting the LLM:
|
|
315
|
+
// the body is correct as-is, we just trim the wrapper to fit it.
|
|
316
|
+
//
|
|
317
|
+
// Three cases:
|
|
318
|
+
// - body uses some inputs: destructure only those
|
|
319
|
+
// - body uses none directly but references `input.X`: keep `input`
|
|
320
|
+
// - body doesn't touch input at all: prefix signature with `_` so
|
|
321
|
+
// noUnusedParameters is happy
|
|
322
|
+
/** Strip string/template/comment content so identifier-reference checks
|
|
323
|
+
* don't match `reward` inside a kebab-case string like `'reward-not-granted'`
|
|
324
|
+
* or `// reward stays as text`. We replace the literal contents with
|
|
325
|
+
* spaces so positions stay roughly aligned in case of debugging. */
|
|
326
|
+
const stripLiteralsAndComments = (src: string): string => {
|
|
327
|
+
return src
|
|
328
|
+
.replace(/\/\*[\s\S]*?\*\//g, (m) => ' '.repeat(m.length))
|
|
329
|
+
.replace(/\/\/[^\n]*/g, (m) => ' '.repeat(m.length))
|
|
330
|
+
.replace(/(['"])(?:\\.|(?!\1).)*\1/g, (m) => m[0] + ' '.repeat(m.length - 2) + m[0])
|
|
331
|
+
.replace(/`(?:\\.|\$\{[^}]*\}|(?!`).)*`/g, (m) => '`' + ' '.repeat(m.length - 2) + '`');
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
/** Detect whether the body manages its own input access (so adding our
|
|
335
|
+
* own destructure would either duplicate-declare or leave us with
|
|
336
|
+
* unused-locals). Three shapes the LLM emits:
|
|
337
|
+
* 1. `const { X, Y } = input;` (destructure)
|
|
338
|
+
* 2. `const X = input.X;` (per-property)
|
|
339
|
+
* 3. `const _X = input.X;` (per-property with rename)
|
|
340
|
+
* If ANY of these appear, the body is its own input setup and we
|
|
341
|
+
* should leave it alone. */
|
|
342
|
+
const bodyHandlesInputItself = (body: string): boolean => {
|
|
343
|
+
const codeOnly = stripLiteralsAndComments(body);
|
|
344
|
+
// Destructure: `const { ... } = input;`
|
|
345
|
+
if (/(?:const|let|var)\s*\{[^}]+\}\s*=\s*input\b/.test(codeOnly)) return true;
|
|
346
|
+
// Per-property access: any `(const|let|var) <name> = input.<name>`
|
|
347
|
+
if (/(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*=\s*input\.[A-Za-z_$][\w$]*/.test(codeOnly)) return true;
|
|
348
|
+
return false;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/** Does the body actually USE the local variable `n` (vs only mention
|
|
352
|
+
* it as an object-literal property name like `step1Result:` in a
|
|
353
|
+
* return object)? A real usage is `n` followed by something other than
|
|
354
|
+
* `:` — i.e. accessed in an expression. We approximate by requiring
|
|
355
|
+
* the next non-whitespace char to be a code-meaningful operator/end. */
|
|
356
|
+
const isRealReference = (n: string, codeOnly: string): boolean => {
|
|
357
|
+
const escaped = n.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
358
|
+
const re = new RegExp(`(?<![A-Za-z0-9_$])${escaped}(?![A-Za-z0-9_$:])`, 'g');
|
|
359
|
+
return re.test(codeOnly);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const buildSignatureAndDestructure = (body: string): { signature: string; destructure: string } => {
|
|
363
|
+
if (inputs.length === 0) {
|
|
364
|
+
return { signature: 'input: Record<string, never>', destructure: '' };
|
|
365
|
+
}
|
|
366
|
+
const codeOnly = stripLiteralsAndComments(body);
|
|
367
|
+
const referenced = inputs.filter((n) => isRealReference(n, codeOnly));
|
|
368
|
+
const usesInputObject = /(?<![A-Za-z0-9_$])input(?![A-Za-z0-9_$])/.test(codeOnly);
|
|
369
|
+
const sigName = (referenced.length > 0 || usesInputObject) ? 'input' : '_input';
|
|
370
|
+
const sig = `${sigName}: { ${inputs.map(n => `${n}: any`).join('; ')} }`;
|
|
371
|
+
// If the body already manages its own input access (destructure or
|
|
372
|
+
// per-property) OR accesses input.X directly, don't add a wrapper
|
|
373
|
+
// destructure — would leave us with unused locals (TS6198) or
|
|
374
|
+
// duplicate declarations (TS2451).
|
|
375
|
+
const bodyAccessesInputProps = /(?<![A-Za-z0-9_$])input\.[A-Za-z_$]/.test(codeOnly);
|
|
376
|
+
const destructure = (referenced.length > 0 && !bodyHandlesInputItself(body) && !bodyAccessesInputProps)
|
|
377
|
+
? ` const { ${referenced.join(', ')} } = input;`
|
|
378
|
+
: '';
|
|
379
|
+
return { signature: sig, destructure };
|
|
380
|
+
};
|
|
241
381
|
|
|
242
382
|
// Build return type from spec declaration (if provided)
|
|
243
383
|
// returns can be:
|
|
@@ -258,11 +398,14 @@ export async function generateAiBehaviorsFile(opts: {
|
|
|
258
398
|
let source: 'AI-CACHED' | 'AI-GENERATED' | 'AI-INVALID' | 'STUB' = body ? 'AI-CACHED' : 'STUB';
|
|
259
399
|
if (body) {
|
|
260
400
|
// Validate cache entry — a previously valid entry may have been
|
|
261
|
-
// corrupted on disk
|
|
401
|
+
// corrupted on disk OR the validation rules may have tightened
|
|
402
|
+
// (e.g. tsc type checks added). A cache hit must still be re-validated
|
|
403
|
+
// through both gates so old bodies don't leak past the new bar.
|
|
262
404
|
const testCode = `export async function ${functionName}(input: any): Promise<any> {\n${body}\n}`;
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
405
|
+
const syntaxError = await validateTypeScript(testCode);
|
|
406
|
+
const typeError = syntaxError ? null : await validateTypeScriptTypes(testCode);
|
|
407
|
+
if (syntaxError || typeError) {
|
|
408
|
+
console.warn(` [ai-validate] cached ${functionName} failed validation: ${syntaxError || typeError}`);
|
|
266
409
|
body = null; // Force regeneration
|
|
267
410
|
source = 'STUB';
|
|
268
411
|
} else {
|
|
@@ -285,17 +428,62 @@ export async function generateAiBehaviorsFile(opts: {
|
|
|
285
428
|
});
|
|
286
429
|
|
|
287
430
|
if (body) {
|
|
288
|
-
//
|
|
431
|
+
// Two-tier validation:
|
|
432
|
+
// 1. esbuild syntax check — fast, catches unbalanced braces, etc.
|
|
433
|
+
// 2. tsc type check — slower, catches `string | undefined` index
|
|
434
|
+
// access, unused locals, and undefined references the LLM
|
|
435
|
+
// regularly produces. On tsc failure, we re-prompt the LLM
|
|
436
|
+
// with the error message appended; only ONE retry to bound
|
|
437
|
+
// cost. If that still fails we keep the body but mark it
|
|
438
|
+
// AI-INVALID so the user sees it needs review.
|
|
289
439
|
const testCode = `export async function ${functionName}(input: any): Promise<any> {\n${body}\n}`;
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
console.warn(` [ai-validate] ${functionName} has syntax error: ${
|
|
293
|
-
//
|
|
294
|
-
body = `// AI-generated code failed validation: ${validationError}\n // Step: ${step}\n throw new Error('AI behavior has invalid syntax — see comment above');`;
|
|
440
|
+
const syntaxError = await validateTypeScript(testCode);
|
|
441
|
+
if (syntaxError) {
|
|
442
|
+
console.warn(` [ai-validate] ${functionName} has syntax error: ${syntaxError}`);
|
|
443
|
+
body = `// AI-generated code failed validation: ${syntaxError}\n // Step: ${step}\n throw new Error('AI behavior has invalid syntax — see comment above');`;
|
|
295
444
|
source = 'AI-INVALID';
|
|
296
445
|
} else {
|
|
297
|
-
|
|
298
|
-
|
|
446
|
+
const typeError = await validateTypeScriptTypes(testCode);
|
|
447
|
+
if (typeError) {
|
|
448
|
+
console.warn(` [ai-validate] ${functionName} type errors: ${typeError}`);
|
|
449
|
+
try {
|
|
450
|
+
const retryHint = `Your previous output produced TypeScript type errors:\n${typeError}\n\nFix these specifically — common causes:\n- RegExp match indices are 'string | undefined'; use non-null assertion or extract to a typed variable\n- Strict null checks: guard or assert before use\n- Don't declare locals you never reference\n\nIMPORTANT: The destructure line \`const { ... } = input;\` is added by the wrapper, NOT by you. Output ONLY the function body that goes AFTER that line — do not repeat the destructure or you will produce duplicate-declaration errors.`;
|
|
451
|
+
const retried = await aiService.generateBehavior({
|
|
452
|
+
step: `${step}\n\n${retryHint}`,
|
|
453
|
+
modelName,
|
|
454
|
+
operationName,
|
|
455
|
+
functionName,
|
|
456
|
+
parameterNames: inputs,
|
|
457
|
+
availableModels,
|
|
458
|
+
spec,
|
|
459
|
+
returnType,
|
|
460
|
+
});
|
|
461
|
+
if (retried) {
|
|
462
|
+
const retryCode = `export async function ${functionName}(input: any): Promise<any> {\n${retried}\n}`;
|
|
463
|
+
const retrySyntaxError = await validateTypeScript(retryCode);
|
|
464
|
+
const retryTypeError = retrySyntaxError ? null : await validateTypeScriptTypes(retryCode);
|
|
465
|
+
if (!retrySyntaxError && !retryTypeError) {
|
|
466
|
+
body = retried;
|
|
467
|
+
source = 'AI-GENERATED';
|
|
468
|
+
cacheWrite(key, body);
|
|
469
|
+
} else {
|
|
470
|
+
// Retry didn't help — keep the original body so the user can fix
|
|
471
|
+
// manually, but mark it as INVALID so it stands out.
|
|
472
|
+
source = 'AI-INVALID';
|
|
473
|
+
cacheWrite(key, body);
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
source = 'AI-INVALID';
|
|
477
|
+
cacheWrite(key, body);
|
|
478
|
+
}
|
|
479
|
+
} catch {
|
|
480
|
+
source = 'AI-INVALID';
|
|
481
|
+
cacheWrite(key, body);
|
|
482
|
+
}
|
|
483
|
+
} else {
|
|
484
|
+
source = 'AI-GENERATED';
|
|
485
|
+
cacheWrite(key, body);
|
|
486
|
+
}
|
|
299
487
|
}
|
|
300
488
|
}
|
|
301
489
|
} catch {
|
|
@@ -335,8 +523,14 @@ ${inputsDoc}${returnsDoc} * Source: ${source}
|
|
|
335
523
|
? 'AI returned code with syntax errors — function throws at runtime. Fix or regenerate.'
|
|
336
524
|
: 'STUB — Claude CLI unavailable. Install Claude Code or implement manually.'}
|
|
337
525
|
*/
|
|
338
|
-
export async function ${functionName}(${
|
|
339
|
-
|
|
526
|
+
export async function ${functionName}(${(() => {
|
|
527
|
+
const { signature: sig } = buildSignatureAndDestructure(body);
|
|
528
|
+
return sig;
|
|
529
|
+
})()}): Promise<${returnType}> {
|
|
530
|
+
${(() => {
|
|
531
|
+
const { destructure } = buildSignatureAndDestructure(body);
|
|
532
|
+
return destructure ? destructure + '\n' : '';
|
|
533
|
+
})()}${body}
|
|
340
534
|
}`);
|
|
341
535
|
}
|
|
342
536
|
|
|
@@ -356,27 +550,28 @@ ${destructure ? destructure + '\n' : ''}${body}
|
|
|
356
550
|
* These functions could not be generated from convention patterns.
|
|
357
551
|
* They are called by ${ownerName} when executing operations.
|
|
358
552
|
*
|
|
553
|
+
* PURE-FUNCTION CONTRACT — these bodies must NOT touch the database, the
|
|
554
|
+
* event bus, or any external service. Persistence and side effects happen
|
|
555
|
+
* in the calling controller; this file does pure transformations only.
|
|
556
|
+
*
|
|
359
557
|
* Options for each function:
|
|
360
558
|
* - Implement manually (recommended for business-critical logic)
|
|
361
559
|
* - Use AI generation: specverse ai generate <function>
|
|
362
560
|
* - Refactor the spec step to use a convention pattern
|
|
363
561
|
*
|
|
364
|
-
* Convention patterns that ARE auto-generated (no
|
|
365
|
-
*
|
|
366
|
-
* "
|
|
367
|
-
* "
|
|
368
|
-
* "
|
|
369
|
-
* "
|
|
370
|
-
* "
|
|
371
|
-
*
|
|
562
|
+
* Convention patterns that ARE auto-generated by the realize engine (no
|
|
563
|
+
* AI needed) — these are emitted inline in the controller, not here:
|
|
564
|
+
* "Find {Model} by {field}" → ORM-specific find call
|
|
565
|
+
* "Create {Model}" → ORM-specific create call
|
|
566
|
+
* "Update {Model} {field} to {value}"
|
|
567
|
+
* "Delete {Model}"
|
|
568
|
+
* "Transition {Model} to {state}"
|
|
569
|
+
* "Count {Model}s per {Group}"
|
|
570
|
+
* See the ORM's step-conventions module for the full list.
|
|
372
571
|
*
|
|
373
572
|
* Generated: ${new Date().toISOString().split('T')[0]}
|
|
374
573
|
*/
|
|
375
574
|
|
|
376
|
-
import { PrismaClient } from '@prisma/client';
|
|
377
|
-
|
|
378
|
-
const prisma = new PrismaClient();
|
|
379
|
-
|
|
380
575
|
${functions.join('\n\n')}
|
|
381
576
|
`;
|
|
382
577
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specverse/engines",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.7.8",
|
|
4
4
|
"description": "SpecVerse toolchain — parser, inference, realize, generators, AI, registry, bundles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -62,26 +62,25 @@
|
|
|
62
62
|
"@ai-sdk/openai-compatible": "^2.0.41",
|
|
63
63
|
"@ai-sdk/provider": "^3.0.8",
|
|
64
64
|
"@specverse/assets": "^1.6.0",
|
|
65
|
-
"@specverse/engines": "^6.4.0",
|
|
66
65
|
"@specverse/entities": "^5.1.0",
|
|
67
66
|
"@specverse/runtime": "^5.0.1",
|
|
68
67
|
"@specverse/types": "^5.1.0",
|
|
69
68
|
"ai": "^6.0.168",
|
|
70
69
|
"ajv": "^8.17.0",
|
|
71
70
|
"ajv-formats": "^2.1.0",
|
|
71
|
+
"esbuild": "^0.25.0",
|
|
72
72
|
"glob": "^10.0.0",
|
|
73
73
|
"graphology": "^0.26.0",
|
|
74
74
|
"graphology-communities-louvain": "^2.0.2",
|
|
75
75
|
"handlebars": "^4.7.9",
|
|
76
76
|
"js-yaml": "^4.1.0",
|
|
77
77
|
"semver": "^7.0.0",
|
|
78
|
+
"typescript": "^5.4.0",
|
|
78
79
|
"yaml": "^2.8.1",
|
|
79
80
|
"zod": "^4.3.6"
|
|
80
81
|
},
|
|
81
82
|
"devDependencies": {
|
|
82
|
-
"@types/node": "^25.5.0"
|
|
83
|
-
"esbuild": "^0.25.0",
|
|
84
|
-
"typescript": "^5.4.0"
|
|
83
|
+
"@types/node": "^25.5.0"
|
|
85
84
|
},
|
|
86
85
|
"files": [
|
|
87
86
|
"dist",
|