@weirdscience/based-client 0.4.1 → 0.6.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.js CHANGED
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/types.ts
2
4
  class BasedError extends Error {
3
5
  code;
@@ -11,6 +13,20 @@ class BasedError extends Error {
11
13
  this.details = details;
12
14
  }
13
15
  }
16
+ function toHookError(err) {
17
+ if (err instanceof BasedError) {
18
+ return {
19
+ code: err.code,
20
+ message: err.message,
21
+ status: err.status,
22
+ details: err.details
23
+ };
24
+ }
25
+ return {
26
+ code: "NETWORK_ERROR",
27
+ message: err instanceof Error ? err.message : String(err)
28
+ };
29
+ }
14
30
 
15
31
  // src/client.ts
16
32
  var DEFAULT_STORAGE_KEY = "based.session";
@@ -49,6 +65,9 @@ function createClient(options) {
49
65
  function getState() {
50
66
  return state;
51
67
  }
68
+ function onAuthStateChange(callback) {
69
+ return subscribe(() => callback(state));
70
+ }
52
71
  async function persist() {
53
72
  if (!storage)
54
73
  return;
@@ -119,16 +138,22 @@ function createClient(options) {
119
138
  if (!headers.has("Content-Type") && init.body) {
120
139
  headers.set("Content-Type", "application/json");
121
140
  }
141
+ const tokenAtRequest = state.accessToken;
122
142
  let res = await fetch(`${baseUrl}${path}`, { ...init, headers });
123
143
  if (res.status === 401 && state.refreshToken) {
124
- const refreshed = await refreshSession();
125
- if (refreshed) {
144
+ const alreadyRefreshed = state.accessToken !== tokenAtRequest;
145
+ const refreshed = alreadyRefreshed ? true : await refreshSession();
146
+ if (refreshed && state.accessToken) {
126
147
  headers.set("Authorization", `Bearer ${state.accessToken}`);
127
148
  res = await fetch(`${baseUrl}${path}`, { ...init, headers });
128
149
  }
129
150
  }
130
151
  return res;
131
152
  }
153
+ async function authError(res, fallback) {
154
+ const json = await res.json().catch(() => null);
155
+ return new BasedError(json?.error?.code ?? "AUTH_ERROR", json?.error?.message || fallback, res.status, json?.error?.details);
156
+ }
132
157
  async function signUp(email, password) {
133
158
  const res = await fetch(`${baseUrl}/auth/signup`, {
134
159
  method: "POST",
@@ -136,8 +161,7 @@ function createClient(options) {
136
161
  body: JSON.stringify({ email, password })
137
162
  });
138
163
  if (!res.ok) {
139
- const json = await res.json().catch(() => null);
140
- throw new Error(json?.error?.message || "Sign up failed");
164
+ throw await authError(res, "Sign up failed");
141
165
  }
142
166
  const { data } = await res.json();
143
167
  setState({
@@ -155,8 +179,7 @@ function createClient(options) {
155
179
  body: JSON.stringify({ email, password })
156
180
  });
157
181
  if (!res.ok) {
158
- const json = await res.json().catch(() => null);
159
- throw new Error(json?.error?.message || "Sign in failed");
182
+ throw await authError(res, "Sign in failed");
160
183
  }
161
184
  const { data } = await res.json();
162
185
  setState({
@@ -178,7 +201,16 @@ function createClient(options) {
178
201
  }
179
202
  setState({ user: null, accessToken: null, refreshToken: null, isLoading: false });
180
203
  }
181
- async function refreshSession() {
204
+ let refreshInFlight = null;
205
+ function refreshSession() {
206
+ if (!refreshInFlight) {
207
+ refreshInFlight = doRefresh().finally(() => {
208
+ refreshInFlight = null;
209
+ });
210
+ }
211
+ return refreshInFlight;
212
+ }
213
+ async function doRefresh() {
182
214
  if (!state.refreshToken)
183
215
  return false;
184
216
  try {
@@ -215,7 +247,7 @@ function createClient(options) {
215
247
  return null;
216
248
  }
217
249
  const { data } = await res.json();
218
- const user = { id: data.id, email: data.email };
250
+ const user = { id: data.id, email: data.email, role: data.role };
219
251
  setState({ user });
220
252
  return user;
221
253
  } catch {
@@ -242,6 +274,8 @@ function createClient(options) {
242
274
  params.set("limit", String(opts.limit));
243
275
  if (opts?.offset !== undefined)
244
276
  params.set("offset", String(opts.offset));
277
+ if (opts?.order !== undefined)
278
+ params.set("order", opts.order);
245
279
  if (opts?.filter) {
246
280
  for (const [key, value] of Object.entries(opts.filter)) {
247
281
  if (value !== undefined)
@@ -302,7 +336,7 @@ function createClient(options) {
302
336
  };
303
337
  }
304
338
  return {
305
- auth: { signUp, signIn, signOut, refreshSession, getUser },
339
+ auth: { signUp, signIn, signOut, refreshSession, getUser, onAuthStateChange },
306
340
  fetch: fetchWithAuth,
307
341
  from,
308
342
  subscribe,
@@ -313,6 +347,7 @@ function createClient(options) {
313
347
  // src/provider.tsx
314
348
  import { createContext, useContext } from "react";
315
349
  import { jsx } from "react/jsx-runtime";
350
+ "use client";
316
351
  var BasedContext = createContext(null);
317
352
  function BasedProvider({
318
353
  client,
@@ -332,9 +367,16 @@ function useBasedClient() {
332
367
  }
333
368
  // src/hooks/use-user.ts
334
369
  import { useSyncExternalStore } from "react";
370
+ "use client";
371
+ var SERVER_SNAPSHOT = Object.freeze({
372
+ user: null,
373
+ accessToken: null,
374
+ refreshToken: null,
375
+ isLoading: true
376
+ });
335
377
  function useUser() {
336
378
  const client = useBasedClient();
337
- const state = useSyncExternalStore(client.subscribe, () => client.getState(), () => client.getState());
379
+ const state = useSyncExternalStore(client.subscribe, () => client.getState(), () => SERVER_SNAPSHOT);
338
380
  return {
339
381
  user: state.user,
340
382
  isLoading: state.isLoading,
@@ -342,83 +384,134 @@ function useUser() {
342
384
  };
343
385
  }
344
386
  // src/hooks/use-query.ts
345
- import { useState, useEffect, useCallback } from "react";
387
+ import {
388
+ useState,
389
+ useEffect,
390
+ useCallback,
391
+ useMemo,
392
+ useRef,
393
+ useSyncExternalStore as useSyncExternalStore2
394
+ } from "react";
395
+ "use client";
396
+ function stableKey(value) {
397
+ if (value === undefined)
398
+ return "undefined";
399
+ if (value === null || typeof value !== "object")
400
+ return JSON.stringify(value);
401
+ if (Array.isArray(value))
402
+ return `[${value.map(stableKey).join(",")}]`;
403
+ const entries = Object.entries(value).filter(([, v]) => v !== undefined).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
404
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableKey(v)}`).join(",")}}`;
405
+ }
346
406
  function useQuery(table, options) {
347
407
  const client = useBasedClient();
348
408
  const enabled = options?.enabled !== false;
409
+ const authKey = useSyncExternalStore2(client.subscribe, () => client.getState().user?.id ?? null, () => null);
349
410
  const [data, setData] = useState(null);
350
411
  const [total, setTotal] = useState(0);
351
412
  const [isLoading, setIsLoading] = useState(enabled);
352
413
  const [error, setError] = useState(null);
353
- const fetchData = useCallback(async () => {
414
+ const optionsKey = stableKey(options);
415
+ const selectOptions = useMemo(() => ({
416
+ filter: options?.filter,
417
+ limit: options?.limit,
418
+ offset: options?.offset,
419
+ order: options?.order
420
+ }), [optionsKey]);
421
+ const latestRequest = useRef(0);
422
+ const runQuery = useCallback(async () => {
423
+ const requestId = ++latestRequest.current;
354
424
  setIsLoading(true);
355
425
  setError(null);
356
426
  try {
357
- const result = await client.from(table).select({
358
- filter: options?.filter,
359
- limit: options?.limit,
360
- offset: options?.offset
361
- });
427
+ const result = await client.from(table).select(selectOptions);
428
+ if (latestRequest.current !== requestId)
429
+ return;
362
430
  setData(result.data);
363
431
  setTotal(result.total);
364
432
  } catch (err) {
365
- const code = err instanceof BasedError ? err.code : "NETWORK_ERROR";
366
- setError({ code, message: err.message });
433
+ if (latestRequest.current !== requestId)
434
+ return;
435
+ setError(toHookError(err));
367
436
  setData(null);
368
437
  setTotal(0);
369
438
  } finally {
370
- setIsLoading(false);
439
+ if (latestRequest.current === requestId)
440
+ setIsLoading(false);
371
441
  }
372
- }, [client, table, JSON.stringify(options)]);
442
+ }, [client, table, selectOptions]);
373
443
  useEffect(() => {
374
444
  if (!enabled) {
375
- setIsLoading(false);
445
+ latestRequest.current += 1;
376
446
  setData(null);
377
447
  setTotal(0);
378
448
  setError(null);
449
+ setIsLoading(false);
379
450
  return;
380
451
  }
381
- fetchData();
382
- }, [fetchData, enabled]);
383
- return { data, total, isLoading, error, refetch: fetchData };
452
+ runQuery();
453
+ return () => {
454
+ latestRequest.current += 1;
455
+ };
456
+ }, [enabled, authKey, runQuery]);
457
+ return { data, total, isLoading, error, refetch: runQuery };
384
458
  }
385
459
  // src/hooks/use-record.ts
386
- import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
460
+ import {
461
+ useState as useState2,
462
+ useEffect as useEffect2,
463
+ useCallback as useCallback2,
464
+ useRef as useRef2,
465
+ useSyncExternalStore as useSyncExternalStore3
466
+ } from "react";
467
+ "use client";
387
468
  function useRecord(table, id, options) {
388
469
  const client = useBasedClient();
389
470
  const enabled = options?.enabled !== false && !!id;
471
+ const authKey = useSyncExternalStore3(client.subscribe, () => client.getState().user?.id ?? null, () => null);
390
472
  const [data, setData] = useState2(null);
391
473
  const [isLoading, setIsLoading] = useState2(enabled);
392
474
  const [error, setError] = useState2(null);
393
- const fetchData = useCallback2(async () => {
475
+ const latestRequest = useRef2(0);
476
+ const runQuery = useCallback2(async () => {
394
477
  if (!id)
395
478
  return;
479
+ const requestId = ++latestRequest.current;
396
480
  setIsLoading(true);
397
481
  setError(null);
398
482
  try {
399
483
  const row = await client.from(table).get(id);
484
+ if (latestRequest.current !== requestId)
485
+ return;
400
486
  setData(row);
401
487
  } catch (err) {
402
- const code = err instanceof BasedError ? err.code : "NETWORK_ERROR";
403
- setError({ code, message: err.message });
488
+ if (latestRequest.current !== requestId)
489
+ return;
490
+ setError(toHookError(err));
404
491
  setData(null);
405
492
  } finally {
406
- setIsLoading(false);
493
+ if (latestRequest.current === requestId)
494
+ setIsLoading(false);
407
495
  }
408
496
  }, [client, table, id]);
409
497
  useEffect2(() => {
410
498
  if (!enabled) {
411
- setIsLoading(false);
499
+ latestRequest.current += 1;
412
500
  setData(null);
413
501
  setError(null);
502
+ setIsLoading(false);
414
503
  return;
415
504
  }
416
- fetchData();
417
- }, [fetchData, enabled]);
418
- return { data, isLoading, error, refetch: fetchData };
505
+ runQuery();
506
+ return () => {
507
+ latestRequest.current += 1;
508
+ };
509
+ }, [enabled, authKey, runQuery]);
510
+ return { data, isLoading, error, refetch: runQuery };
419
511
  }
420
512
  // src/hooks/use-mutation.ts
421
513
  import { useState as useState3, useCallback as useCallback3 } from "react";
514
+ "use client";
422
515
  function useMutation(table, operation) {
423
516
  const client = useBasedClient();
424
517
  const [isLoading, setIsLoading] = useState3(false);
@@ -449,16 +542,17 @@ function useMutation(table, operation) {
449
542
  }
450
543
  }
451
544
  } catch (err) {
452
- const code = err instanceof BasedError ? err.code : "MUTATION_ERROR";
453
- const message = err.message;
454
- setError({ code, message });
455
- throw err;
545
+ setError(toHookError(err));
546
+ return null;
456
547
  } finally {
457
548
  setIsLoading(false);
458
549
  }
459
550
  }, [client, table, operation]);
460
551
  return { mutate, isLoading, error };
461
552
  }
553
+
554
+ // src/index.ts
555
+ "use client";
462
556
  export {
463
557
  useUser,
464
558
  useRecord,
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI1D,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,EACjE,EACA,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAMA;AAED,wBAAgB,cAAc,CAC5B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,KAC9D,WAAW,CAAC,CAAC,CAAC,CAMlB"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI1D,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,EACjE,EACA,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAMA;AAED,wBAAgB,cAAc,CAC5B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,KAC9D,WAAW,CAAC,CAAC,CAAC,CAMlB"}
package/dist/types.d.ts CHANGED
@@ -19,6 +19,11 @@ export interface BasedClientOptions {
19
19
  export interface AuthUser {
20
20
  id: string;
21
21
  email: string;
22
+ /**
23
+ * Workspace role as reported by the server. The first user to sign up is the
24
+ * `owner`; everyone after is a `member`.
25
+ */
26
+ role: "owner" | "member";
22
27
  }
23
28
  export interface AuthState {
24
29
  user: AuthUser | null;
@@ -40,6 +45,12 @@ export interface BasedClient<T extends Record<string, Record<string, unknown>> =
40
45
  * Returns the current authenticated user by calling `/auth/me`.
41
46
  */
42
47
  getUser(): Promise<AuthUser | null>;
48
+ /**
49
+ * Subscribe to auth state changes. The callback receives the new state on
50
+ * every change (sign in, sign out, refresh, rehydration). Returns an
51
+ * unsubscribe function. Sugar over `client.subscribe` + `client.getState`.
52
+ */
53
+ onAuthStateChange(callback: (state: AuthState) => void): () => void;
43
54
  };
44
55
  fetch(path: string, init?: RequestInit): Promise<Response>;
45
56
  /**
@@ -97,24 +108,41 @@ export declare class BasedError extends Error {
97
108
  details?: unknown;
98
109
  constructor(code: string, message: string, status: number, details?: unknown);
99
110
  }
111
+ /**
112
+ * Narrow anything thrown by the data builder into the hooks' error shape.
113
+ * Internal — not part of the public surface.
114
+ */
115
+ export declare function toHookError(err: unknown): HookError;
100
116
  export interface QueryOptions<T = Record<string, unknown>> {
101
117
  filter?: Partial<Record<keyof T, string | number | boolean>>;
102
118
  limit?: number;
103
119
  offset?: number;
120
+ /**
121
+ * Sort order, as `<column>.asc` or `<column>.desc`. Defaults to `id.asc`
122
+ * server-side so pagination is stable.
123
+ */
124
+ order?: `${string & keyof T}.asc` | `${string & keyof T}.desc`;
104
125
  /**
105
126
  * When false, the query won't fire. Useful for gating queries behind auth:
106
127
  * `useQuery("notes", { enabled: !!user })`. Defaults to true.
107
128
  */
108
129
  enabled?: boolean;
109
130
  }
131
+ /**
132
+ * The error shape the hooks expose. Mirrors `BasedError` without being an
133
+ * `Error` instance, so it survives React state and serialization.
134
+ */
135
+ export interface HookError {
136
+ code: string;
137
+ message: string;
138
+ status?: number;
139
+ details?: unknown;
140
+ }
110
141
  export interface QueryResult<T = unknown> {
111
142
  data: T[] | null;
112
143
  total: number;
113
144
  isLoading: boolean;
114
- error: {
115
- code: string;
116
- message: string;
117
- } | null;
145
+ error: HookError | null;
118
146
  refetch: () => void;
119
147
  }
120
148
  export interface RecordOptions {
@@ -126,19 +154,22 @@ export interface RecordOptions {
126
154
  export interface RecordResult<T = unknown> {
127
155
  data: T | null;
128
156
  isLoading: boolean;
129
- error: {
130
- code: string;
131
- message: string;
132
- } | null;
157
+ error: HookError | null;
133
158
  refetch: () => void;
134
159
  }
160
+ /**
161
+ * Which write the `useMutation` hook performs.
162
+ */
163
+ export type MutationOperation = "create" | "update" | "upsert" | "delete";
135
164
  export interface MutationResult<T = unknown> {
136
- mutate: (data: Partial<T> & Record<string, unknown>) => Promise<T>;
165
+ /**
166
+ * Performs the write. Never throws — on failure it resolves to `null` and
167
+ * populates `error`, so `onClick={() => mutate(...)}` can't produce an
168
+ * unhandled rejection.
169
+ */
170
+ mutate: (data: Partial<T> & Record<string, unknown>) => Promise<T | null>;
137
171
  isLoading: boolean;
138
- error: {
139
- code: string;
140
- message: string;
141
- } | null;
172
+ error: HookError | null;
142
173
  }
143
174
  export interface DefaultTables {
144
175
  [table: string]: Record<string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weirdscience/based-client",
3
- "version": "0.4.1",
4
- "description": "React SDK for Based — a minimal self-hosted BaaS",
3
+ "version": "0.6.1",
4
+ "description": "SDK for Based — a minimal self-hosted BaaS. Typed client for any JavaScript app, plus React hooks.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -10,13 +10,20 @@
10
10
  },
11
11
  "homepage": "https://based.weirdscience.dev",
12
12
  "type": "module",
13
- "main": "./dist/index.js",
13
+ "main": "./dist/index.cjs",
14
14
  "module": "./dist/index.js",
15
15
  "types": "./dist/index.d.ts",
16
+ "sideEffects": false,
16
17
  "exports": {
17
18
  ".": {
18
19
  "types": "./dist/index.d.ts",
19
- "import": "./dist/index.js"
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs"
22
+ },
23
+ "./core": {
24
+ "types": "./dist/core.d.ts",
25
+ "import": "./dist/core.js",
26
+ "require": "./dist/core.cjs"
20
27
  }
21
28
  },
22
29
  "files": [
@@ -24,15 +31,27 @@
24
31
  "README.md"
25
32
  ],
26
33
  "scripts": {
27
- "build": "rm -rf dist && NODE_ENV=production bun build src/index.ts --outdir dist --target browser --format esm --external react --external react/jsx-runtime && bun x tsc --emitDeclarationOnly --declaration --outDir dist",
34
+ "build": "rm -rf dist && NODE_ENV=production bun build src/index.ts --outdir dist --target browser --format esm --external react --external react/jsx-runtime --banner '\"use client\";' && NODE_ENV=production bun build src/index.ts --outfile dist/index.cjs --target node --format cjs --external react --external react/jsx-runtime --banner '\"use client\";' && NODE_ENV=production bun build src/core.ts --outfile dist/core.js --target browser --format esm && NODE_ENV=production bun build src/core.ts --outfile dist/core.cjs --target node --format cjs && bun x tsc -p tsconfig.json",
28
35
  "prepublishOnly": "bun run build",
29
- "test": "bun test"
36
+ "test": "bun test",
37
+ "typecheck": "tsc --noEmit -p tsconfig.test.json"
30
38
  },
31
39
  "peerDependencies": {
32
40
  "react": "^18.0.0 || ^19.0.0"
33
41
  },
34
42
  "devDependencies": {
43
+ "@happy-dom/global-registrator": "^20.0.0",
44
+ "@testing-library/dom": "^10.4.1",
45
+ "@testing-library/react": "^16.0.0",
35
46
  "@types/react": "^19.0.0",
47
+ "@types/react-dom": "^19.0.0",
48
+ "react": "^19.0.0",
49
+ "react-dom": "^19.0.0",
36
50
  "typescript": "^5.0.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "react": {
54
+ "optional": true
55
+ }
37
56
  }
38
57
  }