@layers/amba-react-native 3.0.3 → 4.0.1

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 CHANGED
@@ -18,6 +18,12 @@ type PushPlatform = "apns" | "fcm" | "web";
18
18
  interface User {
19
19
  id: string;
20
20
  email?: string | null;
21
+ /** E.164-normalized phone number set by SMS-OTP verify/link flows. */
22
+ phone?: string | null;
23
+ /** `true` once email-OTP verify/link completed for this email. */
24
+ email_verified?: boolean;
25
+ /** `true` once SMS-OTP verify/link completed for this phone. */
26
+ phone_verified?: boolean;
21
27
  display_name?: string | null;
22
28
  avatar_url?: string | null;
23
29
  external_id?: string | null;
@@ -29,6 +35,17 @@ interface User {
29
35
  created_at?: string;
30
36
  updated_at?: string;
31
37
  }
38
+ /**
39
+ * A single identifier attached to the current user. Returned by
40
+ * `Amba.auth.getCurrentIdentifiers()`. `identifier_masked` is server-masked
41
+ * (phone last-4, `a***@domain` for email); raw values stay server-side.
42
+ * Social providers (`apple`, `google`) have `null` masked value.
43
+ */
44
+ interface LinkedIdentifier {
45
+ provider: "sms_otp" | "email_otp" | "apple" | "google";
46
+ verified: boolean;
47
+ identifier_masked: string | null;
48
+ }
32
49
  interface AuthResult {
33
50
  session_token: string;
34
51
  refresh_token: string;
@@ -156,6 +173,15 @@ interface FlagAssignment {
156
173
  variant?: string | null;
157
174
  payload?: unknown;
158
175
  }
176
+ type DiagnosticsEnvironment = "production" | "staging" | "sandbox";
177
+ interface PingResult {
178
+ ok: boolean;
179
+ server_project_id: string | null;
180
+ environment: DiagnosticsEnvironment | null;
181
+ key_fingerprint: string;
182
+ latency_ms: number;
183
+ error: string | null;
184
+ }
159
185
  interface Achievement {
160
186
  id: string;
161
187
  key: string;
@@ -522,6 +548,138 @@ interface OnboardingStatus {
522
548
  completed: boolean;
523
549
  completed_at?: string | null;
524
550
  }
551
+ /**
552
+ * Patch shape for `Amba.users.update`. Mirrors the server's writable
553
+ * user fields — see `apps/api/src/routes/client/users.ts` (the route
554
+ * allows `display_name`, `avatar_url`, `properties`, `timezone` only;
555
+ * `email` is silently ignored and intentionally not part of this type).
556
+ *
557
+ * `timezone` must be a valid IANA name (e.g. `America/New_York`) when
558
+ * set; the server rejects invalid values with `VALIDATION_ERROR`.
559
+ */
560
+ interface UserPatch {
561
+ display_name?: string | null;
562
+ avatar_url?: string | null;
563
+ properties?: Record<string, unknown>;
564
+ timezone?: string | null;
565
+ }
566
+ /**
567
+ * One row from `Amba.sessions.list` — a server-tracked customer-defined
568
+ * app session row. Mirrors the `toSdkSession` projection in
569
+ * `apps/api/src/routes/client/sessions.ts` and the Rust core's
570
+ * `AppSession` struct (`sdks/core/src/sessions.rs`).
571
+ *
572
+ * NOTE: this is NOT a device/auth session record — `/v1/client/sessions`
573
+ * surfaces analytics-style `app_sessions` rows (open/background events).
574
+ * There is no `user_agent` / `ip_address` / `current` field — the server
575
+ * doesn't populate them.
576
+ */
577
+ interface SessionRecord {
578
+ id: string;
579
+ user_id: string;
580
+ session_id?: string | null;
581
+ started_at: string;
582
+ ended_at?: string | null;
583
+ duration_secs?: number | null;
584
+ platform?: string | null;
585
+ app_version?: string | null;
586
+ device_model?: string | null;
587
+ metadata?: Record<string, unknown>;
588
+ }
589
+ /**
590
+ * One offline-replay change submitted to `Amba.sync.pushChanges`.
591
+ * Mirrors `SyncPushInput.changes[]` in `apps/api/src/routes/client/sync.ts`
592
+ * and the Rust core's `SyncChange` struct (`sdks/core/src/sync.rs`).
593
+ * Server resolves conflicts server-wins.
594
+ */
595
+ interface SyncChange {
596
+ /** Collection / table name the change targets. */
597
+ entity_type: string;
598
+ /** Server-side primary key of the row being modified. */
599
+ entity_id: string;
600
+ /** One of `"insert"`, `"update"`, `"delete"`. */
601
+ action: "insert" | "update" | "delete";
602
+ /**
603
+ * Mutation payload — depends on `action`. For inserts/updates this is
604
+ * the row body; for deletes the server tolerates empty.
605
+ */
606
+ data?: Record<string, unknown>;
607
+ /**
608
+ * Client-side ISO-8601 timestamp at which the mutation was captured.
609
+ * Used for the conflict-resolution comparison (server wins when its
610
+ * `last_synced_at` is newer).
611
+ */
612
+ client_timestamp: string;
613
+ }
614
+ /**
615
+ * Per-row conflict surfaced by the server in `pushChanges` responses.
616
+ * `resolution` is `"server_wins"` today.
617
+ */
618
+ interface SyncConflict {
619
+ entity_type: string;
620
+ entity_id: string;
621
+ resolution: "server_wins";
622
+ server_data?: Record<string, unknown>;
623
+ }
624
+ interface SyncPushResult {
625
+ applied: number;
626
+ conflicts: SyncConflict[];
627
+ /** Opaque server-issued cursor to supply to the next `pullChanges`. */
628
+ checkpoint_token: string;
629
+ }
630
+ interface SyncPullResult {
631
+ changes: SyncChange[];
632
+ /** Cursor to supply on the next pull to continue from this point. */
633
+ checkpoint_token: string;
634
+ has_more?: boolean;
635
+ }
636
+ /**
637
+ * Cursor input to `Amba.sync.pullChanges`. The server requires
638
+ * `entity_type`; `checkpoint_token` is optional on the first pull.
639
+ */
640
+ interface SyncPullSince {
641
+ entity_type: string;
642
+ checkpoint_token?: string;
643
+ }
644
+ /** League tier metadata. */
645
+ interface LeagueTier {
646
+ id: string;
647
+ name: string;
648
+ tier_order: number;
649
+ }
650
+ /** Cohort the requester currently belongs to. */
651
+ interface LeagueCohortRef {
652
+ id: string;
653
+ league_id: string;
654
+ /** ISO-8601 date (YYYY-MM-DD) — the Monday that opens the cohort. */
655
+ week_start: string;
656
+ status: string;
657
+ }
658
+ /**
659
+ * Reply from `GET /v1/client/leagues/me`. Mirrors
660
+ * `apps/api/src/routes/client/leagues.ts:GET /me`.
661
+ */
662
+ interface LeagueMembership {
663
+ cohort: LeagueCohortRef | null;
664
+ league: LeagueTier | null;
665
+ rank: number | null;
666
+ score: number;
667
+ member_count: number;
668
+ }
669
+ /**
670
+ * Reply from `GET /v1/client/leagues/me/cohort`. The cohort with every
671
+ * member's anonymised standing — `members[]` carries `display_name` /
672
+ * `score` / `rank` only (no `user_id` leak).
673
+ */
674
+ interface LeagueCohort {
675
+ cohort: LeagueCohortRef | null;
676
+ league: LeagueTier | null;
677
+ members: Array<{
678
+ display_name?: string | null;
679
+ score: number;
680
+ rank: number;
681
+ }>;
682
+ }
525
683
  //#endregion
526
684
  //#region src/error.d.ts
527
685
  /**
@@ -550,7 +708,7 @@ declare class AmbaApiError extends Error {
550
708
  //#endregion
551
709
  //#region src/index.d.ts
552
710
  /** SDK semver — burned in at build time. Bump alongside package.json. */
553
- declare const SDK_VERSION = "3.0.0";
711
+ declare const SDK_VERSION = "4.0.1";
554
712
  /**
555
713
  * Top-level SDK namespace for React Native.
556
714
  */
@@ -569,13 +727,118 @@ declare const Amba: {
569
727
  readonly projectId: string;
570
728
  setDebug: (enabled: boolean) => void;
571
729
  events: {
572
- track: (event: string, properties?: Record<string, unknown>) => Promise<void>;
730
+ /**
731
+ * Track an event.
732
+ *
733
+ * Default routes to the engagement meter (fan-out to segments,
734
+ * workflows, push). Pass `{ telemetry: true }` for high-volume,
735
+ * fire-and-forget events that DON'T need fan-out: UI button
736
+ * clicks, scroll-depth markers, game-loop telemetry. Telemetry
737
+ * events are billed at $0.10 per 1M overage vs $0.50 per 10K for
738
+ * engagement events.
739
+ *
740
+ * @example
741
+ * await Amba.events.track('purchase_completed', { amount: 9.99 });
742
+ * await Amba.events.track('scroll_depth', { px: 1024 }, { telemetry: true });
743
+ */
744
+ track: (event: string, properties?: Record<string, unknown>, options?: {
745
+ telemetry?: boolean;
746
+ }) => Promise<void>;
573
747
  };
574
748
  auth: {
575
749
  signInAnonymously: () => Promise<AuthResult>;
576
750
  signInWithEmail: (email: string, password: string) => Promise<AuthResult>;
577
751
  signUpWithEmail: (email: string, password: string) => Promise<AuthResult>;
578
- signInWithSocial: (provider: SocialProvider, idToken: string) => Promise<AuthResult>;
752
+ /**
753
+ * Sign in with an Apple ID identity token (from
754
+ * `ASAuthorization.identityToken` on iOS / `expo-apple-authentication`).
755
+ * Replaces the 3.x `signInWithSocial('apple', token)` polymorphic form.
756
+ */
757
+ signInWithApple: (identityToken: string) => Promise<AuthResult>;
758
+ /**
759
+ * Sign in with a Google ID token (from Google Sign-In SDK / Expo
760
+ * `expo-auth-session/providers/google`). Replaces the 3.x
761
+ * `signInWithSocial('google', token)` polymorphic form.
762
+ */
763
+ signInWithGoogle: (idToken: string) => Promise<AuthResult>;
764
+ /**
765
+ * Request a one-time passcode for `email`. Server emails a 6-digit
766
+ * code; the user types it in, then call
767
+ * `verifyEmailOtp(email, code)` to exchange for a session.
768
+ */
769
+ requestEmailOtp: (email: string) => Promise<void>;
770
+ /**
771
+ * Exchange `(email, code)` for a session. Returns the same shape
772
+ * as `signInWithEmail`.
773
+ */
774
+ verifyEmailOtp: (email: string, code: string) => Promise<AuthResult>;
775
+ /**
776
+ * Request a one-time passcode by SMS. `phone` must be E.164
777
+ * (starts with +, 8–15 digits). Server sends a 6-digit code;
778
+ * user types it, then call `verifySmsOtp(phone, code)` to
779
+ * exchange for a session.
780
+ */
781
+ requestSmsOtp: (phone: string) => Promise<void>;
782
+ /**
783
+ * Exchange `(phone, code)` for a session. Same shape as
784
+ * `signInWithEmail`.
785
+ */
786
+ verifySmsOtp: (phone: string, code: string) => Promise<AuthResult>;
787
+ /**
788
+ * Request a one-time magic link for `email`. The server emails a
789
+ * deep-link URL containing a single-use token; the app's deep-link
790
+ * handler extracts the token and calls `verifyMagicLink(token)` to
791
+ * exchange for a session. NEW in 4.0.
792
+ */
793
+ requestMagicLink: (email: string) => Promise<void>;
794
+ /**
795
+ * Exchange a magic-link `token` for a session. Same shape as
796
+ * `signInWithEmail`. NEW in 4.0.
797
+ */
798
+ verifyMagicLink: (token: string) => Promise<AuthResult>;
799
+ /**
800
+ * Link a social identity provider to the current (anonymous or
801
+ * identified) user. Upgrades an anonymous session to an identified
802
+ * one without minting a new app_user. NEW in 4.0.
803
+ *
804
+ * Mirrors `AmbaCore::link_account` in the engine — the SDK reads
805
+ * the active session token from local identity state and posts
806
+ * `{ provider, token, session_token }` to `/v1/client/auth/link`,
807
+ * which is the wire shape the server expects. Callers must already
808
+ * have a session (any flow) before linking; an `UNAUTHORIZED` error
809
+ * is thrown if none is present.
810
+ *
811
+ * Email linking via this endpoint is rejected server-side — use
812
+ * `signInWithEmail` / `signUpWithEmail` instead.
813
+ *
814
+ * @param provider — `"apple" | "google"`
815
+ * @param credential — provider identity token (Apple `identityToken`,
816
+ * Google `id_token`).
817
+ */
818
+ linkAccount: (provider: string, credential: string) => Promise<AuthResult>;
819
+ /**
820
+ * Attach a verified phone to the current session's user without
821
+ * minting new tokens. Same `user_id`, same session token. Server
822
+ * returns `PHONE_ALREADY_LINKED` (409) with
823
+ * `details.conflicting_user_id` if the phone is owned by another
824
+ * user — the SDK rethrows as `AmbaApiError`.
825
+ */
826
+ linkSmsOtp: (phone: string, code: string) => Promise<User>;
827
+ /** Symmetric counterpart to `linkSmsOtp` for email. */
828
+ linkEmailOtp: (email: string, code: string) => Promise<User>;
829
+ /**
830
+ * Detach the SMS-OTP identifier from the current session's user.
831
+ * Refused with `LAST_IDENTIFIER` if it would orphan the account.
832
+ */
833
+ unlinkSmsOtp: () => Promise<User>;
834
+ unlinkEmailOtp: () => Promise<User>;
835
+ unlinkApple: () => Promise<User>;
836
+ unlinkGoogle: () => Promise<User>;
837
+ /**
838
+ * Snapshot of identifier providers attached to the current user.
839
+ * Values come back **masked** (phone last-4, `a***@domain`).
840
+ */
841
+ getCurrentIdentifiers: () => Promise<LinkedIdentifier[]>;
579
842
  signOut: (rotateAnonymousId?: boolean) => Promise<void>;
580
843
  refresh: () => Promise<AuthResult>;
581
844
  me: () => Promise<User>;
@@ -583,9 +846,105 @@ declare const Amba: {
583
846
  getAnonymousId: () => Promise<string>;
584
847
  onAuthStateChange: (cb: (session: Session | null) => void) => (() => void);
585
848
  };
849
+ /**
850
+ * Profile read/update for the current user. NEW in 4.0.
851
+ *
852
+ * `get()` — fetches the current user's full record. Short-circuits to
853
+ * `/auth/me` so the server doesn't have to look up the caller twice.
854
+ *
855
+ * Both `users.get(userId)` and `users.update(userId, patch)` are
856
+ * SDK 4.0 surfaces — `userId` omitted = current user, `userId` set
857
+ * = the other user (server route `/v1/client/users/{id}`). The
858
+ * server returns a public-safe profile shape for non-self reads;
859
+ * cross-user writes require the caller to hold `users:write` in
860
+ * their role permissions (403 otherwise).
861
+ */
862
+ users: {
863
+ get: (userId?: string) => Promise<User>;
864
+ /**
865
+ * Update a profile. Two overloads:
866
+ * - `update(patch)` — update the current user (PATCH /users/me).
867
+ * - `update(userId, patch)` — admin-style cross-user update
868
+ * (PATCH /users/{id}); requires `users:write` role permission
869
+ * server-side, else 403.
870
+ */
871
+ update: {
872
+ (patch: UserPatch): Promise<User>;
873
+ (userId: string, patch: UserPatch): Promise<User>;
874
+ };
875
+ };
876
+ /**
877
+ * Server-tracked customer-defined app sessions for the current user.
878
+ * NEW in 4.0. These are the analytics `app_sessions` rows
879
+ * (open/background events), not auth device sessions.
880
+ *
881
+ * - `list()` → `GET /v1/client/sessions` returns `AppSession[]` newest
882
+ * first (capped at 100 by the server).
883
+ * - `revoke(sessionId)` → `POST /v1/client/sessions/:id/end` ends the
884
+ * given session row (idempotent — a second `revoke` on an already-
885
+ * ended session is a no-op). `sessionId` is the row id (UUID)
886
+ * returned by `list()` (the `id` field, not `session_id`). Server
887
+ * has no DELETE on `/sessions/:id` — `end` is the canonical revoke.
888
+ */
889
+ sessions: {
890
+ list: () => Promise<SessionRecord[]>;
891
+ revoke: (sessionId: string) => Promise<void>;
892
+ };
893
+ /**
894
+ * Offline change replay. NEW in 4.0. Wraps `/v1/client/sync` per
895
+ * `apps/api/src/routes/client/sync.ts` and the engine's
896
+ * `SyncModule` (`sdks/core/src/sync.rs`).
897
+ *
898
+ * - `pushChanges(changes)` → `POST /v1/client/sync` with `{ changes }`.
899
+ * Server returns `{ applied, conflicts, checkpoint_token }`.
900
+ * Conflicts are server-wins; callers should re-apply
901
+ * `server_data` from each `SyncConflict` to their local cache
902
+ * before issuing follow-up writes.
903
+ * - `pullChanges({ entity_type, checkpoint_token? })` →
904
+ * `GET /v1/client/sync?entity_type=…&checkpoint_token=…`. Server
905
+ * requires `entity_type`; `checkpoint_token` is optional on the
906
+ * first pull. Returns `{ changes, checkpoint_token, has_more }`.
907
+ *
908
+ * NOTE: The wire is a single `/sync` endpoint with method = action.
909
+ * Earlier 4.0 drafts referenced `/sync/push` and `/sync/pull` — those
910
+ * routes do not exist on the server.
911
+ */
912
+ sync: {
913
+ pushChanges: (changes: SyncChange[]) => Promise<SyncPushResult>;
914
+ pullChanges: (since: {
915
+ entity_type: string;
916
+ checkpoint_token?: string;
917
+ }) => Promise<SyncPullResult>;
918
+ };
586
919
  collections: {
587
920
  find: <T = unknown>(name: string, options?: FindOptions) => Promise<FindResponse<T>>;
588
921
  findOne: <T = unknown>(name: string, id: string) => Promise<T>;
922
+ /**
923
+ * Vector similarity search. Returns the top `k` rows closest to the
924
+ * supplied `vector` by cosine distance (default), optionally
925
+ * further filtered by `where`. NEW in 4.0 — wires to the
926
+ * pgvector-backed `POST /v1/client/collections/:name/find-nearest`
927
+ * route.
928
+ *
929
+ * Wire body matches `NearestRequestBody` in
930
+ * `apps/api/src/routes/client/collections.ts`: `to_vector` (or
931
+ * `to_text` for server-side embedding) + optional `k`, `column`,
932
+ * `distance`, `where`, `includeDeleted`.
933
+ */
934
+ findNearest: <T = unknown>(name: string, vector: number[], k: number, where?: Filter) => Promise<T[]>;
935
+ /**
936
+ * Count rows in a collection, optionally filtered. NEW in 4.0 —
937
+ * wires to `GET /v1/client/collections/:name/count` with an
938
+ * optional `?query={"where":...}` body channel (GET requests
939
+ * can't carry a JSON body, so the server reads the JSON from the
940
+ * `query` param).
941
+ *
942
+ * The server's `/count` route only honors `where` + `includeDeleted`
943
+ * — passing other knobs (`limit`, `cursor`, etc.) returns
944
+ * `INVALID_QUERY_PARAM`. Mirrors the engine's `CollectionsModule::count`
945
+ * (`sdks/core/src/collections.rs`).
946
+ */
947
+ count: (name: string, where?: Filter) => Promise<number>;
589
948
  insert: <T = unknown>(name: string, row: Record<string, unknown>) => Promise<T>;
590
949
  update: <T = unknown>(name: string, id: string, set: Record<string, unknown>) => Promise<T>;
591
950
  delete: (name: string, id: string) => Promise<{
@@ -620,6 +979,45 @@ declare const Amba: {
620
979
  retentionDays?: number;
621
980
  }) => Promise<PresignData>;
622
981
  commit: (uploadId: string, assetId: string) => Promise<MediaAsset>;
982
+ /**
983
+ * List media assets, optionally filtered by a key prefix. NEW in 4.0.
984
+ *
985
+ * Returns the full `{ data, next_cursor }` envelope so paginated
986
+ * listings expose the cursor — aligns with the web SDK shape
987
+ * (`MediaListResponse`) and the engine `ListResponse`.
988
+ */
989
+ list: (prefix?: string) => Promise<{
990
+ data: MediaAsset[];
991
+ next_cursor?: string | null;
992
+ }>;
993
+ /**
994
+ * Soft-delete a media asset by its asset id (the UUID returned
995
+ * from `upload()` / `list()` / `get()`). NEW in 4.0.
996
+ *
997
+ * Wires to `DELETE /v1/client/media/:assetId` per
998
+ * `apps/api/src/routes/client/media.ts:374`. The server scopes
999
+ * deletes by `uploaded_by = current user`. Returns 404 if the
1000
+ * asset doesn't exist or isn't owned by the caller.
1001
+ *
1002
+ * NOTE: takes the asset id (UUID), not the storage key — the
1003
+ * server has no `?key=` query channel. Use `Amba.storage.list()`
1004
+ * to get the id from a `MediaAsset` row.
1005
+ */
1006
+ delete: (assetId: string) => Promise<void>;
1007
+ /**
1008
+ * Download a media asset's bytes by its asset id. Two-step:
1009
+ * resolve the `MediaAsset` metadata (which carries the CDN URL),
1010
+ * then fetch the CDN URL directly with no API headers.
1011
+ *
1012
+ * Returns a `Blob` — RN's fetch surfaces blobs natively
1013
+ * (`response.blob()`). NEW in 4.0.
1014
+ *
1015
+ * Mirrors the engine's `StorageModule::download` in
1016
+ * `sdks/core/src/storage.rs:247` — there is no
1017
+ * `/v1/client/media/download` route on the server; the CDN URL
1018
+ * on the asset row is the canonical fetch target.
1019
+ */
1020
+ download: (assetId: string) => Promise<Blob>;
623
1021
  };
624
1022
  push: {
625
1023
  register: (token: string, platform: PushPlatform, bundleId?: string) => Promise<PushToken>;
@@ -644,6 +1042,29 @@ declare const Amba: {
644
1042
  };
645
1043
  flags: {
646
1044
  fetch: () => Promise<FlagAssignment[]>;
1045
+ /**
1046
+ * Get a single flag assignment by name. NEW in 4.0. Wraps
1047
+ * `GET /v1/client/flags/{key}` — returns `null` when the flag is
1048
+ * unknown or disabled for this user (the server treats both as
1049
+ * 404 by design; the SDK normalizes to `null`). Other errors
1050
+ * (auth, rate-limit, network) still throw.
1051
+ */
1052
+ get: (key: string) => Promise<FlagAssignment | null>;
1053
+ };
1054
+ /**
1055
+ * Wire-verify primitive. Call once after `configure()` to confirm
1056
+ * the SDK is talking to the right project with the right key in
1057
+ * the right environment. See `@layers/amba-web::Amba.diagnostics.ping`
1058
+ * for the canonical usage example — the response shape is identical
1059
+ * across every Amba SDK.
1060
+ *
1061
+ * The ping response is NOT wrapped in the usual `{data: ...}`
1062
+ * envelope — the route returns the `PingResult` shape directly so
1063
+ * an operator running `curl … | jq` sees the structured fields
1064
+ * without an extra unwrap.
1065
+ */
1066
+ diagnostics: {
1067
+ ping: () => Promise<PingResult>;
647
1068
  };
648
1069
  achievements: {
649
1070
  getAll: () => Promise<Achievement[]>;
@@ -670,6 +1091,17 @@ declare const Amba: {
670
1091
  getEntries: (key: string, limit?: number) => Promise<LeaderboardEntry[]>;
671
1092
  getMyRank: (key: string) => Promise<LeaderboardEntry>;
672
1093
  };
1094
+ /**
1095
+ * Tiered weekly cohorts (Duolingo-style leagues). NEW in 4.0.
1096
+ *
1097
+ * `me()` returns the caller's current cohort/tier/score snapshot.
1098
+ * `cohort()` returns the full peer list competing in the same tier
1099
+ * this week — for rendering a league-board UI.
1100
+ */
1101
+ leagues: {
1102
+ me: () => Promise<LeagueMembership>;
1103
+ cohort: () => Promise<LeagueCohort>;
1104
+ };
673
1105
  stores: {
674
1106
  list: () => Promise<Store[]>;
675
1107
  getPurchaseOptions: (storeKey: string) => Promise<PurchaseOption[]>;
@@ -690,9 +1122,35 @@ declare const Amba: {
690
1122
  friends: {
691
1123
  getList: () => Promise<Friendship[]>;
692
1124
  getFriends: () => Promise<Friendship[]>;
1125
+ /**
1126
+ * Send a friend request to `userId`. NEW in 4.0 — the existing
1127
+ * SDK shipped block/unblock but had no request/accept/decline
1128
+ * surface, so customers couldn't actually build a friends graph
1129
+ * without dropping to raw HTTP.
1130
+ */
1131
+ sendRequest: (userId: string) => Promise<Friendship>;
1132
+ /**
1133
+ * Accept an inbound friend request. NEW in 4.0.
1134
+ */
1135
+ acceptRequest: (friendshipId: string) => Promise<Friendship>;
1136
+ /**
1137
+ * Decline an inbound friend request. NEW in 4.0. Server endpoint
1138
+ * is `/:friendshipId/reject` (not `/decline`) — SDK keeps the
1139
+ * `declineRequest` name (intent is clear) but hits the server's
1140
+ * spelling. apps/api/src/routes/client/friends.ts:152.
1141
+ */
1142
+ declineRequest: (friendshipId: string) => Promise<void>;
693
1143
  blockUser: (userId: string) => Promise<Friendship>;
694
1144
  unblockUser: (userId: string) => Promise<void>;
695
1145
  removeBlock: (friendshipId: string) => Promise<void>;
1146
+ /**
1147
+ * `friends.removeFriend(userId)` — unfriend by the other user's id
1148
+ * without needing the friendship row id. NEW in 4.0. Wraps
1149
+ * `DELETE /v1/client/friends/by-user/{userId}`. Server preserves
1150
+ * blocked rows (use `unblockUser` to clear those); 404 → throws
1151
+ * AmbaApiError with code NOT_FOUND.
1152
+ */
1153
+ removeFriend: (userId: string) => Promise<void>;
696
1154
  };
697
1155
  groups: {
698
1156
  create: (params: GroupCreate) => Promise<Group>;
@@ -717,12 +1175,34 @@ declare const Amba: {
717
1175
  * conversations between two users.
718
1176
  */
719
1177
  createConversation: (request: CreateConversationRequest) => Promise<Conversation>;
720
- getConversations: () => Promise<Conversation[]>;
721
- /** Alias matching the `listX` naming convention used elsewhere. */
722
- listConversations: () => Promise<Conversation[]>;
1178
+ /**
1179
+ * `GET /v1/client/messaging/conversations` — list the caller's
1180
+ * conversations. Canonical 4.0 name; the legacy `getConversations`
1181
+ * is removed in 4.0 per the spec.
1182
+ */
1183
+ conversations: () => Promise<Conversation[]>;
723
1184
  sendMessage: (conversationId: string, request: SendMessageRequest) => Promise<Message>;
724
1185
  listMessages: (conversationId: string, opts?: ListMessagesOptions) => Promise<Message[]>;
725
1186
  markRead: (conversationId: string) => Promise<MarkReadResult>;
1187
+ /**
1188
+ * Fetch a single message by id within a conversation. NEW in 4.0.
1189
+ *
1190
+ * The server has no dedicated `GET /messages/:id` route — the
1191
+ * `/messages` list endpoint also doesn't honour a `?message_id=`
1192
+ * query filter (see `apps/api/src/routes/client/messaging.ts:358`,
1193
+ * which returns the full paginated page). We paginate forward
1194
+ * (newest-first, server page size 100) and find the matching id
1195
+ * client-side, mirroring the engine's strategy in
1196
+ * `sdks/core/src/messaging.rs:223`. Walks up to `MAX_PAGES`
1197
+ * (5,000 messages total) before giving up to avoid an unbounded
1198
+ * loop against a giant conversation; callers with longer histories
1199
+ * should keep a local index instead of relying on this helper as a
1200
+ * search primitive.
1201
+ *
1202
+ * Returns `null` when the message id isn't found within the cap
1203
+ * (or the conversation), matching the canonical contract.
1204
+ */
1205
+ getMessage: (conversationId: string, messageId: string) => Promise<Message | null>;
726
1206
  };
727
1207
  moderation: {
728
1208
  reportUser: (request: ReportRequest) => Promise<Report>;
@@ -746,14 +1226,24 @@ declare const Amba: {
746
1226
  };
747
1227
  catalog: {
748
1228
  list: () => Promise<CatalogItem[]>;
1229
+ /**
1230
+ * Get a single catalog item by id. NEW in 4.0 — wires to
1231
+ * `GET /v1/client/catalog/:id`.
1232
+ */
1233
+ get: (id: string) => Promise<CatalogItem>;
749
1234
  };
750
1235
  content: {
751
- getToday: (channel?: string) => Promise<ContentItem | null>;
752
- getLibrary: (channel?: string, options?: {
1236
+ /**
1237
+ * Canonical 4.0 names — `today` / `library` / `item`. The legacy
1238
+ * `getToday` / `getLibrary` / `getItem` are removed in 4.0 per
1239
+ * the spec (CANONICAL_API.md, content section).
1240
+ */
1241
+ today: (channel?: string) => Promise<ContentItem | null>;
1242
+ library: (channel?: string, options?: {
753
1243
  limit?: number;
754
1244
  cursor?: string;
755
1245
  }) => Promise<ContentItem[]>;
756
- getItem: (id: string) => Promise<ContentItem>;
1246
+ item: (id: string) => Promise<ContentItem>;
757
1247
  updateItem: (id: string, state_: unknown) => Promise<ContentItem>;
758
1248
  createItem: (channel: string, item: unknown) => Promise<ContentItem>;
759
1249
  };
@@ -788,5 +1278,5 @@ declare const Amba: {
788
1278
  };
789
1279
  };
790
1280
  //#endregion
791
- export { Achievement, AchievementProgress, AiMessage, AiMessageRequest, AiMessageResponse, AiUsage, Amba, AmbaApiError, type AmbaApiErrorCode, AmbaConfig, AndFilter, AuthResult, CatalogItem, Challenge, ChallengeProgress, ConditionFilter, ConfigBundle, ConsumeRequest, ContentItem, Conversation, ConversationType, CreateConversationRequest, CurrencyBalance, CurrencyTransaction, DeepLink, DeepLinkCreate, EntitlementSource, FeedItem, FeedResponse, Filter, FilterValue, FindOptions, FindResponse, FlagAssignment, Friendship, FriendshipState, Group, GroupCreate, GroupMember, GroupUpdate, InventoryItem, Leaderboard, LeaderboardEntry, ListMessagesOptions, MarkReadResult, MediaAsset, Message, MessageType, NotFilter, OnboardingStatus, OrFilter, OrderBy, PresignData, PurchaseOption, PurchaseRequest, PurchaseResult, PushPlatform, PushToken, ReferralClaim, ReferralCode, Report, ReportRequest, Review, ReviewCreate, ReviewUpdate, Role, SDK_VERSION, SendMessageRequest, Session, SocialProvider, Store, Streak, User, UserEntitlement, XpBalance, XpTransaction };
1281
+ export { Achievement, AchievementProgress, AiMessage, AiMessageRequest, AiMessageResponse, AiUsage, Amba, AmbaApiError, type AmbaApiErrorCode, AmbaConfig, AndFilter, AuthResult, CatalogItem, Challenge, ChallengeProgress, ConditionFilter, ConfigBundle, ConsumeRequest, ContentItem, Conversation, ConversationType, CreateConversationRequest, CurrencyBalance, CurrencyTransaction, DeepLink, DeepLinkCreate, DiagnosticsEnvironment, EntitlementSource, FeedItem, FeedResponse, Filter, FilterValue, FindOptions, FindResponse, FlagAssignment, Friendship, FriendshipState, Group, GroupCreate, GroupMember, GroupUpdate, InventoryItem, Leaderboard, LeaderboardEntry, LeagueCohort, LeagueCohortRef, LeagueMembership, LeagueTier, LinkedIdentifier, ListMessagesOptions, MarkReadResult, MediaAsset, Message, MessageType, NotFilter, OnboardingStatus, OrFilter, OrderBy, PingResult, PresignData, PurchaseOption, PurchaseRequest, PurchaseResult, PushPlatform, PushToken, ReferralClaim, ReferralCode, Report, ReportRequest, Review, ReviewCreate, ReviewUpdate, Role, SDK_VERSION, SendMessageRequest, Session, SessionRecord, SocialProvider, Store, Streak, SyncChange, SyncConflict, SyncPullResult, SyncPullSince, SyncPushResult, User, UserEntitlement, UserPatch, XpBalance, XpTransaction };
792
1282
  //# sourceMappingURL=index.d.ts.map