@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.
Files changed (2) hide show
  1. package/README.md +185 -51
  2. 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" // App ID
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
- isLoading,
267
- hasMore,
268
- loadMore,
269
- error
270
- } = usePagination(api.tasks.listPaginated, {
271
- limit: 20,
272
- filter: { completed: false }
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 PaginatedResult<T> {
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}>Sign Out</button>
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({ provider: "google" })}>
377
- Sign in with Google
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
- // Email/password sign up
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
- // Email/password sign in
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
- // OAuth sign in
457
- await auth.signIn({ provider: "google" });
458
- await auth.signIn({ provider: "github" });
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
- const session = await auth.getSession();
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 to specific bucket
508
- const imageResult = await client.storage.upload(imageFile, "images");
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
- ```ts
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
- // With pagination
521
- const page1 = await client.storage.list("images", { limit: 20 });
522
- const page2 = await client.storage.list("images", {
523
- limit: 20,
524
- cursor: page1.nextCursor
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
- // Auth operations
556
- const profile = await client.admin.auth.getProfile();
557
- const users = await client.admin.auth.listUsers();
558
- await client.admin.auth.updateUser(userId, { role: "admin" });
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
- // API key management
561
- const keys = await client.admin.apiKeys.list();
562
- const newKey = await client.admin.apiKeys.create({ name: "CI/CD" });
563
- await client.admin.apiKeys.revoke(keyId);
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
- // Data operations
566
- const collections = await client.admin.data.listCollections();
567
- const docs = await client.admin.data.query("tasks", { limit: 100 });
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
- ## Publishing (Maintainers)
954
+ ## Keywords
821
955
 
822
- See `docs/npm-publishing.md` for release and publish steps.
956
+ archlast, client, sdk, react, hooks, real-time, websocket, typescript, api
823
957
 
824
958
  ## License
825
959
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archlast/client",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Archlast client SDK for React and API access",
5
5
  "license": "MIT",
6
6
  "repository": {