@cogenta/commerce 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +373 -0
  2. package/dist/admin/permissions.d.ts +57 -0
  3. package/dist/admin/permissions.d.ts.map +1 -0
  4. package/dist/admin/permissions.js +87 -0
  5. package/dist/admin/permissions.js.map +1 -0
  6. package/dist/admin/router.d.ts +53 -0
  7. package/dist/admin/router.d.ts.map +1 -0
  8. package/dist/admin/router.js +476 -0
  9. package/dist/admin/router.js.map +1 -0
  10. package/dist/cart/store.d.ts +91 -0
  11. package/dist/cart/store.d.ts.map +1 -0
  12. package/dist/cart/store.js +342 -0
  13. package/dist/cart/store.js.map +1 -0
  14. package/dist/cart/totals.d.ts +73 -0
  15. package/dist/cart/totals.d.ts.map +1 -0
  16. package/dist/cart/totals.js +65 -0
  17. package/dist/cart/totals.js.map +1 -0
  18. package/dist/catalog/store.d.ts +53 -0
  19. package/dist/catalog/store.d.ts.map +1 -0
  20. package/dist/catalog/store.js +358 -0
  21. package/dist/catalog/store.js.map +1 -0
  22. package/dist/catalog/types.d.ts +95 -0
  23. package/dist/catalog/types.d.ts.map +1 -0
  24. package/dist/catalog/types.js +5 -0
  25. package/dist/catalog/types.js.map +1 -0
  26. package/dist/coupon/store.d.ts +103 -0
  27. package/dist/coupon/store.d.ts.map +1 -0
  28. package/dist/coupon/store.js +181 -0
  29. package/dist/coupon/store.js.map +1 -0
  30. package/dist/customer/store.d.ts +41 -0
  31. package/dist/customer/store.d.ts.map +1 -0
  32. package/dist/customer/store.js +103 -0
  33. package/dist/customer/store.js.map +1 -0
  34. package/dist/index.d.ts +42 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +23 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/invoice/pdf.d.ts +67 -0
  39. package/dist/invoice/pdf.d.ts.map +1 -0
  40. package/dist/invoice/pdf.js +449 -0
  41. package/dist/invoice/pdf.js.map +1 -0
  42. package/dist/invoice/store.d.ts +96 -0
  43. package/dist/invoice/store.d.ts.map +1 -0
  44. package/dist/invoice/store.js +221 -0
  45. package/dist/invoice/store.js.map +1 -0
  46. package/dist/money.d.ts +55 -0
  47. package/dist/money.d.ts.map +1 -0
  48. package/dist/money.js +146 -0
  49. package/dist/money.js.map +1 -0
  50. package/dist/order/store.d.ts +75 -0
  51. package/dist/order/store.d.ts.map +1 -0
  52. package/dist/order/store.js +301 -0
  53. package/dist/order/store.js.map +1 -0
  54. package/dist/order/types.d.ts +67 -0
  55. package/dist/order/types.d.ts.map +1 -0
  56. package/dist/order/types.js +71 -0
  57. package/dist/order/types.js.map +1 -0
  58. package/dist/payment/manual.d.ts +27 -0
  59. package/dist/payment/manual.d.ts.map +1 -0
  60. package/dist/payment/manual.js +105 -0
  61. package/dist/payment/manual.js.map +1 -0
  62. package/dist/payment/registry.d.ts +23 -0
  63. package/dist/payment/registry.d.ts.map +1 -0
  64. package/dist/payment/registry.js +30 -0
  65. package/dist/payment/registry.js.map +1 -0
  66. package/dist/payment/store.d.ts +38 -0
  67. package/dist/payment/store.d.ts.map +1 -0
  68. package/dist/payment/store.js +253 -0
  69. package/dist/payment/store.js.map +1 -0
  70. package/dist/payment/stripe.d.ts +10 -0
  71. package/dist/payment/stripe.d.ts.map +1 -0
  72. package/dist/payment/stripe.js +419 -0
  73. package/dist/payment/stripe.js.map +1 -0
  74. package/dist/payment/types.d.ts +124 -0
  75. package/dist/payment/types.d.ts.map +1 -0
  76. package/dist/payment/types.js +18 -0
  77. package/dist/payment/types.js.map +1 -0
  78. package/dist/rows.d.ts +26 -0
  79. package/dist/rows.d.ts.map +1 -0
  80. package/dist/rows.js +87 -0
  81. package/dist/rows.js.map +1 -0
  82. package/dist/shipping/store.d.ts +88 -0
  83. package/dist/shipping/store.d.ts.map +1 -0
  84. package/dist/shipping/store.js +165 -0
  85. package/dist/shipping/store.js.map +1 -0
  86. package/dist/subscription/store.d.ts +106 -0
  87. package/dist/subscription/store.d.ts.map +1 -0
  88. package/dist/subscription/store.js +310 -0
  89. package/dist/subscription/store.js.map +1 -0
  90. package/dist/tables.d.ts +41 -0
  91. package/dist/tables.d.ts.map +1 -0
  92. package/dist/tables.js +383 -0
  93. package/dist/tables.js.map +1 -0
  94. package/dist/tax/store.d.ts +68 -0
  95. package/dist/tax/store.d.ts.map +1 -0
  96. package/dist/tax/store.js +126 -0
  97. package/dist/tax/store.js.map +1 -0
  98. package/package.json +42 -0
@@ -0,0 +1,419 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ import { CogentaError } from '@cogenta/core';
3
+ /**
4
+ * The optimal payment driver: a real Stripe client, written against Stripe's
5
+ * REST API rather than the `stripe` npm package.
6
+ *
7
+ * Rule R9 — "préférer zéro dépendance à une petite dépendance". The `stripe`
8
+ * package is neither small nor free: it pulls a full HTTP stack and a very
9
+ * large set of generated types for the four calls this driver makes. The same
10
+ * precedent already exists in this codebase (`@cogenta/channels`' hand-written
11
+ * Telegram/Slack/Discord clients, `@cogenta/import`'s hand-rolled WXR parser).
12
+ *
13
+ * The wire format is not guessed: Stripe's API takes
14
+ * `application/x-www-form-urlencoded` in, answers JSON, and authenticates with
15
+ * `Authorization: Bearer <secret key>`. Nested keys use the bracket syntax
16
+ * (`metadata[order_reference]`), which `URLSearchParams` encodes correctly.
17
+ */
18
+ const DEFAULT_API_BASE_URL = 'https://api.stripe.com';
19
+ /** Stripe's own recommendation for a webhook freshness window. */
20
+ const SIGNATURE_FRESHNESS_WINDOW_SECONDS = 5 * 60;
21
+ /** Long enough for a real payment call, short enough that a hung TCP connection is not a hung checkout. */
22
+ const REQUEST_TIMEOUT_MS = 20_000;
23
+ /** An availability probe answers fast or it does not answer: the registry is waiting to fall through. */
24
+ const AVAILABILITY_TIMEOUT_MS = 3_000;
25
+ /**
26
+ * Stripe's PaymentIntent vocabulary, mapped onto the six statuses of the
27
+ * `PaymentGateway` contract. Everything before the money moves is `pending`;
28
+ * a manual-capture intent holding funds is `authorised`.
29
+ */
30
+ const INTENT_STATUS_MAP = {
31
+ requires_payment_method: 'pending',
32
+ requires_confirmation: 'pending',
33
+ requires_action: 'pending',
34
+ processing: 'pending',
35
+ requires_capture: 'authorised',
36
+ succeeded: 'paid',
37
+ canceled: 'cancelled',
38
+ };
39
+ /** Stripe's Refund vocabulary, mapped onto the three a `DriverRefundResult` carries. */
40
+ const REFUND_STATUS_MAP = {
41
+ pending: 'pending',
42
+ requires_action: 'pending',
43
+ succeeded: 'refunded',
44
+ failed: 'failed',
45
+ canceled: 'failed',
46
+ };
47
+ /**
48
+ * The inbound events this driver understands. Every one of them is a statement
49
+ * about where the money is; an event type outside this table is refused rather
50
+ * than mapped to a guess, because guessing "paid" is how goods leave for free.
51
+ */
52
+ const EVENT_TYPE_STATUS = {
53
+ 'payment_intent.succeeded': 'paid',
54
+ 'payment_intent.payment_failed': 'failed',
55
+ 'payment_intent.canceled': 'cancelled',
56
+ 'charge.refunded': 'refunded',
57
+ };
58
+ function asRecord(value) {
59
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
60
+ ? value
61
+ : null;
62
+ }
63
+ function readString(source, key) {
64
+ const value = source?.[key];
65
+ return typeof value === 'string' && value !== '' ? value : null;
66
+ }
67
+ function readNumber(source, key) {
68
+ const value = source?.[key];
69
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
70
+ }
71
+ /**
72
+ * The one place a Stripe failure becomes a Cogenta failure.
73
+ *
74
+ * `details` carries the status code and Stripe's own error identifiers, and
75
+ * nothing else — never the request headers, never the URL with credentials,
76
+ * never the secret key (rule R7). An operator gets what they need to find the
77
+ * call in the Stripe dashboard; a log reader gets nothing they could spend.
78
+ */
79
+ function paymentFailed(message, hint, details, cause) {
80
+ return new CogentaError({
81
+ code: 'COMMERCE_PAYMENT_FAILED',
82
+ message,
83
+ hint,
84
+ details,
85
+ ...(cause === undefined ? {} : { cause }),
86
+ });
87
+ }
88
+ function signatureInvalid(reason) {
89
+ return new CogentaError({
90
+ code: 'COMMERCE_PAYMENT_SIGNATURE_INVALID',
91
+ message: `The Stripe webhook signature was refused: ${reason}.`,
92
+ hint: 'Check that payment.webhookSecret matches the signing secret shown for this endpoint in the Stripe dashboard, that the raw request body is passed unparsed, and that the clock on this server is correct.',
93
+ details: { reason },
94
+ });
95
+ }
96
+ /**
97
+ * Constant-time comparison of two hex digests.
98
+ *
99
+ * Same discipline as `@cogenta/channels`' inbound webhook verification: length
100
+ * is checked first because `timingSafeEqual` throws on a mismatch, and the
101
+ * comparison itself never short-circuits on the first differing byte.
102
+ */
103
+ function digestsMatch(expected, received) {
104
+ const a = Buffer.from(expected, 'utf8');
105
+ const b = Buffer.from(received, 'utf8');
106
+ return a.length === b.length && timingSafeEqual(a, b);
107
+ }
108
+ /**
109
+ * Parses `t=1614556800,v1=<hex>,v1=<hex>`.
110
+ *
111
+ * More than one `v1` is normal, not an anomaly: during a signing-secret
112
+ * rotation Stripe signs each delivery with both secrets, and an endpoint that
113
+ * only looks at the first one goes deaf halfway through the rotation.
114
+ */
115
+ function parseSignatureHeader(header) {
116
+ let timestamp = null;
117
+ const signatures = [];
118
+ for (const part of header.split(',')) {
119
+ const separator = part.indexOf('=');
120
+ if (separator === -1)
121
+ continue;
122
+ const key = part.slice(0, separator).trim();
123
+ const value = part.slice(separator + 1).trim();
124
+ if (key === 't') {
125
+ const parsed = Number(value);
126
+ if (Number.isFinite(parsed))
127
+ timestamp = parsed;
128
+ }
129
+ else if (key === 'v1' && value !== '') {
130
+ signatures.push(value);
131
+ }
132
+ }
133
+ return { timestamp, signatures };
134
+ }
135
+ /** Header names arrive however the HTTP server spelled them; Stripe's is `stripe-signature`. */
136
+ function headerValue(headers, name) {
137
+ for (const [key, value] of Object.entries(headers)) {
138
+ if (key.toLowerCase() === name)
139
+ return value;
140
+ }
141
+ return undefined;
142
+ }
143
+ /**
144
+ * A real Stripe gateway.
145
+ *
146
+ * `stripePaymentDriver()` is the driver (selection, availability, health);
147
+ * this is the instance it hands back once a secret key is known to exist.
148
+ */
149
+ function createStripeGateway(secretKey, baseUrl, webhookSecret, options) {
150
+ const now = options.now ?? Date.now;
151
+ const logger = options.logger;
152
+ async function call(path, init) {
153
+ let response;
154
+ try {
155
+ response = await fetch(`${baseUrl}${path}`, {
156
+ method: init.method,
157
+ headers: {
158
+ authorization: `Bearer ${secretKey}`,
159
+ ...(init.form === undefined
160
+ ? {}
161
+ : { 'content-type': 'application/x-www-form-urlencoded' }),
162
+ },
163
+ ...(init.form === undefined ? {} : { body: init.form.toString() }),
164
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
165
+ });
166
+ }
167
+ catch (error) {
168
+ throw paymentFailed(`Stripe could not be reached for ${init.method} ${path}.`, 'Check outbound network access from this server, and whether Stripe is reporting an incident.', { path, method: init.method }, error);
169
+ }
170
+ const text = await response.text();
171
+ const parsed = text === '' ? null : safeJsonParse(text);
172
+ const body = asRecord(parsed);
173
+ if (!response.ok) {
174
+ const stripeError = asRecord(body?.error);
175
+ throw paymentFailed(`Stripe refused ${init.method} ${path} with HTTP ${response.status}: ${readString(stripeError, 'message') ?? 'no reason given'}`, 'Check the amount, the currency and the payment method in the Stripe dashboard; a 401 means the secret key is wrong or revoked.', {
176
+ path,
177
+ method: init.method,
178
+ status: response.status,
179
+ // Stripe's own identifiers for the failure. Never the key, never the
180
+ // request headers.
181
+ stripeErrorType: readString(stripeError, 'type'),
182
+ stripeErrorCode: readString(stripeError, 'code'),
183
+ });
184
+ }
185
+ if (body === null) {
186
+ throw paymentFailed(`Stripe answered ${init.method} ${path} with something that is not a JSON object.`, 'This is usually a proxy or a captive portal answering instead of Stripe; check payment.apiBaseUrl and the outbound route.', { path, method: init.method, status: response.status });
187
+ }
188
+ return body;
189
+ }
190
+ function safeJsonParse(text) {
191
+ try {
192
+ return JSON.parse(text);
193
+ }
194
+ catch {
195
+ return null;
196
+ }
197
+ }
198
+ /** An unknown status is reported, never guessed: `failed` is the safe reading. */
199
+ function mapIntentStatus(status, externalId) {
200
+ const mapped = status === null ? undefined : INTENT_STATUS_MAP[status];
201
+ if (mapped !== undefined)
202
+ return mapped;
203
+ logger?.warn('Stripe reported a payment intent status this driver does not know.', {
204
+ driver: 'stripe',
205
+ stripeStatus: status,
206
+ externalId,
207
+ mappedTo: 'failed',
208
+ });
209
+ return 'failed';
210
+ }
211
+ function toStartedPayment(intent) {
212
+ const externalId = readString(intent, 'id');
213
+ if (externalId === null) {
214
+ throw paymentFailed('Stripe returned a payment intent without an id.', 'Retry the payment; if it recurs, check the Stripe API version configured on the account.', { received: Object.keys(intent) });
215
+ }
216
+ return {
217
+ externalId,
218
+ status: mapIntentStatus(readString(intent, 'status'), externalId),
219
+ // The client secret is what the shopper's browser needs to finish the
220
+ // payment. It is scoped to this one intent and is meant to reach the
221
+ // front end — it is not an account credential.
222
+ instructions: readString(intent, 'client_secret'),
223
+ };
224
+ }
225
+ return {
226
+ name: 'stripe',
227
+ settlesOffline: false,
228
+ start: async (request) => {
229
+ const form = new URLSearchParams();
230
+ form.set('amount', String(request.amountMinor));
231
+ // Stripe rejects an upper-case code.
232
+ form.set('currency', request.currency.toLowerCase());
233
+ // The reference, not the internal id: this is what comes back on the
234
+ // webhook and what a human reads on a statement.
235
+ form.set('metadata[order_reference]', request.orderReference);
236
+ form.set('receipt_email', request.customerEmail);
237
+ // Lets the account's own payment-method settings decide what the shopper
238
+ // is offered, instead of hard-coding "card" here.
239
+ form.set('automatic_payment_methods[enabled]', 'true');
240
+ if (request.description !== undefined)
241
+ form.set('description', request.description);
242
+ return toStartedPayment(await call('/v1/payment_intents', { method: 'POST', form }));
243
+ },
244
+ fetch: async (externalId) => toStartedPayment(await call(`/v1/payment_intents/${encodeURIComponent(externalId)}`, { method: 'GET' })),
245
+ refund: async (request) => {
246
+ const form = new URLSearchParams();
247
+ form.set('payment_intent', request.externalId);
248
+ // Always explicit: omitting it refunds the whole intent, which is not
249
+ // what a partial refund asked for.
250
+ form.set('amount', String(request.amountMinor));
251
+ const refund = await call('/v1/refunds', { method: 'POST', form });
252
+ const status = readString(refund, 'status');
253
+ const mapped = status === null ? undefined : REFUND_STATUS_MAP[status];
254
+ if (mapped === undefined) {
255
+ logger?.warn('Stripe reported a refund status this driver does not know.', {
256
+ driver: 'stripe',
257
+ stripeStatus: status,
258
+ paymentIntent: request.externalId,
259
+ mappedTo: 'failed',
260
+ });
261
+ }
262
+ return { externalId: readString(refund, 'id'), status: mapped ?? 'failed' };
263
+ },
264
+ verifyEvent: async (payload, headers) => {
265
+ const header = headerValue(headers, 'stripe-signature');
266
+ if (header === undefined || header === '')
267
+ throw signatureInvalid('no stripe-signature header');
268
+ if (webhookSecret === undefined || webhookSecret === '') {
269
+ throw signatureInvalid('no webhook secret is configured for this site');
270
+ }
271
+ const { timestamp, signatures } = parseSignatureHeader(header);
272
+ if (timestamp === null)
273
+ throw signatureInvalid('the header carried no usable timestamp');
274
+ if (signatures.length === 0)
275
+ throw signatureInvalid('the header carried no v1 signature');
276
+ // Freshness before authenticity: a captured, genuinely-signed delivery
277
+ // stays genuinely signed forever, so the window is what stops a replay.
278
+ const ageSeconds = Math.abs(Math.floor(now() / 1000) - timestamp);
279
+ if (ageSeconds > SIGNATURE_FRESHNESS_WINDOW_SECONDS) {
280
+ throw signatureInvalid(`the signed timestamp is ${ageSeconds}s away from now, outside the ${SIGNATURE_FRESHNESS_WINDOW_SECONDS}s window`);
281
+ }
282
+ const expected = createHmac('sha256', webhookSecret)
283
+ .update(`${timestamp}.${payload}`)
284
+ .digest('hex');
285
+ // Every v1 is tried, and the loop never breaks early on a match, so the
286
+ // number of comparisons does not depend on which secret signed it.
287
+ let matched = false;
288
+ for (const candidate of signatures) {
289
+ if (digestsMatch(expected, candidate))
290
+ matched = true;
291
+ }
292
+ if (!matched)
293
+ throw signatureInvalid('no v1 signature matched the configured secret');
294
+ const event = asRecord(safeJsonParse(payload));
295
+ const type = readString(event, 'type');
296
+ const status = type === null ? undefined : EVENT_TYPE_STATUS[type];
297
+ if (status === undefined) {
298
+ throw new CogentaError({
299
+ code: 'COMMERCE_PAYMENT_UNSUPPORTED',
300
+ message: `This driver has no reading for the Stripe event "${type ?? 'unknown'}".`,
301
+ hint: `Narrow the endpoint in the Stripe dashboard to ${Object.keys(EVENT_TYPE_STATUS).join(', ')}.`,
302
+ details: { eventType: type },
303
+ });
304
+ }
305
+ const object = asRecord(asRecord(event?.data)?.object);
306
+ // On a charge, the intent lives in `payment_intent`; on an intent, it is
307
+ // the object's own id. The store keys payments by the intent either way.
308
+ const externalId = type === 'charge.refunded'
309
+ ? (readString(object, 'payment_intent') ?? readString(object, 'id'))
310
+ : readString(object, 'id');
311
+ if (externalId === null) {
312
+ throw paymentFailed(`The Stripe event "${type}" carried no payment identifier.`, 'Check the API version configured on the Stripe account: an older version shapes this event differently.', { eventType: type });
313
+ }
314
+ const amountMinor = type === 'charge.refunded'
315
+ ? (readNumber(object, 'amount_refunded') ?? readNumber(object, 'amount'))
316
+ : readNumber(object, 'amount');
317
+ const currency = readString(object, 'currency');
318
+ return {
319
+ externalId,
320
+ orderReference: readString(asRecord(object?.metadata), 'order_reference'),
321
+ status,
322
+ amountMinor,
323
+ // Stripe sends a lower-case code; every stored record in this package
324
+ // holds the ISO 4217 upper-case one.
325
+ currency: currency === null ? null : currency.toUpperCase(),
326
+ };
327
+ },
328
+ };
329
+ }
330
+ export function stripePaymentDriver(options = {}) {
331
+ let gateway;
332
+ let probe;
333
+ const resolveBaseUrl = (config) => (config.apiBaseUrl ?? DEFAULT_API_BASE_URL).replace(/\/+$/, '');
334
+ return {
335
+ name: 'stripe',
336
+ tier: 'optimal',
337
+ /**
338
+ * Does Stripe actually answer with this key? Not "is a key configured?" —
339
+ * the registry reads a `false` as "fall through to the offline driver", so
340
+ * this must never throw, and must never hang a startup either.
341
+ */
342
+ available: async (config) => {
343
+ if (config.secretKey === undefined || config.secretKey === '')
344
+ return false;
345
+ try {
346
+ const response = await fetch(`${resolveBaseUrl(config)}/v1/balance`, {
347
+ method: 'GET',
348
+ headers: { authorization: `Bearer ${config.secretKey}` },
349
+ signal: AbortSignal.timeout(AVAILABILITY_TIMEOUT_MS),
350
+ });
351
+ // The body is drained so the socket is released rather than left open
352
+ // for the timeout to reap.
353
+ await response.text();
354
+ return response.ok;
355
+ }
356
+ catch {
357
+ return false;
358
+ }
359
+ },
360
+ init: async (config) => {
361
+ if (config.secretKey === undefined || config.secretKey === '') {
362
+ throw new CogentaError({
363
+ code: 'CONFIG_INVALID',
364
+ message: 'The Stripe payment driver needs a secret key.',
365
+ hint: 'Set payment.secretKey (or the COGENTA_PAYMENT_SECRET_KEY environment variable), or leave payment.driver unset to be paid by bank transfer.',
366
+ });
367
+ }
368
+ const baseUrl = resolveBaseUrl(config);
369
+ probe = { secretKey: config.secretKey, baseUrl };
370
+ gateway ??= createStripeGateway(config.secretKey, baseUrl, config.webhookSecret, options);
371
+ return gateway;
372
+ },
373
+ dispose: async () => {
374
+ // Nothing to close: every call is a one-shot `fetch`.
375
+ gateway = undefined;
376
+ probe = undefined;
377
+ },
378
+ health: async () => {
379
+ if (probe === undefined) {
380
+ return { status: 'down', driver: 'stripe', tier: 'optimal', message: 'Not configured.' };
381
+ }
382
+ const startedAt = Date.now();
383
+ try {
384
+ const response = await fetch(`${probe.baseUrl}/v1/balance`, {
385
+ method: 'GET',
386
+ headers: { authorization: `Bearer ${probe.secretKey}` },
387
+ signal: AbortSignal.timeout(AVAILABILITY_TIMEOUT_MS),
388
+ });
389
+ await response.text();
390
+ return response.ok
391
+ ? {
392
+ status: 'ok',
393
+ driver: 'stripe',
394
+ tier: 'optimal',
395
+ latencyMs: Date.now() - startedAt,
396
+ // The key is never named, not even partially.
397
+ message: 'Stripe answered.',
398
+ }
399
+ : {
400
+ status: 'down',
401
+ driver: 'stripe',
402
+ tier: 'optimal',
403
+ latencyMs: Date.now() - startedAt,
404
+ message: `Stripe refused the account check with HTTP ${response.status}.`,
405
+ details: { status: response.status },
406
+ };
407
+ }
408
+ catch {
409
+ return {
410
+ status: 'down',
411
+ driver: 'stripe',
412
+ tier: 'optimal',
413
+ message: 'Stripe did not answer.',
414
+ };
415
+ }
416
+ },
417
+ };
418
+ }
419
+ //# sourceMappingURL=stripe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/payment/stripe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import type { Driver, DriverChoice } from '@cogenta/core';
2
+ /**
3
+ * Where a payment is in its life. Deliberately small.
4
+ *
5
+ * A gateway has dozens of internal states; a shop needs to know whether it has
6
+ * the money. Every driver maps its own vocabulary onto these six, so the order
7
+ * store never branches on a gateway-specific string.
8
+ */
9
+ export declare const PAYMENT_STATUSES: readonly [
10
+ /** Created, waiting for the shopper (or for a bank transfer to arrive). */
11
+ 'pending',
12
+ /** The gateway holds the funds but has not moved them. */
13
+ 'authorised', 'paid', 'failed', 'cancelled', 'refunded'];
14
+ export type PaymentStatus = (typeof PAYMENT_STATUSES)[number];
15
+ export interface PaymentRecord {
16
+ readonly id: string;
17
+ readonly orderId: string;
18
+ readonly driver: string;
19
+ /** The gateway's own identifier, or null for a driver that has none yet. */
20
+ readonly externalId: string | null;
21
+ readonly status: PaymentStatus;
22
+ readonly amountMinor: number;
23
+ readonly currency: string;
24
+ /** Shown to the shopper: bank details, or a URL to finish the payment. */
25
+ readonly instructions: string | null;
26
+ readonly createdAt: string;
27
+ readonly updatedAt: string;
28
+ }
29
+ export interface RefundRecord {
30
+ readonly id: string;
31
+ readonly paymentId: string;
32
+ readonly orderId: string;
33
+ readonly externalId: string | null;
34
+ readonly status: 'pending' | 'refunded' | 'failed';
35
+ readonly amountMinor: number;
36
+ readonly currency: string;
37
+ readonly reason: string | null;
38
+ readonly createdAt: string;
39
+ }
40
+ export interface StartPaymentRequest {
41
+ readonly orderId: string;
42
+ readonly orderReference: string;
43
+ readonly amountMinor: number;
44
+ readonly currency: string;
45
+ readonly customerEmail: string;
46
+ /** Where the shopper should end up after a redirect, if the driver uses one. */
47
+ readonly returnUrl?: string;
48
+ readonly description?: string;
49
+ }
50
+ /** What a driver hands back. Never a record: the store owns persistence. */
51
+ export interface StartedPayment {
52
+ readonly externalId: string | null;
53
+ readonly status: PaymentStatus;
54
+ readonly instructions: string | null;
55
+ }
56
+ export interface DriverRefundRequest {
57
+ readonly externalId: string;
58
+ readonly amountMinor: number;
59
+ readonly currency: string;
60
+ readonly reason?: string;
61
+ }
62
+ export interface DriverRefundResult {
63
+ readonly externalId: string | null;
64
+ readonly status: 'pending' | 'refunded' | 'failed';
65
+ }
66
+ /**
67
+ * A payment event that arrived from outside, already proven authentic.
68
+ *
69
+ * `orderReference` rather than `orderId`: what comes back from a gateway is
70
+ * whatever was put in when the payment started, and a reference is what a
71
+ * human reads on a bank statement.
72
+ */
73
+ export interface PaymentEvent {
74
+ readonly externalId: string;
75
+ readonly orderReference: string | null;
76
+ readonly status: PaymentStatus;
77
+ readonly amountMinor: number | null;
78
+ readonly currency: string | null;
79
+ }
80
+ /**
81
+ * One payment gateway.
82
+ *
83
+ * Interface plus at least two implementations, exactly like cache, queue and
84
+ * storage (R1, ADR-0005). The degraded one — bank transfer — depends on no
85
+ * external service at all, which is what makes R2 true for a shop: no Stripe
86
+ * key, and the till still works. It is not a stub: plenty of real businesses
87
+ * are paid by transfer and nothing else.
88
+ */
89
+ export interface PaymentGateway {
90
+ readonly name: string;
91
+ /**
92
+ * True when money moves outside any API and a human confirms it.
93
+ *
94
+ * The order store branches on this rather than on the driver's name, so a
95
+ * second offline driver (cash on delivery, cheque) needs no new condition
96
+ * anywhere.
97
+ */
98
+ readonly settlesOffline: boolean;
99
+ start(request: StartPaymentRequest): Promise<StartedPayment>;
100
+ /** Re-reads a payment from the gateway. Offline drivers report unchanged. */
101
+ fetch(externalId: string): Promise<StartedPayment>;
102
+ refund(request: DriverRefundRequest): Promise<DriverRefundResult>;
103
+ /**
104
+ * Verifies and decodes an inbound notification.
105
+ *
106
+ * Throws `COMMERCE_PAYMENT_UNSUPPORTED` for a driver that has no inbound
107
+ * channel, and `COMMERCE_PAYMENT_SIGNATURE_INVALID` for one that does and is
108
+ * handed something unsigned. Never returns an unverified event: an
109
+ * unauthenticated "paid" notification is a way to get goods for free.
110
+ */
111
+ verifyEvent(payload: string, headers: Readonly<Record<string, string>>): Promise<PaymentEvent>;
112
+ }
113
+ export interface PaymentConfig extends DriverChoice {
114
+ /** Stripe's secret key. Absent on any site that has not configured one. */
115
+ readonly secretKey?: string;
116
+ /** The signing secret Stripe shows when a webhook endpoint is created. */
117
+ readonly webhookSecret?: string;
118
+ /** Overridden by tests to point at a local server. Never set in production. */
119
+ readonly apiBaseUrl?: string;
120
+ /** Shown to the shopper by the offline driver. Free text, per site. */
121
+ readonly transferInstructions?: string;
122
+ }
123
+ export type PaymentDriver = Driver<PaymentGateway, PaymentConfig>;
124
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/payment/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;AAC3B,2EAA2E;AAC3E,SAAS;AACT,0DAA0D;AAC1D,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAU,CACF,CAAA;AACV,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAA;CACnD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACjC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,KAAK,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IAC5D,6EAA6E;IAC7E,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IAClD,MAAM,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACjE;;;;;;;OAOG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;CAC/F;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;CACvC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Where a payment is in its life. Deliberately small.
3
+ *
4
+ * A gateway has dozens of internal states; a shop needs to know whether it has
5
+ * the money. Every driver maps its own vocabulary onto these six, so the order
6
+ * store never branches on a gateway-specific string.
7
+ */
8
+ export const PAYMENT_STATUSES = [
9
+ /** Created, waiting for the shopper (or for a bank transfer to arrive). */
10
+ 'pending',
11
+ /** The gateway holds the funds but has not moved them. */
12
+ 'authorised',
13
+ 'paid',
14
+ 'failed',
15
+ 'cancelled',
16
+ 'refunded',
17
+ ];
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/payment/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,2EAA2E;IAC3E,SAAS;IACT,0DAA0D;IAC1D,YAAY;IACZ,MAAM;IACN,QAAQ;IACR,WAAW;IACX,UAAU;CACF,CAAA"}
package/dist/rows.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Reading numbers back out of three databases that disagree about them.
3
+ *
4
+ * `bigint` columns do not come back as JavaScript numbers everywhere: `pg`
5
+ * hands back `int8` as a **string** (deliberately — it refuses to lose
6
+ * precision silently), `mysql2` may hand back a `bigint`, and `node:sqlite`
7
+ * gives a plain number. Reading `row.total_minor` and trusting it is therefore
8
+ * a bug that only appears on Postgres, which is exactly the kind of thing this
9
+ * project tests three dialects to catch.
10
+ *
11
+ * Every integer read in this package goes through here.
12
+ */
13
+ export declare function toInt(value: unknown, what: string): number;
14
+ /**
15
+ * Booleans, likewise.
16
+ *
17
+ * Postgres has a real `boolean`, MySQL stores `tinyint`, and SQLite stores
18
+ * whatever it was handed. `0`, `'0'`, `false` and `'false'` all mean false.
19
+ */
20
+ export declare function toBool(value: unknown): boolean;
21
+ /** The value a boolean is written as. Postgres wants a real boolean. */
22
+ export declare function fromBool(value: boolean, dialect: string): boolean | number;
23
+ export declare function toText(value: unknown, what: string): string;
24
+ export declare function toNullableText(value: unknown): string | null;
25
+ export declare function toNullableInt(value: unknown, what: string): number | null;
26
+ //# sourceMappingURL=rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB1D;AAWD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM9C;AAED,wEAAwE;AACxE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAE1E;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzE"}