@crvouga/mockingbird-service-flex 3.9.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +12 -6
- package/dist/{chunk-5DQQEGW6.js → chunk-3FSLZROR.js} +151 -33
- package/dist/chunk-3FSLZROR.js.map +7 -0
- package/dist/{chunk-LS6VVLOL.js → chunk-H6USVBBB.js} +3 -3
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +3 -1
- package/dist/server.d.ts +16 -1
- package/dist/server.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-5DQQEGW6.js.map +0 -7
- /package/dist/{chunk-LS6VVLOL.js.map → chunk-H6USVBBB.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-flex
|
|
2
2
|
|
|
3
|
+
## 4.0.0 (2026-10-29)
|
|
4
|
+
|
|
5
|
+
### ⚠️ Breaking changes
|
|
6
|
+
|
|
7
|
+
- nest webhook objects under their resource key and send refunds as Flex does ([e460af6](https://github.com/crvouga/mockingbird/commit/e460af601280becdf8bd7c4f16dfada2cf181545))
|
|
8
|
+
|
|
9
|
+
## 3.10.0 (2026-10-24)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- add buffered SQL durability ([288bdcc](https://github.com/crvouga/mockingbird/commit/288bdcca84582787a54c4fdf9e803db9aac0b8d7))
|
|
14
|
+
- add efficient browser durability ([a8be579](https://github.com/crvouga/mockingbird/commit/a8be5799a883ddf6f731208e06f399410de4661a))
|
|
15
|
+
|
|
3
16
|
## 3.9.0 (2026-10-21)
|
|
4
17
|
|
|
5
18
|
### Features
|
package/README.md
CHANGED
|
@@ -140,10 +140,14 @@ overrides the origin.
|
|
|
140
140
|
|
|
141
141
|
Svix-signed (`svix-id`, `svix-timestamp` = wall clock, `svix-signature: v1,<base64
|
|
142
142
|
HMAC-SHA256(key, "<id>.<ts>.<body>")>`, key = base64-decoded secret after `fwhsec_`/`whsec_`).
|
|
143
|
-
Body: `{event: {event_id, event_type, object, event_dt, test_mode, created_at}}`.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`
|
|
143
|
+
Body: `{event: {event_id, event_type, object, event_dt, test_mode, created_at}}`. As in Flex's
|
|
144
|
+
OpenAPI (`EventObject`) and production deliveries, `object` holds one key named for the
|
|
145
|
+
resource: checkout events `{checkout_session}` (so `object.checkout_session.checkout_session_id`),
|
|
146
|
+
payment-intent events `{payment_intent}`, `charge.*` events `{charge}` (its intent is
|
|
147
|
+
`charge.payment_intent`), `refund.*` and `charge.refund.updated` events `{refund}` (its intent is
|
|
148
|
+
`refund.payment_intent_id`), `customer.subscription.*` `{subscription}` and `product.updated`
|
|
149
|
+
`{product}`. Payment-intent, charge and refund objects name no checkout session: a receiver
|
|
150
|
+
finds the payment through the payment intent.
|
|
147
151
|
|
|
148
152
|
| Event | When |
|
|
149
153
|
| --- | --- |
|
|
@@ -152,7 +156,7 @@ intent plus `checkout_session_id`, refund events `checkout_session` and `payment
|
|
|
152
156
|
| `checkout.session.async_payment_succeeded` | settling a session whose intent was `processing` |
|
|
153
157
|
| `checkout.session.async_payment_failed` | a decline (page, admin, off-session) |
|
|
154
158
|
| `checkout.session.expired` | `…/expire`, or `expires_at` passing on the emulator clock (default 24 h) |
|
|
155
|
-
| `refund.created
|
|
159
|
+
| `refund.created` (twice), `charge.refunded`, `refund.updated`, `charge.refund.updated` | each refund, through the API or the dashboard (`POST /__admin/sessions/:id/refund`), in the order production delivers a dashboard refund. `checkout.session.refunded` is in Flex's event list but has never been seen on a refund, so it is only sent through `POST /__admin/events` |
|
|
156
160
|
| `product.updated` | `PATCH /v1/products/{id}` and `PUT /__admin/products/:id` |
|
|
157
161
|
| `checkout_session.completed`, `checkout_session.expired` | the aliases, with `PUT /__admin/settings {"eventNaming": "underscored"}` |
|
|
158
162
|
|
|
@@ -168,6 +172,7 @@ retried (immediately, 5 s, 5 min, 30 min, 2 h); `GET /__admin/webhooks`, `…/ev
|
|
|
168
172
|
| `POST /__admin/sessions/:id/complete` | `{card?}`: settle as if paid (HSA card unless `card` is `4242…`). |
|
|
169
173
|
| `POST /__admin/sessions/:id/decline` | Payment intent → `requires_payment_method`. |
|
|
170
174
|
| `POST /__admin/sessions/:id/expire` | Session → `expired`. |
|
|
175
|
+
| `POST /__admin/sessions/:id/refund` | `{amount?}`: a refund made in Flex's dashboard (full by default); emits the refund events. 409 when unpaid, 400 over the unrefunded amount. |
|
|
171
176
|
| `POST /__admin/sessions/:id/require_action` | `{next_action_type?}`: `collect_letter_of_medical_necessity` (default), `provide_second_payment_method`, `provide_alternative_payment_method`, `payment_failed`. |
|
|
172
177
|
| `PUT /__admin/sessions/:id/payment-intent` | `{status, amount_received?}`: `requires_payment_method`, `requires_action`, `processing`, `succeeded`, `canceled`. |
|
|
173
178
|
| `GET /__admin/sessions`, `GET /__admin/sessions/:id` | The namespace's sessions. |
|
|
@@ -221,11 +226,12 @@ so product names are synthesised.
|
|
|
221
226
|
|
|
222
227
|
| Export | Kind | Description |
|
|
223
228
|
| --- | --- | --- |
|
|
224
|
-
| `FlexAPI` | class | The in-process emulator: `fetch(request)`, `reset()`, `settle(id)`, `decline(id)`, `expire(id)`, `requireAction(id, type)`, `setPaymentIntent(id, patch)`, `applyRefund(id, amount)`, `putProduct(product)`, `emitFor(type, target)`, `tick()`, `sessions()`, `subscriptions()`, `present(session, view)`. Options: `sqlite`, `now`, `namespace`, `publicNamespace`, `products`, `settings`, `onEvent`. |
|
|
229
|
+
| `FlexAPI` | class | The in-process emulator: `fetch(request)`, `reset()`, `settle(id)`, `decline(id)`, `expire(id)`, `requireAction(id, type)`, `setPaymentIntent(id, patch)`, `applyRefund(id, amount)`, `dashboardRefund(id, amount?)`, `putProduct(product)`, `emitFor(type, target)`, `tick()`, `sessions()`, `subscriptions()`, `present(session, view)`. Options: `sqlite`, `now`, `namespace`, `publicNamespace`, `products`, `settings`, `onEvent`. |
|
|
225
230
|
| `createRuntime` | function | The emulator with the full service contract. Options: `webhooks: {url, secret, retryDelaysMs?, fetch?}`, `products`, `settings`, `tickMs`, `clock`, `seed`, `adminKey`, `onLog`. |
|
|
226
231
|
| `FLEX_PRESETS` | object | Every named fault preset. |
|
|
227
232
|
| `FLEX_NAMESPACE` | string | The service name, `"flex"`. |
|
|
228
233
|
| `FLEX_EVENT_TYPES` | array | Every webhook event type, aliases included. |
|
|
234
|
+
| `eventObjectKey` | function | The key an event type's `object` is nested under (`refund.created` → `refund`, `charge.refund.updated` → `refund`). |
|
|
229
235
|
| `keyMode` | function | `"test"` for `fsk_test_…`, `"live"` for `fsk_…`, otherwise `undefined`. |
|
|
230
236
|
| `isNextActionType` | function | Whether a string is a next-action type. |
|
|
231
237
|
| `CARDS`, `classifyCard`, `substituteSessionId` | values | The hosted page's test cards, its card classifier, and the `{CHECKOUT_SESSION_ID}` substitution. |
|
|
@@ -331,15 +331,24 @@ var Collection = class {
|
|
|
331
331
|
sqlite;
|
|
332
332
|
namespace;
|
|
333
333
|
collectionName;
|
|
334
|
+
statements = /* @__PURE__ */ new Map();
|
|
335
|
+
prepare(sql) {
|
|
336
|
+
let statement = this.statements.get(sql);
|
|
337
|
+
if (!statement) {
|
|
338
|
+
statement = this.sqlite.prepare(sql);
|
|
339
|
+
this.statements.set(sql, statement);
|
|
340
|
+
}
|
|
341
|
+
return statement;
|
|
342
|
+
}
|
|
334
343
|
constructor(sqlite, namespace, collectionName) {
|
|
335
344
|
this.sqlite = sqlite;
|
|
336
345
|
this.namespace = namespace;
|
|
337
346
|
this.collectionName = collectionName;
|
|
338
347
|
}
|
|
339
348
|
bumpCollectionSeq() {
|
|
340
|
-
const row = this.
|
|
349
|
+
const row = this.prepare("SELECT value FROM mockingbird_sequences WHERE namespace = ? AND name = ? AND kind = 'collection'").get(this.namespace, this.collectionName);
|
|
341
350
|
const next = (row?.value ?? 0) + 1;
|
|
342
|
-
this.
|
|
351
|
+
this.prepare(`INSERT INTO mockingbird_sequences (namespace, name, kind, value) VALUES (?, ?, 'collection', ?)
|
|
343
352
|
ON CONFLICT(namespace, name, kind) DO UPDATE SET value = excluded.value`).run(this.namespace, this.collectionName, next);
|
|
344
353
|
return next;
|
|
345
354
|
}
|
|
@@ -347,13 +356,13 @@ var Collection = class {
|
|
|
347
356
|
return this.sqlite.transaction(() => this.bumpCollectionSeq());
|
|
348
357
|
}
|
|
349
358
|
get(id) {
|
|
350
|
-
const row = this.
|
|
359
|
+
const row = this.prepare("SELECT value FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
351
360
|
if (!row)
|
|
352
361
|
return void 0;
|
|
353
362
|
return JSON.parse(row.value).value;
|
|
354
363
|
}
|
|
355
364
|
has(id) {
|
|
356
|
-
const row = this.
|
|
365
|
+
const row = this.prepare("SELECT 1 AS ok FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
357
366
|
return row !== void 0;
|
|
358
367
|
}
|
|
359
368
|
/** Insert a new record, assigning it the next sequence number. */
|
|
@@ -361,7 +370,7 @@ var Collection = class {
|
|
|
361
370
|
return this.sqlite.transaction(() => {
|
|
362
371
|
const seq = this.bumpCollectionSeq();
|
|
363
372
|
const stored = { seq, value };
|
|
364
|
-
this.
|
|
373
|
+
this.prepare(`INSERT INTO mockingbird_records (namespace, collection, id, seq, value)
|
|
365
374
|
VALUES (?, ?, ?, ?, ?)
|
|
366
375
|
ON CONFLICT(namespace, collection, id) DO UPDATE SET seq = excluded.seq, value = excluded.value`).run(this.namespace, this.collectionName, id, seq, JSON.stringify(stored));
|
|
367
376
|
return stored;
|
|
@@ -370,25 +379,25 @@ var Collection = class {
|
|
|
370
379
|
/** Replace an existing record's value, keeping its position. */
|
|
371
380
|
update(id, value) {
|
|
372
381
|
return this.sqlite.transaction(() => {
|
|
373
|
-
const row = this.
|
|
382
|
+
const row = this.prepare("SELECT seq, value FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?").get(this.namespace, this.collectionName, id);
|
|
374
383
|
if (!row)
|
|
375
384
|
return void 0;
|
|
376
385
|
const stored = { seq: row.seq, value };
|
|
377
|
-
this.
|
|
386
|
+
this.prepare("UPDATE mockingbird_records SET value = ? WHERE namespace = ? AND collection = ? AND id = ?").run(JSON.stringify(stored), this.namespace, this.collectionName, id);
|
|
378
387
|
return stored;
|
|
379
388
|
});
|
|
380
389
|
}
|
|
381
390
|
delete(id) {
|
|
382
|
-
const result = this.
|
|
391
|
+
const result = this.prepare("DELETE FROM mockingbird_records WHERE namespace = ? AND collection = ? AND id = ?").run(this.namespace, this.collectionName, id);
|
|
383
392
|
return result.changes > 0;
|
|
384
393
|
}
|
|
385
394
|
/** How many records the collection holds, without reading them. */
|
|
386
395
|
count() {
|
|
387
|
-
const row = this.
|
|
396
|
+
const row = this.prepare("SELECT COUNT(*) AS n FROM mockingbird_records WHERE namespace = ? AND collection = ?").get(this.namespace, this.collectionName);
|
|
388
397
|
return Number(row?.n ?? 0);
|
|
389
398
|
}
|
|
390
399
|
list(options = {}) {
|
|
391
|
-
const rows = this.
|
|
400
|
+
const rows = this.prepare("SELECT id, seq, value FROM mockingbird_records WHERE namespace = ? AND collection = ?").all(this.namespace, this.collectionName);
|
|
392
401
|
const out = [];
|
|
393
402
|
for (const row of rows) {
|
|
394
403
|
const stored = JSON.parse(row.value);
|
|
@@ -4088,7 +4097,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
4088
4097
|
};
|
|
4089
4098
|
|
|
4090
4099
|
// ../core/dist/version.js
|
|
4091
|
-
var PACKAGE_VERSION = true ? "
|
|
4100
|
+
var PACKAGE_VERSION = true ? "4.0.0" : UNRELEASED_VERSION;
|
|
4092
4101
|
|
|
4093
4102
|
// ../core/dist/signing.js
|
|
4094
4103
|
var encoder = new TextEncoder();
|
|
@@ -7286,6 +7295,17 @@ var adminRoutes = (runtime) => {
|
|
|
7286
7295
|
`session ${params.id}`
|
|
7287
7296
|
);
|
|
7288
7297
|
},
|
|
7298
|
+
"POST /sessions/:id/refund": ({ namespace, params, body }) => {
|
|
7299
|
+
if (body !== void 0 && body !== null && !isRecord5(body)) {
|
|
7300
|
+
return adminError4(400, 'expected {"amount"?: <cents>}');
|
|
7301
|
+
}
|
|
7302
|
+
const amount = isRecord5(body) ? body.amount : void 0;
|
|
7303
|
+
if (amount !== void 0 && typeof amount !== "number") {
|
|
7304
|
+
return adminError4(400, "amount: integer cents");
|
|
7305
|
+
}
|
|
7306
|
+
const outcome = runtime.instance(namespace).dashboardRefund(params.id, amount);
|
|
7307
|
+
return "session" in outcome ? json5(200, outcome.session) : adminError4(outcome.status, outcome.message);
|
|
7308
|
+
},
|
|
7289
7309
|
"PUT /sessions/:id/payment-intent": ({ namespace, params, body }) => {
|
|
7290
7310
|
if (!isRecord5(body) || !PAYMENT_INTENT_STATUSES.includes(String(body.status))) {
|
|
7291
7311
|
return adminError4(400, `status: ${PAYMENT_INTENT_STATUSES.join(" | ")}`);
|
|
@@ -7426,6 +7446,17 @@ var FLEX_EVENT_TYPES = [
|
|
|
7426
7446
|
"charge.refunded",
|
|
7427
7447
|
"charge.refund.updated"
|
|
7428
7448
|
];
|
|
7449
|
+
var eventObjectKey = (type) => {
|
|
7450
|
+
const prefixes2 = [
|
|
7451
|
+
["checkout.session.", "checkout_session"],
|
|
7452
|
+
["checkout_session.", "checkout_session"],
|
|
7453
|
+
["charge.refund.", "refund"],
|
|
7454
|
+
["charge.dispute.", "dispute"],
|
|
7455
|
+
["customer.subscription.", "subscription"]
|
|
7456
|
+
];
|
|
7457
|
+
const match = prefixes2.find(([prefix]) => type.startsWith(prefix));
|
|
7458
|
+
return match ? match[1] : type.split(".")[0];
|
|
7459
|
+
};
|
|
7429
7460
|
var keyMode = (key) => {
|
|
7430
7461
|
if (!key) return void 0;
|
|
7431
7462
|
if (/^fsk_test_[A-Za-z0-9_-]+$/.test(key)) return "test";
|
|
@@ -7901,7 +7932,11 @@ var FlexAPI = class {
|
|
|
7901
7932
|
this.applyRefund(id, amount);
|
|
7902
7933
|
return this.sessionResponse(context, id);
|
|
7903
7934
|
}
|
|
7904
|
-
/**
|
|
7935
|
+
/**
|
|
7936
|
+
* Refund part or all of a paid session, emitting the refund events in the order Flex sends
|
|
7937
|
+
* them for a dashboard refund: `refund.created` twice, `charge.refunded`, then
|
|
7938
|
+
* `refund.updated` and `charge.refund.updated`.
|
|
7939
|
+
*/
|
|
7905
7940
|
applyRefund(id, amount) {
|
|
7906
7941
|
const session = this.state.sessions.get(id);
|
|
7907
7942
|
if (!session) return void 0;
|
|
@@ -7916,20 +7951,74 @@ var FlexAPI = class {
|
|
|
7916
7951
|
created_at: this.iso()
|
|
7917
7952
|
};
|
|
7918
7953
|
this.state.refunds.insert(refund.refund_id, refund);
|
|
7919
|
-
const
|
|
7920
|
-
|
|
7921
|
-
|
|
7954
|
+
const refundObject = this.presentRefund(refund, session.test_mode);
|
|
7955
|
+
const chargeObject = this.presentCharge(next, refund.refund_id);
|
|
7956
|
+
this.emit("refund.created", refundObject, session.test_mode);
|
|
7957
|
+
this.emit("refund.created", refundObject, session.test_mode);
|
|
7958
|
+
this.emit("charge.refunded", chargeObject, session.test_mode);
|
|
7959
|
+
this.emit("refund.updated", refundObject, session.test_mode);
|
|
7960
|
+
this.emit("charge.refund.updated", refundObject, session.test_mode);
|
|
7961
|
+
return this.state.sessions.get(id);
|
|
7962
|
+
}
|
|
7963
|
+
/** Refund a paid session from Flex's dashboard (`POST /__admin/sessions/:id/refund`). */
|
|
7964
|
+
dashboardRefund(id, amount) {
|
|
7965
|
+
const session = this.state.sessions.get(id);
|
|
7966
|
+
if (!session) return { status: 404, message: `no session ${id}` };
|
|
7967
|
+
const received = session.amount_received ?? 0;
|
|
7968
|
+
if (session.status !== "complete" || received <= 0) {
|
|
7969
|
+
return { status: 409, message: `session ${id} has no payment to refund` };
|
|
7970
|
+
}
|
|
7971
|
+
const remaining = received - session.amount_refunded;
|
|
7972
|
+
const value = amount ?? remaining;
|
|
7973
|
+
if (!Number.isInteger(value) || value <= 0 || value > remaining) {
|
|
7974
|
+
return { status: 400, message: `amount must be between 1 and ${remaining}` };
|
|
7975
|
+
}
|
|
7976
|
+
return { session: this.applyRefund(id, value) };
|
|
7977
|
+
}
|
|
7978
|
+
presentRefund(refund, testMode) {
|
|
7979
|
+
return {
|
|
7980
|
+
refund_id: refund.refund_id,
|
|
7981
|
+
amount: refund.amount,
|
|
7982
|
+
status: refund.status,
|
|
7983
|
+
payment_intent_id: refund.payment_intent,
|
|
7984
|
+
items: [],
|
|
7985
|
+
metadata: null,
|
|
7986
|
+
reason: null,
|
|
7987
|
+
reference_id: null,
|
|
7988
|
+
reference_type: null,
|
|
7989
|
+
reference_status: null,
|
|
7990
|
+
balance_transaction: null,
|
|
7991
|
+
failure_balance_transaction: null,
|
|
7992
|
+
test_mode: testMode,
|
|
7993
|
+
created_at: refund.created_at
|
|
7994
|
+
};
|
|
7995
|
+
}
|
|
7996
|
+
presentCharge(session, seed) {
|
|
7997
|
+
const intent = session.payment_intent ? this.state.paymentIntents.get(session.payment_intent) : void 0;
|
|
7998
|
+
const received = session.amount_received ?? 0;
|
|
7999
|
+
return {
|
|
8000
|
+
charge_id: `fch_${seed.slice(4)}`,
|
|
7922
8001
|
payment_intent: session.payment_intent,
|
|
7923
|
-
amount:
|
|
7924
|
-
|
|
7925
|
-
|
|
8002
|
+
amount: received,
|
|
8003
|
+
amount_captured: received,
|
|
8004
|
+
amount_refunded: session.amount_refunded,
|
|
8005
|
+
refunded: session.amount_refunded >= received,
|
|
8006
|
+
paid: true,
|
|
8007
|
+
captured: true,
|
|
8008
|
+
status: "succeeded",
|
|
8009
|
+
customer: session.customer,
|
|
8010
|
+
payment_method_id: intent?.payment_method ?? null,
|
|
8011
|
+
invoice: null,
|
|
8012
|
+
refunds: null,
|
|
8013
|
+
disputed: false,
|
|
8014
|
+
failure_message: null,
|
|
8015
|
+
balance_transaction: null,
|
|
8016
|
+
failure_balance_transaction: null,
|
|
8017
|
+
application_fee_amount: null,
|
|
8018
|
+
transfer_group: null,
|
|
8019
|
+
test_mode: session.test_mode,
|
|
8020
|
+
created_at: intent?.created_at ?? this.iso()
|
|
7926
8021
|
};
|
|
7927
|
-
this.emit("refund.created", { ...refund, status: "pending" }, session.test_mode);
|
|
7928
|
-
this.emit("charge.refunded", charge, session.test_mode);
|
|
7929
|
-
this.emitSession("checkout.session.refunded", id);
|
|
7930
|
-
this.emit("refund.updated", refund, session.test_mode);
|
|
7931
|
-
this.emit("charge.refund.updated", { ...refund, charge: charge.charge_id }, session.test_mode);
|
|
7932
|
-
return this.state.sessions.get(id);
|
|
7933
8022
|
}
|
|
7934
8023
|
// --- customers and setup intents ---------------------------------------------------------
|
|
7935
8024
|
createCustomer(context) {
|
|
@@ -8043,11 +8132,7 @@ var FlexAPI = class {
|
|
|
8043
8132
|
const intent = { ...this.paymentIntentFor(session), ...patch };
|
|
8044
8133
|
this.state.paymentIntents.update(intent.payment_intent_id, intent);
|
|
8045
8134
|
if (patch.status === "succeeded") {
|
|
8046
|
-
this.emit(
|
|
8047
|
-
"payment_intent.succeeded",
|
|
8048
|
-
{ ...intent, checkout_session_id: id },
|
|
8049
|
-
session.test_mode
|
|
8050
|
-
);
|
|
8135
|
+
this.emit("payment_intent.succeeded", { ...intent }, session.test_mode);
|
|
8051
8136
|
}
|
|
8052
8137
|
return intent;
|
|
8053
8138
|
}
|
|
@@ -8174,8 +8259,40 @@ var FlexAPI = class {
|
|
|
8174
8259
|
const product = this.state.products.get(target.productId);
|
|
8175
8260
|
return product ? this.emit(type, { ...product }, product.test_mode) : void 0;
|
|
8176
8261
|
}
|
|
8177
|
-
if (target.sessionId) return
|
|
8178
|
-
|
|
8262
|
+
if (!target.sessionId) return void 0;
|
|
8263
|
+
const session = this.state.sessions.get(target.sessionId);
|
|
8264
|
+
if (!session) return void 0;
|
|
8265
|
+
const key = eventObjectKey(type);
|
|
8266
|
+
const existingIntent = session.payment_intent ? this.state.paymentIntents.get(session.payment_intent) : void 0;
|
|
8267
|
+
if (key === "payment_intent") {
|
|
8268
|
+
const intent = existingIntent ?? {
|
|
8269
|
+
payment_intent_id: `fpi_${session.checkout_session_id.slice(4)}`,
|
|
8270
|
+
amount: session.amount_total,
|
|
8271
|
+
amount_received: null,
|
|
8272
|
+
customer: session.customer,
|
|
8273
|
+
payment_method: null,
|
|
8274
|
+
status: "requires_payment_method",
|
|
8275
|
+
created_at: session.created_at
|
|
8276
|
+
};
|
|
8277
|
+
return this.emit(type, { ...intent }, session.test_mode);
|
|
8278
|
+
}
|
|
8279
|
+
if (key === "refund" || key === "charge") {
|
|
8280
|
+
const refund = this.state.refunds.list().map((row) => row.value).filter((row) => row.checkout_session === session.checkout_session_id).at(-1) ?? {
|
|
8281
|
+
refund_id: this.state.nextId("fre_"),
|
|
8282
|
+
checkout_session: session.checkout_session_id,
|
|
8283
|
+
payment_intent: session.payment_intent,
|
|
8284
|
+
amount: session.amount_received ?? session.amount_total,
|
|
8285
|
+
status: "succeeded",
|
|
8286
|
+
created_at: this.iso()
|
|
8287
|
+
};
|
|
8288
|
+
const current = this.state.sessions.get(session.checkout_session_id);
|
|
8289
|
+
return this.emit(
|
|
8290
|
+
type,
|
|
8291
|
+
key === "refund" ? this.presentRefund(refund, session.test_mode) : this.presentCharge(current, refund.refund_id),
|
|
8292
|
+
session.test_mode
|
|
8293
|
+
);
|
|
8294
|
+
}
|
|
8295
|
+
return this.emitSession(type, target.sessionId);
|
|
8179
8296
|
}
|
|
8180
8297
|
emitSession(type, id) {
|
|
8181
8298
|
const session = this.state.sessions.get(id);
|
|
@@ -8190,7 +8307,7 @@ var FlexAPI = class {
|
|
|
8190
8307
|
const event = {
|
|
8191
8308
|
event_id: this.state.nextId("fevt_"),
|
|
8192
8309
|
event_type: type,
|
|
8193
|
-
object,
|
|
8310
|
+
object: { [eventObjectKey(type)]: object },
|
|
8194
8311
|
event_dt: Math.floor(this.now() / 1e3),
|
|
8195
8312
|
test_mode: testMode,
|
|
8196
8313
|
created_at: this.iso()
|
|
@@ -8318,9 +8435,10 @@ export {
|
|
|
8318
8435
|
createRuntime2 as createRuntime,
|
|
8319
8436
|
FLEX_NAMESPACE,
|
|
8320
8437
|
FLEX_EVENT_TYPES,
|
|
8438
|
+
eventObjectKey,
|
|
8321
8439
|
keyMode,
|
|
8322
8440
|
periodEnd,
|
|
8323
8441
|
FlexAPI,
|
|
8324
8442
|
isNextActionType
|
|
8325
8443
|
};
|
|
8326
|
-
//# sourceMappingURL=chunk-
|
|
8444
|
+
//# sourceMappingURL=chunk-3FSLZROR.js.map
|