cabloy 5.1.116 → 5.1.118

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 (268) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-contract-loop/SKILL.md +8 -2
  3. package/.claude/skills/cabloy-contract-loop/evals/evals.json +6 -0
  4. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +13 -0
  5. package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +16 -3
  6. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +12 -0
  7. package/.github/workflows/vona-test-pg.yml +3 -0
  8. package/.github/workflows/vona-test-sqlite3.yml +3 -0
  9. package/CHANGELOG.md +34 -0
  10. package/CLAUDE.md +2 -0
  11. package/cabloy-docs/.vitepress/config.mjs +6 -0
  12. package/cabloy-docs/ai/docs-skills-rules-mapping.md +7 -0
  13. package/cabloy-docs/backend/aop-overview.md +16 -24
  14. package/cabloy-docs/backend/backend-source-reading-roadmap.md +26 -2
  15. package/cabloy-docs/backend/controller-aop-guide.md +38 -14
  16. package/cabloy-docs/backend/logger-guide.md +1 -0
  17. package/cabloy-docs/backend/menu-guide.md +1 -1
  18. package/cabloy-docs/backend/metrics-guide.md +75 -0
  19. package/cabloy-docs/backend/rate-limit-guide.md +97 -0
  20. package/cabloy-docs/backend/telemetry-guide.md +93 -0
  21. package/cabloy-docs/backend/vona-source-reading-map.md +44 -1
  22. package/cabloy-docs/frontend/model-resource-owner-pattern.md +2 -0
  23. package/cabloy-docs/frontend/ssr-overview.md +2 -0
  24. package/cabloy-docs/fullstack/admin-resource-and-web-self-service.md +329 -0
  25. package/cabloy-docs/fullstack/contract-loop-playbook.md +1 -1
  26. package/cabloy-docs/fullstack/introduction.md +1 -0
  27. package/e2e/specs/a-commerce/commerce.spec.ts +590 -1
  28. package/observability/README.md +18 -0
  29. package/observability/collector/otel-collector.yaml +34 -0
  30. package/observability/docker-compose.metrics.yml +25 -0
  31. package/observability/grafana/provisioning/datasources/prometheus.yaml +8 -0
  32. package/observability/prometheus/prometheus.yaml +7 -0
  33. package/package.json +1 -1
  34. package/vona/env/.env +6 -0
  35. package/vona/packages-cli/cli/package.json +1 -1
  36. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoBaseName%>.tsx_ +1 -1
  37. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoMutateName%>.tsx_ +2 -2
  38. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoResItemName%>.tsx_ +10 -10
  39. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoViewName%>.tsx_ +2 -2
  40. package/vona/packages-cli/cli-set-api/package.json +1 -1
  41. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts +13 -4
  42. package/vona/packages-vona/vona/package.json +1 -1
  43. package/vona/packages-vona/vona-core/package.json +1 -1
  44. package/vona/packages-vona/vona-core/src/lib/core/logger/utils.ts +12 -3
  45. package/vona/packages-vona/vona-core/src/lib/framework/processWorker.ts +1 -1
  46. package/vona/packages-vona/vona-mock/package.json +1 -1
  47. package/vona/packages-vona/vona-mock/src/index.ts +2 -0
  48. package/vona/packages-vona/vona-mock/src/lib/testLock.ts +21 -0
  49. package/vona/pnpm-lock.yaml +345 -53
  50. package/vona/src/backend/config/config/config.ts +1 -0
  51. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/catalog.test.ts +13 -3
  52. package/vona/src/suite/a-commerce/modules/commerce-catalog/test/product.test.ts +124 -70
  53. package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +81 -25
  54. package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/ssrMenu.address.ts +30 -0
  55. package/vona/src/suite/a-commerce/modules/commerce-member/src/controller/address.ts +42 -20
  56. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineCreate.tsx +35 -0
  57. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineItem.tsx +39 -0
  58. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineReq.tsx +11 -0
  59. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineRes.tsx +11 -0
  60. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineUpdate.tsx +10 -0
  61. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressMineView.tsx +10 -0
  62. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectResItem.tsx +1 -7
  63. package/vona/src/suite/a-commerce/modules/commerce-member/src/service/address.ts +43 -42
  64. package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +168 -130
  65. package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +297 -3
  66. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +15 -0
  67. package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +128 -0
  68. package/vona/src/suite/a-commerce/modules/commerce-payment/src/dto/paymentAttemptView.tsx +2 -2
  69. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +5 -2
  70. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAudit.tsx +54 -0
  71. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundAttempt.tsx +37 -0
  72. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundAudit.tsx +47 -0
  73. package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundRequest.tsx +43 -0
  74. package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/paymentAudit.ts +10 -0
  75. package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/refundAttempt.ts +10 -0
  76. package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/refundAudit.ts +10 -0
  77. package/vona/src/suite/a-commerce/modules/commerce-payment/src/model/refundRequest.ts +10 -0
  78. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/mockPaymentAdapter.ts +18 -0
  79. package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +22 -7
  80. package/vona/src/suite/a-commerce/modules/commerce-promotion/src/service/coupon.ts +2 -0
  81. package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponReservation.test.ts +395 -6
  82. package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/ssrMenu.test.ts +14 -0
  83. package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +345 -3
  84. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.index.ts +2 -0
  85. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.version.ts +16 -0
  86. package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.order.ts +30 -0
  87. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/order.ts +112 -0
  88. package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/payment.ts +23 -0
  89. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +4 -4
  90. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderDetail.tsx +93 -0
  91. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderMineReq.tsx +21 -0
  92. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderMineRes.tsx +11 -0
  93. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectReq.tsx +25 -0
  94. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectRes.tsx +11 -0
  95. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSelectResItem.tsx +41 -0
  96. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderShip.tsx +15 -0
  97. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/orderSummary.tsx +47 -0
  98. package/vona/src/suite/a-commerce/modules/{commerce-member/src/dto/addressCreate.tsx → commerce-trade/src/dto/orderView.tsx} +5 -17
  99. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/paymentOutcomeCreate.tsx +16 -0
  100. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/paymentOutcomeResult.tsx +29 -0
  101. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundOutcomeCreate.tsx +16 -0
  102. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundRequestCreate.tsx +15 -0
  103. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundResult.tsx +35 -0
  104. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundReview.tsx +15 -0
  105. package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/shipmentView.tsx +22 -0
  106. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/orderAudit.tsx +54 -6
  107. package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/shipment.tsx +28 -0
  108. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +1 -0
  109. package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/shipment.ts +10 -0
  110. package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +839 -28
  111. package/vona/src/suite/a-commerce/modules/commerce-trade/test/cartOwnership.test.ts +2 -4
  112. package/vona/src/suite/a-commerce/modules/commerce-trade/test/checkoutReservation.test.ts +521 -6
  113. package/vona/src/suite/a-commerce/modules/commerce-trade/test/checkoutTransaction.test.ts +16 -14
  114. package/vona/src/suite/a-commerce/modules/commerce-trade/test/order.test.ts +37 -0
  115. package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +3 -5
  116. package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +712 -0
  117. package/vona/src/suite/a-commerce/modules/commerce-trade/test/refundLifecycle.test.ts +337 -0
  118. package/vona/src/suite/a-commerce/modules/commerce-trade/test/reservationExpiry.test.ts +194 -4
  119. package/vona/src/suite/a-commerce/modules/commerce-trade/test/shipment.test.ts +258 -0
  120. package/vona/src/suite/a-commerce/modules/commerce-trade/test/shipmentRefundRace.test.ts +143 -0
  121. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockBalance.test.ts +2 -4
  122. package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockReservation.test.ts +2 -4
  123. package/vona/src/suite/a-home/modules/home-user/src/.metadata/index.ts +21 -0
  124. package/vona/src/suite/a-home/modules/home-user/src/controller/passportTest.ts +21 -0
  125. package/vona/src/suite/a-home/modules/home-user/test/passportTest.test.ts +77 -0
  126. package/vona/src/suite/cabloy-basic/modules/basic-metrics/package.json +54 -0
  127. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/index.ts +189 -0
  128. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/this.ts +1 -0
  129. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/bean/ssrMenu.metrics.ts +23 -0
  130. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/controller/metrics.ts +21 -0
  131. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/dto/metricsQueue.ts +25 -0
  132. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/dto/metricsRuntime.ts +36 -0
  133. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/dto/metricsSnapshot.ts +21 -0
  134. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/index.ts +1 -0
  135. package/vona/src/suite/cabloy-basic/modules/basic-metrics/src/service/metrics.ts +11 -0
  136. package/vona/src/suite/cabloy-basic/modules/basic-metrics/tsconfig.build.json +11 -0
  137. package/vona/src/suite/cabloy-basic/modules/basic-metrics/tsconfig.json +5 -0
  138. package/vona/src/suite/cabloy-basic/package.json +1 -0
  139. package/vona/src/suite-vendor/a-vona/modules/a-broadcast/package.json +2 -1
  140. package/vona/src/suite-vendor/a-vona/modules/a-broadcast/src/service/broadcast.ts +84 -23
  141. package/vona/src/suite-vendor/a-vona/modules/a-broadcast/src/types/broadcast.ts +7 -1
  142. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  143. package/vona/src/suite-vendor/a-vona/modules/a-core/src/lib/core.ts +8 -0
  144. package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +4 -2
  145. package/vona/src/suite-vendor/a-vona/modules/a-executor/src/service/executor.ts +68 -53
  146. package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
  147. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/bean/middlewareSystem.app.ts +2 -0
  148. package/vona/src/suite-vendor/a-vona/modules/a-instance/src/bean/middlewareSystem.instance.ts +2 -0
  149. package/vona/src/suite-vendor/a-vona/modules/a-metrics/package.json +62 -0
  150. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/.metadata/index.ts +178 -0
  151. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/.metadata/this.ts +1 -0
  152. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/bean/bean.metrics.ts +15 -0
  153. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/bean/middlewareSystem.health.ts +24 -0
  154. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/bean/middlewareSystem.metrics.ts +51 -0
  155. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/config/config.ts +75 -0
  156. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/index.ts +2 -0
  157. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/monkey.ts +27 -0
  158. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/service/health.ts +53 -0
  159. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/service/metrics.ts +222 -0
  160. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/service/metricsRuntime.ts +69 -0
  161. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/types/context.ts +9 -0
  162. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/types/index.ts +2 -0
  163. package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/types/metrics.ts +50 -0
  164. package/vona/src/suite-vendor/a-vona/modules/a-metrics/tsconfig.build.json +11 -0
  165. package/vona/src/suite-vendor/a-vona/modules/a-metrics/tsconfig.json +7 -0
  166. package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/model/metadata/generate.ts +10 -0
  167. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  168. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_cache.ts +12 -0
  169. package/vona/src/suite-vendor/a-vona/modules/a-queue/package.json +4 -2
  170. package/vona/src/suite-vendor/a-vona/modules/a-queue/src/service/queue.ts +103 -54
  171. package/vona/src/suite-vendor/a-vona/modules/a-queue/src/types/queue.ts +5 -0
  172. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/package.json +48 -0
  173. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/.metadata/index.ts +100 -0
  174. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/.metadata/this.ts +2 -0
  175. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/bean/interceptor.rateLimit.ts +72 -0
  176. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/index.ts +2 -0
  177. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/main.ts +28 -0
  178. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/service/rateLimit.ts +75 -0
  179. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/types/index.ts +1 -0
  180. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/src/types/rateLimit.ts +19 -0
  181. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/tsconfig.build.json +11 -0
  182. package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/tsconfig.json +7 -0
  183. package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
  184. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redis.ts +1 -2
  185. package/vona/src/suite-vendor/a-vona/modules/a-redis/src/types/redis.ts +1 -0
  186. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/package.json +63 -0
  187. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/.metadata/index.ts +132 -0
  188. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/.metadata/this.ts +2 -0
  189. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/bean/bean.telemetry.ts +71 -0
  190. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/bean/middlewareSystem.trace.ts +73 -0
  191. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/config/config.ts +83 -0
  192. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/index.ts +2 -0
  193. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/lib/ingress.ts +34 -0
  194. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/monkey.ts +22 -0
  195. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/service/telemetry.ts +201 -0
  196. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/types/index.ts +1 -0
  197. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/src/types/telemetry.ts +22 -0
  198. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/test/telemetry.test.ts +339 -0
  199. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/tsconfig.build.json +11 -0
  200. package/vona/src/suite-vendor/a-vona/modules/a-telemetry/tsconfig.json +7 -0
  201. package/vona/src/suite-vendor/a-vona/package.json +4 -1
  202. package/vona/src/suite-vendor/a-vona/tsconfig.json +3 -0
  203. package/zova/package.original.json +1 -1
  204. package/zova/packages-cli/cli/package.json +2 -2
  205. package/zova/packages-cli/cli-set-front/package.json +1 -1
  206. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.bin.buildRest.ts +3 -2
  207. package/zova/packages-zova/zova/package.json +2 -2
  208. package/zova/pnpm-lock.yaml +47 -72
  209. package/zova/src/front/config/config/config.cabloyCommerce.ts +4 -0
  210. package/zova/src/suite/a-commerce/modules/commerce-member/cli/openapi.config.ts +9 -1
  211. package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +16 -0
  212. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/commerceMemberAddress.ts +94 -50
  213. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +162 -52
  214. package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +2656 -1298
  215. package/zova/src/suite/a-commerce/modules/commerce-member/src/apiSchema/commerceMemberAddress.ts +23 -13
  216. package/zova/src/suite/a-commerce/modules/commerce-member/src/model/addressMine.ts +67 -0
  217. package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +21 -11
  218. package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +10 -0
  219. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/component/tableCellActionRefund.ts +31 -0
  220. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/component/tableCellActionShip.ts +31 -0
  221. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +277 -1
  222. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/checkout.ts +19 -0
  223. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/order.ts +19 -0
  224. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/orders.ts +19 -0
  225. package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/payment.ts +19 -0
  226. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeOrder.ts +218 -0
  227. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradePayment.ts +36 -0
  228. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +91 -8
  229. package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +1019 -74
  230. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeOrder.ts +55 -0
  231. package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradePayment.ts +13 -0
  232. package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionRefund.tsx +40 -0
  233. package/zova/src/suite/a-commerce/modules/commerce-trade/src/bean/tableCell.actionShip.tsx +41 -0
  234. package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionRefund/controller.tsx +106 -0
  235. package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionShip/controller.tsx +66 -0
  236. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +9 -0
  237. package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +9 -0
  238. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +82 -0
  239. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/orderMine.ts +46 -0
  240. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/payment.ts +25 -0
  241. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +14 -3
  242. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +124 -0
  243. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/order/controller.tsx +146 -0
  244. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/orders/controller.tsx +95 -0
  245. package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +88 -0
  246. package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +28 -0
  247. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/command.delete.tsx +3 -2
  248. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionUpdate.tsx +2 -1
  249. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionView.tsx +1 -1
  250. package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/en-us.ts +1 -0
  251. package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/zh-cn.ts +1 -0
  252. package/zova/src/suite/cabloy-basic/modules/basic-metrics/package.json +53 -0
  253. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/index.ts +151 -0
  254. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/page/dashboard.ts +9 -0
  255. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/.metadata/this.ts +1 -0
  256. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/api/basicMetricsMetrics.ts +41 -0
  257. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/index.ts +2 -0
  258. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/model/metrics.ts +16 -0
  259. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/page/dashboard/controller.tsx +95 -0
  260. package/zova/src/suite/cabloy-basic/modules/basic-metrics/src/routes.ts +5 -0
  261. package/zova/src/suite/cabloy-basic/modules/basic-metrics/tsconfig.build.json +13 -0
  262. package/zova/src/suite/cabloy-basic/modules/basic-metrics/tsconfig.json +5 -0
  263. package/zova/src/suite/cabloy-basic/package.json +1 -0
  264. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  265. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +4 -0
  266. package/zova/src/suite-vendor/a-zova/package.json +2 -2
  267. package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressUpdate.tsx +0 -39
  268. package/vona/src/suite/a-commerce/modules/commerce-trade/test/testLock.ts +0 -11
@@ -0,0 +1,10 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { Dto } from 'vona-module-a-web';
4
+
5
+ import { DtoAddressMineCreate } from './addressMineCreate.tsx';
6
+
7
+ export interface IDtoOptionsAddressMineUpdate extends IDecoratorDtoOptions {}
8
+
9
+ @Dto<IDtoOptionsAddressMineUpdate>()
10
+ export class DtoAddressMineUpdate extends DtoAddressMineCreate {}
@@ -0,0 +1,10 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { Dto } from 'vona-module-a-web';
4
+
5
+ import { DtoAddressMineItem } from './addressMineItem.tsx';
6
+
7
+ export interface IDtoOptionsAddressMineView extends IDecoratorDtoOptions {}
8
+
9
+ @Dto<IDtoOptionsAddressMineView>()
10
+ export class DtoAddressMineView extends DtoAddressMineItem {}
@@ -15,9 +15,6 @@ export interface IDtoOptionsAddressSelectResItem extends IDecoratorDtoOptions {}
15
15
  ZovaRender.block('basic-page:blockPage', {
16
16
  blocks: [
17
17
  ZovaRender.block('basic-page:blockFilter'),
18
- ZovaRender.block('basic-page:blockToolbarBulk', {
19
- actions: [ZovaRender.tableActionBulk('basic-table:actionCreate')],
20
- }),
21
18
  ZovaRender.block('basic-page:blockTable'),
22
19
  ZovaRender.block('basic-page:blockPager'),
23
20
  ],
@@ -43,10 +40,7 @@ export class DtoAddressSelectResItem extends $Dto.get(() => ModelAddress, {
43
40
  v.title($locale('Operations')),
44
41
  ZovaRender.order(1, 'max'),
45
42
  ZovaRender.cell('basic-table:actionOperationsRow', {
46
- actions: [
47
- ZovaRender.tableActionRow('basic-table:actionUpdate'),
48
- ZovaRender.tableActionRow('basic-table:actionDelete'),
49
- ],
43
+ actions: [ZovaRender.tableActionRow('basic-table:actionView')],
50
44
  }),
51
45
  )
52
46
  _operationsRow?: unknown;
@@ -1,57 +1,72 @@
1
1
  import type { TableIdentity } from 'table-identity';
2
- import type { IQueryParams } from 'vona-module-a-orm';
2
+ import type { IQueryParams, TypeModelColumns } from 'vona-module-a-orm';
3
3
 
4
4
  import { BeanBase } from 'vona';
5
5
  import { Service } from 'vona-module-a-bean';
6
6
 
7
- import type { DtoAddressCreate } from '../dto/addressCreate.tsx';
7
+ import type { DtoAddressMineCreate } from '../dto/addressMineCreate.tsx';
8
+ import type { DtoAddressMineRes } from '../dto/addressMineRes.tsx';
9
+ import type { DtoAddressMineUpdate } from '../dto/addressMineUpdate.tsx';
10
+ import type { DtoAddressMineView } from '../dto/addressMineView.tsx';
8
11
  import type { DtoAddressSelectRes } from '../dto/addressSelectRes.tsx';
9
- import type { DtoAddressUpdate } from '../dto/addressUpdate.tsx';
10
12
  import type { DtoAddressView } from '../dto/addressView.tsx';
13
+ import type { EntityAddress } from '../entity/address.tsx';
11
14
  import type { ModelAddress } from '../model/address.ts';
12
15
 
16
+ const addressColumns: TypeModelColumns<EntityAddress> = [
17
+ 'id',
18
+ 'recipientName',
19
+ 'phone',
20
+ 'countryCode',
21
+ 'region',
22
+ 'city',
23
+ 'postalCode',
24
+ 'addressLine1',
25
+ 'addressLine2',
26
+ 'createdAt',
27
+ 'updatedAt',
28
+ ];
29
+
13
30
  @Service()
14
31
  export class ServiceAddress extends BeanBase {
15
- async create(address: DtoAddressCreate) {
16
- return await this.scope.model.address.insert({
17
- ...address,
18
- userId: this._getCurrentUserId(),
32
+ async select(params?: IQueryParams<ModelAddress>): Promise<DtoAddressSelectRes> {
33
+ return await this.scope.model.address.selectAndCount({
34
+ ...params,
35
+ orders: params?.orders ?? [['id', 'asc']],
19
36
  });
20
37
  }
21
38
 
22
- async select(params?: IQueryParams<ModelAddress>): Promise<DtoAddressSelectRes> {
39
+ async view(id: TableIdentity): Promise<DtoAddressView | undefined> {
40
+ return await this.scope.model.address.getById(id);
41
+ }
42
+
43
+ async mine(params?: IQueryParams<ModelAddress>): Promise<DtoAddressMineRes> {
23
44
  return await this.scope.model.address.selectAndCount({
24
- columns: [
25
- 'id',
26
- 'recipientName',
27
- 'phone',
28
- 'countryCode',
29
- 'region',
30
- 'city',
31
- 'postalCode',
32
- 'addressLine1',
33
- 'addressLine2',
34
- 'createdAt',
35
- 'updatedAt',
36
- ],
45
+ ...params,
46
+ columns: addressColumns,
37
47
  where: { ...params?.where, userId: this._getCurrentUserId() },
38
- orders: [['id', 'asc']],
39
- limit: params?.limit ?? 20,
40
- offset: params?.offset ?? 0,
48
+ orders: params?.orders ?? [['id', 'asc']],
41
49
  });
42
50
  }
43
51
 
44
- async view(id: TableIdentity): Promise<DtoAddressView | undefined> {
52
+ async viewMine(id: TableIdentity): Promise<DtoAddressMineView | undefined> {
45
53
  return await this._getOwnedAddress(id);
46
54
  }
47
55
 
48
- async update(id: TableIdentity, address: DtoAddressUpdate) {
56
+ async createMine(address: DtoAddressMineCreate) {
57
+ return await this.scope.model.address.insert({
58
+ ...address,
59
+ userId: this._getCurrentUserId(),
60
+ });
61
+ }
62
+
63
+ async updateMine(id: TableIdentity, address: DtoAddressMineUpdate) {
49
64
  const ownedAddress = await this._getOwnedAddress(id);
50
65
  if (!ownedAddress) return;
51
66
  await this.scope.model.address.updateById(ownedAddress.id, address);
52
67
  }
53
68
 
54
- async delete(id: TableIdentity) {
69
+ async deleteMine(id: TableIdentity) {
55
70
  const ownedAddress = await this._getOwnedAddress(id);
56
71
  if (!ownedAddress) return;
57
72
  await this.scope.model.address.deleteById(ownedAddress.id);
@@ -64,21 +79,7 @@ export class ServiceAddress extends BeanBase {
64
79
  private async _getOwnedAddress(id: TableIdentity) {
65
80
  return await this.scope.model.address.get(
66
81
  { id, userId: this._getCurrentUserId() },
67
- {
68
- columns: [
69
- 'id',
70
- 'recipientName',
71
- 'phone',
72
- 'countryCode',
73
- 'region',
74
- 'city',
75
- 'postalCode',
76
- 'addressLine1',
77
- 'addressLine2',
78
- 'createdAt',
79
- 'updatedAt',
80
- ],
81
- },
82
+ { columns: addressColumns },
82
83
  );
83
84
  }
84
85
  }
@@ -1,6 +1,6 @@
1
1
  import type {
2
- DtoAddressCreate,
3
- DtoAddressUpdate,
2
+ DtoAddressMineCreate,
3
+ DtoAddressMineUpdate,
4
4
  EntityAddress,
5
5
  } from 'vona-module-commerce-member';
6
6
 
@@ -11,12 +11,17 @@ import { describe, it } from 'node:test';
11
11
  import { app } from 'vona-mock';
12
12
 
13
13
  const actionPath = '/commerce/member/address';
14
+ const minePath = `${actionPath}/mine`;
15
+ const viewMinePath = `${actionPath}/viewMine/:id`;
16
+ const createMinePath = `${actionPath}/createMine`;
17
+ const updateMinePath = `${actionPath}/updateMine/:id`;
18
+ const deleteMinePath = `${actionPath}/deleteMine/:id`;
14
19
 
15
20
  function createTestId() {
16
21
  return randomUUID().slice(0, 12);
17
22
  }
18
23
 
19
- function createAddress(suffix: string): DtoAddressCreate {
24
+ function createAddress(suffix: string): DtoAddressMineCreate {
20
25
  return {
21
26
  recipientName: `Recipient ${suffix}`,
22
27
  phone: '15555550123',
@@ -45,15 +50,23 @@ async function registerAndSignin(name: string) {
45
50
  return { token: token.accessToken, user: app.bean.passport.currentUser! };
46
51
  }
47
52
 
48
- describe('address.test.ts', () => {
49
- it('denies anonymous address actions', async () => {
53
+ async function deleteOwnedAddresses(ids: Array<number | string | undefined>) {
54
+ for (const id of ids) {
55
+ if (id !== undefined) await app.scope('commerce-member').model.address.deleteById(id);
56
+ }
57
+ }
58
+
59
+ describe('addressOwnership.test.ts', () => {
60
+ it('denies anonymous Admin and Web Address actions', async () => {
50
61
  await app.bean.executor.mockCtx(async () => {
51
62
  for (const [method, path, options] of [
52
- ['post', actionPath, { body: createAddress('anonymous') }],
53
63
  ['get', actionPath, {}],
54
64
  ['get', `${actionPath}/:id`, { params: { id: 999999 } }],
55
- ['patch', `${actionPath}/:id`, { params: { id: 999999 }, body: {} }],
56
- ['delete', `${actionPath}/:id`, { params: { id: 999999 } }],
65
+ ['get', minePath, {}],
66
+ ['get', viewMinePath, { params: { id: 999999 } }],
67
+ ['post', createMinePath, { body: createAddress('anonymous') }],
68
+ ['patch', updateMinePath, { params: { id: 999999 }, body: createAddress('anonymous') }],
69
+ ['delete', deleteMinePath, { params: { id: 999999 } }],
57
70
  ] as const) {
58
71
  const [_, err] = await catchError(() =>
59
72
  app.bean.executor.performAction(method, path, { ...options, innerAccess: false }),
@@ -63,149 +76,174 @@ describe('address.test.ts', () => {
63
76
  });
64
77
  });
65
78
 
66
- it('derives ownership from the authenticated customer and scopes every action', async () => {
67
- await app.bean.executor.mockCtx(async () => {
68
- const suffix = createTestId();
69
- const customerA = await registerAndSignin(`address-a-${suffix}`);
70
- const customerB = await registerAndSignin(`address-b-${suffix}`);
71
- const addressData = createAddress(suffix);
72
- const addressId = await performAs(customerA.token, 'post', actionPath, {
73
- body: { ...addressData, userId: customerB.user.id, iid: 999999 } as any,
74
- });
75
-
76
- const persisted = await app.scope('commerce-member').model.address.getById(addressId);
77
- assert.equal(String(persisted?.userId), String(customerA.user.id));
78
- assert.equal(persisted?.iid, app.ctx.instance.id);
79
-
80
- const ownList = await performAs(customerA.token, 'get', actionPath);
81
- assert.equal(
82
- ownList.list.some(item => String(item.id) === String(addressId)),
83
- true,
84
- );
85
- assert.equal(
86
- ownList.list.every(item => !Object.hasOwn(item, 'userId')),
87
- true,
88
- );
89
- assert.equal(
90
- ownList.list.every(item => !Object.hasOwn(item, 'iid')),
91
- true,
92
- );
93
-
94
- const { addressLine2: _, ...update } = {
95
- ...addressData,
96
- city: 'Oakland',
97
- } satisfies DtoAddressUpdate;
98
- assert.equal(
99
- await performAs(customerA.token, 'patch', `${actionPath}/:id`, {
100
- params: { id: addressId },
101
- body: update,
102
- }),
103
- null,
104
- );
105
- const ownAddress: EntityAddress = await performAs(
106
- customerA.token,
107
- 'get',
108
- `${actionPath}/:id`,
109
- {
110
- params: { id: addressId },
111
- },
112
- );
113
- assert.equal(ownAddress.city, update.city);
114
- assert.equal(ownAddress.addressLine2, addressData.addressLine2);
115
- assert.equal(Object.hasOwn(ownAddress, 'userId'), false);
116
- assert.equal(Object.hasOwn(ownAddress, 'iid'), false);
117
-
118
- const foreignList = await performAs(customerB.token, 'get', actionPath);
119
- assert.equal(
120
- foreignList.list.some(item => String(item.id) === String(addressId)),
121
- false,
122
- );
123
- assert.equal(
124
- await performAs(customerB.token, 'get', `${actionPath}/:id`, { params: { id: addressId } }),
125
- undefined,
126
- );
127
- assert.equal(
128
- await performAs(customerB.token, 'patch', `${actionPath}/:id`, {
129
- params: { id: addressId },
130
- body: { ...addressData, city: 'Los Angeles' },
131
- }),
132
- null,
133
- );
134
- assert.equal(
135
- await performAs(customerB.token, 'delete', `${actionPath}/:id`, {
136
- params: { id: addressId },
137
- }),
138
- null,
139
- );
140
- assert.equal(
141
- (await app.scope('commerce-member').model.address.getById(addressId))?.city,
142
- 'Oakland',
143
- );
144
-
145
- assert.equal(
146
- await performAs(customerA.token, 'delete', `${actionPath}/:id`, {
147
- params: { id: addressId },
148
- }),
149
- null,
150
- );
151
- assert.equal(
152
- await performAs(customerA.token, 'get', `${actionPath}/:id`, { params: { id: addressId } }),
153
- undefined,
154
- );
155
- });
156
- });
157
-
158
- it('treats another instance address as absent', async () => {
159
- let addressId!: number;
160
- let customerDefault!: Awaited<ReturnType<typeof registerAndSignin>>;
161
- const addressDefault = createAddress('default');
79
+ it('derives Web ownership from Passport and treats foreign rows as absent', async () => {
162
80
  await app.bean.executor.mockCtx(async () => {
163
- customerDefault = await registerAndSignin(`address-default-${Date.now()}`);
164
- addressId = await performAs(customerDefault.token, 'post', actionPath, {
165
- body: addressDefault,
166
- });
167
- });
81
+ let addressId: number | undefined;
82
+ try {
83
+ const suffix = createTestId();
84
+ const customerA = await registerAndSignin(`address-a-${suffix}`);
85
+ const customerB = await registerAndSignin(`address-b-${suffix}`);
86
+ const addressData = createAddress(suffix);
87
+ addressId = await performAs(customerA.token, 'post', createMinePath, {
88
+ body: { ...addressData, userId: customerB.user.id, iid: 999999 } as any,
89
+ });
90
+
91
+ const persisted = await app.scope('commerce-member').model.address.getById(addressId);
92
+ assert.equal(String(persisted?.userId), String(customerA.user.id));
93
+ assert.equal(persisted?.iid, app.ctx.instance.id);
94
+
95
+ const ownList = await performAs(customerA.token, 'get', minePath);
96
+ assert.equal(
97
+ ownList.list.some(item => String(item.id) === String(addressId)),
98
+ true,
99
+ );
100
+ assert.equal(
101
+ ownList.list.every(item => !Object.hasOwn(item, 'userId')),
102
+ true,
103
+ );
104
+ assert.equal(
105
+ ownList.list.every(item => !Object.hasOwn(item, 'iid')),
106
+ true,
107
+ );
168
108
 
169
- await app.bean.executor.mockCtx(
170
- async () => {
171
- const customer = await registerAndSignin(`address-share-${Date.now()}`);
109
+ const { addressLine2: _, ...update } = {
110
+ ...addressData,
111
+ city: 'Oakland',
112
+ } satisfies DtoAddressMineUpdate;
172
113
  assert.equal(
173
- await performAs(customer.token, 'get', `${actionPath}/:id`, {
114
+ await performAs(customerA.token, 'patch', updateMinePath, {
174
115
  params: { id: addressId },
116
+ body: update,
175
117
  }),
176
- undefined,
118
+ null,
177
119
  );
178
- const list = await performAs(customer.token, 'get', actionPath);
120
+ const ownAddress: EntityAddress = await performAs(customerA.token, 'get', viewMinePath, {
121
+ params: { id: addressId },
122
+ });
123
+ assert.equal(ownAddress.city, update.city);
124
+ assert.equal(ownAddress.addressLine2, addressData.addressLine2);
125
+ assert.equal(Object.hasOwn(ownAddress, 'userId'), false);
126
+ assert.equal(Object.hasOwn(ownAddress, 'iid'), false);
127
+
128
+ const foreignList = await performAs(customerB.token, 'get', minePath);
179
129
  assert.equal(
180
- list.list.some(item => String(item.id) === String(addressId)),
130
+ foreignList.list.some(item => String(item.id) === String(addressId)),
181
131
  false,
182
132
  );
183
133
  assert.equal(
184
- await performAs(customer.token, 'patch', `${actionPath}/:id`, {
134
+ await performAs(customerB.token, 'get', viewMinePath, { params: { id: addressId } }),
135
+ undefined,
136
+ );
137
+ assert.equal(
138
+ await performAs(customerB.token, 'patch', updateMinePath, {
185
139
  params: { id: addressId },
186
- body: { ...createAddress('foreign'), city: 'Other city' },
140
+ body: { ...addressData, city: 'Los Angeles' },
187
141
  }),
188
142
  null,
189
143
  );
190
144
  assert.equal(
191
- await performAs(customer.token, 'delete', `${actionPath}/:id`, {
192
- params: { id: addressId },
193
- }),
145
+ await performAs(customerB.token, 'delete', deleteMinePath, { params: { id: addressId } }),
194
146
  null,
195
147
  );
196
148
  assert.equal(
197
- await app.scope('commerce-member').model.address.getById(addressId),
198
- undefined,
149
+ (await app.scope('commerce-member').model.address.getById(addressId))?.city,
150
+ 'Oakland',
199
151
  );
200
- },
201
- { instanceName: 'shareTest' as any },
202
- );
152
+ } finally {
153
+ await deleteOwnedAddresses([addressId]);
154
+ }
155
+ });
156
+ });
203
157
 
158
+ it('exposes active-instance Address inspection only to systemAdmin', async () => {
204
159
  await app.bean.executor.mockCtx(async () => {
205
- const address = await performAs(customerDefault.token, 'get', `${actionPath}/:id`, {
206
- params: { id: addressId },
207
- });
208
- assert.equal(address.city, addressDefault.city);
160
+ let addressId: number | undefined;
161
+ try {
162
+ const suffix = createTestId();
163
+ const customer = await registerAndSignin(`address-admin-${suffix}`);
164
+ addressId = await performAs(customer.token, 'post', createMinePath, {
165
+ body: createAddress(suffix),
166
+ });
167
+
168
+ const [_, nonAdminError] = await catchError(() =>
169
+ performAs(customer.token, 'get', actionPath),
170
+ );
171
+ assert.equal(nonAdminError?.code, 403);
172
+
173
+ const admin = await app.bean.passport.signinMock();
174
+ const list = await performAs(admin.accessToken, 'get', actionPath);
175
+ assert.equal(
176
+ list.list.some(item => String(item.id) === String(addressId)),
177
+ true,
178
+ );
179
+ const address = await performAs(admin.accessToken, 'get', `${actionPath}/:id`, {
180
+ params: { id: addressId },
181
+ });
182
+ assert.equal(address?.id, addressId);
183
+
184
+ const permissions = await Promise.all(
185
+ ['create', 'update', 'delete'].map(action =>
186
+ app.bean.permission.retrievePermissionAction('commerce-member:address', action),
187
+ ),
188
+ );
189
+ assert.deepEqual(permissions, [false, false, false]);
190
+ } finally {
191
+ await deleteOwnedAddresses([addressId]);
192
+ }
209
193
  });
210
194
  });
195
+
196
+ it('treats another instance Address as absent on Web actions', async () => {
197
+ let addressId: number | undefined;
198
+ let customerDefault!: Awaited<ReturnType<typeof registerAndSignin>>;
199
+ const addressDefault = createAddress('default');
200
+ try {
201
+ await app.bean.executor.mockCtx(async () => {
202
+ customerDefault = await registerAndSignin(`address-default-${createTestId()}`);
203
+ addressId = await performAs(customerDefault.token, 'post', createMinePath, {
204
+ body: addressDefault,
205
+ });
206
+ });
207
+
208
+ await app.bean.executor.mockCtx(
209
+ async () => {
210
+ const customer = await registerAndSignin(`address-share-${createTestId()}`);
211
+ assert.equal(
212
+ await performAs(customer.token, 'get', viewMinePath, { params: { id: addressId } }),
213
+ undefined,
214
+ );
215
+ const list = await performAs(customer.token, 'get', minePath);
216
+ assert.equal(
217
+ list.list.some(item => String(item.id) === String(addressId)),
218
+ false,
219
+ );
220
+ assert.equal(
221
+ await performAs(customer.token, 'patch', updateMinePath, {
222
+ params: { id: addressId },
223
+ body: { ...createAddress('foreign'), city: 'Other city' },
224
+ }),
225
+ null,
226
+ );
227
+ assert.equal(
228
+ await performAs(customer.token, 'delete', deleteMinePath, {
229
+ params: { id: addressId },
230
+ }),
231
+ null,
232
+ );
233
+ },
234
+ { instanceName: 'shareTest' as any },
235
+ );
236
+
237
+ await app.bean.executor.mockCtx(async () => {
238
+ const address = await performAs(customerDefault.token, 'get', viewMinePath, {
239
+ params: { id: addressId },
240
+ });
241
+ assert.equal(address.city, addressDefault.city);
242
+ });
243
+ } finally {
244
+ await app.bean.executor.mockCtx(async () => {
245
+ await deleteOwnedAddresses([addressId]);
246
+ });
247
+ }
248
+ });
211
249
  });