@reblu/site-contracts 1.14.0 → 1.16.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/CHANGELOG.md CHANGED
@@ -1,5 +1,60 @@
1
1
  # @reblu/site-contracts
2
2
 
3
+ ## 1.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cc4e14e: REB-980: export `DataRequestInput`, `DataRequestSubmission` and `DataRequestType` — the body and 201 acknowledgement (`{ id, requestedAt, slaDueAt }`, the 72h deadline) of `POST /api/site/data-requests`, the public GDPR rights form endpoint. `captcha` (reCAPTCHA v3 token) is required; `name` and `details` are optional.
8
+
9
+ ## 1.15.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 614e826: Shop checkout: full-invoice opt-in and the buyer's identifier (REB-73).
14
+
15
+ `ShopCheckoutInput` gains the optional `wantsFullInvoice` flag, and
16
+ `ShopBillingInput` the optional `billingIdType` (`NIF` for a Spanish
17
+ NIF/NIE/CIF; `02` EU VAT id, `03` passport, `04` ID document of the country
18
+ of residence, `05` residence certificate, `06` other document) and
19
+ `billingIdCountry` (ISO 3166-1 alpha-2, required for `02`–`06`). A full
20
+ invoice needs the identifier, the billing name and a billing address; without
21
+ the identifier the invoice is simplified.
22
+
23
+ `ShopErrorCode` gains two checkout codes, both answered before any payment:
24
+ `BILLING_DATA_REQUIRED` (HTTP 422, `details.field: 'billing'`) when the
25
+ opt-in, or a total over the tenant's simplified-invoice cap, comes without
26
+ those three; and `INVOICING_NOT_READY` (HTTP 503) when the shop cannot issue
27
+ invoices yet. Existing clients that send only `billing.billingNif` keep
28
+ working: its type is derived from the billing address country.
29
+
30
+ - 614e826: Shop checkout: no full-invoice opt-in on a shop that issues no invoices (REB-73).
31
+ - `ShopErrorCode` gains `FULL_INVOICE_UNAVAILABLE` (HTTP 422,
32
+ `details.field: 'wantsFullInvoice'`): `wantsFullInvoice: true` sent to a shop
33
+ whose invoicing is off (`ShopConfig.simplifiedInvoiceCapCents` is `null`) is
34
+ refused before any payment instead of succeeding without an invoice. Clients
35
+ that never send the opt-in are unaffected. The union is additive: a SITE
36
+ with an exhaustive `switch` over `ShopErrorCode` (or a
37
+ `Record<ShopErrorCode, …>`) must add the new member when it upgrades.
38
+ - `@reblu/site-blocks`: new `shopIssuesInvoices(config)`; `FullInvoiceFields`
39
+ takes `issuesInvoices` (default `true`) and renders nothing when it is
40
+ `false`, and `toCheckoutInvoiceFields(value, overCap, issuesInvoices)`
41
+ returns no opt-in and no billing block then. Default Spanish copy for the
42
+ new code in `getShopErrorMessage`.
43
+
44
+ - 614e826: Shop: the order's invoice and the simplified-invoice cap (REB-73).
45
+ - `ShopOrder` gains the optional `invoice: { number, url } | null`
46
+ (`ShopOrderInvoice`): once the sale invoice is issued, its number and the
47
+ shop's authenticated client-portal route that serves it — never a signed
48
+ URL, so the link does not expire; the buyer signs in to open it.
49
+ - `ShopConfig` gains `simplifiedInvoiceCapCents` (cents, never above the legal
50
+ 300000; `null` while the shop issues no invoices): above it, checkout needs
51
+ the buyer's identifier, name and billing address.
52
+ - `@reblu/site-blocks`: new drop-in `OrderInvoiceLink`, which
53
+ `OrderConfirmation` now renders under a confirmed order (labels
54
+ `invoiceLinkLabel`/`invoiceSignInHint`), and default Spanish copy for the
55
+ `BILLING_DATA_REQUIRED`/`INVOICING_NOT_READY` checkout codes in
56
+ `getShopErrorMessage`.
57
+
3
58
  ## 1.14.0
4
59
 
5
60
  ### Minor Changes
package/dist/index.d.cts CHANGED
@@ -81,6 +81,12 @@ export type CustomFieldOption = { value: string; label: string;}
81
81
 
82
82
  export type CustomFieldValueType = "boolean" | "text" | "select" | "multiselect"
83
83
 
84
+ export type DataRequestInput = { requestType: "ACCESS" | "RECTIFICATION" | "ERASURE" | "OBJECTION" | "PORTABILITY" | "RESTRICTION" | "AUTOMATED_DECISION" | "INFORMATION"; email: string; captcha: string; name?: string | undefined; details?: string | undefined;}
85
+
86
+ export type DataRequestSubmission = { id: string; requestedAt: string; slaDueAt: string;}
87
+
88
+ export type DataRequestType = "ACCESS" | "RECTIFICATION" | "ERASURE" | "OBJECTION" | "PORTABILITY" | "RESTRICTION" | "AUTOMATED_DECISION" | "INFORMATION"
89
+
84
90
  export type EmbedReferenceData = { pageSlug: string; pageId?: string | undefined; categorySlug?: string | null | undefined;}
85
91
 
86
92
  export type LeadInput = { name: string; email?: string | undefined; phone?: string | undefined; businessName?: string | undefined; message?: string | undefined; source?: string | undefined; metadata?: Record<string, unknown> | undefined;}
@@ -145,7 +151,7 @@ export type ShopAddressInput = { firstName: string; lastName: string; s
145
151
 
146
152
  export type ShopApplyDiscountInput = { code: string; orderSubtotal: number; customerEmail?: string | undefined;}
147
153
 
148
- export type ShopBillingInput = { billingName: string; billingNif?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined;}
154
+ export type ShopBillingInput = { billingName: string; billingNif?: string | undefined; billingIdType?: "NIF" | "02" | "03" | "04" | "05" | "06" | undefined; billingIdCountry?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined;}
149
155
 
150
156
  export type ShopBundleComponent = { quantity: number; component: { id: string; name: string; slug: string; price: number; };}
151
157
 
@@ -165,11 +171,11 @@ export type ShopCategory = { id: string; name: string; slug: string;
165
171
  */
166
172
  export type ShopCheckEmailInput = { email: string;}
167
173
 
168
- export type ShopCheckoutInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[]; customerEmail: string; customerName: string; successUrl: string; cancelUrl: string; customerPhone?: string | null | undefined; discountCode?: string | undefined; shippingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; billing?: { billingName: string; billingNif?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; } | undefined;}
174
+ export type ShopCheckoutInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[]; customerEmail: string; customerName: string; successUrl: string; cancelUrl: string; customerPhone?: string | null | undefined; discountCode?: string | undefined; shippingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; billing?: { billingName: string; billingNif?: string | undefined; billingIdType?: "NIF" | "02" | "03" | "04" | "05" | "06" | undefined; billingIdCountry?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; } | undefined; wantsFullInvoice?: boolean | undefined;}
169
175
 
170
176
  export type ShopCheckoutSession = { url: string; sessionId: string;}
171
177
 
172
- export type ShopConfig = { shopName: string | null; defaultLowStockThreshold: number; currencyCode: string; stripePublishableKey: string | null; stripeTestPublishableKey: string | null; stripeTestMode: boolean; shippingEnabled: boolean; pickupEnabled: boolean; taxEnabled: boolean; taxIncludedInPrice: boolean; productTrustItems?: { [x: string]: unknown; icon: (string & {}) | "shipping" | "returns" | "secure-payment" | "support" | "gift" | "pickup" | "warranty" | "quality"; text: string; }[] | null | undefined;}
178
+ export type ShopConfig = { shopName: string | null; defaultLowStockThreshold: number; currencyCode: string; stripePublishableKey: string | null; stripeTestPublishableKey: string | null; stripeTestMode: boolean; shippingEnabled: boolean; pickupEnabled: boolean; taxEnabled: boolean; taxIncludedInPrice: boolean; simplifiedInvoiceCapCents?: number | null | undefined; productTrustItems?: { [x: string]: unknown; icon: (string & {}) | "shipping" | "returns" | "secure-payment" | "support" | "gift" | "pickup" | "warranty" | "quality"; text: string; }[] | null | undefined;}
173
179
 
174
180
  export type ShopDiscountApplication = { valid: boolean; discount: number; type: "PERCENTAGE" | "FIXED" | null; code: string | null; error?: string | undefined;}
175
181
 
@@ -181,13 +187,15 @@ export type ShopDiscountApplication = { valid: boolean; discount: number;
181
187
  */
182
188
  export type ShopEmailCheck = { exists: boolean;}
183
189
 
184
- export type ShopErrorCode = "STOCK_CHANGED" | "PRICE_CHANGED" | "PRODUCT_UNAVAILABLE" | "DISCOUNT_INVALID" | "SHIPPING_UNAVAILABLE" | "INVALID_INPUT" | "STORE_DISABLED" | "PAYMENT_PROVIDER_ERROR" | "INTERNAL_ERROR"
190
+ export type ShopErrorCode = "STOCK_CHANGED" | "PRICE_CHANGED" | "PRODUCT_UNAVAILABLE" | "DISCOUNT_INVALID" | "SHIPPING_UNAVAILABLE" | "INVALID_INPUT" | "STORE_DISABLED" | "PAYMENT_PROVIDER_ERROR" | "INTERNAL_ERROR" | "BILLING_DATA_REQUIRED" | "INVOICING_NOT_READY" | "FULL_INVOICE_UNAVAILABLE"
185
191
 
186
192
  export type ShopFacets = { taxonomies: { key: string; label: string; showAsBadge: boolean; selectionMode: "single" | "multiple"; terms: { slug: string; name: string; count: number; }[]; }[]; attributes: { key: string; label: string; valueType: "boolean" | "text" | "select" | "multiselect"; options: { value: string; label: string; count: number; }[]; }[]; price: { min: number; max: number; }; onSale: { count: number; };}
187
193
 
188
194
  export type ShopInventoryRef = { stockQuantity: number; reservedQuantity: number; lowStockThreshold: number | null;}
189
195
 
190
- export type ShopOrder = { id: string; orderNumber: string; status: "PENDING" | "CONFIRMED" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED" | "REFUNDED"; paymentStatus: "PENDING" | "REFUNDED" | "PAID" | "FAILED" | "PARTIALLY_REFUNDED"; customerEmail: string; total: number; items: { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined; }[];}
196
+ export type ShopOrder = { id: string; orderNumber: string; status: "PENDING" | "CONFIRMED" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED" | "REFUNDED"; paymentStatus: "PENDING" | "REFUNDED" | "PAID" | "FAILED" | "PARTIALLY_REFUNDED"; customerEmail: string; total: number; items: { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined; }[]; invoice?: { number: string; url: string; } | null | undefined;}
197
+
198
+ export type ShopOrderInvoice = { number: string; url: string;}
191
199
 
192
200
  export type ShopOrderItem = { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined;}
193
201
 
package/dist/index.d.ts CHANGED
@@ -81,6 +81,12 @@ export type CustomFieldOption = { value: string; label: string;}
81
81
 
82
82
  export type CustomFieldValueType = "boolean" | "text" | "select" | "multiselect"
83
83
 
84
+ export type DataRequestInput = { requestType: "ACCESS" | "RECTIFICATION" | "ERASURE" | "OBJECTION" | "PORTABILITY" | "RESTRICTION" | "AUTOMATED_DECISION" | "INFORMATION"; email: string; captcha: string; name?: string | undefined; details?: string | undefined;}
85
+
86
+ export type DataRequestSubmission = { id: string; requestedAt: string; slaDueAt: string;}
87
+
88
+ export type DataRequestType = "ACCESS" | "RECTIFICATION" | "ERASURE" | "OBJECTION" | "PORTABILITY" | "RESTRICTION" | "AUTOMATED_DECISION" | "INFORMATION"
89
+
84
90
  export type EmbedReferenceData = { pageSlug: string; pageId?: string | undefined; categorySlug?: string | null | undefined;}
85
91
 
86
92
  export type LeadInput = { name: string; email?: string | undefined; phone?: string | undefined; businessName?: string | undefined; message?: string | undefined; source?: string | undefined; metadata?: Record<string, unknown> | undefined;}
@@ -145,7 +151,7 @@ export type ShopAddressInput = { firstName: string; lastName: string; s
145
151
 
146
152
  export type ShopApplyDiscountInput = { code: string; orderSubtotal: number; customerEmail?: string | undefined;}
147
153
 
148
- export type ShopBillingInput = { billingName: string; billingNif?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined;}
154
+ export type ShopBillingInput = { billingName: string; billingNif?: string | undefined; billingIdType?: "NIF" | "02" | "03" | "04" | "05" | "06" | undefined; billingIdCountry?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined;}
149
155
 
150
156
  export type ShopBundleComponent = { quantity: number; component: { id: string; name: string; slug: string; price: number; };}
151
157
 
@@ -165,11 +171,11 @@ export type ShopCategory = { id: string; name: string; slug: string;
165
171
  */
166
172
  export type ShopCheckEmailInput = { email: string;}
167
173
 
168
- export type ShopCheckoutInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[]; customerEmail: string; customerName: string; successUrl: string; cancelUrl: string; customerPhone?: string | null | undefined; discountCode?: string | undefined; shippingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; billing?: { billingName: string; billingNif?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; } | undefined;}
174
+ export type ShopCheckoutInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[]; customerEmail: string; customerName: string; successUrl: string; cancelUrl: string; customerPhone?: string | null | undefined; discountCode?: string | undefined; shippingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; billing?: { billingName: string; billingNif?: string | undefined; billingIdType?: "NIF" | "02" | "03" | "04" | "05" | "06" | undefined; billingIdCountry?: string | undefined; billingEmail?: string | undefined; billingAddress?: { firstName: string; lastName: string; street: string; city: string; postalCode: string; region?: string | undefined; country?: string | undefined; phone?: string | null | undefined; } | undefined; } | undefined; wantsFullInvoice?: boolean | undefined;}
169
175
 
170
176
  export type ShopCheckoutSession = { url: string; sessionId: string;}
171
177
 
172
- export type ShopConfig = { shopName: string | null; defaultLowStockThreshold: number; currencyCode: string; stripePublishableKey: string | null; stripeTestPublishableKey: string | null; stripeTestMode: boolean; shippingEnabled: boolean; pickupEnabled: boolean; taxEnabled: boolean; taxIncludedInPrice: boolean; productTrustItems?: { [x: string]: unknown; icon: (string & {}) | "shipping" | "returns" | "secure-payment" | "support" | "gift" | "pickup" | "warranty" | "quality"; text: string; }[] | null | undefined;}
178
+ export type ShopConfig = { shopName: string | null; defaultLowStockThreshold: number; currencyCode: string; stripePublishableKey: string | null; stripeTestPublishableKey: string | null; stripeTestMode: boolean; shippingEnabled: boolean; pickupEnabled: boolean; taxEnabled: boolean; taxIncludedInPrice: boolean; simplifiedInvoiceCapCents?: number | null | undefined; productTrustItems?: { [x: string]: unknown; icon: (string & {}) | "shipping" | "returns" | "secure-payment" | "support" | "gift" | "pickup" | "warranty" | "quality"; text: string; }[] | null | undefined;}
173
179
 
174
180
  export type ShopDiscountApplication = { valid: boolean; discount: number; type: "PERCENTAGE" | "FIXED" | null; code: string | null; error?: string | undefined;}
175
181
 
@@ -181,13 +187,15 @@ export type ShopDiscountApplication = { valid: boolean; discount: number;
181
187
  */
182
188
  export type ShopEmailCheck = { exists: boolean;}
183
189
 
184
- export type ShopErrorCode = "STOCK_CHANGED" | "PRICE_CHANGED" | "PRODUCT_UNAVAILABLE" | "DISCOUNT_INVALID" | "SHIPPING_UNAVAILABLE" | "INVALID_INPUT" | "STORE_DISABLED" | "PAYMENT_PROVIDER_ERROR" | "INTERNAL_ERROR"
190
+ export type ShopErrorCode = "STOCK_CHANGED" | "PRICE_CHANGED" | "PRODUCT_UNAVAILABLE" | "DISCOUNT_INVALID" | "SHIPPING_UNAVAILABLE" | "INVALID_INPUT" | "STORE_DISABLED" | "PAYMENT_PROVIDER_ERROR" | "INTERNAL_ERROR" | "BILLING_DATA_REQUIRED" | "INVOICING_NOT_READY" | "FULL_INVOICE_UNAVAILABLE"
185
191
 
186
192
  export type ShopFacets = { taxonomies: { key: string; label: string; showAsBadge: boolean; selectionMode: "single" | "multiple"; terms: { slug: string; name: string; count: number; }[]; }[]; attributes: { key: string; label: string; valueType: "boolean" | "text" | "select" | "multiselect"; options: { value: string; label: string; count: number; }[]; }[]; price: { min: number; max: number; }; onSale: { count: number; };}
187
193
 
188
194
  export type ShopInventoryRef = { stockQuantity: number; reservedQuantity: number; lowStockThreshold: number | null;}
189
195
 
190
- export type ShopOrder = { id: string; orderNumber: string; status: "PENDING" | "CONFIRMED" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED" | "REFUNDED"; paymentStatus: "PENDING" | "REFUNDED" | "PAID" | "FAILED" | "PARTIALLY_REFUNDED"; customerEmail: string; total: number; items: { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined; }[];}
196
+ export type ShopOrder = { id: string; orderNumber: string; status: "PENDING" | "CONFIRMED" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED" | "REFUNDED"; paymentStatus: "PENDING" | "REFUNDED" | "PAID" | "FAILED" | "PARTIALLY_REFUNDED"; customerEmail: string; total: number; items: { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined; }[]; invoice?: { number: string; url: string; } | null | undefined;}
197
+
198
+ export type ShopOrderInvoice = { number: string; url: string;}
191
199
 
192
200
  export type ShopOrderItem = { product: { id: string; name: string; slug: string; }; quantity: number; unitPrice: number; total: number; variant?: { id: string; name: string; } | null | undefined;}
193
201
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reblu/site-contracts",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "private": false,
5
5
  "description": "Public, dependency-free TypeScript types for the Reblu SITE API (types only — no Zod, no Prisma at runtime).",
6
6
  "license": "Apache-2.0",