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.
Files changed (87) hide show
  1. package/.cabloy-version +1 -1
  2. package/.github/workflows/agent-governance.yml +2 -2
  3. package/.github/workflows/create-cabloy.yml +2 -2
  4. package/.github/workflows/docs-pages.yml +2 -2
  5. package/.github/workflows/playwright-e2e.yml +4 -4
  6. package/.github/workflows/vona-cov-pg.yml +2 -2
  7. package/.github/workflows/vona-test-crud.yml +2 -2
  8. package/.github/workflows/vona-test-mysql.yml +2 -2
  9. package/.github/workflows/vona-test-pg.yml +2 -2
  10. package/.github/workflows/vona-test-sqlite3.yml +2 -2
  11. package/.github/workflows/vona-tsc.yml +2 -2
  12. package/.github/workflows/zova-ui.yml +2 -2
  13. package/CHANGELOG.md +22 -0
  14. package/package.json +4 -3
  15. package/repo-agent-governance/managed-assets.json +15 -15
  16. package/repo-agent-governance/policies/repository.md +1 -0
  17. package/repo-agent-governance/skills/cabloy-backend-scaffold/SKILL.md +5 -1
  18. package/repo-agent-governance/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +7 -5
  19. package/repo-agent-governance/skills/cabloy-frontend-scaffold/SKILL.md +5 -1
  20. package/repo-agent-governance/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +6 -4
  21. package/repo-docs/backend/unit-testing.md +5 -1
  22. package/repo-docs/frontend/openapi-sdk-guide.md +2 -0
  23. package/repo-docs/frontend/scripts.md +8 -0
  24. package/repo-docs/reference/repo-scripts.md +5 -1
  25. package/scripts/generateOpenapiIsolated.ts +18 -1
  26. package/scripts/runIsolatedTest.test.ts +9 -1
  27. package/scripts/runIsolatedTest.ts +81 -18
  28. package/scripts/strictGenerationDiagnostics.test.ts +1009 -0
  29. package/scripts/strictGenerationDiagnostics.ts +61 -0
  30. package/vona/package.original.json +3 -2
  31. package/vona/packages-cli/cabloy-cli/package.json +1 -1
  32. package/vona/packages-cli/cli/package.json +1 -1
  33. package/vona/packages-cli/cli-set-api/package.json +1 -1
  34. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +14 -4
  35. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateEntryFiles.ts +6 -1
  36. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateVonaMeta.ts +2 -10
  37. package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/validateGenerationPaths.ts +27 -0
  38. package/vona/packages-cli/cli-set-api/test/binDevLifecycle.test.ts +1 -1
  39. package/vona/packages-cli/cli-set-api/test/strictGenerationPrivacy.test.ts +439 -0
  40. package/vona/packages-utils/process-helper/package.json +1 -1
  41. package/vona/packages-utils/process-helper/src/index.test.ts +62 -0
  42. package/vona/packages-utils/process-helper/src/index.ts +9 -4
  43. package/vona/packages-vona/vona/package.json +1 -1
  44. package/vona/packages-vona/vona-core/package.json +1 -1
  45. package/vona/packages-vona/vona-core/src/lib/core/completedReadiness.test.ts +558 -0
  46. package/vona/packages-vona/vona-core/src/lib/core/completedReadiness.ts +389 -0
  47. package/vona/packages-vona/vona-core/src/lib/core/context.ts +3 -0
  48. package/vona/packages-vona/vona-core/src/lib/core/index.ts +11 -0
  49. package/vona/packages-vona/vona-core/src/lib/core/logger/appLogger.ts +10 -2
  50. package/vona/packages-vona/vona-core/src/lib/core/logger/diagnosticLogger.test.ts +268 -68
  51. package/vona/packages-vona/vona-core/src/lib/core/meta.ts +5 -0
  52. package/vona/packages-vona/vona-core/src/lib/core/testFreshness.ts +3 -9
  53. package/vona/packages-vona/vona-core/src/lib/core/testStrictMode.ts +9 -0
  54. package/vona/packages-vona/vona-core/src/lib/framework/start.test.ts +10 -0
  55. package/vona/packages-vona/vona-core/src/lib/framework/start.ts +8 -0
  56. package/vona/packages-vona/vona-mock/package.json +1 -1
  57. package/vona/pnpm-lock.yaml +542 -236
  58. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  59. package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
  60. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/bean/bean.executor.ts +124 -4
  61. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/types/executor.ts +7 -0
  62. package/vona/src/suite-vendor/a-vona/modules/a-executor/test/readyExisting.test.ts +423 -0
  63. package/vona/src/suite-vendor/a-vona/modules/a-executor/test/readyExistingCommit.test.ts +174 -0
  64. package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
  65. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/bean/bean.instance.ts +3 -1
  66. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/lib/existingReadyAdmission.ts +125 -0
  67. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/service/instance.ts +72 -25
  68. package/vona/src/suite-vendor/a-vona/modules/a-instance/test/existingReadyAdmission.test.ts +949 -0
  69. package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
  70. package/vona/src/suite-vendor/a-vona/modules/a-logger/test/middlewareSystem.httpLog.test.ts +61 -59
  71. package/vona/src/suite-vendor/a-vona/modules/a-mail/package.json +1 -1
  72. package/vona/src/suite-vendor/a-vona/modules/a-mail/src/service/mail.ts +5 -0
  73. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  74. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/index.ts +11 -0
  75. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/lib/protectedSqliteRegistry.ts +356 -0
  76. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  77. package/vona/src/suite-vendor/a-vona/modules/a-startup/test/devSeed.test.ts +61 -2
  78. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  79. package/zova/package.original.json +3 -3
  80. package/zova/packages-cli/cli/package.json +4 -4
  81. package/zova/packages-cli/cli-set-front/package.json +2 -2
  82. package/zova/packages-cli/cli-set-front/src/lib/common/restDependencyVersions.ts +22 -1
  83. package/zova/packages-cli/cli-set-front/test/restDependencies.test.ts +137 -0
  84. package/zova/packages-zova/zova/package.json +2 -2
  85. package/zova/pnpm-lock.yaml +448 -641
  86. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  87. 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@11.5.2",
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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabloy/cli",
3
- "version": "3.1.29",
3
+ "version": "3.1.30",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "@cabloy/cli",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-cli",
3
- "version": "1.1.166",
3
+ "version": "1.1.168",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona cli",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-cli-set-api",
3
- "version": "1.1.164",
3
+ "version": "1.1.166",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona cli-set-api",
6
6
  "keywords": [
@@ -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
- const contentDest = `export default ${JSON.stringify(env, null, 2)} as unknown as NodeJS.ProcessEnv;\n`;
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
- const paths = resolveVonaLocalPaths(configOptions.appDir, configMeta.mode);
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
  };