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.
@@ -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 = Array.from({ length: argLength }, (_, idx) => argData[idx]);
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(...queryArgs, skip, limit, sort, { ...option, crystalize: false }),
421
- fetchInsight ? insightFn(...queryArgs, { ...option, crystalize: false }) : null,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "2.1.0-rc.7",
3
+ "version": "2.1.0-rc.9",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -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 query = queryFn(...(hasQueryOption ? args.slice(0, -1) : args), documentQueryHelper);
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) => queryFn(...args, documentQueryHelper),
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 queryFn = getFilterInfoByKey(database.filter, queryKey).queryFn;
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 query = queryFn(...(hasQueryOption ? args.slice(0, -1) : args), documentQueryHelper);
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 doc = Object.assign(Object.create(this.database.doc.prototype), data);
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
- ...new Array(refreshArgLength).fill(null).map((_, i) => args[i] as object),
857
- ...existingQueryArgs.slice(refreshArgLength, slice.args.length),
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
- ...queryArgs,
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>)(...queryArgs, {
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
- ...queryArgsOfModel,
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
- ...queryArgsOfModel,
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
- ...queryArgsOfModel,
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 = isSetQueryAsFunction
1008
- ? (args[0] as (...prevQueryArgs: object[]) => object[])(...queryArgsOfModel)
1009
- : new Array(slice.args.length).fill(null).map((_, i) => args[i] as object);
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
- ...queryArgs,
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
- ...queryArgs,
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
- ...queryArgsOfModel,
1072
+ ...fetchQueryArgs,
1050
1073
  0,
1051
1074
  limitOfModel,
1052
1075
  sort,
package/store/state.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { DataList, PRIMITIVE_DEFAULT_VALUE, PrimitiveRegistry, type SLICE_META } from "akanjs/base";
1
+ import { DataList, type SLICE_META } from "akanjs/base";
2
2
  import { capitalize } from "akanjs/common";
3
- import { type ConstantCls, ConstantRegistry, type DefaultOf } from "akanjs/constant";
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, serializedSlice]) => {
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]: defaultArgs,
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;