@stardeck-customer-apps/testing 0.12.0 → 0.13.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/SKILL.md +32 -1
- package/dist/index.d.mts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +44 -0
- package/dist/index.mjs +44 -0
- package/dist/next/headers-shim.js +1 -0
- package/dist/next/headers-shim.mjs +1 -0
- package/dist/setup.js +40 -0
- package/dist/setup.mjs +40 -0
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -193,6 +193,21 @@ await app.payments.deliverBeamEvent(beamPost, {
|
|
|
193
193
|
// charge-failure or expiry event for bolt payments.
|
|
194
194
|
// EXPIRED is derived from expiresAt on read, never stored.
|
|
195
195
|
|
|
196
|
+
// Fail exactly one real SDK call, then let the next poll recover normally.
|
|
197
|
+
app.payments.failNext("beam.getPaymentLinkStatus", {
|
|
198
|
+
status: 503,
|
|
199
|
+
message: "Beam is temporarily unavailable",
|
|
200
|
+
});
|
|
201
|
+
await expect(payments.getPaymentLinkStatus("plink_test_1")).rejects.toMatchObject({
|
|
202
|
+
statusCode: 503,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Network failures reject fetch instead of returning a PaymentError response.
|
|
206
|
+
app.payments.failNext("stripe.getCheckoutSessionStatus", {
|
|
207
|
+
kind: "network",
|
|
208
|
+
message: "connection reset",
|
|
209
|
+
});
|
|
210
|
+
|
|
196
211
|
// File upload
|
|
197
212
|
const storage = new StorageClient();
|
|
198
213
|
await storage.upload(new File(["hi"], "note.txt", { type: "text/plain" }));
|
|
@@ -302,6 +317,8 @@ externalId })` helper models a trusted platform/channel link, and
|
|
|
302
317
|
identities through the integrations SDK.
|
|
303
318
|
- `app.payments` — checkouts created through payments-sdk:
|
|
304
319
|
`.checkouts`, `.latest()`, `.setProducts()`, `.markPaid(id)`,
|
|
320
|
+
`.setSessionStatus(id, status)`, `.setPaymentLinkStatus(id, status)`,
|
|
321
|
+
`.failNext(operation, failure)`,
|
|
305
322
|
`.deliverStripeEvent(handler, event)`, `.deliverBeamEvent(handler, event)`,
|
|
306
323
|
Bolt+ controls: `.approveBoltIntent(id)`, `.declineBoltIntent(id)`,
|
|
307
324
|
`.expireBoltIntent(id)`, `.listBoltIntents()`, `.getBoltIntent(id)`,
|
|
@@ -385,7 +402,21 @@ cursor, limit })`; `list()` intentionally keeps its previous array shape.
|
|
|
385
402
|
connections/intents/charges, product list) — captured in `app.payments`;
|
|
386
403
|
fulfill checkout via `markPaid` (poll) or `deliverStripeEvent` /
|
|
387
404
|
`deliverBeamEvent` (webhook push). Drive a terminal without hardware via
|
|
388
|
-
`approveBoltIntent` / `declineBoltIntent` / `expireBoltIntent`.
|
|
405
|
+
`approveBoltIntent` / `declineBoltIntent` / `expireBoltIntent`. Beam payment-link
|
|
406
|
+
polling returns the app's original `order.referenceId`; playground project
|
|
407
|
+
scoping is an internal control-plane detail and must not be handled in app code.
|
|
408
|
+
- Payment outcomes are controllable without bypassing the SDK: Stripe sessions
|
|
409
|
+
support `open`, `complete`, and `expired` with `paid`, `unpaid`, or
|
|
410
|
+
`no_payment_required`; Beam links support `ACTIVE`, `DISABLED`, `EXPIRED`,
|
|
411
|
+
`PAID`, `VOIDED`, and `REFUNDED`; Bolt+ supports approve, decline, expiry, and
|
|
412
|
+
cancellation through the real SDK call. Use `app.payments.failNext()` for
|
|
413
|
+
one-shot HTTP or network failures during Stripe checkout creation/status polling
|
|
414
|
+
and Beam payment-link creation/status polling. The operation names are
|
|
415
|
+
`stripe.createCheckout`, `stripe.getCheckoutSessionStatus`,
|
|
416
|
+
`beam.createPaymentLink`, and `beam.getPaymentLinkStatus`. HTTP failures support
|
|
417
|
+
statuses 400, 402, 409, 429, 500, and 503 plus optional `code`, `details`, and
|
|
418
|
+
`retryAfterSeconds`; `{ kind: "network", message }` rejects fetch instead.
|
|
419
|
+
`app.reset()` clears pending failures.
|
|
389
420
|
- `StorageClient` (upload/list/get/patch/delete, presigned upload) — captured
|
|
390
421
|
in `app.storage` against the simulated `STORAGE_URL` host.
|
|
391
422
|
- `client.slack` / `client.line` / `client.facebook` send endpoints — captured
|
package/dist/index.d.mts
CHANGED
|
@@ -138,6 +138,18 @@ interface CapturedCheckout {
|
|
|
138
138
|
metadata?: Record<string, string>;
|
|
139
139
|
createdAt: Date;
|
|
140
140
|
}
|
|
141
|
+
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus";
|
|
142
|
+
type PaymentSimulatorFailure = {
|
|
143
|
+
kind?: "http";
|
|
144
|
+
status: 400 | 402 | 409 | 429 | 500 | 503;
|
|
145
|
+
message: string;
|
|
146
|
+
code?: string;
|
|
147
|
+
details?: unknown;
|
|
148
|
+
retryAfterSeconds?: number;
|
|
149
|
+
} | {
|
|
150
|
+
kind: "network";
|
|
151
|
+
message: string;
|
|
152
|
+
};
|
|
141
153
|
/** Simulated Bolt+ connection as returned by the control-plane store API. */
|
|
142
154
|
interface SimBoltConnection {
|
|
143
155
|
id: string;
|
|
@@ -189,6 +201,8 @@ interface TestPayments {
|
|
|
189
201
|
get checkouts(): CapturedCheckout[];
|
|
190
202
|
latest(): CapturedCheckout | undefined;
|
|
191
203
|
setProducts(products: _stardeck_customer_apps_payments_sdk.Product[]): void;
|
|
204
|
+
/** Fail the next matching SDK request once, then resume normal simulator behavior. */
|
|
205
|
+
failNext(operation: PaymentSimulatorOperation, failure: PaymentSimulatorFailure): void;
|
|
192
206
|
markPaid(id: string): void;
|
|
193
207
|
setSessionStatus(id: string, status: Partial<_stardeck_customer_apps_payments_sdk.CheckoutSessionStatus>): void;
|
|
194
208
|
setPaymentLinkStatus(id: string, status: _stardeck_customer_apps_payments_sdk.BeamPaymentLinkStatus): void;
|
|
@@ -550,4 +564,4 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
550
564
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
551
565
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
552
566
|
|
|
553
|
-
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
567
|
+
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PaymentSimulatorFailure, type PaymentSimulatorOperation, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.d.ts
CHANGED
|
@@ -138,6 +138,18 @@ interface CapturedCheckout {
|
|
|
138
138
|
metadata?: Record<string, string>;
|
|
139
139
|
createdAt: Date;
|
|
140
140
|
}
|
|
141
|
+
type PaymentSimulatorOperation = "stripe.createCheckout" | "stripe.getCheckoutSessionStatus" | "beam.createPaymentLink" | "beam.getPaymentLinkStatus";
|
|
142
|
+
type PaymentSimulatorFailure = {
|
|
143
|
+
kind?: "http";
|
|
144
|
+
status: 400 | 402 | 409 | 429 | 500 | 503;
|
|
145
|
+
message: string;
|
|
146
|
+
code?: string;
|
|
147
|
+
details?: unknown;
|
|
148
|
+
retryAfterSeconds?: number;
|
|
149
|
+
} | {
|
|
150
|
+
kind: "network";
|
|
151
|
+
message: string;
|
|
152
|
+
};
|
|
141
153
|
/** Simulated Bolt+ connection as returned by the control-plane store API. */
|
|
142
154
|
interface SimBoltConnection {
|
|
143
155
|
id: string;
|
|
@@ -189,6 +201,8 @@ interface TestPayments {
|
|
|
189
201
|
get checkouts(): CapturedCheckout[];
|
|
190
202
|
latest(): CapturedCheckout | undefined;
|
|
191
203
|
setProducts(products: _stardeck_customer_apps_payments_sdk.Product[]): void;
|
|
204
|
+
/** Fail the next matching SDK request once, then resume normal simulator behavior. */
|
|
205
|
+
failNext(operation: PaymentSimulatorOperation, failure: PaymentSimulatorFailure): void;
|
|
192
206
|
markPaid(id: string): void;
|
|
193
207
|
setSessionStatus(id: string, status: Partial<_stardeck_customer_apps_payments_sdk.CheckoutSessionStatus>): void;
|
|
194
208
|
setPaymentLinkStatus(id: string, status: _stardeck_customer_apps_payments_sdk.BeamPaymentLinkStatus): void;
|
|
@@ -550,4 +564,4 @@ declare const TEST_ENV_DEFAULTS: {
|
|
|
550
564
|
/** Default location of the DDL snapshot written by `generate-types`. */
|
|
551
565
|
declare const DEFAULT_SCHEMA_PATH = "./src/generated/data-store-schema.sql";
|
|
552
566
|
|
|
553
|
-
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
|
567
|
+
export { type BindingInfo, CONTROL_PLANE_TEST_URL, type CallRouteOptions, type CapturedCheckout, type CapturedDisplay, type CapturedEmail, type CapturedIdentity, type CapturedIdentityLink, type CapturedMessage, type CapturedPrint, type CapturedTestPrint, type CapturedUpload, DATA_STORE_TEST_HOST, DATA_STORE_TEST_URL, DEFAULT_SCHEMA_PATH, type DeviceInfo, type PaymentSimulatorFailure, type PaymentSimulatorOperation, type PeripheralInfo, STORAGE_TEST_HOST, STORAGE_TEST_URL, type SessionTokens, type SimBoltCharge, type SimBoltConnection, type SimBoltIntentRecord, type SimBoltIntentStatus, TEST_ENV_DEFAULTS, type TestApp, type TestAppOptions, TestDataStoreInput, type TestDirectory, type TestEdge, type TestInbox, type TestMessages, type TestPayments, type TestStorage, type TestUser, WORKFLOW_NAME_PREFIX, callRoute, createTestApp, describeWorkflow, parseWorkflowName };
|
package/dist/index.js
CHANGED
|
@@ -108,6 +108,7 @@ var state = globalSingleton("state", () => ({
|
|
|
108
108
|
checkoutCounter: 0,
|
|
109
109
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
110
110
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
111
|
+
paymentFailures: [],
|
|
111
112
|
products: [],
|
|
112
113
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
113
114
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
|
@@ -1274,6 +1275,43 @@ function payErr(error, status = 400, code, details) {
|
|
|
1274
1275
|
if (details !== void 0) body.details = details;
|
|
1275
1276
|
return json(body, status);
|
|
1276
1277
|
}
|
|
1278
|
+
function paymentOperationForRequest(request, pathname) {
|
|
1279
|
+
if (request.method === "POST" && /^\/api\/store\/beam\/[^/]+\/payment-links$/.test(pathname)) {
|
|
1280
|
+
return "beam.createPaymentLink";
|
|
1281
|
+
}
|
|
1282
|
+
if (request.method === "GET" && /^\/api\/store\/beam\/[^/]+\/payment-links\/[^/]+$/.test(pathname)) {
|
|
1283
|
+
return "beam.getPaymentLinkStatus";
|
|
1284
|
+
}
|
|
1285
|
+
if (request.method === "POST" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout$/.test(pathname)) {
|
|
1286
|
+
return "stripe.createCheckout";
|
|
1287
|
+
}
|
|
1288
|
+
if (request.method === "GET" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout-sessions\/[^/]+$/.test(pathname)) {
|
|
1289
|
+
return "stripe.getCheckoutSessionStatus";
|
|
1290
|
+
}
|
|
1291
|
+
return null;
|
|
1292
|
+
}
|
|
1293
|
+
function consumePaymentFailure(request, pathname) {
|
|
1294
|
+
const operation = paymentOperationForRequest(request, pathname);
|
|
1295
|
+
if (!operation) return null;
|
|
1296
|
+
const index = state.paymentFailures.findIndex((entry) => entry.operation === operation);
|
|
1297
|
+
if (index === -1) return null;
|
|
1298
|
+
const [{ failure: failure2 }] = state.paymentFailures.splice(index, 1);
|
|
1299
|
+
if (failure2.kind === "network") {
|
|
1300
|
+
throw new TypeError(failure2.message);
|
|
1301
|
+
}
|
|
1302
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
1303
|
+
if (failure2.retryAfterSeconds !== void 0) {
|
|
1304
|
+
headers.set("Retry-After", String(failure2.retryAfterSeconds));
|
|
1305
|
+
}
|
|
1306
|
+
return new Response(
|
|
1307
|
+
JSON.stringify({
|
|
1308
|
+
error: failure2.message,
|
|
1309
|
+
code: failure2.code ?? "REQUEST_ERROR",
|
|
1310
|
+
...failure2.details !== void 0 ? { details: failure2.details } : {}
|
|
1311
|
+
}),
|
|
1312
|
+
{ status: failure2.status, headers }
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1277
1315
|
function isBoltPaymentMethod(value) {
|
|
1278
1316
|
return typeof value === "string" && BEAM_BOLT_PAYMENT_METHODS.includes(value);
|
|
1279
1317
|
}
|
|
@@ -1417,6 +1455,8 @@ async function deliverEvent(envelope, handler, options) {
|
|
|
1417
1455
|
}
|
|
1418
1456
|
async function handlePaymentsRequest(request, url) {
|
|
1419
1457
|
const pathname = url.pathname;
|
|
1458
|
+
const injectedFailure = consumePaymentFailure(request, pathname);
|
|
1459
|
+
if (injectedFailure) return injectedFailure;
|
|
1420
1460
|
if (/\/billing-portal$/.test(pathname)) {
|
|
1421
1461
|
return payErr("Not found", 404, "NOT_FOUND");
|
|
1422
1462
|
}
|
|
@@ -1711,6 +1751,9 @@ function createPayments() {
|
|
|
1711
1751
|
setProducts(products) {
|
|
1712
1752
|
state.products = products;
|
|
1713
1753
|
},
|
|
1754
|
+
failNext(operation, failure2) {
|
|
1755
|
+
state.paymentFailures.push({ operation, failure: failure2 });
|
|
1756
|
+
},
|
|
1714
1757
|
markPaid(id) {
|
|
1715
1758
|
const session = state.sessionStatuses.get(id);
|
|
1716
1759
|
if (session) {
|
|
@@ -1820,6 +1863,7 @@ function createPayments() {
|
|
|
1820
1863
|
state.checkoutCounter = 0;
|
|
1821
1864
|
state.sessionStatuses.clear();
|
|
1822
1865
|
state.paymentLinks.clear();
|
|
1866
|
+
state.paymentFailures = [];
|
|
1823
1867
|
state.products = [];
|
|
1824
1868
|
state.boltConnections.clear();
|
|
1825
1869
|
state.boltUsedPairingCodes.clear();
|
package/dist/index.mjs
CHANGED
|
@@ -59,6 +59,7 @@ var state = globalSingleton("state", () => ({
|
|
|
59
59
|
checkoutCounter: 0,
|
|
60
60
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
61
61
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
62
|
+
paymentFailures: [],
|
|
62
63
|
products: [],
|
|
63
64
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
64
65
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
|
@@ -1225,6 +1226,43 @@ function payErr(error, status = 400, code, details) {
|
|
|
1225
1226
|
if (details !== void 0) body.details = details;
|
|
1226
1227
|
return json(body, status);
|
|
1227
1228
|
}
|
|
1229
|
+
function paymentOperationForRequest(request, pathname) {
|
|
1230
|
+
if (request.method === "POST" && /^\/api\/store\/beam\/[^/]+\/payment-links$/.test(pathname)) {
|
|
1231
|
+
return "beam.createPaymentLink";
|
|
1232
|
+
}
|
|
1233
|
+
if (request.method === "GET" && /^\/api\/store\/beam\/[^/]+\/payment-links\/[^/]+$/.test(pathname)) {
|
|
1234
|
+
return "beam.getPaymentLinkStatus";
|
|
1235
|
+
}
|
|
1236
|
+
if (request.method === "POST" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout$/.test(pathname)) {
|
|
1237
|
+
return "stripe.createCheckout";
|
|
1238
|
+
}
|
|
1239
|
+
if (request.method === "GET" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout-sessions\/[^/]+$/.test(pathname)) {
|
|
1240
|
+
return "stripe.getCheckoutSessionStatus";
|
|
1241
|
+
}
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
function consumePaymentFailure(request, pathname) {
|
|
1245
|
+
const operation = paymentOperationForRequest(request, pathname);
|
|
1246
|
+
if (!operation) return null;
|
|
1247
|
+
const index = state.paymentFailures.findIndex((entry) => entry.operation === operation);
|
|
1248
|
+
if (index === -1) return null;
|
|
1249
|
+
const [{ failure: failure2 }] = state.paymentFailures.splice(index, 1);
|
|
1250
|
+
if (failure2.kind === "network") {
|
|
1251
|
+
throw new TypeError(failure2.message);
|
|
1252
|
+
}
|
|
1253
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
1254
|
+
if (failure2.retryAfterSeconds !== void 0) {
|
|
1255
|
+
headers.set("Retry-After", String(failure2.retryAfterSeconds));
|
|
1256
|
+
}
|
|
1257
|
+
return new Response(
|
|
1258
|
+
JSON.stringify({
|
|
1259
|
+
error: failure2.message,
|
|
1260
|
+
code: failure2.code ?? "REQUEST_ERROR",
|
|
1261
|
+
...failure2.details !== void 0 ? { details: failure2.details } : {}
|
|
1262
|
+
}),
|
|
1263
|
+
{ status: failure2.status, headers }
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1228
1266
|
function isBoltPaymentMethod(value) {
|
|
1229
1267
|
return typeof value === "string" && BEAM_BOLT_PAYMENT_METHODS.includes(value);
|
|
1230
1268
|
}
|
|
@@ -1368,6 +1406,8 @@ async function deliverEvent(envelope, handler, options) {
|
|
|
1368
1406
|
}
|
|
1369
1407
|
async function handlePaymentsRequest(request, url) {
|
|
1370
1408
|
const pathname = url.pathname;
|
|
1409
|
+
const injectedFailure = consumePaymentFailure(request, pathname);
|
|
1410
|
+
if (injectedFailure) return injectedFailure;
|
|
1371
1411
|
if (/\/billing-portal$/.test(pathname)) {
|
|
1372
1412
|
return payErr("Not found", 404, "NOT_FOUND");
|
|
1373
1413
|
}
|
|
@@ -1662,6 +1702,9 @@ function createPayments() {
|
|
|
1662
1702
|
setProducts(products) {
|
|
1663
1703
|
state.products = products;
|
|
1664
1704
|
},
|
|
1705
|
+
failNext(operation, failure2) {
|
|
1706
|
+
state.paymentFailures.push({ operation, failure: failure2 });
|
|
1707
|
+
},
|
|
1665
1708
|
markPaid(id) {
|
|
1666
1709
|
const session = state.sessionStatuses.get(id);
|
|
1667
1710
|
if (session) {
|
|
@@ -1771,6 +1814,7 @@ function createPayments() {
|
|
|
1771
1814
|
state.checkoutCounter = 0;
|
|
1772
1815
|
state.sessionStatuses.clear();
|
|
1773
1816
|
state.paymentLinks.clear();
|
|
1817
|
+
state.paymentFailures = [];
|
|
1774
1818
|
state.products = [];
|
|
1775
1819
|
state.boltConnections.clear();
|
|
1776
1820
|
state.boltUsedPairingCodes.clear();
|
|
@@ -51,6 +51,7 @@ var state = globalSingleton("state", () => ({
|
|
|
51
51
|
checkoutCounter: 0,
|
|
52
52
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
53
53
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
54
|
+
paymentFailures: [],
|
|
54
55
|
products: [],
|
|
55
56
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
56
57
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
|
@@ -24,6 +24,7 @@ var state = globalSingleton("state", () => ({
|
|
|
24
24
|
checkoutCounter: 0,
|
|
25
25
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
26
26
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
27
|
+
paymentFailures: [],
|
|
27
28
|
products: [],
|
|
28
29
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
29
30
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
package/dist/setup.js
CHANGED
|
@@ -45,6 +45,7 @@ var state = globalSingleton("state", () => ({
|
|
|
45
45
|
checkoutCounter: 0,
|
|
46
46
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
47
47
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
48
|
+
paymentFailures: [],
|
|
48
49
|
products: [],
|
|
49
50
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
50
51
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
|
@@ -1012,6 +1013,43 @@ function payErr(error, status = 400, code, details) {
|
|
|
1012
1013
|
if (details !== void 0) body.details = details;
|
|
1013
1014
|
return json(body, status);
|
|
1014
1015
|
}
|
|
1016
|
+
function paymentOperationForRequest(request, pathname) {
|
|
1017
|
+
if (request.method === "POST" && /^\/api\/store\/beam\/[^/]+\/payment-links$/.test(pathname)) {
|
|
1018
|
+
return "beam.createPaymentLink";
|
|
1019
|
+
}
|
|
1020
|
+
if (request.method === "GET" && /^\/api\/store\/beam\/[^/]+\/payment-links\/[^/]+$/.test(pathname)) {
|
|
1021
|
+
return "beam.getPaymentLinkStatus";
|
|
1022
|
+
}
|
|
1023
|
+
if (request.method === "POST" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout$/.test(pathname)) {
|
|
1024
|
+
return "stripe.createCheckout";
|
|
1025
|
+
}
|
|
1026
|
+
if (request.method === "GET" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout-sessions\/[^/]+$/.test(pathname)) {
|
|
1027
|
+
return "stripe.getCheckoutSessionStatus";
|
|
1028
|
+
}
|
|
1029
|
+
return null;
|
|
1030
|
+
}
|
|
1031
|
+
function consumePaymentFailure(request, pathname) {
|
|
1032
|
+
const operation = paymentOperationForRequest(request, pathname);
|
|
1033
|
+
if (!operation) return null;
|
|
1034
|
+
const index = state.paymentFailures.findIndex((entry) => entry.operation === operation);
|
|
1035
|
+
if (index === -1) return null;
|
|
1036
|
+
const [{ failure: failure2 }] = state.paymentFailures.splice(index, 1);
|
|
1037
|
+
if (failure2.kind === "network") {
|
|
1038
|
+
throw new TypeError(failure2.message);
|
|
1039
|
+
}
|
|
1040
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
1041
|
+
if (failure2.retryAfterSeconds !== void 0) {
|
|
1042
|
+
headers.set("Retry-After", String(failure2.retryAfterSeconds));
|
|
1043
|
+
}
|
|
1044
|
+
return new Response(
|
|
1045
|
+
JSON.stringify({
|
|
1046
|
+
error: failure2.message,
|
|
1047
|
+
code: failure2.code ?? "REQUEST_ERROR",
|
|
1048
|
+
...failure2.details !== void 0 ? { details: failure2.details } : {}
|
|
1049
|
+
}),
|
|
1050
|
+
{ status: failure2.status, headers }
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1015
1053
|
function isBoltPaymentMethod(value) {
|
|
1016
1054
|
return typeof value === "string" && BEAM_BOLT_PAYMENT_METHODS.includes(value);
|
|
1017
1055
|
}
|
|
@@ -1120,6 +1158,8 @@ function storedStatusesForFilter(statuses) {
|
|
|
1120
1158
|
}
|
|
1121
1159
|
async function handlePaymentsRequest(request, url) {
|
|
1122
1160
|
const pathname = url.pathname;
|
|
1161
|
+
const injectedFailure = consumePaymentFailure(request, pathname);
|
|
1162
|
+
if (injectedFailure) return injectedFailure;
|
|
1123
1163
|
if (/\/billing-portal$/.test(pathname)) {
|
|
1124
1164
|
return payErr("Not found", 404, "NOT_FOUND");
|
|
1125
1165
|
}
|
package/dist/setup.mjs
CHANGED
|
@@ -21,6 +21,7 @@ var state = globalSingleton("state", () => ({
|
|
|
21
21
|
checkoutCounter: 0,
|
|
22
22
|
sessionStatuses: /* @__PURE__ */ new Map(),
|
|
23
23
|
paymentLinks: /* @__PURE__ */ new Map(),
|
|
24
|
+
paymentFailures: [],
|
|
24
25
|
products: [],
|
|
25
26
|
boltConnections: /* @__PURE__ */ new Map(),
|
|
26
27
|
boltUsedPairingCodes: /* @__PURE__ */ new Set(),
|
|
@@ -988,6 +989,43 @@ function payErr(error, status = 400, code, details) {
|
|
|
988
989
|
if (details !== void 0) body.details = details;
|
|
989
990
|
return json(body, status);
|
|
990
991
|
}
|
|
992
|
+
function paymentOperationForRequest(request, pathname) {
|
|
993
|
+
if (request.method === "POST" && /^\/api\/store\/beam\/[^/]+\/payment-links$/.test(pathname)) {
|
|
994
|
+
return "beam.createPaymentLink";
|
|
995
|
+
}
|
|
996
|
+
if (request.method === "GET" && /^\/api\/store\/beam\/[^/]+\/payment-links\/[^/]+$/.test(pathname)) {
|
|
997
|
+
return "beam.getPaymentLinkStatus";
|
|
998
|
+
}
|
|
999
|
+
if (request.method === "POST" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout$/.test(pathname)) {
|
|
1000
|
+
return "stripe.createCheckout";
|
|
1001
|
+
}
|
|
1002
|
+
if (request.method === "GET" && /^\/api\/store\/(?!beam\/)[^/]+\/checkout-sessions\/[^/]+$/.test(pathname)) {
|
|
1003
|
+
return "stripe.getCheckoutSessionStatus";
|
|
1004
|
+
}
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
function consumePaymentFailure(request, pathname) {
|
|
1008
|
+
const operation = paymentOperationForRequest(request, pathname);
|
|
1009
|
+
if (!operation) return null;
|
|
1010
|
+
const index = state.paymentFailures.findIndex((entry) => entry.operation === operation);
|
|
1011
|
+
if (index === -1) return null;
|
|
1012
|
+
const [{ failure: failure2 }] = state.paymentFailures.splice(index, 1);
|
|
1013
|
+
if (failure2.kind === "network") {
|
|
1014
|
+
throw new TypeError(failure2.message);
|
|
1015
|
+
}
|
|
1016
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
1017
|
+
if (failure2.retryAfterSeconds !== void 0) {
|
|
1018
|
+
headers.set("Retry-After", String(failure2.retryAfterSeconds));
|
|
1019
|
+
}
|
|
1020
|
+
return new Response(
|
|
1021
|
+
JSON.stringify({
|
|
1022
|
+
error: failure2.message,
|
|
1023
|
+
code: failure2.code ?? "REQUEST_ERROR",
|
|
1024
|
+
...failure2.details !== void 0 ? { details: failure2.details } : {}
|
|
1025
|
+
}),
|
|
1026
|
+
{ status: failure2.status, headers }
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
991
1029
|
function isBoltPaymentMethod(value) {
|
|
992
1030
|
return typeof value === "string" && BEAM_BOLT_PAYMENT_METHODS.includes(value);
|
|
993
1031
|
}
|
|
@@ -1096,6 +1134,8 @@ function storedStatusesForFilter(statuses) {
|
|
|
1096
1134
|
}
|
|
1097
1135
|
async function handlePaymentsRequest(request, url) {
|
|
1098
1136
|
const pathname = url.pathname;
|
|
1137
|
+
const injectedFailure = consumePaymentFailure(request, pathname);
|
|
1138
|
+
if (injectedFailure) return injectedFailure;
|
|
1099
1139
|
if (/\/billing-portal$/.test(pathname)) {
|
|
1100
1140
|
return payErr("Not found", 404, "NOT_FOUND");
|
|
1101
1141
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Vitest test harness for Stardeck customer apps — in-process Postgres (PGlite) plus a control-plane simulator so the real Stardeck SDKs run unmodified in tests",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|