cabloy 5.1.242 → 5.1.243

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 CHANGED
@@ -1 +1 @@
1
- 5.1.242
1
+ 5.1.243
@@ -94,7 +94,7 @@ jobs:
94
94
  run: npm run init
95
95
  - name: run isolated test infrastructure gate
96
96
  # Bound concurrent PowerShell/Add-Type cold starts on Windows runners.
97
- run: node --test ${{ runner.os == 'Windows' && '--test-concurrency=2' || '' }} scripts/testClaimProcesses.test.ts scripts/runIsolatedTest.test.ts scripts/testClaimCleanup.test.ts scripts/testProcessGuardianWindows.test.ts vona/packages-vona/vona-core/src/lib/core/testClaim.test.ts vona/packages-vona/vona-core/src/lib/core/testClaimFilesystem.test.ts vona/packages-vona/vona-core/src/lib/framework/bootstrap.test.ts vona/packages-vona/vona-core/src/lib/framework/useApp.test.ts vona/packages-cli/cli-set-api/test/binBuildEntries.test.ts vona/packages-cli/cli-set-api/test/binTestPatterns.test.ts
97
+ run: node --test ${{ runner.os == 'Windows' && '--test-concurrency=2' || '' }} scripts/testClaimProcesses.test.ts scripts/runIsolatedTest.test.ts scripts/testClaimCleanup.test.ts scripts/testProcessGuardianWindows.test.ts vona/packages-vona/vona-core/src/lib/core/testClaim.test.ts vona/packages-vona/vona-core/src/lib/core/testClaimFilesystem.test.ts vona/packages-vona/vona-core/src/lib/framework/bootstrap.test.ts vona/packages-vona/vona-core/src/lib/framework/useApp.test.ts vona/packages-cli/cli-set-api/test/binBuildEntries.test.ts vona/packages-cli/cli-set-api/test/binBuildFreshInputs.test.ts vona/packages-cli/cli-set-api/test/binTestPatterns.test.ts
98
98
  - name: run A-Pay focused gate
99
99
  run: npm run test -- test-pay/test/paymentSession.test.ts test-pay/test/payMock.test.ts test-pay/test/paypalProvider.test.ts test-pay/test/paypalLifecycle.test.ts test-pay/test/stripeProvider.test.ts test-pay/test/stripeLifecycle.test.ts test-pay/test/outbox.test.ts test-pay/test/webhook.test.ts
100
100
  working-directory: vona
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.1.243
4
+
5
+ ### Bug Fixes
6
+
7
+ - Fix warning logging.
8
+ - Fix logout in demonstration mode.
9
+ - Fix Rollup build caching.
10
+
11
+ ### Improvements
12
+
13
+ - Update the demonstration mode guide.
14
+
3
15
  ## 5.1.242
4
16
 
5
17
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cabloy",
3
- "version": "5.1.242",
3
+ "version": "5.1.243",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A Node.js fullstack framework",
6
6
  "keywords": [
@@ -80,10 +80,13 @@ The Guard depends on Passport-resolved account state, so it makes this decision
80
80
 
81
81
  ## Exempt authentication routes
82
82
 
83
- Demonstration Mode deliberately does not apply to the standard authentication and OAuth routes below. This keeps sign-in, sign-out, registration, account association and migration, OAuth callbacks, and token flows available while the write policy is active.
83
+ Demonstration Mode deliberately does not apply to the standard authentication and OAuth routes below. This keeps sign-in, registration, account association and migration, OAuth callbacks, and token flows available while the write policy is active.
84
+
85
+ In Cabloy Basic, and Cabloy Start, `POST /home/user/passport/logout` is **not exempt**. While Demonstration Mode is enabled, only authenticated, active, non-anonymous whitelisted users may log out; other users receive `403` with `demo-demonstration:1001`.
86
+
87
+ This prevents ordinary visitors sharing a demo account from revoking other visitors' logins. Whitelisted users remain able to log out. The underlying logout semantics are unchanged: logout revokes the shared login state for the current account and authentication record, not just the current browser session. When Demonstration Mode is disabled, this Guard does not restrict logout.
84
88
 
85
89
  ```text
86
- /home/user/passport/logout
87
90
  /home/user/passport/register
88
91
  /home/user/passport/login
89
92
  /home/user/passport/login/:module/:providerName/:clientName?
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-cli",
3
- "version": "1.1.173",
3
+ "version": "1.1.174",
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.171",
3
+ "version": "1.1.172",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona cli-set-api",
6
6
  "keywords": [
@@ -203,6 +203,13 @@ export class CliBinBuild extends BeanCliBase {
203
203
 
204
204
  const sourceMap = process.env.BUILD_SOURCEMAP === 'true';
205
205
 
206
+ // Explicit roots bypass the application's .vona exclusion and prevent stale emit-cache fallback.
207
+ const tsconfig = path.join(projectPath, '.vona/tsconfig.build.json');
208
+ await fse.writeJson(tsconfig, {
209
+ extends: '../tsconfig.json',
210
+ files: ['./bootstrap.ts', './app.ts', './env.ts', './config.ts', './modules-meta.ts'],
211
+ });
212
+
206
213
  const replaceValues = generateConfigDefine(env, ['NODE_ENV', 'META_MODE', 'META_FLAVOR']);
207
214
  for (const relativeName in modulesMeta.modules) {
208
215
  const module = modulesMeta.modules[relativeName];
@@ -265,11 +272,15 @@ export class CliBinBuild extends BeanCliBase {
265
272
  json(),
266
273
  commonjs(),
267
274
  typescript({
275
+ tsconfig,
268
276
  module: 'nodenext',
269
277
  compilerOptions: {
270
278
  noCheck: true,
279
+ noEmit: false,
271
280
  declaration: false,
281
+ declarationMap: false,
272
282
  composite: false,
283
+ incremental: false,
273
284
  sourceMap,
274
285
  },
275
286
  outputToFilesystem: false,
@@ -0,0 +1,152 @@
1
+ import assert from 'node:assert/strict';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import { test } from 'node:test';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const buildUrl = new URL('../src/lib/bean/cli.bin.build.ts', import.meta.url).href;
10
+
11
+ // Keep the actual bundler and transpilers; only isolate CLI initialization.
12
+ const source = `
13
+ import assert from 'node:assert/strict';
14
+ import { readFileSync, readdirSync, writeFileSync } from 'node:fs';
15
+ import { registerHooks } from 'node:module';
16
+ import { join } from 'node:path';
17
+ import { pathToFileURL } from 'node:url';
18
+ const buildUrl = ${JSON.stringify(buildUrl)};
19
+ const projectPath = process.argv[1];
20
+ registerHooks({
21
+ resolve(specifier, context, nextResolve) {
22
+ if (context.parentURL === buildUrl) {
23
+ const mock = specifier === '@cabloy/cli'
24
+ ? 'export class BeanCliBase {}'
25
+ : specifier === './toolsBin/generateVonaMeta.ts'
26
+ ? 'export function generateVonaMeta() { throw new Error("Unexpected generation"); }'
27
+ : undefined;
28
+ if (mock) return { url: 'data:text/javascript,' + encodeURIComponent(mock), shortCircuit: true };
29
+ }
30
+ return nextResolve(specifier, context);
31
+ },
32
+ });
33
+ const { CliBinBuild } = await import(buildUrl);
34
+ const cli = Object.create(CliBinBuild.prototype);
35
+ const cachePath = process.argv[2];
36
+ const poisoned = readFileSync(cachePath, 'utf8');
37
+ for (const [index, flavor] of ['normal', 'ci', 'normal'].entries()) {
38
+ const env = {
39
+ META_MODE: 'prod',
40
+ META_FLAVOR: flavor,
41
+ SERVER_LISTEN_DISABLE: flavor === 'ci' ? 'true' : '',
42
+ generation: index,
43
+ };
44
+ writeFileSync(join(projectPath, '.vona/env.ts'),
45
+ 'export default ' + JSON.stringify(env) + ' as const;');
46
+ writeFileSync(join(projectPath, '.vona/config.ts'),
47
+ 'export default { generation: ' + index + ' };');
48
+ const outDir = join(projectPath, 'dist/build-' + index);
49
+ await cli._rollup(projectPath, env, { modules: {} }, outDir);
50
+ const app = await import(pathToFileURL(join(outDir, 'app.js')).href);
51
+ assert.deepEqual(app.env, env, 'must compile current generated environment, not cached CI output');
52
+ assert.deepEqual(await app.config(), { generation: index });
53
+ assert.equal(app.view, 'fresh-view', 'must retain inherited JSX and legacy decorator compilation');
54
+ assert.equal(readFileSync(cachePath, 'utf8'), poisoned, 'legacy cache must remain in place');
55
+ if (process.env.BUILD_SOURCEMAP === 'true') {
56
+ const maps = readdirSync(outDir).filter(name => name.endsWith('.js.map'));
57
+ assert.ok(maps.length > 0);
58
+ assert.ok(maps.some(name =>
59
+ JSON.parse(readFileSync(join(outDir, name), 'utf8')).sources
60
+ .some(source => source.endsWith('/.vona/env.ts'))));
61
+ }
62
+ }
63
+ `;
64
+
65
+ for (const sourceMap of [false, true]) {
66
+ test(`production build uses fresh generated inputs despite CI cache (sourceMap=${sourceMap})`, () => {
67
+ const projectPath = realpathSync(mkdtempSync(join(tmpdir(), 'vona-bin-build-fresh-')));
68
+ try {
69
+ mkdirSync(join(projectPath, '.vona'));
70
+ mkdirSync(join(projectPath, 'src/backend'), { recursive: true });
71
+ symlinkSync(
72
+ fileURLToPath(new URL('../../../node_modules', import.meta.url)),
73
+ join(projectPath, 'node_modules'),
74
+ process.platform === 'win32' ? 'junction' : 'dir',
75
+ );
76
+ writeFileSync(join(projectPath, 'package.json'), JSON.stringify({ type: 'module' }));
77
+ writeFileSync(
78
+ join(projectPath, 'tsconfig.base.json'),
79
+ JSON.stringify({
80
+ compilerOptions: {
81
+ target: 'ES2020',
82
+ module: 'NodeNext',
83
+ moduleResolution: 'NodeNext',
84
+ incremental: true,
85
+ composite: true,
86
+ declaration: true,
87
+ declarationMap: false,
88
+ jsx: 'react',
89
+ jsxFactory: 'h',
90
+ experimentalDecorators: true,
91
+ emitDecoratorMetadata: true,
92
+ skipLibCheck: true,
93
+ },
94
+ }),
95
+ );
96
+ writeFileSync(
97
+ join(projectPath, 'tsconfig.json'),
98
+ JSON.stringify({
99
+ extends: './tsconfig.base.json',
100
+ compilerOptions: { noEmit: true, composite: false, declaration: false },
101
+ exclude: ['.vona', 'dist', 'node_modules'],
102
+ }),
103
+ );
104
+ writeFileSync(
105
+ join(projectPath, 'src/backend/view.tsx'),
106
+ `function h(tag: string) { return tag; }
107
+ function mark(target: any) { target.value = 'fresh-view'; }
108
+ @mark
109
+ class View { static value: string; }
110
+ export const view = <fixture /> === 'fixture' ? View.value : 'invalid';`,
111
+ );
112
+ writeFileSync(
113
+ join(projectPath, '.vona/app.ts'),
114
+ `export { default as env } from './env.ts';
115
+ export { view } from '../src/backend/view.tsx';
116
+ export async function config() { return (await import('./config.ts')).default; }`,
117
+ );
118
+ writeFileSync(join(projectPath, '.vona/bootstrap.ts'), "export { env } from './app.ts';");
119
+ writeFileSync(join(projectPath, '.vona/modules-meta.ts'), 'export default {};');
120
+ const cachePath = join(
121
+ projectPath,
122
+ '.rollup.cache',
123
+ join(projectPath, '.vona/env.js').replace(/^([a-z]+):/i, '$1'),
124
+ );
125
+ mkdirSync(dirname(cachePath), { recursive: true });
126
+ writeFileSync(
127
+ cachePath,
128
+ 'export default { META_MODE: "prod", META_FLAVOR: "ci", SERVER_LISTEN_DISABLE: "true", generation: "poisoned" };',
129
+ );
130
+ const result = spawnSync(
131
+ process.execPath,
132
+ ['--input-type=module', '--eval', source, projectPath, cachePath],
133
+ {
134
+ cwd: projectPath,
135
+ encoding: 'utf8',
136
+ timeout: 60_000,
137
+ env: {
138
+ ...process.env,
139
+ BUILD_MINIFY: 'false',
140
+ BUILD_SOURCEMAP: String(sourceMap),
141
+ },
142
+ },
143
+ );
144
+ assert.ifError(result.error);
145
+ assert.equal(result.signal, null, result.stderr);
146
+ assert.equal(result.status, 0, result.stderr);
147
+ assert.doesNotMatch(result.stderr, /\[plugin typescript\]/i, result.stderr);
148
+ } finally {
149
+ rmSync(projectPath, { recursive: true, force: true });
150
+ }
151
+ });
152
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona",
3
- "version": "5.1.121",
3
+ "version": "5.1.122",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "Vona is an intuitive, elegant and powerful Node.js framework for rapidly developing enterprise applications of any size",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-core",
3
- "version": "5.1.52",
3
+ "version": "5.1.53",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona",
6
6
  "keywords": [
@@ -90,8 +90,8 @@ export class VonaApplication extends KoaApplication {
90
90
  protocol,
91
91
  secure: false,
92
92
  method: 'POST',
93
- url: '',
94
- path: '',
93
+ url: '/',
94
+ path: '/',
95
95
  socket: {
96
96
  encrypted: false,
97
97
  remoteAddress: '127.0.0.1',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-mock",
3
- "version": "6.1.52",
3
+ "version": "6.1.53",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "vona mock",
6
6
  "keywords": [
@@ -30,7 +30,7 @@ export interface IGuardOptionsDemonstration extends IDecoratorGuardOptionsGlobal
30
30
  methodsForWrite,
31
31
  usernameWhitelist: parseUsernameWhitelist(app.meta.env.DEMONSTRATION_USERNAME_WHITELIST),
32
32
  ignore: [
33
- '/home/user/passport/logout',
33
+ // '/home/user/passport/logout',
34
34
  '/home/user/passport/register',
35
35
  '/home/user/passport/login',
36
36
  '/home/user/passport/login/:module/:providerName/:clientName?',
@@ -29,7 +29,7 @@ function isGuardEnabledForRoute(routePathRaw: string, enable = true): boolean {
29
29
  return app.bean.onion.checkOnionOptionsEnabled({ ...options, enable }, routePathRaw);
30
30
  }
31
31
 
32
- describe('guardDemonstration.test.ts', () => {
32
+ describe('guardDemonstration.test.ts', { concurrency: false }, () => {
33
33
  it('parses a trimmed, deduplicated username whitelist and exposes localized errors', async () => {
34
34
  assert.deepEqual(parseUsernameWhitelist(' admin, demo, ,admin '), ['admin', 'demo']);
35
35
  assert.deepEqual(parseUsernameWhitelist(undefined), []);
@@ -101,11 +101,10 @@ describe('guardDemonstration.test.ts', () => {
101
101
  });
102
102
  });
103
103
 
104
- it('excludes only the configured authentication and OAuth route paths', () => {
104
+ it('exempts the configured authentication and OAuth routes but protects logout', () => {
105
105
  for (const routePathRaw of [
106
106
  '/home/user/passport/login',
107
107
  '/home/user/passport/login/:module/:providerName/:clientName?',
108
- '/home/user/passport/logout',
109
108
  '/home/user/passport/register',
110
109
  '/home/user/passport/associate/:module/:providerName/:clientName?',
111
110
  '/home/user/passport/migrate/:module/:providerName/:clientName?',
@@ -116,6 +115,8 @@ describe('guardDemonstration.test.ts', () => {
116
115
  ]) {
117
116
  assert.equal(isGuardEnabledForRoute(routePathRaw), false);
118
117
  }
118
+ assert.equal(isGuardEnabledForRoute('/home/user/passport/logout'), true);
119
+ assert.equal(isGuardEnabledForRoute('/home/user/passport/logout', false), false);
119
120
  assert.equal(isGuardEnabledForRoute('/test/business/write'), true);
120
121
  });
121
122
  });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-core",
3
- "version": "5.1.68",
3
+ "version": "5.1.69",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-vona",
3
- "version": "5.1.112",
3
+ "version": "5.1.113",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",