lazypock 0.10.2 → 0.12.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.
- package/README.md +117 -127
- package/dist/{chunk-LVEOMG6A.js → chunk-HA22OVUR.js} +51 -9
- package/dist/chunk-HA22OVUR.js.map +1 -0
- package/dist/cli.cjs +49 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.global.js +49 -8
- package/dist/cli.global.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +50 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -14
- package/dist/index.d.ts +35 -14
- package/dist/index.global.js +50 -8
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +98 -9
- package/src/collection.ts +22 -13
- package/src/typegen.ts +2 -0
- package/src/types.ts +31 -7
- package/dist/chunk-LVEOMG6A.js.map +0 -1
package/package.json
CHANGED
package/src/codegen.ts
CHANGED
|
@@ -12,6 +12,23 @@
|
|
|
12
12
|
import type { CollectionSchema, SchemaField } from "./schema";
|
|
13
13
|
import { fieldTypeScriptType } from "./typegen";
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Members already declared by the generated `BaseRecord` interface. A
|
|
17
|
+
* collection field with one of these names must NOT be re-declared on the
|
|
18
|
+
* per-collection read/query interfaces: redeclaring `created`/`updated`
|
|
19
|
+
* (PocketBase-style autodate fields, which the mapper types as `string`) as
|
|
20
|
+
* an optional member makes TypeScript reject the interface with TS2430
|
|
21
|
+
* ("incorrectly extends interface 'BaseRecord'") because the base declares
|
|
22
|
+
* them as required `string`. The base declaration is kept.
|
|
23
|
+
*/
|
|
24
|
+
const BASE_RECORD_KEYS = new Set([
|
|
25
|
+
"id",
|
|
26
|
+
"collectionId",
|
|
27
|
+
"collectionName",
|
|
28
|
+
"created",
|
|
29
|
+
"updated",
|
|
30
|
+
]);
|
|
31
|
+
|
|
15
32
|
/** Format a raw collection name into a valid TS identifier (PascalCase). */
|
|
16
33
|
export function collectionTypeName(name: string): string {
|
|
17
34
|
return name
|
|
@@ -73,11 +90,22 @@ export function generateTypes(
|
|
|
73
90
|
}`);
|
|
74
91
|
}
|
|
75
92
|
|
|
93
|
+
// Resolve relation targets (collectionId → record type) for the expand maps.
|
|
94
|
+
// Only collections with a real id are indexed — schemas without ids (e.g.
|
|
95
|
+
// minimal hand-written snapshots) fall back to the name lookup below.
|
|
96
|
+
const collById = new Map(
|
|
97
|
+
filtered
|
|
98
|
+
.filter((c) => c.id !== undefined && c.id !== "")
|
|
99
|
+
.map((c) => [String(c.id), c]),
|
|
100
|
+
);
|
|
101
|
+
|
|
76
102
|
// One interface per collection
|
|
77
103
|
for (const coll of filtered) {
|
|
78
104
|
const typeName = collectionTypeName(coll.name);
|
|
79
105
|
const fields = coll.fields ?? [];
|
|
80
|
-
const lines = fields
|
|
106
|
+
const lines = fields
|
|
107
|
+
.map((f) => memberLine(f, includeBaseFields))
|
|
108
|
+
.filter((l) => l !== "");
|
|
81
109
|
const body = lines.join("\n");
|
|
82
110
|
sections.push(
|
|
83
111
|
`export interface ${typeName}Record${renderInterface({
|
|
@@ -114,6 +142,9 @@ export function generateTypes(
|
|
|
114
142
|
for (const f of fields) {
|
|
115
143
|
if (f.type === "password") continue;
|
|
116
144
|
const key = fieldKey(f.name);
|
|
145
|
+
// The query interface extends BaseRecord too (when base fields are
|
|
146
|
+
// emitted), so the same key collisions apply.
|
|
147
|
+
if (includeBaseFields && BASE_RECORD_KEYS.has(key)) continue;
|
|
117
148
|
const type = fieldTypeScriptType(f);
|
|
118
149
|
if (type === "never") continue;
|
|
119
150
|
queryLines.push(` ${JSON.stringify(key)}?: ${type};`);
|
|
@@ -124,6 +155,42 @@ export function generateTypes(
|
|
|
124
155
|
body: queryLines.join("\n"),
|
|
125
156
|
})}`,
|
|
126
157
|
);
|
|
158
|
+
|
|
159
|
+
// Expand map — relation field → target record type, so expanded
|
|
160
|
+
// records are typed (`record.expand.user` is `UsersRecord` instead of
|
|
161
|
+
// `unknown`). Built from each relation's `options.collectionId`; auth
|
|
162
|
+
// targets get `& AuthRecord`, multi-relations (maxSelect > 1) get
|
|
163
|
+
// arrays, and unknown targets (e.g. skipped collections) fall back to
|
|
164
|
+
// `unknown` via the `ExpandValue` fallback.
|
|
165
|
+
const expandLines: string[] = [];
|
|
166
|
+
for (const f of fields) {
|
|
167
|
+
if (f.type !== "relation") continue;
|
|
168
|
+
// Resolve the target collection: real PocketBase schemas carry
|
|
169
|
+
// `options.collectionId` (the target collection's id), while some
|
|
170
|
+
// tooling/snapshots use `options.collection` (the target's name).
|
|
171
|
+
// Unknown/absent targets fall back to `unknown` via ExpandValue.
|
|
172
|
+
// SAFETY: both option keys are strings; guard with String().
|
|
173
|
+
const target =
|
|
174
|
+
collById.get(String(f.options?.collectionId ?? "")) ??
|
|
175
|
+
filtered.find(
|
|
176
|
+
(c) => c.name === String(f.options?.collection ?? ""),
|
|
177
|
+
);
|
|
178
|
+
if (!target) continue;
|
|
179
|
+
const targetType = `${collectionTypeName(target.name)}Record${
|
|
180
|
+
target.type === "auth" ? " & AuthRecord" : ""
|
|
181
|
+
}`;
|
|
182
|
+
const many = (f.options?.maxSelect ?? 1) > 1;
|
|
183
|
+
expandLines.push(
|
|
184
|
+
` ${JSON.stringify(fieldKey(f.name))}: ${
|
|
185
|
+
many ? `Array<${targetType}>` : targetType
|
|
186
|
+
};`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
sections.push(
|
|
190
|
+
`export interface ${typeName}ExpandMap${renderInterface({
|
|
191
|
+
body: expandLines.join("\n"),
|
|
192
|
+
})}`,
|
|
193
|
+
);
|
|
127
194
|
}
|
|
128
195
|
|
|
129
196
|
// Auth collection type
|
|
@@ -167,6 +234,15 @@ ${createMapEntries}
|
|
|
167
234
|
.join("\n");
|
|
168
235
|
sections.push(`export interface LazypockQueryFields {
|
|
169
236
|
${queryMapEntries}
|
|
237
|
+
}`);
|
|
238
|
+
|
|
239
|
+
// Expand map — relation field → target record type per collection, bound
|
|
240
|
+
// as the 4th CollectionService generic so expanded records are typed.
|
|
241
|
+
const expandMapEntries = filtered
|
|
242
|
+
.map((c) => ` "${c.name}": ${collectionTypeName(c.name)}ExpandMap;`)
|
|
243
|
+
.join("\n");
|
|
244
|
+
sections.push(`export interface LazypockExpandMaps {
|
|
245
|
+
${expandMapEntries}
|
|
170
246
|
}`);
|
|
171
247
|
|
|
172
248
|
// Runtime schema snapshot — lets the client exclude hidden fields by
|
|
@@ -228,25 +304,31 @@ export class TypedClient extends LazypockClient {
|
|
|
228
304
|
// The (string & {}) intersection keeps the union from collapsing to plain
|
|
229
305
|
// string (which would silently kill the suggestions).
|
|
230
306
|
//
|
|
231
|
-
// The service binds
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
307
|
+
// The service binds four types: the read model, the write-only *CreateData,
|
|
308
|
+
// the *QueryFields (filter/sort/expand/select keys), and the *ExpandMap
|
|
309
|
+
// (relation field → target record type). QueryFields is what lets hidden
|
|
310
|
+
// relation fields — excluded from the read model but still expandable/
|
|
311
|
+
// filterable at runtime — typecheck:
|
|
235
312
|
// client.collection("project_members").getFullList({ expand: "user" }) // ✓
|
|
313
|
+
// ExpandMap is what types the expanded data on the result:
|
|
314
|
+
// const [rec] = await client.collection("posts").getFullList({ expand: "user" });
|
|
315
|
+
// rec.expand?.user // ✓ UsersRecord, not unknown
|
|
236
316
|
override collection<K extends keyof LazypockCollections | (string & {})>(
|
|
237
317
|
name: K,
|
|
238
318
|
): K extends keyof LazypockCollections
|
|
239
319
|
? CollectionService<
|
|
240
320
|
LazypockCollections[K],
|
|
241
321
|
LazypockCreateData[K],
|
|
242
|
-
LazypockQueryFields[K]
|
|
322
|
+
LazypockQueryFields[K],
|
|
323
|
+
LazypockExpandMaps[K]
|
|
243
324
|
>
|
|
244
325
|
: CollectionService<unknown> {
|
|
245
326
|
return super.collection(name) as K extends keyof LazypockCollections
|
|
246
327
|
? CollectionService<
|
|
247
328
|
LazypockCollections[K],
|
|
248
329
|
LazypockCreateData[K],
|
|
249
|
-
LazypockQueryFields[K]
|
|
330
|
+
LazypockQueryFields[K],
|
|
331
|
+
LazypockExpandMaps[K]
|
|
250
332
|
>
|
|
251
333
|
: CollectionService<unknown>;
|
|
252
334
|
}
|
|
@@ -266,12 +348,19 @@ function renderInterface(opts: { extends?: string; body: string }): string {
|
|
|
266
348
|
return `${ext} {\n${opts.body}\n}`;
|
|
267
349
|
}
|
|
268
350
|
|
|
269
|
-
/**
|
|
270
|
-
|
|
351
|
+
/**
|
|
352
|
+
* Render a single interface member line for a field.
|
|
353
|
+
*
|
|
354
|
+
* `skipBaseKeys` is true when the interface extends `BaseRecord`: keys the
|
|
355
|
+
* base already declares are omitted so the child never redeclares them with
|
|
356
|
+
* an incompatible (optional / non-string) type.
|
|
357
|
+
*/
|
|
358
|
+
function memberLine(f: SchemaField, skipBaseKeys = false): string {
|
|
271
359
|
// Hidden fields are excluded from API responses by the schema-aware
|
|
272
360
|
// client default — don't expose them on the read model either.
|
|
273
361
|
if (f.hidden) return "";
|
|
274
362
|
const key = fieldKey(f.name);
|
|
363
|
+
if (skipBaseKeys && BASE_RECORD_KEYS.has(key)) return "";
|
|
275
364
|
const req = f.required || f.type === "password" ? "" : "?";
|
|
276
365
|
const type = fieldTypeScriptType(f);
|
|
277
366
|
// `never` members (passwords) are omitted from read models.
|
package/src/collection.ts
CHANGED
|
@@ -128,8 +128,17 @@ function normalizeAction(
|
|
|
128
128
|
* Defaults to `T`. The codegen client binds a *QueryFields type that includes
|
|
129
129
|
* hidden fields — excluded from the read model but still expandable/filterable
|
|
130
130
|
* at runtime — so `expand: "hiddenRelation"` typechecks.
|
|
131
|
+
* @typeParam TExpand — Map of relation field → target record type. Defaults to
|
|
132
|
+
* `Record<string, unknown>`. The codegen client binds a per-collection
|
|
133
|
+
* *ExpandMap, so `record.expand.user` is typed as the target `UsersRecord`
|
|
134
|
+
* instead of `unknown`.
|
|
131
135
|
*/
|
|
132
|
-
export class CollectionService<
|
|
136
|
+
export class CollectionService<
|
|
137
|
+
T = ApiRecord,
|
|
138
|
+
TData = never,
|
|
139
|
+
TFields = T,
|
|
140
|
+
TExpand = Record<string, unknown>,
|
|
141
|
+
> {
|
|
133
142
|
private http: HttpClient;
|
|
134
143
|
private collectionName: string;
|
|
135
144
|
private authStore?: AuthStore;
|
|
@@ -189,9 +198,9 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
189
198
|
*/
|
|
190
199
|
select<K extends FieldKey<TFields> | "*">(
|
|
191
200
|
...fields: K[]
|
|
192
|
-
): CollectionService<T, TData, TFields> {
|
|
201
|
+
): CollectionService<T, TData, TFields, TExpand> {
|
|
193
202
|
const preset = fields.length === 0 ? "*" : fields.join(",");
|
|
194
|
-
const derived = new CollectionService<T, TData, TFields>(
|
|
203
|
+
const derived = new CollectionService<T, TData, TFields, TExpand>(
|
|
195
204
|
this.http,
|
|
196
205
|
this.collectionName,
|
|
197
206
|
this.authStore,
|
|
@@ -302,7 +311,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
302
311
|
page = 1,
|
|
303
312
|
perPage = 30,
|
|
304
313
|
options?: ListOptions<TFields, E, S, F> & RequestOptions,
|
|
305
|
-
): Promise<ListResult<T2 & { expand?: ExpandObj<E> }> | null> {
|
|
314
|
+
): Promise<ListResult<T2 & { expand?: ExpandObj<E, TExpand> }> | null> {
|
|
306
315
|
const {
|
|
307
316
|
requestKey,
|
|
308
317
|
autoCancel,
|
|
@@ -332,7 +341,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
332
341
|
}).map(([k, v]) => [k, String(v)]),
|
|
333
342
|
),
|
|
334
343
|
).toString();
|
|
335
|
-
return this.http.get<ListResult<T2 & { expand?: ExpandObj<E> }>>(
|
|
344
|
+
return this.http.get<ListResult<T2 & { expand?: ExpandObj<E, TExpand> }>>(
|
|
336
345
|
"/" + this.encodeId(this.collectionName) + "?" + qs,
|
|
337
346
|
{
|
|
338
347
|
requestKey,
|
|
@@ -360,7 +369,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
360
369
|
F extends string = never,
|
|
361
370
|
>(
|
|
362
371
|
options?: ListOptions<TFields, E, S, F> & RequestOptions,
|
|
363
|
-
): Promise<Array<T2 & { expand?: ExpandObj<E> }>> {
|
|
372
|
+
): Promise<Array<T2 & { expand?: ExpandObj<E, TExpand> }>> {
|
|
364
373
|
const { batch = 1000, ...rest } = options ?? {};
|
|
365
374
|
|
|
366
375
|
// Build a stable request key for the whole full-list fetch (NOT per page,
|
|
@@ -373,7 +382,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
373
382
|
? rest.requestKey
|
|
374
383
|
: `getFullList:${this.collectionName}:${stableStringify(rest)}`;
|
|
375
384
|
|
|
376
|
-
const items: Array<T2 & { expand?: ExpandObj<E> }> = [];
|
|
385
|
+
const items: Array<T2 & { expand?: ExpandObj<E, TExpand> }> = [];
|
|
377
386
|
let page = 1;
|
|
378
387
|
for (;;) {
|
|
379
388
|
const res = await this.getList<T2>(
|
|
@@ -386,7 +395,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
386
395
|
} as ListOptions<TFields> & RequestOptions,
|
|
387
396
|
);
|
|
388
397
|
if (!res || !res.items || res.items.length === 0) break;
|
|
389
|
-
items.push(...(res.items as Array<T2 & { expand?: ExpandObj<E> }>));
|
|
398
|
+
items.push(...(res.items as Array<T2 & { expand?: ExpandObj<E, TExpand> }>));
|
|
390
399
|
if (page >= (res.totalPages ?? page)) break;
|
|
391
400
|
page += 1;
|
|
392
401
|
}
|
|
@@ -407,7 +416,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
407
416
|
>(
|
|
408
417
|
filter: FilterString<TFields, F>,
|
|
409
418
|
options?: ListOptions<TFields, E, S, F> & RequestOptions,
|
|
410
|
-
): Promise<(T2 & { expand?: ExpandObj<E> }) | null> {
|
|
419
|
+
): Promise<(T2 & { expand?: ExpandObj<E, TExpand> }) | null> {
|
|
411
420
|
const res = await this.getList<T2, E, S, F>(1, 1, {
|
|
412
421
|
...options,
|
|
413
422
|
filter,
|
|
@@ -423,7 +432,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
423
432
|
getOne<E extends string = never>(
|
|
424
433
|
id: string,
|
|
425
434
|
options?: ReadOptions<TFields, E> & RequestOptions,
|
|
426
|
-
): Promise<(T & { expand?: ExpandObj<E> }) | null> {
|
|
435
|
+
): Promise<(T & { expand?: ExpandObj<E, TExpand> }) | null> {
|
|
427
436
|
const fields = this.effectiveFields(options?.fields);
|
|
428
437
|
if (typeof options?.expand === "string") {
|
|
429
438
|
this.validateExpand(options.expand);
|
|
@@ -432,7 +441,7 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
432
441
|
if (fields !== undefined) qs.set("fields", fields);
|
|
433
442
|
if (typeof options?.expand === "string") qs.set("expand", options.expand);
|
|
434
443
|
const qsStr = qs.toString();
|
|
435
|
-
return this.http.get<T & { expand?: ExpandObj<E> }>(
|
|
444
|
+
return this.http.get<T & { expand?: ExpandObj<E, TExpand> }>(
|
|
436
445
|
"/" +
|
|
437
446
|
this.encodeId(this.collectionName) +
|
|
438
447
|
"/" +
|
|
@@ -550,8 +559,8 @@ export class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
550
559
|
* `types.schemas`). Enables schema-aware defaults: hidden fields are
|
|
551
560
|
* excluded from responses, select/expand are validated.
|
|
552
561
|
*/
|
|
553
|
-
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields> {
|
|
554
|
-
const derived = new CollectionService<T, TData, TFields>(
|
|
562
|
+
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields, TExpand> {
|
|
563
|
+
const derived = new CollectionService<T, TData, TFields, TExpand>(
|
|
555
564
|
this.http,
|
|
556
565
|
this.collectionName,
|
|
557
566
|
this.authStore,
|
package/src/typegen.ts
CHANGED
|
@@ -23,6 +23,7 @@ export function fieldTypeScriptType(
|
|
|
23
23
|
case "editor":
|
|
24
24
|
case "date":
|
|
25
25
|
case "datetime":
|
|
26
|
+
case "autodate":
|
|
26
27
|
return "string";
|
|
27
28
|
case "number":
|
|
28
29
|
return "number";
|
|
@@ -86,6 +87,7 @@ export function fieldTypeKind(field: SchemaField): FieldTypeKind {
|
|
|
86
87
|
case "editor":
|
|
87
88
|
case "date":
|
|
88
89
|
case "datetime":
|
|
90
|
+
case "autodate":
|
|
89
91
|
case "select":
|
|
90
92
|
case "file":
|
|
91
93
|
return "string";
|
package/src/types.ts
CHANGED
|
@@ -149,7 +149,13 @@ export type FieldKey<T> = Extract<keyof T, string> extends never
|
|
|
149
149
|
? string
|
|
150
150
|
: Extract<keyof T, string>;
|
|
151
151
|
|
|
152
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* Valid filter operators, matching the backend FilterCompiler.
|
|
154
|
+
*
|
|
155
|
+
* The `?`-prefixed operators are PocketBase's "any/at least one of"
|
|
156
|
+
* conditions over array-valued fields (multi-select, multiple relation,
|
|
157
|
+
* multiple file). They compile to `= ANY` / `ILIKE ANY` SQL in the backend.
|
|
158
|
+
*/
|
|
153
159
|
export type FilterOp =
|
|
154
160
|
| "="
|
|
155
161
|
| "!="
|
|
@@ -158,7 +164,15 @@ export type FilterOp =
|
|
|
158
164
|
| ">"
|
|
159
165
|
| ">="
|
|
160
166
|
| "<"
|
|
161
|
-
| "<="
|
|
167
|
+
| "<="
|
|
168
|
+
| "?="
|
|
169
|
+
| "?!="
|
|
170
|
+
| "?~"
|
|
171
|
+
| "?!~"
|
|
172
|
+
| "?>"
|
|
173
|
+
| "?>="
|
|
174
|
+
| "?<"
|
|
175
|
+
| "?<=";
|
|
162
176
|
|
|
163
177
|
/** Optional whitespace around a filter operator (`project=x` and `project = x` both compile). */
|
|
164
178
|
type FilterWs = "" | " ";
|
|
@@ -412,17 +426,27 @@ type TopExpandKey<S extends string> = S extends `${infer A}.${string}` ? A : S;
|
|
|
412
426
|
type ExpandKeys<S extends string> = S extends "" ? never :
|
|
413
427
|
S extends `${infer H},${infer T}` ? TopExpandKey<H> | ExpandKeys<T> : TopExpandKey<S>;
|
|
414
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Value type of one expanded relation: the target record from the expand
|
|
431
|
+
* map (`TExpand`, e.g. the codegen-generated `PostsExpandMap`) when the key
|
|
432
|
+
* is a known relation, `unknown` otherwise.
|
|
433
|
+
*/
|
|
434
|
+
type ExpandValue<K extends string, TExpand> = K extends keyof TExpand ? TExpand[K] : unknown;
|
|
435
|
+
|
|
415
436
|
/**
|
|
416
437
|
* The `expand` property attached to records when `expand` is used. Keys are
|
|
417
438
|
* parsed from the caller's expand literal (dot-paths collapse to their first
|
|
418
|
-
* segment)
|
|
419
|
-
*
|
|
420
|
-
* `
|
|
439
|
+
* segment) and each value is typed from `TExpand` — a per-collection map of
|
|
440
|
+
* relation field → target record type (the codegen CLI emits these), so
|
|
441
|
+
* `record.expand.user` is `UsersRecord`, not `unknown`.
|
|
442
|
+
*
|
|
443
|
+
* Falls back to `Record<string, unknown>` when the expand value is dynamic
|
|
444
|
+
* or absent, or when no expand map is bound (hand-written services).
|
|
421
445
|
*/
|
|
422
|
-
export type ExpandObj<E extends string
|
|
446
|
+
export type ExpandObj<E extends string, TExpand = Record<string, unknown>> =
|
|
423
447
|
[E] extends [never] ? Record<string, unknown> :
|
|
424
448
|
[string] extends [E] ? Record<string, unknown> :
|
|
425
|
-
Partial<
|
|
449
|
+
Partial<{ [K in ExpandKeys<E>]: ExpandValue<K, TExpand> }>;
|
|
426
450
|
|
|
427
451
|
/**
|
|
428
452
|
* Query options for list/read operations, typed against a record shape `T`.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/typegen.ts","../src/codegen.ts"],"sourcesContent":["// ── 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\n\t\t// Write-only create data: what `create()`/`update()` accept. This\n\t\t// intentionally includes password fields (and hidden fields) that are\n\t\t// excluded from the read model — the server accepts them on write,\n\t\t// hashes passwords, and never returns them in responses.\n\t\tconst createLines: string[] = [];\n\t\tconst seenKeys = new Set<string>();\n\t\tfor (const f of fields) {\n\t\t\tfor (const { key, line } of createDataMemberLines(f)) {\n\t\t\t\tif (seenKeys.has(key)) continue;\n\t\t\t\tseenKeys.add(key);\n\t\t\t\tcreateLines.push(line);\n\t\t\t}\n\t\t}\n\t\tsections.push(\n\t\t\t`export interface ${typeName}CreateData${renderInterface({\n\t\t\t\tbody: createLines.join(\"\\n\"),\n\t\t\t})}`,\n\t\t);\n\n\t\t// Query fields — the key set for filter/sort/expand/select. This\n\t\t// intentionally includes hidden fields: a hidden relation is still\n\t\t// expandable/filterable at runtime (the server resolves it) even\n\t\t// though it is excluded from the read model. Only password fields\n\t\t// are never queryable.\n\t\tconst queryLines: string[] = [];\n\t\tfor (const f of fields) {\n\t\t\tif (f.type === \"password\") continue;\n\t\t\tconst key = fieldKey(f.name);\n\t\t\tconst type = fieldTypeScriptType(f);\n\t\t\tif (type === \"never\") continue;\n\t\t\tqueryLines.push(` ${JSON.stringify(key)}?: ${type};`);\n\t\t}\n\t\tsections.push(\n\t\t\t`export interface ${typeName}QueryFields${renderInterface({\n\t\t\t\textends: includeBaseFields ? \"BaseRecord\" : undefined,\n\t\t\t\tbody: queryLines.join(\"\\n\"),\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// Create-data map — typed `create()`/`update()` payloads, including\n\t// write-only password fields.\n\tconst createMapEntries = filtered\n\t\t.map((c) => ` \"${c.name}\": ${collectionTypeName(c.name)}CreateData;`)\n\t\t.join(\"\\n\");\n\tsections.push(`export interface LazypockCreateData {\n${createMapEntries}\n}`);\n\n\t// Query-fields map — filter/sort/expand/select keys per collection,\n\t// including hidden fields (valid at runtime despite being excluded from\n\t// the read model). Auth collections get the auth system keys too.\n\tconst queryMapEntries = filtered\n\t\t.map(\n\t\t\t(c) =>\n\t\t\t\t` \"${c.name}\": ${collectionTypeName(c.name)}QueryFields${\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 LazypockQueryFields {\n${queryMapEntries}\n}`);\n\n\t// Runtime schema snapshot — lets the client exclude hidden fields by\n\t// default, validate select/expand, and derive visible field lists.\n\tconst schemaEntries = collections\n\t\t.map(\n\t\t\t(c) =>\n\t\t\t\t` {\n id: ${JSON.stringify(c.id ?? null)},\n name: ${JSON.stringify(c.name)},\n type: ${JSON.stringify(c.type)},\n system: ${JSON.stringify(c.system ?? false)},\n fields: ${JSON.stringify(c.fields ?? [], null, 2)},\n rules: ${JSON.stringify(c.rules ?? {})},\n options: ${JSON.stringify(c.options ?? {})},\n }`,\n\t\t)\n\t\t.join(\",\\n\");\n\tsections.push(`// Schema snapshot (runtime) — hidden-field exclusion + query validation.\nexport const lazypockSchema: import(\"${packageName}\").CollectionSchema[] = [\n${schemaEntries}\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 *\n * For auth collections the generated *CreateData type includes the\n * write-only password field, so creating a user is type-safe:\n * client.collection(\"users\").create({ email, password }) // ✓\n *\n * The schema snapshot is wired into the client automatically, so hidden\n * fields are excluded from responses and select/expand are validated.\n */\nexport function createClient(options: LazypockClientOptions): TypedClient {\n return new TypedClient({\n ...options,\n types: {\n ...options.types,\n schemas: options.types?.schemas ?? lazypockSchema,\n },\n });\n}\n\nexport class TypedClient extends LazypockClient {\n // The constraint is \"keyof LazypockCollections | (string & {})\" rather than a\n // bare generic string or a strict keyof:\n // - the keyof LazypockCollections member is what makes the IDE suggest\n // collection names, and known literals resolve to the typed service:\n // client.collection(\"posts\") // suggested + typed\n // - the string & {} member keeps unknown/dynamic names compiling — they\n // resolve to the untyped service, so a studio that manages\n // user-created collections can still call collection(someString).\n //\n // The (string & {}) intersection keeps the union from collapsing to plain\n // string (which would silently kill the suggestions).\n //\n // The service binds three types: the read model, the write-only *CreateData,\n // and the *QueryFields (filter/sort/expand/select keys). QueryFields is what\n // lets hidden relation fields — excluded from the read model but still\n // expandable/filterable at runtime — typecheck:\n // client.collection(\"project_members\").getFullList({ expand: \"user\" }) // ✓\n override collection<K extends keyof LazypockCollections | (string & {})>(\n name: K,\n ): K extends keyof LazypockCollections\n ? CollectionService<\n LazypockCollections[K],\n LazypockCreateData[K],\n LazypockQueryFields[K]\n >\n : CollectionService<unknown> {\n return super.collection(name) as K extends keyof LazypockCollections\n ? CollectionService<\n LazypockCollections[K],\n LazypockCreateData[K],\n LazypockQueryFields[K]\n >\n : 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\t// Hidden fields are excluded from API responses by the schema-aware\n\t// client default — don't expose them on the read model either.\n\tif (f.hidden) return \"\";\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\n/**\n * Render the write-only create-data members for a field.\n *\n * Unlike the read model, create/update data includes password fields (sent as\n * plain strings — the server hashes them) and hidden fields: the server\n * accepts them on write and never returns them in responses.\n *\n * Password fields are exposed under the canonical PocketBase API key\n * `password` (the server accepts `password` for any single password field and\n * hashes it into the backing column, e.g. `password_hash`), with the raw\n * metadata name kept as a backward-compat alias.\n *\n * A field is only marked required when it actually needs a client value:\n * fields with a server-side default (`options.defaultValue`) and the auth\n * system fields `verified` / `emailVisibility` (the server defaults them to\n * false/true even though the snapshot doesn't carry `defaultValue`) stay\n * optional, so `create({ email, password })` typechecks without forcing\n * callers to send values the server would fill in anyway. Password fields\n * are optional (accounts may exist without a password, e.g. OAuth-only).\n */\nfunction createDataMemberLines(\n\tf: SchemaField,\n): { key: string; line: string }[] {\n\t// Autodate columns are server-managed; never writable.\n\tif (f.type === \"autodate\") return [];\n\tconst rawName = fieldKey(f.name);\n\tconst serverDefaulted =\n\t\tf.options?.defaultValue !== undefined ||\n\t\t(f.system && (f.name === \"verified\" || f.name === \"emailVisibility\"));\n\tconst req = f.required && !serverDefaulted ? \"\" : \"?\";\n\tconst type = f.type === \"password\" ? \"string\" : fieldTypeScriptType(f);\n\tif (type === \"never\") return [];\n\n\tconst members = [\n\t\t{ key: rawName, line: ` ${JSON.stringify(rawName)}${req}: ${type};` },\n\t];\n\t// Write-only password: canonical key is `password` (PocketBase parity) —\n\t// the server accepts `password` for any single password field and hashes\n\t// it. The raw metadata name (e.g. `password_hash`) stays as a compat alias.\n\tif (f.type === \"password\" && rawName !== \"password\") {\n\t\tmembers.unshift({\n\t\t\tkey: \"password\",\n\t\t\tline: ` ${JSON.stringify(\"password\")}${req}: ${type};`,\n\t\t});\n\t}\n\treturn members;\n}\n"],"mappings":"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","names":[]}
|