@basictech/react 0.7.0 → 0.8.0-beta.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.
@@ -1,23 +1,24 @@
1
1
 
2
2
  
3
- > @basictech/react@0.7.0-beta.6 build
3
+ > @basictech/react@0.7.0 build
4
4
  > tsup
5
5
 
6
6
  CLI Building entry: src/index.ts
7
7
  CLI Using tsconfig: tsconfig.json
8
- CLI tsup v7.2.0
8
+ CLI tsup v8.5.1
9
9
  CLI Using tsup config: /Users/raz/codebook/basic/libs/client-ts/packages/react/tsup.config.ts
10
10
  CLI Target: es2022
11
11
  CLI Cleaning output folder
12
12
  CJS Build start
13
13
  ESM Build start
14
- ESM dist/index.mjs 55.69 KB
15
- ESM dist/index.mjs.map 116.91 KB
16
- ESM ⚡️ Build success in 21ms
17
- CJS dist/index.js 57.98 KB
18
- CJS dist/index.js.map 116.96 KB
19
- CJS ⚡️ Build success in 21ms
20
- DTS Build start
21
- DTS ⚡️ Build success in 1353ms
22
- DTS dist/index.d.ts 9.48 KB
23
- DTS dist/index.d.mts 9.48 KB
14
+ ESM dist/index.mjs 60.82 KB
15
+ ESM dist/index.mjs.map 128.64 KB
16
+ ESM ⚡️ Build success in 30ms
17
+ CJS dist/index.js 63.30 KB
18
+ CJS dist/index.js.map 128.74 KB
19
+ CJS ⚡️ Build success in 30ms
20
+ DTS Build start
21
+ DTS ⚡️ Build success in 908ms
22
+ DTS dist/index.d.ts 11.15 KB
23
+ DTS dist/index.d.mts 11.15 KB
24
+ ⠙
@@ -13,7 +13,7 @@ This guide provides comprehensive REST API specifications and requirements for i
13
13
  - [Session Management](#session-management)
14
14
  - [Password Management](#password-management)
15
15
  - [Email Verification](#email-verification)
16
- - [Username Availability](#username-availability)
16
+ - [Handle Availability](#handle-availability)
17
17
  - [DID Resolution](#did-resolution)
18
18
  2. [OAuth2 Implementation](#oauth2-implementation)
19
19
  - [Discovery & Configuration](#discovery--configuration)
@@ -36,7 +36,7 @@ This guide provides comprehensive REST API specifications and requirements for i
36
36
 
37
37
  ## PDS Authentication
38
38
 
39
- PDS authentication provides username/password-based authentication with email verification, password reset, and decentralized identifiers (DIDs). This is meant for clients of the PDS server, usually a front-end.
39
+ PDS authentication provides handle/password-based authentication with email verification, password reset, and decentralized identifiers (DIDs). This is meant for clients of the PDS server, usually a front-end.
40
40
 
41
41
  ---
42
42
 
@@ -44,7 +44,7 @@ PDS authentication provides username/password-based authentication with email ve
44
44
 
45
45
  **Endpoint:** `POST /auth/signup`
46
46
 
47
- Create a new user account with username and password.
47
+ Create a new user account with handle and password.
48
48
 
49
49
  #### Request
50
50
 
@@ -54,7 +54,7 @@ Content-Type: application/json
54
54
 
55
55
  {
56
56
  "type": "password",
57
- "username": "john_doe",
57
+ "handle": "john_doe",
58
58
  "password": "securepassword123",
59
59
  "email": "john@example.com",
60
60
  "name": "John Doe"
@@ -66,7 +66,7 @@ Content-Type: application/json
66
66
  | Parameter | Type | Required | Description |
67
67
  |-----------|------|----------|-------------|
68
68
  | `type` | string | Yes | Authentication type. Must be `"password"` |
69
- | `username` | string | Yes | Unique username (alphanumeric, underscores) |
69
+ | `handle` | string | Yes | Unique handle (alphanumeric, 2-30 chars) |
70
70
  | `password` | string | Yes | User password (minimum 3 characters) |
71
71
  | `email` | string | No | User email address (for verification) |
72
72
  | `name` | string | No | User's display name |
@@ -78,7 +78,7 @@ Content-Type: application/json
78
78
  {
79
79
  "data": {
80
80
  "id": "acc_12345",
81
- "username": "john_doe",
81
+ "handle": "john_doe.basic.id",
82
82
  "email": "john@example.com",
83
83
  "name": "John Doe",
84
84
  "created_at": "2025-09-29T10:00:00Z"
@@ -109,7 +109,7 @@ The verification token is valid for **24 hours**.
109
109
 
110
110
  **Endpoint:** `POST /auth/login`
111
111
 
112
- Authenticate with username and password to receive access and refresh tokens.
112
+ Authenticate with handle and password to receive access and refresh tokens.
113
113
 
114
114
  #### Request
115
115
 
@@ -118,7 +118,7 @@ POST /auth/login HTTP/1.1
118
118
  Content-Type: application/json
119
119
 
120
120
  {
121
- "username": "john_doe",
121
+ "handle": "john_doe",
122
122
  "password": "securepassword123"
123
123
  }
124
124
  ```
@@ -127,7 +127,7 @@ Content-Type: application/json
127
127
 
128
128
  | Parameter | Type | Required | Description |
129
129
  |-----------|------|----------|-------------|
130
- | `username` | string | Yes | User's username or email |
130
+ | `handle` | string | Yes | User's handle or email |
131
131
  | `password` | string | Yes | User's password |
132
132
 
133
133
  #### Response
@@ -336,7 +336,7 @@ Content-Type: application/json
336
336
 
337
337
  | Parameter | Type | Required | Description |
338
338
  |-----------|------|----------|-------------|
339
- | `identifier` | string | Yes | User's email or username |
339
+ | `identifier` | string | Yes | User's email or handle |
340
340
 
341
341
  #### Response
342
342
 
@@ -344,7 +344,7 @@ Content-Type: application/json
344
344
  ```json
345
345
  {
346
346
  "success": true,
347
- "message": "If an account with that email/username exists, a password reset link has been sent"
347
+ "message": "If an account with that email/handle exists, a password reset link has been sent"
348
348
  }
349
349
  ```
350
350
 
@@ -507,23 +507,25 @@ Content-Type: application/json
507
507
 
508
508
  ---
509
509
 
510
- ### Username Availability
510
+ ### Handle Availability
511
511
 
512
- **Endpoint:** `GET /auth/check-username`
512
+ **Endpoint:** `GET /auth/check-handle`
513
513
 
514
- Check if a username is available for registration.
514
+ Check if a handle is available for registration.
515
515
 
516
516
  #### Request
517
517
 
518
518
  ```http
519
- GET /auth/check-username?username=john_doe HTTP/1.1
519
+ GET /auth/check-handle?handle=john_doe HTTP/1.1
520
520
  ```
521
521
 
522
+ > **Backward compatibility:** The legacy `GET /auth/check-username` endpoint redirects to `/auth/check-handle`.
523
+
522
524
  #### Query Parameters
523
525
 
524
526
  | Parameter | Type | Required | Description |
525
527
  |-----------|------|----------|-------------|
526
- | `username` | string | Yes | Username to check |
528
+ | `handle` | string | Yes | Handle to check |
527
529
 
528
530
  #### Response
529
531
 
@@ -938,7 +940,7 @@ Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
938
940
  "id": "acc_12345",
939
941
  "name": "John Doe",
940
942
  "email": "john@example.com",
941
- "username": "john_doe"
943
+ "handle_bare": "john_doe"
942
944
  }
943
945
  ```
944
946
 
@@ -1001,7 +1003,7 @@ The server uses a hierarchical scope-based authorization system for fine-grained
1001
1003
 
1002
1004
  | Scope | Description |
1003
1005
  |-------|-------------|
1004
- | `profile:read` | User profile information (name, username) |
1006
+ | `profile:read` | User profile information (name, handle) |
1005
1007
  | `email:read` | User's email address |
1006
1008
  | `openid:read` | OpenID Connect authentication |
1007
1009
 
package/changelog.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # 1.3.4
2
2
 
3
+ ## 0.8.0-beta.1
4
+
5
+ ### Minor Changes
6
+
7
+ - uth updates
8
+
9
+ ## 0.8.0-beta.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Overhaul auth system: extract AuthManager, add PKCE, cross-tab sync, proactive token refresh, enriched error handling, and fix DELETE Content-Type issue
14
+
15
+ ## Unreleased
16
+
17
+ ### Patch Changes
18
+
19
+ - **DBStatus:** Add `ERROR_WILL_RETRY` to align with dexie-syncable status code 4 (error but will retry). Export `DBStatus` enum from the package. Document all `DBStatus` values in readme, including when `ERROR_WILL_RETRY` occurs (e.g. expired token). Enables UI to show "Reconnecting…" or future token refresh on this state.
20
+
3
21
  ## 0.7.0
4
22
 
5
23
  ### Minor Changes
@@ -203,7 +221,6 @@
203
221
  - 96e0156: update schema validation
204
222
  - cda3d16: add schema validation
205
223
  - 2c898ae: update useQuery hook
206
-
207
224
  - no need to pass param as a function, can now enter query directly
208
225
  - defaults to empty array when loading
209
226
 
@@ -259,7 +276,6 @@
259
276
  ### Minor Changes
260
277
 
261
278
  - update useQuery hook
262
-
263
279
  - no need to pass param as a function, can now enter query directly
264
280
  - defaults to empty array when loading
265
281
 
package/dist/index.d.mts CHANGED
@@ -92,6 +92,10 @@ interface AuthError {
92
92
  status: number;
93
93
  message: string;
94
94
  response?: any;
95
+ /** Classifies the error for UI display (e.g. "session expired" vs "forbidden") */
96
+ errorType: 'expired' | 'forbidden' | 'revoked' | 'network' | 'unknown';
97
+ /** True if this error occurred after a retry with a refreshed token */
98
+ afterRetry: boolean;
95
99
  }
96
100
  /**
97
101
  * Custom error class for Remote DB API errors
@@ -102,13 +106,20 @@ declare class RemoteDBError extends Error {
102
106
  response?: any;
103
107
  constructor(message: string, status: number, response?: any);
104
108
  }
109
+ /**
110
+ * Options for getToken (e.g. force refresh after 401)
111
+ */
112
+ interface GetTokenOptions$1 {
113
+ /** When true, refresh the access token before returning (e.g. after server returned 401) */
114
+ forceRefresh?: boolean;
115
+ }
105
116
  /**
106
117
  * Configuration for RemoteDB
107
118
  */
108
119
  interface RemoteDBConfig {
109
120
  serverUrl: string;
110
121
  projectId: string;
111
- getToken: () => Promise<string>;
122
+ getToken: (options?: GetTokenOptions$1) => Promise<string>;
112
123
  schema?: any;
113
124
  /** Enable debug logging (default: false) */
114
125
  debug?: boolean;
@@ -233,12 +244,35 @@ declare const STORAGE_KEYS: {
233
244
  readonly AUTH_STATE: "basic_auth_state";
234
245
  readonly REDIRECT_URI: "basic_redirect_uri";
235
246
  readonly SERVER_URL: "basic_server_url";
247
+ readonly PDS_ENDPOINTS: "basic_pds_endpoints";
248
+ readonly LAST_CONNECT_REPORT: "basic_last_connect_report";
236
249
  readonly DEBUG: "basic_debug";
250
+ readonly CODE_VERIFIER: "basic_code_verifier";
251
+ };
252
+
253
+ type User = {
254
+ sub?: string;
255
+ name?: string;
256
+ email?: string;
257
+ picture?: string;
258
+ };
259
+ type AuthResult = {
260
+ success: boolean;
261
+ error?: string;
262
+ code?: string;
263
+ };
264
+ type GetTokenOptions = {
265
+ forceRefresh?: boolean;
237
266
  };
238
267
 
239
268
  type AuthConfig = {
240
269
  scopes?: string | string[];
270
+ /** @deprecated Use pds_url instead */
241
271
  server_url?: string;
272
+ /** PDS URL for auth and data (default: https://pds.basic.id) */
273
+ pds_url?: string;
274
+ /** Admin server URL for connect reporting (default: https://api.basic.tech) */
275
+ admin_url?: string;
242
276
  ws_url?: string;
243
277
  };
244
278
  type BasicProviderProps = {
@@ -266,25 +300,12 @@ declare enum DBStatus {
266
300
  CONNECTING = "CONNECTING",
267
301
  ONLINE = "ONLINE",
268
302
  SYNCING = "SYNCING",
269
- ERROR = "ERROR"
303
+ ERROR = "ERROR",
304
+ /** Sync reported an error but will retry (e.g. expired token). Used for status code 4 from dexie-syncable. */
305
+ ERROR_WILL_RETRY = "ERROR_WILL_RETRY",
306
+ /** Token expired; the SDK is refreshing and will reconnect automatically. */
307
+ ERROR_TOKEN_EXPIRED = "ERROR_TOKEN_EXPIRED"
270
308
  }
271
- type User = {
272
- name?: string;
273
- email?: string;
274
- id?: string;
275
- primaryEmailAddress?: {
276
- emailAddress: string;
277
- };
278
- fullName?: string;
279
- };
280
- /**
281
- * Auth result type for signInWithCode
282
- */
283
- type AuthResult = {
284
- success: boolean;
285
- error?: string;
286
- code?: string;
287
- };
288
309
  /**
289
310
  * Context type for useBasic hook
290
311
  */
@@ -292,10 +313,19 @@ type BasicContextType = {
292
313
  isReady: boolean;
293
314
  isSignedIn: boolean;
294
315
  user: User | null;
316
+ /** The user's DID (Decentralized Identifier), extracted from the access token `sub` claim */
317
+ did: string | null;
318
+ /** Space-separated scope string from the access token */
319
+ scope: string | null;
320
+ /** Check if a specific scope is granted (e.g., hasScope('profile')) */
321
+ hasScope: (scope: string) => boolean;
322
+ /** Returns scopes that were requested but not granted in the current token */
323
+ missingScopes: () => string[];
295
324
  signIn: () => Promise<void>;
325
+ signInWithHandle: (handle: string) => Promise<void>;
296
326
  signOut: () => Promise<void>;
297
327
  signInWithCode: (code: string, state?: string) => Promise<AuthResult>;
298
- getToken: () => Promise<string>;
328
+ getToken: (options?: GetTokenOptions) => Promise<string>;
299
329
  getSignInUrl: (redirectUri?: string) => Promise<string>;
300
330
  db: BasicDB;
301
331
  dbStatus: DBStatus;
@@ -314,4 +344,31 @@ type BasicContextType = {
314
344
  declare function BasicProvider({ children, project_id: project_id_prop, schema, debug, storage, auth, dbMode }: BasicProviderProps): react_jsx_runtime.JSX.Element;
315
345
  declare function useBasic(): BasicContextType;
316
346
 
317
- export { AuthConfig, AuthError, AuthResult, BasicContextType, BasicDB, BasicProvider, BasicProviderProps, BasicStorage, Collection, DBMode, LocalStorageAdapter, NotAuthenticatedError, RemoteCollection, RemoteDB, RemoteDBConfig, RemoteDBError, STORAGE_KEYS, useBasic };
347
+ type ResolvedDid = {
348
+ did: string;
349
+ handle?: string;
350
+ didDocument: Record<string, unknown>;
351
+ pdsUrl: string;
352
+ authorization_endpoint: string;
353
+ token_endpoint: string;
354
+ userinfo_endpoint: string;
355
+ };
356
+ /**
357
+ * Convert a did:web DID to the HTTPS URL where its DID document lives.
358
+ *
359
+ * did:web:pds.basic.id:did:abc123 -> https://pds.basic.id/did/abc123/did.json
360
+ * did:web:example.com -> https://example.com/.well-known/did.json
361
+ */
362
+ declare function resolveDidWebUrl(did: string): string | null;
363
+ /**
364
+ * Fetch a DID document by DID, extract the PDS URL, and discover OAuth endpoints.
365
+ */
366
+ declare function resolveDid(did: string): Promise<ResolvedDid>;
367
+ /**
368
+ * Resolve a handle (e.g. "alice.basic.id") to a DID and discover PDS + OAuth endpoints.
369
+ *
370
+ * Fetches https://{handle}/.well-known/did.json per the did:web spec.
371
+ */
372
+ declare function resolveHandle(handle: string): Promise<ResolvedDid>;
373
+
374
+ export { type AuthConfig, type AuthError, type AuthResult, type BasicContextType, type BasicDB, BasicProvider, type BasicProviderProps, type BasicStorage, type Collection, type DBMode, DBStatus, type GetTokenOptions$1 as GetTokenOptions, LocalStorageAdapter, NotAuthenticatedError, RemoteCollection, RemoteDB, type RemoteDBConfig, RemoteDBError, type ResolvedDid, STORAGE_KEYS, resolveDid, resolveDidWebUrl, resolveHandle, useBasic };
package/dist/index.d.ts CHANGED
@@ -92,6 +92,10 @@ interface AuthError {
92
92
  status: number;
93
93
  message: string;
94
94
  response?: any;
95
+ /** Classifies the error for UI display (e.g. "session expired" vs "forbidden") */
96
+ errorType: 'expired' | 'forbidden' | 'revoked' | 'network' | 'unknown';
97
+ /** True if this error occurred after a retry with a refreshed token */
98
+ afterRetry: boolean;
95
99
  }
96
100
  /**
97
101
  * Custom error class for Remote DB API errors
@@ -102,13 +106,20 @@ declare class RemoteDBError extends Error {
102
106
  response?: any;
103
107
  constructor(message: string, status: number, response?: any);
104
108
  }
109
+ /**
110
+ * Options for getToken (e.g. force refresh after 401)
111
+ */
112
+ interface GetTokenOptions$1 {
113
+ /** When true, refresh the access token before returning (e.g. after server returned 401) */
114
+ forceRefresh?: boolean;
115
+ }
105
116
  /**
106
117
  * Configuration for RemoteDB
107
118
  */
108
119
  interface RemoteDBConfig {
109
120
  serverUrl: string;
110
121
  projectId: string;
111
- getToken: () => Promise<string>;
122
+ getToken: (options?: GetTokenOptions$1) => Promise<string>;
112
123
  schema?: any;
113
124
  /** Enable debug logging (default: false) */
114
125
  debug?: boolean;
@@ -233,12 +244,35 @@ declare const STORAGE_KEYS: {
233
244
  readonly AUTH_STATE: "basic_auth_state";
234
245
  readonly REDIRECT_URI: "basic_redirect_uri";
235
246
  readonly SERVER_URL: "basic_server_url";
247
+ readonly PDS_ENDPOINTS: "basic_pds_endpoints";
248
+ readonly LAST_CONNECT_REPORT: "basic_last_connect_report";
236
249
  readonly DEBUG: "basic_debug";
250
+ readonly CODE_VERIFIER: "basic_code_verifier";
251
+ };
252
+
253
+ type User = {
254
+ sub?: string;
255
+ name?: string;
256
+ email?: string;
257
+ picture?: string;
258
+ };
259
+ type AuthResult = {
260
+ success: boolean;
261
+ error?: string;
262
+ code?: string;
263
+ };
264
+ type GetTokenOptions = {
265
+ forceRefresh?: boolean;
237
266
  };
238
267
 
239
268
  type AuthConfig = {
240
269
  scopes?: string | string[];
270
+ /** @deprecated Use pds_url instead */
241
271
  server_url?: string;
272
+ /** PDS URL for auth and data (default: https://pds.basic.id) */
273
+ pds_url?: string;
274
+ /** Admin server URL for connect reporting (default: https://api.basic.tech) */
275
+ admin_url?: string;
242
276
  ws_url?: string;
243
277
  };
244
278
  type BasicProviderProps = {
@@ -266,25 +300,12 @@ declare enum DBStatus {
266
300
  CONNECTING = "CONNECTING",
267
301
  ONLINE = "ONLINE",
268
302
  SYNCING = "SYNCING",
269
- ERROR = "ERROR"
303
+ ERROR = "ERROR",
304
+ /** Sync reported an error but will retry (e.g. expired token). Used for status code 4 from dexie-syncable. */
305
+ ERROR_WILL_RETRY = "ERROR_WILL_RETRY",
306
+ /** Token expired; the SDK is refreshing and will reconnect automatically. */
307
+ ERROR_TOKEN_EXPIRED = "ERROR_TOKEN_EXPIRED"
270
308
  }
271
- type User = {
272
- name?: string;
273
- email?: string;
274
- id?: string;
275
- primaryEmailAddress?: {
276
- emailAddress: string;
277
- };
278
- fullName?: string;
279
- };
280
- /**
281
- * Auth result type for signInWithCode
282
- */
283
- type AuthResult = {
284
- success: boolean;
285
- error?: string;
286
- code?: string;
287
- };
288
309
  /**
289
310
  * Context type for useBasic hook
290
311
  */
@@ -292,10 +313,19 @@ type BasicContextType = {
292
313
  isReady: boolean;
293
314
  isSignedIn: boolean;
294
315
  user: User | null;
316
+ /** The user's DID (Decentralized Identifier), extracted from the access token `sub` claim */
317
+ did: string | null;
318
+ /** Space-separated scope string from the access token */
319
+ scope: string | null;
320
+ /** Check if a specific scope is granted (e.g., hasScope('profile')) */
321
+ hasScope: (scope: string) => boolean;
322
+ /** Returns scopes that were requested but not granted in the current token */
323
+ missingScopes: () => string[];
295
324
  signIn: () => Promise<void>;
325
+ signInWithHandle: (handle: string) => Promise<void>;
296
326
  signOut: () => Promise<void>;
297
327
  signInWithCode: (code: string, state?: string) => Promise<AuthResult>;
298
- getToken: () => Promise<string>;
328
+ getToken: (options?: GetTokenOptions) => Promise<string>;
299
329
  getSignInUrl: (redirectUri?: string) => Promise<string>;
300
330
  db: BasicDB;
301
331
  dbStatus: DBStatus;
@@ -314,4 +344,31 @@ type BasicContextType = {
314
344
  declare function BasicProvider({ children, project_id: project_id_prop, schema, debug, storage, auth, dbMode }: BasicProviderProps): react_jsx_runtime.JSX.Element;
315
345
  declare function useBasic(): BasicContextType;
316
346
 
317
- export { AuthConfig, AuthError, AuthResult, BasicContextType, BasicDB, BasicProvider, BasicProviderProps, BasicStorage, Collection, DBMode, LocalStorageAdapter, NotAuthenticatedError, RemoteCollection, RemoteDB, RemoteDBConfig, RemoteDBError, STORAGE_KEYS, useBasic };
347
+ type ResolvedDid = {
348
+ did: string;
349
+ handle?: string;
350
+ didDocument: Record<string, unknown>;
351
+ pdsUrl: string;
352
+ authorization_endpoint: string;
353
+ token_endpoint: string;
354
+ userinfo_endpoint: string;
355
+ };
356
+ /**
357
+ * Convert a did:web DID to the HTTPS URL where its DID document lives.
358
+ *
359
+ * did:web:pds.basic.id:did:abc123 -> https://pds.basic.id/did/abc123/did.json
360
+ * did:web:example.com -> https://example.com/.well-known/did.json
361
+ */
362
+ declare function resolveDidWebUrl(did: string): string | null;
363
+ /**
364
+ * Fetch a DID document by DID, extract the PDS URL, and discover OAuth endpoints.
365
+ */
366
+ declare function resolveDid(did: string): Promise<ResolvedDid>;
367
+ /**
368
+ * Resolve a handle (e.g. "alice.basic.id") to a DID and discover PDS + OAuth endpoints.
369
+ *
370
+ * Fetches https://{handle}/.well-known/did.json per the did:web spec.
371
+ */
372
+ declare function resolveHandle(handle: string): Promise<ResolvedDid>;
373
+
374
+ export { type AuthConfig, type AuthError, type AuthResult, type BasicContextType, type BasicDB, BasicProvider, type BasicProviderProps, type BasicStorage, type Collection, type DBMode, DBStatus, type GetTokenOptions$1 as GetTokenOptions, LocalStorageAdapter, NotAuthenticatedError, RemoteCollection, RemoteDB, type RemoteDBConfig, RemoteDBError, type ResolvedDid, STORAGE_KEYS, resolveDid, resolveDidWebUrl, resolveHandle, useBasic };