payment-kit 1.29.1 → 1.29.3

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 (343) hide show
  1. package/api/dev.ts +41 -2
  2. package/api/hono.d.ts +42 -0
  3. package/api/node-sqlite.d.ts +12 -0
  4. package/api/src/bootstrap.ts +47 -0
  5. package/api/src/crons/base.ts +3 -3
  6. package/api/src/crons/currency.ts +1 -1
  7. package/api/src/crons/index.ts +41 -37
  8. package/api/src/crons/metering-subscription-detection.ts +1 -1
  9. package/api/src/crons/overdue-detection.ts +2 -2
  10. package/api/src/crons/retry-pending-events.ts +6 -0
  11. package/api/src/crons/tenant-fanout.ts +82 -0
  12. package/api/src/host-node/did-connect-runtime-node.ts +33 -0
  13. package/api/src/host-node/serve-static-arc.ts +68 -0
  14. package/api/src/host-node/serve-static.ts +41 -0
  15. package/api/src/index.ts +22 -161
  16. package/api/src/integrations/app-store/client.ts +3 -4
  17. package/api/src/integrations/app-store/handlers/subscription.ts +7 -7
  18. package/api/src/integrations/app-store/signed-data-verifier.ts +3 -2
  19. package/api/src/integrations/arcblock/token.ts +21 -7
  20. package/api/src/integrations/google-play/handlers/subscription.ts +6 -6
  21. package/api/src/integrations/google-play/handlers/voided.ts +2 -2
  22. package/api/src/integrations/google-play/verify.ts +3 -2
  23. package/api/src/integrations/iap-reconcile.ts +3 -5
  24. package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
  25. package/api/src/integrations/stripe/handlers/subscription.ts +3 -3
  26. package/api/src/libs/archive/query.ts +19 -0
  27. package/api/src/libs/audit.ts +61 -4
  28. package/api/src/libs/auth.ts +247 -47
  29. package/api/src/libs/context.ts +89 -1
  30. package/api/src/libs/currency.ts +2 -2
  31. package/api/src/libs/dayjs.ts +8 -2
  32. package/api/src/libs/did-connect/runtime-did-connect-js.ts +88 -0
  33. package/api/src/libs/did-connect/tenant-identity.ts +221 -0
  34. package/api/src/libs/drivers/auth-storage.ts +118 -0
  35. package/api/src/libs/drivers/cron.ts +264 -0
  36. package/api/src/libs/drivers/db.ts +170 -0
  37. package/api/src/libs/drivers/identity.ts +142 -0
  38. package/api/src/libs/drivers/index.ts +40 -0
  39. package/api/src/libs/drivers/locks.ts +226 -0
  40. package/api/src/libs/drivers/migrate-runner.ts +70 -0
  41. package/api/src/libs/drivers/queue.ts +104 -0
  42. package/api/src/libs/drivers/secrets.ts +194 -0
  43. package/api/src/libs/env.ts +170 -54
  44. package/api/src/libs/exchange-rate/service.ts +7 -6
  45. package/api/src/libs/http-fetch-adapter.ts +60 -0
  46. package/api/src/libs/invoice.ts +1 -1
  47. package/api/src/libs/lock.ts +51 -47
  48. package/api/src/libs/logger.ts +48 -8
  49. package/api/src/libs/notification/index.ts +1 -1
  50. package/api/src/libs/notification/template/customer-credit-low-balance.ts +2 -1
  51. package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -1
  52. package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -1
  53. package/api/src/libs/overdraft-protection.ts +1 -1
  54. package/api/src/libs/payout.ts +1 -1
  55. package/api/src/libs/queue/index.ts +271 -52
  56. package/api/src/libs/queue/runtime.ts +175 -0
  57. package/api/src/libs/resource.ts +3 -3
  58. package/api/src/libs/secrets.ts +38 -0
  59. package/api/src/libs/session.ts +3 -2
  60. package/api/src/libs/subscription.ts +5 -5
  61. package/api/src/libs/tenant.ts +92 -0
  62. package/api/src/libs/url.ts +3 -3
  63. package/api/src/libs/util.ts +21 -13
  64. package/api/src/middlewares/hono/cdn.ts +63 -0
  65. package/api/src/middlewares/hono/context.ts +80 -0
  66. package/api/src/middlewares/hono/csrf.ts +83 -0
  67. package/api/src/middlewares/hono/fallback.ts +194 -0
  68. package/api/src/middlewares/hono/pipeline.ts +73 -0
  69. package/api/src/middlewares/hono/resource-mount.ts +42 -0
  70. package/api/src/middlewares/hono/resource.ts +63 -0
  71. package/api/src/middlewares/hono/security.ts +209 -0
  72. package/api/src/middlewares/hono/session.ts +114 -0
  73. package/api/src/middlewares/hono/xss.ts +61 -0
  74. package/api/src/queues/auto-recharge.ts +12 -10
  75. package/api/src/queues/checkout-session.ts +38 -21
  76. package/api/src/queues/credit-consume.ts +40 -36
  77. package/api/src/queues/credit-grant.ts +25 -18
  78. package/api/src/queues/credit-reconciliation.ts +7 -5
  79. package/api/src/queues/discount-status.ts +9 -6
  80. package/api/src/queues/event.ts +41 -11
  81. package/api/src/queues/exchange-rate-health.ts +49 -30
  82. package/api/src/queues/invoice.ts +18 -15
  83. package/api/src/queues/notification.ts +14 -7
  84. package/api/src/queues/payment.ts +64 -37
  85. package/api/src/queues/payout.ts +37 -21
  86. package/api/src/queues/refund.ts +36 -18
  87. package/api/src/queues/subscription.ts +83 -53
  88. package/api/src/queues/token-transfer.ts +15 -10
  89. package/api/src/queues/usage-record.ts +8 -5
  90. package/api/src/queues/vendors/commission.ts +7 -5
  91. package/api/src/queues/vendors/fulfillment-coordinator.ts +17 -13
  92. package/api/src/queues/vendors/fulfillment.ts +4 -2
  93. package/api/src/queues/vendors/return-processor.ts +5 -3
  94. package/api/src/queues/vendors/return-scanner.ts +5 -4
  95. package/api/src/queues/vendors/status-check.ts +10 -7
  96. package/api/src/queues/webhook.ts +60 -32
  97. package/api/src/routes/connect/shared.ts +1 -2
  98. package/api/src/routes/connect/subscribe.ts +3 -3
  99. package/api/src/routes/{archive.ts → hono/archive.ts} +69 -64
  100. package/api/src/routes/{auto-recharge-configs.ts → hono/auto-recharge-configs.ts} +39 -28
  101. package/api/src/routes/{checkout-sessions.ts → hono/checkout-sessions.ts} +790 -923
  102. package/api/src/routes/{coupons.ts → hono/coupons.ts} +93 -76
  103. package/api/src/routes/{credit-grants.ts → hono/credit-grants.ts} +140 -126
  104. package/api/src/routes/hono/credit-tokens.ts +43 -0
  105. package/api/src/routes/{credit-transactions.ts → hono/credit-transactions.ts} +37 -29
  106. package/api/src/routes/{customers.ts → hono/customers.ts} +199 -224
  107. package/api/src/routes/{donations.ts → hono/donations.ts} +41 -32
  108. package/api/src/routes/{entitlements.ts → hono/entitlements.ts} +28 -25
  109. package/api/src/routes/{events.ts → hono/events.ts} +107 -71
  110. package/api/src/routes/{exchange-rate-providers.ts → hono/exchange-rate-providers.ts} +138 -126
  111. package/api/src/routes/hono/exchange-rates.ts +77 -0
  112. package/api/src/routes/hono/index.ts +115 -0
  113. package/api/src/routes/{integrations → hono/integrations}/app-store.ts +68 -48
  114. package/api/src/routes/{integrations → hono/integrations}/google-play.ts +78 -58
  115. package/api/src/routes/hono/integrations/stripe.ts +74 -0
  116. package/api/src/routes/{invoices.ts → hono/invoices.ts} +253 -244
  117. package/api/src/routes/{meter-events.ts → hono/meter-events.ts} +120 -110
  118. package/api/src/routes/hono/meters.ts +288 -0
  119. package/api/src/routes/hono/passports.ts +73 -0
  120. package/api/src/routes/{payment-currencies.ts → hono/payment-currencies.ts} +219 -197
  121. package/api/src/routes/{payment-intents.ts → hono/payment-intents.ts} +136 -132
  122. package/api/src/routes/{payment-links.ts → hono/payment-links.ts} +145 -128
  123. package/api/src/routes/{payment-methods.ts → hono/payment-methods.ts} +125 -93
  124. package/api/src/routes/{payment-stats.ts → hono/payment-stats.ts} +30 -25
  125. package/api/src/routes/{payouts.ts → hono/payouts.ts} +55 -47
  126. package/api/src/routes/{prices.ts → hono/prices.ts} +265 -242
  127. package/api/src/routes/{pricing-table.ts → hono/pricing-table.ts} +94 -87
  128. package/api/src/routes/{products.ts → hono/products.ts} +172 -159
  129. package/api/src/routes/{promotion-codes.ts → hono/promotion-codes.ts} +207 -185
  130. package/api/src/routes/hono/redirect.ts +24 -0
  131. package/api/src/routes/{refunds.ts → hono/refunds.ts} +98 -83
  132. package/api/src/routes/{settings.ts → hono/settings.ts} +64 -55
  133. package/api/src/routes/{subscription-items.ts → hono/subscription-items.ts} +64 -57
  134. package/api/src/routes/{subscriptions.ts → hono/subscriptions.ts} +475 -528
  135. package/api/src/routes/{tax-rates.ts → hono/tax-rates.ts} +71 -70
  136. package/api/src/routes/hono/tool.ts +69 -0
  137. package/api/src/routes/{usage-records.ts → hono/usage-records.ts} +47 -42
  138. package/api/src/routes/{vendor.ts → hono/vendor.ts} +315 -167
  139. package/api/src/routes/{webhook-attempts.ts → hono/webhook-attempts.ts} +17 -13
  140. package/api/src/routes/hono/webhook-endpoints.ts +126 -0
  141. package/api/src/service.ts +814 -0
  142. package/api/src/store/migrations/20230911-seeding.ts +2 -1
  143. package/api/src/store/migrations/20260609-remove-did-space-jobs.ts +23 -0
  144. package/api/src/store/migrations/20260610-tenant-columns.ts +40 -0
  145. package/api/src/store/migrations/20260611-tenant-backfill.ts +33 -0
  146. package/api/src/store/models/auto-recharge-config.ts +22 -10
  147. package/api/src/store/models/checkout-session.ts +15 -14
  148. package/api/src/store/models/coupon.ts +29 -20
  149. package/api/src/store/models/credit-grant.ts +38 -29
  150. package/api/src/store/models/credit-transaction.ts +32 -21
  151. package/api/src/store/models/customer.ts +19 -17
  152. package/api/src/store/models/discount.ts +11 -2
  153. package/api/src/store/models/entitlement-grant.ts +21 -9
  154. package/api/src/store/models/entitlement-product.ts +21 -9
  155. package/api/src/store/models/entitlement.ts +19 -10
  156. package/api/src/store/models/event.ts +18 -9
  157. package/api/src/store/models/exchange-rate-provider.ts +17 -4
  158. package/api/src/store/models/invoice-item.ts +18 -9
  159. package/api/src/store/models/invoice.ts +16 -8
  160. package/api/src/store/models/meter-event.ts +27 -9
  161. package/api/src/store/models/meter.ts +31 -22
  162. package/api/src/store/models/payment-currency.ts +25 -8
  163. package/api/src/store/models/payment-intent.ts +15 -6
  164. package/api/src/store/models/payment-link.ts +15 -6
  165. package/api/src/store/models/payment-method.ts +38 -22
  166. package/api/src/store/models/payment-stat.ts +18 -9
  167. package/api/src/store/models/payout.ts +15 -6
  168. package/api/src/store/models/price-quote.ts +17 -8
  169. package/api/src/store/models/price.ts +24 -12
  170. package/api/src/store/models/pricing-table.ts +29 -20
  171. package/api/src/store/models/product-vendor.ts +20 -10
  172. package/api/src/store/models/product.ts +15 -6
  173. package/api/src/store/models/promotion-code.ts +14 -6
  174. package/api/src/store/models/refund.ts +15 -6
  175. package/api/src/store/models/revenue-snapshot.ts +21 -9
  176. package/api/src/store/models/setting.ts +18 -9
  177. package/api/src/store/models/setup-intent.ts +36 -27
  178. package/api/src/store/models/subscription-item.ts +21 -9
  179. package/api/src/store/models/subscription-schedule.ts +21 -9
  180. package/api/src/store/models/subscription.ts +21 -10
  181. package/api/src/store/models/tax-rate.ts +29 -21
  182. package/api/src/store/models/usage-record.ts +11 -2
  183. package/api/src/store/models/webhook-attempt.ts +18 -9
  184. package/api/src/store/models/webhook-endpoint.ts +18 -9
  185. package/api/src/store/scoped-core.ts +55 -0
  186. package/api/src/store/scoped.ts +247 -0
  187. package/api/src/store/sequelize.ts +82 -23
  188. package/api/src/store/sql-migrations.ts +20 -0
  189. package/api/src/store/tenant-backfill.ts +260 -0
  190. package/api/src/store/tenant-model.ts +124 -0
  191. package/api/src/store/tenant-tables.ts +50 -0
  192. package/api/tests/bootstrap/bootstrap.spec.ts +162 -0
  193. package/api/tests/crons/tenant-fanout.spec.ts +158 -0
  194. package/api/tests/embedded/embedded-multi-mode-d3.spec.ts +257 -0
  195. package/api/tests/fixtures/bare-query-violation.ts +13 -0
  196. package/api/tests/fixtures/core-env-violation.ts +10 -0
  197. package/api/tests/fixtures/host-read-violation.ts +19 -0
  198. package/api/tests/fixtures/tenants.ts +4 -0
  199. package/api/tests/integrations/iap-tenant.spec.ts +284 -0
  200. package/api/tests/libs/archive-query.spec.ts +26 -0
  201. package/api/tests/libs/audit-tenant.spec.ts +153 -0
  202. package/api/tests/libs/context.spec.ts +204 -0
  203. package/api/tests/libs/core-config.spec.ts +115 -0
  204. package/api/tests/libs/cron-driver-d2.spec.ts +237 -0
  205. package/api/tests/libs/crons-conservation-d2.spec.ts +52 -0
  206. package/api/tests/libs/did-connect-runtime-js.spec.ts +98 -0
  207. package/api/tests/libs/did-connect-tenant-identity.spec.ts +159 -0
  208. package/api/tests/libs/lock-tenant.spec.ts +66 -0
  209. package/api/tests/libs/scoped.spec.ts +222 -0
  210. package/api/tests/libs/secrets-facade.spec.ts +52 -0
  211. package/api/tests/libs/service-host.spec.ts +37 -0
  212. package/api/tests/libs/tenancy-slot-authority.spec.ts +209 -0
  213. package/api/tests/libs/tenant-middleware.spec.ts +42 -0
  214. package/api/tests/libs/tenant-scanner.spec.ts +120 -0
  215. package/api/tests/middlewares/hono/cdn.spec.ts +70 -0
  216. package/api/tests/middlewares/hono/context.spec.ts +113 -0
  217. package/api/tests/middlewares/hono/csrf.spec.ts +136 -0
  218. package/api/tests/middlewares/hono/fallback.spec.ts +67 -0
  219. package/api/tests/middlewares/hono/pipeline.spec.ts +47 -0
  220. package/api/tests/middlewares/hono/security.spec.ts +181 -0
  221. package/api/tests/middlewares/hono/session.spec.ts +42 -0
  222. package/api/tests/middlewares/hono/xss.spec.ts +81 -0
  223. package/api/tests/models/tenant-backfill.spec.ts +287 -0
  224. package/api/tests/models/tenant-columns-model.spec.ts +46 -0
  225. package/api/tests/models/tenant-columns.spec.ts +161 -0
  226. package/api/tests/queues/credit-consume-batch.spec.ts +8 -1
  227. package/api/tests/queues/credit-consume.spec.ts +8 -1
  228. package/api/tests/queues/event-tenant.spec.ts +292 -0
  229. package/api/tests/queues/exchange-rate-health-tenant-d6.spec.ts +62 -0
  230. package/api/tests/queues/queue-parity.spec.ts +249 -0
  231. package/api/tests/queues/queue-runtime-surface.spec.ts +277 -0
  232. package/api/tests/queues/queue-teardown-d2.spec.ts +127 -0
  233. package/api/tests/queues/tenant-matrix-a.spec.ts +245 -0
  234. package/api/tests/queues/tenant-matrix-b.spec.ts +168 -0
  235. package/api/tests/routes/connect/hono-attach.spec.ts +107 -0
  236. package/api/tests/service/collapse.spec.ts +96 -0
  237. package/api/tests/service/didconnect-storage-slot.spec.ts +60 -0
  238. package/api/tests/service/fail-closed-http.spec.ts +79 -0
  239. package/api/tests/service/static-arc-handler.spec.ts +101 -0
  240. package/api/tests/service/static-externalized.spec.ts +48 -0
  241. package/api/tests/store/tenant-crosscut.spec.ts +202 -0
  242. package/api/tests/store/tenant-model-spike.spec.ts +177 -0
  243. package/api/tests/store/tenant-model.spec.ts +162 -0
  244. package/api/tests/store/tenant-residual.spec.ts +196 -0
  245. package/api/third.d.ts +4 -0
  246. package/blocklet.yml +1 -1
  247. package/cloudflare/MIGRATION-RUNBOOK.md +3 -8
  248. package/cloudflare/README.md +34 -27
  249. package/cloudflare/STAGING-MIGRATION-GUIDE.md +3 -15
  250. package/cloudflare/build.ts +33 -13
  251. package/cloudflare/cf-adapter.ts +419 -0
  252. package/cloudflare/did-connect-runtime.ts +96 -0
  253. package/cloudflare/did-connect-token-storage.ts +151 -0
  254. package/cloudflare/esbuild-cf-config.cjs +407 -0
  255. package/cloudflare/migrations/0006_tenant_columns.sql +46 -0
  256. package/cloudflare/migrations/0007_tenant_backfill_indexes.sql +65 -0
  257. package/cloudflare/migrations/0008_schema_parity.sql +16 -0
  258. package/cloudflare/migrations/0009_remove_did_space_jobs.sql +5 -0
  259. package/cloudflare/queue-runtime-mode.ts +13 -0
  260. package/cloudflare/run-build.js +33 -403
  261. package/cloudflare/scripts/cf-package-import-probe.mjs +90 -0
  262. package/cloudflare/scripts/didconnect-mock-smoke.mjs +140 -0
  263. package/cloudflare/shims/blocklet-sdk/asset-host-transformer.ts +20 -0
  264. package/cloudflare/shims/blocklet-sdk/config.ts +8 -1
  265. package/cloudflare/shims/blocklet-sdk/login.ts +12 -0
  266. package/cloudflare/shims/blocklet-sdk/service-api.ts +14 -0
  267. package/cloudflare/shims/blocklet-sdk/session.ts +4 -2
  268. package/cloudflare/shims/blocklet-sdk/util-constants.ts +8 -0
  269. package/cloudflare/shims/blocklet-sdk/wallet-authenticator.ts +16 -1
  270. package/cloudflare/shims/blocklet-sdk/wallet-handler.ts +18 -3
  271. package/cloudflare/shims/cron.ts +38 -158
  272. package/cloudflare/shims/events.ts +124 -0
  273. package/cloudflare/shims/fastq.ts +15 -1
  274. package/cloudflare/shims/nedb-storage.ts +16 -8
  275. package/cloudflare/shims/xss.ts +8 -0
  276. package/cloudflare/tenant-middleware.ts +36 -0
  277. package/cloudflare/tests/cf-adapter.spec.ts +244 -0
  278. package/cloudflare/tests/did-connect-token-storage.spec.ts +105 -0
  279. package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
  280. package/cloudflare/tests/worker-handler-gate.spec.ts +69 -0
  281. package/cloudflare/vite.config.ts +53 -45
  282. package/cloudflare/worker.ts +261 -448
  283. package/cloudflare/wrangler.json +0 -6
  284. package/cloudflare/wrangler.jsonc +0 -6
  285. package/cloudflare/wrangler.local-e2e.jsonc +25 -0
  286. package/cloudflare/wrangler.staging.json +0 -6
  287. package/jest.config.js +3 -1
  288. package/package.json +33 -38
  289. package/scripts/bootstrap-inject.ts +166 -0
  290. package/scripts/core-env-whitelist.json +1 -0
  291. package/scripts/e2e-12b-runtime.ts +149 -0
  292. package/scripts/e2e-core-config.ts +125 -0
  293. package/scripts/e2e-d1-tenancy.ts +116 -0
  294. package/scripts/e2e-d2-cron-queue.ts +139 -0
  295. package/scripts/e2e-d3-embedded-multi.ts +171 -0
  296. package/scripts/e2e-hono-s2.ts +125 -0
  297. package/scripts/e2e-hono-s3e.ts +135 -0
  298. package/scripts/e2e-hono-s4.ts +114 -0
  299. package/scripts/e2e-migration-contract.ts +100 -0
  300. package/scripts/e2e-s0.ts +61 -0
  301. package/scripts/e2e-s1.ts +107 -0
  302. package/scripts/e2e-s2.ts +178 -0
  303. package/scripts/e2e-s3.ts +110 -0
  304. package/scripts/e2e-s4.ts +191 -0
  305. package/scripts/e2e-s5.ts +139 -0
  306. package/scripts/e2e-s6.ts +127 -0
  307. package/scripts/e2e-tenant-model.ts +119 -0
  308. package/scripts/e2e-tenant-worker.ts +199 -0
  309. package/scripts/gen-sql-migrations.js +46 -0
  310. package/scripts/phase8-codemod.js +219 -0
  311. package/scripts/phase9a-env-getters-codemod.js +82 -0
  312. package/scripts/scan-core-env.js +109 -0
  313. package/scripts/scan-tenant-queries.js +235 -0
  314. package/scripts/schema-drift-guard.ts +210 -0
  315. package/scripts/tenant-scan-whitelist.json +1 -0
  316. package/src/app.tsx +2 -1
  317. package/src/env.d.ts +13 -1
  318. package/src/libs/service-host.ts +13 -0
  319. package/tsconfig.json +1 -1
  320. package/vite.arc.config.ts +159 -0
  321. package/api/src/libs/did-space.ts +0 -235
  322. package/api/src/libs/middleware.ts +0 -50
  323. package/api/src/libs/security.ts +0 -192
  324. package/api/src/queues/space.ts +0 -662
  325. package/api/src/routes/credit-tokens.ts +0 -38
  326. package/api/src/routes/exchange-rates.ts +0 -87
  327. package/api/src/routes/index.ts +0 -142
  328. package/api/src/routes/integrations/stripe.ts +0 -61
  329. package/api/src/routes/meters.ts +0 -274
  330. package/api/src/routes/passports.ts +0 -68
  331. package/api/src/routes/redirect.ts +0 -20
  332. package/api/src/routes/tool.ts +0 -65
  333. package/api/src/routes/webhook-endpoints.ts +0 -126
  334. package/api/tests/routes/credit-grants.spec.ts +0 -1261
  335. package/cloudflare/did-connect-auth.ts +0 -527
  336. package/cloudflare/shims/did-space-js.ts +0 -17
  337. package/cloudflare/shims/did-space.ts +0 -11
  338. package/cloudflare/shims/express-compat/index.ts +0 -80
  339. package/cloudflare/shims/express-compat/types.ts +0 -41
  340. package/cloudflare/shims/lock.ts +0 -115
  341. package/cloudflare/shims/queue.ts +0 -611
  342. package/cloudflare/tests/shims/queue-delayed-persist.spec.ts +0 -87
  343. package/cloudflare/tests/shims/queue-scheduled.spec.ts +0 -186
@@ -1,18 +1,24 @@
1
- import { Router } from 'express';
1
+ // Phase 3 (express→hono) hono fork of routes/meter-events.ts. Sub-app with
2
+ // routes relative to /api/meter-events (mounted via mountResourceGroup). The
3
+ // business logic is unchanged; only the express plumbing becomes hono:
4
+ // req.body → c.get('sanitizedBody') ?? {}; res.status(n).json(x) → c.json(x, n).
5
+ // req.(c.get('customer_id') ?? query.customer_id) → (c.get('customer_id') ?? c.req.query('customer_id')) [SECURITY].
6
+ import { Hono } from 'hono';
2
7
  import Joi from 'joi';
3
8
  import { Op, QueryTypes, Sequelize } from 'sequelize';
4
9
 
5
10
  import { fromTokenToUnit } from '@ocap/util';
6
- import { createListParamSchema, getOrder, getWhereFromKvQuery, MetadataSchema } from '../libs/api';
7
- import logger from '../libs/logger';
8
- import { authenticate } from '../libs/security';
9
- import { formatMetadata } from '../libs/util';
10
- import { trimDecimals } from '../libs/math-utils';
11
- import { Customer, Meter, MeterEvent, MeterEventStatus, PaymentCurrency, Subscription } from '../store/models';
11
+ import { createListParamSchema, getOrder, getWhereFromKvQuery, MetadataSchema } from '../../libs/api';
12
+ import { getInstanceDid } from '../../libs/context';
13
+ import logger from '../../libs/logger';
14
+ import { authenticate } from '../../middlewares/hono/security';
15
+ import { formatMetadata } from '../../libs/util';
16
+ import { trimDecimals } from '../../libs/math-utils';
17
+ import { Customer, Meter, MeterEvent, MeterEventStatus, PaymentCurrency, Subscription } from '../../store/models';
12
18
 
13
- import { getCachedMeter, getCachedCurrency } from '../libs/reference-cache';
19
+ import { getCachedMeter, getCachedCurrency } from '../../libs/reference-cache';
14
20
 
15
- const router = Router();
21
+ const app = new Hono();
16
22
  const auth = authenticate<MeterEvent>({ component: true, roles: ['owner', 'admin'] });
17
23
  const authMine = authenticate<MeterEvent>({ component: true, roles: ['owner', 'admin'], mine: true });
18
24
 
@@ -79,9 +85,9 @@ const statsSchema = Joi.object({
79
85
  granularity: Joi.string().valid('minute', 'hour', 'day').default('day'),
80
86
  });
81
87
 
82
- router.get('/', authMine, async (req, res) => {
88
+ app.get('/', authMine, async (c) => {
83
89
  try {
84
- const { page, pageSize, ...query } = await listSchema.validateAsync(req.query, { stripUnknown: true });
90
+ const { page, pageSize, ...query } = await listSchema.validateAsync(c.req.query(), { stripUnknown: true });
85
91
  const where = getWhereFromKvQuery(query.q);
86
92
 
87
93
  if (typeof query.livemode === 'boolean') {
@@ -98,10 +104,13 @@ router.get('/', authMine, async (req, res) => {
98
104
  }
99
105
  }
100
106
 
101
- if (query.customer_id) {
107
+ if (c.get('customer_id') ?? query.customer_id) {
102
108
  where[Op.and] = where[Op.and] || [];
103
109
  where[Op.and].push(
104
- Sequelize.where(Sequelize.literal("json_extract(payload, '$.customer_id')"), query.customer_id)
110
+ Sequelize.where(
111
+ Sequelize.literal("json_extract(payload, '$.customer_id')"),
112
+ c.get('customer_id') ?? query.customer_id
113
+ )
105
114
  );
106
115
  }
107
116
 
@@ -130,20 +139,20 @@ router.get('/', authMine, async (req, res) => {
130
139
  offset: (page - 1) * pageSize,
131
140
  limit: pageSize,
132
141
  });
133
- const expanded = await MeterEvent.expand(list, !!req.livemode, {
142
+ const expanded = await MeterEvent.expand(list, !!c.get('livemode'), {
134
143
  customer: true,
135
144
  subscription: true,
136
145
  meter: !!query.meter_id,
137
146
  });
138
147
 
139
- res.json({ count, list: expanded, paging: { page, pageSize } });
148
+ return c.json({ count, list: expanded, paging: { page, pageSize } });
140
149
  } catch (err) {
141
150
  logger.error('Error listing meter events', err);
142
- res.status(400).json({ error: err?.message });
151
+ return c.json({ error: (err as any)?.message }, 400);
143
152
  }
144
153
  });
145
154
 
146
- router.get('/stats', authMine, async (req, res) => {
155
+ app.get('/stats', authMine, async (c) => {
147
156
  try {
148
157
  const {
149
158
  meter_id: meterId,
@@ -151,11 +160,11 @@ router.get('/stats', authMine, async (req, res) => {
151
160
  end,
152
161
  customer_id: customerId,
153
162
  granularity,
154
- } = await statsSchema.validateAsync(req.query, { stripUnknown: true });
163
+ } = await statsSchema.validateAsync(c.req.query(), { stripUnknown: true });
155
164
 
156
165
  const meter = await Meter.findByPk(meterId);
157
166
  if (!meter) {
158
- return res.status(404).json({ error: 'Meter not found' });
167
+ return c.json({ error: 'Meter not found' }, 404);
159
168
  }
160
169
 
161
170
  const startDate = new Date(start * 1000);
@@ -177,11 +186,14 @@ router.get('/stats', authMine, async (req, res) => {
177
186
  }
178
187
 
179
188
  // 构建查询条件
189
+ // 洞 G (Phase 4): raw stats read on meter_events (tenant table) — guard with
190
+ // instance_did so a tenant only ever aggregates its own events.
180
191
  let whereClause =
181
- 'event_name = :eventName AND livemode = :livemode AND created_at >= :startDate AND created_at <= :endDate';
192
+ 'event_name = :eventName AND livemode = :livemode AND instance_did = :instance_did AND created_at >= :startDate AND created_at <= :endDate';
182
193
  const replacements: any = {
183
194
  eventName: meter.event_name,
184
- livemode: !!req.livemode,
195
+ livemode: !!c.get('livemode'),
196
+ instance_did: getInstanceDid(),
185
197
  startDate: startDate.toISOString(),
186
198
  endDate: endDate.toISOString(),
187
199
  };
@@ -192,12 +204,12 @@ router.get('/stats', authMine, async (req, res) => {
192
204
  }
193
205
 
194
206
  const statsQuery = `
195
- SELECT
207
+ SELECT
196
208
  ${dateFormat} as date,
197
209
  ${dateFormat} as timestamp,
198
210
  COUNT(*) as event_count,
199
211
  COALESCE(SUM(CAST(payload->>'value' AS DECIMAL)), 0) as total_value
200
- FROM meter_events
212
+ FROM meter_events
201
213
  WHERE ${whereClause}
202
214
  GROUP BY ${groupBy}
203
215
  ORDER BY ${groupBy}
@@ -205,7 +217,7 @@ router.get('/stats', authMine, async (req, res) => {
205
217
 
206
218
  const { sequelize } = MeterEvent;
207
219
  if (!sequelize) {
208
- return res.status(500).json({ error: 'Database connection not available' });
220
+ return c.json({ error: 'Database connection not available' }, 500);
209
221
  }
210
222
 
211
223
  const stats = await sequelize.query(statsQuery, {
@@ -213,7 +225,7 @@ router.get('/stats', authMine, async (req, res) => {
213
225
  type: QueryTypes.SELECT,
214
226
  });
215
227
 
216
- return res.json({
228
+ return c.json({
217
229
  count: stats.length,
218
230
  list: stats.map((item: any) => ({
219
231
  ...item,
@@ -222,98 +234,93 @@ router.get('/stats', authMine, async (req, res) => {
222
234
  });
223
235
  } catch (err) {
224
236
  logger.error('Error getting meter event stats', err);
225
- return res.status(400).json({ error: err?.message });
237
+ return c.json({ error: (err as any)?.message }, 400);
226
238
  }
227
239
  });
228
240
 
229
- router.post('/', auth, async (req, res) => {
241
+ app.post('/', auth, async (c) => {
230
242
  const t0 = performance.now();
231
243
  try {
232
- const { error } = meterEventSchema.validate(req.body);
244
+ const body = c.get('sanitizedBody') ?? {};
245
+ const { error } = meterEventSchema.validate(body);
233
246
  if (error) {
234
- return res.status(400).json({ error: `Meter event create request invalid: ${error.message}` });
247
+ return c.json({ error: `Meter event create request invalid: ${error.message}` }, 400);
235
248
  }
236
249
 
237
250
  // Phase 1: dedupe + meter + customer lookups in parallel (all independent)
238
251
  let t1 = performance.now();
239
252
  const [existing, meter, customer] = await Promise.all([
240
- MeterEvent.isEventExists(req.body.identifier),
241
- getCachedMeter(req.body.event_name),
242
- Customer.findByPkOrDid(req.body.payload.customer_id),
253
+ MeterEvent.isEventExists(body.identifier),
254
+ getCachedMeter(body.event_name),
255
+ Customer.findByPkOrDid(body.payload.customer_id),
243
256
  ]);
244
257
  const tPhase1 = performance.now() - t1;
245
258
 
246
259
  if (existing) {
247
- return res.status(400).json({ error: `Event with identifier "${req.body.identifier}" already exists` });
260
+ return c.json({ error: `Event with identifier "${body.identifier}" already exists` }, 400);
248
261
  }
249
262
  if (!meter) {
250
- return res
251
- .status(400)
252
- .json({ error: `Meter not found for event name "${req.body.event_name}"`, code: 'METER_NOT_FOUND' });
263
+ return c.json({ error: `Meter not found for event name "${body.event_name}"`, code: 'METER_NOT_FOUND' }, 400);
253
264
  }
254
265
  if (meter.status !== 'active') {
255
- return res
256
- .status(400)
257
- .json({ error: 'Meter is not active, please activate it first.', code: 'METER_NOT_ACTIVE' });
266
+ return c.json({ error: 'Meter is not active, please activate it first.', code: 'METER_NOT_ACTIVE' }, 400);
258
267
  }
259
268
  if (!customer) {
260
- return res.status(400).json({ error: 'Customer not found' });
269
+ return c.json({ error: 'Customer not found' }, 400);
261
270
  }
262
271
 
263
272
  // Phase 2: currency + subscription in parallel (currency depends on meter)
264
273
  t1 = performance.now();
265
274
  const [paymentCurrency, subscription] = await Promise.all([
266
275
  getCachedCurrency(meter.currency_id),
267
- req.body.payload.subscription_id
268
- ? Subscription.findByPk(req.body.payload.subscription_id)
269
- : Promise.resolve(null),
276
+ body.payload.subscription_id ? Subscription.findByPk(body.payload.subscription_id) : Promise.resolve(null),
270
277
  ]);
271
278
  const tPhase2 = performance.now() - t1;
272
279
 
273
280
  if (!paymentCurrency) {
274
- return res.status(400).json({ error: `Payment currency not found for meter "${meter.id}"` });
281
+ return c.json({ error: `Payment currency not found for meter "${meter.id}"` }, 400);
275
282
  }
276
283
 
277
284
  if (subscription) {
278
285
  if (subscription.currency_id !== paymentCurrency.id) {
279
- return res.status(400).json({ error: 'Subscription currency does not match meter currency' });
286
+ return c.json({ error: 'Subscription currency does not match meter currency' }, 400);
280
287
  }
281
288
  if (!subscription.isConsumesCredit()) {
282
- return res.status(400).json({ error: 'Subscription does not consume credit' });
289
+ return c.json({ error: 'Subscription does not consume credit' }, 400);
283
290
  }
284
- if (subscription.customer_id !== req.body.payload.customer_id) {
285
- return res.status(400).json({ error: 'This is not your subscription' });
291
+ if (subscription.customer_id !== body.payload.customer_id) {
292
+ return c.json({ error: 'This is not your subscription' }, 400);
286
293
  }
287
294
  if (subscription.isImmutable()) {
288
- return res.status(400).json({ error: 'Subscription is immutable' });
295
+ return c.json({ error: 'Subscription is immutable' }, 400);
289
296
  }
290
- } else if (req.body.payload.subscription_id) {
291
- return res.status(400).json({ error: `Subscription not found for meter event "${req.body.event_name}"` });
297
+ } else if (body.payload.subscription_id) {
298
+ return c.json({ error: `Subscription not found for meter event "${body.event_name}"` }, 400);
292
299
  }
293
300
 
294
- const timestamp = req.body.timestamp || req.body.payload.timestamp || Math.floor(Date.now() / 1000);
301
+ const timestamp = body.timestamp || body.payload.timestamp || Math.floor(Date.now() / 1000);
295
302
 
296
- const value = trimDecimals(req.body.payload.value, paymentCurrency.decimal);
303
+ const value = trimDecimals(body.payload.value, paymentCurrency.decimal);
297
304
  const eventData = {
298
- event_name: req.body.event_name,
305
+ event_name: body.event_name,
299
306
  payload: {
300
307
  customer_id: customer.id,
301
308
  currency_id: paymentCurrency.id,
302
309
  decimal: paymentCurrency.decimal,
303
310
  unit: paymentCurrency.name,
304
- subscription_id: req.body.payload.subscription_id,
311
+ subscription_id: body.payload.subscription_id,
305
312
  value: fromTokenToUnit(value, paymentCurrency.decimal).toString(),
306
313
  },
307
- identifier: req.body.identifier,
314
+ identifier: body.identifier,
308
315
  livemode: meter.livemode,
309
316
  processed: false,
310
317
  status: 'pending' as MeterEventStatus,
311
318
  attempt_count: 0,
312
319
  credit_consumed: '0',
313
320
  credit_pending: fromTokenToUnit(value, paymentCurrency.decimal).toString(),
314
- created_via: req.user?.via || 'api',
315
- metadata: formatMetadata(req.body.metadata),
316
- source_data: req.body.source_data,
321
+ created_via: c.get('user')?.via || 'api',
322
+ metadata: formatMetadata(body.metadata),
323
+ source_data: body.source_data,
317
324
  timestamp,
318
325
  };
319
326
 
@@ -335,9 +342,9 @@ router.post('/', auth, async (req, res) => {
335
342
  `create;dur=${tCreate.toFixed(1)}`,
336
343
  `total;dur=${tTotal.toFixed(1)}`,
337
344
  ];
338
- res.set('Server-Timing', timings.join(', '));
345
+ c.header('Server-Timing', timings.join(', '));
339
346
 
340
- return res.json({
347
+ return c.json({
341
348
  ...event.toJSON(),
342
349
  processing: {
343
350
  queued: true,
@@ -345,42 +352,43 @@ router.post('/', auth, async (req, res) => {
345
352
  },
346
353
  });
347
354
  } catch (err) {
348
- logger.error('create meter event failed', { error: err?.message, request: req.body });
349
- return res.status(400).json({ error: err?.message });
355
+ logger.error('create meter event failed', { error: (err as any)?.message, request: c.get('sanitizedBody') ?? {} });
356
+ return c.json({ error: (err as any)?.message }, 400);
350
357
  }
351
358
  });
352
359
 
353
- router.get('/pending-amount', authMine, async (req, res) => {
360
+ app.get('/pending-amount', authMine, async (c) => {
354
361
  try {
355
362
  const params: any = {
356
- livemode: !!req.livemode,
363
+ livemode: !!c.get('livemode'),
357
364
  };
358
- if (req.query.subscription_id) {
359
- params.subscriptionId = req.query.subscription_id;
365
+ if (c.req.query('subscription_id')) {
366
+ params.subscriptionId = c.req.query('subscription_id');
360
367
  }
361
- if (req.query.currency_id) {
362
- params.currencyId = req.query.currency_id;
368
+ if (c.req.query('currency_id')) {
369
+ params.currencyId = c.req.query('currency_id');
363
370
  }
364
- if (req.query.customer_id) {
365
- if (typeof req.query.customer_id !== 'string') {
366
- return res.status(400).json({ error: 'Customer ID must be a string' });
371
+ const rawCustomerId = c.get('customer_id') ?? c.req.query('customer_id');
372
+ if (rawCustomerId) {
373
+ if (typeof rawCustomerId !== 'string') {
374
+ return c.json({ error: 'Customer ID must be a string' }, 400);
367
375
  }
368
- const customer = await Customer.findByPkOrDid(req.query.customer_id);
376
+ const customer = await Customer.findByPkOrDid(rawCustomerId);
369
377
  if (!customer) {
370
- return res.status(404).json({ error: 'Customer not found' });
378
+ return c.json({ error: 'Customer not found' }, 404);
371
379
  }
372
380
  params.customerId = customer.id;
373
381
  }
374
382
  const [summary] = await MeterEvent.getPendingAmounts(params);
375
- return res.json(summary);
383
+ return c.json(summary);
376
384
  } catch (err) {
377
385
  logger.error('Error getting meter event pending amount', err);
378
- return res.status(400).json({ error: err?.message });
386
+ return c.json({ error: (err as any)?.message }, 400);
379
387
  }
380
388
  });
381
389
 
382
390
  // Get overdue summary by credit currency (action-required amounts grouped by currency)
383
- router.get('/overdue-summary', auth, async (req, res) => {
391
+ app.get('/overdue-summary', auth, async (c) => {
384
392
  try {
385
393
  // Query to aggregate credit_pending by currency, showing overdue amounts per credit currency
386
394
  const results = await MeterEvent.sequelize!.query<{
@@ -389,21 +397,21 @@ router.get('/overdue-summary', auth, async (req, res) => {
389
397
  customer_count: number;
390
398
  event_count: number;
391
399
  }>(
392
- `SELECT
400
+ `SELECT
393
401
  m.currency_id,
394
402
  SUM(CAST(me.credit_pending AS DECIMAL(40,0))) as total_pending,
395
403
  COUNT(DISTINCT json_extract(me.payload, '$.customer_id')) as customer_count,
396
404
  COUNT(*) as event_count
397
405
  FROM meter_events me
398
406
  JOIN meters m ON me.event_name = m.event_name
399
- WHERE me.livemode = :livemode
407
+ WHERE me.livemode = :livemode
400
408
  AND me.status IN ('requires_capture', 'requires_action')
401
409
  AND m.status = 'active'
402
410
  GROUP BY m.currency_id
403
411
  HAVING total_pending > 0
404
412
  ORDER BY total_pending DESC`,
405
413
  {
406
- replacements: { livemode: req.livemode ? 1 : 0 },
414
+ replacements: { livemode: c.get('livemode') ? 1 : 0 },
407
415
  type: QueryTypes.SELECT,
408
416
  }
409
417
  );
@@ -412,7 +420,7 @@ router.get('/overdue-summary', auth, async (req, res) => {
412
420
  const currencyIds = results.map((r) => r.currency_id);
413
421
  const currencies =
414
422
  currencyIds.length > 0 ? await PaymentCurrency.findAll({ where: { id: { [Op.in]: currencyIds } } }) : [];
415
- const currencyMap = new Map(currencies.map((c) => [c.id, c]));
423
+ const currencyMap = new Map(currencies.map((cur) => [cur.id, cur]));
416
424
 
417
425
  // Filter out results whose currency no longer exists (e.g. deleted currency)
418
426
  const list = results
@@ -431,26 +439,26 @@ router.get('/overdue-summary', auth, async (req, res) => {
431
439
  })
432
440
  .filter((item): item is NonNullable<typeof item> => item !== null);
433
441
 
434
- return res.json({ list });
442
+ return c.json({ list });
435
443
  } catch (err) {
436
444
  logger.error('Error getting overdue summary', err);
437
- return res.status(400).json({ error: err?.message });
445
+ return c.json({ error: (err as any)?.message }, 400);
438
446
  }
439
447
  });
440
448
 
441
449
  // Get all customers with credit overdue (action-required amount > 0), grouped by customer + currency
442
- router.get('/overdue-customers', auth, async (req, res) => {
450
+ app.get('/overdue-customers', auth, async (c) => {
443
451
  try {
444
- const page = Math.max(1, parseInt(String(req.query.page || '1'), 10));
445
- const pageSize = Math.min(100, Math.max(1, parseInt(String(req.query.pageSize || '20'), 10)));
452
+ const page = Math.max(1, parseInt(String(c.req.query('page') || '1'), 10));
453
+ const pageSize = Math.min(100, Math.max(1, parseInt(String(c.req.query('pageSize') || '20'), 10)));
446
454
  const offset = (page - 1) * pageSize;
447
- const currencyId = req.query.currency_id as string | undefined;
448
- const searchQuery = req.query.q as string | undefined;
455
+ const currencyId = c.req.query('currency_id') as string | undefined;
456
+ const searchQuery = c.req.query('q') as string | undefined;
449
457
 
450
458
  // If search query provided, first find matching customer IDs
451
459
  let customerFilter = '';
452
- const replacements: any = { livemode: req.livemode ? 1 : 0, limit: pageSize, offset };
453
- const countReplacements: any = { livemode: req.livemode ? 1 : 0 };
460
+ const replacements: any = { livemode: c.get('livemode') ? 1 : 0, limit: pageSize, offset };
461
+ const countReplacements: any = { livemode: c.get('livemode') ? 1 : 0 };
454
462
 
455
463
  // Build currency filter
456
464
  let currencyFilter = '';
@@ -473,9 +481,9 @@ router.get('/overdue-customers', auth, async (req, res) => {
473
481
  },
474
482
  attributes: ['id'],
475
483
  });
476
- const searchCustomerIds = searchCustomers.map((c) => c.id);
484
+ const searchCustomerIds = searchCustomers.map((cust) => cust.id);
477
485
  if (searchCustomerIds.length === 0) {
478
- return res.json({ list: [], count: 0, paging: { page, pageSize } });
486
+ return c.json({ list: [], count: 0, paging: { page, pageSize } });
479
487
  }
480
488
  // Generate parameterized placeholders for customer IDs
481
489
  const placeholders = searchCustomerIds.map((_, i) => `:searchId${i}`);
@@ -493,14 +501,14 @@ router.get('/overdue-customers', auth, async (req, res) => {
493
501
  total_pending: string;
494
502
  event_count: number;
495
503
  }>(
496
- `SELECT
504
+ `SELECT
497
505
  json_extract(me.payload, '$.customer_id') as customer_id,
498
506
  m.currency_id as currency_id,
499
507
  SUM(CAST(me.credit_pending AS DECIMAL(40,0))) as total_pending,
500
508
  COUNT(*) as event_count
501
509
  FROM meter_events me
502
510
  JOIN meters m ON me.event_name = m.event_name
503
- WHERE me.livemode = :livemode
511
+ WHERE me.livemode = :livemode
504
512
  AND me.status IN ('requires_capture', 'requires_action')
505
513
  AND m.status = 'active'
506
514
  ${currencyFilter}
@@ -521,7 +529,7 @@ router.get('/overdue-customers', auth, async (req, res) => {
521
529
  SELECT json_extract(me.payload, '$.customer_id') as customer_id, m.currency_id
522
530
  FROM meter_events me
523
531
  JOIN meters m ON me.event_name = m.event_name
524
- WHERE me.livemode = :livemode
532
+ WHERE me.livemode = :livemode
525
533
  AND me.status IN ('requires_capture', 'requires_action')
526
534
  AND m.status = 'active'
527
535
  ${currencyFilter}
@@ -541,11 +549,11 @@ router.get('/overdue-customers', auth, async (req, res) => {
541
549
 
542
550
  // Fetch customer and currency details
543
551
  const customers = customerIds.length > 0 ? await Customer.findAll({ where: { id: { [Op.in]: customerIds } } }) : [];
544
- const customerMap = new Map(customers.map((c) => [c.id, c]));
552
+ const customerMap = new Map(customers.map((cust) => [cust.id, cust]));
545
553
 
546
- const currencies =
554
+ const fetchedCurrencies =
547
555
  currencyIds.length > 0 ? await PaymentCurrency.findAll({ where: { id: { [Op.in]: currencyIds } } }) : [];
548
- const currencyMap = new Map(currencies.map((c) => [c.id, c]));
556
+ const currencyMap = new Map(fetchedCurrencies.map((cur) => [cur.id, cur]));
549
557
 
550
558
  const list = results.map((r) => ({
551
559
  customer: customerMap.get(r.customer_id),
@@ -554,19 +562,21 @@ router.get('/overdue-customers', auth, async (req, res) => {
554
562
  event_count: r.event_count,
555
563
  }));
556
564
 
557
- return res.json({ list, count, paging: { page, pageSize } });
565
+ return c.json({ list, count, paging: { page, pageSize } });
558
566
  } catch (err) {
559
567
  logger.error('Error getting overdue customers', err);
560
- return res.status(400).json({ error: err?.message });
568
+ return c.json({ error: (err as any)?.message }, 400);
561
569
  }
562
570
  });
563
- router.get('/:id', authMine, async (req, res) => {
571
+
572
+ app.get('/:id', authMine, async (c) => {
564
573
  try {
565
- logger.info('get meter event', { id: req.params.id });
566
- const event = await MeterEvent.findByPk(req.params.id);
574
+ const id = c.req.param('id');
575
+ logger.info('get meter event', { id });
576
+ const event = await MeterEvent.findByPk(id);
567
577
 
568
578
  if (!event) {
569
- return res.status(404).json({ error: 'Meter event not found' });
579
+ return c.json({ error: 'Meter event not found' }, 404);
570
580
  }
571
581
 
572
582
  const customerId = event.getCustomerId();
@@ -574,10 +584,10 @@ router.get('/:id', authMine, async (req, res) => {
574
584
  const subscription = subscriptionId ? await Subscription.findByPk(subscriptionId) : null;
575
585
  const customer = customerId ? await Customer.findByPk(customerId) : null;
576
586
  if (!customer) {
577
- return res.status(404).json({ error: 'Customer not found' });
587
+ return c.json({ error: 'Customer not found' }, 404);
578
588
  }
579
- if (customer.did !== req.user?.did && !['owner', 'admin'].includes(req.user?.role || '')) {
580
- return res.status(403).json({ error: 'You are not allowed to access this resource' });
589
+ if (customer.did !== c.get('user')?.did && !['owner', 'admin'].includes(c.get('user')?.role || '')) {
590
+ return c.json({ error: 'You are not allowed to access this resource' }, 403);
581
591
  }
582
592
  const meter = await Meter.getMeterByEventName(event.event_name);
583
593
  let paymentCurrency = null;
@@ -592,11 +602,11 @@ router.get('/:id', authMine, async (req, res) => {
592
602
  meter,
593
603
  paymentCurrency,
594
604
  };
595
- return res.json(result);
605
+ return c.json(result);
596
606
  } catch (err) {
597
607
  logger.error('Error getting meter event', err);
598
- return res.status(400).json({ error: err?.message });
608
+ return c.json({ error: (err as any)?.message }, 400);
599
609
  }
600
610
  });
601
611
 
602
- export default router;
612
+ export default app;