@proveanything/smartlinks 2.0.54 → 2.0.56

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/dist/http.js CHANGED
@@ -210,6 +210,9 @@ function shouldSkipCache(path) {
210
210
  // Never cache auth, account, or user-identity endpoints — they depend on session state.
211
211
  if (/\/(auth|account)\//i.test(path))
212
212
  return true;
213
+ // Realtime tokens are single-use (a reused one is rejected by the provider) — never cache them.
214
+ if (/\/(push\/token|realtime\/)/i.test(path))
215
+ return true;
213
216
  // Never cache /me endpoints (contact/me, loyalty/me, etc.) — always user-specific.
214
217
  if (/\/me(\?|$)/i.test(path))
215
218
  return true;
package/dist/openapi.yaml CHANGED
@@ -123,7 +123,7 @@ paths:
123
123
  get:
124
124
  tags:
125
125
  - realtime
126
- summary: Get an Ably token for admin real-time communication.
126
+ summary: (subscribe only).
127
127
  operationId: realtime_getAdminToken
128
128
  security:
129
129
  - bearerAuth: []
@@ -13960,7 +13960,7 @@ paths:
13960
13960
  get:
13961
13961
  tags:
13962
13962
  - realtime
13963
- summary: realtime.getPublicToken
13963
+ summary: "`collection:{collectionId}:*` (subscribe; publish only for the collection's admins)."
13964
13964
  operationId: realtime_getPublicToken
13965
13965
  security: []
13966
13966
  parameters:
@@ -14018,6 +14018,33 @@ paths:
14018
14018
  description: Unauthorized
14019
14019
  404:
14020
14020
  description: Not found
14021
+ /public/realtime/publish:
14022
+ post:
14023
+ tags:
14024
+ - realtime
14025
+ summary: "One of your app's declared channels (manifest `realtime.channels`)."
14026
+ operationId: realtime_channel
14027
+ security: []
14028
+ responses:
14029
+ 200:
14030
+ description: Success
14031
+ content:
14032
+ application/json:
14033
+ schema:
14034
+ type: object
14035
+ additionalProperties: true
14036
+ 400:
14037
+ description: Bad request
14038
+ 401:
14039
+ description: Unauthorized
14040
+ 404:
14041
+ description: Not found
14042
+ requestBody:
14043
+ required: true
14044
+ content:
14045
+ application/json:
14046
+ schema:
14047
+ $ref: "#/components/schemas/RealtimeScope"
14021
14048
  /public/tags/{tagId}:
14022
14049
  get:
14023
14050
  tags:
@@ -19618,6 +19645,9 @@ components:
19618
19645
  $ref: "#/components/schemas/AppManifestExecutor"
19619
19646
  functions:
19620
19647
  $ref: "#/components/schemas/AppManifestFunctions"
19648
+ realtime:
19649
+ type: object
19650
+ additionalProperties: true
19621
19651
  data:
19622
19652
  $ref: "#/components/schemas/AppDataDeclaration"
19623
19653
  headless:
@@ -29830,6 +29860,79 @@ components:
29830
29860
  - nonce
29831
29861
  - mac
29832
29862
  - clientId
29863
+ RealtimeScope:
29864
+ type: object
29865
+ properties:
29866
+ collectionId:
29867
+ type: string
29868
+ appId:
29869
+ type: string
29870
+ required:
29871
+ - collectionId
29872
+ RealtimeMessage:
29873
+ type: object
29874
+ properties:
29875
+ channel:
29876
+ type: string
29877
+ event:
29878
+ type: string
29879
+ data: {}
29880
+ at:
29881
+ type: number
29882
+ required:
29883
+ - channel
29884
+ - event
29885
+ - data
29886
+ RealtimeChangeEvent:
29887
+ type: object
29888
+ properties:
29889
+ type:
29890
+ type: string
29891
+ id:
29892
+ type: string
29893
+ appId:
29894
+ type: string
29895
+ recordType:
29896
+ type: string
29897
+ productId:
29898
+ type: string
29899
+ proofId:
29900
+ type: string
29901
+ status:
29902
+ type: string
29903
+ at:
29904
+ type: number
29905
+ required:
29906
+ - type
29907
+ - at
29908
+ RealtimeChangeFilter:
29909
+ type: object
29910
+ properties:
29911
+ type:
29912
+ type: string
29913
+ id:
29914
+ type: string
29915
+ appId:
29916
+ type: string
29917
+ recordType:
29918
+ type: string
29919
+ productId:
29920
+ type: string
29921
+ proofId:
29922
+ type: string
29923
+ RealtimeChannelDeclaration:
29924
+ type: object
29925
+ properties:
29926
+ name:
29927
+ type: string
29928
+ subscribe:
29929
+ type: object
29930
+ additionalProperties: true
29931
+ publish:
29932
+ type: object
29933
+ additionalProperties: true
29934
+ required:
29935
+ - name
29833
29936
  RealtimeChannelPattern:
29834
29937
  type: string
29835
29938
  ResearchFetchRequest:
@@ -30958,28 +31061,3 @@ components:
30958
31061
  properties:
30959
31062
  appId:
30960
31063
  type: string
30961
- AllocateSequenceInput:
30962
- type: object
30963
- properties:
30964
- appId:
30965
- type: string
30966
- sequenceId:
30967
- type: string
30968
- subjectId:
30969
- type: string
30970
- productId:
30971
- type: string
30972
- required:
30973
- - appId
30974
- - sequenceId
30975
- - subjectId
30976
- AllocatedSequence:
30977
- type: object
30978
- properties:
30979
- number:
30980
- type: number
30981
- isNew:
30982
- type: boolean
30983
- required:
30984
- - number
30985
- - isNew
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  import type { AppDataDeclaration, AppHeadlessDeclaration } from './headless.js';
4
+ import type { RealtimeChannelDeclaration } from './realtime.js';
4
5
  /**
5
6
  * A bundle (widget or container) as returned by the collection widgets endpoint.
6
7
  *
@@ -806,6 +807,16 @@ export interface AppManifest {
806
807
  * @see AppManifestFunctions
807
808
  */
808
809
  functions?: AppManifestFunctions;
810
+ /**
811
+ * SmartLinks Realtime: the live channels this app uses, with who may listen and who may send
812
+ * (docs/realtime.md). Only declared channels exist — anything else is refused.
813
+ * ```json
814
+ * "realtime": { "channels": [ { "name": "draw", "subscribe": "public", "publish": "admin" } ] }
815
+ * ```
816
+ */
817
+ realtime?: {
818
+ channels: RealtimeChannelDeclaration[];
819
+ };
809
820
  /**
810
821
  * The app's public data model: its data types, how each is stored, fields, examples and read
811
822
  * recipes. Required for `headless`. @see AppDataDeclaration · docs/headless-providers.md
@@ -42,3 +42,47 @@ export interface AblyTokenRequest {
42
42
  * - collection:abc:users:active
43
43
  */
44
44
  export type RealtimeChannelPattern = string;
45
+ /** Where a realtime listener lives: the collection, and (for app channels) the app. */
46
+ export interface RealtimeScope {
47
+ collectionId: string;
48
+ appId?: string;
49
+ }
50
+ /** A message on a channel. `channel` is the logical name ("draw", "feed:admin"). */
51
+ export interface RealtimeMessage {
52
+ channel: string;
53
+ event: string;
54
+ data: unknown;
55
+ /** When it was sent (ms since epoch), when known. */
56
+ at?: number;
57
+ }
58
+ /** "This changed" — ids only; refetch through the normal API. */
59
+ export interface RealtimeChangeEvent {
60
+ /** 'product' | 'proof' | 'asset' | 'record' | 'collection' | 'collection.apps' | 'settings' | … */
61
+ type: string;
62
+ id?: string;
63
+ appId?: string;
64
+ recordType?: string;
65
+ productId?: string;
66
+ proofId?: string;
67
+ /** 'created' | 'updated' | 'deleted' (records) or 'create' | 'update' | 'delete' (products, proofs…) */
68
+ status?: string;
69
+ at: number;
70
+ }
71
+ /** Which changes to hear about — every field given must match. */
72
+ export interface RealtimeChangeFilter {
73
+ type?: string;
74
+ id?: string;
75
+ appId?: string;
76
+ recordType?: string;
77
+ productId?: string;
78
+ proofId?: string;
79
+ }
80
+ /** A channel an app declares in its manifest (`realtime.channels`). */
81
+ export interface RealtimeChannelDeclaration {
82
+ /** Lowercase letters, numbers, - and _; up to 40 characters. */
83
+ name: string;
84
+ /** Who may listen. Default 'admin'. */
85
+ subscribe?: "public" | "signedIn" | "admin";
86
+ /** Who may send: those levels, or 'server' (only the app's server functions). Default 'server'. */
87
+ publish?: "public" | "signedIn" | "admin" | "server";
88
+ }
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.54 | Generated: 2026-10-12T17:51:26.609Z
3
+ Version: 2.0.56 | Generated: 2026-10-12T20:58:59.335Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -154,7 +154,6 @@ The Smartlinks SDK is organized into the following namespaces:
154
154
  - **realtime** - Functions for realtime operations
155
155
  - **research** - Functions for research operations
156
156
  - **secrets** - Functions for secrets operations
157
- - **sequence** - Functions for sequence operations
158
157
  - **tags** - Functions for tags operations
159
158
  - **template** - Functions for template operations
160
159
  - **translations** - Functions for translations operations
@@ -2851,6 +2850,7 @@ interface AppManifest {
2851
2850
  publicViews?: PublicView[];
2852
2851
  executor?: AppManifestExecutor;
2853
2852
  functions?: AppManifestFunctions;
2853
+ realtime?: { channels: RealtimeChannelDeclaration[] };
2854
2854
  data?: AppDataDeclaration;
2855
2855
  headless?: AppHeadlessDeclaration;
2856
2856
  [key: string]: any;
@@ -9142,6 +9142,59 @@ interface AblyTokenRequest {
9142
9142
  }
9143
9143
  ```
9144
9144
 
9145
+ **RealtimeScope** (interface)
9146
+ ```typescript
9147
+ interface RealtimeScope {
9148
+ collectionId: string
9149
+ appId?: string
9150
+ }
9151
+ ```
9152
+
9153
+ **RealtimeMessage** (interface)
9154
+ ```typescript
9155
+ interface RealtimeMessage {
9156
+ channel: string
9157
+ event: string
9158
+ data: unknown
9159
+ at?: number
9160
+ }
9161
+ ```
9162
+
9163
+ **RealtimeChangeEvent** (interface)
9164
+ ```typescript
9165
+ interface RealtimeChangeEvent {
9166
+ type: string
9167
+ id?: string
9168
+ appId?: string
9169
+ recordType?: string
9170
+ productId?: string
9171
+ proofId?: string
9172
+ status?: string
9173
+ at: number
9174
+ }
9175
+ ```
9176
+
9177
+ **RealtimeChangeFilter** (interface)
9178
+ ```typescript
9179
+ interface RealtimeChangeFilter {
9180
+ type?: string
9181
+ id?: string
9182
+ appId?: string
9183
+ recordType?: string
9184
+ productId?: string
9185
+ proofId?: string
9186
+ }
9187
+ ```
9188
+
9189
+ **RealtimeChannelDeclaration** (interface)
9190
+ ```typescript
9191
+ interface RealtimeChannelDeclaration {
9192
+ name: string
9193
+ subscribe?: "public" | "signedIn" | "admin"
9194
+ publish?: "public" | "signedIn" | "admin" | "server"
9195
+ }
9196
+ ```
9197
+
9145
9198
  **RealtimeChannelPattern** = `string`
9146
9199
 
9147
9200
  ### research
@@ -9869,26 +9922,6 @@ interface AppSecretOptions {
9869
9922
  }
9870
9923
  ```
9871
9924
 
9872
- ### sequence (api)
9873
-
9874
- **AllocateSequenceInput** (interface)
9875
- ```typescript
9876
- interface AllocateSequenceInput {
9877
- appId: string
9878
- sequenceId: string
9879
- subjectId: string
9880
- productId?: string
9881
- }
9882
- ```
9883
-
9884
- **AllocatedSequence** (interface)
9885
- ```typescript
9886
- interface AllocatedSequence {
9887
- number: number
9888
- isNew: boolean
9889
- }
9890
- ```
9891
-
9892
9925
  ### conditions (utils)
9893
9926
 
9894
9927
  **BaseCondition** (interface)
@@ -12189,11 +12222,20 @@ Reset rate limit for a user
12189
12222
 
12190
12223
  ### realtime
12191
12224
 
12225
+ **channel**(scope: RealtimeScope & { appId: string }, name: string) → `void`
12226
+ One of your app's declared channels (manifest `realtime.channels`). ```ts const draw = realtime.channel({ collectionId, appId }, "draw") const off = draw.subscribe("status", (m) => setStatus(m.data)) await draw.publish("status", { phase: "spinning" }) // if the channel lets this viewer publish ```
12227
+
12228
+ **onChange**(scope: RealtimeScope, filter: RealtimeChangeFilter, onChangeFn: (change: RealtimeChangeEvent) → `void`
12229
+ Something changed: refetch it. IDs only — never data. Admins of the collection see every change; everyone else sees changes to public things (public app records, products). Filter by `type` ('product' | 'proof' | 'asset' | 'record' | 'collection' | 'collection.apps' | 'settings'), `id`, `appId`, `recordType`, `productId`, `proofId`. ```ts const off = realtime.onChange({ collectionId }, { type: "record", appId, recordType: "entry" }, () => refetch()) ```
12230
+
12231
+ **onMine**(scope: RealtimeScope, onMessage: (msg: RealtimeMessage) → `void`
12232
+ Messages for the signed-in person only (e.g. "scan" — a tag they just scanned on another device).
12233
+
12192
12234
  **getPublicToken**(params: RealtimeTokenRequest) → `Promise<AblyTokenRequest>`
12193
- Get an Ably token for public (user-scoped) real-time communication. This endpoint returns an Ably TokenRequest that can be used to initialize an Ably client with appropriate permissions for the specified collection and optional app. Requires user authentication (Bearer token). ```ts const tokenRequest = await realtime.getPublicToken({ collectionId: 'my-collection-id', appId: 'my-app-id' }) // Use with Ably const ably = new Ably.Realtime.Promise({ authCallback: async (data, callback) => { callback(null, tokenRequest) } }) // Subscribe to channels matching the pattern const channel = ably.channels.get('collection:my-collection-id:app:my-app-id:chat:general') await channel.subscribe('message', (msg) => console.log(msg.data)) ```
12235
+ `collection:{collectionId}:*` (subscribe; publish only for the collection's admins).
12194
12236
 
12195
12237
  **getAdminToken**() → `Promise<AblyTokenRequest>`
12196
- Get an Ably token for admin real-time communication. This endpoint returns an Ably TokenRequest that can be used to initialize an Ably client with admin permissions to receive system notifications and alerts. Admin users get subscribe-only (read-only) access to the interaction:{userId} channel pattern. Requires admin authentication (Bearer token). ```ts const tokenRequest = await realtime.getAdminToken() // Use with Ably const ably = new Ably.Realtime.Promise({ authCallback: async (data, callback) => { callback(null, tokenRequest) } }) // Subscribe to admin interaction channel const userId = 'my-user-id' const channel = ably.channels.get(`interaction:${userId}`) await channel.subscribe((message) => { console.log('Admin notification:', message.data) }) ```
12238
+ (subscribe only).
12197
12239
 
12198
12240
  ### research
12199
12241
 
@@ -12251,11 +12293,6 @@ Soft-delete a secret. DELETE /secrets/:ref
12251
12293
  id: string,
12252
12294
  query: { limit?: number; offset?: number } = {}) → `Promise<SegmentRecipientsResponse>`
12253
12295
 
12254
- ### sequence
12255
-
12256
- **allocate**(collectionId: string, input: AllocateSequenceInput) → `Promise<AllocatedSequence>`
12257
- Allocate (or return the existing) sequence number for a subject. Idempotent — safe to call on load (auto-enter) and on a button tap; a subject that already has a number gets it back with `isNew: false`. const { number, isNew } = await sequence.allocate(collectionId, { appId: 'raffle-app', sequenceId: 'raffle', subjectId: claimSetId, }) `ctx.sl.counters.next()` + `ctx.sl.appRecords.claim()` (docs/server-functions.md).
12258
-
12259
12296
  ### sessions
12260
12297
 
12261
12298
  **stats**(collectionId: string) → `Promise<SessionStatistics>`
package/docs/overview.md CHANGED
@@ -69,7 +69,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
69
69
  | **Portal Request Action** | `docs/portal-request-action.md` | Triggering portal built-in actions (__qrScanner, __share, __logout, etc.) from sub-apps |
70
70
  | **Interactions** | `docs/interactions.md` | Business events, outcomes, voting, competitions, and journey triggers |
71
71
  | **App Config Files** | `docs/app-manifest.md` | Full field-by-field reference for both JSON config files |
72
- | **Real-time Messaging** | `docs/realtime.md` | Adding Ably real-time features (chat, live updates) |
72
+ | **Realtime** | `docs/realtime.md` | Live updates: change events (refetch when something changes) and declared app channels (a draw, a status) — no provider library or keys |
73
73
  | **Liquid Templates** | `docs/liquid-templates.md` | Dynamic content rendering with LiquidJS |
74
74
  | **Iframe Responder** | `docs/iframe-responder.md` | Iframe communication and proxy mode internals |
75
75
  | **AI Guide Template** | `docs/ai-guide-template.md` | Template for creating `public/ai-guide.md` — customise per app |
@@ -93,7 +93,6 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
93
93
  | **Container Tracking** | `docs/container-tracking.md` | Physical/logical **item** container groupings — *not* app containers (see containers.md) |
94
94
  | **Lots** | `docs/lots.md` | Cross-SKU production "Lot" entity |
95
95
  | **Loyalty** | `docs/loyalty.md` | Points, members, earning rules |
96
- | **Sequences** | `docs/sequences.md` | RETIRING — number things in your own server function: `ctx.sl.counters` + `appRecords.claim` (server-functions.md) |
97
96
  | **Integrations** | `docs/integrations.md` | Inbound/outbound external-system integration flows |
98
97
  | **Item Context** | `docs/item-context.md` | The `itemContext` container prop (serial / NFC authenticity context) |
99
98
  | **Native Facade** | `docs/native-facade.md` | `host.native` / `SL.native` device-capability facade |
@@ -359,7 +358,7 @@ The SmartLinks SDK is organised into namespaces. See `docs/API_SUMMARY.md` for t
359
358
  - `contact` — Customer contact management
360
359
  - `comms` / `broadcasts` — Notifications and campaigns
361
360
  - `asset` — File/image uploads
362
- - `realtime` — Ably real-time messaging (see `docs/realtime.md`)
361
+ - `realtime` — SmartLinks Realtime: `onChange`, `channel`, `onMine` (see `docs/realtime.md`)
363
362
 
364
363
  ---
365
364