@proveanything/smartlinks 1.15.20 → 1.15.22

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.15.20 | Generated: 2026-08-25T07:03:45.544Z
3
+ Version: 1.15.22 | Generated: 2026-08-27T17:34:12.788Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -33,6 +33,9 @@ For detailed guides on specific features:
33
33
  - **[Theme System](theme.system.md)** - Theme configuration and customization
34
34
  - **[Theme Defaults](theme-defaults.md)** - Default theme values and presets
35
35
  - **[Proof Claiming Methods](proof-claiming-methods.md)** - All methods for claiming/registering product ownership (NFC tags, serial numbers, auto-generated claims)
36
+ - **[Proof Share Grants](proof-share-grants.md)** - Delegated, scoped, revocable bearer access to a single proof (read/comment/verify-owner links)
37
+ - **[Proof Ownership Transfer](proof-ownership-transfer.md)** - Moving a proof to a new owner: directed transfer, open release, accept/cancel, and the state machine
38
+ - **[Item Context](item-context.md)** - The `itemContext` container prop derived from a serial-proof URL or NFC tap (what item the URL points at)
36
39
  - **[Product Facets SDK](PRODUCT_FACETS_SDK.md)** - Admin and public product facet endpoints and TypeScript interfaces
37
40
  - **[Attestations](attestations.md)** - Append-only fact log with cryptographic chain integrity, time-series analytics, and public/owner/admin visibility
38
41
  - **[Auth Kit](auth-kit.md)** - End-user authentication flows (email/password, magic link, OTP, OAuth) for microapps
@@ -8264,6 +8267,11 @@ interface PortalPathParams {
8264
8267
  proof?: Proof | string
8265
8268
  queryParams?: Record<string, string>
8266
8269
  pathOnly?: boolean
8270
+ * Override custom-domain detection. When the collection is served from its own
8271
+ * custom domain, a GS1 link resolves `/01/{gtin}` directly (the host identifies
8272
+ * the collection), so the `/gc/{shortId}` prefix is dropped. Left undefined, this
8273
+ * is auto-detected from `collection.redirectUrl` or a non-platform `portalUrl` host.
8274
+ customDomain?: boolean
8267
8275
  }
8268
8276
  ```
8269
8277
 
@@ -77,16 +77,26 @@ Builds a full portal URL based on the provided parameters. Returns full URL by d
77
77
 
78
78
  - `pathOnly` (optional, default: `false`) - Return only the path without domain
79
79
  Set to `true` to get `/c/abc/prod` instead of `https://domain.com/c/abc/prod`
80
+ - `customDomain` (optional) - Override custom-domain detection. When a collection is
81
+ served from its own custom domain, a GS1 link resolves `/01/{gtin}` directly (the host
82
+ identifies the collection), so the `/gc/{shortId}` prefix is dropped. Leave unset to
83
+ auto-detect from `collection.redirectUrl` or a non-platform `portalUrl` host.
80
84
 
81
85
  **Path Formats:**
82
86
 
83
87
  - Basic product: `/c/{shortId}/{productId}`
84
88
  - With proof: `/c/{shortId}/{productId}/{proofId}`
85
- - GTIN (own): `/01/{gtin}` (when product.ownGtin is true)
86
- - GTIN (not own): `/gc/{shortId}/01/{gtin}` (when product.ownGtin is false)
89
+ - GTIN (own, or on a custom domain): `/01/{gtin}` when `product.ownGtin` is set, **or** the
90
+ collection is on its own custom domain (bare `/01/` resolves via the host)
91
+ - GTIN (not own, on the shared platform domain): `/gc/{shortId}/01/{gtin}`
87
92
  - With batch: adds `/10/{batchId}` and optionally `?17={expiryDate}`
88
93
  - With variant: adds `/22/{variantId}`
89
94
 
95
+ **Custom domain behaviour:** On `smartlinks.app`, a non-master GTIN needs the `/gc/{shortId}`
96
+ collection prefix so the server can scope it; a master GTIN (`ownGtin`) uses bare `/01/`.
97
+ On a collection's **own custom domain**, the host already identifies the collection, so the
98
+ generator emits the clean `https://customdomain/01/{gtin}` for any product — no `/gc/` prefix.
99
+
90
100
  ## Examples
91
101
 
92
102
  ### Full URL (Default Behavior)
@@ -30,6 +30,13 @@ export interface PortalPathParams {
30
30
  queryParams?: Record<string, string>;
31
31
  /** Return only the path without domain (default: false, returns full URL) */
32
32
  pathOnly?: boolean;
33
+ /**
34
+ * Override custom-domain detection. When the collection is served from its own
35
+ * custom domain, a GS1 link resolves `/01/{gtin}` directly (the host identifies
36
+ * the collection), so the `/gc/{shortId}` prefix is dropped. Left undefined, this
37
+ * is auto-detected from `collection.redirectUrl` or a non-platform `portalUrl` host.
38
+ */
39
+ customDomain?: boolean;
33
40
  }
34
41
  /**
35
42
  * Builds a portal path/URL based on the provided parameters.
@@ -43,8 +50,9 @@ export interface PortalPathParams {
43
50
  * Supports multiple path formats:
44
51
  * - Basic product: `/c/{shortId}/{productId}`
45
52
  * - With proof: `/c/{shortId}/{productId}/{proofId}`
46
- * - GTIN (own): `/01/{gtin}` - ownGtin is read from the product object
47
- * - GTIN (not own): `/gc/{shortId}/01/{gtin}`
53
+ * - GTIN (own, or on a custom domain): `/01/{gtin}` `ownGtin` is read from the product;
54
+ * a custom domain (see `customDomain` / `collection.redirectUrl`) also uses this bare form
55
+ * - GTIN (not own, on the shared platform domain): `/gc/{shortId}/01/{gtin}`
48
56
  * - With batch: adds `/10/{batchId}` and optionally `?17={expiryDate}`
49
57
  * - With variant: adds `/22/{variantId}`
50
58
  *
@@ -1,3 +1,21 @@
1
+ // Hosts served by the platform itself (not a collection's own custom domain). A base
2
+ // URL on any of these is NOT a custom domain, so non-master GTINs still need the
3
+ // `/gc/{shortId}` collection prefix. `portalUrl` is only ever set to the platform
4
+ // default or a collection's custom domain, so exact-host matching is sufficient here.
5
+ const PLATFORM_HOSTS = ['smartlinks.app', 'mysmartlinks.app', 'zt.smartlinks.io'];
6
+ /** True when `baseUrl`'s host is a collection's own custom domain (not a platform host). */
7
+ function baseIsCustomDomain(baseUrl) {
8
+ if (!baseUrl)
9
+ return false;
10
+ let host;
11
+ try {
12
+ host = new URL(baseUrl).hostname.toLowerCase().replace(/^www\./, '');
13
+ }
14
+ catch (_a) {
15
+ return false;
16
+ }
17
+ return host.length > 0 && !PLATFORM_HOSTS.includes(host);
18
+ }
1
19
  /**
2
20
  * Builds a portal path/URL based on the provided parameters.
3
21
  *
@@ -10,8 +28,9 @@
10
28
  * Supports multiple path formats:
11
29
  * - Basic product: `/c/{shortId}/{productId}`
12
30
  * - With proof: `/c/{shortId}/{productId}/{proofId}`
13
- * - GTIN (own): `/01/{gtin}` - ownGtin is read from the product object
14
- * - GTIN (not own): `/gc/{shortId}/01/{gtin}`
31
+ * - GTIN (own, or on a custom domain): `/01/{gtin}` `ownGtin` is read from the product;
32
+ * a custom domain (see `customDomain` / `collection.redirectUrl`) also uses this bare form
33
+ * - GTIN (not own, on the shared platform domain): `/gc/{shortId}/01/{gtin}`
15
34
  * - With batch: adds `/10/{batchId}` and optionally `?17={expiryDate}`
16
35
  * - With variant: adds `/22/{variantId}`
17
36
  *
@@ -60,20 +79,26 @@
60
79
  * ```
61
80
  */
62
81
  export function buildPortalPath(params) {
63
- var _a, _b;
82
+ var _a, _b, _c;
64
83
  const { collection, product, productId, batch, batchId, variant, proof, queryParams = {}, pathOnly = false } = params;
65
84
  // Extract values from collection
66
85
  const shortId = collection.shortId;
67
86
  const baseUrl = 'portalUrl' in collection ? collection.portalUrl : undefined;
87
+ // A collection on its own custom domain resolves `/01/{gtin}` directly (the host
88
+ // maps to the collection server-side), so the `/gc/{shortId}` prefix is dropped.
89
+ // Explicit override wins; otherwise detect from `redirectUrl` (the server's own
90
+ // custom-domain signal) or a non-platform `portalUrl` host.
91
+ const redirectUrl = 'redirectUrl' in collection ? collection.redirectUrl : undefined;
92
+ const customDomain = (_a = params.customDomain) !== null && _a !== void 0 ? _a : (!!redirectUrl || baseIsCustomDomain(baseUrl));
68
93
  // Extract product values
69
94
  let gtin;
70
95
  let ownGtin;
71
96
  let extractedProductId;
72
97
  if (product) {
73
98
  extractedProductId = product.id;
74
- gtin = (_a = product.gtin) !== null && _a !== void 0 ? _a : undefined;
99
+ gtin = (_b = product.gtin) !== null && _b !== void 0 ? _b : undefined;
75
100
  // ownGtin is a critical product setting - only read from product, never override
76
- ownGtin = 'ownGtin' in product ? (_b = product.ownGtin) !== null && _b !== void 0 ? _b : undefined : undefined;
101
+ ownGtin = 'ownGtin' in product ? (_c = product.ownGtin) !== null && _c !== void 0 ? _c : undefined : undefined;
77
102
  }
78
103
  else if (productId) {
79
104
  extractedProductId = productId;
@@ -114,8 +139,11 @@ export function buildPortalPath(params) {
114
139
  const searchParams = new URLSearchParams();
115
140
  // Build pathname based on GTIN or product ID
116
141
  if (gtin) {
117
- // GS1 Digital Link format
118
- if (ownGtin) {
142
+ // GS1 Digital Link format. A bare `/01/{gtin}` is used when the product owns the
143
+ // GTIN globally (master registry) OR when we're on the collection's custom domain
144
+ // (the host resolves the collection). Otherwise the GTIN must be scoped to the
145
+ // collection with the `/gc/{shortId}` prefix on the shared platform domain.
146
+ if (ownGtin || customDomain) {
119
147
  pathname = `/01/${gtin}`;
120
148
  }
121
149
  else {
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 1.15.20 | Generated: 2026-08-25T07:03:45.544Z
3
+ Version: 1.15.22 | Generated: 2026-08-27T17:34:12.788Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -33,6 +33,9 @@ For detailed guides on specific features:
33
33
  - **[Theme System](theme.system.md)** - Theme configuration and customization
34
34
  - **[Theme Defaults](theme-defaults.md)** - Default theme values and presets
35
35
  - **[Proof Claiming Methods](proof-claiming-methods.md)** - All methods for claiming/registering product ownership (NFC tags, serial numbers, auto-generated claims)
36
+ - **[Proof Share Grants](proof-share-grants.md)** - Delegated, scoped, revocable bearer access to a single proof (read/comment/verify-owner links)
37
+ - **[Proof Ownership Transfer](proof-ownership-transfer.md)** - Moving a proof to a new owner: directed transfer, open release, accept/cancel, and the state machine
38
+ - **[Item Context](item-context.md)** - The `itemContext` container prop derived from a serial-proof URL or NFC tap (what item the URL points at)
36
39
  - **[Product Facets SDK](PRODUCT_FACETS_SDK.md)** - Admin and public product facet endpoints and TypeScript interfaces
37
40
  - **[Attestations](attestations.md)** - Append-only fact log with cryptographic chain integrity, time-series analytics, and public/owner/admin visibility
38
41
  - **[Auth Kit](auth-kit.md)** - End-user authentication flows (email/password, magic link, OTP, OAuth) for microapps
@@ -8264,6 +8267,11 @@ interface PortalPathParams {
8264
8267
  proof?: Proof | string
8265
8268
  queryParams?: Record<string, string>
8266
8269
  pathOnly?: boolean
8270
+ * Override custom-domain detection. When the collection is served from its own
8271
+ * custom domain, a GS1 link resolves `/01/{gtin}` directly (the host identifies
8272
+ * the collection), so the `/gc/{shortId}` prefix is dropped. Left undefined, this
8273
+ * is auto-detected from `collection.redirectUrl` or a non-platform `portalUrl` host.
8274
+ customDomain?: boolean
8267
8275
  }
8268
8276
  ```
8269
8277
 
package/docs/utils.md CHANGED
@@ -77,16 +77,26 @@ Builds a full portal URL based on the provided parameters. Returns full URL by d
77
77
 
78
78
  - `pathOnly` (optional, default: `false`) - Return only the path without domain
79
79
  Set to `true` to get `/c/abc/prod` instead of `https://domain.com/c/abc/prod`
80
+ - `customDomain` (optional) - Override custom-domain detection. When a collection is
81
+ served from its own custom domain, a GS1 link resolves `/01/{gtin}` directly (the host
82
+ identifies the collection), so the `/gc/{shortId}` prefix is dropped. Leave unset to
83
+ auto-detect from `collection.redirectUrl` or a non-platform `portalUrl` host.
80
84
 
81
85
  **Path Formats:**
82
86
 
83
87
  - Basic product: `/c/{shortId}/{productId}`
84
88
  - With proof: `/c/{shortId}/{productId}/{proofId}`
85
- - GTIN (own): `/01/{gtin}` (when product.ownGtin is true)
86
- - GTIN (not own): `/gc/{shortId}/01/{gtin}` (when product.ownGtin is false)
89
+ - GTIN (own, or on a custom domain): `/01/{gtin}` when `product.ownGtin` is set, **or** the
90
+ collection is on its own custom domain (bare `/01/` resolves via the host)
91
+ - GTIN (not own, on the shared platform domain): `/gc/{shortId}/01/{gtin}`
87
92
  - With batch: adds `/10/{batchId}` and optionally `?17={expiryDate}`
88
93
  - With variant: adds `/22/{variantId}`
89
94
 
95
+ **Custom domain behaviour:** On `smartlinks.app`, a non-master GTIN needs the `/gc/{shortId}`
96
+ collection prefix so the server can scope it; a master GTIN (`ownGtin`) uses bare `/01/`.
97
+ On a collection's **own custom domain**, the host already identifies the collection, so the
98
+ generator emits the clean `https://customdomain/01/{gtin}` for any product — no `/gc/` prefix.
99
+
90
100
  ## Examples
91
101
 
92
102
  ### Full URL (Default Behavior)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.15.20",
3
+ "version": "1.15.22",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -17,6 +17,7 @@
17
17
  "README.md"
18
18
  ],
19
19
  "scripts": {
20
+ "test": "node test/run.cjs",
20
21
  "build": "tsc && node generate-api-summary.js && node generate-openapi.js && node scripts/copy-docs-to-dist.js",
21
22
  "docs": "typedoc",
22
23
  "docs:summary": "node generate-api-summary.js",