@reblu/site-contracts 1.1.0 → 1.3.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 +74 -0
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# @reblu/site-contracts
|
|
2
2
|
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- baa36cf: Expose each taxonomy axis's selection mode on `ShopFacets` (REB-809).
|
|
8
|
+
|
|
9
|
+
`ShopFacets.taxonomies[].selectionMode` is a new required field: `'single' |
|
|
10
|
+
'multiple'`, mirroring REB-801's per-axis `TaxonomySelectionMode`. It reflects
|
|
11
|
+
how many terms a PRODUCT may carry on that axis, not how many the SITE
|
|
12
|
+
storefront filter may select at once — `GET /api/site/shop/products`'s
|
|
13
|
+
`taxonomy[<key>]` param still accepts only one term slug per axis regardless
|
|
14
|
+
of this value (see `@reblu/site-blocks`'s `ShopFilters` docs).
|
|
15
|
+
|
|
16
|
+
Additive: a new required field on the existing `ShopFacets` shape, populated
|
|
17
|
+
for every axis. A SITE build that has not migrated its `ShopFacets` type yet
|
|
18
|
+
keeps working unchanged — the extra field is simply ignored at runtime.
|
|
19
|
+
|
|
20
|
+
## 1.2.0
|
|
21
|
+
|
|
22
|
+
### Minor Changes
|
|
23
|
+
|
|
24
|
+
- 34b15c4: Expose the academy verification gate's field list on `AcademyCourseDetail` (REB-83).
|
|
25
|
+
|
|
26
|
+
`AcademyCourseDetail.validationFields` is a new field: an ordered array of
|
|
27
|
+
`AcademyValidationFieldPublic` (`{ key, label, required, maxLength? }`), the
|
|
28
|
+
tenant's OWN configured list of data points its access-validation gate asks
|
|
29
|
+
for (e.g. a colegiado number and a professional college), resolved server-side
|
|
30
|
+
from `AcademyConfig.validationFields` — or derived as a single legacy field
|
|
31
|
+
under the key `'validationField'` when the tenant has not configured a list
|
|
32
|
+
yet, so an already-integrated SITE keeps working unchanged. A SITE renders
|
|
33
|
+
its enrollment form from this array instead of a fixed field.
|
|
34
|
+
|
|
35
|
+
Additive: a new required field on the existing `AcademyCourseDetail` shape
|
|
36
|
+
(populated for every course, empty array when the gate does not apply) and a
|
|
37
|
+
new exported type. The existing `validationFieldLabel` field is unchanged and
|
|
38
|
+
still present for a SITE build that has not migrated to the new array yet.
|
|
39
|
+
|
|
40
|
+
- 7ff47d7: Add the cookie-consent fields to `Analytics` (REB-642). _Entry added after
|
|
41
|
+
publishing (REB-787): these fields shipped in 1.2.0, but no changeset
|
|
42
|
+
targeted this package, so the generated notes above left them out._
|
|
43
|
+
|
|
44
|
+
`GET /api/site/analytics` now also returns what a SITE needs to run the
|
|
45
|
+
`@reblu/site-next/consent` banner. There is still one request, and the root
|
|
46
|
+
layout already makes it:
|
|
47
|
+
- `consentRequired: boolean`: `true` when the tenant has a valid GA4 or
|
|
48
|
+
Clarity id (computed from the already-validated `gaId`/`clarityId`, so an
|
|
49
|
+
id that fails validation never requires a banner). reCAPTCHA is excluded
|
|
50
|
+
on purpose because it is strictly necessary. `false` means no configured
|
|
51
|
+
vendor needs consent, so the SITE can skip the banner.
|
|
52
|
+
`<ConsentedAnalytics>` does not read this field.
|
|
53
|
+
- `cookiePolicyVersion: string | null`: a content hash of the tenant's cookie
|
|
54
|
+
policy. It is the same algorithm as `cookiePolicyVersion()` in
|
|
55
|
+
`@reblu/site-next/consent-server` on the same text, and a shared test
|
|
56
|
+
vector keeps the two identical. Pass it to
|
|
57
|
+
`<ConsentProvider policyVersion>`. When the tenant edits the policy in
|
|
58
|
+
nexus, the hash changes and visitors are asked again. `null` means no
|
|
59
|
+
policy is stored.
|
|
60
|
+
- `cookieBanner`: the banner copy the tenant edits in nexus:
|
|
61
|
+
`{ enabled, title, body, acceptLabel, rejectLabel, manageLabel, policyUrl }`.
|
|
62
|
+
A `null` text field means the SDK default applies. Map `body` to the
|
|
63
|
+
banner's `description` text and `policyUrl` to `policyHref`. The buttons
|
|
64
|
+
and categories are fixed and have no field here.
|
|
65
|
+
- `cookieInventory`: `{ vendor, category }[]`, where `category` is
|
|
66
|
+
`'necessary' | 'analytics' | 'marketing'`. It lists only the vendors this
|
|
67
|
+
SITE actually loads, and is meant for the cookie-policy table.
|
|
68
|
+
|
|
69
|
+
**Consumer note:** the four fields are required on the `Analytics` type.
|
|
70
|
+
Runtime responses always include them, but code that builds an `Analytics`
|
|
71
|
+
object by hand (for example test fixtures) must now set them. A neutral
|
|
72
|
+
fixture is `consentRequired: false`, `cookiePolicyVersion: null`,
|
|
73
|
+
`cookieBanner: { enabled: true, title: null, body: null, acceptLabel: null,
|
|
74
|
+
rejectLabel: null, manageLabel: null, policyUrl: null }`,
|
|
75
|
+
`cookieInventory: []`.
|
|
76
|
+
|
|
3
77
|
## 1.1.0
|
|
4
78
|
|
|
5
79
|
### Minor Changes
|
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type AcademyCategoryPublic = { id: string; name: string; slug: string; sortOrder: number;}
|
|
7
7
|
|
|
8
|
-
export type AcademyCourseDetail = { id: string; slug: string; title: string; shortDescription: string | null; coverUrl: string | null; priceCents: number; accessMode: "IMMEDIATE" | "DRIP" | "COHORT"; category: { id: string; name: string; slug: string; sortOrder: number; } | null; description: string | null; modules: { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[]; }[]; instructors: { id: string; firstName: string | null; lastName: string | null; avatarUrl: string | null; }[]; salesEnabled: boolean; requiresValidation: boolean; validationFieldLabel: string | null;}
|
|
8
|
+
export type AcademyCourseDetail = { id: string; slug: string; title: string; shortDescription: string | null; coverUrl: string | null; priceCents: number; accessMode: "IMMEDIATE" | "DRIP" | "COHORT"; category: { id: string; name: string; slug: string; sortOrder: number; } | null; description: string | null; modules: { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[]; }[]; instructors: { id: string; firstName: string | null; lastName: string | null; avatarUrl: string | null; }[]; salesEnabled: boolean; requiresValidation: boolean; validationFieldLabel: string | null; validationFields: { key: string; label: string; required: boolean; maxLength?: number | undefined; }[];}
|
|
9
9
|
|
|
10
10
|
export type AcademyCourseSort = "price_asc" | "price_desc" | "newest"
|
|
11
11
|
|
|
@@ -17,7 +17,9 @@ export type AcademyLessonPublic = { id: string; slug: string; title: st
|
|
|
17
17
|
|
|
18
18
|
export type AcademyModulePublic = { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[];}
|
|
19
19
|
|
|
20
|
-
export type
|
|
20
|
+
export type AcademyValidationFieldPublic = { key: string; label: string; required: boolean; maxLength?: number | undefined;}
|
|
21
|
+
|
|
22
|
+
export type Analytics = { gaId: string | null; clarityId: string | null; recaptchaSiteKey: string | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; metaPixelId: string | null; metaVerificationContent: string | null; googleVerificationContent: string | null; consentRequired: boolean; cookiePolicyVersion: string | null; cookieBanner: { enabled: boolean; title: string | null; body: string | null; acceptLabel: string | null; rejectLabel: string | null; manageLabel: string | null; policyUrl: string | null; }; cookieInventory: { vendor: string; category: "necessary" | "analytics" | "marketing"; }[];}
|
|
21
23
|
|
|
22
24
|
export type BlogAuthor = { firstName: string | null; lastName: string | null; avatarUrl: string | null;}
|
|
23
25
|
|
|
@@ -143,7 +145,7 @@ export type ShopDiscountApplication = { valid: boolean; discount: number;
|
|
|
143
145
|
|
|
144
146
|
export type ShopEmailCheck = { exists: boolean;}
|
|
145
147
|
|
|
146
|
-
export type ShopFacets = { taxonomies: { key: string; label: string; showAsBadge: boolean; 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; };}
|
|
148
|
+
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; };}
|
|
147
149
|
|
|
148
150
|
export type ShopInventoryRef = { stockQuantity: number; reservedQuantity: number; lowStockThreshold: number | null;}
|
|
149
151
|
|
|
@@ -169,6 +171,8 @@ export type ShopSort = "price_asc" | "price_desc" | "newest" | "on_sale"
|
|
|
169
171
|
|
|
170
172
|
export type ShopTaxRateRef = { rate: number; type: "IVA" | "IGIC" | "RETENTION" | "OTHER"; isExempt: boolean;}
|
|
171
173
|
|
|
174
|
+
export type ShopTaxonomySelectionMode = "single" | "multiple"
|
|
175
|
+
|
|
172
176
|
export type ShopTaxonomyTermRef = { taxonomyKey: string; taxonomyLabel: string; showAsBadge: boolean; slug: string; name: string; imageUrl: string | null;}
|
|
173
177
|
|
|
174
178
|
export type ShopValidateCartInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[];}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type AcademyCategoryPublic = { id: string; name: string; slug: string; sortOrder: number;}
|
|
7
7
|
|
|
8
|
-
export type AcademyCourseDetail = { id: string; slug: string; title: string; shortDescription: string | null; coverUrl: string | null; priceCents: number; accessMode: "IMMEDIATE" | "DRIP" | "COHORT"; category: { id: string; name: string; slug: string; sortOrder: number; } | null; description: string | null; modules: { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[]; }[]; instructors: { id: string; firstName: string | null; lastName: string | null; avatarUrl: string | null; }[]; salesEnabled: boolean; requiresValidation: boolean; validationFieldLabel: string | null;}
|
|
8
|
+
export type AcademyCourseDetail = { id: string; slug: string; title: string; shortDescription: string | null; coverUrl: string | null; priceCents: number; accessMode: "IMMEDIATE" | "DRIP" | "COHORT"; category: { id: string; name: string; slug: string; sortOrder: number; } | null; description: string | null; modules: { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[]; }[]; instructors: { id: string; firstName: string | null; lastName: string | null; avatarUrl: string | null; }[]; salesEnabled: boolean; requiresValidation: boolean; validationFieldLabel: string | null; validationFields: { key: string; label: string; required: boolean; maxLength?: number | undefined; }[];}
|
|
9
9
|
|
|
10
10
|
export type AcademyCourseSort = "price_asc" | "price_desc" | "newest"
|
|
11
11
|
|
|
@@ -17,7 +17,9 @@ export type AcademyLessonPublic = { id: string; slug: string; title: st
|
|
|
17
17
|
|
|
18
18
|
export type AcademyModulePublic = { id: string; title: string; description: string | null; lessons: { id: string; slug: string; title: string; isFreePreview: boolean; durationSeconds: number | null; hasVideo: boolean; }[];}
|
|
19
19
|
|
|
20
|
-
export type
|
|
20
|
+
export type AcademyValidationFieldPublic = { key: string; label: string; required: boolean; maxLength?: number | undefined;}
|
|
21
|
+
|
|
22
|
+
export type Analytics = { gaId: string | null; clarityId: string | null; recaptchaSiteKey: string | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; metaPixelId: string | null; metaVerificationContent: string | null; googleVerificationContent: string | null; consentRequired: boolean; cookiePolicyVersion: string | null; cookieBanner: { enabled: boolean; title: string | null; body: string | null; acceptLabel: string | null; rejectLabel: string | null; manageLabel: string | null; policyUrl: string | null; }; cookieInventory: { vendor: string; category: "necessary" | "analytics" | "marketing"; }[];}
|
|
21
23
|
|
|
22
24
|
export type BlogAuthor = { firstName: string | null; lastName: string | null; avatarUrl: string | null;}
|
|
23
25
|
|
|
@@ -143,7 +145,7 @@ export type ShopDiscountApplication = { valid: boolean; discount: number;
|
|
|
143
145
|
|
|
144
146
|
export type ShopEmailCheck = { exists: boolean;}
|
|
145
147
|
|
|
146
|
-
export type ShopFacets = { taxonomies: { key: string; label: string; showAsBadge: boolean; 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; };}
|
|
148
|
+
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; };}
|
|
147
149
|
|
|
148
150
|
export type ShopInventoryRef = { stockQuantity: number; reservedQuantity: number; lowStockThreshold: number | null;}
|
|
149
151
|
|
|
@@ -169,6 +171,8 @@ export type ShopSort = "price_asc" | "price_desc" | "newest" | "on_sale"
|
|
|
169
171
|
|
|
170
172
|
export type ShopTaxRateRef = { rate: number; type: "IVA" | "IGIC" | "RETENTION" | "OTHER"; isExempt: boolean;}
|
|
171
173
|
|
|
174
|
+
export type ShopTaxonomySelectionMode = "single" | "multiple"
|
|
175
|
+
|
|
172
176
|
export type ShopTaxonomyTermRef = { taxonomyKey: string; taxonomyLabel: string; showAsBadge: boolean; slug: string; name: string; imageUrl: string | null;}
|
|
173
177
|
|
|
174
178
|
export type ShopValidateCartInput = { items: { productId: string; quantity: number; variantId?: string | null | undefined; }[];}
|
package/package.json
CHANGED