@proveanything/smartlinks 1.13.5 → 1.13.8

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 CHANGED
@@ -75,13 +75,13 @@ initializeApi({
75
75
  List public collections and fetch products:
76
76
 
77
77
  ```ts
78
- import { collection, product } from '@proveanything/smartlinks'
78
+ import { collection, products } from '@proveanything/smartlinks'
79
79
 
80
80
  const collections = await collection.list(false) // public endpoint
81
81
  const first = collections[0]
82
82
  if (first) {
83
- const products = await product.list(first.id, false) // public endpoint
84
- console.log('First product:', products[0])
83
+ const items = await products.list(first.id, false) // public endpoint
84
+ console.log('First product:', items[0])
85
85
  }
86
86
  ```
87
87
 
@@ -90,28 +90,51 @@ if (first) {
90
90
  **Public storefront or portal experience**
91
91
 
92
92
  ```ts
93
- import { initializeApi, collection, product } from '@proveanything/smartlinks'
93
+ import { initializeApi, collection, products } from '@proveanything/smartlinks'
94
94
 
95
95
  initializeApi({ baseURL: 'https://smartlinks.app/api/v1' })
96
96
 
97
97
  const collections = await collection.list(false)
98
- const products = await product.list('collectionId', false)
98
+ const items = await products.list('collectionId', false)
99
99
  ```
100
100
 
101
101
  **Server-side admin scripts or back office tools**
102
102
 
103
103
  ```ts
104
- import { initializeApi, product } from '@proveanything/smartlinks'
104
+ import { initializeApi, products } from '@proveanything/smartlinks'
105
105
 
106
106
  initializeApi({
107
107
  baseURL: 'https://smartlinks.app/api/v1',
108
108
  apiKey: process.env.SMARTLINKS_API_KEY,
109
109
  })
110
110
 
111
- const created = await product.create('collectionId', { name: 'New product' })
111
+ const created = await products.create('collectionId', { name: 'New product' })
112
112
  console.log(created.id)
113
113
  ```
114
114
 
115
+ ### Product API migration: use products (plural)
116
+
117
+ The SDK keeps `product` (singular) for backward compatibility, but it is deprecated.
118
+ For all new integrations, use `products` (plural).
119
+
120
+ ```ts
121
+ // Preferred
122
+ import { products } from '@proveanything/smartlinks'
123
+
124
+ await products.get(collectionId, productId, false)
125
+ await products.list(collectionId, false)
126
+ await products.query(collectionId, { query: { search: 'cabernet' } })
127
+ ```
128
+
129
+ Quick mapping:
130
+
131
+ - `product.get` -> `products.get`
132
+ - `product.list` -> `products.list`
133
+ - `product.create` -> `products.create`
134
+ - `product.update` -> `products.update`
135
+ - `product.remove` -> `products.remove`
136
+ - `product.find` / `product.publicFind` -> `products.query` / `products.get`
137
+
115
138
  **AI-powered assistant or setup flow**
116
139
 
117
140
  ```ts
@@ -181,10 +204,10 @@ The SDK automatically normalizes various server error response formats into a co
181
204
  // { error: "..." }
182
205
 
183
206
  // All are normalized to SmartlinksApiError with consistent access:
184
- import { SmartlinksApiError, product } from '@proveanything/smartlinks'
207
+ import { SmartlinksApiError, products } from '@proveanything/smartlinks'
185
208
 
186
209
  try {
187
- const item = await product.get('collectionId', 'productId', false)
210
+ const item = await products.get('collectionId', 'productId', false)
188
211
  } catch (error) {
189
212
  if (error instanceof SmartlinksApiError) {
190
213
  console.error({
@@ -286,15 +309,15 @@ For complete documentation, see [docs/utils.md](docs/utils.md).
286
309
  ### Products
287
310
 
288
311
  ```ts
289
- import { product } from '@proveanything/smartlinks'
312
+ import { products } from '@proveanything/smartlinks'
290
313
 
291
314
  // Public fetch
292
- const item = await product.get('collectionId', 'productId', false)
315
+ const item = await products.get('collectionId', 'productId', false)
293
316
 
294
317
  // Admin create/update/delete (requires auth)
295
- await product.create('collectionId', { name: 'New product' })
296
- await product.update('collectionId', 'productId', { description: 'Updated' })
297
- await product.remove('collectionId', 'productId')
318
+ await products.create('collectionId', { name: 'New product' })
319
+ await products.update('collectionId', 'productId', { description: 'Updated' })
320
+ await products.remove('collectionId', 'productId')
298
321
  ```
299
322
 
300
323
  ### Assets
package/dist/README.md CHANGED
@@ -38,16 +38,21 @@ initializeApi({
38
38
  List public collections and fetch products:
39
39
 
40
40
  ```ts
41
- import { collection, product } from '@proveanything/smartlinks'
41
+ import { collection, products } from '@proveanything/smartlinks'
42
42
 
43
43
  const collections = await collection.list(false) // public endpoint
44
44
  const first = collections[0]
45
45
  if (first) {
46
- const products = await product.list(first.id, false) // public endpoint
47
- console.log('First product:', products[0])
46
+ const items = await products.list(first.id, false) // public endpoint
47
+ console.log('First product:', items[0])
48
48
  }
49
49
  ```
50
50
 
51
+ ### Product API migration: use products (plural)
52
+
53
+ The SDK keeps `product` (singular) for backward compatibility, but it is deprecated.
54
+ For all new integrations, use `products` (plural).
55
+
51
56
  ## Authentication
52
57
 
53
58
  Use the built-in helpers to log in and verify tokens. After a successful login, the SDK stores the bearer token for subsequent calls.
@@ -100,10 +105,10 @@ The SDK automatically normalizes various server error response formats into a co
100
105
  // { error: "..." }
101
106
 
102
107
  // All are normalized to SmartlinksApiError with consistent access:
103
- import { SmartlinksApiError, product } from '@proveanything/smartlinks'
108
+ import { SmartlinksApiError, products } from '@proveanything/smartlinks'
104
109
 
105
110
  try {
106
- const item = await product.get('collectionId', 'productId', false)
111
+ const item = await products.get('collectionId', 'productId', false)
107
112
  } catch (error) {
108
113
  if (error instanceof SmartlinksApiError) {
109
114
  console.error({
@@ -160,15 +165,15 @@ For comprehensive error handling examples and migration guidance, see:
160
165
  ### Products
161
166
 
162
167
  ```ts
163
- import { product } from '@proveanything/smartlinks'
168
+ import { products } from '@proveanything/smartlinks'
164
169
 
165
170
  // Public fetch
166
- const item = await product.get('collectionId', 'productId', false)
171
+ const item = await products.get('collectionId', 'productId', false)
167
172
 
168
173
  // Admin create/update/delete (requires auth)
169
- await product.create('collectionId', { name: 'New product' })
170
- await product.update('collectionId', 'productId', { description: 'Updated' })
171
- await product.remove('collectionId', 'productId')
174
+ await products.create('collectionId', { name: 'New product' })
175
+ await products.update('collectionId', 'productId', { description: 'Updated' })
176
+ await products.remove('collectionId', 'productId')
172
177
  ```
173
178
 
174
179
  ### Assets
@@ -276,7 +276,7 @@ function queueAnalytics(path, body, options) {
276
276
  const preferBeacon = (options === null || options === void 0 ? void 0 : options.preferBeacon) !== false;
277
277
  if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function' && preferBeacon) {
278
278
  try {
279
- const blob = new Blob([payload], { type: 'application/json' });
279
+ const blob = new Blob([payload], { type: 'text/plain;charset=UTF-8' });
280
280
  const queued = navigator.sendBeacon(url, blob);
281
281
  if (queued)
282
282
  return { queued: true, transport: 'beacon' };
@@ -287,9 +287,12 @@ function queueAnalytics(path, body, options) {
287
287
  if (typeof fetch === 'function') {
288
288
  void fetch(url, {
289
289
  method: 'POST',
290
- headers: Object.assign({ 'Content-Type': 'application/json' }, headers),
291
- body: payload,
290
+ mode: 'cors',
292
291
  keepalive: true,
292
+ headers: {
293
+ 'Content-Type': 'text/plain;charset=UTF-8',
294
+ },
295
+ body: payload,
293
296
  }).catch(() => { });
294
297
  return { queued: true, transport: 'fetch' };
295
298
  }
@@ -107,6 +107,9 @@ export declare namespace app {
107
107
  /**
108
108
  * List records with optional query parameters
109
109
  * GET /records
110
+ *
111
+ * Public/owner callers only receive records with `status: "active"`.
112
+ * Admin callers can query all statuses (for example `draft`/`archived`).
110
113
  */
111
114
  function list(collectionId: string, appId: string, params?: RecordListQueryParams, admin?: boolean): Promise<PaginatedResponse<AppRecord>>;
112
115
  /**
@@ -196,7 +199,7 @@ export declare namespace app {
196
199
  * ordered by specificity descending (most specific first).
197
200
  * POST /records/match
198
201
  *
199
- * @param admin - false for public endpoint (visibility-filtered), true for admin
202
+ * @param admin - false for public endpoint (visibility-filtered, active-only), true for admin
200
203
  *
201
204
  * @example
202
205
  * ```ts
@@ -245,7 +248,7 @@ export declare namespace app {
245
248
  * deduplicated and sorted by specificity descending.
246
249
  * POST /records/resolve-all
247
250
  *
248
- * @param admin - false for public (visibility-filtered), true for admin (all records)
251
+ * @param admin - false for public (visibility-filtered, active-only), true for admin (all statuses)
249
252
  */
250
253
  function resolveAll(collectionId: string, appId: string, input: ResolveAllParams, admin?: boolean): Promise<ResolveAllResult>;
251
254
  /**
@@ -203,6 +203,9 @@ export var app;
203
203
  /**
204
204
  * List records with optional query parameters
205
205
  * GET /records
206
+ *
207
+ * Public/owner callers only receive records with `status: "active"`.
208
+ * Admin callers can query all statuses (for example `draft`/`archived`).
206
209
  */
207
210
  async function list(collectionId, appId, params, admin = false) {
208
211
  const path = basePath(collectionId, appId, admin);
@@ -323,7 +326,7 @@ export var app;
323
326
  * ordered by specificity descending (most specific first).
324
327
  * POST /records/match
325
328
  *
326
- * @param admin - false for public endpoint (visibility-filtered), true for admin
329
+ * @param admin - false for public endpoint (visibility-filtered, active-only), true for admin
327
330
  *
328
331
  * @example
329
332
  * ```ts
@@ -384,7 +387,7 @@ export var app;
384
387
  * deduplicated and sorted by specificity descending.
385
388
  * POST /records/resolve-all
386
389
  *
387
- * @param admin - false for public (visibility-filtered), true for admin (all records)
390
+ * @param admin - false for public (visibility-filtered, active-only), true for admin (all statuses)
388
391
  */
389
392
  async function resolveAll(collectionId, appId, input, admin = false) {
390
393
  const path = `${basePath(collectionId, appId, admin)}/resolve-all`;
package/dist/api/asset.js CHANGED
@@ -9,9 +9,20 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { request, post, put, del, getApiHeaders, isProxyEnabled, proxyUploadFormData } from "../http";
12
+ import { request, post, put, del, getApiHeaders, getBaseURL, isProxyEnabled, proxyUploadFormData } from "../http";
13
13
  export var asset;
14
14
  (function (asset) {
15
+ function resolveApiUrl(path) {
16
+ const configuredBase = getBaseURL();
17
+ if (configuredBase) {
18
+ return `${configuredBase}${path}`;
19
+ }
20
+ // Backward compatibility for legacy browser integrations that set a global base URL.
21
+ if (typeof window !== 'undefined' && window.SMARTLINKS_API_BASEURL) {
22
+ return `${window.SMARTLINKS_API_BASEURL}${path}`;
23
+ }
24
+ throw new Error('HTTP client is not initialized. Call initializeApi(...) first.');
25
+ }
15
26
  /**
16
27
  * Error type for asset uploads
17
28
  */
@@ -55,9 +66,7 @@ export var asset;
55
66
  formData.append("metadata", JSON.stringify(options.metadata));
56
67
  // If progress callback provided and NOT in proxy mode, use XHR for progress events (browser-only)
57
68
  if (options.onProgress && typeof window !== "undefined" && !isProxyEnabled()) {
58
- const url = (typeof window !== "undefined" && window.SMARTLINKS_API_BASEURL)
59
- ? window.SMARTLINKS_API_BASEURL + path
60
- : path;
69
+ const url = resolveApiUrl(path);
61
70
  const headers = getApiHeaders ? getApiHeaders() : {};
62
71
  return new Promise((resolve, reject) => {
63
72
  const xhr = new XMLHttpRequest();
@@ -346,9 +355,7 @@ export var asset;
346
355
  const formData = new FormData();
347
356
  formData.append('file', options.file);
348
357
  if (options.onProgress && typeof window !== 'undefined' && !isProxyEnabled()) {
349
- const url = (typeof window !== 'undefined' && window.SMARTLINKS_API_BASEURL)
350
- ? window.SMARTLINKS_API_BASEURL + path
351
- : path;
358
+ const url = resolveApiUrl(path);
352
359
  const headers = getApiHeaders ? getApiHeaders() : {};
353
360
  return new Promise((resolve, reject) => {
354
361
  const xhr = new XMLHttpRequest();
@@ -469,9 +476,7 @@ export var asset;
469
476
  if (options.metadata)
470
477
  formData.append('metadata', JSON.stringify(options.metadata));
471
478
  if (options.onProgress && typeof window !== 'undefined' && !isProxyEnabled()) {
472
- const baseUrl = (typeof window !== 'undefined' && window.SMARTLINKS_API_BASEURL)
473
- ? window.SMARTLINKS_API_BASEURL + path
474
- : path;
479
+ const baseUrl = resolveApiUrl(path);
475
480
  const headers = Object.assign(Object.assign({}, getApiHeaders()), { 'X-Upload-Token': options.tokenId });
476
481
  return new Promise((resolve, reject) => {
477
482
  const xhr = new XMLHttpRequest();
@@ -508,9 +513,7 @@ export var asset;
508
513
  }
509
514
  // Pass the token as a header via a custom fetch; post() doesn't accept extra headers,
510
515
  // so we build the request manually using the same base URL resolution.
511
- const baseUrl = (typeof window !== 'undefined' && window.SMARTLINKS_API_BASEURL)
512
- ? window.SMARTLINKS_API_BASEURL + path
513
- : path;
516
+ const baseUrl = resolveApiUrl(path);
514
517
  const headers = Object.assign(Object.assign({}, getApiHeaders()), { 'X-Upload-Token': options.tokenId });
515
518
  const response = await fetch(baseUrl, { method: 'POST', headers, body: formData });
516
519
  if (!response.ok) {
@@ -1,4 +1,4 @@
1
- import type { AuthLoginResponse, PhoneSendCodeResponse, PhoneVerifyResponse, PasswordResetRequestResponse, VerifyResetTokenResponse, PasswordResetCompleteResponse, EmailVerificationActionResponse, EmailVerifyTokenResponse, AuthKitConfig, MagicLinkSendResponse, MagicLinkVerifyResponse, UserProfile, ProfileUpdateData, SuccessResponse } from "../types/authKit";
1
+ import type { AuthLoginResponse, PhoneSendCodeResponse, PhoneVerifyResponse, PasswordResetRequestResponse, VerifyResetTokenResponse, PasswordResetCompleteResponse, EmailVerificationActionResponse, EmailVerifyTokenResponse, AuthKitConfig, MagicLinkSendResponse, MagicLinkVerifyResponse, UserProfile, ProfileUpdateData, SuccessResponse, SendWhatsAppRequest, SendWhatsAppResponse, VerifyWhatsAppResponse, WhatsAppStatusResponse, SendSmsVerifyRequest, SendSmsVerifyResponse, VerifySmsResponse, UpsertContactRequest, UpsertContactResponse } from "../types/authKit";
2
2
  /**
3
3
  * Namespace containing helper functions for the new AuthKit API.
4
4
  * Legacy collection-based authKit helpers retained (marked as *Legacy*).
@@ -27,6 +27,18 @@ export declare namespace authKit {
27
27
  function sendPhoneCode(clientId: string, phoneNumber: string): Promise<PhoneSendCodeResponse>;
28
28
  /** Verify phone verification code (public). */
29
29
  function verifyPhoneCode(clientId: string, phoneNumber: string, code: string): Promise<PhoneVerifyResponse>;
30
+ /** Send a WhatsApp verification deep-link (public). */
31
+ function sendWhatsApp(clientId: string, body: SendWhatsAppRequest): Promise<SendWhatsAppResponse>;
32
+ /** Manually verify WhatsApp token if inbound webhook path is unavailable (public). */
33
+ function verifyWhatsApp(clientId: string, token: string, phoneNumber: string): Promise<VerifyWhatsAppResponse>;
34
+ /** Poll WhatsApp verification status for a token (public). */
35
+ function getWhatsAppStatus(clientId: string, token: string): Promise<WhatsAppStatusResponse>;
36
+ /** Send an SMS click-to-verify link (public). */
37
+ function sendSmsVerify(clientId: string, body: SendSmsVerifyRequest): Promise<SendSmsVerifyResponse>;
38
+ /** Verify an SMS click-to-verify token via API (public). */
39
+ function verifySms(clientId: string, token: string, phoneNumber?: string): Promise<VerifySmsResponse>;
40
+ /** Upsert contact identity after lightweight verification (public). */
41
+ function upsertContact(clientId: string, body: UpsertContactRequest): Promise<UpsertContactResponse>;
30
42
  function requestPasswordReset(clientId: string, data: {
31
43
  email: string;
32
44
  redirectUrl?: string;
@@ -46,6 +46,40 @@ export var authKit;
46
46
  return post(`/authkit/${encodeURIComponent(clientId)}/auth/phone/verify`, { phoneNumber, code });
47
47
  }
48
48
  authKit.verifyPhoneCode = verifyPhoneCode;
49
+ /** Send a WhatsApp verification deep-link (public). */
50
+ async function sendWhatsApp(clientId, body) {
51
+ return post(`/authkit/${encodeURIComponent(clientId)}/auth/whatsapp/send`, body);
52
+ }
53
+ authKit.sendWhatsApp = sendWhatsApp;
54
+ /** Manually verify WhatsApp token if inbound webhook path is unavailable (public). */
55
+ async function verifyWhatsApp(clientId, token, phoneNumber) {
56
+ return post(`/authkit/${encodeURIComponent(clientId)}/auth/whatsapp/verify`, { token, phoneNumber });
57
+ }
58
+ authKit.verifyWhatsApp = verifyWhatsApp;
59
+ /** Poll WhatsApp verification status for a token (public). */
60
+ async function getWhatsAppStatus(clientId, token) {
61
+ const encodedToken = encodeURIComponent(token);
62
+ return request(`/authkit/${encodeURIComponent(clientId)}/auth/whatsapp/status?token=${encodedToken}`);
63
+ }
64
+ authKit.getWhatsAppStatus = getWhatsAppStatus;
65
+ /** Send an SMS click-to-verify link (public). */
66
+ async function sendSmsVerify(clientId, body) {
67
+ return post(`/authkit/${encodeURIComponent(clientId)}/auth/sms/send`, body);
68
+ }
69
+ authKit.sendSmsVerify = sendSmsVerify;
70
+ /** Verify an SMS click-to-verify token via API (public). */
71
+ async function verifySms(clientId, token, phoneNumber) {
72
+ const payload = { token };
73
+ if (phoneNumber)
74
+ payload.phoneNumber = phoneNumber;
75
+ return post(`/authkit/${encodeURIComponent(clientId)}/auth/sms/verify`, payload);
76
+ }
77
+ authKit.verifySms = verifySms;
78
+ /** Upsert contact identity after lightweight verification (public). */
79
+ async function upsertContact(clientId, body) {
80
+ return post(`/authkit/${encodeURIComponent(clientId)}/contact/upsert`, body);
81
+ }
82
+ authKit.upsertContact = upsertContact;
49
83
  /* ===================================
50
84
  * Password Reset (Public flows)
51
85
  * =================================== */
@@ -106,7 +106,7 @@ export declare namespace comms {
106
106
  * No broadcast record is created. The send is logged to the contact's
107
107
  * communication history with sourceType: 'transactional'.
108
108
  *
109
- * POST /admin/collection/:collectionId/comm.send
109
+ * POST /admin/collection/:collectionId/comm/send
110
110
  *
111
111
  * @example
112
112
  * ```typescript
package/dist/api/comms.js CHANGED
@@ -201,7 +201,7 @@ export var comms;
201
201
  * No broadcast record is created. The send is logged to the contact's
202
202
  * communication history with sourceType: 'transactional'.
203
203
  *
204
- * POST /admin/collection/:collectionId/comm.send
204
+ * POST /admin/collection/:collectionId/comm/send
205
205
  *
206
206
  * @example
207
207
  * ```typescript
@@ -222,8 +222,19 @@ export var comms;
222
222
  * ```
223
223
  */
224
224
  async function sendTransactional(collectionId, body) {
225
- const path = `/admin/collection/${encodeURIComponent(collectionId)}/comm.send`;
226
- return post(path, body);
225
+ const encodedCollectionId = encodeURIComponent(collectionId);
226
+ const path = `/admin/collection/${encodedCollectionId}/comm/send`;
227
+ try {
228
+ return await post(path, body);
229
+ }
230
+ catch (error) {
231
+ // Backward compatibility for deployments still serving the legacy route.
232
+ if ((error === null || error === void 0 ? void 0 : error.statusCode) === 404 || (error === null || error === void 0 ? void 0 : error.code) === 404) {
233
+ const legacyPath = `/admin/collection/${encodedCollectionId}/comm.send`;
234
+ return post(legacyPath, body);
235
+ }
236
+ throw error;
237
+ }
227
238
  }
228
239
  comms.sendTransactional = sendTransactional;
229
240
  /**
@@ -75,7 +75,7 @@ export async function getPublicToken(params) {
75
75
  if (params.appId) {
76
76
  queryParams.append('appId', params.appId);
77
77
  }
78
- return request(`/api/public/push/token?${queryParams.toString()}`);
78
+ return request(`/public/push/token?${queryParams.toString()}`);
79
79
  }
80
80
  /**
81
81
  * Get an Ably token for admin real-time communication.
@@ -109,5 +109,5 @@ export async function getPublicToken(params) {
109
109
  * ```
110
110
  */
111
111
  export async function getAdminToken() {
112
- return request('/api/admin/auth/push');
112
+ return request('/admin/auth/push');
113
113
  }