akanjs 2.3.5-rc.9 → 2.3.5

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.
Files changed (81) hide show
  1. package/base/base.ts +6 -2
  2. package/base/primitiveRegistry.ts +50 -46
  3. package/base/symbols.ts +16 -11
  4. package/base/types.ts +12 -0
  5. package/constant/constantRegistry.ts +10 -9
  6. package/constant/deserialize.ts +7 -7
  7. package/constant/fieldInfo.ts +173 -31
  8. package/constant/getDefault.ts +2 -2
  9. package/constant/immerify.ts +2 -2
  10. package/constant/purify.ts +19 -4
  11. package/constant/serialize.ts +6 -5
  12. package/constant/types.ts +9 -1
  13. package/constant/via.ts +312 -57
  14. package/dictionary/dictInfo.ts +28 -38
  15. package/dictionary/locale.ts +36 -38
  16. package/document/by.ts +84 -21
  17. package/document/database.ts +53 -18
  18. package/document/databaseRegistry.ts +7 -3
  19. package/document/filterMeta.ts +26 -14
  20. package/document/into.ts +71 -76
  21. package/document/types.ts +4 -2
  22. package/fetch/fetchType/endpointFetch.type.ts +6 -3
  23. package/fetch/fetchType/sliceFetch.type.ts +24 -13
  24. package/package.json +1 -1
  25. package/service/predefinedAdaptor/compress.adaptor.ts +9 -9
  26. package/service/predefinedAdaptor/database.adaptor.ts +3 -7
  27. package/service/serve.ts +17 -52
  28. package/service/types.ts +61 -21
  29. package/signal/endpoint.ts +2 -1
  30. package/signal/endpointInfo.ts +53 -23
  31. package/signal/internal.ts +2 -1
  32. package/signal/internalInfo.ts +71 -23
  33. package/signal/serverSignal.ts +23 -57
  34. package/signal/slice.ts +35 -35
  35. package/signal/sliceInfo.ts +63 -47
  36. package/signal/types.ts +23 -17
  37. package/store/action.ts +57 -44
  38. package/store/state.ts +47 -36
  39. package/store/stateBuilder.ts +3 -3
  40. package/store/store.ts +61 -15
  41. package/store/types.ts +16 -6
  42. package/types/base/base.d.ts +5 -1
  43. package/types/base/primitiveRegistry.d.ts +43 -38
  44. package/types/base/symbols.d.ts +5 -0
  45. package/types/base/types.d.ts +1 -0
  46. package/types/constant/constantRegistry.d.ts +3 -8
  47. package/types/constant/deserialize.d.ts +2 -2
  48. package/types/constant/fieldInfo.d.ts +41 -20
  49. package/types/constant/immerify.d.ts +2 -2
  50. package/types/constant/purify.d.ts +3 -2
  51. package/types/constant/serialize.d.ts +2 -2
  52. package/types/constant/types.d.ts +6 -1
  53. package/types/constant/via.d.ts +143 -22
  54. package/types/dictionary/dictInfo.d.ts +18 -11
  55. package/types/dictionary/locale.d.ts +23 -16
  56. package/types/document/by.d.ts +44 -7
  57. package/types/document/database.d.ts +9 -7
  58. package/types/document/databaseRegistry.d.ts +5 -4
  59. package/types/document/filterMeta.d.ts +18 -11
  60. package/types/document/into.d.ts +46 -19
  61. package/types/document/types.d.ts +3 -2
  62. package/types/fetch/fetchType/endpointFetch.type.d.ts +2 -2
  63. package/types/fetch/fetchType/sliceFetch.type.d.ts +11 -11
  64. package/types/service/serve.d.ts +4 -5
  65. package/types/service/serviceModule.d.ts +5 -5
  66. package/types/service/types.d.ts +23 -5
  67. package/types/signal/endpoint.d.ts +2 -1
  68. package/types/signal/endpointInfo.d.ts +40 -15
  69. package/types/signal/internal.d.ts +2 -1
  70. package/types/signal/internalInfo.d.ts +46 -12
  71. package/types/signal/serverSignal.d.ts +15 -12
  72. package/types/signal/slice.d.ts +8 -6
  73. package/types/signal/sliceInfo.d.ts +41 -20
  74. package/types/signal/types.d.ts +23 -17
  75. package/types/store/action.d.ts +25 -22
  76. package/types/store/baseSt.d.ts +42 -13
  77. package/types/store/state.d.ts +23 -26
  78. package/types/store/stateBuilder.d.ts +2 -2
  79. package/types/store/store.d.ts +17 -5
  80. package/types/store/types.d.ts +9 -3
  81. package/ui/Signal/makeExample.ts +3 -3
package/base/base.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Cls } from ".";
1
+ import type { CLIENT_VALUE, Cls, DEFAULT_VALUE, PURIFIED_VALUE, SERVER_VALUE } from ".";
2
2
  import { Float, Int } from "./primitiveRegistry";
3
3
 
4
4
  class EnumPrototype {}
@@ -6,6 +6,10 @@ export type EnumInstance<RefName extends string = string, T = string | number> =
6
6
  { refName: RefName; value: T },
7
7
  {
8
8
  refName: RefName;
9
+ [SERVER_VALUE]: T;
10
+ [CLIENT_VALUE]: T;
11
+ [DEFAULT_VALUE]: T;
12
+ [PURIFIED_VALUE]: T;
9
13
  type: StringConstructor | typeof Int | typeof Float;
10
14
  values: readonly T[];
11
15
  valueMap: Map<T, number>;
@@ -71,7 +75,7 @@ export const enumOf = <RefName extends string, T = string | number>(
71
75
  readonly refName = refName;
72
76
  declare readonly value: T;
73
77
  }
74
- return Enum;
78
+ return Enum as unknown as EnumInstance<RefName, T>;
75
79
  };
76
80
 
77
81
  /** Id-keyed list helper used for light model collections and immutable-style list updates. */
@@ -1,5 +1,5 @@
1
1
  import dayjsLib, { type Dayjs } from "dayjs";
2
-
2
+ import { CLIENT_VALUE, DEFAULT_VALUE, EXAMPLE_VALUE, PURIFIED_VALUE, SERVER_VALUE } from "./symbols";
3
3
  import type { Cls } from "./types";
4
4
 
5
5
  export type { Dayjs };
@@ -44,17 +44,14 @@ export class PrimitiveRegistry {
44
44
  }
45
45
  }
46
46
 
47
- export const PRIMITIVE_SERVER_VALUE = Symbol.for("PRIMITIVE_SERVER_VALUE");
48
- export const PRIMITIVE_CLIENT_VALUE = Symbol.for("PRIMITIVE_CLIENT_VALUE");
49
- export const PRIMITIVE_DEFAULT_VALUE = Symbol.for("PRIMITIVE_DEFAULT_VALUE");
50
- export const PRIMITIVE_EXAMPLE_VALUE = Symbol.for("PRIMITIVE_EXAMPLE_VALUE");
51
47
  export type PrimitiveValue = string | number | boolean | Dayjs | Date | null | undefined;
52
48
  export class PrimitiveScalar {
53
49
  static refName: string;
54
- static [PRIMITIVE_SERVER_VALUE]: unknown;
55
- static [PRIMITIVE_CLIENT_VALUE]: unknown;
56
- static [PRIMITIVE_DEFAULT_VALUE]: unknown = null;
57
- static [PRIMITIVE_EXAMPLE_VALUE]: unknown = null;
50
+ static [SERVER_VALUE]: unknown;
51
+ static [CLIENT_VALUE]: unknown;
52
+ static [DEFAULT_VALUE]: unknown = null;
53
+ static [PURIFIED_VALUE]: unknown = null;
54
+ static [EXAMPLE_VALUE]: unknown = null;
58
55
 
59
56
  static validate(value: PrimitiveValue): boolean {
60
57
  return true;
@@ -105,10 +102,11 @@ export class PrimitiveScalar {
105
102
  /** Integer primitive scalar. Accepts safe integer numbers after parsing. */
106
103
  export class Int extends PrimitiveScalar {
107
104
  static override refName: "Int" = "Int";
108
- static override [PRIMITIVE_SERVER_VALUE]: number;
109
- static override [PRIMITIVE_CLIENT_VALUE]: number;
110
- static override [PRIMITIVE_DEFAULT_VALUE]: number = 0;
111
- static override [PRIMITIVE_EXAMPLE_VALUE]: number = 0;
105
+ static override [SERVER_VALUE]: number;
106
+ static override [CLIENT_VALUE]: number;
107
+ static override [DEFAULT_VALUE]: number = 0;
108
+ static override [PURIFIED_VALUE]: number = 0;
109
+ static override [EXAMPLE_VALUE]: number = 0;
112
110
 
113
111
  static override validate(value: string | number): boolean {
114
112
  return typeof value === "number" && Number.isSafeInteger(value);
@@ -125,10 +123,11 @@ PrimitiveRegistry.register(Int);
125
123
  /** Floating point primitive scalar. Accepts finite numbers after parsing. */
126
124
  export class Float extends PrimitiveScalar {
127
125
  static override refName: "Float" = "Float";
128
- static override [PRIMITIVE_SERVER_VALUE]: number;
129
- static override [PRIMITIVE_CLIENT_VALUE]: number;
130
- static override [PRIMITIVE_DEFAULT_VALUE]: number = 0;
131
- static override [PRIMITIVE_EXAMPLE_VALUE]: number = 0;
126
+ static override [SERVER_VALUE]: number;
127
+ static override [CLIENT_VALUE]: number;
128
+ static override [DEFAULT_VALUE]: number = 0;
129
+ static override [PURIFIED_VALUE]: number = 0;
130
+ static override [EXAMPLE_VALUE]: number = 0;
132
131
 
133
132
  static override validate(value: string | number): boolean {
134
133
  return typeof value === "number" && Number.isFinite(value);
@@ -145,10 +144,11 @@ PrimitiveRegistry.register(Float);
145
144
  /** 24-character hexadecimal id primitive used by Akan document and signal models. */
146
145
  export class ID extends PrimitiveScalar {
147
146
  static override refName: "ID" = "ID";
148
- static override [PRIMITIVE_SERVER_VALUE]: string;
149
- static override [PRIMITIVE_CLIENT_VALUE]: string;
150
- static override [PRIMITIVE_DEFAULT_VALUE]: string = "";
151
- static override [PRIMITIVE_EXAMPLE_VALUE]: string = "1234567890abcdef12345678";
147
+ static override [SERVER_VALUE]: string;
148
+ static override [CLIENT_VALUE]: string;
149
+ static override [DEFAULT_VALUE]: string = "";
150
+ static override [PURIFIED_VALUE]: string = "";
151
+ static override [EXAMPLE_VALUE]: string = "1234567890abcdef12345678";
152
152
 
153
153
  static override validate(value: string): boolean {
154
154
  if (typeof value !== "string") return false;
@@ -161,7 +161,7 @@ export class ID extends PrimitiveScalar {
161
161
  return String(value);
162
162
  }
163
163
  static override _checkValue(value: PrimitiveValue, options: { optional?: boolean } = {}): void {
164
- if (value === ID[PRIMITIVE_DEFAULT_VALUE]) return;
164
+ if (value === ID[DEFAULT_VALUE]) return;
165
165
 
166
166
  super._checkValue(value, options);
167
167
  }
@@ -171,17 +171,18 @@ PrimitiveRegistry.register(ID);
171
171
  /** Open object primitive for intentionally flexible payloads or metadata blobs. */
172
172
  export class Any extends PrimitiveScalar {
173
173
  static override refName: "Any" = "Any";
174
- static override [PRIMITIVE_DEFAULT_VALUE]: object | null = null;
175
- static override [PRIMITIVE_EXAMPLE_VALUE]: object = {};
174
+ static override [DEFAULT_VALUE]: object | null = null;
175
+ static override [EXAMPLE_VALUE]: object = {};
176
176
  }
177
177
  PrimitiveRegistry.register(Any);
178
178
 
179
179
  export class Upload extends PrimitiveScalar {
180
180
  static override refName: "Upload" = "Upload";
181
- static override [PRIMITIVE_SERVER_VALUE]: File;
182
- static override [PRIMITIVE_CLIENT_VALUE]: File;
183
- static override [PRIMITIVE_DEFAULT_VALUE]: File | null = null;
184
- static override [PRIMITIVE_EXAMPLE_VALUE] = "FileUpload";
181
+ static override [SERVER_VALUE]: File;
182
+ static override [CLIENT_VALUE]: File;
183
+ static override [DEFAULT_VALUE]: File | null = null;
184
+ static override [PURIFIED_VALUE]: File;
185
+ static override [EXAMPLE_VALUE] = "FileUpload";
185
186
  __TEMP_TYPE__: "Upload" = "Upload";
186
187
  }
187
188
  PrimitiveRegistry.register(Upload);
@@ -189,10 +190,11 @@ PrimitiveRegistry.register(Upload);
189
190
  declare global {
190
191
  interface StringConstructor {
191
192
  refName: "String";
192
- [PRIMITIVE_SERVER_VALUE]: string;
193
- [PRIMITIVE_CLIENT_VALUE]: string;
194
- [PRIMITIVE_DEFAULT_VALUE]: string;
195
- [PRIMITIVE_EXAMPLE_VALUE]: string;
193
+ [SERVER_VALUE]: string;
194
+ [CLIENT_VALUE]: string;
195
+ [DEFAULT_VALUE]: string;
196
+ [PURIFIED_VALUE]: string;
197
+ [EXAMPLE_VALUE]: string;
196
198
  validate(value: string): boolean;
197
199
  parseValue(input: string): string;
198
200
  serializeValue(value: string): string;
@@ -202,10 +204,11 @@ declare global {
202
204
  }
203
205
  interface BooleanConstructor {
204
206
  refName: "Boolean";
205
- [PRIMITIVE_SERVER_VALUE]: boolean;
206
- [PRIMITIVE_CLIENT_VALUE]: boolean;
207
- [PRIMITIVE_DEFAULT_VALUE]: boolean;
208
- [PRIMITIVE_EXAMPLE_VALUE]: boolean;
207
+ [SERVER_VALUE]: boolean;
208
+ [CLIENT_VALUE]: boolean;
209
+ [DEFAULT_VALUE]: boolean;
210
+ [PURIFIED_VALUE]: boolean;
211
+ [EXAMPLE_VALUE]: boolean;
209
212
  validate(value: boolean | number): boolean;
210
213
  parseValue(input: boolean | number): boolean | number;
211
214
  serializeValue(value: boolean | number): boolean | number;
@@ -215,10 +218,11 @@ declare global {
215
218
  }
216
219
  interface DateConstructor {
217
220
  refName: "Date";
218
- [PRIMITIVE_SERVER_VALUE]: Dayjs;
219
- [PRIMITIVE_CLIENT_VALUE]: Dayjs;
220
- [PRIMITIVE_DEFAULT_VALUE]: Dayjs;
221
- [PRIMITIVE_EXAMPLE_VALUE]: string;
221
+ [SERVER_VALUE]: Dayjs;
222
+ [CLIENT_VALUE]: Dayjs;
223
+ [DEFAULT_VALUE]: Dayjs;
224
+ [PURIFIED_VALUE]: Dayjs;
225
+ [EXAMPLE_VALUE]: string;
222
226
  validate(value: Date): boolean;
223
227
  parseValue(input: Date): Dayjs;
224
228
  serializeValue(value: Dayjs | Date): Date;
@@ -287,8 +291,8 @@ const scalarPrimitiveStatics = {
287
291
 
288
292
  Object.assign(String, scalarPrimitiveStatics, {
289
293
  refName: "String",
290
- [PRIMITIVE_DEFAULT_VALUE]: "",
291
- [PRIMITIVE_EXAMPLE_VALUE]: "String",
294
+ [DEFAULT_VALUE]: "",
295
+ [EXAMPLE_VALUE]: "String",
292
296
  validate(value: string) {
293
297
  return typeof value === "string";
294
298
  },
@@ -311,8 +315,8 @@ const normalizeBooleanPrimitiveValue = (value: boolean | number): boolean | null
311
315
  Object.assign(Boolean, {
312
316
  ...scalarPrimitiveStatics,
313
317
  refName: "Boolean",
314
- [PRIMITIVE_DEFAULT_VALUE]: false,
315
- [PRIMITIVE_EXAMPLE_VALUE]: true,
318
+ [DEFAULT_VALUE]: false,
319
+ [EXAMPLE_VALUE]: true,
316
320
  validate(value: boolean | number) {
317
321
  return normalizeBooleanPrimitiveValue(value) !== null;
318
322
  },
@@ -328,8 +332,8 @@ PrimitiveRegistry.register(Boolean);
328
332
  Object.assign(Date, {
329
333
  ...scalarPrimitiveStatics,
330
334
  refName: "Date",
331
- [PRIMITIVE_DEFAULT_VALUE]: dayjs(new Date(-1)),
332
- [PRIMITIVE_EXAMPLE_VALUE]: dayjs(new Date().toISOString()),
335
+ [DEFAULT_VALUE]: dayjs(new Date(-1)),
336
+ [EXAMPLE_VALUE]: dayjs(new Date().toISOString()),
333
337
  validate(value: Date | string | number) {
334
338
  const date = new Date(value);
335
339
  if (Number.isNaN(date.getTime())) return false;
package/base/symbols.ts CHANGED
@@ -1,11 +1,16 @@
1
- export const FIELD_META = Symbol.for("akanjs.field");
2
- export const SLICE_META = Symbol.for("akanjs.slice");
3
- export const FILTER_META = Symbol.for("akanjs.filter");
4
- export const LOADER_META = Symbol.for("akanjs.loader");
5
- export const INJECT_META = Symbol.for("akanjs.inject");
6
- export const ENDPOINT_META = Symbol.for("akanjs.endpoint");
7
- export const INTERNAL_META = Symbol.for("akanjs.internal");
8
- export const STATE_META = Symbol.for("akanjs.state");
9
- export const STATE_INIT_META = Symbol.for("akanjs.state.init");
10
- export const STATE_DERIVED_META = Symbol.for("akanjs.state.derived");
11
- export const ACTION_META = Symbol.for("akanjs.action");
1
+ export const FIELD_META = Symbol.for("akan.field");
2
+ export const SLICE_META = Symbol.for("akan.slice");
3
+ export const FILTER_META = Symbol.for("akan.filter");
4
+ export const LOADER_META = Symbol.for("akan.loader");
5
+ export const INJECT_META = Symbol.for("akan.inject");
6
+ export const ENDPOINT_META = Symbol.for("akan.endpoint");
7
+ export const INTERNAL_META = Symbol.for("akan.internal");
8
+ export const STATE_META = Symbol.for("akan.state");
9
+ export const STATE_INIT_META = Symbol.for("akan.state.init");
10
+ export const STATE_DERIVED_META = Symbol.for("akan.state.derived");
11
+ export const ACTION_META = Symbol.for("akan.action");
12
+ export const SERVER_VALUE = Symbol.for("akan.value.server");
13
+ export const CLIENT_VALUE = Symbol.for("akan.value.client");
14
+ export const DEFAULT_VALUE = Symbol.for("akan.value.default");
15
+ export const EXAMPLE_VALUE = Symbol.for("akan.value.example");
16
+ export const PURIFIED_VALUE = Symbol.for("akan.value.purified");
package/base/types.ts CHANGED
@@ -48,6 +48,18 @@ export type ObjectAssign<Objects extends object[], Acc = unknown> = Objects exte
48
48
  ? ObjectAssign<Rest, Assign<Acc, First>>
49
49
  : Acc;
50
50
 
51
+ export type ObjectAssignKeyOfObjects<
52
+ T extends object[],
53
+ Key extends PropertyKey,
54
+ Acc = Record<never, never>,
55
+ > = T extends [infer First extends object, ...infer Rest extends object[]]
56
+ ? Key extends keyof First
57
+ ? First[Key] extends object
58
+ ? ObjectAssignKeyOfObjects<Rest, Key, Assign<Acc, First[Key]>>
59
+ : ObjectAssignKeyOfObjects<Rest, Key, Acc>
60
+ : ObjectAssignKeyOfObjects<Rest, Key, Acc>
61
+ : Acc;
62
+
51
63
  export type MergeAll<T extends object[], Acc = unknown> = T extends [
52
64
  infer First extends object,
53
65
  ...infer Rest extends object[],
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  type Cls,
3
3
  type EnumInstance,
4
- FIELD_META,
5
4
  type GetStateObject,
6
5
  isEnum,
7
6
  PrimitiveRegistry,
@@ -9,14 +8,16 @@ import {
9
8
  type PrimitiveValue,
10
9
  } from "akanjs/base";
11
10
  import { capitalize, lowerlize } from "akanjs/common";
12
- import { type ConstantCls, deserialize, type FieldObject, type PurifiedModel, serialize } from ".";
11
+ import {
12
+ type ConstantCls,
13
+ type ConstantModelRef,
14
+ deserialize,
15
+ type FieldObject,
16
+ type PurifiedModel,
17
+ serialize,
18
+ } from ".";
13
19
  import type { ConstantType, DefaultOf, DocumentModel, QueryOf } from "./types";
14
20
 
15
- type ConstantModelRef<FieldObj extends FieldObject = FieldObject> = Cls<
16
- unknown,
17
- { [FIELD_META]: FieldObj; modelType: ConstantType }
18
- >;
19
-
20
21
  /** Runtime registry for Akan constant model metadata, refs, enums, and generated model contracts. */
21
22
  export class ConstantRegistry {
22
23
  static database = new Map<string, ConstantModel>();
@@ -107,7 +108,7 @@ export class ConstantRegistry {
107
108
  InputRef extends ConstantModelRef,
108
109
  ObjectRef extends ConstantModelRef,
109
110
  FullFieldObj extends FieldObject,
110
- FullRef extends ConstantModelRef<FullFieldObj>,
111
+ FullRef extends ConstantModelRef<any, FullFieldObj>,
111
112
  LightRef extends ConstantModelRef,
112
113
  InsightRef extends ConstantModelRef,
113
114
  Input = InstanceType<InputRef>,
@@ -200,7 +201,7 @@ export class ConstantRegistry {
200
201
  _StateLight: null as unknown as GetStateObject<Light>,
201
202
  _StateInsight: null as unknown as GetStateObject<Insight>,
202
203
  };
203
- ConstantRegistry.setDatabase(refName, cnst as ConstantModel);
204
+ ConstantRegistry.setDatabase(refName, cnst as unknown as ConstantModel);
204
205
  Object.entries(constExports).forEach(([key, value]) => {
205
206
  if ((modelRefSet as Set<unknown>).has(value)) return;
206
207
  else if (typeof value === "function" && isEnum(value as Cls))
@@ -1,8 +1,8 @@
1
- import { applyFnToArrayObjects, type Cls, FIELD_META, PrimitiveRegistry, type PrimitiveScalar } from "akanjs/base";
1
+ import { Any, applyFnToArrayObjects, type Cls, FIELD_META, PrimitiveRegistry, type PrimitiveScalar } from "akanjs/base";
2
2
 
3
- import { type ConstantCls, ConstantRegistry, type FieldProps } from ".";
3
+ import { type ConstantCls, type ConstantModelRef, ConstantRegistry, type FieldProps } from ".";
4
4
 
5
- const getDeserializeFn = (inputRef: ConstantCls | PrimitiveScalar) => {
5
+ const getDeserializeFn = (inputRef: ConstantModelRef | PrimitiveScalar) => {
6
6
  const deserializeFn = PrimitiveRegistry.has(inputRef as Cls)
7
7
  ? (value: unknown) => (inputRef as unknown as typeof PrimitiveScalar)._parse(value as never)
8
8
  : (value: unknown) => value as object;
@@ -13,14 +13,14 @@ const deserializeMap = (value: unknown, field: Pick<FieldProps, "of">) => {
13
13
  return Object.fromEntries(
14
14
  Object.entries(value as Record<string, unknown>).map(([key, val]) => [
15
15
  key,
16
- applyFnToArrayObjects(val, (v: never) => deserializeInput(v, field.of as ConstantCls, 0)),
16
+ applyFnToArrayObjects(val, (v: never) => deserializeInput(v, field.of as ConstantModelRef, 0)),
17
17
  ]),
18
18
  );
19
19
  };
20
20
 
21
21
  const deserializeInput = <Input = unknown>(
22
22
  value: Input | Input[],
23
- inputRef: ConstantCls<Input> | PrimitiveScalar,
23
+ inputRef: ConstantModelRef<Input> | PrimitiveScalar,
24
24
  arrDepth: number,
25
25
  convertFn: (value: unknown) => unknown = (value: unknown) => value,
26
26
  ): Input | Input[] => {
@@ -58,13 +58,13 @@ const deserializeInput = <Input = unknown>(
58
58
  };
59
59
 
60
60
  export const deserialize = (
61
- argRef: ConstantCls | PrimitiveScalar,
61
+ argRef: ConstantModelRef | PrimitiveScalar,
62
62
  arrDepth: number,
63
63
  value: unknown,
64
64
  { key, nullable = false, convertFn }: { key?: string; nullable?: boolean; convertFn?: (value: unknown) => unknown },
65
65
  ) => {
66
66
  if (nullable && (value === null || value === undefined)) return null;
67
- else if (!nullable && (value === null || value === undefined))
67
+ else if (!nullable && (value === null || value === undefined) && argRef !== Any)
68
68
  throw new Error(`Invalid Value (Nullable) in ${key} ${argRef} for value ${value}`);
69
69
  return deserializeInput(value, argRef, arrDepth, convertFn) as object[];
70
70
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  type Any,
3
3
  arraiedModel,
4
+ CLIENT_VALUE,
4
5
  type Cls,
5
6
  type Dayjs,
6
7
  type EnumInstance,
@@ -9,19 +10,19 @@ import {
9
10
  ID,
10
11
  Int,
11
12
  isEnum,
12
- PRIMITIVE_CLIENT_VALUE,
13
- PRIMITIVE_SERVER_VALUE,
14
13
  PrimitiveRegistry,
15
14
  type PrimitiveScalar,
15
+ SERVER_VALUE,
16
16
  type SingleValue,
17
17
  type UnCls,
18
18
  } from "akanjs/base";
19
19
  import { ConstantRegistry } from "./constantRegistry";
20
- import type { ConstantCls } from "./via";
20
+ import type { BaseObject } from "./types";
21
+ import type { ConstantModelRef } from "./via";
21
22
 
22
23
  export type ParamFieldType =
23
24
  | (typeof PrimitiveScalar & {
24
- [PRIMITIVE_CLIENT_VALUE]: string | number | boolean | Dayjs;
25
+ [CLIENT_VALUE]: string | number | boolean | Dayjs;
25
26
  })
26
27
  | EnumInstance<string, any>;
27
28
 
@@ -38,23 +39,41 @@ export type FieldToValue<Field, MapValue = any> = Field extends null
38
39
  ? Map<string, FieldToValue<MapValue>>
39
40
  : Field extends (infer F)[]
40
41
  ? FieldToValue<F>[]
41
- : Field extends { [PRIMITIVE_SERVER_VALUE]: infer V }
42
- ? V
43
- : Field extends EnumInstance<string, infer V>
44
- ? V
45
- : Field extends Cls
46
- ? UnCls<Field>
47
- : never;
42
+ : Field extends typeof PrimitiveScalar | StringConstructor | BooleanConstructor | DateConstructor
43
+ ? Field[typeof SERVER_VALUE]
44
+ : Field extends ConstantModelRef
45
+ ? UnCls<Field>
46
+ : Field extends { [SERVER_VALUE]: infer V }
47
+ ? V
48
+ : Field extends Cls
49
+ ? UnCls<Field>
50
+ : never;
48
51
  export interface FieldInfoObject {
49
- [key: string]: FieldInfo<any, ConstantFieldTypeInput | null, any>;
52
+ [key: string]: FieldInfo<
53
+ any,
54
+ ConstantFieldTypeInput | null,
55
+ any,
56
+ any,
57
+ any,
58
+ boolean,
59
+ boolean,
60
+ boolean,
61
+ boolean,
62
+ boolean,
63
+ boolean,
64
+ boolean
65
+ >;
50
66
  }
51
67
  export type ExtractFieldInfoObject<Obj extends FieldInfoObject> = {
52
- [K in keyof Obj]: Obj[K] extends FieldInfo<any, infer FieldValue, infer ExplicitType, infer MapValue>
53
- ? unknown extends ExplicitType
54
- ? FieldToValue<FieldValue, MapValue>
55
- : ExplicitType
56
- : never;
68
+ [K in keyof Obj]: unknown extends Obj[K]["explicitType"]
69
+ ? FieldToValue<Obj[K]["value"], Obj[K]["mapValue"]>
70
+ : Obj[K]["explicitType"];
57
71
  };
72
+ type FieldKindSource<Value> = NonNullable<SingleValue<Value>>;
73
+ type IsNullableValue<Value> = null extends Value ? true : false;
74
+ type FieldInfoValue<Value, ExplicitType, MapValue> = unknown extends ExplicitType
75
+ ? FieldToValue<Value, MapValue>
76
+ : ExplicitType;
58
77
 
59
78
  export type ConstantFieldKind = "property" | "hidden" | "secret" | "resolve";
60
79
 
@@ -93,11 +112,36 @@ class FieldInfo<
93
112
  Value extends ConstantFieldTypeInput | null = null,
94
113
  ExplicitType = unknown,
95
114
  MapValue = Value extends MapConstructor ? typeof PrimitiveScalar : never,
115
+ KindSource = FieldKindSource<Value>,
116
+ IsRelation extends boolean = UnCls<KindSource> extends BaseObject ? true : false,
117
+ IsEnum extends boolean = KindSource extends EnumInstance<string, any> ? true : false,
118
+ IsPrimitive extends boolean = KindSource extends typeof PrimitiveScalar ? true : false,
119
+ IsMap extends boolean = KindSource extends MapConstructor ? true : false,
120
+ IsScalar extends boolean = IsRelation extends true
121
+ ? false
122
+ : IsEnum extends true
123
+ ? false
124
+ : IsPrimitive extends true
125
+ ? false
126
+ : IsMap extends true
127
+ ? false
128
+ : true,
129
+ IsHidden extends boolean = FieldType extends "hidden" ? true : false,
130
+ IsSecret extends boolean = FieldType extends "secret" ? true : false,
96
131
  > {
97
132
  readonly value: Value;
98
133
  readonly type: ConstantFieldTypeInput;
99
134
  readonly option: ConstantFieldProps;
100
135
  declare explicitType: ExplicitType;
136
+ declare mapValue: MapValue;
137
+ declare _isEnum: IsEnum;
138
+ declare _isPrimitive: IsPrimitive;
139
+ declare _isScalar: IsScalar;
140
+ declare _isRelation: IsRelation;
141
+ declare _isHidden: IsHidden;
142
+ declare _isSecret: IsSecret;
143
+ declare _isMap: IsMap;
144
+
101
145
  constructor(value: Value, option: ConstantFieldProps<FieldType, any, MapValue>) {
102
146
  this.value = value;
103
147
  const [singleValue, arrDepth] = getNonArrayModel(value as Cls);
@@ -148,7 +192,7 @@ interface ConstantFieldBuildProps<
148
192
  of?: MapValue;
149
193
  validate?: (value: FieldValue, model: any) => boolean;
150
194
  text?: "search" | "filter";
151
- modelRef: ConstantCls;
195
+ modelRef: ConstantModelRef;
152
196
  arrDepth: number;
153
197
  optArrDepth: number;
154
198
  meta: Metadata;
@@ -161,15 +205,65 @@ export interface FieldProps extends ConstantFieldBuildProps {
161
205
  isMap: boolean;
162
206
  }
163
207
 
164
- export type FieldInfoObjectToFieldObject<Obj extends FieldInfoObject> = {
165
- [K in keyof Obj]: Obj[K] extends FieldInfo<infer FieldType, infer Value, infer ExplicitType, infer MapValue>
166
- ? ConstantField<
208
+ type ConstantFieldFromInfoParts<
209
+ FieldType extends ConstantFieldKind,
210
+ Value extends ConstantFieldTypeInput | null,
211
+ ExplicitType,
212
+ MapValue,
213
+ IsRelation extends boolean,
214
+ IsEnum extends boolean,
215
+ IsPrimitive extends boolean,
216
+ IsMap extends boolean,
217
+ IsScalar extends boolean,
218
+ IsHidden extends boolean,
219
+ IsSecret extends boolean,
220
+ _FieldValue = FieldInfoValue<Value, ExplicitType, MapValue>,
221
+ > = ConstantField<
222
+ FieldType,
223
+ Value,
224
+ _FieldValue,
225
+ MapValue,
226
+ IsNullableValue<_FieldValue>,
227
+ IsRelation,
228
+ IsEnum,
229
+ IsPrimitive,
230
+ IsScalar,
231
+ IsHidden,
232
+ IsSecret,
233
+ IsMap
234
+ >;
235
+ type ConstantFieldFromInfo<Info> =
236
+ Info extends FieldInfo<
237
+ infer FieldType,
238
+ infer Value,
239
+ infer ExplicitType,
240
+ infer MapValue,
241
+ infer _KindSource,
242
+ infer IsRelation,
243
+ infer IsEnum,
244
+ infer IsPrimitive,
245
+ infer IsMap,
246
+ infer IsScalar,
247
+ infer IsHidden,
248
+ infer IsSecret
249
+ >
250
+ ? ConstantFieldFromInfoParts<
167
251
  FieldType,
168
252
  Value,
169
- unknown extends ExplicitType ? FieldToValue<Value, MapValue> : ExplicitType,
170
- MapValue
253
+ ExplicitType,
254
+ MapValue,
255
+ IsRelation,
256
+ IsEnum,
257
+ IsPrimitive,
258
+ IsMap,
259
+ IsScalar,
260
+ IsHidden,
261
+ IsSecret
171
262
  >
172
263
  : never;
264
+
265
+ export type FieldInfoObjectToFieldObject<Obj extends FieldInfoObject> = {
266
+ [K in keyof Obj]: ConstantFieldFromInfo<Obj[K]>;
173
267
  };
174
268
 
175
269
  /** Runtime metadata for a single Akan constant field. */
@@ -178,7 +272,14 @@ export class ConstantField<
178
272
  Value extends ConstantFieldTypeInput | null = any,
179
273
  FieldValue = any,
180
274
  MapValue = any,
181
- Nullable extends boolean = false,
275
+ Nullable extends boolean = boolean,
276
+ IsRelation extends boolean = boolean,
277
+ IsEnum extends boolean = boolean,
278
+ IsPrimitive extends boolean = boolean,
279
+ IsScalar extends boolean = boolean,
280
+ IsHidden extends boolean = boolean,
281
+ IsSecret extends boolean = boolean,
282
+ IsMap extends boolean = boolean,
182
283
  Metadata = { [key: string]: any },
183
284
  > implements ConstantFieldBuildProps<FieldType, FieldValue, MapValue, Metadata>
184
285
  {
@@ -214,11 +315,17 @@ export class ConstantField<
214
315
  readonly of?: MapValue;
215
316
  readonly validate?: (value: FieldValue, model: any) => boolean;
216
317
  readonly text?: "search" | "filter";
217
- readonly modelRef: ConstantCls;
318
+ readonly modelRef: ConstantModelRef;
218
319
  readonly arrDepth: number;
219
320
  readonly optArrDepth: number;
220
321
  readonly meta: Metadata;
221
-
322
+ declare _isScalar: IsScalar;
323
+ declare _isRelation: IsRelation;
324
+ declare _isEnum: IsEnum;
325
+ declare _isPrimitive: IsPrimitive;
326
+ declare _isHidden: IsHidden;
327
+ declare _isSecret: IsSecret;
328
+ declare _isMap: IsMap;
222
329
  constructor(props: ConstantFieldBuildProps<FieldType, FieldValue, MapValue, Metadata>) {
223
330
  this.nullable = props.nullable as unknown as Nullable;
224
331
  this.ref = props.ref;
@@ -250,11 +357,46 @@ export class ConstantField<
250
357
  Value extends ConstantFieldTypeInput | null = null,
251
358
  FieldValue = any,
252
359
  MapValue = any,
253
- Nullable extends boolean = false,
360
+ Nullable extends boolean = IsNullableValue<FieldInfoValue<Value, FieldValue, MapValue>>,
361
+ KindSource = FieldKindSource<Value>,
362
+ IsRelation extends boolean = false,
363
+ IsEnum extends boolean = false,
364
+ IsPrimitive extends boolean = false,
365
+ IsMap extends boolean = false,
366
+ IsScalar extends boolean = false,
367
+ IsHidden extends boolean = false,
368
+ IsSecret extends boolean = false,
254
369
  Metadata = { [key: string]: any },
255
370
  >(
256
- fieldInfo: FieldInfo<FieldType, Value, FieldValue, MapValue>,
257
- ): ConstantField<FieldType, Value, FieldValue, MapValue, Nullable, Metadata> {
371
+ fieldInfo: FieldInfo<
372
+ FieldType,
373
+ Value,
374
+ FieldValue,
375
+ MapValue,
376
+ KindSource,
377
+ IsRelation,
378
+ IsEnum,
379
+ IsPrimitive,
380
+ IsMap,
381
+ IsScalar,
382
+ IsHidden,
383
+ IsSecret
384
+ >,
385
+ ): ConstantField<
386
+ FieldType,
387
+ Value,
388
+ FieldValue,
389
+ MapValue,
390
+ Nullable,
391
+ IsRelation,
392
+ IsEnum,
393
+ IsPrimitive,
394
+ IsScalar,
395
+ IsHidden,
396
+ IsSecret,
397
+ IsMap,
398
+ Metadata
399
+ > {
258
400
  const [modelRef, arrDepth] = getNonArrayModel(fieldInfo.type as Cls);
259
401
  const [option, optArrDepth] = getNonArrayModel(fieldInfo.option);
260
402
 
@@ -263,7 +405,7 @@ export class ConstantField<
263
405
  if (isMap && !option.of) throw new Error("Map type must have 'of' option");
264
406
 
265
407
  return new ConstantField({
266
- nullable: option.nullable ?? ((option.default === "" ? true : false) as unknown as Nullable),
408
+ nullable: option.nullable ?? ((option.default === "") as unknown as Nullable),
267
409
  ref: option.ref,
268
410
  refPath: option.refPath,
269
411
  refType: option.refType,
@@ -298,7 +440,7 @@ export class ConstantField<
298
440
  return this.arrDepth > 0;
299
441
  }
300
442
  get isMap() {
301
- return this.modelRef === Map;
443
+ return (this.modelRef as Cls) === Map;
302
444
  }
303
445
  getProps(): FieldProps {
304
446
  return {
@@ -1,4 +1,4 @@
1
- import { FIELD_META, PRIMITIVE_DEFAULT_VALUE, type PrimitiveScalar } from "akanjs/base";
1
+ import { DEFAULT_VALUE, FIELD_META, type PrimitiveScalar } from "akanjs/base";
2
2
  import type { FieldObject } from ".";
3
3
  import type { DefaultOf } from "./types";
4
4
 
@@ -12,7 +12,7 @@ export const getDefault = <T>(fieldObj: FieldObject): DefaultOf<T> => {
12
12
  } else if (field.isArray) result[key] = [];
13
13
  else if (field.nullable) result[key] = null;
14
14
  else if (field.isClass) result[key] = field.isScalar ? getDefault(field.modelRef[FIELD_META]) : null;
15
- else result[key] = (field.modelRef as unknown as typeof PrimitiveScalar)[PRIMITIVE_DEFAULT_VALUE];
15
+ else result[key] = (field.modelRef as unknown as typeof PrimitiveScalar)[DEFAULT_VALUE];
16
16
  }
17
17
  return result as DefaultOf<T>;
18
18
  };