@spacelr/sdk 0.1.7 → 0.1.9

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
@@ -58,8 +58,10 @@ interface RegisterResponse {
58
58
  username: string;
59
59
  displayName?: string;
60
60
  };
61
- access_token: string;
62
- refresh_token: string;
61
+ /** Omitted by the server when `emailVerificationRequired` is true. */
62
+ access_token?: string;
63
+ /** Omitted by the server when `emailVerificationRequired` is true. */
64
+ refresh_token?: string;
63
65
  emailVerificationRequired?: boolean;
64
66
  }
65
67
  interface TokenResponse {
@@ -430,11 +432,58 @@ declare class RealtimeClient {
430
432
  private resubscribeAll;
431
433
  }
432
434
 
435
+ type AuthState = 'authenticated' | 'unauthenticated';
436
+ type AuthStateListener = (state: AuthState) => void | Promise<void>;
433
437
  declare class AuthModule {
434
438
  private http;
435
439
  private tokenManager;
436
440
  private config;
441
+ private stateListeners;
442
+ private unsubscribeAuthLost;
443
+ private lastEmittedState;
437
444
  constructor(http: HttpClient, tokenManager: TokenManager, config: SpacelrClientConfig);
445
+ /**
446
+ * Returns true if a non-expired access token is currently in storage.
447
+ * Does NOT make a network request — safe for route guards and other
448
+ * hot paths that run on every navigation.
449
+ *
450
+ * A token within the refresh buffer (about to expire) still counts as
451
+ * authenticated because the next protected request will auto-refresh it.
452
+ *
453
+ * Any error from the underlying TokenStorage (corrupt JSON, quota, etc.)
454
+ * is treated as "not authenticated" rather than propagated, so route
455
+ * guards can't be crashed by a misbehaving storage backend.
456
+ */
457
+ isAuthenticated(): Promise<boolean>;
458
+ /**
459
+ * Subscribe to auth-state transitions. The callback fires:
460
+ * - 'authenticated' after a successful login/register/exchange/2FA-verify
461
+ * - 'unauthenticated' after logout or when a token refresh fails
462
+ *
463
+ * Only fires for transitions that happen after the subscription. If the
464
+ * user is already logged in at subscribe time (e.g. tokens restored from
465
+ * storage on app boot), no 'authenticated' event is emitted — call
466
+ * `isAuthenticated()` once up-front for the initial state.
467
+ *
468
+ * Silent token refreshes do NOT produce an event (auth state is
469
+ * unchanged). Subscribe to `spacelrClient.onTokenRefreshed(...)` if you
470
+ * need to observe successful refreshes.
471
+ *
472
+ * Listener may return `void` or `Promise<void>`. Rejections are swallowed
473
+ * so one broken subscriber can't poison others or the auth flow. The
474
+ * dispatch is fire-and-forget: `logout()` / `login()` resolve as soon as
475
+ * the dispatch loop returns, without awaiting async listeners.
476
+ *
477
+ * Returns an unsubscribe function.
478
+ */
479
+ onAuthStateChange(listener: AuthStateListener): () => void;
480
+ /**
481
+ * Detach this AuthModule from the TokenManager. Call when discarding the
482
+ * client (tests, HMR, multi-client setups) to avoid leaking the internal
483
+ * onAuthLost subscription. Idempotent — safe to call more than once.
484
+ */
485
+ dispose(): void;
486
+ private emitState;
438
487
  login(params: LoginParams): Promise<LoginResponse>;
439
488
  register(params: RegisterParams): Promise<RegisterResponse>;
440
489
  refresh(refreshToken: string): Promise<TokenResponse>;
@@ -544,6 +593,21 @@ interface DeleteResult {
544
593
  interface FindByIdOptions {
545
594
  populate?: PopulateOption[];
546
595
  }
596
+ /**
597
+ * Options for a server-side substring search.
598
+ *
599
+ * Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
600
+ * `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
601
+ */
602
+ interface SearchOptions {
603
+ query: string;
604
+ fields: string[];
605
+ filter?: Record<string, unknown>;
606
+ sort?: Record<string, 1 | -1>;
607
+ limit?: number;
608
+ offset?: number;
609
+ select?: string[];
610
+ }
547
611
  interface SubscribeHandlers<T = Record<string, unknown>> {
548
612
  where?: Record<string, string | number | boolean>;
549
613
  onInsert?: (doc: T & {
@@ -586,6 +650,18 @@ declare class CollectionRef<T = Record<string, unknown>> {
586
650
  _id?: string;
587
651
  })[]): Promise<InsertResult>;
588
652
  find(filter?: Record<string, unknown>): QueryBuilder<T>;
653
+ /**
654
+ * Server-side substring search across the specified fields.
655
+ *
656
+ * The query is regex-escaped server-side and matched case-insensitively via
657
+ * MongoDB `$regex`. Performance note: unanchored case-insensitive regex
658
+ * cannot use a standard B-tree index — on very large collections consider
659
+ * narrowing with `filter` to scope the scan.
660
+ *
661
+ * Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
662
+ * `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
663
+ */
664
+ search(opts: SearchOptions): Promise<FindResult<T>>;
589
665
  findById(id: string, options?: FindByIdOptions): Promise<T & {
590
666
  _id: string;
591
667
  }>;
@@ -665,7 +741,14 @@ declare class NotificationsModule {
665
741
  }
666
742
 
667
743
  interface FunctionInvokeOptions {
668
- secret: string;
744
+ /** Webhook secret — used for `webhook` and `hybrid` invokeMode. */
745
+ secret?: string;
746
+ /**
747
+ * If true, the SDK attaches the currently signed-in user's bearer token
748
+ * via `Authorization` (managed by the SDK's TokenManager). Use for
749
+ * `authenticated`, `hybrid`, or `public` invokeMode.
750
+ */
751
+ authenticated?: boolean;
669
752
  payload?: Record<string, unknown>;
670
753
  }
671
754
  interface FunctionInvokeResult {
@@ -677,11 +760,15 @@ declare class FunctionsModule {
677
760
  private http;
678
761
  constructor(http: HttpClient);
679
762
  /**
680
- * Invoke a function via webhook trigger.
763
+ * Invoke a function.
681
764
  * Calls POST /api/v1/functions/:projectId/:functionId/invoke
682
- * with X-Webhook-Secret header.
765
+ *
766
+ * Provide `secret` for webhook/hybrid functions, `authenticated: true` for
767
+ * JWT-based invocation, or both for hybrid (JWT wins). Public mode needs
768
+ * neither, though `authenticated: true` still populates `event.auth` inside
769
+ * the function.
683
770
  */
684
- invoke(projectId: string, functionId: string, options: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
771
+ invoke(projectId: string, functionId: string, options?: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
685
772
  }
686
773
 
687
774
  interface SpacelrClient {
@@ -741,4 +828,4 @@ interface SpacelrClient {
741
828
  }
742
829
  declare function createClient(config: SpacelrClientConfig): SpacelrClient;
743
830
 
744
- export { type ApiResponse, type AuthLostReason, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type SubscribeHandlers, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge };
831
+ export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type SearchOptions, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type SubscribeHandlers, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge };
package/dist/index.d.ts CHANGED
@@ -58,8 +58,10 @@ interface RegisterResponse {
58
58
  username: string;
59
59
  displayName?: string;
60
60
  };
61
- access_token: string;
62
- refresh_token: string;
61
+ /** Omitted by the server when `emailVerificationRequired` is true. */
62
+ access_token?: string;
63
+ /** Omitted by the server when `emailVerificationRequired` is true. */
64
+ refresh_token?: string;
63
65
  emailVerificationRequired?: boolean;
64
66
  }
65
67
  interface TokenResponse {
@@ -430,11 +432,58 @@ declare class RealtimeClient {
430
432
  private resubscribeAll;
431
433
  }
432
434
 
435
+ type AuthState = 'authenticated' | 'unauthenticated';
436
+ type AuthStateListener = (state: AuthState) => void | Promise<void>;
433
437
  declare class AuthModule {
434
438
  private http;
435
439
  private tokenManager;
436
440
  private config;
441
+ private stateListeners;
442
+ private unsubscribeAuthLost;
443
+ private lastEmittedState;
437
444
  constructor(http: HttpClient, tokenManager: TokenManager, config: SpacelrClientConfig);
445
+ /**
446
+ * Returns true if a non-expired access token is currently in storage.
447
+ * Does NOT make a network request — safe for route guards and other
448
+ * hot paths that run on every navigation.
449
+ *
450
+ * A token within the refresh buffer (about to expire) still counts as
451
+ * authenticated because the next protected request will auto-refresh it.
452
+ *
453
+ * Any error from the underlying TokenStorage (corrupt JSON, quota, etc.)
454
+ * is treated as "not authenticated" rather than propagated, so route
455
+ * guards can't be crashed by a misbehaving storage backend.
456
+ */
457
+ isAuthenticated(): Promise<boolean>;
458
+ /**
459
+ * Subscribe to auth-state transitions. The callback fires:
460
+ * - 'authenticated' after a successful login/register/exchange/2FA-verify
461
+ * - 'unauthenticated' after logout or when a token refresh fails
462
+ *
463
+ * Only fires for transitions that happen after the subscription. If the
464
+ * user is already logged in at subscribe time (e.g. tokens restored from
465
+ * storage on app boot), no 'authenticated' event is emitted — call
466
+ * `isAuthenticated()` once up-front for the initial state.
467
+ *
468
+ * Silent token refreshes do NOT produce an event (auth state is
469
+ * unchanged). Subscribe to `spacelrClient.onTokenRefreshed(...)` if you
470
+ * need to observe successful refreshes.
471
+ *
472
+ * Listener may return `void` or `Promise<void>`. Rejections are swallowed
473
+ * so one broken subscriber can't poison others or the auth flow. The
474
+ * dispatch is fire-and-forget: `logout()` / `login()` resolve as soon as
475
+ * the dispatch loop returns, without awaiting async listeners.
476
+ *
477
+ * Returns an unsubscribe function.
478
+ */
479
+ onAuthStateChange(listener: AuthStateListener): () => void;
480
+ /**
481
+ * Detach this AuthModule from the TokenManager. Call when discarding the
482
+ * client (tests, HMR, multi-client setups) to avoid leaking the internal
483
+ * onAuthLost subscription. Idempotent — safe to call more than once.
484
+ */
485
+ dispose(): void;
486
+ private emitState;
438
487
  login(params: LoginParams): Promise<LoginResponse>;
439
488
  register(params: RegisterParams): Promise<RegisterResponse>;
440
489
  refresh(refreshToken: string): Promise<TokenResponse>;
@@ -544,6 +593,21 @@ interface DeleteResult {
544
593
  interface FindByIdOptions {
545
594
  populate?: PopulateOption[];
546
595
  }
596
+ /**
597
+ * Options for a server-side substring search.
598
+ *
599
+ * Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
600
+ * `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
601
+ */
602
+ interface SearchOptions {
603
+ query: string;
604
+ fields: string[];
605
+ filter?: Record<string, unknown>;
606
+ sort?: Record<string, 1 | -1>;
607
+ limit?: number;
608
+ offset?: number;
609
+ select?: string[];
610
+ }
547
611
  interface SubscribeHandlers<T = Record<string, unknown>> {
548
612
  where?: Record<string, string | number | boolean>;
549
613
  onInsert?: (doc: T & {
@@ -586,6 +650,18 @@ declare class CollectionRef<T = Record<string, unknown>> {
586
650
  _id?: string;
587
651
  })[]): Promise<InsertResult>;
588
652
  find(filter?: Record<string, unknown>): QueryBuilder<T>;
653
+ /**
654
+ * Server-side substring search across the specified fields.
655
+ *
656
+ * The query is regex-escaped server-side and matched case-insensitively via
657
+ * MongoDB `$regex`. Performance note: unanchored case-insensitive regex
658
+ * cannot use a standard B-tree index — on very large collections consider
659
+ * narrowing with `filter` to scope the scan.
660
+ *
661
+ * Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
662
+ * `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
663
+ */
664
+ search(opts: SearchOptions): Promise<FindResult<T>>;
589
665
  findById(id: string, options?: FindByIdOptions): Promise<T & {
590
666
  _id: string;
591
667
  }>;
@@ -665,7 +741,14 @@ declare class NotificationsModule {
665
741
  }
666
742
 
667
743
  interface FunctionInvokeOptions {
668
- secret: string;
744
+ /** Webhook secret — used for `webhook` and `hybrid` invokeMode. */
745
+ secret?: string;
746
+ /**
747
+ * If true, the SDK attaches the currently signed-in user's bearer token
748
+ * via `Authorization` (managed by the SDK's TokenManager). Use for
749
+ * `authenticated`, `hybrid`, or `public` invokeMode.
750
+ */
751
+ authenticated?: boolean;
669
752
  payload?: Record<string, unknown>;
670
753
  }
671
754
  interface FunctionInvokeResult {
@@ -677,11 +760,15 @@ declare class FunctionsModule {
677
760
  private http;
678
761
  constructor(http: HttpClient);
679
762
  /**
680
- * Invoke a function via webhook trigger.
763
+ * Invoke a function.
681
764
  * Calls POST /api/v1/functions/:projectId/:functionId/invoke
682
- * with X-Webhook-Secret header.
765
+ *
766
+ * Provide `secret` for webhook/hybrid functions, `authenticated: true` for
767
+ * JWT-based invocation, or both for hybrid (JWT wins). Public mode needs
768
+ * neither, though `authenticated: true` still populates `event.auth` inside
769
+ * the function.
683
770
  */
684
- invoke(projectId: string, functionId: string, options: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
771
+ invoke(projectId: string, functionId: string, options?: FunctionInvokeOptions): Promise<FunctionInvokeResult>;
685
772
  }
686
773
 
687
774
  interface SpacelrClient {
@@ -741,4 +828,4 @@ interface SpacelrClient {
741
828
  }
742
829
  declare function createClient(config: SpacelrClientConfig): SpacelrClient;
743
830
 
744
- export { type ApiResponse, type AuthLostReason, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type SubscribeHandlers, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge };
831
+ export { type ApiResponse, type AuthLostReason, type AuthState, type AuthStateListener, type AuthorizationUrlParams, BrowserTokenStorage, CodeChallengeMethod, type ConnectionState, type DatabaseChangeEvent, type DownloadUrlResponse, type ExchangeCodeParams, type FileInfo, type FileListResponse, FileVisibility, type FunctionInvokeOptions, type FunctionInvokeResult, GrantType, type InitMultipartUploadParams, type InitMultipartUploadResponse, type JWK, type JWKSResponse, type ListFilesParams, type LoginParams, type LoginResponse, MemoryTokenStorage, type OpenIDConfiguration, type PKCEChallenge, type PartEtag, type PushSubscriptionInfo, type QuotaInfo, type RegisterParams, type RegisterResponse, type SearchOptions, type ShareFileParams, SharePermission, SpacelrAuthError, type SpacelrClient, type SpacelrClientConfig, SpacelrEmailVerificationRequiredError, SpacelrError, SpacelrNetworkError, SpacelrTimeoutError, SpacelrTwoFactorRequiredError, type StoredTokens, type SubscribeHandlers, type TokenResponse, type TokenStorage, type TwoFactorResponse, type TwoFactorVerifyParams, type UnshareFileParams, type UploadFileParams, type UploadLargeFileParams, type UploadProgress, type UserInfo, type UserProfile, type VapidKeyResponse, createClient, generatePKCEChallenge };
package/dist/index.js CHANGED
@@ -901,6 +901,8 @@ var RealtimeClient = class {
901
901
  // libs/sdk/src/modules/auth.module.ts
902
902
  var AuthModule = class {
903
903
  constructor(http, tokenManager, config) {
904
+ this.stateListeners = /* @__PURE__ */ new Set();
905
+ this.lastEmittedState = null;
904
906
  this.http = http;
905
907
  this.tokenManager = tokenManager;
906
908
  this.config = config;
@@ -913,6 +915,84 @@ var AuthModule = class {
913
915
  expiresAt
914
916
  };
915
917
  });
918
+ this.unsubscribeAuthLost = this.tokenManager.onAuthLost(
919
+ () => this.emitState("unauthenticated")
920
+ );
921
+ }
922
+ /**
923
+ * Returns true if a non-expired access token is currently in storage.
924
+ * Does NOT make a network request — safe for route guards and other
925
+ * hot paths that run on every navigation.
926
+ *
927
+ * A token within the refresh buffer (about to expire) still counts as
928
+ * authenticated because the next protected request will auto-refresh it.
929
+ *
930
+ * Any error from the underlying TokenStorage (corrupt JSON, quota, etc.)
931
+ * is treated as "not authenticated" rather than propagated, so route
932
+ * guards can't be crashed by a misbehaving storage backend.
933
+ */
934
+ async isAuthenticated() {
935
+ try {
936
+ const tokens = await this.tokenManager.getStoredTokens();
937
+ if (!tokens?.accessToken) return false;
938
+ if (tokens.expiresAt && tokens.expiresAt * 1e3 <= Date.now()) return false;
939
+ return true;
940
+ } catch {
941
+ return false;
942
+ }
943
+ }
944
+ /**
945
+ * Subscribe to auth-state transitions. The callback fires:
946
+ * - 'authenticated' after a successful login/register/exchange/2FA-verify
947
+ * - 'unauthenticated' after logout or when a token refresh fails
948
+ *
949
+ * Only fires for transitions that happen after the subscription. If the
950
+ * user is already logged in at subscribe time (e.g. tokens restored from
951
+ * storage on app boot), no 'authenticated' event is emitted — call
952
+ * `isAuthenticated()` once up-front for the initial state.
953
+ *
954
+ * Silent token refreshes do NOT produce an event (auth state is
955
+ * unchanged). Subscribe to `spacelrClient.onTokenRefreshed(...)` if you
956
+ * need to observe successful refreshes.
957
+ *
958
+ * Listener may return `void` or `Promise<void>`. Rejections are swallowed
959
+ * so one broken subscriber can't poison others or the auth flow. The
960
+ * dispatch is fire-and-forget: `logout()` / `login()` resolve as soon as
961
+ * the dispatch loop returns, without awaiting async listeners.
962
+ *
963
+ * Returns an unsubscribe function.
964
+ */
965
+ onAuthStateChange(listener) {
966
+ this.stateListeners.add(listener);
967
+ return () => {
968
+ this.stateListeners.delete(listener);
969
+ };
970
+ }
971
+ /**
972
+ * Detach this AuthModule from the TokenManager. Call when discarding the
973
+ * client (tests, HMR, multi-client setups) to avoid leaking the internal
974
+ * onAuthLost subscription. Idempotent — safe to call more than once.
975
+ */
976
+ dispose() {
977
+ this.unsubscribeAuthLost();
978
+ this.unsubscribeAuthLost = () => {
979
+ };
980
+ this.stateListeners.clear();
981
+ this.lastEmittedState = null;
982
+ }
983
+ emitState(state) {
984
+ if (state === this.lastEmittedState) return;
985
+ this.lastEmittedState = state;
986
+ for (const listener of this.stateListeners) {
987
+ try {
988
+ const result = listener(state);
989
+ if (result && typeof result.then === "function") {
990
+ result.then(void 0, () => {
991
+ });
992
+ }
993
+ } catch {
994
+ }
995
+ }
916
996
  }
917
997
  async login(params) {
918
998
  const response = await this.http.request({
@@ -958,6 +1038,7 @@ var AuthModule = class {
958
1038
  } catch {
959
1039
  }
960
1040
  await this.tokenManager.clearTokens();
1041
+ this.emitState("unauthenticated");
961
1042
  }
962
1043
  async verifyEmail(token) {
963
1044
  return this.http.request({
@@ -1028,6 +1109,7 @@ var AuthModule = class {
1028
1109
  refreshToken: response.refresh_token,
1029
1110
  expiresAt
1030
1111
  });
1112
+ this.emitState("authenticated");
1031
1113
  return response;
1032
1114
  }
1033
1115
  async generatePKCE() {
@@ -1110,6 +1192,7 @@ var AuthModule = class {
1110
1192
  refreshToken: response.refresh_token,
1111
1193
  expiresAt
1112
1194
  });
1195
+ this.emitState("authenticated");
1113
1196
  }
1114
1197
  async storeTokensFromRegister(response) {
1115
1198
  if (!response.access_token) return;
@@ -1117,6 +1200,7 @@ var AuthModule = class {
1117
1200
  accessToken: response.access_token,
1118
1201
  refreshToken: response.refresh_token
1119
1202
  });
1203
+ this.emitState("authenticated");
1120
1204
  }
1121
1205
  };
1122
1206
 
@@ -1413,6 +1497,25 @@ var CollectionRef = class {
1413
1497
  find(filter) {
1414
1498
  return new QueryBuilder(this.http, this.basePath, filter);
1415
1499
  }
1500
+ /**
1501
+ * Server-side substring search across the specified fields.
1502
+ *
1503
+ * The query is regex-escaped server-side and matched case-insensitively via
1504
+ * MongoDB `$regex`. Performance note: unanchored case-insensitive regex
1505
+ * cannot use a standard B-tree index — on very large collections consider
1506
+ * narrowing with `filter` to scope the scan.
1507
+ *
1508
+ * Limits: `query` 1–200 chars, `fields` 1–10 entries (each matching
1509
+ * `/^[a-zA-Z0-9_.]+$/`, max 64 chars), `limit` max 100.
1510
+ */
1511
+ async search(opts) {
1512
+ return this.http.request({
1513
+ method: "POST",
1514
+ path: `${this.basePath}/search`,
1515
+ body: opts,
1516
+ authenticated: true
1517
+ });
1518
+ }
1416
1519
  async findById(id, options) {
1417
1520
  const query = {};
1418
1521
  if (options?.populate?.length) {
@@ -1669,19 +1772,25 @@ var FunctionsModule = class {
1669
1772
  this.http = http;
1670
1773
  }
1671
1774
  /**
1672
- * Invoke a function via webhook trigger.
1775
+ * Invoke a function.
1673
1776
  * Calls POST /api/v1/functions/:projectId/:functionId/invoke
1674
- * with X-Webhook-Secret header.
1777
+ *
1778
+ * Provide `secret` for webhook/hybrid functions, `authenticated: true` for
1779
+ * JWT-based invocation, or both for hybrid (JWT wins). Public mode needs
1780
+ * neither, though `authenticated: true` still populates `event.auth` inside
1781
+ * the function.
1675
1782
  */
1676
- async invoke(projectId, functionId, options) {
1783
+ async invoke(projectId, functionId, options = {}) {
1784
+ const headers = {};
1785
+ if (options.secret) {
1786
+ headers["X-Webhook-Secret"] = options.secret;
1787
+ }
1677
1788
  return this.http.request({
1678
1789
  method: "POST",
1679
1790
  path: `/api/v1/functions/${encodeURIComponent(projectId)}/${encodeURIComponent(functionId)}/invoke`,
1680
- headers: {
1681
- "X-Webhook-Secret": options.secret
1682
- },
1791
+ headers,
1683
1792
  body: options.payload ?? {},
1684
- authenticated: false
1793
+ authenticated: options.authenticated ?? false
1685
1794
  });
1686
1795
  }
1687
1796
  };