payment-kit 1.29.0 → 1.29.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/dev.ts +41 -2
- package/api/hono.d.ts +42 -0
- package/api/node-sqlite.d.ts +12 -0
- package/api/src/bootstrap.ts +36 -0
- package/api/src/crons/base.ts +3 -3
- package/api/src/crons/currency.ts +1 -1
- package/api/src/crons/index.ts +27 -24
- package/api/src/crons/metering-subscription-detection.ts +1 -1
- package/api/src/crons/overdue-detection.ts +2 -2
- package/api/src/crons/retry-pending-events.ts +6 -0
- package/api/src/index.ts +22 -161
- package/api/src/integrations/app-store/client.ts +3 -4
- package/api/src/integrations/app-store/handlers/subscription.ts +7 -7
- package/api/src/integrations/app-store/signed-data-verifier.ts +3 -2
- package/api/src/integrations/arcblock/token.ts +21 -7
- package/api/src/integrations/google-play/handlers/subscription.ts +6 -6
- package/api/src/integrations/google-play/handlers/voided.ts +2 -2
- package/api/src/integrations/google-play/verify.ts +3 -2
- package/api/src/integrations/iap-reconcile.ts +3 -5
- package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
- package/api/src/integrations/stripe/handlers/subscription.ts +3 -3
- package/api/src/libs/archive/query.ts +19 -0
- package/api/src/libs/audit.ts +61 -4
- package/api/src/libs/auth.ts +99 -38
- package/api/src/libs/context.ts +78 -1
- package/api/src/libs/currency.ts +2 -2
- package/api/src/libs/dayjs.ts +8 -2
- package/api/src/libs/drivers/auth-storage.ts +118 -0
- package/api/src/libs/drivers/cron.ts +264 -0
- package/api/src/libs/drivers/db.ts +170 -0
- package/api/src/libs/drivers/identity.ts +81 -0
- package/api/src/libs/drivers/index.ts +40 -0
- package/api/src/libs/drivers/locks.ts +226 -0
- package/api/src/libs/drivers/migrate-runner.ts +70 -0
- package/api/src/libs/drivers/queue.ts +104 -0
- package/api/src/libs/drivers/secrets.ts +194 -0
- package/api/src/libs/env.ts +170 -54
- package/api/src/libs/exchange-rate/service.ts +7 -6
- package/api/src/libs/http-fetch-adapter.ts +50 -0
- package/api/src/libs/invoice.ts +1 -1
- package/api/src/libs/lock.ts +51 -47
- package/api/src/libs/logger.ts +48 -8
- package/api/src/libs/notification/index.ts +1 -1
- package/api/src/libs/notification/template/customer-credit-low-balance.ts +2 -1
- package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -1
- package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -1
- package/api/src/libs/overdraft-protection.ts +1 -1
- package/api/src/libs/payout.ts +1 -1
- package/api/src/libs/queue/index.ts +259 -52
- package/api/src/libs/queue/runtime.ts +175 -0
- package/api/src/libs/resource.ts +3 -3
- package/api/src/libs/secrets.ts +38 -0
- package/api/src/libs/session.ts +3 -2
- package/api/src/libs/subscription.ts +5 -5
- package/api/src/libs/tenant.ts +92 -0
- package/api/src/libs/url.ts +3 -3
- package/api/src/libs/util.ts +21 -13
- package/api/src/middlewares/hono/cdn.ts +63 -0
- package/api/src/middlewares/hono/context.ts +73 -0
- package/api/src/middlewares/hono/csrf.ts +72 -0
- package/api/src/middlewares/hono/fallback.ts +194 -0
- package/api/src/middlewares/hono/pipeline.ts +73 -0
- package/api/src/middlewares/hono/resource-mount.ts +42 -0
- package/api/src/middlewares/hono/resource.ts +63 -0
- package/api/src/middlewares/hono/security.ts +214 -0
- package/api/src/middlewares/hono/session.ts +114 -0
- package/api/src/middlewares/hono/xss.ts +61 -0
- package/api/src/queues/auto-recharge.ts +12 -10
- package/api/src/queues/checkout-session.ts +17 -12
- package/api/src/queues/credit-consume.ts +40 -36
- package/api/src/queues/credit-grant.ts +25 -18
- package/api/src/queues/credit-reconciliation.ts +7 -5
- package/api/src/queues/discount-status.ts +9 -6
- package/api/src/queues/event.ts +12 -4
- package/api/src/queues/exchange-rate-health.ts +49 -30
- package/api/src/queues/invoice.ts +18 -15
- package/api/src/queues/notification.ts +14 -7
- package/api/src/queues/payment.ts +41 -28
- package/api/src/queues/payout.ts +9 -5
- package/api/src/queues/refund.ts +18 -12
- package/api/src/queues/subscription.ts +83 -53
- package/api/src/queues/token-transfer.ts +15 -10
- package/api/src/queues/usage-record.ts +8 -5
- package/api/src/queues/vendors/commission.ts +7 -5
- package/api/src/queues/vendors/fulfillment-coordinator.ts +17 -13
- package/api/src/queues/vendors/fulfillment.ts +4 -2
- package/api/src/queues/vendors/return-processor.ts +5 -3
- package/api/src/queues/vendors/return-scanner.ts +5 -4
- package/api/src/queues/vendors/status-check.ts +10 -7
- package/api/src/queues/webhook.ts +60 -32
- package/api/src/routes/connect/shared.ts +1 -2
- package/api/src/routes/connect/subscribe.ts +3 -3
- package/api/src/routes/{archive.ts → hono/archive.ts} +69 -64
- package/api/src/routes/{auto-recharge-configs.ts → hono/auto-recharge-configs.ts} +39 -28
- package/api/src/routes/{checkout-sessions.ts → hono/checkout-sessions.ts} +790 -923
- package/api/src/routes/{coupons.ts → hono/coupons.ts} +93 -76
- package/api/src/routes/{credit-grants.ts → hono/credit-grants.ts} +140 -126
- package/api/src/routes/hono/credit-tokens.ts +43 -0
- package/api/src/routes/{credit-transactions.ts → hono/credit-transactions.ts} +37 -29
- package/api/src/routes/{customers.ts → hono/customers.ts} +193 -223
- package/api/src/routes/{donations.ts → hono/donations.ts} +41 -32
- package/api/src/routes/{entitlements.ts → hono/entitlements.ts} +28 -25
- package/api/src/routes/{events.ts → hono/events.ts} +107 -71
- package/api/src/routes/{exchange-rate-providers.ts → hono/exchange-rate-providers.ts} +138 -126
- package/api/src/routes/hono/exchange-rates.ts +77 -0
- package/api/src/routes/hono/index.ts +115 -0
- package/api/src/routes/{integrations → hono/integrations}/app-store.ts +68 -48
- package/api/src/routes/{integrations → hono/integrations}/google-play.ts +78 -58
- package/api/src/routes/hono/integrations/stripe.ts +74 -0
- package/api/src/routes/{invoices.ts → hono/invoices.ts} +253 -244
- package/api/src/routes/{meter-events.ts → hono/meter-events.ts} +120 -110
- package/api/src/routes/hono/meters.ts +288 -0
- package/api/src/routes/hono/passports.ts +73 -0
- package/api/src/routes/{payment-currencies.ts → hono/payment-currencies.ts} +219 -197
- package/api/src/routes/{payment-intents.ts → hono/payment-intents.ts} +136 -132
- package/api/src/routes/{payment-links.ts → hono/payment-links.ts} +145 -128
- package/api/src/routes/{payment-methods.ts → hono/payment-methods.ts} +125 -93
- package/api/src/routes/{payment-stats.ts → hono/payment-stats.ts} +30 -25
- package/api/src/routes/{payouts.ts → hono/payouts.ts} +55 -47
- package/api/src/routes/{prices.ts → hono/prices.ts} +265 -242
- package/api/src/routes/{pricing-table.ts → hono/pricing-table.ts} +94 -87
- package/api/src/routes/{products.ts → hono/products.ts} +172 -159
- package/api/src/routes/{promotion-codes.ts → hono/promotion-codes.ts} +207 -185
- package/api/src/routes/hono/redirect.ts +24 -0
- package/api/src/routes/{refunds.ts → hono/refunds.ts} +96 -80
- package/api/src/routes/{settings.ts → hono/settings.ts} +64 -55
- package/api/src/routes/{subscription-items.ts → hono/subscription-items.ts} +64 -57
- package/api/src/routes/{subscriptions.ts → hono/subscriptions.ts} +475 -528
- package/api/src/routes/{tax-rates.ts → hono/tax-rates.ts} +71 -70
- package/api/src/routes/hono/tool.ts +69 -0
- package/api/src/routes/{usage-records.ts → hono/usage-records.ts} +47 -42
- package/api/src/routes/{vendor.ts → hono/vendor.ts} +315 -167
- package/api/src/routes/{webhook-attempts.ts → hono/webhook-attempts.ts} +17 -13
- package/api/src/routes/hono/webhook-endpoints.ts +126 -0
- package/api/src/service.ts +667 -0
- package/api/src/store/migrations/20230911-seeding.ts +2 -1
- package/api/src/store/migrations/20260609-remove-did-space-jobs.ts +23 -0
- package/api/src/store/migrations/20260610-tenant-columns.ts +40 -0
- package/api/src/store/migrations/20260611-tenant-backfill.ts +33 -0
- package/api/src/store/models/auto-recharge-config.ts +22 -10
- package/api/src/store/models/checkout-session.ts +15 -14
- package/api/src/store/models/coupon.ts +29 -20
- package/api/src/store/models/credit-grant.ts +38 -29
- package/api/src/store/models/credit-transaction.ts +32 -21
- package/api/src/store/models/customer.ts +19 -17
- package/api/src/store/models/discount.ts +11 -2
- package/api/src/store/models/entitlement-grant.ts +21 -9
- package/api/src/store/models/entitlement-product.ts +21 -9
- package/api/src/store/models/entitlement.ts +19 -10
- package/api/src/store/models/event.ts +18 -9
- package/api/src/store/models/exchange-rate-provider.ts +17 -4
- package/api/src/store/models/invoice-item.ts +18 -9
- package/api/src/store/models/invoice.ts +16 -8
- package/api/src/store/models/meter-event.ts +27 -9
- package/api/src/store/models/meter.ts +31 -22
- package/api/src/store/models/payment-currency.ts +25 -8
- package/api/src/store/models/payment-intent.ts +15 -6
- package/api/src/store/models/payment-link.ts +15 -6
- package/api/src/store/models/payment-method.ts +38 -22
- package/api/src/store/models/payment-stat.ts +18 -9
- package/api/src/store/models/payout.ts +15 -6
- package/api/src/store/models/price-quote.ts +17 -8
- package/api/src/store/models/price.ts +24 -12
- package/api/src/store/models/pricing-table.ts +29 -20
- package/api/src/store/models/product-vendor.ts +20 -10
- package/api/src/store/models/product.ts +15 -6
- package/api/src/store/models/promotion-code.ts +14 -6
- package/api/src/store/models/refund.ts +15 -6
- package/api/src/store/models/revenue-snapshot.ts +21 -9
- package/api/src/store/models/setting.ts +18 -9
- package/api/src/store/models/setup-intent.ts +36 -27
- package/api/src/store/models/subscription-item.ts +21 -9
- package/api/src/store/models/subscription-schedule.ts +21 -9
- package/api/src/store/models/subscription.ts +21 -10
- package/api/src/store/models/tax-rate.ts +29 -21
- package/api/src/store/models/usage-record.ts +11 -2
- package/api/src/store/models/webhook-attempt.ts +18 -9
- package/api/src/store/models/webhook-endpoint.ts +18 -9
- package/api/src/store/scoped-core.ts +55 -0
- package/api/src/store/scoped.ts +247 -0
- package/api/src/store/sequelize.ts +66 -22
- package/api/src/store/sql-migrations.ts +20 -0
- package/api/src/store/tenant-backfill.ts +260 -0
- package/api/src/store/tenant-model.ts +124 -0
- package/api/src/store/tenant-tables.ts +50 -0
- package/api/tests/embedded/embedded-multi-mode-d3.spec.ts +257 -0
- package/api/tests/fixtures/bare-query-violation.ts +13 -0
- package/api/tests/fixtures/core-env-violation.ts +10 -0
- package/api/tests/fixtures/host-read-violation.ts +19 -0
- package/api/tests/fixtures/tenants.ts +4 -0
- package/api/tests/integrations/iap-tenant.spec.ts +284 -0
- package/api/tests/libs/archive-query.spec.ts +26 -0
- package/api/tests/libs/audit-tenant.spec.ts +153 -0
- package/api/tests/libs/context.spec.ts +204 -0
- package/api/tests/libs/core-config.spec.ts +115 -0
- package/api/tests/libs/cron-driver-d2.spec.ts +237 -0
- package/api/tests/libs/crons-conservation-d2.spec.ts +52 -0
- package/api/tests/libs/lock-tenant.spec.ts +66 -0
- package/api/tests/libs/scoped.spec.ts +222 -0
- package/api/tests/libs/secrets-facade.spec.ts +52 -0
- package/api/tests/libs/tenancy-slot-authority.spec.ts +209 -0
- package/api/tests/libs/tenant-middleware.spec.ts +42 -0
- package/api/tests/libs/tenant-scanner.spec.ts +120 -0
- package/api/tests/middlewares/hono/cdn.spec.ts +70 -0
- package/api/tests/middlewares/hono/context.spec.ts +113 -0
- package/api/tests/middlewares/hono/csrf.spec.ts +136 -0
- package/api/tests/middlewares/hono/fallback.spec.ts +67 -0
- package/api/tests/middlewares/hono/pipeline.spec.ts +47 -0
- package/api/tests/middlewares/hono/security.spec.ts +181 -0
- package/api/tests/middlewares/hono/session.spec.ts +42 -0
- package/api/tests/middlewares/hono/xss.spec.ts +81 -0
- package/api/tests/models/tenant-backfill.spec.ts +287 -0
- package/api/tests/models/tenant-columns-model.spec.ts +46 -0
- package/api/tests/models/tenant-columns.spec.ts +161 -0
- package/api/tests/queues/credit-consume-batch.spec.ts +8 -1
- package/api/tests/queues/credit-consume.spec.ts +8 -1
- package/api/tests/queues/event-tenant.spec.ts +236 -0
- package/api/tests/queues/exchange-rate-health-tenant-d6.spec.ts +62 -0
- package/api/tests/queues/queue-parity.spec.ts +249 -0
- package/api/tests/queues/queue-runtime-surface.spec.ts +277 -0
- package/api/tests/queues/queue-teardown-d2.spec.ts +127 -0
- package/api/tests/queues/tenant-matrix-a.spec.ts +245 -0
- package/api/tests/queues/tenant-matrix-b.spec.ts +168 -0
- package/api/tests/routes/connect/hono-attach.spec.ts +107 -0
- package/api/tests/service/collapse.spec.ts +96 -0
- package/api/tests/store/tenant-crosscut.spec.ts +202 -0
- package/api/tests/store/tenant-model-spike.spec.ts +177 -0
- package/api/tests/store/tenant-model.spec.ts +162 -0
- package/api/tests/store/tenant-residual.spec.ts +196 -0
- package/api/third.d.ts +4 -0
- package/blocklet.yml +1 -1
- package/cloudflare/README.md +26 -6
- package/cloudflare/build.ts +28 -13
- package/cloudflare/did-connect-auth.ts +0 -217
- package/cloudflare/docs/2026-06-10-bundle-size-analysis.md +288 -0
- package/cloudflare/migrations/0006_tenant_columns.sql +46 -0
- package/cloudflare/migrations/0007_tenant_backfill_indexes.sql +65 -0
- package/cloudflare/migrations/0008_schema_parity.sql +16 -0
- package/cloudflare/migrations/0009_remove_did_space_jobs.sql +5 -0
- package/cloudflare/queue-runtime-mode.ts +13 -0
- package/cloudflare/run-build.js +31 -56
- package/cloudflare/shims/blocklet-sdk/asset-host-transformer.ts +20 -0
- package/cloudflare/shims/blocklet-sdk/config.ts +8 -1
- package/cloudflare/shims/blocklet-sdk/login.ts +12 -0
- package/cloudflare/shims/blocklet-sdk/service-api.ts +14 -0
- package/cloudflare/shims/blocklet-sdk/session.ts +4 -2
- package/cloudflare/shims/blocklet-sdk/util-constants.ts +8 -0
- package/cloudflare/shims/blocklet-sdk/util-csrf.ts +13 -0
- package/cloudflare/shims/blocklet-sdk/util-wallet.ts +8 -0
- package/cloudflare/shims/cron.ts +38 -158
- package/cloudflare/shims/events.ts +124 -0
- package/cloudflare/shims/fastq.ts +15 -1
- package/cloudflare/shims/nedb-storage.ts +16 -8
- package/cloudflare/shims/node-fetch.ts +35 -0
- package/cloudflare/shims/xss.ts +8 -0
- package/cloudflare/tenant-middleware.ts +36 -0
- package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
- package/cloudflare/tests/worker-handler-gate.spec.ts +44 -0
- package/cloudflare/worker.ts +204 -433
- package/cloudflare/wrangler.local-e2e.jsonc +26 -0
- package/jest.config.js +3 -1
- package/package.json +33 -38
- package/scripts/core-env-whitelist.json +1 -0
- package/scripts/e2e-12b-runtime.ts +149 -0
- package/scripts/e2e-core-config.ts +125 -0
- package/scripts/e2e-d1-tenancy.ts +116 -0
- package/scripts/e2e-d2-cron-queue.ts +139 -0
- package/scripts/e2e-d3-embedded-multi.ts +171 -0
- package/scripts/e2e-hono-s2.ts +125 -0
- package/scripts/e2e-hono-s3e.ts +135 -0
- package/scripts/e2e-hono-s4.ts +114 -0
- package/scripts/e2e-migration-contract.ts +100 -0
- package/scripts/e2e-s0.ts +61 -0
- package/scripts/e2e-s1.ts +107 -0
- package/scripts/e2e-s2.ts +178 -0
- package/scripts/e2e-s3.ts +110 -0
- package/scripts/e2e-s4.ts +191 -0
- package/scripts/e2e-s5.ts +139 -0
- package/scripts/e2e-s6.ts +127 -0
- package/scripts/e2e-tenant-model.ts +119 -0
- package/scripts/e2e-tenant-worker.ts +199 -0
- package/scripts/gen-sql-migrations.js +46 -0
- package/scripts/phase8-codemod.js +219 -0
- package/scripts/phase9a-env-getters-codemod.js +82 -0
- package/scripts/scan-core-env.js +109 -0
- package/scripts/scan-tenant-queries.js +235 -0
- package/scripts/schema-drift-guard.ts +210 -0
- package/scripts/tenant-scan-whitelist.json +1 -0
- package/src/env.d.ts +13 -1
- package/tsconfig.json +1 -1
- package/api/src/libs/did-space.ts +0 -235
- package/api/src/libs/middleware.ts +0 -50
- package/api/src/libs/security.ts +0 -192
- package/api/src/queues/space.ts +0 -662
- package/api/src/routes/credit-tokens.ts +0 -38
- package/api/src/routes/exchange-rates.ts +0 -87
- package/api/src/routes/index.ts +0 -142
- package/api/src/routes/integrations/stripe.ts +0 -61
- package/api/src/routes/meters.ts +0 -274
- package/api/src/routes/passports.ts +0 -68
- package/api/src/routes/redirect.ts +0 -20
- package/api/src/routes/tool.ts +0 -65
- package/api/src/routes/webhook-endpoints.ts +0 -126
- package/api/tests/routes/credit-grants.spec.ts +0 -1261
- package/cloudflare/shims/did-space-js.ts +0 -17
- package/cloudflare/shims/did-space.ts +0 -11
- package/cloudflare/shims/express-compat/index.ts +0 -80
- package/cloudflare/shims/express-compat/types.ts +0 -41
- package/cloudflare/shims/lock.ts +0 -115
- package/cloudflare/shims/queue.ts +0 -611
- package/cloudflare/tests/shims/queue-delayed-persist.spec.ts +0 -87
- package/cloudflare/tests/shims/queue-scheduled.spec.ts +0 -186
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
// Phase 3 (express→hono) — hono fork of routes/exchange-rate-providers.ts. Sub-app with
|
|
2
|
+
// routes relative to /api/exchange-rate-providers (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
|
+
import { Hono } from 'hono';
|
|
2
6
|
import pick from 'lodash/pick';
|
|
3
7
|
import { Op } from 'sequelize';
|
|
4
8
|
|
|
5
|
-
import { authenticate } from '
|
|
6
|
-
import { ExchangeRateProvider } from '
|
|
7
|
-
import { TokenDataProvider } from '
|
|
8
|
-
import { CoinGeckoProvider } from '
|
|
9
|
-
import { CoinMarketCapProvider } from '
|
|
9
|
+
import { authenticate } from '../../middlewares/hono/security';
|
|
10
|
+
import { ExchangeRateProvider } from '../../store/models/exchange-rate-provider';
|
|
11
|
+
import { TokenDataProvider } from '../../libs/exchange-rate/token-data-provider';
|
|
12
|
+
import { CoinGeckoProvider } from '../../libs/exchange-rate/coingecko-provider';
|
|
13
|
+
import { CoinMarketCapProvider } from '../../libs/exchange-rate/coinmarketcap-provider';
|
|
10
14
|
|
|
11
|
-
const
|
|
15
|
+
const app = new Hono();
|
|
12
16
|
const auth = authenticate({ component: true, roles: ['owner', 'admin'], ensureLogin: true });
|
|
13
17
|
const allowedStatuses = ['active', 'degraded', 'paused', 'inactive'];
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
app.get('/', auth, async (c) => {
|
|
16
20
|
const providers = await ExchangeRateProvider.findAll({
|
|
17
21
|
order: [
|
|
18
22
|
['priority', 'ASC'],
|
|
@@ -26,10 +30,10 @@ router.get('/', auth, async (_req, res) => {
|
|
|
26
30
|
config: ExchangeRateProvider.maskConfig(p.config),
|
|
27
31
|
}));
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
return c.json({ data: maskedProviders });
|
|
30
34
|
});
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
app.post('/', auth, async (c) => {
|
|
33
37
|
const {
|
|
34
38
|
name,
|
|
35
39
|
type = 'token-data',
|
|
@@ -39,18 +43,15 @@ router.post('/', auth, async (req, res) => {
|
|
|
39
43
|
config = {},
|
|
40
44
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
41
45
|
paused_reason = null,
|
|
42
|
-
} =
|
|
46
|
+
} = c.get('sanitizedBody') ?? {};
|
|
43
47
|
if (!name) {
|
|
44
|
-
|
|
45
|
-
return;
|
|
48
|
+
return c.json({ error: 'name is required' }, 400);
|
|
46
49
|
}
|
|
47
50
|
if (Number.isNaN(Number(priority))) {
|
|
48
|
-
|
|
49
|
-
return;
|
|
51
|
+
return c.json({ error: 'priority must be a number' }, 400);
|
|
50
52
|
}
|
|
51
53
|
if (!allowedStatuses.includes(status)) {
|
|
52
|
-
|
|
53
|
-
return;
|
|
54
|
+
return c.json({ error: 'invalid status' }, 400);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
const provider = await ExchangeRateProvider.create({
|
|
@@ -63,39 +64,7 @@ router.post('/', auth, async (req, res) => {
|
|
|
63
64
|
config: ExchangeRateProvider.encryptConfig(config),
|
|
64
65
|
});
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
router.put('/:id', auth, async (req, res) => {
|
|
70
|
-
const provider = await ExchangeRateProvider.findByPk(req.params.id);
|
|
71
|
-
if (!provider) {
|
|
72
|
-
res.status(404).json({ error: 'Provider not found' });
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Note: 'type' is intentionally excluded - cannot be changed after creation
|
|
77
|
-
const updates = pick(req.body, ['name', 'enabled', 'priority', 'status', 'paused_reason', 'config']);
|
|
78
|
-
if (updates.priority !== undefined && Number.isNaN(Number(updates.priority))) {
|
|
79
|
-
res.status(400).json({ error: 'priority must be a number' });
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (updates.status && !allowedStatuses.includes(updates.status)) {
|
|
83
|
-
res.status(400).json({ error: 'invalid status' });
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Encrypt config if it's being updated
|
|
88
|
-
if (updates.config) {
|
|
89
|
-
const existingConfig = ExchangeRateProvider.decryptConfig(provider.config) || {};
|
|
90
|
-
const mergedConfig = { ...existingConfig, ...updates.config };
|
|
91
|
-
if (updates.config.api_key === '') {
|
|
92
|
-
delete mergedConfig.api_key;
|
|
93
|
-
}
|
|
94
|
-
updates.config = ExchangeRateProvider.encryptConfig(mergedConfig);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await provider.update(updates);
|
|
98
|
-
res.json({ data: provider });
|
|
67
|
+
return c.json({ data: provider });
|
|
99
68
|
});
|
|
100
69
|
|
|
101
70
|
// TECHNICAL DEBT: Exchange rate provider management bypasses AFS layer
|
|
@@ -106,75 +75,18 @@ router.put('/:id', auth, async (req, res) => {
|
|
|
106
75
|
// Decision: Accepted as pragmatic completion of existing system (2026-01-12)
|
|
107
76
|
// Reference: ai/intent/20260112-token-data-provider-management-alignment.md
|
|
108
77
|
|
|
109
|
-
/**
|
|
110
|
-
* DELETE endpoint - Remove an exchange rate provider
|
|
111
|
-
* Safety constraints:
|
|
112
|
-
* 1. Cannot delete provider that is currently in use
|
|
113
|
-
* 2. Cannot delete the last enabled provider
|
|
114
|
-
*/
|
|
115
|
-
router.delete('/:id', auth, async (req, res) => {
|
|
116
|
-
const provider = await ExchangeRateProvider.findByPk(req.params.id);
|
|
117
|
-
if (!provider) {
|
|
118
|
-
res.status(404).json({ error: 'Provider not found' });
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Safety Check 1: Get active provider (same logic as frontend)
|
|
123
|
-
const allProviders = await ExchangeRateProvider.findAll({
|
|
124
|
-
order: [
|
|
125
|
-
['priority', 'ASC'],
|
|
126
|
-
['created_at', 'ASC'],
|
|
127
|
-
],
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const activeProviders = allProviders
|
|
131
|
-
.filter((p) => p.enabled && p.status !== 'paused')
|
|
132
|
-
.sort((a, b) => a.priority - b.priority);
|
|
133
|
-
|
|
134
|
-
const activeProviderId = activeProviders[0]?.id || null;
|
|
135
|
-
|
|
136
|
-
if (provider.id === activeProviderId) {
|
|
137
|
-
res.status(400).json({
|
|
138
|
-
error: 'Cannot delete provider that is currently in use',
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Safety Check 2: Ensure we're not deleting the last enabled provider
|
|
144
|
-
const otherEnabledCount = await ExchangeRateProvider.count({
|
|
145
|
-
where: {
|
|
146
|
-
id: { [Op.ne]: req.params.id },
|
|
147
|
-
enabled: true,
|
|
148
|
-
status: { [Op.ne]: 'paused' },
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
if (otherEnabledCount === 0 && provider.enabled && provider.status !== 'paused') {
|
|
153
|
-
res.status(400).json({
|
|
154
|
-
error:
|
|
155
|
-
'Cannot delete the last enabled provider. Please ensure at least one other provider is enabled before deleting this one.',
|
|
156
|
-
});
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// All checks passed, safe to delete
|
|
161
|
-
await provider.destroy();
|
|
162
|
-
|
|
163
|
-
res.json({ success: true });
|
|
164
|
-
});
|
|
165
|
-
|
|
166
78
|
/**
|
|
167
79
|
* POST /test-connection - Test provider connection without saving
|
|
168
80
|
* Validates provider configuration by attempting to fetch a test rate
|
|
81
|
+
* Registered before /:id routes so the static segment wins
|
|
169
82
|
*/
|
|
170
|
-
|
|
171
|
-
const { type, config = {}, provider_id: providerId } =
|
|
83
|
+
app.post('/test-connection', auth, async (c) => {
|
|
84
|
+
const { type, config = {}, provider_id: providerId } = c.get('sanitizedBody') ?? {};
|
|
172
85
|
|
|
173
86
|
// Validate provider type
|
|
174
87
|
const allowedTypes = ['token-data', 'coingecko', 'coinmarketcap'];
|
|
175
88
|
if (!type || !allowedTypes.includes(type)) {
|
|
176
|
-
|
|
177
|
-
return;
|
|
89
|
+
return c.json({ error: 'Invalid provider type' }, 400);
|
|
178
90
|
}
|
|
179
91
|
|
|
180
92
|
// Decrypt config if it contains encrypted api_key
|
|
@@ -209,15 +121,16 @@ router.post('/test-connection', auth, async (req, res) => {
|
|
|
209
121
|
provider = new CoinMarketCapProvider(effectiveConfig || undefined);
|
|
210
122
|
break;
|
|
211
123
|
default:
|
|
212
|
-
|
|
213
|
-
return;
|
|
124
|
+
return c.json({ error: 'Invalid provider type' }, 400);
|
|
214
125
|
}
|
|
215
126
|
} catch (error: any) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
127
|
+
return c.json(
|
|
128
|
+
{
|
|
129
|
+
success: false,
|
|
130
|
+
error: error.message || 'Failed to initialize provider',
|
|
131
|
+
},
|
|
132
|
+
200
|
|
133
|
+
);
|
|
221
134
|
}
|
|
222
135
|
|
|
223
136
|
const testSymbol = type === 'token-data' ? 'ABT' : 'ETH';
|
|
@@ -227,7 +140,7 @@ router.post('/test-connection', auth, async (req, res) => {
|
|
|
227
140
|
const result = await provider.fetch(testSymbol);
|
|
228
141
|
const responseTime = Date.now() - startTime;
|
|
229
142
|
|
|
230
|
-
|
|
143
|
+
return c.json({
|
|
231
144
|
success: true,
|
|
232
145
|
responseTime,
|
|
233
146
|
rate: result.rate,
|
|
@@ -236,13 +149,112 @@ router.post('/test-connection', auth, async (req, res) => {
|
|
|
236
149
|
});
|
|
237
150
|
} catch (error: any) {
|
|
238
151
|
const responseTime = Date.now() - startTime;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
152
|
+
return c.json(
|
|
153
|
+
{
|
|
154
|
+
success: false,
|
|
155
|
+
responseTime,
|
|
156
|
+
error: error.message || 'Connection test failed',
|
|
157
|
+
symbol: testSymbol,
|
|
158
|
+
},
|
|
159
|
+
200
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* DELETE endpoint - Remove an exchange rate provider
|
|
166
|
+
* Safety constraints:
|
|
167
|
+
* 1. Cannot delete provider that is currently in use
|
|
168
|
+
* 2. Cannot delete the last enabled provider
|
|
169
|
+
*/
|
|
170
|
+
app.put('/:id', auth, async (c) => {
|
|
171
|
+
const provider = await ExchangeRateProvider.findByPk(c.req.param('id'));
|
|
172
|
+
if (!provider) {
|
|
173
|
+
return c.json({ error: 'Provider not found' }, 404);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Note: 'type' is intentionally excluded - cannot be changed after creation
|
|
177
|
+
const updates = pick(c.get('sanitizedBody') ?? {}, [
|
|
178
|
+
'name',
|
|
179
|
+
'enabled',
|
|
180
|
+
'priority',
|
|
181
|
+
'status',
|
|
182
|
+
'paused_reason',
|
|
183
|
+
'config',
|
|
184
|
+
]);
|
|
185
|
+
if (updates.priority !== undefined && Number.isNaN(Number(updates.priority))) {
|
|
186
|
+
return c.json({ error: 'priority must be a number' }, 400);
|
|
245
187
|
}
|
|
188
|
+
if (updates.status && !allowedStatuses.includes(updates.status)) {
|
|
189
|
+
return c.json({ error: 'invalid status' }, 400);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Encrypt config if it's being updated
|
|
193
|
+
if (updates.config) {
|
|
194
|
+
const existingConfig = ExchangeRateProvider.decryptConfig(provider.config) || {};
|
|
195
|
+
const mergedConfig = { ...existingConfig, ...updates.config };
|
|
196
|
+
if (updates.config.api_key === '') {
|
|
197
|
+
delete mergedConfig.api_key;
|
|
198
|
+
}
|
|
199
|
+
updates.config = ExchangeRateProvider.encryptConfig(mergedConfig);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
await provider.update(updates);
|
|
203
|
+
return c.json({ data: provider });
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
app.delete('/:id', auth, async (c) => {
|
|
207
|
+
const provider = await ExchangeRateProvider.findByPk(c.req.param('id'));
|
|
208
|
+
if (!provider) {
|
|
209
|
+
return c.json({ error: 'Provider not found' }, 404);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Safety Check 1: Get active provider (same logic as frontend)
|
|
213
|
+
const allProviders = await ExchangeRateProvider.findAll({
|
|
214
|
+
order: [
|
|
215
|
+
['priority', 'ASC'],
|
|
216
|
+
['created_at', 'ASC'],
|
|
217
|
+
],
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const activeProviders = allProviders
|
|
221
|
+
.filter((p) => p.enabled && p.status !== 'paused')
|
|
222
|
+
.sort((a, b) => a.priority - b.priority);
|
|
223
|
+
|
|
224
|
+
const activeProviderId = activeProviders[0]?.id || null;
|
|
225
|
+
|
|
226
|
+
if (provider.id === activeProviderId) {
|
|
227
|
+
return c.json(
|
|
228
|
+
{
|
|
229
|
+
error: 'Cannot delete provider that is currently in use',
|
|
230
|
+
},
|
|
231
|
+
400
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Safety Check 2: Ensure we're not deleting the last enabled provider
|
|
236
|
+
const otherEnabledCount = await ExchangeRateProvider.count({
|
|
237
|
+
where: {
|
|
238
|
+
id: { [Op.ne]: c.req.param('id') },
|
|
239
|
+
enabled: true,
|
|
240
|
+
status: { [Op.ne]: 'paused' },
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
if (otherEnabledCount === 0 && provider.enabled && provider.status !== 'paused') {
|
|
245
|
+
return c.json(
|
|
246
|
+
{
|
|
247
|
+
error:
|
|
248
|
+
'Cannot delete the last enabled provider. Please ensure at least one other provider is enabled before deleting this one.',
|
|
249
|
+
},
|
|
250
|
+
400
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// All checks passed, safe to delete
|
|
255
|
+
await provider.destroy();
|
|
256
|
+
|
|
257
|
+
return c.json({ success: true });
|
|
246
258
|
});
|
|
247
259
|
|
|
248
|
-
export default
|
|
260
|
+
export default app;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Phase 3a (express→hono) — hono fork of routes/exchange-rates.ts. Sub-app with
|
|
2
|
+
// routes relative to /api/exchange-rates (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
|
+
import { Hono } from 'hono';
|
|
6
|
+
|
|
7
|
+
import { getExchangeRateService } from '../../libs/exchange-rate/service';
|
|
8
|
+
import { getExchangeRateSymbol, hasTokenAddress } from '../../libs/exchange-rate/token-address-mapping';
|
|
9
|
+
import { authenticate } from '../../middlewares/hono/security';
|
|
10
|
+
import { ChainType, PaymentCurrency, PaymentMethod } from '../../store/models';
|
|
11
|
+
|
|
12
|
+
const app = new Hono();
|
|
13
|
+
const auth = authenticate({ component: true, roles: ['owner', 'admin'], ensureLogin: true });
|
|
14
|
+
const exchangeRateService = getExchangeRateService();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Validate if exchange rate can be fetched for a currency.
|
|
18
|
+
* Used during price creation/editing to validate the base currency.
|
|
19
|
+
*/
|
|
20
|
+
app.post('/validate', auth, async (c) => {
|
|
21
|
+
try {
|
|
22
|
+
const { currency: currencyId } = (c.get('sanitizedBody') ?? {}) as any;
|
|
23
|
+
|
|
24
|
+
if (!currencyId) {
|
|
25
|
+
return c.json({ error: 'currency is required' }, 400);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const paymentCurrency = (await PaymentCurrency.findByPk(currencyId, {
|
|
29
|
+
include: [{ model: PaymentMethod, as: 'payment_method' }],
|
|
30
|
+
})) as PaymentCurrency & { payment_method: PaymentMethod };
|
|
31
|
+
|
|
32
|
+
if (!paymentCurrency) {
|
|
33
|
+
return c.json({ error: 'Currency not found' }, 400);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (paymentCurrency.payment_method?.type === 'stripe') {
|
|
37
|
+
return c.json({ error: `Currency ${paymentCurrency.symbol} is not supported.`, supported: false }, 400);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!hasTokenAddress(paymentCurrency.symbol, paymentCurrency.payment_method?.type as ChainType)) {
|
|
41
|
+
return c.json({ error: `Currency ${paymentCurrency.symbol} is not supported.`, supported: false }, 400);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const rateSymbol = getExchangeRateSymbol(
|
|
46
|
+
paymentCurrency.symbol,
|
|
47
|
+
paymentCurrency.payment_method?.type as ChainType
|
|
48
|
+
);
|
|
49
|
+
const rateResult = await exchangeRateService.getRate(rateSymbol);
|
|
50
|
+
|
|
51
|
+
return c.json({
|
|
52
|
+
supported: true,
|
|
53
|
+
currency: paymentCurrency.symbol,
|
|
54
|
+
base_currency: 'USD',
|
|
55
|
+
rate: rateResult.rate,
|
|
56
|
+
timestamp_ms: rateResult.timestamp_ms,
|
|
57
|
+
fetched_at: rateResult.fetched_at,
|
|
58
|
+
provider_id: rateResult.provider_id,
|
|
59
|
+
provider_name: rateResult.provider_name,
|
|
60
|
+
provider_display: rateResult.provider_display,
|
|
61
|
+
providers: rateResult.providers,
|
|
62
|
+
consensus_method: rateResult.consensus_method,
|
|
63
|
+
degraded: rateResult.degraded,
|
|
64
|
+
degraded_reason: rateResult.degraded_reason,
|
|
65
|
+
});
|
|
66
|
+
} catch (error: any) {
|
|
67
|
+
return c.json(
|
|
68
|
+
{ error: `Failed to fetch exchange rate for ${paymentCurrency.symbol}: ${error.message}`, supported: false },
|
|
69
|
+
400
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
} catch (error: any) {
|
|
73
|
+
return c.json({ error: error.message }, 400);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export default app;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Phase 3 (express→hono) — registry of MIGRATED native resource domains. Each
|
|
2
|
+
// domain is mounted via mountResourceGroup (app-shell pipeline + livemode +
|
|
3
|
+
// optional baseCurrency, scoped to the prefix). Domains NOT listed here are still
|
|
4
|
+
// served by the legacy express app through the catch-all bridge; both coexist
|
|
5
|
+
// until Phase 4 deletes the express modules. Batches add domains here one PR at a
|
|
6
|
+
// time (3a → 3f).
|
|
7
|
+
import type { Hono, MiddlewareHandler } from 'hono';
|
|
8
|
+
import { mountResourceGroup } from '../../middlewares/hono/resource-mount';
|
|
9
|
+
|
|
10
|
+
import exchangeRates from './exchange-rates';
|
|
11
|
+
import paymentCurrencies from './payment-currencies';
|
|
12
|
+
import paymentStats from './payment-stats';
|
|
13
|
+
import pricingTable from './pricing-table';
|
|
14
|
+
import customers from './customers';
|
|
15
|
+
import paymentMethods from './payment-methods';
|
|
16
|
+
import products from './products';
|
|
17
|
+
import prices from './prices';
|
|
18
|
+
import checkoutSessions from './checkout-sessions';
|
|
19
|
+
import subscriptions from './subscriptions';
|
|
20
|
+
import invoices from './invoices';
|
|
21
|
+
import paymentIntents from './payment-intents';
|
|
22
|
+
import coupons from './coupons';
|
|
23
|
+
import promotionCodes from './promotion-codes';
|
|
24
|
+
import creditGrants from './credit-grants';
|
|
25
|
+
import creditTokens from './credit-tokens';
|
|
26
|
+
import creditTransactions from './credit-transactions';
|
|
27
|
+
import meterEvents from './meter-events';
|
|
28
|
+
import usageRecords from './usage-records';
|
|
29
|
+
import stripeIntegration from './integrations/stripe';
|
|
30
|
+
import appStoreIntegration from './integrations/app-store';
|
|
31
|
+
import googlePlayIntegration from './integrations/google-play';
|
|
32
|
+
import autoRechargeConfigs from './auto-recharge-configs';
|
|
33
|
+
import donations from './donations';
|
|
34
|
+
import entitlements from './entitlements';
|
|
35
|
+
import events from './events';
|
|
36
|
+
import exchangeRateProviders from './exchange-rate-providers';
|
|
37
|
+
import meters from './meters';
|
|
38
|
+
import passports from './passports';
|
|
39
|
+
import paymentLinks from './payment-links';
|
|
40
|
+
import payouts from './payouts';
|
|
41
|
+
import redirect from './redirect';
|
|
42
|
+
import refunds from './refunds';
|
|
43
|
+
import settings from './settings';
|
|
44
|
+
import subscriptionItems from './subscription-items';
|
|
45
|
+
import taxRates from './tax-rates';
|
|
46
|
+
import tool from './tool';
|
|
47
|
+
import vendor from './vendor';
|
|
48
|
+
import webhookAttempts from './webhook-attempts';
|
|
49
|
+
import webhookEndpoints from './webhook-endpoints';
|
|
50
|
+
import archive from './archive';
|
|
51
|
+
|
|
52
|
+
export function mountMigratedResources(native: Hono, opts: { appShell?: MiddlewareHandler[] } = {}): void {
|
|
53
|
+
// The node host passes its full app-shell pipeline (cors/xss/csrf/cdn/i18n/
|
|
54
|
+
// context). The CF worker passes nothing → mountResourceGroup defaults to the
|
|
55
|
+
// LITE app-shell (xss only; the worker owns cors + tenant and never ran csrf/cdn).
|
|
56
|
+
const shell = opts.appShell;
|
|
57
|
+
const g = (prefix: string, subApp: Hono, o: { baseCurrency?: boolean } = {}) =>
|
|
58
|
+
mountResourceGroup(native, prefix, subApp, { ...o, appShell: shell });
|
|
59
|
+
|
|
60
|
+
// ── Batch 3a (low-risk read-only / validation) ─────────────────────────────
|
|
61
|
+
g('/api/exchange-rates', exchangeRates);
|
|
62
|
+
g('/api/payment-currencies', paymentCurrencies);
|
|
63
|
+
g('/api/payment-stats', paymentStats);
|
|
64
|
+
g('/api/pricing-tables', pricingTable);
|
|
65
|
+
|
|
66
|
+
// ── Batch 3b (customers / payment-methods / products / prices) ──────────────
|
|
67
|
+
g('/api/customers', customers);
|
|
68
|
+
g('/api/payment-methods', paymentMethods);
|
|
69
|
+
g('/api/products', products, { baseCurrency: true });
|
|
70
|
+
g('/api/prices', prices, { baseCurrency: true });
|
|
71
|
+
|
|
72
|
+
// ── Batch 3c (checkout-sessions / subscriptions / invoices / payment-intents) ─
|
|
73
|
+
g('/api/checkout-sessions', checkoutSessions, { baseCurrency: true });
|
|
74
|
+
g('/api/subscriptions', subscriptions);
|
|
75
|
+
g('/api/invoices', invoices);
|
|
76
|
+
g('/api/payment-intents', paymentIntents);
|
|
77
|
+
|
|
78
|
+
// ── Batch 3d (coupons / promotion-codes / credit-* / meter-events / usage-records)
|
|
79
|
+
g('/api/coupons', coupons);
|
|
80
|
+
g('/api/promotion-codes', promotionCodes);
|
|
81
|
+
g('/api/credit-grants', creditGrants);
|
|
82
|
+
g('/api/credit-tokens', creditTokens);
|
|
83
|
+
g('/api/credit-transactions', creditTransactions);
|
|
84
|
+
g('/api/meter-events', meterEvents);
|
|
85
|
+
g('/api/usage-records', usageRecords);
|
|
86
|
+
|
|
87
|
+
// ── Batch 3e (integrations) — Stripe webhook is RAW-BODY (xss skips that path,
|
|
88
|
+
// route reads c.req.arrayBuffer); app-store/google-play are normal JSON. ──────
|
|
89
|
+
g('/api/integrations/stripe', stripeIntegration);
|
|
90
|
+
g('/api/integrations/app-store', appStoreIntegration);
|
|
91
|
+
g('/api/integrations/google-play', googlePlayIntegration);
|
|
92
|
+
|
|
93
|
+
// ── Batch 3f (remaining domains) ────────────────────────────────────────────
|
|
94
|
+
g('/api/auto-recharge-configs', autoRechargeConfigs);
|
|
95
|
+
g('/api/donations', donations, { baseCurrency: true });
|
|
96
|
+
g('/api/entitlements', entitlements);
|
|
97
|
+
g('/api/events', events);
|
|
98
|
+
g('/api/exchange-rate-providers', exchangeRateProviders);
|
|
99
|
+
g('/api/meters', meters);
|
|
100
|
+
g('/api/passports', passports);
|
|
101
|
+
g('/api/payment-links', paymentLinks, { baseCurrency: true });
|
|
102
|
+
g('/api/payouts', payouts);
|
|
103
|
+
g('/api/redirect', redirect);
|
|
104
|
+
g('/api/refunds', refunds);
|
|
105
|
+
g('/api/settings', settings);
|
|
106
|
+
g('/api/subscription-items', subscriptionItems);
|
|
107
|
+
g('/api/tax-rates', taxRates);
|
|
108
|
+
g('/api/tool', tool);
|
|
109
|
+
g('/api/vendors', vendor);
|
|
110
|
+
g('/api/webhook-attempts', webhookAttempts);
|
|
111
|
+
g('/api/webhook-endpoints', webhookEndpoints);
|
|
112
|
+
g('/api/archive', archive);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default mountMigratedResources;
|