@proveanything/smartlinks 1.9.19 → 1.9.20

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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.9.19 | Generated: 2026-04-16T12:41:11.180Z
3
+ Version: 1.9.20 | Generated: 2026-04-17T10:13:30.466Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -6847,6 +6847,18 @@ interface UserInfo {
6847
6847
  interface ProductInfo {
6848
6848
  id: string
6849
6849
  tags?: Record<string, any>
6850
+ * Facet values assigned to this product.
6851
+ * Shape mirrors `ProductFacetMap`: a map of facet key → array of value objects.
6852
+ * Each value object must have at minimum a `key` string property.
6853
+ *
6854
+ * @example
6855
+ * ```ts
6856
+ * {
6857
+ * material: [{ key: 'cotton', name: 'Cotton' }],
6858
+ * certifications: [{ key: 'organic', name: 'Organic' }, { key: 'recycled', name: 'Recycled' }]
6859
+ * }
6860
+ * ```
6861
+ facets?: Record<string, Array<{ key: string; [k: string]: unknown }>>
6850
6862
  }
6851
6863
  ```
6852
6864
 
@@ -114,10 +114,62 @@ export interface ItemStatusCondition extends BaseCondition {
114
114
  type: 'itemStatus';
115
115
  statusType: 'isClaimable' | 'notClaimable' | 'noProof' | 'hasProof' | 'isVirtual' | 'notVirtual';
116
116
  }
117
+ /**
118
+ * Facet-based condition — gates on the facet values assigned to the current product.
119
+ *
120
+ * The `facetKey` identifies which facet dimension to inspect (e.g. `'material'`, `'region'`,
121
+ * `'certifications'`). The optional `values` array lists the value `key`s to test.
122
+ *
123
+ * ### Match modes (`matchMode`)
124
+ *
125
+ * | Mode | Passes when |
126
+ * |------|-------------|
127
+ * | `'any'` (default) | The product has **at least one** of the listed values on this facet |
128
+ * | `'all'` | The product has **every** listed value (multi-value facets only) |
129
+ * | `'none'` | The product has **none** of the listed values |
130
+ * | `'hasFacet'` | The product has **any** value on this facet (ignores `values`) |
131
+ * | `'notHasFacet'` | The product has **no** values on this facet (ignores `values`) |
132
+ *
133
+ * ### Examples
134
+ *
135
+ * ```typescript
136
+ * // Must carry the 'cotton' or 'linen' value on the 'material' facet
137
+ * { type: 'facet', facetKey: 'material', matchMode: 'any', values: ['cotton', 'linen'] }
138
+ *
139
+ * // Must carry BOTH 'organic' and 'recycled' on the 'certifications' facet
140
+ * { type: 'facet', facetKey: 'certifications', matchMode: 'all', values: ['organic', 'recycled'] }
141
+ *
142
+ * // Must NOT carry 'discontinued' on the 'status' facet
143
+ * { type: 'facet', facetKey: 'status', matchMode: 'none', values: ['discontinued'] }
144
+ *
145
+ * // Product must have at least one value on the 'region' facet
146
+ * { type: 'facet', facetKey: 'region', matchMode: 'hasFacet' }
147
+ * ```
148
+ */
149
+ export interface FacetCondition extends BaseCondition {
150
+ type: 'facet';
151
+ /** The facet dimension key to inspect (e.g. `'material'`, `'region'`) */
152
+ facetKey: string;
153
+ /**
154
+ * How to match against `values`.
155
+ * - `'any'` — pass if the product has at least one of the listed values (default)
156
+ * - `'all'` — pass if the product has every listed value
157
+ * - `'none'` — pass if the product has none of the listed values
158
+ * - `'hasFacet'` — pass if the product has any value on this facet (ignores `values`)
159
+ * - `'notHasFacet'` — pass if the product has no values on this facet (ignores `values`)
160
+ */
161
+ matchMode?: 'any' | 'all' | 'none' | 'hasFacet' | 'notHasFacet';
162
+ /**
163
+ * Facet value keys to test against.
164
+ * Required for `'any'`, `'all'`, and `'none'` match modes.
165
+ * Ignored for `'hasFacet'` and `'notHasFacet'`.
166
+ */
167
+ values?: string[];
168
+ }
117
169
  /**
118
170
  * Union of all condition types
119
171
  */
120
- export type Condition = CountryCondition | VersionCondition | DeviceCondition | NestedCondition | UserCondition | ProductCondition | TagCondition | DateCondition | GeofenceCondition | ValueCondition | ItemStatusCondition;
172
+ export type Condition = CountryCondition | VersionCondition | DeviceCondition | NestedCondition | UserCondition | ProductCondition | TagCondition | FacetCondition | DateCondition | GeofenceCondition | ValueCondition | ItemStatusCondition;
121
173
  /**
122
174
  * Condition set that combines multiple conditions
123
175
  */
@@ -166,6 +218,23 @@ export interface UserInfo {
166
218
  export interface ProductInfo {
167
219
  id: string;
168
220
  tags?: Record<string, any>;
221
+ /**
222
+ * Facet values assigned to this product.
223
+ * Shape mirrors `ProductFacetMap`: a map of facet key → array of value objects.
224
+ * Each value object must have at minimum a `key` string property.
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * {
229
+ * material: [{ key: 'cotton', name: 'Cotton' }],
230
+ * certifications: [{ key: 'organic', name: 'Organic' }, { key: 'recycled', name: 'Recycled' }]
231
+ * }
232
+ * ```
233
+ */
234
+ facets?: Record<string, Array<{
235
+ key: string;
236
+ [k: string]: unknown;
237
+ }>>;
169
238
  }
170
239
  /**
171
240
  * Proof information for condition validation
@@ -234,6 +303,7 @@ export interface ConditionDebugOptions {
234
303
  * - **user** - User authentication status (logged in, owner, admin)
235
304
  * - **product** - Product-specific conditions
236
305
  * - **tag** - Product tag-based conditions
306
+ * - **facet** - Product facet-based conditions (any/all/none of specific facet values)
237
307
  * - **date** - Time-based conditions (before, after, between dates)
238
308
  * - **geofence** - Location-based restrictions
239
309
  * - **value** - Custom field comparisons
@@ -93,7 +93,7 @@ function summarizeConditionSet(condition) {
93
93
  return `${(_a = condition.type) !== null && _a !== void 0 ? _a : 'and'} (${(_c = (_b = condition.conditions) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0} conditions)`;
94
94
  }
95
95
  function summarizeCondition(condition) {
96
- var _a, _b;
96
+ var _a, _b, _c, _d, _e;
97
97
  switch (condition.type) {
98
98
  case 'country':
99
99
  return `country regions=${((_a = condition.regions) === null || _a === void 0 ? void 0 : _a.join(',')) || 'none'} countries=${((_b = condition.countries) === null || _b === void 0 ? void 0 : _b.join(',')) || 'none'} contains=${condition.contains}`;
@@ -115,6 +115,11 @@ function summarizeCondition(condition) {
115
115
  return `geofence contains=${condition.contains}`;
116
116
  case 'value':
117
117
  return `value field=${condition.field} ${condition.validationType} ${String(condition.value)}`;
118
+ case 'facet': {
119
+ const mode = (_c = condition.matchMode) !== null && _c !== void 0 ? _c : 'any';
120
+ const vals = (_e = (_d = condition.values) === null || _d === void 0 ? void 0 : _d.join(', ')) !== null && _e !== void 0 ? _e : '—';
121
+ return `facet key=${condition.facetKey} mode=${mode} values=[${vals}]`;
122
+ }
118
123
  case 'itemStatus':
119
124
  return `itemStatus ${condition.statusType}`;
120
125
  default:
@@ -143,6 +148,8 @@ async function evaluateConditionEntry(condition, params) {
143
148
  return validateGeofence(condition, params);
144
149
  case 'value':
145
150
  return validateValue(condition, params);
151
+ case 'facet':
152
+ return validateFacet(condition, params);
146
153
  case 'itemStatus':
147
154
  return validateItemStatus(condition, params);
148
155
  default:
@@ -162,6 +169,7 @@ async function evaluateConditionEntry(condition, params) {
162
169
  * - **user** - User authentication status (logged in, owner, admin)
163
170
  * - **product** - Product-specific conditions
164
171
  * - **tag** - Product tag-based conditions
172
+ * - **facet** - Product facet-based conditions (any/all/none of specific facet values)
165
173
  * - **date** - Time-based conditions (before, after, between dates)
166
174
  * - **geofence** - Location-based restrictions
167
175
  * - **value** - Custom field comparisons
@@ -730,6 +738,82 @@ async function validateValue(condition, params) {
730
738
  },
731
739
  };
732
740
  }
741
+ /**
742
+ * Validate facet-based condition
743
+ */
744
+ async function validateFacet(condition, params) {
745
+ var _a, _b, _c;
746
+ const { facetKey, matchMode = 'any', values = [] } = condition;
747
+ const facets = (_a = params.product) === null || _a === void 0 ? void 0 : _a.facets;
748
+ // No product
749
+ if (!((_b = params.product) === null || _b === void 0 ? void 0 : _b.id)) {
750
+ return {
751
+ passed: false,
752
+ detail: 'Product ID was not available.',
753
+ context: { facetKey, matchMode },
754
+ };
755
+ }
756
+ const assigned = (_c = facets === null || facets === void 0 ? void 0 : facets[facetKey]) !== null && _c !== void 0 ? _c : [];
757
+ const assignedKeys = assigned.map(v => v.key);
758
+ // Presence-only modes — ignore `values`
759
+ if (matchMode === 'hasFacet') {
760
+ return {
761
+ passed: assignedKeys.length > 0,
762
+ detail: `Product ${assigned.length > 0 ? 'has' : 'does not have'} values on facet '${facetKey}'.`,
763
+ context: { facetKey, assignedKeys },
764
+ };
765
+ }
766
+ if (matchMode === 'notHasFacet') {
767
+ return {
768
+ passed: assignedKeys.length === 0,
769
+ detail: `Product ${assigned.length === 0 ? 'has no' : 'has'} values on facet '${facetKey}'.`,
770
+ context: { facetKey, assignedKeys },
771
+ };
772
+ }
773
+ // Value-matching modes require at least one value to test
774
+ if (values.length === 0) {
775
+ return {
776
+ passed: false,
777
+ detail: `Facet condition for '${facetKey}' with matchMode '${matchMode}' requires at least one value.`,
778
+ context: { facetKey, matchMode },
779
+ };
780
+ }
781
+ if (matchMode === 'any') {
782
+ const matched = values.filter(v => assignedKeys.includes(v));
783
+ return {
784
+ passed: matched.length > 0,
785
+ detail: matched.length > 0
786
+ ? `Product matched facet '${facetKey}' value(s): [${matched.join(', ')}].`
787
+ : `Product did not match any of [${values.join(', ')}] on facet '${facetKey}'.`,
788
+ context: { facetKey, matchMode, testedValues: values, matched, assignedKeys },
789
+ };
790
+ }
791
+ if (matchMode === 'all') {
792
+ const missing = values.filter(v => !assignedKeys.includes(v));
793
+ return {
794
+ passed: missing.length === 0,
795
+ detail: missing.length === 0
796
+ ? `Product has all required values on facet '${facetKey}'.`
797
+ : `Product is missing [${missing.join(', ')}] on facet '${facetKey}'.`,
798
+ context: { facetKey, matchMode, testedValues: values, missing, assignedKeys },
799
+ };
800
+ }
801
+ if (matchMode === 'none') {
802
+ const matched = values.filter(v => assignedKeys.includes(v));
803
+ return {
804
+ passed: matched.length === 0,
805
+ detail: matched.length === 0
806
+ ? `Product correctly has none of [${values.join(', ')}] on facet '${facetKey}'.`
807
+ : `Product has forbidden value(s) [${matched.join(', ')}] on facet '${facetKey}'.`,
808
+ context: { facetKey, matchMode, testedValues: values, matched, assignedKeys },
809
+ };
810
+ }
811
+ return {
812
+ passed: false,
813
+ detail: `Unsupported facet matchMode '${matchMode}'.`,
814
+ context: { facetKey, matchMode },
815
+ };
816
+ }
733
817
  /**
734
818
  * Validate item status condition
735
819
  */
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.9.19 | Generated: 2026-04-16T12:41:11.180Z
3
+ Version: 1.9.20 | Generated: 2026-04-17T10:13:30.466Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -6847,6 +6847,18 @@ interface UserInfo {
6847
6847
  interface ProductInfo {
6848
6848
  id: string
6849
6849
  tags?: Record<string, any>
6850
+ * Facet values assigned to this product.
6851
+ * Shape mirrors `ProductFacetMap`: a map of facet key → array of value objects.
6852
+ * Each value object must have at minimum a `key` string property.
6853
+ *
6854
+ * @example
6855
+ * ```ts
6856
+ * {
6857
+ * material: [{ key: 'cotton', name: 'Cotton' }],
6858
+ * certifications: [{ key: 'organic', name: 'Organic' }, { key: 'recycled', name: 'Recycled' }]
6859
+ * }
6860
+ * ```
6861
+ facets?: Record<string, Array<{ key: string; [k: string]: unknown }>>
6850
6862
  }
6851
6863
  ```
6852
6864
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.9.19",
3
+ "version": "1.9.20",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",