akanjs 2.1.0-rc.7 → 2.1.0-rc.9
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/document/filterMeta.ts +5 -0
- package/fetch/client/fetchClient.ts +17 -3
- package/package.json +1 -1
- package/server/resolver/database.resolver.ts +8 -5
- package/server/resolver/service.resolver.ts +6 -3
- package/service/predefinedAdaptor/database.adaptor.ts +2 -1
- package/store/action.ts +38 -15
- package/store/state.ts +4 -13
- package/types/document/filterMeta.d.ts +1 -0
package/document/filterMeta.ts
CHANGED
|
@@ -93,6 +93,11 @@ export const getFilterSortByKey = (modelRef: FilterCls, key: string) => {
|
|
|
93
93
|
return filterMeta.sort[key];
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
+
export const fillMissingFilterArgs = (filterInfo: FilterInfo, args: unknown[]) => {
|
|
97
|
+
if (args.length >= filterInfo.args.length) return args;
|
|
98
|
+
return [...args, ...Array(filterInfo.args.length - args.length).fill(undefined)];
|
|
99
|
+
};
|
|
100
|
+
|
|
96
101
|
export type BaseFilterSortKey = "latest" | "oldest";
|
|
97
102
|
export type BaseFilterQueryKey = "any";
|
|
98
103
|
export type BaseFilterKey = BaseFilterSortKey | BaseFilterQueryKey;
|
|
@@ -19,6 +19,16 @@ import { WsClient } from "./wsClient";
|
|
|
19
19
|
type FetchHandler = (...args: unknown[]) => PromiseOrObject<unknown>;
|
|
20
20
|
type UnknownRecord = Record<string, unknown>;
|
|
21
21
|
|
|
22
|
+
const isNullableArg = (arg: SerializedArg) => arg.nullable ?? arg.type === "search";
|
|
23
|
+
|
|
24
|
+
const normalizeQueryArgs = (queryArgs: unknown[], args: SerializedArg[]) => {
|
|
25
|
+
let length = Math.min(queryArgs.length, args.length);
|
|
26
|
+
while (length > 0 && isNullableArg(args[length - 1]) && queryArgs[length - 1] == null) length--;
|
|
27
|
+
return queryArgs.slice(0, length);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const expandQueryArgs = (queryArgs: unknown[], args: SerializedArg[]) => args.map((_, idx) => queryArgs[idx]);
|
|
31
|
+
|
|
22
32
|
export type FetchProxy<
|
|
23
33
|
FetchType = unknown,
|
|
24
34
|
SliceMetaObj extends Record<string, SliceMeta> = Record<never, never>,
|
|
@@ -411,14 +421,18 @@ export class FetchClient {
|
|
|
411
421
|
const listFn = this.handler[names.list] as (...args: unknown[]) => Promise<unknown[]>;
|
|
412
422
|
const insightFn = this.handler[names.insight] as (...args: unknown[]) => Promise<unknown>;
|
|
413
423
|
const initFn = async (...argData: unknown[]) => {
|
|
414
|
-
const queryArgs =
|
|
424
|
+
const queryArgs = normalizeQueryArgs(
|
|
425
|
+
Array.from({ length: Math.min(argData.length, argLength) }, (_, idx) => argData[idx]),
|
|
426
|
+
slice.args,
|
|
427
|
+
);
|
|
428
|
+
const fetchQueryArgs = expandQueryArgs(queryArgs, slice.args);
|
|
415
429
|
const option = (argData[argLength] ?? {}) as { page?: number; limit?: number; sort?: string; insight?: boolean };
|
|
416
430
|
const { page = 1, limit = 20, sort = "latest", insight: fetchInsight = true } = option;
|
|
417
431
|
const skip = (page - 1) * limit;
|
|
418
432
|
|
|
419
433
|
const [modelObjList, modelObjInsight] = (await Promise.all([
|
|
420
|
-
listFn(...
|
|
421
|
-
fetchInsight ? insightFn(...
|
|
434
|
+
listFn(...fetchQueryArgs, skip, limit, sort, { ...option, crystalize: false }),
|
|
435
|
+
fetchInsight ? insightFn(...fetchQueryArgs, { ...option, crystalize: false }) : null,
|
|
422
436
|
])) as unknown as [BaseObject[], BaseInsight];
|
|
423
437
|
const modelList = new DataList(modelObjList.map((modelObj) => new cnst.light(modelObj)));
|
|
424
438
|
const modelInsight = new cnst.insight(modelObjInsight);
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
DocumentSchema,
|
|
12
12
|
documentQueryHelper,
|
|
13
13
|
type FindQueryOption,
|
|
14
|
+
fillMissingFilterArgs,
|
|
14
15
|
getFilterInfoByKey,
|
|
15
16
|
getFilterMeta,
|
|
16
17
|
getFilterSortByKey,
|
|
@@ -338,7 +339,8 @@ export class DatabaseResolver {
|
|
|
338
339
|
const filterInfo = getFilterInfoByKey(database.filter, queryKey);
|
|
339
340
|
const queryFn = filterInfo.queryFn;
|
|
340
341
|
if (!queryFn) throw new Error(`No query function for key: ${queryKey}`);
|
|
341
|
-
const
|
|
342
|
+
const queryArgs = fillMissingFilterArgs(filterInfo, hasQueryOption ? args.slice(0, -1) : args);
|
|
343
|
+
const query = queryFn(...queryArgs, documentQueryHelper);
|
|
342
344
|
const queryOption = hasQueryOption ? lastArg : {};
|
|
343
345
|
return { query, queryOption };
|
|
344
346
|
};
|
|
@@ -371,18 +373,19 @@ export class DatabaseResolver {
|
|
|
371
373
|
return (this as unknown as DatabaseInstance).__pickId(query, queryOption);
|
|
372
374
|
},
|
|
373
375
|
[`exists${capitalize(queryKey)}`]: async function (...args: any) {
|
|
374
|
-
const query = queryFn(...args, documentQueryHelper);
|
|
376
|
+
const query = queryFn(...fillMissingFilterArgs(filterInfo, args), documentQueryHelper);
|
|
375
377
|
return (this as unknown as DatabaseInstance).__exists(query);
|
|
376
378
|
},
|
|
377
379
|
[`count${capitalize(queryKey)}`]: async function (...args: any) {
|
|
378
|
-
const query = queryFn(...args, documentQueryHelper);
|
|
380
|
+
const query = queryFn(...fillMissingFilterArgs(filterInfo, args), documentQueryHelper);
|
|
379
381
|
return (this as unknown as DatabaseInstance).__count(query);
|
|
380
382
|
},
|
|
381
383
|
[`insight${capitalize(queryKey)}`]: async function (...args: any) {
|
|
382
|
-
const query = queryFn(...args, documentQueryHelper);
|
|
384
|
+
const query = queryFn(...fillMissingFilterArgs(filterInfo, args), documentQueryHelper);
|
|
383
385
|
return (this as unknown as DatabaseInstance).__insight(query);
|
|
384
386
|
},
|
|
385
|
-
[`query${capitalize(queryKey)}`]: (...args: any) =>
|
|
387
|
+
[`query${capitalize(queryKey)}`]: (...args: any) =>
|
|
388
|
+
queryFn(...fillMissingFilterArgs(filterInfo, args), documentQueryHelper),
|
|
386
389
|
});
|
|
387
390
|
});
|
|
388
391
|
applyMixins(DatabaseModelInstance, [database.model]);
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type Doc,
|
|
9
9
|
documentQueryHelper,
|
|
10
10
|
type FindQueryOption,
|
|
11
|
+
fillMissingFilterArgs,
|
|
11
12
|
getFilterInfoByKey,
|
|
12
13
|
getFilterMeta,
|
|
13
14
|
type ListQueryOption,
|
|
@@ -116,9 +117,11 @@ export class ServiceResolver {
|
|
|
116
117
|
typeof lastArg.skip === "number" ||
|
|
117
118
|
typeof lastArg.limit === "number" ||
|
|
118
119
|
typeof lastArg.sort === "string");
|
|
119
|
-
const
|
|
120
|
+
const filterInfo = getFilterInfoByKey(database.filter, queryKey);
|
|
121
|
+
const queryFn = filterInfo.queryFn;
|
|
120
122
|
if (!queryFn) throw new Error(`No query function for key: ${queryKey}`);
|
|
121
|
-
const
|
|
123
|
+
const queryArgs = fillMissingFilterArgs(filterInfo, hasQueryOption ? args.slice(0, -1) : args);
|
|
124
|
+
const query = queryFn(...queryArgs, documentQueryHelper);
|
|
122
125
|
const queryOption = hasQueryOption ? lastArg : {};
|
|
123
126
|
return { query, queryOption };
|
|
124
127
|
};
|
|
@@ -167,7 +170,7 @@ export class ServiceResolver {
|
|
|
167
170
|
return this.__insight(query);
|
|
168
171
|
},
|
|
169
172
|
[`query${capitalize(queryKey)}`]: function (this: DatabaseService, ...args: any) {
|
|
170
|
-
return queryFn(...args, documentQueryHelper);
|
|
173
|
+
return queryFn(...fillMissingFilterArgs(filterInfo, args), documentQueryHelper);
|
|
171
174
|
},
|
|
172
175
|
});
|
|
173
176
|
});
|
|
@@ -1003,7 +1003,8 @@ export class SqliteDocumentStore {
|
|
|
1003
1003
|
const store = this;
|
|
1004
1004
|
const original = JSON.parse(JSON.stringify(sanitizeJson(originalData) ?? {})) as Record<string, unknown>;
|
|
1005
1005
|
const isNew = !originalData.id;
|
|
1006
|
-
const
|
|
1006
|
+
const hydratedData = isNew ? this.prepareDocument(data) : data;
|
|
1007
|
+
const doc = Object.assign(Object.create(this.database.doc.prototype), hydratedData);
|
|
1007
1008
|
Object.defineProperties(doc, {
|
|
1008
1009
|
set: {
|
|
1009
1010
|
value(patch: DocumentRecord) {
|
package/store/action.ts
CHANGED
|
@@ -25,6 +25,17 @@ type SliceActionKey =
|
|
|
25
25
|
| "setQueryArgsOfModel"
|
|
26
26
|
| "setSortOfModel";
|
|
27
27
|
|
|
28
|
+
const isNullableSliceArg = (arg: SerializedSlice["args"][number]) => arg.nullable ?? arg.type === "search";
|
|
29
|
+
|
|
30
|
+
const normalizeQueryArgs = (queryArgs: unknown[], sliceArgs: SerializedSlice["args"]) => {
|
|
31
|
+
let length = Math.min(queryArgs.length, sliceArgs.length);
|
|
32
|
+
while (length > 0 && isNullableSliceArg(sliceArgs[length - 1]) && queryArgs[length - 1] == null) length--;
|
|
33
|
+
return queryArgs.slice(0, length);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const expandQueryArgs = (queryArgs: unknown[], sliceArgs: SerializedSlice["args"]) =>
|
|
37
|
+
sliceArgs.map((_, idx) => queryArgs[idx]);
|
|
38
|
+
|
|
28
39
|
export interface CreateOption<Full extends { id: string }> {
|
|
29
40
|
idx?: number;
|
|
30
41
|
path?: string;
|
|
@@ -852,10 +863,13 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
852
863
|
const refreshArgLength = Math.min(args.length, slice.args.length);
|
|
853
864
|
const currentState = this.get() as { [key: string]: any };
|
|
854
865
|
const existingQueryArgs = currentState[namesOfSlice.queryArgsOfModel] as object[];
|
|
855
|
-
const queryArgs =
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
866
|
+
const queryArgs = normalizeQueryArgs(
|
|
867
|
+
[
|
|
868
|
+
...new Array(refreshArgLength).fill(null).map((_, i) => args[i] as object),
|
|
869
|
+
...existingQueryArgs.slice(refreshArgLength, slice.args.length),
|
|
870
|
+
],
|
|
871
|
+
slice.args,
|
|
872
|
+
);
|
|
859
873
|
const {
|
|
860
874
|
default: defaultFromInitForm,
|
|
861
875
|
insight,
|
|
@@ -881,15 +895,16 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
881
895
|
)
|
|
882
896
|
return;
|
|
883
897
|
else this.set({ [namesOfSlice.modelListLoading]: true });
|
|
898
|
+
const fetchQueryArgs = expandQueryArgs(queryArgs, slice.args);
|
|
884
899
|
const [modelDataList, modelInsight] = await Promise.all([
|
|
885
900
|
(fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
886
|
-
...
|
|
901
|
+
...fetchQueryArgs,
|
|
887
902
|
(page - 1) * limit,
|
|
888
903
|
limit,
|
|
889
904
|
sort,
|
|
890
905
|
{ ...fetchPolicy, onError: initForm.onError },
|
|
891
906
|
),
|
|
892
|
-
(fetch[namesOfSlice.modelInsight] as (...args: any[]) => Promise<Insight & BaseInsight>)(...
|
|
907
|
+
(fetch[namesOfSlice.modelInsight] as (...args: any[]) => Promise<Insight & BaseInsight>)(...fetchQueryArgs, {
|
|
893
908
|
...fetchPolicy,
|
|
894
909
|
onError: initForm.onError,
|
|
895
910
|
}),
|
|
@@ -934,8 +949,9 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
934
949
|
const sortOfModel = currentState[namesOfSlice.sortOfModel] as Sort;
|
|
935
950
|
if (pageOfModel === page) return;
|
|
936
951
|
this.set({ [namesOfSlice.modelListLoading]: true });
|
|
952
|
+
const fetchQueryArgs = expandQueryArgs(queryArgsOfModel, slice.args);
|
|
937
953
|
const modelDataList = await (fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
938
|
-
...
|
|
954
|
+
...fetchQueryArgs,
|
|
939
955
|
(page - 1) * limitOfModel,
|
|
940
956
|
limitOfModel,
|
|
941
957
|
sortOfModel,
|
|
@@ -957,8 +973,9 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
957
973
|
const sortOfModel = currentState[namesOfSlice.sortOfModel] as Sort;
|
|
958
974
|
if (pageOfModel === page) return;
|
|
959
975
|
const addFront = page < pageOfModel;
|
|
976
|
+
const fetchQueryArgs = expandQueryArgs(queryArgsOfModel, slice.args);
|
|
960
977
|
const modelDataList = await (fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
961
|
-
...
|
|
978
|
+
...fetchQueryArgs,
|
|
962
979
|
(page - 1) * limitOfModel,
|
|
963
980
|
limitOfModel,
|
|
964
981
|
sortOfModel,
|
|
@@ -979,8 +996,9 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
979
996
|
if (limitOfModel === limit) return;
|
|
980
997
|
const skip = (pageOfModel - 1) * limitOfModel;
|
|
981
998
|
const page = Math.max(Math.floor((skip - 1) / limit) + 1, 1);
|
|
999
|
+
const fetchQueryArgs = expandQueryArgs(queryArgsOfModel, slice.args);
|
|
982
1000
|
const modelDataList = await (fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
983
|
-
...
|
|
1001
|
+
...fetchQueryArgs,
|
|
984
1002
|
(page - 1) * limit,
|
|
985
1003
|
limit,
|
|
986
1004
|
sortOfModel,
|
|
@@ -1004,9 +1022,12 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
1004
1022
|
const currentState = this.get() as { [key: string]: any };
|
|
1005
1023
|
const options = (isSetQueryAsFunction ? args[1] : args[slice.args.length]) as FetchPolicy | undefined;
|
|
1006
1024
|
const queryArgsOfModel = currentState[namesOfSlice.queryArgsOfModel] as object[];
|
|
1007
|
-
const queryArgs =
|
|
1008
|
-
|
|
1009
|
-
|
|
1025
|
+
const queryArgs = normalizeQueryArgs(
|
|
1026
|
+
isSetQueryAsFunction
|
|
1027
|
+
? (args[0] as (...prevQueryArgs: object[]) => object[])(...queryArgsOfModel)
|
|
1028
|
+
: new Array(slice.args.length).fill(null).map((_, i) => args[i] as object),
|
|
1029
|
+
slice.args,
|
|
1030
|
+
);
|
|
1010
1031
|
const limitOfModel = currentState[namesOfSlice.limitOfModel] as number;
|
|
1011
1032
|
const sortOfModel = currentState[namesOfSlice.sortOfModel] as Sort;
|
|
1012
1033
|
if (isQueryEqual(queryArgsOfModel, queryArgs)) {
|
|
@@ -1014,16 +1035,17 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
1014
1035
|
return;
|
|
1015
1036
|
}
|
|
1016
1037
|
this.set({ [namesOfSlice.modelListLoading]: true });
|
|
1038
|
+
const fetchQueryArgs = expandQueryArgs(queryArgs, slice.args);
|
|
1017
1039
|
const [modelDataList, modelInsight] = await Promise.all([
|
|
1018
1040
|
(fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
1019
|
-
...
|
|
1041
|
+
...fetchQueryArgs,
|
|
1020
1042
|
0,
|
|
1021
1043
|
limitOfModel,
|
|
1022
1044
|
sortOfModel,
|
|
1023
1045
|
options,
|
|
1024
1046
|
),
|
|
1025
1047
|
(fetch[namesOfSlice.modelInsight] as (...args: any[]) => Promise<Insight & BaseInsight>)(
|
|
1026
|
-
...
|
|
1048
|
+
...fetchQueryArgs,
|
|
1027
1049
|
options,
|
|
1028
1050
|
),
|
|
1029
1051
|
]);
|
|
@@ -1045,8 +1067,9 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
|
|
|
1045
1067
|
const sortOfModel = currentState[namesOfSlice.sortOfModel] as Sort;
|
|
1046
1068
|
if (sortOfModel === sort) return;
|
|
1047
1069
|
this.set({ [namesOfSlice.modelListLoading]: true });
|
|
1070
|
+
const fetchQueryArgs = expandQueryArgs(queryArgsOfModel, slice.args);
|
|
1048
1071
|
const modelDataList = await (fetch[namesOfSlice.modelList] as (...args: any[]) => Promise<Light[]>)(
|
|
1049
|
-
...
|
|
1072
|
+
...fetchQueryArgs,
|
|
1050
1073
|
0,
|
|
1051
1074
|
limitOfModel,
|
|
1052
1075
|
sort,
|
package/store/state.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DataList,
|
|
1
|
+
import { DataList, type SLICE_META } from "akanjs/base";
|
|
2
2
|
import { capitalize } from "akanjs/common";
|
|
3
|
-
import {
|
|
3
|
+
import { ConstantRegistry, type DefaultOf } from "akanjs/constant";
|
|
4
4
|
import type { ExtractSort, FilterInstance } from "akanjs/document";
|
|
5
5
|
import type { SerializedSlice, SliceCls, SliceInfoArgs } from "akanjs/signal";
|
|
6
6
|
import type { Submit } from "./types";
|
|
@@ -180,16 +180,7 @@ export const createSliceState = (refName: string, slice: { [key: string]: Serial
|
|
|
180
180
|
sortOfModel: `sortOf${className}`,
|
|
181
181
|
};
|
|
182
182
|
const sliceState: Record<string, unknown> = {};
|
|
183
|
-
Object.entries(slice).forEach(([suffix
|
|
184
|
-
const defaultArgs = serializedSlice.args.map((arg) => {
|
|
185
|
-
if (arg.modelType) {
|
|
186
|
-
const modelRef = ConstantRegistry.getModelRef(arg.refName, arg.modelType) as ConstantCls;
|
|
187
|
-
return modelRef.getDefault();
|
|
188
|
-
} else {
|
|
189
|
-
const modelRef = PrimitiveRegistry.get(arg.refName);
|
|
190
|
-
return modelRef[PRIMITIVE_DEFAULT_VALUE];
|
|
191
|
-
}
|
|
192
|
-
});
|
|
183
|
+
Object.entries(slice).forEach(([suffix]) => {
|
|
193
184
|
const sliceName = `${refName}${capitalize(suffix)}`;
|
|
194
185
|
const SliceName = capitalize(sliceName);
|
|
195
186
|
const namesOfSlice: { [key in SliceStateKey]: string } = {
|
|
@@ -217,7 +208,7 @@ export const createSliceState = (refName: string, slice: { [key: string]: Serial
|
|
|
217
208
|
[namesOfSlice.lastPageOfModel]: 1,
|
|
218
209
|
[namesOfSlice.pageOfModel]: 1,
|
|
219
210
|
[namesOfSlice.limitOfModel]: 20,
|
|
220
|
-
[namesOfSlice.queryArgsOfModel]:
|
|
211
|
+
[namesOfSlice.queryArgsOfModel]: [],
|
|
221
212
|
[namesOfSlice.sortOfModel]: "latest",
|
|
222
213
|
};
|
|
223
214
|
Object.assign(sliceState, singleSliceState);
|
|
@@ -18,6 +18,7 @@ export declare const setFilterMeta: (filterRef: Cls<unknown, {
|
|
|
18
18
|
export declare const getFilterInfoByKey: <ArgNames extends string[] = [], Args extends any[] = any[], Model = any>(modelRef: FilterCls, key: string) => FilterInfo<ArgNames, Args, Model>;
|
|
19
19
|
export declare const setFilterInfoByKey: <ArgNames extends string[] = [], Args extends any[] = any[], Model = any>(modelRef: Cls<Model>, key: string, filterInfo: FilterInfo<ArgNames, Args, Model>) => void;
|
|
20
20
|
export declare const getFilterSortByKey: (modelRef: FilterCls, key: string) => unknown;
|
|
21
|
+
export declare const fillMissingFilterArgs: (filterInfo: FilterInfo, args: unknown[]) => any[];
|
|
21
22
|
export type BaseFilterSortKey = "latest" | "oldest";
|
|
22
23
|
export type BaseFilterQueryKey = "any";
|
|
23
24
|
export type BaseFilterKey = BaseFilterSortKey | BaseFilterQueryKey;
|