@rebasepro/client 0.0.1-canary.f81da60 → 0.1.2

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/auth.d.ts CHANGED
@@ -50,7 +50,12 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
50
50
  accessToken: string;
51
51
  refreshToken: string;
52
52
  }>;
53
- signInWithGoogle: (idToken: string) => Promise<{
53
+ signInWithGoogle: (tokenOrPayload: string | {
54
+ idToken?: string;
55
+ accessToken?: string;
56
+ code?: string;
57
+ redirectUri?: string;
58
+ }) => Promise<{
54
59
  user: RebaseUser;
55
60
  accessToken: string;
56
61
  refreshToken: string;
@@ -0,0 +1,49 @@
1
+ import type { Transport } from "./transport";
2
+ /**
3
+ * Client interface for invoking custom backend functions.
4
+ *
5
+ * Custom functions are Hono route files auto-mounted by the Rebase backend
6
+ * at `/api/functions/{name}`. The `FunctionsClient` wraps the shared
7
+ * transport so callers never need to manually construct URLs or inject
8
+ * auth tokens.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const result = await client.functions.invoke<{ job: Job }>('extract-job', {
13
+ * url: 'https://example.com/posting',
14
+ * html: htmlContent,
15
+ * });
16
+ * ```
17
+ */
18
+ export interface FunctionsClient {
19
+ /**
20
+ * Invoke a custom backend function by name.
21
+ *
22
+ * @typeParam T - Expected shape of the response payload.
23
+ * @param name - Function name (the filename without extension, e.g. `"extract-job"`).
24
+ * @param payload - Optional JSON-serialisable body sent as `POST`.
25
+ * @param options - Optional overrides (HTTP method, sub-path, extra headers).
26
+ * @returns The parsed JSON response from the function.
27
+ */
28
+ invoke<T = unknown>(name: string, payload?: unknown, options?: FunctionInvokeOptions): Promise<T>;
29
+ }
30
+ export interface FunctionInvokeOptions {
31
+ /** HTTP method — defaults to `"POST"`. */
32
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
33
+ /** Sub-path appended after the function name, e.g. `"status/123"`. */
34
+ path?: string;
35
+ /** Extra headers merged into the request (auth is still injected automatically). */
36
+ headers?: Record<string, string>;
37
+ }
38
+ /**
39
+ * Create a `FunctionsClient` backed by the given transport.
40
+ *
41
+ * The transport already handles:
42
+ * - Base URL resolution
43
+ * - JWT injection via `Authorization: Bearer`
44
+ * - 401 retry / `onUnauthorized` flow
45
+ * - Consistent error throwing via `RebaseApiError`
46
+ *
47
+ * @internal
48
+ */
49
+ export declare function createFunctionsClient(transport: Transport): FunctionsClient;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { createAuth, CreateAuthOptions } from "./auth";
3
3
  import { createAdmin, CreateAdminOptions } from "./admin";
4
4
  import { createCron, CreateCronOptions } from "./cron";
5
5
  import { CollectionClient } from "./collection";
6
+ import type { FunctionsClient } from "./functions";
6
7
  export * from "./transport";
7
8
  export * from "./auth";
8
9
  export * from "./admin";
@@ -11,6 +12,7 @@ export * from "./collection";
11
12
  export * from "./websocket";
12
13
  export * from "./storage";
13
14
  export * from "./reviver";
15
+ export * from "./functions";
14
16
  export interface CreateRebaseClientOptions extends RebaseClientConfig {
15
17
  auth?: CreateAuthOptions;
16
18
  admin?: CreateAdminOptions;
@@ -26,6 +28,7 @@ export type RebaseClient<DB = Record<string, unknown>> = BaseRebaseClient<DB> &
26
28
  auth: ReturnType<typeof createAuth>;
27
29
  admin: ReturnType<typeof createAdmin>;
28
30
  cron: ReturnType<typeof createCron>;
31
+ functions: FunctionsClient;
29
32
  ws?: RebaseWebSocketClient;
30
33
  storage?: StorageSource;
31
34
  call: <T = unknown>(endpoint: string, payload?: unknown) => Promise<T>;
package/dist/index.es.js CHANGED
@@ -381,21 +381,18 @@ function createAuth(transport, options) {
381
381
  refreshToken: session.refreshToken
382
382
  };
383
383
  }
384
- async function signInWithGoogle(idToken) {
384
+ async function signInWithGoogle(tokenOrPayload) {
385
385
  const fetchFn = getFetch();
386
+ const body = typeof tokenOrPayload === "string" ? { idToken: tokenOrPayload } : tokenOrPayload;
386
387
  const res = await fetchFn(authUrl("/google"), {
387
388
  method: "POST",
388
389
  headers: { "Content-Type": "application/json" },
389
- body: JSON.stringify({ idToken })
390
+ body: JSON.stringify(body)
390
391
  });
391
- const body = await res.json().catch(() => ({}));
392
- if (!res.ok) throwApiError(res.status, body, res.statusText);
393
- const session = handleAuthResponse(body, "SIGNED_IN");
394
- return {
395
- user: session.user,
396
- accessToken: session.accessToken,
397
- refreshToken: session.refreshToken
398
- };
392
+ const responseBody = await res.json().catch(() => ({}));
393
+ if (!res.ok) throwApiError(res.status, responseBody, res.statusText);
394
+ const session = handleAuthResponse(responseBody, "SIGNED_IN");
395
+ return { user: session.user, accessToken: session.accessToken, refreshToken: session.refreshToken };
399
396
  }
400
397
  async function signInWithLinkedin(code, redirectUri) {
401
398
  const fetchFn = getFetch();
@@ -1149,6 +1146,23 @@ function createCollectionClient(transport, slug, ws) {
1149
1146
  }
1150
1147
  return client;
1151
1148
  }
1149
+ function createFunctionsClient(transport) {
1150
+ return {
1151
+ async invoke(name, payload, options) {
1152
+ const method = options?.method ?? "POST";
1153
+ const subPath = options?.path ? `/${options.path.replace(/^\//, "")}` : "";
1154
+ const routePath = `/functions/${encodeURIComponent(name)}${subPath}`;
1155
+ const init = { method };
1156
+ if (payload !== void 0 && method !== "GET") {
1157
+ init.body = JSON.stringify(payload);
1158
+ }
1159
+ if (options?.headers) {
1160
+ init.headers = options.headers;
1161
+ }
1162
+ return transport.request(routePath, init);
1163
+ }
1164
+ };
1165
+ }
1152
1166
  function rehydrateEntity(entity) {
1153
1167
  return entity;
1154
1168
  }
@@ -1260,11 +1274,11 @@ class RebaseWebSocketClient {
1260
1274
  if (!this.ws) return;
1261
1275
  if (token) {
1262
1276
  this.authenticate(token).catch((e) => {
1263
- if (this.ws) console.warn("WebSocket auto-auth failed:", e);
1277
+ if (this.ws) console.debug("WebSocket auto-auth skipped:", e?.message || e);
1264
1278
  });
1265
1279
  }
1266
1280
  }).catch((e) => {
1267
- if (this.ws) console.warn("WebSocket auto-auth failed:", e);
1281
+ if (this.ws) console.debug("WebSocket auto-auth skipped:", e?.message || e);
1268
1282
  });
1269
1283
  }
1270
1284
  }
@@ -1303,7 +1317,7 @@ class RebaseWebSocketClient {
1303
1317
  console.debug("WebSocket auto-authenticated");
1304
1318
  }
1305
1319
  } catch (error) {
1306
- console.warn("WebSocket auto-auth failed, requests may fail:", error);
1320
+ console.debug("WebSocket connected without auth:", error?.message || error);
1307
1321
  }
1308
1322
  }
1309
1323
  this.emit(wasReconnect ? "reconnect" : "connect");
@@ -2188,6 +2202,7 @@ function createRebaseClient(options) {
2188
2202
  const admin = createAdmin(transport, options.admin);
2189
2203
  const cron = createCron(transport, options.cron);
2190
2204
  const storage = createStorage(transport);
2205
+ const functions = createFunctionsClient(transport);
2191
2206
  const resolvedWsUrl = options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl);
2192
2207
  let ws;
2193
2208
  if (resolvedWsUrl) {
@@ -2244,6 +2259,7 @@ function createRebaseClient(options) {
2244
2259
  auth,
2245
2260
  admin,
2246
2261
  cron,
2262
+ functions,
2247
2263
  storage,
2248
2264
  ws,
2249
2265
  setToken: transport.setToken,
@@ -2274,6 +2290,7 @@ export {
2274
2290
  createAuth,
2275
2291
  createCollectionClient,
2276
2292
  createCron,
2293
+ createFunctionsClient,
2277
2294
  createMemoryStorage,
2278
2295
  createRebaseClient,
2279
2296
  createStorage,