cabloy 5.1.220 → 5.1.222
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/.cabloy-version +1 -1
- package/.github/workflows/agent-governance.yml +2 -2
- package/.github/workflows/create-cabloy.yml +2 -2
- package/.github/workflows/docs-pages.yml +2 -2
- package/.github/workflows/playwright-e2e.yml +4 -4
- package/.github/workflows/vona-cov-pg.yml +2 -2
- package/.github/workflows/vona-test-crud.yml +2 -2
- package/.github/workflows/vona-test-mysql.yml +2 -2
- package/.github/workflows/vona-test-pg.yml +2 -2
- package/.github/workflows/vona-test-sqlite3.yml +2 -2
- package/.github/workflows/vona-tsc.yml +2 -2
- package/.github/workflows/zova-ui.yml +2 -2
- package/CHANGELOG.md +22 -0
- package/package.json +4 -3
- package/repo-agent-governance/managed-assets.json +15 -15
- package/repo-agent-governance/policies/repository.md +1 -0
- package/repo-agent-governance/skills/cabloy-backend-scaffold/SKILL.md +5 -1
- package/repo-agent-governance/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +7 -5
- package/repo-agent-governance/skills/cabloy-frontend-scaffold/SKILL.md +5 -1
- package/repo-agent-governance/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +6 -4
- package/repo-docs/backend/unit-testing.md +5 -1
- package/repo-docs/frontend/openapi-sdk-guide.md +2 -0
- package/repo-docs/frontend/scripts.md +8 -0
- package/repo-docs/reference/repo-scripts.md +5 -1
- package/scripts/generateOpenapiIsolated.ts +18 -1
- package/scripts/runIsolatedTest.test.ts +9 -1
- package/scripts/runIsolatedTest.ts +81 -18
- package/scripts/strictGenerationDiagnostics.test.ts +1009 -0
- package/scripts/strictGenerationDiagnostics.ts +61 -0
- package/vona/package.original.json +3 -2
- package/vona/packages-cli/cabloy-cli/package.json +1 -1
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +14 -4
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateEntryFiles.ts +6 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateVonaMeta.ts +2 -10
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/validateGenerationPaths.ts +27 -0
- package/vona/packages-cli/cli-set-api/test/binDevLifecycle.test.ts +1 -1
- package/vona/packages-cli/cli-set-api/test/strictGenerationPrivacy.test.ts +439 -0
- package/vona/packages-utils/process-helper/package.json +1 -1
- package/vona/packages-utils/process-helper/src/index.test.ts +62 -0
- package/vona/packages-utils/process-helper/src/index.ts +9 -4
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-core/src/lib/core/completedReadiness.test.ts +558 -0
- package/vona/packages-vona/vona-core/src/lib/core/completedReadiness.ts +389 -0
- package/vona/packages-vona/vona-core/src/lib/core/context.ts +3 -0
- package/vona/packages-vona/vona-core/src/lib/core/index.ts +11 -0
- package/vona/packages-vona/vona-core/src/lib/core/logger/appLogger.ts +10 -2
- package/vona/packages-vona/vona-core/src/lib/core/logger/diagnosticLogger.test.ts +268 -68
- package/vona/packages-vona/vona-core/src/lib/core/meta.ts +5 -0
- package/vona/packages-vona/vona-core/src/lib/core/testFreshness.ts +3 -9
- package/vona/packages-vona/vona-core/src/lib/core/testStrictMode.ts +9 -0
- package/vona/packages-vona/vona-core/src/lib/framework/start.test.ts +10 -0
- package/vona/packages-vona/vona-core/src/lib/framework/start.ts +8 -0
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +542 -236
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-executor/src/bean/bean.executor.ts +124 -4
- package/vona/src/suite-vendor/a-vona/modules/a-executor/src/types/executor.ts +7 -0
- package/vona/src/suite-vendor/a-vona/modules/a-executor/test/readyExisting.test.ts +423 -0
- package/vona/src/suite-vendor/a-vona/modules/a-executor/test/readyExistingCommit.test.ts +174 -0
- package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-instance/src/bean/bean.instance.ts +3 -1
- package/vona/src/suite-vendor/a-vona/modules/a-instance/src/lib/existingReadyAdmission.ts +125 -0
- package/vona/src/suite-vendor/a-vona/modules/a-instance/src/service/instance.ts +72 -25
- package/vona/src/suite-vendor/a-vona/modules/a-instance/test/existingReadyAdmission.test.ts +949 -0
- package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/test/middlewareSystem.httpLog.test.ts +61 -59
- package/vona/src/suite-vendor/a-vona/modules/a-mail/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-mail/src/service/mail.ts +5 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/index.ts +11 -0
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/lib/protectedSqliteRegistry.ts +356 -0
- package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-startup/test/devSeed.test.ts +61 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/package.original.json +3 -3
- package/zova/packages-cli/cli/package.json +4 -4
- package/zova/packages-cli/cli-set-front/package.json +2 -2
- package/zova/packages-cli/cli-set-front/src/lib/common/restDependencyVersions.ts +22 -1
- package/zova/packages-cli/cli-set-front/test/restDependencies.test.ts +137 -0
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +448 -641
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { StdioOptions } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
import { Writable } from 'node:stream';
|
|
4
|
+
|
|
5
|
+
import { requiresFreshTestResources } from '../vona/packages-vona/vona-core/src/lib/core/testStrictMode.ts';
|
|
6
|
+
|
|
7
|
+
export type StrictGenerationStage =
|
|
8
|
+
| 'arguments'
|
|
9
|
+
| 'preparation'
|
|
10
|
+
| 'startup'
|
|
11
|
+
| 'operation'
|
|
12
|
+
| 'shutdown'
|
|
13
|
+
| 'operation-and-shutdown'
|
|
14
|
+
| 'generator'
|
|
15
|
+
| 'cleanup'
|
|
16
|
+
| 'run';
|
|
17
|
+
|
|
18
|
+
const failureStages = new WeakMap<object, StrictGenerationStage>();
|
|
19
|
+
|
|
20
|
+
export class StrictGenerationError extends Error {
|
|
21
|
+
readonly stage: StrictGenerationStage;
|
|
22
|
+
|
|
23
|
+
constructor(stage: StrictGenerationStage) {
|
|
24
|
+
super(`Strict contract generation failed: ${stage}`);
|
|
25
|
+
this.name = 'StrictGenerationError';
|
|
26
|
+
this.stage = stage;
|
|
27
|
+
failureStages.set(this, stage);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function strictGenerationFailure(stage: StrictGenerationStage, error?: unknown) {
|
|
32
|
+
const previous = error && typeof error === 'object' ? failureStages.get(error) : undefined;
|
|
33
|
+
return new StrictGenerationError(previous ?? stage);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function usesStrictGeneration(env: NodeJS.ProcessEnv): boolean {
|
|
37
|
+
try {
|
|
38
|
+
return requiresFreshTestResources(env);
|
|
39
|
+
} catch {
|
|
40
|
+
throw new StrictGenerationError('arguments');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function guardianStdio(strict: boolean): StdioOptions {
|
|
45
|
+
return strict ? ['ignore', 'ignore', 'ignore', 'ipc'] : ['inherit', 'inherit', 'inherit', 'ipc'];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function discardNativeOutput() {
|
|
49
|
+
const discard = () =>
|
|
50
|
+
new Writable({
|
|
51
|
+
write(_chunk, _encoding, callback) {
|
|
52
|
+
callback();
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
return { stdout: discard(), stderr: discard() };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function reportIsolatedDiagnostic(strict: boolean, category: string, value?: unknown) {
|
|
59
|
+
if (strict) console.error(`Strict contract generation: ${category}`);
|
|
60
|
+
else console.error(value);
|
|
61
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "vona",
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
|
-
"packageManager": "pnpm@
|
|
5
|
+
"packageManager": "pnpm@12.14.0",
|
|
6
6
|
"description": "Vona is an intuitive, elegant and powerful Node.js framework for rapidly developing enterprise applications of any size",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"homepage": "https://github.com/vonajs/vona#readme",
|
|
17
17
|
"engines": {
|
|
18
|
-
"node": ">=24.4.0"
|
|
18
|
+
"node": ">=24.4.0",
|
|
19
|
+
"pnpm": ">=11.5.2"
|
|
19
20
|
},
|
|
20
21
|
"scripts": {
|
|
21
22
|
"vona": "node ./packages-cli/cli/src/bin/vona.ts",
|
|
@@ -5,7 +5,7 @@ import { BeanCliBase } from '@cabloy/cli';
|
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
6
|
import nodemon from 'nodemon';
|
|
7
7
|
import { rimraf } from 'rimraf';
|
|
8
|
-
import { resolveVonaLocalPaths } from 'vona-core';
|
|
8
|
+
import { requiresFreshTestResources, resolveVonaLocalPaths } from 'vona-core';
|
|
9
9
|
|
|
10
10
|
import type { VonaBinConfigOptions } from './toolsBin/types.ts';
|
|
11
11
|
|
|
@@ -48,16 +48,21 @@ export class CliBinDev extends BeanCliBase {
|
|
|
48
48
|
const workers = resolveTestWorkers(mode, argv.workers);
|
|
49
49
|
const flavor: VonaMetaFlavor = argv.flavor || 'normal';
|
|
50
50
|
const configMeta: VonaConfigMeta = { flavor, mode };
|
|
51
|
+
const strict = requiresFreshTestResources();
|
|
51
52
|
const paths = resolveVonaLocalPaths(projectPath, mode);
|
|
53
|
+
if (strict && (mode !== 'test' || !paths.runId)) {
|
|
54
|
+
throw new Error('Strict generation requires an isolated test run in test mode');
|
|
55
|
+
}
|
|
52
56
|
const configOptions: VonaBinConfigOptions = {
|
|
53
57
|
appDir: projectPath,
|
|
54
58
|
runtimeDir: paths.generatedDir,
|
|
55
59
|
workers,
|
|
56
60
|
};
|
|
57
61
|
try {
|
|
58
|
-
const { modulesMeta } = await generateVonaMeta(configMeta, configOptions);
|
|
62
|
+
const { env, modulesMeta } = await generateVonaMeta(configMeta, configOptions);
|
|
59
63
|
if (mode === 'test') {
|
|
60
|
-
await this._runTest(projectPath);
|
|
64
|
+
if (strict) await this._runTest(projectPath, env);
|
|
65
|
+
else await this._runTest(projectPath);
|
|
61
66
|
} else {
|
|
62
67
|
await this._run(projectPath, modulesMeta);
|
|
63
68
|
}
|
|
@@ -66,7 +71,11 @@ export class CliBinDev extends BeanCliBase {
|
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
async _runTest(projectPath: string) {
|
|
74
|
+
async _runTest(projectPath: string, resolvedEnv?: NodeJS.ProcessEnv) {
|
|
75
|
+
const strict = requiresFreshTestResources();
|
|
76
|
+
if (strict && !resolvedEnv) {
|
|
77
|
+
throw new Error('Strict generation requires resolved environment handoff');
|
|
78
|
+
}
|
|
70
79
|
const generatedDir = resolveVonaLocalPaths(projectPath, 'test').generatedDir;
|
|
71
80
|
const child = spawn(
|
|
72
81
|
process.execPath,
|
|
@@ -74,6 +83,7 @@ export class CliBinDev extends BeanCliBase {
|
|
|
74
83
|
{
|
|
75
84
|
cwd: projectPath,
|
|
76
85
|
stdio: 'inherit',
|
|
86
|
+
...(strict ? { env: { ...process.env, ...resolvedEnv } } : {}),
|
|
77
87
|
},
|
|
78
88
|
);
|
|
79
89
|
const forwardSignal = (signal: NodeJS.Signals) => child.kill(signal);
|
|
@@ -10,6 +10,7 @@ import type { VonaBinConfigOptions } from './types.ts';
|
|
|
10
10
|
|
|
11
11
|
import { resolveTemplatePath } from '../../../utils.ts';
|
|
12
12
|
import { copyTemplateFile, getEnvMeta } from '../../utils.ts';
|
|
13
|
+
import { validateGenerationPaths } from './validateGenerationPaths.ts';
|
|
13
14
|
// import { generateZod } from './generateZod.ts';
|
|
14
15
|
|
|
15
16
|
export async function generateEntryFiles(
|
|
@@ -18,6 +19,7 @@ export async function generateEntryFiles(
|
|
|
18
19
|
modulesMeta: Awaited<ReturnType<typeof glob>>,
|
|
19
20
|
env: NodeJS.ProcessEnv,
|
|
20
21
|
) {
|
|
22
|
+
const strict = validateGenerationPaths(configMeta, configOptions);
|
|
21
23
|
// config
|
|
22
24
|
await __generateConfig();
|
|
23
25
|
// modules meta
|
|
@@ -103,7 +105,10 @@ export async function generateEntryFiles(
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
async function __generateEnvJson() {
|
|
106
|
-
|
|
108
|
+
// Strict generation retains the selected app.meta.env surface, never its resolved values.
|
|
109
|
+
const contentDest = strict
|
|
110
|
+
? `const keys = ${JSON.stringify(Object.keys(env).filter(key => env[key] !== undefined))};\nexport default Object.fromEntries(keys.filter(key => process.env[key] !== undefined).map(key => [key, process.env[key]])) as NodeJS.ProcessEnv;\n`
|
|
111
|
+
: `export default ${JSON.stringify(env, null, 2)} as unknown as NodeJS.ProcessEnv;\n`;
|
|
107
112
|
// output
|
|
108
113
|
const fileDest = path.join(configOptions.appDir, configOptions.runtimeDir, 'env.ts');
|
|
109
114
|
fse.ensureFileSync(fileDest);
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import type { VonaConfigMeta } from '@cabloy/module-info';
|
|
2
2
|
|
|
3
|
-
import { assertTestRunOwner, resolveVonaLocalPaths } from 'vona-core';
|
|
4
|
-
|
|
5
3
|
import type { VonaBinConfigOptions } from './types.ts';
|
|
6
4
|
|
|
7
5
|
import { createConfigUtils } from './configUtils.ts';
|
|
8
6
|
import { generateEntryFiles } from './generateEntryFiles.ts';
|
|
7
|
+
import { validateGenerationPaths } from './validateGenerationPaths.ts';
|
|
9
8
|
|
|
10
9
|
export async function generateVonaMeta(
|
|
11
10
|
configMeta: VonaConfigMeta,
|
|
12
11
|
configOptions: VonaBinConfigOptions,
|
|
13
12
|
) {
|
|
14
|
-
|
|
15
|
-
if (paths.runId) {
|
|
16
|
-
if (configOptions.runtimeDir !== paths.generatedDir) {
|
|
17
|
-
throw new Error('Isolated test generated directory does not match its run ID');
|
|
18
|
-
}
|
|
19
|
-
assertTestRunOwner(paths.dataRoot, paths.runId);
|
|
20
|
-
assertTestRunOwner(paths.generatedRoot, paths.runId);
|
|
21
|
-
}
|
|
13
|
+
validateGenerationPaths(configMeta, configOptions);
|
|
22
14
|
// config utils
|
|
23
15
|
const configUtils = createConfigUtils(configMeta, configOptions);
|
|
24
16
|
// env
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VonaConfigMeta } from '@cabloy/module-info';
|
|
2
|
+
|
|
3
|
+
import { assertTestRunOwner, requiresFreshTestResources, resolveVonaLocalPaths } from 'vona-core';
|
|
4
|
+
|
|
5
|
+
import type { VonaBinConfigOptions } from './types.ts';
|
|
6
|
+
|
|
7
|
+
export function validateGenerationPaths(
|
|
8
|
+
configMeta: VonaConfigMeta,
|
|
9
|
+
configOptions: VonaBinConfigOptions,
|
|
10
|
+
) {
|
|
11
|
+
const strict = requiresFreshTestResources();
|
|
12
|
+
if (strict && configMeta.mode !== 'test') {
|
|
13
|
+
throw new Error('Strict generation requires test mode');
|
|
14
|
+
}
|
|
15
|
+
const paths = resolveVonaLocalPaths(configOptions.appDir, configMeta.mode);
|
|
16
|
+
if (strict && !paths.runId) {
|
|
17
|
+
throw new Error('Strict generation requires an isolated test run');
|
|
18
|
+
}
|
|
19
|
+
if (paths.runId) {
|
|
20
|
+
if (configOptions.runtimeDir !== paths.generatedDir) {
|
|
21
|
+
throw new Error('Isolated test generated directory does not match its run ID');
|
|
22
|
+
}
|
|
23
|
+
assertTestRunOwner(paths.dataRoot, paths.runId);
|
|
24
|
+
assertTestRunOwner(paths.generatedRoot, paths.runId);
|
|
25
|
+
}
|
|
26
|
+
return strict;
|
|
27
|
+
}
|
|
@@ -26,7 +26,7 @@ const source = `
|
|
|
26
26
|
'@cabloy/cli': 'export class BeanCliBase {}',
|
|
27
27
|
'nodemon': 'export default globalThis.nodemonMock;',
|
|
28
28
|
'rimraf': 'export function rimraf() { throw new Error("Unexpected cleanup"); }',
|
|
29
|
-
'vona-core': 'export function resolveVonaLocalPaths() { throw new Error("Unexpected app access"); }',
|
|
29
|
+
'vona-core': 'export function resolveVonaLocalPaths() { throw new Error("Unexpected app access"); } export function requiresFreshTestResources() { return false; }',
|
|
30
30
|
'../utils.ts': 'export function getImportEsm() { return "--import=./.vona/register.js"; }',
|
|
31
31
|
'./toolsBin/generateVonaMeta.ts': 'export function generateVonaMeta() { throw new Error("Unexpected generation"); }',
|
|
32
32
|
};
|