@archlast/client 0.1.0 → 0.1.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/README.md +185 -51
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,7 +60,14 @@ import { ArchlastClient } from "@archlast/client";
|
|
|
60
60
|
const client = new ArchlastClient(
|
|
61
61
|
"ws://localhost:4000/ws", // WebSocket URL
|
|
62
62
|
"http://localhost:4000", // HTTP URL
|
|
63
|
-
"web"
|
|
63
|
+
"web", // App ID
|
|
64
|
+
undefined, // Optional: auth URL (for same-origin proxy)
|
|
65
|
+
{
|
|
66
|
+
autoConnect: true, // Auto-connect WebSocket (default: true)
|
|
67
|
+
isAdmin: false, // Admin mode (default: false)
|
|
68
|
+
apiKey: "arch_key", // Optional: Better-Auth API key
|
|
69
|
+
betterAuthCookies: {}, // Optional: Better-Auth session cookies
|
|
70
|
+
}
|
|
64
71
|
);
|
|
65
72
|
```
|
|
66
73
|
|
|
@@ -262,15 +269,21 @@ import { usePagination } from "@archlast/client/react";
|
|
|
262
269
|
|
|
263
270
|
function InfiniteTaskList() {
|
|
264
271
|
const {
|
|
265
|
-
items,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
items, // Accumulated items across all pages
|
|
273
|
+
cursor, // Current cursor for next page
|
|
274
|
+
isDone, // Whether pagination is complete
|
|
275
|
+
hasMore, // Convenience flag: !isDone && cursor exists
|
|
276
|
+
isLoading, // Loading state
|
|
277
|
+
loadMore, // Function to load next page
|
|
278
|
+
refresh, // Function to reset and reload from first page
|
|
279
|
+
page, // Optional: current page number (if server provides)
|
|
280
|
+
pageSize, // Optional: page size (if server provides)
|
|
281
|
+
total, // Optional: total count (if server provides)
|
|
282
|
+
} = usePagination(
|
|
283
|
+
api.tasks.listPaginated,
|
|
284
|
+
{ completed: false }, // Base args (no cursor/limit)
|
|
285
|
+
{ limit: 20 } // Options
|
|
286
|
+
);
|
|
274
287
|
|
|
275
288
|
return (
|
|
276
289
|
<div>
|
|
@@ -288,6 +301,8 @@ function InfiniteTaskList() {
|
|
|
288
301
|
{isLoading ? "Loading..." : "Load More"}
|
|
289
302
|
</button>
|
|
290
303
|
)}
|
|
304
|
+
|
|
305
|
+
<button onClick={refresh}>Refresh</button>
|
|
291
306
|
</div>
|
|
292
307
|
);
|
|
293
308
|
}
|
|
@@ -296,10 +311,16 @@ function InfiniteTaskList() {
|
|
|
296
311
|
**Server-side query must return:**
|
|
297
312
|
|
|
298
313
|
```ts
|
|
299
|
-
interface
|
|
314
|
+
interface PaginatedResponse<T> {
|
|
300
315
|
items: T[];
|
|
301
316
|
continueCursor: string | null;
|
|
302
317
|
isDone: boolean;
|
|
318
|
+
page?: number; // Optional
|
|
319
|
+
pageSize?: number; // Optional
|
|
320
|
+
total?: number; // Optional
|
|
321
|
+
}
|
|
322
|
+
continueCursor: string | null;
|
|
323
|
+
isDone: boolean;
|
|
303
324
|
}
|
|
304
325
|
```
|
|
305
326
|
|
|
@@ -347,18 +368,18 @@ function FileUploader() {
|
|
|
347
368
|
|
|
348
369
|
### useAuth
|
|
349
370
|
|
|
350
|
-
Authentication state and actions.
|
|
371
|
+
Authentication state and actions via the `ArchlastAuthClient` wrapper.
|
|
351
372
|
|
|
352
373
|
```ts
|
|
353
374
|
import { useAuth } from "@archlast/client/react";
|
|
354
375
|
|
|
355
376
|
function AuthButton() {
|
|
356
377
|
const {
|
|
357
|
-
signIn,
|
|
358
|
-
signOut,
|
|
359
378
|
isAuthenticated,
|
|
360
379
|
user,
|
|
361
|
-
isLoading
|
|
380
|
+
isLoading,
|
|
381
|
+
signIn,
|
|
382
|
+
signOut
|
|
362
383
|
} = useAuth();
|
|
363
384
|
|
|
364
385
|
if (isLoading) return <Spinner />;
|
|
@@ -367,14 +388,47 @@ function AuthButton() {
|
|
|
367
388
|
return (
|
|
368
389
|
<div>
|
|
369
390
|
<span>Welcome, {user?.name}</span>
|
|
370
|
-
<button onClick={signOut}>
|
|
391
|
+
<button onClick={() => signOut()}>
|
|
392
|
+
Sign Out
|
|
393
|
+
</button>
|
|
394
|
+
</div>
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return (
|
|
399
|
+
<button onClick={() => signIn({ email: "user@example.com", password: "..." })}>
|
|
400
|
+
Sign In
|
|
401
|
+
</button>
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Using Better-Auth React Hooks
|
|
407
|
+
|
|
408
|
+
For full-featured auth in React, use Better-Auth's `useSession` hook:
|
|
409
|
+
|
|
410
|
+
```tsx
|
|
411
|
+
import { authClient } from "./lib/better-auth"; // Your Better-Auth client
|
|
412
|
+
|
|
413
|
+
function AuthButton() {
|
|
414
|
+
const { data: session, isPending } = authClient.useSession();
|
|
415
|
+
|
|
416
|
+
if (isPending) return <Spinner />;
|
|
417
|
+
|
|
418
|
+
if (session?.user) {
|
|
419
|
+
return (
|
|
420
|
+
<div>
|
|
421
|
+
<span>Welcome, {session.user.name}</span>
|
|
422
|
+
<button onClick={() => authClient.signOut()}>
|
|
423
|
+
Sign Out
|
|
424
|
+
</button>
|
|
371
425
|
</div>
|
|
372
426
|
);
|
|
373
427
|
}
|
|
374
428
|
|
|
375
429
|
return (
|
|
376
|
-
<button onClick={() => signIn({
|
|
377
|
-
Sign
|
|
430
|
+
<button onClick={() => authClient.signIn.email({ email, password })}>
|
|
431
|
+
Sign In
|
|
378
432
|
</button>
|
|
379
433
|
);
|
|
380
434
|
}
|
|
@@ -431,39 +485,97 @@ unsubscribe();
|
|
|
431
485
|
|
|
432
486
|
## Authentication
|
|
433
487
|
|
|
488
|
+
Archlast uses [Better-Auth](https://www.better-auth.com/) for authentication. The server exposes Better-Auth endpoints at `/api/auth/*`.
|
|
489
|
+
|
|
434
490
|
### Using the Auth Client
|
|
435
491
|
|
|
492
|
+
The `ArchlastAuthClient` provides a wrapper around Better-Auth endpoints:
|
|
493
|
+
|
|
436
494
|
```ts
|
|
437
495
|
import { ArchlastAuthClient } from "@archlast/client/auth";
|
|
438
496
|
|
|
439
497
|
const auth = new ArchlastAuthClient({
|
|
440
|
-
baseUrl: "http://localhost:4000"
|
|
498
|
+
baseUrl: "http://localhost:4000",
|
|
499
|
+
apiKey: "arch_your_api_key" // Optional: for programmatic access
|
|
441
500
|
});
|
|
442
501
|
|
|
443
|
-
//
|
|
502
|
+
// Sign up with email/password
|
|
503
|
+
// POST /api/auth/sign-up/email
|
|
444
504
|
await auth.signUp({
|
|
445
505
|
email: "user@example.com",
|
|
446
506
|
password: "secure_password",
|
|
447
507
|
name: "John Doe"
|
|
448
508
|
});
|
|
449
509
|
|
|
450
|
-
//
|
|
510
|
+
// Sign in with email/password
|
|
511
|
+
// POST /api/auth/sign-in/email
|
|
451
512
|
await auth.signIn({
|
|
452
513
|
email: "user@example.com",
|
|
453
514
|
password: "secure_password"
|
|
454
515
|
});
|
|
455
516
|
|
|
456
|
-
//
|
|
457
|
-
await auth.signIn({
|
|
458
|
-
|
|
517
|
+
// Sign in with username (if username plugin enabled)
|
|
518
|
+
await auth.signIn({
|
|
519
|
+
username: "johndoe",
|
|
520
|
+
password: "secure_password"
|
|
521
|
+
});
|
|
459
522
|
|
|
460
523
|
// Get current session
|
|
461
|
-
|
|
524
|
+
// GET /api/auth/get-session
|
|
525
|
+
const state = await auth.getState();
|
|
526
|
+
console.log(state.isAuthenticated, state.user);
|
|
462
527
|
|
|
463
528
|
// Sign out
|
|
464
529
|
await auth.signOut();
|
|
465
530
|
```
|
|
466
531
|
|
|
532
|
+
### Using Better-Auth Client Directly
|
|
533
|
+
|
|
534
|
+
For full Better-Auth features (OAuth, organization, admin), use the Better-Auth client directly:
|
|
535
|
+
|
|
536
|
+
```ts
|
|
537
|
+
import { createAuthClient } from "better-auth/react";
|
|
538
|
+
import {
|
|
539
|
+
adminClient,
|
|
540
|
+
usernameClient,
|
|
541
|
+
organizationClient,
|
|
542
|
+
// Optional plugins (add as needed):
|
|
543
|
+
// anonymousClient, // For guest users
|
|
544
|
+
// apiKeyClient, // For API key management
|
|
545
|
+
} from "better-auth/client/plugins";
|
|
546
|
+
|
|
547
|
+
const authClient = createAuthClient({
|
|
548
|
+
baseURL: "http://localhost:4000/api/auth",
|
|
549
|
+
fetchOptions: { credentials: "include" },
|
|
550
|
+
plugins: [
|
|
551
|
+
adminClient(),
|
|
552
|
+
usernameClient(),
|
|
553
|
+
organizationClient(),
|
|
554
|
+
],
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// Email sign in (typical for user-facing apps)
|
|
558
|
+
await authClient.signIn.email({
|
|
559
|
+
email: "user@example.com",
|
|
560
|
+
password: "secure_password",
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Username sign in (used by dashboard)
|
|
564
|
+
await authClient.signIn.username({
|
|
565
|
+
username: "admin",
|
|
566
|
+
password: "secure_password",
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// Session management
|
|
570
|
+
const { data: session } = authClient.useSession();
|
|
571
|
+
|
|
572
|
+
// Organization management
|
|
573
|
+
await authClient.organization.create({ name: "My Team" });
|
|
574
|
+
|
|
575
|
+
// Admin operations (requires admin role)
|
|
576
|
+
await authClient.admin.listUsers({ limit: 10 });
|
|
577
|
+
```
|
|
578
|
+
|
|
467
579
|
### Auth State in Components
|
|
468
580
|
|
|
469
581
|
```tsx
|
|
@@ -504,24 +616,29 @@ const result = await client.storage.upload(file);
|
|
|
504
616
|
console.log("Storage ID:", result.id);
|
|
505
617
|
console.log("URL:", result.url);
|
|
506
618
|
|
|
507
|
-
// Upload
|
|
508
|
-
const
|
|
619
|
+
// Upload with explicit content type
|
|
620
|
+
const blob = new Blob(["data"], { type: "application/octet-stream" });
|
|
621
|
+
const binaryResult = await client.storage.upload(blob, "application/octet-stream");
|
|
509
622
|
```
|
|
510
623
|
|
|
511
624
|
### List Files
|
|
512
625
|
|
|
513
|
-
|
|
514
|
-
// List all files
|
|
515
|
-
const files = await client.storage.list();
|
|
516
|
-
|
|
517
|
-
// List files in bucket
|
|
518
|
-
const images = await client.storage.list("images");
|
|
626
|
+
### List Files
|
|
519
627
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
628
|
+
```ts
|
|
629
|
+
// List files with pagination
|
|
630
|
+
const { items } = await client.storage.list(20, 0); // limit, offset
|
|
631
|
+
|
|
632
|
+
// Next page
|
|
633
|
+
const page2 = await client.storage.list(20, 20);
|
|
634
|
+
|
|
635
|
+
// Items structure
|
|
636
|
+
items.forEach(file => {
|
|
637
|
+
console.log(file.id); // Storage ID
|
|
638
|
+
console.log(file.fileName); // Original filename
|
|
639
|
+
console.log(file.contentType); // MIME type
|
|
640
|
+
console.log(file.size); // Size in bytes
|
|
641
|
+
console.log(file.url); // Public URL
|
|
525
642
|
});
|
|
526
643
|
```
|
|
527
644
|
|
|
@@ -551,22 +668,39 @@ console.log(metadata.createdAt); // Date
|
|
|
551
668
|
|
|
552
669
|
Access admin functionality (requires admin privileges).
|
|
553
670
|
|
|
671
|
+
### Admin Auth Client
|
|
672
|
+
|
|
673
|
+
The `AdminClient` currently provides authentication management:
|
|
674
|
+
|
|
554
675
|
```ts
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
558
|
-
|
|
676
|
+
import { AdminClient } from "@archlast/client/admin";
|
|
677
|
+
|
|
678
|
+
const admin = new AdminClient("http://localhost:4000", {
|
|
679
|
+
apiKey: "arch_your_api_key" // Optional: Better-Auth API key
|
|
680
|
+
});
|
|
559
681
|
|
|
560
|
-
//
|
|
561
|
-
|
|
562
|
-
const
|
|
563
|
-
await
|
|
682
|
+
// Admin authentication
|
|
683
|
+
await admin.auth.signIn(email, password);
|
|
684
|
+
const { user } = await admin.auth.getProfile();
|
|
685
|
+
await admin.auth.signOut();
|
|
564
686
|
|
|
565
|
-
//
|
|
566
|
-
const
|
|
567
|
-
|
|
687
|
+
// Session management
|
|
688
|
+
const { sessions } = await admin.auth.getSessions();
|
|
689
|
+
await admin.auth.revokeSession(sessionId);
|
|
690
|
+
await admin.auth.signOutAll();
|
|
568
691
|
```
|
|
569
692
|
|
|
693
|
+
**Available Methods:**
|
|
694
|
+
|
|
695
|
+
- `admin.auth.signIn(email, password)` - Admin sign in
|
|
696
|
+
- `admin.auth.signOut()` - Sign out current session
|
|
697
|
+
- `admin.auth.getProfile()` - Get admin profile
|
|
698
|
+
- `admin.auth.getSessions()` - List all sessions
|
|
699
|
+
- `admin.auth.revokeSession(sessionId)` - Revoke specific session
|
|
700
|
+
- `admin.auth.signOutAll()` - Sign out from all sessions
|
|
701
|
+
|
|
702
|
+
**Note:** Additional admin clients (users, data, API keys) may be added in future releases.
|
|
703
|
+
|
|
570
704
|
---
|
|
571
705
|
|
|
572
706
|
## tRPC Integration
|
|
@@ -817,9 +951,9 @@ function App() {
|
|
|
817
951
|
|
|
818
952
|
---
|
|
819
953
|
|
|
820
|
-
##
|
|
954
|
+
## Keywords
|
|
821
955
|
|
|
822
|
-
|
|
956
|
+
archlast, client, sdk, react, hooks, real-time, websocket, typescript, api
|
|
823
957
|
|
|
824
958
|
## License
|
|
825
959
|
|