@rebuy/rebuy 3.60.4 → 3.61.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/dist/index.cjs CHANGED
@@ -1228,7 +1228,22 @@ var SmartCartTierProduct = import_zod.z.looseObject({
1228
1228
  });
1229
1229
  var SmartCartTierExclusion = import_zod.z.looseObject({
1230
1230
  collectionIds: import_zod.z.array(import_zod.z.coerce.number()).optional().catch(void 0),
1231
- productIds: import_zod.z.array(import_zod.z.coerce.number()).optional().catch(void 0),
1231
+ /**
1232
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
1233
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
1234
+ * Flat parallel id lists cannot express that mapping.
1235
+ *
1236
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
1237
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
1238
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
1239
+ * rule in silence — the exclusion just never reaches checkout.
1240
+ */
1241
+ products: import_zod.z.array(
1242
+ import_zod.z.looseObject({
1243
+ productId: import_zod.z.coerce.number().optional().catch(void 0),
1244
+ variantIds: import_zod.z.array(import_zod.z.coerce.number()).optional().catch(void 0)
1245
+ })
1246
+ ).optional().catch(void 0),
1232
1247
  tags: import_zod.z.array(import_zod.z.string()).optional().catch(void 0),
1233
1248
  type: import_zod.z.string().optional().catch(void 0)
1234
1249
  });
@@ -4124,7 +4139,17 @@ var GIFT_LABELS = {
4124
4139
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
4125
4140
  var CABProgressTierExclusion = import_zod61.z.object({
4126
4141
  collectionIds: import_zod61.z.array(import_zod61.z.number().int().positive()).default(() => []),
4127
- productIds: import_zod61.z.array(import_zod61.z.number().int().positive()).default(() => []),
4142
+ /**
4143
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
4144
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
4145
+ * picker stores a whole-product selection, and a populated one means those variants.
4146
+ */
4147
+ products: import_zod61.z.array(
4148
+ import_zod61.z.object({
4149
+ productId: import_zod61.z.number().int().positive(),
4150
+ variantIds: import_zod61.z.array(import_zod61.z.number().int().positive()).default(() => [])
4151
+ })
4152
+ ).default(() => []),
4128
4153
  tags: import_zod61.z.array(import_zod61.z.string().min(1)).default(() => []),
4129
4154
  type: import_zod61.z.enum(progressTierExclusionTypes)
4130
4155
  });
package/dist/index.mjs CHANGED
@@ -746,7 +746,22 @@ var SmartCartTierProduct = z.looseObject({
746
746
  });
747
747
  var SmartCartTierExclusion = z.looseObject({
748
748
  collectionIds: z.array(z.coerce.number()).optional().catch(void 0),
749
- productIds: z.array(z.coerce.number()).optional().catch(void 0),
749
+ /**
750
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
751
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
752
+ * Flat parallel id lists cannot express that mapping.
753
+ *
754
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
755
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
756
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
757
+ * rule in silence — the exclusion just never reaches checkout.
758
+ */
759
+ products: z.array(
760
+ z.looseObject({
761
+ productId: z.coerce.number().optional().catch(void 0),
762
+ variantIds: z.array(z.coerce.number()).optional().catch(void 0)
763
+ })
764
+ ).optional().catch(void 0),
750
765
  tags: z.array(z.string()).optional().catch(void 0),
751
766
  type: z.string().optional().catch(void 0)
752
767
  });
@@ -3642,7 +3657,17 @@ var GIFT_LABELS = {
3642
3657
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
3643
3658
  var CABProgressTierExclusion = z61.object({
3644
3659
  collectionIds: z61.array(z61.number().int().positive()).default(() => []),
3645
- productIds: z61.array(z61.number().int().positive()).default(() => []),
3660
+ /**
3661
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
3662
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
3663
+ * picker stores a whole-product selection, and a populated one means those variants.
3664
+ */
3665
+ products: z61.array(
3666
+ z61.object({
3667
+ productId: z61.number().int().positive(),
3668
+ variantIds: z61.array(z61.number().int().positive()).default(() => [])
3669
+ })
3670
+ ).default(() => []),
3646
3671
  tags: z61.array(z61.string().min(1)).default(() => []),
3647
3672
  type: z61.enum(progressTierExclusionTypes)
3648
3673
  });
@@ -138,7 +138,10 @@ export declare const CabUserConfig: z.ZodObject<{
138
138
  discountType: z.ZodOptional<z.ZodString>;
139
139
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
140
140
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
141
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
141
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
142
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
143
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
144
+ }, z.core.$loose>>>>;
142
145
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
143
146
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
144
147
  }, z.core.$loose>>>>;
@@ -1317,7 +1317,17 @@ var GIFT_LABELS = {
1317
1317
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1318
1318
  var CABProgressTierExclusion = import_zod15.z.object({
1319
1319
  collectionIds: import_zod15.z.array(import_zod15.z.number().int().positive()).default(() => []),
1320
- productIds: import_zod15.z.array(import_zod15.z.number().int().positive()).default(() => []),
1320
+ /**
1321
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1322
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1323
+ * picker stores a whole-product selection, and a populated one means those variants.
1324
+ */
1325
+ products: import_zod15.z.array(
1326
+ import_zod15.z.object({
1327
+ productId: import_zod15.z.number().int().positive(),
1328
+ variantIds: import_zod15.z.array(import_zod15.z.number().int().positive()).default(() => [])
1329
+ })
1330
+ ).default(() => []),
1321
1331
  tags: import_zod15.z.array(import_zod15.z.string().min(1)).default(() => []),
1322
1332
  type: import_zod15.z.enum(progressTierExclusionTypes)
1323
1333
  });
@@ -1102,7 +1102,17 @@ var GIFT_LABELS = {
1102
1102
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1103
1103
  var CABProgressTierExclusion = z15.object({
1104
1104
  collectionIds: z15.array(z15.number().int().positive()).default(() => []),
1105
- productIds: z15.array(z15.number().int().positive()).default(() => []),
1105
+ /**
1106
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1107
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1108
+ * picker stores a whole-product selection, and a populated one means those variants.
1109
+ */
1110
+ products: z15.array(
1111
+ z15.object({
1112
+ productId: z15.number().int().positive(),
1113
+ variantIds: z15.array(z15.number().int().positive()).default(() => [])
1114
+ })
1115
+ ).default(() => []),
1106
1116
  tags: z15.array(z15.string().min(1)).default(() => []),
1107
1117
  type: z15.enum(progressTierExclusionTypes)
1108
1118
  });
@@ -23,7 +23,10 @@ export declare const SmartCartTierProduct: z.ZodObject<{
23
23
  */
24
24
  export declare const SmartCartTierExclusion: z.ZodObject<{
25
25
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
26
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
26
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
27
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
28
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
29
+ }, z.core.$loose>>>>;
27
30
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
28
31
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
29
32
  }, z.core.$loose>;
@@ -61,7 +64,10 @@ export declare const SmartCartTier: z.ZodObject<{
61
64
  discountType: z.ZodOptional<z.ZodString>;
62
65
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
63
66
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
64
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
67
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
68
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
69
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
70
+ }, z.core.$loose>>>>;
65
71
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
66
72
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
67
73
  }, z.core.$loose>>>>;
@@ -130,7 +136,10 @@ export declare const SmartCartBar: z.ZodObject<{
130
136
  discountType: z.ZodOptional<z.ZodString>;
131
137
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
132
138
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
133
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
139
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
140
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
141
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
142
+ }, z.core.$loose>>>>;
134
143
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
135
144
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
136
145
  }, z.core.$loose>>>>;
@@ -198,7 +207,10 @@ export declare const SmartCartComponent: z.ZodObject<{
198
207
  discountType: z.ZodOptional<z.ZodString>;
199
208
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
200
209
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
201
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
210
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
211
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
212
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
213
+ }, z.core.$loose>>>>;
202
214
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
203
215
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
204
216
  }, z.core.$loose>>>>;
@@ -277,7 +289,10 @@ export declare const SmartCartConfig: z.ZodObject<{
277
289
  discountType: z.ZodOptional<z.ZodString>;
278
290
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
279
291
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
280
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
292
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
293
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
294
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
295
+ }, z.core.$loose>>>>;
281
296
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
282
297
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
283
298
  }, z.core.$loose>>>>;
@@ -312,4 +327,5 @@ export declare const SmartCartConfig: z.ZodObject<{
312
327
  export type SmartCartBar = z.infer<typeof SmartCartBar>;
313
328
  export type SmartCartConfig = z.infer<typeof SmartCartConfig>;
314
329
  export type SmartCartTier = z.infer<typeof SmartCartTier>;
330
+ export type SmartCartTierExclusion = z.infer<typeof SmartCartTierExclusion>;
315
331
  export type SmartCartTierProduct = z.infer<typeof SmartCartTierProduct>;
@@ -127,7 +127,22 @@ var SmartCartTierProduct = import_zod2.z.looseObject({
127
127
  });
128
128
  var SmartCartTierExclusion = import_zod2.z.looseObject({
129
129
  collectionIds: import_zod2.z.array(import_zod2.z.coerce.number()).optional().catch(void 0),
130
- productIds: import_zod2.z.array(import_zod2.z.coerce.number()).optional().catch(void 0),
130
+ /**
131
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
132
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
133
+ * Flat parallel id lists cannot express that mapping.
134
+ *
135
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
136
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
137
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
138
+ * rule in silence — the exclusion just never reaches checkout.
139
+ */
140
+ products: import_zod2.z.array(
141
+ import_zod2.z.looseObject({
142
+ productId: import_zod2.z.coerce.number().optional().catch(void 0),
143
+ variantIds: import_zod2.z.array(import_zod2.z.coerce.number()).optional().catch(void 0)
144
+ })
145
+ ).optional().catch(void 0),
131
146
  tags: import_zod2.z.array(import_zod2.z.string()).optional().catch(void 0),
132
147
  type: import_zod2.z.string().optional().catch(void 0)
133
148
  });
@@ -103,7 +103,22 @@ var SmartCartTierProduct = z2.looseObject({
103
103
  });
104
104
  var SmartCartTierExclusion = z2.looseObject({
105
105
  collectionIds: z2.array(z2.coerce.number()).optional().catch(void 0),
106
- productIds: z2.array(z2.coerce.number()).optional().catch(void 0),
106
+ /**
107
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
108
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
109
+ * Flat parallel id lists cannot express that mapping.
110
+ *
111
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
112
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
113
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
114
+ * rule in silence — the exclusion just never reaches checkout.
115
+ */
116
+ products: z2.array(
117
+ z2.looseObject({
118
+ productId: z2.coerce.number().optional().catch(void 0),
119
+ variantIds: z2.array(z2.coerce.number()).optional().catch(void 0)
120
+ })
121
+ ).optional().catch(void 0),
107
122
  tags: z2.array(z2.string()).optional().catch(void 0),
108
123
  type: z2.string().optional().catch(void 0)
109
124
  });
@@ -118,7 +118,10 @@ export declare const UserConfig: z.ZodObject<{
118
118
  discountType: z.ZodOptional<z.ZodString>;
119
119
  exclusions: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
120
120
  collectionIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
121
- productIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
121
+ products: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodObject<{
122
+ productId: z.ZodCatch<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
123
+ variantIds: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>>;
124
+ }, z.core.$loose>>>>;
122
125
  tags: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodString>>>;
123
126
  type: z.ZodCatch<z.ZodOptional<z.ZodString>>;
124
127
  }, z.core.$loose>>>>;
@@ -1138,7 +1138,17 @@ var GIFT_LABELS = {
1138
1138
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1139
1139
  var CABProgressTierExclusion = import_zod18.z.object({
1140
1140
  collectionIds: import_zod18.z.array(import_zod18.z.number().int().positive()).default(() => []),
1141
- productIds: import_zod18.z.array(import_zod18.z.number().int().positive()).default(() => []),
1141
+ /**
1142
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1143
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1144
+ * picker stores a whole-product selection, and a populated one means those variants.
1145
+ */
1146
+ products: import_zod18.z.array(
1147
+ import_zod18.z.object({
1148
+ productId: import_zod18.z.number().int().positive(),
1149
+ variantIds: import_zod18.z.array(import_zod18.z.number().int().positive()).default(() => [])
1150
+ })
1151
+ ).default(() => []),
1142
1152
  tags: import_zod18.z.array(import_zod18.z.string().min(1)).default(() => []),
1143
1153
  type: import_zod18.z.enum(progressTierExclusionTypes)
1144
1154
  });
@@ -1113,7 +1113,17 @@ var GIFT_LABELS = {
1113
1113
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1114
1114
  var CABProgressTierExclusion = z18.object({
1115
1115
  collectionIds: z18.array(z18.number().int().positive()).default(() => []),
1116
- productIds: z18.array(z18.number().int().positive()).default(() => []),
1116
+ /**
1117
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1118
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1119
+ * picker stores a whole-product selection, and a populated one means those variants.
1120
+ */
1121
+ products: z18.array(
1122
+ z18.object({
1123
+ productId: z18.number().int().positive(),
1124
+ variantIds: z18.array(z18.number().int().positive()).default(() => [])
1125
+ })
1126
+ ).default(() => []),
1117
1127
  tags: z18.array(z18.string().min(1)).default(() => []),
1118
1128
  type: z18.enum(progressTierExclusionTypes)
1119
1129
  });
@@ -235,8 +235,8 @@ export type ProgressTierUnit = (typeof progressTierUnits)[number];
235
235
  /** What a per-tier exclusion rule matches cart lines by (onsite `CartProgressBarTierExclusionType`). */
236
236
  export declare const progressTierExclusionTypes: readonly ["collections", "products", "tags"];
237
237
  export declare const ProgressTierExclusionType: {
238
- readonly tags: "tags";
239
238
  readonly products: "products";
239
+ readonly tags: "tags";
240
240
  readonly collections: "collections";
241
241
  };
242
242
  export type ProgressTierExclusionType = (typeof progressTierExclusionTypes)[number];
@@ -5,16 +5,20 @@ import { type SectionDetails } from './shared';
5
5
  * One per-tier exclusion rule (onsite `getTierExclusionTotal`): cart lines matching the rule's `type` list
6
6
  * are subtracted from THIS tier's progress only, after the bar-level exclusions (gift lines, the exclusion
7
7
  * tag, `excludedVariantIds`) have already removed theirs — so a line is never double-counted. The client
8
- * resolves collections and tags per cart product from the Storefront API; `productIds` match the line's
9
- * product directly. Lists default empty so a rule always reads as "match nothing" rather than throwing.
8
+ * resolves collections and tags per cart product from the Storefront API; `products` match the line's
9
+ * product directly, narrowed to the entry's `variantIds` when it lists any. Lists default empty
10
+ * so a rule always reads as "match nothing" rather than throwing.
10
11
  */
11
12
  export declare const CABProgressTierExclusion: z.ZodObject<{
12
13
  collectionIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
13
- productIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
14
+ products: z.ZodDefault<z.ZodArray<z.ZodObject<{
15
+ productId: z.ZodNumber;
16
+ variantIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
17
+ }, z.core.$strip>>>;
14
18
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
15
19
  type: z.ZodEnum<{
16
- tags: "tags";
17
20
  products: "products";
21
+ tags: "tags";
18
22
  collections: "collections";
19
23
  }>;
20
24
  }, z.core.$strip>;
@@ -29,11 +33,14 @@ export declare const CABProgressTier: z.ZodObject<{
29
33
  }, z.core.$strip>>;
30
34
  exclusions: z.ZodDefault<z.ZodArray<z.ZodObject<{
31
35
  collectionIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
32
- productIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
36
+ products: z.ZodDefault<z.ZodArray<z.ZodObject<{
37
+ productId: z.ZodNumber;
38
+ variantIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
39
+ }, z.core.$strip>>>;
33
40
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
34
41
  type: z.ZodEnum<{
35
- tags: "tags";
36
42
  products: "products";
43
+ tags: "tags";
37
44
  collections: "collections";
38
45
  }>;
39
46
  }, z.core.$strip>>>;
@@ -373,11 +380,14 @@ export declare const CABProgressBarSection: z.ZodLazy<z.ZodObject<{
373
380
  }, z.core.$strip>>;
374
381
  exclusions: z.ZodDefault<z.ZodArray<z.ZodObject<{
375
382
  collectionIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
376
- productIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
383
+ products: z.ZodDefault<z.ZodArray<z.ZodObject<{
384
+ productId: z.ZodNumber;
385
+ variantIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
386
+ }, z.core.$strip>>>;
377
387
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
378
388
  type: z.ZodEnum<{
379
- tags: "tags";
380
389
  products: "products";
390
+ tags: "tags";
381
391
  collections: "collections";
382
392
  }>;
383
393
  }, z.core.$strip>>>;
@@ -1576,7 +1576,22 @@ var SmartCartTierProduct = import_zod19.z.looseObject({
1576
1576
  });
1577
1577
  var SmartCartTierExclusion = import_zod19.z.looseObject({
1578
1578
  collectionIds: import_zod19.z.array(import_zod19.z.coerce.number()).optional().catch(void 0),
1579
- productIds: import_zod19.z.array(import_zod19.z.coerce.number()).optional().catch(void 0),
1579
+ /**
1580
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
1581
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
1582
+ * Flat parallel id lists cannot express that mapping.
1583
+ *
1584
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
1585
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
1586
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
1587
+ * rule in silence — the exclusion just never reaches checkout.
1588
+ */
1589
+ products: import_zod19.z.array(
1590
+ import_zod19.z.looseObject({
1591
+ productId: import_zod19.z.coerce.number().optional().catch(void 0),
1592
+ variantIds: import_zod19.z.array(import_zod19.z.coerce.number()).optional().catch(void 0)
1593
+ })
1594
+ ).optional().catch(void 0),
1580
1595
  tags: import_zod19.z.array(import_zod19.z.string()).optional().catch(void 0),
1581
1596
  type: import_zod19.z.string().optional().catch(void 0)
1582
1597
  });
@@ -2388,7 +2403,17 @@ var GIFT_LABELS = {
2388
2403
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
2389
2404
  var CABProgressTierExclusion = import_zod33.z.object({
2390
2405
  collectionIds: import_zod33.z.array(import_zod33.z.number().int().positive()).default(() => []),
2391
- productIds: import_zod33.z.array(import_zod33.z.number().int().positive()).default(() => []),
2406
+ /**
2407
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
2408
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
2409
+ * picker stores a whole-product selection, and a populated one means those variants.
2410
+ */
2411
+ products: import_zod33.z.array(
2412
+ import_zod33.z.object({
2413
+ productId: import_zod33.z.number().int().positive(),
2414
+ variantIds: import_zod33.z.array(import_zod33.z.number().int().positive()).default(() => [])
2415
+ })
2416
+ ).default(() => []),
2392
2417
  tags: import_zod33.z.array(import_zod33.z.string().min(1)).default(() => []),
2393
2418
  type: import_zod33.z.enum(progressTierExclusionTypes)
2394
2419
  });
@@ -3600,7 +3625,7 @@ var containsHtml = (text) => HTML_TAG_RE2.test(text);
3600
3625
  var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
3601
3626
  var normalizeTextValue = (value, options2 = {}) => {
3602
3627
  const tokenized = normalizeTokens(value);
3603
- return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
3628
+ return containsHtml(tokenized) || options2.defaultTextStyle || options2.blockSpacing ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
3604
3629
  };
3605
3630
  var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
3606
3631
  var normalizeTextContent = (node) => {
@@ -5325,13 +5350,21 @@ var giftOf = (tier) => {
5325
5350
  variantIds: positiveIds(product.variantIds)
5326
5351
  };
5327
5352
  };
5328
- var RULE_LIST = { collections: "collectionIds", products: "productIds", tags: "tags" };
5353
+ var RULE_LIST = { collections: "collectionIds", products: "products", tags: "tags" };
5354
+ var exclusionProducts = (rule) => (rule.products ?? []).flatMap((entry) => {
5355
+ const productId2 = entry.productId;
5356
+ if (!Number.isInteger(productId2) || !productId2 || productId2 <= 0) return [];
5357
+ const requested = entry.variantIds ?? [];
5358
+ const variantIds = positiveIds(requested);
5359
+ if (requested.length > 0 && variantIds.length === 0) return [];
5360
+ return [{ productId: productId2, variantIds }];
5361
+ });
5329
5362
  var exclusionsOf = (tier) => {
5330
5363
  if (!tier.exclusionsEnabled) return void 0;
5331
5364
  const rules = (tier.exclusions ?? []).flatMap((rule) => {
5332
5365
  const parsed = CABProgressTierExclusion.safeParse({
5333
5366
  ...rule.type === "collections" && { collectionIds: positiveIds(rule.collectionIds) },
5334
- ...rule.type === "products" && { productIds: positiveIds(rule.productIds) },
5367
+ ...rule.type === "products" && { products: exclusionProducts(rule) },
5335
5368
  ...rule.type === "tags" && { tags: (rule.tags ?? []).map((tag) => tag.trim()).filter(Boolean) },
5336
5369
  type: rule.type
5337
5370
  });
@@ -5844,7 +5877,7 @@ var label = (text) => ({
5844
5877
  content: { en: text },
5845
5878
  sectionType: SectionType.text
5846
5879
  });
5847
- var AS_DOC = { defaultTextStyle: {} };
5880
+ var AS_DOC = { blockSpacing: Spacing.none, defaultTextStyle: {} };
5848
5881
  var safeTextValue = (raw, options2) => {
5849
5882
  const converted = normalizeTextValue(raw, options2);
5850
5883
  return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
@@ -5872,7 +5905,7 @@ var dspLabel = (raw, fallback) => ({
5872
5905
  sectionType: SectionType.text
5873
5906
  });
5874
5907
  var smallText = (raw) => ({
5875
- content: { en: safeTextValue(raw, { defaultTextStyle: { fontSize: "small" } }) },
5908
+ content: { en: safeTextValue(raw, { blockSpacing: Spacing.none, defaultTextStyle: { fontSize: "small" } }) },
5876
5909
  sectionType: SectionType.text
5877
5910
  });
5878
5911
  var styled = (value, { align, bold, color, fontSize, href }) => ({
@@ -1503,7 +1503,22 @@ var SmartCartTierProduct = z19.looseObject({
1503
1503
  });
1504
1504
  var SmartCartTierExclusion = z19.looseObject({
1505
1505
  collectionIds: z19.array(z19.coerce.number()).optional().catch(void 0),
1506
- productIds: z19.array(z19.coerce.number()).optional().catch(void 0),
1506
+ /**
1507
+ * onsite keeps each excluded product with ITS OWN variants, the same shape the bar-level
1508
+ * `excludedProducts` uses, so a rule can exclude one variant of B without touching A.
1509
+ * Flat parallel id lists cannot express that mapping.
1510
+ *
1511
+ * camelCase like every other key in this file, NOT the `product_id` / `variant_ids` the onsite
1512
+ * payload spells: `parseShielded` runs `deepCamelCase` over the tree BEFORE any schema sees it.
1513
+ * A snake_case key here reads as absent, every entry drops, and the converter discards the whole
1514
+ * rule in silence — the exclusion just never reaches checkout.
1515
+ */
1516
+ products: z19.array(
1517
+ z19.looseObject({
1518
+ productId: z19.coerce.number().optional().catch(void 0),
1519
+ variantIds: z19.array(z19.coerce.number()).optional().catch(void 0)
1520
+ })
1521
+ ).optional().catch(void 0),
1507
1522
  tags: z19.array(z19.string()).optional().catch(void 0),
1508
1523
  type: z19.string().optional().catch(void 0)
1509
1524
  });
@@ -2315,7 +2330,17 @@ var GIFT_LABELS = {
2315
2330
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
2316
2331
  var CABProgressTierExclusion = z33.object({
2317
2332
  collectionIds: z33.array(z33.number().int().positive()).default(() => []),
2318
- productIds: z33.array(z33.number().int().positive()).default(() => []),
2333
+ /**
2334
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
2335
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
2336
+ * picker stores a whole-product selection, and a populated one means those variants.
2337
+ */
2338
+ products: z33.array(
2339
+ z33.object({
2340
+ productId: z33.number().int().positive(),
2341
+ variantIds: z33.array(z33.number().int().positive()).default(() => [])
2342
+ })
2343
+ ).default(() => []),
2319
2344
  tags: z33.array(z33.string().min(1)).default(() => []),
2320
2345
  type: z33.enum(progressTierExclusionTypes)
2321
2346
  });
@@ -3527,7 +3552,7 @@ var containsHtml = (text) => HTML_TAG_RE2.test(text);
3527
3552
  var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
3528
3553
  var normalizeTextValue = (value, options2 = {}) => {
3529
3554
  const tokenized = normalizeTokens(value);
3530
- return containsHtml(tokenized) || options2.defaultTextStyle ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
3555
+ return containsHtml(tokenized) || options2.defaultTextStyle || options2.blockSpacing ? htmlToTiptap(tokenized, options2) : decodeTextEntities(tokenized);
3531
3556
  };
3532
3557
  var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
3533
3558
  var normalizeTextContent = (node) => {
@@ -5252,13 +5277,21 @@ var giftOf = (tier) => {
5252
5277
  variantIds: positiveIds(product.variantIds)
5253
5278
  };
5254
5279
  };
5255
- var RULE_LIST = { collections: "collectionIds", products: "productIds", tags: "tags" };
5280
+ var RULE_LIST = { collections: "collectionIds", products: "products", tags: "tags" };
5281
+ var exclusionProducts = (rule) => (rule.products ?? []).flatMap((entry) => {
5282
+ const productId2 = entry.productId;
5283
+ if (!Number.isInteger(productId2) || !productId2 || productId2 <= 0) return [];
5284
+ const requested = entry.variantIds ?? [];
5285
+ const variantIds = positiveIds(requested);
5286
+ if (requested.length > 0 && variantIds.length === 0) return [];
5287
+ return [{ productId: productId2, variantIds }];
5288
+ });
5256
5289
  var exclusionsOf = (tier) => {
5257
5290
  if (!tier.exclusionsEnabled) return void 0;
5258
5291
  const rules = (tier.exclusions ?? []).flatMap((rule) => {
5259
5292
  const parsed = CABProgressTierExclusion.safeParse({
5260
5293
  ...rule.type === "collections" && { collectionIds: positiveIds(rule.collectionIds) },
5261
- ...rule.type === "products" && { productIds: positiveIds(rule.productIds) },
5294
+ ...rule.type === "products" && { products: exclusionProducts(rule) },
5262
5295
  ...rule.type === "tags" && { tags: (rule.tags ?? []).map((tag) => tag.trim()).filter(Boolean) },
5263
5296
  type: rule.type
5264
5297
  });
@@ -5771,7 +5804,7 @@ var label = (text) => ({
5771
5804
  content: { en: text },
5772
5805
  sectionType: SectionType.text
5773
5806
  });
5774
- var AS_DOC = { defaultTextStyle: {} };
5807
+ var AS_DOC = { blockSpacing: Spacing.none, defaultTextStyle: {} };
5775
5808
  var safeTextValue = (raw, options2) => {
5776
5809
  const converted = normalizeTextValue(raw, options2);
5777
5810
  return checkForHTML(converted) ? converted : normalizeTextValue(htmlToPlainText(raw), options2);
@@ -5799,7 +5832,7 @@ var dspLabel = (raw, fallback) => ({
5799
5832
  sectionType: SectionType.text
5800
5833
  });
5801
5834
  var smallText = (raw) => ({
5802
- content: { en: safeTextValue(raw, { defaultTextStyle: { fontSize: "small" } }) },
5835
+ content: { en: safeTextValue(raw, { blockSpacing: Spacing.none, defaultTextStyle: { fontSize: "small" } }) },
5803
5836
  sectionType: SectionType.text
5804
5837
  });
5805
5838
  var styled = (value, { align, bold, color, fontSize, href }) => ({
@@ -1146,7 +1146,17 @@ var GIFT_LABELS = {
1146
1146
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1147
1147
  var CABProgressTierExclusion = import_zod16.z.object({
1148
1148
  collectionIds: import_zod16.z.array(import_zod16.z.number().int().positive()).default(() => []),
1149
- productIds: import_zod16.z.array(import_zod16.z.number().int().positive()).default(() => []),
1149
+ /**
1150
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1151
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1152
+ * picker stores a whole-product selection, and a populated one means those variants.
1153
+ */
1154
+ products: import_zod16.z.array(
1155
+ import_zod16.z.object({
1156
+ productId: import_zod16.z.number().int().positive(),
1157
+ variantIds: import_zod16.z.array(import_zod16.z.number().int().positive()).default(() => [])
1158
+ })
1159
+ ).default(() => []),
1150
1160
  tags: import_zod16.z.array(import_zod16.z.string().min(1)).default(() => []),
1151
1161
  type: import_zod16.z.enum(progressTierExclusionTypes)
1152
1162
  });
@@ -2358,7 +2368,7 @@ var containsHtml = (text) => HTML_TAG_RE2.test(text);
2358
2368
  var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
2359
2369
  var normalizeTextValue = (value, options = {}) => {
2360
2370
  const tokenized = normalizeTokens(value);
2361
- return containsHtml(tokenized) || options.defaultTextStyle ? htmlToTiptap(tokenized, options) : decodeTextEntities(tokenized);
2371
+ return containsHtml(tokenized) || options.defaultTextStyle || options.blockSpacing ? htmlToTiptap(tokenized, options) : decodeTextEntities(tokenized);
2362
2372
  };
2363
2373
  var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
2364
2374
  var normalizeTextContent = (node) => {
@@ -4875,13 +4885,21 @@ var giftOf = (tier) => {
4875
4885
  variantIds: positiveIds(product.variantIds)
4876
4886
  };
4877
4887
  };
4878
- var RULE_LIST = { collections: "collectionIds", products: "productIds", tags: "tags" };
4888
+ var RULE_LIST = { collections: "collectionIds", products: "products", tags: "tags" };
4889
+ var exclusionProducts = (rule) => (rule.products ?? []).flatMap((entry) => {
4890
+ const productId = entry.productId;
4891
+ if (!Number.isInteger(productId) || !productId || productId <= 0) return [];
4892
+ const requested = entry.variantIds ?? [];
4893
+ const variantIds = positiveIds(requested);
4894
+ if (requested.length > 0 && variantIds.length === 0) return [];
4895
+ return [{ productId, variantIds }];
4896
+ });
4879
4897
  var exclusionsOf = (tier) => {
4880
4898
  if (!tier.exclusionsEnabled) return void 0;
4881
4899
  const rules = (tier.exclusions ?? []).flatMap((rule) => {
4882
4900
  const parsed = CABProgressTierExclusion.safeParse({
4883
4901
  ...rule.type === "collections" && { collectionIds: positiveIds(rule.collectionIds) },
4884
- ...rule.type === "products" && { productIds: positiveIds(rule.productIds) },
4902
+ ...rule.type === "products" && { products: exclusionProducts(rule) },
4885
4903
  ...rule.type === "tags" && { tags: (rule.tags ?? []).map((tag) => tag.trim()).filter(Boolean) },
4886
4904
  type: rule.type
4887
4905
  });
@@ -1085,7 +1085,17 @@ var GIFT_LABELS = {
1085
1085
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
1086
1086
  var CABProgressTierExclusion = z16.object({
1087
1087
  collectionIds: z16.array(z16.number().int().positive()).default(() => []),
1088
- productIds: z16.array(z16.number().int().positive()).default(() => []),
1088
+ /**
1089
+ * `products` rules: each excluded product with ITS OWN variants, mirroring the bar-level
1090
+ * excluded products. An empty `variantIds` means "the whole product", which is how the admin
1091
+ * picker stores a whole-product selection, and a populated one means those variants.
1092
+ */
1093
+ products: z16.array(
1094
+ z16.object({
1095
+ productId: z16.number().int().positive(),
1096
+ variantIds: z16.array(z16.number().int().positive()).default(() => [])
1097
+ })
1098
+ ).default(() => []),
1089
1099
  tags: z16.array(z16.string().min(1)).default(() => []),
1090
1100
  type: z16.enum(progressTierExclusionTypes)
1091
1101
  });
@@ -2297,7 +2307,7 @@ var containsHtml = (text) => HTML_TAG_RE2.test(text);
2297
2307
  var isObject = (x) => x !== null && typeof x === "object" && !Array.isArray(x);
2298
2308
  var normalizeTextValue = (value, options = {}) => {
2299
2309
  const tokenized = normalizeTokens(value);
2300
- return containsHtml(tokenized) || options.defaultTextStyle ? htmlToTiptap(tokenized, options) : decodeTextEntities(tokenized);
2310
+ return containsHtml(tokenized) || options.defaultTextStyle || options.blockSpacing ? htmlToTiptap(tokenized, options) : decodeTextEntities(tokenized);
2301
2311
  };
2302
2312
  var normalizeLangValue = (value) => typeof value === "string" ? normalizeTextValue(value) : value;
2303
2313
  var normalizeTextContent = (node) => {
@@ -4814,13 +4824,21 @@ var giftOf = (tier) => {
4814
4824
  variantIds: positiveIds(product.variantIds)
4815
4825
  };
4816
4826
  };
4817
- var RULE_LIST = { collections: "collectionIds", products: "productIds", tags: "tags" };
4827
+ var RULE_LIST = { collections: "collectionIds", products: "products", tags: "tags" };
4828
+ var exclusionProducts = (rule) => (rule.products ?? []).flatMap((entry) => {
4829
+ const productId = entry.productId;
4830
+ if (!Number.isInteger(productId) || !productId || productId <= 0) return [];
4831
+ const requested = entry.variantIds ?? [];
4832
+ const variantIds = positiveIds(requested);
4833
+ if (requested.length > 0 && variantIds.length === 0) return [];
4834
+ return [{ productId, variantIds }];
4835
+ });
4818
4836
  var exclusionsOf = (tier) => {
4819
4837
  if (!tier.exclusionsEnabled) return void 0;
4820
4838
  const rules = (tier.exclusions ?? []).flatMap((rule) => {
4821
4839
  const parsed = CABProgressTierExclusion.safeParse({
4822
4840
  ...rule.type === "collections" && { collectionIds: positiveIds(rule.collectionIds) },
4823
- ...rule.type === "products" && { productIds: positiveIds(rule.productIds) },
4841
+ ...rule.type === "products" && { products: exclusionProducts(rule) },
4824
4842
  ...rule.type === "tags" && { tags: (rule.tags ?? []).map((tag) => tag.trim()).filter(Boolean) },
4825
4843
  type: rule.type
4826
4844
  });
@@ -1,6 +1,6 @@
1
1
  import { type TiptapDocument } from '../schema/widgets/checkout-and-beyond/text';
2
2
  import { type HtmlToTiptapOptions } from '../transforms/htmlToTiptap/htmlToTiptap';
3
- export type NormalizeTextOptions = Pick<HtmlToTiptapOptions, 'defaultTextStyle'>;
3
+ export type NormalizeTextOptions = Pick<HtmlToTiptapOptions, 'blockSpacing' | 'defaultTextStyle'>;
4
4
  /**
5
5
  * THE text pipeline for one content value — the single path every text a CAB tree renders takes,
6
6
  * whether it is merchant-authored, converted from a legacy widget, or third-party ad creative:
@@ -16,7 +16,8 @@ export type NormalizeTextOptions = Pick<HtmlToTiptapOptions, 'defaultTextStyle'>
16
16
  *
17
17
  * `defaultTextStyle` is the server-side analogue of React's `defaultTextStyle` prop: the doc's runs
18
18
  * carry that `textStyle` unless the markup set their own. A default forces plain text through the
19
- * converter too, since only a doc can carry a mark.
19
+ * converter too, since only a doc can carry a mark. `blockSpacing` does the same, since only a doc
20
+ * carries it (REB-25181).
20
21
  *
21
22
  * NOT idempotent for entity-bearing strings (`&amp;amp;` → `&amp;` → `&`), by nature of decoding.
22
23
  * That is safe because this runs at SERVE time on the stored original and its output is returned,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebuy/rebuy",
3
- "version": "3.60.4",
3
+ "version": "3.61.0",
4
4
  "description": "Shared zod schemas, legacy-to-CAB widget transforms, and server orchestrators for Rebuy's Shopify consumers (rebuy-api, admin-nextjs, rebuy-shopify-extensions)",
5
5
  "license": "MIT",
6
6
  "author": "Rebuy, Inc.",