@proveanything/smartlinks 1.3.25 → 1.3.27
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/README.md +48 -0
- package/dist/api/ai.d.ts +6 -380
- package/dist/api/ai.js +15 -15
- package/dist/api/index.d.ts +0 -1
- package/dist/docs/API_SUMMARY.md +2259 -2271
- package/dist/docs/utils.md +651 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/types/ai.d.ts +379 -0
- package/dist/types/ai.js +5 -0
- package/dist/types/collection.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/conditions.d.ts +287 -0
- package/dist/utils/conditions.js +453 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/paths.d.ts +82 -0
- package/dist/utils/paths.js +164 -0
- package/docs/API_SUMMARY.md +2259 -2271
- package/docs/utils.md +651 -0
- package/package.json +1 -1
package/docs/utils.md
ADDED
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
# Utility Functions
|
|
2
|
+
|
|
3
|
+
The smartlinks SDK includes utilities for common tasks like building portal URLs and validating conditional rendering logic.
|
|
4
|
+
|
|
5
|
+
> **See also:** [API Summary](API_SUMMARY.md) for the complete SDK reference.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { utils } from '@proveanything/smartlinks'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Path Builder Utility
|
|
14
|
+
|
|
15
|
+
Pass in objects (collection, product, batch, etc.) and the function extracts what it needs to build portal URLs.
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
Pass objects where you have them, or just IDs for simpler cases:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { utils } from '@evrythng/smartlinks'
|
|
23
|
+
|
|
24
|
+
// Pass objects - extracts shortId, portalUrl, product ID, GTIN, ownGtin
|
|
25
|
+
const path = utils.buildPortalPath({
|
|
26
|
+
collection: myCollection,
|
|
27
|
+
product: myProduct // ownGtin is read from product, not overridden
|
|
28
|
+
})
|
|
29
|
+
// Returns: https://portal.smartlinks.io/c/abc123/prod123
|
|
30
|
+
|
|
31
|
+
// Or just IDs if you don't have full objects
|
|
32
|
+
const path2 = utils.buildPortalPath({
|
|
33
|
+
collection: { shortId: 'abc123' },
|
|
34
|
+
productId: 'prod1'
|
|
35
|
+
})
|
|
36
|
+
// Returns: /c/abc123/prod1
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Path Builder Function
|
|
40
|
+
|
|
41
|
+
### `buildPortalPath(params)`
|
|
42
|
+
|
|
43
|
+
Builds a portal path/URL based on the provided parameters.
|
|
44
|
+
|
|
45
|
+
**Parameters:**
|
|
46
|
+
|
|
47
|
+
- `collection` (required) - Collection object or `{ shortId: string, portalUrl?: string }`
|
|
48
|
+
Extracts: `shortId` and optional `portalUrl` for base URL
|
|
49
|
+
|
|
50
|
+
- `product` (optional) - Full product object
|
|
51
|
+
Extracts: `id`, `gtin`, and `ownGtin` (ownGtin is a critical product setting - read only, never overridden)
|
|
52
|
+
|
|
53
|
+
- `productId` (optional) - Just a product ID string
|
|
54
|
+
Use this if you don't have the full product object
|
|
55
|
+
|
|
56
|
+
- `batch` (optional) - Batch object
|
|
57
|
+
Extracts: `id` and `expiryDate`
|
|
58
|
+
|
|
59
|
+
- `batchId` (optional) - Just a batch ID string
|
|
60
|
+
Use this if you don't have the full batch object (no expiry date)
|
|
61
|
+
|
|
62
|
+
- `variant` (optional) - Variant object OR just a variant ID string
|
|
63
|
+
- If object: extracts `id`
|
|
64
|
+
- If string: uses as variant ID
|
|
65
|
+
|
|
66
|
+
- `proof` (optional) - Proof object OR just a proof ID string
|
|
67
|
+
- If object: extracts `id`
|
|
68
|
+
- If string: uses as proof ID
|
|
69
|
+
|
|
70
|
+
- `queryParams` (optional) - Additional query parameters object
|
|
71
|
+
|
|
72
|
+
**Path Formats:**
|
|
73
|
+
|
|
74
|
+
- Basic product: `/c/{shortId}/{productId}`
|
|
75
|
+
- With proof: `/c/{shortId}/{productId}/{proofId}`
|
|
76
|
+
- GTIN (own): `/01/{gtin}` (when product.ownGtin is true)
|
|
77
|
+
- GTIN (not own): `/gc/{shortId}/01/{gtin}` (when product.ownGtin is false)
|
|
78
|
+
- With batch: adds `/10/{batchId}` and optionally `?17={expiryDate}`
|
|
79
|
+
- With variant: adds `/22/{variantId}`
|
|
80
|
+
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
### Pass Objects
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Collection and product objects
|
|
87
|
+
utils.buildPortalPath({
|
|
88
|
+
collection: myCollection, // extracts shortId and portalUrl
|
|
89
|
+
product: myProduct // extracts id, gtin, ownGtin (if present)
|
|
90
|
+
})
|
|
91
|
+
// Returns: https://portal.smartlinks.io/c/abc123/prod123
|
|
92
|
+
|
|
93
|
+
// With proof object
|
|
94
|
+
utils.buildPortalPath({
|
|
95
|
+
collection: myCollection,
|
|
96
|
+
product: myProduct,
|
|
97
|
+
proof: myProof // extracts id
|
|
98
|
+
})
|
|
99
|
+
// Returns: https://portal.smartlinks.io/c/abc123/prod123/proof789
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### GTIN Paths
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// Product owns GTIN (ownGtin read from product.ownGtin)
|
|
106
|
+
utils.buildPortalPath({
|
|
107
|
+
collection: myCollection,
|
|
108
|
+
product: myProduct // if myProduct.ownGtin === true
|
|
109
|
+
})
|
|
110
|
+
// Returns: https://portal.smartlinks.io/01/1234567890123
|
|
111
|
+
|
|
112
|
+
// Product doesn't own GTIN (shared/master GTIN)
|
|
113
|
+
utils.buildPortalPath({
|
|
114
|
+
collection: myCollection,
|
|
115
|
+
product: myProduct // if myProduct.ownGtin === false
|
|
116
|
+
})
|
|
117
|
+
// Returns: https://portal.smartlinks.io/gc/abc123/01/1234567890123
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### With Batch Object or ID
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Batch object includes expiry date
|
|
124
|
+
utils.buildPortalPath({
|
|
125
|
+
collection: myCollection,
|
|
126
|
+
product: myProduct,
|
|
127
|
+
batch: myBatch // extracts id and expiryDate
|
|
128
|
+
})
|
|
129
|
+
// Returns: https://portal.smartlinks.io/01/1234567890123/10/batch456?17=260630
|
|
130
|
+
|
|
131
|
+
// Just batch ID (no expiry)
|
|
132
|
+
utils.buildPortalPath({
|
|
133
|
+
collection: myCollection,
|
|
134
|
+
product: myProduct,
|
|
135
|
+
batchId: 'batch456' // just string, no expiry date
|
|
136
|
+
})
|
|
137
|
+
// Returns: https://portal.smartlinks.io/01/1234567890123/10/batch456
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### With Variant
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
utils.buildPortalPath({
|
|
144
|
+
collection: myCollection,
|
|
145
|
+
product: myProduct,
|
|
146
|
+
batch: myBatch,
|
|
147
|
+
variant: myVariant // extracts id
|
|
148
|
+
})
|
|
149
|
+
// Returns: https://portal.smartlinks.io/01/1234567890123/10/batch456/22/var1?17=260630
|
|
150
|
+
|
|
151
|
+
// Or just variant ID
|
|
152
|
+
utils.buildPortalPath({
|
|
153
|
+
collection: myCollection,
|
|
154
|
+
product: myProduct,
|
|
155
|
+
variant: 'var1'
|
|
156
|
+
})
|
|
157
|
+
// Returns: https://portal.smartlinks.io/01/1234567890123/22/var1
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### With Query Parameters
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
utils.buildPortalPath({
|
|
164
|
+
collection: myCollection,
|
|
165
|
+
product: myProduct,
|
|
166
|
+
queryParams: {
|
|
167
|
+
utm_source: 'email',
|
|
168
|
+
utm_campaign: 'launch',
|
|
169
|
+
lang: 'fr'
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
// Returns: https://portal.smartlinks.io/c/abc123/prod123?utm_source=email&utm_campaign=launch&lang=fr
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Just IDs (No Full Objects)
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Minimal - just IDs
|
|
179
|
+
utils.buildPortalPath({
|
|
180
|
+
collection: { shortId: 'abc123' },
|
|
181
|
+
productId: 'prod1',
|
|
182
|
+
batchId: 'batch1',
|
|
183
|
+
variant: 'var1'
|
|
184
|
+
})
|
|
185
|
+
// Returns: /c/abc123/prod1
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Use Cases
|
|
189
|
+
|
|
190
|
+
### QR Code Generation
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
const qrUrl = utils.buildPortalPath({
|
|
194
|
+
collection: myCollection,
|
|
195
|
+
product: myProduct, // ownGtin read from product
|
|
196
|
+
batch: currentBatch, // includes expiry date
|
|
197
|
+
queryParams: { source: 'qr' }
|
|
198
|
+
})
|
|
199
|
+
// Use qrUrl to generate QR code
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Email Campaign Links
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
const emailLink = utils.buildPortalPath({
|
|
206
|
+
collection: myCollection,
|
|
207
|
+
product: featuredProduct,
|
|
208
|
+
queryParams: {
|
|
209
|
+
utm_source: 'newsletter',
|
|
210
|
+
utm_medium: 'email',
|
|
211
|
+
utm_campaign: 'product-launch'
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### NFC Tag Programming
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const nfcUrl = utils.buildPortalPath({
|
|
220
|
+
collection: myCollection,
|
|
221
|
+
product: myProduct,
|
|
222
|
+
queryParams: { nfc: '1' }
|
|
223
|
+
})
|
|
224
|
+
// Program NFC tag with nfcUrl
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Dynamic Navigation
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
function getProductUrl(product: Product, collection: Collection) {
|
|
231
|
+
return utils.buildPortalPath({
|
|
232
|
+
collection,
|
|
233
|
+
product, // ownGtin automatically read from product
|
|
234
|
+
batch: product.currentBatch
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## TypeScript Support
|
|
240
|
+
|
|
241
|
+
The utility function is fully typed:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import type { PortalPathParams } from '@evrythng/smartlinks'
|
|
245
|
+
import type { Product, Collection } from '@evrythng/smartlinks'
|
|
246
|
+
|
|
247
|
+
const params: PortalPathParams = {
|
|
248
|
+
collection: myCollection,
|
|
249
|
+
product: myProduct
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const path = utils.buildPortalPath(params)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Condition Validation Utility
|
|
256
|
+
|
|
257
|
+
The `validateCondition` function helps determine if content should be shown or hidden based on various criteria like geography, device type, user status, dates, and more.
|
|
258
|
+
|
|
259
|
+
### Basic Usage
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { utils } from '@proveanything/smartlinks'
|
|
263
|
+
|
|
264
|
+
// Check if user is in EU
|
|
265
|
+
const canShow = await utils.validateCondition({
|
|
266
|
+
condition: {
|
|
267
|
+
type: 'and',
|
|
268
|
+
conditions: [{
|
|
269
|
+
type: 'country',
|
|
270
|
+
useRegions: true,
|
|
271
|
+
regions: ['eu'],
|
|
272
|
+
contains: true
|
|
273
|
+
}]
|
|
274
|
+
},
|
|
275
|
+
user: {
|
|
276
|
+
valid: true,
|
|
277
|
+
location: { country: 'DE' }
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// Multiple conditions with AND logic
|
|
282
|
+
const showFeature = await utils.validateCondition({
|
|
283
|
+
condition: {
|
|
284
|
+
type: 'and',
|
|
285
|
+
conditions: [
|
|
286
|
+
{ type: 'user', userType: 'valid' },
|
|
287
|
+
{ type: 'device', displays: ['mobile'], contains: true },
|
|
288
|
+
{ type: 'date', dateTest: 'after', afterDate: '2026-01-01' }
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
user: { valid: true },
|
|
292
|
+
stats: { mobile: true }
|
|
293
|
+
})
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Supported Condition Types
|
|
297
|
+
|
|
298
|
+
#### Country-Based Conditions
|
|
299
|
+
Filter by country codes or predefined regions (EU, EEA, UK, North America, Asia Pacific):
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
await utils.validateCondition({
|
|
303
|
+
condition: {
|
|
304
|
+
type: 'and',
|
|
305
|
+
conditions: [{
|
|
306
|
+
type: 'country',
|
|
307
|
+
useRegions: true,
|
|
308
|
+
regions: ['eu', 'uk'],
|
|
309
|
+
contains: true // true = show IN these regions, false = hide IN these regions
|
|
310
|
+
}]
|
|
311
|
+
},
|
|
312
|
+
user: { valid: true, location: { country: 'FR' } }
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
// Or specific countries
|
|
316
|
+
await utils.validateCondition({
|
|
317
|
+
condition: {
|
|
318
|
+
type: 'and',
|
|
319
|
+
conditions: [{
|
|
320
|
+
type: 'country',
|
|
321
|
+
countries: ['US', 'CA', 'MX'],
|
|
322
|
+
contains: true
|
|
323
|
+
}]
|
|
324
|
+
},
|
|
325
|
+
user: { valid: true, location: { country: 'US' } }
|
|
326
|
+
})
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### Device & Platform Conditions
|
|
330
|
+
Target specific devices or platforms:
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
await utils.validateCondition({
|
|
334
|
+
condition: {
|
|
335
|
+
type: 'and',
|
|
336
|
+
conditions: [{
|
|
337
|
+
type: 'device',
|
|
338
|
+
displays: ['ios', 'android', 'mobile'],
|
|
339
|
+
contains: true
|
|
340
|
+
}]
|
|
341
|
+
},
|
|
342
|
+
stats: {
|
|
343
|
+
platform: { ios: true },
|
|
344
|
+
mobile: true
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Supported displays: `'android'`, `'ios'`, `'win'`, `'mac'`, `'desktop'`, `'mobile'`
|
|
350
|
+
|
|
351
|
+
#### User Status Conditions
|
|
352
|
+
Check authentication and permissions:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// Logged in users only
|
|
356
|
+
await utils.validateCondition({
|
|
357
|
+
condition: {
|
|
358
|
+
type: 'and',
|
|
359
|
+
conditions: [{ type: 'user', userType: 'valid' }]
|
|
360
|
+
},
|
|
361
|
+
user: { valid: true, uid: 'user123' }
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
// Collection admins only
|
|
365
|
+
await utils.validateCondition({
|
|
366
|
+
condition: {
|
|
367
|
+
type: 'and',
|
|
368
|
+
conditions: [{ type: 'user', userType: 'admin' }]
|
|
369
|
+
},
|
|
370
|
+
user: { valid: true, uid: 'user123' },
|
|
371
|
+
collection: { id: 'col1', roles: { 'user123': 'admin' } }
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
// Proof owners only
|
|
375
|
+
await utils.validateCondition({
|
|
376
|
+
condition: {
|
|
377
|
+
type: 'and',
|
|
378
|
+
conditions: [{ type: 'user', userType: 'owner' }]
|
|
379
|
+
},
|
|
380
|
+
user: { valid: true, uid: 'user123' },
|
|
381
|
+
proof: { userId: 'user123' }
|
|
382
|
+
})
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
User types: `'valid'`, `'invalid'`, `'owner'`, `'admin'`, `'group'`
|
|
386
|
+
|
|
387
|
+
#### Date & Time Conditions
|
|
388
|
+
Show/hide content based on dates:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
// Show after specific date
|
|
392
|
+
await utils.validateCondition({
|
|
393
|
+
condition: {
|
|
394
|
+
type: 'and',
|
|
395
|
+
conditions: [{
|
|
396
|
+
type: 'date',
|
|
397
|
+
dateTest: 'after',
|
|
398
|
+
afterDate: '2026-06-01'
|
|
399
|
+
}]
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
// Show during date range
|
|
404
|
+
await utils.validateCondition({
|
|
405
|
+
condition: {
|
|
406
|
+
type: 'and',
|
|
407
|
+
conditions: [{
|
|
408
|
+
type: 'date',
|
|
409
|
+
dateTest: 'between',
|
|
410
|
+
rangeDate: ['2026-01-01', '2026-12-31']
|
|
411
|
+
}]
|
|
412
|
+
}
|
|
413
|
+
})
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Date tests: `'before'`, `'after'`, `'between'`
|
|
417
|
+
|
|
418
|
+
#### Product & Tag Conditions
|
|
419
|
+
Filter by specific products or product tags:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
// Specific products
|
|
423
|
+
await utils.validateCondition({
|
|
424
|
+
condition: {
|
|
425
|
+
type: 'and',
|
|
426
|
+
conditions: [{
|
|
427
|
+
type: 'product',
|
|
428
|
+
productIds: ['prod1', 'prod2'],
|
|
429
|
+
contains: true
|
|
430
|
+
}]
|
|
431
|
+
},
|
|
432
|
+
product: { id: 'prod1' }
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
// Products with specific tags
|
|
436
|
+
await utils.validateCondition({
|
|
437
|
+
condition: {
|
|
438
|
+
type: 'and',
|
|
439
|
+
conditions: [{
|
|
440
|
+
type: 'tag',
|
|
441
|
+
tags: ['premium', 'featured'],
|
|
442
|
+
contains: true
|
|
443
|
+
}]
|
|
444
|
+
},
|
|
445
|
+
product: { id: 'prod1', tags: { premium: true } }
|
|
446
|
+
})
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### Item Status Conditions
|
|
450
|
+
Check proof/item status:
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
await utils.validateCondition({
|
|
454
|
+
condition: {
|
|
455
|
+
type: 'and',
|
|
456
|
+
conditions: [{
|
|
457
|
+
type: 'itemStatus',
|
|
458
|
+
statusType: 'isClaimable'
|
|
459
|
+
}]
|
|
460
|
+
},
|
|
461
|
+
proof: { claimable: true }
|
|
462
|
+
})
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Status types: `'isClaimable'`, `'notClaimable'`, `'noProof'`, `'hasProof'`, `'isVirtual'`, `'notVirtual'`
|
|
466
|
+
|
|
467
|
+
#### Version Conditions
|
|
468
|
+
For A/B testing or versioned content:
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
await utils.validateCondition({
|
|
472
|
+
condition: {
|
|
473
|
+
type: 'and',
|
|
474
|
+
conditions: [{
|
|
475
|
+
type: 'version',
|
|
476
|
+
versions: ['v2', 'v3'],
|
|
477
|
+
contains: true
|
|
478
|
+
}]
|
|
479
|
+
},
|
|
480
|
+
stats: { version: 'v2' }
|
|
481
|
+
})
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
#### Value Comparison Conditions
|
|
485
|
+
Compare custom field values:
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
await utils.validateCondition({
|
|
489
|
+
condition: {
|
|
490
|
+
type: 'and',
|
|
491
|
+
conditions: [{
|
|
492
|
+
type: 'value',
|
|
493
|
+
field: 'product.inventory.quantity', // dot notation
|
|
494
|
+
fieldType: 'integer',
|
|
495
|
+
validationType: 'greater',
|
|
496
|
+
value: 10
|
|
497
|
+
}]
|
|
498
|
+
},
|
|
499
|
+
product: { inventory: { quantity: 25 } }
|
|
500
|
+
})
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Validation types: `'equal'`, `'not'`, `'greater'`, `'less'`
|
|
504
|
+
Field types: `'string'`, `'boolean'`, `'integer'`, `'number'`
|
|
505
|
+
|
|
506
|
+
#### Geofence Conditions
|
|
507
|
+
Location-based restrictions using bounding boxes:
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
await utils.validateCondition({
|
|
511
|
+
condition: {
|
|
512
|
+
type: 'and',
|
|
513
|
+
conditions: [{
|
|
514
|
+
type: 'geofence',
|
|
515
|
+
top: 50.0,
|
|
516
|
+
bottom: 40.0,
|
|
517
|
+
left: -10.0,
|
|
518
|
+
right: 5.0,
|
|
519
|
+
contains: true // true = inside box, false = outside box
|
|
520
|
+
}]
|
|
521
|
+
},
|
|
522
|
+
user: {
|
|
523
|
+
valid: true,
|
|
524
|
+
location: { latitude: 45.0, longitude: 0.0 }
|
|
525
|
+
}
|
|
526
|
+
})
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
#### Nested Conditions
|
|
530
|
+
Reference other condition sets for reusability:
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
await utils.validateCondition({
|
|
534
|
+
condition: {
|
|
535
|
+
type: 'and',
|
|
536
|
+
conditions: [{
|
|
537
|
+
type: 'condition',
|
|
538
|
+
conditionId: 'mobile-users-condition',
|
|
539
|
+
passes: true // true = must pass, false = must fail
|
|
540
|
+
}]
|
|
541
|
+
},
|
|
542
|
+
conditionId: 'mobile-users-condition',
|
|
543
|
+
fetchCondition: async (collectionId, conditionId) => {
|
|
544
|
+
// Your logic to fetch condition by ID
|
|
545
|
+
return { type: 'and', conditions: [...] }
|
|
546
|
+
},
|
|
547
|
+
collection: { id: 'col1' }
|
|
548
|
+
})
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Combining Conditions (AND/OR Logic)
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
// AND logic (all must pass)
|
|
555
|
+
await utils.validateCondition({
|
|
556
|
+
condition: {
|
|
557
|
+
type: 'and',
|
|
558
|
+
conditions: [
|
|
559
|
+
{ type: 'user', userType: 'valid' },
|
|
560
|
+
{ type: 'device', displays: ['mobile'], contains: true },
|
|
561
|
+
{ type: 'country', useRegions: true, regions: ['eu'], contains: true }
|
|
562
|
+
]
|
|
563
|
+
},
|
|
564
|
+
user: { valid: true, location: { country: 'FR' } },
|
|
565
|
+
stats: { mobile: true }
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
// OR logic (any can pass)
|
|
569
|
+
await utils.validateCondition({
|
|
570
|
+
condition: {
|
|
571
|
+
type: 'or',
|
|
572
|
+
conditions: [
|
|
573
|
+
{ type: 'user', userType: 'admin' },
|
|
574
|
+
{ type: 'product', productIds: ['featured1'], contains: true }
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
user: { valid: false },
|
|
578
|
+
product: { id: 'featured1' }
|
|
579
|
+
})
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Common Use Cases
|
|
583
|
+
|
|
584
|
+
#### Page Rendering Control
|
|
585
|
+
```typescript
|
|
586
|
+
const showPremiumContent = await utils.validateCondition({
|
|
587
|
+
condition: {
|
|
588
|
+
type: 'and',
|
|
589
|
+
conditions: [
|
|
590
|
+
{ type: 'user', userType: 'valid' },
|
|
591
|
+
{ type: 'tag', tags: ['premium'], contains: true }
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
user: { valid: true },
|
|
595
|
+
product: { id: 'prod1', tags: { premium: true } }
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
if (showPremiumContent) {
|
|
599
|
+
// Render premium content
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### Regional Feature Rollout
|
|
604
|
+
```typescript
|
|
605
|
+
const showNewFeature = await utils.validateCondition({
|
|
606
|
+
condition: {
|
|
607
|
+
type: 'and',
|
|
608
|
+
conditions: [
|
|
609
|
+
{ type: 'country', useRegions: true, regions: ['northamerica'], contains: true },
|
|
610
|
+
{ type: 'date', dateTest: 'after', afterDate: '2026-03-01' }
|
|
611
|
+
]
|
|
612
|
+
},
|
|
613
|
+
user: { valid: true, location: { country: 'US' } }
|
|
614
|
+
})
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
#### Mobile-Only Features
|
|
618
|
+
```typescript
|
|
619
|
+
const showMobileFeature = await utils.validateCondition({
|
|
620
|
+
condition: {
|
|
621
|
+
type: 'and',
|
|
622
|
+
conditions: [
|
|
623
|
+
{ type: 'device', displays: ['mobile'], contains: true }
|
|
624
|
+
]
|
|
625
|
+
},
|
|
626
|
+
stats: { mobile: true, platform: { ios: true } }
|
|
627
|
+
})
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### Available Regions
|
|
631
|
+
|
|
632
|
+
Predefined regions for country conditions:
|
|
633
|
+
- **eu** - European Union (27 member states)
|
|
634
|
+
- **eea** - European Economic Area (EU + EFTA countries)
|
|
635
|
+
- **uk** - United Kingdom
|
|
636
|
+
- **northamerica** - US, CA, MX
|
|
637
|
+
- **asiapacific** - AU, NZ, JP, KR, SG, HK, TW, TH, MY, PH, ID, VN, IN
|
|
638
|
+
|
|
639
|
+
## More Examples
|
|
640
|
+
|
|
641
|
+
See [examples/utils-demo.ts](../examples/utils-demo.ts) for comprehensive examples.
|
|
642
|
+
|
|
643
|
+
## Related Documentation
|
|
644
|
+
|
|
645
|
+
- **[API Summary](API_SUMMARY.md)** - Complete SDK reference with all namespaces and functions
|
|
646
|
+
- **[QR Codes](API_SUMMARY.md#qr)** - QR code lookup functions that work with generated paths
|
|
647
|
+
- **[NFC](API_SUMMARY.md#nfc)** - NFC tag claiming and validation
|
|
648
|
+
- **[Collections](API_SUMMARY.md#collection)** - Collection management functions
|
|
649
|
+
- **[Products](API_SUMMARY.md#product)** - Product CRUD operations
|
|
650
|
+
- **[Batches](API_SUMMARY.md#batch)** - Batch management
|
|
651
|
+
- **[Proofs](API_SUMMARY.md#proof)** - Proof creation and claiming
|