akanjs 3.0.0-alpha.7 → 3.0.0-alpha.8

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.
@@ -1,9 +1,16 @@
1
1
  import { isDayjs } from "./isDayjs";
2
2
 
3
- export const deepObjectify = <T = unknown>(
4
- obj: T | null | undefined,
5
- option: { serializable?: boolean; convertDate?: "string" | "number" } = {},
6
- ): T => {
3
+ interface DeepObjectifyOption {
4
+ serializable?: boolean;
5
+ convertDate?: "string" | "number";
6
+ }
7
+
8
+ const objectifyChild = (value: unknown, option: DeepObjectifyOption): unknown => {
9
+ const modelValue = value as { __ModelType__?: string } | null | undefined;
10
+ return modelValue?.__ModelType__ && !option.serializable ? value : deepObjectify(value, option);
11
+ };
12
+
13
+ export const deepObjectify = <T = unknown>(obj: T | null | undefined, option: DeepObjectifyOption = {}): T => {
7
14
  if (isDayjs(obj) || obj?.constructor === Date) {
8
15
  if (!option.serializable && !option.convertDate) return obj as T;
9
16
  if (option.convertDate === "string") return obj.toISOString() as T;
@@ -12,13 +19,20 @@ export const deepObjectify = <T = unknown>(
12
19
  else return (isDayjs(obj) ? obj.toDate() : obj) as T;
13
20
  } else if (Array.isArray(obj)) {
14
21
  return obj.map((o: unknown) => deepObjectify(o, option)) as T;
22
+ } else if (obj instanceof Map) {
23
+
24
+ const entries = [...obj.entries()].map(
25
+ ([key, value]: [string, unknown]) => [key, objectifyChild(value, option)] as const,
26
+ );
27
+ return (option.serializable ? Object.fromEntries(entries) : new Map(entries)) as T;
28
+ } else if (obj instanceof Set) {
29
+ const values = [...obj.values()].map((value: unknown) => objectifyChild(value, option));
30
+ return (option.serializable ? values : new Set(values)) as T;
15
31
  } else if (obj && typeof obj === "object") {
16
32
  const val: Record<string, unknown> = {};
17
33
  const objRecord = obj as Record<string, unknown>;
18
34
  Object.keys(obj).forEach((key) => {
19
- const fieldValue = objRecord[key] as { __ModelType__: string } | null | undefined;
20
- if (fieldValue?.__ModelType__ && !option.serializable) val[key] = fieldValue;
21
- else if (typeof objRecord[key] !== "function") val[key] = deepObjectify(fieldValue, option);
35
+ if (typeof objRecord[key] !== "function") val[key] = objectifyChild(objRecord[key], option);
22
36
  });
23
37
  return val as T;
24
38
  } else {
package/common/pathSet.ts CHANGED
@@ -1,16 +1,28 @@
1
1
  type MutableIndexable = Record<string | number, unknown>;
2
2
  type PathSegment = string | number;
3
+ type Container = MutableIndexable | Map<PathSegment, unknown>;
3
4
 
4
5
  const toPathSegments = (path: string | readonly PathSegment[]) =>
5
6
  Array.isArray(path) ? [...path] : path.toString().match(/[^.[\]]+/g) || [];
6
7
 
8
+ const readChild = (container: Container, key: PathSegment) =>
9
+ container instanceof Map ? container.get(key) : container[key];
10
+
11
+ const writeChild = (container: Container, key: PathSegment, value: unknown) => {
12
+ if (container instanceof Map) container.set(key, value);
13
+ else container[key] = value;
14
+ };
15
+
7
16
  export const pathSet = <T>(obj: T, path: string | readonly PathSegment[], value: unknown): T => {
8
17
  if (Object(obj) !== obj) return obj;
9
18
  const pathSegments = toPathSegments(path);
10
- pathSegments.slice(0, -1).reduce<MutableIndexable>((a, c, i) => {
11
- if (Object(a[c]) === a[c]) return a[c] as MutableIndexable;
12
- a[c] = Math.abs(Number(pathSegments[i + 1])) >> 0 === +pathSegments[i + 1] ? [] : {};
13
- return a[c] as MutableIndexable;
14
- }, obj as MutableIndexable)[pathSegments[pathSegments.length - 1]] = value;
19
+ const parent = pathSegments.slice(0, -1).reduce<Container>((a, c, i) => {
20
+ const child = readChild(a, c);
21
+ if (Object(child) === child) return child as Container;
22
+ const created = Math.abs(Number(pathSegments[i + 1])) >> 0 === +pathSegments[i + 1] ? [] : {};
23
+ writeChild(a, c, created);
24
+ return created as unknown as Container;
25
+ }, obj as Container);
26
+ writeChild(parent, pathSegments[pathSegments.length - 1], value);
15
27
  return obj;
16
28
  };
@@ -30,8 +30,10 @@ export const crystalize = (field: FieldProps, value: unknown): unknown => {
30
30
  isArray: false,
31
31
  arrDepth: 0,
32
32
  };
33
+
34
+ const entries = value instanceof Map ? [...value.entries()] : Object.entries(value as Record<string, unknown>);
33
35
  return new Map(
34
- Object.entries(value as Record<string, unknown>).map(([key, val]) => [
36
+ entries.map(([key, val]: [string, unknown]) => [
35
37
  key,
36
38
  field.of
37
39
  ? applyFnToArrayObjects(val, (v: never) => crystalize(mapValueField, v))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "3.0.0-alpha.7",
3
+ "version": "3.0.0-alpha.8",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
package/store/action.ts CHANGED
@@ -751,7 +751,7 @@ export const makeActions = (refName: string, slice: { [key: string]: SerializedS
751
751
  const id = typeof modelOrId === "string" ? modelOrId : modelOrId.id;
752
752
  this.set({ [names.modelFormLoading]: id, [names.modelModal]: modal ?? "edit" });
753
753
  const model = await (fetch[names.model] as (...args: any[]) => Promise<Full>)(id, { onError });
754
- const modelForm = deepObjectify<Input>(model as unknown as Input);
754
+ const modelForm = immerify(modelRef, deepObjectify<Input>(model as unknown as Input) as object) as Input;
755
755
  this.set({
756
756
  [names.model]: model,
757
757
  [names.modelFormLoading]: false,
@@ -1,13 +1,15 @@
1
1
  import { ACTION_META, STATE_DERIVED_META, STATE_INIT_META } from "akanjs/base";
2
2
  import { Translator } from "akanjs/client";
3
3
  import { capitalize, Logger, parseAkanI18nEnv } from "akanjs/common";
4
- import { produce } from "immer";
4
+ import { enableMapSet, produce } from "immer";
5
5
  import type { RefObject } from "react";
6
6
  import { useEffect, useRef, useSyncExternalStore } from "./hooks";
7
7
  import type { RootStoreCls } from "./rootStore";
8
8
  import type { SliceStateKey } from "./state";
9
9
  import { evaluateInitializers, type SearchParamsState, type StateDerivedMeta } from "./stateBuilder";
10
10
 
11
+ enableMapSet();
12
+
11
13
  type StoreStateRecord = Record<string, unknown>;
12
14
  type StoreAction = (...args: unknown[]) => unknown;
13
15
  type TranslationParam = Record<string, string | number>;
@@ -1,4 +1,6 @@
1
- export declare const deepObjectify: <T = unknown>(obj: T | null | undefined, option?: {
1
+ interface DeepObjectifyOption {
2
2
  serializable?: boolean;
3
3
  convertDate?: "string" | "number";
4
- }) => T;
4
+ }
5
+ export declare const deepObjectify: <T = unknown>(obj: T | null | undefined, option?: DeepObjectifyOption) => T;
6
+ export {};