@fayz-ai/shop 0.10.0 → 0.12.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 (65) hide show
  1. package/dist/{chunk-IL6GA4ER.js → chunk-2WACO2TG.js} +3 -3
  2. package/dist/{chunk-IL6GA4ER.js.map → chunk-2WACO2TG.js.map} +1 -1
  3. package/dist/{chunk-RGTIJQJL.js → chunk-6BO2TMZ5.js} +3 -3
  4. package/dist/{chunk-RGTIJQJL.js.map → chunk-6BO2TMZ5.js.map} +1 -1
  5. package/dist/{chunk-XOP6SHPB.js → chunk-NWW3WJ7Y.js} +4 -10
  6. package/dist/chunk-NWW3WJ7Y.js.map +1 -0
  7. package/dist/{chunk-XERLK5LD.js → chunk-STRNMFC4.js} +28 -5
  8. package/dist/chunk-STRNMFC4.js.map +1 -0
  9. package/dist/{chunk-U3O2I3RM.js → chunk-U6HV3LVP.js} +385 -23
  10. package/dist/chunk-U6HV3LVP.js.map +1 -0
  11. package/dist/data/checkout-gateways.d.ts +28 -0
  12. package/dist/data/checkout-gateways.d.ts.map +1 -0
  13. package/dist/data/customer-search.d.ts +3 -0
  14. package/dist/data/customer-search.d.ts.map +1 -0
  15. package/dist/data/functions.d.ts +9 -0
  16. package/dist/data/functions.d.ts.map +1 -0
  17. package/dist/data/media.d.ts +37 -0
  18. package/dist/data/media.d.ts.map +1 -0
  19. package/dist/data/mock-provider.d.ts +40 -8
  20. package/dist/data/mock-provider.d.ts.map +1 -1
  21. package/dist/data/provider.d.ts +205 -7
  22. package/dist/data/provider.d.ts.map +1 -1
  23. package/dist/data/supabase-provider.d.ts +118 -5
  24. package/dist/data/supabase-provider.d.ts.map +1 -1
  25. package/dist/data/tables.d.ts +3 -0
  26. package/dist/data/tables.d.ts.map +1 -1
  27. package/dist/entities/index.d.ts +0 -1
  28. package/dist/entities/index.d.ts.map +1 -1
  29. package/dist/entities.js +2 -2
  30. package/dist/index.d.ts +16 -5
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +925 -60
  33. package/dist/index.js.map +1 -1
  34. package/dist/inventory/index.d.ts +2 -2
  35. package/dist/inventory/index.d.ts.map +1 -1
  36. package/dist/inventory/stock-types.d.ts +60 -1
  37. package/dist/inventory/stock-types.d.ts.map +1 -1
  38. package/dist/inventory/supabase-stock-store.d.ts +1 -0
  39. package/dist/inventory/supabase-stock-store.d.ts.map +1 -1
  40. package/dist/inventory.js +1 -1
  41. package/dist/lib/commerce.d.ts.map +1 -1
  42. package/dist/lib/document.d.ts +13 -0
  43. package/dist/lib/document.d.ts.map +1 -0
  44. package/dist/lib/variant-matrix.d.ts +120 -0
  45. package/dist/lib/variant-matrix.d.ts.map +1 -0
  46. package/dist/mock.js +2 -2
  47. package/dist/providers/checkout.d.ts +129 -0
  48. package/dist/providers/checkout.d.ts.map +1 -0
  49. package/dist/providers/index.d.ts +5 -0
  50. package/dist/providers/index.d.ts.map +1 -0
  51. package/dist/providers/shipping.d.ts +43 -0
  52. package/dist/providers/shipping.d.ts.map +1 -0
  53. package/dist/providers.js +70 -0
  54. package/dist/providers.js.map +1 -0
  55. package/dist/runtime.js +3 -3
  56. package/dist/shipping/label-provider.d.ts +43 -0
  57. package/dist/shipping/label-provider.d.ts.map +1 -0
  58. package/dist/types.d.ts +475 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/package.json +8 -4
  61. package/dist/chunk-U3O2I3RM.js.map +0 -1
  62. package/dist/chunk-XERLK5LD.js.map +0 -1
  63. package/dist/chunk-XOP6SHPB.js.map +0 -1
  64. package/dist/entities/sidecar.d.ts +0 -9
  65. package/dist/entities/sidecar.d.ts.map +0 -1
package/dist/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
- export { getShopProvider, resetShopProvider, setShopProvider } from './chunk-IL6GA4ER.js';
2
- import './chunk-U3O2I3RM.js';
1
+ export { getShopProvider, resetShopProvider, setShopProvider } from './chunk-2WACO2TG.js';
2
+ import './chunk-U6HV3LVP.js';
3
3
  import './chunk-IKNGCRUM.js';
4
- import './chunk-XOP6SHPB.js';
4
+ import './chunk-NWW3WJ7Y.js';
5
5
  import './chunk-3GERSY5F.js';
6
6
  //# sourceMappingURL=runtime.js.map
7
7
  //# sourceMappingURL=runtime.js.map
@@ -0,0 +1,43 @@
1
+ import type { ShippingLabel, ShippingLabelOption } from '../types';
2
+ export interface ShippingLabelProvider {
3
+ /** Connector slug — the id `plg_connections.connector_id` carries. */
4
+ id: string;
5
+ /** How the merchant knows them ("Melhor Envio"). Shown in the panel. */
6
+ label: string;
7
+ /** Services and prices for one order. Free, repeatable, spends nothing. */
8
+ quote(orderId: string): Promise<{
9
+ options: ShippingLabelOption[];
10
+ label: ShippingLabel | null;
11
+ }>;
12
+ /** SPENDS the merchant's balance. Idempotent per order by contract. */
13
+ buy(orderId: string, serviceId: number): Promise<ShippingLabel>;
14
+ /** The label PDF, as many times as the merchant needs it. */
15
+ print(orderId: string): Promise<string | null>;
16
+ /** What the carrier says now. */
17
+ track(orderId: string): Promise<ShippingLabel['tracking']>;
18
+ }
19
+ export declare function registerShippingLabelProvider(provider: ShippingLabelProvider): void;
20
+ export declare function listShippingLabelProviders(): ShippingLabelProvider[];
21
+ /** Test seam — the registry is module state, and a test that registers a fake
22
+ * must not leak it into the next one. */
23
+ export declare function resetShippingLabelProviders(): void;
24
+ export interface ResolveShippingLabelOptions {
25
+ /** Connector ids the store has ACTIVE, in the order the panel lists them. */
26
+ connected: readonly string[];
27
+ /**
28
+ * The merchant's explicit choice, when they made one.
29
+ *
30
+ * `''` (empty, not undefined) is a decision too — "I print labels myself" —
31
+ * and it must beat every connected carrier, exactly as the payment provider
32
+ * setting treats "confirmo à mão".
33
+ */
34
+ preferred?: string | null;
35
+ }
36
+ /**
37
+ * Which carrier issues this store's labels — or nobody.
38
+ *
39
+ * Null is a first-class answer and the common one: most stores dispatch by hand,
40
+ * and the panel must show them the manual path without a dead button beside it.
41
+ */
42
+ export declare function resolveShippingLabelProvider(options: ResolveShippingLabelOptions): ShippingLabelProvider | null;
43
+ //# sourceMappingURL=label-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label-provider.d.ts","sourceRoot":"","sources":["../../src/shipping/label-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAiBlE,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAA;IACV,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;QAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;IAChG,uEAAuE;IACvE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IAC/D,6DAA6D;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC9C,iCAAiC;IACjC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAA;CAC3D;AAID,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAEnF;AAED,wBAAgB,0BAA0B,IAAI,qBAAqB,EAAE,CAEpE;AAED;0CAC0C;AAC1C,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,MAAM,WAAW,2BAA2B;IAC1C,6EAA6E;IAC7E,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,2BAA2B,GACnC,qBAAqB,GAAG,IAAI,CAkB9B"}
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,9 +25,41 @@ 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;
24
65
  /**
@@ -62,12 +103,56 @@ export interface ProductVariant {
62
103
  status: 'active' | 'archived';
63
104
  /** Variant-specific photo; null falls back to the product's primary image. */
64
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;
65
122
  }
66
123
  /** What ShopProvider.getProductVariants answers for one product. */
67
124
  export interface ProductVariantSet {
68
125
  options: ProductOption[];
69
126
  variants: ProductVariant[];
70
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>;
155
+ }
71
156
  export interface ProductImage {
72
157
  id: string;
73
158
  productId: string;
@@ -93,6 +178,12 @@ export interface CreateProductInput {
93
178
  isPhysical?: boolean;
94
179
  weight?: number;
95
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;
96
187
  }
97
188
  export interface UpdateProductInput {
98
189
  name?: string;
@@ -110,6 +201,12 @@ export interface UpdateProductInput {
110
201
  isPhysical?: boolean;
111
202
  weight?: number | null;
112
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;
113
210
  }
114
211
  export interface ListProductsOptions {
115
212
  status?: ProductStatus;
@@ -213,9 +310,25 @@ export interface Order {
213
310
  paymentMethodKind: PaymentMethodKind | null;
214
311
  paidAt: string | null;
215
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[];
216
318
  createdAt: string;
217
319
  updatedAt: string;
218
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
+ }
219
332
  export interface OrderItem {
220
333
  id: string;
221
334
  orderId: string;
@@ -298,8 +411,143 @@ export interface ShippingAddressInput {
298
411
  recipient?: string;
299
412
  phone?: string;
300
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;
301
422
  }
302
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
+ * Qual adquirente deve cobrar — o slug de `plg_shop_settings.payment_provider`.
466
+ *
467
+ * Ausente cai na AbacatePay, que é onde tudo estava quando havia um gateway só.
468
+ * Não é um dado que o comprador escolhe: quem passa é a vitrine, a partir dos
469
+ * ajustes da loja, e a função reconfere tudo o que envolve dinheiro do lado de
470
+ * lá de qualquer forma.
471
+ */
472
+ provider?: string | null;
473
+ }
474
+ export interface CheckoutSession {
475
+ sessionId: string;
476
+ /** Recalculado no servidor. O navegador exibe; nunca decide. */
477
+ total: number;
478
+ charge: PaymentCharge | null;
479
+ state: 'open' | 'paid' | 'failed' | 'expired';
480
+ /**
481
+ * Quem abriu esta cobrança — o slug do adquirente, não o nome dele.
482
+ *
483
+ * Devolvido para que a consulta seguinte bata na função certa sem reler os
484
+ * ajustes da loja. Uma sessão pertence ao adquirente que a abriu para sempre:
485
+ * trocar de provedor no meio do caminho perguntaria a um gateway por uma
486
+ * transação que está no outro.
487
+ */
488
+ provider?: string | null;
489
+ }
490
+ /** `orderId` só aparece quando o pagamento entrou — é ele que prova a compra. */
491
+ export interface CheckoutSettlement {
492
+ /** `pending` is what the acquirer answers while the buyer still has the QR
493
+ * code open — the ordinary case, and the one a caller must never read as a
494
+ * refusal. Only `failed`, `expired` and `cancelled` end the wait. */
495
+ state: 'open' | 'pending' | 'paid' | 'failed' | 'expired' | 'cancelled' | 'unknown';
496
+ orderId?: string | null;
497
+ reason?: string | null;
498
+ }
499
+ /** A carrier label, from quote to tracking. `labelUrl` is a PDF the merchant prints. */
500
+ export interface ShippingLabelOption {
501
+ serviceId: number;
502
+ name: string;
503
+ carrier: string;
504
+ price: number;
505
+ etaMinDays?: number | null;
506
+ etaMaxDays?: number | null;
507
+ }
508
+ /** A carrier drop-off point, as a settings screen lists it. */
509
+ export interface ShippingAgency {
510
+ id: string;
511
+ name: string;
512
+ city: string;
513
+ state: string;
514
+ address: string;
515
+ /** Carrier service ids this one accepts — a choice that hides them is a
516
+ * choice the merchant discovers is wrong at the first dispatch. */
517
+ services: string[];
518
+ }
519
+ export interface ShippingLabel {
520
+ labelId: string;
521
+ labelUrl?: string | null;
522
+ status?: string | null;
523
+ tracking?: {
524
+ code: string | null;
525
+ status: string | null;
526
+ url: string | null;
527
+ } | null;
528
+ }
529
+ /** What a connected acquirer can be asked to open. Card waits for hosted fields. */
530
+ export type PaymentChargeMethod = 'pix';
531
+ /**
532
+ * A charge the buyer can act on. `qrcodeBase64` is a bare base64 PNG — no
533
+ * `data:` prefix — because that is how the provider returns it.
534
+ */
535
+ export interface PaymentCharge {
536
+ emv: string;
537
+ qrcodeBase64: string | null;
538
+ expiresAt: string;
539
+ }
540
+ /**
541
+ * `unopened` is not an error: the page may ask for the state before the charge
542
+ * call has returned. `failed` is the provider's final no.
543
+ */
544
+ export interface PaymentChargeResult {
545
+ state: 'pending' | 'paid' | 'refunded' | 'failed' | 'unopened';
546
+ orderId: string;
547
+ reference?: string | null;
548
+ charge?: PaymentCharge | null;
549
+ providerStatus?: string | null;
550
+ }
303
551
  /**
304
552
  * A range of postal codes the store delivers to, with its own price and ETA.
305
553
  *
@@ -321,9 +569,208 @@ export interface ShippingZone {
321
569
  etaMaxDays?: number | null;
322
570
  active: boolean;
323
571
  sortOrder: number;
572
+ /**
573
+ * A zone the store REFUSES (0048) — "não entrego aqui", by any means.
574
+ *
575
+ * It beats every other zone covering the same postcode and it beats a carrier
576
+ * quote, because the refusal is about the store and not about who carries the
577
+ * parcel. Enforced server-side on the order, so a direct POST cannot get
578
+ * around it. `rate` and the ETA are ignored on an excluded zone.
579
+ *
580
+ * Not-cadastrar is a different thing: a broad zone covering a whole region
581
+ * already accepts the street the merchant wants to avoid, and there was no way
582
+ * to carve an exception out of it.
583
+ */
584
+ excluded: boolean;
585
+ /** Which profile owns this range (0049). Undefined = the general profile. */
586
+ profileId?: string | null;
324
587
  }
325
588
  export type CreateShippingZoneInput = Omit<ShippingZone, 'id' | 'tenantId'>;
326
589
  export type UpdateShippingZoneInput = Partial<CreateShippingZoneInput>;
590
+ export type ShippingPackageKind = 'box' | 'envelope' | 'soft';
591
+ /**
592
+ * A box the store actually owns (plg_shop_packages, 0046).
593
+ *
594
+ * The freight engine picks the SMALLEST of these the cart fits in and adds
595
+ * `emptyWeightGrams` to what the carrier weighs. Before this cadastro existed
596
+ * the box was a constant in the edge function — 4×16×20cm for every store —
597
+ * and the difference between the quote and the label came out of the
598
+ * merchant's margin.
599
+ *
600
+ * `isDefault` is the box a cart falls back to when some item has no
601
+ * measurements. That fallback used to be the constant; it is data now.
602
+ */
603
+ export interface ShippingPackage {
604
+ id: string;
605
+ tenantId: string;
606
+ name: string;
607
+ kind: ShippingPackageKind;
608
+ heightCm: number;
609
+ widthCm: number;
610
+ lengthCm: number;
611
+ /** Grams, because that is how a merchant reads a carton's own weight. */
612
+ emptyWeightGrams: number;
613
+ isDefault: boolean;
614
+ active: boolean;
615
+ }
616
+ export type CreateShippingPackageInput = Omit<ShippingPackage, 'id' | 'tenantId'>;
617
+ export type UpdateShippingPackageInput = Partial<CreateShippingPackageInput>;
618
+ /**
619
+ * A named group of products with its own delivery zones (0049).
620
+ *
621
+ * The general mechanism behind "estes produtos vão de outro jeito", copied from
622
+ * Shopify's shipping profiles: refrigerated, fragile, oversized and made-to-order
623
+ * are all the same shape — a set of products the store ships differently — and
624
+ * modelling them one column at a time is how a settings screen ends up with four
625
+ * radios that each answer one merchant's question.
626
+ *
627
+ * INHERITANCE is by NULL on both ends: a product with no profile uses the
628
+ * general one, and a zone with no profile belongs to the general one. That is
629
+ * what lets this ship without migrating a single existing product or zone.
630
+ */
631
+ export interface ShippingProfile {
632
+ id: string;
633
+ tenantId: string;
634
+ name: string;
635
+ /**
636
+ * Whether a freight gateway may quote for the products in this profile.
637
+ *
638
+ * Undefined inherits `StoreSettings.carrierQuotes`. `false` is what replaces
639
+ * the old cold-chain policy: these products leave only through the zones the
640
+ * store declared itself. In a cart that mixes profiles the most restrictive one
641
+ * wins — otherwise "these do not go by truck" would be undone by adding a mug.
642
+ */
643
+ carrierQuotes?: boolean;
644
+ /** The general profile, so the screen has somewhere to hang unprofiled zones. */
645
+ isDefault: boolean;
646
+ }
647
+ export type CreateShippingProfileInput = Omit<ShippingProfile, 'id' | 'tenantId'>;
648
+ export type UpdateShippingProfileInput = Partial<CreateShippingProfileInput>;
649
+ /**
650
+ * The store-wide delivery fallback (public.shipping_settings, 0015).
651
+ *
652
+ * A zone always wins over this. It is what a store charges for an address no
653
+ * zone covers — and for a store that has declared no zone at all, which is how
654
+ * most start. A tenant with no row at all charges nothing, which is the safe
655
+ * default: inventing a freight nobody configured is worse than free delivery.
656
+ */
657
+ export interface ShippingSettings {
658
+ flatRate: number;
659
+ /** Subtotal (after discount) at or above which delivery is free. */
660
+ freeAbove?: number | null;
661
+ currency: string;
662
+ }
663
+ export type UpdateShippingSettingsInput = Partial<ShippingSettings>;
664
+ /**
665
+ * Per-field checkout policy. Keyed by the form field the storefront renders.
666
+ *
667
+ * A record rather than columns because the SET OF FIELDS is the variable part:
668
+ * a store selling downloads has no use for a district, and the next storefront
669
+ * will want one nobody has thought of. `visible: false` implies not required —
670
+ * a field nobody can see cannot be filled in.
671
+ */
672
+ export type CheckoutFieldKey = 'name' | 'email' | 'phone' | 'document' | 'street' | 'number' | 'complement' | 'district' | 'city' | 'state' | 'postalCode';
673
+ export interface CheckoutFieldPolicy {
674
+ visible?: boolean;
675
+ required?: boolean;
676
+ }
677
+ /**
678
+ * The store's commercial policy — what plg_shop_settings holds (0044b).
679
+ *
680
+ * Every field is OPTIONAL and `undefined` means NOT DECIDED, which is a
681
+ * different thing from a false or an empty list: not-decided keeps whatever the
682
+ * app declared in its StorefrontConfig, while `paymentMethods: []` would be a
683
+ * merchant who accepts nothing. That distinction is what lets this ship to eight
684
+ * live storefronts without changing any of them on deploy day.
685
+ *
686
+ * Two of these are enforced SERVER-SIDE by a trigger (`paymentMethods`,
687
+ * `guestCheckout`); the rest are read by the storefront. The docs on each say
688
+ * which, because "the checkbox is off" and "the server refuses" are promises of
689
+ * very different strength.
690
+ */
691
+ export interface StoreSettings {
692
+ /** Vitrine display. Undefined = the app's own currency/locale. */
693
+ currency?: string;
694
+ locale?: string;
695
+ showOutOfStock?: boolean;
696
+ /** Admin-side: makes SKU mandatory on the product form. Not a storefront rule. */
697
+ requireSku?: boolean;
698
+ /** ERP ownership of stock (0029). 'external' means a connector owns the numbers. */
699
+ stockOwnership?: 'internal' | 'external';
700
+ /** What the checkout may offer. ENFORCED: an order naming a method outside
701
+ * this list is refused by the server, not merely hidden by the form. */
702
+ paymentMethods?: PaymentMethodKind[];
703
+ /** Which connected gateway charges, when more than one is connected. The id of
704
+ * a ConnectorDefinition ('appmax'), never a credential. */
705
+ paymentProvider?: string;
706
+ /** ENFORCED: a storefront order with no account-linked customer is refused
707
+ * when this is explicitly false. */
708
+ guestCheckout?: boolean;
709
+ /** Storefront-side only — confirming an e-mail is a fact about the auth
710
+ * provider, not about the order, so the server does not police it. */
711
+ requireConfirmedEmail?: boolean;
712
+ marketingOptIn?: boolean;
713
+ discountsEnabled?: boolean;
714
+ checkoutFields?: Partial<Record<CheckoutFieldKey, CheckoutFieldPolicy>>;
715
+ /** 'never' — every shipment is created by hand. 'on_payment' — one is created
716
+ * when the payment is confirmed. 'always' — when the order is placed. */
717
+ autoFulfill?: 'never' | 'on_payment' | 'always';
718
+ notifyNewOrder?: boolean;
719
+ notifyLowStock?: boolean;
720
+ /**
721
+ * A declaração que viaja com o pedido — para você, para o motoboy, e na
722
+ * observação da etiqueta. Nunca mostrada ao comprador.
723
+ *
724
+ * Onde ficou a política de frio: num PERFIL DE ENTREGA (0049). "Refrigerado só
725
+ * sai no meu carro" é uma frase sobre logística, e uma coluna de três valores
726
+ * só respondia por temperatura — a loja seguinte pede o mesmo para frágil, para
727
+ * volumoso, para sob encomenda. Um perfil atende os quatro sem código novo.
728
+ */
729
+ /**
730
+ * Whether a freight GATEWAY may quote for this store (0048).
731
+ *
732
+ * Melhor Envio is not a carrier — it is a gateway that brings Correios,
733
+ * Jadlog, Loggi and others behind one connection. So the store's question is
734
+ * not "which carrier" but WHO CALCULATES: the merchant, from her zones, or a
735
+ * gateway, from the shopper's postcode.
736
+ *
737
+ * `false` = the merchant calculates, and no gateway is asked even if one is
738
+ * connected. Undefined = not decided, which behaves as today (ask if
739
+ * connected). It has to be storable rather than inferred from "no connection":
740
+ * the day someone connects a gateway in this app, a store that dispatches by
741
+ * hand would start receiving carrier prices it never chose — and 0044b makes a
742
+ * gateway quote WIN over the zones when it answers.
743
+ */
744
+ carrierQuotes?: boolean;
745
+ /**
746
+ * The note that travels with the parcel ("caixa térmica com gelo, entregar em
747
+ * até 24h"). Admin-side and carrier-side only — never shown to the shopper,
748
+ * which is why `shop_store_settings()` does not return it.
749
+ */
750
+ handlingNote?: string;
751
+ }
752
+ export type UpdateStoreSettingsInput = Partial<StoreSettings>;
753
+ /**
754
+ * The answer to "does this store deliver to this postcode?" (0048,
755
+ * `shop_delivery_check`), asked with the address and BEFORE the card.
756
+ *
757
+ * Two separate facts, because they are not the same question:
758
+ * · `refused` — an exclusion zone covers it. A no from the store, true even
759
+ * where a carrier would happily deliver.
760
+ * · `ownZone` — a zone of the store's own covers it. What tells "our car"
761
+ * from "a gateway", and what a shipping profile with the gateway off (0049)
762
+ * narrows a product to.
763
+ *
764
+ * Deliberately NOT "is there freight": that is `quoteShipping`, which also
765
+ * consults a carrier. Answering both here would tell every carrier-only store
766
+ * that it does not deliver anywhere.
767
+ */
768
+ export interface DeliveryCheck {
769
+ refused: boolean;
770
+ /** The exclusion zone's name, so the shopper reads a reason and not an error. */
771
+ refusedZone?: string | null;
772
+ ownZone: boolean;
773
+ }
327
774
  /**
328
775
  * One delivery option for a postal code, as quoted by shop_quote_shipping.
329
776
  *
@@ -413,6 +860,10 @@ export interface ShopCustomer {
413
860
  lastName: string;
414
861
  email: string | null;
415
862
  phone: string | null;
863
+ /** CPF/CNPJ, digits only. The person's, not the order's — an invoice issued
864
+ * months later needs the document that was valid on the day it is issued,
865
+ * and the order keeps its own frozen copy for that. */
866
+ document?: string | null;
416
867
  notes: string | null;
417
868
  ordersCount: number;
418
869
  totalSpent: number;
@@ -424,6 +875,7 @@ export interface CreateCustomerInput {
424
875
  lastName?: string;
425
876
  email?: string;
426
877
  phone?: string;
878
+ document?: string;
427
879
  notes?: string;
428
880
  }
429
881
  export interface UpdateCustomerInput {
@@ -431,6 +883,7 @@ export interface UpdateCustomerInput {
431
883
  lastName?: string;
432
884
  email?: string | null;
433
885
  phone?: string | null;
886
+ document?: string | null;
434
887
  notes?: string | null;
435
888
  }
436
889
  export interface ListCustomersOptions {
@@ -749,6 +1202,26 @@ export interface UpdateGiftCardInput {
749
1202
  note?: string | null;
750
1203
  }
751
1204
  export type MediaFileKind = 'image' | 'video' | 'document';
1205
+ /**
1206
+ * The record a file hangs off.
1207
+ *
1208
+ * Without this a media library is a wall of anonymous thumbnails: a merchant can
1209
+ * see that a photo is bad and has nowhere to go to replace it. Only products own
1210
+ * files today; the shape is a discriminated union so a collection or a category
1211
+ * can join without changing the screens that read it.
1212
+ */
1213
+ export interface MediaFileReference {
1214
+ type: 'product';
1215
+ /** The record's id — what the admin route is built from. */
1216
+ id: string;
1217
+ /** The record's name, for the card's link. */
1218
+ label: string;
1219
+ /** The attachment row (plg_shop_product_images.id). Deleting a file from the
1220
+ * library targets this: detaching it IS the deletion. */
1221
+ attachmentId: string;
1222
+ /** True for the photo the storefront leads with. */
1223
+ isCover?: boolean;
1224
+ }
752
1225
  export interface MediaFile {
753
1226
  /** Storage path relative to the bucket — the stable identity. */
754
1227
  id: string;
@@ -760,5 +1233,7 @@ export interface MediaFile {
760
1233
  /** Upper-cased extension, for the card's type caption (WEBP, MP4…). */
761
1234
  extension: string;
762
1235
  createdAt: string;
1236
+ /** Absent for files uploaded straight to the library, which belong to nothing. */
1237
+ reference?: MediaFileReference;
763
1238
  }
764
1239
  //# sourceMappingURL=types.d.ts.map