@develemit/commerce-server 0.3.0 → 0.6.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/README.md CHANGED
@@ -51,6 +51,11 @@ const sweeper = startHoldSweeper(db, { intervalMs: 60_000 });
51
51
  app.addHook('onClose', async () => sweeper.stop());
52
52
  ```
53
53
 
54
+ `resolvePayment(process.env)` picks Stripe or the fake gateway from the
55
+ environment (it refuses the fake gateway when `NODE_ENV=production` and
56
+ half-configured Stripe keys), and `checkoutUrls(webUrl)` builds the `urls`
57
+ option; use them instead of hand-writing both.
58
+
54
59
  `payment` and `urls` go together. Omit both (`commercePlugin({ db, currency })`)
55
60
  for a catalog-only mount: the checkout, webhook, and order routes aren't
56
61
  registered, so `/checkout` returns 404.
@@ -105,6 +110,28 @@ matters.
105
110
  The package never reads `process.env`; pass everything in. Load products with
106
111
  `seedProducts(db, products)`, an idempotent upsert on `slug`.
107
112
 
113
+ ## Order emails
114
+
115
+ `orderEmailLines(order, { locale, labels })` builds the money and address
116
+ pieces of an order email from the `OrderDetail` a hook receives. You write the
117
+ layout and copy.
118
+
119
+ ```ts
120
+ onOrderPaid: async (order) => {
121
+ const lines = orderEmailLines(order);
122
+ await mailer.send({
123
+ to: order.email,
124
+ text: `${lines.text.items}\n${lines.text.totals}\n\n${lines.text.address}`,
125
+ html: `<table>${lines.html.items}${lines.html.totals}</table>${lines.html.address}`,
126
+ });
127
+ },
128
+ ```
129
+
130
+ The result also has structured `items`, `subtotal`, `discount` (absent when
131
+ no discount applied), `shipping`, `total` and `address` (absent for pickup).
132
+ HTML output is `<tr>` / `<p>` fragments with `& < > " '` escaped. Override
133
+ copy with `labels`.
134
+
108
135
  ## Running a shop
109
136
 
110
137
  The order lifecycle, from the host's side:
@@ -161,20 +188,36 @@ app root before `commercePlugin`, so its `onSend` runs after the catalog's.
161
188
  Webhook raw-body parsing is request-side and unaffected by compression.
162
189
  - **Retries:** refunds require an `Idempotency-Key`; reuse it when retrying so
163
190
  a refund can't be issued twice.
191
+ - **Rate limiting:** `POST /checkout/discount/preview` lets anyone test codes.
192
+ Rate-limit it (and `POST /checkout`) at the host or CDN; the kit doesn't.
164
193
  - Admin routes: see [Admin API](docs/admin.md).
165
194
 
166
195
  ## Routes
167
196
 
168
197
  Relative to the host's prefix:
169
198
 
170
- | Route | Purpose |
171
- | -------------------------------- | ---------------------------------------------------------- |
172
- | `GET /catalog/products` | Active products (`?category=`, `?featured=true`) |
173
- | `GET /catalog/products/:slug` | One product, or 404 `PRODUCT_NOT_FOUND` |
174
- | `GET /catalog/categories` | Active product counts per category |
175
- | `POST /checkout` | `{ items: [{ productId, quantity }] }` → `{ url }`, or 409 |
176
- | `POST /orders/webhooks/stripe` | Stripe webhook (raw body, `stripe-signature` header) |
177
- | `GET /orders/session/:sessionId` | `orderSummarySchema` for the success page |
199
+ | Route | Purpose |
200
+ | --------------------------------- | --------------------------------------------------------------- |
201
+ | `GET /catalog/products` | Active products (`?category=`, `?featured=true`) |
202
+ | `GET /catalog/products/:slug` | One product, or 404 `PRODUCT_NOT_FOUND` |
203
+ | `GET /catalog/categories` | Active product counts per category |
204
+ | `POST /checkout` | `{ items: [{ productId, quantity }] }` → `{ url }`, or 409 |
205
+ | `POST /checkout/discount/preview` | `{ code, items }` → discount preview, or 422 `DISCOUNT_INVALID` |
206
+ | `POST /orders/webhooks/stripe` | Stripe webhook (raw body, `stripe-signature` header) |
207
+ | `GET /orders/session/:sessionId` | `orderSummarySchema` for the success page |
208
+
209
+ ## Discounts
210
+
211
+ `POST /checkout/discount/preview` takes `{ code, items }` and answers
212
+ `{ code, discountCents, subtotalCents, currency }`, or 422
213
+ `{ error: 'DISCOUNT_INVALID', reason }`. The subtotal is priced from the
214
+ database over the items that are currently purchasable in the shop currency;
215
+ unavailable items are left out, matching what checkout would charge. Rules run
216
+ in order and the first failure wins: not found, inactive, not started, expired,
217
+ currency (fixed codes), minimum subtotal, redemptions exhausted. Percent codes
218
+ round down; fixed codes never exceed the subtotal; shipping is never
219
+ discounted. An inactive code is reported as `not_found` so drafts don't leak.
220
+ Responses are `Cache-Control: no-store`.
178
221
 
179
222
  ## How checkout stays honest
180
223
 
package/dist/index.d.ts CHANGED
@@ -560,6 +560,40 @@ declare const commerceSchema: {
560
560
  identity: undefined;
561
561
  generated: undefined;
562
562
  }, {}, {}>;
563
+ discountCents: drizzle_orm_pg_core.PgColumn<{
564
+ name: "discount_cents";
565
+ tableName: "commerce_orders";
566
+ dataType: "number";
567
+ columnType: "PgInteger";
568
+ data: number;
569
+ driverParam: string | number;
570
+ notNull: true;
571
+ hasDefault: true;
572
+ isPrimaryKey: false;
573
+ isAutoincrement: false;
574
+ hasRuntimeDefault: false;
575
+ enumValues: undefined;
576
+ baseColumn: never;
577
+ identity: undefined;
578
+ generated: undefined;
579
+ }, {}, {}>;
580
+ discountCode: drizzle_orm_pg_core.PgColumn<{
581
+ name: "discount_code";
582
+ tableName: "commerce_orders";
583
+ dataType: "string";
584
+ columnType: "PgText";
585
+ data: string;
586
+ driverParam: string;
587
+ notNull: false;
588
+ hasDefault: false;
589
+ isPrimaryKey: false;
590
+ isAutoincrement: false;
591
+ hasRuntimeDefault: false;
592
+ enumValues: [string, ...string[]];
593
+ baseColumn: never;
594
+ identity: undefined;
595
+ generated: undefined;
596
+ }, {}, {}>;
563
597
  shippingCents: drizzle_orm_pg_core.PgColumn<{
564
598
  name: "shipping_cents";
565
599
  tableName: "commerce_orders";
@@ -1238,6 +1272,360 @@ declare const commerceSchema: {
1238
1272
  };
1239
1273
  dialect: "pg";
1240
1274
  }>;
1275
+ discounts: drizzle_orm_pg_core.PgTableWithColumns<{
1276
+ name: "commerce_discounts";
1277
+ schema: undefined;
1278
+ columns: {
1279
+ id: drizzle_orm_pg_core.PgColumn<{
1280
+ name: "id";
1281
+ tableName: "commerce_discounts";
1282
+ dataType: "string";
1283
+ columnType: "PgUUID";
1284
+ data: string;
1285
+ driverParam: string;
1286
+ notNull: true;
1287
+ hasDefault: true;
1288
+ isPrimaryKey: true;
1289
+ isAutoincrement: false;
1290
+ hasRuntimeDefault: false;
1291
+ enumValues: undefined;
1292
+ baseColumn: never;
1293
+ identity: undefined;
1294
+ generated: undefined;
1295
+ }, {}, {}>;
1296
+ code: drizzle_orm_pg_core.PgColumn<{
1297
+ name: "code";
1298
+ tableName: "commerce_discounts";
1299
+ dataType: "string";
1300
+ columnType: "PgText";
1301
+ data: string;
1302
+ driverParam: string;
1303
+ notNull: true;
1304
+ hasDefault: false;
1305
+ isPrimaryKey: false;
1306
+ isAutoincrement: false;
1307
+ hasRuntimeDefault: false;
1308
+ enumValues: [string, ...string[]];
1309
+ baseColumn: never;
1310
+ identity: undefined;
1311
+ generated: undefined;
1312
+ }, {}, {}>;
1313
+ type: drizzle_orm_pg_core.PgColumn<{
1314
+ name: "type";
1315
+ tableName: "commerce_discounts";
1316
+ dataType: "string";
1317
+ columnType: "PgText";
1318
+ data: "fixed" | "percent";
1319
+ driverParam: string;
1320
+ notNull: true;
1321
+ hasDefault: false;
1322
+ isPrimaryKey: false;
1323
+ isAutoincrement: false;
1324
+ hasRuntimeDefault: false;
1325
+ enumValues: ["percent", "fixed"];
1326
+ baseColumn: never;
1327
+ identity: undefined;
1328
+ generated: undefined;
1329
+ }, {}, {}>;
1330
+ percentOff: drizzle_orm_pg_core.PgColumn<{
1331
+ name: "percent_off";
1332
+ tableName: "commerce_discounts";
1333
+ dataType: "number";
1334
+ columnType: "PgInteger";
1335
+ data: number;
1336
+ driverParam: string | number;
1337
+ notNull: false;
1338
+ hasDefault: false;
1339
+ isPrimaryKey: false;
1340
+ isAutoincrement: false;
1341
+ hasRuntimeDefault: false;
1342
+ enumValues: undefined;
1343
+ baseColumn: never;
1344
+ identity: undefined;
1345
+ generated: undefined;
1346
+ }, {}, {}>;
1347
+ amountOffCents: drizzle_orm_pg_core.PgColumn<{
1348
+ name: "amount_off_cents";
1349
+ tableName: "commerce_discounts";
1350
+ dataType: "number";
1351
+ columnType: "PgInteger";
1352
+ data: number;
1353
+ driverParam: string | number;
1354
+ notNull: false;
1355
+ hasDefault: false;
1356
+ isPrimaryKey: false;
1357
+ isAutoincrement: false;
1358
+ hasRuntimeDefault: false;
1359
+ enumValues: undefined;
1360
+ baseColumn: never;
1361
+ identity: undefined;
1362
+ generated: undefined;
1363
+ }, {}, {}>;
1364
+ currency: drizzle_orm_pg_core.PgColumn<{
1365
+ name: "currency";
1366
+ tableName: "commerce_discounts";
1367
+ dataType: "string";
1368
+ columnType: "PgText";
1369
+ data: string;
1370
+ driverParam: string;
1371
+ notNull: false;
1372
+ hasDefault: false;
1373
+ isPrimaryKey: false;
1374
+ isAutoincrement: false;
1375
+ hasRuntimeDefault: false;
1376
+ enumValues: [string, ...string[]];
1377
+ baseColumn: never;
1378
+ identity: undefined;
1379
+ generated: undefined;
1380
+ }, {}, {}>;
1381
+ minSubtotalCents: drizzle_orm_pg_core.PgColumn<{
1382
+ name: "min_subtotal_cents";
1383
+ tableName: "commerce_discounts";
1384
+ dataType: "number";
1385
+ columnType: "PgInteger";
1386
+ data: number;
1387
+ driverParam: string | number;
1388
+ notNull: false;
1389
+ hasDefault: false;
1390
+ isPrimaryKey: false;
1391
+ isAutoincrement: false;
1392
+ hasRuntimeDefault: false;
1393
+ enumValues: undefined;
1394
+ baseColumn: never;
1395
+ identity: undefined;
1396
+ generated: undefined;
1397
+ }, {}, {}>;
1398
+ startsAt: drizzle_orm_pg_core.PgColumn<{
1399
+ name: "starts_at";
1400
+ tableName: "commerce_discounts";
1401
+ dataType: "date";
1402
+ columnType: "PgTimestamp";
1403
+ data: Date;
1404
+ driverParam: string;
1405
+ notNull: false;
1406
+ hasDefault: false;
1407
+ isPrimaryKey: false;
1408
+ isAutoincrement: false;
1409
+ hasRuntimeDefault: false;
1410
+ enumValues: undefined;
1411
+ baseColumn: never;
1412
+ identity: undefined;
1413
+ generated: undefined;
1414
+ }, {}, {}>;
1415
+ endsAt: drizzle_orm_pg_core.PgColumn<{
1416
+ name: "ends_at";
1417
+ tableName: "commerce_discounts";
1418
+ dataType: "date";
1419
+ columnType: "PgTimestamp";
1420
+ data: Date;
1421
+ driverParam: string;
1422
+ notNull: false;
1423
+ hasDefault: false;
1424
+ isPrimaryKey: false;
1425
+ isAutoincrement: false;
1426
+ hasRuntimeDefault: false;
1427
+ enumValues: undefined;
1428
+ baseColumn: never;
1429
+ identity: undefined;
1430
+ generated: undefined;
1431
+ }, {}, {}>;
1432
+ maxRedemptions: drizzle_orm_pg_core.PgColumn<{
1433
+ name: "max_redemptions";
1434
+ tableName: "commerce_discounts";
1435
+ dataType: "number";
1436
+ columnType: "PgInteger";
1437
+ data: number;
1438
+ driverParam: string | number;
1439
+ notNull: false;
1440
+ hasDefault: false;
1441
+ isPrimaryKey: false;
1442
+ isAutoincrement: false;
1443
+ hasRuntimeDefault: false;
1444
+ enumValues: undefined;
1445
+ baseColumn: never;
1446
+ identity: undefined;
1447
+ generated: undefined;
1448
+ }, {}, {}>;
1449
+ active: drizzle_orm_pg_core.PgColumn<{
1450
+ name: "active";
1451
+ tableName: "commerce_discounts";
1452
+ dataType: "boolean";
1453
+ columnType: "PgBoolean";
1454
+ data: boolean;
1455
+ driverParam: boolean;
1456
+ notNull: true;
1457
+ hasDefault: true;
1458
+ isPrimaryKey: false;
1459
+ isAutoincrement: false;
1460
+ hasRuntimeDefault: false;
1461
+ enumValues: undefined;
1462
+ baseColumn: never;
1463
+ identity: undefined;
1464
+ generated: undefined;
1465
+ }, {}, {}>;
1466
+ createdAt: drizzle_orm_pg_core.PgColumn<{
1467
+ name: "created_at";
1468
+ tableName: "commerce_discounts";
1469
+ dataType: "date";
1470
+ columnType: "PgTimestamp";
1471
+ data: Date;
1472
+ driverParam: string;
1473
+ notNull: true;
1474
+ hasDefault: true;
1475
+ isPrimaryKey: false;
1476
+ isAutoincrement: false;
1477
+ hasRuntimeDefault: false;
1478
+ enumValues: undefined;
1479
+ baseColumn: never;
1480
+ identity: undefined;
1481
+ generated: undefined;
1482
+ }, {}, {}>;
1483
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
1484
+ name: "updated_at";
1485
+ tableName: "commerce_discounts";
1486
+ dataType: "date";
1487
+ columnType: "PgTimestamp";
1488
+ data: Date;
1489
+ driverParam: string;
1490
+ notNull: true;
1491
+ hasDefault: true;
1492
+ isPrimaryKey: false;
1493
+ isAutoincrement: false;
1494
+ hasRuntimeDefault: false;
1495
+ enumValues: undefined;
1496
+ baseColumn: never;
1497
+ identity: undefined;
1498
+ generated: undefined;
1499
+ }, {}, {}>;
1500
+ };
1501
+ dialect: "pg";
1502
+ }>;
1503
+ discountRedemptions: drizzle_orm_pg_core.PgTableWithColumns<{
1504
+ name: "commerce_discount_redemptions";
1505
+ schema: undefined;
1506
+ columns: {
1507
+ id: drizzle_orm_pg_core.PgColumn<{
1508
+ name: "id";
1509
+ tableName: "commerce_discount_redemptions";
1510
+ dataType: "string";
1511
+ columnType: "PgUUID";
1512
+ data: string;
1513
+ driverParam: string;
1514
+ notNull: true;
1515
+ hasDefault: true;
1516
+ isPrimaryKey: true;
1517
+ isAutoincrement: false;
1518
+ hasRuntimeDefault: false;
1519
+ enumValues: undefined;
1520
+ baseColumn: never;
1521
+ identity: undefined;
1522
+ generated: undefined;
1523
+ }, {}, {}>;
1524
+ discountId: drizzle_orm_pg_core.PgColumn<{
1525
+ name: "discount_id";
1526
+ tableName: "commerce_discount_redemptions";
1527
+ dataType: "string";
1528
+ columnType: "PgUUID";
1529
+ data: string;
1530
+ driverParam: string;
1531
+ notNull: true;
1532
+ hasDefault: false;
1533
+ isPrimaryKey: false;
1534
+ isAutoincrement: false;
1535
+ hasRuntimeDefault: false;
1536
+ enumValues: undefined;
1537
+ baseColumn: never;
1538
+ identity: undefined;
1539
+ generated: undefined;
1540
+ }, {}, {}>;
1541
+ orderId: drizzle_orm_pg_core.PgColumn<{
1542
+ name: "order_id";
1543
+ tableName: "commerce_discount_redemptions";
1544
+ dataType: "string";
1545
+ columnType: "PgUUID";
1546
+ data: string;
1547
+ driverParam: string;
1548
+ notNull: true;
1549
+ hasDefault: false;
1550
+ isPrimaryKey: false;
1551
+ isAutoincrement: false;
1552
+ hasRuntimeDefault: false;
1553
+ enumValues: undefined;
1554
+ baseColumn: never;
1555
+ identity: undefined;
1556
+ generated: undefined;
1557
+ }, {}, {}>;
1558
+ status: drizzle_orm_pg_core.PgColumn<{
1559
+ name: "status";
1560
+ tableName: "commerce_discount_redemptions";
1561
+ dataType: "string";
1562
+ columnType: "PgText";
1563
+ data: "released" | "committed" | "reserved";
1564
+ driverParam: string;
1565
+ notNull: true;
1566
+ hasDefault: true;
1567
+ isPrimaryKey: false;
1568
+ isAutoincrement: false;
1569
+ hasRuntimeDefault: false;
1570
+ enumValues: ["reserved", "committed", "released"];
1571
+ baseColumn: never;
1572
+ identity: undefined;
1573
+ generated: undefined;
1574
+ }, {}, {}>;
1575
+ amountCents: drizzle_orm_pg_core.PgColumn<{
1576
+ name: "amount_cents";
1577
+ tableName: "commerce_discount_redemptions";
1578
+ dataType: "number";
1579
+ columnType: "PgInteger";
1580
+ data: number;
1581
+ driverParam: string | number;
1582
+ notNull: true;
1583
+ hasDefault: false;
1584
+ isPrimaryKey: false;
1585
+ isAutoincrement: false;
1586
+ hasRuntimeDefault: false;
1587
+ enumValues: undefined;
1588
+ baseColumn: never;
1589
+ identity: undefined;
1590
+ generated: undefined;
1591
+ }, {}, {}>;
1592
+ createdAt: drizzle_orm_pg_core.PgColumn<{
1593
+ name: "created_at";
1594
+ tableName: "commerce_discount_redemptions";
1595
+ dataType: "date";
1596
+ columnType: "PgTimestamp";
1597
+ data: Date;
1598
+ driverParam: string;
1599
+ notNull: true;
1600
+ hasDefault: true;
1601
+ isPrimaryKey: false;
1602
+ isAutoincrement: false;
1603
+ hasRuntimeDefault: false;
1604
+ enumValues: undefined;
1605
+ baseColumn: never;
1606
+ identity: undefined;
1607
+ generated: undefined;
1608
+ }, {}, {}>;
1609
+ updatedAt: drizzle_orm_pg_core.PgColumn<{
1610
+ name: "updated_at";
1611
+ tableName: "commerce_discount_redemptions";
1612
+ dataType: "date";
1613
+ columnType: "PgTimestamp";
1614
+ data: Date;
1615
+ driverParam: string;
1616
+ notNull: true;
1617
+ hasDefault: true;
1618
+ isPrimaryKey: false;
1619
+ isAutoincrement: false;
1620
+ hasRuntimeDefault: false;
1621
+ enumValues: undefined;
1622
+ baseColumn: never;
1623
+ identity: undefined;
1624
+ generated: undefined;
1625
+ }, {}, {}>;
1626
+ };
1627
+ dialect: "pg";
1628
+ }>;
1241
1629
  };
1242
1630
  type CommerceSchema = typeof commerceSchema;
1243
1631
 
@@ -1290,6 +1678,11 @@ interface CreateCheckoutSessionInput {
1290
1678
  shippingCountries: string[];
1291
1679
  shippingRates: ShippingRateOption[];
1292
1680
  expiresAt: Date;
1681
+ discount?: CheckoutDiscount;
1682
+ }
1683
+ interface CheckoutDiscount {
1684
+ code: string;
1685
+ amountCents: number;
1293
1686
  }
1294
1687
  interface CheckoutSession {
1295
1688
  id: string;
@@ -1387,12 +1780,17 @@ interface CheckoutOptions {
1387
1780
  urls: CheckoutUrls;
1388
1781
  shippingCountries?: string[];
1389
1782
  hooks?: OrderHooks;
1783
+ devCheckout?: boolean | DevCheckoutSetting;
1784
+ }
1785
+ interface DevCheckoutSetting {
1786
+ apiUrl?: string;
1390
1787
  }
1391
1788
  interface CatalogOnlyOptions {
1392
1789
  payment?: undefined;
1393
1790
  urls?: undefined;
1394
1791
  shippingCountries?: undefined;
1395
1792
  hooks?: undefined;
1793
+ devCheckout?: undefined;
1396
1794
  }
1397
1795
  type CommercePluginOptions = {
1398
1796
  db: CommerceDb;
@@ -1427,6 +1825,8 @@ interface SignedWebhook {
1427
1825
  signature: string;
1428
1826
  }
1429
1827
  interface FakeGateway extends PaymentGateway {
1828
+ readonly kind: 'fake';
1829
+ useSessionUrl(build: (sessionId: string) => string): void;
1430
1830
  readonly sessions: (CreateCheckoutSessionInput & {
1431
1831
  id: string;
1432
1832
  })[];
@@ -1453,6 +1853,7 @@ interface FakeGatewayOptions {
1453
1853
  secret?: string;
1454
1854
  }
1455
1855
  declare function createFakeGateway({ secret, }?: FakeGatewayOptions): FakeGateway;
1856
+ declare function isFakeGateway(gateway: PaymentGateway): gateway is FakeGateway;
1456
1857
 
1457
1858
  interface HoldSweeperOptions {
1458
1859
  intervalMs?: number;
@@ -1463,6 +1864,42 @@ interface HoldSweeper {
1463
1864
  }
1464
1865
  declare function startHoldSweeper(db: CommerceDb, { intervalMs, onError }?: HoldSweeperOptions): HoldSweeper;
1465
1866
 
1867
+ interface EmailLine {
1868
+ label: string;
1869
+ amount: string;
1870
+ }
1871
+ interface OrderEmailLabels {
1872
+ subtotal: string;
1873
+ discount: (code: string | null) => string;
1874
+ shipping: (label: string | null) => string;
1875
+ total: string;
1876
+ }
1877
+ interface OrderEmailLinesOptions {
1878
+ locale?: string;
1879
+ labels?: Partial<OrderEmailLabels>;
1880
+ }
1881
+ interface OrderEmailLinesText {
1882
+ items: string;
1883
+ totals: string;
1884
+ address: string;
1885
+ }
1886
+ interface OrderEmailLinesHtml {
1887
+ items: string;
1888
+ totals: string;
1889
+ address: string;
1890
+ }
1891
+ interface OrderEmailLines {
1892
+ items: EmailLine[];
1893
+ subtotal: EmailLine;
1894
+ discount?: EmailLine;
1895
+ shipping: EmailLine;
1896
+ total: EmailLine;
1897
+ address?: string[];
1898
+ text: OrderEmailLinesText;
1899
+ html: OrderEmailLinesHtml;
1900
+ }
1901
+ declare function orderEmailLines(order: OrderDetail, options?: OrderEmailLinesOptions): OrderEmailLines;
1902
+
1466
1903
  declare function runCommerceMigrations(db: NodePgDatabase<any>): Promise<void>;
1467
1904
 
1468
1905
  interface SeedProduct {
@@ -1503,5 +1940,30 @@ interface MemoryStorage extends FileStorage {
1503
1940
  }
1504
1941
  declare function createMemoryStorage(baseUrl?: string): MemoryStorage;
1505
1942
 
1506
- export { ProductNotFoundError, SESSION_ID_PLACEHOLDER, WebhookSignatureError, catalogPlugin, commercePlugin, commerceSchema, createFakeGateway, createMemoryStorage, createStripeGateway, ordersPlugin, runCommerceMigrations, seedProducts, seedShippingRates, startHoldSweeper };
1507
- export type { AdminOptions, CatalogCacheOptions, CatalogPluginOptions, CategoryLabels, CheckoutLine, CheckoutSession, CheckoutUrls, ChosenShipping, CommerceDb, CommercePluginOptions, CommerceSchema, CreateCheckoutSessionInput, FakeGateway, FakeGatewayOptions, FileStorage, GatewayRefund, HoldSweeper, HoldSweeperOptions, MemoryStorage, OrderHooks, OrdersPluginOptions, PaymentEvent, PaymentGateway, RefundInput, SeedProduct, SeedShippingRate, ShippingAddress, ShippingRateOption, SignedWebhook, StoredFile, StripeGatewayOptions };
1943
+ interface DiskStorageOptions {
1944
+ dir: string;
1945
+ publicUrl: string;
1946
+ }
1947
+ interface StoredFileStream {
1948
+ stream: Readable;
1949
+ contentType: string | undefined;
1950
+ size: number;
1951
+ }
1952
+ declare function createDiskStorage(options: DiskStorageOptions): FileStorage;
1953
+ declare function openStoredFile(dir: string, key: string): Promise<StoredFileStream | null>;
1954
+
1955
+ interface PaymentEnv {
1956
+ NODE_ENV?: string;
1957
+ PAYMENT_GATEWAY?: string;
1958
+ STRIPE_SECRET_KEY?: string;
1959
+ STRIPE_WEBHOOK_SECRET?: string;
1960
+ }
1961
+ declare function resolvePayment(env?: PaymentEnv): PaymentGateway;
1962
+ interface CheckoutUrlPaths {
1963
+ successPath?: string;
1964
+ cancelPath?: string;
1965
+ }
1966
+ declare function checkoutUrls(webUrl: string, { successPath, cancelPath, }?: CheckoutUrlPaths): CheckoutUrls;
1967
+
1968
+ export { ProductNotFoundError, SESSION_ID_PLACEHOLDER, WebhookSignatureError, catalogPlugin, checkoutUrls, commercePlugin, commerceSchema, createDiskStorage, createFakeGateway, createMemoryStorage, createStripeGateway, isFakeGateway, openStoredFile, orderEmailLines, ordersPlugin, resolvePayment, runCommerceMigrations, seedProducts, seedShippingRates, startHoldSweeper };
1969
+ export type { AdminOptions, CatalogCacheOptions, CatalogPluginOptions, CategoryLabels, CheckoutDiscount, CheckoutLine, CheckoutSession, CheckoutUrlPaths, CheckoutUrls, ChosenShipping, CommerceDb, CommercePluginOptions, CommerceSchema, CreateCheckoutSessionInput, DevCheckoutSetting, DiskStorageOptions, EmailLine, FakeGateway, FakeGatewayOptions, FileStorage, GatewayRefund, HoldSweeper, HoldSweeperOptions, MemoryStorage, OrderEmailLabels, OrderEmailLines, OrderEmailLinesOptions, OrderHooks, OrdersPluginOptions, PaymentEnv, PaymentEvent, PaymentGateway, RefundInput, SeedProduct, SeedShippingRate, ShippingAddress, ShippingRateOption, SignedWebhook, StoredFile, StoredFileStream, StripeGatewayOptions };