lazypock 0.2.0 → 0.3.0

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 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/http.ts","../src/auth.ts","../src/collection.ts","../src/realtime.ts","../src/files.ts","../src/collections.ts","../src/typegen.ts","../src/codegen.ts","../src/lazypock.ts","../src/client.ts"],"sourcesContent":["// ── Lazypock SDK — Public Entry ────────────────────────\n//\n// Re-exports everything from the LazypockClient module plus the\n// typed-client factory. Keep this file a thin barrel so there are\n// no circular imports.\n\nexport {\n\t// LazypockClient + options + everything it re-exports\n\tAuthStore,\n\tApiError,\n\tHttpClient,\n\tRealtimeService,\n\twsUrlFromBaseUrl,\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\tLazypockClient,\n\tCollectionService,\n\tCollectionsService,\n\tgenerateTypes,\n\tcollectionTypeName,\n\tfieldTypeScriptType,\n\tfieldTypeKind,\n\tschemaFieldType,\n} from \"./lazypock\";\nexport { TypedClient, createClient } from \"./client\";\n\nexport type {\n\t// types\n\tStorageAdapter,\n\tAuthModel,\n\tApiRecord,\n\tListResult,\n\tRecordShape,\n\tCreateData,\n\tUpdateData,\n\tSystemFields,\n\tRequestOptions,\n\tFileRecord,\n\t// schema\n\tCollectionSchema,\n\tSchemaField,\n\t// options\n\tLazypockClientOptions,\n} from \"./lazypock\";\nexport type { LazypockCollections } from \"./client\";\nexport type { RealtimeMessage, RealtimeCallback } from \"./collection\";\nexport type { CollectionsMessage } from \"./collections\";\n","// ── Record & Collection types ───────────────────────────\n\n/**\n * Base shape every record returned from any collection satisfies.\n * Generated record interfaces extend this.\n */\nexport interface BaseRecordFields {\n\tid: string;\n\tcollectionId: string;\n\tcollectionName: string;\n\tcreated: string;\n\tupdated: string;\n}\n\n/** Shape of a record returned from any collection. */\nexport interface ApiRecord extends BaseRecordFields {\n\t[key: string]: unknown;\n}\n\n/**\n * Structural marker for concrete record shapes (generated or hand-written).\n * Used to differentiate a typed collection service from the untyped default.\n */\nexport type RecordShape = Record<string, unknown>;\n\n/** System fields every record carries — not user-provided on create. */\nexport type SystemFields =\n\t| \"id\"\n\t| \"collectionId\"\n\t| \"collectionName\"\n\t| \"created\"\n\t| \"updated\";\n\n/**\n * Data accepted by `create()`: any subset of `T`'s fields, but\n * never the system fields. Unknown/extra keys are rejected at compile\n * time via excess-property checking (object literals).\n */\nexport type CreateData<T> = Partial<Omit<T, SystemFields>>;\n\n/**\n * Data accepted by `update()`: any subset of `T`'s fields.\n * Unknown/extra keys are rejected at compile time.\n */\nexport type UpdateData<T> = Partial<Omit<T, SystemFields>>;\n\n/** Paginated list response matching PocketBase format. */\nexport interface ListResult<T = ApiRecord> {\n\titems: T[];\n\tpage: number;\n\tperPage: number;\n\ttotalItems: number;\n\ttotalPages: number;\n}\n\n/** HTTP method supported by the client. */\nexport type Method = \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n\nexport interface RequestOptions {\n\t/** Search/filter params */\n\tparams?: Record<string, string>;\n\t/** Raw request headers to merge */\n\theaders?: Record<string, string>;\n\t/** Abort signal */\n\tsignal?: AbortSignal;\n\t/** Custom fetch implementation (for RN or test mocking) */\n\tfetch?: typeof globalThis.fetch;\n\t/**\n\t * Request identifier used by the auto-cancellation mechanism.\n\t *\n\t * Pending requests sharing the same key cancel each other — only the\n\t * last one is executed (PocketBase `requestKey` semantics).\n\t *\n\t * - `string` — use this exact key instead of the default `METHOD + path`.\n\t * - `null` — disable auto-cancellation for this request (never auto-cancelled).\n\t *\n\t * @default `${method} ${path}`\n\t */\n\trequestKey?: string | null;\n\t/**\n\t * Disable auto-cancellation for this request.\n\t * Alias of `requestKey: null` (PocketBase `$autoCancel: false` compat).\n\t */\n\tautoCancel?: boolean;\n\t/**\n\t * Custom request key used for auto-cancellation.\n\t * Alias of `requestKey` (PocketBase `$cancelKey` compat).\n\t */\n\tcancelKey?: string;\n}\n\nexport class ApiError extends Error {\n\treadonly data: unknown;\n\treadonly status: number;\n\t/**\n\t * `true` when this error was caused by an aborted/cancelled request\n\t * (auto-cancelled duplicate, or manually via `cancelRequest()` /\n\t * `cancelAllRequests()` / an external AbortSignal).\n\t */\n\treadonly isAbort: boolean;\n\n\tconstructor(message: string, data: unknown, status: number, isAbort = false) {\n\t\tsuper(message);\n\t\tthis.name = \"ApiError\";\n\t\tthis.data = data;\n\t\tthis.status = status;\n\t\tthis.isAbort = isAbort;\n\t}\n}\n","// ── HTTP Client ─────────────────────────────────────────\n// Only relies on globalThis.fetch — works in browser, React Native, and Node 18+\n\nimport { ApiError, type Method, type RequestOptions } from \"./types\";\nimport type { AuthStore } from \"./auth\";\n\n/**\n * Low-level HTTP client wrapping `fetch` with automatic auth token injection.\n * Only relies on `globalThis.fetch` — works in browser, React Native, and Node 18+.\n */\n/** Detect whether an unknown thrown value is an abort/`AbortError`-style error. */\nfunction isAbortError(err: unknown): boolean {\n\treturn (\n\t\terr instanceof Error &&\n\t\t(err.name === \"AbortError\" || err.message === \"Aborted\")\n\t);\n}\n\nexport class HttpClient {\n\tprivate baseUrl: string;\n\tprivate authStore: AuthStore;\n\tprivate defaultFetch: typeof globalThis.fetch;\n\n\t/**\n\t * Abort controllers for in-flight requests, keyed by their cancellation key\n\t * (default `METHOD path`). A new request with the same key aborts the\n\t * previous one — PocketBase-style auto-cancellation of duplicated requests.\n\t */\n\tprivate cancelControllers: Record<string, AbortController> = {};\n\n\t/** Global toggle for the auto-cancellation behaviour (default: on). */\n\tprivate enableAutoCancellation = true;\n\n\t/**\n\t * @param baseUrl The API base URL (e.g. `http://localhost:4000/api`). Trailing slash stripped.\n\t * @param authStore The auth store providing the token for Authorization headers.\n\t */\n\tconstructor(baseUrl: string, authStore: AuthStore) {\n\t\tthis.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.authStore = authStore;\n\t\tthis.defaultFetch = globalThis.fetch.bind(globalThis);\n\t}\n\n\tprivate async refreshAuth(): Promise<{\n\t\ttoken: string;\n\t\trecord: Record<string, unknown>;\n\t} | null> {\n\t\tconst collection = this.authStore.collectionName;\n\t\tif (!collection) return null;\n\t\ttry {\n\t\t\tconst url =\n\t\t\t\tthis.baseUrl + \"/\" + encodeURIComponent(collection) + \"/auth-refresh\";\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t};\n\t\t\tif (this.authStore.token) {\n\t\t\t\theaders[\"Authorization\"] = \"Bearer \" + this.authStore.token;\n\t\t\t}\n\t\t\tconst res = await this.defaultFetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t});\n\t\t\tif (!res.ok) {\n\t\t\t\tthis.authStore.clear();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst data = (await res.json()) as Record<string, unknown>;\n\t\t\tif (data && typeof data.token === \"string\") {\n\t\t\t\tthis.authStore.set(\n\t\t\t\t\tdata.token,\n\t\t\t\t\t(data.record as Record<string, unknown> as any) ?? null,\n\t\t\t\t);\n\t\t\t\treturn data as { token: string; record: Record<string, unknown> };\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Globally enable or disable auto-cancellation of duplicated pending requests.\n\t * Fluent — returns `this` for chaining.\n\t */\n\tautoCancellation(enable: boolean): this {\n\t\tthis.enableAutoCancellation = !!enable;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Abort a pending request identified by its cancellation key\n\t * (default `METHOD path`, e.g. `\"GET /api/posts\"`). No-op if not pending.\n\t */\n\tcancelRequest(requestKey: string): this {\n\t\tconst controller = this.cancelControllers[requestKey];\n\t\tif (controller) {\n\t\t\tcontroller.abort();\n\t\t\tdelete this.cancelControllers[requestKey];\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Abort all pending requests. */\n\tcancelAllRequests(): this {\n\t\tfor (const key in this.cancelControllers) {\n\t\t\tthis.cancelControllers[key].abort();\n\t\t}\n\t\tthis.cancelControllers = {};\n\t\treturn this;\n\t}\n\n\t/**\n\t * Make an HTTP request with automatic auth token injection and optional auto-refresh.\n\t *\n\t * Auto-cancellation: a request keyed by `options.requestKey` (default\n\t * `METHOD path`) aborts any previous pending request with the same key,\n\t * so only the last duplicate executes. Set `requestKey: null` or\n\t * `autoCancel: false` to opt out per request.\n\t *\n\t * @param method HTTP method.\n\t * @param path URL path (appended to baseUrl).\n\t * @param body JSON-serializable body, or FormData for file uploads.\n\t * @param options Optional request options.\n\t * @returns Parsed JSON response, or null for 204 No Content.\n\t * @throws {ApiError} On non-2xx responses or when the request is aborted\n\t * (aborted requests throw an `ApiError` with `isAbort === true`).\n\t */\n\tasync request<T = unknown>(\n\t\tmethod: Method,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\t// Auto-refresh if token is expired\n\t\tif (this.authStore.isExpired && this.authStore.collectionName) {\n\t\t\tawait this.refreshAuth();\n\t\t}\n\n\t\t// Resolve the auto-cancellation key (PocketBase `requestKey` semantics):\n\t\t// - options.requestKey null → disabled for this request\n\t\t// - options.requestKey string → use it verbatim\n\t\t// - options.autoCancel false → disabled (legacy compat)\n\t\t// - options.cancelKey string → use it verbatim (legacy compat)\n\t\t// - otherwise → default to `${method} ${path}`\n\t\tlet requestKey: string | null =\n\t\t\toptions?.requestKey === undefined\n\t\t\t\t? (options?.cancelKey ?? `${method} ${path}`)\n\t\t\t\t: options.requestKey;\n\t\tif (options?.autoCancel === false) requestKey = null;\n\n\t\t// Wire a fresh AbortController for this request, merging any caller signal.\n\t\t// When auto-cancellation is enabled, the previous pending request sharing\n\t\t// our key is aborted first (only the last duplicate executes).\n\t\tlet controller: AbortController | null = null;\n\t\tconst externalSignal = options?.signal;\n\t\tif (requestKey !== null) {\n\t\t\tif (this.enableAutoCancellation) {\n\t\t\t\tthis.cancelRequest(requestKey);\n\t\t\t}\n\t\t\tcontroller = new AbortController();\n\t\t\tthis.cancelControllers[requestKey] = controller;\n\t\t\tif (externalSignal?.aborted) {\n\t\t\t\tcontroller.abort();\n\t\t\t} else if (externalSignal) {\n\t\t\t\texternalSignal.addEventListener(\"abort\", () => controller?.abort(), {\n\t\t\t\t\tonce: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tconst signal = controller?.signal ?? externalSignal;\n\n\t\tlet url = this.baseUrl + path;\n\t\tif (options?.params) {\n\t\t\tconst qs = new URLSearchParams(options.params).toString();\n\t\t\tif (qs) {\n\t\t\t\turl += (path.includes(\"?\") ? \"&\" : \"?\") + qs;\n\t\t\t}\n\t\t}\n\t\tconst headers: Record<string, string> = {\n\t\t\t...options?.headers,\n\t\t};\n\n\t\t// Don't set Content-Type for FormData (browser sets multipart boundary)\n\t\tif (!(body instanceof FormData)) {\n\t\t\theaders[\"Content-Type\"] = \"application/json\";\n\t\t}\n\n\t\tif (this.authStore.token) {\n\t\t\theaders[\"Authorization\"] = \"Bearer \" + this.authStore.token;\n\t\t}\n\n\t\tconst init: RequestInit = {\n\t\t\tmethod,\n\t\t\theaders,\n\t\t\tsignal,\n\t\t};\n\n\t\tif (body != null && method !== \"GET\" && method !== \"DELETE\") {\n\t\t\tif (body instanceof FormData) {\n\t\t\t\tinit.body = body;\n\t\t\t} else {\n\t\t\t\tinit.body = JSON.stringify(body);\n\t\t\t}\n\t\t}\n\n\t\tlet res: Response | null = null;\n\t\tconst fetcher = options?.fetch ?? this.defaultFetch;\n\t\ttry {\n\t\t\tres = await fetcher(url, init);\n\t\t} catch (err) {\n\t\t\t// Aborted (auto-cancelled duplicate, manual cancel, or external signal)\n\t\t\t// → normalized ApiError with isAbort === true, like PocketBase.\n\t\t\tif (isAbortError(err)) {\n\t\t\t\tthrow new ApiError(\n\t\t\t\t\t\"The request was aborted (most likely auto-cancelled by a newer request with the same requestKey)\",\n\t\t\t\t\t{},\n\t\t\t\t\t0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\t// The request has settled — no longer pending, so drop the controller\n\t\t\t// unless a newer request already replaced it (same key).\n\t\t\tif (\n\t\t\t\trequestKey !== null &&\n\t\t\t\tthis.cancelControllers[requestKey] === controller\n\t\t\t) {\n\t\t\t\tdelete this.cancelControllers[requestKey];\n\t\t\t}\n\t\t}\n\n\t\tif (res!.status === 204) return null;\n\n\t\t// Safely parse JSON — some errored responses may have empty or non-JSON bodies\n\t\tlet bodyText = \"\";\n\t\tlet data: Record<string, unknown> = {};\n\t\ttry {\n\t\t\tbodyText = await res.text();\n\t\t\tif (bodyText) {\n\t\t\t\tdata = JSON.parse(bodyText) as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not JSON — keep data as empty object\n\t\t}\n\n\t\tif (!res!.ok) {\n\t\t\tthrow new ApiError(\n\t\t\t\t(typeof data.message === \"string\" ? data.message : res!.statusText) ||\n\t\t\t\t\t`Request failed with status ${res!.status}`,\n\t\t\t\tdata,\n\t\t\t\tres!.status,\n\t\t\t);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t/**\n\t * HTTP GET.\n\t * @param path URL path.\n\t * @param options Optional request options.\n\t */\n\tget<T = unknown>(path: string, options?: RequestOptions): Promise<T | null> {\n\t\treturn this.request<T>(\"GET\", path, undefined, options);\n\t}\n\n\t/**\n\t * HTTP POST.\n\t * @param path URL path.\n\t * @param body Optional request body.\n\t * @param options Optional request options.\n\t */\n\tpost<T = unknown>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"POST\", path, body, options);\n\t}\n\n\t/**\n\t * HTTP PATCH.\n\t * @param path URL path.\n\t * @param body Optional request body.\n\t * @param options Optional request options.\n\t */\n\tpatch<T = unknown>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"PATCH\", path, body, options);\n\t}\n\n\t/**\n\t * HTTP DELETE.\n\t * @param path URL path.\n\t * @param options Optional request options.\n\t */\n\tdelete<T = unknown>(\n\t\tpath: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"DELETE\", path, undefined, options);\n\t}\n}\n","// ── Auth Store ──────────────────────────────────────────\n// Pluggable storage adapter: swap for AsyncStorage on RN, localStorage on web, etc.\n\n/**\n * Interface for pluggable persistence backends.\n * Swap for `AsyncStorage` on React Native, `localStorage` on web, etc.\n */\nexport interface StorageAdapter {\n\t/** Retrieve a stored value by key. */\n\tget(key: string): string | null | Promise<string | null>;\n\t/** Persist a key-value pair. */\n\tset(key: string, value: string): void | Promise<void>;\n\t/** Remove a stored value by key. */\n\tremove(key: string): void | Promise<void>;\n}\n\n/** Shape of an authenticated user record (from auth collections). */\nexport interface AuthModel {\n\tid: string;\n\t[key: string]: unknown;\n}\n\n/** Callback signature for auth state changes. */\nexport type AuthListener = (model: AuthModel | null, token: string) => void;\n\n// Server token TTL: 7 days (matches Phoenix.Token max_age)\nconst TOKEN_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport class AuthStore {\n\tprivate _token = \"\";\n\tprivate _model: AuthModel | null = null;\n\tprivate _tokenExpiresAt: number | null = null;\n\tprivate _collectionName: string | null = null;\n\tprivate listeners = new Set<AuthListener>();\n\tprivate storage: StorageAdapter;\n\n\t/**\n\t * Create an AuthStore with optional custom storage adapter.\n\t * @param storage Persistence backend. Defaults to `memoryStorage` (localStorage fallback).\n\t */\n\tconstructor(storage?: StorageAdapter) {\n\t\tthis.storage = storage ?? {\n\t\t\tget: (_key: string) => null,\n\t\t\tset: () => {},\n\t\t\tremove: () => {},\n\t\t};\n\t}\n\n\t/** The current JWT token string, or empty string if not authenticated. */\n\tget token(): string {\n\t\treturn this._token;\n\t}\n\n\t/** The current authenticated user record, or null. */\n\tget model(): AuthModel | null {\n\t\treturn this._model;\n\t}\n\n\t/** Whether a token exists (does not check expiry). */\n\tget isValid(): boolean {\n\t\treturn !!this._token;\n\t}\n\n\t/**\n\t * Whether the current token has expired (with a 30-second buffer).\n\t * Returns false when no expiry has been recorded (e.g. superuser tokens).\n\t */\n\tget isExpired(): boolean {\n\t\treturn (\n\t\t\tthis._tokenExpiresAt !== null &&\n\t\t\tDate.now() >= this._tokenExpiresAt - 30000\n\t\t);\n\t}\n\n\t/** The auth collection name used for automatic token refresh. */\n\tget collectionName(): string | null {\n\t\treturn this._collectionName;\n\t}\n\n\t/**\n\t * Set the auth collection name (used internally by auto-refresh).\n\t * @param name The collection name, or null for superuser tokens.\n\t */\n\tsetCollectionName(name: string | null): void {\n\t\tthis._collectionName = name;\n\t}\n\n\t/**\n\t * Load persisted auth state from storage.\n\t * Should be called once at application startup.\n\t */\n\tasync init(): Promise<void> {\n\t\tconst [token, model, expiresAt] = await Promise.all([\n\t\t\tthis.storage.get(\"auth_token\"),\n\t\t\tthis.storage.get(\"auth_model\"),\n\t\t\tthis.storage.get(\"auth_expires_at\"),\n\t\t]);\n\t\tif (token) this._token = token;\n\t\tif (expiresAt) this._tokenExpiresAt = parseInt(expiresAt, 10) || null;\n\t\tif (model) {\n\t\t\ttry {\n\t\t\t\tthis._model = JSON.parse(model);\n\t\t\t} catch {\n\t\t\t\t// ignore corrupt data\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Update the current auth token and model, persist to storage, and notify listeners.\n\t * @param token The JWT token string.\n\t * @param model The authenticated user record, or null for superusers.\n\t */\n\tset(token: string, model: AuthModel | null): void {\n\t\tthis._token = token;\n\t\tthis._model = model;\n\t\tthis._tokenExpiresAt = Date.now() + TOKEN_TTL_MS;\n\t\tvoid Promise.all([\n\t\t\tthis.storage.set(\"auth_token\", token),\n\t\t\tthis.storage.set(\"auth_expires_at\", String(this._tokenExpiresAt)),\n\t\t\tmodel\n\t\t\t\t? this.storage.set(\"auth_model\", JSON.stringify(model))\n\t\t\t\t: this.storage.remove(\"auth_model\"),\n\t\t]);\n\t\tthis.notify();\n\t}\n\n\t/**\n\t * Clear all auth state (token, model, expiry) and notify listeners.\n\t */\n\tclear(): void {\n\t\tthis._token = \"\";\n\t\tthis._model = null;\n\t\tthis._tokenExpiresAt = null;\n\t\tthis._collectionName = null;\n\t\tvoid Promise.all([\n\t\t\tthis.storage.remove(\"auth_token\"),\n\t\t\tthis.storage.remove(\"auth_expires_at\"),\n\t\t\tthis.storage.remove(\"auth_model\"),\n\t\t]);\n\t\tthis.notify();\n\t}\n\n\t/**\n\t * Register a listener for auth state changes.\n\t * @param fn Callback invoked with (model, token) on every change.\n\t * @returns An unsubscribe function.\n\t */\n\tonChange(fn: AuthListener): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\tprivate notify(): void {\n\t\tfor (const fn of this.listeners) {\n\t\t\tfn(this._model, this._token);\n\t\t}\n\t}\n}\n\n// ── Memory-only storage (default, works everywhere) ─────\n/** Default storage adapter using `localStorage` with graceful fallback. */\nexport const memoryStorage: StorageAdapter = {\n\tget(key: string) {\n\t\ttry {\n\t\t\treturn localStorage.getItem(key);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t},\n\tset(key: string, value: string) {\n\t\ttry {\n\t\t\tlocalStorage.setItem(key, value);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t},\n\tremove(key: string) {\n\t\ttry {\n\t\t\tlocalStorage.removeItem(key);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t},\n};\n","// ── Collection Service ──────────────────────────────────\n// Typed CRUD for a single collection (like PocketBase's pb.collection(name))\n\nimport type { HttpClient } from \"./http\";\nimport type { AuthStore, AuthModel } from \"./auth\";\nimport type {\n\tApiRecord,\n\tListResult,\n\tRequestOptions,\n\tCreateData,\n\tUpdateData,\n} from \"./types\";\nimport type { RealtimeService } from \"./realtime\";\n\n/**\n * A realtime record-change event delivered to subscription callbacks.\n * Mirrors PocketBase's RealtimeService result shape (`action` + `record`).\n */\nexport interface RealtimeMessage {\n\taction: \"create\" | \"update\" | \"delete\";\n\trecord: Record<string, unknown>;\n\ttopic?: string;\n}\n\n/** Subscription callback for a collection's realtime events. */\nexport type RealtimeCallback = (e: RealtimeMessage) => void;\n\n/** Raw event passed by the low-level realtime service. */\ninterface RealtimeEventLike {\n\tevent: string;\n\ttopic: string;\n\tpayload?: Record<string, unknown>;\n}\n\n/** Map a raw event/action to a normalised create/update/delete action. */\nfunction normalizeAction(\n\tevent: string,\n\trawAction?: unknown,\n): RealtimeMessage[\"action\"] {\n\tif (typeof rawAction === \"string\") {\n\t\tconst a = rawAction.toLowerCase();\n\t\tif (a === \"create\" || a === \"update\" || a === \"delete\") {\n\t\t\treturn a;\n\t\t}\n\t}\n\tif (event === \"record_change\") return \"update\";\n\tif (event === \"create\" || event === \"record_create\") return \"create\";\n\tif (event === \"delete\" || event === \"record_delete\") return \"delete\";\n\treturn \"update\";\n}\n\n/**\n * Typed CRUD service for a single dynamic collection.\n * Get an instance via {@link LazypockClient.collection}.\n *\n * @typeParam T — The record shape for this collection. Defaults to {@link ApiRecord}.\n */\nexport class CollectionService<T = ApiRecord> {\n\tprivate http: HttpClient;\n\tprivate collectionName: string;\n\tprivate authStore?: AuthStore;\n\tprivate realtime?: RealtimeService;\n\n\t/** @internal */\n\tconstructor(\n\t\thttp: HttpClient,\n\t\tcollectionName: string,\n\t\tauthStore?: AuthStore,\n\t\trealtime?: RealtimeService,\n\t) {\n\t\tthis.http = http;\n\t\tthis.collectionName = collectionName;\n\t\tthis.authStore = authStore;\n\t\tthis.realtime = realtime;\n\t}\n\n\tprivate encodeId(id: string): string {\n\t\treturn encodeURIComponent(id);\n\t}\n\n\t/**\n\t * Fetch a paginated list of records (PocketBase `getList`).\n\t *\n\t * @param page Page number (default 1).\n\t * @param perPage Records per page (default 30).\n\t * @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.\n\t */\n\tgetList<T2 = T>(\n\t\tpage = 1,\n\t\tperPage = 30,\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<ListResult<T2> | null> {\n\t\tconst { requestKey, autoCancel, cancelKey, ...rest } = options ?? {};\n\t\tconst qs = new URLSearchParams(\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.entries({\n\t\t\t\t\tpage: String(page),\n\t\t\t\t\tperPage: String(perPage),\n\t\t\t\t\t...rest,\n\t\t\t\t}).map(([k, v]) => [k, String(v)]),\n\t\t\t),\n\t\t).toString();\n\t\treturn this.http.get<ListResult<T2>>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"?\" + qs,\n\t\t\t{ requestKey, autoCancel, cancelKey },\n\t\t);\n\t}\n\n\t/**\n\t * Fetch all records at once (auto-paginates). Mirrors PocketBase's\n\t * `pb.collection(name).getFullList()`.\n\t *\n\t * @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.\n\t */\n\tasync getFullList<T2 = T>(\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<Array<T2>> {\n\t\tconst { batch = 1000, ...rest } = options ?? {};\n\t\tconst items: T2[] = [];\n\t\tlet page = 1;\n\t\tfor (;;) {\n\t\t\tconst res = await this.getList<T2>(\n\t\t\t\tpage,\n\t\t\t\tbatch as number,\n\t\t\t\t{\n\t\t\t\t\t// disable auto-cancellation across pages — each page request is unique\n\t\t\t\t\t...rest,\n\t\t\t\t\trequestKey: null,\n\t\t\t\t} as Record<string, unknown> & RequestOptions,\n\t\t\t);\n\t\t\tif (!res || !res.items || res.items.length === 0) break;\n\t\t\titems.push(...(res.items as T2[]));\n\t\t\tif (page >= (res.totalPages ?? page)) break;\n\t\t\tpage += 1;\n\t\t}\n\t\treturn items;\n\t}\n\n\t/**\n\t * Fetch the first record matching a filter (PocketBase `getFirstListItem`).\n\t *\n\t * @param filter Filter expression (e.g. `title = 'x'`).\n\t * @param options Optional request options.\n\t */\n\tasync getFirstListItem<T2 = T>(\n\t\tfilter: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T2 | null> {\n\t\tconst res = await this.getList<T2>(1, 1, {\n\t\t\t...options,\n\t\t\tfilter,\n\t\t});\n\t\treturn res?.items?.[0] ?? null;\n\t}\n\n\t/**\n\t * Get a single record by ID.\n\t * @param id Record ID.\n\t * @param options Optional request options.\n\t */\n\tgetOne(id: string, options?: RequestOptions): Promise<T | null> {\n\t\treturn this.http.get<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new record.\n\t * @param data Record fields. When `T` is a concrete shape (e.g. a generated\n\t * record type), excess/unknown fields are rejected at compile time.\n\t * @param options Optional request options.\n\t */\n\tcreate(\n\t\tdata: T extends ApiRecord ? Record<string, unknown> : CreateData<T>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http.post<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName),\n\t\t\tdata,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Update a record by ID.\n\t * @param id Record ID.\n\t * @param data Updated record fields. When `T` is a concrete shape, `data`\n\t * must be a partial of `T` — unknown fields are rejected.\n\t * @param options Optional request options.\n\t */\n\tupdate(\n\t\tid: string,\n\t\tdata: T extends ApiRecord ? Record<string, unknown> : UpdateData<T>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http.patch<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\tdata,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Delete a record by ID.\n\t * @param id Record ID.\n\t * @param options Optional request options.\n\t */\n\tdelete(id: string, options?: RequestOptions): Promise<null> {\n\t\treturn this.http.delete(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\toptions,\n\t\t);\n\t}\n\t// ── Expand / Relation Fields ──\n\n\t/**\n\t * Get a list of expandable (relation) fields for this collection.\n\t * Useful for constructing `expand` query parameters.\n\t */\n\tasync expandFields(\n\t\toptions?: RequestOptions,\n\t): Promise<{ field: string; targetCollection: string }[] | null> {\n\t\tconst data = await this.http.get<{\n\t\t\tfields?: {\n\t\t\t\tname: string;\n\t\t\t\ttype: string;\n\t\t\t\toptions?: Record<string, string>;\n\t\t\t}[];\n\t\t}>(\"/collections/\" + this.encodeId(this.collectionName), options);\n\t\tif (!data?.fields) return null;\n\t\treturn data.fields\n\t\t\t.filter((f) => f.type === \"relation\" && f.options?.collection)\n\t\t\t.map((f) => ({\n\t\t\t\tfield: f.name,\n\t\t\t\ttargetCollection: f.options!.collection,\n\t\t\t}));\n\t}\n\n\t/**\n\t * Cast this service to a specific record shape.\n\t * Use when you have a hand-written or generated interface for the\n\t * collection and want compile-time checking of create/update/list.\n\t *\n\t * @example\n\t * ```ts\n\t * interface Post {\n\t * id: string;\n\t * title: string;\n\t * published: boolean;\n\t * }\n\t * const posts = client.collection(\"posts\").typed<Post>();\n\t * await posts.create({ title: \"Hi\", published: true }); // ✓\n\t * await posts.create({ nope: 1 }); // ✗ compile error\n\t * ```\n\t */\n\ttyped<TRecord = ApiRecord>(): CollectionService<TRecord> {\n\t\treturn this as unknown as CollectionService<TRecord>;\n\t}\n\n\t// ── Realtime Subscriptions (PocketBase-style) ──\n\n\t/**\n\t * Subscribe to realtime changes for this collection.\n\t * The event's `action` is one of `\"create\" | \"update\" | \"delete\"`.\n\t *\n\t * Access is governed by the collection's `listRule` (PocketBase semantics):\n\t * public collections allow anonymous subscriptions; other collections\n\t * require a matching logged-in user or superuser.\n\t *\n\t * @param callback Received on every record change.\n\t * @param recordId Optional — subscribe to a single record instead of `*`.\n\t * @returns A function that unsubscribes this callback.\n\t */\n\tsubscribe(callback: RealtimeCallback, recordId?: string): () => void {\n\t\tif (!this.realtime) {\n\t\t\tconsole.warn(\"[lazypock] No realtime service configured.\");\n\t\t\treturn () => {};\n\t\t}\n\t\tconst topic =\n\t\t\t\"collection:\" + this.collectionName + (recordId ? \":\" + recordId : \"\");\n\t\tconst handler = (raw: RealtimeEventLike) => {\n\t\t\tconst record = (raw.payload?.[\"record\"] ?? {}) as Record<string, unknown>;\n\t\t\tcallback({\n\t\t\t\taction: normalizeAction(raw.event, raw.payload?.[\"action\"]),\n\t\t\t\trecord,\n\t\t\t\ttopic: raw.topic,\n\t\t\t});\n\t\t};\n\t\tthis.realtime.ensureConnected();\n\t\tthis.realtime.subscribe(topic, handler as never);\n\t\treturn () => this.realtime?.unsubscribe(topic, handler as never);\n\t}\n\n\t/**\n\t * Unsubscribe all callbacks from this collection (or a specific record).\n\t * @param recordId Optional record id; omitting it unsubs everything.\n\t */\n\tunsubscribe(recordId?: string): void {\n\t\tconst topic =\n\t\t\t\"collection:\" + this.collectionName + (recordId ? \":\" + recordId : \"\");\n\t\tthis.realtime?.unsubscribe(topic);\n\t}\n\n\t// ── Auth Collection Methods ──\n\n\t/**\n\t * Authenticate with email/password against this auth collection.\n\t * Stores the returned token and user model in the auth store.\n\t */\n\tasync authWithPassword(\n\t\tidentity: string,\n\t\tpassword: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-with-password\",\n\t\t\t{ identity, password },\n\t\t\toptions,\n\t\t);\n\t\tif (data && this.authStore) {\n\t\t\tthis.authStore.setCollectionName(this.collectionName);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Refresh the auth token for the currently authenticated user.\n\t * Updates the stored token and user model.\n\t */\n\tasync authRefresh(\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-refresh\",\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t\tif (data && this.authStore) {\n\t\t\tthis.authStore.setCollectionName(this.collectionName);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Get available auth methods for this collection.\n\t */\n\t// ── end Realtime ──\n\n\tasync authMethods(\n\t\toptions?: RequestOptions,\n\t): Promise<Record<string, unknown> | null> {\n\t\treturn this.http.get<Record<string, unknown>>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-methods\",\n\t\t\toptions,\n\t\t);\n\t}\n}\n","// ── Phoenix Channel WebSocket Client ──────────────────\n//\n// Implements the Phoenix Channels protocol over WebSocket\n// to subscribe to collection realtime updates.\n//\n// Protocol: Phoenix V1 JSON Serializer (object-based messages).\n// Sends messages as JSON objects with {topic, event, payload, ref, join_ref}.\n// Receives messages as JSON objects with {topic, event, payload, ref}.\n\ninterface RealtimeEvent {\n\tevent: string;\n\ttopic: string;\n\tpayload: Record<string, unknown>;\n}\n\ninterface SubEntry {\n\ttopic: string;\n\tcallback: (e: RealtimeEvent) => void;\n}\n\nexport type RealtimeConnectOpts = {\n\t/** WebSocket URL (e.g. ws://localhost:4000/socket/websocket) */\n\turl: string;\n\t/** Auth token to pass as query param */\n\ttoken?: string;\n};\n\n/**\n * Derive a WebSocket URL from an HTTP base URL.\n * http://localhost:4000/api → ws://localhost:4000/socket/websocket\n */\nexport function wsUrlFromBaseUrl(baseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(baseUrl);\n\t\tconst protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n\t\treturn `${protocol}//${url.host}/socket/websocket`;\n\t} catch {\n\t\treturn `${baseUrl.replace(/^http/, \"ws\").replace(/\\/api$/, \"\")}/socket/websocket`;\n\t}\n}\n\n/**\n * Phoenix Channel client for real-time collection subscriptions.\n *\n * Connects via WebSocket and subscribes to collection topics.\n * Includes automatic reconnection with exponential backoff.\n *\n * @example\n * ```ts\n * const rt = new RealtimeService();\n * rt.connect({ url: wsUrlFromBaseUrl('http://localhost:4000/api') });\n * rt.subscribe('collection:posts', (e) => console.log(e));\n * ```\n */\nexport class RealtimeService {\n\tprivate ws: WebSocket | null = null;\n\tprivate refCounter = 0;\n\tprivate subscriptions = new Map<string, SubEntry[]>();\n\tprivate reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate reconnectAttempt = 0;\n\tprivate maxReconnectDelay = 5000;\n\n\t// Callbacks for connection state\n\tonReconnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (err: Event) => void;\n\n\tprivate url: string = \"\";\n\tprivate token: string | undefined;\n\n\t/** Whether the WebSocket is currently open. */\n\tget isOpen(): boolean {\n\t\treturn this.ws?.readyState === WebSocket.OPEN;\n\t}\n\n\t/**\n\t * The most recently used WebSocket URL (set on {@link connect}).\n\t * Useful for SDK convenience methods that auto-connect before subscribing.\n\t */\n\tget lastUrl(): string {\n\t\treturn this.url;\n\t}\n\n\t/** The auth token configured for this connection (set on connect). */\n\tget lastToken(): string | undefined {\n\t\treturn this.token;\n\t}\n\n\t/**\n\t * Set the socket URL. Useful before subscribing so the SDK can\n\t * auto-connect on the first {@link subscribe}.\n\t */\n\tsetUrl(url: string): void {\n\t\tthis.url = url;\n\t}\n\n\t/*\n\t * Ensure the socket is connected, then subscribe.\n\t * Used by collection-level convenience wrappers so a connection is opened\n\t * automatically on the first subscribe (matching PocketBase behaviour —\n\t * works for anonymous/public collections too).\n\t */\n\tensureConnected(): void {\n\t\tif (this.isOpen || !this.url) return;\n\t\tif (typeof WebSocket === \"undefined\") return;\n\t\tthis.doConnect();\n\t}\n\n\tconnect(opts: RealtimeConnectOpts): void {\n\t\tthis.url = opts.url;\n\t\tthis.token = opts.token;\n\t\tthis.reconnectAttempt = 0;\n\t\tthis.doConnect();\n\t}\n\n\tdisconnect(): void {\n\t\tthis.clearReconnectTimer();\n\t\tthis.ws?.close();\n\t\tthis.ws = null;\n\t}\n\n\t/**\n\t * Subscribe to a topic (e.g. \"collection:posts\" or \"collection:posts:*\").\n\t * The backend Channel authorizes via listRule on join.\n\t */\n\tsubscribe(topic: string, callback: (e: RealtimeEvent) => void): void {\n\t\tconst subs = this.subscriptions.get(topic) || [];\n\t\tsubs.push({ topic, callback });\n\t\tthis.subscriptions.set(topic, subs);\n\n\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\tthis.joinTopic(topic);\n\t\t}\n\t}\n\n\t/**\n\t * Unsubscribe a specific callback from a topic.\n\t */\n\tunsubscribe(topic: string, callback?: (e: RealtimeEvent) => void): void {\n\t\tif (!callback) {\n\t\t\tthis.subscriptions.delete(topic);\n\t\t\treturn;\n\t\t}\n\t\tconst subs = this.subscriptions\n\t\t\t.get(topic)\n\t\t\t?.filter((s) => s.callback !== callback);\n\t\tif (subs && subs.length > 0) {\n\t\t\tthis.subscriptions.set(topic, subs);\n\t\t} else {\n\t\t\tthis.subscriptions.delete(topic);\n\t\t}\n\t}\n\n\tprivate resubscribeAll(): void {\n\t\tfor (const topic of this.subscriptions.keys()) {\n\t\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\tthis.joinTopic(topic);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate doConnect(): void {\n\t\tif (typeof WebSocket === \"undefined\") {\n\t\t\tconsole.warn(\n\t\t\t\t\"[lazypock] WebSocket not available — realtime subscriptions disabled\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tlet url = this.url;\n\t\tif (this.token) {\n\t\t\turl +=\n\t\t\t\t(url.includes(\"?\") ? \"&\" : \"?\") +\n\t\t\t\t\"token=\" +\n\t\t\t\tencodeURIComponent(this.token);\n\t\t}\n\n\t\tthis.ws = new WebSocket(url);\n\n\t\tthis.ws.onopen = () => {\n\t\t\tthis.reconnectAttempt = 0;\n\t\t\tthis.resubscribeAll();\n\t\t\tthis.startHeartbeat();\n\t\t};\n\n\t\tthis.ws.onmessage = (msg: MessageEvent) => {\n\t\t\tthis.handleMessage(msg.data);\n\t\t};\n\n\t\tthis.ws.onclose = () => {\n\t\t\tthis.stopHeartbeat();\n\t\t\tthis.onDisconnect?.();\n\t\t\tthis.scheduleReconnect();\n\t\t};\n\n\t\tthis.ws.onerror = (err: Event) => {\n\t\t\tthis.onError?.(err);\n\t\t};\n\t}\n\n\tprivate handleMessage(data: string): void {\n\t\tlet parsed: Record<string, unknown>;\n\t\ttry {\n\t\t\tparsed = JSON.parse(data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof parsed !== \"object\" || !parsed.topic || !parsed.event) return;\n\n\t\tconst topic = parsed.topic as string;\n\t\tconst event = parsed.event as string;\n\t\tconst payload = (parsed.payload as Record<string, unknown>) || {};\n\n\t\t// Handle phx_reply (join/heartbeat responses)\n\t\tif (event === \"phx_reply\") return;\n\n\t\t// Relay incoming events to all subscribers of this topic\n\t\tconst subs = this.subscriptions.get(topic);\n\t\tif (subs) {\n\t\t\tconst e: RealtimeEvent = {\n\t\t\t\tevent,\n\t\t\t\ttopic,\n\t\t\t\tpayload: payload as Record<string, unknown>,\n\t\t\t};\n\t\t\tfor (const s of subs) {\n\t\t\t\ttry {\n\t\t\t\t\ts.callback(e);\n\t\t\t\t} catch {\n\t\t\t\t\t// swallow callback errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate joinTopic(topic: string): void {\n\t\tconst ref = this.nextRef();\n\t\t// Phoenix V1 JSON Serializer expects a JSON object, not an array\n\t\tconst msg = JSON.stringify({\n\t\t\ttopic: topic,\n\t\t\tevent: \"phx_join\",\n\t\t\tpayload: {},\n\t\t\tref: ref,\n\t\t});\n\t\tthis.ws?.send(msg);\n\t}\n\n\tprivate nextRef(): string {\n\t\tthis.refCounter++;\n\t\treturn this.refCounter.toString();\n\t}\n\n\t// ── Heartbeat ──\n\n\tprivate heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\n\tprivate startHeartbeat(): void {\n\t\tthis.stopHeartbeat();\n\t\tthis.heartbeatInterval = setInterval(() => {\n\t\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\tconst ref = this.nextRef();\n\t\t\t\t// Phoenix V1 JSON Serializer expects a JSON object\n\t\t\t\tconst msg = JSON.stringify({\n\t\t\t\t\ttopic: \"phoenix\",\n\t\t\t\t\tevent: \"heartbeat\",\n\t\t\t\t\tpayload: {},\n\t\t\t\t\tref: ref,\n\t\t\t\t});\n\t\t\t\tthis.ws.send(msg);\n\t\t\t}\n\t\t}, 30_000);\n\t}\n\n\tprivate stopHeartbeat(): void {\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t\tthis.heartbeatInterval = null;\n\t\t}\n\t}\n\n\t// ── Reconnect ──\n\n\tprivate scheduleReconnect(): void {\n\t\tthis.clearReconnectTimer();\n\t\tconst delay = Math.min(\n\t\t\t1000 * 2 ** this.reconnectAttempt,\n\t\t\tthis.maxReconnectDelay,\n\t\t);\n\t\tthis.reconnectAttempt++;\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.reconnectTimer = null;\n\t\t\tthis.onReconnect?.();\n\t\t\tthis.doConnect();\n\t\t}, delay);\n\t}\n\n\tprivate clearReconnectTimer(): void {\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t}\n}\n","// ── File Service ─────────────────────────────────────────\n// Upload, download, and delete files.\n\nimport type { HttpClient } from \"./http\";\nimport type { RequestOptions } from \"./types\";\n\n/** Response shape from the server file endpoints */\nexport interface FileRecord {\n\tid: string;\n\tfilename: string;\n\tmimeType: string;\n\tsize: number;\n\turl: string;\n\t/** Map of thumbnail size => URL, e.g. { \"50x50\": \"/api/files/<id>/thumbs/50x50\" } */\n\tthumbs?: Record<string, string>;\n\t[key: string]: unknown;\n}\n\n/**\n * Construct a file URL from the API base URL and file ID.\n */\nexport function getFileUrl(baseUrl: string, fileId: string): string {\n\treturn baseUrl.replace(/\\/+$/, \"\") + \"/files/\" + encodeURIComponent(fileId);\n}\n\n/**\n * Construct a thumbnail URL from the API base URL, file ID, and thumb size.\n * @param size e.g. \"50x50\"\n */\nexport function getThumbUrl(baseUrl: string, fileId: string, size: string): string {\n\treturn (\n\t\tbaseUrl.replace(/\\/+$/, \"\") +\n\t\t\"/files/\" +\n\t\tencodeURIComponent(fileId) +\n\t\t\"/thumbs/\" +\n\t\tencodeURIComponent(size)\n\t);\n}\n\n/**\n * Construct an on-demand scaled image URL from the API base URL, file ID, and size.\n *\n * The size is an ImageMagick geometry: \"100\" (width, keep aspect), \"100x100\"\n * (fit within box), \"100x100!\" (exact crop), \"x200\" (height). The server\n * generates and caches the scaled image on first request.\n * @param size e.g. \"100x100\"\n */\nexport function getScaleUrl(baseUrl: string, fileId: string, size: string): string {\n\treturn (\n\t\tbaseUrl.replace(/\\/+$/, \"\") +\n\t\t\"/files/\" +\n\t\tencodeURIComponent(fileId) +\n\t\t\"/scale/\" +\n\t\tencodeURIComponent(size)\n\t);\n}\n\n\n/**\n * Service for file upload, retrieval, and deletion.\n * Access via {@link LazypockClient.files}.\n */\nexport class FilesService {\n\tconstructor(private http: HttpClient) {}\n\n\t/**\n\t * Upload a file or blob.\n\t *\n\t * @param file The File or Blob to upload.\n\t * @param filename Optional filename (required if `file` is a Blob without a name).\n\t * @param options Optional request options (signal, custom fetch).\n\t * @param meta Optional metadata: collectionName, recordId, fieldName for ownership tracking.\n\t */\n\tasync upload(\n\t\tfile: File | Blob,\n\t\tfilename?: string,\n\t\toptions?: RequestOptions,\n\t\tmeta?: { collectionName?: string; recordId?: string; fieldName?: string },\n\t): Promise<FileRecord | null> {\n\t\tif (typeof FormData === \"undefined\") {\n\t\t\tthrow new Error(\"FormData is not available in this environment\");\n\t\t}\n\n\t\tconst formData = new FormData();\n\t\tconst name = filename || (file instanceof File ? file.name : \"file\");\n\t\tformData.append(\"file\", file, name);\n\n\t\tif (meta?.collectionName)\n\t\t\tformData.append(\"collection_name\", meta.collectionName);\n\t\tif (meta?.recordId) formData.append(\"record_id\", meta.recordId);\n\t\tif (meta?.fieldName) formData.append(\"field_name\", meta.fieldName);\n\n\t\tconst data = await this.http.request<Record<string, unknown>>(\n\t\t\t\"POST\",\n\t\t\t\"/files\",\n\t\t\tformData,\n\t\t\toptions,\n\t\t);\n\n\t\treturn data as FileRecord | null;\n\t}\n\n\t/**\n\t * List uploaded files (newest first), with optional filters.\n\t *\n\t * @param options Filters and pagination.\n\t */\n\tasync list(options?: {\n\t\tpage?: number;\n\t\tperPage?: number;\n\t\tcollectionName?: string;\n\t\tfieldName?: string;\n\t\tmime?: string;\n\t}): Promise<{ items: FileRecord[]; page: number; perPage: number; total: number }> {\n\t\tconst params: Record<string, string> = {};\n\t\tif (options?.page !== undefined) params[\"page\"] = String(options.page);\n\t\tif (options?.perPage !== undefined) params[\"perPage\"] = String(options.perPage);\n\t\tif (options?.collectionName) params[\"collectionName\"] = options.collectionName;\n\t\tif (options?.fieldName) params[\"fieldName\"] = options.fieldName;\n\t\tif (options?.mime) params[\"mime\"] = options.mime;\n\n\t\tconst data = await this.http.request<{\n\t\t\titems: FileRecord[];\n\t\t\tpage: number;\n\t\t\tperPage: number;\n\t\t\ttotal: number;\n\t\t}>(\"GET\", \"/files\", undefined, { params });\n\t\treturn (\n\t\t\tdata ?? { items: [], page: 1, perPage: 50, total: 0 }\n\t\t) as {\n\t\t\titems: FileRecord[];\n\t\t\tpage: number;\n\t\t\tperPage: number;\n\t\t\ttotal: number;\n\t\t};\n\t}\n\n\t/**\n\t * Fetch file metadata including URL.\n\t * @param fileId The file ID.\n\t */\n\n\t/**\n\t * Fetch file metadata including URL.\n\t * @param fileId The file ID.\n\t */\n\tasync getUrl(fileId: string): Promise<string | null> {\n\t\tconst data = await this.http.request<Record<string, unknown>>(\n\t\t\t\"GET\",\n\t\t\t\"/files/\" + encodeURIComponent(fileId),\n\t\t);\n\t\tif (data && typeof data === \"object\" && \"url\" in data) {\n\t\t\treturn (data as Record<string, unknown>).url as string;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Delete a file by ID.\n\t * @param fileId The file ID.\n\t * @param options Optional request options.\n\t */\n\tasync delete(fileId: string, options?: RequestOptions): Promise<null> {\n\t\treturn this.http.request<null>(\n\t\t\t\"DELETE\",\n\t\t\t\"/files/\" + encodeURIComponent(fileId),\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t}\n}\n","// ── Collections Service ─────────────────────────────────\n// Registry-level service for collections (CRUD + realtime registry events),\n// mirroring PocketBase's `pb.collections` service.\n//\n// Get an instance via {@link LazypockClient.collections}.\n//\n// This is distinct from `CollectionService` (single collection record\n// events) — it operates on the *collections* themselves: listing / creating /\n// updating / deleting collections via `/api/collections`, and subscribing to\n// the `collections` registry channel (AdminChannel), which fires when\n// collections themselves are created / updated / deleted.\n\nimport type { HttpClient } from \"./http\";\nimport type { RealtimeService } from \"./realtime\";\nimport type { ListResult, RequestOptions, ApiRecord } from \"./types\";\n\nconst REGISTRY_TOPIC = \"collections\";\n\n/**\n * Registry-level realtime events for the collections admin channel.\n * The backend (AdminChannel) broadcasts the action as the *event name*,\n * with the collection JSON as the payload.\n */\nexport interface CollectionsMessage {\n\taction: \"create\" | \"update\" | \"delete\";\n\t/** The collection payload (id + metadata), or {} when unavailable. */\n\tcollection: Record<string, unknown>;\n\ttopic?: string;\n}\n\n/**\n * Registry service for collections (list/create/update/delete + realtime\n * registry events). Mirrors PocketBase's `pb.collections`.\n */\nexport class CollectionsService {\n\tprivate http?: HttpClient;\n\tprivate realtime?: RealtimeService;\n\n\t/** @internal */\n\tconstructor(http?: HttpClient, realtime?: RealtimeService) {\n\t\tthis.http = http;\n\t\tthis.realtime = realtime;\n\t}\n\n\t/**\n\t * Fetch a paginated list of collections (admin).\n\t *\n\t * @param params Optional query params (`page`, `perPage`, `filter`, `sort`).\n\t * @param options Optional request options.\n\t */\n\tasync getList<T = ApiRecord>(\n\t\tparams?: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<ListResult<T> | null> {\n\t\tconst qs = params\n\t\t\t? \"?\" +\n\t\t\t\tnew URLSearchParams(\n\t\t\t\t\tObject.fromEntries(\n\t\t\t\t\t\tObject.entries(params).map(([k, v]) => [k, String(v)]),\n\t\t\t\t\t),\n\t\t\t\t).toString()\n\t\t\t: \"\";\n\t\treturn this.http?.get<ListResult<T>>(\"/collections\" + qs, options) ?? null;\n\t}\n\n\t/**\n\t * Fetch all collections at once (auto-paginates). Mirrors PocketBase's\n\t * `pb.collections.getFullList()` — defaults to listing everything.\n\t *\n\t * @param options Query params (`sort`, `batch`, etc.) or request options.\n\t */\n\tasync getFullList<T = ApiRecord>(\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<Array<T>> {\n\t\tif (!this.http) return [];\n\t\tconst { batch = 1000, ...rest } = options ?? {};\n\t\tconst items: T[] = [];\n\t\tlet page = 1;\n\t\t// Auto-paginate until empty (bounded by perPage and totalPages).\n\t\tfor (;;) {\n\t\t\tconst res = await this.getList<T>({\n\t\t\t\t...rest,\n\t\t\t\tpage,\n\t\t\t\tperPage: batch,\n\t\t\t} as Record<string, unknown>);\n\t\t\tif (!res || !res.items || res.items.length === 0) break;\n\t\t\titems.push(...(res.items as T[]));\n\t\t\tif (page >= (res.totalPages ?? page)) break;\n\t\t\tpage += 1;\n\t\t}\n\t\treturn items;\n\t}\n\n\t/**\n\t * Get a single collection by ID or name (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param options Optional request options.\n\t */\n\tasync getOne<T = ApiRecord>(\n\t\tid: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn (\n\t\t\tthis.http?.get<T>(\"/collections/\" + encodeURIComponent(id), options) ??\n\t\t\tnull\n\t\t);\n\t}\n\n\t/**\n\t * Create a new collection (admin).\n\t *\n\t * @param data Collection definition (name, type, fields, options, rules, etc.).\n\t * @param options Optional request options.\n\t */\n\tasync create<T = ApiRecord>(\n\t\tdata: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http?.post<T>(\"/collections\", data, options) ?? null;\n\t}\n\n\t/**\n\t * Update an existing collection (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param data Updated collection fields.\n\t * @param options Optional request options.\n\t */\n\tasync update<T = ApiRecord>(\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn (\n\t\t\tthis.http?.patch<T>(\n\t\t\t\t\"/collections/\" + encodeURIComponent(id),\n\t\t\t\tdata,\n\t\t\t\toptions,\n\t\t\t) ?? null\n\t\t);\n\t}\n\n\t/**\n\t * Delete a collection (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param options Optional request options.\n\t */\n\tasync delete(id: string, options?: RequestOptions): Promise<boolean> {\n\t\tconst res = this.http?.delete(\n\t\t\t\"/collections/\" + encodeURIComponent(id),\n\t\t\toptions,\n\t\t);\n\t\treturn res == null ? false : true;\n\t}\n\n\t/**\n\t * Subscribe to collection registry changes.\n\t *\n\t * @param callback Received on every collection create/update/delete.\n\t * @returns A function that unsubscribes this callback.\n\t */\n\tsubscribe(callback: (e: CollectionsMessage) => void): () => void {\n\t\tif (!this.realtime) {\n\t\t\tconsole.warn(\"[lazypock] No realtime service configured.\");\n\t\t\treturn () => {};\n\t\t}\n\t\tconst handler = (raw: {\n\t\t\tevent: string;\n\t\t\ttopic: string;\n\t\t\tpayload?: Record<string, unknown>;\n\t\t}) => {\n\t\t\tcallback({\n\t\t\t\taction: normalizeAction(raw.event),\n\t\t\t\tcollection: (raw.payload ?? {}) as Record<string, unknown>,\n\t\t\t\ttopic: raw.topic,\n\t\t\t});\n\t\t};\n\t\tthis.realtime.ensureConnected();\n\t\tthis.realtime.subscribe(REGISTRY_TOPIC, handler as never);\n\t\treturn () => this.realtime?.unsubscribe(REGISTRY_TOPIC, handler as never);\n\t}\n\n\t/**\n\t * Unsubscribe all callbacks from the registry channel.\n\t */\n\tunsubscribe(): void {\n\t\tthis.realtime?.unsubscribe(REGISTRY_TOPIC);\n\t}\n}\n\n/** Map a registry event name (create/update/delete) to an action. */\nfunction normalizeAction(event: string): CollectionsMessage[\"action\"] {\n\tconst e = event.toLowerCase();\n\tif (e === \"create\") return \"create\";\n\tif (e === \"update\") return \"update\";\n\tif (e === \"delete\") return \"delete\";\n\treturn \"update\";\n}\n","// ── Type mapping (runtime + codegen) ────────────────────\n// Maps server field types to TypeScript types.\n// Shared by the runtime `SchemaTypes` helper and the codegen CLI.\n\nimport type { SchemaField } from \"./schema\";\n\n/**\n * Map a single server field to its TypeScript type string.\n * Used by the codegen CLI to emit interface members.\n *\n * @param field The field definition.\n * @param fallback Fallback type for unknown field types (default `unknown`).\n */\nexport function fieldTypeScriptType(\n\tfield: SchemaField,\n\tfallback = \"unknown\",\n): string {\n\tconst opts = field.options ?? {};\n\tswitch (field.type) {\n\t\tcase \"text\":\n\t\tcase \"email\":\n\t\tcase \"url\":\n\t\tcase \"editor\":\n\t\tcase \"date\":\n\t\tcase \"datetime\":\n\t\t\treturn \"string\";\n\t\tcase \"number\":\n\t\t\treturn \"number\";\n\t\tcase \"bool\":\n\t\t\treturn \"boolean\";\n\t\tcase \"select\": {\n\t\t\tconst values = Array.isArray(opts.values) ? opts.values : [];\n\t\t\tif (values.length > 0) {\n\t\t\t\treturn values.map((v) => JSON.stringify(String(v))).join(\" | \");\n\t\t\t}\n\t\t\treturn \"string\";\n\t\t}\n\t\tcase \"multi_select\": {\n\t\t\tconst values = Array.isArray(opts.values) ? opts.values : [];\n\t\t\tif (values.length > 0) {\n\t\t\t\treturn `(${values.map((v) => JSON.stringify(String(v))).join(\" | \")})[]`;\n\t\t\t}\n\t\t\treturn \"string[]\";\n\t\t}\n\t\tcase \"file\":\n\t\t\treturn \"string\";\n\t\tcase \"multi_file\":\n\t\t\treturn \"string[]\";\n\t\tcase \"json\":\n\t\tcase \"geo\":\n\t\t\treturn \"Record<string, unknown>\";\n\t\tcase \"relation\":\n\t\t\t// Relations store the target record's ID (string) — or an array\n\t\t\t// of IDs when multi-relation (maxSelect > 1).\n\t\t\treturn (opts.maxSelect ?? 1) > 1 ? \"string[]\" : \"string\";\n\t\tcase \"password\":\n\t\t\t// Passwords are write-only; never expose on read models.\n\t\t\treturn \"never\";\n\t\tdefault:\n\t\t\treturn fallback;\n\t}\n}\n\n/**\n * Returns the runtime type kind for a field — used by {@link schemaFieldType}\n * to build structural types at runtime.\n */\nexport type FieldTypeKind =\n\t| \"string\"\n\t| \"number\"\n\t| \"boolean\"\n\t| \"string-array\"\n\t| \"json\"\n\t| \"relation\"\n\t| \"relation-many\"\n\t| \"password\"\n\t| \"unknown\";\n\n/** Map a server field to its runtime type kind. */\nexport function fieldTypeKind(field: SchemaField): FieldTypeKind {\n\tconst opts = field.options ?? {};\n\tswitch (field.type) {\n\t\tcase \"text\":\n\t\tcase \"email\":\n\t\tcase \"url\":\n\t\tcase \"editor\":\n\t\tcase \"date\":\n\t\tcase \"datetime\":\n\t\tcase \"select\":\n\t\tcase \"file\":\n\t\t\treturn \"string\";\n\t\tcase \"number\":\n\t\t\treturn \"number\";\n\t\tcase \"bool\":\n\t\t\treturn \"boolean\";\n\t\tcase \"multi_select\":\n\t\tcase \"multi_file\":\n\t\t\treturn \"string-array\";\n\t\tcase \"json\":\n\t\tcase \"geo\":\n\t\t\treturn \"json\";\n\t\tcase \"relation\":\n\t\t\treturn (opts.maxSelect ?? 1) > 1 ? \"relation-many\" : \"relation\";\n\t\tcase \"password\":\n\t\t\treturn \"password\";\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n}\n\n/**\n * Derive a TypeScript field type from a {@link SchemaField} — the runtime\n * counterpart to the codegen mapper. Lets consumers build typed clients\n * from a fetched schema without running the CLI.\n */\nexport function schemaFieldType(field: SchemaField): unknown {\n\tswitch (fieldTypeKind(field)) {\n\t\tcase \"string\":\n\t\t\treturn String;\n\t\tcase \"number\":\n\t\t\treturn Number;\n\t\tcase \"boolean\":\n\t\t\treturn Boolean;\n\t\tcase \"string-array\":\n\t\t\treturn [String] as const;\n\t\tcase \"relation\":\n\t\t\treturn String;\n\t\tcase \"relation-many\":\n\t\t\treturn [String] as const;\n\t\tcase \"json\":\n\t\t\treturn Object;\n\t\tcase \"password\":\n\t\t\treturn undefined;\n\t\tcase \"unknown\":\n\t\t\treturn undefined;\n\t}\n}\n","// ── Codegen ─────────────────────────────────────────────\n// Generates a `lazypock.types.ts` module from the live API schema.\n//\n// The generated file exports:\n// - One interface per collection (e.g. `PostsRecord`)\n// - A `LazypockCollections` map: { posts: PostsRecord; users: UsersRecord; ... }\n// - A `createClient()` factory pre-bound to those types, so\n// `client.collection(\"posts\").create({ title: \"x\" })` is fully type-checked.\n//\n// The CLI in `src/cli.ts` wires this to `GET /collections`.\n\nimport type { CollectionSchema, SchemaField } from \"./schema\";\nimport { fieldTypeScriptType } from \"./typegen\";\n\n/** Format a raw collection name into a valid TS identifier (PascalCase). */\nexport function collectionTypeName(name: string): string {\n\treturn name\n\t\t.split(/[^a-zA-Z0-9]+/)\n\t\t.filter(Boolean)\n\t\t.map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n\t\t.join(\"\")\n\t\t.replace(/^[0-9]/, \"_$&\");\n}\n\n/** Interface member name — sanitize hyphens/spaces but keep readability. */\nexport function fieldKey(name: string): string {\n\treturn name.replace(/[^a-zA-Z0-9_]/g, \"_\");\n}\n\n\n\n/**\n * Generate the full TypeScript source for the typed SDK module.\n *\n * @param collections Collections fetched from the API.\n * @param options Generation options.\n */\nexport function generateTypes(\n\tcollections: CollectionSchema[],\n\toptions: {\n\t\t/** Import specifier for the lazypock package (default `lazypock`). */\n\t\tpackageName?: string;\n\t\t/** Emit base record fields (id, created, updated, …). Default true. */\n\t\tincludeBaseFields?: boolean;\n\t\t/** Skip system collections (names starting with `_` or `users`). Default false. */\n\t\tskipSystem?: boolean;\n\t} = {},\n): string {\n\tconst {\n\t\tpackageName = \"lazypock\",\n\t\tincludeBaseFields = true,\n\t\tskipSystem = false,\n\t} = options;\n\n\tconst filtered = skipSystem\n\t\t? collections.filter(\n\t\t\t\t(c) => !c.system && !c.name.startsWith(\"_\") && c.name !== \"users\",\n\t\t\t)\n\t\t: collections;\n\n\tconst sections: string[] = [];\n\tsections.push(`// ── Auto-generated by lazypock-ts ──────────────────────────\n// Do not edit by hand. Regenerate with: npx lazypock-gen\n// Schema snapshot: ${new Date().toISOString()}`);\n\n\tif (includeBaseFields) {\n\t\tsections.push(`export interface BaseRecord {\n id: string;\n collectionId: string;\n collectionName: string;\n created: string;\n updated: string;\n}`);\n\t}\n\n\t// One interface per collection\n\tfor (const coll of filtered) {\n\t\tconst typeName = collectionTypeName(coll.name);\n\t\tconst fields = coll.fields ?? [];\n\t\tconst lines = fields.map((f) => memberLine(f)).filter((l) => l !== \"\");\n\t\tconst body = lines.join(\"\\n\");\n\t\tsections.push(\n\t\t\t`export interface ${typeName}Record${renderInterface({\n\t\t\t\textends: includeBaseFields ? \"BaseRecord\" : undefined,\n\t\t\t\tbody,\n\t\t\t})}`,\n\t\t);\n\t}\n\n\t// Auth collection type\n\tsections.push(`export interface AuthRecord extends BaseRecord {\n email: string;\n verified: boolean;\n}`);\n\n\t// Collections map\n\tconst mapEntries = filtered\n\t\t.map(\n\t\t\t(c) =>\n\t\t\t\t` \"${c.name}\": ${collectionTypeName(c.name)}Record${\n\t\t\t\t\tc.type === \"auth\" ? \" & AuthRecord\" : \"\"\n\t\t\t\t};`,\n\t\t)\n\t\t.join(\"\\n\");\n\tsections.push(`export interface LazypockCollections {\n${mapEntries}\n}`);\n\n\t// createClient factory\n\tsections.push(`import { LazypockClient, type LazypockClientOptions, type CollectionService } from \"${packageName}\";\n\n/**\n * Create a Lazypock client typed against this schema snapshot.\n * Collection access is fully type-checked:\n * client.collection(\"posts\").create({ title: \"x\" }) // title must exist\n */\nexport function createClient(options: LazypockClientOptions): TypedClient {\n return new TypedClient(options);\n}\n\nexport class TypedClient extends LazypockClient {\n override collection<T extends string>(name: T): T extends keyof LazypockCollections\n ? CollectionService<LazypockCollections[T]>\n : CollectionService<unknown> {\n return super.collection(name) as T extends keyof LazypockCollections ? CollectionService<LazypockCollections[T]> : CollectionService<unknown>;\n }\n}\n`);\n\n\treturn sections.join(\"\\n\\n\") + \"\\n\";\n}\n\n/**\n * Render the interface body including the extends clause.\n * Empty body → ` extends BaseRecord {}` (valid TS).\n */\nfunction renderInterface(opts: { extends?: string; body: string }): string {\n\tconst ext = opts.extends ? ` extends ${opts.extends}` : \"\";\n\tif (!opts.body) return `${ext} {}`;\n\treturn `${ext} {\\n${opts.body}\\n}`;\n}\n\n/** Render a single interface member line for a field. */\nfunction memberLine(f: SchemaField): string {\n\tconst key = fieldKey(f.name);\n\tconst req = f.required || f.type === \"password\" ? \"\" : \"?\";\n\tconst type = fieldTypeScriptType(f);\n\t// `never` members (passwords) are omitted from read models.\n\tif (type === \"never\") return \"\";\n\treturn ` ${JSON.stringify(key)}${req}: ${type};`;\n}\n","// ── LazypockClient — Root Client ───────────────────────\n// Extracted into its own module to avoid a circular import with\n// the typed-client factory (src/client.ts).\n\nimport { HttpClient } from \"./http\";\nimport {\n\tAuthStore,\n\tmemoryStorage,\n\ttype StorageAdapter,\n\ttype AuthModel,\n} from \"./auth\";\nimport { CollectionService } from \"./collection\";\nimport {\n\tApiError,\n\ttype ApiRecord,\n\ttype ListResult,\n\ttype RecordShape,\n\ttype CreateData,\n\ttype UpdateData,\n\ttype SystemFields,\n\ttype RequestOptions,\n} from \"./types\";\nimport { RealtimeService, wsUrlFromBaseUrl } from \"./realtime\";\nimport {\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\ttype FileRecord,\n} from \"./files\";\nimport { CollectionsService } from \"./collections\";\nimport type { CollectionSchema, SchemaField } from \"./schema\";\nimport { generateTypes, collectionTypeName } from \"./codegen\";\nimport { fieldTypeScriptType, fieldTypeKind, schemaFieldType } from \"./typegen\";\n\nexport {\n\tAuthStore,\n\tApiError,\n\tHttpClient,\n\tRealtimeService,\n\twsUrlFromBaseUrl,\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\tCollectionService,\n\tCollectionsService,\n\tgenerateTypes,\n\tcollectionTypeName,\n\tfieldTypeScriptType,\n\tfieldTypeKind,\n\tschemaFieldType,\n};\nexport type {\n\tStorageAdapter,\n\tAuthModel,\n\tApiRecord,\n\tListResult,\n\tRecordShape,\n\tCreateData,\n\tUpdateData,\n\tSystemFields,\n\tRequestOptions,\n\tFileRecord,\n\tCollectionSchema,\n\tSchemaField,\n};\n\n/** Options for constructing a {@link LazypockClient}. */\nexport interface LazypockClientOptions {\n\t/** API base URL (e.g. 'http://localhost:4000/api') */\n\tbaseUrl: string;\n\t/** Custom storage adapter (default: localStorage fallback) */\n\tstorage?: StorageAdapter;\n\t/** Explicit auth store instance (for sharing across modules) */\n\tauthStore?: AuthStore;\n\t/** Real-time service for Phoenix Channel WebSocket subscriptions */\n\trealtime?: RealtimeService;\n\t/**\n\t * Optional schema types for generating typed services at runtime.\n\t * When provided, `collection()` returns a service whose create/update\n\t * inputs are validated against the mapped field types.\n\t *\n\t * @experimental\n\t */\n\ttypes?: {\n\t\t/** Collection schemas fetched from the API (e.g. via `GET /collections`). */\n\t\tschemas?: CollectionSchema[];\n\t};\n}\n\n/**\n * Lazypock API client.\n *\n * Provides methods for authentication, CRUD operations on dynamic collections,\n * file management, and real-time subscriptions.\n *\n * @example\n * ```ts\n * const client = new LazypockClient({ baseUrl: 'http://localhost:4000/api' });\n * await client.login('admin@example.com', 'password');\n * const posts = await client.collection('posts').getList();\n * ```\n */\nexport class LazypockClient {\n\treadonly http: HttpClient;\n\treadonly authStore: AuthStore;\n\treadonly realtime: RealtimeService;\n\treadonly collections: CollectionsService;\n\treadonly files: FilesService;\n\tprivate collectionCache = new Map<string, CollectionService>();\n\tprivate schemaByName?: Map<string, CollectionSchema>;\n\n\t/**\n\t * Create a new Lazypock client.\n\t * @param options Configuration options.\n\t */\n\tconstructor(options: LazypockClientOptions) {\n\t\tconst baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.authStore =\n\t\t\toptions.authStore ?? new AuthStore(options.storage ?? memoryStorage);\n\t\tthis.http = new HttpClient(baseUrl, this.authStore);\n\t\tthis.realtime = options.realtime ?? new RealtimeService();\n\t\t// Cache the socket URL so collection-level subscribe() can auto-connect.\n\t\tif (!options.realtime) {\n\t\t\tthis.realtime.setUrl(wsUrlFromBaseUrl(baseUrl));\n\t\t}\n\t\tthis.files = new FilesService(this.http);\n\t\tthis.collections = new CollectionsService(this.http, this.realtime);\n\t\tif (options.types?.schemas) {\n\t\t\tthis.schemaByName = new Map(\n\t\t\t\toptions.types.schemas.map((s) => [s.name, s]),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a service for the given collection.\n\t * Services are cached after first access.\n\t *\n\t * For typed CRUD, either:\n\t * - cast at the call site: `client.collection(\"posts\").typed<Post>()`\n\t * - or use the typed factory: `createClient<{ posts: Post }>()`\n\t *\n\t * @param name The collection name.\n\t * @returns A {@link CollectionService} instance.\n\t */\n\tcollection(name: string): CollectionService<unknown> {\n\t\tlet svc = this.collectionCache.get(name);\n\t\tif (!svc) {\n\t\t\tsvc = new CollectionService(\n\t\t\t\tthis.http,\n\t\t\t\tname,\n\t\t\t\tthis.authStore,\n\t\t\t\tthis.realtime,\n\t\t\t);\n\t\t\tthis.collectionCache.set(name, svc);\n\t\t}\n\t\treturn svc;\n\t}\n\n\t/**\n\t * Get a typed service whose record shape is derived from the schema\n\t * passed via `options.types.schemas` (if available), or fall back to\n\t * the untyped service otherwise.\n\t *\n\t * @experimental\n\t */\n\tcollectionFor<TRecord = ApiRecord>(name: string): CollectionService<TRecord> {\n\t\treturn this.collection(name) as unknown as CollectionService<TRecord>;\n\t}\n\n\t/**\n\t * Generate TypeScript types from the schemas provided to this client\n\t * (via `options.types.schemas`). Returns a string ready to write to a\n\t * `lazypock.types.ts` file.\n\t */\n\tgenerateTypes(options?: { packageName?: string }): string {\n\t\tconst schemas = this.schemaByName ? [...this.schemaByName.values()] : [];\n\t\treturn generateTypes(schemas, options);\n\t}\n\n\t// ── Auto-cancellation (PocketBase `autoCancellation` parity) ──\n\n\t/**\n\t * Globally enable or disable auto-cancellation of duplicated pending requests.\n\t *\n\t * When enabled (default), a new request whose `requestKey` (default\n\t * `HTTP_METHOD + path`) matches a still-pending request aborts the previous\n\t * one — only the last duplicate executes.\n\t *\n\t * @example\n\t * ```ts\n\t * client.autoCancellation(false); // keep every request\n\t * ```\n\t */\n\tautoCancellation(enable: boolean): this {\n\t\tthis.http.autoCancellation(enable);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Abort a single pending request by its cancellation key\n\t * (default `HTTP_METHOD + path`, e.g. `\"GET /api/posts?page=1\"`).\n\t * The request rejects with an `ApiError` whose `isAbort` is `true`.\n\t */\n\tcancelRequest(requestKey: string): this {\n\t\tthis.http.cancelRequest(requestKey);\n\t\treturn this;\n\t}\n\n\t/** Abort all pending requests. */\n\tcancelAllRequests(): this {\n\t\tthis.http.cancelAllRequests();\n\t\treturn this;\n\t}\n\n\t// ── Auth ──\n\n\t/** Check whether any superuser exists (for login vs setup screen routing). */\n\tasync checkSuperuser(): Promise<{ has_superuser: boolean } | null> {\n\t\treturn this.http.get<{ has_superuser: boolean }>(\"/superusers/check\");\n\t}\n\n\t/**\n\t * Create the initial superuser account.\n\t * Only works when no superuser exists yet.\n\t * Stores the returned token in the auth store.\n\t * @param email Superuser email.\n\t * @param password Superuser password (min 8 chars).\n\t */\n\tasync setup(\n\t\temail: string,\n\t\tpassword: string,\n\t): Promise<({ token: string } & Record<string, unknown>) | null> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string } & Record<string, unknown>\n\t\t>(\"/superusers/setup\", { email, password });\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(null);\n\t\t\tthis.authStore.set(data.token, null);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Authenticate as a superuser or auth collection user.\n\t *\n\t * When `collection` is provided, authenticates against\n\t * `/{collection}/auth-with-password`. Otherwise logs in as superuser.\n\t * Stores the returned token in the auth store.\n\t *\n\t * @param email User email or identity.\n\t * @param password User password.\n\t * @param collection Optional auth collection name.\n\t */\n\tasync login(\n\t\temail: string,\n\t\tpassword: string,\n\t\tcollection?: string,\n\t): Promise<({ token: string } & Record<string, unknown>) | null> {\n\t\tlet data;\n\t\tif (collection) {\n\t\t\tdata = await this.http.post<\n\t\t\t\t{ token: string; record: Record<string, unknown> } & Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tunknown\n\t\t\t\t>\n\t\t\t>(\"/\" + encodeURIComponent(collection) + \"/auth-with-password\", {\n\t\t\t\tidentity: email,\n\t\t\t\tpassword,\n\t\t\t});\n\t\t\tif (data && data.record) {\n\t\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t\t}\n\t} else {\n\t\t\t// Superuser login — PocketBase parity: `_superusers` is an auth collection.\n\t\t\t// Falls back to the legacy /superusers/login for older servers.\n\t\t\ttry {\n\t\t\t\tdata = await this.http.post<\n\t\t\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t\t\t>(\"/_superusers/auth-with-password\", {\n\t\t\t\t\tidentity: email,\n\t\t\t\t\tpassword,\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tdata = null;\n\t\t\t}\n\t\t\tif (!data) {\n\t\t\t\tdata = await this.http.post<\n\t\t\t\t\t{ token: string } & Record<string, unknown>\n\t\t\t\t>(\"/superusers/login\", { email, password });\n\t\t\t}\n\t\t\tif (data) {\n\t\t\t\tthis.authStore.setCollectionName(null);\n\t\t\t\tthis.authStore.set(data.token, null);\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Fetch the current authenticated identity (superuser OR auth collection user).\n\t * Uses `GET /api/me` (PocketBase parity) — works with both superuser tokens\n\t * and auth collection user tokens.\n\t */\n\tasync me<T = ApiRecord>(options?: RequestOptions): Promise<T | null> {\n\t\tconst data = await this.http.get<T>(\"/me\", options);\n\t\tif (data) {\n\t\t\t// Update the auth model with fresh data\n\t\t\tthis.authStore.set(this.authStore.token, data as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Authenticate against an auth collection with email/password.\n\t * Stores the returned token and user record in the auth store.\n\t *\n\t * @param collection The auth collection name.\n\t * @param identity Email or username.\n\t * @param password Password.\n\t * @param options Optional request options.\n\t */\n\tasync authWithPassword(\n\t\tcollection: string,\n\t\tidentity: string,\n\t\tpassword: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + encodeURIComponent(collection) + \"/auth-with-password\",\n\t\t\t{ identity, password },\n\t\t\toptions,\n\t\t);\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Refresh an auth collection token.\n\t * Uses the currently stored auth token.\n\t *\n\t * @param collection The auth collection name.\n\t * @param options Optional request options.\n\t */\n\tasync authRefresh(\n\t\tcollection: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + encodeURIComponent(collection) + \"/auth-refresh\",\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/** Clear the current auth state and remove persisted tokens. */\n\tlogout(): void {\n\t\tthis.authStore.clear();\n\t}\n\n\t// ── Health ──\n\n\t/** Ping the API health endpoint. */\n\thealth(options?: RequestOptions): Promise<Record<string, unknown> | null> {\n\t\treturn this.http.get<Record<string, unknown>>(\"/health\", options);\n\t}\n}\n","// ── Typed client factory ────────────────────────────────\n// Generic over a collections map, so collection access is type-checked\n// without hand-writing interfaces — pair with the codegen CLI output.\n\nimport { LazypockClient } from \"./lazypock\";\nimport type { CollectionService } from \"./collection\";\nimport type { LazypockClientOptions } from \"./lazypock\";\n\n/**\n * A collections map: `{ posts: PostRecord; users: UserRecord; ... }`.\n * Generated by the codegen CLI (`npx lazypock-gen`) or written by hand.\n */\nexport type LazypockCollections = Record<string, unknown>;\n\n/**\n * Client typed against a {@link LazypockCollections} map.\n *\n * ```ts\n * import { createClient } from \"lazypock/generated\";\n * const client = createClient({ baseUrl: \"http://localhost:4000/api\" });\n * const posts = await client.collection(\"posts\").list<PostsRecord>();\n * ```\n */\nexport class TypedClient<\n\tTCollections extends LazypockCollections = LazypockCollections,\n> extends LazypockClient {\n\t/**\n\t * Get a typed service for a collection.\n\t * When `TCollections` is provided, unknown collection names are rejected.\n\t * @typeParam K — Collection name (keyof TCollections).\n\t */\n\toverride collection<K extends keyof TCollections>(\n\t\tname: K,\n\t): CollectionService<TCollections[K]>;\n\toverride collection(name: string): CollectionService<unknown> {\n\t\treturn super.collection(name) as unknown as CollectionService<unknown>;\n\t}\n}\n\n/**\n * Create a {@link TypedClient}.\n * @typeParam TCollections — Map of collection name → record shape.\n */\nexport function createClient<\n\tTCollections extends LazypockCollections = LazypockCollections,\n>(options: LazypockClientOptions): TypedClient<TCollections> {\n\treturn new TypedClient<TCollections>(options);\n}\n"],"mappings":"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","names":["normalizeAction"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/cache.ts","../src/http.ts","../src/auth.ts","../src/collection.ts","../src/realtime.ts","../src/files.ts","../src/collections.ts","../src/typegen.ts","../src/codegen.ts","../src/lazypock.ts","../src/client.ts"],"sourcesContent":["// ── Lazypock SDK — Public Entry ────────────────────────\n//\n// Re-exports everything from the LazypockClient module plus the\n// typed-client factory. Keep this file a thin barrel so there are\n// no circular imports.\n\nexport {\n\t// LazypockClient + options + everything it re-exports\n\tAuthStore,\n\tApiError,\n\tHttpClient,\n\tRealtimeService,\n\twsUrlFromBaseUrl,\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\tLazypockClient,\n\tCollectionService,\n\tCollectionsService,\n\tgenerateTypes,\n\tcollectionTypeName,\n\tfieldTypeScriptType,\n\tfieldTypeKind,\n\tschemaFieldType,\n\tCacheStore,\n\tresolveCacheDirective,\n} from \"./lazypock\";\nexport { TypedClient, createClient } from \"./client\";\n\nexport type {\n\t// types\n\tStorageAdapter,\n\tAuthModel,\n\tApiRecord,\n\tListResult,\n\tRecordShape,\n\tCreateData,\n\tUpdateData,\n\tSystemFields,\n\tRequestOptions,\n\tFileRecord,\n\t// cache\n\tCacheConfig,\n\tCacheRequestOptions,\n\t// schema\n\tCollectionSchema,\n\tSchemaField,\n\t// options\n\tLazypockClientOptions,\n} from \"./lazypock\";\nexport type { LazypockCollections } from \"./client\";\nexport type { RealtimeMessage, RealtimeCallback } from \"./collection\";\nexport type { CollectionsMessage } from \"./collections\";\n","// ── Record & Collection types ───────────────────────────\n\n/**\n * Base shape every record returned from any collection satisfies.\n * Generated record interfaces extend this.\n */\nexport interface BaseRecordFields {\n\tid: string;\n\tcollectionId: string;\n\tcollectionName: string;\n\tcreated: string;\n\tupdated: string;\n}\n\n/** Shape of a record returned from any collection. */\nexport interface ApiRecord extends BaseRecordFields {\n\t[key: string]: unknown;\n}\n\n/**\n * Structural marker for concrete record shapes (generated or hand-written).\n * Used to differentiate a typed collection service from the untyped default.\n */\nexport type RecordShape = Record<string, unknown>;\n\n/** System fields every record carries — not user-provided on create. */\nexport type SystemFields =\n\t| \"id\"\n\t| \"collectionId\"\n\t| \"collectionName\"\n\t| \"created\"\n\t| \"updated\";\n\n/**\n * Data accepted by `create()`: any subset of `T`'s fields, but\n * never the system fields. Unknown/extra keys are rejected at compile\n * time via excess-property checking (object literals).\n */\nexport type CreateData<T> = Partial<Omit<T, SystemFields>>;\n\n/**\n * Data accepted by `update()`: any subset of `T`'s fields.\n * Unknown/extra keys are rejected at compile time.\n */\nexport type UpdateData<T> = Partial<Omit<T, SystemFields>>;\n\n/** Paginated list response matching PocketBase format. */\nexport interface ListResult<T = ApiRecord> {\n\titems: T[];\n\tpage: number;\n\tperPage: number;\n\ttotalItems: number;\n\ttotalPages: number;\n}\n\n/** HTTP method supported by the client. */\nexport type Method = \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n\nexport interface RequestOptions {\n\t/** Search/filter params */\n\tparams?: Record<string, string>;\n\t/** Raw request headers to merge */\n\theaders?: Record<string, string>;\n\t/** Abort signal */\n\tsignal?: AbortSignal;\n\t/** Custom fetch implementation (for RN or test mocking) */\n\tfetch?: typeof globalThis.fetch;\n\t/**\n\t * Cache control for this request (see {@link CacheRequestOptions}).\n\t * Resolved against the client's global cache config when unset.\n\t */\n\tcache?: boolean | number | { ttl?: number; key?: string };\n\t/** Alias of `cache: <ms>` — cache this GET for `ttl` milliseconds. */\n\tttl?: number;\n\t/**\n\t * Extra cache namespaces to invalidate when this mutation succeeds.\n\t * The current collection is always invalidated automatically.\n\t */\n\tinvalidate?: string[];\n\t/**\n\t * Request identifier used by the auto-cancellation mechanism.\n\t *\n\t * Pending requests sharing the same key cancel each other — only the\n\t * last one is executed (PocketBase `requestKey` semantics).\n\t *\n\t * - `string` — use this exact key instead of the default `METHOD + path`.\n\t * - `null` — disable auto-cancellation for this request (never auto-cancelled).\n\t *\n\t * @default `${method} ${path}`\n\t */\n\trequestKey?: string | null;\n\t/**\n\t * Disable auto-cancellation for this request.\n\t * Alias of `requestKey: null` (PocketBase `$autoCancel: false` compat).\n\t */\n\tautoCancel?: boolean;\n\t/**\n\t * Custom request key used for auto-cancellation.\n\t * Alias of `requestKey` (PocketBase `$cancelKey` compat).\n\t */\n\tcancelKey?: string;\n}\n\nexport class ApiError extends Error {\n\treadonly data: unknown;\n\treadonly status: number;\n\t/**\n\t * `true` when this error was caused by an aborted/cancelled request\n\t * (auto-cancelled duplicate, or manually via `cancelRequest()` /\n\t * `cancelAllRequests()` / an external AbortSignal).\n\t */\n\treadonly isAbort: boolean;\n\n\tconstructor(message: string, data: unknown, status: number, isAbort = false) {\n\t\tsuper(message);\n\t\tthis.name = \"ApiError\";\n\t\tthis.data = data;\n\t\tthis.status = status;\n\t\tthis.isAbort = isAbort;\n\t}\n}\n","// ── Cache Store ──────────────────────────────────────────\n// Pluggable query-cache for GET responses. Mirrors the AuthStore pattern:\n// a default memory store (Map) with an optional custom storage adapter\n// (localStorage, AsyncStorage, IndexedDB, ...) for cross-page persistence.\n\nimport type { StorageAdapter } from \"./auth\";\n\n/** Options for enabling/customising the client's query cache. */\nexport interface CacheConfig {\n\t/**\n\t * Master switch. When `true`, readable GET requests are cached with the\n\t * default TTL unless a request opts out via `{ cache: false }`.\n\t *\n\t * When `false` (default), caching is disabled unless a request opts in\n\t * via `{ cache: true }` or `{ ttl: <ms> }`. Opt-in works regardless.\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Default time-to-live for cached entries, in milliseconds.\n\t * @default 60_000 (1 minute)\n\t */\n\tdefaultTTL?: number;\n\t/**\n\t * Optional persistence backend (same interface as AuthStore's storage).\n\t * Defaults to an in-memory Map — swap for `localStorage` / `AsyncStorage`\n\t * to keep the cache across page reloads / app restarts.\n\t */\n\tstore?: StorageAdapter;\n\t/**\n\t * Max number of entries to keep in memory (LRU eviction).\n\t * @default 500\n\t */\n\tmaxEntries?: number;\n\t/**\n\t * When true and the client has an active realtime subscription for a\n\t * collection, inbound create/update/delete events invalidate that\n\t * collection's cached entries automatically.\n\t * @default false — only local mutations invalidate (explicit + predictable)\n\t */\n\tinvalidateOnRealtime?: boolean;\n}\n\n/** Per-request cache controls (mixed into {@link RequestOptions}). */\nexport interface CacheRequestOptions {\n\t/**\n\t * Cache control for this request:\n\t * - `true` — cache with the default (or global) TTL\n\t * - `false` — always fetch fresh, bypass cache (and don't store the result)\n\t * - a number — cache with this TTL in milliseconds\n\t * - an object — `{ ttl, key }` for finer control\n\t *\n\t * When unset, the global `cache.enabled` flag decides.\n\t */\n\tcache?: boolean | number | { ttl?: number; key?: string };\n\t/** Alias of `cache: <ms>` (convenience, reads naturally). */\n\tttl?: number;\n\t/**\n\t * Extra cache namespaces to invalidate when this mutation succeeds.\n\t * The current collection is always invalidated automatically.\n\t * @example create({ ... }, { invalidate: ['users'] })\n\t */\n\tinvalidate?: string[];\n}\n\n/** A single cached entry. */\ninterface CacheEntry<T = unknown> {\n\tvalue: T;\n\texpiresAt: number;\n\t/** Namespace (collection name) this entry belongs to — for invalidation. */\n\tnamespace?: string;\n\t/** Prefix tags (e.g. `getList:posts`) for deleteByPrefix. */\n\ttags?: string[];\n}\n\n/** LRU-ish memory store + optional persistent adapter hybrid. */\nexport class CacheStore {\n\tprivate memory = new Map<string, CacheEntry>();\n\tprivate readonly ttl: number;\n\tprivate readonly persistence?: StorageAdapter;\n\tprivate readonly maxEntries: number;\n\tprivate hits = 0;\n\tprivate misses = 0;\n\tprivate namespaceEntries = new Map<string, Set<string>>();\n\t/** Key → set of prefix tags registered for that key (e.g. `getList:posts`). */\n\tprivate prefixEntries = new Map<string, Set<string>>();\n\n\tconstructor(config: {\n\t\tdefaultTTL?: number;\n\t\tstore?: StorageAdapter;\n\t\tmaxEntries?: number;\n\t} = {}) {\n\t\tthis.ttl = config.defaultTTL ?? 60_000;\n\t\tthis.persistence = config.store;\n\t\tthis.maxEntries = config.maxEntries ?? 500;\n\t}\n\n\t/** Resolve the effective TTL: request override → global default. */\n\tprivate resolveTTL(ttl?: number): number {\n\t\treturn ttl && ttl > 0 ? ttl : this.ttl;\n\t}\n\n\t/**\n\t * Read a cached value. Fast sync path (memory) with async persistence\n\t * fallback for adapters whose `get` returns a Promise.\n\t * @param key Cache key (e.g. `\"GET /posts?page=1\"`).\n\t * @returns The cached value, or undefined when absent/expired (the hit is\n\t * cleared on expiry so a stale value is never served).\n\t */\n\tasync get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst mem = this.memory.get(key);\n\t\tif (mem !== undefined) {\n\t\t\tif (Date.now() > mem.expiresAt) {\n\t\t\t\tthis.delete(key);\n\t\t\t\tthis.misses++;\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// refresh recency for LRU eviction\n\t\t\tthis.memory.delete(key);\n\t\t\tthis.memory.set(key, mem);\n\t\t\tthis.hits++;\n\t\t\treturn mem.value as T;\n\t\t}\n\t\tif (this.persistence) {\n\t\t\tconst entry = await this.readPersisted(key);\n\t\t\tif (entry) {\n\t\t\t\tif (Date.now() > entry.expiresAt) {\n\t\t\t\t\tthis.delete(key);\n\t\t\t\t\tthis.misses++;\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tthis.hits++;\n\t\t\t\treturn entry.value as T;\n\t\t\t}\n\t\t}\n\t\tthis.misses++;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Store a value.\n\t * @param key Cache key.\n\t * @param value The response payload.\n\t * @param ttlOverride Optional TTL override (ms).\n\t * @param namespace Optional namespace for group invalidation.\n\t */\n\tset(\n\t\tkey: string,\n\t\tvalue: unknown,\n\t\tttlOverride?: number,\n\t\tnamespace?: string,\n\t\ttags?: string[],\n\t): void {\n\t\tconst expiresAt = Date.now() + this.resolveTTL(ttlOverride);\n\t\tconst entry: CacheEntry = { value, expiresAt, namespace, tags };\n\t\tthis.memory.set(key, entry);\n\n\t\t// LRU eviction when over capacity\n\t\tif (this.memory.size > this.maxEntries) {\n\t\t\tconst oldest = this.memory.keys().next().value as string | undefined;\n\t\t\tif (oldest !== undefined) this.delete(oldest);\n\t\t}\n\n\t\tif (namespace) {\n\t\t\tlet keys = this.namespaceEntries.get(namespace);\n\t\t\tif (!keys) {\n\t\t\t\tkeys = new Set();\n\t\t\t\tthis.namespaceEntries.set(namespace, keys);\n\t\t\t}\n\t\t\tkeys.add(key);\n\t\t}\n\n\t\tfor (const tag of tags ?? []) {\n\t\t\tlet keys = this.prefixEntries.get(tag);\n\t\t\tif (!keys) {\n\t\t\t\tkeys = new Set();\n\t\t\t\tthis.prefixEntries.set(tag, keys);\n\t\t\t}\n\t\t\tkeys.add(key);\n\t\t}\n\n\t\tif (this.persistence) {\n\t\t\tvoid this.persistence.set(this.persistKey(key), JSON.stringify(entry));\n\t\t}\n\t}\n\n\t/**\n\t * Invalidate entries belonging to a namespace (e.g. a collection name).\n\t * Also clears the namespace index entry.\n\t */\n\tinvalidate(namespace: string): void {\n\t\tconst keys = Array.from(this.namespaceEntries.get(namespace) ?? []);\n\t\tfor (const key of keys) this.delete(key);\n\t\tthis.namespaceEntries.delete(namespace);\n\t}\n\n\t/** Remove a single key. */\n\tdelete(key: string): void {\n\t\tconst entry = this.memory.get(key);\n\t\tif (entry?.namespace) {\n\t\t\tconst set = this.namespaceEntries.get(entry.namespace);\n\t\t\tif (set) {\n\t\t\t\tset.delete(key);\n\t\t\t\tif (set.size === 0) this.namespaceEntries.delete(entry.namespace);\n\t\t\t}\n\t\t}\n\t\tfor (const tag of entry?.tags ?? []) {\n\t\t\tconst set = this.prefixEntries.get(tag);\n\t\t\tif (set) {\n\t\t\t\tset.delete(key);\n\t\t\t\tif (set.size === 0) this.prefixEntries.delete(tag);\n\t\t\t}\n\t\t}\n\t\tthis.memory.delete(key);\n\t\tif (this.persistence) {\n\t\t\tvoid this.persistence.remove(this.persistKey(key));\n\t\t}\n\t}\n\n\t/**\n\t * Delete every entry whose key starts with `prefix`.\n\t *\n\t * Useful for fine-grained invalidation, e.g.:\n\t * ```ts\n\t * client.cache.deleteByPrefix('getList:posts'); // delete all getList cache\n\t * client.cache.deleteByPrefix('getOne:posts'); // delete all getOne cache\n\t * ```\n\t */\n\tdeleteByPrefix(prefix: string): void {\n\t\tif (!prefix) return;\n\t\t// exact tag match (fast path — the common `op:collection` case)\n\t\tconst tagged = this.prefixEntries.get(prefix);\n\t\tif (tagged) {\n\t\t\tfor (const key of Array.from(tagged)) this.delete(key);\n\t\t\tthis.prefixEntries.delete(prefix);\n\t\t\treturn;\n\t\t}\n\t\t// general prefix scan (e.g. `posts` matches any `op:posts`/`GET /posts`)\n\t\tfor (const key of Array.from(this.memory.keys())) {\n\t\t\tif (key.startsWith(prefix)) this.delete(key);\n\t\t}\n\t}\n\n\t/** Drop every cached entry (memory + persistence). */\n\tclear(): void {\n\t\tthis.memory.clear();\n\t\tthis.namespaceEntries.clear();\n\t\tthis.prefixEntries.clear();\n\t\t// Best-effort: clear all persisted keys via the adapter. The adapter has\n\t\t// no list API, so we track a prefix index in memory only — a full\n\t\t// persistence wipe is only possible if the adapter supports enumeration.\n\t\t// Most use localStorage directly; callers may also recreate the client.\n\t}\n\n\t/** Cache hit/miss/entry statistics. */\n\tstats(): { hits: number; misses: number; entries: number } {\n\t\treturn { hits: this.hits, misses: this.misses, entries: this.memory.size };\n\t}\n\n\tprivate persistKey(key: string): string {\n\t\treturn \"lazypock:cache:\" + key;\n\t}\n\n\tprivate async readPersisted(key: string): Promise<CacheEntry | undefined> {\n\t\tif (!this.persistence) return undefined;\n\t\tconst raw = await this.persistence.get(this.persistKey(key));\n\t\tif (raw == null) return undefined;\n\t\ttry {\n\t\t\tconst entry = JSON.parse(raw) as CacheEntry;\n\t\t\t// Re-hydrate a copy in memory (TTL checked by caller)\n\t\t\tthis.memory.set(key, entry);\n\t\t\tif (entry.namespace) {\n\t\t\t\tlet keys = this.namespaceEntries.get(entry.namespace);\n\t\t\t\tif (!keys) {\n\t\t\t\t\tkeys = new Set();\n\t\t\t\t\tthis.namespaceEntries.set(entry.namespace, keys);\n\t\t\t\t}\n\t\t\t\tkeys.add(key);\n\t\t\t}\n\t\t\tfor (const tag of entry.tags ?? []) {\n\t\t\t\tlet keys = this.prefixEntries.get(tag);\n\t\t\t\tif (!keys) {\n\t\t\t\t\tkeys = new Set();\n\t\t\t\t\tthis.prefixEntries.set(tag, keys);\n\t\t\t\t}\n\t\t\t\tkeys.add(key);\n\t\t\t}\n\t\t\treturn entry;\n\t\t} catch {\n\t\t\tvoid this.persistence.remove(this.persistKey(key));\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n\n// ── Helpers ──\n\n/** Resolve per-request cache options into a usable directive. */\nexport function resolveCacheDirective(opts?: {\n\tcache?: boolean | number | { ttl?: number; key?: string };\n\tttl?: number;\n}): { enabled: boolean; ttl?: number; key?: string } | null {\n\tif (!opts) return null;\n\t// convenience alias: ttl: 5000 → cache for 5s\n\tif (typeof opts.ttl === \"number\" && opts.ttl > 0) {\n\t\treturn { enabled: true, ttl: opts.ttl };\n\t}\n\tconst c = opts.cache;\n\tif (c === undefined) return null; // use global enabled flag\n\tif (c === true) return { enabled: true };\n\tif (c === false) return { enabled: false };\n\tif (typeof c === \"number\") return { enabled: true, ttl: c > 0 ? c : undefined };\n\t// object form\n\treturn { enabled: true, ttl: c.ttl, key: c.key };\n}","// ── HTTP Client ─────────────────────────────────────────\n// Only relies on globalThis.fetch — works in browser, React Native, and Node 18+\n\nimport { ApiError, type Method, type RequestOptions } from \"./types\";\nimport type { AuthStore } from \"./auth\";\nimport type { CacheStore } from \"./cache\";\nimport { resolveCacheDirective } from \"./cache\";\n\n/**\n * Low-level HTTP client wrapping `fetch` with automatic auth token injection.\n * Only relies on `globalThis.fetch` — works in browser, React Native, and Node 18+.\n */\n/** Detect whether an unknown thrown value is an abort/`AbortError`-style error. */\nfunction isAbortError(err: unknown): boolean {\n\treturn (\n\t\terr instanceof Error &&\n\t\t(err.name === \"AbortError\" || err.message === \"Aborted\")\n\t);\n}\n\nexport class HttpClient {\n\tprivate baseUrl: string;\n\tprivate authStore: AuthStore;\n\tprivate defaultFetch: typeof globalThis.fetch;\n\t/** Optional query cache store (wired when the client enables caching). */\n\tprivate cache?: CacheStore;\n\t/** Master switch resolved from CacheConfig.enabled. */\n\tprivate cacheEnabled = false;\n\n\t/**\n\t * Abort controllers for in-flight requests, keyed by their cancellation key\n\t * (default `METHOD path`). A new request with the same key aborts the\n\t * previous one — PocketBase-style auto-cancellation of duplicated requests.\n\t */\n\tprivate cancelControllers: Record<string, AbortController> = {};\n\n\t/** Global toggle for the auto-cancellation behaviour (default: on). */\n\tprivate enableAutoCancellation = true;\n\n\t/**\n\t * @param baseUrl The API base URL (e.g. `http://localhost:4000/api`). Trailing slash stripped.\n\t * @param authStore The auth store providing the token for Authorization headers.\n\t */\n\tconstructor(baseUrl: string, authStore: AuthStore) {\n\t\tthis.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.authStore = authStore;\n\t\tthis.defaultFetch = globalThis.fetch.bind(globalThis);\n\t}\n\n\t/**\n\t * Attach a cache store + master switch.\n\t * Called by the client constructor when cache config is present.\n\t */\n\tsetCache(cache: CacheStore, enabled: boolean): void {\n\t\tthis.cache = cache;\n\t\tthis.cacheEnabled = enabled;\n\t}\n\n\t/** Whether the global cache flag is on (requests opt in/out individually too). */\n\tget cacheIsEnabled(): boolean {\n\t\treturn this.cacheEnabled;\n\t}\n\n\tprivate async refreshAuth(): Promise<{\n\t\ttoken: string;\n\t\trecord: Record<string, unknown>;\n\t} | null> {\n\t\tconst collection = this.authStore.collectionName;\n\t\tif (!collection) return null;\n\t\ttry {\n\t\t\tconst url =\n\t\t\t\tthis.baseUrl + \"/\" + encodeURIComponent(collection) + \"/auth-refresh\";\n\t\t\tconst headers: Record<string, string> = {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t};\n\t\t\tif (this.authStore.token) {\n\t\t\t\theaders[\"Authorization\"] = \"Bearer \" + this.authStore.token;\n\t\t\t}\n\t\t\tconst res = await this.defaultFetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t});\n\t\t\tif (!res.ok) {\n\t\t\t\tthis.authStore.clear();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst data = (await res.json()) as Record<string, unknown>;\n\t\t\tif (data && typeof data.token === \"string\") {\n\t\t\t\tthis.authStore.set(\n\t\t\t\t\tdata.token,\n\t\t\t\t\t(data.record as Record<string, unknown> as any) ?? null,\n\t\t\t\t);\n\t\t\t\treturn data as { token: string; record: Record<string, unknown> };\n\t\t\t}\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Globally enable or disable auto-cancellation of duplicated pending requests.\n\t * Fluent — returns `this` for chaining.\n\t */\n\tautoCancellation(enable: boolean): this {\n\t\tthis.enableAutoCancellation = !!enable;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Abort a pending request identified by its cancellation key\n\t * (default `METHOD path`, e.g. `\"GET /api/posts\"`). No-op if not pending.\n\t */\n\tcancelRequest(requestKey: string): this {\n\t\tconst controller = this.cancelControllers[requestKey];\n\t\tif (controller) {\n\t\t\tcontroller.abort();\n\t\t\tdelete this.cancelControllers[requestKey];\n\t\t}\n\t\treturn this;\n\t}\n\n\t/** Abort all pending requests. */\n\tcancelAllRequests(): this {\n\t\tfor (const key in this.cancelControllers) {\n\t\t\tthis.cancelControllers[key].abort();\n\t\t}\n\t\tthis.cancelControllers = {};\n\t\treturn this;\n\t}\n\n\t/**\n\t * Make an HTTP request with automatic auth token injection and optional auto-refresh.\n\t *\n\t * Auto-cancellation: a request keyed by `options.requestKey` (default\n\t * `METHOD path`) aborts any previous pending request with the same key,\n\t * so only the last duplicate executes. Set `requestKey: null` or\n\t * `autoCancel: false` to opt out per request.\n\t *\n\t * @param method HTTP method.\n\t * @param path URL path (appended to baseUrl).\n\t * @param body JSON-serializable body, or FormData for file uploads.\n\t * @param options Optional request options.\n\t * @returns Parsed JSON response, or null for 204 No Content.\n\t * @throws {ApiError} On non-2xx responses or when the request is aborted\n\t * (aborted requests throw an `ApiError` with `isAbort === true`).\n\t */\n\t/** Invalidate a namespace (collection name). No-op when cache is off. */\n\tinvalidateCache(namespace: string): void {\n\t\tthis.cache?.invalidate(namespace);\n\t}\n\n\t/** Current cache statistics (hits/misses/entries), or null when disabled. */\n\tcacheStats(): { hits: number; misses: number; entries: number } | null {\n\t\treturn this.cache ? this.cache.stats() : null;\n\t}\n\n\tasync request<T = unknown>(\n\t\tmethod: Method,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\t// Auto-refresh if token is expired\n\t\tif (this.authStore.isExpired && this.authStore.collectionName) {\n\t\t\tawait this.refreshAuth();\n\t\t}\n\n\t\t// ── Cache resolution (read path) ────────────────────────────────\n\t\t// Only cacheable reads (GET) participate. Cache keys are scoped by auth\n\t\t// token so user A's cached list can never leak to user B (or anonymous).\n\t\t//\n\t\t// Effective caching for this request:\n\t\t// - per-request { cache } / { ttl } present → use it (true enables,\n\t\t// false bypasses, number/object sets TTL)\n\t\t// - otherwise → fall back to the global cache.enabled flag\n\t\tconst cacheDirective = resolveCacheDirective(options);\n\t\tconst wantCache =\n\t\t\tcacheDirective !== null\n\t\t\t\t? cacheDirective.enabled\n\t\t\t\t: this.cacheEnabled;\n\t\tconst cacheKey =\n\t\t\tmethod === \"GET\" && this.cache && wantCache\n\t\t\t\t? this.cacheKeyFor(method, path, options?.params)\n\t\t\t\t: null;\n\t\tif (cacheKey !== null) {\n\t\t\tconst hit = await this.cache?.get(cacheKey);\n\t\t\tif (hit !== undefined) return hit as T;\n\t\t}\n\n\t\t// Resolve the auto-cancellation key (PocketBase `requestKey` semantics):\n\t\t// - options.requestKey null → disabled for this request\n\t\t// - options.requestKey string → use it verbatim\n\t\t// - options.autoCancel false → disabled (legacy compat)\n\t\t// - options.cancelKey string → use it verbatim (legacy compat)\n\t\t// - otherwise → default to `${method} ${path}`\n\t\tlet requestKey: string | null =\n\t\t\toptions?.requestKey === undefined\n\t\t\t\t? (options?.cancelKey ?? `${method} ${path}`)\n\t\t\t\t: options.requestKey;\n\t\tif (options?.autoCancel === false) requestKey = null;\n\n\t\t// Wire a fresh AbortController for this request, merging any caller signal.\n\t\t// When auto-cancellation is enabled, the previous pending request sharing\n\t\t// our key is aborted first (only the last duplicate executes).\n\t\tlet controller: AbortController | null = null;\n\t\tconst externalSignal = options?.signal;\n\t\tif (requestKey !== null) {\n\t\t\tif (this.enableAutoCancellation) {\n\t\t\t\tthis.cancelRequest(requestKey);\n\t\t\t}\n\t\t\tcontroller = new AbortController();\n\t\t\tthis.cancelControllers[requestKey] = controller;\n\t\t\tif (externalSignal?.aborted) {\n\t\t\t\tcontroller.abort();\n\t\t\t} else if (externalSignal) {\n\t\t\t\texternalSignal.addEventListener(\"abort\", () => controller?.abort(), {\n\t\t\t\t\tonce: true,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tconst signal = controller?.signal ?? externalSignal;\n\n\t\tlet url = this.baseUrl + path;\n\t\tif (options?.params) {\n\t\t\tconst qs = new URLSearchParams(options.params).toString();\n\t\t\tif (qs) {\n\t\t\t\turl += (path.includes(\"?\") ? \"&\" : \"?\") + qs;\n\t\t\t}\n\t\t}\n\t\tconst headers: Record<string, string> = {\n\t\t\t...options?.headers,\n\t\t};\n\n\t\t// Don't set Content-Type for FormData (browser sets multipart boundary)\n\t\tif (!(body instanceof FormData)) {\n\t\t\theaders[\"Content-Type\"] = \"application/json\";\n\t\t}\n\n\t\tif (this.authStore.token) {\n\t\t\theaders[\"Authorization\"] = \"Bearer \" + this.authStore.token;\n\t\t}\n\n\t\tconst init: RequestInit = {\n\t\t\tmethod,\n\t\t\theaders,\n\t\t\tsignal,\n\t\t};\n\n\t\tif (body != null && method !== \"GET\" && method !== \"DELETE\") {\n\t\t\tif (body instanceof FormData) {\n\t\t\t\tinit.body = body;\n\t\t\t} else {\n\t\t\t\tinit.body = JSON.stringify(body);\n\t\t\t}\n\t\t}\n\n\t\tlet res: Response | null = null;\n\t\tconst fetcher = options?.fetch ?? this.defaultFetch;\n\t\ttry {\n\t\t\tres = await fetcher(url, init);\n\t\t} catch (err) {\n\t\t\t// Aborted (auto-cancelled duplicate, manual cancel, or external signal)\n\t\t\t// → normalized ApiError with isAbort === true, like PocketBase.\n\t\t\tif (isAbortError(err)) {\n\t\t\t\tthrow new ApiError(\n\t\t\t\t\t\"The request was aborted (most likely auto-cancelled by a newer request with the same requestKey)\",\n\t\t\t\t\t{},\n\t\t\t\t\t0,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\t// The request has settled — no longer pending, so drop the controller\n\t\t\t// unless a newer request already replaced it (same key).\n\t\t\tif (\n\t\t\t\trequestKey !== null &&\n\t\t\t\tthis.cancelControllers[requestKey] === controller\n\t\t\t) {\n\t\t\t\tdelete this.cancelControllers[requestKey];\n\t\t\t}\n\t\t}\n\n\t\tif (res!.status === 204) return null;\n\n\t\t// Safely parse JSON — some errored responses may have empty or non-JSON bodies\n\t\tlet bodyText = \"\";\n\t\tlet data: Record<string, unknown> = {};\n\t\ttry {\n\t\t\tbodyText = await res.text();\n\t\t\tif (bodyText) {\n\t\t\t\tdata = JSON.parse(bodyText) as Record<string, unknown>;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not JSON — keep data as empty object\n\t\t}\n\n\t\tif (!res!.ok) {\n\t\t\tthrow new ApiError(\n\t\t\t\t(typeof data.message === \"string\" ? data.message : res!.statusText) ||\n\t\t\t\t\t`Request failed with status ${res!.status}`,\n\t\t\t\tdata,\n\t\t\t\tres!.status,\n\t\t\t);\n\t\t}\n\n\t\t// ── Cache store (read path) ─────────────────────────────────────\n\t\t// Persist successful GET payloads when the directive wants caching.\n\t\tif (cacheKey !== null && this.cache) {\n\t\t\tconst namespace = this.namespaceFromPath(path);\n\t\t\tconst ttl = cacheDirective?.ttl;\n\t\t\tconst tags = this.cacheTagsFor(path, namespace);\n\t\t\tthis.cache.set(\n\t\t\t\tcacheKey,\n\t\t\t\tdata,\n\t\t\t\tttl,\n\t\t\t\tnamespace ?? undefined,\n\t\t\t\ttags,\n\t\t\t);\n\t\t}\n\n\t\t// ── Cache invalidation (write path) ────────────────────────────\n\t\t// Mutations invalidate the affected collection's cached entries so\n\t\t// subsequent reads don't serve stale lists. The current collection is\n\t\t// always invalidated; `options.invalidate` adds extra namespaces.\n\t\tif (method !== \"GET\" && this.cache) {\n\t\t\tconst namespaces = new Set<string>();\n\t\t\tconst ns = this.namespaceFromPath(path);\n\t\t\tif (ns) namespaces.add(ns);\n\t\t\tfor (const extra of options?.invalidate ?? []) {\n\t\t\t\tif (extra) namespaces.add(extra);\n\t\t\t}\n\t\t\tfor (const nsName of namespaces) this.cache.invalidate(nsName);\n\t\t}\n\n\t\treturn data as T;\n\t}\n\n\t// ── Cache key/namespace helpers ──\n\n\t/** Build a token-scoped cache key: `METHOD path|token-hash|params`. */\n\tprivate cacheKeyFor(\n\t\tmethod: Method,\n\t\tpath: string,\n\t\tparams?: Record<string, string>,\n\t): string {\n\t\tconst token = this.authStore.token || \"anon\";\n\t\tconst qs = params ? \"?\" + new URLSearchParams(params).toString() : \"\";\n\t\treturn `${method} ${path}${qs}|${token}`;\n\t}\n\n\t/** Best-effort namespace (collection name) from a REST path. */\n\tprivate namespaceFromPath(path: string): string | undefined {\n\t\t// /posts/abc-123 → posts ; /collections/xyz → collections\n\t\t// strip any query string first (/posts?page=1 → /posts)\n\t\tconst clean = path.split(\"?\")[0];\n\t\tconst parts = clean.split(\"/\").filter(Boolean);\n\t\tif (parts.length === 0) return undefined;\n\t\tif (parts[0] === \"collections\" || parts[0] === \"_superusers\") {\n\t\t\treturn parts[0];\n\t\t}\n\t\treturn parts[0];\n\t}\n\n\t/**\n\t * Semantic prefix tags for `deleteByPrefix`, derived from the REST shape:\n\t * - `/{collection}?...` → `getList:{collection}`\n\t * - `/{collection}/{id}` → `getOne:{collection}`\n\t * - `/collections?...` / `/collections/{id}` → `collections:getList` / `collections:getOne`\n\t */\n\tprivate cacheTagsFor(path: string, namespace: string | undefined): string[] {\n\t\tif (!namespace) return [];\n\t\tconst clean = path.split(\"?\")[0];\n\t\tconst parts = clean.split(\"/\").filter(Boolean);\n\t\tif (parts[0] === \"collections\" || parts[0] === \"_superusers\") {\n\t\t\tconst op = parts.length >= 2 ? \"getOne\" : \"getList\";\n\t\t\treturn [`${namespace}:${op}`];\n\t\t}\n\t\t// /posts (list) vs /posts/{id} (one)\n\t\tconst op = parts.length >= 2 ? \"getOne\" : \"getList\";\n\t\treturn [`${op}:${namespace}`];\n\t}\n\n\t/**\n\t * HTTP GET.\n\t * @param path URL path.\n\t * @param options Optional request options.\n\t */\n\tget<T = unknown>(path: string, options?: RequestOptions): Promise<T | null> {\n\t\treturn this.request<T>(\"GET\", path, undefined, options);\n\t}\n\n\t/**\n\t * HTTP POST.\n\t * @param path URL path.\n\t * @param body Optional request body.\n\t * @param options Optional request options.\n\t */\n\tpost<T = unknown>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"POST\", path, body, options);\n\t}\n\n\t/**\n\t * HTTP PATCH.\n\t * @param path URL path.\n\t * @param body Optional request body.\n\t * @param options Optional request options.\n\t */\n\tpatch<T = unknown>(\n\t\tpath: string,\n\t\tbody?: unknown,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"PATCH\", path, body, options);\n\t}\n\n\t/**\n\t * HTTP DELETE.\n\t * @param path URL path.\n\t * @param options Optional request options.\n\t */\n\tdelete<T = unknown>(\n\t\tpath: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.request<T>(\"DELETE\", path, undefined, options);\n\t}\n}\n","// ── Auth Store ──────────────────────────────────────────\n// Pluggable storage adapter: swap for AsyncStorage on RN, localStorage on web, etc.\n\n/**\n * Interface for pluggable persistence backends.\n * Swap for `AsyncStorage` on React Native, `localStorage` on web, etc.\n */\nexport interface StorageAdapter {\n\t/** Retrieve a stored value by key. */\n\tget(key: string): string | null | Promise<string | null>;\n\t/** Persist a key-value pair. */\n\tset(key: string, value: string): void | Promise<void>;\n\t/** Remove a stored value by key. */\n\tremove(key: string): void | Promise<void>;\n}\n\n/** Shape of an authenticated user record (from auth collections). */\nexport interface AuthModel {\n\tid: string;\n\t[key: string]: unknown;\n}\n\n/** Callback signature for auth state changes. */\nexport type AuthListener = (model: AuthModel | null, token: string) => void;\n\n// Server token TTL: 7 days (matches Phoenix.Token max_age)\nconst TOKEN_TTL_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport class AuthStore {\n\tprivate _token = \"\";\n\tprivate _model: AuthModel | null = null;\n\tprivate _tokenExpiresAt: number | null = null;\n\tprivate _collectionName: string | null = null;\n\tprivate listeners = new Set<AuthListener>();\n\tprivate storage: StorageAdapter;\n\n\t/**\n\t * Create an AuthStore with optional custom storage adapter.\n\t * @param storage Persistence backend. Defaults to `memoryStorage` (localStorage fallback).\n\t */\n\tconstructor(storage?: StorageAdapter) {\n\t\tthis.storage = storage ?? {\n\t\t\tget: (_key: string) => null,\n\t\t\tset: () => {},\n\t\t\tremove: () => {},\n\t\t};\n\t}\n\n\t/** The current JWT token string, or empty string if not authenticated. */\n\tget token(): string {\n\t\treturn this._token;\n\t}\n\n\t/** The current authenticated user record, or null. */\n\tget model(): AuthModel | null {\n\t\treturn this._model;\n\t}\n\n\t/** Whether a token exists (does not check expiry). */\n\tget isValid(): boolean {\n\t\treturn !!this._token;\n\t}\n\n\t/**\n\t * Whether the current token has expired (with a 30-second buffer).\n\t * Returns false when no expiry has been recorded (e.g. superuser tokens).\n\t */\n\tget isExpired(): boolean {\n\t\treturn (\n\t\t\tthis._tokenExpiresAt !== null &&\n\t\t\tDate.now() >= this._tokenExpiresAt - 30000\n\t\t);\n\t}\n\n\t/** The auth collection name used for automatic token refresh. */\n\tget collectionName(): string | null {\n\t\treturn this._collectionName;\n\t}\n\n\t/**\n\t * Set the auth collection name (used internally by auto-refresh).\n\t * @param name The collection name, or null for superuser tokens.\n\t */\n\tsetCollectionName(name: string | null): void {\n\t\tthis._collectionName = name;\n\t}\n\n\t/**\n\t * Load persisted auth state from storage.\n\t * Should be called once at application startup.\n\t */\n\tasync init(): Promise<void> {\n\t\tconst [token, model, expiresAt] = await Promise.all([\n\t\t\tthis.storage.get(\"auth_token\"),\n\t\t\tthis.storage.get(\"auth_model\"),\n\t\t\tthis.storage.get(\"auth_expires_at\"),\n\t\t]);\n\t\tif (token) this._token = token;\n\t\tif (expiresAt) this._tokenExpiresAt = parseInt(expiresAt, 10) || null;\n\t\tif (model) {\n\t\t\ttry {\n\t\t\t\tthis._model = JSON.parse(model);\n\t\t\t} catch {\n\t\t\t\t// ignore corrupt data\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Update the current auth token and model, persist to storage, and notify listeners.\n\t * @param token The JWT token string.\n\t * @param model The authenticated user record, or null for superusers.\n\t */\n\tset(token: string, model: AuthModel | null): void {\n\t\tthis._token = token;\n\t\tthis._model = model;\n\t\tthis._tokenExpiresAt = Date.now() + TOKEN_TTL_MS;\n\t\tvoid Promise.all([\n\t\t\tthis.storage.set(\"auth_token\", token),\n\t\t\tthis.storage.set(\"auth_expires_at\", String(this._tokenExpiresAt)),\n\t\t\tmodel\n\t\t\t\t? this.storage.set(\"auth_model\", JSON.stringify(model))\n\t\t\t\t: this.storage.remove(\"auth_model\"),\n\t\t]);\n\t\tthis.notify();\n\t}\n\n\t/**\n\t * Clear all auth state (token, model, expiry) and notify listeners.\n\t */\n\tclear(): void {\n\t\tthis._token = \"\";\n\t\tthis._model = null;\n\t\tthis._tokenExpiresAt = null;\n\t\tthis._collectionName = null;\n\t\tvoid Promise.all([\n\t\t\tthis.storage.remove(\"auth_token\"),\n\t\t\tthis.storage.remove(\"auth_expires_at\"),\n\t\t\tthis.storage.remove(\"auth_model\"),\n\t\t]);\n\t\tthis.notify();\n\t}\n\n\t/**\n\t * Register a listener for auth state changes.\n\t * @param fn Callback invoked with (model, token) on every change.\n\t * @returns An unsubscribe function.\n\t */\n\tonChange(fn: AuthListener): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\tprivate notify(): void {\n\t\tfor (const fn of this.listeners) {\n\t\t\tfn(this._model, this._token);\n\t\t}\n\t}\n}\n\n// ── Memory-only storage (default, works everywhere) ─────\n/** Default storage adapter using `localStorage` with graceful fallback. */\nexport const memoryStorage: StorageAdapter = {\n\tget(key: string) {\n\t\ttry {\n\t\t\treturn localStorage.getItem(key);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t},\n\tset(key: string, value: string) {\n\t\ttry {\n\t\t\tlocalStorage.setItem(key, value);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t},\n\tremove(key: string) {\n\t\ttry {\n\t\t\tlocalStorage.removeItem(key);\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t},\n};\n","// ── Collection Service ──────────────────────────────────\n// Typed CRUD for a single collection (like PocketBase's pb.collection(name))\n\nimport type { HttpClient } from \"./http\";\nimport type { AuthStore, AuthModel } from \"./auth\";\nimport type {\n\tApiRecord,\n\tListResult,\n\tRequestOptions,\n\tCreateData,\n\tUpdateData,\n} from \"./types\";\nimport type { RealtimeService } from \"./realtime\";\n\n/**\n * A realtime record-change event delivered to subscription callbacks.\n * Mirrors PocketBase's RealtimeService result shape (`action` + `record`).\n */\nexport interface RealtimeMessage {\n\taction: \"create\" | \"update\" | \"delete\";\n\trecord: Record<string, unknown>;\n\ttopic?: string;\n}\n\n/** Subscription callback for a collection's realtime events. */\nexport type RealtimeCallback = (e: RealtimeMessage) => void;\n\n/** Raw event passed by the low-level realtime service. */\ninterface RealtimeEventLike {\n\tevent: string;\n\ttopic: string;\n\tpayload?: Record<string, unknown>;\n}\n\n/** Map a raw event/action to a normalised create/update/delete action. */\nfunction normalizeAction(\n\tevent: string,\n\trawAction?: unknown,\n): RealtimeMessage[\"action\"] {\n\tif (typeof rawAction === \"string\") {\n\t\tconst a = rawAction.toLowerCase();\n\t\tif (a === \"create\" || a === \"update\" || a === \"delete\") {\n\t\t\treturn a;\n\t\t}\n\t}\n\tif (event === \"record_change\") return \"update\";\n\tif (event === \"create\" || event === \"record_create\") return \"create\";\n\tif (event === \"delete\" || event === \"record_delete\") return \"delete\";\n\treturn \"update\";\n}\n\n/**\n * Typed CRUD service for a single dynamic collection.\n * Get an instance via {@link LazypockClient.collection}.\n *\n * @typeParam T — The record shape for this collection. Defaults to {@link ApiRecord}.\n */\nexport class CollectionService<T = ApiRecord> {\n\tprivate http: HttpClient;\n\tprivate collectionName: string;\n\tprivate authStore?: AuthStore;\n\tprivate realtime?: RealtimeService;\n\n\t/** @internal */\n\tconstructor(\n\t\thttp: HttpClient,\n\t\tcollectionName: string,\n\t\tauthStore?: AuthStore,\n\t\trealtime?: RealtimeService,\n\t) {\n\t\tthis.http = http;\n\t\tthis.collectionName = collectionName;\n\t\tthis.authStore = authStore;\n\t\tthis.realtime = realtime;\n\t}\n\n\tprivate encodeId(id: string): string {\n\t\treturn encodeURIComponent(id);\n\t}\n\n\t/**\n\t * Fetch a paginated list of records (PocketBase `getList`).\n\t *\n\t * @param page Page number (default 1).\n\t * @param perPage Records per page (default 30).\n\t * @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.\n\t */\n\tgetList<T2 = T>(\n\t\tpage = 1,\n\t\tperPage = 30,\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<ListResult<T2> | null> {\n\t\tconst {\n\t\t\trequestKey,\n\t\t\tautoCancel,\n\t\t\tcancelKey,\n\t\t\tfetch,\n\t\t\theaders,\n\t\t\tsignal,\n\t\t\tcache,\n\t\t\tttl,\n\t\t\tinvalidate,\n\t\t\tparams,\n\t\t\t...queryParams\n\t\t} = options ?? {};\n\t\tconst qs = new URLSearchParams(\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.entries({\n\t\t\t\t\tpage: String(page),\n\t\t\t\t\tperPage: String(perPage),\n\t\t\t\t\t...queryParams,\n\t\t\t\t}).map(([k, v]) => [k, String(v)]),\n\t\t\t),\n\t\t).toString();\n\t\treturn this.http.get<ListResult<T2>>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"?\" + qs,\n\t\t\t{\n\t\t\t\trequestKey,\n\t\t\t\tautoCancel,\n\t\t\t\tcancelKey,\n\t\t\t\tfetch,\n\t\t\t\theaders,\n\t\t\t\tsignal,\n\t\t\t\tcache,\n\t\t\t\tttl,\n\t\t\t\tinvalidate,\n\t\t\t\tparams,\n\t\t\t} as RequestOptions,\n\t\t);\n\t}\n\n\t/**\n\t * Fetch all records at once (auto-paginates). Mirrors PocketBase's\n\t * `pb.collection(name).getFullList()`.\n\t *\n\t * @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.\n\t */\n\tasync getFullList<T2 = T>(\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<Array<T2>> {\n\t\tconst { batch = 1000, ...rest } = options ?? {};\n\t\tconst items: T2[] = [];\n\t\tlet page = 1;\n\t\tfor (;;) {\n\t\t\tconst res = await this.getList<T2>(\n\t\t\t\tpage,\n\t\t\t\tbatch as number,\n\t\t\t\t{\n\t\t\t\t\t// disable auto-cancellation across pages — each page request is unique\n\t\t\t\t\t...rest,\n\t\t\t\t\trequestKey: null,\n\t\t\t\t} as Record<string, unknown> & RequestOptions,\n\t\t\t);\n\t\t\tif (!res || !res.items || res.items.length === 0) break;\n\t\t\titems.push(...(res.items as T2[]));\n\t\t\tif (page >= (res.totalPages ?? page)) break;\n\t\t\tpage += 1;\n\t\t}\n\t\treturn items;\n\t}\n\n\t/**\n\t * Fetch the first record matching a filter (PocketBase `getFirstListItem`).\n\t *\n\t * @param filter Filter expression (e.g. `title = 'x'`).\n\t * @param options Optional request options.\n\t */\n\tasync getFirstListItem<T2 = T>(\n\t\tfilter: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T2 | null> {\n\t\tconst res = await this.getList<T2>(1, 1, {\n\t\t\t...options,\n\t\t\tfilter,\n\t\t});\n\t\treturn res?.items?.[0] ?? null;\n\t}\n\n\t/**\n\t * Get a single record by ID.\n\t * @param id Record ID.\n\t * @param options Optional request options.\n\t */\n\tgetOne(id: string, options?: RequestOptions): Promise<T | null> {\n\t\treturn this.http.get<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new record.\n\t * @param data Record fields. When `T` is a concrete shape (e.g. a generated\n\t * record type), excess/unknown fields are rejected at compile time.\n\t * @param options Optional request options.\n\t */\n\tcreate(\n\t\tdata: T extends ApiRecord ? Record<string, unknown> : CreateData<T>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http.post<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName),\n\t\t\tdata,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Update a record by ID.\n\t * @param id Record ID.\n\t * @param data Updated record fields. When `T` is a concrete shape, `data`\n\t * must be a partial of `T` — unknown fields are rejected.\n\t * @param options Optional request options.\n\t */\n\tupdate(\n\t\tid: string,\n\t\tdata: T extends ApiRecord ? Record<string, unknown> : UpdateData<T>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http.patch<T>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\tdata,\n\t\t\toptions,\n\t\t);\n\t}\n\n\t/**\n\t * Delete a record by ID.\n\t * @param id Record ID.\n\t * @param options Optional request options.\n\t */\n\tdelete(id: string, options?: RequestOptions): Promise<null> {\n\t\treturn this.http.delete(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/\" + this.encodeId(id),\n\t\t\toptions,\n\t\t);\n\t}\n\t// ── Expand / Relation Fields ──\n\n\t/**\n\t * Get a list of expandable (relation) fields for this collection.\n\t * Useful for constructing `expand` query parameters.\n\t */\n\tasync expandFields(\n\t\toptions?: RequestOptions,\n\t): Promise<{ field: string; targetCollection: string }[] | null> {\n\t\tconst data = await this.http.get<{\n\t\t\tfields?: {\n\t\t\t\tname: string;\n\t\t\t\ttype: string;\n\t\t\t\toptions?: Record<string, string>;\n\t\t\t}[];\n\t\t}>(\"/collections/\" + this.encodeId(this.collectionName), options);\n\t\tif (!data?.fields) return null;\n\t\treturn data.fields\n\t\t\t.filter((f) => f.type === \"relation\" && f.options?.collection)\n\t\t\t.map((f) => ({\n\t\t\t\tfield: f.name,\n\t\t\t\ttargetCollection: f.options!.collection,\n\t\t\t}));\n\t}\n\n\t/**\n\t * Cast this service to a specific record shape.\n\t * Use when you have a hand-written or generated interface for the\n\t * collection and want compile-time checking of create/update/list.\n\t *\n\t * @example\n\t * ```ts\n\t * interface Post {\n\t * id: string;\n\t * title: string;\n\t * published: boolean;\n\t * }\n\t * const posts = client.collection(\"posts\").typed<Post>();\n\t * await posts.create({ title: \"Hi\", published: true }); // ✓\n\t * await posts.create({ nope: 1 }); // ✗ compile error\n\t * ```\n\t */\n\ttyped<TRecord = ApiRecord>(): CollectionService<TRecord> {\n\t\treturn this as unknown as CollectionService<TRecord>;\n\t}\n\n\t// ── Realtime Subscriptions (PocketBase-style) ──\n\n\t/**\n\t * Subscribe to realtime changes for this collection.\n\t * The event's `action` is one of `\"create\" | \"update\" | \"delete\"`.\n\t *\n\t * Access is governed by the collection's `listRule` (PocketBase semantics):\n\t * public collections allow anonymous subscriptions; other collections\n\t * require a matching logged-in user or superuser.\n\t *\n\t * @param callback Received on every record change.\n\t * @param recordId Optional — subscribe to a single record instead of `*`.\n\t * @returns A function that unsubscribes this callback.\n\t */\n\tsubscribe(callback: RealtimeCallback, recordId?: string): () => void {\n\t\tif (!this.realtime) {\n\t\t\tconsole.warn(\"[lazypock] No realtime service configured.\");\n\t\t\treturn () => {};\n\t\t}\n\t\tconst topic =\n\t\t\t\"collection:\" + this.collectionName + (recordId ? \":\" + recordId : \"\");\n\t\tconst handler = (raw: RealtimeEventLike) => {\n\t\t\tconst record = (raw.payload?.[\"record\"] ?? {}) as Record<string, unknown>;\n\t\t\tcallback({\n\t\t\t\taction: normalizeAction(raw.event, raw.payload?.[\"action\"]),\n\t\t\t\trecord,\n\t\t\t\ttopic: raw.topic,\n\t\t\t});\n\t\t};\n\t\tthis.realtime.ensureConnected();\n\t\tthis.realtime.subscribe(topic, handler as never);\n\t\treturn () => this.realtime?.unsubscribe(topic, handler as never);\n\t}\n\n\t/**\n\t * Unsubscribe all callbacks from this collection (or a specific record).\n\t * @param recordId Optional record id; omitting it unsubs everything.\n\t */\n\tunsubscribe(recordId?: string): void {\n\t\tconst topic =\n\t\t\t\"collection:\" + this.collectionName + (recordId ? \":\" + recordId : \"\");\n\t\tthis.realtime?.unsubscribe(topic);\n\t}\n\n\t// ── Auth Collection Methods ──\n\n\t/**\n\t * Authenticate with email/password against this auth collection.\n\t * Stores the returned token and user model in the auth store.\n\t */\n\tasync authWithPassword(\n\t\tidentity: string,\n\t\tpassword: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-with-password\",\n\t\t\t{ identity, password },\n\t\t\toptions,\n\t\t);\n\t\tif (data && this.authStore) {\n\t\t\tthis.authStore.setCollectionName(this.collectionName);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Refresh the auth token for the currently authenticated user.\n\t * Updates the stored token and user model.\n\t */\n\tasync authRefresh(\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-refresh\",\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t\tif (data && this.authStore) {\n\t\t\tthis.authStore.setCollectionName(this.collectionName);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Get available auth methods for this collection.\n\t */\n\t// ── end Realtime ──\n\n\tasync authMethods(\n\t\toptions?: RequestOptions,\n\t): Promise<Record<string, unknown> | null> {\n\t\treturn this.http.get<Record<string, unknown>>(\n\t\t\t\"/\" + this.encodeId(this.collectionName) + \"/auth-methods\",\n\t\t\toptions,\n\t\t);\n\t}\n}\n","// ── Phoenix Channel WebSocket Client ──────────────────\n//\n// Implements the Phoenix Channels protocol over WebSocket\n// to subscribe to collection realtime updates.\n//\n// Protocol: Phoenix V1 JSON Serializer (object-based messages).\n// Sends messages as JSON objects with {topic, event, payload, ref, join_ref}.\n// Receives messages as JSON objects with {topic, event, payload, ref}.\n\ninterface RealtimeEvent {\n\tevent: string;\n\ttopic: string;\n\tpayload: Record<string, unknown>;\n}\n\ninterface SubEntry {\n\ttopic: string;\n\tcallback: (e: RealtimeEvent) => void;\n}\n\nexport type RealtimeConnectOpts = {\n\t/** WebSocket URL (e.g. ws://localhost:4000/socket/websocket) */\n\turl: string;\n\t/** Auth token to pass as query param */\n\ttoken?: string;\n};\n\n/**\n * Derive a WebSocket URL from an HTTP base URL.\n * http://localhost:4000/api → ws://localhost:4000/socket/websocket\n */\nexport function wsUrlFromBaseUrl(baseUrl: string): string {\n\ttry {\n\t\tconst url = new URL(baseUrl);\n\t\tconst protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n\t\treturn `${protocol}//${url.host}/socket/websocket`;\n\t} catch {\n\t\treturn `${baseUrl.replace(/^http/, \"ws\").replace(/\\/api$/, \"\")}/socket/websocket`;\n\t}\n}\n\n/**\n * Phoenix Channel client for real-time collection subscriptions.\n *\n * Connects via WebSocket and subscribes to collection topics.\n * Includes automatic reconnection with exponential backoff.\n *\n * @example\n * ```ts\n * const rt = new RealtimeService();\n * rt.connect({ url: wsUrlFromBaseUrl('http://localhost:4000/api') });\n * rt.subscribe('collection:posts', (e) => console.log(e));\n * ```\n */\nexport class RealtimeService {\n\tprivate ws: WebSocket | null = null;\n\tprivate refCounter = 0;\n\tprivate subscriptions = new Map<string, SubEntry[]>();\n\tprivate reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\tprivate reconnectAttempt = 0;\n\tprivate maxReconnectDelay = 5000;\n\n\t// Callbacks for connection state\n\tonReconnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (err: Event) => void;\n\n\tprivate url: string = \"\";\n\tprivate token: string | undefined;\n\n\t/** Whether the WebSocket is currently open. */\n\tget isOpen(): boolean {\n\t\treturn this.ws?.readyState === WebSocket.OPEN;\n\t}\n\n\t/**\n\t * The most recently used WebSocket URL (set on {@link connect}).\n\t * Useful for SDK convenience methods that auto-connect before subscribing.\n\t */\n\tget lastUrl(): string {\n\t\treturn this.url;\n\t}\n\n\t/** The auth token configured for this connection (set on connect). */\n\tget lastToken(): string | undefined {\n\t\treturn this.token;\n\t}\n\n\t/**\n\t * Set the socket URL. Useful before subscribing so the SDK can\n\t * auto-connect on the first {@link subscribe}.\n\t */\n\tsetUrl(url: string): void {\n\t\tthis.url = url;\n\t}\n\n\t/*\n\t * Ensure the socket is connected, then subscribe.\n\t * Used by collection-level convenience wrappers so a connection is opened\n\t * automatically on the first subscribe (matching PocketBase behaviour —\n\t * works for anonymous/public collections too).\n\t */\n\tensureConnected(): void {\n\t\tif (this.isOpen || !this.url) return;\n\t\tif (typeof WebSocket === \"undefined\") return;\n\t\tthis.doConnect();\n\t}\n\n\tconnect(opts: RealtimeConnectOpts): void {\n\t\tthis.url = opts.url;\n\t\tthis.token = opts.token;\n\t\tthis.reconnectAttempt = 0;\n\t\tthis.doConnect();\n\t}\n\n\tdisconnect(): void {\n\t\tthis.clearReconnectTimer();\n\t\tthis.ws?.close();\n\t\tthis.ws = null;\n\t}\n\n\t/**\n\t * Subscribe to a topic (e.g. \"collection:posts\" or \"collection:posts:*\").\n\t * The backend Channel authorizes via listRule on join.\n\t */\n\tsubscribe(topic: string, callback: (e: RealtimeEvent) => void): void {\n\t\tconst subs = this.subscriptions.get(topic) || [];\n\t\tsubs.push({ topic, callback });\n\t\tthis.subscriptions.set(topic, subs);\n\n\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\tthis.joinTopic(topic);\n\t\t}\n\t}\n\n\t/**\n\t * Unsubscribe a specific callback from a topic.\n\t */\n\tunsubscribe(topic: string, callback?: (e: RealtimeEvent) => void): void {\n\t\tif (!callback) {\n\t\t\tthis.subscriptions.delete(topic);\n\t\t\treturn;\n\t\t}\n\t\tconst subs = this.subscriptions\n\t\t\t.get(topic)\n\t\t\t?.filter((s) => s.callback !== callback);\n\t\tif (subs && subs.length > 0) {\n\t\t\tthis.subscriptions.set(topic, subs);\n\t\t} else {\n\t\t\tthis.subscriptions.delete(topic);\n\t\t}\n\t}\n\n\tprivate resubscribeAll(): void {\n\t\tfor (const topic of this.subscriptions.keys()) {\n\t\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\tthis.joinTopic(topic);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate doConnect(): void {\n\t\tif (typeof WebSocket === \"undefined\") {\n\t\t\tconsole.warn(\n\t\t\t\t\"[lazypock] WebSocket not available — realtime subscriptions disabled\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tlet url = this.url;\n\t\tif (this.token) {\n\t\t\turl +=\n\t\t\t\t(url.includes(\"?\") ? \"&\" : \"?\") +\n\t\t\t\t\"token=\" +\n\t\t\t\tencodeURIComponent(this.token);\n\t\t}\n\n\t\tthis.ws = new WebSocket(url);\n\n\t\tthis.ws.onopen = () => {\n\t\t\tthis.reconnectAttempt = 0;\n\t\t\tthis.resubscribeAll();\n\t\t\tthis.startHeartbeat();\n\t\t};\n\n\t\tthis.ws.onmessage = (msg: MessageEvent) => {\n\t\t\tthis.handleMessage(msg.data);\n\t\t};\n\n\t\tthis.ws.onclose = () => {\n\t\t\tthis.stopHeartbeat();\n\t\t\tthis.onDisconnect?.();\n\t\t\tthis.scheduleReconnect();\n\t\t};\n\n\t\tthis.ws.onerror = (err: Event) => {\n\t\t\tthis.onError?.(err);\n\t\t};\n\t}\n\n\tprivate handleMessage(data: string): void {\n\t\tlet parsed: Record<string, unknown>;\n\t\ttry {\n\t\t\tparsed = JSON.parse(data) as Record<string, unknown>;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof parsed !== \"object\" || !parsed.topic || !parsed.event) return;\n\n\t\tconst topic = parsed.topic as string;\n\t\tconst event = parsed.event as string;\n\t\tconst payload = (parsed.payload as Record<string, unknown>) || {};\n\n\t\t// Handle phx_reply (join/heartbeat responses)\n\t\tif (event === \"phx_reply\") return;\n\n\t\t// Relay incoming events to all subscribers of this topic\n\t\tconst subs = this.subscriptions.get(topic);\n\t\tif (subs) {\n\t\t\tconst e: RealtimeEvent = {\n\t\t\t\tevent,\n\t\t\t\ttopic,\n\t\t\t\tpayload: payload as Record<string, unknown>,\n\t\t\t};\n\t\t\tfor (const s of subs) {\n\t\t\t\ttry {\n\t\t\t\t\ts.callback(e);\n\t\t\t\t} catch {\n\t\t\t\t\t// swallow callback errors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate joinTopic(topic: string): void {\n\t\tconst ref = this.nextRef();\n\t\t// Phoenix V1 JSON Serializer expects a JSON object, not an array\n\t\tconst msg = JSON.stringify({\n\t\t\ttopic: topic,\n\t\t\tevent: \"phx_join\",\n\t\t\tpayload: {},\n\t\t\tref: ref,\n\t\t});\n\t\tthis.ws?.send(msg);\n\t}\n\n\tprivate nextRef(): string {\n\t\tthis.refCounter++;\n\t\treturn this.refCounter.toString();\n\t}\n\n\t// ── Heartbeat ──\n\n\tprivate heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n\n\tprivate startHeartbeat(): void {\n\t\tthis.stopHeartbeat();\n\t\tthis.heartbeatInterval = setInterval(() => {\n\t\t\tif (this.ws?.readyState === WebSocket.OPEN) {\n\t\t\t\tconst ref = this.nextRef();\n\t\t\t\t// Phoenix V1 JSON Serializer expects a JSON object\n\t\t\t\tconst msg = JSON.stringify({\n\t\t\t\t\ttopic: \"phoenix\",\n\t\t\t\t\tevent: \"heartbeat\",\n\t\t\t\t\tpayload: {},\n\t\t\t\t\tref: ref,\n\t\t\t\t});\n\t\t\t\tthis.ws.send(msg);\n\t\t\t}\n\t\t}, 30_000);\n\t}\n\n\tprivate stopHeartbeat(): void {\n\t\tif (this.heartbeatInterval) {\n\t\t\tclearInterval(this.heartbeatInterval);\n\t\t\tthis.heartbeatInterval = null;\n\t\t}\n\t}\n\n\t// ── Reconnect ──\n\n\tprivate scheduleReconnect(): void {\n\t\tthis.clearReconnectTimer();\n\t\tconst delay = Math.min(\n\t\t\t1000 * 2 ** this.reconnectAttempt,\n\t\t\tthis.maxReconnectDelay,\n\t\t);\n\t\tthis.reconnectAttempt++;\n\t\tthis.reconnectTimer = setTimeout(() => {\n\t\t\tthis.reconnectTimer = null;\n\t\t\tthis.onReconnect?.();\n\t\t\tthis.doConnect();\n\t\t}, delay);\n\t}\n\n\tprivate clearReconnectTimer(): void {\n\t\tif (this.reconnectTimer) {\n\t\t\tclearTimeout(this.reconnectTimer);\n\t\t\tthis.reconnectTimer = null;\n\t\t}\n\t}\n}\n","// ── File Service ─────────────────────────────────────────\n// Upload, download, and delete files.\n\nimport type { HttpClient } from \"./http\";\nimport type { RequestOptions } from \"./types\";\n\n/** Response shape from the server file endpoints */\nexport interface FileRecord {\n\tid: string;\n\tfilename: string;\n\tmimeType: string;\n\tsize: number;\n\turl: string;\n\t/** Map of thumbnail size => URL, e.g. { \"50x50\": \"/api/files/<id>/thumbs/50x50\" } */\n\tthumbs?: Record<string, string>;\n\t[key: string]: unknown;\n}\n\n/**\n * Construct a file URL from the API base URL and file ID.\n */\nexport function getFileUrl(baseUrl: string, fileId: string): string {\n\treturn baseUrl.replace(/\\/+$/, \"\") + \"/files/\" + encodeURIComponent(fileId);\n}\n\n/**\n * Construct a thumbnail URL from the API base URL, file ID, and thumb size.\n * @param size e.g. \"50x50\"\n */\nexport function getThumbUrl(baseUrl: string, fileId: string, size: string): string {\n\treturn (\n\t\tbaseUrl.replace(/\\/+$/, \"\") +\n\t\t\"/files/\" +\n\t\tencodeURIComponent(fileId) +\n\t\t\"/thumbs/\" +\n\t\tencodeURIComponent(size)\n\t);\n}\n\n/**\n * Construct an on-demand scaled image URL from the API base URL, file ID, and size.\n *\n * The size is an ImageMagick geometry: \"100\" (width, keep aspect), \"100x100\"\n * (fit within box), \"100x100!\" (exact crop), \"x200\" (height). The server\n * generates and caches the scaled image on first request.\n * @param size e.g. \"100x100\"\n */\nexport function getScaleUrl(baseUrl: string, fileId: string, size: string): string {\n\treturn (\n\t\tbaseUrl.replace(/\\/+$/, \"\") +\n\t\t\"/files/\" +\n\t\tencodeURIComponent(fileId) +\n\t\t\"/scale/\" +\n\t\tencodeURIComponent(size)\n\t);\n}\n\n\n/**\n * Service for file upload, retrieval, and deletion.\n * Access via {@link LazypockClient.files}.\n */\nexport class FilesService {\n\tconstructor(private http: HttpClient) {}\n\n\t/**\n\t * Upload a file or blob.\n\t *\n\t * @param file The File or Blob to upload.\n\t * @param filename Optional filename (required if `file` is a Blob without a name).\n\t * @param options Optional request options (signal, custom fetch).\n\t * @param meta Optional metadata: collectionName, recordId, fieldName for ownership tracking.\n\t */\n\tasync upload(\n\t\tfile: File | Blob,\n\t\tfilename?: string,\n\t\toptions?: RequestOptions,\n\t\tmeta?: { collectionName?: string; recordId?: string; fieldName?: string },\n\t): Promise<FileRecord | null> {\n\t\tif (typeof FormData === \"undefined\") {\n\t\t\tthrow new Error(\"FormData is not available in this environment\");\n\t\t}\n\n\t\tconst formData = new FormData();\n\t\tconst name = filename || (file instanceof File ? file.name : \"file\");\n\t\tformData.append(\"file\", file, name);\n\n\t\tif (meta?.collectionName)\n\t\t\tformData.append(\"collection_name\", meta.collectionName);\n\t\tif (meta?.recordId) formData.append(\"record_id\", meta.recordId);\n\t\tif (meta?.fieldName) formData.append(\"field_name\", meta.fieldName);\n\n\t\tconst data = await this.http.request<Record<string, unknown>>(\n\t\t\t\"POST\",\n\t\t\t\"/files\",\n\t\t\tformData,\n\t\t\toptions,\n\t\t);\n\n\t\treturn data as FileRecord | null;\n\t}\n\n\t/**\n\t * List uploaded files (newest first), with optional filters.\n\t *\n\t * @param options Filters and pagination.\n\t */\n\tasync list(options?: {\n\t\tpage?: number;\n\t\tperPage?: number;\n\t\tcollectionName?: string;\n\t\tfieldName?: string;\n\t\tmime?: string;\n\t}): Promise<{ items: FileRecord[]; page: number; perPage: number; total: number }> {\n\t\tconst params: Record<string, string> = {};\n\t\tif (options?.page !== undefined) params[\"page\"] = String(options.page);\n\t\tif (options?.perPage !== undefined) params[\"perPage\"] = String(options.perPage);\n\t\tif (options?.collectionName) params[\"collectionName\"] = options.collectionName;\n\t\tif (options?.fieldName) params[\"fieldName\"] = options.fieldName;\n\t\tif (options?.mime) params[\"mime\"] = options.mime;\n\n\t\tconst data = await this.http.request<{\n\t\t\titems: FileRecord[];\n\t\t\tpage: number;\n\t\t\tperPage: number;\n\t\t\ttotal: number;\n\t\t}>(\"GET\", \"/files\", undefined, { params });\n\t\treturn (\n\t\t\tdata ?? { items: [], page: 1, perPage: 50, total: 0 }\n\t\t) as {\n\t\t\titems: FileRecord[];\n\t\t\tpage: number;\n\t\t\tperPage: number;\n\t\t\ttotal: number;\n\t\t};\n\t}\n\n\t/**\n\t * Fetch file metadata including URL.\n\t * @param fileId The file ID.\n\t */\n\n\t/**\n\t * Fetch file metadata including URL.\n\t * @param fileId The file ID.\n\t */\n\tasync getUrl(fileId: string): Promise<string | null> {\n\t\tconst data = await this.http.request<Record<string, unknown>>(\n\t\t\t\"GET\",\n\t\t\t\"/files/\" + encodeURIComponent(fileId),\n\t\t);\n\t\tif (data && typeof data === \"object\" && \"url\" in data) {\n\t\t\treturn (data as Record<string, unknown>).url as string;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Delete a file by ID.\n\t * @param fileId The file ID.\n\t * @param options Optional request options.\n\t */\n\tasync delete(fileId: string, options?: RequestOptions): Promise<null> {\n\t\treturn this.http.request<null>(\n\t\t\t\"DELETE\",\n\t\t\t\"/files/\" + encodeURIComponent(fileId),\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t}\n}\n","// ── Collections Service ─────────────────────────────────\n// Registry-level service for collections (CRUD + realtime registry events),\n// mirroring PocketBase's `pb.collections` service.\n//\n// Get an instance via {@link LazypockClient.collections}.\n//\n// This is distinct from `CollectionService` (single collection record\n// events) — it operates on the *collections* themselves: listing / creating /\n// updating / deleting collections via `/api/collections`, and subscribing to\n// the `collections` registry channel (AdminChannel), which fires when\n// collections themselves are created / updated / deleted.\n\nimport type { HttpClient } from \"./http\";\nimport type { RealtimeService } from \"./realtime\";\nimport type { ListResult, RequestOptions, ApiRecord } from \"./types\";\n\nconst REGISTRY_TOPIC = \"collections\";\n\n/**\n * Registry-level realtime events for the collections admin channel.\n * The backend (AdminChannel) broadcasts the action as the *event name*,\n * with the collection JSON as the payload.\n */\nexport interface CollectionsMessage {\n\taction: \"create\" | \"update\" | \"delete\";\n\t/** The collection payload (id + metadata), or {} when unavailable. */\n\tcollection: Record<string, unknown>;\n\ttopic?: string;\n}\n\n/**\n * Registry service for collections (list/create/update/delete + realtime\n * registry events). Mirrors PocketBase's `pb.collections`.\n */\nexport class CollectionsService {\n\tprivate http?: HttpClient;\n\tprivate realtime?: RealtimeService;\n\n\t/** @internal */\n\tconstructor(http?: HttpClient, realtime?: RealtimeService) {\n\t\tthis.http = http;\n\t\tthis.realtime = realtime;\n\t}\n\n\t/**\n\t * Fetch a paginated list of collections (admin).\n\t *\n\t * @param params Optional query params (`page`, `perPage`, `filter`, `sort`).\n\t * @param options Optional request options.\n\t */\n\tasync getList<T = ApiRecord>(\n\t\tparams?: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<ListResult<T> | null> {\n\t\tconst qs = params\n\t\t\t? \"?\" +\n\t\t\t\tnew URLSearchParams(\n\t\t\t\t\tObject.fromEntries(\n\t\t\t\t\t\tObject.entries(params).map(([k, v]) => [k, String(v)]),\n\t\t\t\t\t),\n\t\t\t\t).toString()\n\t\t\t: \"\";\n\t\treturn this.http?.get<ListResult<T>>(\"/collections\" + qs, options) ?? null;\n\t}\n\n\t/**\n\t * Fetch all collections at once (auto-paginates). Mirrors PocketBase's\n\t * `pb.collections.getFullList()` — defaults to listing everything.\n\t *\n\t * @param options Query params (`sort`, `batch`, etc.) or request options.\n\t */\n\tasync getFullList<T = ApiRecord>(\n\t\toptions?: Record<string, unknown> & RequestOptions,\n\t): Promise<Array<T>> {\n\t\tif (!this.http) return [];\n\t\tconst { batch = 1000, ...rest } = options ?? {};\n\t\tconst items: T[] = [];\n\t\tlet page = 1;\n\t\t// Auto-paginate until empty (bounded by perPage and totalPages).\n\t\tfor (;;) {\n\t\t\tconst res = await this.getList<T>({\n\t\t\t\t...rest,\n\t\t\t\tpage,\n\t\t\t\tperPage: batch,\n\t\t\t} as Record<string, unknown>);\n\t\t\tif (!res || !res.items || res.items.length === 0) break;\n\t\t\titems.push(...(res.items as T[]));\n\t\t\tif (page >= (res.totalPages ?? page)) break;\n\t\t\tpage += 1;\n\t\t}\n\t\treturn items;\n\t}\n\n\t/**\n\t * Get a single collection by ID or name (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param options Optional request options.\n\t */\n\tasync getOne<T = ApiRecord>(\n\t\tid: string,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn (\n\t\t\tthis.http?.get<T>(\"/collections/\" + encodeURIComponent(id), options) ??\n\t\t\tnull\n\t\t);\n\t}\n\n\t/**\n\t * Create a new collection (admin).\n\t *\n\t * @param data Collection definition (name, type, fields, options, rules, etc.).\n\t * @param options Optional request options.\n\t */\n\tasync create<T = ApiRecord>(\n\t\tdata: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn this.http?.post<T>(\"/collections\", data, options) ?? null;\n\t}\n\n\t/**\n\t * Update an existing collection (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param data Updated collection fields.\n\t * @param options Optional request options.\n\t */\n\tasync update<T = ApiRecord>(\n\t\tid: string,\n\t\tdata: Record<string, unknown>,\n\t\toptions?: RequestOptions,\n\t): Promise<T | null> {\n\t\treturn (\n\t\t\tthis.http?.patch<T>(\n\t\t\t\t\"/collections/\" + encodeURIComponent(id),\n\t\t\t\tdata,\n\t\t\t\toptions,\n\t\t\t) ?? null\n\t\t);\n\t}\n\n\t/**\n\t * Delete a collection (admin).\n\t *\n\t * @param id Collection ID or name.\n\t * @param options Optional request options.\n\t */\n\tasync delete(id: string, options?: RequestOptions): Promise<boolean> {\n\t\tconst res = this.http?.delete(\n\t\t\t\"/collections/\" + encodeURIComponent(id),\n\t\t\toptions,\n\t\t);\n\t\treturn res == null ? false : true;\n\t}\n\n\t/**\n\t * Subscribe to collection registry changes.\n\t *\n\t * @param callback Received on every collection create/update/delete.\n\t * @returns A function that unsubscribes this callback.\n\t */\n\tsubscribe(callback: (e: CollectionsMessage) => void): () => void {\n\t\tif (!this.realtime) {\n\t\t\tconsole.warn(\"[lazypock] No realtime service configured.\");\n\t\t\treturn () => {};\n\t\t}\n\t\tconst handler = (raw: {\n\t\t\tevent: string;\n\t\t\ttopic: string;\n\t\t\tpayload?: Record<string, unknown>;\n\t\t}) => {\n\t\t\tcallback({\n\t\t\t\taction: normalizeAction(raw.event),\n\t\t\t\tcollection: (raw.payload ?? {}) as Record<string, unknown>,\n\t\t\t\ttopic: raw.topic,\n\t\t\t});\n\t\t};\n\t\tthis.realtime.ensureConnected();\n\t\tthis.realtime.subscribe(REGISTRY_TOPIC, handler as never);\n\t\treturn () => this.realtime?.unsubscribe(REGISTRY_TOPIC, handler as never);\n\t}\n\n\t/**\n\t * Unsubscribe all callbacks from the registry channel.\n\t */\n\tunsubscribe(): void {\n\t\tthis.realtime?.unsubscribe(REGISTRY_TOPIC);\n\t}\n}\n\n/** Map a registry event name (create/update/delete) to an action. */\nfunction normalizeAction(event: string): CollectionsMessage[\"action\"] {\n\tconst e = event.toLowerCase();\n\tif (e === \"create\") return \"create\";\n\tif (e === \"update\") return \"update\";\n\tif (e === \"delete\") return \"delete\";\n\treturn \"update\";\n}\n","// ── Type mapping (runtime + codegen) ────────────────────\n// Maps server field types to TypeScript types.\n// Shared by the runtime `SchemaTypes` helper and the codegen CLI.\n\nimport type { SchemaField } from \"./schema\";\n\n/**\n * Map a single server field to its TypeScript type string.\n * Used by the codegen CLI to emit interface members.\n *\n * @param field The field definition.\n * @param fallback Fallback type for unknown field types (default `unknown`).\n */\nexport function fieldTypeScriptType(\n\tfield: SchemaField,\n\tfallback = \"unknown\",\n): string {\n\tconst opts = field.options ?? {};\n\tswitch (field.type) {\n\t\tcase \"text\":\n\t\tcase \"email\":\n\t\tcase \"url\":\n\t\tcase \"editor\":\n\t\tcase \"date\":\n\t\tcase \"datetime\":\n\t\t\treturn \"string\";\n\t\tcase \"number\":\n\t\t\treturn \"number\";\n\t\tcase \"bool\":\n\t\t\treturn \"boolean\";\n\t\tcase \"select\": {\n\t\t\tconst values = Array.isArray(opts.values) ? opts.values : [];\n\t\t\tif (values.length > 0) {\n\t\t\t\treturn values.map((v) => JSON.stringify(String(v))).join(\" | \");\n\t\t\t}\n\t\t\treturn \"string\";\n\t\t}\n\t\tcase \"multi_select\": {\n\t\t\tconst values = Array.isArray(opts.values) ? opts.values : [];\n\t\t\tif (values.length > 0) {\n\t\t\t\treturn `(${values.map((v) => JSON.stringify(String(v))).join(\" | \")})[]`;\n\t\t\t}\n\t\t\treturn \"string[]\";\n\t\t}\n\t\tcase \"file\":\n\t\t\treturn \"string\";\n\t\tcase \"multi_file\":\n\t\t\treturn \"string[]\";\n\t\tcase \"json\":\n\t\tcase \"geo\":\n\t\t\treturn \"Record<string, unknown>\";\n\t\tcase \"relation\":\n\t\t\t// Relations store the target record's ID (string) — or an array\n\t\t\t// of IDs when multi-relation (maxSelect > 1).\n\t\t\treturn (opts.maxSelect ?? 1) > 1 ? \"string[]\" : \"string\";\n\t\tcase \"password\":\n\t\t\t// Passwords are write-only; never expose on read models.\n\t\t\treturn \"never\";\n\t\tdefault:\n\t\t\treturn fallback;\n\t}\n}\n\n/**\n * Returns the runtime type kind for a field — used by {@link schemaFieldType}\n * to build structural types at runtime.\n */\nexport type FieldTypeKind =\n\t| \"string\"\n\t| \"number\"\n\t| \"boolean\"\n\t| \"string-array\"\n\t| \"json\"\n\t| \"relation\"\n\t| \"relation-many\"\n\t| \"password\"\n\t| \"unknown\";\n\n/** Map a server field to its runtime type kind. */\nexport function fieldTypeKind(field: SchemaField): FieldTypeKind {\n\tconst opts = field.options ?? {};\n\tswitch (field.type) {\n\t\tcase \"text\":\n\t\tcase \"email\":\n\t\tcase \"url\":\n\t\tcase \"editor\":\n\t\tcase \"date\":\n\t\tcase \"datetime\":\n\t\tcase \"select\":\n\t\tcase \"file\":\n\t\t\treturn \"string\";\n\t\tcase \"number\":\n\t\t\treturn \"number\";\n\t\tcase \"bool\":\n\t\t\treturn \"boolean\";\n\t\tcase \"multi_select\":\n\t\tcase \"multi_file\":\n\t\t\treturn \"string-array\";\n\t\tcase \"json\":\n\t\tcase \"geo\":\n\t\t\treturn \"json\";\n\t\tcase \"relation\":\n\t\t\treturn (opts.maxSelect ?? 1) > 1 ? \"relation-many\" : \"relation\";\n\t\tcase \"password\":\n\t\t\treturn \"password\";\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n}\n\n/**\n * Derive a TypeScript field type from a {@link SchemaField} — the runtime\n * counterpart to the codegen mapper. Lets consumers build typed clients\n * from a fetched schema without running the CLI.\n */\nexport function schemaFieldType(field: SchemaField): unknown {\n\tswitch (fieldTypeKind(field)) {\n\t\tcase \"string\":\n\t\t\treturn String;\n\t\tcase \"number\":\n\t\t\treturn Number;\n\t\tcase \"boolean\":\n\t\t\treturn Boolean;\n\t\tcase \"string-array\":\n\t\t\treturn [String] as const;\n\t\tcase \"relation\":\n\t\t\treturn String;\n\t\tcase \"relation-many\":\n\t\t\treturn [String] as const;\n\t\tcase \"json\":\n\t\t\treturn Object;\n\t\tcase \"password\":\n\t\t\treturn undefined;\n\t\tcase \"unknown\":\n\t\t\treturn undefined;\n\t}\n}\n","// ── Codegen ─────────────────────────────────────────────\n// Generates a `lazypock.types.ts` module from the live API schema.\n//\n// The generated file exports:\n// - One interface per collection (e.g. `PostsRecord`)\n// - A `LazypockCollections` map: { posts: PostsRecord; users: UsersRecord; ... }\n// - A `createClient()` factory pre-bound to those types, so\n// `client.collection(\"posts\").create({ title: \"x\" })` is fully type-checked.\n//\n// The CLI in `src/cli.ts` wires this to `GET /collections`.\n\nimport type { CollectionSchema, SchemaField } from \"./schema\";\nimport { fieldTypeScriptType } from \"./typegen\";\n\n/** Format a raw collection name into a valid TS identifier (PascalCase). */\nexport function collectionTypeName(name: string): string {\n\treturn name\n\t\t.split(/[^a-zA-Z0-9]+/)\n\t\t.filter(Boolean)\n\t\t.map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n\t\t.join(\"\")\n\t\t.replace(/^[0-9]/, \"_$&\");\n}\n\n/** Interface member name — sanitize hyphens/spaces but keep readability. */\nexport function fieldKey(name: string): string {\n\treturn name.replace(/[^a-zA-Z0-9_]/g, \"_\");\n}\n\n\n\n/**\n * Generate the full TypeScript source for the typed SDK module.\n *\n * @param collections Collections fetched from the API.\n * @param options Generation options.\n */\nexport function generateTypes(\n\tcollections: CollectionSchema[],\n\toptions: {\n\t\t/** Import specifier for the lazypock package (default `lazypock`). */\n\t\tpackageName?: string;\n\t\t/** Emit base record fields (id, created, updated, …). Default true. */\n\t\tincludeBaseFields?: boolean;\n\t\t/** Skip system collections (names starting with `_` or `users`). Default false. */\n\t\tskipSystem?: boolean;\n\t} = {},\n): string {\n\tconst {\n\t\tpackageName = \"lazypock\",\n\t\tincludeBaseFields = true,\n\t\tskipSystem = false,\n\t} = options;\n\n\tconst filtered = skipSystem\n\t\t? collections.filter(\n\t\t\t\t(c) => !c.system && !c.name.startsWith(\"_\") && c.name !== \"users\",\n\t\t\t)\n\t\t: collections;\n\n\tconst sections: string[] = [];\n\tsections.push(`// ── Auto-generated by lazypock-ts ──────────────────────────\n// Do not edit by hand. Regenerate with: npx lazypock-gen\n// Schema snapshot: ${new Date().toISOString()}`);\n\n\tif (includeBaseFields) {\n\t\tsections.push(`export interface BaseRecord {\n id: string;\n collectionId: string;\n collectionName: string;\n created: string;\n updated: string;\n}`);\n\t}\n\n\t// One interface per collection\n\tfor (const coll of filtered) {\n\t\tconst typeName = collectionTypeName(coll.name);\n\t\tconst fields = coll.fields ?? [];\n\t\tconst lines = fields.map((f) => memberLine(f)).filter((l) => l !== \"\");\n\t\tconst body = lines.join(\"\\n\");\n\t\tsections.push(\n\t\t\t`export interface ${typeName}Record${renderInterface({\n\t\t\t\textends: includeBaseFields ? \"BaseRecord\" : undefined,\n\t\t\t\tbody,\n\t\t\t})}`,\n\t\t);\n\t}\n\n\t// Auth collection type\n\tsections.push(`export interface AuthRecord extends BaseRecord {\n email: string;\n verified: boolean;\n}`);\n\n\t// Collections map\n\tconst mapEntries = filtered\n\t\t.map(\n\t\t\t(c) =>\n\t\t\t\t` \"${c.name}\": ${collectionTypeName(c.name)}Record${\n\t\t\t\t\tc.type === \"auth\" ? \" & AuthRecord\" : \"\"\n\t\t\t\t};`,\n\t\t)\n\t\t.join(\"\\n\");\n\tsections.push(`export interface LazypockCollections {\n${mapEntries}\n}`);\n\n\t// createClient factory\n\tsections.push(`import { LazypockClient, type LazypockClientOptions, type CollectionService } from \"${packageName}\";\n\n/**\n * Create a Lazypock client typed against this schema snapshot.\n * Collection access is fully type-checked:\n * client.collection(\"posts\").create({ title: \"x\" }) // title must exist\n */\nexport function createClient(options: LazypockClientOptions): TypedClient {\n return new TypedClient(options);\n}\n\nexport class TypedClient extends LazypockClient {\n override collection<T extends string>(name: T): T extends keyof LazypockCollections\n ? CollectionService<LazypockCollections[T]>\n : CollectionService<unknown> {\n return super.collection(name) as T extends keyof LazypockCollections ? CollectionService<LazypockCollections[T]> : CollectionService<unknown>;\n }\n}\n`);\n\n\treturn sections.join(\"\\n\\n\") + \"\\n\";\n}\n\n/**\n * Render the interface body including the extends clause.\n * Empty body → ` extends BaseRecord {}` (valid TS).\n */\nfunction renderInterface(opts: { extends?: string; body: string }): string {\n\tconst ext = opts.extends ? ` extends ${opts.extends}` : \"\";\n\tif (!opts.body) return `${ext} {}`;\n\treturn `${ext} {\\n${opts.body}\\n}`;\n}\n\n/** Render a single interface member line for a field. */\nfunction memberLine(f: SchemaField): string {\n\tconst key = fieldKey(f.name);\n\tconst req = f.required || f.type === \"password\" ? \"\" : \"?\";\n\tconst type = fieldTypeScriptType(f);\n\t// `never` members (passwords) are omitted from read models.\n\tif (type === \"never\") return \"\";\n\treturn ` ${JSON.stringify(key)}${req}: ${type};`;\n}\n","// ── LazypockClient — Root Client ───────────────────────\n// Extracted into its own module to avoid a circular import with\n// the typed-client factory (src/client.ts).\n\nimport { HttpClient } from \"./http\";\nimport {\n\tAuthStore,\n\tmemoryStorage,\n\ttype StorageAdapter,\n\ttype AuthModel,\n} from \"./auth\";\nimport { CollectionService } from \"./collection\";\nimport {\n\tApiError,\n\ttype ApiRecord,\n\ttype ListResult,\n\ttype RecordShape,\n\ttype CreateData,\n\ttype UpdateData,\n\ttype SystemFields,\n\ttype RequestOptions,\n} from \"./types\";\nimport { RealtimeService, wsUrlFromBaseUrl } from \"./realtime\";\nimport {\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\ttype FileRecord,\n} from \"./files\";\nimport { CollectionsService } from \"./collections\";\nimport type { CollectionSchema, SchemaField } from \"./schema\";\nimport { generateTypes, collectionTypeName } from \"./codegen\";\nimport { fieldTypeScriptType, fieldTypeKind, schemaFieldType } from \"./typegen\";\nimport { CacheStore, type CacheConfig, type CacheRequestOptions } from \"./cache\";\nimport { resolveCacheDirective } from \"./cache\";\n\nexport {\n\tAuthStore,\n\tApiError,\n\tHttpClient,\n\tRealtimeService,\n\twsUrlFromBaseUrl,\n\tFilesService,\n\tgetFileUrl,\n\tgetThumbUrl,\n\tgetScaleUrl,\n\tCollectionService,\n\tCollectionsService,\n\tgenerateTypes,\n\tcollectionTypeName,\n\tfieldTypeScriptType,\n\tfieldTypeKind,\n\tschemaFieldType,\n};\nexport type {\n\tStorageAdapter,\n\tAuthModel,\n\tApiRecord,\n\tListResult,\n\tRecordShape,\n\tCreateData,\n\tUpdateData,\n\tSystemFields,\n\tRequestOptions,\n\tFileRecord,\n\tCollectionSchema,\n\tSchemaField,\n};\nexport type { CacheConfig, CacheRequestOptions };\nexport { CacheStore, resolveCacheDirective };\n\n/**\n * Callable cache namespace: `client.cache(config)` configures, and\n * `client.cache.deleteByPrefix(...)` etc. manage cached entries.\n */\nexport interface CacheController {\n\t/** Configure the query cache at runtime. */\n\t(config?: CacheConfig): LazypockClient;\n\t/** Delete every entry whose key starts with `prefix` (e.g. `getList:posts`). */\n\tdeleteByPrefix(prefix: string): void;\n\t/** Invalidate a collection's cached entries (alias of invalidateCache). */\n\tinvalidate(namespace: string): void;\n\t/** Drop every cached entry. */\n\tclear(): void;\n\t/** Cache hit/miss/entry stats, or null when never configured. */\n\tstats(): { hits: number; misses: number; entries: number } | null;\n}\n\n/** Options for constructing a {@link LazypockClient}. */\nexport interface LazypockClientOptions {\n\t/** API base URL (e.g. 'http://localhost:4000/api') */\n\tbaseUrl: string;\n\t/** Custom storage adapter (default: localStorage fallback) */\n\tstorage?: StorageAdapter;\n\t/** Explicit auth store instance (for sharing across modules) */\n\tauthStore?: AuthStore;\n\t/** Real-time service for Phoenix Channel WebSocket subscriptions */\n\trealtime?: RealtimeService;\n\t/**\n\t * Query cache configuration. Disabled by default.\n\t *\n\t * ```ts\n\t * const client = createClient({\n\t * baseUrl: '...',\n\t * cache: {\n\t * enabled: true,\n\t * defaultTTL: 30_000,\n\t * store: myStorage, // optional persistence (same interface as auth)\n\t * },\n\t * });\n\t * ```\n\t *\n\t * When enabled, readable GETs are cached. Requests can opt out via\n\t * `{ cache: false }`, or opt in with a custom TTL via `{ ttl: ms }`.\n\t */\n\tcache?: CacheConfig;\n\t/**\n\t * Optional schema types for generating typed services at runtime.\n\t * When provided, `collection()` returns a service whose create/update\n\t * inputs are validated against the mapped field types.\n\t *\n\t * @experimental\n\t */\n\ttypes?: {\n\t\t/** Collection schemas fetched from the API (e.g. via `GET /collections`). */\n\t\tschemas?: CollectionSchema[];\n\t};\n}\n\n/**\n * Lazypock API client.\n *\n * Provides methods for authentication, CRUD operations on dynamic collections,\n * file management, and real-time subscriptions.\n *\n * @example\n * ```ts\n * const client = new LazypockClient({ baseUrl: 'http://localhost:4000/api' });\n * await client.login('admin@example.com', 'password');\n * const posts = await client.collection('posts').getList();\n * ```\n */\nexport class LazypockClient {\n\treadonly http: HttpClient;\n\treadonly authStore: AuthStore;\n\treadonly realtime: RealtimeService;\n\treadonly collections: CollectionsService;\n\treadonly files: FilesService;\n\tprivate collectionCache = new Map<string, CollectionService>();\n\tprivate schemaByName?: Map<string, CollectionSchema>;\n\tprivate cacheStore?: CacheStore;\n\t/** Namespace → realtime unsubscribe; used for realtime-driven invalidation. */\n\tprivate realtimeInvalidators = new Map<string, () => void>();\n\n\t/**\n\t * Create a new Lazypock client.\n\t * @param options Configuration options.\n\t */\n\tconstructor(options: LazypockClientOptions) {\n\t\tconst baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.authStore =\n\t\t\toptions.authStore ?? new AuthStore(options.storage ?? memoryStorage);\n\t\tthis.http = new HttpClient(baseUrl, this.authStore);\n\t\tthis.realtime = options.realtime ?? new RealtimeService();\n\t\t// Cache the socket URL so collection-level subscribe() can auto-connect.\n\t\tif (!options.realtime) {\n\t\t\tthis.realtime.setUrl(wsUrlFromBaseUrl(baseUrl));\n\t\t}\n\t\tthis.files = new FilesService(this.http);\n\t\tthis.collections = new CollectionsService(this.http, this.realtime);\n\t\tif (options.cache) {\n\t\t\tthis.cacheStore = new CacheStore({\n\t\t\t\tdefaultTTL: options.cache.defaultTTL,\n\t\t\t\tstore: options.cache.store,\n\t\t\t\tmaxEntries: options.cache.maxEntries,\n\t\t\t});\n\t\t\tthis.http.setCache(this.cacheStore, options.cache.enabled ?? false);\n\t\t}\n\t\tif (options.types?.schemas) {\n\t\t\tthis.schemaByName = new Map(\n\t\t\t\toptions.types.schemas.map((s) => [s.name, s]),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a service for the given collection.\n\t * Services are cached after first access.\n\t *\n\t * For typed CRUD, either:\n\t * - cast at the call site: `client.collection(\"posts\").typed<Post>()`\n\t * - or use the typed factory: `createClient<{ posts: Post }>()`\n\t *\n\t * @param name The collection name.\n\t * @returns A {@link CollectionService} instance.\n\t */\n\tcollection(name: string): CollectionService<unknown> {\n\t\tlet svc = this.collectionCache.get(name);\n\t\tif (!svc) {\n\t\t\tsvc = new CollectionService(\n\t\t\t\tthis.http,\n\t\t\t\tname,\n\t\t\t\tthis.authStore,\n\t\t\t\tthis.realtime,\n\t\t\t);\n\t\t\tthis.collectionCache.set(name, svc);\n\t\t}\n\t\treturn svc;\n\t}\n\n\t/**\n\t * Get a typed service whose record shape is derived from the schema\n\t * passed via `options.types.schemas` (if available), or fall back to\n\t * the untyped service otherwise.\n\t *\n\t * @experimental\n\t */\n\tcollectionFor<TRecord = ApiRecord>(name: string): CollectionService<TRecord> {\n\t\treturn this.collection(name) as unknown as CollectionService<TRecord>;\n\t}\n\n\t/**\n\t * Generate TypeScript types from the schemas provided to this client\n\t * (via `options.types.schemas`). Returns a string ready to write to a\n\t * `lazypock.types.ts` file.\n\t */\n\tgenerateTypes(options?: { packageName?: string }): string {\n\t\tconst schemas = this.schemaByName ? [...this.schemaByName.values()] : [];\n\t\treturn generateTypes(schemas, options);\n\t}\n\n\t// ── Auto-cancellation (PocketBase `autoCancellation` parity) ──\n\n\t/**\n\t * Globally enable or disable auto-cancellation of duplicated pending requests.\n\t *\n\t * When enabled (default), a new request whose `requestKey` (default\n\t * `HTTP_METHOD + path`) matches a still-pending request aborts the previous\n\t * one — only the last duplicate executes.\n\t *\n\t * @example\n\t * ```ts\n\t * client.autoCancellation(false); // keep every request\n\t * ```\n\t */\n\tautoCancellation(enable: boolean): this {\n\t\tthis.http.autoCancellation(enable);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Abort a single pending request by its cancellation key\n\t * (default `HTTP_METHOD + path`, e.g. `\"GET /api/posts?page=1\"`).\n\t * The request rejects with an `ApiError` whose `isAbort` is `true`.\n\t */\n\tcancelRequest(requestKey: string): this {\n\t\tthis.http.cancelRequest(requestKey);\n\t\treturn this;\n\t}\n\n\t/** Abort all pending requests. */\n\tcancelAllRequests(): this {\n\t\tthis.http.cancelAllRequests();\n\t\treturn this;\n\t}\n\n\t// ── Query cache (opt-in by default; opt-out per request) ──\n\n\t/**\n\t * Configure the query cache at runtime (also a namespace for cache\n\t * management methods).\n\t *\n\t * ```ts\n\t * client.cache({ enabled: true, defaultTTL: 30_000 });\n\t * client.cache.deleteByPrefix('getList:posts'); // all list caches for posts\n\t * client.cache.deleteByPrefix('getOne:posts'); // all one-record caches\n\t * ```\n\t *\n\t * When enabled, GET requests cache their payload; mutations invalidate the\n\t * affected collection automatically. Individual requests can opt out with\n\t * `{ cache: false }` or override the TTL with `{ ttl: ms }`.\n\t */\n\treadonly cache: CacheController = Object.assign(\n\t\t((config?: CacheConfig) => {\n\t\t\tif (!this.cacheStore) {\n\t\t\t\t// Lazy-create so `.cache({ enabled: true })` works even when the\n\t\t\t\t// constructor wasn't given cache config.\n\t\t\t\tthis.cacheStore = new CacheStore({\n\t\t\t\t\tdefaultTTL: config?.defaultTTL,\n\t\t\t\t\tstore: config?.store,\n\t\t\t\t\tmaxEntries: config?.maxEntries,\n\t\t\t\t});\n\t\t\t\tthis.http.setCache(this.cacheStore, config?.enabled ?? true);\n\t\t\t} else {\n\t\t\t\tif (config?.enabled !== undefined) {\n\t\t\t\t\tthis.http.setCache(this.cacheStore, config.enabled);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t}) as (config?: CacheConfig) => LazypockClient,\n\t\t{\n\t\t\tdeleteByPrefix: (prefix: string) => this.cacheStore?.deleteByPrefix(prefix),\n\t\t\tinvalidate: (namespace: string) => this.cacheStore?.invalidate(namespace),\n\t\t\tclear: () => {\n\t\t\t\tthis.cacheStore?.clear();\n\t\t\t\tfor (const unsub of this.realtimeInvalidators.values()) unsub();\n\t\t\t\tthis.realtimeInvalidators.clear();\n\t\t\t},\n\t\t\tstats: () => (this.cacheStore ? this.cacheStore.stats() : null),\n\t\t},\n\t);\n\n\t/**\n\t * Drop every cached entry (all collections / namespaces).\n\t * Also disables realtime-driven invalidation subscriptions.\n\t */\n\tclearCache(): this {\n\t\tthis.cacheStore?.clear();\n\t\tfor (const unsub of this.realtimeInvalidators.values()) unsub();\n\t\tthis.realtimeInvalidators.clear();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Invalidate cached entries for a collection (or custom namespace).\n\t * Runs automatically on mutations — call explicitly when data changed\n\t * out-of-band (e.g. another client wrote to the same collection).\n\t */\n\tinvalidateCache(namespace: string): this {\n\t\tthis.cacheStore?.invalidate(namespace);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Cache hit/miss/entry statistics.\n\t * Returns null when caching was never configured.\n\t */\n\tcacheStats(): { hits: number; misses: number; entries: number } | null {\n\t\treturn this.cacheStore ? this.cacheStore.stats() : null;\n\t}\n\n\t/**\n\t * Subscribe a collection's cache to realtime invalidation: any inbound\n\t * create/update/delete event for the collection clears its cached entries.\n\t * Returns an unsubscribe function.\n\t */\n\tinvalidateCacheOnRealtime(collectionName: string): () => void {\n\t\tif (!this.cacheStore) {\n\t\t\t// ensure a store exists so invalidation has somewhere to go\n\t\t\tthis.cache({ enabled: false });\n\t\t}\n\t\tconst existing = this.realtimeInvalidators.get(collectionName);\n\t\tif (existing) return existing;\n\t\tconst unsub = this.collection(collectionName).subscribe(() => {\n\t\t\tthis.cacheStore?.invalidate(collectionName);\n\t\t});\n\t\tthis.realtimeInvalidators.set(collectionName, unsub);\n\t\treturn unsub;\n\t}\n\n\t// ── Auth ──\n\n\t/** Check whether any superuser exists (for login vs setup screen routing). */\n\tasync checkSuperuser(): Promise<{ has_superuser: boolean } | null> {\n\t\treturn this.http.get<{ has_superuser: boolean }>(\"/superusers/check\");\n\t}\n\n\t/**\n\t * Create the initial superuser account.\n\t * Only works when no superuser exists yet.\n\t * Stores the returned token in the auth store.\n\t * @param email Superuser email.\n\t * @param password Superuser password (min 8 chars).\n\t */\n\tasync setup(\n\t\temail: string,\n\t\tpassword: string,\n\t): Promise<({ token: string } & Record<string, unknown>) | null> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string } & Record<string, unknown>\n\t\t>(\"/superusers/setup\", { email, password });\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(null);\n\t\t\tthis.authStore.set(data.token, null);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Authenticate as a superuser or auth collection user.\n\t *\n\t * When `collection` is provided, authenticates against\n\t * `/{collection}/auth-with-password`. Otherwise logs in as superuser.\n\t * Stores the returned token in the auth store.\n\t *\n\t * @param email User email or identity.\n\t * @param password User password.\n\t * @param collection Optional auth collection name.\n\t */\n\tasync login(\n\t\temail: string,\n\t\tpassword: string,\n\t\tcollection?: string,\n\t): Promise<({ token: string } & Record<string, unknown>) | null> {\n\t\tlet data;\n\t\tif (collection) {\n\t\t\tdata = await this.http.post<\n\t\t\t\t{ token: string; record: Record<string, unknown> } & Record<\n\t\t\t\t\tstring,\n\t\t\t\t\tunknown\n\t\t\t\t>\n\t\t\t>(\"/\" + encodeURIComponent(collection) + \"/auth-with-password\", {\n\t\t\t\tidentity: email,\n\t\t\t\tpassword,\n\t\t\t});\n\t\t\tif (data && data.record) {\n\t\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t\t}\n\t} else {\n\t\t\t// Superuser login — PocketBase parity: `_superusers` is an auth collection.\n\t\t\t// Falls back to the legacy /superusers/login for older servers.\n\t\t\ttry {\n\t\t\t\tdata = await this.http.post<\n\t\t\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t\t\t>(\"/_superusers/auth-with-password\", {\n\t\t\t\t\tidentity: email,\n\t\t\t\t\tpassword,\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\tdata = null;\n\t\t\t}\n\t\t\tif (!data) {\n\t\t\t\tdata = await this.http.post<\n\t\t\t\t\t{ token: string } & Record<string, unknown>\n\t\t\t\t>(\"/superusers/login\", { email, password });\n\t\t\t}\n\t\t\tif (data) {\n\t\t\t\tthis.authStore.setCollectionName(null);\n\t\t\t\tthis.authStore.set(data.token, null);\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Fetch the current authenticated identity (superuser OR auth collection user).\n\t * Uses `GET /api/me` (PocketBase parity) — works with both superuser tokens\n\t * and auth collection user tokens.\n\t */\n\tasync me<T = ApiRecord>(options?: RequestOptions): Promise<T | null> {\n\t\tconst data = await this.http.get<T>(\"/me\", options);\n\t\tif (data) {\n\t\t\t// Update the auth model with fresh data\n\t\t\tthis.authStore.set(this.authStore.token, data as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Authenticate against an auth collection with email/password.\n\t * Stores the returned token and user record in the auth store.\n\t *\n\t * @param collection The auth collection name.\n\t * @param identity Email or username.\n\t * @param password Password.\n\t * @param options Optional request options.\n\t */\n\tasync authWithPassword(\n\t\tcollection: string,\n\t\tidentity: string,\n\t\tpassword: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + encodeURIComponent(collection) + \"/auth-with-password\",\n\t\t\t{ identity, password },\n\t\t\toptions,\n\t\t);\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/**\n\t * Refresh an auth collection token.\n\t * Uses the currently stored auth token.\n\t *\n\t * @param collection The auth collection name.\n\t * @param options Optional request options.\n\t */\n\tasync authRefresh(\n\t\tcollection: string,\n\t\toptions?: RequestOptions,\n\t): Promise<\n\t\t({ token: string; record: ApiRecord } & Record<string, unknown>) | null\n\t> {\n\t\tconst data = await this.http.post<\n\t\t\t{ token: string; record: ApiRecord } & Record<string, unknown>\n\t\t>(\n\t\t\t\"/\" + encodeURIComponent(collection) + \"/auth-refresh\",\n\t\t\tundefined,\n\t\t\toptions,\n\t\t);\n\t\tif (data) {\n\t\t\tthis.authStore.setCollectionName(collection);\n\t\t\tthis.authStore.set(data.token, data.record as unknown as AuthModel);\n\t\t}\n\t\treturn data;\n\t}\n\n\t/** Clear the current auth state and remove persisted tokens. */\n\tlogout(): void {\n\t\tthis.authStore.clear();\n\t}\n\n\t// ── Health ──\n\n\t/** Ping the API health endpoint. */\n\thealth(options?: RequestOptions): Promise<Record<string, unknown> | null> {\n\t\treturn this.http.get<Record<string, unknown>>(\"/health\", options);\n\t}\n}\n","// ── Typed client factory ────────────────────────────────\n// Generic over a collections map, so collection access is type-checked\n// without hand-writing interfaces — pair with the codegen CLI output.\n\nimport { LazypockClient } from \"./lazypock\";\nimport type { CollectionService } from \"./collection\";\nimport type { LazypockClientOptions } from \"./lazypock\";\n\n/**\n * A collections map: `{ posts: PostRecord; users: UserRecord; ... }`.\n * Generated by the codegen CLI (`npx lazypock-gen`) or written by hand.\n */\nexport type LazypockCollections = Record<string, unknown>;\n\n/**\n * Client typed against a {@link LazypockCollections} map.\n *\n * ```ts\n * import { createClient } from \"lazypock/generated\";\n * const client = createClient({ baseUrl: \"http://localhost:4000/api\" });\n * const posts = await client.collection(\"posts\").list<PostsRecord>();\n * ```\n */\nexport class TypedClient<\n\tTCollections extends LazypockCollections = LazypockCollections,\n> extends LazypockClient {\n\t/**\n\t * Get a typed service for a collection.\n\t * When `TCollections` is provided, unknown collection names are rejected.\n\t * @typeParam K — Collection name (keyof TCollections).\n\t */\n\toverride collection<K extends keyof TCollections>(\n\t\tname: K,\n\t): CollectionService<TCollections[K]>;\n\toverride collection(name: string): CollectionService<unknown> {\n\t\treturn super.collection(name) as unknown as CollectionService<unknown>;\n\t}\n}\n\n/**\n * Create a {@link TypedClient}.\n * @typeParam TCollections — Map of collection name → record shape.\n */\nexport function createClient<\n\tTCollections extends LazypockCollections = LazypockCollections,\n>(options: LazypockClientOptions): TypedClient<TCollections> {\n\treturn new TypedClient<TCollections>(options);\n}\n"],"mappings":"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","names":["op","normalizeAction"]}