cabloy 5.1.141 → 5.1.142

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 (92) hide show
  1. package/.cabloy-version +1 -1
  2. package/.github/workflows/playwright-e2e.yml +2 -2
  3. package/CHANGELOG.md +21 -0
  4. package/cabloy-docs/frontend/form-guide.md +47 -0
  5. package/cabloy-docs/frontend/markdown-guide.md +50 -17
  6. package/cabloy-docs/frontend/route-alias-guide.md +20 -0
  7. package/cabloy-docs/frontend/scripts.md +9 -11
  8. package/cabloy-docs/frontend/zova-form-under-the-hood.md +25 -0
  9. package/cabloy-docs/fullstack/parallel-worktree-environment.md +1 -1
  10. package/cabloy-docs/fullstack/quickstart.md +5 -4
  11. package/cabloy-docs/reference/repo-scripts.md +29 -42
  12. package/e2e/config/playwright.config.ts +34 -0
  13. package/e2e/scripts/e2e.ts +2 -27
  14. package/e2e/scripts/runE2e.ts +62 -0
  15. package/e2e/scripts/runE2eArgs.test.ts +75 -0
  16. package/e2e/scripts/runE2eArgs.ts +158 -0
  17. package/e2e/specs/{a-commerce/commerce.spec.ts → a-commerce.spec.ts} +361 -30
  18. package/e2e/specs/{cabloy-basic/account.spec.ts → account.spec.ts} +1 -2
  19. package/oxlint.config.ts +3 -0
  20. package/package.json +3 -9
  21. package/scripts/upgrade.ts +63 -68
  22. package/vona/packages-utils/lint/package.json +1 -1
  23. package/vona/packages-utils/lint/src/oxc/lint.ts +1 -1
  24. package/vona/packages-utils/lint/src/oxc/lintVue.ts +1 -1
  25. package/vona/pnpm-lock.yaml +41 -41
  26. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundRecoveryView.tsx +7 -2
  27. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +31 -15
  28. package/vona/src/suite/a-home/modules/home-user/package.json +1 -0
  29. package/vona/src/suite/a-home/modules/home-user/src/service/account.ts +15 -2
  30. package/vona/src/suite/a-home/modules/home-user/test/accountActivation.test.ts +34 -4
  31. package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/package.json +2 -1
  32. package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/src/.metadata/index.ts +26 -0
  33. package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/src/bean/imageScene.markdown.ts +13 -0
  34. package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
  35. package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
  36. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +23 -0
  37. package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/refundOperation.ts +7 -0
  38. package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
  39. package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +1 -1
  40. package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
  41. package/vona/src/suite-vendor/a-pay/package.json +5 -5
  42. package/zova/packages-utils/zova-jsx/package.json +2 -2
  43. package/zova/packages-zova/zova/package.json +3 -3
  44. package/zova/packages-zova/zova-core/package.json +1 -1
  45. package/zova/packages-zova/zova-core/src/bean/resource/locale/type.ts +1 -0
  46. package/zova/pnpm-lock.yaml +63 -18
  47. package/zova/src/front/config/config/config.cabloyBasicWeb.ts +3 -1
  48. package/zova/src/front/config/config/config.cabloyCommerce.ts +4 -2
  49. package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +64 -63
  50. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +6 -1
  51. package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionRefund/controller.tsx +413 -134
  52. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +76 -0
  53. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +67 -0
  54. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +1 -0
  55. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +1 -1
  56. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +7 -7
  57. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/order/controller.tsx +46 -9
  58. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +50 -30
  59. package/zova/src/suite/cabloy-basic/modules/basic-captcha/src/component/formFieldCaptcha/controller.tsx +6 -2
  60. package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +9 -15
  61. package/zova/src/suite/cabloy-basic/modules/basic-markdown/package.json +10 -2
  62. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/.metadata/index.ts +11 -2
  63. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/.metadata/locales.ts +7 -0
  64. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/component/formFieldMarkdown/controller.tsx +723 -5
  65. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/component/formFieldMarkdown/render.tsx +461 -2
  66. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/config/locale/en-us.ts +59 -0
  67. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/config/locale/zh-cn.ts +59 -0
  68. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/index.ts +1 -0
  69. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/lib/codeBlockLanguages.ts +42 -0
  70. package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/lib/richTextContentStyle.ts +20 -0
  71. package/zova/src/suite/cabloy-basic/modules/basic-markdown/test/lib/codeBlockLanguages.test.ts +25 -0
  72. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  73. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +1 -0
  74. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  75. package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
  76. package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +26 -12
  77. package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +1 -1
  78. package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
  79. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockMockPayment.ts +26 -0
  80. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockMockPayment.ts +8 -1
  81. package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +13 -1
  82. package/zova/src/suite-vendor/a-pay/package.json +3 -3
  83. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  84. package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx +2 -0
  85. package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts +7 -6
  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 +3 -3
  88. package/e2e/config/playwright.basic.config.ts +0 -3
  89. package/e2e/config/playwright.commerce.config.ts +0 -3
  90. package/e2e/config/playwright.shared.config.ts +0 -38
  91. package/e2e/scripts/testE2eClean.ts +0 -56
  92. /package/e2e/specs/{cabloy-basic/basic.spec.ts → cabloy-basic.spec.ts} +0 -0
@@ -59,14 +59,17 @@ const OVERWRITE_DIRS_CABLOY_BASIC: string[] = [
59
59
  'zova/src/suite/a-devui',
60
60
  ];
61
61
 
62
- const FRAMEWORK_E2E_DIRS_CABLOY_BASIC: string[] = [
63
- 'e2e/config',
64
- 'e2e/scripts',
65
- 'e2e/specs/cabloy-basic',
66
- 'e2e/specs/a-commerce',
62
+ const FRAMEWORK_E2E_DIRS_CABLOY_BASIC: string[] = ['e2e/config', 'e2e/scripts'];
63
+
64
+ const FRAMEWORK_E2E_FILES_CABLOY_BASIC: string[] = [
65
+ 'e2e/specs/cabloy-basic.spec.ts',
66
+ 'e2e/specs/account.spec.ts',
67
+ 'e2e/specs/a-commerce.spec.ts',
67
68
  ];
68
69
 
69
- const FRAMEWORK_E2E_SCRIPT_NAMES_CABLOY_BASIC: string[] = [
70
+ const FRAMEWORK_E2E_SCRIPT_NAMES_CABLOY_BASIC: string[] = ['test:e2e', 'test:e2e:fast'];
71
+
72
+ const FRAMEWORK_E2E_LEGACY_SCRIPT_NAMES_CABLOY_BASIC: string[] = [
70
73
  'test:e2e:basic',
71
74
  'test:e2e:basic:web',
72
75
  'test:e2e:basic:admin',
@@ -75,15 +78,11 @@ const FRAMEWORK_E2E_SCRIPT_NAMES_CABLOY_BASIC: string[] = [
75
78
  'test:e2e:commerce:web',
76
79
  'test:e2e:commerce:admin',
77
80
  'test:e2e:commerce:clean',
81
+ 'test:e2e:basic:flow',
78
82
  ];
79
83
 
80
84
  const FRAMEWORK_E2E_DEV_DEPENDENCY_CABLOY_BASIC = '@playwright/test';
81
85
 
82
- const OBSOLETE_FRAMEWORK_E2E_SCRIPTS_CABLOY_BASIC: Record<string, string> = {
83
- 'test:e2e:basic:flow':
84
- 'playwright test --config e2e/config/playwright.basic.config.ts --grep ATP-BASIC-FLOW-01',
85
- };
86
-
87
86
  const MERGE_DIRS: string[] = [
88
87
  // Claude project assets
89
88
  '.claude/commands',
@@ -231,24 +230,6 @@ async function extractTarball(tarballPath: string, targetDir: string): Promise<v
231
230
  }
232
231
  }
233
232
 
234
- function needsBasicE2eReconciliation(): boolean {
235
- if (!isCabloyBasic()) return false;
236
-
237
- for (const dir of FRAMEWORK_E2E_DIRS_CABLOY_BASIC) {
238
- if (!existsSync(resolve(ROOT_DIR, dir))) return true;
239
- }
240
-
241
- const packageJson = readPackageJson(resolve(ROOT_DIR, 'package.json'));
242
- for (const name of FRAMEWORK_E2E_SCRIPT_NAMES_CABLOY_BASIC) {
243
- const script = packageJson.scripts?.[name];
244
- if (!script?.includes('e2e/')) return true;
245
- }
246
- for (const [name, value] of Object.entries(OBSOLETE_FRAMEWORK_E2E_SCRIPTS_CABLOY_BASIC)) {
247
- if (packageJson.scripts?.[name] === value) return true;
248
- }
249
- return !packageJson.devDependencies?.[FRAMEWORK_E2E_DEV_DEPENDENCY_CABLOY_BASIC];
250
- }
251
-
252
233
  function mergeFrameworkE2eAssets(dryRun?: boolean): void {
253
234
  if (!isCabloyBasic()) return;
254
235
 
@@ -264,6 +245,38 @@ function mergeFrameworkE2eAssets(dryRun?: boolean): void {
264
245
  }
265
246
  copyDirectory(src, dest);
266
247
  }
248
+
249
+ for (const file of FRAMEWORK_E2E_FILES_CABLOY_BASIC) {
250
+ const src = resolve(TEMP_DIR, file);
251
+ const dest = resolve(ROOT_DIR, file);
252
+ if (!existsSync(src)) {
253
+ throw new Error(`Expected framework E2E file in package: ${file}`);
254
+ }
255
+ if (dryRun) {
256
+ log(` [dry-run] Overwrite framework E2E file: ${file}`);
257
+ continue;
258
+ }
259
+ mkdirSync(dirname(dest), { recursive: true });
260
+ cpSync(src, dest);
261
+ }
262
+
263
+ const legacyFrameworkFiles: string[] = [
264
+ 'e2e/config/playwright.basic.config.ts',
265
+ 'e2e/config/playwright.commerce.config.ts',
266
+ 'e2e/config/playwright.shared.config.ts',
267
+ 'e2e/specs/cabloy-basic/basic.spec.ts',
268
+ 'e2e/specs/cabloy-basic/account.spec.ts',
269
+ 'e2e/specs/a-commerce/commerce.spec.ts',
270
+ ];
271
+ for (const file of legacyFrameworkFiles) {
272
+ const dest = resolve(ROOT_DIR, file);
273
+ if (!existsSync(dest)) continue;
274
+ if (dryRun) {
275
+ log(` [dry-run] Remove legacy framework E2E file: ${file}`);
276
+ continue;
277
+ }
278
+ rmSync(dest, { force: true });
279
+ }
267
280
  }
268
281
 
269
282
  function reconcileFrameworkE2ePackageJson(dryRun?: boolean): void {
@@ -324,18 +337,11 @@ function reconcileFrameworkE2ePackageJson(dryRun?: boolean): void {
324
337
  }
325
338
  }
326
339
 
327
- for (const [name, value] of Object.entries(OBSOLETE_FRAMEWORK_E2E_SCRIPTS_CABLOY_BASIC)) {
328
- const currentValue = projectPackage.scripts?.[name];
329
- if (!currentValue) continue;
330
- if (currentValue !== value) {
331
- log(
332
- ` Retain customized obsolete framework E2E script package.json scripts.${name}; remove it manually if no longer needed.`,
333
- );
334
- continue;
335
- }
340
+ for (const name of FRAMEWORK_E2E_LEGACY_SCRIPT_NAMES_CABLOY_BASIC) {
341
+ if (!projectPackage.scripts?.[name]) continue;
336
342
  changed = true;
337
343
  if (dryRun) {
338
- log(` [dry-run] Remove obsolete framework E2E script package.json scripts.${name}`);
344
+ log(` [dry-run] Remove legacy framework E2E script package.json scripts.${name}`);
339
345
  } else {
340
346
  delete projectPackage.scripts?.[name];
341
347
  }
@@ -513,41 +519,30 @@ async function main(): Promise<void> {
513
519
 
514
520
  const latestPackageInfo = await fetchLatestPackageInfo();
515
521
  const currentVersion = readVersionMarker();
516
- const basicE2eIncomplete = needsBasicE2eReconciliation();
517
-
518
- if (currentVersion) {
519
- log(`Current project Cabloy version: ${currentVersion}`);
520
- } else {
521
- log(
522
- `Warning: Missing ${VERSION_MARKER_FILE}, continuing with upgrade for backward compatibility.`,
522
+ if (!currentVersion) {
523
+ throw new Error(
524
+ `Missing ${VERSION_MARKER_FILE}; this project is not a supported Cabloy upgrade target.`,
523
525
  );
524
526
  }
527
+
528
+ log(`Current project Cabloy version: ${currentVersion}`);
525
529
  log(`Latest Cabloy version: ${latestPackageInfo.version}`);
526
530
 
527
- if (currentVersion) {
528
- const comparison = compareVersions(currentVersion, latestPackageInfo.version);
529
- if (comparison === 0) {
530
- if (basicE2eIncomplete) {
531
- log(
532
- `Cabloy is already up to date (current: ${currentVersion}), but the Cabloy Basic E2E baseline is incomplete. Repairing it in this upgrade; no additional upgrade command is required.\n`,
533
- );
534
- } else if (!dryRun) {
535
- log(`Cabloy is already up to date (current: ${currentVersion}). Skipping upgrade.`);
536
- return;
537
- } else {
538
- log(
539
- `Cabloy is already up to date (current: ${currentVersion}). Continuing dry-run to show overwrite plan.\n`,
540
- );
541
- }
542
- } else if (comparison > 0) {
543
- throw new Error(
544
- `Project Cabloy version ${currentVersion} is newer than npm latest ${latestPackageInfo.version}. Aborting upgrade.`,
545
- );
546
- } else {
547
- log(`Upgrading Cabloy from ${currentVersion} to ${latestPackageInfo.version}...\n`);
531
+ const comparison = compareVersions(currentVersion, latestPackageInfo.version);
532
+ if (comparison === 0) {
533
+ if (!dryRun) {
534
+ log(`Cabloy is already up to date (current: ${currentVersion}). Skipping upgrade.`);
535
+ return;
548
536
  }
537
+ log(
538
+ `Cabloy is already up to date (current: ${currentVersion}). Continuing dry-run to show overwrite plan.\n`,
539
+ );
540
+ } else if (comparison > 0) {
541
+ throw new Error(
542
+ `Project Cabloy version ${currentVersion} is newer than npm latest ${latestPackageInfo.version}. Aborting upgrade.`,
543
+ );
549
544
  } else {
550
- log(`Upgrading Cabloy to ${latestPackageInfo.version}...\n`);
545
+ log(`Upgrading Cabloy from ${currentVersion} to ${latestPackageInfo.version}...\n`);
551
546
  }
552
547
 
553
548
  try {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabloy/lint",
3
- "version": "5.1.31",
3
+ "version": "5.1.32",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "Node Style Guide for Cabloy.",
6
6
  "files": [
@@ -452,7 +452,7 @@ const _configDefault: OxlintConfig = {
452
452
  propElementValues: 'always',
453
453
  },
454
454
  ],
455
- '@stylistic/jsx-curly-newline': 'error',
455
+ '@stylistic/jsx-curly-newline': 'off',
456
456
  '@stylistic/jsx-curly-spacing': ['error', 'never'],
457
457
  '@stylistic/jsx-equals-spacing': 'error',
458
458
  '@stylistic/jsx-first-prop-new-line': 'error',
@@ -450,7 +450,7 @@ const _configDefault: OxlintConfig = {
450
450
  propElementValues: 'always',
451
451
  },
452
452
  ],
453
- '@stylistic/jsx-curly-newline': 'error',
453
+ '@stylistic/jsx-curly-newline': 'off',
454
454
  '@stylistic/jsx-curly-spacing': ['error', 'never'],
455
455
  '@stylistic/jsx-equals-spacing': 'error',
456
456
  '@stylistic/jsx-first-prop-new-line': 'error',
@@ -564,8 +564,8 @@ importers:
564
564
  specifier: npm:@cabloy/zod@4.3.8
565
565
  version: '@cabloy/zod@4.3.8'
566
566
  zova:
567
- specifier: ^5.1.150
568
- version: 5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
567
+ specifier: ^5.1.151
568
+ version: 5.1.151(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
569
569
  zova-jsx:
570
570
  specifier: ^1.1.86
571
571
  version: 1.1.86(typescript@5.9.3)
@@ -597,8 +597,8 @@ importers:
597
597
  specifier: ^5.1.50
598
598
  version: 5.1.50
599
599
  zova-module-a-pay:
600
- specifier: ^5.0.5
601
- version: 5.0.5
600
+ specifier: ^5.0.6
601
+ version: 5.0.6
602
602
  zova-module-a-router:
603
603
  specifier: ^5.1.34
604
604
  version: 5.1.34
@@ -615,8 +615,8 @@ importers:
615
615
  specifier: ^5.1.38
616
616
  version: 5.1.38(vue@3.5.39(typescript@5.9.3))
617
617
  zova-module-pay-mock:
618
- specifier: ^5.0.3
619
- version: 5.0.3
618
+ specifier: ^5.0.4
619
+ version: 5.0.4
620
620
  zova-module-rest-resource:
621
621
  specifier: ^5.1.45
622
622
  version: 5.1.45
@@ -642,8 +642,8 @@ importers:
642
642
  specifier: npm:@cabloy/zod@4.3.8
643
643
  version: '@cabloy/zod@4.3.8'
644
644
  zova:
645
- specifier: ^5.1.150
646
- version: 5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
645
+ specifier: ^5.1.151
646
+ version: 5.1.151(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
647
647
  zova-jsx:
648
648
  specifier: ^1.1.86
649
649
  version: 1.1.86(typescript@5.9.3)
@@ -675,8 +675,8 @@ importers:
675
675
  specifier: ^5.1.50
676
676
  version: 5.1.50
677
677
  zova-module-a-pay:
678
- specifier: ^5.0.5
679
- version: 5.0.5
678
+ specifier: ^5.0.6
679
+ version: 5.0.6
680
680
  zova-module-a-router:
681
681
  specifier: ^5.1.34
682
682
  version: 5.1.34
@@ -693,8 +693,8 @@ importers:
693
693
  specifier: ^5.1.38
694
694
  version: 5.1.38(vue@3.5.39(typescript@5.9.3))
695
695
  zova-module-pay-mock:
696
- specifier: ^5.0.3
697
- version: 5.0.3
696
+ specifier: ^5.0.4
697
+ version: 5.0.4
698
698
  zova-module-rest-resource:
699
699
  specifier: ^5.1.45
700
700
  version: 5.1.45
@@ -720,8 +720,8 @@ importers:
720
720
  specifier: npm:@cabloy/zod@4.3.8
721
721
  version: '@cabloy/zod@4.3.8'
722
722
  zova:
723
- specifier: ^5.1.150
724
- version: 5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
723
+ specifier: ^5.1.151
724
+ version: 5.1.151(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
725
725
  zova-jsx:
726
726
  specifier: ^1.1.86
727
727
  version: 1.1.86(typescript@5.9.3)
@@ -753,8 +753,8 @@ importers:
753
753
  specifier: ^5.1.50
754
754
  version: 5.1.50
755
755
  zova-module-a-pay:
756
- specifier: ^5.0.5
757
- version: 5.0.5
756
+ specifier: ^5.0.6
757
+ version: 5.0.6
758
758
  zova-module-a-router:
759
759
  specifier: ^5.1.34
760
760
  version: 5.1.34
@@ -771,8 +771,8 @@ importers:
771
771
  specifier: ^5.1.38
772
772
  version: 5.1.38(vue@3.5.39(typescript@5.9.3))
773
773
  zova-module-pay-mock:
774
- specifier: ^5.0.3
775
- version: 5.0.3
774
+ specifier: ^5.0.4
775
+ version: 5.0.4
776
776
  zova-module-rest-resource:
777
777
  specifier: ^5.1.45
778
778
  version: 5.1.45
@@ -798,8 +798,8 @@ importers:
798
798
  specifier: npm:@cabloy/zod@4.3.8
799
799
  version: '@cabloy/zod@4.3.8'
800
800
  zova:
801
- specifier: ^5.1.150
802
- version: 5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
801
+ specifier: ^5.1.151
802
+ version: 5.1.151(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
803
803
  zova-jsx:
804
804
  specifier: ^1.1.86
805
805
  version: 1.1.86(typescript@5.9.3)
@@ -831,8 +831,8 @@ importers:
831
831
  specifier: ^5.1.50
832
832
  version: 5.1.50
833
833
  zova-module-a-pay:
834
- specifier: ^5.0.5
835
- version: 5.0.5
834
+ specifier: ^5.0.6
835
+ version: 5.0.6
836
836
  zova-module-a-router:
837
837
  specifier: ^5.1.34
838
838
  version: 5.1.34
@@ -849,8 +849,8 @@ importers:
849
849
  specifier: ^5.1.38
850
850
  version: 5.1.38(vue@3.5.39(typescript@5.9.3))
851
851
  zova-module-pay-mock:
852
- specifier: ^5.0.3
853
- version: 5.0.3
852
+ specifier: ^5.0.4
853
+ version: 5.0.4
854
854
  zova-module-rest-resource:
855
855
  specifier: ^5.1.45
856
856
  version: 5.1.45
@@ -8994,8 +8994,8 @@ packages:
8994
8994
  zova-module-a-openapi@5.1.50:
8995
8995
  resolution: {integrity: sha512-ZrYFZaVARpBf5ByfCtCPD4z/2ByAZn42XsKUJZuqWcvVrccY7v3kaiXoCrfQAz9aDar+wqwXOo548eAHz4wzqg==}
8996
8996
 
8997
- zova-module-a-pay@5.0.5:
8998
- resolution: {integrity: sha512-+6TgviG9wuX37uhB//ezvF/zeUihq8RdysXEpkIY+wTQnA0ZwEnORrXDPaiboIz970zWQBJme8bfwv+1ntw/Vw==}
8997
+ zova-module-a-pay@5.0.6:
8998
+ resolution: {integrity: sha512-k1MXVsaN3zCgFDLQkUaUoN9W8Z02TWTsFr/h1A8ljUBAQccFiQusmt1035qvLYHidrHX64fC4R5F8SuIDLNf3w==}
8999
8999
 
9000
9000
  zova-module-a-router@5.1.34:
9001
9001
  resolution: {integrity: sha512-6XAia5GVmdJqUcwGW9r2vJ2JomnU0QMHK7y7QQoniUZ0JqDj7SWFbSYXd6WDlvLU7Kd5yt4WfyzE7GQVb/HcnA==}
@@ -9012,8 +9012,8 @@ packages:
9012
9012
  zova-module-a-ssrhmr@5.1.23:
9013
9013
  resolution: {integrity: sha512-BiwI/lodmJgWU5whwI4iEd3ZTbWCFIxG/V0YOejHaPqk85viFAVn9xlURNdpo3A9yFKRZDZja4IA8WuO6i0QAA==}
9014
9014
 
9015
- zova-module-a-ssrserver@5.1.25:
9016
- resolution: {integrity: sha512-Xq0vMR6TqErul8ik3X5ywXR4M62TKBehebEj6a6pPY75nJwNycEly2VWQZ6gF0dnnY+MBIKLhV9kstM0dxutKw==}
9015
+ zova-module-a-ssrserver@5.1.26:
9016
+ resolution: {integrity: sha512-1NK1hG1ruwGTvSgCGQ2fWCulTHi7PSOm8ZWVkrEQAhPnMs992IOTapKCXMl6mlGchnylfUfWRbpZ6OmzSGDICw==}
9017
9017
 
9018
9018
  zova-module-a-style@5.1.35:
9019
9019
  resolution: {integrity: sha512-i73I3wFvdQonj3l4fkovkKBZwSK4s6D4vL3AVfVvFJ4eIboKH2yw0hCILKRzLoESNQ0T+lNS6ozeimvtA4/6DQ==}
@@ -9027,17 +9027,17 @@ packages:
9027
9027
  zova-module-a-zova@5.1.101:
9028
9028
  resolution: {integrity: sha512-htiX0YX6kytmTiiiVuTH5lVcM5doff/AYIbiIxcoOU955q6vxrKNT4TQSGZiaAGY9cb45kr4n75nLunGxxaOPQ==}
9029
9029
 
9030
- zova-module-pay-mock@5.0.3:
9031
- resolution: {integrity: sha512-v4Zg+3kKOTnBufsRnUPV+1FHCwD8zQMiaP1et4jFeaSENzKYcuCwBqeHDTtRuBXC0+2J+fDi36YOQzMsM5fE3A==}
9030
+ zova-module-pay-mock@5.0.4:
9031
+ resolution: {integrity: sha512-olXNzUK7wuNThHiE8ND/8wu9eFhMODI7l/Tcdh7/fFe5EWRhPL37HCj8gjYy1gHcuFQdN3+gim3Zqmp7JG5nFw==}
9032
9032
 
9033
9033
  zova-module-rest-resource@5.1.45:
9034
9034
  resolution: {integrity: sha512-QqzqBaeObbnnVdfhQZLFaU6/gSaL9BJzmzgKR6d/GkucDWezDlfISyoPstp+NhkBs1VPR4yk5nhKVG9jRlx/6w==}
9035
9035
 
9036
- zova-suite-a-zova@5.1.149:
9037
- resolution: {integrity: sha512-Atwl93ucs8Ma3MBi/NK8sYcsTQimkKXLsHEoJ8LCXEdca/MQ9I43HoCLUOPjUhTIl9DRICQ+7ZzvhiGaXaFvzQ==}
9036
+ zova-suite-a-zova@5.1.150:
9037
+ resolution: {integrity: sha512-UZ/yRFWylL/MFKDvxlFYBZ6vb+WEW6NsOZSXztSfmOc8jevuZCy0I1lwgIZppR7wNWiBMdIt/jq7CqTHYhvMjw==}
9038
9038
 
9039
- zova@5.1.150:
9040
- resolution: {integrity: sha512-nRv1MICJQAU5nfyi5v6gBVQjHzoOEL8F8rgWu7kwLD9ChAcOnKyTk2DQLgRjTHu+khCqDMdoBFk5TDb4joSgcA==}
9039
+ zova@5.1.151:
9040
+ resolution: {integrity: sha512-ORpFNcMYRmoWtIGIGGswPpeLgrYiax9prStB3Em0umUFGxVLPg9Yt0R1/psFlFgcC9WionitSz4WBhjvcra8Xw==}
9041
9041
 
9042
9042
  zwitch@1.0.5:
9043
9043
  resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==}
@@ -15401,7 +15401,7 @@ snapshots:
15401
15401
  openapi3-ts: 4.6.0
15402
15402
  typestyle: 2.4.0
15403
15403
 
15404
- zova-module-a-pay@5.0.5: {}
15404
+ zova-module-a-pay@5.0.6: {}
15405
15405
 
15406
15406
  zova-module-a-router@5.1.34: {}
15407
15407
 
@@ -15419,7 +15419,7 @@ snapshots:
15419
15419
  '@cabloy/socket': link:packages-utils/socket
15420
15420
  debounce: 3.0.0
15421
15421
 
15422
- zova-module-a-ssrserver@5.1.25:
15422
+ zova-module-a-ssrserver@5.1.26:
15423
15423
  dependencies:
15424
15424
  ms: 2.1.3
15425
15425
 
@@ -15458,11 +15458,11 @@ snapshots:
15458
15458
  - typescript
15459
15459
  - vue
15460
15460
 
15461
- zova-module-pay-mock@5.0.3: {}
15461
+ zova-module-pay-mock@5.0.4: {}
15462
15462
 
15463
15463
  zova-module-rest-resource@5.1.45: {}
15464
15464
 
15465
- zova-suite-a-zova@5.1.149(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3)):
15465
+ zova-suite-a-zova@5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3)):
15466
15466
  dependencies:
15467
15467
  zova-module-a-api: 5.1.22
15468
15468
  zova-module-a-app: 5.1.26
@@ -15484,7 +15484,7 @@ snapshots:
15484
15484
  zova-module-a-routertabs: 5.1.34
15485
15485
  zova-module-a-ssr: 5.1.37
15486
15486
  zova-module-a-ssrhmr: 5.1.23
15487
- zova-module-a-ssrserver: 5.1.25
15487
+ zova-module-a-ssrserver: 5.1.26
15488
15488
  zova-module-a-style: 5.1.35
15489
15489
  zova-module-a-table: 5.1.38(vue@3.5.39(typescript@5.9.3))
15490
15490
  zova-module-a-zod: 5.1.37
@@ -15496,10 +15496,10 @@ snapshots:
15496
15496
  - typescript
15497
15497
  - vue
15498
15498
 
15499
- zova@5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3)):
15499
+ zova@5.1.151(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3)):
15500
15500
  dependencies:
15501
15501
  zova-core: 5.1.86(patch_hash=144450bd7a567a6067e5857c0cf4c780981b7e90bc48745c09e1696a9b6f1b97)(typescript@5.9.3)
15502
- zova-suite-a-zova: 5.1.149(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
15502
+ zova-suite-a-zova: 5.1.150(typescript@5.9.3)(vue@3.5.39(typescript@5.9.3))
15503
15503
  transitivePeerDependencies:
15504
15504
  - '@vue/composition-api'
15505
15505
  - debug
@@ -62,8 +62,13 @@ export class DtoRefundRecoveryView {
62
62
  @Api.field(v.optional())
63
63
  finalizedAt?: Date;
64
64
 
65
- @Api.field(z.enum(['none', 'reconcile_only', 'query_only', 'retry_same_key']))
66
- recoveryDisposition: 'none' | 'reconcile_only' | 'query_only' | 'retry_same_key';
65
+ @Api.field(z.enum(['none', 'await_webhook', 'reconcile_only', 'query_only', 'retry_same_key']))
66
+ recoveryDisposition:
67
+ | 'none'
68
+ | 'await_webhook'
69
+ | 'reconcile_only'
70
+ | 'query_only'
71
+ | 'retry_same_key';
67
72
 
68
73
  @Api.field(v.required())
69
74
  recoveryMessage: string;
@@ -880,6 +880,11 @@ export class ServiceOrder extends BeanBase {
880
880
  };
881
881
  }
882
882
 
883
+ private _providerSupportsRefundQuery(providerName: string, clientName: string) {
884
+ const { provider } = this.bean.payProvider.resolveByName(providerName, clientName);
885
+ return typeof provider.queryRefund === 'function';
886
+ }
887
+
883
888
  private _refundRecoveryView(
884
889
  linked: Awaited<ReturnType<typeof this.refundRecoveryLinkage>>,
885
890
  ): DtoRefundRecoveryView {
@@ -893,7 +898,14 @@ export class ServiceOrder extends BeanBase {
893
898
  hasUnresolvedReconciliation,
894
899
  } = linked;
895
900
  const canQuery = Boolean(
896
- refundOperation.providerRefundId && providerOperation.state !== 'succeeded',
901
+ refundOperation.providerRefundId &&
902
+ providerOperation.state !== 'succeeded' &&
903
+ this._providerSupportsRefundQuery(paymentSession.providerName, paymentSession.clientName),
904
+ );
905
+ const canAwaitWebhook = Boolean(
906
+ refundOperation.providerRefundId &&
907
+ providerOperation.state !== 'succeeded' &&
908
+ !this._providerSupportsRefundQuery(paymentSession.providerName, paymentSession.clientName),
897
909
  );
898
910
  const canRetry =
899
911
  !refundOperation.providerRefundId &&
@@ -909,21 +921,25 @@ export class ServiceOrder extends BeanBase {
909
921
  providerOperation.errorCode === 'refund_submission_outcome_unknown' &&
910
922
  Boolean(providerOperation.submittedAt) &&
911
923
  !hasUnresolvedReconciliation;
912
- const recoveryDisposition = canQuery
913
- ? 'query_only'
914
- : canRetry
915
- ? 'retry_same_key'
916
- : canReconcile
917
- ? 'reconcile_only'
918
- : 'none';
924
+ const recoveryDisposition = canAwaitWebhook
925
+ ? 'await_webhook'
926
+ : canQuery
927
+ ? 'query_only'
928
+ : canRetry
929
+ ? 'retry_same_key'
930
+ : canReconcile
931
+ ? 'reconcile_only'
932
+ : 'none';
919
933
  const recoveryMessage =
920
- recoveryDisposition === 'query_only'
921
- ? 'A verified provider refund identifier is available. Reconcile without resubmitting.'
922
- : recoveryDisposition === 'reconcile_only'
923
- ? 'Provider refund outcome is unknown. Record reconciliation before considering a retry.'
924
- : recoveryDisposition === 'retry_same_key'
925
- ? 'Reconciliation was unresolved. A single acknowledged retry may reuse the original provider request.'
926
- : 'No provider refund submission is available. Do not create or manually declare a replacement refund.';
934
+ recoveryDisposition === 'await_webhook'
935
+ ? 'A provider refund identifier is available. Wait for the verified provider webhook; do not resubmit or reconcile by querying.'
936
+ : recoveryDisposition === 'query_only'
937
+ ? 'A verified provider refund identifier is available. Reconcile without resubmitting.'
938
+ : recoveryDisposition === 'reconcile_only'
939
+ ? 'Provider refund outcome is unknown. Record reconciliation before considering a retry.'
940
+ : recoveryDisposition === 'retry_same_key'
941
+ ? 'Reconciliation was unresolved. A single acknowledged retry may reuse the original provider request.'
942
+ : 'No provider refund submission is available. Do not create or manually declare a replacement refund.';
927
943
  return {
928
944
  orderId: order.id,
929
945
  refundRequestId: refundRequest.id,
@@ -53,6 +53,7 @@
53
53
  "a-mail": "5.0.0",
54
54
  "a-ratelimit": "5.0.0",
55
55
  "a-redlock": "5.0.0",
56
+ "a-ssr": "5.0.0",
56
57
  "a-vona": "5.0.0",
57
58
  "auth-simple": "5.0.0"
58
59
  }
@@ -217,7 +217,11 @@ export class ServiceAccount extends BeanBase {
217
217
  const link = this._getActivationLinkWithToken(consumerLink, rawToken);
218
218
  await this.bean.mail.send({
219
219
  to: currentUser.email,
220
- subject: this.scope.locale.ActivationEmailSubject(),
220
+ subject: replaceTemplate(this.scope.locale.ActivationEmailSubject(), {
221
+ userName: currentUser.name,
222
+ link,
223
+ siteName: this.ctx.instance.title || this.app.meta.env.APP_TITLE,
224
+ }),
221
225
  text: replaceTemplate(this.scope.locale.ActivationEmailBody(), {
222
226
  userName: currentUser.name,
223
227
  link,
@@ -559,12 +563,21 @@ export class ServiceAccount extends BeanBase {
559
563
 
560
564
  private _getActivationLink(consumerUrl: string): URL {
561
565
  const url = this._getConsumerLink(consumerUrl, 'activation');
562
- if (url.pathname !== activationConsumerPath) {
566
+ if (!this._isActivationConsumerPath(url.pathname)) {
563
567
  this.app.throw(503, 'account activation consumer URL is invalid');
564
568
  }
565
569
  return url;
566
570
  }
567
571
 
572
+ private _isActivationConsumerPath(pathname: string) {
573
+ if (pathname === activationConsumerPath) return true;
574
+ const sites = this.app.scope('a-ssr').service.ssr.getSitesEnabled();
575
+ return sites.some(site => {
576
+ const publicPath = String(site.beanOptions.options?.publicPath ?? '');
577
+ return publicPath && pathname === `/${publicPath}${activationConsumerPath}`;
578
+ });
579
+ }
580
+
568
581
  private _getPasswordSetLink(consumerUrl: string): URL {
569
582
  return this._getConsumerLink(consumerUrl, 'password-set');
570
583
  }
@@ -5,6 +5,7 @@ import { acquireTestLock, app } from 'vona-mock';
5
5
 
6
6
  const activationConsumePath = '/home/user/account/activation/consume';
7
7
  const activationConsumerUrl = 'https://account.example.test/home/user/activation';
8
+ const activationConsumerUrlAdmin = 'https://account.example.test/admin/home/user/activation';
8
9
 
9
10
  describe('accountActivation.test.ts', { concurrency: false, sequential: true }, () => {
10
11
  const releases: Array<() => void> = [];
@@ -73,6 +74,26 @@ describe('accountActivation.test.ts', { concurrency: false, sequential: true },
73
74
  }
74
75
  });
75
76
 
77
+ it('preserves an enabled SSR site public path in activation links', async () => {
78
+ let fixture: IFixture | undefined;
79
+ let restoreSites: (() => void) | undefined;
80
+ try {
81
+ fixture = await createFixture();
82
+ restoreSites = configureAdminSsrSite();
83
+ const issued = await issueActivationLink(fixture, activationConsumerUrlAdmin);
84
+ assert.equal(issued.path, '/admin/home/user/activation');
85
+ assert.deepEqual(await getActivationState(getDigest(issued.token)), {
86
+ purpose: 'account-activation',
87
+ userId: fixture.userId,
88
+ consumerPath: '/home/user/activation',
89
+ email: fixture.email,
90
+ });
91
+ } finally {
92
+ restoreSites?.();
93
+ if (fixture) await removeFixture(fixture);
94
+ }
95
+ });
96
+
76
97
  it('issues an activation link through registration and activates the registered user', async () => {
77
98
  let registration: IRegistration | undefined;
78
99
  try {
@@ -175,6 +196,17 @@ interface IRegistration extends IFixture {
175
196
  path: string;
176
197
  }
177
198
 
199
+ function configureAdminSsrSite() {
200
+ const service = app.scope('a-ssr').service.ssr;
201
+ const getSitesEnabled = service.getSitesEnabled;
202
+ service.getSitesEnabled = (() => [
203
+ { beanOptions: { options: { publicPath: 'admin' } } },
204
+ ]) as typeof service.getSitesEnabled;
205
+ return () => {
206
+ service.getSitesEnabled = getSitesEnabled;
207
+ };
208
+ }
209
+
178
210
  async function configureActivation() {
179
211
  return await app.bean.executor.mockCtx(async () => {
180
212
  const options =
@@ -288,7 +320,7 @@ async function removeFixture(fixture: IFixture) {
288
320
  });
289
321
  }
290
322
 
291
- async function issueActivationLink(fixture: IFixture) {
323
+ async function issueActivationLink(fixture: IFixture, consumerUrl = activationConsumerUrl) {
292
324
  let text: unknown;
293
325
  const mail = app.bean.mail;
294
326
  const send = mail.send;
@@ -297,9 +329,7 @@ async function issueActivationLink(fixture: IFixture) {
297
329
  };
298
330
  try {
299
331
  await app.bean.executor.mockCtx(async () => {
300
- await app
301
- .scope('home-user')
302
- .service.account.issueActivationLink(fixture.userId, activationConsumerUrl);
332
+ await app.scope('home-user').service.account.issueActivationLink(fixture.userId, consumerUrl);
303
333
  });
304
334
  } finally {
305
335
  mail.send = send;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-markdown",
3
- "version": "5.0.1",
3
+ "version": "5.0.2",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "Vona Module"
@@ -58,6 +58,7 @@
58
58
  "title": "a-markdown",
59
59
  "vonaModule": {
60
60
  "dependencies": {
61
+ "a-image": "5.0.0",
61
62
  "a-vona": "5.0.0"
62
63
  }
63
64
  }