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.
- package/common/deepObjectify.ts +21 -7
- package/common/pathSet.ts +17 -5
- package/constant/crystalize.ts +3 -1
- package/package.json +1 -1
- package/store/action.ts +1 -1
- package/store/storeInstance.ts +3 -1
- package/types/common/deepObjectify.d.ts +4 -2
package/common/deepObjectify.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { isDayjs } from "./isDayjs";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
};
|
package/constant/crystalize.ts
CHANGED
|
@@ -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
|
-
|
|
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
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,
|
package/store/storeInstance.ts
CHANGED
|
@@ -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
|
-
|
|
1
|
+
interface DeepObjectifyOption {
|
|
2
2
|
serializable?: boolean;
|
|
3
3
|
convertDate?: "string" | "number";
|
|
4
|
-
}
|
|
4
|
+
}
|
|
5
|
+
export declare const deepObjectify: <T = unknown>(obj: T | null | undefined, option?: DeepObjectifyOption) => T;
|
|
6
|
+
export {};
|