lazypock 0.1.0 → 0.1.2

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/src/index.ts CHANGED
@@ -1,423 +1,44 @@
1
- // ── Lazypock SDK — Root Client ─────────────────────────
2
- // Usage:
3
- // const client = new LazypockClient({ baseUrl: 'http://localhost:4000/api' });
4
- // await client.authStore.init();
5
- // await client.login('admin@example.com', 'password');
6
- // const records = await client.collection('articles').list();
7
-
8
- import { HttpClient } from "./http";
9
- import {
10
- AuthStore,
11
- memoryStorage,
12
- type StorageAdapter,
13
- type AuthModel,
14
- } from "./auth";
15
- import { CollectionService } from "./collection";
16
- import {
17
- ApiError,
18
- type ApiRecord,
19
- type ListResult,
20
- type RequestOptions,
21
- } from "./types";
22
- import { RealtimeService, wsUrlFromBaseUrl } from "./realtime";
23
- import { FilesService, getFileUrl, type FileRecord } from "./files";
1
+ // ── Lazypock SDK — Public Entry ────────────────────────
2
+ //
3
+ // Re-exports everything from the LazypockClient module plus the
4
+ // typed-client factory. Keep this file a thin barrel so there are
5
+ // no circular imports.
24
6
 
25
7
  export {
8
+ // LazypockClient + options + everything it re-exports
26
9
  AuthStore,
27
10
  ApiError,
28
11
  RealtimeService,
29
12
  wsUrlFromBaseUrl,
30
13
  FilesService,
31
14
  getFileUrl,
32
- };
15
+ LazypockClient,
16
+ CollectionService,
17
+ generateTypes,
18
+ collectionTypeName,
19
+ fieldTypeScriptType,
20
+ fieldTypeKind,
21
+ schemaFieldType,
22
+ } from "./lazypock";
23
+ export { TypedClient, createClient } from "./client";
24
+
33
25
  export type {
26
+ // types
34
27
  StorageAdapter,
35
28
  AuthModel,
36
29
  ApiRecord,
37
30
  ListResult,
31
+ RecordShape,
32
+ CreateData,
33
+ UpdateData,
34
+ SystemFields,
38
35
  RequestOptions,
39
36
  FileRecord,
40
- };
41
-
42
- /** Options for constructing a {@link LazypockClient}. */
43
- export interface LazypockClientOptions {
44
- /** API base URL (e.g. 'http://localhost:4000/api') */
45
- baseUrl: string;
46
- /** Custom storage adapter (default: localStorage fallback) */
47
- storage?: StorageAdapter;
48
- /** Explicit auth store instance (for sharing across modules) */
49
- authStore?: AuthStore;
50
- /** Real-time service for Phoenix Channel WebSocket subscriptions */
51
- realtime?: RealtimeService;
52
- }
53
-
54
- /**
55
- * Lazypock API client.
56
- *
57
- * Provides methods for authentication, CRUD operations on dynamic collections,
58
- * file management, and real-time subscriptions.
59
- *
60
- * @example
61
- * ```ts
62
- * const client = new LazypockClient({ baseUrl: 'http://localhost:4000/api' });
63
- * await client.login('admin@example.com', 'password');
64
- * const posts = await client.collection('posts').list();
65
- * ```
66
- */
67
- export class LazypockClient {
68
- readonly http: HttpClient;
69
- readonly authStore: AuthStore;
70
- readonly realtime: RealtimeService;
71
- readonly files: FilesService;
72
- private collectionCache = new Map<string, CollectionService>();
73
-
74
- /**
75
- * Create a new Lazypock client.
76
- * @param options Configuration options.
77
- */
78
- constructor(options: LazypockClientOptions) {
79
- const baseUrl = options.baseUrl.replace(/\/+$/, "");
80
- this.authStore =
81
- options.authStore ?? new AuthStore(options.storage ?? memoryStorage);
82
- this.http = new HttpClient(baseUrl, this.authStore);
83
- this.realtime = options.realtime ?? new RealtimeService();
84
- this.files = new FilesService(this.http);
85
- }
86
-
87
- /**
88
- * Get or create a typed service for the given collection.
89
- * Services are cached after first access.
90
- *
91
- * @param name The collection name.
92
- * @returns A {@link CollectionService} instance.
93
- */
94
- collection(name: string): CollectionService {
95
- let svc = this.collectionCache.get(name);
96
- if (!svc) {
97
- svc = new CollectionService(this.http, name, this.authStore);
98
- this.collectionCache.set(name, svc);
99
- }
100
- return svc as unknown as CollectionService;
101
- }
102
-
103
- // ── Auth ──
104
-
105
- /** Check whether any superuser exists (for login vs setup screen routing). */
106
- async checkSuperuser(): Promise<{ has_superuser: boolean } | null> {
107
- return this.http.get<{ has_superuser: boolean }>("/superusers/check");
108
- }
109
-
110
- /**
111
- * Create the initial superuser account.
112
- * Only works when no superuser exists yet.
113
- * Stores the returned token in the auth store.
114
- * @param email Superuser email.
115
- * @param password Superuser password (min 8 chars).
116
- */
117
- async setup(
118
- email: string,
119
- password: string,
120
- ): Promise<({ token: string } & Record<string, unknown>) | null> {
121
- const data = await this.http.post<
122
- { token: string } & Record<string, unknown>
123
- >("/superusers/setup", { email, password });
124
- if (data) {
125
- this.authStore.setCollectionName(null);
126
- this.authStore.set(data.token, null);
127
- }
128
- return data;
129
- }
130
-
131
- /**
132
- * Authenticate as a superuser or auth collection user.
133
- *
134
- * When `collection` is provided, authenticates against
135
- * `/{collection}/auth-with-password`. Otherwise logs in as superuser.
136
- * Stores the returned token in the auth store.
137
- *
138
- * @param email User email or identity.
139
- * @param password User password.
140
- * @param collection Optional auth collection name.
141
- */
142
- async login(
143
- email: string,
144
- password: string,
145
- collection?: string,
146
- ): Promise<({ token: string } & Record<string, unknown>) | null> {
147
- let data;
148
- if (collection) {
149
- data = await this.http.post<
150
- { token: string; record: Record<string, unknown> } & Record<
151
- string,
152
- unknown
153
- >
154
- >("/" + encodeURIComponent(collection) + "/auth-with-password", {
155
- identity: email,
156
- password,
157
- });
158
- if (data && data.record) {
159
- this.authStore.setCollectionName(collection);
160
- this.authStore.set(data.token, data.record as unknown as AuthModel);
161
- }
162
- } else {
163
- data = await this.http.post<{ token: string } & Record<string, unknown>>(
164
- "/superusers/login",
165
- { email, password },
166
- );
167
- if (data) {
168
- this.authStore.setCollectionName(null);
169
- this.authStore.set(data.token, null);
170
- }
171
- }
172
- return data;
173
- }
174
-
175
- /** Fetch the current superuser profile and refresh the auth model. */
176
- async me<T = ApiRecord>(options?: RequestOptions): Promise<T | null> {
177
- const data = await this.http.get<T>("/superusers/me", options);
178
- if (data) {
179
- // Update the auth model with fresh data
180
- this.authStore.set(this.authStore.token, data as unknown as AuthModel);
181
- }
182
- return data;
183
- }
184
-
185
- /**
186
- * Authenticate against an auth collection with email/password.
187
- * Stores the returned token and user record in the auth store.
188
- *
189
- * @param collection The auth collection name.
190
- * @param identity Email or username.
191
- * @param password Password.
192
- * @param options Optional request options.
193
- */
194
- async authWithPassword(
195
- collection: string,
196
- identity: string,
197
- password: string,
198
- options?: RequestOptions,
199
- ): Promise<
200
- ({ token: string; record: ApiRecord } & Record<string, unknown>) | null
201
- > {
202
- const data = await this.http.post<
203
- { token: string; record: ApiRecord } & Record<string, unknown>
204
- >(
205
- "/" + encodeURIComponent(collection) + "/auth-with-password",
206
- { identity, password },
207
- options,
208
- );
209
- if (data) {
210
- this.authStore.setCollectionName(collection);
211
- this.authStore.set(data.token, data.record as unknown as AuthModel);
212
- }
213
- return data;
214
- }
215
-
216
- /**
217
- * Refresh an auth collection token.
218
- * Uses the currently stored auth token.
219
- *
220
- * @param collection The auth collection name.
221
- * @param options Optional request options.
222
- */
223
- async authRefresh(
224
- collection: string,
225
- options?: RequestOptions,
226
- ): Promise<
227
- ({ token: string; record: ApiRecord } & Record<string, unknown>) | null
228
- > {
229
- const data = await this.http.post<
230
- { token: string; record: ApiRecord } & Record<string, unknown>
231
- >(
232
- "/" + encodeURIComponent(collection) + "/auth-refresh",
233
- undefined,
234
- options,
235
- );
236
- if (data) {
237
- this.authStore.setCollectionName(collection);
238
- this.authStore.set(data.token, data.record as unknown as AuthModel);
239
- }
240
- return data;
241
- }
242
-
243
- /** Clear the current auth state and remove persisted tokens. */
244
- logout(): void {
245
- this.authStore.clear();
246
- }
247
-
248
- // ── Health ──
249
-
250
- /** Ping the API health endpoint. */
251
- health(options?: RequestOptions): Promise<Record<string, unknown> | null> {
252
- return this.http.get<Record<string, unknown>>("/health", options);
253
- }
254
-
255
- // ── Collection Management (admin) ──
256
-
257
- /**
258
- * List all collections (admin).
259
- * @param q URL query string (e.g. `page=1&perPage=200`).
260
- * @param options Optional request options.
261
- */
262
- listCollections(
263
- q?: string,
264
- options?: RequestOptions,
265
- ): Promise<ListResult<ApiRecord> | null> {
266
- return this.http.get<ListResult<ApiRecord>>(
267
- "/collections" + (q ? "?" + q : ""),
268
- options,
269
- );
270
- }
271
-
272
- /**
273
- * Get a single collection by ID or name.
274
- * @param id Collection ID or name.
275
- * @param options Optional request options.
276
- */
277
- getCollection(
278
- id: string,
279
- options?: RequestOptions,
280
- ): Promise<ApiRecord | null> {
281
- return this.http.get<ApiRecord>(
282
- "/collections/" + encodeURIComponent(id),
283
- options,
284
- );
285
- }
286
-
287
- /**
288
- * Create a new collection (admin).
289
- * @param data Collection definition (name, type, fields, options, rules, etc.).
290
- * @param options Optional request options.
291
- */
292
- createCollection(
293
- data: Record<string, unknown>,
294
- options?: RequestOptions,
295
- ): Promise<ApiRecord | null> {
296
- return this.http.post<ApiRecord>("/collections", data, options);
297
- }
298
-
299
- /**
300
- * Update an existing collection (admin).
301
- * @param id Collection ID or name.
302
- * @param data Updated collection fields.
303
- * @param options Optional request options.
304
- */
305
- updateCollection(
306
- id: string,
307
- data: Record<string, unknown>,
308
- options?: RequestOptions,
309
- ): Promise<ApiRecord | null> {
310
- return this.http.patch<ApiRecord>(
311
- "/collections/" + encodeURIComponent(id),
312
- data,
313
- options,
314
- );
315
- }
316
-
317
- /**
318
- * Delete a collection (admin).
319
- * @param id Collection ID or name.
320
- * @param options Optional request options.
321
- */
322
- deleteCollection(id: string, options?: RequestOptions): Promise<null> {
323
- return this.http.delete("/collections/" + encodeURIComponent(id), options);
324
- }
325
-
326
- // ── Records (dynamic collection) ──
327
-
328
- /**
329
- * List records from a dynamic collection with optional filter/sort/pagination.
330
- *
331
- * @param coll Collection name.
332
- * @param params Query parameters including:
333
- * - `filter` — PocketBase filter syntax (e.g. `title~'hello' && published=true`)
334
- * - `sort` — Comma-separated, `-` prefix for DESC (e.g. `-created,title`)
335
- * - `page` — Page number (default: 1)
336
- * - `perPage` — Items per page (default: 30, max: 200)
337
- * - `expand` — Comma-separated relation fields (e.g. `author,category`)
338
- * @param options Optional request options.
339
- */
340
- listRecords(
341
- coll: string,
342
- params?: Record<string, string>,
343
- options?: RequestOptions,
344
- ): Promise<ListResult<ApiRecord> | null> {
345
- const qs = params ? "?" + new URLSearchParams(params).toString() : "";
346
- return this.http.get<ListResult<ApiRecord>>(
347
- "/" + encodeURIComponent(coll) + qs,
348
- options,
349
- );
350
- }
351
-
352
- /**
353
- * Get a single record by ID.
354
- * @param coll Collection name.
355
- * @param id Record ID.
356
- * @param options Optional request options.
357
- */
358
- getRecord(
359
- coll: string,
360
- id: string,
361
- options?: RequestOptions,
362
- ): Promise<ApiRecord | null> {
363
- return this.http.get<ApiRecord>(
364
- "/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
365
- options,
366
- );
367
- }
368
-
369
- /**
370
- * Create a record in a dynamic collection.
371
- * @param coll Collection name.
372
- * @param data Record fields.
373
- * @param options Optional request options.
374
- */
375
- createRecord(
376
- coll: string,
377
- data: Record<string, unknown>,
378
- options?: RequestOptions,
379
- ): Promise<ApiRecord | null> {
380
- return this.http.post<ApiRecord>(
381
- "/" + encodeURIComponent(coll),
382
- data,
383
- options,
384
- );
385
- }
386
-
387
- /**
388
- * Update a record in a dynamic collection.
389
- * @param coll Collection name.
390
- * @param id Record ID.
391
- * @param data Updated record fields.
392
- * @param options Optional request options.
393
- */
394
- updateRecord(
395
- coll: string,
396
- id: string,
397
- data: Record<string, unknown>,
398
- options?: RequestOptions,
399
- ): Promise<ApiRecord | null> {
400
- return this.http.patch<ApiRecord>(
401
- "/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
402
- data,
403
- options,
404
- );
405
- }
406
-
407
- /**
408
- * Delete a record from a dynamic collection.
409
- * @param coll Collection name.
410
- * @param id Record ID.
411
- * @param options Optional request options.
412
- */
413
- deleteRecord(
414
- coll: string,
415
- id: string,
416
- options?: RequestOptions,
417
- ): Promise<null> {
418
- return this.http.delete(
419
- "/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
420
- options,
421
- );
422
- }
423
- }
37
+ // schema
38
+ CollectionSchema,
39
+ SchemaField,
40
+ // options
41
+ LazypockClientOptions,
42
+ } from "./lazypock";
43
+ export type { LazypockCollections } from "./client";
44
+ export type { RealtimeMessage, RealtimeCallback } from "./collection";