@codecks/fetch 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,182 @@
1
+ //#region src/models/_type-helpers.d.ts
2
+ declare const __nominal__type: unique symbol;
3
+ type FilterNeverKeys<T> = { [K in keyof T as T[K] extends never ? never : K]: T[K] };
4
+ type Nominal<Type, Identifier> = Type & {
5
+ readonly [__nominal__type]: Identifier;
6
+ };
7
+ //#endregion
8
+ //#region src/models/_fields.d.ts
9
+ type TypedField<K extends string, X, Opts extends BaseOpts> = {
10
+ type: K;
11
+ _: [X, Opts];
12
+ };
13
+ type BaseOpts = {
14
+ optional?: boolean;
15
+ };
16
+ type FieldEntry = TypedField<string, any, any>;
17
+ type InferSimpleFieldEntry<T extends FieldEntry> = T extends TypedField<any, infer X, infer Opts> ? Opts extends {
18
+ optional: true;
19
+ } ? X | null | "yes" : X : never;
20
+ //#endregion
21
+ //#region src/models/_desc.d.ts
22
+ type ModelDesc<TName extends string, TFields extends FieldDesc, TRelations extends RelationsDesc, TKey extends (keyof TFields & string)[]> = {
23
+ name: TName;
24
+ keys: TKey;
25
+ fields: TFields;
26
+ relations: TRelations;
27
+ };
28
+ type AnyDesc = ModelDesc<any, any, any, any[]>;
29
+ type FieldDesc = Record<string, FieldEntry>;
30
+ type BelongsToOpts<TFk extends string> = {
31
+ type: "belongsTo";
32
+ fk: TFk;
33
+ };
34
+ type HasManyOpts = {
35
+ type: "hasMany";
36
+ };
37
+ type HasOneOpts = {
38
+ type: "hasOne";
39
+ };
40
+ type RelationOpts = BelongsToOpts<any> | HasManyOpts | HasOneOpts;
41
+ type RelationEntry<TRelName extends string, TOpts extends RelationOpts> = {
42
+ relName: TRelName;
43
+ options: TOpts;
44
+ };
45
+ type RelationsDesc = Record<string, RelationEntry<any, any>>;
46
+ type InferFieldType<T extends FieldEntry> = T extends FieldEntry ? InferSimpleFieldEntry<T> : never;
47
+ //#endregion
48
+ //#region src/has-many-filter-type.d.ts
49
+ type ModelMap$1 = Record<string, AnyDesc>;
50
+ type OneOrArray<T> = T | T[];
51
+ type NormalAndNegatedKeys<T> = T & { [K in keyof T & string as `!${K}`]: T[K] };
52
+ type OrderString<T extends string> = `${T}` | `-${T}`;
53
+ type OrderExpr<T> = {
54
+ field: T;
55
+ dir: "asc" | "desc";
56
+ };
57
+ type Order<T extends AnyDesc> = OneOrArray<OrderString<keyof T["fields"] extends string ? keyof T["fields"] : never>> | OneOrArray<OrderExpr<T["fields"]>>;
58
+ type Operators<T> = {
59
+ op: "lt" | "lte" | "gt" | "gte";
60
+ value: T;
61
+ } | {
62
+ op: "eq" | "neq";
63
+ value: T | null;
64
+ } | {
65
+ op: "in" | "notIn";
66
+ value: T[];
67
+ } | (T extends string ? {
68
+ op: "contains";
69
+ value: string;
70
+ } : never) | (T extends Array<infer El> ? {
71
+ op: "has";
72
+ value: El;
73
+ } | {
74
+ op: "overlaps";
75
+ value: El[];
76
+ } : never);
77
+ type FieldQuery<T extends AnyDesc> = { [K in keyof T["fields"]]?: null | OneOrArray<InferFieldType<T["fields"][K]>> | Operators<InferFieldType<T["fields"][K]>> };
78
+ type RelationQuery<T extends AnyDesc, TMap extends ModelMap$1> = NormalAndNegatedKeys<{ [K in keyof T["relations"]]?: SimpleFilter<TMap[T["relations"][K]["relName"]], TMap> }>;
79
+ type SimpleFilter<T extends AnyDesc, TMap extends ModelMap$1> = FieldQuery<T> | RelationQuery<T, TMap>;
80
+ type Filter<T extends AnyDesc, TMap extends ModelMap$1> = SimpleFilter<T, TMap> & {
81
+ $and?: Filter<T, TMap>[];
82
+ $or?: Filter<T, TMap>[];
83
+ };
84
+ //#endregion
85
+ //#region src/query-type.d.ts
86
+ type ModelMap = Record<string, AnyDesc>;
87
+ type SerializableRelationQuery = {
88
+ asField: true;
89
+ } | {
90
+ asField: false;
91
+ fields?: string[];
92
+ relations?: Record<string, SerializableRelationQuery>;
93
+ };
94
+ interface ModelQuery<T extends AnyDesc, TMap extends ModelMap> {
95
+ fields?: (keyof T["fields"] & string)[];
96
+ relations?: RelQuery<T, TMap>;
97
+ }
98
+ interface SimpleHasManyQuery<T extends AnyDesc, TMap extends ModelMap> extends ModelQuery<T, TMap> {
99
+ type?: "query";
100
+ orderBy?: Order<T>;
101
+ limit?: number;
102
+ offset?: number;
103
+ filter?: Filter<T, TMap>;
104
+ as?: string;
105
+ }
106
+ interface CountOrExistQuery<T extends AnyDesc, TMap extends ModelMap> {
107
+ type: "count" | "exists";
108
+ filter?: Filter<T, TMap>;
109
+ as: string;
110
+ fields?: never;
111
+ relations?: never;
112
+ }
113
+ interface FirstOrLastQuery<T extends AnyDesc, TMap extends ModelMap> extends ModelQuery<T, TMap> {
114
+ type: "first";
115
+ filter?: Filter<T, TMap>;
116
+ as: string;
117
+ orderBy: Order<T>;
118
+ }
119
+ type HasManyQuery<T extends AnyDesc, TMap extends ModelMap> = SimpleHasManyQuery<T, TMap> | CountOrExistQuery<T, TMap> | FirstOrLastQuery<T, TMap>;
120
+ type AbstractHasManyQuery = (ModelQuery<any, any> & {
121
+ type?: "query" | "first";
122
+ as?: string;
123
+ }) | {
124
+ type: "count" | "exists";
125
+ as: string;
126
+ };
127
+ type HasManyQueryWithAs<T extends AnyDesc, TMap extends ModelMap> = HasManyQuery<T, TMap> & {
128
+ as: string;
129
+ };
130
+ type HasManyRelQueryEntry<T extends AnyDesc, TMap extends ModelMap, K extends keyof ExtractHasMany<T, TMap>> = HasManyQuery<TMap[T["relations"][K]["relName"]], TMap> | HasManyQueryWithAs<TMap[T["relations"][K]["relName"]], TMap>[];
131
+ type RelQueryEntry<T extends AnyDesc, TMap extends ModelMap, K extends keyof T["relations"]> = K extends keyof ExtractHasMany<T, TMap> ? HasManyRelQueryEntry<T, TMap, K> : ModelQuery<TMap[T["relations"][K]["relName"]], TMap>;
132
+ /**
133
+ * examples for account:
134
+ * {disabledBy: {fields: []}} // belongst
135
+ * {cards: {fields: []}}
136
+ * {cards: [{as: "myCards", fields: []}]}
137
+ */
138
+ type RelQuery<T extends AnyDesc, TMap extends ModelMap> = { [K in keyof T["relations"]]?: RelQueryEntry<T, TMap, K> };
139
+ type EnsureModelQuery<T> = T extends ModelQuery<any, any> ? T : never;
140
+ type EnsureHasManyQuery<T> = T extends AbstractHasManyQuery ? T : never;
141
+ type EnrichBelongsTo<M extends AnyDesc, TMap extends ModelMap> = FilterNeverKeys<{ [K in keyof M["relations"]]: M["relations"][K] extends RelationEntry<any, infer Opts> ? Opts extends BelongsToOpts<infer TFk> ? {
142
+ model: TMap[M["relations"][K]["relName"]];
143
+ fk: TFk;
144
+ field: M["fields"][TFk] extends TypedField<"belongsTo", infer FieldType, infer FieldOpts> ? {
145
+ type: FieldType;
146
+ } & FieldOpts : never;
147
+ } : never : never }>;
148
+ type ExtractHasMany<M extends AnyDesc, TMap extends ModelMap> = FilterNeverKeys<{ [K in keyof M["relations"]]: M["relations"][K] extends RelationEntry<infer RelName, {
149
+ type: "hasMany";
150
+ }> ? {
151
+ model: TMap[RelName];
152
+ } : never }>;
153
+ type ExtractHasOne<M extends AnyDesc, TMap extends ModelMap> = FilterNeverKeys<{ [K in keyof M["relations"]]: M["relations"][K] extends RelationEntry<infer RelName, {
154
+ type: "hasOne";
155
+ }> ? {
156
+ model: TMap[RelName];
157
+ } : never }>;
158
+ type InferModelQuery<M extends AnyDesc, Q extends ModelQuery<M, TMap>, TMap extends ModelMap> = (Q["fields"] extends (keyof M["fields"])[] ? { [K in Q["fields"][number]]: InferFieldType<M["fields"][K]> } : {}) & (Q["relations"] extends RelQuery<M, TMap> ? InferRelQuery<M, Q["relations"], TMap> : {}) & { [K in M["keys"][number] & string]: InferFieldType<M["fields"][K]> } & {
159
+ "~model": M["name"];
160
+ "~key": string;
161
+ };
162
+ type IsOptional<T, Test> = Test extends true ? T | null : T;
163
+ type EmptyObjIfNever<T> = [T] extends [never] ? {} : T;
164
+ type ExtractRelQueryArray<M extends AnyDesc, TMap extends ModelMap, Q extends RelQuery<M, TMap>> = { [K in keyof Q]: K extends keyof ExtractHasMany<M, TMap> ? Q[K] extends HasManyQueryWithAs<any, any>[] ? { [Item in Q[K][number] as Item["as"]]: InferHasMany<ExtractHasMany<M, TMap>[K]["model"], TMap, Item> } : never : never }[keyof Q];
165
+ type InferHasMany<M extends AnyDesc, TMap extends ModelMap, QM extends HasManyQuery<M, TMap>> = QM extends {
166
+ type: "count";
167
+ } ? number : QM extends {
168
+ type: "exist";
169
+ } ? boolean : QM extends {
170
+ type: "first";
171
+ } ? InferModelQuery<M, EnsureModelQuery<QM>, TMap> | null : InferModelQuery<M, EnsureModelQuery<QM>, TMap>[];
172
+ type InferRelEntry<M extends AnyDesc, TMap extends ModelMap, Q extends RelQuery<any, any>, K extends keyof Q> = K extends keyof EnrichBelongsTo<M, TMap> ? IsOptional<InferModelQuery<EnrichBelongsTo<M, TMap>[K]["model"], EnsureModelQuery<Q[K]>, TMap>, EnrichBelongsTo<M, TMap>[K]["field"]["optional"]> : K extends keyof ExtractHasMany<M, TMap> ? InferHasMany<ExtractHasMany<M, TMap>[K]["model"], TMap, EnsureHasManyQuery<Q[K]>> : K extends keyof ExtractHasOne<M, TMap> ? InferModelQuery<ExtractHasOne<M, TMap>[K]["model"], EnsureModelQuery<Q[K]>, TMap> : never;
173
+ type InferKeyName<Q extends RelQuery<any, any>, K extends keyof Q> = Q[K] extends Array<any> ? never : Q[K] extends {
174
+ as: string;
175
+ } ? K extends keyof ExtractHasMany<any, any> ? Q[K]["as"] : K : K;
176
+ type InferRelQuery<M extends AnyDesc, Q extends RelQuery<M, TMap>, TMap extends ModelMap> = EmptyObjIfNever<ExtractRelQueryArray<M, TMap, Q>> & EmptyObjIfNever<{ [K in keyof Q as InferKeyName<Q, K>]: InferRelEntry<M, TMap, Q, K> }>;
177
+ type Instance<M extends keyof ModelMap> = {
178
+ "~model": M;
179
+ "~key": string;
180
+ };
181
+ //#endregion
182
+ export { AnyDesc, InferModelQuery, InferRelQuery, Instance, ModelDesc, ModelQuery, Nominal, RelQuery, RelationEntry, SerializableRelationQuery, TypedField };
@@ -0,0 +1,44 @@
1
+ import { AnyDesc, ModelQuery } from "./query-type-MH8IxqbW.js";
2
+ import { BaseLoader, LoaderResult } from "./loader-types-DJdGWL4B.js";
3
+
4
+ //#region src/_exploration/immediate-cache.d.ts
5
+ type FieldMeta = {
6
+ state: "fresh";
7
+ } | {
8
+ state: "dirty";
9
+ };
10
+ interface FieldCache<T = any> {
11
+ value: T;
12
+ partKeys: string[];
13
+ meta: FieldMeta;
14
+ }
15
+ type ModelInstance = Map<string, FieldCache>;
16
+ type ModelCache = Map<string, ModelInstance>;
17
+ declare class ImmediateCache {
18
+ cache: ModelCache;
19
+ partKeyToFields: Map<string, FieldCache<any>[]>;
20
+ private getInstanceKey;
21
+ get(model: string, key: string, field: string): FieldCache | undefined;
22
+ set(model: string, key: string, partialInstance: Record<string, {
23
+ value: unknown;
24
+ partKeys: string[];
25
+ }>, meta: FieldMeta): void;
26
+ setMetaByPartKeys(partKeys: string[], meta: FieldMeta): void;
27
+ }
28
+ //#endregion
29
+ //#region src/_exploration/store.d.ts
30
+ declare class Store {
31
+ private loader;
32
+ cache: ImmediateCache;
33
+ modelMap: Record<string, AnyDesc>;
34
+ constructor(loader: BaseLoader);
35
+ loadData(model: string, ids: string[], q: ModelQuery<any, any>, acceptDirty?: boolean, iteration?: number): LoaderResult;
36
+ onLoaded(model: string, key: string, partialInstance: Record<string, unknown>): void;
37
+ /**
38
+ * Recursively check if query data is in cache
39
+ * Accumulates missing requests in the missingRequests array
40
+ */
41
+ private checkQueryRecursive;
42
+ }
43
+ //#endregion
44
+ export { Store };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codecks/fetch",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Quickly create deeply nested queries for the Codecks API with advanced TypeScript support",
5
5
  "type": "module",
6
6
  "license": "MIT",