@proveanything/smartlinks 1.8.12 → 1.9.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.
@@ -0,0 +1,347 @@
1
+ # Product Facets SDK Reference
2
+
3
+ Simple SDK-facing reference for the facet API.
4
+
5
+ This document covers:
6
+
7
+ - admin facet endpoints
8
+ - public facet endpoints
9
+ - collection-level facet routes
10
+ - TypeScript interfaces for facet definitions, values, and aggregation queries
11
+
12
+ ## Current route model
13
+
14
+ The facet API stays under `/api/v1`.
15
+
16
+ Facets are mounted directly under the collection.
17
+
18
+ ### Admin base
19
+
20
+ ```ts
21
+ /api/v1/admin/collection/:collectionId/facets
22
+ ```
23
+
24
+ ### Public base
25
+
26
+ ```ts
27
+ /api/v1/public/collection/:collectionId/facets
28
+ ```
29
+
30
+ ## Admin endpoints
31
+
32
+ ### List facet definitions
33
+
34
+ ```ts
35
+ GET /api/v1/admin/collection/:collectionId/facets
36
+ ```
37
+
38
+ Optional query params:
39
+
40
+ ```ts
41
+ includeValues?: boolean
42
+ includeDeleted?: boolean
43
+ kind?: 'system' | 'custom'
44
+ reserved?: boolean
45
+ ```
46
+
47
+ ### Create facet definition
48
+
49
+ ```ts
50
+ POST /api/v1/admin/collection/:collectionId/facets
51
+ ```
52
+
53
+ ### Get facet definition
54
+
55
+ ```ts
56
+ GET /api/v1/admin/collection/:collectionId/facets/:facetKey
57
+ ```
58
+
59
+ Optional query params:
60
+
61
+ ```ts
62
+ includeValues?: boolean
63
+ includeDeleted?: boolean
64
+ ```
65
+
66
+ ### Update facet definition
67
+
68
+ ```ts
69
+ PUT /api/v1/admin/collection/:collectionId/facets/:facetKey
70
+ ```
71
+
72
+ ### Delete facet definition
73
+
74
+ ```ts
75
+ DELETE /api/v1/admin/collection/:collectionId/facets/:facetKey
76
+ ```
77
+
78
+ Current behavior:
79
+
80
+ - reserved facet definitions cannot be deleted
81
+ - facet definitions with product assignments cannot be deleted
82
+
83
+ ### List facet values
84
+
85
+ ```ts
86
+ GET /api/v1/admin/collection/:collectionId/facets/:facetKey/values
87
+ ```
88
+
89
+ Optional query params:
90
+
91
+ ```ts
92
+ includeDeleted?: boolean
93
+ ```
94
+
95
+ ### Create facet value
96
+
97
+ ```ts
98
+ POST /api/v1/admin/collection/:collectionId/facets/:facetKey/values
99
+ ```
100
+
101
+ ### Get facet value
102
+
103
+ ```ts
104
+ GET /api/v1/admin/collection/:collectionId/facets/:facetKey/values/:valueKey
105
+ ```
106
+
107
+ Optional query params:
108
+
109
+ ```ts
110
+ includeDeleted?: boolean
111
+ ```
112
+
113
+ ### Update facet value
114
+
115
+ ```ts
116
+ PUT /api/v1/admin/collection/:collectionId/facets/:facetKey/values/:valueKey
117
+ ```
118
+
119
+ ### Delete facet value
120
+
121
+ ```ts
122
+ DELETE /api/v1/admin/collection/:collectionId/facets/:facetKey/values/:valueKey
123
+ ```
124
+
125
+ Current behavior:
126
+
127
+ - deleting a facet value removes its product assignments
128
+ - affected product `facets` summaries are synchronized after the delete
129
+
130
+ ### Query facet counts
131
+
132
+ ```ts
133
+ POST /api/v1/admin/collection/:collectionId/facets/query
134
+ ```
135
+
136
+ Supported query filters now:
137
+
138
+ - `search`
139
+ - `status`
140
+ - `schemaType`
141
+ - `type`
142
+ - `productIds`
143
+ - `sku`
144
+ - `gtin`
145
+ - `category`
146
+ - `tags`
147
+ - `facetEquals`
148
+
149
+ ## Public endpoints
150
+
151
+ ### List facet definitions
152
+
153
+ ```ts
154
+ GET /api/v1/public/collection/:collectionId/facets
155
+ ```
156
+
157
+ Optional query params:
158
+
159
+ ```ts
160
+ includeValues?: boolean
161
+ ```
162
+
163
+ ### Get facet definition
164
+
165
+ ```ts
166
+ GET /api/v1/public/collection/:collectionId/facets/:facetKey
167
+ ```
168
+
169
+ Optional query params:
170
+
171
+ ```ts
172
+ includeValues?: boolean
173
+ ```
174
+
175
+ ### List facet values
176
+
177
+ ```ts
178
+ GET /api/v1/public/collection/:collectionId/facets/:facetKey/values
179
+ ```
180
+
181
+ ### Get facet value
182
+
183
+ ```ts
184
+ GET /api/v1/public/collection/:collectionId/facets/:facetKey/values/:valueKey
185
+ ```
186
+
187
+ ### Query facet counts
188
+
189
+ ```ts
190
+ POST /api/v1/public/collection/:collectionId/facets/query
191
+ ```
192
+
193
+ Public endpoints are read-only.
194
+
195
+ ## TypeScript interfaces
196
+
197
+ ## Core JSON types
198
+
199
+ ```ts
200
+ export type JsonPrimitive = string | number | boolean | null
201
+
202
+ export type JsonValue =
203
+ | JsonPrimitive
204
+ | JsonValue[]
205
+ | { [key: string]: JsonValue }
206
+ ```
207
+
208
+ ## Facet definition types
209
+
210
+ ```ts
211
+ export interface FacetDefinition {
212
+ id: string
213
+ orgId: string
214
+ collectionId: string
215
+ key: string
216
+ name: string
217
+ description?: string | null
218
+ cardinality: 'single' | 'multi'
219
+ kind: 'system' | 'custom'
220
+ hierarchical: boolean
221
+ reserved: boolean
222
+ config: Record<string, JsonValue>
223
+ createdAt: string
224
+ updatedAt: string
225
+ deletedAt?: string | null
226
+ values?: FacetValue[]
227
+ }
228
+
229
+ export interface FacetDefinitionWriteInput {
230
+ key?: string
231
+ name: string
232
+ description?: string | null
233
+ cardinality?: 'single' | 'multi'
234
+ kind?: 'system' | 'custom'
235
+ hierarchical?: boolean
236
+ reserved?: boolean
237
+ config?: Record<string, JsonValue>
238
+ }
239
+ ```
240
+
241
+ ## Facet value types
242
+
243
+ ```ts
244
+ export interface FacetValue {
245
+ id: string
246
+ orgId: string
247
+ collectionId: string
248
+ facetDefinitionId: string
249
+ facetKey?: string
250
+ key: string
251
+ slug?: string | null
252
+ name: string
253
+ shortName?: string | null
254
+ description?: string | null
255
+ color?: string | null
256
+ icon?: string | null
257
+ image?: Record<string, JsonValue> | null
258
+ metadata: Record<string, JsonValue>
259
+ sortOrder: number
260
+ parentValueId?: string | null
261
+ parentValueKey?: string | null
262
+ createdAt: string
263
+ updatedAt: string
264
+ deletedAt?: string | null
265
+ count?: number
266
+ }
267
+
268
+ export interface FacetValueWriteInput {
269
+ key?: string
270
+ slug?: string | null
271
+ name: string
272
+ shortName?: string | null
273
+ description?: string | null
274
+ color?: string | null
275
+ icon?: string | null
276
+ image?: Record<string, JsonValue> | null
277
+ metadata?: Record<string, JsonValue>
278
+ sortOrder?: number
279
+ parentValueKey?: string | null
280
+ }
281
+ ```
282
+
283
+ ## List response types
284
+
285
+ ```ts
286
+ export interface FacetListResponse {
287
+ items: FacetDefinition[]
288
+ }
289
+
290
+ export interface FacetValueListResponse {
291
+ facet: FacetDefinition
292
+ items: FacetValue[]
293
+ }
294
+
295
+ export interface FacetValueResponse {
296
+ facet: FacetDefinition
297
+ item: FacetValue
298
+ }
299
+ ```
300
+
301
+ ## Query types
302
+
303
+ ```ts
304
+ export interface FacetQueryRequest {
305
+ facetKeys?: string[]
306
+ includeEmpty?: boolean
307
+ includeDeleted?: boolean
308
+ query?: {
309
+ search?: string
310
+ status?: string[]
311
+ schemaType?: string[]
312
+ type?: string[]
313
+ productIds?: string[]
314
+ sku?: string
315
+ gtin?: string
316
+ category?: string[]
317
+ tags?: string[]
318
+ facetEquals?: Record<string, JsonValue | JsonValue[]>
319
+ }
320
+ }
321
+
322
+ export interface FacetBucket {
323
+ facetKey: string
324
+ valueKey: string
325
+ name?: string
326
+ count: number
327
+ }
328
+
329
+ export interface FacetQueryResponse {
330
+ items: Array<{
331
+ facet: FacetDefinition
332
+ values: FacetValue[]
333
+ }>
334
+ buckets: FacetBucket[]
335
+ meta?: {
336
+ source?: 'postgres'
337
+ matchedProducts?: number
338
+ }
339
+ }
340
+ ```
341
+
342
+ ## Notes for SDK implementers
343
+
344
+ - treat facet definitions and facet values as collection-scoped resources
345
+ - use the facet API to manage definitions and values
346
+ - use product read/write routes to assign facet data onto products
347
+ - treat `label` and `category` as reserved system facets when present
package/dist/http.d.ts CHANGED
@@ -117,7 +117,8 @@ export declare function configureSdkCache(options: {
117
117
  * ```ts
118
118
  * invalidateCache() // clear everything
119
119
  * invalidateCache('/collection/abc123') // one specific collection
120
- * invalidateCache('/product/') // all product responses
120
+ * invalidateCache('/product/') // all legacy singular product responses
121
+ * invalidateCache('/products/') // all canonical plural product responses
121
122
  * ```
122
123
  */
123
124
  export declare function invalidateCache(urlPattern?: string): void;
package/dist/http.js CHANGED
@@ -83,7 +83,7 @@ const CACHE_TTL_RULES = [
83
83
  { pattern: /\/proof\/[^/]*(\?.*)?$/i, ttlMs: 30000 },
84
84
  { pattern: /\/attestation\/[^/]*(\?.*)?$/i, ttlMs: 2 * 60000 },
85
85
  // Slow-changing top-level resources — long TTLs, matched only when path ends at the ID
86
- { pattern: /\/product\/[^/]*(\?.*)?$/i, ttlMs: 60 * 60000 },
86
+ { pattern: /\/products?\/[^/]*(\?.*)?$/i, ttlMs: 60 * 60000 },
87
87
  { pattern: /\/variant\/[^/]*(\?.*)?$/i, ttlMs: 60 * 60000 },
88
88
  { pattern: /\/collection\/[^/]*(\?.*)?$/i, ttlMs: 60 * 60000 }, // 1 hour
89
89
  ];
@@ -507,7 +507,8 @@ export function configureSdkCache(options) {
507
507
  * ```ts
508
508
  * invalidateCache() // clear everything
509
509
  * invalidateCache('/collection/abc123') // one specific collection
510
- * invalidateCache('/product/') // all product responses
510
+ * invalidateCache('/product/') // all legacy singular product responses
511
+ * invalidateCache('/products/') // all canonical plural product responses
511
512
  * ```
512
513
  */
513
514
  export function invalidateCache(urlPattern) {
@@ -593,7 +593,7 @@ export class IframeResponder {
593
593
  }
594
594
  // Product request - ONLY match direct product endpoint, not app config endpoints
595
595
  if (this.cache.product && this.options.productId) {
596
- const productMatch = path.match(/^public\/collection\/[^/]+\/product\/([^/]+)$/);
596
+ const productMatch = path.match(/^public\/collection\/[^/]+\/products?\/([^/]+)$/);
597
597
  if (productMatch && productMatch[1] === this.options.productId) {
598
598
  return JSON.parse(JSON.stringify(this.cache.product));
599
599
  }
package/dist/index.d.ts CHANGED
@@ -16,7 +16,8 @@ export type { BatchResponse, BatchCreateRequest, BatchUpdateRequest, } from "./t
16
16
  export type { VariantResponse, VariantCreateRequest, VariantUpdateRequest, } from "./types/variant";
17
17
  export type { BroadcastSendRequest } from "./types/broadcasts";
18
18
  export type { AppConfigOptions } from "./api/appConfiguration";
19
- export type { ProductCreateRequest, ProductUpdateRequest, Product, } from "./types/product";
19
+ export type { AdditionalGtin, ISODateString, JsonPrimitive, JsonValue, ProductCreateRequest, ProductClaimCreateInput, ProductClaimCreateRequestBody, ProductClaimLookupInput, ProductFacetMap, ProductFacetValue, ProductImage, ProductImageThumbnails, ProductImageUrlInput, ProductKey, ProductQueryRequest, ProductQueryResponse, ProductUpdateRequest, Product, ProductWriteInput, PublicProduct, } from "./types/product";
20
+ export type { FacetBucket, FacetDefinition, FacetDefinitionWriteInput, FacetGetParams, FacetListParams, FacetListResponse, FacetQueryRequest, FacetQueryResponse, FacetValue, FacetValueDefinition, FacetValueGetParams, FacetValueListParams, FacetValueListResponse, FacetValueResponse, FacetValueWriteInput, PublicFacetListParams, } from "./types/facets";
20
21
  export type { Collection, CollectionResponse, CollectionCreateRequest, CollectionUpdateRequest, } from "./types/collection";
21
22
  export type { Proof, ProofResponse, ProofCreateRequest, ProofUpdateRequest, ProofClaimRequest, } from "./types/proof";
22
23
  export type { QrShortCodeLookupResponse, } from "./types/qr";