lazypock 0.1.3 → 0.1.6

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.d.cts CHANGED
@@ -50,11 +50,39 @@ interface RequestOptions {
50
50
  signal?: AbortSignal;
51
51
  /** Custom fetch implementation (for RN or test mocking) */
52
52
  fetch?: typeof globalThis.fetch;
53
+ /**
54
+ * Request identifier used by the auto-cancellation mechanism.
55
+ *
56
+ * Pending requests sharing the same key cancel each other — only the
57
+ * last one is executed (PocketBase `requestKey` semantics).
58
+ *
59
+ * - `string` — use this exact key instead of the default `METHOD + path`.
60
+ * - `null` — disable auto-cancellation for this request (never auto-cancelled).
61
+ *
62
+ * @default `${method} ${path}`
63
+ */
64
+ requestKey?: string | null;
65
+ /**
66
+ * Disable auto-cancellation for this request.
67
+ * Alias of `requestKey: null` (PocketBase `$autoCancel: false` compat).
68
+ */
69
+ autoCancel?: boolean;
70
+ /**
71
+ * Custom request key used for auto-cancellation.
72
+ * Alias of `requestKey` (PocketBase `$cancelKey` compat).
73
+ */
74
+ cancelKey?: string;
53
75
  }
54
76
  declare class ApiError extends Error {
55
77
  readonly data: unknown;
56
78
  readonly status: number;
57
- constructor(message: string, data: unknown, status: number);
79
+ /**
80
+ * `true` when this error was caused by an aborted/cancelled request
81
+ * (auto-cancelled duplicate, or manually via `cancelRequest()` /
82
+ * `cancelAllRequests()` / an external AbortSignal).
83
+ */
84
+ readonly isAbort: boolean;
85
+ constructor(message: string, data: unknown, status: number, isAbort?: boolean);
58
86
  }
59
87
 
60
88
  /**
@@ -130,29 +158,51 @@ declare class AuthStore {
130
158
  private notify;
131
159
  }
132
160
 
133
- /**
134
- * Low-level HTTP client wrapping `fetch` with automatic auth token injection.
135
- * Only relies on `globalThis.fetch` — works in browser, React Native, and Node 18+.
136
- */
137
161
  declare class HttpClient {
138
162
  private baseUrl;
139
163
  private authStore;
140
164
  private defaultFetch;
165
+ /**
166
+ * Abort controllers for in-flight requests, keyed by their cancellation key
167
+ * (default `METHOD path`). A new request with the same key aborts the
168
+ * previous one — PocketBase-style auto-cancellation of duplicated requests.
169
+ */
170
+ private cancelControllers;
171
+ /** Global toggle for the auto-cancellation behaviour (default: on). */
172
+ private enableAutoCancellation;
141
173
  /**
142
174
  * @param baseUrl The API base URL (e.g. `http://localhost:4000/api`). Trailing slash stripped.
143
175
  * @param authStore The auth store providing the token for Authorization headers.
144
176
  */
145
177
  constructor(baseUrl: string, authStore: AuthStore);
146
178
  private refreshAuth;
179
+ /**
180
+ * Globally enable or disable auto-cancellation of duplicated pending requests.
181
+ * Fluent — returns `this` for chaining.
182
+ */
183
+ autoCancellation(enable: boolean): this;
184
+ /**
185
+ * Abort a pending request identified by its cancellation key
186
+ * (default `METHOD path`, e.g. `"GET /api/posts"`). No-op if not pending.
187
+ */
188
+ cancelRequest(requestKey: string): this;
189
+ /** Abort all pending requests. */
190
+ cancelAllRequests(): this;
147
191
  /**
148
192
  * Make an HTTP request with automatic auth token injection and optional auto-refresh.
149
193
  *
194
+ * Auto-cancellation: a request keyed by `options.requestKey` (default
195
+ * `METHOD path`) aborts any previous pending request with the same key,
196
+ * so only the last duplicate executes. Set `requestKey: null` or
197
+ * `autoCancel: false` to opt out per request.
198
+ *
150
199
  * @param method HTTP method.
151
200
  * @param path URL path (appended to baseUrl).
152
201
  * @param body JSON-serializable body, or FormData for file uploads.
153
202
  * @param options Optional request options.
154
203
  * @returns Parsed JSON response, or null for 204 No Content.
155
- * @throws {ApiError} On non-2xx responses.
204
+ * @throws {ApiError} On non-2xx responses or when the request is aborted
205
+ * (aborted requests throw an `ApiError` with `isAbort === true`).
156
206
  */
157
207
  request<T = unknown>(method: Method, path: string, body?: unknown, options?: RequestOptions): Promise<T | null>;
158
208
  /**
@@ -288,11 +338,27 @@ declare class CollectionService<T = ApiRecord> {
288
338
  constructor(http: HttpClient, collectionName: string, authStore?: AuthStore, realtime?: RealtimeService);
289
339
  private encodeId;
290
340
  /**
291
- * List records with optional filter/sort/pagination.
292
- * @param params Query parameters including `filter`, `sort`, `page`, `perPage`, `expand`.
341
+ * Fetch a paginated list of records (PocketBase `getList`).
342
+ *
343
+ * @param page Page number (default 1).
344
+ * @param perPage Records per page (default 30).
345
+ * @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.
346
+ */
347
+ getList<T2 = T>(page?: number, perPage?: number, options?: Record<string, unknown> & RequestOptions): Promise<ListResult<T2> | null>;
348
+ /**
349
+ * Fetch all records at once (auto-paginates). Mirrors PocketBase's
350
+ * `pb.collection(name).getFullList()`.
351
+ *
352
+ * @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.
353
+ */
354
+ getFullList<T2 = T>(options?: Record<string, unknown> & RequestOptions): Promise<Array<T2>>;
355
+ /**
356
+ * Fetch the first record matching a filter (PocketBase `getFirstListItem`).
357
+ *
358
+ * @param filter Filter expression (e.g. `title = 'x'`).
293
359
  * @param options Optional request options.
294
360
  */
295
- list(params?: Record<string, string>, options?: RequestOptions): Promise<ListResult<T> | null>;
361
+ getFirstListItem<T2 = T>(filter: string, options?: RequestOptions): Promise<T2 | null>;
296
362
  /**
297
363
  * Get a single record by ID.
298
364
  * @param id Record ID.
@@ -393,12 +459,28 @@ interface FileRecord {
393
459
  mimeType: string;
394
460
  size: number;
395
461
  url: string;
462
+ /** Map of thumbnail size => URL, e.g. { "50x50": "/api/files/<id>/thumbs/50x50" } */
463
+ thumbs?: Record<string, string>;
396
464
  [key: string]: unknown;
397
465
  }
398
466
  /**
399
467
  * Construct a file URL from the API base URL and file ID.
400
468
  */
401
469
  declare function getFileUrl(baseUrl: string, fileId: string): string;
470
+ /**
471
+ * Construct a thumbnail URL from the API base URL, file ID, and thumb size.
472
+ * @param size e.g. "50x50"
473
+ */
474
+ declare function getThumbUrl(baseUrl: string, fileId: string, size: string): string;
475
+ /**
476
+ * Construct an on-demand scaled image URL from the API base URL, file ID, and size.
477
+ *
478
+ * The size is an ImageMagick geometry: "100" (width, keep aspect), "100x100"
479
+ * (fit within box), "100x100!" (exact crop), "x200" (height). The server
480
+ * generates and caches the scaled image on first request.
481
+ * @param size e.g. "100x100"
482
+ */
483
+ declare function getScaleUrl(baseUrl: string, fileId: string, size: string): string;
402
484
  /**
403
485
  * Service for file upload, retrieval, and deletion.
404
486
  * Access via {@link LazypockClient.files}.
@@ -419,6 +501,27 @@ declare class FilesService {
419
501
  recordId?: string;
420
502
  fieldName?: string;
421
503
  }): Promise<FileRecord | null>;
504
+ /**
505
+ * List uploaded files (newest first), with optional filters.
506
+ *
507
+ * @param options Filters and pagination.
508
+ */
509
+ list(options?: {
510
+ page?: number;
511
+ perPage?: number;
512
+ collectionName?: string;
513
+ fieldName?: string;
514
+ mime?: string;
515
+ }): Promise<{
516
+ items: FileRecord[];
517
+ page: number;
518
+ perPage: number;
519
+ total: number;
520
+ }>;
521
+ /**
522
+ * Fetch file metadata including URL.
523
+ * @param fileId The file ID.
524
+ */
422
525
  /**
423
526
  * Fetch file metadata including URL.
424
527
  * @param fileId The file ID.
@@ -432,6 +535,82 @@ declare class FilesService {
432
535
  delete(fileId: string, options?: RequestOptions): Promise<null>;
433
536
  }
434
537
 
538
+ /**
539
+ * Registry-level realtime events for the collections admin channel.
540
+ * The backend (AdminChannel) broadcasts the action as the *event name*,
541
+ * with the collection JSON as the payload.
542
+ */
543
+ interface CollectionsMessage {
544
+ action: "create" | "update" | "delete";
545
+ /** The collection payload (id + metadata), or {} when unavailable. */
546
+ collection: Record<string, unknown>;
547
+ topic?: string;
548
+ }
549
+ /**
550
+ * Registry service for collections (list/create/update/delete + realtime
551
+ * registry events). Mirrors PocketBase's `pb.collections`.
552
+ */
553
+ declare class CollectionsService {
554
+ private http?;
555
+ private realtime?;
556
+ /** @internal */
557
+ constructor(http?: HttpClient, realtime?: RealtimeService);
558
+ /**
559
+ * Fetch a paginated list of collections (admin).
560
+ *
561
+ * @param params Optional query params (`page`, `perPage`, `filter`, `sort`).
562
+ * @param options Optional request options.
563
+ */
564
+ getList<T = ApiRecord>(params?: Record<string, unknown>, options?: RequestOptions): Promise<ListResult<T> | null>;
565
+ /**
566
+ * Fetch all collections at once (auto-paginates). Mirrors PocketBase's
567
+ * `pb.collections.getFullList()` — defaults to listing everything.
568
+ *
569
+ * @param options Query params (`sort`, `batch`, etc.) or request options.
570
+ */
571
+ getFullList<T = ApiRecord>(options?: Record<string, unknown> & RequestOptions): Promise<Array<T>>;
572
+ /**
573
+ * Get a single collection by ID or name (admin).
574
+ *
575
+ * @param id Collection ID or name.
576
+ * @param options Optional request options.
577
+ */
578
+ getOne<T = ApiRecord>(id: string, options?: RequestOptions): Promise<T | null>;
579
+ /**
580
+ * Create a new collection (admin).
581
+ *
582
+ * @param data Collection definition (name, type, fields, options, rules, etc.).
583
+ * @param options Optional request options.
584
+ */
585
+ create<T = ApiRecord>(data: Record<string, unknown>, options?: RequestOptions): Promise<T | null>;
586
+ /**
587
+ * Update an existing collection (admin).
588
+ *
589
+ * @param id Collection ID or name.
590
+ * @param data Updated collection fields.
591
+ * @param options Optional request options.
592
+ */
593
+ update<T = ApiRecord>(id: string, data: Record<string, unknown>, options?: RequestOptions): Promise<T | null>;
594
+ /**
595
+ * Delete a collection (admin).
596
+ *
597
+ * @param id Collection ID or name.
598
+ * @param options Optional request options.
599
+ */
600
+ delete(id: string, options?: RequestOptions): Promise<boolean>;
601
+ /**
602
+ * Subscribe to collection registry changes.
603
+ *
604
+ * @param callback Received on every collection create/update/delete.
605
+ * @returns A function that unsubscribes this callback.
606
+ */
607
+ subscribe(callback: (e: CollectionsMessage) => void): () => void;
608
+ /**
609
+ * Unsubscribe all callbacks from the registry channel.
610
+ */
611
+ unsubscribe(): void;
612
+ }
613
+
435
614
  /** A single field definition as returned by `GET /collections`. */
436
615
  interface SchemaField {
437
616
  id?: string;
@@ -534,13 +713,14 @@ interface LazypockClientOptions {
534
713
  * ```ts
535
714
  * const client = new LazypockClient({ baseUrl: 'http://localhost:4000/api' });
536
715
  * await client.login('admin@example.com', 'password');
537
- * const posts = await client.collection('posts').list();
716
+ * const posts = await client.collection('posts').getList();
538
717
  * ```
539
718
  */
540
719
  declare class LazypockClient {
541
720
  readonly http: HttpClient;
542
721
  readonly authStore: AuthStore;
543
722
  readonly realtime: RealtimeService;
723
+ readonly collections: CollectionsService;
544
724
  readonly files: FilesService;
545
725
  private collectionCache;
546
726
  private schemaByName?;
@@ -577,6 +757,27 @@ declare class LazypockClient {
577
757
  generateTypes(options?: {
578
758
  packageName?: string;
579
759
  }): string;
760
+ /**
761
+ * Globally enable or disable auto-cancellation of duplicated pending requests.
762
+ *
763
+ * When enabled (default), a new request whose `requestKey` (default
764
+ * `HTTP_METHOD + path`) matches a still-pending request aborts the previous
765
+ * one — only the last duplicate executes.
766
+ *
767
+ * @example
768
+ * ```ts
769
+ * client.autoCancellation(false); // keep every request
770
+ * ```
771
+ */
772
+ autoCancellation(enable: boolean): this;
773
+ /**
774
+ * Abort a single pending request by its cancellation key
775
+ * (default `HTTP_METHOD + path`, e.g. `"GET /api/posts?page=1"`).
776
+ * The request rejects with an `ApiError` whose `isAbort` is `true`.
777
+ */
778
+ cancelRequest(requestKey: string): this;
779
+ /** Abort all pending requests. */
780
+ cancelAllRequests(): this;
580
781
  /** Check whether any superuser exists (for login vs setup screen routing). */
581
782
  checkSuperuser(): Promise<{
582
783
  has_superuser: boolean;
@@ -635,79 +836,6 @@ declare class LazypockClient {
635
836
  logout(): void;
636
837
  /** Ping the API health endpoint. */
637
838
  health(options?: RequestOptions): Promise<Record<string, unknown> | null>;
638
- /**
639
- * List all collections (admin).
640
- * @param q URL query string (e.g. `page=1&perPage=200`).
641
- * @param options Optional request options.
642
- */
643
- listCollections(q?: string, options?: RequestOptions): Promise<ListResult<ApiRecord> | null>;
644
- /**
645
- * Get a single collection by ID or name.
646
- * @param id Collection ID or name.
647
- * @param options Optional request options.
648
- */
649
- getCollection(id: string, options?: RequestOptions): Promise<ApiRecord | null>;
650
- /**
651
- * Create a new collection (admin).
652
- * @param data Collection definition (name, type, fields, options, rules, etc.).
653
- * @param options Optional request options.
654
- */
655
- createCollection(data: Record<string, unknown>, options?: RequestOptions): Promise<ApiRecord | null>;
656
- /**
657
- * Update an existing collection (admin).
658
- * @param id Collection ID or name.
659
- * @param data Updated collection fields.
660
- * @param options Optional request options.
661
- */
662
- updateCollection(id: string, data: Record<string, unknown>, options?: RequestOptions): Promise<ApiRecord | null>;
663
- /**
664
- * Delete a collection (admin).
665
- * @param id Collection ID or name.
666
- * @param options Optional request options.
667
- */
668
- deleteCollection(id: string, options?: RequestOptions): Promise<null>;
669
- /**
670
- * List records from a dynamic collection with optional filter/sort/pagination.
671
- *
672
- * @param coll Collection name.
673
- * @param params Query parameters including:
674
- * - `filter` — PocketBase filter syntax (e.g. `title~'hello' && published=true`)
675
- * - `sort` — Comma-separated, `-` prefix for DESC (e.g. `-created,title`)
676
- * - `page` — Page number (default: 1)
677
- * - `perPage` — Items per page (default: 30, max: 200)
678
- * - `expand` — Comma-separated relation fields (e.g. `author,category`)
679
- * @param options Optional request options.
680
- */
681
- listRecords(coll: string, params?: Record<string, string>, options?: RequestOptions): Promise<ListResult<ApiRecord> | null>;
682
- /**
683
- * Get a single record by ID.
684
- * @param coll Collection name.
685
- * @param id Record ID.
686
- * @param options Optional request options.
687
- */
688
- getRecord(coll: string, id: string, options?: RequestOptions): Promise<ApiRecord | null>;
689
- /**
690
- * Create a record in a dynamic collection.
691
- * @param coll Collection name.
692
- * @param data Record fields.
693
- * @param options Optional request options.
694
- */
695
- createRecord(coll: string, data: Record<string, unknown>, options?: RequestOptions): Promise<ApiRecord | null>;
696
- /**
697
- * Update a record in a dynamic collection.
698
- * @param coll Collection name.
699
- * @param id Record ID.
700
- * @param data Updated record fields.
701
- * @param options Optional request options.
702
- */
703
- updateRecord(coll: string, id: string, data: Record<string, unknown>, options?: RequestOptions): Promise<ApiRecord | null>;
704
- /**
705
- * Delete a record from a dynamic collection.
706
- * @param coll Collection name.
707
- * @param id Record ID.
708
- * @param options Optional request options.
709
- */
710
- deleteRecord(coll: string, id: string, options?: RequestOptions): Promise<null>;
711
839
  }
712
840
 
713
841
  /**
@@ -738,4 +866,4 @@ declare class TypedClient<TCollections extends LazypockCollections = LazypockCol
738
866
  */
739
867
  declare function createClient<TCollections extends LazypockCollections = LazypockCollections>(options: LazypockClientOptions): TypedClient<TCollections>;
740
868
 
741
- export { ApiError, type ApiRecord, type AuthModel, AuthStore, type CollectionSchema, CollectionService, type CreateData, type FileRecord, FilesService, LazypockClient, type LazypockClientOptions, type LazypockCollections, type ListResult, type RealtimeCallback, type RealtimeMessage, RealtimeService, type RecordShape, type RequestOptions, type SchemaField, type StorageAdapter, type SystemFields, TypedClient, type UpdateData, collectionTypeName, createClient, fieldTypeKind, fieldTypeScriptType, generateTypes, getFileUrl, schemaFieldType, wsUrlFromBaseUrl };
869
+ export { ApiError, type ApiRecord, type AuthModel, AuthStore, type CollectionSchema, CollectionService, type CollectionsMessage, CollectionsService, type CreateData, type FileRecord, FilesService, HttpClient, LazypockClient, type LazypockClientOptions, type LazypockCollections, type ListResult, type RealtimeCallback, type RealtimeMessage, RealtimeService, type RecordShape, type RequestOptions, type SchemaField, type StorageAdapter, type SystemFields, TypedClient, type UpdateData, collectionTypeName, createClient, fieldTypeKind, fieldTypeScriptType, generateTypes, getFileUrl, getScaleUrl, getThumbUrl, schemaFieldType, wsUrlFromBaseUrl };