@crvouga/mockingbird-service-flex 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  runCli,
4
4
  serveCommand,
5
5
  serveTarget
6
- } from "./chunk-Q6AKODYZ.js";
7
- import "./chunk-RB3RIE5G.js";
6
+ } from "./chunk-7ZR3HG2Y.js";
7
+ import "./chunk-CTPIFEBJ.js";
8
8
 
9
9
  // src/cli.ts
10
10
  var code = await runCli(
package/dist/index.d.ts CHANGED
@@ -657,15 +657,50 @@ type SetupIntentRecord = {
657
657
  type NextAction = {
658
658
  type: NextActionType;
659
659
  } & Record<string, unknown>;
660
+ /** How often a recurring price bills (`price_data.recurring`). */
661
+ type Recurring = {
662
+ interval: "day" | "week" | "month" | "year";
663
+ interval_count?: number;
664
+ };
660
665
  type LineItemRecord = {
661
666
  price_data: {
662
667
  product: string;
663
668
  unit_amount: number;
669
+ recurring?: Recurring | null;
664
670
  };
665
671
  quantity: number;
666
672
  amount_total: number;
667
673
  };
668
- type SessionMode = "payment" | "off_session" | "setup";
674
+ /** What a subscription-mode session was created with (`subscription_data`). */
675
+ type SubscriptionData = {
676
+ cancel_at_period_end?: boolean;
677
+ metadata?: Record<string, string>;
678
+ };
679
+ type SessionMode = "payment" | "subscription" | "off_session" | "setup";
680
+ declare const SUBSCRIPTION_STATUSES: readonly ["incomplete", "incomplete_expired", "trialing", "active", "past_due", "canceled", "unpaid", "paused"];
681
+ type SubscriptionStatus = (typeof SUBSCRIPTION_STATUSES)[number];
682
+ /** A subscription a paid subscription-mode checkout session created. */
683
+ type SubscriptionRecord = {
684
+ subscription_id: string;
685
+ status: SubscriptionStatus;
686
+ items: {
687
+ price_data: {
688
+ product: string;
689
+ unit_amount: number;
690
+ recurring: Recurring;
691
+ };
692
+ quantity: number;
693
+ }[];
694
+ customer: string | null;
695
+ default_payment_method: string | null;
696
+ cancel_at_period_end: boolean;
697
+ current_period_start: string;
698
+ current_period_end: string;
699
+ canceled_at: string | null;
700
+ metadata: Record<string, string> | null;
701
+ test_mode: boolean;
702
+ created_at: string;
703
+ };
669
704
  type SessionStatus = "open" | "paid" | "complete" | "canceled" | "expired";
670
705
  type SessionRecord = {
671
706
  checkout_session_id: string;
@@ -676,6 +711,9 @@ type SessionRecord = {
676
711
  customer: string | null;
677
712
  payment_intent: string | null;
678
713
  setup_intent: string | null;
714
+ /** The subscription a paid subscription-mode session created. */
715
+ subscription: string | null;
716
+ subscription_data: SubscriptionData | null;
679
717
  mode: SessionMode;
680
718
  status: SessionStatus;
681
719
  /** The hosted page (`redirect_url` and `url`). */
@@ -745,6 +783,7 @@ declare class FlexState {
745
783
  readonly paymentIntents: Collection<PaymentIntentRecord>;
746
784
  readonly setupIntents: Collection<SetupIntentRecord>;
747
785
  readonly refunds: Collection<RefundRecord>;
786
+ readonly subscriptions: Collection<SubscriptionRecord>;
748
787
  readonly settings: Collection<Settings>;
749
788
  readonly ids: IdSequence;
750
789
  constructor(sqlite: SqliteClient, namespace: string, seed: {
@@ -923,10 +962,10 @@ type OpenAPIDocument = {
923
962
  };
924
963
 
925
964
  declare const document: OpenAPIDocument;
926
- type OperationId = "ListProducts" | "CreateProduct" | "GetProduct" | "UpdateProduct" | "ListCheckoutSessions" | "CreateCheckoutSession" | "GetCheckoutSession" | "RefundCheckoutSession" | "CreateCustomer" | "GetSetupIntent" | "HostedCheckoutPage" | "SubmitHostedCheckout" | "CancelHostedCheckout";
927
- type SupportedOperationId = "ListProducts" | "CreateProduct" | "GetProduct" | "UpdateProduct" | "ListCheckoutSessions" | "CreateCheckoutSession" | "GetCheckoutSession" | "RefundCheckoutSession" | "CreateCustomer" | "GetSetupIntent" | "HostedCheckoutPage" | "SubmitHostedCheckout" | "CancelHostedCheckout";
928
- declare const operationIds: readonly ["ListProducts", "CreateProduct", "GetProduct", "UpdateProduct", "ListCheckoutSessions", "CreateCheckoutSession", "GetCheckoutSession", "RefundCheckoutSession", "CreateCustomer", "GetSetupIntent", "HostedCheckoutPage", "SubmitHostedCheckout", "CancelHostedCheckout"];
929
- declare const supportedOperationIds: readonly ["ListProducts", "CreateProduct", "GetProduct", "UpdateProduct", "ListCheckoutSessions", "CreateCheckoutSession", "GetCheckoutSession", "RefundCheckoutSession", "CreateCustomer", "GetSetupIntent", "HostedCheckoutPage", "SubmitHostedCheckout", "CancelHostedCheckout"];
965
+ type OperationId = "ListProducts" | "CreateProduct" | "GetProduct" | "UpdateProduct" | "ListCheckoutSessions" | "CreateCheckoutSession" | "GetCheckoutSession" | "RefundCheckoutSession" | "CreateCustomer" | "GetSetupIntent" | "GetSubscription" | "HostedCheckoutPage" | "SubmitHostedCheckout" | "CancelHostedCheckout";
966
+ type SupportedOperationId = "ListProducts" | "CreateProduct" | "GetProduct" | "UpdateProduct" | "ListCheckoutSessions" | "CreateCheckoutSession" | "GetCheckoutSession" | "RefundCheckoutSession" | "CreateCustomer" | "GetSetupIntent" | "GetSubscription" | "HostedCheckoutPage" | "SubmitHostedCheckout" | "CancelHostedCheckout";
967
+ declare const operationIds: readonly ["ListProducts", "CreateProduct", "GetProduct", "UpdateProduct", "ListCheckoutSessions", "CreateCheckoutSession", "GetCheckoutSession", "RefundCheckoutSession", "CreateCustomer", "GetSetupIntent", "GetSubscription", "HostedCheckoutPage", "SubmitHostedCheckout", "CancelHostedCheckout"];
968
+ declare const supportedOperationIds: readonly ["ListProducts", "CreateProduct", "GetProduct", "UpdateProduct", "ListCheckoutSessions", "CreateCheckoutSession", "GetCheckoutSession", "RefundCheckoutSession", "CreateCustomer", "GetSetupIntent", "GetSubscription", "HostedCheckoutPage", "SubmitHostedCheckout", "CancelHostedCheckout"];
930
969
 
931
970
  /** Test cards the hosted page recognises (spaces are ignored). */
932
971
  declare const CARDS: {
@@ -995,7 +1034,7 @@ declare const createRuntime: (options?: FlexRuntimeOptions) => FlexRuntime;
995
1034
 
996
1035
  declare const FLEX_NAMESPACE = "flex";
997
1036
  /** Every webhook event type the mock sends (our receiver reconciles on each). */
998
- declare const FLEX_EVENT_TYPES: readonly ["product.updated", "checkout.session.completed", "checkout_session.completed", "checkout.session.async_payment_succeeded", "checkout.session.async_payment_failed", "checkout.session.refunded", "checkout.session.expired", "checkout_session.expired", "payment_intent.succeeded", "refund.created", "refund.updated", "charge.refunded", "charge.refund.updated"];
1037
+ declare const FLEX_EVENT_TYPES: readonly ["product.updated", "checkout.session.completed", "checkout_session.completed", "checkout.session.async_payment_succeeded", "checkout.session.async_payment_failed", "checkout.session.refunded", "checkout.session.expired", "checkout_session.expired", "payment_intent.succeeded", "customer.subscription.created", "refund.created", "refund.updated", "charge.refunded", "charge.refund.updated"];
999
1038
  type FlexEventType = (typeof FLEX_EVENT_TYPES)[number];
1000
1039
  /** The event inside the `{event: {...}}` webhook envelope. */
1001
1040
  type FlexEvent = {
@@ -1023,6 +1062,12 @@ type SessionView = {
1023
1062
  expandCustomer: boolean;
1024
1063
  expandPaymentIntent: boolean;
1025
1064
  };
1065
+ /**
1066
+ * The end of a billing period that starts at `startMs`: `interval_count` intervals later.
1067
+ * Month and year steps keep the day of month, clamped to the target month's length
1068
+ * (Jan 31 + 1 month = Feb 28/29), the way card-network billing anchors do.
1069
+ */
1070
+ declare const periodEnd: (startMs: number, recurring: Recurring) => number;
1026
1071
  /**
1027
1072
  * Stateful mock of the Flex HSA/FSA payments API.
1028
1073
  *
@@ -1069,6 +1114,14 @@ declare class FlexAPI implements FetchAPI$1 {
1069
1114
  private createCustomer;
1070
1115
  private newCustomer;
1071
1116
  private getSetupIntent;
1117
+ private getSubscription;
1118
+ /**
1119
+ * Start the subscription a paid subscription-mode session buys: active, billed from now
1120
+ * for one period of its first recurring line item, charged to the card just used.
1121
+ */
1122
+ private startSubscription;
1123
+ /** The subscriptions paid subscription-mode sessions created in this namespace. */
1124
+ subscriptions(): SubscriptionRecord[];
1072
1125
  private paymentIntentFor;
1073
1126
  /** Create or update the session's payment intent (`PUT /__admin/sessions/:id/payment-intent`). */
1074
1127
  setPaymentIntent(id: string, patch: Partial<Pick<PaymentIntentRecord, "status" | "amount_received" | "payment_method" | "customer">>): PaymentIntentRecord | undefined;
@@ -1108,5 +1161,5 @@ declare class FlexAPI implements FetchAPI$1 {
1108
1161
  /** Whether a string is one of the next-action types. */
1109
1162
  declare const isNextActionType: (value: unknown) => value is NextActionType;
1110
1163
 
1111
- export { CARDS, CORPUS_ROWS, DEFAULT_SETTINGS, ELIGIBILITIES, FLEX_EVENT_TYPES, FLEX_NAMESPACE, FLEX_PRESETS, FlexAPI, NEXT_ACTION_TYPES, PAYMENT_INTENT_STATUSES, classifyCard, corpusProduct, createRuntime, document, isNextActionType, keyMode, operationIds, substituteSessionId, supportedOperationIds };
1112
- export type { CardOutcome, CorpusRow, CustomerRecord, Eligibility, FetchAPI$1 as FetchAPI, FlexAPIOptions, FlexEvent, FlexEventType, FlexRuntime, FlexRuntimeOptions, LineItemRecord, NextAction, NextActionType, OperationId, PaymentIntentRecord, PaymentIntentStatus, PaymentMethodRecord, ProductRecord, RefundRecord, SessionMode, SessionRecord, SessionStatus, Settings, SetupIntentRecord, SqliteClient, SupportedOperationId };
1164
+ export { CARDS, CORPUS_ROWS, DEFAULT_SETTINGS, ELIGIBILITIES, FLEX_EVENT_TYPES, FLEX_NAMESPACE, FLEX_PRESETS, FlexAPI, NEXT_ACTION_TYPES, PAYMENT_INTENT_STATUSES, SUBSCRIPTION_STATUSES, classifyCard, corpusProduct, createRuntime, document, isNextActionType, keyMode, operationIds, periodEnd, substituteSessionId, supportedOperationIds };
1165
+ export type { CardOutcome, CorpusRow, CustomerRecord, Eligibility, FetchAPI$1 as FetchAPI, FlexAPIOptions, FlexEvent, FlexEventType, FlexRuntime, FlexRuntimeOptions, LineItemRecord, NextAction, NextActionType, OperationId, PaymentIntentRecord, PaymentIntentStatus, PaymentMethodRecord, ProductRecord, Recurring, RefundRecord, SessionMode, SessionRecord, SessionStatus, Settings, SetupIntentRecord, SqliteClient, SubscriptionData, SubscriptionRecord, SubscriptionStatus, SupportedOperationId };
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  FlexAPI,
10
10
  NEXT_ACTION_TYPES,
11
11
  PAYMENT_INTENT_STATUSES,
12
+ SUBSCRIPTION_STATUSES,
12
13
  classifyCard,
13
14
  corpusProduct,
14
15
  createRuntime,
@@ -16,9 +17,10 @@ import {
16
17
  isNextActionType,
17
18
  keyMode,
18
19
  operationIds,
20
+ periodEnd,
19
21
  substituteSessionId,
20
22
  supportedOperationIds
21
- } from "./chunk-RB3RIE5G.js";
23
+ } from "./chunk-CTPIFEBJ.js";
22
24
  export {
23
25
  CARDS,
24
26
  CORPUS_ROWS,
@@ -30,6 +32,7 @@ export {
30
32
  FlexAPI,
31
33
  NEXT_ACTION_TYPES,
32
34
  PAYMENT_INTENT_STATUSES,
35
+ SUBSCRIPTION_STATUSES,
33
36
  classifyCard,
34
37
  corpusProduct,
35
38
  createRuntime,
@@ -37,6 +40,7 @@ export {
37
40
  isNextActionType,
38
41
  keyMode,
39
42
  operationIds,
43
+ periodEnd,
40
44
  substituteSessionId,
41
45
  supportedOperationIds
42
46
  };
package/dist/server.d.ts CHANGED
@@ -1160,15 +1160,50 @@ type SetupIntentRecord = {
1160
1160
  type NextAction = {
1161
1161
  type: NextActionType;
1162
1162
  } & Record<string, unknown>;
1163
+ /** How often a recurring price bills (`price_data.recurring`). */
1164
+ type Recurring = {
1165
+ interval: "day" | "week" | "month" | "year";
1166
+ interval_count?: number;
1167
+ };
1163
1168
  type LineItemRecord = {
1164
1169
  price_data: {
1165
1170
  product: string;
1166
1171
  unit_amount: number;
1172
+ recurring?: Recurring | null;
1167
1173
  };
1168
1174
  quantity: number;
1169
1175
  amount_total: number;
1170
1176
  };
1171
- type SessionMode = "payment" | "off_session" | "setup";
1177
+ /** What a subscription-mode session was created with (`subscription_data`). */
1178
+ type SubscriptionData = {
1179
+ cancel_at_period_end?: boolean;
1180
+ metadata?: Record<string, string>;
1181
+ };
1182
+ type SessionMode = "payment" | "subscription" | "off_session" | "setup";
1183
+ declare const SUBSCRIPTION_STATUSES: readonly ["incomplete", "incomplete_expired", "trialing", "active", "past_due", "canceled", "unpaid", "paused"];
1184
+ type SubscriptionStatus = (typeof SUBSCRIPTION_STATUSES)[number];
1185
+ /** A subscription a paid subscription-mode checkout session created. */
1186
+ type SubscriptionRecord = {
1187
+ subscription_id: string;
1188
+ status: SubscriptionStatus;
1189
+ items: {
1190
+ price_data: {
1191
+ product: string;
1192
+ unit_amount: number;
1193
+ recurring: Recurring;
1194
+ };
1195
+ quantity: number;
1196
+ }[];
1197
+ customer: string | null;
1198
+ default_payment_method: string | null;
1199
+ cancel_at_period_end: boolean;
1200
+ current_period_start: string;
1201
+ current_period_end: string;
1202
+ canceled_at: string | null;
1203
+ metadata: Record<string, string> | null;
1204
+ test_mode: boolean;
1205
+ created_at: string;
1206
+ };
1172
1207
  type SessionStatus = "open" | "paid" | "complete" | "canceled" | "expired";
1173
1208
  type SessionRecord = {
1174
1209
  checkout_session_id: string;
@@ -1179,6 +1214,9 @@ type SessionRecord = {
1179
1214
  customer: string | null;
1180
1215
  payment_intent: string | null;
1181
1216
  setup_intent: string | null;
1217
+ /** The subscription a paid subscription-mode session created. */
1218
+ subscription: string | null;
1219
+ subscription_data: SubscriptionData | null;
1182
1220
  mode: SessionMode;
1183
1221
  status: SessionStatus;
1184
1222
  /** The hosted page (`redirect_url` and `url`). */
@@ -1245,6 +1283,7 @@ declare class FlexState {
1245
1283
  readonly paymentIntents: Collection<PaymentIntentRecord>;
1246
1284
  readonly setupIntents: Collection<SetupIntentRecord>;
1247
1285
  readonly refunds: Collection<RefundRecord>;
1286
+ readonly subscriptions: Collection<SubscriptionRecord>;
1248
1287
  readonly settings: Collection<Settings>;
1249
1288
  readonly ids: IdSequence;
1250
1289
  constructor(sqlite: SqliteClient, namespace: string, seed: {
@@ -1327,6 +1366,14 @@ declare class FlexAPI implements FetchAPI {
1327
1366
  private createCustomer;
1328
1367
  private newCustomer;
1329
1368
  private getSetupIntent;
1369
+ private getSubscription;
1370
+ /**
1371
+ * Start the subscription a paid subscription-mode session buys: active, billed from now
1372
+ * for one period of its first recurring line item, charged to the card just used.
1373
+ */
1374
+ private startSubscription;
1375
+ /** The subscriptions paid subscription-mode sessions created in this namespace. */
1376
+ subscriptions(): SubscriptionRecord[];
1330
1377
  private paymentIntentFor;
1331
1378
  /** Create or update the session's payment intent (`PUT /__admin/sessions/:id/payment-intent`). */
1332
1379
  setPaymentIntent(id: string, patch: Partial<Pick<PaymentIntentRecord, "status" | "amount_received" | "payment_method" | "customer">>): PaymentIntentRecord | undefined;
package/dist/server.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  DEFAULT_PORT,
3
3
  createServer,
4
4
  serveTarget
5
- } from "./chunk-Q6AKODYZ.js";
6
- import "./chunk-RB3RIE5G.js";
5
+ } from "./chunk-7ZR3HG2Y.js";
6
+ import "./chunk-CTPIFEBJ.js";
7
7
  export {
8
8
  DEFAULT_PORT,
9
9
  createServer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@crvouga/mockingbird-service-flex",
3
- "version": "0.2.0",
4
- "description": "Stateful mock of the Flex HSA/FSA payments API: products (recorded catalog corpus), checkout sessions in payment, off-session and setup modes, customers, setup intents, refunds, the hosted checkout page, and Svix-signed webhooks.",
3
+ "version": "0.3.0",
4
+ "description": "Stateful mock of the Flex HSA/FSA payments API: products (recorded catalog corpus), checkout sessions in payment, subscription, off-session and setup modes, subscriptions, customers, setup intents, refunds, the hosted checkout page, and Svix-signed webhooks.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -54,7 +54,7 @@
54
54
  "layer": "service",
55
55
  "category": "payments",
56
56
  "displayName": "Flex",
57
- "status": "wip",
57
+ "status": "ready",
58
58
  "playground": {
59
59
  "headers": {
60
60
  "authorization": "Bearer fsk_test_mockingbird"