lazypock 0.10.2 → 0.11.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 +19 -5
- package/dist/{chunk-LVEOMG6A.js → chunk-RYUQWFG2.js} +38 -7
- package/dist/chunk-RYUQWFG2.js.map +1 -0
- package/dist/cli.cjs +37 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.global.js +37 -6
- package/dist/cli.global.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +37 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -12
- package/dist/index.d.ts +27 -12
- package/dist/index.global.js +37 -6
- 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 +66 -6
- package/src/collection.ts +22 -13
- package/src/types.ts +15 -5
- package/dist/chunk-LVEOMG6A.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -231,18 +231,29 @@ type FilterString<T, F extends string = never> = F & (F extends ValidFilter<T, F
|
|
|
231
231
|
type TopExpandKey<S extends string> = S extends `${infer A}.${string}` ? A : S;
|
|
232
232
|
/** Top-level keys of a comma-separated expand literal (`"a,b"` → `"a" | "b"`). */
|
|
233
233
|
type ExpandKeys<S extends string> = S extends "" ? never : S extends `${infer H},${infer T}` ? TopExpandKey<H> | ExpandKeys<T> : TopExpandKey<S>;
|
|
234
|
+
/**
|
|
235
|
+
* Value type of one expanded relation: the target record from the expand
|
|
236
|
+
* map (`TExpand`, e.g. the codegen-generated `PostsExpandMap`) when the key
|
|
237
|
+
* is a known relation, `unknown` otherwise.
|
|
238
|
+
*/
|
|
239
|
+
type ExpandValue<K extends string, TExpand> = K extends keyof TExpand ? TExpand[K] : unknown;
|
|
234
240
|
/**
|
|
235
241
|
* The `expand` property attached to records when `expand` is used. Keys are
|
|
236
242
|
* parsed from the caller's expand literal (dot-paths collapse to their first
|
|
237
|
-
* segment)
|
|
238
|
-
*
|
|
239
|
-
* `
|
|
243
|
+
* segment) and each value is typed from `TExpand` — a per-collection map of
|
|
244
|
+
* relation field → target record type (the codegen CLI emits these), so
|
|
245
|
+
* `record.expand.user` is `UsersRecord`, not `unknown`.
|
|
246
|
+
*
|
|
247
|
+
* Falls back to `Record<string, unknown>` when the expand value is dynamic
|
|
248
|
+
* or absent, or when no expand map is bound (hand-written services).
|
|
240
249
|
*/
|
|
241
|
-
type ExpandObj<E extends string
|
|
250
|
+
type ExpandObj<E extends string, TExpand = Record<string, unknown>> = [
|
|
242
251
|
E
|
|
243
252
|
] extends [never] ? Record<string, unknown> : [
|
|
244
253
|
string
|
|
245
|
-
] extends [E] ? Record<string, unknown> : Partial<
|
|
254
|
+
] extends [E] ? Record<string, unknown> : Partial<{
|
|
255
|
+
[K in ExpandKeys<E>]: ExpandValue<K, TExpand>;
|
|
256
|
+
}>;
|
|
246
257
|
/**
|
|
247
258
|
* Query options for list/read operations, typed against a record shape `T`.
|
|
248
259
|
*
|
|
@@ -640,8 +651,12 @@ interface RealtimeSubscribeOptions {
|
|
|
640
651
|
* Defaults to `T`. The codegen client binds a *QueryFields type that includes
|
|
641
652
|
* hidden fields — excluded from the read model but still expandable/filterable
|
|
642
653
|
* at runtime — so `expand: "hiddenRelation"` typechecks.
|
|
654
|
+
* @typeParam TExpand — Map of relation field → target record type. Defaults to
|
|
655
|
+
* `Record<string, unknown>`. The codegen client binds a per-collection
|
|
656
|
+
* *ExpandMap, so `record.expand.user` is typed as the target `UsersRecord`
|
|
657
|
+
* instead of `unknown`.
|
|
643
658
|
*/
|
|
644
|
-
declare class CollectionService<T = ApiRecord, TData = never, TFields = T
|
|
659
|
+
declare class CollectionService<T = ApiRecord, TData = never, TFields = T, TExpand = Record<string, unknown>> {
|
|
645
660
|
private http;
|
|
646
661
|
private collectionName;
|
|
647
662
|
private authStore?;
|
|
@@ -680,7 +695,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
680
695
|
* `fields` param — the server returns every non-password field.
|
|
681
696
|
* Pass `select("*")` to restore the default after a projection.
|
|
682
697
|
*/
|
|
683
|
-
select<K extends FieldKey<TFields> | "*">(...fields: K[]): CollectionService<T, TData, TFields>;
|
|
698
|
+
select<K extends FieldKey<TFields> | "*">(...fields: K[]): CollectionService<T, TData, TFields, TExpand>;
|
|
684
699
|
/**
|
|
685
700
|
* Fields to send with reads:
|
|
686
701
|
* 1. explicit `options.fields` (caller wins)
|
|
@@ -714,7 +729,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
714
729
|
* @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.
|
|
715
730
|
*/
|
|
716
731
|
getList<T2 = T, E extends string = never, S extends string = never, F extends string = never>(page?: number, perPage?: number, options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<ListResult<T2 & {
|
|
717
|
-
expand?: ExpandObj<E>;
|
|
732
|
+
expand?: ExpandObj<E, TExpand>;
|
|
718
733
|
}> | null>;
|
|
719
734
|
/**
|
|
720
735
|
* Fetch all records at once (auto-paginates). Mirrors PocketBase's
|
|
@@ -723,7 +738,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
723
738
|
* @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.
|
|
724
739
|
*/
|
|
725
740
|
getFullList<T2 = T, E extends string = never, S extends string = never, F extends string = never>(options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<Array<T2 & {
|
|
726
|
-
expand?: ExpandObj<E>;
|
|
741
|
+
expand?: ExpandObj<E, TExpand>;
|
|
727
742
|
}>>;
|
|
728
743
|
/**
|
|
729
744
|
* Fetch the first record matching a filter (PocketBase `getFirstListItem`).
|
|
@@ -732,7 +747,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
732
747
|
* @param options Optional request options.
|
|
733
748
|
*/
|
|
734
749
|
getFirstListItem<T2 = T, F extends string = never, E extends string = never, S extends string = never>(filter: FilterString<TFields, F>, options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<(T2 & {
|
|
735
|
-
expand?: ExpandObj<E>;
|
|
750
|
+
expand?: ExpandObj<E, TExpand>;
|
|
736
751
|
}) | null>;
|
|
737
752
|
/**
|
|
738
753
|
* Get a single record by ID.
|
|
@@ -740,7 +755,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
740
755
|
* @param options Optional request options.
|
|
741
756
|
*/
|
|
742
757
|
getOne<E extends string = never>(id: string, options?: ReadOptions<TFields, E> & RequestOptions): Promise<(T & {
|
|
743
|
-
expand?: ExpandObj<E>;
|
|
758
|
+
expand?: ExpandObj<E, TExpand>;
|
|
744
759
|
}) | null>;
|
|
745
760
|
/**
|
|
746
761
|
* Create a new record.
|
|
@@ -794,7 +809,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
794
809
|
* `types.schemas`). Enables schema-aware defaults: hidden fields are
|
|
795
810
|
* excluded from responses, select/expand are validated.
|
|
796
811
|
*/
|
|
797
|
-
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields>;
|
|
812
|
+
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields, TExpand>;
|
|
798
813
|
/**
|
|
799
814
|
* Subscribe to realtime changes for this collection.
|
|
800
815
|
* The event's `action` is one of `"create" | "update" | "delete"` and the
|
package/dist/index.d.ts
CHANGED
|
@@ -231,18 +231,29 @@ type FilterString<T, F extends string = never> = F & (F extends ValidFilter<T, F
|
|
|
231
231
|
type TopExpandKey<S extends string> = S extends `${infer A}.${string}` ? A : S;
|
|
232
232
|
/** Top-level keys of a comma-separated expand literal (`"a,b"` → `"a" | "b"`). */
|
|
233
233
|
type ExpandKeys<S extends string> = S extends "" ? never : S extends `${infer H},${infer T}` ? TopExpandKey<H> | ExpandKeys<T> : TopExpandKey<S>;
|
|
234
|
+
/**
|
|
235
|
+
* Value type of one expanded relation: the target record from the expand
|
|
236
|
+
* map (`TExpand`, e.g. the codegen-generated `PostsExpandMap`) when the key
|
|
237
|
+
* is a known relation, `unknown` otherwise.
|
|
238
|
+
*/
|
|
239
|
+
type ExpandValue<K extends string, TExpand> = K extends keyof TExpand ? TExpand[K] : unknown;
|
|
234
240
|
/**
|
|
235
241
|
* The `expand` property attached to records when `expand` is used. Keys are
|
|
236
242
|
* parsed from the caller's expand literal (dot-paths collapse to their first
|
|
237
|
-
* segment)
|
|
238
|
-
*
|
|
239
|
-
* `
|
|
243
|
+
* segment) and each value is typed from `TExpand` — a per-collection map of
|
|
244
|
+
* relation field → target record type (the codegen CLI emits these), so
|
|
245
|
+
* `record.expand.user` is `UsersRecord`, not `unknown`.
|
|
246
|
+
*
|
|
247
|
+
* Falls back to `Record<string, unknown>` when the expand value is dynamic
|
|
248
|
+
* or absent, or when no expand map is bound (hand-written services).
|
|
240
249
|
*/
|
|
241
|
-
type ExpandObj<E extends string
|
|
250
|
+
type ExpandObj<E extends string, TExpand = Record<string, unknown>> = [
|
|
242
251
|
E
|
|
243
252
|
] extends [never] ? Record<string, unknown> : [
|
|
244
253
|
string
|
|
245
|
-
] extends [E] ? Record<string, unknown> : Partial<
|
|
254
|
+
] extends [E] ? Record<string, unknown> : Partial<{
|
|
255
|
+
[K in ExpandKeys<E>]: ExpandValue<K, TExpand>;
|
|
256
|
+
}>;
|
|
246
257
|
/**
|
|
247
258
|
* Query options for list/read operations, typed against a record shape `T`.
|
|
248
259
|
*
|
|
@@ -640,8 +651,12 @@ interface RealtimeSubscribeOptions {
|
|
|
640
651
|
* Defaults to `T`. The codegen client binds a *QueryFields type that includes
|
|
641
652
|
* hidden fields — excluded from the read model but still expandable/filterable
|
|
642
653
|
* at runtime — so `expand: "hiddenRelation"` typechecks.
|
|
654
|
+
* @typeParam TExpand — Map of relation field → target record type. Defaults to
|
|
655
|
+
* `Record<string, unknown>`. The codegen client binds a per-collection
|
|
656
|
+
* *ExpandMap, so `record.expand.user` is typed as the target `UsersRecord`
|
|
657
|
+
* instead of `unknown`.
|
|
643
658
|
*/
|
|
644
|
-
declare class CollectionService<T = ApiRecord, TData = never, TFields = T
|
|
659
|
+
declare class CollectionService<T = ApiRecord, TData = never, TFields = T, TExpand = Record<string, unknown>> {
|
|
645
660
|
private http;
|
|
646
661
|
private collectionName;
|
|
647
662
|
private authStore?;
|
|
@@ -680,7 +695,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
680
695
|
* `fields` param — the server returns every non-password field.
|
|
681
696
|
* Pass `select("*")` to restore the default after a projection.
|
|
682
697
|
*/
|
|
683
|
-
select<K extends FieldKey<TFields> | "*">(...fields: K[]): CollectionService<T, TData, TFields>;
|
|
698
|
+
select<K extends FieldKey<TFields> | "*">(...fields: K[]): CollectionService<T, TData, TFields, TExpand>;
|
|
684
699
|
/**
|
|
685
700
|
* Fields to send with reads:
|
|
686
701
|
* 1. explicit `options.fields` (caller wins)
|
|
@@ -714,7 +729,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
714
729
|
* @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.
|
|
715
730
|
*/
|
|
716
731
|
getList<T2 = T, E extends string = never, S extends string = never, F extends string = never>(page?: number, perPage?: number, options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<ListResult<T2 & {
|
|
717
|
-
expand?: ExpandObj<E>;
|
|
732
|
+
expand?: ExpandObj<E, TExpand>;
|
|
718
733
|
}> | null>;
|
|
719
734
|
/**
|
|
720
735
|
* Fetch all records at once (auto-paginates). Mirrors PocketBase's
|
|
@@ -723,7 +738,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
723
738
|
* @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.
|
|
724
739
|
*/
|
|
725
740
|
getFullList<T2 = T, E extends string = never, S extends string = never, F extends string = never>(options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<Array<T2 & {
|
|
726
|
-
expand?: ExpandObj<E>;
|
|
741
|
+
expand?: ExpandObj<E, TExpand>;
|
|
727
742
|
}>>;
|
|
728
743
|
/**
|
|
729
744
|
* Fetch the first record matching a filter (PocketBase `getFirstListItem`).
|
|
@@ -732,7 +747,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
732
747
|
* @param options Optional request options.
|
|
733
748
|
*/
|
|
734
749
|
getFirstListItem<T2 = T, F extends string = never, E extends string = never, S extends string = never>(filter: FilterString<TFields, F>, options?: ListOptions<TFields, E, S, F> & RequestOptions): Promise<(T2 & {
|
|
735
|
-
expand?: ExpandObj<E>;
|
|
750
|
+
expand?: ExpandObj<E, TExpand>;
|
|
736
751
|
}) | null>;
|
|
737
752
|
/**
|
|
738
753
|
* Get a single record by ID.
|
|
@@ -740,7 +755,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
740
755
|
* @param options Optional request options.
|
|
741
756
|
*/
|
|
742
757
|
getOne<E extends string = never>(id: string, options?: ReadOptions<TFields, E> & RequestOptions): Promise<(T & {
|
|
743
|
-
expand?: ExpandObj<E>;
|
|
758
|
+
expand?: ExpandObj<E, TExpand>;
|
|
744
759
|
}) | null>;
|
|
745
760
|
/**
|
|
746
761
|
* Create a new record.
|
|
@@ -794,7 +809,7 @@ declare class CollectionService<T = ApiRecord, TData = never, TFields = T> {
|
|
|
794
809
|
* `types.schemas`). Enables schema-aware defaults: hidden fields are
|
|
795
810
|
* excluded from responses, select/expand are validated.
|
|
796
811
|
*/
|
|
797
|
-
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields>;
|
|
812
|
+
withSchema(schema: CollectionSchema): CollectionService<T, TData, TFields, TExpand>;
|
|
798
813
|
/**
|
|
799
814
|
* Subscribe to realtime changes for this collection.
|
|
800
815
|
* The event's `action` is one of `"create" | "update" | "delete"` and the
|
package/dist/index.global.js
CHANGED
|
@@ -1553,6 +1553,9 @@ var Lazypock = (() => {
|
|
|
1553
1553
|
updated: string;
|
|
1554
1554
|
}`);
|
|
1555
1555
|
}
|
|
1556
|
+
const collById = new Map(
|
|
1557
|
+
filtered.filter((c) => c.id !== void 0 && c.id !== "").map((c) => [String(c.id), c])
|
|
1558
|
+
);
|
|
1556
1559
|
for (const coll of filtered) {
|
|
1557
1560
|
const typeName = collectionTypeName(coll.name);
|
|
1558
1561
|
const fields = coll.fields ?? [];
|
|
@@ -1592,6 +1595,24 @@ var Lazypock = (() => {
|
|
|
1592
1595
|
body: queryLines.join("\n")
|
|
1593
1596
|
})}`
|
|
1594
1597
|
);
|
|
1598
|
+
const expandLines = [];
|
|
1599
|
+
for (const f of fields) {
|
|
1600
|
+
if (f.type !== "relation") continue;
|
|
1601
|
+
const target = collById.get(String(f.options?.collectionId ?? "")) ?? filtered.find(
|
|
1602
|
+
(c) => c.name === String(f.options?.collection ?? "")
|
|
1603
|
+
);
|
|
1604
|
+
if (!target) continue;
|
|
1605
|
+
const targetType = `${collectionTypeName(target.name)}Record${target.type === "auth" ? " & AuthRecord" : ""}`;
|
|
1606
|
+
const many = (f.options?.maxSelect ?? 1) > 1;
|
|
1607
|
+
expandLines.push(
|
|
1608
|
+
` ${JSON.stringify(fieldKey(f.name))}: ${many ? `Array<${targetType}>` : targetType};`
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
sections.push(
|
|
1612
|
+
`export interface ${typeName}ExpandMap${renderInterface({
|
|
1613
|
+
body: expandLines.join("\n")
|
|
1614
|
+
})}`
|
|
1615
|
+
);
|
|
1595
1616
|
}
|
|
1596
1617
|
sections.push(`export interface AuthRecord extends BaseRecord {
|
|
1597
1618
|
email: string;
|
|
@@ -1612,6 +1633,10 @@ ${createMapEntries}
|
|
|
1612
1633
|
).join("\n");
|
|
1613
1634
|
sections.push(`export interface LazypockQueryFields {
|
|
1614
1635
|
${queryMapEntries}
|
|
1636
|
+
}`);
|
|
1637
|
+
const expandMapEntries = filtered.map((c) => ` "${c.name}": ${collectionTypeName(c.name)}ExpandMap;`).join("\n");
|
|
1638
|
+
sections.push(`export interface LazypockExpandMaps {
|
|
1639
|
+
${expandMapEntries}
|
|
1615
1640
|
}`);
|
|
1616
1641
|
const schemaEntries = collections.map(
|
|
1617
1642
|
(c) => ` {
|
|
@@ -1665,25 +1690,31 @@ export class TypedClient extends LazypockClient {
|
|
|
1665
1690
|
// The (string & {}) intersection keeps the union from collapsing to plain
|
|
1666
1691
|
// string (which would silently kill the suggestions).
|
|
1667
1692
|
//
|
|
1668
|
-
// The service binds
|
|
1669
|
-
//
|
|
1670
|
-
//
|
|
1671
|
-
//
|
|
1693
|
+
// The service binds four types: the read model, the write-only *CreateData,
|
|
1694
|
+
// the *QueryFields (filter/sort/expand/select keys), and the *ExpandMap
|
|
1695
|
+
// (relation field \u2192 target record type). QueryFields is what lets hidden
|
|
1696
|
+
// relation fields \u2014 excluded from the read model but still expandable/
|
|
1697
|
+
// filterable at runtime \u2014 typecheck:
|
|
1672
1698
|
// client.collection("project_members").getFullList({ expand: "user" }) // \u2713
|
|
1699
|
+
// ExpandMap is what types the expanded data on the result:
|
|
1700
|
+
// const [rec] = await client.collection("posts").getFullList({ expand: "user" });
|
|
1701
|
+
// rec.expand?.user // \u2713 UsersRecord, not unknown
|
|
1673
1702
|
override collection<K extends keyof LazypockCollections | (string & {})>(
|
|
1674
1703
|
name: K,
|
|
1675
1704
|
): K extends keyof LazypockCollections
|
|
1676
1705
|
? CollectionService<
|
|
1677
1706
|
LazypockCollections[K],
|
|
1678
1707
|
LazypockCreateData[K],
|
|
1679
|
-
LazypockQueryFields[K]
|
|
1708
|
+
LazypockQueryFields[K],
|
|
1709
|
+
LazypockExpandMaps[K]
|
|
1680
1710
|
>
|
|
1681
1711
|
: CollectionService<unknown> {
|
|
1682
1712
|
return super.collection(name) as K extends keyof LazypockCollections
|
|
1683
1713
|
? CollectionService<
|
|
1684
1714
|
LazypockCollections[K],
|
|
1685
1715
|
LazypockCreateData[K],
|
|
1686
|
-
LazypockQueryFields[K]
|
|
1716
|
+
LazypockQueryFields[K],
|
|
1717
|
+
LazypockExpandMaps[K]
|
|
1687
1718
|
>
|
|
1688
1719
|
: CollectionService<unknown>;
|
|
1689
1720
|
}
|