@fayz-ai/shop 0.9.0 → 0.11.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 (163) hide show
  1. package/README.md +18 -1
  2. package/dist/admin.d.ts +2 -0
  3. package/dist/admin.d.ts.map +1 -0
  4. package/dist/catalog.d.ts +1 -3
  5. package/dist/catalog.d.ts.map +1 -1
  6. package/dist/catalog.js +2 -2
  7. package/dist/{chunk-IYQHKMLB.js → chunk-2WACO2TG.js} +4 -4
  8. package/dist/chunk-2WACO2TG.js.map +1 -0
  9. package/dist/chunk-3GERSY5F.js +526 -0
  10. package/dist/chunk-3GERSY5F.js.map +1 -0
  11. package/dist/chunk-6BO2TMZ5.js +93 -0
  12. package/dist/chunk-6BO2TMZ5.js.map +1 -0
  13. package/dist/chunk-FQPGE3YN.js +3 -0
  14. package/dist/{chunk-JR25TISO.js.map → chunk-FQPGE3YN.js.map} +1 -1
  15. package/dist/{chunk-CTKZ6O2J.js → chunk-IKNGCRUM.js} +41 -15
  16. package/dist/chunk-IKNGCRUM.js.map +1 -0
  17. package/dist/chunk-KLDS7IPU.js +17 -0
  18. package/dist/chunk-KLDS7IPU.js.map +1 -0
  19. package/dist/chunk-NWW3WJ7Y.js +136 -0
  20. package/dist/chunk-NWW3WJ7Y.js.map +1 -0
  21. package/dist/chunk-STRNMFC4.js +1438 -0
  22. package/dist/chunk-STRNMFC4.js.map +1 -0
  23. package/dist/chunk-U6HV3LVP.js +1170 -0
  24. package/dist/chunk-U6HV3LVP.js.map +1 -0
  25. package/dist/client.d.ts +2 -0
  26. package/dist/client.d.ts.map +1 -0
  27. package/dist/data/customer-search.d.ts +3 -0
  28. package/dist/data/customer-search.d.ts.map +1 -0
  29. package/dist/data/functions.d.ts +9 -0
  30. package/dist/data/functions.d.ts.map +1 -0
  31. package/dist/data/media.d.ts +37 -0
  32. package/dist/data/media.d.ts.map +1 -0
  33. package/dist/{mock-catalog.d.ts → data/mock-catalog.d.ts} +21 -1
  34. package/dist/data/mock-catalog.d.ts.map +1 -0
  35. package/dist/data/mock-provider.d.ts +165 -0
  36. package/dist/data/mock-provider.d.ts.map +1 -0
  37. package/dist/data/mock.d.ts +3 -0
  38. package/dist/data/mock.d.ts.map +1 -0
  39. package/dist/data/provider.d.ts +335 -0
  40. package/dist/data/provider.d.ts.map +1 -0
  41. package/dist/data/supabase-provider.d.ts +208 -0
  42. package/dist/data/supabase-provider.d.ts.map +1 -0
  43. package/dist/data/tables.d.ts +38 -0
  44. package/dist/data/tables.d.ts.map +1 -0
  45. package/dist/data/tenant.d.ts.map +1 -0
  46. package/dist/entities/entity-reconcile.d.ts +32 -0
  47. package/dist/entities/entity-reconcile.d.ts.map +1 -0
  48. package/dist/entities/entity-sql.d.ts +50 -0
  49. package/dist/entities/entity-sql.d.ts.map +1 -0
  50. package/dist/entities/entity-store.d.ts +58 -0
  51. package/dist/entities/entity-store.d.ts.map +1 -0
  52. package/dist/entities/index.d.ts +10 -0
  53. package/dist/entities/index.d.ts.map +1 -0
  54. package/dist/entities/mock-entity-store.d.ts +17 -0
  55. package/dist/entities/mock-entity-store.d.ts.map +1 -0
  56. package/dist/entities/supabase-entity-store.d.ts +8 -0
  57. package/dist/entities/supabase-entity-store.d.ts.map +1 -0
  58. package/dist/entities.js +159 -0
  59. package/dist/entities.js.map +1 -0
  60. package/dist/index.d.ts +28 -12
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1558 -40
  63. package/dist/index.js.map +1 -1
  64. package/dist/inventory/allocation.d.ts +98 -0
  65. package/dist/inventory/allocation.d.ts.map +1 -0
  66. package/dist/inventory/index.d.ts +13 -0
  67. package/dist/inventory/index.d.ts.map +1 -0
  68. package/dist/inventory/mock-stock-store.d.ts +89 -0
  69. package/dist/inventory/mock-stock-store.d.ts.map +1 -0
  70. package/dist/inventory/postgrest-double.d.ts +65 -0
  71. package/dist/inventory/postgrest-double.d.ts.map +1 -0
  72. package/dist/inventory/shopify-mapping.d.ts +67 -0
  73. package/dist/inventory/shopify-mapping.d.ts.map +1 -0
  74. package/dist/inventory/stock-contract.d.ts +46 -0
  75. package/dist/inventory/stock-contract.d.ts.map +1 -0
  76. package/dist/inventory/stock-store.d.ts +96 -0
  77. package/dist/inventory/stock-store.d.ts.map +1 -0
  78. package/dist/inventory/stock-types.d.ts +351 -0
  79. package/dist/inventory/stock-types.d.ts.map +1 -0
  80. package/dist/inventory/supabase-stock-store.d.ts +60 -0
  81. package/dist/inventory/supabase-stock-store.d.ts.map +1 -0
  82. package/dist/inventory/vocabulary.d.ts +86 -0
  83. package/dist/inventory/vocabulary.d.ts.map +1 -0
  84. package/dist/inventory.js +4 -0
  85. package/dist/inventory.js.map +1 -0
  86. package/dist/lib/catalog.d.ts +4 -0
  87. package/dist/lib/catalog.d.ts.map +1 -0
  88. package/dist/{commerce.d.ts → lib/commerce.d.ts} +2 -2
  89. package/dist/lib/commerce.d.ts.map +1 -0
  90. package/dist/lib/document.d.ts +13 -0
  91. package/dist/lib/document.d.ts.map +1 -0
  92. package/dist/lib/emails.d.ts +50 -0
  93. package/dist/lib/emails.d.ts.map +1 -0
  94. package/dist/lib/message-events.d.ts +4 -0
  95. package/dist/lib/message-events.d.ts.map +1 -0
  96. package/dist/lib/runtime.d.ts +5 -0
  97. package/dist/lib/runtime.d.ts.map +1 -0
  98. package/dist/lib/variant-matrix.d.ts +120 -0
  99. package/dist/lib/variant-matrix.d.ts.map +1 -0
  100. package/dist/mock.d.ts +1 -2
  101. package/dist/mock.d.ts.map +1 -1
  102. package/dist/mock.js +4 -2
  103. package/dist/provider.d.ts +1 -88
  104. package/dist/provider.d.ts.map +1 -1
  105. package/dist/providers/checkout.d.ts +129 -0
  106. package/dist/providers/checkout.d.ts.map +1 -0
  107. package/dist/providers/index.d.ts +5 -0
  108. package/dist/providers/index.d.ts.map +1 -0
  109. package/dist/providers/shipping.d.ts +43 -0
  110. package/dist/providers/shipping.d.ts.map +1 -0
  111. package/dist/providers.js +70 -0
  112. package/dist/providers.js.map +1 -0
  113. package/dist/rules/adapter.d.ts +36 -0
  114. package/dist/rules/adapter.d.ts.map +1 -0
  115. package/dist/rules/attributes.d.ts +64 -0
  116. package/dist/rules/attributes.d.ts.map +1 -0
  117. package/dist/rules/context.d.ts +43 -0
  118. package/dist/rules/context.d.ts.map +1 -0
  119. package/dist/rules/evaluator.d.ts +37 -0
  120. package/dist/rules/evaluator.d.ts.map +1 -0
  121. package/dist/rules/index.d.ts +13 -0
  122. package/dist/rules/index.d.ts.map +1 -0
  123. package/dist/rules/prices.d.ts +25 -0
  124. package/dist/rules/prices.d.ts.map +1 -0
  125. package/dist/rules/rule-types.d.ts +160 -0
  126. package/dist/rules/rule-types.d.ts.map +1 -0
  127. package/dist/rules.js +22 -0
  128. package/dist/rules.js.map +1 -0
  129. package/dist/runtime.d.ts +1 -4
  130. package/dist/runtime.d.ts.map +1 -1
  131. package/dist/runtime.js +5 -3
  132. package/dist/shipping/label-provider.d.ts +43 -0
  133. package/dist/shipping/label-provider.d.ts.map +1 -0
  134. package/dist/types.d.ts +688 -0
  135. package/dist/types.d.ts.map +1 -1
  136. package/package.json +30 -20
  137. package/dist/chunk-CTKZ6O2J.js.map +0 -1
  138. package/dist/chunk-IYQHKMLB.js.map +0 -1
  139. package/dist/chunk-JR25TISO.js +0 -3
  140. package/dist/chunk-SVTCJ6HP.js +0 -440
  141. package/dist/chunk-SVTCJ6HP.js.map +0 -1
  142. package/dist/commerce.d.ts.map +0 -1
  143. package/dist/mock-catalog.d.ts.map +0 -1
  144. package/dist/mock-provider.d.ts +0 -60
  145. package/dist/mock-provider.d.ts.map +0 -1
  146. package/dist/supabase-provider.d.ts +0 -56
  147. package/dist/supabase-provider.d.ts.map +0 -1
  148. package/dist/tables.d.ts +0 -12
  149. package/dist/tables.d.ts.map +0 -1
  150. package/dist/tenant.d.ts.map +0 -1
  151. package/src/catalog.ts +0 -3
  152. package/src/commerce.ts +0 -120
  153. package/src/index.ts +0 -40
  154. package/src/mock-catalog.ts +0 -266
  155. package/src/mock-provider.ts +0 -480
  156. package/src/mock.ts +0 -2
  157. package/src/provider.ts +0 -117
  158. package/src/runtime.ts +0 -20
  159. package/src/supabase-provider.ts +0 -754
  160. package/src/tables.ts +0 -17
  161. package/src/tenant.ts +0 -21
  162. package/src/types.ts +0 -623
  163. /package/dist/{tenant.d.ts → data/tenant.d.ts} +0 -0
package/dist/types.d.ts CHANGED
@@ -1,4 +1,13 @@
1
1
  export type ProductStatus = 'draft' | 'active' | 'archived';
2
+ /**
3
+ * A handling requirement declared on a product (0048).
4
+ *
5
+ * This is a DECLARATION, not a guarantee: it is what travels to whoever carries
6
+ * the parcel — a carrier's refrigerated service, a motoboy, or the merchant's
7
+ * own car. What RESTRICTS who may carry it is the product's shipping profile
8
+ * (0049), not this list — this one only travels.
9
+ */
10
+ export type HandlingRequirement = 'refrigerated' | 'frozen' | 'fragile';
2
11
  export interface Product {
3
12
  id: string;
4
13
  tenantId: string;
@@ -16,11 +25,133 @@ export interface Product {
16
25
  images: ProductImage[];
17
26
  categoryId: string | null;
18
27
  categoryName: string | null;
28
+ /** False keeps the product out of the freight calculation entirely (0001,
29
+ * finally read in FAY-1407). */
19
30
  isPhysical: boolean;
20
31
  weight: number | null;
32
+ /** The unit `weight` is in. Honoured by the packing code — it is not
33
+ * decoration, and a catalogue in grams quoted as kg is a thousandfold error. */
21
34
  weightUnit: string;
35
+ /** Centimetres (0044b/0046). Null is "not measured", which degrades the cart
36
+ * to the store's default package rather than inventing a size. */
37
+ heightCm?: number | null;
38
+ widthCm?: number | null;
39
+ lengthCm?: number | null;
40
+ /**
41
+ * Em que embalagem da loja este produto vai (0047). NULL = a padrão da
42
+ * loja, que é o estado de todo produto no dia da aplicação. Aponta para
43
+ * plg_shop_packages; a medida está lá, não aqui.
44
+ */
45
+ packageId?: string | null;
46
+ /**
47
+ * What the box needs from whoever carries it (0048). Empty is "nothing
48
+ * declared", which is how every catalogue starts.
49
+ *
50
+ * On the PRODUCT and not the variant on purpose: needing cold is a property of
51
+ * what is inside, and a chocolate melts in all three sizes. Weight and
52
+ * dimensions live on the variant because those genuinely differ.
53
+ *
54
+ * Optional and not `HandlingRequirement[]`: eleven apps build Product literals
55
+ * from source, and a required field on a shared interface makes a declaration
56
+ * nobody asked for into a build break in every one of them. The live provider
57
+ * always returns an array, so a reader may treat `undefined` as empty.
58
+ */
59
+ handling?: HandlingRequirement[];
60
+ /** Which delivery profile ships this product (0049). Undefined = the general
61
+ * one, which is every product nobody has moved. */
62
+ shippingProfileId?: string | null;
22
63
  createdAt: string;
23
64
  updatedAt: string;
65
+ /**
66
+ * Option axes from the variant tables (0028), position-ordered — present
67
+ * when the read path fetched them (products.bySlug attaches them via
68
+ * ShopProvider.getProductVariants). Undefined means "not fetched", NOT
69
+ * "no options": list reads skip variants on purpose.
70
+ */
71
+ options?: ProductOption[];
72
+ /** Sellable variants (0028), present under the same conditions as `options`. */
73
+ variants?: ProductVariant[];
74
+ }
75
+ /**
76
+ * One option axis of a product ('Tamanho' → ['P','M','G']). Mirrors
77
+ * plg_shop_product_options: the axis `name` is also the key used inside each
78
+ * variant's `options` object — that is what ties the two together.
79
+ */
80
+ export interface ProductOption {
81
+ id: string;
82
+ name: string;
83
+ /** Ordered values for the picker (P before M before G is not alphabetical). */
84
+ values: string[];
85
+ position: number;
86
+ }
87
+ /**
88
+ * The sellable unit once a product has option axes. Mirrors
89
+ * plg_shop_product_variants: `price` null inherits the product price;
90
+ * inventory is per-variant (two sizes never share a counter again).
91
+ */
92
+ export interface ProductVariant {
93
+ id: string;
94
+ productId: string;
95
+ /** The combination this variant IS, e.g. {"Tamanho":"P","Cor":"Azul"}. */
96
+ options: Record<string, string>;
97
+ sku: string | null;
98
+ /** Null inherits the product's price. */
99
+ price: number | null;
100
+ compareAtPrice: number | null;
101
+ inventoryCount: number;
102
+ position: number;
103
+ status: 'active' | 'archived';
104
+ /** Variant-specific photo; null falls back to the product's primary image. */
105
+ imageId: string | null;
106
+ /**
107
+ * 0037's placeholder sellable unit for a product that declares no axes. MUST
108
+ * BE INVISIBLE to the merchant — no row in the variant grid, no options label.
109
+ */
110
+ isDefaultVariant?: boolean;
111
+ /**
112
+ * Shipping measurements (0046). Null inherits the product's, exactly like
113
+ * `price` — a camiseta P and a GG do not occupy the same box, and a
114
+ * catalogue where every size weighs the same is measured once, on the
115
+ * product, and never again.
116
+ */
117
+ weight?: number | null;
118
+ weightUnit?: string | null;
119
+ heightCm?: number | null;
120
+ widthCm?: number | null;
121
+ lengthCm?: number | null;
122
+ }
123
+ /** What ShopProvider.getProductVariants answers for one product. */
124
+ export interface ProductVariantSet {
125
+ options: ProductOption[];
126
+ variants: ProductVariant[];
127
+ }
128
+ /** One axis as the admin submits it. Order of `values` is the picker's order. */
129
+ export interface ProductOptionInput {
130
+ name: string;
131
+ values: string[];
132
+ }
133
+ /**
134
+ * The variant fields the admin owns. `inventoryCount` is deliberately ABSENT:
135
+ * since 0034 stock is a ledger and since 0036 `inventory_count` is its mirror,
136
+ * so a write here would be a second truth. Stock moves through
137
+ * ShopProvider.setVariantStock, which appends a movement.
138
+ */
139
+ export interface UpdateProductVariantInput {
140
+ sku?: string | null;
141
+ price?: number | null;
142
+ compareAtPrice?: number | null;
143
+ position?: number;
144
+ status?: 'active' | 'archived';
145
+ imageId?: string | null;
146
+ weight?: number | null;
147
+ weightUnit?: string | null;
148
+ heightCm?: number | null;
149
+ widthCm?: number | null;
150
+ lengthCm?: number | null;
151
+ }
152
+ export interface CreateProductVariantInput extends UpdateProductVariantInput {
153
+ /** The combination this variant IS. Empty is refused — that shape is 0037's. */
154
+ options: Record<string, string>;
24
155
  }
25
156
  export interface ProductImage {
26
157
  id: string;
@@ -47,6 +178,12 @@ export interface CreateProductInput {
47
178
  isPhysical?: boolean;
48
179
  weight?: number;
49
180
  weightUnit?: string;
181
+ heightCm?: number | null;
182
+ widthCm?: number | null;
183
+ lengthCm?: number | null;
184
+ packageId?: string | null;
185
+ handling?: HandlingRequirement[];
186
+ shippingProfileId?: string | null;
50
187
  }
51
188
  export interface UpdateProductInput {
52
189
  name?: string;
@@ -64,6 +201,12 @@ export interface UpdateProductInput {
64
201
  isPhysical?: boolean;
65
202
  weight?: number | null;
66
203
  weightUnit?: string;
204
+ heightCm?: number | null;
205
+ widthCm?: number | null;
206
+ lengthCm?: number | null;
207
+ packageId?: string | null;
208
+ handling?: HandlingRequirement[];
209
+ shippingProfileId?: string | null;
67
210
  }
68
211
  export interface ListProductsOptions {
69
212
  status?: ProductStatus;
@@ -167,9 +310,25 @@ export interface Order {
167
310
  paymentMethodKind: PaymentMethodKind | null;
168
311
  paidAt: string | null;
169
312
  items: OrderItem[];
313
+ /**
314
+ * What the buyer needs to follow the box (0052). Only `getOrder` fills it —
315
+ * on a list, `[]` means "not asked for" as much as "nothing shipped".
316
+ */
317
+ shipments?: OrderShipment[];
170
318
  createdAt: string;
171
319
  updatedAt: string;
172
320
  }
321
+ /** One non-cancelled shipment, as the buyer's own window returns it. */
322
+ export interface OrderShipment {
323
+ id: string;
324
+ status: string;
325
+ carrier: string | null;
326
+ trackingCode: string | null;
327
+ trackingUrl: string | null;
328
+ shippedAt: string | null;
329
+ estimatedDeliveryAt: string | null;
330
+ deliveredAt: string | null;
331
+ }
173
332
  export interface OrderItem {
174
333
  id: string;
175
334
  orderId: string;
@@ -223,6 +382,13 @@ export interface ListOrdersOptions {
223
382
  export interface PlaceOrderLine {
224
383
  productId: string;
225
384
  quantity: number;
385
+ /**
386
+ * Variant to sell (0028/0029). When present the server prices the line from
387
+ * the variant, checks and decrements the VARIANT's stock, and derives the
388
+ * options label from the variant's combination. Absent = the product-level
389
+ * path, unchanged.
390
+ */
391
+ variantId?: string;
226
392
  /** Variant/options label appended to the stored item name (display only). */
227
393
  optionsLabel?: string;
228
394
  }
@@ -245,8 +411,125 @@ export interface ShippingAddressInput {
245
411
  recipient?: string;
246
412
  phone?: string;
247
413
  label?: string;
414
+ /**
415
+ * CPF/CNPJ of whoever is buying — digits only. It is NOT part of the address:
416
+ * it travels here because shop_place_order cannot grow a parameter without a
417
+ * DROP, and 0050's BEFORE INSERT trigger lifts it into
418
+ * plg_shop_orders.customer_document and removes it from the stored jsonb.
419
+ * Read the column, never this field.
420
+ */
421
+ document?: string;
248
422
  }
249
423
  export type PaymentMethodKind = 'pix' | 'credit_card' | 'debit_card' | 'boleto' | 'cash' | 'other';
424
+ export interface CreateFulfillmentInput {
425
+ orderId: string;
426
+ /** Free text: the merchant's own courier is as valid as a named carrier. */
427
+ carrier?: string;
428
+ /** With one, the shipment is already in transit; without, it is picking. */
429
+ trackingCode?: string;
430
+ locationId?: string;
431
+ notes?: string;
432
+ /** Partial shipment. Omitted means everything still outstanding. */
433
+ items?: Array<{
434
+ orderItemId: string;
435
+ quantity: number;
436
+ }>;
437
+ }
438
+ export interface ShipFulfillmentInput {
439
+ trackingCode?: string;
440
+ trackingUrl?: string;
441
+ carrier?: string;
442
+ }
443
+ /**
444
+ * O carrinho congelado enquanto o comprador paga.
445
+ *
446
+ * Existe porque o pedido passou a nascer DEPOIS do pagamento. Entre "escolhi
447
+ * pagar" e "paguei" não há pedido nenhum — há esta sessão, com os preços que o
448
+ * SERVIDOR recalculou, e é dela que o pedido é criado quando o dinheiro entra.
449
+ */
450
+ export interface CheckoutSessionInput {
451
+ items: Array<{
452
+ productId: string;
453
+ variantId?: string | null;
454
+ quantity: number;
455
+ optionsLabel?: string | null;
456
+ }>;
457
+ customer: {
458
+ name?: string | null;
459
+ email: string;
460
+ };
461
+ shippingAddress?: ShippingAddressInput;
462
+ discountCode?: string | null;
463
+ paymentMethod?: PaymentMethodKind;
464
+ }
465
+ export interface CheckoutSession {
466
+ sessionId: string;
467
+ /** Recalculado no servidor. O navegador exibe; nunca decide. */
468
+ total: number;
469
+ charge: PaymentCharge | null;
470
+ state: 'open' | 'paid' | 'failed' | 'expired';
471
+ }
472
+ /** `orderId` só aparece quando o pagamento entrou — é ele que prova a compra. */
473
+ export interface CheckoutSettlement {
474
+ /** `pending` is what the acquirer answers while the buyer still has the QR
475
+ * code open — the ordinary case, and the one a caller must never read as a
476
+ * refusal. Only `failed`, `expired` and `cancelled` end the wait. */
477
+ state: 'open' | 'pending' | 'paid' | 'failed' | 'expired' | 'cancelled' | 'unknown';
478
+ orderId?: string | null;
479
+ reason?: string | null;
480
+ }
481
+ /** A carrier label, from quote to tracking. `labelUrl` is a PDF the merchant prints. */
482
+ export interface ShippingLabelOption {
483
+ serviceId: number;
484
+ name: string;
485
+ carrier: string;
486
+ price: number;
487
+ etaMinDays?: number | null;
488
+ etaMaxDays?: number | null;
489
+ }
490
+ /** A carrier drop-off point, as a settings screen lists it. */
491
+ export interface ShippingAgency {
492
+ id: string;
493
+ name: string;
494
+ city: string;
495
+ state: string;
496
+ address: string;
497
+ /** Carrier service ids this one accepts — a choice that hides them is a
498
+ * choice the merchant discovers is wrong at the first dispatch. */
499
+ services: string[];
500
+ }
501
+ export interface ShippingLabel {
502
+ labelId: string;
503
+ labelUrl?: string | null;
504
+ status?: string | null;
505
+ tracking?: {
506
+ code: string | null;
507
+ status: string | null;
508
+ url: string | null;
509
+ } | null;
510
+ }
511
+ /** What a connected acquirer can be asked to open. Card waits for hosted fields. */
512
+ export type PaymentChargeMethod = 'pix';
513
+ /**
514
+ * A charge the buyer can act on. `qrcodeBase64` is a bare base64 PNG — no
515
+ * `data:` prefix — because that is how the provider returns it.
516
+ */
517
+ export interface PaymentCharge {
518
+ emv: string;
519
+ qrcodeBase64: string | null;
520
+ expiresAt: string;
521
+ }
522
+ /**
523
+ * `unopened` is not an error: the page may ask for the state before the charge
524
+ * call has returned. `failed` is the provider's final no.
525
+ */
526
+ export interface PaymentChargeResult {
527
+ state: 'pending' | 'paid' | 'refunded' | 'failed' | 'unopened';
528
+ orderId: string;
529
+ reference?: string | null;
530
+ charge?: PaymentCharge | null;
531
+ providerStatus?: string | null;
532
+ }
250
533
  /**
251
534
  * A range of postal codes the store delivers to, with its own price and ETA.
252
535
  *
@@ -268,9 +551,208 @@ export interface ShippingZone {
268
551
  etaMaxDays?: number | null;
269
552
  active: boolean;
270
553
  sortOrder: number;
554
+ /**
555
+ * A zone the store REFUSES (0048) — "não entrego aqui", by any means.
556
+ *
557
+ * It beats every other zone covering the same postcode and it beats a carrier
558
+ * quote, because the refusal is about the store and not about who carries the
559
+ * parcel. Enforced server-side on the order, so a direct POST cannot get
560
+ * around it. `rate` and the ETA are ignored on an excluded zone.
561
+ *
562
+ * Not-cadastrar is a different thing: a broad zone covering a whole region
563
+ * already accepts the street the merchant wants to avoid, and there was no way
564
+ * to carve an exception out of it.
565
+ */
566
+ excluded: boolean;
567
+ /** Which profile owns this range (0049). Undefined = the general profile. */
568
+ profileId?: string | null;
271
569
  }
272
570
  export type CreateShippingZoneInput = Omit<ShippingZone, 'id' | 'tenantId'>;
273
571
  export type UpdateShippingZoneInput = Partial<CreateShippingZoneInput>;
572
+ export type ShippingPackageKind = 'box' | 'envelope' | 'soft';
573
+ /**
574
+ * A box the store actually owns (plg_shop_packages, 0046).
575
+ *
576
+ * The freight engine picks the SMALLEST of these the cart fits in and adds
577
+ * `emptyWeightGrams` to what the carrier weighs. Before this cadastro existed
578
+ * the box was a constant in the edge function — 4×16×20cm for every store —
579
+ * and the difference between the quote and the label came out of the
580
+ * merchant's margin.
581
+ *
582
+ * `isDefault` is the box a cart falls back to when some item has no
583
+ * measurements. That fallback used to be the constant; it is data now.
584
+ */
585
+ export interface ShippingPackage {
586
+ id: string;
587
+ tenantId: string;
588
+ name: string;
589
+ kind: ShippingPackageKind;
590
+ heightCm: number;
591
+ widthCm: number;
592
+ lengthCm: number;
593
+ /** Grams, because that is how a merchant reads a carton's own weight. */
594
+ emptyWeightGrams: number;
595
+ isDefault: boolean;
596
+ active: boolean;
597
+ }
598
+ export type CreateShippingPackageInput = Omit<ShippingPackage, 'id' | 'tenantId'>;
599
+ export type UpdateShippingPackageInput = Partial<CreateShippingPackageInput>;
600
+ /**
601
+ * A named group of products with its own delivery zones (0049).
602
+ *
603
+ * The general mechanism behind "estes produtos vão de outro jeito", copied from
604
+ * Shopify's shipping profiles: refrigerated, fragile, oversized and made-to-order
605
+ * are all the same shape — a set of products the store ships differently — and
606
+ * modelling them one column at a time is how a settings screen ends up with four
607
+ * radios that each answer one merchant's question.
608
+ *
609
+ * INHERITANCE is by NULL on both ends: a product with no profile uses the
610
+ * general one, and a zone with no profile belongs to the general one. That is
611
+ * what lets this ship without migrating a single existing product or zone.
612
+ */
613
+ export interface ShippingProfile {
614
+ id: string;
615
+ tenantId: string;
616
+ name: string;
617
+ /**
618
+ * Whether a freight gateway may quote for the products in this profile.
619
+ *
620
+ * Undefined inherits `StoreSettings.carrierQuotes`. `false` is what replaces
621
+ * the old cold-chain policy: these products leave only through the zones the
622
+ * store declared itself. In a cart that mixes profiles the most restrictive one
623
+ * wins — otherwise "these do not go by truck" would be undone by adding a mug.
624
+ */
625
+ carrierQuotes?: boolean;
626
+ /** The general profile, so the screen has somewhere to hang unprofiled zones. */
627
+ isDefault: boolean;
628
+ }
629
+ export type CreateShippingProfileInput = Omit<ShippingProfile, 'id' | 'tenantId'>;
630
+ export type UpdateShippingProfileInput = Partial<CreateShippingProfileInput>;
631
+ /**
632
+ * The store-wide delivery fallback (public.shipping_settings, 0015).
633
+ *
634
+ * A zone always wins over this. It is what a store charges for an address no
635
+ * zone covers — and for a store that has declared no zone at all, which is how
636
+ * most start. A tenant with no row at all charges nothing, which is the safe
637
+ * default: inventing a freight nobody configured is worse than free delivery.
638
+ */
639
+ export interface ShippingSettings {
640
+ flatRate: number;
641
+ /** Subtotal (after discount) at or above which delivery is free. */
642
+ freeAbove?: number | null;
643
+ currency: string;
644
+ }
645
+ export type UpdateShippingSettingsInput = Partial<ShippingSettings>;
646
+ /**
647
+ * Per-field checkout policy. Keyed by the form field the storefront renders.
648
+ *
649
+ * A record rather than columns because the SET OF FIELDS is the variable part:
650
+ * a store selling downloads has no use for a district, and the next storefront
651
+ * will want one nobody has thought of. `visible: false` implies not required —
652
+ * a field nobody can see cannot be filled in.
653
+ */
654
+ export type CheckoutFieldKey = 'name' | 'email' | 'phone' | 'document' | 'street' | 'number' | 'complement' | 'district' | 'city' | 'state' | 'postalCode';
655
+ export interface CheckoutFieldPolicy {
656
+ visible?: boolean;
657
+ required?: boolean;
658
+ }
659
+ /**
660
+ * The store's commercial policy — what plg_shop_settings holds (0044b).
661
+ *
662
+ * Every field is OPTIONAL and `undefined` means NOT DECIDED, which is a
663
+ * different thing from a false or an empty list: not-decided keeps whatever the
664
+ * app declared in its StorefrontConfig, while `paymentMethods: []` would be a
665
+ * merchant who accepts nothing. That distinction is what lets this ship to eight
666
+ * live storefronts without changing any of them on deploy day.
667
+ *
668
+ * Two of these are enforced SERVER-SIDE by a trigger (`paymentMethods`,
669
+ * `guestCheckout`); the rest are read by the storefront. The docs on each say
670
+ * which, because "the checkbox is off" and "the server refuses" are promises of
671
+ * very different strength.
672
+ */
673
+ export interface StoreSettings {
674
+ /** Vitrine display. Undefined = the app's own currency/locale. */
675
+ currency?: string;
676
+ locale?: string;
677
+ showOutOfStock?: boolean;
678
+ /** Admin-side: makes SKU mandatory on the product form. Not a storefront rule. */
679
+ requireSku?: boolean;
680
+ /** ERP ownership of stock (0029). 'external' means a connector owns the numbers. */
681
+ stockOwnership?: 'internal' | 'external';
682
+ /** What the checkout may offer. ENFORCED: an order naming a method outside
683
+ * this list is refused by the server, not merely hidden by the form. */
684
+ paymentMethods?: PaymentMethodKind[];
685
+ /** Which connected gateway charges, when more than one is connected. The id of
686
+ * a ConnectorDefinition ('appmax'), never a credential. */
687
+ paymentProvider?: string;
688
+ /** ENFORCED: a storefront order with no account-linked customer is refused
689
+ * when this is explicitly false. */
690
+ guestCheckout?: boolean;
691
+ /** Storefront-side only — confirming an e-mail is a fact about the auth
692
+ * provider, not about the order, so the server does not police it. */
693
+ requireConfirmedEmail?: boolean;
694
+ marketingOptIn?: boolean;
695
+ discountsEnabled?: boolean;
696
+ checkoutFields?: Partial<Record<CheckoutFieldKey, CheckoutFieldPolicy>>;
697
+ /** 'never' — every shipment is created by hand. 'on_payment' — one is created
698
+ * when the payment is confirmed. 'always' — when the order is placed. */
699
+ autoFulfill?: 'never' | 'on_payment' | 'always';
700
+ notifyNewOrder?: boolean;
701
+ notifyLowStock?: boolean;
702
+ /**
703
+ * A declaração que viaja com o pedido — para você, para o motoboy, e na
704
+ * observação da etiqueta. Nunca mostrada ao comprador.
705
+ *
706
+ * Onde ficou a política de frio: num PERFIL DE ENTREGA (0049). "Refrigerado só
707
+ * sai no meu carro" é uma frase sobre logística, e uma coluna de três valores
708
+ * só respondia por temperatura — a loja seguinte pede o mesmo para frágil, para
709
+ * volumoso, para sob encomenda. Um perfil atende os quatro sem código novo.
710
+ */
711
+ /**
712
+ * Whether a freight GATEWAY may quote for this store (0048).
713
+ *
714
+ * Melhor Envio is not a carrier — it is a gateway that brings Correios,
715
+ * Jadlog, Loggi and others behind one connection. So the store's question is
716
+ * not "which carrier" but WHO CALCULATES: the merchant, from her zones, or a
717
+ * gateway, from the shopper's postcode.
718
+ *
719
+ * `false` = the merchant calculates, and no gateway is asked even if one is
720
+ * connected. Undefined = not decided, which behaves as today (ask if
721
+ * connected). It has to be storable rather than inferred from "no connection":
722
+ * the day someone connects a gateway in this app, a store that dispatches by
723
+ * hand would start receiving carrier prices it never chose — and 0044b makes a
724
+ * gateway quote WIN over the zones when it answers.
725
+ */
726
+ carrierQuotes?: boolean;
727
+ /**
728
+ * The note that travels with the parcel ("caixa térmica com gelo, entregar em
729
+ * até 24h"). Admin-side and carrier-side only — never shown to the shopper,
730
+ * which is why `shop_store_settings()` does not return it.
731
+ */
732
+ handlingNote?: string;
733
+ }
734
+ export type UpdateStoreSettingsInput = Partial<StoreSettings>;
735
+ /**
736
+ * The answer to "does this store deliver to this postcode?" (0048,
737
+ * `shop_delivery_check`), asked with the address and BEFORE the card.
738
+ *
739
+ * Two separate facts, because they are not the same question:
740
+ * · `refused` — an exclusion zone covers it. A no from the store, true even
741
+ * where a carrier would happily deliver.
742
+ * · `ownZone` — a zone of the store's own covers it. What tells "our car"
743
+ * from "a gateway", and what a shipping profile with the gateway off (0049)
744
+ * narrows a product to.
745
+ *
746
+ * Deliberately NOT "is there freight": that is `quoteShipping`, which also
747
+ * consults a carrier. Answering both here would tell every carrier-only store
748
+ * that it does not deliver anywhere.
749
+ */
750
+ export interface DeliveryCheck {
751
+ refused: boolean;
752
+ /** The exclusion zone's name, so the shopper reads a reason and not an error. */
753
+ refusedZone?: string | null;
754
+ ownZone: boolean;
755
+ }
274
756
  /**
275
757
  * One delivery option for a postal code, as quoted by shop_quote_shipping.
276
758
  *
@@ -345,6 +827,12 @@ export interface PlaceOrderInput {
345
827
  shippingAddress?: ShippingAddressInput;
346
828
  /** How the buyer is paying. Opens the ledger row in public.transactions. */
347
829
  paymentMethod?: PaymentMethodKind;
830
+ /**
831
+ * Machine-readable metadata stamped on the order, namespaced by contributor
832
+ * (spine M7's order.metadata extension point). Persisted by providers that
833
+ * support it (0029's plg_shop_orders.metadata); others may ignore it.
834
+ */
835
+ metadata?: Record<string, unknown>;
348
836
  items: PlaceOrderLine[];
349
837
  }
350
838
  export interface ShopCustomer {
@@ -354,6 +842,10 @@ export interface ShopCustomer {
354
842
  lastName: string;
355
843
  email: string | null;
356
844
  phone: string | null;
845
+ /** CPF/CNPJ, digits only. The person's, not the order's — an invoice issued
846
+ * months later needs the document that was valid on the day it is issued,
847
+ * and the order keeps its own frozen copy for that. */
848
+ document?: string | null;
357
849
  notes: string | null;
358
850
  ordersCount: number;
359
851
  totalSpent: number;
@@ -365,6 +857,7 @@ export interface CreateCustomerInput {
365
857
  lastName?: string;
366
858
  email?: string;
367
859
  phone?: string;
860
+ document?: string;
368
861
  notes?: string;
369
862
  }
370
863
  export interface UpdateCustomerInput {
@@ -372,6 +865,7 @@ export interface UpdateCustomerInput {
372
865
  lastName?: string;
373
866
  email?: string | null;
374
867
  phone?: string | null;
868
+ document?: string | null;
375
869
  notes?: string | null;
376
870
  }
377
871
  export interface ListCustomersOptions {
@@ -530,4 +1024,198 @@ export interface CartTotals {
530
1024
  shippingTotal: number;
531
1025
  total: number;
532
1026
  }
1027
+ export type EmailEventKey = 'order_confirmation' | 'order_paid' | 'order_shipped' | 'order_delivered' | 'order_cancelled' | 'refund_confirmation' | 'customer_welcome' | 'abandoned_cart';
1028
+ /** Transacional responde a um ato do cliente; marketing é iniciativa da loja —
1029
+ * e é a distinção que decide se o envio precisa de consentimento. */
1030
+ export type EmailTemplateKind = 'transactional' | 'marketing';
1031
+ export interface EmailTemplate {
1032
+ id: string;
1033
+ tenantId: string;
1034
+ event: EmailEventKey;
1035
+ /** Ligado. Null = usar o `defaultEnabled` do catálogo — a mesma regra de
1036
+ * subject/body. Sem isso, salvar só o TEXTO de um modelo nunca tocado
1037
+ * gravava `false` e desligava o e-mail sem ninguém pedir. */
1038
+ enabled: boolean | null;
1039
+ /** Assunto. Null = usar o padrão que o SDK define para este evento. */
1040
+ subject: string | null;
1041
+ /** Corpo. Null = usar o padrão. */
1042
+ body: string | null;
1043
+ updatedAt: string;
1044
+ }
1045
+ export interface UpsertEmailTemplateInput {
1046
+ event: EmailEventKey;
1047
+ /** Omitir = não mexer no estado atual. Null = voltar ao padrão do catálogo. */
1048
+ enabled?: boolean | null;
1049
+ subject?: string | null;
1050
+ body?: string | null;
1051
+ }
1052
+ export interface CustomerGroup {
1053
+ id: string;
1054
+ tenantId: string;
1055
+ name: string;
1056
+ description: string | null;
1057
+ /** Chip colour in the admin. Null = default neutral. */
1058
+ color: string | null;
1059
+ /** Members, cheapest shape — counts and chips without a customer join. */
1060
+ customerIds: string[];
1061
+ createdAt: string;
1062
+ updatedAt: string;
1063
+ }
1064
+ export interface CreateCustomerGroupInput {
1065
+ name: string;
1066
+ description?: string | null;
1067
+ color?: string | null;
1068
+ customerIds?: string[];
1069
+ }
1070
+ export type UpdateCustomerGroupInput = Partial<CreateCustomerGroupInput>;
1071
+ /**
1072
+ * A segment's rule, as explicit columns rather than opaque JSON: every
1073
+ * criterion here is one the customer list can actually evaluate, so a saved
1074
+ * segment always has a real, checkable membership. A free-form rule blob would
1075
+ * let the admin store conditions nothing knows how to answer.
1076
+ *
1077
+ * All criteria are AND-ed. Every field null = matches everyone.
1078
+ */
1079
+ export interface CustomerSegment {
1080
+ id: string;
1081
+ tenantId: string;
1082
+ name: string;
1083
+ description: string | null;
1084
+ minOrders: number | null;
1085
+ maxOrders: number | null;
1086
+ minSpent: number | null;
1087
+ maxSpent: number | null;
1088
+ /** ISO date — customer joined on or after this day. */
1089
+ joinedAfter: string | null;
1090
+ joinedBefore: string | null;
1091
+ createdAt: string;
1092
+ updatedAt: string;
1093
+ }
1094
+ export interface CreateCustomerSegmentInput {
1095
+ name: string;
1096
+ description?: string | null;
1097
+ minOrders?: number | null;
1098
+ maxOrders?: number | null;
1099
+ minSpent?: number | null;
1100
+ maxSpent?: number | null;
1101
+ joinedAfter?: string | null;
1102
+ joinedBefore?: string | null;
1103
+ }
1104
+ export type UpdateCustomerSegmentInput = Partial<CreateCustomerSegmentInput>;
1105
+ export interface Collection {
1106
+ id: string;
1107
+ tenantId: string;
1108
+ title: string;
1109
+ /** URL segment on the storefront. Derived from the title when omitted. */
1110
+ handle: string;
1111
+ description: string | null;
1112
+ imageUrl: string | null;
1113
+ /** Storefront <title>; falls back to `title` when empty. */
1114
+ seoTitle: string | null;
1115
+ seoDescription: string | null;
1116
+ published: boolean;
1117
+ sortOrder: number;
1118
+ /** Members, cheapest possible shape — counts and chips without a product join. */
1119
+ productIds: string[];
1120
+ createdAt: string;
1121
+ updatedAt: string;
1122
+ }
1123
+ export interface CreateCollectionInput {
1124
+ title: string;
1125
+ handle?: string;
1126
+ description?: string | null;
1127
+ imageUrl?: string | null;
1128
+ seoTitle?: string | null;
1129
+ seoDescription?: string | null;
1130
+ published?: boolean;
1131
+ sortOrder?: number;
1132
+ productIds?: string[];
1133
+ }
1134
+ export interface UpdateCollectionInput {
1135
+ title?: string;
1136
+ handle?: string;
1137
+ description?: string | null;
1138
+ imageUrl?: string | null;
1139
+ seoTitle?: string | null;
1140
+ seoDescription?: string | null;
1141
+ published?: boolean;
1142
+ sortOrder?: number;
1143
+ productIds?: string[];
1144
+ }
1145
+ export type GiftCardStatus = 'active' | 'redeemed' | 'expired' | 'disabled';
1146
+ export interface GiftCard {
1147
+ id: string;
1148
+ tenantId: string;
1149
+ /** What the buyer types at checkout. Unique per tenant, stored upper-case. */
1150
+ code: string;
1151
+ /** Face value at issue, in the store currency. Never changes. */
1152
+ initialBalance: number;
1153
+ /** What is left to spend. The only field redemption moves. */
1154
+ balance: number;
1155
+ currency: string;
1156
+ status: GiftCardStatus;
1157
+ /** Null = never expires. */
1158
+ expiresAt: string | null;
1159
+ /** Recipient, when the card was issued to a known customer. */
1160
+ customerId: string | null;
1161
+ customerEmail: string | null;
1162
+ note: string | null;
1163
+ createdAt: string;
1164
+ updatedAt: string;
1165
+ }
1166
+ export interface CreateGiftCardInput {
1167
+ code?: string;
1168
+ initialBalance: number;
1169
+ currency?: string;
1170
+ status?: GiftCardStatus;
1171
+ expiresAt?: string | null;
1172
+ customerId?: string | null;
1173
+ customerEmail?: string | null;
1174
+ note?: string | null;
1175
+ }
1176
+ export interface UpdateGiftCardInput {
1177
+ code?: string;
1178
+ /** Adjusting the remaining balance (a goodwill top-up, a correction). */
1179
+ balance?: number;
1180
+ status?: GiftCardStatus;
1181
+ expiresAt?: string | null;
1182
+ customerId?: string | null;
1183
+ customerEmail?: string | null;
1184
+ note?: string | null;
1185
+ }
1186
+ export type MediaFileKind = 'image' | 'video' | 'document';
1187
+ /**
1188
+ * The record a file hangs off.
1189
+ *
1190
+ * Without this a media library is a wall of anonymous thumbnails: a merchant can
1191
+ * see that a photo is bad and has nowhere to go to replace it. Only products own
1192
+ * files today; the shape is a discriminated union so a collection or a category
1193
+ * can join without changing the screens that read it.
1194
+ */
1195
+ export interface MediaFileReference {
1196
+ type: 'product';
1197
+ /** The record's id — what the admin route is built from. */
1198
+ id: string;
1199
+ /** The record's name, for the card's link. */
1200
+ label: string;
1201
+ /** The attachment row (plg_shop_product_images.id). Deleting a file from the
1202
+ * library targets this: detaching it IS the deletion. */
1203
+ attachmentId: string;
1204
+ /** True for the photo the storefront leads with. */
1205
+ isCover?: boolean;
1206
+ }
1207
+ export interface MediaFile {
1208
+ /** Storage path relative to the bucket — the stable identity. */
1209
+ id: string;
1210
+ name: string;
1211
+ url: string;
1212
+ kind: MediaFileKind;
1213
+ /** Bytes. 0 when the backend does not report a size. */
1214
+ size: number;
1215
+ /** Upper-cased extension, for the card's type caption (WEBP, MP4…). */
1216
+ extension: string;
1217
+ createdAt: string;
1218
+ /** Absent for files uploaded straight to the library, which belong to nothing. */
1219
+ reference?: MediaFileReference;
1220
+ }
533
1221
  //# sourceMappingURL=types.d.ts.map