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.
- 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 +47 -0
- package/api/src/crons/base.ts +3 -3
- package/api/src/crons/currency.ts +1 -1
- package/api/src/crons/index.ts +41 -37
- 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/crons/tenant-fanout.ts +82 -0
- package/api/src/host-node/did-connect-runtime-node.ts +33 -0
- package/api/src/host-node/serve-static-arc.ts +68 -0
- package/api/src/host-node/serve-static.ts +41 -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 +247 -47
- package/api/src/libs/context.ts +89 -1
- package/api/src/libs/currency.ts +2 -2
- package/api/src/libs/dayjs.ts +8 -2
- package/api/src/libs/did-connect/runtime-did-connect-js.ts +88 -0
- package/api/src/libs/did-connect/tenant-identity.ts +221 -0
- 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 +142 -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 +60 -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 +271 -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 +80 -0
- package/api/src/middlewares/hono/csrf.ts +83 -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 +209 -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 +38 -21
- 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 +41 -11
- 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 +64 -37
- package/api/src/queues/payout.ts +37 -21
- package/api/src/queues/refund.ts +36 -18
- 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} +199 -224
- 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} +98 -83
- 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 +814 -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 +82 -23
- 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/bootstrap/bootstrap.spec.ts +162 -0
- package/api/tests/crons/tenant-fanout.spec.ts +158 -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/did-connect-runtime-js.spec.ts +98 -0
- package/api/tests/libs/did-connect-tenant-identity.spec.ts +159 -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/service-host.spec.ts +37 -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 +292 -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/service/didconnect-storage-slot.spec.ts +60 -0
- package/api/tests/service/fail-closed-http.spec.ts +79 -0
- package/api/tests/service/static-arc-handler.spec.ts +101 -0
- package/api/tests/service/static-externalized.spec.ts +48 -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/MIGRATION-RUNBOOK.md +3 -8
- package/cloudflare/README.md +34 -27
- package/cloudflare/STAGING-MIGRATION-GUIDE.md +3 -15
- package/cloudflare/build.ts +33 -13
- package/cloudflare/cf-adapter.ts +419 -0
- package/cloudflare/did-connect-runtime.ts +96 -0
- package/cloudflare/did-connect-token-storage.ts +151 -0
- package/cloudflare/esbuild-cf-config.cjs +407 -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 +33 -403
- package/cloudflare/scripts/cf-package-import-probe.mjs +90 -0
- package/cloudflare/scripts/didconnect-mock-smoke.mjs +140 -0
- 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/wallet-authenticator.ts +16 -1
- package/cloudflare/shims/blocklet-sdk/wallet-handler.ts +18 -3
- 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/xss.ts +8 -0
- package/cloudflare/tenant-middleware.ts +36 -0
- package/cloudflare/tests/cf-adapter.spec.ts +244 -0
- package/cloudflare/tests/did-connect-token-storage.spec.ts +105 -0
- package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
- package/cloudflare/tests/worker-handler-gate.spec.ts +69 -0
- package/cloudflare/vite.config.ts +53 -45
- package/cloudflare/worker.ts +261 -448
- package/cloudflare/wrangler.json +0 -6
- package/cloudflare/wrangler.jsonc +0 -6
- package/cloudflare/wrangler.local-e2e.jsonc +25 -0
- package/cloudflare/wrangler.staging.json +0 -6
- package/jest.config.js +3 -1
- package/package.json +33 -38
- package/scripts/bootstrap-inject.ts +166 -0
- 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/app.tsx +2 -1
- package/src/env.d.ts +13 -1
- package/src/libs/service-host.ts +13 -0
- package/tsconfig.json +1 -1
- package/vite.arc.config.ts +159 -0
- 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/did-connect-auth.ts +0 -527
- 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
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// S3-CF (DID convergence) — the REAL @arcblock/did-connect-js runtime, SHARED by
|
|
2
|
+
// the non-blocklet-server hosts (CF + arc-node embedded).
|
|
3
|
+
//
|
|
4
|
+
// Both build the same authenticator/handlers; they differ ONLY in the host adapter
|
|
5
|
+
// passed in here (tokenStorage, chain config, txEncoder, timeout). The signing
|
|
6
|
+
// wallet + appInfo are FUNCTION-VALUED and resolved per-request, per-tenant through
|
|
7
|
+
// the shared `resolveTenantIdentity` (AUTH_SERVICE.getInstanceAppIdentity) — never
|
|
8
|
+
// a fixed isolate key — so one isolate serves every tenant with its own appSk.
|
|
9
|
+
//
|
|
10
|
+
// @arcblock/did-connect-js supports function-valued `wallet` (base.js: typeof
|
|
11
|
+
// wallet === 'function' → resolved via getWalletInfo with a timeout before each
|
|
12
|
+
// sign), so per-tenant signing is safe.
|
|
13
|
+
|
|
14
|
+
import type { DidConnectRuntime, DidConnectTokenStorage } from '../auth';
|
|
15
|
+
import { resolveTenantIdentity } from './tenant-identity';
|
|
16
|
+
|
|
17
|
+
/** Chain config for the DID-Connect authenticator (id/type/host), or a resolver. */
|
|
18
|
+
export type ChainInfoOption =
|
|
19
|
+
| { id: string; type: string; host: string }
|
|
20
|
+
| ((params: any) => { id: string; type: string; host: string } | Promise<{ id: string; type: string; host: string }>);
|
|
21
|
+
|
|
22
|
+
export interface DidConnectJsRuntimeOptions {
|
|
23
|
+
/** Host-injected token store (CF: D1 tenant-aware adapter). Omit to let
|
|
24
|
+
* buildTokenStorage fall back to the file-backed nedb default (arc-node). */
|
|
25
|
+
tokenStorage?: DidConnectTokenStorage;
|
|
26
|
+
/** Chain config for `signature`/`prepareTx` claims (omit on chain-less hosts). */
|
|
27
|
+
chainInfo?: ChainInfoOption;
|
|
28
|
+
/** On-chain tx encoder (CF: @ocap/client/encode CBOR encoder). Omit to disable tx claims. */
|
|
29
|
+
txEncoder?: (params: { type: string; data: any; wallet: any; chainHost: string }) => Promise<Buffer>;
|
|
30
|
+
/** Authenticator timeout (CF chain RPC can exceed the 8s default; worker used 30s). */
|
|
31
|
+
timeout?: number;
|
|
32
|
+
/** Branding fallback when an instance's getInstanceAppIdentity omits appInfo. */
|
|
33
|
+
defaultAppInfo?: { name?: string; description?: string; icon?: string };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DEFAULT_APP_INFO = {
|
|
37
|
+
name: 'Payment Kit',
|
|
38
|
+
description: 'Payment Kit',
|
|
39
|
+
icon: 'https://www.arcblock.io/favicon.ico',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a DID-Connect runtime backed by the real @arcblock/did-connect-js stack.
|
|
44
|
+
* Used by `createCloudflareDidConnectRuntime` (CF) and the arc-node embedded host.
|
|
45
|
+
*/
|
|
46
|
+
export function createDidConnectJsRuntime(opts: DidConnectJsRuntimeOptions): DidConnectRuntime {
|
|
47
|
+
const fallbackAppInfo = { ...DEFAULT_APP_INFO, ...(opts.defaultAppInfo ?? {}) };
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
tokenStorage: opts.tokenStorage,
|
|
51
|
+
|
|
52
|
+
createAuthenticator() {
|
|
53
|
+
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
54
|
+
const { WalletAuthenticator } = require('@arcblock/did-connect-js');
|
|
55
|
+
|
|
56
|
+
const config: Record<string, any> = {
|
|
57
|
+
// Function-valued, per-tenant: resolve the signing wallet from the host
|
|
58
|
+
// IdentityDriver.getInstanceAppIdentity each time the authenticator signs.
|
|
59
|
+
// `.toJSON()` matches the standalone worker (the SDK reconstructs the full
|
|
60
|
+
// wallet — incl. sk — via fromJSON before signing).
|
|
61
|
+
wallet: async () => {
|
|
62
|
+
const { wallet } = await resolveTenantIdentity();
|
|
63
|
+
return wallet.toJSON();
|
|
64
|
+
},
|
|
65
|
+
appInfo: async ({ baseUrl }: { baseUrl?: string } = {}) => {
|
|
66
|
+
const { appInfo } = await resolveTenantIdentity();
|
|
67
|
+
return {
|
|
68
|
+
name: appInfo.name || fallbackAppInfo.name,
|
|
69
|
+
description: appInfo.description || fallbackAppInfo.description,
|
|
70
|
+
icon: appInfo.icon || fallbackAppInfo.icon,
|
|
71
|
+
link: appInfo.link || baseUrl,
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
timeout: opts.timeout ?? 30000,
|
|
75
|
+
};
|
|
76
|
+
if (opts.chainInfo) config.chainInfo = opts.chainInfo;
|
|
77
|
+
if (opts.txEncoder) config.txEncoder = opts.txEncoder;
|
|
78
|
+
|
|
79
|
+
return new WalletAuthenticator(config);
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
createHandlers({ authenticator, tokenStorage }) {
|
|
83
|
+
// eslint-disable-next-line global-require, import/no-extraneous-dependencies
|
|
84
|
+
const { WalletHandlers } = require('@arcblock/did-connect-js');
|
|
85
|
+
return new WalletHandlers({ authenticator, tokenStorage });
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// S3-CF (DID convergence) — the SHARED per-tenant DID-Connect identity resolver.
|
|
2
|
+
//
|
|
3
|
+
// Both non-blocklet-server runtimes (CF + arc-node embedded) build their REAL
|
|
4
|
+
// `@arcblock/did-connect-js` WalletAuthenticator from a per-tenant signing wallet
|
|
5
|
+
// resolved HERE — never from a fixed isolate-level APP_SK. The signing identity
|
|
6
|
+
// comes from the host IdentityDriver's `getInstanceAppIdentity(instanceDid)`
|
|
7
|
+
// (AUTH_SERVICE-backed), which already resolves the arc run-mode (instance app:sk
|
|
8
|
+
// → instance identity; else auth-service root; else fail-closed), so payment-core
|
|
9
|
+
// never reimplements "instance ?? root" and never reads connect-service internals.
|
|
10
|
+
//
|
|
11
|
+
// The wallet is derived from the returned `appSk` with @ocap/wallet (a stable
|
|
12
|
+
// public API) — the same ROLE_APPLICATION/ED25519/SHA3 wallet type the standalone
|
|
13
|
+
// CF worker used. The blocklet-server runtime does NOT use this resolver (it keeps
|
|
14
|
+
// the @blocklet/sdk wallet wrapper); only the AUTH_SERVICE/did-connect-js runtimes do.
|
|
15
|
+
//
|
|
16
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
17
|
+
import * as Mcrypto from '@ocap/mcrypto';
|
|
18
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
19
|
+
import { fromSecretKey, WalletType } from '@ocap/wallet';
|
|
20
|
+
import type { WalletObject } from '@ocap/wallet';
|
|
21
|
+
|
|
22
|
+
import { getInstanceDid } from '../context';
|
|
23
|
+
import { getIdentityDriver, type InstanceAppInfo, type BlockletDirectory } from '../drivers';
|
|
24
|
+
import logger from '../logger';
|
|
25
|
+
|
|
26
|
+
const walletType = {
|
|
27
|
+
role: Mcrypto.types.RoleType.ROLE_APPLICATION,
|
|
28
|
+
pk: Mcrypto.types.KeyType.ED25519,
|
|
29
|
+
hash: Mcrypto.types.HashType.SHA3,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// The ethereum business wallet is derived from the SAME instance appSk as the
|
|
33
|
+
// arcblock wallet, mirroring @blocklet/sdk getWallet('ethereum', appSk): the
|
|
34
|
+
// secp256k1/keccak WalletType('ethereum') over the first 66 chars of the appSk.
|
|
35
|
+
// Using @ocap/wallet directly (not the SDK) keeps this CF-worker-safe — the CF
|
|
36
|
+
// build shims the SDK wallet-* modules, but @ocap/wallet is a stable public API.
|
|
37
|
+
const ethWalletType = WalletType('ethereum');
|
|
38
|
+
|
|
39
|
+
export interface ResolvedTenantIdentity {
|
|
40
|
+
instanceDid: string;
|
|
41
|
+
/** App signing wallet derived from the instance appSk (the DID-Connect signer). */
|
|
42
|
+
wallet: WalletObject;
|
|
43
|
+
/** Ethereum business wallet derived from the same appSk (EVM chains / refunds). */
|
|
44
|
+
ethWallet: WalletObject;
|
|
45
|
+
/** Permanent app signing wallet (when keys rotated); falls back to `wallet`. */
|
|
46
|
+
permanentWallet: WalletObject;
|
|
47
|
+
/** Branding for DID-Connect prompts (name/description/icon/link). */
|
|
48
|
+
appInfo: InstanceAppInfo;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Per-instance TTL cache of the DERIVED identity (Layer 2 of
|
|
52
|
+
// wallet-authenticator-dynamic.md). The business wallet proxies (libs/auth.ts)
|
|
53
|
+
// read it SYNCHRONOUSLY via getCachedTenantIdentity, so resolveTenantIdentity
|
|
54
|
+
// (async — it RPCs getInstanceAppIdentity) must run first per request/job (the
|
|
55
|
+
// HTTP contextMiddleware and queue runJobWithTenant warm it). TTL bounds key-
|
|
56
|
+
// rotation staleness; for a single-tenant deployment this holds exactly one entry.
|
|
57
|
+
// A hard size cap (insertion-order eviction via Map iteration) keeps a host with
|
|
58
|
+
// many tenants from growing the map unbounded — expired entries are pruned on
|
|
59
|
+
// read but never proactively, so the cap is the only growth bound.
|
|
60
|
+
const IDENTITY_TTL_MS = 5 * 60 * 1000;
|
|
61
|
+
const IDENTITY_CACHE_MAX = 512;
|
|
62
|
+
const identityCache = new Map<string, { value: ResolvedTenantIdentity; expiry: number }>();
|
|
63
|
+
|
|
64
|
+
function cacheIdentity(instanceDid: string, value: ResolvedTenantIdentity): void {
|
|
65
|
+
identityCache.set(instanceDid, { value, expiry: Date.now() + IDENTITY_TTL_MS });
|
|
66
|
+
// evict the oldest entry (Map preserves insertion order) once over the cap
|
|
67
|
+
if (identityCache.size > IDENTITY_CACHE_MAX) {
|
|
68
|
+
const oldest = identityCache.keys().next().value;
|
|
69
|
+
if (oldest !== undefined) identityCache.delete(oldest);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Drop a tenant's cached identity (or all) — key rotation / test isolation. */
|
|
74
|
+
export function clearTenantIdentityCache(instanceDid?: string): void {
|
|
75
|
+
if (instanceDid) identityCache.delete(instanceDid);
|
|
76
|
+
else identityCache.clear();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Whether the active host runtime resolves app identity dynamically per tenant
|
|
81
|
+
* (arc-node embedded + CF, via AUTH_SERVICE.getInstanceAppIdentity) vs the
|
|
82
|
+
* blocklet-server runtime, which keeps the @blocklet/sdk env wallet. The
|
|
83
|
+
* business wallet proxies branch on this so blocklet-server stays byte-for-byte
|
|
84
|
+
* unchanged (it never touches the resolver / cache).
|
|
85
|
+
*/
|
|
86
|
+
export function hasDynamicIdentity(): boolean {
|
|
87
|
+
return typeof getIdentityDriver().getInstanceAppIdentity === 'function';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve the current (or given) tenant's DID-Connect signing identity. Throws a
|
|
92
|
+
* clear error — never silently falls back to a fixed key — when:
|
|
93
|
+
* - the active IdentityDriver does not implement getInstanceAppIdentity (a
|
|
94
|
+
* non-SDK runtime reached an SDK-only driver), or
|
|
95
|
+
* - the instance has no app signing key (fail-closed; AUTH_SERVICE 4.0.3 itself
|
|
96
|
+
* fails closed when neither instance app:sk nor root APP_SK exists).
|
|
97
|
+
*/
|
|
98
|
+
export async function resolveTenantIdentity(instanceDidArg?: string): Promise<ResolvedTenantIdentity> {
|
|
99
|
+
const instanceDid = instanceDidArg ?? getInstanceDid();
|
|
100
|
+
|
|
101
|
+
const cached = identityCache.get(instanceDid);
|
|
102
|
+
if (cached && cached.expiry > Date.now()) return cached.value;
|
|
103
|
+
|
|
104
|
+
const driver = getIdentityDriver();
|
|
105
|
+
if (typeof driver.getInstanceAppIdentity !== 'function') {
|
|
106
|
+
throw new Error(
|
|
107
|
+
'resolveTenantIdentity: the active IdentityDriver does not implement getInstanceAppIdentity — ' +
|
|
108
|
+
'a non-blocklet-server DID-Connect runtime requires an AUTH_SERVICE-backed identity driver'
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const identity = await driver.getInstanceAppIdentity(instanceDid);
|
|
112
|
+
if (!identity || !identity.appSk) {
|
|
113
|
+
throw new Error(`resolveTenantIdentity: no app signing key for instance "${instanceDid}" (fail-closed)`);
|
|
114
|
+
}
|
|
115
|
+
// A too-short appSk would silently yield a WRONG ethereum address (slice below)
|
|
116
|
+
// and thus a wrong receiving/signing wallet — fail closed instead. A real
|
|
117
|
+
// ED25519 app sk is 128 hex chars; the eth slice needs at least 66.
|
|
118
|
+
if (identity.appSk.length < 66) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`resolveTenantIdentity: appSk for instance "${instanceDid}" is too short ` +
|
|
121
|
+
`(${identity.appSk.length} chars) to derive a wallet (fail-closed)`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
const wallet = fromSecretKey(identity.appSk, walletType) as WalletObject;
|
|
125
|
+
// Mirror @blocklet/sdk getWallet('ethereum', appSk): secp256k1 over appSk[0..66].
|
|
126
|
+
const ethWallet = fromSecretKey(identity.appSk.slice(0, 66), ethWalletType) as WalletObject;
|
|
127
|
+
const permanentWallet = identity.appPsk ? (fromSecretKey(identity.appPsk, walletType) as WalletObject) : wallet;
|
|
128
|
+
const value: ResolvedTenantIdentity = {
|
|
129
|
+
instanceDid,
|
|
130
|
+
wallet,
|
|
131
|
+
ethWallet,
|
|
132
|
+
permanentWallet,
|
|
133
|
+
appInfo: identity.appInfo ?? {},
|
|
134
|
+
};
|
|
135
|
+
cacheIdentity(instanceDid, value);
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* SYNCHRONOUS accessor for the current (or given) tenant's resolved identity —
|
|
141
|
+
* the business wallet proxies (libs/auth.ts) call this on every `wallet.address`
|
|
142
|
+
* / `wallet.sign(...)`. It NEVER resolves (no RPC): it reads the cache that
|
|
143
|
+
* `warmTenantIdentity` populated earlier in the request/job. A miss means the
|
|
144
|
+
* identity was never warmed (fail-closed): throw rather than silently fall back
|
|
145
|
+
* to a wrong/default key.
|
|
146
|
+
*/
|
|
147
|
+
export function getCachedTenantIdentity(instanceDidArg?: string): ResolvedTenantIdentity {
|
|
148
|
+
const instanceDid = instanceDidArg ?? getInstanceDid();
|
|
149
|
+
const cached = identityCache.get(instanceDid);
|
|
150
|
+
if (!cached || cached.expiry <= Date.now()) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`tenant identity for "${instanceDid}" is not resolved (fail-closed) — ` +
|
|
153
|
+
'warmTenantIdentity must run in the request/job scope before any wallet access'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
return cached.value;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Best-effort warm of the current tenant's identity into the cache so later
|
|
161
|
+
* SYNCHRONOUS wallet access resolves. No-op for the blocklet-server runtime
|
|
162
|
+
* (env wallet, no dynamic driver). Errors are swallowed (logged): a request that
|
|
163
|
+
* never touches a wallet must not be blocked by an identity hiccup, while one
|
|
164
|
+
* that DOES touch it still fails-closed at getCachedTenantIdentity.
|
|
165
|
+
*/
|
|
166
|
+
export async function warmTenantIdentity(instanceDidArg?: string): Promise<void> {
|
|
167
|
+
if (!hasDynamicIdentity()) return;
|
|
168
|
+
try {
|
|
169
|
+
await resolveTenantIdentity(instanceDidArg);
|
|
170
|
+
} catch (err: unknown) {
|
|
171
|
+
logger.warn('[tenant-identity] warm failed — wallet access will fail-closed', {
|
|
172
|
+
error: err instanceof Error ? err.message : String(err),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The host user directory for the embedded runtime. In the DID-Connect world the
|
|
178
|
+
// user's DID IS the wallet DID, so getUser echoes it as a connected wallet account
|
|
179
|
+
// (so getWalletDid(user) resolves to the user's own DID); the rest are no-ops. This
|
|
180
|
+
// is the shared semantics the CF build-alias shim also implements
|
|
181
|
+
// (cloudflare/shims/blocklet-sdk/auth-service.ts).
|
|
182
|
+
const EMBEDDED_DIRECTORY: BlockletDirectory = {
|
|
183
|
+
getUser(did: string) {
|
|
184
|
+
if (!did) return { user: null };
|
|
185
|
+
return {
|
|
186
|
+
user: { did, fullName: did, email: '', phone: '', remark: '', connectedAccounts: [{ provider: 'wallet', did }] },
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
getUsers() {
|
|
190
|
+
return { users: [] };
|
|
191
|
+
},
|
|
192
|
+
getVault() {
|
|
193
|
+
return null;
|
|
194
|
+
},
|
|
195
|
+
getBlocklet() {
|
|
196
|
+
return { id: '', site: { id: '' } };
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* The embedded host identity services — the AUTH_SERVICE-backed implementations of
|
|
202
|
+
* the optional IdentityDriver methods, derived entirely from getInstanceAppIdentity
|
|
203
|
+
* (so a host need not reimplement them). arc-node spreads BOTH into its identity
|
|
204
|
+
* driver; CF spreads `getBusinessWallet` only (it keeps its build-alias directory
|
|
205
|
+
* shim). Stateless — every call reads the active driver via resolveTenantIdentity /
|
|
206
|
+
* getCachedTenantIdentity, so one instance serves every tenant.
|
|
207
|
+
*/
|
|
208
|
+
export function createEmbeddedIdentityServices(): {
|
|
209
|
+
getBusinessWallet(chain: 'arcblock' | 'ethereum'): WalletObject;
|
|
210
|
+
directory(): BlockletDirectory;
|
|
211
|
+
} {
|
|
212
|
+
return {
|
|
213
|
+
getBusinessWallet(chain: 'arcblock' | 'ethereum'): WalletObject {
|
|
214
|
+
const identity = getCachedTenantIdentity();
|
|
215
|
+
return chain === 'ethereum' ? identity.ethWallet : identity.wallet;
|
|
216
|
+
},
|
|
217
|
+
directory(): BlockletDirectory {
|
|
218
|
+
return EMBEDDED_DIRECTORY;
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Phase 8 (W2-1a): DID Connect token storage on the db driver.
|
|
2
|
+
//
|
|
3
|
+
// In Blocklet Server the real @arcblock/did-connect-storage-nedb (file-backed)
|
|
4
|
+
// is used unchanged. In the CF worker that package was aliased to a NO-OP stub
|
|
5
|
+
// (cloudflare/shims/nedb-storage.ts) — DID Connect state was silently dropped.
|
|
6
|
+
// This is the from-scratch persistent implementation on top of the db driver
|
|
7
|
+
// contract, so the same code runs on the node (sqlite) and d1 backends and is
|
|
8
|
+
// covered by the driver consistency suite.
|
|
9
|
+
//
|
|
10
|
+
// Records are flexible JSON documents keyed by `token` (the DID-Auth session
|
|
11
|
+
// token, globally unique — no instance_did column needed; isolation is by the
|
|
12
|
+
// unguessable token, matching the original file store's scope).
|
|
13
|
+
|
|
14
|
+
import type { DbDriver } from './db';
|
|
15
|
+
|
|
16
|
+
const { EventEmitter } = require('events');
|
|
17
|
+
|
|
18
|
+
const TABLE = 'did_auth_records';
|
|
19
|
+
|
|
20
|
+
export interface AuthRecord {
|
|
21
|
+
token: string;
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class DbAuthStorage extends EventEmitter {
|
|
26
|
+
private driver: DbDriver;
|
|
27
|
+
private ready: Promise<void> | null = null;
|
|
28
|
+
|
|
29
|
+
constructor(driver: DbDriver) {
|
|
30
|
+
super();
|
|
31
|
+
if (!driver) throw new Error('DbAuthStorage requires a db driver');
|
|
32
|
+
this.driver = driver;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// idempotent lazy schema — the original file store self-managed its db file
|
|
36
|
+
// (it was never part of the Umzug/D1 migration chain), so we keep that here.
|
|
37
|
+
private ensureTable(): Promise<void> {
|
|
38
|
+
if (!this.ready) {
|
|
39
|
+
this.ready = this.driver
|
|
40
|
+
.exec(
|
|
41
|
+
`CREATE TABLE IF NOT EXISTS ${TABLE} (` +
|
|
42
|
+
'token TEXT PRIMARY KEY, ' +
|
|
43
|
+
'doc TEXT NOT NULL, ' +
|
|
44
|
+
'created_at INTEGER NOT NULL, ' +
|
|
45
|
+
'updated_at INTEGER NOT NULL)'
|
|
46
|
+
)
|
|
47
|
+
.then(() => undefined)
|
|
48
|
+
.catch((err) => {
|
|
49
|
+
// reset so a transient failure can be retried on next call
|
|
50
|
+
this.ready = null;
|
|
51
|
+
throw err;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return this.ready;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async read(token: string): Promise<AuthRecord | null> {
|
|
58
|
+
if (!token) throw new Error('token is required to read auth record');
|
|
59
|
+
await this.ensureTable();
|
|
60
|
+
const row = await this.driver.get<{ doc: string }>(`SELECT doc FROM ${TABLE} WHERE token = ?`, [token]);
|
|
61
|
+
if (!row) return null;
|
|
62
|
+
return JSON.parse(row.doc) as AuthRecord;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async create(token: string, status = 'created'): Promise<AuthRecord> {
|
|
66
|
+
if (!token) throw new Error('token is required to create auth record');
|
|
67
|
+
await this.ensureTable();
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const doc: AuthRecord = { token, status, createdAt: now, updatedAt: now };
|
|
70
|
+
await this.driver.exec(`INSERT INTO ${TABLE} (token, doc, created_at, updated_at) VALUES (?, ?, ?, ?)`, [
|
|
71
|
+
token,
|
|
72
|
+
JSON.stringify(doc),
|
|
73
|
+
now,
|
|
74
|
+
now,
|
|
75
|
+
]);
|
|
76
|
+
this.emit('create', doc);
|
|
77
|
+
return doc;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async update(token: string, updates: Record<string, any> = {}): Promise<AuthRecord | null> {
|
|
81
|
+
if (!token) throw new Error('token is required to update auth record');
|
|
82
|
+
await this.ensureTable();
|
|
83
|
+
const current = await this.read(token);
|
|
84
|
+
if (!current) return null;
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
const merged: AuthRecord = { ...current, ...updates, token, updatedAt: now };
|
|
87
|
+
await this.driver.exec(`UPDATE ${TABLE} SET doc = ?, updated_at = ? WHERE token = ?`, [
|
|
88
|
+
JSON.stringify(merged),
|
|
89
|
+
now,
|
|
90
|
+
token,
|
|
91
|
+
]);
|
|
92
|
+
this.emit('update', merged);
|
|
93
|
+
return merged;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async delete(token: string): Promise<number> {
|
|
97
|
+
if (!token) throw new Error('token is required to delete auth record');
|
|
98
|
+
await this.ensureTable();
|
|
99
|
+
const res = await this.driver.exec(`DELETE FROM ${TABLE} WHERE token = ?`, [token]);
|
|
100
|
+
this.emit('destroy', token);
|
|
101
|
+
return res.changes;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async exist(token: string, did: any): Promise<boolean> {
|
|
105
|
+
if (!token) throw new Error('token is required to check auth record');
|
|
106
|
+
const doc = await this.read(token);
|
|
107
|
+
return !!doc && doc.did === did;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async clear(): Promise<void> {
|
|
111
|
+
await this.ensureTable();
|
|
112
|
+
await this.driver.exec(`DELETE FROM ${TABLE}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function createAuthStorage(driver: DbDriver): DbAuthStorage {
|
|
117
|
+
return new DbAuthStorage(driver);
|
|
118
|
+
}
|