@layers/amba-web 4.0.3 → 4.0.5
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/index.d.ts +863 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1572 -12
- package/dist/index.js.map +1 -1
- package/dist-rn/index.d.ts +863 -20
- package/dist-rn/index.js +1572 -12
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,16 @@ interface AmbaConfig {
|
|
|
19
19
|
* Defaults to `"https://api.amba.dev"`.
|
|
20
20
|
*/
|
|
21
21
|
apiUrl?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Base URL for `Amba.functions.invoke()`. Set this to call your deployed
|
|
24
|
+
* functions through a custom domain or a non-prod environment, e.g.
|
|
25
|
+
* `"https://api.example.com"` or `"https://<id>.staging.fn.amba.host"`.
|
|
26
|
+
* `invoke(name, body)` POSTs to `"<functionsBaseUrl>/<name>"`.
|
|
27
|
+
*
|
|
28
|
+
* When omitted, the SDK resolves the default host automatically on first
|
|
29
|
+
* use (one cached round-trip) — no configuration needed for production.
|
|
30
|
+
*/
|
|
31
|
+
functionsBaseUrl?: string;
|
|
22
32
|
/**
|
|
23
33
|
* If `true`, blocks all telemetry until `setConsent(granted)` is called.
|
|
24
34
|
* Required for SOC2 / GDPR strict modes.
|
|
@@ -104,6 +114,38 @@ interface OrderBy {
|
|
|
104
114
|
column: string;
|
|
105
115
|
direction: "asc" | "desc";
|
|
106
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Eager-load related rows from another collection in the same `find` call,
|
|
119
|
+
* avoiding an N+1 round-trip per base row. Single-level (MVP).
|
|
120
|
+
*
|
|
121
|
+
* belongs-to — each base row's `localKey` column points at the related row:
|
|
122
|
+
* { collection: "novels", localKey: "novel_id", as: "novel", single: true }
|
|
123
|
+
* → row.novel = the matching novels row (or null)
|
|
124
|
+
*
|
|
125
|
+
* has-many — the related collection's `foreignKey` column points back at the
|
|
126
|
+
* base row's id:
|
|
127
|
+
* { collection: "chapters", foreignKey: "novel_id", as: "chapters" }
|
|
128
|
+
* → row.chapters = the matching chapters rows (array)
|
|
129
|
+
*
|
|
130
|
+
* The included collection's own read policy + soft-delete are honored.
|
|
131
|
+
*/
|
|
132
|
+
interface IncludeClause {
|
|
133
|
+
/** Target collection to eager-load from. */
|
|
134
|
+
collection: string;
|
|
135
|
+
/** belongs-to: FK column on the base row pointing at the target. */
|
|
136
|
+
localKey?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Join column on the target. belongs-to: defaults to `id`. has-many:
|
|
139
|
+
* required — the FK column on the target pointing back at the base id.
|
|
140
|
+
*/
|
|
141
|
+
foreignKey?: string;
|
|
142
|
+
/** Result key the nested data lands under on each base row. */
|
|
143
|
+
as: string;
|
|
144
|
+
/** belongs-to only: nest a single object instead of an array. */
|
|
145
|
+
single?: boolean;
|
|
146
|
+
/** has-many only: cap related rows per base row (default 100, max 1000). */
|
|
147
|
+
limit?: number;
|
|
148
|
+
}
|
|
107
149
|
interface FindOptions {
|
|
108
150
|
filter?: Filter;
|
|
109
151
|
order?: OrderBy[];
|
|
@@ -111,12 +153,61 @@ interface FindOptions {
|
|
|
111
153
|
cursor?: string;
|
|
112
154
|
select?: string[];
|
|
113
155
|
include_deleted?: boolean;
|
|
156
|
+
/** Eager-load related rows from other collections (kills N+1). */
|
|
157
|
+
include?: IncludeClause[];
|
|
114
158
|
}
|
|
115
159
|
interface FindResponse<T> {
|
|
116
160
|
data: T[];
|
|
117
161
|
next_cursor?: string | null;
|
|
118
162
|
has_more: boolean;
|
|
119
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Options for {@link Amba.collections.upsert}.
|
|
166
|
+
*
|
|
167
|
+
* `conflictTarget` is the set of columns covered by the unique index the
|
|
168
|
+
* upsert arbitrates on (e.g. `["user_id", "kind"]`). Every column must be
|
|
169
|
+
* present in the inserted row. `onConflict: "ignore"` keeps the existing
|
|
170
|
+
* row and returns it; `"update"` merges the supplied columns into it.
|
|
171
|
+
*/
|
|
172
|
+
interface UpsertOptions {
|
|
173
|
+
onConflict: "ignore" | "update";
|
|
174
|
+
conflictTarget: string[];
|
|
175
|
+
}
|
|
176
|
+
/** Result of {@link Amba.collections.deleteWhere} — the soft-deleted row count. */
|
|
177
|
+
interface DeleteManyResult {
|
|
178
|
+
data: {
|
|
179
|
+
deleted: number;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* One operation in an atomic multi-collection transaction
|
|
184
|
+
* ({@link Amba.collections.transaction}). Mirrors the single-row methods:
|
|
185
|
+
* `insert` carries `row` (+ optional upsert controls); `update` carries `id` +
|
|
186
|
+
* `set` (+ optional `expected` compare-and-set); `delete` carries `id` (+
|
|
187
|
+
* optional `expected`). `where` is an extra guard predicate AND'd onto the
|
|
188
|
+
* owner scope.
|
|
189
|
+
*/
|
|
190
|
+
interface TransactionOp {
|
|
191
|
+
collection: string;
|
|
192
|
+
op: "insert" | "update" | "delete";
|
|
193
|
+
id?: string;
|
|
194
|
+
row?: Record<string, unknown>;
|
|
195
|
+
set?: Record<string, unknown>;
|
|
196
|
+
where?: Record<string, unknown>;
|
|
197
|
+
expected?: Record<string, unknown>;
|
|
198
|
+
onConflict?: "ignore" | "update";
|
|
199
|
+
conflictTarget?: string[];
|
|
200
|
+
}
|
|
201
|
+
/** One per-op result returned by a committed transaction. */
|
|
202
|
+
interface TransactionOpResult {
|
|
203
|
+
index: number;
|
|
204
|
+
op: "insert" | "update" | "delete";
|
|
205
|
+
collection: string;
|
|
206
|
+
id: string | null;
|
|
207
|
+
created?: boolean;
|
|
208
|
+
deleted?: boolean;
|
|
209
|
+
row?: Record<string, unknown>;
|
|
210
|
+
}
|
|
120
211
|
interface MediaAsset {
|
|
121
212
|
id: string;
|
|
122
213
|
bucket: string;
|
|
@@ -142,27 +233,120 @@ interface PushToken {
|
|
|
142
233
|
bundle_id?: string | null;
|
|
143
234
|
created_at: string;
|
|
144
235
|
}
|
|
145
|
-
|
|
236
|
+
/**
|
|
237
|
+
* Store an entitlement's purchase resolved from. `"web"` is the neutral bucket
|
|
238
|
+
* for any non-native checkout (it replaced the former `"stripe"` value).
|
|
239
|
+
*/
|
|
240
|
+
type EntitlementStore = "app_store" | "play_store" | "web";
|
|
241
|
+
/** Lifecycle phase of the subscription period backing the entitlement. */
|
|
242
|
+
type EntitlementPeriodType = "trial" | "intro" | "normal";
|
|
243
|
+
/**
|
|
244
|
+
* A server-evaluated entitlement grant, mirroring the
|
|
245
|
+
* `GET /v1/client/entitlements` response field-for-field. `store` and
|
|
246
|
+
* `period_type` are nullable, CHECK-constrained text columns, typed
|
|
247
|
+
* loosely (`… | (string & {}) | null`) so an unexpected value from a newer
|
|
248
|
+
* server never breaks decoding while still autocompleting the known set.
|
|
249
|
+
*/
|
|
146
250
|
interface UserEntitlement {
|
|
147
|
-
|
|
148
|
-
|
|
251
|
+
/** Project-defined entitlement key (e.g. `"pro"`) — what `has()` checks. */
|
|
252
|
+
entitlement_id: string;
|
|
149
253
|
is_active: boolean;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
254
|
+
product_id?: string | null;
|
|
255
|
+
store?: EntitlementStore | (string & {}) | null;
|
|
256
|
+
purchase_date?: string | null;
|
|
257
|
+
expiration_date?: string | null;
|
|
258
|
+
period_type?: EntitlementPeriodType | (string & {}) | null;
|
|
259
|
+
}
|
|
260
|
+
/** Result of `entitlements.restore()` — the active set after a server re-sync. */
|
|
261
|
+
interface RestoreResult {
|
|
262
|
+
restored_count: number;
|
|
263
|
+
entitlements: UserEntitlement[];
|
|
264
|
+
}
|
|
265
|
+
/** A product behind an offering package (provider-neutral). */
|
|
266
|
+
interface OfferingProduct {
|
|
267
|
+
product_id: string;
|
|
268
|
+
display_name?: string | null;
|
|
269
|
+
description?: string | null;
|
|
270
|
+
product_type?: string | null;
|
|
271
|
+
/** Map of neutral store id → that store's product identifier. */
|
|
272
|
+
store_product_refs: Record<string, string>;
|
|
273
|
+
grants_entitlement_id?: string | null;
|
|
274
|
+
trial_period_days?: number | null;
|
|
275
|
+
/** ISO-8601 duration display hint (e.g. "P1M", "P1Y"). */
|
|
276
|
+
duration?: string | null;
|
|
277
|
+
}
|
|
278
|
+
/** A package — one product at a position within an offering. */
|
|
279
|
+
interface OfferingPackage {
|
|
280
|
+
package_id: string;
|
|
281
|
+
position: number;
|
|
153
282
|
metadata: Record<string, unknown>;
|
|
283
|
+
product: OfferingProduct | null;
|
|
284
|
+
}
|
|
285
|
+
interface Offering {
|
|
286
|
+
offering_id: string;
|
|
287
|
+
display_name?: string | null;
|
|
288
|
+
description?: string | null;
|
|
289
|
+
/** Whether this is the default offering to show. */
|
|
290
|
+
current: boolean;
|
|
291
|
+
metadata: Record<string, unknown>;
|
|
292
|
+
packages: OfferingPackage[];
|
|
293
|
+
}
|
|
294
|
+
/** The shape `offerings()` returns. */
|
|
295
|
+
interface OfferingsResult {
|
|
296
|
+
offerings: Offering[];
|
|
297
|
+
current_offering_id: string | null;
|
|
154
298
|
}
|
|
155
299
|
interface AiMessage {
|
|
156
300
|
role: string;
|
|
157
301
|
content: unknown;
|
|
158
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* A single vendor-neutral image for vision (multimodal) prompts. Provide a
|
|
305
|
+
* remote `url` OR base64 `data` (+ optional `mime`). Amba maps it to the
|
|
306
|
+
* model's native image format — you never touch provider-specific shapes.
|
|
307
|
+
*/
|
|
308
|
+
interface AiImageInput {
|
|
309
|
+
/** Remote image URL. Use this OR `data`, not both. */
|
|
310
|
+
url?: string;
|
|
311
|
+
/** Base64-encoded image bytes (no `data:` prefix). */
|
|
312
|
+
data?: string;
|
|
313
|
+
/** MIME type for a base64 image (e.g. `"image/png"`). Defaults to image/png. */
|
|
314
|
+
mime?: string;
|
|
315
|
+
}
|
|
316
|
+
/** A vendor-neutral content block inside a message's `content` array. */
|
|
317
|
+
type AiContentBlock = {
|
|
318
|
+
type: "text";
|
|
319
|
+
text: string;
|
|
320
|
+
} | {
|
|
321
|
+
type: "image";
|
|
322
|
+
url?: string;
|
|
323
|
+
data?: string;
|
|
324
|
+
mime?: string;
|
|
325
|
+
};
|
|
159
326
|
interface AiMessageRequest {
|
|
160
327
|
prompt_slug: string;
|
|
161
328
|
variables?: Record<string, unknown>;
|
|
162
329
|
messages?: AiMessage[];
|
|
330
|
+
/**
|
|
331
|
+
* Image(s) to send to a vision-capable prompt. They attach to the last user
|
|
332
|
+
* message as vendor-neutral content blocks; the backend maps them to the
|
|
333
|
+
* model's native image format. The prompt's model must be vision-capable, or
|
|
334
|
+
* the call returns `ai_model_not_multimodal`. Omit for text-only prompts.
|
|
335
|
+
*/
|
|
336
|
+
images?: AiImageInput[];
|
|
163
337
|
max_tokens?: number;
|
|
164
338
|
temperature?: number;
|
|
165
339
|
enable_prompt_cache?: boolean;
|
|
340
|
+
/**
|
|
341
|
+
* Opt into a streamed (SSE) response from the backend. NOTE: the buffered
|
|
342
|
+
* `ai.anthropic.messages.create()` decodes a single JSON envelope, so it
|
|
343
|
+
* ignores this flag — to consume streamed tokens use the dedicated
|
|
344
|
+
* `ai.anthropic.messages.stream()` / `ai.openai.chat.completions.stream()`
|
|
345
|
+
* methods, which set `stream: true` for you and yield text deltas as they
|
|
346
|
+
* arrive plus a final usage event. The field exists so the request type
|
|
347
|
+
* matches the backend contract.
|
|
348
|
+
*/
|
|
349
|
+
stream?: boolean;
|
|
166
350
|
}
|
|
167
351
|
interface AiUsage {
|
|
168
352
|
input_tokens: number;
|
|
@@ -175,6 +359,13 @@ interface AiMessageResponse {
|
|
|
175
359
|
usage: AiUsage;
|
|
176
360
|
stop_reason?: string | null;
|
|
177
361
|
model: string;
|
|
362
|
+
/**
|
|
363
|
+
* Computed USD cost of this call (input + output + cache token rates,
|
|
364
|
+
* summed server-side). `null` when the model isn't in the cost table — the
|
|
365
|
+
* call still succeeds; the cost is just unattributed. Read it to surface
|
|
366
|
+
* per-call spend without a separate analytics round-trip.
|
|
367
|
+
*/
|
|
368
|
+
cost_usd?: number | null;
|
|
178
369
|
}
|
|
179
370
|
/**
|
|
180
371
|
* Resolved remote config returned by `config.fetch()`.
|
|
@@ -267,17 +458,23 @@ interface ChallengeProgress {
|
|
|
267
458
|
claimed_at?: string | null;
|
|
268
459
|
}
|
|
269
460
|
interface CurrencyBalance {
|
|
270
|
-
|
|
271
|
-
|
|
461
|
+
currency_code: string;
|
|
462
|
+
name: string;
|
|
463
|
+
is_premium: boolean;
|
|
272
464
|
balance: number;
|
|
273
|
-
|
|
465
|
+
lifetime_earned: number;
|
|
466
|
+
lifetime_spent: number;
|
|
274
467
|
}
|
|
275
468
|
interface CurrencyTransaction {
|
|
276
469
|
id: string;
|
|
277
|
-
|
|
278
|
-
|
|
470
|
+
app_user_id?: string;
|
|
471
|
+
currency_code: string;
|
|
472
|
+
amount: number;
|
|
279
473
|
balance_after: number;
|
|
280
|
-
|
|
474
|
+
transaction_type?: string;
|
|
475
|
+
source?: string;
|
|
476
|
+
reference_id?: string | null;
|
|
477
|
+
idempotency_key?: string | null;
|
|
281
478
|
created_at: string;
|
|
282
479
|
}
|
|
283
480
|
interface InventoryItem {
|
|
@@ -688,6 +885,8 @@ interface LeagueCohortMember {
|
|
|
688
885
|
display_name?: string | null;
|
|
689
886
|
score: number;
|
|
690
887
|
rank: number;
|
|
888
|
+
/** `true` for the requesting user's own row (server-derived; no id leak). */
|
|
889
|
+
is_me?: boolean;
|
|
691
890
|
}
|
|
692
891
|
interface LeagueMembership {
|
|
693
892
|
cohort: LeagueCohort | null;
|
|
@@ -705,6 +904,60 @@ interface MediaListResponse {
|
|
|
705
904
|
data: MediaAsset[];
|
|
706
905
|
next_cursor?: string | null;
|
|
707
906
|
}
|
|
907
|
+
/** A single asset within a media catalog, resolved to a public URL. */
|
|
908
|
+
interface MediaCatalogItem {
|
|
909
|
+
media_id: string;
|
|
910
|
+
position: number;
|
|
911
|
+
caption?: string | null;
|
|
912
|
+
metadata: Record<string, unknown>;
|
|
913
|
+
filename: string;
|
|
914
|
+
mime_type: string;
|
|
915
|
+
/** Stable, long-cacheable public URL for the asset. */
|
|
916
|
+
url: string;
|
|
917
|
+
thumbnail_url?: string | null;
|
|
918
|
+
alt_text?: string | null;
|
|
919
|
+
blurhash?: string | null;
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* A curated, slug-addressable bundle of media assets fetched in one call.
|
|
923
|
+
* Items are returned in their configured order.
|
|
924
|
+
*/
|
|
925
|
+
interface MediaCatalog {
|
|
926
|
+
slug: string;
|
|
927
|
+
name: string;
|
|
928
|
+
description?: string | null;
|
|
929
|
+
metadata: Record<string, unknown>;
|
|
930
|
+
updated_at: string;
|
|
931
|
+
items: MediaCatalogItem[];
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* One rule a candidate event would trigger, as returned by
|
|
935
|
+
* `Amba.events.explain`. `would` describes the effect that WOULD be produced
|
|
936
|
+
* if the event were tracked for real; `note` (when present) flags a per-user
|
|
937
|
+
* gate (daily limit, cooldown, balance cap) that would suppress or reduce it.
|
|
938
|
+
*/
|
|
939
|
+
interface ExplainMatchedRule {
|
|
940
|
+
rule_type: "xp" | "currency_grant" | "feed" | "streak" | "webhook";
|
|
941
|
+
rule_id: string;
|
|
942
|
+
name: string;
|
|
943
|
+
would: Record<string, unknown>;
|
|
944
|
+
note?: string;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Result of a read-only event rule dry-run (`Amba.events.explain`). Producing
|
|
948
|
+
* this commits no side effect — it is a preview of what tracking the event
|
|
949
|
+
* would do across XP, currency grants, feed items, streaks, and webhooks.
|
|
950
|
+
*/
|
|
951
|
+
interface EventExplainResult {
|
|
952
|
+
event: {
|
|
953
|
+
name: string;
|
|
954
|
+
properties: Record<string, unknown>;
|
|
955
|
+
user_id: string | null;
|
|
956
|
+
};
|
|
957
|
+
matched: ExplainMatchedRule[];
|
|
958
|
+
evaluated_surfaces: string[];
|
|
959
|
+
unmatched_reason_samples?: string[];
|
|
960
|
+
}
|
|
708
961
|
/**
|
|
709
962
|
* Options for `Amba.collections.findNearest`.
|
|
710
963
|
*
|
|
@@ -727,6 +980,46 @@ interface NearestOptions {
|
|
|
727
980
|
interface NearestResponse<T> {
|
|
728
981
|
data: T[];
|
|
729
982
|
}
|
|
983
|
+
/**
|
|
984
|
+
* When a local notification should fire. Exactly one shape:
|
|
985
|
+
*
|
|
986
|
+
* - `{ at: Date }` — fire once at an absolute time.
|
|
987
|
+
* - `{ inSeconds, repeats? }` — fire after a relative delay.
|
|
988
|
+
*
|
|
989
|
+
* Local notifications are scheduled and fired by the device itself, with
|
|
990
|
+
* no server involvement — distinct from remote push (`Amba.push.*`).
|
|
991
|
+
* Browser scheduling is partial; see `notifications.scheduleLocal`.
|
|
992
|
+
*/
|
|
993
|
+
type LocalNotificationTrigger = {
|
|
994
|
+
at: Date | string;
|
|
995
|
+
} | {
|
|
996
|
+
inSeconds: number;
|
|
997
|
+
repeats?: boolean;
|
|
998
|
+
};
|
|
999
|
+
/** Input to `Amba.notifications.scheduleLocal`. */
|
|
1000
|
+
interface ScheduleLocalNotificationInput {
|
|
1001
|
+
/** Optional stable id; omit to let the platform mint one. */
|
|
1002
|
+
id?: string;
|
|
1003
|
+
/** Notification title (required, non-empty). */
|
|
1004
|
+
title: string;
|
|
1005
|
+
/** Notification body text. */
|
|
1006
|
+
body: string;
|
|
1007
|
+
/** Arbitrary payload delivered to the app when the notification is tapped. */
|
|
1008
|
+
data?: Record<string, unknown>;
|
|
1009
|
+
/** When to fire it. */
|
|
1010
|
+
trigger: LocalNotificationTrigger;
|
|
1011
|
+
}
|
|
1012
|
+
/** Handle returned by `scheduleLocal`; `id` is accepted by `cancelLocal`. */
|
|
1013
|
+
interface LocalNotificationHandle {
|
|
1014
|
+
id: string;
|
|
1015
|
+
}
|
|
1016
|
+
/** A pending local notification, as reported by `listScheduledLocal`. */
|
|
1017
|
+
interface ScheduledLocalNotification {
|
|
1018
|
+
id: string;
|
|
1019
|
+
title: string;
|
|
1020
|
+
body: string;
|
|
1021
|
+
data?: Record<string, unknown>;
|
|
1022
|
+
}
|
|
730
1023
|
//#endregion
|
|
731
1024
|
//#region src/realtime.d.ts
|
|
732
1025
|
/**
|
|
@@ -825,6 +1118,184 @@ declare class ConversationSubscription<T = unknown> {
|
|
|
825
1118
|
constructor(ctx: RealtimeContext, conversationId: string);
|
|
826
1119
|
subscribe(cb: (change: MessageChange<T>) => void, options?: SubscribeOptions): Unsubscribe;
|
|
827
1120
|
}
|
|
1121
|
+
/** Which slice of the signed-in user's gamification state changed. */
|
|
1122
|
+
type GamificationKind = "xp" | "level" | "achievement" | "streak";
|
|
1123
|
+
/**
|
|
1124
|
+
* A live change to the signed-in user's gamification state. `kind` says which
|
|
1125
|
+
* slice moved; `data` carries the new state inline so you can update without a
|
|
1126
|
+
* re-fetch:
|
|
1127
|
+
* - `xp` — `{ total_xp, level, delta }`
|
|
1128
|
+
* - `level` — `{ level, total_xp }`
|
|
1129
|
+
* - `achievement` — `{ achievement_id, unlocked }`
|
|
1130
|
+
* - `streak` — `{ streak_id, count, status, ... }`
|
|
1131
|
+
*
|
|
1132
|
+
* If a payload was too large to deliver inline, `truncated` is `true` and `data`
|
|
1133
|
+
* is empty — re-fetch with `Amba.xp.getBalance()` / `Amba.streaks.getAll()` etc.
|
|
1134
|
+
*/
|
|
1135
|
+
interface GamificationChange<T = Record<string, unknown>> {
|
|
1136
|
+
kind: GamificationKind;
|
|
1137
|
+
data: T;
|
|
1138
|
+
truncated?: boolean;
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Builder returned by `Amba.gamification`. Call `.subscribe(cb)` to receive the
|
|
1142
|
+
* signed-in user's xp / level / achievement / streak changes live instead of
|
|
1143
|
+
* polling.
|
|
1144
|
+
*
|
|
1145
|
+
* const unsub = Amba.gamification.subscribe((change) => {
|
|
1146
|
+
* // change.kind: "xp" | "level" | "achievement" | "streak"
|
|
1147
|
+
* // change.data: the new state
|
|
1148
|
+
* });
|
|
1149
|
+
* unsub(); // stop listening
|
|
1150
|
+
*
|
|
1151
|
+
* Delivery is scoped to the signed-in user — you only ever receive your own
|
|
1152
|
+
* gamification changes, never another user's. Reconnects with the same
|
|
1153
|
+
* exponential backoff as collection subscriptions.
|
|
1154
|
+
*/
|
|
1155
|
+
declare class GamificationSubscription {
|
|
1156
|
+
private readonly ctx;
|
|
1157
|
+
constructor(ctx: RealtimeContext);
|
|
1158
|
+
subscribe(cb: (change: GamificationChange) => void, options?: SubscribeOptions): Unsubscribe;
|
|
1159
|
+
}
|
|
1160
|
+
//#endregion
|
|
1161
|
+
//#region src/ai-stream.d.ts
|
|
1162
|
+
/** A streamed token delta — append `text` to your running output buffer. */
|
|
1163
|
+
interface AiStreamDelta {
|
|
1164
|
+
type: "delta";
|
|
1165
|
+
/** The incremental text the model just produced. */
|
|
1166
|
+
text: string;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Terminal event. Emitted once when the stream completes cleanly. `usage`
|
|
1170
|
+
* carries the token accounting accumulated across the stream (zeroed fields
|
|
1171
|
+
* when the vendor didn't report a given counter); `model` / `stopReason` are
|
|
1172
|
+
* populated when the vendor surfaced them.
|
|
1173
|
+
*/
|
|
1174
|
+
interface AiStreamDone {
|
|
1175
|
+
type: "done";
|
|
1176
|
+
usage: AiUsage;
|
|
1177
|
+
model?: string;
|
|
1178
|
+
stopReason?: string | null;
|
|
1179
|
+
}
|
|
1180
|
+
/** Vendor-neutral event yielded by the streaming AI methods. */
|
|
1181
|
+
type AiStreamEvent = AiStreamDelta | AiStreamDone;
|
|
1182
|
+
/** Options accepted by the streaming AI methods. */
|
|
1183
|
+
interface AiStreamOptions {
|
|
1184
|
+
/**
|
|
1185
|
+
* Optional callback invoked for every text delta as it arrives — a
|
|
1186
|
+
* convenience over iterating, useful when you only care about appending
|
|
1187
|
+
* tokens to the UI. Fires in addition to the yielded `delta` events.
|
|
1188
|
+
*/
|
|
1189
|
+
onChunk?: (text: string) => void;
|
|
1190
|
+
}
|
|
1191
|
+
//#endregion
|
|
1192
|
+
//#region src/resilience.d.ts
|
|
1193
|
+
/**
|
|
1194
|
+
* Offline mutation queue + optimistic-update helpers — framework-agnostic
|
|
1195
|
+
* orchestration that sits ABOVE the collection / event write methods.
|
|
1196
|
+
*
|
|
1197
|
+
* Nothing here touches the SDK runtime directly: the queue is handed a
|
|
1198
|
+
* small `KvStore` (durable key/value persistence) and a `WriteExecutor`
|
|
1199
|
+
* (the function that actually performs a queued mutation against the API).
|
|
1200
|
+
* That keeps the same code identical across every JS SDK target — only the
|
|
1201
|
+
* adapters that supply storage + the executor differ per platform.
|
|
1202
|
+
*
|
|
1203
|
+
* Design:
|
|
1204
|
+
* - A write that fails because the device is offline (a transport-level
|
|
1205
|
+
* network error, or `navigator.onLine === false`) is appended to a
|
|
1206
|
+
* durable outbox instead of throwing all the way up.
|
|
1207
|
+
* - Each queued op carries a stable idempotency key. On replay the key is
|
|
1208
|
+
* forwarded to the API's collection-write idempotency support so a
|
|
1209
|
+
* mutation that actually reached the server before the connection
|
|
1210
|
+
* dropped is never applied twice.
|
|
1211
|
+
* - On reconnect (`online` event) the outbox is flushed in FIFO order;
|
|
1212
|
+
* each op is removed only after it succeeds, so a mid-flush failure
|
|
1213
|
+
* leaves the remainder intact for the next attempt.
|
|
1214
|
+
*/
|
|
1215
|
+
/**
|
|
1216
|
+
* Minimal durable key/value contract the outbox persists through. Both the
|
|
1217
|
+
* browser `localStorage` adapter and the React Native AsyncStorage adapter
|
|
1218
|
+
* satisfy this — the queue never assumes anything else.
|
|
1219
|
+
*/
|
|
1220
|
+
interface KvStore {
|
|
1221
|
+
get(key: string): Promise<string | null> | string | null;
|
|
1222
|
+
set(key: string, value: string): Promise<void> | void;
|
|
1223
|
+
delete(key: string): Promise<void> | void;
|
|
1224
|
+
}
|
|
1225
|
+
/** The kinds of mutation the outbox can durably replay. */
|
|
1226
|
+
type OutboxOpKind = "collection.insert" | "collection.update" | "collection.delete" | "track";
|
|
1227
|
+
/**
|
|
1228
|
+
* A single durably-queued mutation. `idempotencyKey` is reused verbatim on
|
|
1229
|
+
* every replay attempt so the server dedupes a COLLECTION write that landed
|
|
1230
|
+
* before the connection dropped (the events `track` API has no idempotency
|
|
1231
|
+
* channel, so `track` replays are at-least-once — a rare reconnect duplicate
|
|
1232
|
+
* is acceptable for fire-and-forget analytics). `enqueuedAt` is an ISO
|
|
1233
|
+
* timestamp for inspection.
|
|
1234
|
+
*/
|
|
1235
|
+
interface OutboxOp {
|
|
1236
|
+
/** Stable per-op id (the idempotency key for collection writes). */
|
|
1237
|
+
idempotencyKey: string;
|
|
1238
|
+
kind: OutboxOpKind;
|
|
1239
|
+
/** Target collection name (absent for `track`). */
|
|
1240
|
+
collection?: string;
|
|
1241
|
+
/** Row id for update / delete. */
|
|
1242
|
+
id?: string;
|
|
1243
|
+
/** Insert row / update set payload. */
|
|
1244
|
+
payload?: Record<string, unknown>;
|
|
1245
|
+
/** Event name for `track`. */
|
|
1246
|
+
event?: string;
|
|
1247
|
+
/** Event properties for `track`. */
|
|
1248
|
+
properties?: Record<string, unknown>;
|
|
1249
|
+
/** Whether the tracked event was telemetry-tier. */
|
|
1250
|
+
telemetry?: boolean;
|
|
1251
|
+
/**
|
|
1252
|
+
* ISO timestamp the `track` originally OCCURRED, captured at enqueue. Replayed
|
|
1253
|
+
* as the events body `timestamp` (→ `occurred_at`) so a buffered event keeps
|
|
1254
|
+
* its real time instead of being re-stamped at flush. (Attribution is by the
|
|
1255
|
+
* session user at replay time — the events route has no body-id channel.)
|
|
1256
|
+
*/
|
|
1257
|
+
occurredAt?: string;
|
|
1258
|
+
enqueuedAt: string;
|
|
1259
|
+
}
|
|
1260
|
+
/** Result of a {@link OfflineQueue.flush}. */
|
|
1261
|
+
interface FlushResult {
|
|
1262
|
+
/** Ops successfully replayed and removed from the outbox. */
|
|
1263
|
+
flushed: number;
|
|
1264
|
+
/**
|
|
1265
|
+
* Ops dropped because their replay failed deterministically (a coded server
|
|
1266
|
+
* rejection like `VALIDATION_ERROR` / `NOT_FOUND` that would fail identically
|
|
1267
|
+
* forever). Dropping them prevents one poisoned op from wedging the queue;
|
|
1268
|
+
* the drain continues past it.
|
|
1269
|
+
*/
|
|
1270
|
+
dropped: number;
|
|
1271
|
+
/** Ops still pending after the flush (a replay failed and stopped it). */
|
|
1272
|
+
remaining: number;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Apply a local change immediately, fire the real mutation, and roll the
|
|
1276
|
+
* local change back if the mutation fails. Framework-agnostic: `apply` and
|
|
1277
|
+
* `rollback` operate on whatever local view you hand them (a React state
|
|
1278
|
+
* setter, a store, an in-memory cache).
|
|
1279
|
+
*
|
|
1280
|
+
* Resolves with the mutation's result on success. On failure it invokes
|
|
1281
|
+
* `rollback` (with the value `apply` returned, so you can restore a captured
|
|
1282
|
+
* snapshot) and rethrows the original error.
|
|
1283
|
+
*
|
|
1284
|
+
* @example
|
|
1285
|
+
* await withOptimistic({
|
|
1286
|
+
* apply: () => { const prev = todos; setTodos([...todos, draft]); return prev; },
|
|
1287
|
+
* mutate: () => Amba.collections.insert("todos", draft),
|
|
1288
|
+
* rollback: (prev) => setTodos(prev),
|
|
1289
|
+
* });
|
|
1290
|
+
*/
|
|
1291
|
+
declare function withOptimistic<TApply, TResult>(spec: {
|
|
1292
|
+
/** Mutate the local view now. Return a snapshot for `rollback` to restore. */
|
|
1293
|
+
apply: () => TApply;
|
|
1294
|
+
/** The real async mutation against the API. */
|
|
1295
|
+
mutate: () => Promise<TResult>;
|
|
1296
|
+
/** Undo the local change. Receives whatever `apply` returned. */
|
|
1297
|
+
rollback: (applied: TApply) => void;
|
|
1298
|
+
}): Promise<TResult>;
|
|
828
1299
|
//#endregion
|
|
829
1300
|
//#region src/error.d.ts
|
|
830
1301
|
/**
|
|
@@ -844,14 +1315,58 @@ declare class ConversationSubscription<T = unknown> {
|
|
|
844
1315
|
* `new AmbaApiError("MY_CODE", "...")` without coordinating with this
|
|
845
1316
|
* package's TypeScript types.
|
|
846
1317
|
*/
|
|
847
|
-
type AmbaApiErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "CONFLICT" | "RATE_LIMITED" | "VALIDATION_ERROR" | "NETWORK_ERROR" | "HTTP_ERROR" | "CIRCUIT_OPEN" | "CONSENT_NOT_GRANTED" | "NOT_INITIALIZED" | "INVALID_CONFIG" | "INVALID_ARGUMENT" | "PUSH_PERMISSION_DENIED" | "PUSH_REGISTRATION_FAILED" | "NOT_SANDBOX_TIER" | "UNKNOWN_ERROR" | (string & {});
|
|
1318
|
+
type AmbaApiErrorCode = "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "CONFLICT" | "RATE_LIMITED" | "VALIDATION_ERROR" | "NETWORK_ERROR" | "HTTP_ERROR" | "CIRCUIT_OPEN" | "CONSENT_NOT_GRANTED" | "NOT_INITIALIZED" | "INVALID_CONFIG" | "INVALID_ARGUMENT" | "PUSH_PERMISSION_DENIED" | "PUSH_REGISTRATION_FAILED" | "LOCAL_NOTIFICATIONS_UNAVAILABLE" | "LOCAL_NOTIFICATIONS_PERMISSION_DENIED" | "NOT_SANDBOX_TIER" | "UNKNOWN_ERROR" | (string & {});
|
|
848
1319
|
declare class AmbaApiError extends Error {
|
|
849
1320
|
readonly code: AmbaApiErrorCode;
|
|
850
1321
|
readonly details?: unknown;
|
|
1322
|
+
/**
|
|
1323
|
+
* Server-side request / trace id (the `X-Amba-Request-Id` response
|
|
1324
|
+
* header, falling back to the `request_id` field in the standard error
|
|
1325
|
+
* envelope). Present on errors thrown by `Amba.functions.invoke()` so a
|
|
1326
|
+
* failed run can be correlated with server logs
|
|
1327
|
+
* (`functions logs --request-id <traceId>`). `undefined` when the failure
|
|
1328
|
+
* happened before a response was received (e.g. a transport error).
|
|
1329
|
+
*/
|
|
1330
|
+
traceId?: string;
|
|
851
1331
|
constructor(code: AmbaApiErrorCode, message: string, details?: unknown);
|
|
852
1332
|
}
|
|
853
1333
|
//#endregion
|
|
1334
|
+
//#region src/local-notifications.d.ts
|
|
1335
|
+
/**
|
|
1336
|
+
* The web `notifications` namespace. Web capability is partial — see the
|
|
1337
|
+
* module-level doc. The returned handle includes `scheduledVia` so apps
|
|
1338
|
+
* can detect whether the notification was handed to the OS
|
|
1339
|
+
* (`"os-trigger"`) or relies on an in-page timer (`"timer"`).
|
|
1340
|
+
*/
|
|
1341
|
+
declare const notifications: {
|
|
1342
|
+
scheduleLocal(input: ScheduleLocalNotificationInput): Promise<LocalNotificationHandle & {
|
|
1343
|
+
scheduledVia: "os-trigger" | "timer";
|
|
1344
|
+
}>;
|
|
1345
|
+
cancelLocal(id: string): Promise<void>;
|
|
1346
|
+
listScheduledLocal(): Promise<ScheduledLocalNotification[]>;
|
|
1347
|
+
};
|
|
1348
|
+
type LocalNotificationsNamespace = typeof notifications;
|
|
1349
|
+
//#endregion
|
|
854
1350
|
//#region src/index.d.ts
|
|
1351
|
+
/** Options for `Amba.functions.invoke`. */
|
|
1352
|
+
interface InvokeOptions {
|
|
1353
|
+
/** HTTP method. Defaults to `"POST"`. */
|
|
1354
|
+
method?: "POST" | "GET" | "PUT" | "PATCH" | "DELETE";
|
|
1355
|
+
/** Extra headers merged on top of the injected auth headers. */
|
|
1356
|
+
headers?: Record<string, string>;
|
|
1357
|
+
/**
|
|
1358
|
+
* Called with the server-side request / trace id (the
|
|
1359
|
+
* `X-Amba-Request-Id` response header) as soon as a response is
|
|
1360
|
+
* received — on both success and failure. Use it to correlate a run with
|
|
1361
|
+
* server logs (`functions logs --request-id <traceId>`). `null` when the
|
|
1362
|
+
* server returned no trace id (e.g. a pre-auth rejection that doesn't
|
|
1363
|
+
* stamp the header).
|
|
1364
|
+
*
|
|
1365
|
+
* The same id is also attached to any thrown `AmbaApiError` as
|
|
1366
|
+
* `error.traceId`, so error-path correlation works without a callback.
|
|
1367
|
+
*/
|
|
1368
|
+
onTraceId?: (traceId: string | null) => void;
|
|
1369
|
+
}
|
|
855
1370
|
/**
|
|
856
1371
|
* Top-level SDK namespace.
|
|
857
1372
|
*
|
|
@@ -900,6 +1415,23 @@ declare const Amba: {
|
|
|
900
1415
|
track: (event: string, properties?: Record<string, unknown>, options?: {
|
|
901
1416
|
telemetry?: boolean;
|
|
902
1417
|
}) => Promise<void>;
|
|
1418
|
+
/**
|
|
1419
|
+
* Dry-run an event against the rule engine WITHOUT firing it. Returns
|
|
1420
|
+
* which rules would match and what each WOULD produce — XP awards,
|
|
1421
|
+
* currency grants, feed items, streak qualification, and webhook
|
|
1422
|
+
* deliveries — so you can predict the consequences of a `track` call
|
|
1423
|
+
* before committing any side effect. Nothing is written.
|
|
1424
|
+
*
|
|
1425
|
+
* Pass `{ userId }` to also preview per-user gating (daily limits,
|
|
1426
|
+
* cooldowns, balance caps); omit it for the user-independent base match.
|
|
1427
|
+
*
|
|
1428
|
+
* @example
|
|
1429
|
+
* const plan = await Amba.events.explain('lesson_completed', { score: 90 });
|
|
1430
|
+
* // plan.matched → [{ rule_type: 'xp', would: { xp_delta: 25 }, ... }, ...]
|
|
1431
|
+
*/
|
|
1432
|
+
explain: (event: string, properties?: Record<string, unknown>, options?: {
|
|
1433
|
+
userId?: string | null;
|
|
1434
|
+
}) => Promise<EventExplainResult>;
|
|
903
1435
|
};
|
|
904
1436
|
/** Authentication flows. */
|
|
905
1437
|
auth: {
|
|
@@ -1009,6 +1541,32 @@ declare const Amba: {
|
|
|
1009
1541
|
* code is `EMAIL_ALREADY_LINKED`.
|
|
1010
1542
|
*/
|
|
1011
1543
|
linkEmailOtp: (email: string, code: string) => Promise<User>;
|
|
1544
|
+
/**
|
|
1545
|
+
* Upgrade an anonymous (or any current) session by attaching an
|
|
1546
|
+
* email + password credential — converting the current user in place
|
|
1547
|
+
* to an email-identified account so its data (streak, library,
|
|
1548
|
+
* progress, `anonymous_id`) is preserved rather than minting a new
|
|
1549
|
+
* user.
|
|
1550
|
+
*
|
|
1551
|
+
* Guarantees (symmetric to `linkEmailOtp`):
|
|
1552
|
+
*
|
|
1553
|
+
* - **Same `user_id`** before and after.
|
|
1554
|
+
* - **Session token unchanged.** No rotation; `onAuthStateChange`
|
|
1555
|
+
* does NOT fire.
|
|
1556
|
+
* - **Idempotent.** Re-linking the same email to the same user
|
|
1557
|
+
* succeeds.
|
|
1558
|
+
* - **Collision.** If the email is already owned by a different user,
|
|
1559
|
+
* throws an error with `code = "EMAIL_ALREADY_LINKED"` and
|
|
1560
|
+
* `details.conflicting_user_id` populated.
|
|
1561
|
+
*
|
|
1562
|
+
* After linking, the user can sign in with `signInWithEmail(email,
|
|
1563
|
+
* password)`. Requires an active session — throws `UNAUTHORIZED`
|
|
1564
|
+
* otherwise.
|
|
1565
|
+
*
|
|
1566
|
+
* @returns the updated user record (with `email` set and
|
|
1567
|
+
* `email_verified = true`).
|
|
1568
|
+
*/
|
|
1569
|
+
linkEmailPassword: (email: string, password: string) => Promise<User>;
|
|
1012
1570
|
/**
|
|
1013
1571
|
* Detach the SMS-OTP identifier from the current session's user.
|
|
1014
1572
|
* Refused with `LAST_IDENTIFIER` if this would leave the account
|
|
@@ -1121,6 +1679,54 @@ declare const Amba: {
|
|
|
1121
1679
|
deleted: boolean;
|
|
1122
1680
|
};
|
|
1123
1681
|
}>;
|
|
1682
|
+
/**
|
|
1683
|
+
* Insert a row, resolving a unique-index conflict instead of failing.
|
|
1684
|
+
*
|
|
1685
|
+
* With `options.onConflict: "ignore"` a conflicting row is left
|
|
1686
|
+
* untouched and returned; with `"update"` the supplied columns are
|
|
1687
|
+
* merged into the existing row. `options.conflictTarget` names the
|
|
1688
|
+
* unique-index columns to arbitrate on (e.g. `["user_id", "kind"]`) and
|
|
1689
|
+
* every one must be present in `row`. Auto-RLS still applies — the
|
|
1690
|
+
* ignore-fallback / merge is scoped to the caller's own rows.
|
|
1691
|
+
*
|
|
1692
|
+
* @example
|
|
1693
|
+
* await Amba.collections.upsert("prefs",
|
|
1694
|
+
* { kind: "theme", value: "dark" },
|
|
1695
|
+
* { onConflict: "update", conflictTarget: ["kind"] });
|
|
1696
|
+
*/
|
|
1697
|
+
upsert: <T = unknown>(name: string, row: Record<string, unknown>, options: UpsertOptions) => Promise<T>;
|
|
1698
|
+
/**
|
|
1699
|
+
* Bulk soft-delete every row matching `filter`. Returns the count of
|
|
1700
|
+
* rows deleted. Auto-RLS scopes the delete to the caller's own rows;
|
|
1701
|
+
* soft-deleted rows can be brought back with {@link restore}.
|
|
1702
|
+
*
|
|
1703
|
+
* @example
|
|
1704
|
+
* const { data } = await Amba.collections.deleteWhere(
|
|
1705
|
+
* "todos", Amba.collections.where.eq("status", "done"));
|
|
1706
|
+
* console.log(`${data.deleted} removed`);
|
|
1707
|
+
*/
|
|
1708
|
+
deleteWhere: (name: string, filter: Filter) => Promise<DeleteManyResult>;
|
|
1709
|
+
/**
|
|
1710
|
+
* Restore a previously soft-deleted row by id (clears `deleted_at`).
|
|
1711
|
+
* Returns the restored row. Only rows currently soft-deleted and owned
|
|
1712
|
+
* by the caller can be restored; anything else resolves as not-found.
|
|
1713
|
+
*/
|
|
1714
|
+
restore: <T = unknown>(name: string, id: string) => Promise<T>;
|
|
1715
|
+
/**
|
|
1716
|
+
* Run an ordered list of writes (insert / update / delete, across any
|
|
1717
|
+
* collections) as ONE atomic transaction. The whole batch commits, or — if
|
|
1718
|
+
* any op fails — rolls back entirely; a partial multi-write can never
|
|
1719
|
+
* persist. Resolves to the per-op results; throws naming the failing op
|
|
1720
|
+
* index (`details.opIndex`) on rollback. Each op honors the same auto-RLS /
|
|
1721
|
+
* owner-scoping / compare-and-set rules as the single-row methods.
|
|
1722
|
+
*
|
|
1723
|
+
* @example
|
|
1724
|
+
* await Amba.collections.transaction([
|
|
1725
|
+
* { collection: "carts", op: "insert", row: { sku: "widget", qty: 2 } },
|
|
1726
|
+
* { collection: "inventory", op: "update", id: invId, set: { reserved: 2 } },
|
|
1727
|
+
* ]);
|
|
1728
|
+
*/
|
|
1729
|
+
transaction: (operations: TransactionOp[]) => Promise<TransactionOpResult[]>;
|
|
1124
1730
|
/**
|
|
1125
1731
|
* Vector-search the collection (SDK 4.0). Returns the `k` nearest
|
|
1126
1732
|
* neighbors of `options.query_vector` against the column named
|
|
@@ -1140,6 +1746,45 @@ declare const Amba: {
|
|
|
1140
1746
|
* a bare number on the JS side.
|
|
1141
1747
|
*/
|
|
1142
1748
|
count: (name: string, filter?: Filter) => Promise<number>;
|
|
1749
|
+
/**
|
|
1750
|
+
* Optimistic insert — update a local view immediately, fire the real
|
|
1751
|
+
* insert, and roll the local view back if it fails. The reconcile is your
|
|
1752
|
+
* own (replace the temporary local row with the server's authoritative
|
|
1753
|
+
* row in your `apply`/`rollback` handlers). Thin convenience over the
|
|
1754
|
+
* exported {@link withOptimistic} so the common single-write case reads
|
|
1755
|
+
* clean; for multi-step flows use `withOptimistic` directly.
|
|
1756
|
+
*
|
|
1757
|
+
* Optimistic writes always hit the network directly — they are NOT
|
|
1758
|
+
* diverted to the offline outbox even when `Amba.offline` is enabled.
|
|
1759
|
+
* Optimistic UI needs an unambiguous outcome: this resolves only on a
|
|
1760
|
+
* confirmed server write, and rejects (running your `rollback`) on any
|
|
1761
|
+
* failure including being offline. To buffer-and-replay instead, use the
|
|
1762
|
+
* plain `insert`/`update`/`delete` with the outbox on.
|
|
1763
|
+
*
|
|
1764
|
+
* @example
|
|
1765
|
+
* await Amba.collections.optimisticInsert("todos", draft, {
|
|
1766
|
+
* apply: () => { const prev = todos; setTodos([...todos, draft]); return prev; },
|
|
1767
|
+
* rollback: (prev) => setTodos(prev),
|
|
1768
|
+
* });
|
|
1769
|
+
*/
|
|
1770
|
+
optimisticInsert: <T = unknown, TApply = unknown>(name: string, row: Record<string, unknown>, view: {
|
|
1771
|
+
apply: () => TApply;
|
|
1772
|
+
rollback: (applied: TApply) => void;
|
|
1773
|
+
}) => Promise<T>;
|
|
1774
|
+
/** Optimistic update — see {@link optimisticInsert}. */
|
|
1775
|
+
optimisticUpdate: <T = unknown, TApply = unknown>(name: string, id: string, set: Record<string, unknown>, view: {
|
|
1776
|
+
apply: () => TApply;
|
|
1777
|
+
rollback: (applied: TApply) => void;
|
|
1778
|
+
}) => Promise<T>;
|
|
1779
|
+
/** Optimistic delete — see {@link optimisticInsert}. */
|
|
1780
|
+
optimisticDelete: <TApply = unknown>(name: string, id: string, view: {
|
|
1781
|
+
apply: () => TApply;
|
|
1782
|
+
rollback: (applied: TApply) => void;
|
|
1783
|
+
}) => Promise<{
|
|
1784
|
+
data: {
|
|
1785
|
+
deleted: boolean;
|
|
1786
|
+
};
|
|
1787
|
+
}>;
|
|
1143
1788
|
/** Filter DSL helpers — pass into `find({ filter: f })`. */
|
|
1144
1789
|
where: {
|
|
1145
1790
|
eq: (column: string, value: FilterValue) => Filter;
|
|
@@ -1169,7 +1814,7 @@ declare const Amba: {
|
|
|
1169
1814
|
retentionDays?: number;
|
|
1170
1815
|
}) => Promise<PresignData>;
|
|
1171
1816
|
/**
|
|
1172
|
-
* Complete-flow upload: presign → PUT to
|
|
1817
|
+
* Complete-flow upload: presign → PUT to object storage → commit.
|
|
1173
1818
|
* Returns the finalized MediaAsset.
|
|
1174
1819
|
*/
|
|
1175
1820
|
upload: (params: {
|
|
@@ -1187,7 +1832,7 @@ declare const Amba: {
|
|
|
1187
1832
|
list: (prefix?: string) => Promise<MediaListResponse>;
|
|
1188
1833
|
/**
|
|
1189
1834
|
* Soft-delete the asset (SDK 4.0). Accepts the asset id returned
|
|
1190
|
-
* by `presign` / `commit` / `list`. The corresponding
|
|
1835
|
+
* by `presign` / `commit` / `list`. The corresponding storage object
|
|
1191
1836
|
* is removed asynchronously on the server.
|
|
1192
1837
|
*/
|
|
1193
1838
|
delete: (assetId: string) => Promise<void>;
|
|
@@ -1196,11 +1841,23 @@ declare const Amba: {
|
|
|
1196
1841
|
* the Uint8Array returned by the engine, so consumers can
|
|
1197
1842
|
* call `.text()` / `.arrayBuffer()` / `.stream()` directly or
|
|
1198
1843
|
* pipe to a `URL.createObjectURL()` for preview. The two-step
|
|
1199
|
-
* fetch (asset metadata → CDN GET) is handled
|
|
1200
|
-
*
|
|
1844
|
+
* fetch (asset metadata → CDN GET) is handled inside the SDK
|
|
1845
|
+
* core; this method is single-call from the consumer.
|
|
1201
1846
|
*/
|
|
1202
1847
|
download: (assetId: string) => Promise<Blob>;
|
|
1203
1848
|
};
|
|
1849
|
+
/** Curated public-asset catalogs. */
|
|
1850
|
+
media: {
|
|
1851
|
+
/**
|
|
1852
|
+
* Fetch a public media catalog by slug
|
|
1853
|
+
* (`GET /v1/client/media/catalogs/:slug`). A catalog is a named,
|
|
1854
|
+
* curated bundle of assets your app loads in one call — each item
|
|
1855
|
+
* resolves to a stable, long-cacheable public URL, returned in the
|
|
1856
|
+
* order configured for the catalog. Only catalogs published as public
|
|
1857
|
+
* are readable; the call needs the client key but no signed-in user.
|
|
1858
|
+
*/
|
|
1859
|
+
catalog: (slug: string) => Promise<MediaCatalog>;
|
|
1860
|
+
};
|
|
1204
1861
|
/** Offline change replay (SDK 4.0). */
|
|
1205
1862
|
sync: {
|
|
1206
1863
|
/**
|
|
@@ -1221,6 +1878,53 @@ declare const Amba: {
|
|
|
1221
1878
|
*/
|
|
1222
1879
|
pullChanges: (since: PullChangesCursor) => Promise<PullChangesResult>;
|
|
1223
1880
|
};
|
|
1881
|
+
/**
|
|
1882
|
+
* Automatic offline mutation queue (opt-in).
|
|
1883
|
+
*
|
|
1884
|
+
* Once enabled, a collection write (`insert` / `update` / `delete`) or a
|
|
1885
|
+
* `track` that fails because the device is offline is buffered to a durable
|
|
1886
|
+
* local outbox instead of throwing — then replayed in order the moment
|
|
1887
|
+
* connectivity returns. Replays reuse a per-op idempotency key so a write
|
|
1888
|
+
* that actually reached the server before the connection dropped is never
|
|
1889
|
+
* applied twice.
|
|
1890
|
+
*
|
|
1891
|
+
* This is distinct from `Amba.sync` (manual change replay): `offline` is
|
|
1892
|
+
* the automatic, fire-and-forget safety net for ordinary writes.
|
|
1893
|
+
*
|
|
1894
|
+
* @example
|
|
1895
|
+
* Amba.offline.enable(); // call once after configure()
|
|
1896
|
+
* await Amba.collections.insert("todos", { title: "Buy milk" }); // queues if offline
|
|
1897
|
+
* // ...reconnect...
|
|
1898
|
+
* console.log(await Amba.offline.pendingCount()); // drains automatically
|
|
1899
|
+
*/
|
|
1900
|
+
offline: {
|
|
1901
|
+
/**
|
|
1902
|
+
* Turn the outbox on and start auto-flushing on reconnect. Idempotent —
|
|
1903
|
+
* a repeat call detaches the prior `online` listener before re-attaching,
|
|
1904
|
+
* so it never stacks listeners. Immediately attempts a flush in case ops
|
|
1905
|
+
* were persisted in a prior session. Returns a disable function that
|
|
1906
|
+
* detaches the reconnect listener (queued ops are NOT dropped — call
|
|
1907
|
+
* `clear()` for that).
|
|
1908
|
+
*
|
|
1909
|
+
* The disabler is tied to THIS activation: once a later `enable()` (or a
|
|
1910
|
+
* `configure()`) supersedes it, calling it is a no-op — so a stale disabler
|
|
1911
|
+
* can never turn a freshly re-enabled outbox off.
|
|
1912
|
+
*/
|
|
1913
|
+
enable: () => (() => void);
|
|
1914
|
+
/** Whether the outbox is currently enabled. */
|
|
1915
|
+
isEnabled: () => boolean;
|
|
1916
|
+
/** Count of writes awaiting replay. */
|
|
1917
|
+
pendingCount: () => Promise<number>;
|
|
1918
|
+
/** Snapshot the pending ops (a copy — safe to inspect). */
|
|
1919
|
+
pending: () => Promise<OutboxOp[]>;
|
|
1920
|
+
/**
|
|
1921
|
+
* Force a replay attempt now (also runs automatically on reconnect).
|
|
1922
|
+
* Resolves with `{ flushed, dropped, remaining }` (dropped = ops the server rejected deterministically on replay, removed so they cannot wedge the queue).
|
|
1923
|
+
*/
|
|
1924
|
+
flush: () => Promise<FlushResult>;
|
|
1925
|
+
/** Drop every queued write without replaying. */
|
|
1926
|
+
clear: () => Promise<void>;
|
|
1927
|
+
};
|
|
1224
1928
|
/** Push notifications. */
|
|
1225
1929
|
push: {
|
|
1226
1930
|
register: (token: string, platform: PushPlatform, bundleId?: string) => Promise<PushToken>;
|
|
@@ -1228,19 +1932,142 @@ declare const Amba: {
|
|
|
1228
1932
|
getTokens: () => Promise<PushToken[]>;
|
|
1229
1933
|
subscribe: (topic: string) => Promise<void>;
|
|
1230
1934
|
unsubscribe: (topic: string) => Promise<void>;
|
|
1935
|
+
/**
|
|
1936
|
+
* Auto re-register the device's Web Push subscription when the browser
|
|
1937
|
+
* rotates it.
|
|
1938
|
+
*
|
|
1939
|
+
* The browser can silently roll a push subscription (key rollover,
|
|
1940
|
+
* permission re-grant); when it does, the service worker fires
|
|
1941
|
+
* `pushsubscriptionchange` and the old endpoint stops delivering. Call
|
|
1942
|
+
* this from your service worker (where that event fires) and the SDK
|
|
1943
|
+
* re-registers the fresh endpoint through the idempotent
|
|
1944
|
+
* {@link register} path automatically.
|
|
1945
|
+
*
|
|
1946
|
+
* No-op (returns a no-op detacher) in runtimes without service-worker /
|
|
1947
|
+
* push support, so it's safe to call unconditionally. Returns an
|
|
1948
|
+
* unsubscribe function.
|
|
1949
|
+
*
|
|
1950
|
+
* @example
|
|
1951
|
+
* // in your service worker
|
|
1952
|
+
* Amba.push.enableAutoRotation();
|
|
1953
|
+
*/
|
|
1954
|
+
enableAutoRotation: () => (() => void);
|
|
1231
1955
|
};
|
|
1232
|
-
/**
|
|
1956
|
+
/**
|
|
1957
|
+
* On-device local notifications — `scheduleLocal` / `cancelLocal` /
|
|
1958
|
+
* `listScheduledLocal`. Fire from the device without a server
|
|
1959
|
+
* round-trip (reminders, streak nudges), distinct from remote push
|
|
1960
|
+
* (`Amba.push.*`). Browser scheduling is partial: the OS-backed path
|
|
1961
|
+
* needs the experimental Notification Triggers API + an active Service
|
|
1962
|
+
* Worker (Chromium today); without it the SDK falls back to an in-page
|
|
1963
|
+
* timer and reports `scheduledVia: "timer"` so the degradation is
|
|
1964
|
+
* visible — never a silent no-op. See `./local-notifications.ts`.
|
|
1965
|
+
*/
|
|
1966
|
+
notifications: {
|
|
1967
|
+
scheduleLocal(input: ScheduleLocalNotificationInput): Promise<LocalNotificationHandle & {
|
|
1968
|
+
scheduledVia: "os-trigger" | "timer";
|
|
1969
|
+
}>;
|
|
1970
|
+
cancelLocal(id: string): Promise<void>;
|
|
1971
|
+
listScheduledLocal(): Promise<ScheduledLocalNotification[]>;
|
|
1972
|
+
};
|
|
1973
|
+
/** Subscription entitlements — feature gates resolved server-side. */
|
|
1233
1974
|
entitlements: {
|
|
1234
1975
|
list: () => Promise<UserEntitlement[]>;
|
|
1235
1976
|
has: (name: string) => Promise<boolean>;
|
|
1977
|
+
/**
|
|
1978
|
+
* Restore purchases — re-sync the user's owned entitlements from the
|
|
1979
|
+
* server and return the active set. Required for App Store review (3.1.1);
|
|
1980
|
+
* wire it to a "Restore Purchases" button. Rejects (access unchanged) if
|
|
1981
|
+
* the server can't reach the validation engine — show a retry message.
|
|
1982
|
+
*/
|
|
1983
|
+
restore: () => Promise<RestoreResult>;
|
|
1236
1984
|
};
|
|
1985
|
+
/**
|
|
1986
|
+
* Subscription offerings — the packages your paywall renders, provider-
|
|
1987
|
+
* neutral. Pass an `offeringId` to fetch one offering; omit it for all.
|
|
1988
|
+
*/
|
|
1989
|
+
offerings: (offeringId?: string) => Promise<OfferingsResult>;
|
|
1237
1990
|
/** LLM proxy. */
|
|
1238
1991
|
ai: {
|
|
1239
1992
|
anthropic: {
|
|
1240
1993
|
messages: {
|
|
1241
1994
|
create: (request: AiMessageRequest) => Promise<AiMessageResponse>;
|
|
1995
|
+
/**
|
|
1996
|
+
* Stream the response token-by-token instead of waiting for the full
|
|
1997
|
+
* buffered reply. Returns an async iterable of vendor-neutral events:
|
|
1998
|
+
* zero or more `{type:'delta', text}` as tokens arrive, then exactly
|
|
1999
|
+
* one `{type:'done', usage, model, stopReason}` when the stream ends.
|
|
2000
|
+
*
|
|
2001
|
+
* ```ts
|
|
2002
|
+
* let answer = "";
|
|
2003
|
+
* for await (const ev of Amba.ai.anthropic.messages.stream({ prompt_slug: "chat" })) {
|
|
2004
|
+
* if (ev.type === "delta") answer += ev.text;
|
|
2005
|
+
* else console.log("tokens:", ev.usage.output_tokens);
|
|
2006
|
+
* }
|
|
2007
|
+
* ```
|
|
2008
|
+
*
|
|
2009
|
+
* Pass `{ onChunk }` to also receive each delta via callback. Throws
|
|
2010
|
+
* an `AmbaApiError` on a transport failure or a non-2xx response.
|
|
2011
|
+
*/
|
|
2012
|
+
stream: (request: AiMessageRequest, options?: AiStreamOptions) => AsyncGenerator<AiStreamEvent, void, unknown>;
|
|
1242
2013
|
};
|
|
1243
2014
|
};
|
|
2015
|
+
openai: {
|
|
2016
|
+
chat: {
|
|
2017
|
+
completions: {
|
|
2018
|
+
/**
|
|
2019
|
+
* Stream an OpenAI-routed prompt token-by-token. Same event shape
|
|
2020
|
+
* as `Amba.ai.anthropic.messages.stream` — the vendor split is just
|
|
2021
|
+
* a stable wire path; the server resolves the real provider from the
|
|
2022
|
+
* prompt's registered configuration.
|
|
2023
|
+
*/
|
|
2024
|
+
stream: (request: AiMessageRequest, options?: AiStreamOptions) => AsyncGenerator<AiStreamEvent, void, unknown>;
|
|
2025
|
+
};
|
|
2026
|
+
};
|
|
2027
|
+
};
|
|
2028
|
+
};
|
|
2029
|
+
/**
|
|
2030
|
+
* Invoke a deployed function by name, with the project's client key (and
|
|
2031
|
+
* the live session token, if any) injected automatically.
|
|
2032
|
+
*
|
|
2033
|
+
* This is the authenticated way to call your functions — prefer it over
|
|
2034
|
+
* hand-rolling `fetch` against a function URL, which leaves the call
|
|
2035
|
+
* unauthenticated (a footgun when the function holds secrets).
|
|
2036
|
+
*
|
|
2037
|
+
* The return value is unchanged (the parsed body, typed `T`). To
|
|
2038
|
+
* correlate a run with server logs, read the trace id additively:
|
|
2039
|
+
* pass `options.onTraceId` to receive the `X-Amba-Request-Id` on every
|
|
2040
|
+
* response, and on failure read `error.traceId` off the thrown
|
|
2041
|
+
* `AmbaApiError`. Then `functions logs --request-id <traceId>` pulls the
|
|
2042
|
+
* matching server log.
|
|
2043
|
+
*
|
|
2044
|
+
* @example
|
|
2045
|
+
* const result = await Amba.functions.invoke<{ ok: boolean }>(
|
|
2046
|
+
* 'send_welcome_email',
|
|
2047
|
+
* { to: 'user@example.com' },
|
|
2048
|
+
* { onTraceId: (id) => console.log('trace', id) },
|
|
2049
|
+
* );
|
|
2050
|
+
*
|
|
2051
|
+
* @example
|
|
2052
|
+
* try {
|
|
2053
|
+
* await Amba.functions.invoke('charge', { amount: 100 });
|
|
2054
|
+
* } catch (err) {
|
|
2055
|
+
* if (err instanceof AmbaApiError) {
|
|
2056
|
+
* console.error(`failed (trace ${err.traceId}): ${err.message}`);
|
|
2057
|
+
* }
|
|
2058
|
+
* }
|
|
2059
|
+
*
|
|
2060
|
+
* @param name The deployed function name.
|
|
2061
|
+
* @param body JSON-serializable request body (omitted for GET).
|
|
2062
|
+
* @param options Method, extra headers, and an `onTraceId` callback.
|
|
2063
|
+
* @returns The parsed JSON response (or the raw text if not JSON).
|
|
2064
|
+
* @throws AmbaApiError on a network failure or a non-2xx response. When
|
|
2065
|
+
* the function / router returns the standard `{ error: { code, message } }`
|
|
2066
|
+
* envelope, those surface as the thrown error's `code` + `message`; the
|
|
2067
|
+
* server trace id (when present) is attached as `error.traceId`.
|
|
2068
|
+
*/
|
|
2069
|
+
functions: {
|
|
2070
|
+
invoke: <T = unknown>(name: string, body?: unknown, options?: InvokeOptions) => Promise<T>;
|
|
1244
2071
|
};
|
|
1245
2072
|
/** Remote config bundle. */
|
|
1246
2073
|
config: {
|
|
@@ -1340,6 +2167,22 @@ declare const Amba: {
|
|
|
1340
2167
|
getAll: () => Promise<Streak[]>;
|
|
1341
2168
|
qualify: (streakKey: string) => Promise<Streak>;
|
|
1342
2169
|
};
|
|
2170
|
+
/**
|
|
2171
|
+
* Live gamification updates for the signed-in user. Call `.subscribe(cb)` to
|
|
2172
|
+
* receive xp / level / achievement / streak changes the instant they happen,
|
|
2173
|
+
* instead of polling `xp.getBalance()` / `streaks.getAll()` on a timer.
|
|
2174
|
+
*
|
|
2175
|
+
* @example
|
|
2176
|
+
* const unsub = Amba.gamification.subscribe((change) => {
|
|
2177
|
+
* // change.kind: "xp" | "level" | "achievement" | "streak"
|
|
2178
|
+
* if (change.kind === "level") showLevelUp(change.data.level);
|
|
2179
|
+
* });
|
|
2180
|
+
* // later: unsub();
|
|
2181
|
+
*
|
|
2182
|
+
* You only ever receive your own gamification changes — never another user's.
|
|
2183
|
+
* Requires an authenticated session.
|
|
2184
|
+
*/
|
|
2185
|
+
readonly gamification: GamificationSubscription;
|
|
1343
2186
|
/** Activity feeds. */
|
|
1344
2187
|
feeds: {
|
|
1345
2188
|
getActivity: (feed?: string, cursor?: string) => Promise<FeedResponse>;
|
|
@@ -1559,7 +2402,7 @@ declare function getCoreWasm(): AmbaCoreWasm;
|
|
|
1559
2402
|
* `verify-sdk-version-coherence` GH action gates every publish on the
|
|
1560
2403
|
* pair agreeing (and matching the `web-v<X.Y.Z>` tag when tag-triggered).
|
|
1561
2404
|
*/
|
|
1562
|
-
declare const SDK_VERSION = "4.0.
|
|
2405
|
+
declare const SDK_VERSION = "4.0.5";
|
|
1563
2406
|
//#endregion
|
|
1564
|
-
export { Achievement, AchievementProgress, AiMessage, AiMessageRequest, AiMessageResponse, AiUsage, Amba, AmbaApiError, type AmbaApiErrorCode, AmbaConfig, AndFilter, AppSession, AuthResult, CatalogItem, Challenge, ChallengeProgress, CollectionSubscription, ConditionFilter, ConfigBundle, ConsumeRequest, ContentItem, Conversation, ConversationParticipant, ConversationSubscription, ConversationType, CreateConversationRequest, CurrencyBalance, CurrencyTransaction, DeepLink, DeepLinkCreate, DiagnosticsEnvironment,
|
|
2407
|
+
export { Achievement, AchievementProgress, AiContentBlock, AiImageInput, AiMessage, AiMessageRequest, AiMessageResponse, type AiStreamDelta, type AiStreamDone, type AiStreamEvent, type AiStreamOptions, AiUsage, Amba, AmbaApiError, type AmbaApiErrorCode, AmbaConfig, AndFilter, AppSession, AuthResult, CatalogItem, Challenge, ChallengeProgress, CollectionSubscription, ConditionFilter, ConfigBundle, ConsumeRequest, ContentItem, Conversation, ConversationParticipant, ConversationSubscription, ConversationType, CreateConversationRequest, CurrencyBalance, CurrencyTransaction, DeepLink, DeepLinkCreate, DeleteManyResult, DiagnosticsEnvironment, EntitlementPeriodType, EntitlementStore, EventExplainResult, ExplainMatchedRule, FeedItem, FeedResponse, Filter, FilterValue, FindOptions, FindResponse, FlagAssignment, type FlushResult, Friendship, FriendshipState, type GamificationChange, type GamificationKind, GamificationSubscription, Group, GroupCreate, GroupMember, GroupUpdate, IncludeClause, InventoryItem, InvokeOptions, type KvStore, Leaderboard, LeaderboardEntry, LeagueCohort, LeagueCohortMember, LeagueCohortView, LeagueMembership, LeagueTier, LinkedIdentifier, ListMessagesOptions, LocalNotificationHandle, LocalNotificationTrigger, type LocalNotificationsNamespace, MarkReadResult, MediaAsset, MediaCatalog, MediaCatalogItem, MediaListResponse, Message, type MessageChange, MessageType, NearestOptions, NearestResponse, NotFilter, Offering, OfferingPackage, OfferingProduct, OfferingsResult, OnboardingStatus, OrFilter, OrderBy, type OutboxOp, type OutboxOpKind, PingResult, PresignData, PullChangesCursor, PullChangesResult, PurchaseOption, PurchaseRequest, PurchaseResult, PushChangesResult, PushPlatform, PushToken, type RealtimeChange, ReferralClaim, ReferralCode, Report, ReportRequest, RestoreResult, Review, ReviewCreate, ReviewUpdate, Role, type RowChangeOp, SDK_VERSION, ScheduleLocalNotificationInput, ScheduledLocalNotification, SendMessageRequest, Session, SocialProvider, Store, Streak, type SubscribeOptions, SyncChange, SyncConflict, TransactionOp, TransactionOpResult, type Unsubscribe, UpsertOptions, User, UserEntitlement, XpBalance, XpTransaction, getCoreWasm, withOptimistic };
|
|
1565
2408
|
//# sourceMappingURL=index.d.ts.map
|