@mesub/node 0.1.5 → 0.1.6

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 (58) hide show
  1. package/README.md +18 -5
  2. package/dist/{chunk-43Q4PNF7.cjs → chunk-4M3ACBWX.cjs} +28 -2
  3. package/dist/chunk-4M3ACBWX.cjs.map +1 -0
  4. package/dist/{chunk-D3MM42ZL.cjs → chunk-5LDAYKUA.cjs} +7 -7
  5. package/dist/{chunk-D3MM42ZL.cjs.map → chunk-5LDAYKUA.cjs.map} +1 -1
  6. package/dist/{chunk-SFK52JDW.cjs → chunk-5THDILDD.cjs} +16 -3
  7. package/dist/chunk-5THDILDD.cjs.map +1 -0
  8. package/dist/{chunk-ELS6KPJQ.js → chunk-ANBU7BJU.js} +2 -2
  9. package/dist/{chunk-PH5LR5WA.js → chunk-EGGKTDHO.js} +2 -2
  10. package/dist/{chunk-IHGJN3QZ.js → chunk-QDBKSJ56.js} +16 -3
  11. package/dist/chunk-QDBKSJ56.js.map +1 -0
  12. package/dist/{chunk-JJWHMB2X.js → chunk-R4H46TSQ.js} +28 -2
  13. package/dist/chunk-R4H46TSQ.js.map +1 -0
  14. package/dist/{chunk-6XJWKRCN.cjs → chunk-TDRUSUBV.cjs} +4 -4
  15. package/dist/{chunk-6XJWKRCN.cjs.map → chunk-TDRUSUBV.cjs.map} +1 -1
  16. package/dist/{client-BZB6KIGd.d.cts → client-B2DttW-V.d.cts} +18 -2
  17. package/dist/{client-Q5QhXphp.d.ts → client-BHrc_yO3.d.ts} +18 -2
  18. package/dist/{errors-BN4ZWUfM.d.ts → errors-CTFJfJoF.d.ts} +1 -1
  19. package/dist/{errors-DcLfunS-.d.cts → errors-xk1hGCOf.d.cts} +1 -1
  20. package/dist/express.cjs +21 -21
  21. package/dist/express.d.cts +7 -7
  22. package/dist/express.d.ts +7 -7
  23. package/dist/express.js +3 -3
  24. package/dist/{guard-D4AB5HtN.d.cts → guard-CDC9mDWY.d.cts} +1 -1
  25. package/dist/{guard-CaXiHMVF.d.ts → guard-CrGTKKXV.d.ts} +1 -1
  26. package/dist/index.cjs +3 -3
  27. package/dist/index.d.cts +5 -5
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.js +2 -2
  30. package/dist/nest.cjs +13 -13
  31. package/dist/nest.d.cts +5 -5
  32. package/dist/nest.d.ts +5 -5
  33. package/dist/nest.js +2 -2
  34. package/dist/next.cjs +20 -20
  35. package/dist/next.d.cts +7 -7
  36. package/dist/next.d.ts +7 -7
  37. package/dist/next.js +3 -3
  38. package/dist/{routes-DT8EFWSl.d.cts → routes-BpOV9UAR.d.cts} +2 -2
  39. package/dist/{routes-KoaD1Xsk.d.ts → routes-DWhspa6s.d.ts} +2 -2
  40. package/dist/situations.cjs +2 -2
  41. package/dist/situations.d.cts +41 -1
  42. package/dist/situations.d.ts +41 -1
  43. package/dist/situations.js +1 -1
  44. package/dist/{subscriptions-B6Lin6i_.d.ts → subscriptions-Dy_BNyPE.d.cts} +6 -3
  45. package/dist/{subscriptions-B6Lin6i_.d.cts → subscriptions-Dy_BNyPE.d.ts} +6 -3
  46. package/dist/testing.cjs +19 -15
  47. package/dist/testing.cjs.map +1 -1
  48. package/dist/testing.d.cts +9 -6
  49. package/dist/testing.d.ts +9 -6
  50. package/dist/testing.js +5 -1
  51. package/dist/testing.js.map +1 -1
  52. package/package.json +1 -1
  53. package/dist/chunk-43Q4PNF7.cjs.map +0 -1
  54. package/dist/chunk-IHGJN3QZ.js.map +0 -1
  55. package/dist/chunk-JJWHMB2X.js.map +0 -1
  56. package/dist/chunk-SFK52JDW.cjs.map +0 -1
  57. /package/dist/{chunk-ELS6KPJQ.js.map → chunk-ANBU7BJU.js.map} +0 -0
  58. /package/dist/{chunk-PH5LR5WA.js.map → chunk-EGGKTDHO.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/situations.ts"],"sourcesContent":["/**\n * One sentence per subscription situation, for the subscriber and for the\n * merchant, and what each of them can do about it: the canonical wording of\n * 2026-10-05, agreed with the backend. Show these instead of writing your\n * own: hand-written ones drift, and some are false (\"add funds\" on a removed\n * approval, \"nothing more is charged\" on a stopped subscription).\n *\n * Browser-safe: this module imports types only, so `@mesub/node/situations`\n * loads in a page, a widget or a docs site with nothing of Node.\n *\n * Templates carry `{placeholders}`. A `[segment]` holds a placeholder `/v1`\n * does not always serve: it is shown when every placeholder in it has a\n * value, and left out otherwise, so the sentence stays true without it.\n */\nimport type { AccessAnswer, BlockedReason, EndReason, LateReason, StopReason } from './answer.js';\nimport type { ServerSubscription } from './subscriptions.js';\n\n/** Who acts. */\nexport type SituationActor = 'subscriber' | 'merchant';\n\n/**\n * What can be done. `add_funds` has no route (the wallet does it).\n * `transaction` hands a pending checkout a fresh transaction to sign\n * (`subscriptions.transaction`, Mesub-io/backend#427). `retry` is\n * the subscriber's \"Pay now\" with the API key (`subscriptions.retry`,\n * Mesub-io/backend#354), and the merchant's on the Mesub dashboard; `upgrade`\n * exists on the dashboard only.\n */\nexport type SituationActionId =\n | 'subscribe'\n | 'transaction'\n | 'submit'\n | 'cancel'\n | 'resume'\n | 'close'\n | 'add_funds'\n | 'retry'\n | 'upgrade'\n | 'retrieve'\n | 'list';\n\n/** One action of a situation, as the table lists it. */\nexport interface SituationActionTemplate {\n readonly by: SituationActor;\n readonly action: SituationActionId;\n /** The method of `@mesub/node`, when there is one: `subscriptions.cancel`, … */\n readonly sdk?: string;\n /** The API route behind it. */\n readonly route?: string;\n /** On the Mesub dashboard only: an API key cannot call it. */\n readonly dashboard?: true;\n /** The sentence to show before the subscriber signs it, a key of `CONFIRMATIONS`. */\n readonly confirm?: ConfirmationKey;\n /** Only while the date in this field of the subscription is ahead. */\n readonly until?: 'access_until' | 'retry_deadline';\n /**\n * Only while the subscription is `closable` (Mesub-io/backend#402): left\n * out where Mesub says `closable: false`, its `closable_from` in the\n * sentence when a date is known.\n */\n readonly when?: 'closable';\n}\n\n/**\n * A sentence, or one per tier where the canonical sentence names both:\n * `retries` for Dev and Business (Mesub retries on its own), `free` for Free\n * (hand retries until `retry_deadline`).\n */\nexport type SituationText = string | { readonly retries: string; readonly free: string };\n\nexport interface Situation {\n readonly subscriber: SituationText;\n readonly merchant: SituationText;\n readonly actions: readonly SituationActionTemplate[];\n}\n\nconst SUBSCRIBE = {\n by: 'subscriber',\n action: 'subscribe',\n sdk: 'subscriptions.create',\n route: 'POST /v1/subscriptions',\n} as const;\nconst CANCEL = {\n by: 'subscriber',\n action: 'cancel',\n sdk: 'subscriptions.cancel',\n route: 'POST /v1/subscriptions/:id/cancel',\n} as const;\nconst RESUME = {\n by: 'subscriber',\n action: 'resume',\n sdk: 'subscriptions.resume',\n route: 'POST /v1/subscriptions/:id/resume',\n until: 'access_until',\n} as const;\nconst CLOSE = {\n by: 'subscriber',\n action: 'close',\n sdk: 'subscriptions.close',\n route: 'POST /v1/subscriptions/:id/close',\n confirm: 'confirm_close',\n when: 'closable',\n} as const;\n/** A close on a plan that is gone or over: nothing to subscribe to again after it. */\nconst CLOSE_OVER = { ...CLOSE, confirm: 'confirm_close_over' } as const;\nconst ADD_FUNDS = { by: 'subscriber', action: 'add_funds' } as const;\n/** Does not count as a retry, and doubles the wait before the next one. */\nconst RETRY = {\n by: 'merchant',\n action: 'retry',\n route: 'POST /merchant/subscriptions/:id/retry',\n dashboard: true,\n} as const;\n/**\n * The subscriber's own, shown as \"Pay now\" (Mesub-io/backend#354): the same\n * rules as the merchant's, nothing to sign, and refused first when it cannot\n * succeed (a short wallet, an approval gone), so no retry is spent for nothing.\n */\nconst PAY_NOW = {\n by: 'subscriber',\n action: 'retry',\n sdk: 'subscriptions.retry',\n route: 'POST /v1/subscriptions/:id/retry',\n} as const;\nconst UPGRADE = {\n by: 'merchant',\n action: 'upgrade',\n route: 'POST /projects/:id/upgrade',\n dashboard: true,\n} as const;\nconst CANCEL_PAID = { ...CANCEL, confirm: 'confirm_cancel_paid' } as const;\n\n/**\n * A block of the merchant's setup, as the subscriber reads it: one sentence for\n * all but a gone token, which no payment can lift.\n */\nconst BLOCKED_BY_SETUP =\n 'Mesub cannot take your payments for {plan_name} for now, because of how the plan is set up, not because of anything you did: there is nothing for you to do or sign, and Mesub keeps trying.[ You keep access until {access_until} if no payment goes through by then.] Access comes back on its own with the first payment that goes through.';\n/** The subscriber's sentence on a token its issuer paused or gave a hook: not the merchant's either. */\nconst BLOCKED_BY_TOKEN =\n 'Mesub cannot take your payments for {plan_name} for now, because of the token it is paid in, not because of anything you did: there is nothing for you to do or sign, and Mesub keeps trying.[ You keep access until {access_until} if no payment goes through by then.] Access comes back on its own with the first payment that goes through.';\n/** How a merchant's sentence on a block ends, whatever the cause but a gone token. */\nconst BLOCKED_ACCESS =\n '[ Access ends on {access_until} if nothing is collected by then.] Access comes back with the first payment that goes through, with nothing for the subscriber to sign.';\n/**\n * How both sentences on a gone token end: Mesub still tries, and no payment\n * can land on a token that no longer exists.\n */\nconst NEVER_BACK =\n 'No payment can go through on this plan again, so once access ends it does not come back.';\nconst CANCEL_BEHIND = { ...CANCEL, confirm: 'confirm_cancel_behind' } as const;\n\n/**\n * The canonical table, by situation key. The renewal checks\n * (`active_renewal_*`) are left out: Mesub serves them on its dashboard\n * only, never on `/v1`.\n */\nexport const SITUATIONS = {\n // Running\n none: {\n subscriber: 'You are not subscribed to {plan_name}.',\n merchant: 'This customer has no subscription to {plan_name}.',\n actions: [SUBSCRIBE],\n },\n active: {\n subscriber: 'Active. Your next payment of {amount} is on {next_charge_at}.',\n merchant: 'Active and paid up. Next payment of {amount} on {next_charge_at}.',\n actions: [CANCEL_PAID],\n },\n // The plan ends before another charge: the last period, paid in full.\n active_last_period: {\n subscriber:\n 'Active until {access_until}: {plan_name} is ending, and no further payment will be taken.',\n merchant:\n 'Active and paid up, in its last period: the plan is ending, so no further payment is taken. Access ends on {access_until}.',\n actions: [CANCEL_PAID],\n },\n active_unbilled: {\n subscriber: 'Active until {access_until}. No further payment is scheduled.',\n merchant:\n \"Not billed: this subscription's terms were never signed through Mesub, so Mesub never takes a payment for it. Access ends on {access_until}.\",\n actions: [],\n },\n\n // Late (`unpaid`)\n // The plan ends before the next retry: none is scheduled, whatever the reason.\n unpaid_last_period: {\n subscriber:\n 'Your payment of {amount} is late, and Mesub will not try again on its own: {plan_name} is ending. You keep access until {access_until}.',\n merchant:\n 'Payment late, with no retry ahead: the plan ends before the next one. Access continues until {access_until}, and the subscription ends with the plan.',\n actions: [PAY_NOW, CANCEL_BEHIND, RETRY],\n },\n unpaid_insufficient_balance_retries: {\n subscriber:\n 'Your payment of {amount} is late because your wallet held too little, and nothing was taken. Add {amount} to your wallet, then pay it now, with nothing to sign; otherwise Mesub tries again on {next_retry_at}. Your subscription stops if no payment goes through by {access_until}.',\n merchant:\n \"Payment late: the wallet was short. Retry[ {next_retry_number} of {retries_allowed}] on {next_retry_at}, or sooner by hand, yours or the subscriber's. Access continues until {access_until}; the subscription stops then if every retry fails.\",\n actions: [ADD_FUNDS, PAY_NOW, CANCEL_BEHIND, RETRY],\n },\n unpaid_insufficient_balance_free: {\n subscriber:\n 'Your payment of {amount} is late because your wallet held too little, so your access is off. Add {amount} to your wallet, then pay it now, with nothing to sign, before {retry_deadline}; if no payment goes through by then, the subscription stops.',\n merchant:\n 'Payment late: the wallet was short. On Free, Mesub does not retry on its own: you or the subscriber can retry by hand, up to 3 times between you, 10 minutes apart, until {retry_deadline}. Access is off meanwhile, and it stops after that.',\n actions: [\n ADD_FUNDS,\n { ...PAY_NOW, until: 'retry_deadline' },\n CANCEL_BEHIND,\n { ...RETRY, until: 'retry_deadline' },\n ],\n },\n unpaid_approval_revoked: {\n subscriber:\n \"Mesub could not take your payment of {amount}: your wallet no longer approves it (the approval was removed, or replaced by another app's). Adding funds will not fix this, and removing the approval did not cancel the subscription: Cancel it if you want to stop.\",\n merchant: {\n retries:\n \"Payment late: the subscriber's wallet no longer approves Mesub (removed in the wallet, or replaced by another app's approval). Every retry fails until it is back, and no Mesub route restores it today. It stops on {access_until}.\",\n free: \"Payment late: the subscriber's wallet no longer approves Mesub (removed in the wallet, or replaced by another app's approval). Every retry fails until it is back, and no Mesub route restores it today. It stops at {retry_deadline}.\",\n },\n // A retry by hand is accepted by the dashboard but fails, and the\n // subscriber's is refused (`retry_cannot_succeed`): neither is offered.\n actions: [CANCEL_BEHIND],\n },\n unpaid_authority_closed: {\n subscriber:\n \"Mesub can no longer take payments for this subscription: your wallet's approval for {token} was closed for good, so adding funds will not help. Cancel it, then close it once its period ends if you want to subscribe again.\",\n merchant: {\n retries:\n \"Payment late, for good: the subscriber's subscription authority for {token} was closed (or re-created), so no retry can succeed. It stops on {access_until}, unless the subscriber cancels first.\",\n free: \"Payment late, for good: the subscriber's subscription authority for {token} was closed (or re-created), so no retry can succeed. It stops at {retry_deadline}, unless the subscriber cancels first.\",\n },\n // Close, then subscribe, come once it is cancelled and its period ended.\n actions: [CANCEL_BEHIND],\n },\n unpaid_unknown: {\n subscriber:\n 'Your wallet refused the payment of {amount}, so nothing was taken. Check that it still holds {amount} in {token} and can send it, then pay it now, or Cancel to stop.',\n merchant:\n \"Payment late: the network refused the payment for a reason Mesub does not name (for example a frozen {token} account). See the last attempt's reason.\",\n actions: [PAY_NOW, CANCEL_BEHIND, RETRY],\n },\n\n // Blocked: every charge fails for a reason that is not the subscriber's\n // (Mesub-io/backend#398). The status does not move, access has an end.\n // Worded here from the API's own comments, after the table of 2026-10-05.\n blocked_mesub: {\n subscriber:\n \"Mesub cannot take your payments for {plan_name} for now, because of a problem on Mesub's side: there is nothing for you to do or sign, and Mesub keeps trying.[ You keep access until {access_until} if no payment goes through by then.] Access comes back on its own with the first payment that goes through.\",\n merchant: `Payments blocked[ since {blocked_since}] by a problem on Mesub's side: nothing to fix on yours, and none of it is the subscriber's doing. Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_puller_not_allowed: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: Mesub's puller was taken off the plan on chain, so Mesub can take no payment for it. Add Mesub back to the plan's pullers, with the wallet that owns the plan; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_receiver_not_allowed: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the wallet that receives its payments is not among the plan's destinations on chain. Choose one that is; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_receiver_account_missing: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the wallet that receives its payments has no token account for the plan's token, and nobody else on the plan can be paid. Open that account; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_receiver_account_frozen: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the token account of the wallet that receives its payments is frozen, so it cannot take payments. Choose another receiving wallet, or ask the token's issuer to unfreeze that account; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_receiver_account_needs_memo: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the token account of the wallet that receives its payments requires a memo on every payment in, which Mesub's charges do not carry. Turn that requirement off for the account, or choose another receiving wallet; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_receiver_account_confidential_only: {\n subscriber: BLOCKED_BY_SETUP,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the token account of the wallet that receives its payments takes confidential transfers only, and Mesub's charges are plain ones. Allow plain transfers into the account, or choose another receiving wallet; Mesub keeps trying.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n // The token issuer's to lift, not the merchant's (Mesub-io/backend#396).\n blocked_mint_paused: {\n subscriber: BLOCKED_BY_TOKEN,\n merchant: `Payments blocked[ since {blocked_since}] by the plan's token: its issuer paused it, so no payment in it can move. Only the issuer can lift the pause, and Mesub charges again once they do.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_mint_transfer_hook: {\n subscriber: BLOCKED_BY_TOKEN,\n merchant: `Payments blocked[ since {blocked_since}] by the plan's token: its issuer made every transfer of it run their own program, which Mesub does not support yet. Mesub charges again if the issuer removes it; otherwise, create a new plan with another token.${BLOCKED_ACCESS}`,\n actions: [CANCEL],\n },\n blocked_mint_gone: {\n subscriber: `Mesub can no longer take your payments for {plan_name}: the token it is paid in no longer exists. This is not because of anything you did, and there is nothing for you to do or sign.[ You keep access until {access_until}.] ${NEVER_BACK}`,\n merchant: `Payments blocked[ since {blocked_since}] by your plan's setup: the plan's token no longer exists on chain, so nothing can be collected on it. Create a new plan with another token.[ Access ends on {access_until}.] ${NEVER_BACK}`,\n actions: [CANCEL],\n },\n\n // Cancelled\n cancelled_with_access: {\n subscriber:\n 'Cancelled: nothing more will be taken, and you keep access until {access_until}. Resume before then to keep it going.',\n merchant:\n 'Cancelled[ on {cancelled_at}]: access runs until {access_until}, and nothing more will be taken.',\n actions: [{ ...RESUME, confirm: 'confirm_resume' }],\n },\n cancelled_no_access: {\n subscriber:\n 'Cancelled. Your last payment was missed, so you have no access, and Mesub will not collect it; you can close the subscription[ from {closable_from}] to get your deposit back.',\n merchant:\n 'Cancelled while behind[ on {cancelled_at}]: no access, and Mesub will not collect the missed payment. The subscriber can close it[ from {closable_from}], and must do so before subscribing again.',\n // Not resume (refused) and not subscribe (refused until it is closed).\n actions: [CLOSE],\n },\n cancelled_ended: {\n subscriber:\n 'This subscription has ended. Close it to get your deposit back; you need to close it before subscribing to {plan_name} again.',\n merchant:\n \"Ended by the subscriber's cancellation. Its subscription account stays open until the subscriber closes it, which they must do before subscribing again.\",\n actions: [CLOSE],\n },\n\n // Stopped\n stopped: {\n subscriber:\n \"Your subscription stopped after missed payments, and your access has ended; Mesub will not take payments for it again. Its subscription account stays open on your wallet, so the plan's owner could still charge it: Cancel if you are not coming back.\",\n // `{stop_cause}` from `stop_reason` (`STOP_CAUSES`), left out while it is null.\n merchant:\n \"Stopped[: {stop_cause}]. Mesub takes nothing more and access is off. The subscription account stays open on chain, and you, as the plan's owner, could still pull from it, until the subscriber cancels and closes it. The subscriber can come back over it.\",\n // Subscribing again restarts it, while it is not cancelled on chain,\n // the plan's terms are unchanged and the project has a free seat. A\n // close only once Mesub says it is `closable`: cancelled on chain\n // without Mesub, and past its end.\n actions: [CANCEL_BEHIND, SUBSCRIBE, CLOSE],\n },\n // The wallet closed its subscription authority for good (Mesub-io/backend#394,\n // #402): nobody can charge it again, and it cannot be restarted. Worded\n // from the stopped emails' `authority-closed` variants.\n stopped_authority_closed: {\n subscriber:\n \"Your wallet's approval for {token} was closed for good, so no payment can go through for this subscription any more: it has stopped, your access is over, and it cannot be restarted. Close it to get your deposit back; you can then subscribe to {plan_name} again.\",\n merchant:\n \"Stopped for good: the subscriber's wallet approval for {token} was closed, so nobody can take payments from this subscription any more, you as the plan's owner included, and the subscriber cannot come back over it. They can close it at once to get their deposit back.\",\n actions: [CLOSE],\n },\n\n // Paused\n paused: {\n subscriber:\n 'Paused by {merchant_name}: nothing will be taken, and you keep access until {access_until}.',\n merchant:\n \"Paused: your project is over its tier's subscriber limit, so Mesub takes nothing from this subscriber. Access runs to the end of the paid period ({access_until}). Move back up a tier to restart payments.\",\n actions: [CANCEL_PAID, UPGRADE],\n },\n paused_access_over: {\n subscriber:\n 'Paused by {merchant_name}: nothing is taken, and your access has ended. If {merchant_name} unpauses it, a payment is due at once; Cancel to stop for good.',\n merchant:\n 'Paused over your tier limit, and its paid period is over, so access is off. Moving back up a tier makes a payment due at once.',\n actions: [CANCEL, UPGRADE],\n },\n paused_cancelled: {\n subscriber:\n 'Cancelled: nothing more will be taken, and you keep access until {access_until}. You can resume before then, but it stays paused, with no payment, until {merchant_name} unpauses it.',\n merchant: 'Cancelled while paused over your tier limit; access until {access_until}.',\n actions: [{ ...RESUME, confirm: 'confirm_resume_paused' }],\n },\n\n // Ended\n ended_closed: {\n subscriber:\n 'You closed this subscription, and its deposit is back in your wallet. You can subscribe to {plan_name} again at any time.',\n merchant:\n 'Ended: the subscriber closed it and got the deposit back. They can subscribe again.',\n actions: [SUBSCRIBE],\n },\n ended_authority_closed: {\n subscriber:\n \"This subscription's account was closed outside Mesub, so it has ended and nothing more can be taken. You can subscribe to {plan_name} again.\",\n merchant:\n 'Ended: its subscription account was found closed on chain, without Mesub. The subscriber can subscribe again.',\n actions: [SUBSCRIBE],\n },\n ended_plan_removed: {\n subscriber:\n '{merchant_name} removed {plan_name}, so your subscription has ended and nothing more will be taken.',\n // Closed through Mesub since Mesub-io/backend#344.\n merchant:\n \"Ended: the plan account was deleted. The subscriber's subscription account may still hold their deposit, which they get back by closing it.\",\n actions: [CLOSE_OVER],\n },\n ended_plan_replaced: {\n subscriber:\n '{merchant_name} replaced {plan_name} with another plan, so this subscription has ended and nothing more will be taken.',\n merchant:\n \"Ended: another plan now stands at this plan's address, and this subscription was never signed for it.\",\n actions: [CLOSE_OVER],\n },\n ended_plan_ended: {\n // `{plan_ends_at}` is the plan's `ends_at`, not on a subscription.\n subscriber:\n '{plan_name} reached its end date[ ({plan_ends_at})], so your subscription has ended and nothing more will be taken.',\n merchant: 'Ended: the plan passed its end date.',\n // Also read off a running row in the minutes before Mesub ends it,\n // which is not `closable` yet: the close shows once it is.\n actions: [CLOSE_OVER],\n },\n ended_unknown: {\n subscriber: 'This subscription has ended, and nothing more will be taken.',\n merchant: 'Ended (before Mesub recorded reasons).',\n actions: [],\n },\n\n // Checkout and history\n pending: {\n subscriber:\n 'Not signed yet. Approve it in your wallet to pay the first {amount} and start the subscription.',\n merchant: 'Checkout started, not signed yet: nothing is on chain and nothing was charged.',\n // A fresh transaction when the wallet is ready, or after `transaction_expired`.\n actions: [\n {\n by: 'merchant',\n action: 'transaction',\n sdk: 'subscriptions.transaction',\n route: 'POST /v1/subscriptions/:id/transaction',\n },\n {\n by: 'merchant',\n action: 'submit',\n sdk: 'subscriptions.submit',\n route: 'POST /v1/subscriptions/:id/submit',\n },\n ],\n },\n expired: {\n subscriber:\n 'This checkout was never signed, so nothing was charged. Subscribe again to start.',\n merchant: 'Checkout expired unsigned. Nothing on chain.',\n actions: [SUBSCRIBE],\n },\n failed: {\n subscriber:\n 'This subscription did not start: what reached the network was not the transaction prepared for it. If money left your wallet for it, contact {merchant_name}.',\n merchant:\n \"Failed: what landed on chain is not what Mesub built (see the submit reason). Check the wallet's transactions before creating a new one.\",\n actions: [\n {\n by: 'merchant',\n action: 'retrieve',\n sdk: 'subscriptions.retrieve',\n route: 'GET /v1/subscriptions/:id',\n },\n SUBSCRIBE,\n ],\n },\n superseded: {\n // Hide it from subscribers: the newer row is the one in force.\n subscriber: 'Replaced by your newer subscription to {plan_name}.',\n // `{replaced_at}`, when the newer row was created, is not on this row.\n merchant:\n 'An earlier subscription of this wallet, replaced when it subscribed again[ on {replaced_at}]. Read the current one.',\n actions: [\n {\n by: 'merchant',\n action: 'list',\n sdk: 'subscriptions.list',\n route: 'GET /v1/subscriptions',\n },\n ],\n },\n} as const satisfies Record<string, Situation>;\n\n/** The sentences to show before the subscriber signs an action. */\nexport const CONFIRMATIONS = {\n confirm_cancel_paid:\n 'Cancel {plan_name}? Nothing more will be taken, and you keep access until {access_until}.',\n confirm_cancel_behind:\n 'Cancel {plan_name}? Your access ends now and Mesub will not collect the missed payment; you can close it once the current period ends.',\n confirm_resume:\n 'Resume {plan_name}? Nothing is taken now; your next payment of {amount} is on {access_until}.',\n confirm_resume_paused:\n 'Resume {plan_name}? Nothing is taken now, and nothing will be until {merchant_name} unpauses it.',\n confirm_close:\n 'Close {plan_name}? This deletes its subscription account and returns its deposit to your wallet; you can then subscribe again.',\n confirm_close_over:\n 'Close {plan_name}? This deletes its subscription account and returns its deposit to your wallet.',\n} as const;\n\n/** Shown beside every sentence, which therefore need not repeat it. */\nexport const ACCESS_LINE = { granted: 'Access until {access_until}', denied: 'No access' } as const;\n\nexport type ConfirmationKey = keyof typeof CONFIRMATIONS;\n\n/**\n * A situation of the table, or `unknown`: a status or a reason newer than\n * this release, whose sentences are the access line, true of any situation.\n */\nexport type SituationKey = keyof typeof SITUATIONS | 'unknown';\n\nexport interface ExplainOptions {\n /** What \"now\" is, for actions open until a date. Defaults to the clock. */\n now?: Date;\n /** What neither `/v1/access` nor a subscription carries, as you show it. */\n names?: {\n /** `{plan_name}`. Defaults to the plan's slug. */\n plan?: string;\n /** `{merchant_name}`: your name, as subscribers know it. */\n merchant?: string;\n /** `{amount}`: the plan's amount with its symbol, such as `9.99 USDC`. */\n amount?: string;\n /** `{token}`: the plan's token symbol, such as `USDC`. */\n token?: string;\n };\n /**\n * How a date is written. Defaults to the ISO 8601 string as Mesub serves\n * it, the same in every locale: pass your own to show local time.\n */\n formatDate?: (iso: string) => string;\n}\n\nexport interface ExplainedAction {\n by: SituationActor;\n action: SituationActionId;\n sdk?: string;\n route?: string;\n dashboard?: true;\n /** Until when it can be done, as served (ISO 8601). */\n until?: string;\n /** The sentence to show before the subscriber signs it, filled. */\n confirm?: string;\n}\n\nexport interface Explanation {\n key: SituationKey;\n /** For the subscriber, filled. */\n subscriber: string;\n /** For the merchant, filled. */\n merchant: string;\n /** \"Access until …\" or \"No access\", to show beside either sentence. */\n access: string;\n /** What can be done now, by whom. */\n actions: ExplainedAction[];\n /**\n * Placeholders left as `{name}` in a sentence, since nothing gave them a\n * value: pass them in `options.names`, or check the answer's fields.\n */\n missing: string[];\n}\n\n/** What `explain` reads: an answer of `/v1/access` or a subscription. */\nexport type Explainable = AccessAnswer | ServerSubscription;\n\n/**\n * `closed_elsewhere` keeps the situation `authority_closed` had before\n * Mesub-io/backend#476 renamed it, id included: both read as one.\n */\nconst END_REASONS: Record<EndReason, keyof typeof SITUATIONS> = {\n cancelled: 'cancelled_ended',\n closed: 'ended_closed',\n closed_elsewhere: 'ended_authority_closed',\n authority_closed: 'ended_authority_closed',\n plan_removed: 'ended_plan_removed',\n plan_replaced: 'ended_plan_replaced',\n plan_ended: 'ended_plan_ended',\n};\n\nconst LATE_REASONS: Record<Exclude<LateReason, 'insufficient_balance'>, keyof typeof SITUATIONS> = {\n approval_revoked: 'unpaid_approval_revoked',\n authority_closed: 'unpaid_authority_closed',\n};\n\n/**\n * What `{stop_cause}` reads for each reason that leaves the subscription to\n * come back over. `authority_closed` has a situation of its own.\n */\nconst STOP_CAUSES: Record<Exclude<StopReason, 'authority_closed'>, string> = {\n out_of_retries: 'every retry of the missed payment failed',\n retry_deadline_passed: 'the last day to pay the missed payment passed',\n};\n\nconst BLOCKED_REASONS: Record<BlockedReason, keyof typeof SITUATIONS> = {\n mesub: 'blocked_mesub',\n puller_not_allowed: 'blocked_puller_not_allowed',\n receiver_not_allowed: 'blocked_receiver_not_allowed',\n receiver_account_missing: 'blocked_receiver_account_missing',\n receiver_account_frozen: 'blocked_receiver_account_frozen',\n receiver_account_needs_memo: 'blocked_receiver_account_needs_memo',\n receiver_account_confidential_only: 'blocked_receiver_account_confidential_only',\n mint_gone: 'blocked_mint_gone',\n mint_paused: 'blocked_mint_paused',\n mint_transfer_hook: 'blocked_mint_transfer_hook',\n};\n\n/** A key that is its status, whatever else the answer says. */\nconst BY_STATUS = new Set(['none', 'pending', 'expired', 'failed', 'superseded']);\n\n/** Free is read as a `retry_deadline` set: `/v1` does not serve the tier. */\nfunction isFree(input: Explainable): boolean {\n return input.retry_deadline != null;\n}\n\n/** Billed and running: neither parked nor one Mesub never pulls, which `payment_status` says. */\nfunction isBilled(input: Explainable): boolean {\n return input.payment_status !== 'none';\n}\n\n/**\n * Which situation an answer is in, in the canonical order: status first,\n * then paused, then blocked, then the end or late reason. Never throws: a\n * status or a reason this release does not know is `unknown`.\n *\n * A plan's end is read from what it leaves on the answer, which carries no\n * `ends_at`: access with no charge or retry ahead is the last period, and a\n * running status without access is the minutes between the end and the job\n * that ends the row. That one reads as ended already.\n */\nexport function situationOf(input: Explainable): SituationKey {\n const status: string = input.status;\n const paused = input.paused === true;\n\n if (BY_STATUS.has(status)) return status as SituationKey;\n\n if (paused && (status === 'active' || status === 'unpaid' || status === 'cancelled')) {\n if (status === 'cancelled') return 'paused_cancelled';\n return input.access ? 'paused' : 'paused_access_over';\n }\n\n // Before the plan's end is read off a running row without access: a\n // blocked one loses its access too, and has not ended.\n const blocked: string | null = input.blocked_reason ?? null;\n if (blocked !== null && (status === 'active' || status === 'unpaid')) {\n return Object.hasOwn(BLOCKED_REASONS, blocked)\n ? BLOCKED_REASONS[blocked as BlockedReason]\n : 'unknown';\n }\n\n switch (status) {\n case 'ended': {\n const reason: string | null = input.end_reason ?? null;\n if (reason === null) return 'ended_unknown';\n return Object.hasOwn(END_REASONS, reason)\n ? END_REASONS[reason as EndReason]\n : 'unknown';\n }\n case 'cancelled':\n if (input.access) return 'cancelled_with_access';\n // Paid up and cut short by the plan's end: it ends as cancelled.\n return input.payment_status === 'paid' ? 'cancelled_ended' : 'cancelled_no_access';\n case 'unpaid': {\n const reason: string | null = input.late_reason ?? null;\n const named = reason !== null && reason !== 'insufficient_balance';\n if (named && !Object.hasOwn(LATE_REASONS, reason)) return 'unknown';\n // On Free a late one has no access and no retry of Mesub's, end or not.\n if (!isFree(input) && isBilled(input) && input.next_retry_at == null) {\n if (!input.access) return 'ended_plan_ended';\n if (input.access_until != null) return 'unpaid_last_period';\n }\n if (reason === null) return 'unpaid_unknown';\n if (reason === 'insufficient_balance') {\n return isFree(input)\n ? 'unpaid_insufficient_balance_free'\n : 'unpaid_insufficient_balance_retries';\n }\n return LATE_REASONS[reason as keyof typeof LATE_REASONS];\n }\n case 'active':\n if (!isBilled(input)) return 'active_unbilled';\n if (!input.access) return 'ended_plan_ended';\n return input.access_until != null && input.next_charge_at == null\n ? 'active_last_period'\n : 'active';\n case 'stopped': {\n const reason: string | null = input.stop_reason ?? null;\n if (reason === 'authority_closed') return 'stopped_authority_closed';\n // A reason newer than this release may not leave it to come back over.\n return reason === null || Object.hasOwn(STOP_CAUSES, reason) ? 'stopped' : 'unknown';\n }\n default:\n return 'unknown';\n }\n}\n\n/**\n * The situation of a subscription, in words: one sentence for the\n * subscriber, one for the merchant, the access line, and what each can do\n * now. Takes an answer of `/v1/access` or a subscription as `@mesub/node`\n * returns them. Never throws.\n *\n * ```ts\n * const { subscriber, access, actions } = explain(answer, {\n * names: { plan: 'Pro', merchant: 'Acme', amount: '9.99 USDC', token: 'USDC' },\n * });\n * ```\n */\nexport function explain(input: Explainable, options: ExplainOptions = {}): Explanation {\n const key = situationOf(input);\n const values = valuesOf(input, options);\n const missing = new Set<string>();\n const fill = (template: string): string => render(template, values, missing);\n const accessLine = fill(input.access ? ACCESS_LINE.granted : ACCESS_LINE.denied);\n\n if (key === 'unknown') {\n return {\n key,\n subscriber: accessLine,\n merchant: accessLine,\n access: accessLine,\n actions: [],\n missing: [...missing],\n };\n }\n\n const situation: Situation = SITUATIONS[key];\n const tier = isFree(input) ? 'free' : 'retries';\n const pick = (text: SituationText): string => (typeof text === 'string' ? text : text[tier]);\n const now = (options.now ?? new Date()).getTime();\n const actions: ExplainedAction[] = [];\n\n for (const template of situation.actions) {\n const { until: field, confirm, when, ...rest } = template;\n const action: ExplainedAction = { ...rest };\n\n // Undefined only on an answer cached by an older SDK: offered, as the table says.\n if (when === 'closable' && input.closable === false) continue;\n\n if (field !== undefined) {\n const until = input[field];\n if (until != null) {\n if (Date.parse(until) <= now) continue;\n action.until = until;\n }\n }\n if (confirm !== undefined) action.confirm = fill(CONFIRMATIONS[confirm]);\n actions.push(action);\n }\n\n return {\n key,\n subscriber: fill(pick(situation.subscriber)),\n merchant: fill(pick(situation.merchant)),\n access: accessLine,\n actions,\n missing: [...missing],\n };\n}\n\n/** Every value a placeholder can take from this answer and these options. */\nfunction valuesOf(input: Explainable, options: ExplainOptions): Record<string, string | undefined> {\n const date = options.formatDate ?? ((iso: string) => iso);\n const asDate = (iso: string | null | undefined) => (iso == null ? undefined : date(iso));\n const asNumber = (n: number | null | undefined) => (n == null ? undefined : String(n));\n const names = options.names ?? {};\n\n return {\n plan_name: names.plan ?? input.plan ?? undefined,\n merchant_name: names.merchant,\n amount: names.amount,\n token: names.token,\n access_until: asDate(input.access_until),\n next_charge_at: asDate(input.next_charge_at),\n next_retry_at: asDate(input.next_retry_at),\n retry_deadline: asDate(input.retry_deadline),\n blocked_since: asDate(input.blocked_since),\n // `/v1/access` only.\n cancelled_at: asDate('cancelled_at' in input ? input.cancelled_at : null),\n // On a subscription only.\n next_retry_number: asNumber('next_retry_number' in input ? input.next_retry_number : null),\n retries_allowed: asNumber('retries_allowed' in input ? input.retries_allowed : null),\n closable_from: asDate(input.closable_from),\n stop_cause: stopCauseOf(input.stop_reason),\n // Not served on `/v1` (yet): their segments are left out.\n plan_ends_at: undefined,\n replaced_at: undefined,\n };\n}\n\n/** The words of a stop reason this release names, undefined for any other. */\nfunction stopCauseOf(reason: string | null | undefined): string | undefined {\n return reason != null && Object.hasOwn(STOP_CAUSES, reason)\n ? STOP_CAUSES[reason as keyof typeof STOP_CAUSES]\n : undefined;\n}\n\nconst PLACEHOLDER = /\\{([a-z_]+)\\}/g;\n\n/**\n * Fills a template: a `[segment]` with a placeholder lacking a value is left\n * out, and a placeholder outside one is kept as `{name}` and noted missing.\n */\nfunction render(\n template: string,\n values: Record<string, string | undefined>,\n missing: Set<string>,\n): string {\n const segments = template.replace(/\\[([^[\\]]*)\\]/g, (_, segment: string) =>\n [...segment.matchAll(PLACEHOLDER)].every(([, name]) => values[name!] !== undefined)\n ? segment\n : '',\n );\n\n return segments.replace(PLACEHOLDER, (whole, name: string) => {\n const value = values[name];\n if (value !== undefined) return value;\n missing.add(name);\n return whole;\n });\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
- var _chunkSFK52JDWcjs = require('./chunk-SFK52JDW.cjs');
4
+ var _chunk5THDILDDcjs = require('./chunk-5THDILDD.cjs');
5
5
 
6
6
  // src/guard.ts
7
7
  var DENIAL_STATUS = {
@@ -16,7 +16,7 @@ function retryAfterOf(outcome) {
16
16
  }
17
17
  var shared;
18
18
  function defaultClient() {
19
- shared ??= new (0, _chunkSFK52JDWcjs.Mesub)();
19
+ shared ??= new (0, _chunk5THDILDDcjs.Mesub)();
20
20
  return shared;
21
21
  }
22
22
  function plansOf(plan, request) {
@@ -49,7 +49,7 @@ function checkCustomer(options) {
49
49
  async function askerOf(request, customer) {
50
50
  const named = await customer(request);
51
51
  if (named === null || named === void 0) return null;
52
- const asked = _chunkSFK52JDWcjs.customerOf.call(void 0, named);
52
+ const asked = _chunk5THDILDDcjs.customerOf.call(void 0, named);
53
53
  if (asked.value === "") {
54
54
  throw new TypeError(
55
55
  "`customer` returned an empty value: return null when nobody is signed in."
@@ -117,4 +117,4 @@ function denialOf(outcome) {
117
117
 
118
118
 
119
119
  exports.retryAfterOf = retryAfterOf; exports.defaultClient = defaultClient; exports.plansOf = plansOf; exports.checkPlan = checkPlan; exports.checkCustomer = checkCustomer; exports.askerOf = askerOf; exports.guard = guard; exports.denialBody = denialBody; exports.accessOf = accessOf; exports.denialOf = denialOf;
120
- //# sourceMappingURL=chunk-6XJWKRCN.cjs.map
120
+ //# sourceMappingURL=chunk-TDRUSUBV.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/node-sdk/node-sdk/dist/chunk-6XJWKRCN.cjs","../src/guard.ts"],"names":[],"mappings":"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","file":"/home/runner/work/node-sdk/node-sdk/dist/chunk-6XJWKRCN.cjs","sourcesContent":[null,"import type { AccessAnswer, Customer } from './answer.js';\nimport { type Decision, Mesub } from './client.js';\nimport { type Asked, customerOf } from './customer.js';\n\n/** Why a request was turned away, and what it answers by default. */\nexport type DenialReason = 'unauthenticated' | 'no_access' | 'unavailable';\n\nexport type GuardOutcome =\n | { allowed: true; customer: Asked; plan: string; decision: Decision }\n | { allowed: false; reason: DenialReason; decision?: Decision };\n\n/** Who is asking and what Mesub answered, as a guarded route receives it. */\nexport interface MesubAccess {\n /**\n * The wallet that pays. Asked by external id or email, the one Mesub\n * answered with; null when the answer is the outage fallback's and holds none.\n */\n wallet: string | null;\n /** Who Mesub was asked about: a wallet, your own id for them, or their email. */\n customer: Asked;\n /** The plan that let the request through: the first of the list that did. */\n plan: string;\n /** Mesub's answer for that plan. */\n answer: AccessAnswer | null;\n /** The answer came from the outage fallback. */\n stale: boolean;\n}\n\n/** A refusal, as `onDenied` receives it. */\nexport interface Denial {\n reason: DenialReason;\n /** 401, 402 or 503: what would be answered without `onDenied`. */\n status: number;\n /** Mesub's answer, for the first plan asked when there are several. */\n answer: AccessAnswer | null;\n}\n\n/** What a guard answers by default for each refusal. */\nexport const DENIAL_STATUS: Record<DenialReason, number> = {\n unauthenticated: 401,\n no_access: 402,\n unavailable: 503,\n};\n\n/**\n * Seconds a client should wait before asking again when Mesub is unreachable\n * and did not say how long itself.\n */\nexport const UNAVAILABLE_RETRY_AFTER_S = 30;\n\n/**\n * The `Retry-After` of a guard's 503, in seconds: the one Mesub sent with its\n * 429 or 503 when it sent one, `UNAVAILABLE_RETRY_AFTER_S` otherwise (#132).\n */\nexport function retryAfterOf(outcome: Extract<GuardOutcome, { allowed: false }>): string {\n const asked = outcome.decision?.retryAfter;\n\n return String(asked === undefined ? UNAVAILABLE_RETRY_AFTER_S : Math.ceil(asked / 1000));\n}\n\nlet shared: Mesub | undefined;\n\n/** The client a middleware uses when given none: built once, from MESUB_API_KEY. */\nexport function defaultClient(): Mesub {\n shared ??= new Mesub();\n\n return shared;\n}\n\n/**\n * The plan a guard asks about: one, any one of several (the first that grants\n * lets the request through), or either of those worked out per request.\n */\nexport type PlanOption<Req> =\n string | readonly string[] | ((request: Req) => string | readonly string[]);\n\n/**\n * The plans a guard asks about for that request, in order, each once. A\n * plan that is not a non-empty string, or no plan at all, is a broken\n * integration: thrown, never read as a refusal.\n */\nexport function plansOf<Req>(plan: PlanOption<Req>, request: Req): string[] {\n return checkedPlans(typeof plan === 'function' ? plan(request) : plan);\n}\n\n/**\n * Checks a fixed plan when the guard is built, so a typo fails at start-up\n * rather than on the first request. One worked out per request is checked\n * then, by `plansOf`.\n */\nexport function checkPlan<Req>(plan: PlanOption<Req>): void {\n if (typeof plan !== 'function') checkedPlans(plan);\n}\n\n/**\n * Each plan a guard asks about is one call to `/v1/access`, made for every\n * request, against the key's 1000 calls a minute. Three is what a Dev\n * project can hold; a list longer than that is more likely built from the\n * request than written by hand.\n */\nconst MAX_PLANS = 3;\n\nfunction checkedPlans(value: unknown): string[] {\n const plans: unknown[] =\n typeof value === 'string' ? [value] : Array.isArray(value) ? value : [];\n\n if (plans.length === 0 || !plans.every((plan) => typeof plan === 'string' && plan !== '')) {\n throw new TypeError('A guard needs a plan, or a list of plans, as non-empty strings.');\n }\n\n const unique = [...new Set(plans as string[])];\n\n if (unique.length > MAX_PLANS) {\n throw new TypeError(\n `A guard asks about ${MAX_PLANS} plans at most: each one is a call to Mesub on every request.`,\n );\n }\n\n return unique;\n}\n\n/**\n * Who is asking, from your own auth: `(req) => ({ external_id: req.user.id })`,\n * a wallet, or an email. Null or undefined when nobody is signed in, a 401.\n * May be async.\n *\n * It must come from a session you verified, never from the request itself (a\n * query, a body, a header the caller writes): whoever names a subscriber\n * would get their access.\n */\nexport type CustomerOption<Req> = (\n request: Req,\n) => Customer | string | null | undefined | Promise<Customer | string | null | undefined>;\n\n/** Checked when the guard is built: without `customer` it could not tell who is asking. */\nexport function checkCustomer<Req>(options: { customer: CustomerOption<Req> }): void {\n if (typeof options?.customer !== 'function') {\n throw new TypeError(\n 'A guard needs `customer`: a function of the request returning who is signed in, ' +\n 'e.g. `(req) => ({ external_id: req.user.id })`.',\n );\n }\n}\n\n/**\n * Who is asking, as `customer` names them, or null for nobody.\n *\n * A `customer` that returns something Mesub cannot be asked about (two\n * identifiers, an empty one, not a string) is a broken integration: thrown.\n */\nexport async function askerOf<Req>(\n request: Req,\n customer: CustomerOption<Req>,\n): Promise<Asked | null> {\n const named = await customer(request);\n\n if (named === null || named === undefined) return null;\n\n const asked = customerOf(named);\n\n if (asked.value === '') {\n throw new TypeError(\n '`customer` returned an empty value: return null when nobody is signed in.',\n );\n }\n\n return asked;\n}\n\n/** The customer as `decide` takes it. */\nfunction asCustomer(asked: Asked): Customer | string {\n if (asked.kind === 'wallet') return asked.value;\n\n return asked.kind === 'email' ? { email: asked.value } : { external_id: asked.value };\n}\n\n/**\n * The one decision the middlewares make: who is asking, from `askerOf`, then\n * whether they have access to one of the plans.\n *\n * - nobody is asking (`customer` returned null): `unauthenticated`\n * - the fallback of `hasAccess` otherwise, per plan, through `decide`,\n * within the client's `guardTimeout`. The plans are asked at once, so\n * several fit the same budget, and read in order: the first that grants\n * lets the request through, without waiting for the ones after it.\n * `unavailable` when none grants and Mesub failed (outage, rate limit) or\n * the budget ran out on one with nothing cached: 402 only ever means\n * Mesub said no, for every plan\n *\n * An integration error (a bad API key, an unknown plan) is thrown, unless a\n * plan before it in the list already granted.\n *\n * `plansFor` runs only once somebody is identified: a plan worked out from\n * the request never runs, nor throws, for an anonymous one.\n */\nexport async function guard(\n client: Mesub,\n asked: Asked | null,\n plansFor: () => readonly string[],\n): Promise<GuardOutcome> {\n if (!asked) return { allowed: false, reason: 'unauthenticated' };\n\n const plans = plansFor();\n const customer = asCustomer(asked);\n const pending = plans.map((plan) => client.decide(customer, plan));\n\n // The ones not read, once a plan before them grants, must not reject unhandled.\n for (const decision of pending) decision.catch(() => undefined);\n\n let first: Decision | undefined;\n let unavailable: Decision | undefined;\n\n for (const [index, next] of pending.entries()) {\n const decision = await next;\n\n if (decision.access) {\n return { allowed: true, customer: asked, plan: plans[index]!, decision };\n }\n\n first ??= decision;\n // Mesub failed or did not answer within the budget, and nothing was\n // cached for that customer and plan: not a no, an outage.\n if (decision.unavailable) unavailable ??= decision;\n }\n\n if (unavailable) return { allowed: false, reason: 'unavailable', decision: unavailable };\n\n return { allowed: false, reason: 'no_access', ...(first ? { decision: first } : {}) };\n}\n\n/** The body a refusal answers with. `status` only when there is an answer to read it from. */\nexport function denialBody(outcome: Extract<GuardOutcome, { allowed: false }>) {\n return {\n access: false,\n reason: outcome.reason,\n ...(outcome.decision?.answer ? { status: outcome.decision.answer.status } : {}),\n };\n}\n\nexport function accessOf(outcome: Extract<GuardOutcome, { allowed: true }>): MesubAccess {\n const { customer } = outcome;\n\n return {\n wallet:\n customer.kind === 'wallet' ? customer.value : (outcome.decision.answer?.wallet ?? null),\n customer,\n plan: outcome.plan,\n answer: outcome.decision.answer,\n stale: outcome.decision.stale,\n };\n}\n\nexport function denialOf(outcome: Extract<GuardOutcome, { allowed: false }>): Denial {\n return {\n reason: outcome.reason,\n status: DENIAL_STATUS[outcome.reason],\n answer: outcome.decision?.answer ?? null,\n };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/node-sdk/node-sdk/dist/chunk-TDRUSUBV.cjs","../src/guard.ts"],"names":[],"mappings":"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","file":"/home/runner/work/node-sdk/node-sdk/dist/chunk-TDRUSUBV.cjs","sourcesContent":[null,"import type { AccessAnswer, Customer } from './answer.js';\nimport { type Decision, Mesub } from './client.js';\nimport { type Asked, customerOf } from './customer.js';\n\n/** Why a request was turned away, and what it answers by default. */\nexport type DenialReason = 'unauthenticated' | 'no_access' | 'unavailable';\n\nexport type GuardOutcome =\n | { allowed: true; customer: Asked; plan: string; decision: Decision }\n | { allowed: false; reason: DenialReason; decision?: Decision };\n\n/** Who is asking and what Mesub answered, as a guarded route receives it. */\nexport interface MesubAccess {\n /**\n * The wallet that pays. Asked by external id or email, the one Mesub\n * answered with; null when the answer is the outage fallback's and holds none.\n */\n wallet: string | null;\n /** Who Mesub was asked about: a wallet, your own id for them, or their email. */\n customer: Asked;\n /** The plan that let the request through: the first of the list that did. */\n plan: string;\n /** Mesub's answer for that plan. */\n answer: AccessAnswer | null;\n /** The answer came from the outage fallback. */\n stale: boolean;\n}\n\n/** A refusal, as `onDenied` receives it. */\nexport interface Denial {\n reason: DenialReason;\n /** 401, 402 or 503: what would be answered without `onDenied`. */\n status: number;\n /** Mesub's answer, for the first plan asked when there are several. */\n answer: AccessAnswer | null;\n}\n\n/** What a guard answers by default for each refusal. */\nexport const DENIAL_STATUS: Record<DenialReason, number> = {\n unauthenticated: 401,\n no_access: 402,\n unavailable: 503,\n};\n\n/**\n * Seconds a client should wait before asking again when Mesub is unreachable\n * and did not say how long itself.\n */\nexport const UNAVAILABLE_RETRY_AFTER_S = 30;\n\n/**\n * The `Retry-After` of a guard's 503, in seconds: the one Mesub sent with its\n * 429 or 503 when it sent one, `UNAVAILABLE_RETRY_AFTER_S` otherwise (#132).\n */\nexport function retryAfterOf(outcome: Extract<GuardOutcome, { allowed: false }>): string {\n const asked = outcome.decision?.retryAfter;\n\n return String(asked === undefined ? UNAVAILABLE_RETRY_AFTER_S : Math.ceil(asked / 1000));\n}\n\nlet shared: Mesub | undefined;\n\n/** The client a middleware uses when given none: built once, from MESUB_API_KEY. */\nexport function defaultClient(): Mesub {\n shared ??= new Mesub();\n\n return shared;\n}\n\n/**\n * The plan a guard asks about: one, any one of several (the first that grants\n * lets the request through), or either of those worked out per request.\n */\nexport type PlanOption<Req> =\n string | readonly string[] | ((request: Req) => string | readonly string[]);\n\n/**\n * The plans a guard asks about for that request, in order, each once. A\n * plan that is not a non-empty string, or no plan at all, is a broken\n * integration: thrown, never read as a refusal.\n */\nexport function plansOf<Req>(plan: PlanOption<Req>, request: Req): string[] {\n return checkedPlans(typeof plan === 'function' ? plan(request) : plan);\n}\n\n/**\n * Checks a fixed plan when the guard is built, so a typo fails at start-up\n * rather than on the first request. One worked out per request is checked\n * then, by `plansOf`.\n */\nexport function checkPlan<Req>(plan: PlanOption<Req>): void {\n if (typeof plan !== 'function') checkedPlans(plan);\n}\n\n/**\n * Each plan a guard asks about is one call to `/v1/access`, made for every\n * request, against the key's 1000 calls a minute. Three is what a Dev\n * project can hold; a list longer than that is more likely built from the\n * request than written by hand.\n */\nconst MAX_PLANS = 3;\n\nfunction checkedPlans(value: unknown): string[] {\n const plans: unknown[] =\n typeof value === 'string' ? [value] : Array.isArray(value) ? value : [];\n\n if (plans.length === 0 || !plans.every((plan) => typeof plan === 'string' && plan !== '')) {\n throw new TypeError('A guard needs a plan, or a list of plans, as non-empty strings.');\n }\n\n const unique = [...new Set(plans as string[])];\n\n if (unique.length > MAX_PLANS) {\n throw new TypeError(\n `A guard asks about ${MAX_PLANS} plans at most: each one is a call to Mesub on every request.`,\n );\n }\n\n return unique;\n}\n\n/**\n * Who is asking, from your own auth: `(req) => ({ external_id: req.user.id })`,\n * a wallet, or an email. Null or undefined when nobody is signed in, a 401.\n * May be async.\n *\n * It must come from a session you verified, never from the request itself (a\n * query, a body, a header the caller writes): whoever names a subscriber\n * would get their access.\n */\nexport type CustomerOption<Req> = (\n request: Req,\n) => Customer | string | null | undefined | Promise<Customer | string | null | undefined>;\n\n/** Checked when the guard is built: without `customer` it could not tell who is asking. */\nexport function checkCustomer<Req>(options: { customer: CustomerOption<Req> }): void {\n if (typeof options?.customer !== 'function') {\n throw new TypeError(\n 'A guard needs `customer`: a function of the request returning who is signed in, ' +\n 'e.g. `(req) => ({ external_id: req.user.id })`.',\n );\n }\n}\n\n/**\n * Who is asking, as `customer` names them, or null for nobody.\n *\n * A `customer` that returns something Mesub cannot be asked about (two\n * identifiers, an empty one, not a string) is a broken integration: thrown.\n */\nexport async function askerOf<Req>(\n request: Req,\n customer: CustomerOption<Req>,\n): Promise<Asked | null> {\n const named = await customer(request);\n\n if (named === null || named === undefined) return null;\n\n const asked = customerOf(named);\n\n if (asked.value === '') {\n throw new TypeError(\n '`customer` returned an empty value: return null when nobody is signed in.',\n );\n }\n\n return asked;\n}\n\n/** The customer as `decide` takes it. */\nfunction asCustomer(asked: Asked): Customer | string {\n if (asked.kind === 'wallet') return asked.value;\n\n return asked.kind === 'email' ? { email: asked.value } : { external_id: asked.value };\n}\n\n/**\n * The one decision the middlewares make: who is asking, from `askerOf`, then\n * whether they have access to one of the plans.\n *\n * - nobody is asking (`customer` returned null): `unauthenticated`\n * - the fallback of `hasAccess` otherwise, per plan, through `decide`,\n * within the client's `guardTimeout`. The plans are asked at once, so\n * several fit the same budget, and read in order: the first that grants\n * lets the request through, without waiting for the ones after it.\n * `unavailable` when none grants and Mesub failed (outage, rate limit) or\n * the budget ran out on one with nothing cached: 402 only ever means\n * Mesub said no, for every plan\n *\n * An integration error (a bad API key, an unknown plan) is thrown, unless a\n * plan before it in the list already granted.\n *\n * `plansFor` runs only once somebody is identified: a plan worked out from\n * the request never runs, nor throws, for an anonymous one.\n */\nexport async function guard(\n client: Mesub,\n asked: Asked | null,\n plansFor: () => readonly string[],\n): Promise<GuardOutcome> {\n if (!asked) return { allowed: false, reason: 'unauthenticated' };\n\n const plans = plansFor();\n const customer = asCustomer(asked);\n const pending = plans.map((plan) => client.decide(customer, plan));\n\n // The ones not read, once a plan before them grants, must not reject unhandled.\n for (const decision of pending) decision.catch(() => undefined);\n\n let first: Decision | undefined;\n let unavailable: Decision | undefined;\n\n for (const [index, next] of pending.entries()) {\n const decision = await next;\n\n if (decision.access) {\n return { allowed: true, customer: asked, plan: plans[index]!, decision };\n }\n\n first ??= decision;\n // Mesub failed or did not answer within the budget, and nothing was\n // cached for that customer and plan: not a no, an outage.\n if (decision.unavailable) unavailable ??= decision;\n }\n\n if (unavailable) return { allowed: false, reason: 'unavailable', decision: unavailable };\n\n return { allowed: false, reason: 'no_access', ...(first ? { decision: first } : {}) };\n}\n\n/** The body a refusal answers with. `status` only when there is an answer to read it from. */\nexport function denialBody(outcome: Extract<GuardOutcome, { allowed: false }>) {\n return {\n access: false,\n reason: outcome.reason,\n ...(outcome.decision?.answer ? { status: outcome.decision.answer.status } : {}),\n };\n}\n\nexport function accessOf(outcome: Extract<GuardOutcome, { allowed: true }>): MesubAccess {\n const { customer } = outcome;\n\n return {\n wallet:\n customer.kind === 'wallet' ? customer.value : (outcome.decision.answer?.wallet ?? null),\n customer,\n plan: outcome.plan,\n answer: outcome.decision.answer,\n stale: outcome.decision.stale,\n };\n}\n\nexport function denialOf(outcome: Extract<GuardOutcome, { allowed: false }>): Denial {\n return {\n reason: outcome.reason,\n status: DENIAL_STATUS[outcome.reason],\n answer: outcome.decision?.answer ?? null,\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { j as ServerSubscription, B as BlockedReason, T as Transport, R as RequestOptions, w as Subscriptions, A as AccessAnswer, a as AccessList, C as Customer, b as AccessOptions } from './subscriptions-B6Lin6i_.cjs';
1
+ import { j as ServerSubscription, B as BlockedReason, T as Transport, R as RequestOptions, w as Subscriptions, A as AccessAnswer, a as AccessList, C as Customer, b as AccessOptions } from './subscriptions-Dy_BNyPE.cjs';
2
2
 
3
3
  /** One cached answer, with the two moments that decide what it is still good for. */
4
4
  interface CacheEntry<T> {
@@ -231,6 +231,13 @@ interface RenewedDetail {
231
231
  period_end: string;
232
232
  /** The transaction that paid it. */
233
233
  signature: string;
234
+ /**
235
+ * What the receiver's account got of it: `amount` less the fee a
236
+ * Token-2022 mint withholds. Book revenue from it. Null when not known
237
+ * (a transfer Mesub pulled before it kept it), absent from a Mesub that
238
+ * predates it.
239
+ */
240
+ amount_received?: string | null;
234
241
  }
235
242
  /** `subscription.payment_failed`: a pull missed, and what comes next. */
236
243
  interface PaymentFailedDetail {
@@ -577,6 +584,10 @@ declare class Plans {
577
584
  retrieve(slug: string, options?: RequestOptions): Promise<Plan>;
578
585
  }
579
586
 
587
+ /** The project your API key belongs to, from `mesub.project()`. */
588
+ interface Project {
589
+ id: string;
590
+ }
580
591
  /** What a guard decided, and on which answer. */
581
592
  interface Decision {
582
593
  access: boolean;
@@ -673,6 +684,11 @@ declare class Mesub {
673
684
  */
674
685
  private readonly flights;
675
686
  constructor(options?: MesubOptions);
687
+ /**
688
+ * The project your API key belongs to: the quickest way to check that a
689
+ * key works. A wrong key throws `invalid_api_key`. Never cached.
690
+ */
691
+ project(options?: RequestOptions): Promise<Project>;
676
692
  /**
677
693
  * Everything Mesub knows about that customer on that plan: whether they
678
694
  * have access, their status, their dates. Served from the cache while fresh.
@@ -763,4 +779,4 @@ declare class Mesub {
763
779
  private decideBy;
764
780
  }
765
781
 
766
- export { AccessCache as A, type SubscriptionPausedEvent as B, type CacheStore as C, DEFAULT_MAX_STALE_MS as D, type EndedDetail as E, type FirstPayment as F, type SubscriptionPaymentFailedEvent as G, type HeaderSource as H, type SubscriptionRenewalUpcomingEvent as I, type SubscriptionRenewedEvent as J, type SubscriptionResumedEvent as K, type SubscriptionStoppedEvent as L, Mesub as M, type NoDetail as N, type SubscriptionUnpausedEvent as O, type PaymentFailedDetail as P, type WebhookEvent as Q, type RenewalIssue as R, type StoppedDetail as S, type TestEvent as T, type WebhookEventType as U, type VerifyWebhookOptions as V, type WebhookBody as W, Webhooks as X, verifyWebhook as Y, type CacheEntry as a, type AccessCacheOptions as b, type AccessChangedDetail as c, type CachedAnswer as d, type CreatedDetail as e, type Decision as f, type EventList as g, type EventListParams as h, type EventNetwork as i, type EventType as j, Events as k, type MesubEvent as l, type MesubOptions as m, type Plan as n, type PlanStatus as o, type PlanToken as p, Plans as q, type RenewalUpcomingDetail as r, type RenewedDetail as s, type Revalidating as t, type SubscriptionAccessGrantedEvent as u, type SubscriptionAccessRevokedEvent as v, type SubscriptionCancelledEvent as w, type SubscriptionCreatedEvent as x, type SubscriptionEndedEvent as y, type SubscriptionExpiredEvent as z };
782
+ export { AccessCache as A, type SubscriptionExpiredEvent as B, type CacheStore as C, DEFAULT_MAX_STALE_MS as D, type EndedDetail as E, type FirstPayment as F, type SubscriptionPausedEvent as G, type HeaderSource as H, type SubscriptionPaymentFailedEvent as I, type SubscriptionRenewalUpcomingEvent as J, type SubscriptionRenewedEvent as K, type SubscriptionResumedEvent as L, Mesub as M, type NoDetail as N, type SubscriptionStoppedEvent as O, type PaymentFailedDetail as P, type SubscriptionUnpausedEvent as Q, type RenewalIssue as R, type StoppedDetail as S, type TestEvent as T, type WebhookEvent as U, type VerifyWebhookOptions as V, type WebhookBody as W, type WebhookEventType as X, Webhooks as Y, verifyWebhook as Z, type CacheEntry as a, type AccessCacheOptions as b, type AccessChangedDetail as c, type CachedAnswer as d, type CreatedDetail as e, type Decision as f, type EventList as g, type EventListParams as h, type EventNetwork as i, type EventType as j, Events as k, type MesubEvent as l, type MesubOptions as m, type Plan as n, type PlanStatus as o, type PlanToken as p, Plans as q, type Project as r, type RenewalUpcomingDetail as s, type RenewedDetail as t, type Revalidating as u, type SubscriptionAccessGrantedEvent as v, type SubscriptionAccessRevokedEvent as w, type SubscriptionCancelledEvent as x, type SubscriptionCreatedEvent as y, type SubscriptionEndedEvent as z };
@@ -1,4 +1,4 @@
1
- import { j as ServerSubscription, B as BlockedReason, T as Transport, R as RequestOptions, w as Subscriptions, A as AccessAnswer, a as AccessList, C as Customer, b as AccessOptions } from './subscriptions-B6Lin6i_.js';
1
+ import { j as ServerSubscription, B as BlockedReason, T as Transport, R as RequestOptions, w as Subscriptions, A as AccessAnswer, a as AccessList, C as Customer, b as AccessOptions } from './subscriptions-Dy_BNyPE.js';
2
2
 
3
3
  /** One cached answer, with the two moments that decide what it is still good for. */
4
4
  interface CacheEntry<T> {
@@ -231,6 +231,13 @@ interface RenewedDetail {
231
231
  period_end: string;
232
232
  /** The transaction that paid it. */
233
233
  signature: string;
234
+ /**
235
+ * What the receiver's account got of it: `amount` less the fee a
236
+ * Token-2022 mint withholds. Book revenue from it. Null when not known
237
+ * (a transfer Mesub pulled before it kept it), absent from a Mesub that
238
+ * predates it.
239
+ */
240
+ amount_received?: string | null;
234
241
  }
235
242
  /** `subscription.payment_failed`: a pull missed, and what comes next. */
236
243
  interface PaymentFailedDetail {
@@ -577,6 +584,10 @@ declare class Plans {
577
584
  retrieve(slug: string, options?: RequestOptions): Promise<Plan>;
578
585
  }
579
586
 
587
+ /** The project your API key belongs to, from `mesub.project()`. */
588
+ interface Project {
589
+ id: string;
590
+ }
580
591
  /** What a guard decided, and on which answer. */
581
592
  interface Decision {
582
593
  access: boolean;
@@ -673,6 +684,11 @@ declare class Mesub {
673
684
  */
674
685
  private readonly flights;
675
686
  constructor(options?: MesubOptions);
687
+ /**
688
+ * The project your API key belongs to: the quickest way to check that a
689
+ * key works. A wrong key throws `invalid_api_key`. Never cached.
690
+ */
691
+ project(options?: RequestOptions): Promise<Project>;
676
692
  /**
677
693
  * Everything Mesub knows about that customer on that plan: whether they
678
694
  * have access, their status, their dates. Served from the cache while fresh.
@@ -763,4 +779,4 @@ declare class Mesub {
763
779
  private decideBy;
764
780
  }
765
781
 
766
- export { AccessCache as A, type SubscriptionPausedEvent as B, type CacheStore as C, DEFAULT_MAX_STALE_MS as D, type EndedDetail as E, type FirstPayment as F, type SubscriptionPaymentFailedEvent as G, type HeaderSource as H, type SubscriptionRenewalUpcomingEvent as I, type SubscriptionRenewedEvent as J, type SubscriptionResumedEvent as K, type SubscriptionStoppedEvent as L, Mesub as M, type NoDetail as N, type SubscriptionUnpausedEvent as O, type PaymentFailedDetail as P, type WebhookEvent as Q, type RenewalIssue as R, type StoppedDetail as S, type TestEvent as T, type WebhookEventType as U, type VerifyWebhookOptions as V, type WebhookBody as W, Webhooks as X, verifyWebhook as Y, type CacheEntry as a, type AccessCacheOptions as b, type AccessChangedDetail as c, type CachedAnswer as d, type CreatedDetail as e, type Decision as f, type EventList as g, type EventListParams as h, type EventNetwork as i, type EventType as j, Events as k, type MesubEvent as l, type MesubOptions as m, type Plan as n, type PlanStatus as o, type PlanToken as p, Plans as q, type RenewalUpcomingDetail as r, type RenewedDetail as s, type Revalidating as t, type SubscriptionAccessGrantedEvent as u, type SubscriptionAccessRevokedEvent as v, type SubscriptionCancelledEvent as w, type SubscriptionCreatedEvent as x, type SubscriptionEndedEvent as y, type SubscriptionExpiredEvent as z };
782
+ export { AccessCache as A, type SubscriptionExpiredEvent as B, type CacheStore as C, DEFAULT_MAX_STALE_MS as D, type EndedDetail as E, type FirstPayment as F, type SubscriptionPausedEvent as G, type HeaderSource as H, type SubscriptionPaymentFailedEvent as I, type SubscriptionRenewalUpcomingEvent as J, type SubscriptionRenewedEvent as K, type SubscriptionResumedEvent as L, Mesub as M, type NoDetail as N, type SubscriptionStoppedEvent as O, type PaymentFailedDetail as P, type SubscriptionUnpausedEvent as Q, type RenewalIssue as R, type StoppedDetail as S, type TestEvent as T, type WebhookEvent as U, type VerifyWebhookOptions as V, type WebhookBody as W, type WebhookEventType as X, Webhooks as Y, verifyWebhook as Z, type CacheEntry as a, type AccessCacheOptions as b, type AccessChangedDetail as c, type CachedAnswer as d, type CreatedDetail as e, type Decision as f, type EventList as g, type EventListParams as h, type EventNetwork as i, type EventType as j, Events as k, type MesubEvent as l, type MesubOptions as m, type Plan as n, type PlanStatus as o, type PlanToken as p, Plans as q, type Project as r, type RenewalUpcomingDetail as s, type RenewedDetail as t, type Revalidating as u, type SubscriptionAccessGrantedEvent as v, type SubscriptionAccessRevokedEvent as w, type SubscriptionCancelledEvent as x, type SubscriptionCreatedEvent as y, type SubscriptionEndedEvent as z };
@@ -1,4 +1,4 @@
1
- import { j as ServerSubscription } from './subscriptions-B6Lin6i_.js';
1
+ import { j as ServerSubscription } from './subscriptions-Dy_BNyPE.js';
2
2
 
3
3
  /**
4
4
  * Stable codes to branch on, one per kind of failure; `apiCode` tells the
@@ -1,4 +1,4 @@
1
- import { j as ServerSubscription } from './subscriptions-B6Lin6i_.cjs';
1
+ import { j as ServerSubscription } from './subscriptions-Dy_BNyPE.cjs';
2
2
 
3
3
  /**
4
4
  * Stable codes to branch on, one per kind of failure; `apiCode` tells the
package/dist/express.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkD3MM42ZLcjs = require('./chunk-D3MM42ZL.cjs');
6
+ var _chunk5LDAYKUAcjs = require('./chunk-5LDAYKUA.cjs');
7
7
 
8
8
 
9
9
 
@@ -15,16 +15,16 @@ var _chunkD3MM42ZLcjs = require('./chunk-D3MM42ZL.cjs');
15
15
 
16
16
 
17
17
 
18
- var _chunk6XJWKRCNcjs = require('./chunk-6XJWKRCN.cjs');
18
+ var _chunkTDRUSUBVcjs = require('./chunk-TDRUSUBV.cjs');
19
19
 
20
20
 
21
- var _chunkSFK52JDWcjs = require('./chunk-SFK52JDW.cjs');
21
+ var _chunk5THDILDDcjs = require('./chunk-5THDILDD.cjs');
22
22
 
23
23
  // src/express.ts
24
24
  function forNext(error) {
25
- if (!(error instanceof _chunkSFK52JDWcjs.MesubError) || error.status === null) return error;
25
+ if (!(error instanceof _chunk5THDILDDcjs.MesubError) || error.status === null) return error;
26
26
  if (error.status < 400 || error.status >= 500) return error;
27
- return new (0, _chunkSFK52JDWcjs.MesubError)(error.message, {
27
+ return new (0, _chunk5THDILDDcjs.MesubError)(error.message, {
28
28
  status: 500,
29
29
  code: error.code,
30
30
  apiCode: error.apiCode,
@@ -36,30 +36,30 @@ function forNext(error) {
36
36
  });
37
37
  }
38
38
  function requirePlan(plan, options) {
39
- _chunk6XJWKRCNcjs.checkPlan.call(void 0, plan);
40
- _chunk6XJWKRCNcjs.checkCustomer.call(void 0, options);
39
+ _chunkTDRUSUBVcjs.checkPlan.call(void 0, plan);
40
+ _chunkTDRUSUBVcjs.checkCustomer.call(void 0, options);
41
41
  return async (req, res, next) => {
42
42
  try {
43
- const client = _nullishCoalesce(options.client, () => ( _chunk6XJWKRCNcjs.defaultClient.call(void 0, )));
44
- const outcome = await _chunk6XJWKRCNcjs.guard.call(void 0,
43
+ const client = _nullishCoalesce(options.client, () => ( _chunkTDRUSUBVcjs.defaultClient.call(void 0, )));
44
+ const outcome = await _chunkTDRUSUBVcjs.guard.call(void 0,
45
45
  client,
46
- await _chunk6XJWKRCNcjs.askerOf.call(void 0, req, options.customer),
47
- () => _chunk6XJWKRCNcjs.plansOf.call(void 0, plan, req)
46
+ await _chunkTDRUSUBVcjs.askerOf.call(void 0, req, options.customer),
47
+ () => _chunkTDRUSUBVcjs.plansOf.call(void 0, plan, req)
48
48
  );
49
49
  if (outcome.allowed) {
50
- const locals = _chunk6XJWKRCNcjs.accessOf.call(void 0, outcome);
50
+ const locals = _chunkTDRUSUBVcjs.accessOf.call(void 0, outcome);
51
51
  res.locals["mesub"] = locals;
52
52
  return next();
53
53
  }
54
- const denial = _chunk6XJWKRCNcjs.denialOf.call(void 0, outcome);
54
+ const denial = _chunkTDRUSUBVcjs.denialOf.call(void 0, outcome);
55
55
  if (options.onDenied) {
56
56
  await options.onDenied(denial, req, res, next);
57
57
  return;
58
58
  }
59
59
  if (outcome.reason === "unavailable") {
60
- res.setHeader("Retry-After", _chunk6XJWKRCNcjs.retryAfterOf.call(void 0, outcome));
60
+ res.setHeader("Retry-After", _chunkTDRUSUBVcjs.retryAfterOf.call(void 0, outcome));
61
61
  }
62
- res.status(denial.status).json(_chunk6XJWKRCNcjs.denialBody.call(void 0, outcome));
62
+ res.status(denial.status).json(_chunkTDRUSUBVcjs.denialBody.call(void 0, outcome));
63
63
  } catch (error) {
64
64
  next(forNext(error));
65
65
  }
@@ -74,14 +74,14 @@ async function jsonBody(req) {
74
74
  for await (const chunk of req) {
75
75
  const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
76
76
  size += bytes.length;
77
- if (size > _chunkD3MM42ZLcjs.MAX_BODY_BYTES) throw new RangeError("The body is too large.");
77
+ if (size > _chunk5LDAYKUAcjs.MAX_BODY_BYTES) throw new RangeError("The body is too large.");
78
78
  chunks.push(bytes);
79
79
  }
80
80
  if (size === 0) return void 0;
81
81
  return JSON.parse(Buffer.concat(chunks).toString("utf8"));
82
82
  }
83
83
  function mesubRoutes(options) {
84
- _chunkD3MM42ZLcjs.checkWidgetOptions.call(void 0, options);
84
+ _chunk5LDAYKUAcjs.checkWidgetOptions.call(void 0, options);
85
85
  return async (req, res, next) => {
86
86
  try {
87
87
  let body;
@@ -98,10 +98,10 @@ function mesubRoutes(options) {
98
98
  return;
99
99
  }
100
100
  const publicRead = req.method === "GET" && req.path.startsWith("/plans/");
101
- const asked = publicRead ? null : await _chunkD3MM42ZLcjs.widgetCustomer.call(void 0, req, options.customer);
101
+ const asked = publicRead ? null : await _chunk5LDAYKUAcjs.widgetCustomer.call(void 0, req, options.customer);
102
102
  const email = asked && options.email ? await options.email(req) : void 0;
103
- const answer = await _chunkD3MM42ZLcjs.handleWidget.call(void 0,
104
- _nullishCoalesce(options.client, () => ( _chunk6XJWKRCNcjs.defaultClient.call(void 0, ))),
103
+ const answer = await _chunk5LDAYKUAcjs.handleWidget.call(void 0,
104
+ _nullishCoalesce(options.client, () => ( _chunkTDRUSUBVcjs.defaultClient.call(void 0, ))),
105
105
  {
106
106
  method: req.method,
107
107
  path: req.path,
@@ -125,5 +125,5 @@ function mesubRoutes(options) {
125
125
 
126
126
 
127
127
 
128
- exports.MesubError = _chunkSFK52JDWcjs.MesubError; exports.mesubRoutes = mesubRoutes; exports.requirePlan = requirePlan;
128
+ exports.MesubError = _chunk5THDILDDcjs.MesubError; exports.mesubRoutes = mesubRoutes; exports.requirePlan = requirePlan;
129
129
  //# sourceMappingURL=express.cjs.map
@@ -1,11 +1,11 @@
1
1
  import { Request, Response, NextFunction, RequestHandler } from 'express';
2
- import { M as Mesub } from './client-BZB6KIGd.cjs';
3
- import { M as MesubAccess, C as CustomerOption, D as Denial, P as PlanOption } from './guard-D4AB5HtN.cjs';
4
- export { A as Asked, a as DenialReason } from './guard-D4AB5HtN.cjs';
5
- import { W as WidgetRoutesOptions } from './routes-DT8EFWSl.cjs';
6
- export { a as WidgetPayment, b as WidgetSubscriptionDetail, c as WidgetSubscriptionList } from './routes-DT8EFWSl.cjs';
7
- export { M as MesubError } from './errors-DcLfunS-.cjs';
8
- export { C as Customer } from './subscriptions-B6Lin6i_.cjs';
2
+ import { M as Mesub } from './client-B2DttW-V.cjs';
3
+ import { M as MesubAccess, C as CustomerOption, D as Denial, P as PlanOption } from './guard-CDC9mDWY.cjs';
4
+ export { A as Asked, a as DenialReason } from './guard-CDC9mDWY.cjs';
5
+ import { W as WidgetRoutesOptions } from './routes-BpOV9UAR.cjs';
6
+ export { a as WidgetPayment, b as WidgetSubscriptionDetail, c as WidgetSubscriptionList } from './routes-BpOV9UAR.cjs';
7
+ export { M as MesubError } from './errors-xk1hGCOf.cjs';
8
+ export { C as Customer } from './subscriptions-Dy_BNyPE.cjs';
9
9
 
10
10
  /** `@mesub/node/express`: `requirePlan()`. */
11
11
 
package/dist/express.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Request, Response, NextFunction, RequestHandler } from 'express';
2
- import { M as Mesub } from './client-Q5QhXphp.js';
3
- import { M as MesubAccess, C as CustomerOption, D as Denial, P as PlanOption } from './guard-CaXiHMVF.js';
4
- export { A as Asked, a as DenialReason } from './guard-CaXiHMVF.js';
5
- import { W as WidgetRoutesOptions } from './routes-KoaD1Xsk.js';
6
- export { a as WidgetPayment, b as WidgetSubscriptionDetail, c as WidgetSubscriptionList } from './routes-KoaD1Xsk.js';
7
- export { M as MesubError } from './errors-BN4ZWUfM.js';
8
- export { C as Customer } from './subscriptions-B6Lin6i_.js';
2
+ import { M as Mesub } from './client-BHrc_yO3.js';
3
+ import { M as MesubAccess, C as CustomerOption, D as Denial, P as PlanOption } from './guard-CrGTKKXV.js';
4
+ export { A as Asked, a as DenialReason } from './guard-CrGTKKXV.js';
5
+ import { W as WidgetRoutesOptions } from './routes-DWhspa6s.js';
6
+ export { a as WidgetPayment, b as WidgetSubscriptionDetail, c as WidgetSubscriptionList } from './routes-DWhspa6s.js';
7
+ export { M as MesubError } from './errors-CTFJfJoF.js';
8
+ export { C as Customer } from './subscriptions-Dy_BNyPE.js';
9
9
 
10
10
  /** `@mesub/node/express`: `requirePlan()`. */
11
11
 
package/dist/express.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  checkWidgetOptions,
4
4
  handleWidget,
5
5
  widgetCustomer
6
- } from "./chunk-ELS6KPJQ.js";
6
+ } from "./chunk-ANBU7BJU.js";
7
7
  import {
8
8
  accessOf,
9
9
  askerOf,
@@ -15,10 +15,10 @@ import {
15
15
  guard,
16
16
  plansOf,
17
17
  retryAfterOf
18
- } from "./chunk-PH5LR5WA.js";
18
+ } from "./chunk-EGGKTDHO.js";
19
19
  import {
20
20
  MesubError
21
- } from "./chunk-IHGJN3QZ.js";
21
+ } from "./chunk-QDBKSJ56.js";
22
22
 
23
23
  // src/express.ts
24
24
  function forNext(error) {
@@ -1,4 +1,4 @@
1
- import { C as Customer, A as AccessAnswer } from './subscriptions-B6Lin6i_.cjs';
1
+ import { C as Customer, A as AccessAnswer } from './subscriptions-Dy_BNyPE.cjs';
2
2
 
3
3
  /** Who a call is about, normalised as Mesub reads it. */
4
4
  interface Asked {
@@ -1,4 +1,4 @@
1
- import { C as Customer, A as AccessAnswer } from './subscriptions-B6Lin6i_.js';
1
+ import { C as Customer, A as AccessAnswer } from './subscriptions-Dy_BNyPE.js';
2
2
 
3
3
  /** Who a call is about, normalised as Mesub reads it. */
4
4
  interface Asked {
package/dist/index.cjs CHANGED
@@ -10,14 +10,14 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkSFK52JDWcjs = require('./chunk-SFK52JDW.cjs');
13
+ var _chunk5THDILDDcjs = require('./chunk-5THDILDD.cjs');
14
14
 
15
15
 
16
16
 
17
17
 
18
18
 
19
19
 
20
- var _chunk43Q4PNF7cjs = require('./chunk-43Q4PNF7.cjs');
20
+ var _chunk4M3ACBWXcjs = require('./chunk-4M3ACBWX.cjs');
21
21
 
22
22
 
23
23
 
@@ -35,5 +35,5 @@ var _chunk43Q4PNF7cjs = require('./chunk-43Q4PNF7.cjs');
35
35
 
36
36
 
37
37
 
38
- exports.ACCESS_LINE = _chunk43Q4PNF7cjs.ACCESS_LINE; exports.API_VERSION = _chunkSFK52JDWcjs.API_VERSION; exports.API_VERSION_HEADER = _chunkSFK52JDWcjs.API_VERSION_HEADER; exports.AccessCache = _chunkSFK52JDWcjs.AccessCache; exports.CONFIRMATIONS = _chunk43Q4PNF7cjs.CONFIRMATIONS; exports.DEFAULT_MAX_ENTRIES = _chunkSFK52JDWcjs.DEFAULT_MAX_ENTRIES; exports.DEFAULT_MAX_STALE_MS = _chunkSFK52JDWcjs.DEFAULT_MAX_STALE_MS; exports.MemoryStore = _chunkSFK52JDWcjs.MemoryStore; exports.Mesub = _chunkSFK52JDWcjs.Mesub; exports.MesubError = _chunkSFK52JDWcjs.MesubError; exports.MesubSubmitError = _chunkSFK52JDWcjs.MesubSubmitError; exports.SITUATIONS = _chunk43Q4PNF7cjs.SITUATIONS; exports.VERSION = _chunkSFK52JDWcjs.VERSION; exports.explain = _chunk43Q4PNF7cjs.explain; exports.situationOf = _chunk43Q4PNF7cjs.situationOf; exports.verifyWebhook = _chunkSFK52JDWcjs.verifyWebhook;
38
+ exports.ACCESS_LINE = _chunk4M3ACBWXcjs.ACCESS_LINE; exports.API_VERSION = _chunk5THDILDDcjs.API_VERSION; exports.API_VERSION_HEADER = _chunk5THDILDDcjs.API_VERSION_HEADER; exports.AccessCache = _chunk5THDILDDcjs.AccessCache; exports.CONFIRMATIONS = _chunk4M3ACBWXcjs.CONFIRMATIONS; exports.DEFAULT_MAX_ENTRIES = _chunk5THDILDDcjs.DEFAULT_MAX_ENTRIES; exports.DEFAULT_MAX_STALE_MS = _chunk5THDILDDcjs.DEFAULT_MAX_STALE_MS; exports.MemoryStore = _chunk5THDILDDcjs.MemoryStore; exports.Mesub = _chunk5THDILDDcjs.Mesub; exports.MesubError = _chunk5THDILDDcjs.MesubError; exports.MesubSubmitError = _chunk5THDILDDcjs.MesubSubmitError; exports.SITUATIONS = _chunk4M3ACBWXcjs.SITUATIONS; exports.VERSION = _chunk5THDILDDcjs.VERSION; exports.explain = _chunk4M3ACBWXcjs.explain; exports.situationOf = _chunk4M3ACBWXcjs.situationOf; exports.verifyWebhook = _chunk5THDILDDcjs.verifyWebhook;
39
39
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { C as CacheStore, a as CacheEntry } from './client-BZB6KIGd.cjs';
2
- export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, R as RenewalIssue, r as RenewalUpcomingDetail, s as RenewedDetail, t as Revalidating, S as StoppedDetail, u as SubscriptionAccessGrantedEvent, v as SubscriptionAccessRevokedEvent, w as SubscriptionCancelledEvent, x as SubscriptionCreatedEvent, y as SubscriptionEndedEvent, z as SubscriptionExpiredEvent, B as SubscriptionPausedEvent, G as SubscriptionPaymentFailedEvent, I as SubscriptionRenewalUpcomingEvent, J as SubscriptionRenewedEvent, K as SubscriptionResumedEvent, L as SubscriptionStoppedEvent, O as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, Q as WebhookEvent, U as WebhookEventType, X as Webhooks, Y as verifyWebhook } from './client-BZB6KIGd.cjs';
3
- export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-DcLfunS-.cjs';
4
- export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-B6Lin6i_.cjs';
1
+ import { C as CacheStore, a as CacheEntry } from './client-B2DttW-V.cjs';
2
+ export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, r as Project, R as RenewalIssue, s as RenewalUpcomingDetail, t as RenewedDetail, u as Revalidating, S as StoppedDetail, v as SubscriptionAccessGrantedEvent, w as SubscriptionAccessRevokedEvent, x as SubscriptionCancelledEvent, y as SubscriptionCreatedEvent, z as SubscriptionEndedEvent, B as SubscriptionExpiredEvent, G as SubscriptionPausedEvent, I as SubscriptionPaymentFailedEvent, J as SubscriptionRenewalUpcomingEvent, K as SubscriptionRenewedEvent, L as SubscriptionResumedEvent, O as SubscriptionStoppedEvent, Q as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, U as WebhookEvent, X as WebhookEventType, Y as Webhooks, Z as verifyWebhook } from './client-B2DttW-V.cjs';
3
+ export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-xk1hGCOf.cjs';
4
+ export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-Dy_BNyPE.cjs';
5
5
  export { ACCESS_LINE, CONFIRMATIONS, ConfirmationKey, ExplainOptions, Explainable, ExplainedAction, Explanation, SITUATIONS, Situation, SituationActionId, SituationActionTemplate, SituationActor, SituationKey, SituationText, explain, situationOf } from './situations.cjs';
6
6
 
7
7
  /** Kept in step with package.json by `test/version.spec.ts`. */
8
- declare const VERSION = "0.1.5";
8
+ declare const VERSION = "0.1.6";
9
9
  /**
10
10
  * The version of the Mesub API this release was written against, sent in
11
11
  * the `Mesub-Version` header of every call, so the API can change its
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { C as CacheStore, a as CacheEntry } from './client-Q5QhXphp.js';
2
- export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, R as RenewalIssue, r as RenewalUpcomingDetail, s as RenewedDetail, t as Revalidating, S as StoppedDetail, u as SubscriptionAccessGrantedEvent, v as SubscriptionAccessRevokedEvent, w as SubscriptionCancelledEvent, x as SubscriptionCreatedEvent, y as SubscriptionEndedEvent, z as SubscriptionExpiredEvent, B as SubscriptionPausedEvent, G as SubscriptionPaymentFailedEvent, I as SubscriptionRenewalUpcomingEvent, J as SubscriptionRenewedEvent, K as SubscriptionResumedEvent, L as SubscriptionStoppedEvent, O as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, Q as WebhookEvent, U as WebhookEventType, X as Webhooks, Y as verifyWebhook } from './client-Q5QhXphp.js';
3
- export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-BN4ZWUfM.js';
4
- export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-B6Lin6i_.js';
1
+ import { C as CacheStore, a as CacheEntry } from './client-BHrc_yO3.js';
2
+ export { A as AccessCache, b as AccessCacheOptions, c as AccessChangedDetail, d as CachedAnswer, e as CreatedDetail, D as DEFAULT_MAX_STALE_MS, f as Decision, E as EndedDetail, g as EventList, h as EventListParams, i as EventNetwork, j as EventType, k as Events, F as FirstPayment, H as HeaderSource, M as Mesub, l as MesubEvent, m as MesubOptions, N as NoDetail, P as PaymentFailedDetail, n as Plan, o as PlanStatus, p as PlanToken, q as Plans, r as Project, R as RenewalIssue, s as RenewalUpcomingDetail, t as RenewedDetail, u as Revalidating, S as StoppedDetail, v as SubscriptionAccessGrantedEvent, w as SubscriptionAccessRevokedEvent, x as SubscriptionCancelledEvent, y as SubscriptionCreatedEvent, z as SubscriptionEndedEvent, B as SubscriptionExpiredEvent, G as SubscriptionPausedEvent, I as SubscriptionPaymentFailedEvent, J as SubscriptionRenewalUpcomingEvent, K as SubscriptionRenewedEvent, L as SubscriptionResumedEvent, O as SubscriptionStoppedEvent, Q as SubscriptionUnpausedEvent, T as TestEvent, V as VerifyWebhookOptions, W as WebhookBody, U as WebhookEvent, X as WebhookEventType, Y as Webhooks, Z as verifyWebhook } from './client-BHrc_yO3.js';
3
+ export { M as MesubError, a as MesubErrorCode, b as MesubErrorOptions, c as MesubSubmitError, d as MesubSubmitErrorOptions } from './errors-CTFJfJoF.js';
4
+ export { A as AccessAnswer, a as AccessList, b as AccessOptions, c as AttemptsParams, B as BlockedReason, d as ConfirmOptions, e as ConfirmParams, f as ConfirmReasonCode, g as ConfirmResult, C as Customer, E as EndReason, L as LateReason, h as ListParams, P as PaymentStatus, i as PullOutcome, R as RequestOptions, S as ServedAttempt, j as ServerSubscription, k as ServerSubscriptionList, l as ServerSubscriptionStatus, m as StopReason, n as SubmitOptions, o as SubmitParams, p as SubmitResult, q as SubscribeCosts, r as SubscribeParams, s as SubscribeTransaction, t as SubscriptionAttempt, u as SubscriptionAttemptList, v as SubscriptionStatus, w as Subscriptions, W as WalletTransaction } from './subscriptions-Dy_BNyPE.js';
5
5
  export { ACCESS_LINE, CONFIRMATIONS, ConfirmationKey, ExplainOptions, Explainable, ExplainedAction, Explanation, SITUATIONS, Situation, SituationActionId, SituationActionTemplate, SituationActor, SituationKey, SituationText, explain, situationOf } from './situations.js';
6
6
 
7
7
  /** Kept in step with package.json by `test/version.spec.ts`. */
8
- declare const VERSION = "0.1.5";
8
+ declare const VERSION = "0.1.6";
9
9
  /**
10
10
  * The version of the Mesub API this release was written against, sent in
11
11
  * the `Mesub-Version` header of every call, so the API can change its