akanjs 2.3.8-rc.2 → 2.3.8-rc.4

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/base/symbols.ts CHANGED
@@ -4,6 +4,9 @@ export const FILTER_META = Symbol.for("akan.filter");
4
4
  export const LOADER_META = Symbol.for("akan.loader");
5
5
  export const INJECT_META = Symbol.for("akan.inject");
6
6
  export const ENDPOINT_META = Symbol.for("akan.endpoint");
7
+ export const ENDPOINT_DICT_SHAPE: unique symbol = Symbol.for("akan.endpoint.dictShape") as never;
8
+ export const SLICE_DICT_SHAPE: unique symbol = Symbol.for("akan.slice.dictShape") as never;
9
+ export const FILTER_DICT_SHAPE: unique symbol = Symbol.for("akan.filter.dictShape") as never;
7
10
  export const INTERNAL_META = Symbol.for("akan.internal");
8
11
  export const STATE_META = Symbol.for("akan.state");
9
12
  export const STATE_INIT_META = Symbol.for("akan.state.init");
@@ -1,40 +1,62 @@
1
- import type { GetStateObject } from "akanjs/base";
1
+ import type { ENDPOINT_DICT_SHAPE, FILTER_DICT_SHAPE, GetStateObject, SLICE_DICT_SHAPE } from "akanjs/base";
2
2
  import { capitalize } from "akanjs/common";
3
3
  import type { BaseInsight, BaseObject } from "akanjs/constant";
4
- import type { BaseFilterQueryKey, BaseFilterSortKey, FilterCls, FilterInfo, FilterInstance } from "akanjs/document";
5
4
  import type {
6
- EndpInfoArgNames,
5
+ BaseFilterQueryKey,
6
+ BaseFilterSortKey,
7
+ FilterCls,
8
+ FilterDictShape as FilterCompactShape,
9
+ FilterDictArgShape,
10
+ FilterInfo,
11
+ FilterInstance,
12
+ } from "akanjs/document";
13
+ import type {
7
14
  EndpointCls,
15
+ EndpointDictShape as EndpointCompactShape,
8
16
  EndpointInfo,
9
17
  SliceCls,
18
+ SliceDictShape as SliceCompactShape,
10
19
  SliceInfo,
11
- SliceInfoArgNames,
12
20
  } from "akanjs/signal";
13
21
  import type { DictionaryNode, RootDictionary } from "./trans";
14
22
 
15
23
  type MutableDictionaryNode = DictionaryNode & { t?: string; desc?: DictionaryNode };
16
24
  type EnumValueKey = string | number;
17
- type AnyFilterShape = FilterInstance<Record<string, FilterInfo>, Record<string, unknown>>;
25
+ type DictArgShape = { [key: string]: readonly string[] };
26
+ type AnyFilterShape = FilterCompactShape<FilterInstance<Record<string, FilterInfo>, Record<string, unknown>>>;
18
27
  type DictFilterShape<Filter> =
19
28
  Filter extends FilterCls<infer FilterShape>
20
- ? FilterShape
21
- : Filter extends FilterInstance
22
- ? Filter
23
- : Filter extends { query: Record<string, FilterInfo>; sort: Record<string, unknown> }
24
- ? Filter
25
- : AnyFilterShape;
29
+ ? FilterCompactShape<FilterShape>
30
+ : Filter extends { readonly [FILTER_DICT_SHAPE]: infer CompactShape extends FilterDictArgShape }
31
+ ? CompactShape
32
+ : Filter extends FilterInstance
33
+ ? FilterCompactShape<Filter>
34
+ : Filter extends { query: Record<string, FilterInfo>; sort: Record<string, unknown> }
35
+ ? FilterCompactShape<Filter>
36
+ : Filter extends { query: DictArgShape; sort: Record<string, true> }
37
+ ? Filter
38
+ : AnyFilterShape;
26
39
  type DictSliceShape<Slice> =
27
40
  Slice extends SliceCls<infer _SrvModule, infer SliceInfoObj>
28
- ? SliceInfoObj
29
- : Slice extends Record<string, SliceInfo>
30
- ? Slice
31
- : Record<never, never>;
41
+ ? SliceCompactShape<SliceInfoObj>
42
+ : Slice extends { readonly [SLICE_DICT_SHAPE]: infer CompactShape extends DictArgShape }
43
+ ? CompactShape
44
+ : Slice extends DictArgShape
45
+ ? Slice
46
+ : Slice extends Record<string, SliceInfo>
47
+ ? SliceCompactShape<Slice>
48
+ : Record<never, never>;
32
49
  type DictEndpointShape<Endpoint> =
33
50
  Endpoint extends EndpointCls<infer _SrvModule, infer EndpointInfoObj>
34
- ? EndpointInfoObj
35
- : Endpoint extends Record<string, EndpointInfo>
36
- ? Endpoint
37
- : Record<never, never>;
51
+ ? EndpointCompactShape<EndpointInfoObj>
52
+ : Endpoint extends { readonly [ENDPOINT_DICT_SHAPE]: infer CompactShape extends DictArgShape }
53
+ ? CompactShape
54
+ : Endpoint extends DictArgShape
55
+ ? Endpoint
56
+ : Endpoint extends Record<string, EndpointInfo>
57
+ ? EndpointCompactShape<Endpoint>
58
+ : Record<never, never>;
59
+ type DictArgNames<ArgNames> = ArgNames extends readonly string[] ? ArgNames[number] : never;
38
60
  type DictFilterQuery<Filter> = DictFilterShape<Filter>["query"];
39
61
  type DictFilterSort<Filter> = DictFilterShape<Filter>["sort"];
40
62
 
@@ -282,22 +304,14 @@ export class ModelDictInfo<
282
304
  }
283
305
  query<Filter>(
284
306
  translate: (fn: (trans: Languages) => FunctionTranslation<Languages>) => {
285
- [K in Exclude<keyof DictFilterQuery<Filter>, QueryKey>]: DictFilterQuery<Filter>[K] extends FilterInfo<
286
- infer ArgNames,
287
- infer _Args,
288
- infer _Model
289
- >
290
- ? FunctionTranslation<Languages, ArgNames[number]>
291
- : never;
307
+ [K in Exclude<keyof DictFilterQuery<Filter>, QueryKey>]: FunctionTranslation<
308
+ Languages,
309
+ DictArgNames<DictFilterQuery<Filter>[K]>
310
+ >;
292
311
  },
293
312
  ) {
294
313
  Object.assign(this.queryDictionary, translate(fn), ModelDictInfo.baseQueryDictionary) as unknown as {
295
- [K in keyof DictFilterQuery<Filter>]: FunctionTranslation<
296
- Languages,
297
- DictFilterQuery<Filter>[K] extends FilterInfo<infer ArgNames, infer _Args, infer _Model>
298
- ? ArgNames[number]
299
- : never
300
- >;
314
+ [K in keyof DictFilterQuery<Filter>]: FunctionTranslation<Languages, DictArgNames<DictFilterQuery<Filter>[K]>>;
301
315
  };
302
316
  return this as unknown as ModelDictInfo<
303
317
  Languages,
@@ -363,10 +377,10 @@ export class ModelDictInfo<
363
377
  }
364
378
  slice<Slice>(
365
379
  translate: (fn: (trans: Languages) => FunctionTranslation<Languages>) => {
366
- [K in Exclude<keyof DictSliceShape<Slice>, SliceKey>]: DictSliceShape<Slice>[K] extends infer Info extends
367
- SliceInfo
368
- ? FunctionTranslation<Languages, SliceInfoArgNames<Info>[number]>
369
- : never;
380
+ [K in Exclude<keyof DictSliceShape<Slice>, SliceKey>]: FunctionTranslation<
381
+ Languages,
382
+ DictArgNames<DictSliceShape<Slice>[K]>
383
+ >;
370
384
  },
371
385
  ) {
372
386
  Object.assign(this.sliceDictionary, translate(fn), ModelDictInfo.baseSliceDictionary) as unknown as {
@@ -388,12 +402,10 @@ export class ModelDictInfo<
388
402
  }
389
403
  endpoint<Endpoint>(
390
404
  translate: (fn: (trans: Languages) => FunctionTranslation<Languages>) => {
391
- [K in Exclude<
392
- keyof DictEndpointShape<Endpoint>,
393
- EndpointKey
394
- >]: DictEndpointShape<Endpoint>[K] extends infer Info extends EndpointInfo
395
- ? FunctionTranslation<Languages, EndpInfoArgNames<Info>[number]>
396
- : never;
405
+ [K in Exclude<keyof DictEndpointShape<Endpoint>, EndpointKey>]: FunctionTranslation<
406
+ Languages,
407
+ DictArgNames<DictEndpointShape<Endpoint>[K]>
408
+ >;
397
409
  },
398
410
  ) {
399
411
  Object.assign(this.endpointDictionary, translate(fn)) as unknown as {
@@ -1009,9 +1021,10 @@ export class ServiceDictInfo<
1009
1021
  }
1010
1022
  endpoint<Endpoint>(
1011
1023
  translate: (fn: (trans: Languages) => FunctionTranslation<Languages>) => {
1012
- [K in keyof DictEndpointShape<Endpoint>]: DictEndpointShape<Endpoint>[K] extends infer Info extends EndpointInfo
1013
- ? FunctionTranslation<Languages, EndpInfoArgNames<Info>[number]>
1014
- : never;
1024
+ [K in keyof DictEndpointShape<Endpoint>]: FunctionTranslation<
1025
+ Languages,
1026
+ DictArgNames<DictEndpointShape<Endpoint>[K]>
1027
+ >;
1015
1028
  },
1016
1029
  ) {
1017
1030
  Object.assign(this.endpointDictionary, translate(fn)) as unknown as {
@@ -1,7 +1,28 @@
1
- import type { GetStateObject, MergedValues } from "akanjs/base";
1
+ import type {
2
+ ENDPOINT_DICT_SHAPE,
3
+ FILTER_DICT_SHAPE,
4
+ GetStateObject,
5
+ MergedValues,
6
+ SLICE_DICT_SHAPE,
7
+ } from "akanjs/base";
2
8
  import type { BaseInsight, BaseObject } from "akanjs/constant";
3
- import type { FilterCls, FilterInfo, FilterInstance } from "akanjs/document";
4
- import type { EndpInfoArgNames, EndpointInfo, SliceInfo, SliceInfoArgNames, SliceInfoRefName } from "akanjs/signal";
9
+ import type {
10
+ FilterCls,
11
+ FilterDictShape as FilterCompactShape,
12
+ FilterDictArgShape,
13
+ FilterInfo,
14
+ FilterInstance,
15
+ } from "akanjs/document";
16
+ import type {
17
+ EndpointCls,
18
+ EndpointDictShape as EndpointCompactShape,
19
+ EndpointInfo,
20
+ SliceCls,
21
+ SliceDictShape as SliceCompactShape,
22
+ SliceInfo,
23
+ SliceInfoArgNames,
24
+ SliceInfoRefName,
25
+ } from "akanjs/signal";
5
26
  import type { ModelDictInfo, ScalarDictInfo, ServiceDictInfo } from ".";
6
27
 
7
28
  interface Trans {
@@ -16,35 +37,61 @@ interface FnTrans<ArgKey extends string> {
16
37
  desc?: string;
17
38
  arg?: { [key in ArgKey]: FieldTrans };
18
39
  }
19
- type AnyFilterShape = FilterInstance<Record<string, FilterInfo>, Record<string, unknown>>;
40
+ type DictArgShape = { [key: string]: readonly string[] };
41
+ type AnyFilterShape = FilterCompactShape<FilterInstance<Record<string, FilterInfo>, Record<string, unknown>>>;
20
42
  type DictFilterShape<Filter> =
21
43
  Filter extends FilterCls<infer FilterShape>
22
- ? FilterShape
23
- : Filter extends FilterInstance
24
- ? Filter
25
- : Filter extends { query: Record<string, FilterInfo>; sort: Record<string, unknown> }
26
- ? Filter
27
- : AnyFilterShape;
44
+ ? FilterCompactShape<FilterShape>
45
+ : Filter extends { readonly [FILTER_DICT_SHAPE]: infer CompactShape extends FilterDictArgShape }
46
+ ? CompactShape
47
+ : Filter extends FilterInstance
48
+ ? FilterCompactShape<Filter>
49
+ : Filter extends { query: Record<string, FilterInfo>; sort: Record<string, unknown> }
50
+ ? FilterCompactShape<Filter>
51
+ : Filter extends { query: DictArgShape; sort: Record<string, true> }
52
+ ? Filter
53
+ : AnyFilterShape;
28
54
  type DictFilterQuery<Filter> = DictFilterShape<Filter>["query"];
29
55
  type DictFilterSort<Filter> = DictFilterShape<Filter>["sort"];
56
+ type DictArgNames<ArgNames> = ArgNames extends readonly string[] ? ArgNames[number] : never;
57
+ type DictEndpointShape<Endpoint> =
58
+ Endpoint extends EndpointCls<infer _SrvModule, infer EndpointInfoObj>
59
+ ? EndpointCompactShape<EndpointInfoObj>
60
+ : Endpoint extends { readonly [ENDPOINT_DICT_SHAPE]: infer CompactShape extends DictArgShape }
61
+ ? CompactShape
62
+ : Endpoint extends DictArgShape
63
+ ? Endpoint
64
+ : Endpoint extends Record<string, EndpointInfo>
65
+ ? EndpointCompactShape<Endpoint>
66
+ : Record<never, never>;
67
+ type DictSliceShape<Slice> =
68
+ Slice extends SliceCls<infer _SrvModule, infer SliceInfoObj>
69
+ ? SliceCompactShape<SliceInfoObj>
70
+ : Slice extends { readonly [SLICE_DICT_SHAPE]: infer CompactShape extends DictArgShape }
71
+ ? CompactShape
72
+ : Slice extends DictArgShape
73
+ ? Slice
74
+ : Slice extends Record<string, SliceInfo>
75
+ ? SliceCompactShape<Slice>
76
+ : Record<never, never>;
30
77
  type FilterTranslatorKey<Filter> = {
31
78
  [Key in keyof DictFilterQuery<Filter> & string]:
32
79
  | `${Key}`
33
80
  | `${Key}.desc`
34
- | (DictFilterQuery<Filter>[Key] extends FilterInfo<infer ArgNames, infer _Args>
35
- ? ArgNames[number] extends string
36
- ? `${Key}.arg.${ArgNames[number]}` | `${Key}.arg.${ArgNames[number]}.desc`
37
- : never
81
+ | (DictArgNames<DictFilterQuery<Filter>[Key]> extends string
82
+ ?
83
+ | `${Key}.arg.${DictArgNames<DictFilterQuery<Filter>[Key]>}`
84
+ | `${Key}.arg.${DictArgNames<DictFilterQuery<Filter>[Key]>}.desc`
38
85
  : never);
39
86
  }[keyof DictFilterQuery<Filter> & string];
40
- type EndpointTranslatorKey<Endpoint extends { [key: string]: EndpointInfo }> = {
41
- [Key in keyof Endpoint & string]:
87
+ type EndpointTranslatorKey<Endpoint> = {
88
+ [Key in keyof DictEndpointShape<Endpoint> & string]:
42
89
  | `${Key}`
43
90
  | `${Key}.desc`
44
- | `${Key}.arg.${EndpInfoArgNames<Endpoint[Key]>[number]}`
45
- | `${Key}.arg.${EndpInfoArgNames<Endpoint[Key]>[number]}.desc`;
46
- }[keyof Endpoint & string];
47
- type SliceTranslatorKey<Slice> = {
91
+ | `${Key}.arg.${DictArgNames<DictEndpointShape<Endpoint>[Key]>}`
92
+ | `${Key}.arg.${DictArgNames<DictEndpointShape<Endpoint>[Key]>}.desc`;
93
+ }[keyof DictEndpointShape<Endpoint> & string];
94
+ type FullSliceTranslatorKey<Slice> = {
48
95
  [Key in keyof Slice & string]: Slice[Key] extends infer Info extends SliceInfo
49
96
  ?
50
97
  | `${SliceInfoRefName<Info>}List${Capitalize<Key>}`
@@ -57,6 +104,21 @@ type SliceTranslatorKey<Slice> = {
57
104
  | `${SliceInfoRefName<Info>}Insight${Capitalize<Key>}.arg.${SliceInfoArgNames<Info>[number]}.desc`
58
105
  : never;
59
106
  }[keyof Slice & string];
107
+ type CompactSliceTranslatorKey<T extends string, Slice> = {
108
+ [Key in keyof DictSliceShape<Slice> & string]: Key extends ""
109
+ ? never
110
+ :
111
+ | `${T}List${Capitalize<Key>}`
112
+ | `${T}List${Capitalize<Key>}.desc`
113
+ | `${T}List${Capitalize<Key>}.arg.${DictArgNames<DictSliceShape<Slice>[Key]> | "skip" | "limit" | "sort"}`
114
+ | `${T}List${Capitalize<Key>}.arg.${DictArgNames<DictSliceShape<Slice>[Key]> | "skip" | "limit" | "sort"}.desc`
115
+ | `${T}Insight${Capitalize<Key>}`
116
+ | `${T}Insight${Capitalize<Key>}.desc`
117
+ | `${T}Insight${Capitalize<Key>}.arg.${DictArgNames<DictSliceShape<Slice>[Key]>}`
118
+ | `${T}Insight${Capitalize<Key>}.arg.${DictArgNames<DictSliceShape<Slice>[Key]>}.desc`;
119
+ }[keyof DictSliceShape<Slice> & string];
120
+ type SliceTranslatorKey<T extends string, Slice> =
121
+ Slice extends Record<string, SliceInfo> ? FullSliceTranslatorKey<Slice> : CompactSliceTranslatorKey<T, Slice>;
60
122
 
61
123
  type SliceApiTrans<
62
124
  T extends string,
@@ -85,8 +147,8 @@ export type ModelTrans<
85
147
  Model extends BaseObject,
86
148
  Insight extends BaseInsight,
87
149
  Filter,
88
- Slice extends { [key: string]: SliceInfo },
89
- Endpoint extends { [key: string]: EndpointInfo },
150
+ Slice,
151
+ Endpoint,
90
152
  ErrorKey extends string,
91
153
  EtcKey extends string,
92
154
  > = {
@@ -95,35 +157,25 @@ export type ModelTrans<
95
157
  model: { [K in keyof GetStateObject<Model>]: FieldTrans };
96
158
  insight: { [K in keyof GetStateObject<Insight>]: FieldTrans };
97
159
  query: {
98
- [K in keyof DictFilterQuery<Filter>]: DictFilterQuery<Filter>[K] extends FilterInfo<infer ArgNames, infer _Args>
99
- ? FnTrans<ArgNames[number]>
100
- : never;
160
+ [K in keyof DictFilterQuery<Filter>]: FnTrans<DictArgNames<DictFilterQuery<Filter>[K]>>;
101
161
  };
102
162
  sort: { [K in keyof DictFilterSort<Filter>]: FieldTrans };
103
163
  api: {
104
- [K in keyof Endpoint]: FnTrans<EndpInfoArgNames<Endpoint[K]>[number]>;
164
+ [K in keyof DictEndpointShape<Endpoint>]: FnTrans<DictArgNames<DictEndpointShape<Endpoint>[K]>>;
105
165
  } & BaseModelCrudGetApiTrans<T> &
106
166
  MergedValues<{
107
- [K in keyof Slice]: SliceApiTrans<SliceInfoRefName<Slice[K]>, K & string, SliceInfoArgNames<Slice[K]>[number]>;
167
+ [K in keyof DictSliceShape<Slice>]: SliceApiTrans<T, K & string, DictArgNames<DictSliceShape<Slice>[K]>>;
108
168
  }>;
109
169
  error: { [K in ErrorKey]: Trans };
110
170
  } & { [K in EtcKey]: Trans };
111
- export type ModelTranslatorKey<
112
- T extends string,
113
- Model,
114
- Insight,
115
- Filter,
116
- Slice extends { [key: string]: SliceInfo },
117
- Endpoint extends { [key: string]: EndpointInfo },
118
- EtcKey extends string,
119
- > =
171
+ export type ModelTranslatorKey<T extends string, Model, Insight, Filter, Slice, Endpoint, EtcKey extends string> =
120
172
  | `${T}.modelName`
121
173
  | `${T}.modelDesc`
122
174
  | `${T}.${keyof GetStateObject<Model> & string}${"" | ".desc"}`
123
175
  | `${T}.insight.${keyof GetStateObject<Insight> & string}${"" | ".desc"}`
124
176
  | `${T}.query.${FilterTranslatorKey<Filter>}`
125
177
  | `${T}.sort.${keyof DictFilterSort<Filter> & string}${"" | ".desc"}`
126
- | `${T}.signal.${EndpointTranslatorKey<Endpoint> | SliceTranslatorKey<Slice>}`
178
+ | `${T}.signal.${EndpointTranslatorKey<Endpoint> | SliceTranslatorKey<T, Slice>}`
127
179
  | `${T}.${EtcKey}`;
128
180
 
129
181
  export type ScalarTrans<_T extends string, Model, ErrorKey extends string, EtcKey extends string> = {
@@ -138,22 +190,15 @@ export type ScalarTranslatorKey<T extends string, Model, EtcKey extends string>
138
190
  | `${T}.${keyof GetStateObject<Model> & string}${"" | ".desc"}`
139
191
  | `${T}.${EtcKey}`;
140
192
 
141
- export type ServiceTrans<
142
- _T extends string,
143
- Endpoint extends { [key: string]: EndpointInfo },
144
- ErrorKey extends string,
145
- EtcKey extends string,
146
- > = {
193
+ export type ServiceTrans<_T extends string, Endpoint, ErrorKey extends string, EtcKey extends string> = {
147
194
  api: {
148
- [K in keyof Endpoint]: FnTrans<EndpInfoArgNames<Endpoint[K]>[number]>;
195
+ [K in keyof DictEndpointShape<Endpoint>]: FnTrans<DictArgNames<DictEndpointShape<Endpoint>[K]>>;
149
196
  };
150
197
  error: { [K in ErrorKey]: Trans };
151
198
  } & { [K in EtcKey]: Trans };
152
- export type ServiceTranslatorKey<
153
- T extends string,
154
- Endpoint extends { [key: string]: EndpointInfo },
155
- EtcKey extends string,
156
- > = `${T}.signal.${EndpointTranslatorKey<Endpoint>}` | `${T}.${EtcKey}`;
199
+ export type ServiceTranslatorKey<T extends string, Endpoint, EtcKey extends string> =
200
+ | `${T}.signal.${EndpointTranslatorKey<Endpoint>}`
201
+ | `${T}.${EtcKey}`;
157
202
 
158
203
  export type EnumTrans<EnumValue extends string | number> = {
159
204
  [key in EnumValue]: Trans;
@@ -174,8 +219,8 @@ export const registerModelTrans = <
174
219
  Model extends BaseObject,
175
220
  Insight extends BaseInsight,
176
221
  Filter,
177
- Slice extends { [key: string]: SliceInfo },
178
- Endpoint extends { [key: string]: EndpointInfo },
222
+ Slice,
223
+ Endpoint,
179
224
  ModelDict,
180
225
  >(
181
226
  modelDict: ModelDict,
@@ -233,7 +278,7 @@ export const registerScalarTrans = <T extends string, Model, ScalarDict>(
233
278
  : never;
234
279
  };
235
280
 
236
- export const registerServiceTrans = <T extends string, Endpoint extends { [key: string]: EndpointInfo }, ServiceDict>(
281
+ export const registerServiceTrans = <T extends string, Endpoint, ServiceDict>(
237
282
  serviceDict: ServiceDict,
238
283
  ): ServiceDict extends ServiceDictInfo<infer _Languages, infer _EndpointKey, infer ErrorKey, infer EtcKey>
239
284
  ? DictModule<ServiceTranslatorKey<T, Endpoint, EtcKey>, `${T}.error.${ErrorKey}`>
@@ -1,16 +1,12 @@
1
- import type { Dayjs, MergedValues, PromiseOrObject } from "akanjs/base";
1
+ import type { MergedValues, PromiseOrObject } from "akanjs/base";
2
2
  import { Logger } from "akanjs/common";
3
3
  import type { DocumentModel, QueryOf } from "akanjs/constant";
4
- import type { CacheAdaptor } from "akanjs/service";
4
+ import type { CacheAdaptor, CacheSetOptions } from "akanjs/service";
5
5
  import type { DataLoader } from "./dataLoader";
6
6
  import type { ExtractQuery, ExtractSort, FilterInstance } from "./filterMeta";
7
7
  import type { CRUDEventType, Mdl, SaveEventType } from "./into";
8
8
  import type { DataInputOf, FindQueryOption, ListQueryOption } from "./types";
9
9
 
10
- export interface RedisSetOptions {
11
- expireAt?: Dayjs;
12
- }
13
-
14
10
  export class CacheDatabase<T = unknown> {
15
11
  private logger: Logger;
16
12
  constructor(
@@ -19,7 +15,7 @@ export class CacheDatabase<T = unknown> {
19
15
  ) {
20
16
  this.logger = new Logger(`${refName}Cache`);
21
17
  }
22
- async set(topic: string, key: string, value: string | number | Buffer, option: RedisSetOptions = {}) {
18
+ async set(topic: string, key: string, value: string | number | Buffer, option: CacheSetOptions = {}) {
23
19
  await this.cache.set(this.refName, `${topic}:${key}`, value, option);
24
20
  }
25
21
  async get<T extends string | number | Buffer>(topic: string, key: string): Promise<T | undefined> {
@@ -1,5 +1,5 @@
1
1
  import type { Cls, MergeAllDoubleKeyOfObjects, MergeAllKeyOfTypes } from "akanjs/base";
2
- import { FILTER_META } from "akanjs/base";
2
+ import { FILTER_DICT_SHAPE, FILTER_META } from "akanjs/base";
3
3
  import type {
4
4
  BaseObject,
5
5
  ConstantFieldTypeInput,
@@ -109,6 +109,21 @@ export type FilterInstance<
109
109
  query: Query;
110
110
  sort: Sort;
111
111
  };
112
+ export type FilterDictArgShape = {
113
+ query: { [key: string]: readonly string[] };
114
+ sort: { [key: string]: true };
115
+ };
116
+ export type FilterDictShape<Filter extends FilterInstance> = {
117
+ query: {
118
+ [K in keyof Filter["query"]]: Filter["query"][K] extends FilterInfo<infer ArgNames, infer _Args, infer _Model>
119
+ ? ArgNames
120
+ : never;
121
+ };
122
+ sort: { [K in keyof Filter["sort"]]: true };
123
+ };
124
+ export interface FilterDictShapeCarrier<DictShape extends FilterDictArgShape = FilterDictArgShape> {
125
+ readonly [FILTER_DICT_SHAPE]: DictShape;
126
+ }
112
127
  interface BaseQuery<Model> {
113
128
  any: FilterInfo<[], [], Model>;
114
129
  }
@@ -140,8 +155,9 @@ export type ExtractQuery<Filter extends FilterInstance> = {
140
155
  };
141
156
  export type ExtractSort<Filter extends FilterInstance> = keyof Filter["sort"];
142
157
  export interface FilterCls<Filter extends FilterInstance = any, Query = unknown, Sort = unknown>
143
- extends Cls<{ [key: string]: any }> {
158
+ extends Cls<FilterDictShapeCarrier<FilterDictShape<Filter>> & { [key: string]: unknown }> {
144
159
  [FILTER_META]: Filter;
160
+ prototype: FilterDictShapeCarrier<FilterDictShape<Filter>> & { [key: string]: unknown };
145
161
  sortField: Set<string>;
146
162
  _Query: Query;
147
163
  _Sort: Sort;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "2.3.8-rc.2",
3
+ "version": "2.3.8-rc.4",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -16,7 +16,7 @@ import type {
16
16
  SliceCls,
17
17
  } from "akanjs/signal";
18
18
  import type { Adaptor, AdaptorCls, Service, ServiceCls } from ".";
19
- import type { CacheAdaptor } from "./predefinedAdaptor";
19
+ import type { CacheAdaptor, CacheSetOptions } from "./predefinedAdaptor";
20
20
 
21
21
  export type InjectType = "database" | "service" | "use" | "signal" | "plug" | "env" | "memory";
22
22
 
@@ -29,6 +29,7 @@ interface InjectBuilderOptions<ReturnType> {
29
29
  local?: boolean;
30
30
  default?: unknown;
31
31
  isMap?: boolean;
32
+ cacheOption?: CacheSetOptions;
32
33
  parentRefName: string;
33
34
  }
34
35
 
@@ -99,6 +100,7 @@ export class InjectInfo<
99
100
  readonly adaptor?: AdaptorCls;
100
101
  readonly default?: unknown;
101
102
  readonly isMap?: boolean;
103
+ readonly cacheOption?: CacheSetOptions;
102
104
  readonly parentRefName: string;
103
105
  constructor(type: Type, options: InjectBuilderOptions<ReturnType>) {
104
106
  this.type = type;
@@ -110,6 +112,7 @@ export class InjectInfo<
110
112
  this.set = options.set;
111
113
  this.default = options.default;
112
114
  this.isMap = options.isMap ?? false;
115
+ this.cacheOption = options.cacheOption;
113
116
  this.parentRefName = options.parentRefName;
114
117
  }
115
118
  static async resolveInjection(
@@ -261,9 +264,9 @@ export class InjectInfo<
261
264
  const value = await cacheAdaptor.hget(topic, propKey, key);
262
265
  return value === undefined || value === null ? undefined : getter(value);
263
266
  };
264
- const set = async (key: string, value: unknown) => {
267
+ const set = async (key: string, value: unknown, option?: CacheSetOptions) => {
265
268
  const setValue = setter(value);
266
- await cacheAdaptor.hset(topic, propKey, key, setValue);
269
+ await cacheAdaptor.hset(topic, propKey, key, setValue, option ?? injectInfo.cacheOption);
267
270
  };
268
271
  Object.defineProperty(instance, propKey, {
269
272
  value: {
@@ -272,17 +275,21 @@ export class InjectInfo<
272
275
  delete: async (key: string) => {
273
276
  await cacheAdaptor.hdelete(topic, propKey, key);
274
277
  },
275
- getOrInsert: async (key: string, value: unknown) => {
278
+ getOrInsert: async (key: string, value: unknown, option?: CacheSetOptions) => {
276
279
  const existingValue = await get(key);
277
280
  if (existingValue !== undefined) return existingValue;
278
- await set(key, value);
281
+ await set(key, value, option);
279
282
  return value;
280
283
  },
281
- getOrInsertComputed: async (key: string, compute: (key: string) => unknown | Promise<unknown>) => {
284
+ getOrInsertComputed: async (
285
+ key: string,
286
+ compute: (key: string) => unknown | Promise<unknown>,
287
+ option?: CacheSetOptions,
288
+ ) => {
282
289
  const existingValue = await get(key);
283
290
  if (existingValue !== undefined) return existingValue;
284
291
  const value = await compute(key);
285
- await set(key, value);
292
+ await set(key, value, option);
286
293
  return value;
287
294
  },
288
295
  keys: async () => await cacheAdaptor.hkeys(topic, propKey),
@@ -306,10 +313,10 @@ export class InjectInfo<
306
313
  const value = await cacheAdaptor.get("akan:memory", propKey);
307
314
  return value === null ? value : getter(value);
308
315
  },
309
- set: async (value: unknown) => {
316
+ set: async (value: unknown, option?: CacheSetOptions) => {
310
317
  const setter = injectInfo.set as unknown as (value: unknown) => string | number | Buffer;
311
318
  const setValue = setter(value);
312
- await cacheAdaptor.set("akan:memory", propKey, setValue);
319
+ await cacheAdaptor.set("akan:memory", propKey, setValue, option ?? injectInfo.cacheOption);
313
320
  },
314
321
  delete: async () => {
315
322
  await cacheAdaptor.delete("akan:memory", propKey);
@@ -362,6 +369,7 @@ export const injectionBuilder = (parentRefName: string) => ({
362
369
  local?: Local;
363
370
  default?: DefaultValue;
364
371
  of?: MapValue;
372
+ expireAt?: CacheSetOptions["expireAt"];
365
373
  get?: GetFn;
366
374
  set?: (value: ReturnType<GetFn>) => GetFieldValue<ValueRef, ExplicitType>;
367
375
  } = {},
@@ -385,19 +393,24 @@ export const injectionBuilder = (parentRefName: string) => ({
385
393
  : MapConstructor extends ValueRef
386
394
  ? {
387
395
  get: (key: string) => Promise<MapFieldValue | undefined>;
388
- set: (key: string, value: MapFieldValue) => Promise<void>;
396
+ set: (key: string, value: MapFieldValue, option?: CacheSetOptions) => Promise<void>;
389
397
  delete: (key: string) => Promise<void>;
390
- getOrInsert: (key: string, value: MapFieldValue) => Promise<MapFieldValue>;
398
+ getOrInsert: (key: string, value: MapFieldValue, option?: CacheSetOptions) => Promise<MapFieldValue>;
391
399
  getOrInsertComputed: (
392
400
  key: string,
393
401
  compute: (key: string) => MapFieldValue | Promise<MapFieldValue>,
402
+ option?: CacheSetOptions,
394
403
  ) => Promise<MapFieldValue>;
395
404
  keys: () => Promise<string[]>;
396
405
  entries: () => Promise<[string, MapFieldValue][]>;
397
406
  forEach: (callback: (value: MapFieldValue, key: string) => void | Promise<void>) => Promise<void>;
398
407
  clear: () => Promise<void>;
399
408
  }
400
- : { get: () => Promise<UseValue>; set: (value: UseValue) => Promise<void>; delete: () => Promise<void> },
409
+ : {
410
+ get: () => Promise<UseValue>;
411
+ set: (value: UseValue, option?: CacheSetOptions) => Promise<void>;
412
+ delete: () => Promise<void>;
413
+ },
401
414
  never,
402
415
  ValueRef
403
416
  >("memory", {
@@ -416,6 +429,7 @@ export const injectionBuilder = (parentRefName: string) => ({
416
429
  },
417
430
  default: opts.default as unknown,
418
431
  isMap,
432
+ cacheOption: opts.expireAt ? { expireAt: opts.expireAt } : undefined,
419
433
  parentRefName,
420
434
  });
421
435
  },
@@ -2,8 +2,12 @@ import type { BaseEnv, Dayjs, SshOptions } from "akanjs/base";
2
2
  import type { Redis } from "ioredis";
3
3
  import { adapt } from "../adapt";
4
4
 
5
+ export interface CacheSetOptions {
6
+ expireAt?: Dayjs;
7
+ }
8
+
5
9
  export interface CacheAdaptor {
6
- set(topic: string, key: string, value: string | number | Buffer, option?: { expireAt?: Dayjs }): Promise<void>;
10
+ set(topic: string, key: string, value: string | number | Buffer, option?: CacheSetOptions): Promise<void>;
7
11
  get<T extends string | number | Buffer>(topic: string, key: string): Promise<T | undefined>;
8
12
  delete(topic: string, key: string): Promise<void>;
9
13
  getClient?(): Redis;
@@ -12,7 +16,7 @@ export interface CacheAdaptor {
12
16
  key: string,
13
17
  subKey: string,
14
18
  value: string | number | Buffer,
15
- option?: { expireAt?: Dayjs },
19
+ option?: CacheSetOptions,
16
20
  ): Promise<void>;
17
21
  hget<T extends string | number | Buffer>(topic: string, key: string, subKey: string): Promise<T | undefined>;
18
22
  hdelete(topic: string, key: string, subKey: string): Promise<void>;
@@ -63,12 +67,7 @@ export class RedisCache
63
67
  }))
64
68
  implements CacheAdaptor
65
69
  {
66
- async set(
67
- topic: string,
68
- key: string,
69
- value: string | number | Buffer,
70
- option: { expireAt?: Dayjs } = {},
71
- ): Promise<void> {
70
+ async set(topic: string, key: string, value: string | number | Buffer, option: CacheSetOptions = {}): Promise<void> {
72
71
  const expireTime = option.expireAt?.toDate().getTime();
73
72
  if (expireTime) await this.redis.set(`${topic}:${key}`, value, "PXAT", expireTime);
74
73
  else await this.redis.set(`${topic}:${key}`, value);
@@ -85,7 +84,7 @@ export class RedisCache
85
84
  key: string,
86
85
  subKey: string,
87
86
  value: string | number | Buffer,
88
- option?: { expireAt?: Dayjs },
87
+ option?: CacheSetOptions,
89
88
  ): Promise<void> {
90
89
  const expireTime = option?.expireAt?.toDate().getTime();
91
90
  const redisKey = `${topic}:${key}`;