payweave 0.0.0

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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -0
  3. package/dist/_tsup-dts-rollup.d.ts +19470 -0
  4. package/dist/chunk-4R5OGOCC.js +94 -0
  5. package/dist/chunk-4R5OGOCC.js.map +1 -0
  6. package/dist/chunk-535Q3GUN.js +175 -0
  7. package/dist/chunk-535Q3GUN.js.map +1 -0
  8. package/dist/chunk-67NRYGRC.js +192 -0
  9. package/dist/chunk-67NRYGRC.js.map +1 -0
  10. package/dist/chunk-CGQ73I4I.js +568 -0
  11. package/dist/chunk-CGQ73I4I.js.map +1 -0
  12. package/dist/chunk-CJEYDHY6.js +18 -0
  13. package/dist/chunk-CJEYDHY6.js.map +1 -0
  14. package/dist/chunk-CR63JAAS.js +3 -0
  15. package/dist/chunk-CR63JAAS.js.map +1 -0
  16. package/dist/chunk-E633MKVX.js +1507 -0
  17. package/dist/chunk-E633MKVX.js.map +1 -0
  18. package/dist/chunk-FBPOCXRZ.js +1135 -0
  19. package/dist/chunk-FBPOCXRZ.js.map +1 -0
  20. package/dist/chunk-HTRGMZFH.js +267 -0
  21. package/dist/chunk-HTRGMZFH.js.map +1 -0
  22. package/dist/chunk-IUVGM3K7.js +765 -0
  23. package/dist/chunk-IUVGM3K7.js.map +1 -0
  24. package/dist/chunk-JD4OZHRI.js +326 -0
  25. package/dist/chunk-JD4OZHRI.js.map +1 -0
  26. package/dist/chunk-NV3MZF7L.js +139 -0
  27. package/dist/chunk-NV3MZF7L.js.map +1 -0
  28. package/dist/chunk-NXQBP35U.js +13 -0
  29. package/dist/chunk-NXQBP35U.js.map +1 -0
  30. package/dist/chunk-QJHXDZYC.js +412 -0
  31. package/dist/chunk-QJHXDZYC.js.map +1 -0
  32. package/dist/chunk-TWZK62TZ.js +83 -0
  33. package/dist/chunk-TWZK62TZ.js.map +1 -0
  34. package/dist/cli/index.js +35381 -0
  35. package/dist/core/index.d.ts +85 -0
  36. package/dist/core/index.js +6 -0
  37. package/dist/core/index.js.map +1 -0
  38. package/dist/db/drizzle/index.d.ts +6 -0
  39. package/dist/db/drizzle/index.js +1532 -0
  40. package/dist/db/drizzle/index.js.map +1 -0
  41. package/dist/db/index.d.ts +43 -0
  42. package/dist/db/index.js +3 -0
  43. package/dist/db/index.js.map +1 -0
  44. package/dist/db/mongodb/index.d.ts +3 -0
  45. package/dist/db/mongodb/index.js +934 -0
  46. package/dist/db/mongodb/index.js.map +1 -0
  47. package/dist/db/mysql/index.d.ts +1 -0
  48. package/dist/db/mysql/index.js +12 -0
  49. package/dist/db/mysql/index.js.map +1 -0
  50. package/dist/db/postgres/index.d.ts +5 -0
  51. package/dist/db/postgres/index.js +791 -0
  52. package/dist/db/postgres/index.js.map +1 -0
  53. package/dist/db/prisma/index.d.ts +1 -0
  54. package/dist/db/prisma/index.js +12 -0
  55. package/dist/db/prisma/index.js.map +1 -0
  56. package/dist/db/sqlite/index.d.ts +5 -0
  57. package/dist/db/sqlite/index.js +750 -0
  58. package/dist/db/sqlite/index.js.map +1 -0
  59. package/dist/express/index.d.ts +1 -0
  60. package/dist/express/index.js +3 -0
  61. package/dist/express/index.js.map +1 -0
  62. package/dist/fastify/index.d.ts +1 -0
  63. package/dist/fastify/index.js +3 -0
  64. package/dist/fastify/index.js.map +1 -0
  65. package/dist/flutterwave/index.d.ts +27 -0
  66. package/dist/flutterwave/index.js +9 -0
  67. package/dist/flutterwave/index.js.map +1 -0
  68. package/dist/index.d.ts +85 -0
  69. package/dist/index.js +3677 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/next/index.d.ts +1 -0
  72. package/dist/next/index.js +3 -0
  73. package/dist/next/index.js.map +1 -0
  74. package/dist/paystack/index.d.ts +33 -0
  75. package/dist/paystack/index.js +9 -0
  76. package/dist/paystack/index.js.map +1 -0
  77. package/dist/products/index.d.ts +22 -0
  78. package/dist/products/index.js +7 -0
  79. package/dist/products/index.js.map +1 -0
  80. package/dist/testing/index.d.ts +11 -0
  81. package/dist/testing/index.js +69 -0
  82. package/dist/testing/index.js.map +1 -0
  83. package/dist/unified/index.d.ts +41 -0
  84. package/dist/unified/index.js +6 -0
  85. package/dist/unified/index.js.map +1 -0
  86. package/dist/webhooks/index.d.ts +8 -0
  87. package/dist/webhooks/index.js +8 -0
  88. package/dist/webhooks/index.js.map +1 -0
  89. package/package.json +164 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/config.ts","../src/core/retry.ts","../src/core/version.ts","../src/core/http.ts","../src/core/provider.ts"],"names":["environment","baseUrl","err","z"],"mappings":"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","file":"chunk-IUVGM3K7.js","sourcesContent":["/**\n * Config schema, environment inference, and base-URL resolution.\n *\n * Two roots live here:\n *\n * 1. **Provider-KEYED root** (`payweaveConfigSchema` + `resolvePayweaveConfig`)\n * — the primary entry point. Providers are optional top-level keys\n * (`stripe` / `paystack` / `flutterwave`); `createPayweave` mounts on this.\n * 2. **Discriminated root** (`sdkConfigSchema` + `resolveConfig`) — internal\n * per-provider resolution that the keyed root delegates to for the actual\n * paystack/flutterwave environment-inference and base-URL logic.\n *\n * Invalid config throws {@link PayweaveConfigError} synchronously — we never\n * send a request with a key we cannot classify.\n */\nimport { z } from \"zod\";\nimport type { DatabaseAdapter } from \"../db/index\";\nimport { resolvePlanPricing, type Plan, type ResolvedPlanPrice } from \"../products/plan\";\nimport { PayweaveConfigError } from \"./errors\";\nimport type { FetchLike } from \"./http\";\nimport type { Logger } from \"./logger\";\n\n// ── Base URLs ────────────────────────────────────────────────────────────────\n/** Paystack REST base — same host for test and live (env is key-derived). */\nexport const PAYSTACK_BASE_URL = \"https://api.paystack.co\";\n/** Flutterwave v3 REST base — same host for test and live (env is key-derived). */\nexport const FLW_V3_BASE_URL = \"https://api.flutterwave.com/v3\";\n/**\n * ⚠️ VERIFY AT BUILD TIME against developer.flutterwave.com → Environments with\n * the version selector pinned to v4. v4 uses a distinct sandbox host and OAuth,\n * with explicit (not key-inferred) environments. These are PLACEHOLDERS.\n */\nexport const FLW_V4_BASE_URL = \"https://api.flutterwave.cloud/f4bexperience\";\n/** ⚠️ VERIFY AT BUILD TIME — v4 sandbox host (placeholder, see above). */\nexport const FLW_V4_SANDBOX_URL = \"https://api.flutterwave.cloud/developersandbox\";\n/**\n * ⚠️ VERIFY AT BUILD TIME — v4 OAuth token endpoint / grant / TTL against the\n * v4 Authentication docs. Consumed by the OAuth auth strategy (core/http).\n */\nexport const FLW_V4_TOKEN_URL =\n \"https://idp.flutterwave.com/realms/flutterwave/protocol/openid-connect/token\";\n/** Stripe REST base — one host for test AND live; env is key-derived. */\nexport const STRIPE_BASE_URL = \"https://api.stripe.com\";\n/**\n * The Stripe API version this SDK was built against, pinned via the\n * `Stripe-Version` header on EVERY request so provider-side version drift\n * cannot change payload shapes under us. Overridable per\n * client through `stripe.apiVersion`. Current version confirmed at\n * https://docs.stripe.com/api/versioning (verified 2026-07-12): monthly\n * releases are `YYYY-MM-DD.<major-release-name>`.\n */\nexport const STRIPE_API_VERSION = \"2026-06-24.dahlia\";\n\n// ── Schema ───────────────────────────────────────────────────────────────────\nconst commonFields = {\n timeoutMs: z.number().int().positive().optional(),\n maxRetries: z.number().int().nonnegative().optional(),\n baseUrl: z.string().min(1).optional(),\n fetch: z.custom<FetchLike>((v) => typeof v === \"function\").optional(),\n environment: z.enum([\"test\", \"live\"]).optional(),\n logger: z.custom<Logger>((v) => typeof v === \"function\").optional(),\n allowInsecureBaseUrl: z.boolean().optional(),\n};\n\nconst paystackConfigSchema = z.object({\n provider: z.literal(\"paystack\"),\n secretKey: z.string().min(1),\n ...commonFields,\n});\n\nconst flwV3ConfigSchema = z.object({\n provider: z.literal(\"flutterwave\"),\n version: z.literal(\"v3\").default(\"v3\"),\n secretKey: z.string().min(1),\n encryptionKey: z.string().optional(),\n webhookSecret: z.string().optional(),\n ...commonFields,\n});\n\nconst flwV4ConfigSchema = z.object({\n provider: z.literal(\"flutterwave\"),\n version: z.literal(\"v4\"),\n clientId: z.string().min(1),\n clientSecret: z.string().min(1),\n encryptionKey: z.string().optional(),\n webhookSecret: z.string().optional(),\n ...commonFields,\n});\n\n/** Flutterwave union, discriminated on `version` (`v3` default applied below). */\nconst flutterwaveConfigSchema = z.discriminatedUnion(\"version\", [\n flwV3ConfigSchema,\n flwV4ConfigSchema,\n]);\n\n/**\n * Top-level SDK config schema: a `discriminatedUnion` on `provider` (faster and\n * with precise, targeted errors vs a sequential `z.union`). The preprocess\n * injects the default `version: \"v3\"` for a Flutterwave config that omits it,\n * BEFORE discrimination, so the nested version-discriminated union can route it\n * — `version: \"v4\"` opts into the OAuth shape (`clientId` + `clientSecret`).\n */\nexport const sdkConfigSchema = z.preprocess((val) => {\n if (\n val !== null &&\n typeof val === \"object\" &&\n !Array.isArray(val) &&\n (val as Record<string, unknown>).provider === \"flutterwave\" &&\n !(\"version\" in val)\n ) {\n return { ...(val as Record<string, unknown>), version: \"v3\" };\n }\n return val;\n}, z.discriminatedUnion(\"provider\", [paystackConfigSchema, flutterwaveConfigSchema]));\n\nexport type PaystackConfig = z.input<typeof paystackConfigSchema>;\nexport type FlutterwaveV3Config = z.input<typeof flwV3ConfigSchema>;\nexport type FlutterwaveV4Config = z.input<typeof flwV4ConfigSchema>;\nexport type FlutterwaveConfig = FlutterwaveV3Config | FlutterwaveV4Config;\nexport type SDKConfig = PaystackConfig | FlutterwaveConfig;\n\n/** Fully-resolved config: defaults applied, environment + baseUrl decided. */\nexport interface ResolvedConfig {\n provider: \"paystack\" | \"flutterwave\";\n version: \"v3\" | \"v4\" | undefined;\n environment: \"test\" | \"live\";\n baseUrl: string;\n secretKey: string | undefined;\n clientId: string | undefined;\n clientSecret: string | undefined;\n encryptionKey: string | undefined;\n webhookSecret: string | undefined;\n timeoutMs: number;\n maxRetries: number;\n fetch: FetchLike | undefined;\n logger: Logger | undefined;\n allowInsecureBaseUrl: boolean;\n /** v4 only — OAuth token endpoint the auth strategy hits. */\n tokenUrl: string | undefined;\n}\n\n/** Defaults. */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\nexport const DEFAULT_MAX_RETRIES = 2;\n\n/**\n * Infer `\"test\" | \"live\"` from a Paystack / Flutterwave-v3 / Stripe secret key\n * prefix. Throws {@link PayweaveConfigError} naming the expected prefixes for a\n * malformed/unrecognized key (we never send a request with a key we can't\n * classify). Flutterwave v4 does NOT use this — its environment is explicit.\n */\nexport function inferEnvironment(\n provider: \"paystack\" | \"flutterwave\" | \"stripe\",\n secretKey: string,\n): \"test\" | \"live\" {\n if (provider === \"paystack\") {\n if (secretKey.startsWith(\"sk_test_\")) return \"test\";\n if (secretKey.startsWith(\"sk_live_\")) return \"live\";\n throw new PayweaveConfigError(\n \"Unrecognized Paystack secret key — expected an 'sk_test_' or 'sk_live_' prefix.\",\n { provider },\n );\n }\n if (provider === \"stripe\") {\n // Standard keys (sk_) and restricted keys (rk_) both carry the env in the\n // prefix. A bare \"rk_\" without test/live is unclassifiable.\n if (secretKey.startsWith(\"sk_test_\") || secretKey.startsWith(\"rk_test_\")) return \"test\";\n if (secretKey.startsWith(\"sk_live_\") || secretKey.startsWith(\"rk_live_\")) return \"live\";\n throw new PayweaveConfigError(\n \"Unrecognized Stripe secret key — expected an 'sk_test_', 'sk_live_', 'rk_test_', or 'rk_live_' prefix.\",\n { provider },\n );\n }\n if (secretKey.startsWith(\"FLWSECK_TEST-\")) return \"test\";\n if (secretKey.startsWith(\"FLWSECK-\")) return \"live\";\n throw new PayweaveConfigError(\n \"Unrecognized Flutterwave secret key — expected an 'FLWSECK_TEST-' or 'FLWSECK-' prefix.\",\n { provider },\n );\n}\n\nfunction toConfigError(err: unknown): PayweaveConfigError {\n if (err instanceof z.ZodError) {\n const detail = err.issues\n .map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"; \");\n return new PayweaveConfigError(`Invalid Payweave config — ${detail}`);\n }\n if (err instanceof PayweaveConfigError) return err;\n return new PayweaveConfigError(\n `Invalid Payweave config — ${err instanceof Error ? err.message : String(err)}`,\n );\n}\n\nfunction guardBaseUrl(\n baseUrl: string,\n allowInsecure: boolean,\n logger: Logger | undefined,\n provider: \"paystack\" | \"flutterwave\" | \"stripe\",\n): void {\n if (/^https:\\/\\//i.test(baseUrl)) return;\n if (!allowInsecure) {\n throw new PayweaveConfigError(\n `Refusing non-HTTPS baseUrl \"${baseUrl}\". Set allowInsecureBaseUrl: true to override (testing only).`,\n { provider },\n );\n }\n logger?.({\n type: \"warn\",\n message: `⚠️ INSECURE baseUrl \"${baseUrl}\" — credentials will be sent unencrypted. Never do this in production.`,\n });\n}\n\n/**\n * Parse + fully resolve raw SDK config. Applies defaults, infers the\n * environment (throwing on conflict with an explicit `environment`), selects\n * the base URL, and enforces the HTTPS guard. Throws\n * {@link PayweaveConfigError} synchronously for any invalid input.\n */\nexport function resolveConfig(input: unknown): ResolvedConfig {\n let parsed: z.output<typeof sdkConfigSchema>;\n try {\n parsed = sdkConfigSchema.parse(input);\n } catch (err) {\n throw toConfigError(err);\n }\n\n const timeoutMs = parsed.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxRetries = parsed.maxRetries ?? DEFAULT_MAX_RETRIES;\n const allowInsecureBaseUrl = parsed.allowInsecureBaseUrl ?? false;\n const logger = parsed.logger;\n\n if (parsed.provider === \"paystack\") {\n const environment = resolveKeyedEnvironment(\"paystack\", parsed.secretKey, parsed.environment);\n const baseUrl = parsed.baseUrl ?? PAYSTACK_BASE_URL;\n guardBaseUrl(baseUrl, allowInsecureBaseUrl, logger, \"paystack\");\n return {\n provider: \"paystack\",\n version: undefined,\n environment,\n baseUrl,\n secretKey: parsed.secretKey,\n clientId: undefined,\n clientSecret: undefined,\n encryptionKey: undefined,\n webhookSecret: undefined,\n timeoutMs,\n maxRetries,\n fetch: parsed.fetch,\n logger,\n allowInsecureBaseUrl,\n tokenUrl: undefined,\n };\n }\n\n // Flutterwave\n if (parsed.version === \"v4\") {\n // v4: environment is explicit (default \"test\"); separate sandbox host.\n const environment = parsed.environment ?? \"test\";\n const baseUrl =\n parsed.baseUrl ?? (environment === \"test\" ? FLW_V4_SANDBOX_URL : FLW_V4_BASE_URL);\n guardBaseUrl(baseUrl, allowInsecureBaseUrl, logger, \"flutterwave\");\n return {\n provider: \"flutterwave\",\n version: \"v4\",\n environment,\n baseUrl,\n secretKey: undefined,\n clientId: parsed.clientId,\n clientSecret: parsed.clientSecret,\n encryptionKey: parsed.encryptionKey,\n webhookSecret: parsed.webhookSecret,\n timeoutMs,\n maxRetries,\n fetch: parsed.fetch,\n logger,\n allowInsecureBaseUrl,\n tokenUrl: FLW_V4_TOKEN_URL,\n };\n }\n\n // Flutterwave v3\n const environment = resolveKeyedEnvironment(\"flutterwave\", parsed.secretKey, parsed.environment);\n const baseUrl = parsed.baseUrl ?? FLW_V3_BASE_URL;\n guardBaseUrl(baseUrl, allowInsecureBaseUrl, logger, \"flutterwave\");\n return {\n provider: \"flutterwave\",\n version: \"v3\",\n environment,\n baseUrl,\n secretKey: parsed.secretKey,\n clientId: undefined,\n clientSecret: undefined,\n encryptionKey: parsed.encryptionKey,\n webhookSecret: parsed.webhookSecret,\n timeoutMs,\n maxRetries,\n fetch: parsed.fetch,\n logger,\n allowInsecureBaseUrl,\n tokenUrl: undefined,\n };\n}\n\nfunction resolveKeyedEnvironment(\n provider: \"paystack\" | \"flutterwave\" | \"stripe\",\n secretKey: string,\n explicit: \"test\" | \"live\" | undefined,\n): \"test\" | \"live\" {\n const inferred = inferEnvironment(provider, secretKey);\n if (explicit && explicit !== inferred) {\n throw new PayweaveConfigError(\n `environment \"${explicit}\" conflicts with the ${provider} key prefix (which indicates \"${inferred}\"). ` +\n `Remove the explicit environment or use a matching key.`,\n { provider },\n );\n }\n return inferred;\n}\n\n// ═════════════════════════════════════════════════════════════════════════════\n// Provider-KEYED root — the primary entry point that `createPayweave` mounts\n// on. The plumbing above (base URLs, commonFields, per-provider sub-schemas,\n// inferEnvironment, guards) is shared with the `sdkConfigSchema`/`resolveConfig`\n// root below.\n// ═════════════════════════════════════════════════════════════════════════════\n\n/** Canonical provider-key order — also the iteration order of resolution. */\nexport const PAYWEAVE_PROVIDER_KEYS = [\"stripe\", \"paystack\", \"flutterwave\"] as const;\n\nconst providerKeySchema = z.enum(PAYWEAVE_PROVIDER_KEYS);\n\n/** Union of the top-level provider config keys accepted by `createPayweave`. */\nexport type PayweaveProviderKey = z.infer<typeof providerKeySchema>;\n\n/**\n * Stripe per-provider config.\n * `secretKey` accepts standard (`sk_*`) and restricted (`rk_*`) keys\n * (https://docs.stripe.com/api/authentication — verified 2026-07-12); env is\n * inferred from the prefix by {@link inferEnvironment}. Auth headers and the\n * form-encoding transport are wired by `src/stripe/http-options`.\n */\nexport const stripeProviderConfigSchema = z.object({\n secretKey: z.string().min(1),\n /** `whsec_*` — REQUIRED before any `webhooks.*` call (fail closed); optional here. */\n webhookSecret: z.string().optional(),\n /** Pins the `Stripe-Version` header; defaults to {@link STRIPE_API_VERSION}. */\n apiVersion: z.string().optional(),\n /**\n * Connect platforms only — a connected account id (`acct_*`) sent as the\n * `Stripe-Account` header on every request so calls act on that account\n * (https://docs.stripe.com/connect/authentication — verified 2026-07-12).\n */\n accountId: z.string().min(1).optional(),\n ...commonFields,\n});\n\n/** Paystack per-provider config — the legacy shape minus its `provider` discriminator. */\nexport const paystackProviderConfigSchema = paystackConfigSchema.omit({ provider: true });\n\n/**\n * Flutterwave per-provider config. Reuses {@link flutterwaveConfigSchema} (and\n * the legacy root's v3-default preprocess behavior) UNCHANGED — rule 6: the\n * `version` discriminator (`\"v3\"` default, `\"v4\"` opt-in) lives INSIDE the\n * `flutterwave` key; the top-level shape does not change per version. The\n * preprocess injects the `provider` literal the reused union expects plus the\n * `\"v3\"` default, exactly as the legacy root does.\n */\nexport const flutterwaveProviderConfigSchema = z.preprocess((val) => {\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n const withDefaults: Record<string, unknown> = { ...(val as Record<string, unknown>) };\n if (!(\"version\" in withDefaults)) withDefaults.version = \"v3\";\n withDefaults.provider = \"flutterwave\";\n return withDefaults;\n }\n return val;\n}, flutterwaveConfigSchema);\n\nconst isPlainObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\nconst storeHasMethod = (store: unknown, method: string): boolean =>\n isPlainObject(store) && typeof store[method] === \"function\";\n\n/**\n * Cheap structural check for the real `DatabaseAdapter` contract: the six\n * stores must be present with one spot-checked method each, plus `dialect` +\n * `transaction`. Deliberately NOT\n * a deep validation — adapters are `payweave/db/*` factory outputs that\n * validate their own input eagerly; this guard exists to\n * catch handing us a raw driver/ORM client (e.g. a `PrismaClient`) instead of\n * `prismaAdapter(prisma)`.\n */\nconst isDatabaseAdapter = (v: unknown): v is DatabaseAdapter =>\n isPlainObject(v) &&\n typeof v.dialect === \"string\" &&\n typeof v.transaction === \"function\" &&\n storeHasMethod(v.customers, \"upsert\") &&\n storeHasMethod(v.plans, \"pushVersion\") &&\n storeHasMethod(v.subscriptions, \"getActive\") &&\n storeHasMethod(v.balances, \"consume\") &&\n storeHasMethod(v.webhookEvents, \"claim\") &&\n storeHasMethod(v.migrations, \"apply\");\n\nconst databaseAdapterSchema = z.custom<DatabaseAdapter>(\n isDatabaseAdapter,\n \"expected a payweave/db/* database adapter object\",\n);\n\n/**\n * Cheap structural check for a real `plan()` output: a spot\n * check on `id`/`default`/`includes`, mirroring {@link isDatabaseAdapter}'s\n * philosophy — deliberately NOT a deep validation (`plan()` already validated\n * the definition eagerly at definition time; this guard exists to catch a\n * raw plain object standing in for a `plan()` call).\n */\nconst isPlan = (v: unknown): v is Plan =>\n isPlainObject(v) &&\n typeof v.id === \"string\" &&\n typeof v.default === \"boolean\" &&\n Array.isArray(v.includes);\n\nconst planSchema = z.custom<Plan>(\n isPlan,\n \"expected a plan() definition (see plans-and-features.md)\",\n);\n\n/**\n * The provider-keyed root config schema. STRICT: unknown\n * top-level keys are rejected (rule 1 — catches typos like `stipe`). Rules 2–5\n * are cross-field and enforced by {@link resolvePayweaveConfig}.\n */\nexport const payweaveConfigSchema = z.strictObject({\n // ── Providers (at least one — rule 2, enforced in the resolver) ──\n stripe: stripeProviderConfigSchema.optional(),\n paystack: paystackProviderConfigSchema.optional(),\n flutterwave: flutterwaveProviderConfigSchema.optional(),\n\n /** Routing target for unified/billing calls — must name a configured key (rule 3). */\n defaultProvider: providerKeySchema.optional(),\n\n // ── Billing platform (billing surface activates when present) ──\n database: databaseAdapterSchema.optional(),\n products: z.array(planSchema).optional(),\n /** ISO 4217 — used by plan prices without an explicit currency. */\n defaultCurrency: z.string().min(1).optional(),\n\n // ── Common transport options (shared across providers) ──\n timeoutMs: commonFields.timeoutMs,\n maxRetries: commonFields.maxRetries,\n fetch: commonFields.fetch,\n logger: commonFields.logger,\n /** Explicit env — per-provider key inference still applies; conflicts throw (rule 4). */\n environment: commonFields.environment,\n});\n\nexport type StripeProviderConfig = z.input<typeof stripeProviderConfigSchema>;\nexport type PaystackProviderConfig = z.input<typeof paystackProviderConfigSchema>;\n\n/** `Omit` that distributes over unions, preserving each member's own keys. */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\n/** Flutterwave keyed input — the legacy v3/v4 input union minus the injected `provider`. */\nexport type FlutterwaveProviderConfig = DistributiveOmit<FlutterwaveConfig, \"provider\">;\n\n/**\n * Input type for `createPayweave`. Assembled from\n * z.input-derived pieces rather than `z.input<typeof payweaveConfigSchema>`\n * because the `flutterwave` key's preprocess erases its input type (same\n * reason the legacy root hand-assembles `SDKConfig`), and `products` accepts\n * readonly arrays per spec.\n */\nexport type PayweaveConfig = {\n stripe?: StripeProviderConfig | undefined;\n paystack?: PaystackProviderConfig | undefined;\n flutterwave?: FlutterwaveProviderConfig | undefined;\n defaultProvider?: PayweaveProviderKey | undefined;\n /** The `payweave/db/*` adapter powering the billing surface. */\n database?: DatabaseAdapter | undefined;\n /** `plan()` outputs — plan/feature ids become type-safe. */\n products?: readonly Plan[] | undefined;\n defaultCurrency?: string | undefined;\n timeoutMs?: number | undefined;\n maxRetries?: number | undefined;\n fetch?: FetchLike | undefined;\n logger?: Logger | undefined;\n environment?: \"test\" | \"live\" | undefined;\n};\n\n/**\n * One provider's fully-resolved config — shaped like the legacy\n * {@link ResolvedConfig} (so `createPayweave` builds one `HttpClient` per\n * provider via the same wiring) plus the Stripe-only `apiVersion` passthrough.\n */\nexport interface ResolvedProviderConfig extends Omit<ResolvedConfig, \"provider\"> {\n provider: PayweaveProviderKey;\n /** Stripe only — pins the `Stripe-Version` header. */\n apiVersion: string | undefined;\n /** Stripe only — Connect `Stripe-Account` header (`acct_*`), absent for other providers. */\n accountId?: string | undefined;\n}\n\n/**\n * One plan AFTER config-parse-time price resolution: `price` is already\n * integer minor units (or `undefined` for a free plan) — no float ever\n * crosses the config boundary. Every other field is exactly what `plan()`\n * returned.\n */\nexport type ResolvedProduct = Omit<Plan, \"price\"> & { readonly price: ResolvedPlanPrice | undefined };\n\n/** Fully-resolved keyed root: what `createPayweave` consumes. */\nexport interface ResolvedPayweaveConfig {\n /** Configured provider keys in canonical order ({@link PAYWEAVE_PROVIDER_KEYS}). */\n providers: readonly PayweaveProviderKey[];\n defaultProvider: PayweaveProviderKey;\n /** Single client-wide environment — mixed test/live is rejected (rule 4). */\n environment: \"test\" | \"live\";\n /** Per-provider resolved configs keyed by provider. */\n providerConfigs: Readonly<Partial<Record<PayweaveProviderKey, ResolvedProviderConfig>>>;\n database: DatabaseAdapter | undefined;\n /** Cross-plan-validated, minor-units-resolved products. */\n products: readonly ResolvedProduct[] | undefined;\n defaultCurrency: string | undefined;\n timeoutMs: number;\n maxRetries: number;\n fetch: FetchLike | undefined;\n logger: Logger | undefined;\n}\n\n/** Rule 2's exact message. */\nconst AT_LEAST_ONE_PROVIDER =\n \"configure at least one provider — e.g. createPayweave({ stripe: { secretKey } })\";\n\ntype RootParsed = z.output<typeof payweaveConfigSchema>;\n\n/** Drop `undefined` values so an explicit `{ timeoutMs: undefined }` cannot clobber a root default. */\nfunction compact(obj: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) out[key] = value;\n }\n return out;\n}\n\n/** Root transport options merged UNDER each provider key (the sub-config wins). */\nfunction rootTransport(parsed: RootParsed): Record<string, unknown> {\n return compact({\n timeoutMs: parsed.timeoutMs,\n maxRetries: parsed.maxRetries,\n fetch: parsed.fetch,\n logger: parsed.logger,\n environment: parsed.environment,\n });\n}\n\nfunction resolveStripeEntry(\n sub: z.output<typeof stripeProviderConfigSchema>,\n parsed: RootParsed,\n): ResolvedProviderConfig {\n const logger = sub.logger ?? parsed.logger;\n const allowInsecureBaseUrl = sub.allowInsecureBaseUrl ?? false;\n // Rule 4: env is key-inferred; an explicit environment (key-level beats root)\n // that conflicts with the prefix throws inside resolveKeyedEnvironment.\n const environment = resolveKeyedEnvironment(\n \"stripe\",\n sub.secretKey,\n sub.environment ?? parsed.environment,\n );\n const baseUrl = sub.baseUrl ?? STRIPE_BASE_URL;\n guardBaseUrl(baseUrl, allowInsecureBaseUrl, logger, \"stripe\");\n return {\n provider: \"stripe\",\n version: undefined,\n environment,\n baseUrl,\n secretKey: sub.secretKey,\n clientId: undefined,\n clientSecret: undefined,\n encryptionKey: undefined,\n webhookSecret: sub.webhookSecret,\n timeoutMs: sub.timeoutMs ?? parsed.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: sub.maxRetries ?? parsed.maxRetries ?? DEFAULT_MAX_RETRIES,\n fetch: sub.fetch ?? parsed.fetch,\n logger,\n allowInsecureBaseUrl,\n tokenUrl: undefined,\n apiVersion: sub.apiVersion,\n accountId: sub.accountId,\n };\n}\n\n/**\n * Delegate a paystack/flutterwave key to the legacy {@link resolveConfig} —\n * base-URL defaults, the HTTPS guard, v3/v4 handling, and per-key env\n * inference (rule 4's per-key half) are reused rather than re-implemented.\n */\nfunction resolveLegacyEntry(\n key: \"paystack\" | \"flutterwave\",\n sub: object,\n parsed: RootParsed,\n): ResolvedProviderConfig {\n const merged = { ...rootTransport(parsed), ...compact({ ...sub }), provider: key };\n return { ...resolveConfig(merged), apiVersion: undefined };\n}\n\n// ── Cross-plan validation + price resolution ────────────────────────────────\n// These rules need the WHOLE `products` array, unlike `plan()`'s own\n// per-plan checks (cross-plan rules belong to config parse, not there).\n// Every violation here is a {@link PayweaveConfigError} (a config-parse\n// failure); the one exception is the money conversion below, whose\n// decimal-guard/amount-bound failures are the spec-fixed\n// {@link PayweaveValidationError} from `resolvePlanPricing`, propagated\n// unchanged.\n\n/** Rule: plan ids are unique across the whole `products` array. */\nfunction assertUniquePlanIds(products: readonly Plan[]): void {\n const seen = new Set<string>();\n for (const p of products) {\n if (seen.has(p.id)) {\n throw new PayweaveConfigError(\n `duplicate plan id \"${p.id}\" — plan ids must be unique across products.`,\n );\n }\n seen.add(p.id);\n }\n}\n\n/** Rule: at most one `default: true` plan per group. */\nfunction assertOneDefaultPerGroup(products: readonly Plan[]): void {\n const defaultPlanIdByGroup = new Map<string, string>();\n for (const p of products) {\n if (!p.default || p.group === undefined) continue;\n const existing = defaultPlanIdByGroup.get(p.group);\n if (existing !== undefined) {\n throw new PayweaveConfigError(\n `group \"${p.group}\" has more than one default plan (\"${existing}\" and \"${p.id}\") — only one ` +\n \"plan per group can be default: true.\",\n );\n }\n defaultPlanIdByGroup.set(p.group, p.id);\n }\n}\n\n/** Rule: a feature id is never used with conflicting `type`s across plans. */\nfunction assertNoConflictingFeatureTypes(products: readonly Plan[]): void {\n const typeByFeatureId = new Map<string, { type: string; planId: string }>();\n for (const p of products) {\n for (const inclusion of p.includes) {\n const existing = typeByFeatureId.get(inclusion.featureId);\n if (existing === undefined) {\n typeByFeatureId.set(inclusion.featureId, { type: inclusion.type, planId: p.id });\n continue;\n }\n if (existing.type !== inclusion.type) {\n throw new PayweaveConfigError(\n `feature \"${inclusion.featureId}\" is used as both \"${existing.type}\" (plan \"${existing.planId}\") ` +\n `and \"${inclusion.type}\" (plan \"${p.id}\") — a feature must have the same type everywhere.`,\n );\n }\n }\n }\n}\n\n/**\n * Cross-plan validation + price resolution over the WHOLE `products` array —\n * runs once at config parse, after rule 5 (`products` require `database`)\n * has already passed. In order:\n *\n * 1. plan ids are unique across the array;\n * 2. at most one `default: true` plan per group;\n * 3. a feature id is never used with conflicting `type`s across plans;\n * 4. every paid plan resolves a currency (its own, or `defaultCurrency`) and\n * converts to integer minor units via {@link resolvePlanPricing} — \"neither\n * present\" is this function's own {@link PayweaveConfigError}; the\n * decimal-guard/amount-bound failures from `resolvePlanPricing` itself are\n * {@link PayweaveValidationError}, propagated unchanged.\n *\n * Returns `undefined` when `products` was not configured.\n */\nfunction resolveProducts(\n products: readonly Plan[] | undefined,\n defaultCurrency: string | undefined,\n): readonly ResolvedProduct[] | undefined {\n if (products === undefined) return undefined;\n\n assertUniquePlanIds(products);\n assertOneDefaultPerGroup(products);\n assertNoConflictingFeatureTypes(products);\n\n return products.map((p): ResolvedProduct => {\n if (p.price === undefined) {\n return { ...p, price: undefined };\n }\n const currency = p.price.currency ?? defaultCurrency;\n if (currency === undefined) {\n throw new PayweaveConfigError(\n `plan \"${p.id}\": price has no currency — set price.currency or configure defaultCurrency.`,\n );\n }\n return { ...p, price: resolvePlanPricing(p, currency) };\n });\n}\n\n/**\n * Parse + fully resolve a provider-keyed `createPayweave` config, enforcing\n * six resolution rules in order:\n *\n * 1. strict parse — unknown top-level keys throw (typos like `stipe`);\n * 2. at least one provider key;\n * 3. `defaultProvider` (single-provider default / required with multiple /\n * must name a configured key);\n * 4. per-key environment inference (Paystack + Flutterwave-v3 + Stripe key\n * prefixes; Flutterwave v4 explicit), explicit-`environment` conflicts,\n * and mixed-environment rejection across providers;\n * 5. `products` require `database`;\n * 6. Flutterwave's `version` discriminator stays inside its key (v3 default).\n *\n * Throws {@link PayweaveConfigError} synchronously for every violation.\n */\nexport function resolvePayweaveConfig(input: unknown): ResolvedPayweaveConfig {\n // Rule 1 — strict parse.\n let parsed: RootParsed;\n try {\n parsed = payweaveConfigSchema.parse(input);\n } catch (err) {\n throw toConfigError(err);\n }\n\n // Rule 2 — at least one provider key (explicit `undefined` counts as absent).\n const providers = PAYWEAVE_PROVIDER_KEYS.filter((key) => parsed[key] !== undefined);\n const [firstProvider] = providers;\n if (firstProvider === undefined) {\n throw new PayweaveConfigError(AT_LEAST_ONE_PROVIDER);\n }\n\n // Rule 3 — defaultProvider resolution.\n let defaultProvider: PayweaveProviderKey;\n if (parsed.defaultProvider !== undefined) {\n if (!providers.includes(parsed.defaultProvider)) {\n throw new PayweaveConfigError(\n `defaultProvider \"${parsed.defaultProvider}\" is not a configured provider — ` +\n `configured: ${providers.join(\", \")}.`,\n );\n }\n defaultProvider = parsed.defaultProvider;\n } else if (providers.length === 1) {\n defaultProvider = firstProvider;\n } else {\n throw new PayweaveConfigError(\n `multiple providers configured (${providers.join(\", \")}) — set defaultProvider to one of them.`,\n );\n }\n\n // Rule 4 — resolve each key (per-key inference/conflicts throw inside), then\n // check the explicit root environment and mixed environments across keys.\n const providerConfigs: Partial<Record<PayweaveProviderKey, ResolvedProviderConfig>> = {};\n const environments: Array<readonly [PayweaveProviderKey, \"test\" | \"live\"]> = [];\n if (parsed.stripe !== undefined) {\n const entry = resolveStripeEntry(parsed.stripe, parsed);\n providerConfigs.stripe = entry;\n environments.push([\"stripe\", entry.environment]);\n }\n if (parsed.paystack !== undefined) {\n const entry = resolveLegacyEntry(\"paystack\", parsed.paystack, parsed);\n providerConfigs.paystack = entry;\n environments.push([\"paystack\", entry.environment]);\n }\n if (parsed.flutterwave !== undefined) {\n const entry = resolveLegacyEntry(\"flutterwave\", parsed.flutterwave, parsed);\n providerConfigs.flutterwave = entry;\n environments.push([\"flutterwave\", entry.environment]);\n }\n\n if (parsed.environment !== undefined) {\n for (const [key, env] of environments) {\n if (env !== parsed.environment) {\n throw new PayweaveConfigError(\n `environment \"${parsed.environment}\" conflicts with the ${key} provider's ` +\n `resolved environment \"${env}\". Remove the explicit environment or align the ${key} config.`,\n { provider: key },\n );\n }\n }\n }\n\n const distinctEnvs = new Set(environments.map(([, env]) => env));\n if (distinctEnvs.size > 1) {\n const detail = environments.map(([key, env]) => `${key} is \"${env}\"`).join(\", \");\n throw new PayweaveConfigError(\n `mixed environments across providers — ${detail}. ` +\n \"One Payweave client must be all-test or all-live; use separate clients to mix.\",\n );\n }\n const firstEnvironment = environments[0];\n if (firstEnvironment === undefined) {\n // Unreachable: `providers` is non-empty (rule 2) and every key resolved.\n throw new PayweaveConfigError(AT_LEAST_ONE_PROVIDER);\n }\n\n // Rule 5 — products require a database.\n if (parsed.products !== undefined && parsed.database === undefined) {\n throw new PayweaveConfigError(\"plans need a database — pass a payweave/db/* adapter\");\n }\n\n // Cross-plan validation + price resolution needs the whole array, so it\n // happens here rather than inside `plan()`.\n const products = resolveProducts(parsed.products, parsed.defaultCurrency);\n\n return {\n providers,\n defaultProvider,\n environment: firstEnvironment[1],\n providerConfigs,\n database: parsed.database,\n products,\n defaultCurrency: parsed.defaultCurrency,\n timeoutMs: parsed.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: parsed.maxRetries ?? DEFAULT_MAX_RETRIES,\n fetch: parsed.fetch,\n logger: parsed.logger,\n };\n}\n","/**\n * Retry policy (TDD §6.2, PRD §6.4). Full-jitter exponential backoff for\n * network errors and 429/5xx. Eligibility is deliberately conservative: only\n * GETs, or POSTs the caller made idempotent with an `idempotencyKey`. A bare\n * POST (a charge) is NEVER auto-retried.\n */\n\n/** Tunable backoff parameters. */\nexport interface RetryPolicy {\n /** Max retry attempts AFTER the initial try (TDD default: 2). */\n maxRetries: number;\n /** Base backoff in ms (TDD: 250). */\n baseMs: number;\n /** Backoff cap in ms (TDD: 8000). */\n capMs: number;\n}\n\n/** Default retry policy. */\nexport const DEFAULT_RETRY_POLICY: RetryPolicy = {\n maxRetries: 2,\n baseMs: 250,\n capMs: 8_000,\n};\n\n/** HTTP statuses that are retryable (transient) per TDD §6.2. */\nexport const RETRYABLE_STATUSES: ReadonlySet<number> = new Set([429, 500, 502, 503, 504]);\n\n/** `Retry-After` is honored but capped at this ceiling. */\nexport const RETRY_AFTER_CAP_MS = 30_000;\n\n/** True when `status` is one we may retry (given eligibility + attempts left). */\nexport function isRetryableStatus(status: number): boolean {\n return RETRYABLE_STATUSES.has(status);\n}\n\n/**\n * Retry eligibility by method + idempotency. GET is always eligible;\n * any other method is eligible ONLY when the caller supplied an idempotency key.\n * This is what guarantees a bare POST charge is never silently re-sent.\n */\nexport function isRetryableRequest(method: string, idempotencyKey?: string): boolean {\n return method.toUpperCase() === \"GET\" || idempotencyKey != null;\n}\n\n/**\n * Full-jitter backoff: `random(0, min(cap, base * 2^attempt))`.\n * `attempt` is 0-based (0 = first retry). `rng` is injectable for deterministic\n * tests.\n */\nexport function backoffDelay(\n attempt: number,\n policy: RetryPolicy = DEFAULT_RETRY_POLICY,\n rng: () => number = Math.random,\n): number {\n const ceiling = Math.min(policy.capMs, policy.baseMs * 2 ** attempt);\n return Math.floor(rng() * ceiling);\n}\n\n/**\n * Parse a `Retry-After` header value — either delta-seconds or an HTTP-date —\n * into milliseconds, capped at {@link RETRY_AFTER_CAP_MS}. Returns `null` when\n * absent or unparseable (caller falls back to computed backoff).\n *\n * @param headerValue - Raw `Retry-After` header (or `null`).\n * @param now - Current epoch ms (injectable for tests).\n */\nexport function parseRetryAfter(\n headerValue: string | null | undefined,\n now: number = Date.now(),\n): number | null {\n if (headerValue == null) return null;\n const trimmed = headerValue.trim();\n if (trimmed === \"\") return null;\n\n // delta-seconds form\n if (/^\\d+$/.test(trimmed)) {\n const seconds = Number(trimmed);\n return Math.min(seconds * 1000, RETRY_AFTER_CAP_MS);\n }\n\n // HTTP-date form\n const when = Date.parse(trimmed);\n if (!Number.isNaN(when)) {\n return Math.min(Math.max(0, when - now), RETRY_AFTER_CAP_MS);\n }\n return null;\n}\n","/** Single source of truth for the SDK version (mirrors package.json#version). */\nexport const SDK_VERSION = \"0.0.0\";\n","/**\n * HttpClient + pluggable auth strategies. One class backs every\n * resource. Builds URLs, applies auth, enforces timeouts via `AbortSignal`,\n * runs the retry policy, maps non-2xx via {@link mapHttpError}, and\n * emits redacted logger events. Response schemas LOG drift and never throw.\n */\nimport type { ZodType } from \"zod\";\nimport {\n mapHttpError,\n PayweaveError,\n PayweaveAuthError,\n PayweaveNetworkError,\n type PayweaveProvider,\n} from \"./errors\";\nimport type { Logger } from \"./logger\";\nimport { redact } from \"./redact\";\nimport {\n backoffDelay,\n DEFAULT_RETRY_POLICY,\n isRetryableRequest,\n isRetryableStatus,\n parseRetryAfter,\n type RetryPolicy,\n} from \"./retry\";\nimport { SDK_VERSION } from \"./version\";\n\n/**\n * Structural header bag — the subset of `Headers` we read/write. Defined\n * locally because the declaration-rollup step (api-extractor) cannot follow the\n * global `Headers`/`Request`/`Response`/`RequestInit` symbols. The real global\n * `Headers` is assignable to this.\n */\nexport interface HeadersLike {\n get(name: string): string | null;\n set(name: string, value: string): void;\n has(name: string): boolean;\n forEach(callback: (value: string, key: string) => void): void;\n}\n\n/** Structural abort signal — the subset the client passes through. */\nexport interface AbortSignalLike {\n readonly aborted: boolean;\n}\n\n/** Minimal structural request init for {@link FetchLike} (no global DOM types). */\nexport interface FetchRequestInit {\n method?: string;\n headers?: HeadersLike | Record<string, string>;\n body?: string;\n signal?: AbortSignalLike;\n}\n\n/** Minimal structural response — the subset of `Response` the client uses. */\nexport interface FetchResponse {\n readonly ok: boolean;\n readonly status: number;\n readonly headers: HeadersLike;\n text(): Promise<string>;\n json(): Promise<unknown>;\n}\n\n/**\n * Structural `fetch` type — the global `fetch` is assignable to it (via a cast\n * at the injection point). We avoid `typeof fetch` and every global DOM type so\n * the declaration rollup succeeds; injectable for tests/custom runtimes.\n */\nexport type FetchLike = (\n input: string | URL,\n init?: FetchRequestInit,\n) => Promise<FetchResponse>;\n\n/**\n * Pluggable authentication. `bearer` for Paystack + Flutterwave v3; OAuth\n * client-credentials for Flutterwave v4. `applyAuth` mutates the outgoing\n * headers; `refresh` (optional) forces a token refresh for the one-shot 401\n * retry.\n */\nexport interface AuthStrategy {\n applyAuth(init: { headers: HeadersLike }): Promise<void>;\n /** Force a credential refresh (v4 OAuth). Absent for static bearer keys. */\n refresh?(): Promise<void>;\n}\n\n/**\n * An encoded request body: the exact bytes to send plus the `Content-Type`\n * that describes them.\n */\nexport interface EncodedBody {\n contentType: string;\n body: string;\n}\n\n/**\n * Per-provider request-body serializer hook (docs/v1/providers.md §3.1,\n * PW-601). The default is JSON ({@link jsonBodyEncoder}); Stripe injects a\n * deterministic `application/x-www-form-urlencoded` encoder from\n * `src/stripe/form-encoding`. The client invokes the encoder EXACTLY ONCE per\n * `request()` call — every retry re-sends the same encoded bytes, so a\n * non-deterministic encoder can never produce divergent attempts.\n */\nexport type BodyEncoder = (body: unknown) => EncodedBody;\n\n/**\n * Default {@link BodyEncoder}: JSON. Byte-identical to the pre-hook behavior\n * (`Content-Type: application/json` + `JSON.stringify`).\n */\nfunction jsonBodyEncoder(body: unknown): EncodedBody {\n return { contentType: \"application/json\", body: JSON.stringify(body) };\n}\n\n/** Static `Authorization: Bearer <secretKey>` (Paystack, Flutterwave v3). */\nexport function bearer(secretKey: string): AuthStrategy {\n return {\n async applyAuth(init) {\n init.headers.set(\"Authorization\", `Bearer ${secretKey}`);\n },\n };\n}\n\n/** Response shape of the v4 OAuth token endpoint (fields we consume). */\ninterface TokenResponse {\n access_token?: unknown;\n expires_in?: unknown;\n}\n\n/**\n * OAuth 2.0 client-credentials strategy for Flutterwave v4. In-memory token\n * cache with refresh at 80% of TTL, single-flight refresh (concurrent callers\n * await one fetch), and a forced refresh usable for the one-shot 401 retry.\n *\n * ⚠️ VERIFY AT BUILD TIME against the v4 Authentication docs: the exact token\n * endpoint, `grant_type`, request encoding, and the TTL/`expires_in` field.\n */\nexport function oauthClientCredentials(opts: {\n clientId: string;\n clientSecret: string;\n tokenUrl: string;\n fetch?: FetchLike;\n logger?: Logger;\n}): AuthStrategy {\n const doFetch: FetchLike = opts.fetch ?? (fetch as unknown as FetchLike);\n let token: string | null = null;\n let refreshAtMs = 0;\n let inflight: Promise<string> | null = null;\n\n async function fetchToken(): Promise<string> {\n // ⚠️ VERIFY: grant_type/encoding per v4 Authentication docs.\n const body = new URLSearchParams({\n grant_type: \"client_credentials\",\n client_id: opts.clientId,\n client_secret: opts.clientSecret,\n });\n let res: FetchResponse;\n try {\n res = await doFetch(opts.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Accept: \"application/json\",\n },\n body: body.toString(),\n });\n } catch (err) {\n throw new PayweaveNetworkError(\"Failed to reach the Flutterwave v4 token endpoint.\", {\n provider: \"flutterwave\",\n cause: err,\n });\n }\n if (!res.ok) {\n throw new PayweaveAuthError(\n `Flutterwave v4 token request failed (${res.status}).`,\n { provider: \"flutterwave\", httpStatus: res.status },\n );\n }\n const json = (await res.json()) as TokenResponse;\n if (typeof json.access_token !== \"string\") {\n throw new PayweaveAuthError(\"Flutterwave v4 token response had no access_token.\", {\n provider: \"flutterwave\",\n });\n }\n const ttlSeconds = typeof json.expires_in === \"number\" ? json.expires_in : 600;\n // Refresh at 80% of TTL to avoid using a token that expires mid-flight.\n refreshAtMs = Date.now() + ttlSeconds * 1000 * 0.8;\n token = json.access_token;\n return token;\n }\n\n async function getToken(force: boolean): Promise<string> {\n if (!force && token !== null && Date.now() < refreshAtMs) return token;\n // Single-flight: concurrent callers share one in-flight token fetch.\n if (inflight) return inflight;\n inflight = fetchToken().finally(() => {\n inflight = null;\n });\n return inflight;\n }\n\n return {\n async applyAuth(init) {\n const t = await getToken(false);\n init.headers.set(\"Authorization\", `Bearer ${t}`);\n },\n async refresh() {\n await getToken(true);\n },\n };\n}\n\n/**\n * Constructor options for {@link HttpClient}. Optional fields include\n * `undefined` so they can be wired straight from a {@link ResolvedConfig} under\n * `exactOptionalPropertyTypes`.\n */\nexport interface HttpClientOptions {\n baseUrl: string;\n auth: AuthStrategy;\n provider: PayweaveProvider;\n version?: \"v3\" | \"v4\" | undefined;\n timeoutMs?: number | undefined;\n maxRetries?: number | undefined;\n fetch?: FetchLike | undefined;\n logger?: Logger | undefined;\n userAgent?: string | undefined;\n /**\n * Request-body serializer. Omitted → JSON, byte-identical to the\n * historical behavior. Stripe passes its form encoder here so no JSON body\n * ever leaves the Stripe client.\n */\n bodyEncoder?: BodyEncoder | undefined;\n}\n\n/** Query values — `undefined`/`null` entries are dropped from the URL. */\nexport type QueryValue = string | number | boolean | undefined | null;\n\n/** Options for a single {@link HttpClient.request}. */\nexport interface RequestOptions<TRes> {\n method: string;\n path: string;\n query?: Record<string, QueryValue>;\n body?: unknown;\n /** Presence makes a non-GET request retry-eligible. */\n idempotencyKey?: string;\n timeoutMs?: number;\n /** Response schema — drift is logged, never thrown (TDD §6.1 step 6). */\n schema?: ZodType<TRes>;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isAbortError(err: unknown): boolean {\n return (\n err instanceof Error && (err.name === \"AbortError\" || err.name === \"TimeoutError\")\n );\n}\n\n/**\n * The single HTTP client used by every resource. Stateless per request; safe to\n * share across a provider client.\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly auth: AuthStrategy;\n private readonly provider: PayweaveProvider;\n private readonly timeoutMs: number;\n private readonly policy: RetryPolicy;\n private readonly doFetch: FetchLike;\n private readonly logger: Logger | undefined;\n private readonly userAgent: string;\n private readonly encodeBody: BodyEncoder;\n\n constructor(options: HttpClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.auth = options.auth;\n this.provider = options.provider;\n this.timeoutMs = options.timeoutMs ?? 30_000;\n this.policy = {\n ...DEFAULT_RETRY_POLICY,\n maxRetries: options.maxRetries ?? DEFAULT_RETRY_POLICY.maxRetries,\n };\n this.doFetch = options.fetch ?? (fetch as unknown as FetchLike);\n this.logger = options.logger;\n this.userAgent = options.userAgent ?? `payweave/${SDK_VERSION} (${options.provider})`;\n this.encodeBody = options.bodyEncoder ?? jsonBodyEncoder;\n }\n\n private buildUrl(path: string, query?: Record<string, QueryValue>): string {\n const rel = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(this.baseUrl + rel);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n url.searchParams.set(key, String(value));\n }\n }\n return url.toString();\n }\n\n private log(event: Parameters<Logger>[0]): void {\n this.logger?.(event);\n }\n\n /**\n * Execute a request with auth, timeout, retry, and error mapping. On 2xx,\n * JSON-parses and (if `schema` given) `safeParse`s — drift is logged and the\n * raw JSON returned, never thrown.\n */\n async request<TRes = unknown>(opts: RequestOptions<TRes>): Promise<TRes> {\n const method = opts.method.toUpperCase();\n const url = this.buildUrl(opts.path, opts.query);\n const eligible = isRetryableRequest(method, opts.idempotencyKey);\n // Encode the body ONCE, outside the retry loop: every attempt re-sends the\n // exact same bytes, and a bodyEncoder is never re-invoked per attempt\n // (PW-601 — retries must be byte-identical even for a non-pure encoder).\n const encoded = opts.body !== undefined ? this.encodeBody(opts.body) : undefined;\n let attempt = 0;\n let did401Refresh = false;\n\n for (;;) {\n const headers = new Headers();\n headers.set(\"Accept\", \"application/json\");\n headers.set(\"User-Agent\", this.userAgent);\n if (encoded !== undefined) headers.set(\"Content-Type\", encoded.contentType);\n if (opts.idempotencyKey) headers.set(\"Idempotency-Key\", opts.idempotencyKey);\n\n const signal = AbortSignal.timeout(opts.timeoutMs ?? this.timeoutMs);\n\n let res: FetchResponse;\n try {\n // Auth is applied INSIDE the try so a failing token fetch (v4 OAuth\n // client-credentials) is subject to the retry policy and error mapping\n // instead of escaping raw and bypassing retry entirely.\n await this.auth.applyAuth({ headers });\n this.log({\n type: \"request\",\n provider: this.provider,\n method,\n url,\n attempt,\n headers: redact(headers),\n body: redact(opts.body),\n });\n res = await this.doFetch(url, {\n method,\n headers,\n ...(encoded !== undefined ? { body: encoded.body } : {}),\n signal,\n });\n } catch (err) {\n // A PayweaveError from applyAuth (a PayweaveAuthError, or a\n // PayweaveNetworkError from the token endpoint) is preserved as-is —\n // never re-wrapped, so a real auth failure isn't masked as a network\n // error. Only raw fetch/transport errors become PayweaveNetworkError.\n const known = err instanceof PayweaveError;\n const finalErr = known\n ? err\n : new PayweaveNetworkError(\n isAbortError(err)\n ? `Request to ${this.provider} timed out after ${opts.timeoutMs ?? this.timeoutMs}ms.`\n : `Network error contacting ${this.provider}.`,\n { provider: this.provider, cause: err },\n );\n if (eligible && finalErr.isRetryable && attempt < this.policy.maxRetries) {\n const delay = backoffDelay(attempt, this.policy);\n this.log({\n type: \"retry\",\n provider: this.provider,\n attempt,\n reason: known ? \"auth\" : \"network\",\n delay,\n });\n await sleep(delay);\n attempt += 1;\n continue;\n }\n this.log({ type: \"error\", provider: this.provider, error: finalErr.toJSON() });\n throw finalErr;\n }\n\n if (res.ok) {\n const json = await this.readJson(res);\n this.log({\n type: \"response\",\n provider: this.provider,\n status: res.status,\n body: redact(json),\n });\n if (opts.schema) {\n const parsed = opts.schema.safeParse(json);\n if (!parsed.success) {\n // Provider drift MUST NOT break consumers — log and pass raw through.\n this.log({\n type: \"schema_drift\",\n provider: this.provider,\n path: opts.path,\n issues: parsed.error.issues.map((i) => ({\n path: i.path.join(\".\"),\n message: i.message,\n })),\n });\n return json as TRes;\n }\n return parsed.data;\n }\n return json as TRes;\n }\n\n // Non-2xx.\n const errorBody = await this.readJson(res);\n const retryAfterMs = parseRetryAfter(res.headers.get(\"retry-after\"));\n // `request-id` is Stripe's spelling (https://docs.stripe.com/api/errors).\n const requestId =\n res.headers.get(\"x-request-id\") ??\n res.headers.get(\"x-requestid\") ??\n res.headers.get(\"request-id\") ??\n undefined;\n\n // One forced-refresh retry on 401 for OAuth strategies (does not consume\n // a retry attempt — the token was simply stale).\n if (res.status === 401 && this.auth.refresh && !did401Refresh) {\n did401Refresh = true;\n this.log({ type: \"retry\", provider: this.provider, attempt, reason: \"401-refresh\" });\n await this.auth.refresh();\n continue;\n }\n\n if (isRetryableStatus(res.status) && eligible && attempt < this.policy.maxRetries) {\n const delay = retryAfterMs ?? backoffDelay(attempt, this.policy);\n this.log({\n type: \"retry\",\n provider: this.provider,\n attempt,\n reason: `status-${res.status}`,\n delay,\n });\n await sleep(delay);\n attempt += 1;\n continue;\n }\n\n const err = mapHttpError(this.provider, res.status, errorBody, {\n ...(retryAfterMs !== null ? { retryAfterMs } : {}),\n ...(requestId !== undefined ? { requestId } : {}),\n });\n this.log({ type: \"error\", provider: this.provider, error: err.toJSON() });\n throw err;\n }\n }\n\n private async readJson(res: FetchResponse): Promise<unknown> {\n const text = await res.text();\n if (text === \"\") return undefined;\n try {\n return JSON.parse(text);\n } catch {\n // Non-JSON body (HTML error page, etc.) — surface as a string.\n return text;\n }\n }\n}\n","/**\n * Provider adapter contract v2.\n * Third parties (and our own three adapters) implement {@link ProviderAdapter};\n * {@link defineProvider} is the Arcie-style identity helper that also validates\n * the shape at runtime. Adapters may depend ONLY on `core/`; `unified/` depends\n * on adapters, never the reverse.\n *\n * v2 additions over the v1 shape (additive — every v1 field is unchanged):\n * - `configKey` + `configSchema`: the root config key an adapter registers\n * under and the Zod schema validating its slice of config, so third-party\n * adapters can compose onto `createPayweave`'s config WITHOUT core edits\n * - `webhooks.signatureHeader`: the webhook signature header name this\n * adapter's scheme is detected by — the multi-provider\n * dispatcher matches on header NAMES only, never the body.\n * - `unified`: unchanged shape, documented as a PARTIAL surface — an adapter\n * may implement any subset of the unified ops (not every provider supports\n * every op).\n * - `billing`: a typed placeholder for the billing-adapter conformance suite\n * — present so adapters can start declaring the slot, not yet enforced or\n * consumed anywhere.\n */\nimport { z } from \"zod\";\nimport { PayweaveConfigError } from \"./errors\";\nimport type { HttpClient, HeadersLike } from \"./http\";\nimport type { ResolvedProviderConfig } from \"./config\";\n\n/** Per-environment endpoint spec. */\nexport interface EnvSpec {\n baseUrl: string;\n}\n\n/** Case-insensitive header source accepted by webhook verification. */\nexport type HeaderLookup = HeadersLike | Record<string, string | string[] | undefined>;\n\n/**\n * Case-insensitive header lookup shared by adapter webhook verifiers. Accepts\n * a WHATWG `Headers` instance or a plain/array header record — an\n * explicitly-`undefined` record value counts as ABSENT. Mirrors (but does not\n * replace) `webhooks/dispatch.ts`'s own private detection-table lookup; kept\n * here so `core/`-only adapters never need to import from `webhooks/**`.\n */\nexport function readHeader(headers: HeaderLookup, name: string): string | undefined {\n if (typeof Headers !== \"undefined\" && headers instanceof Headers) {\n return headers.get(name) ?? undefined;\n }\n const lower = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lower) {\n return Array.isArray(value) ? value[0] : value;\n }\n }\n return undefined;\n}\n\n/** A provider-native webhook event after parsing (pre-normalization). */\nexport interface ProviderEvent {\n type: string;\n data: unknown;\n raw: unknown;\n id?: string;\n}\n\n/** A normalized, provider-agnostic event (fleshed out by the unified wave). */\nexport interface UnifiedEvent {\n provider: string;\n type: string;\n unifiedType: string;\n data: unknown;\n raw: unknown;\n dedupeKey?: string;\n}\n\n/**\n * Optional unified-layer operations an adapter can implement to join Surface\n * B. Deliberately loose/PARTIAL — a real adapter may (and\n * often does) implement only a subset of `UnifiedNamespace`'s ops; the actual\n * per-op shape lives in `unified/types.ts` (which `core/` never imports —\n * dependency direction is `unified/` → adapters → `core/`, never reversed).\n */\nexport type UnifiedOps = Record<string, unknown>;\n\n/**\n * Billing-adapter conformance slot — a typed placeholder for third-party\n * adapters that want to participate in the billing surface\n * (`subscribe`/`check`/`report`); the shape is intentionally opaque today\n * (mirrors {@link UnifiedOps}'s own looseness) — the conformance suite that\n * gives it real structure and enforces it is separate follow-up work. Not\n * consumed anywhere yet.\n */\nexport type BillingOps = Record<string, unknown>;\n\n/**\n * The contract every provider adapter satisfies. `id` is the\n * adapter's identity; `configKey` is the root config key it registers under\n * (usually equal to `id` — kept separate so a third-party adapter can choose\n * its own key without colliding). `webhooks.verify` runs on raw bytes with a\n * timing-safe comparison; `webhooks.toUnified` uses `unified/mappings.ts`.\n */\nexport interface ProviderAdapter {\n readonly id: string;\n /**\n * Root config key this adapter registers under — the\n * key third-party consumers pass to `createPayweave({ [configKey]: ... })`.\n */\n readonly configKey: string;\n /**\n * Zod schema validating this adapter's slice of the root config. Kept as a\n * loose `z.ZodType` (not generic over a config type) — same \"assert\n * presence/shape, not signatures\" philosophy {@link defineProvider} already\n * uses for the method fields below — so a third-party adapter's own config\n * shape composes onto the root schema without `core/` needing to know it.\n */\n configSchema: z.ZodType;\n readonly environments: { test: EnvSpec; live: EnvSpec };\n inferEnvironment(secretKey: string): \"test\" | \"live\" | null;\n createHttp(cfg: ResolvedProviderConfig): HttpClient;\n webhooks: {\n /**\n * The webhook signature header name this adapter's scheme is detected by\n * (e.g. `\"stripe-signature\"`). Drives multi-provider header dispatch —\n * matched case-insensitively, on the header NAME only.\n */\n signatureHeader: string;\n verify(input: { rawBody: string | Uint8Array; headers: HeaderLookup; secret: string }): boolean;\n parse(rawBody: string): ProviderEvent;\n toUnified(e: ProviderEvent): UnifiedEvent;\n };\n /** Partial unified-ops surface (Surface B) this adapter implements — see {@link UnifiedOps}. */\n unified?: UnifiedOps;\n /** Billing conformance slot (placeholder) — typed, not implemented. */\n billing?: BillingOps;\n}\n\nconst isFn = (v: unknown): boolean => typeof v === \"function\";\nconst fnSchema = z.custom<(...args: never[]) => unknown>(isFn, {\n message: \"expected a function\",\n});\nconst envSpecSchema = z.object({ baseUrl: z.string().min(1) });\nconst zodSchemaSchema = z.custom<z.ZodType>((v) => v instanceof z.ZodType, {\n message: \"expected a zod schema\",\n});\n\n/**\n * Structural runtime schema for a {@link ProviderAdapter}. Kept loose (methods\n * validated as functions) — we assert presence/shape, not signatures.\n */\nconst providerAdapterSchema = z.object({\n id: z.string().min(1),\n configKey: z.string().min(1),\n configSchema: zodSchemaSchema,\n environments: z.object({ test: envSpecSchema, live: envSpecSchema }),\n inferEnvironment: fnSchema,\n createHttp: fnSchema,\n webhooks: z.object({\n signatureHeader: z.string().min(1),\n verify: fnSchema,\n parse: fnSchema,\n toUnified: fnSchema,\n }),\n unified: z.record(z.string(), z.unknown()).optional(),\n billing: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Identity helper that validates an adapter's shape at runtime (Arcie `define*`\n * pattern). Returns the same object (typed) on success; throws\n * {@link PayweaveConfigError} describing the first structural problem otherwise.\n *\n * @example\n * const myProvider = defineProvider({ id: \"acme\", configKey: \"acme\", configSchema, ... });\n */\nexport function defineProvider(adapter: ProviderAdapter): ProviderAdapter {\n const result = providerAdapterSchema.safeParse(adapter);\n if (!result.success) {\n const detail = result.error.issues\n .map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"; \");\n throw new PayweaveConfigError(`Invalid provider adapter — ${detail}`);\n }\n return adapter;\n}\n"]}
@@ -0,0 +1,326 @@
1
+ import { money, toMajor, toMinor } from './chunk-TWZK62TZ.js';
2
+ import { toUnifiedStatus } from './chunk-67NRYGRC.js';
3
+ import { PayweaveNotFoundError } from './chunk-HTRGMZFH.js';
4
+ import { randomUUID } from 'crypto';
5
+
6
+ function generateReference() {
7
+ return `pwv_${randomUUID().replace(/-/g, "")}`;
8
+ }
9
+
10
+ // src/unified/internal.ts
11
+ function asRecord(value) {
12
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
13
+ return value;
14
+ }
15
+ return void 0;
16
+ }
17
+ function asRecordArray(value) {
18
+ if (!Array.isArray(value)) return [];
19
+ const out = [];
20
+ for (const item of value) {
21
+ const rec = asRecord(item);
22
+ if (rec) out.push(rec);
23
+ }
24
+ return out;
25
+ }
26
+ function readString(rec, key) {
27
+ const v = rec?.[key];
28
+ return typeof v === "string" ? v : void 0;
29
+ }
30
+ function readNumber(rec, key) {
31
+ const v = rec?.[key];
32
+ return typeof v === "number" ? v : void 0;
33
+ }
34
+ function envelopeData(envelope) {
35
+ return asRecord(asRecord(envelope)?.data);
36
+ }
37
+ function envelopeDataArray(envelope) {
38
+ return asRecordArray(asRecord(envelope)?.data);
39
+ }
40
+
41
+ // src/unified/paystack.ts
42
+ function createPaystackUnified(http) {
43
+ return {
44
+ checkout: {
45
+ async create(input) {
46
+ const reference = input.reference ?? generateReference();
47
+ const body = {
48
+ email: input.customer.email,
49
+ amount: input.amount.value,
50
+ currency: input.amount.currency,
51
+ reference
52
+ };
53
+ if (input.redirectUrl !== void 0) body.callback_url = input.redirectUrl;
54
+ if (input.metadata !== void 0) body.metadata = input.metadata;
55
+ const raw = await http.request({
56
+ method: "POST",
57
+ path: "/transaction/initialize",
58
+ body
59
+ });
60
+ const data = envelopeData(raw);
61
+ return {
62
+ checkoutUrl: readString(data, "authorization_url") ?? "",
63
+ reference,
64
+ providerRef: readString(data, "reference") ?? readString(data, "access_code"),
65
+ raw
66
+ };
67
+ }
68
+ },
69
+ async verify(input) {
70
+ const raw = await http.request({
71
+ method: "GET",
72
+ path: `/transaction/verify/${encodeURIComponent(input.reference)}`
73
+ });
74
+ const data = envelopeData(raw);
75
+ const currency = readString(data, "currency") ?? "NGN";
76
+ const amountValue = readNumber(data, "amount") ?? 0;
77
+ const customer = asRecord(data?.customer);
78
+ return {
79
+ status: toUnifiedStatus("paystack", void 0, readString(data, "status")),
80
+ amount: money(amountValue, currency),
81
+ customer: {
82
+ email: readString(customer, "email"),
83
+ name: readString(customer, "name")
84
+ },
85
+ paidAt: readString(data, "paid_at"),
86
+ channel: readString(data, "channel"),
87
+ raw
88
+ };
89
+ },
90
+ refunds: {
91
+ async create(input) {
92
+ const body = { transaction: input.reference };
93
+ if (input.amount !== void 0) {
94
+ body.amount = input.amount.value;
95
+ body.currency = input.amount.currency;
96
+ }
97
+ const raw = await http.request({
98
+ method: "POST",
99
+ path: "/refund",
100
+ body
101
+ });
102
+ const data = envelopeData(raw);
103
+ const id = readNumber(data, "id");
104
+ return {
105
+ providerRef: id !== void 0 ? String(id) : void 0,
106
+ status: readString(data, "status"),
107
+ raw
108
+ };
109
+ }
110
+ },
111
+ transfers: {
112
+ async create(input) {
113
+ const reference = input.reference ?? generateReference();
114
+ const recipientRaw = await http.request({
115
+ method: "POST",
116
+ path: "/transferrecipient",
117
+ body: {
118
+ type: input.recipient.type ?? "nuban",
119
+ name: input.recipient.name ?? input.recipient.accountNumber,
120
+ account_number: input.recipient.accountNumber,
121
+ bank_code: input.recipient.bankCode,
122
+ currency: input.currency
123
+ }
124
+ });
125
+ const recipientCode = readString(envelopeData(recipientRaw), "recipient_code");
126
+ const body = {
127
+ source: "balance",
128
+ amount: input.amount,
129
+ // minor units pass through
130
+ recipient: recipientCode,
131
+ currency: input.currency,
132
+ reference
133
+ };
134
+ if (input.reason !== void 0) body.reason = input.reason;
135
+ const raw = await http.request({
136
+ method: "POST",
137
+ path: "/transfer",
138
+ body
139
+ });
140
+ const data = envelopeData(raw);
141
+ return {
142
+ reference,
143
+ providerRef: readString(data, "transfer_code"),
144
+ status: toUnifiedStatus("paystack", void 0, readString(data, "status")),
145
+ raw
146
+ };
147
+ }
148
+ },
149
+ banks: {
150
+ async list(input) {
151
+ const raw = await http.request({
152
+ method: "GET",
153
+ path: "/bank",
154
+ query: { country: input.country }
155
+ });
156
+ return envelopeDataArray(raw).map((bank) => ({
157
+ name: readString(bank, "name"),
158
+ code: readString(bank, "code"),
159
+ raw: bank
160
+ }));
161
+ },
162
+ async resolveAccount(input) {
163
+ const raw = await http.request({
164
+ method: "GET",
165
+ path: "/bank/resolve",
166
+ query: { account_number: input.accountNumber, bank_code: input.bankCode }
167
+ });
168
+ const data = envelopeData(raw);
169
+ return {
170
+ accountNumber: readString(data, "account_number"),
171
+ accountName: readString(data, "account_name"),
172
+ raw
173
+ };
174
+ }
175
+ }
176
+ };
177
+ }
178
+
179
+ // src/unified/flutterwave.ts
180
+ function createFlutterwaveUnified(http, version) {
181
+ return {
182
+ checkout: {
183
+ async create(input) {
184
+ const reference = input.reference ?? generateReference();
185
+ const amountMajor = toMajor(money(input.amount.value, input.amount.currency));
186
+ const customer = { email: input.customer.email };
187
+ if (input.customer.name !== void 0) customer.name = input.customer.name;
188
+ if (input.customer.phone !== void 0) customer.phonenumber = input.customer.phone;
189
+ const body = {
190
+ tx_ref: reference,
191
+ amount: amountMajor,
192
+ currency: input.amount.currency,
193
+ customer
194
+ };
195
+ if (input.redirectUrl !== void 0) body.redirect_url = input.redirectUrl;
196
+ if (input.metadata !== void 0) body.meta = input.metadata;
197
+ const raw = await http.request({
198
+ method: "POST",
199
+ path: "/payments",
200
+ body
201
+ });
202
+ const data = envelopeData(raw);
203
+ return {
204
+ checkoutUrl: readString(data, "link") ?? "",
205
+ reference,
206
+ // The create response is tx_ref-based (no flw_ref yet); fall back to it.
207
+ providerRef: readString(data, "flw_ref") ?? reference,
208
+ raw
209
+ };
210
+ }
211
+ },
212
+ async verify(input) {
213
+ const raw = await http.request({
214
+ method: "GET",
215
+ path: "/transactions/verify_by_reference",
216
+ query: { tx_ref: input.reference }
217
+ });
218
+ const data = envelopeData(raw);
219
+ const currency = readString(data, "currency") ?? "NGN";
220
+ const amountMajor = readNumber(data, "amount") ?? 0;
221
+ const customer = asRecord(data?.customer);
222
+ return {
223
+ status: toUnifiedStatus("flutterwave", version, readString(data, "status")),
224
+ amount: toMinor(amountMajor, currency),
225
+ customer: {
226
+ email: readString(customer, "email"),
227
+ name: readString(customer, "name")
228
+ },
229
+ // v3 has no explicit paid_at on the txn — fall back to created_at.
230
+ paidAt: readString(data, "paid_at") ?? readString(data, "created_at"),
231
+ channel: readString(data, "payment_type"),
232
+ raw
233
+ };
234
+ },
235
+ refunds: {
236
+ async create(input) {
237
+ const verifyRaw = await http.request({
238
+ method: "GET",
239
+ path: "/transactions/verify_by_reference",
240
+ query: { tx_ref: input.reference }
241
+ });
242
+ const txId = readNumber(envelopeData(verifyRaw), "id");
243
+ if (txId === void 0) {
244
+ throw new PayweaveNotFoundError(
245
+ `Could not resolve a Flutterwave transaction id for reference "${input.reference}".`,
246
+ { provider: "flutterwave", raw: verifyRaw }
247
+ );
248
+ }
249
+ const body = {};
250
+ if (input.amount !== void 0) {
251
+ body.amount = toMajor(money(input.amount.value, input.amount.currency));
252
+ }
253
+ const raw = await http.request({
254
+ method: "POST",
255
+ path: `/transactions/${String(txId)}/refund`,
256
+ body
257
+ });
258
+ const data = envelopeData(raw);
259
+ const id = readNumber(data, "id");
260
+ return {
261
+ providerRef: id !== void 0 ? String(id) : void 0,
262
+ status: readString(data, "status"),
263
+ raw
264
+ };
265
+ }
266
+ },
267
+ transfers: {
268
+ async create(input) {
269
+ const reference = input.reference ?? generateReference();
270
+ const amountMajor = toMajor(money(input.amount, input.currency));
271
+ const body = {
272
+ account_bank: input.recipient.bankCode,
273
+ account_number: input.recipient.accountNumber,
274
+ amount: amountMajor,
275
+ currency: input.currency,
276
+ reference
277
+ };
278
+ if (input.reason !== void 0) body.narration = input.reason;
279
+ if (input.recipient.name !== void 0) body.beneficiary_name = input.recipient.name;
280
+ const raw = await http.request({
281
+ method: "POST",
282
+ path: "/transfers",
283
+ body
284
+ });
285
+ const data = envelopeData(raw);
286
+ const id = readNumber(data, "id");
287
+ return {
288
+ reference,
289
+ providerRef: id !== void 0 ? String(id) : void 0,
290
+ status: toUnifiedStatus("flutterwave", version, readString(data, "status")),
291
+ raw
292
+ };
293
+ }
294
+ },
295
+ banks: {
296
+ async list(input) {
297
+ const raw = await http.request({
298
+ method: "GET",
299
+ path: `/banks/${encodeURIComponent(input.country)}`
300
+ });
301
+ return envelopeDataArray(raw).map((bank) => ({
302
+ name: readString(bank, "name"),
303
+ code: readString(bank, "code"),
304
+ raw: bank
305
+ }));
306
+ },
307
+ async resolveAccount(input) {
308
+ const raw = await http.request({
309
+ method: "POST",
310
+ path: "/accounts/resolve",
311
+ body: { account_number: input.accountNumber, account_bank: input.bankCode }
312
+ });
313
+ const data = envelopeData(raw);
314
+ return {
315
+ accountNumber: readString(data, "account_number"),
316
+ accountName: readString(data, "account_name"),
317
+ raw
318
+ };
319
+ }
320
+ }
321
+ };
322
+ }
323
+
324
+ export { createFlutterwaveUnified, createPaystackUnified, generateReference };
325
+ //# sourceMappingURL=chunk-JD4OZHRI.js.map
326
+ //# sourceMappingURL=chunk-JD4OZHRI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/unified/reference.ts","../src/unified/internal.ts","../src/unified/paystack.ts","../src/unified/flutterwave.ts"],"names":[],"mappings":"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","file":"chunk-JD4OZHRI.js","sourcesContent":["/**\n * Unified-layer reference generator (PRD §6.2 / §4). When a consumer omits\n * `reference` on a unified op, the SDK generates one and returns it in the\n * result. The `pwv_` prefix is mandated by the naming rules and is\n * deliberately NOT `pk_` (that collides with Paystack's public-key prefix).\n *\n * No existing generator lives in `core/` (checked: `core/` has no ulid/reference\n * helper), so this implements one with `node:crypto`'s `randomUUID` — the\n * dashes are stripped to give a compact, opaque, ULID-shaped token. `uuidv7`\n * (ordered) is only worth pulling in if lexical ordering is needed; it is not\n * here, and `zod`+`node:crypto`+`fetch` is the only-runtime-deps rule.\n */\nimport { randomUUID } from \"node:crypto\";\n\n/** Generate a fresh unified reference, e.g. `pwv_9f8c1e2a...`. */\nexport function generateReference(): string {\n return `pwv_${randomUUID().replace(/-/g, \"\")}`;\n}\n","/**\n * Internal, type-safe readers for provider response envelopes used by the\n * unified layer. The unified ops call `http.request` WITHOUT a response schema\n * (staying decoupled from Surface A schemas), so responses arrive as `unknown` —\n * these helpers narrow them without ever reaching for `any`.\n *\n * Both providers wrap payloads in `{ status, message, data }` (Paystack `status`\n * is a boolean; Flutterwave's is the string `\"success\"`); either way the useful\n * payload is under `data`. `raw` on every unified result is the WHOLE envelope.\n */\n\n/** Narrow an unknown to a plain object, or `undefined`. */\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return undefined;\n}\n\n/** Narrow an unknown to an array of records (drops non-object entries). */\nexport function asRecordArray(value: unknown): Record<string, unknown>[] {\n if (!Array.isArray(value)) return [];\n const out: Record<string, unknown>[] = [];\n for (const item of value) {\n const rec = asRecord(item);\n if (rec) out.push(rec);\n }\n return out;\n}\n\n/** Read a string field from a record, or `undefined`. */\nexport function readString(\n rec: Record<string, unknown> | undefined,\n key: string,\n): string | undefined {\n const v = rec?.[key];\n return typeof v === \"string\" ? v : undefined;\n}\n\n/** Read a numeric field from a record, or `undefined`. */\nexport function readNumber(\n rec: Record<string, unknown> | undefined,\n key: string,\n): number | undefined {\n const v = rec?.[key];\n return typeof v === \"number\" ? v : undefined;\n}\n\n/** The `data` object out of a `{ status, message, data }` envelope. */\nexport function envelopeData(envelope: unknown): Record<string, unknown> | undefined {\n return asRecord(asRecord(envelope)?.data);\n}\n\n/** The `data` array out of a `{ status, message, data: [...] }` envelope. */\nexport function envelopeDataArray(envelope: unknown): Record<string, unknown>[] {\n return asRecordArray(asRecord(envelope)?.data);\n}\n","/**\n * Paystack unified-layer implementation (Surface B, PRD §6.2). Routes the six\n * unified ops to Paystack REST endpoints via `http.request` directly — this\n * keeps `unified/` decoupled from the Surface A resource classes while reusing\n * the same shared {@link HttpClient} (auth, retries, error mapping, redaction).\n *\n * Amount contract: the unified layer speaks MINOR units and Paystack ALSO uses\n * minor units (kobo), so amounts pass through unchanged (provider-reference §1).\n * Status is normalized through `toUnifiedStatus(\"paystack\", …)`.\n */\nimport type { HttpClient } from \"../core/http\";\nimport { money } from \"../core/money\";\nimport { toUnifiedStatus } from \"./mappings\";\nimport { generateReference } from \"./reference\";\nimport {\n asRecord,\n envelopeData,\n envelopeDataArray,\n readNumber,\n readString,\n} from \"./internal\";\nimport type {\n BanksListInput,\n CheckoutCreateInput,\n CheckoutCreateResult,\n RefundCreateInput,\n RefundCreateResult,\n ResolveAccountInput,\n ResolvedAccountResult,\n TransferCreateInput,\n TransferCreateResult,\n UnifiedBank,\n UnifiedNamespace,\n VerifyInput,\n VerifyResult,\n} from \"./types\";\n\n/** Build the Paystack unified namespace over a shared {@link HttpClient}. */\nexport function createPaystackUnified(http: HttpClient): UnifiedNamespace {\n return {\n checkout: {\n async create(input: CheckoutCreateInput): Promise<CheckoutCreateResult> {\n const reference = input.reference ?? generateReference();\n // Paystack amounts are kobo (minor) — the unified `value` passes through.\n const body: Record<string, unknown> = {\n email: input.customer.email,\n amount: input.amount.value,\n currency: input.amount.currency,\n reference,\n };\n if (input.redirectUrl !== undefined) body.callback_url = input.redirectUrl;\n if (input.metadata !== undefined) body.metadata = input.metadata;\n\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/transaction/initialize\",\n body,\n });\n const data = envelopeData(raw);\n return {\n checkoutUrl: readString(data, \"authorization_url\") ?? \"\",\n reference,\n providerRef: readString(data, \"reference\") ?? readString(data, \"access_code\"),\n raw,\n };\n },\n },\n\n async verify(input: VerifyInput): Promise<VerifyResult> {\n // Paystack verifies by reference (provider-reference §5.2). A 404 surfaces\n // as PayweaveNotFoundError from http.request's error map — never swallowed.\n const raw = await http.request<unknown>({\n method: \"GET\",\n path: `/transaction/verify/${encodeURIComponent(input.reference)}`,\n });\n const data = envelopeData(raw);\n const currency = readString(data, \"currency\") ?? \"NGN\";\n // Paystack amount is already MINOR units (kobo) — wrap as Money directly.\n const amountValue = readNumber(data, \"amount\") ?? 0;\n const customer = asRecord(data?.customer);\n return {\n status: toUnifiedStatus(\"paystack\", undefined, readString(data, \"status\")),\n amount: money(amountValue, currency),\n customer: {\n email: readString(customer, \"email\"),\n name: readString(customer, \"name\"),\n },\n paidAt: readString(data, \"paid_at\"),\n channel: readString(data, \"channel\"),\n raw,\n };\n },\n\n refunds: {\n async create(input: RefundCreateInput): Promise<RefundCreateResult> {\n // POST /refund — `transaction` accepts the reference; amount in kobo.\n const body: Record<string, unknown> = { transaction: input.reference };\n if (input.amount !== undefined) {\n body.amount = input.amount.value; // already minor units\n body.currency = input.amount.currency;\n }\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/refund\",\n body,\n });\n const data = envelopeData(raw);\n const id = readNumber(data, \"id\");\n return {\n providerRef: id !== undefined ? String(id) : undefined,\n status: readString(data, \"status\"),\n raw,\n };\n },\n },\n\n transfers: {\n async create(input: TransferCreateInput): Promise<TransferCreateResult> {\n const reference = input.reference ?? generateReference();\n // Two-step (Paystack has no single \"transfer to account\" call): create a\n // transfer recipient to obtain an RCP_… code, then initiate the transfer.\n // NOTE(verify): the recipient `type` defaults to \"nuban\"; other rails\n // (mobile_money/basa) need the caller to pass `recipient.type`.\n const recipientRaw = await http.request<unknown>({\n method: \"POST\",\n path: \"/transferrecipient\",\n body: {\n type: input.recipient.type ?? \"nuban\",\n name: input.recipient.name ?? input.recipient.accountNumber,\n account_number: input.recipient.accountNumber,\n bank_code: input.recipient.bankCode,\n currency: input.currency,\n },\n });\n const recipientCode = readString(envelopeData(recipientRaw), \"recipient_code\");\n\n const body: Record<string, unknown> = {\n source: \"balance\",\n amount: input.amount, // minor units pass through\n recipient: recipientCode,\n currency: input.currency,\n reference,\n };\n if (input.reason !== undefined) body.reason = input.reason;\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/transfer\",\n body,\n });\n const data = envelopeData(raw);\n return {\n reference,\n providerRef: readString(data, \"transfer_code\"),\n status: toUnifiedStatus(\"paystack\", undefined, readString(data, \"status\")),\n raw,\n };\n },\n },\n\n banks: {\n async list(input: BanksListInput): Promise<UnifiedBank[]> {\n const raw = await http.request<unknown>({\n method: \"GET\",\n path: \"/bank\",\n query: { country: input.country },\n });\n return envelopeDataArray(raw).map((bank) => ({\n name: readString(bank, \"name\"),\n code: readString(bank, \"code\"),\n raw: bank,\n }));\n },\n\n async resolveAccount(input: ResolveAccountInput): Promise<ResolvedAccountResult> {\n const raw = await http.request<unknown>({\n method: \"GET\",\n path: \"/bank/resolve\",\n query: { account_number: input.accountNumber, bank_code: input.bankCode },\n });\n const data = envelopeData(raw);\n return {\n accountNumber: readString(data, \"account_number\"),\n accountName: readString(data, \"account_name\"),\n raw,\n };\n },\n },\n };\n}\n","/**\n * Flutterwave (v3) unified-layer implementation (Surface B, PRD §6.2). Routes\n * the six unified ops to Flutterwave v3 REST endpoints via `http.request`\n * directly, keeping `unified/` decoupled from the Surface A resource classes.\n *\n * Amount contract: the unified layer speaks MINOR units but Flutterwave v3 uses\n * MAJOR units (provider-reference §1), so this adapter converts on the way out\n * (`toMajor`) and back on the way in (`toMinor`) using core Money — integer-safe,\n * never float math. Status is normalized via `toUnifiedStatus(\"flutterwave\", …)`.\n *\n * NOTE(verify): the endpoints/paths here are Flutterwave **v3**. v4 is a\n * different generation (OAuth, restructured payloads, `succeeded` status vocab)\n * and would need its own unified impl; the `version` is threaded through only so\n * status normalization uses the right vocabulary if a v4 client reaches here.\n */\nimport type { HttpClient } from \"../core/http\";\nimport { PayweaveNotFoundError } from \"../core/errors\";\nimport { money, toMajor, toMinor } from \"../core/money\";\nimport { toUnifiedStatus, type MappingVersion } from \"./mappings\";\nimport { generateReference } from \"./reference\";\nimport {\n asRecord,\n envelopeData,\n envelopeDataArray,\n readNumber,\n readString,\n} from \"./internal\";\nimport type {\n BanksListInput,\n CheckoutCreateInput,\n CheckoutCreateResult,\n RefundCreateInput,\n RefundCreateResult,\n ResolveAccountInput,\n ResolvedAccountResult,\n TransferCreateInput,\n TransferCreateResult,\n UnifiedBank,\n UnifiedNamespace,\n VerifyInput,\n VerifyResult,\n} from \"./types\";\n\n/** Build the Flutterwave unified namespace over a shared {@link HttpClient}. */\nexport function createFlutterwaveUnified(\n http: HttpClient,\n version: MappingVersion,\n): UnifiedNamespace {\n return {\n checkout: {\n async create(input: CheckoutCreateInput): Promise<CheckoutCreateResult> {\n const reference = input.reference ?? generateReference();\n // Unified minor units → Flutterwave major units (e.g. 500000 kobo → 5000).\n const amountMajor = toMajor(money(input.amount.value, input.amount.currency));\n const customer: Record<string, unknown> = { email: input.customer.email };\n if (input.customer.name !== undefined) customer.name = input.customer.name;\n if (input.customer.phone !== undefined) customer.phonenumber = input.customer.phone;\n\n const body: Record<string, unknown> = {\n tx_ref: reference,\n amount: amountMajor,\n currency: input.amount.currency,\n customer,\n };\n if (input.redirectUrl !== undefined) body.redirect_url = input.redirectUrl;\n if (input.metadata !== undefined) body.meta = input.metadata;\n\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/payments\",\n body,\n });\n const data = envelopeData(raw);\n return {\n checkoutUrl: readString(data, \"link\") ?? \"\",\n reference,\n // The create response is tx_ref-based (no flw_ref yet); fall back to it.\n providerRef: readString(data, \"flw_ref\") ?? reference,\n raw,\n };\n },\n },\n\n async verify(input: VerifyInput): Promise<VerifyResult> {\n // Flutterwave verifies by tx_ref via a dedicated endpoint (the by-id verify\n // needs the numeric id). A 404 surfaces as PayweaveNotFoundError.\n const raw = await http.request<unknown>({\n method: \"GET\",\n path: \"/transactions/verify_by_reference\",\n query: { tx_ref: input.reference },\n });\n const data = envelopeData(raw);\n const currency = readString(data, \"currency\") ?? \"NGN\";\n // Flutterwave amount is MAJOR units — convert back to minor units (Money).\n const amountMajor = readNumber(data, \"amount\") ?? 0;\n const customer = asRecord(data?.customer);\n return {\n status: toUnifiedStatus(\"flutterwave\", version, readString(data, \"status\")),\n amount: toMinor(amountMajor, currency),\n customer: {\n email: readString(customer, \"email\"),\n name: readString(customer, \"name\"),\n },\n // v3 has no explicit paid_at on the txn — fall back to created_at.\n paidAt: readString(data, \"paid_at\") ?? readString(data, \"created_at\"),\n channel: readString(data, \"payment_type\"),\n raw,\n };\n },\n\n refunds: {\n async create(input: RefundCreateInput): Promise<RefundCreateResult> {\n // Flutterwave refunds are keyed by the numeric transaction id, not the\n // reference. Two-step: resolve the tx_ref to an id via verify_by_reference,\n // then POST /transactions/:id/refund (amount converted to major units).\n const verifyRaw = await http.request<unknown>({\n method: \"GET\",\n path: \"/transactions/verify_by_reference\",\n query: { tx_ref: input.reference },\n });\n const txId = readNumber(envelopeData(verifyRaw), \"id\");\n if (txId === undefined) {\n // Guard: an unresolved reference would otherwise POST to\n // /transactions/undefined/refund and yield a misleading 4xx.\n throw new PayweaveNotFoundError(\n `Could not resolve a Flutterwave transaction id for reference \"${input.reference}\".`,\n { provider: \"flutterwave\", raw: verifyRaw },\n );\n }\n\n const body: Record<string, unknown> = {};\n if (input.amount !== undefined) {\n body.amount = toMajor(money(input.amount.value, input.amount.currency));\n }\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: `/transactions/${String(txId)}/refund`,\n body,\n });\n const data = envelopeData(raw);\n const id = readNumber(data, \"id\");\n return {\n providerRef: id !== undefined ? String(id) : undefined,\n status: readString(data, \"status\"),\n raw,\n };\n },\n },\n\n transfers: {\n async create(input: TransferCreateInput): Promise<TransferCreateResult> {\n const reference = input.reference ?? generateReference();\n // Flutterwave takes raw account details on the transfer itself (no\n // separate recipient object like Paystack). NOTE(verify): recipient\n // `type` is Paystack-only and is ignored here.\n const amountMajor = toMajor(money(input.amount, input.currency));\n const body: Record<string, unknown> = {\n account_bank: input.recipient.bankCode,\n account_number: input.recipient.accountNumber,\n amount: amountMajor,\n currency: input.currency,\n reference,\n };\n if (input.reason !== undefined) body.narration = input.reason;\n if (input.recipient.name !== undefined) body.beneficiary_name = input.recipient.name;\n\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/transfers\",\n body,\n });\n const data = envelopeData(raw);\n const id = readNumber(data, \"id\");\n return {\n reference,\n providerRef: id !== undefined ? String(id) : undefined,\n status: toUnifiedStatus(\"flutterwave\", version, readString(data, \"status\")),\n raw,\n };\n },\n },\n\n banks: {\n async list(input: BanksListInput): Promise<UnifiedBank[]> {\n const raw = await http.request<unknown>({\n method: \"GET\",\n path: `/banks/${encodeURIComponent(input.country)}`,\n });\n return envelopeDataArray(raw).map((bank) => ({\n name: readString(bank, \"name\"),\n code: readString(bank, \"code\"),\n raw: bank,\n }));\n },\n\n async resolveAccount(input: ResolveAccountInput): Promise<ResolvedAccountResult> {\n const raw = await http.request<unknown>({\n method: \"POST\",\n path: \"/accounts/resolve\",\n body: { account_number: input.accountNumber, account_bank: input.bankCode },\n });\n const data = envelopeData(raw);\n return {\n accountNumber: readString(data, \"account_number\"),\n accountName: readString(data, \"account_name\"),\n raw,\n };\n },\n },\n };\n}\n"]}