@ragable/sdk 0.8.0 → 0.8.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.mts CHANGED
@@ -708,7 +708,7 @@ declare class AuthBroadcastChannel {
708
708
  close(): void;
709
709
  }
710
710
 
711
- type AuthChangeEvent = "INITIAL_SESSION" | "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "USER_UPDATED";
711
+ type AuthChangeEvent = "INITIAL_SESSION" | "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "TOKEN_REFRESH_FAILED" | "USER_UPDATED";
712
712
  type AuthUserMetadata = Record<string, unknown>;
713
713
  interface DefaultAuthUser<Metadata extends AuthUserMetadata = AuthUserMetadata> {
714
714
  id: string;
@@ -783,10 +783,26 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
783
783
  private listeners;
784
784
  private broadcast;
785
785
  private visibilityHandler;
786
- private initialized;
786
+ /** Memoizes the one-shot restore so concurrent callers (constructor eager init,
787
+ * every `onAuthStateChange` subscriber, `getSession`) share a single result.
788
+ * Non-null also means "restore has started", replacing the old boolean flag. */
789
+ private initializePromise;
790
+ /** Bumped on every explicit session change (sign-in/out, refresh). The async
791
+ * restore captures this and refuses to overwrite a newer session op that
792
+ * landed while it was reading storage (e.g. a sign-out during page load). */
793
+ private sessionEpoch;
787
794
  constructor(config: RagableAuthConfig);
788
795
  private log;
796
+ /**
797
+ * Restore a persisted session (once). Memoized: every caller awaits the same
798
+ * promise, so the eager constructor init, `getSession`, and each
799
+ * `onAuthStateChange` subscriber's INITIAL_SESSION replay never race or
800
+ * double-restore. Does NOT emit `INITIAL_SESSION` globally — that event is
801
+ * delivered per-subscriber by `onAuthStateChange` (Supabase-parity), so a
802
+ * listener attached after restore still sees the existing session.
803
+ */
789
804
  initialize(): Promise<AuthSession<U> | null>;
805
+ private _initialize;
790
806
  signUp(credentials: AuthSignUpCredentials<MetadataForUser<U>>): Promise<PostgrestResult<{
791
807
  user: U;
792
808
  session: AuthSession<U>;
@@ -835,7 +851,14 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
835
851
  };
836
852
  };
837
853
  getAccessToken(): string | null;
838
- getValidAccessToken(): Promise<string | null>;
854
+ /**
855
+ * Returns an access token guaranteed fresh for at least `refreshSkewSeconds`,
856
+ * refreshing (single-flight) if needed. Pass `force: true` to bypass the skew
857
+ * check and refresh now — used by the transport's 401 handler so a token the
858
+ * server rejected (key rotation, clock skew, early revocation) self-heals on
859
+ * retry instead of failing the call.
860
+ */
861
+ getValidAccessToken(force?: boolean): Promise<string | null>;
839
862
  getCurrentSession(): AuthSession<U> | null;
840
863
  register(body: {
841
864
  email: string;
@@ -891,7 +914,17 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
891
914
  private emit;
892
915
  private scheduleRefresh;
893
916
  private clearRefreshTimer;
917
+ /**
918
+ * Refresh the session, deduplicating concurrent callers onto one in-flight
919
+ * request. Side effects (persisting the new session, or clearing it and
920
+ * emitting SIGNED_OUT / TOKEN_REFRESH_FAILED) run exactly once inside the
921
+ * shared promise, so two callers can't double-emit. Resolves to the new
922
+ * session, or `null` when the refresh failed.
923
+ */
894
924
  singleFlightRefresh(refreshToken: string): Promise<AuthSession<U> | null>;
925
+ /** Clear the session locally and emit SIGNED_OUT after a definitively-rejected
926
+ * refresh, so onAuthStateChange-driven UI redirects to login. */
927
+ private handleTerminalRefreshFailure;
895
928
  private _doRefresh;
896
929
  private setupVisibilityListener;
897
930
  }
@@ -1340,13 +1373,23 @@ type FunctionInvoker<F extends RagableFunctions = DefaultRagableFunctions> = {
1340
1373
 
1341
1374
  /** Canonical browser/server API base (`…/api`, no trailing slash). */
1342
1375
  declare function normalizeBrowserApiBase(): string;
1343
- type BrowserDataAuthMode = "user" | "publicAnon" | "admin";
1376
+ type BrowserDataAuthMode = "user" | "publicAnon" | "admin" | "auto";
1344
1377
  /**
1345
- * Resolves how database requests are authorized. If `dataAuth` is omitted and a
1346
- * static browser data key is configured (`dataStaticKey` / `getDataStaticKey`),
1347
- * defaults to **`publicAnon`** so public apps can use shared collections without
1348
- * sign-in. Use explicit **`dataAuth: "user"`** when you need JWT sessions; use
1349
- * **`"admin"`** when the static key is a data-admin key.
1378
+ * Resolves how database / storage requests are authorized.
1379
+ *
1380
+ * Default (when `dataAuth` is omitted):
1381
+ * - **`auto`** when BOTH a static data key AND user auth (an `authGroupId` or a
1382
+ * `getAccessToken` callback) are configured the generated-site case. This is
1383
+ * the Supabase model: send the signed-in user's JWT when a session exists, and
1384
+ * fall back to the public anon key for logged-out visitors. Without this, a
1385
+ * shipped anon key permanently shadows the user session, so owner/group/claim/
1386
+ * authenticated collection grants can never match a signed-in user.
1387
+ * - **`publicAnon`** when only a static key is configured (no auth group) — a
1388
+ * purely public app.
1389
+ * - **`user`** when neither — JWT-only.
1390
+ *
1391
+ * Set `dataAuth` explicitly to override: `"user"` (JWT required), `"publicAnon"`
1392
+ * (anon key only, never upgrade), or `"admin"` (the static key is a data-admin key).
1350
1393
  */
1351
1394
  declare function effectiveDataAuth(options: RagableBrowserClientOptions): BrowserDataAuthMode;
1352
1395
  interface RagableBrowserClientOptions {
@@ -1461,6 +1504,12 @@ declare class RagableBrowserAuthClient<AuthUser extends object = DefaultAuthUser
1461
1504
  getSession(): Promise<PostgrestResult<{
1462
1505
  session: AuthSession<AuthUser> | null;
1463
1506
  }>>;
1507
+ /**
1508
+ * Returns a valid (auto-refreshed) access token for the current session, or
1509
+ * `null` if signed out. The sanctioned way to obtain a token for a hand-rolled
1510
+ * `fetch` to a custom endpoint — never read tokens out of storage yourself.
1511
+ */
1512
+ getValidAccessToken(): Promise<string | null>;
1464
1513
  }
1465
1514
  interface BrowserSqlQueryParams {
1466
1515
  databaseInstanceId?: string;
@@ -1556,6 +1605,15 @@ type CollectionRowWithMeta<Row extends Record<string, unknown> = Record<string,
1556
1605
  };
1557
1606
  declare function collectionRecordToRowWithMeta<Row extends Record<string, unknown>>(record: BrowserCollectionRecord<Row>): CollectionRowWithMeta<Row>;
1558
1607
  declare function collectionRecordsToRowWithMeta<Row extends Record<string, unknown>>(records: BrowserCollectionRecord<Row>[]): CollectionRowWithMeta<Row>[];
1608
+ /**
1609
+ * Rows returned by a find: {@link CollectionRowWithMeta} when the params carry
1610
+ * a literal `return: "flat"`, envelope {@link BrowserCollectionRecord}s
1611
+ * otherwise. Keeps the default (envelope) call sites free of union-narrowing —
1612
+ * `res.data[0].data` typechecks without a cast.
1613
+ */
1614
+ type CollectionFindResult<Row extends Record<string, unknown>, Params> = Params extends {
1615
+ return: "flat";
1616
+ } ? CollectionRowWithMeta<Row>[] : BrowserCollectionRecord<Row>[];
1559
1617
  type BrowserCollectionFindParams<Row extends Record<string, unknown> = Record<string, unknown>> = {
1560
1618
  where?: WhereInput<Row>;
1561
1619
  filters?: Array<{
@@ -1586,11 +1644,11 @@ declare class BrowserCollectionApi<Row extends Record<string, unknown> = Record<
1586
1644
  * Query collection rows. Prefer this over the deprecated `find` alias.
1587
1645
  * Use `return: "flat"` to get {@link CollectionRowWithMeta} without nested `.data`.
1588
1646
  */
1589
- findMany: (whereOrParams?: WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>) => Promise<PostgrestResult<BrowserCollectionRecord<RowD<Row>>[] | CollectionRowWithMeta<RowD<Row>>[]>>;
1647
+ findMany: <Params extends WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>>(whereOrParams?: Params) => Promise<PostgrestResult<CollectionFindResult<RowD<Row>, Params>>>;
1590
1648
  /**
1591
1649
  * @deprecated Use {@link BrowserCollectionApi.findMany} — same behavior.
1592
1650
  */
1593
- find: (whereOrParams?: WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>) => Promise<PostgrestResult<BrowserCollectionRecord<RowD<Row>>[] | CollectionRowWithMeta<RowD<Row>>[]>>;
1651
+ find: <Params extends WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>>(whereOrParams?: Params) => Promise<PostgrestResult<CollectionFindResult<RowD<Row>, Params>>>;
1594
1652
  /**
1595
1653
  * At most one row, `data` is the record or `null` if none match (not an error).
1596
1654
  */
@@ -1811,10 +1869,24 @@ declare class BrowserStorageBucketClient {
1811
1869
  private readonly options;
1812
1870
  private readonly fetchImpl;
1813
1871
  private readonly bucketId;
1814
- constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, bucketId: string);
1872
+ private readonly ragableAuth;
1873
+ constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, bucketId: string, ragableAuth?: RagableAuth | null);
1815
1874
  private get authGroupId();
1816
1875
  private base;
1876
+ /**
1877
+ * Same credential resolution as the database client (see resolveDatabaseAuthBearer):
1878
+ * in the generated-site default (`auto`), a signed-in user's auto-refreshed JWT
1879
+ * is used so storage calls carry the user's identity; logged-out visitors fall
1880
+ * back to the anon key. Previously storage ignored the managed session entirely.
1881
+ */
1817
1882
  private bearerToken;
1883
+ /**
1884
+ * The storage backend has historically returned HTTP 200 with an `{ error }`
1885
+ * body on some failures; without this guard the SDK would resolve those as
1886
+ * successful uploads/deletes. Treat any 2xx whose body carries a non-empty
1887
+ * `error` as a failure.
1888
+ */
1889
+ private assertNoEmbeddedError;
1818
1890
  private req;
1819
1891
  list(params?: {
1820
1892
  prefix?: string;
@@ -1883,7 +1955,8 @@ declare class BrowserStorageBucketClient {
1883
1955
  declare class RagableBrowserStorageClient {
1884
1956
  private readonly options;
1885
1957
  private readonly fetchImpl;
1886
- constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch);
1958
+ private readonly ragableAuth;
1959
+ constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, ragableAuth?: RagableAuth | null);
1887
1960
  from(bucketId: string): BrowserStorageBucketClient;
1888
1961
  }
1889
1962
  interface MailSendParams {
@@ -2156,6 +2229,13 @@ declare class RagableBrowser<Database extends RagableDatabase = DefaultRagableDa
2156
2229
  constructor(options: RagableBrowserClientOptions);
2157
2230
  /** Delegates to `database.from()`. Kept for back-compat — prefer `database.from()`. */
2158
2231
  from: <TableName extends RagableTableNames<Database>>(table: TableName, databaseInstanceId?: string) => PostgrestTableApi<Database, TableName>;
2232
+ /**
2233
+ * Resolves once the persisted session has been restored (and refreshed if it
2234
+ * was expired). Await this before reading auth state at startup to avoid a
2235
+ * logged-out flash, e.g. `const session = await client.ready()`. Resolves
2236
+ * `null` when no auth group is configured or no session is stored.
2237
+ */
2238
+ ready(): Promise<AuthSession<AuthUser> | null>;
2159
2239
  destroy(): void;
2160
2240
  }
2161
2241
  declare function createBrowserClient<Database extends RagableDatabase = DefaultRagableDatabase, AuthUser extends object = DefaultAuthUser, Functions extends RagableFunctions = DefaultRagableFunctions>(options: RagableBrowserClientOptions): RagableBrowser<Database, AuthUser, Functions>;
package/dist/index.d.ts CHANGED
@@ -708,7 +708,7 @@ declare class AuthBroadcastChannel {
708
708
  close(): void;
709
709
  }
710
710
 
711
- type AuthChangeEvent = "INITIAL_SESSION" | "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "USER_UPDATED";
711
+ type AuthChangeEvent = "INITIAL_SESSION" | "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "TOKEN_REFRESH_FAILED" | "USER_UPDATED";
712
712
  type AuthUserMetadata = Record<string, unknown>;
713
713
  interface DefaultAuthUser<Metadata extends AuthUserMetadata = AuthUserMetadata> {
714
714
  id: string;
@@ -783,10 +783,26 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
783
783
  private listeners;
784
784
  private broadcast;
785
785
  private visibilityHandler;
786
- private initialized;
786
+ /** Memoizes the one-shot restore so concurrent callers (constructor eager init,
787
+ * every `onAuthStateChange` subscriber, `getSession`) share a single result.
788
+ * Non-null also means "restore has started", replacing the old boolean flag. */
789
+ private initializePromise;
790
+ /** Bumped on every explicit session change (sign-in/out, refresh). The async
791
+ * restore captures this and refuses to overwrite a newer session op that
792
+ * landed while it was reading storage (e.g. a sign-out during page load). */
793
+ private sessionEpoch;
787
794
  constructor(config: RagableAuthConfig);
788
795
  private log;
796
+ /**
797
+ * Restore a persisted session (once). Memoized: every caller awaits the same
798
+ * promise, so the eager constructor init, `getSession`, and each
799
+ * `onAuthStateChange` subscriber's INITIAL_SESSION replay never race or
800
+ * double-restore. Does NOT emit `INITIAL_SESSION` globally — that event is
801
+ * delivered per-subscriber by `onAuthStateChange` (Supabase-parity), so a
802
+ * listener attached after restore still sees the existing session.
803
+ */
789
804
  initialize(): Promise<AuthSession<U> | null>;
805
+ private _initialize;
790
806
  signUp(credentials: AuthSignUpCredentials<MetadataForUser<U>>): Promise<PostgrestResult<{
791
807
  user: U;
792
808
  session: AuthSession<U>;
@@ -835,7 +851,14 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
835
851
  };
836
852
  };
837
853
  getAccessToken(): string | null;
838
- getValidAccessToken(): Promise<string | null>;
854
+ /**
855
+ * Returns an access token guaranteed fresh for at least `refreshSkewSeconds`,
856
+ * refreshing (single-flight) if needed. Pass `force: true` to bypass the skew
857
+ * check and refresh now — used by the transport's 401 handler so a token the
858
+ * server rejected (key rotation, clock skew, early revocation) self-heals on
859
+ * retry instead of failing the call.
860
+ */
861
+ getValidAccessToken(force?: boolean): Promise<string | null>;
839
862
  getCurrentSession(): AuthSession<U> | null;
840
863
  register(body: {
841
864
  email: string;
@@ -891,7 +914,17 @@ declare class RagableAuth<U extends object = DefaultAuthUser> {
891
914
  private emit;
892
915
  private scheduleRefresh;
893
916
  private clearRefreshTimer;
917
+ /**
918
+ * Refresh the session, deduplicating concurrent callers onto one in-flight
919
+ * request. Side effects (persisting the new session, or clearing it and
920
+ * emitting SIGNED_OUT / TOKEN_REFRESH_FAILED) run exactly once inside the
921
+ * shared promise, so two callers can't double-emit. Resolves to the new
922
+ * session, or `null` when the refresh failed.
923
+ */
894
924
  singleFlightRefresh(refreshToken: string): Promise<AuthSession<U> | null>;
925
+ /** Clear the session locally and emit SIGNED_OUT after a definitively-rejected
926
+ * refresh, so onAuthStateChange-driven UI redirects to login. */
927
+ private handleTerminalRefreshFailure;
895
928
  private _doRefresh;
896
929
  private setupVisibilityListener;
897
930
  }
@@ -1340,13 +1373,23 @@ type FunctionInvoker<F extends RagableFunctions = DefaultRagableFunctions> = {
1340
1373
 
1341
1374
  /** Canonical browser/server API base (`…/api`, no trailing slash). */
1342
1375
  declare function normalizeBrowserApiBase(): string;
1343
- type BrowserDataAuthMode = "user" | "publicAnon" | "admin";
1376
+ type BrowserDataAuthMode = "user" | "publicAnon" | "admin" | "auto";
1344
1377
  /**
1345
- * Resolves how database requests are authorized. If `dataAuth` is omitted and a
1346
- * static browser data key is configured (`dataStaticKey` / `getDataStaticKey`),
1347
- * defaults to **`publicAnon`** so public apps can use shared collections without
1348
- * sign-in. Use explicit **`dataAuth: "user"`** when you need JWT sessions; use
1349
- * **`"admin"`** when the static key is a data-admin key.
1378
+ * Resolves how database / storage requests are authorized.
1379
+ *
1380
+ * Default (when `dataAuth` is omitted):
1381
+ * - **`auto`** when BOTH a static data key AND user auth (an `authGroupId` or a
1382
+ * `getAccessToken` callback) are configured the generated-site case. This is
1383
+ * the Supabase model: send the signed-in user's JWT when a session exists, and
1384
+ * fall back to the public anon key for logged-out visitors. Without this, a
1385
+ * shipped anon key permanently shadows the user session, so owner/group/claim/
1386
+ * authenticated collection grants can never match a signed-in user.
1387
+ * - **`publicAnon`** when only a static key is configured (no auth group) — a
1388
+ * purely public app.
1389
+ * - **`user`** when neither — JWT-only.
1390
+ *
1391
+ * Set `dataAuth` explicitly to override: `"user"` (JWT required), `"publicAnon"`
1392
+ * (anon key only, never upgrade), or `"admin"` (the static key is a data-admin key).
1350
1393
  */
1351
1394
  declare function effectiveDataAuth(options: RagableBrowserClientOptions): BrowserDataAuthMode;
1352
1395
  interface RagableBrowserClientOptions {
@@ -1461,6 +1504,12 @@ declare class RagableBrowserAuthClient<AuthUser extends object = DefaultAuthUser
1461
1504
  getSession(): Promise<PostgrestResult<{
1462
1505
  session: AuthSession<AuthUser> | null;
1463
1506
  }>>;
1507
+ /**
1508
+ * Returns a valid (auto-refreshed) access token for the current session, or
1509
+ * `null` if signed out. The sanctioned way to obtain a token for a hand-rolled
1510
+ * `fetch` to a custom endpoint — never read tokens out of storage yourself.
1511
+ */
1512
+ getValidAccessToken(): Promise<string | null>;
1464
1513
  }
1465
1514
  interface BrowserSqlQueryParams {
1466
1515
  databaseInstanceId?: string;
@@ -1556,6 +1605,15 @@ type CollectionRowWithMeta<Row extends Record<string, unknown> = Record<string,
1556
1605
  };
1557
1606
  declare function collectionRecordToRowWithMeta<Row extends Record<string, unknown>>(record: BrowserCollectionRecord<Row>): CollectionRowWithMeta<Row>;
1558
1607
  declare function collectionRecordsToRowWithMeta<Row extends Record<string, unknown>>(records: BrowserCollectionRecord<Row>[]): CollectionRowWithMeta<Row>[];
1608
+ /**
1609
+ * Rows returned by a find: {@link CollectionRowWithMeta} when the params carry
1610
+ * a literal `return: "flat"`, envelope {@link BrowserCollectionRecord}s
1611
+ * otherwise. Keeps the default (envelope) call sites free of union-narrowing —
1612
+ * `res.data[0].data` typechecks without a cast.
1613
+ */
1614
+ type CollectionFindResult<Row extends Record<string, unknown>, Params> = Params extends {
1615
+ return: "flat";
1616
+ } ? CollectionRowWithMeta<Row>[] : BrowserCollectionRecord<Row>[];
1559
1617
  type BrowserCollectionFindParams<Row extends Record<string, unknown> = Record<string, unknown>> = {
1560
1618
  where?: WhereInput<Row>;
1561
1619
  filters?: Array<{
@@ -1586,11 +1644,11 @@ declare class BrowserCollectionApi<Row extends Record<string, unknown> = Record<
1586
1644
  * Query collection rows. Prefer this over the deprecated `find` alias.
1587
1645
  * Use `return: "flat"` to get {@link CollectionRowWithMeta} without nested `.data`.
1588
1646
  */
1589
- findMany: (whereOrParams?: WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>) => Promise<PostgrestResult<BrowserCollectionRecord<RowD<Row>>[] | CollectionRowWithMeta<RowD<Row>>[]>>;
1647
+ findMany: <Params extends WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>>(whereOrParams?: Params) => Promise<PostgrestResult<CollectionFindResult<RowD<Row>, Params>>>;
1590
1648
  /**
1591
1649
  * @deprecated Use {@link BrowserCollectionApi.findMany} — same behavior.
1592
1650
  */
1593
- find: (whereOrParams?: WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>) => Promise<PostgrestResult<BrowserCollectionRecord<RowD<Row>>[] | CollectionRowWithMeta<RowD<Row>>[]>>;
1651
+ find: <Params extends WhereInput<RowD<Row>> | BrowserCollectionFindParams<RowD<Row>>>(whereOrParams?: Params) => Promise<PostgrestResult<CollectionFindResult<RowD<Row>, Params>>>;
1594
1652
  /**
1595
1653
  * At most one row, `data` is the record or `null` if none match (not an error).
1596
1654
  */
@@ -1811,10 +1869,24 @@ declare class BrowserStorageBucketClient {
1811
1869
  private readonly options;
1812
1870
  private readonly fetchImpl;
1813
1871
  private readonly bucketId;
1814
- constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, bucketId: string);
1872
+ private readonly ragableAuth;
1873
+ constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, bucketId: string, ragableAuth?: RagableAuth | null);
1815
1874
  private get authGroupId();
1816
1875
  private base;
1876
+ /**
1877
+ * Same credential resolution as the database client (see resolveDatabaseAuthBearer):
1878
+ * in the generated-site default (`auto`), a signed-in user's auto-refreshed JWT
1879
+ * is used so storage calls carry the user's identity; logged-out visitors fall
1880
+ * back to the anon key. Previously storage ignored the managed session entirely.
1881
+ */
1817
1882
  private bearerToken;
1883
+ /**
1884
+ * The storage backend has historically returned HTTP 200 with an `{ error }`
1885
+ * body on some failures; without this guard the SDK would resolve those as
1886
+ * successful uploads/deletes. Treat any 2xx whose body carries a non-empty
1887
+ * `error` as a failure.
1888
+ */
1889
+ private assertNoEmbeddedError;
1818
1890
  private req;
1819
1891
  list(params?: {
1820
1892
  prefix?: string;
@@ -1883,7 +1955,8 @@ declare class BrowserStorageBucketClient {
1883
1955
  declare class RagableBrowserStorageClient {
1884
1956
  private readonly options;
1885
1957
  private readonly fetchImpl;
1886
- constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch);
1958
+ private readonly ragableAuth;
1959
+ constructor(options: RagableBrowserClientOptions, fetchImpl: typeof fetch, ragableAuth?: RagableAuth | null);
1887
1960
  from(bucketId: string): BrowserStorageBucketClient;
1888
1961
  }
1889
1962
  interface MailSendParams {
@@ -2156,6 +2229,13 @@ declare class RagableBrowser<Database extends RagableDatabase = DefaultRagableDa
2156
2229
  constructor(options: RagableBrowserClientOptions);
2157
2230
  /** Delegates to `database.from()`. Kept for back-compat — prefer `database.from()`. */
2158
2231
  from: <TableName extends RagableTableNames<Database>>(table: TableName, databaseInstanceId?: string) => PostgrestTableApi<Database, TableName>;
2232
+ /**
2233
+ * Resolves once the persisted session has been restored (and refreshed if it
2234
+ * was expired). Await this before reading auth state at startup to avoid a
2235
+ * logged-out flash, e.g. `const session = await client.ready()`. Resolves
2236
+ * `null` when no auth group is configured or no session is stored.
2237
+ */
2238
+ ready(): Promise<AuthSession<AuthUser> | null>;
2159
2239
  destroy(): void;
2160
2240
  }
2161
2241
  declare function createBrowserClient<Database extends RagableDatabase = DefaultRagableDatabase, AuthUser extends object = DefaultAuthUser, Functions extends RagableFunctions = DefaultRagableFunctions>(options: RagableBrowserClientOptions): RagableBrowser<Database, AuthUser, Functions>;