@diphyx/harlemify 4.0.1 → 5.1.0
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/README.md +30 -44
- package/dist/module.d.mts +5 -0
- package/dist/module.d.ts +5 -0
- package/dist/module.json +1 -1
- package/dist/runtime/composables/action.d.ts +16 -3
- package/dist/runtime/composables/action.js +47 -3
- package/dist/runtime/composables/model.d.ts +22 -0
- package/dist/runtime/composables/model.js +32 -0
- package/dist/runtime/composables/view.d.ts +33 -0
- package/dist/runtime/composables/view.js +54 -0
- package/dist/runtime/core/layers/action.d.ts +3 -2
- package/dist/runtime/core/layers/action.js +37 -69
- package/dist/runtime/core/layers/model.js +14 -0
- package/dist/runtime/core/layers/shape.d.ts +2 -2
- package/dist/runtime/core/layers/shape.js +3 -2
- package/dist/runtime/core/layers/view.d.ts +2 -2
- package/dist/runtime/core/layers/view.js +27 -5
- package/dist/runtime/core/store.d.ts +5 -23
- package/dist/runtime/core/store.js +8 -28
- package/dist/runtime/core/types/action.d.ts +79 -121
- package/dist/runtime/core/types/action.js +0 -16
- package/dist/runtime/core/types/base.d.ts +6 -0
- package/dist/runtime/core/types/base.js +0 -0
- package/dist/runtime/core/types/model.d.ts +47 -32
- package/dist/runtime/core/types/model.js +14 -0
- package/dist/runtime/core/types/shape.d.ts +30 -5
- package/dist/runtime/core/types/store.d.ts +14 -0
- package/dist/runtime/core/types/store.js +0 -0
- package/dist/runtime/core/types/view.d.ts +35 -24
- package/dist/runtime/core/types/view.js +5 -0
- package/dist/runtime/core/utils/action.d.ts +4 -4
- package/dist/runtime/core/utils/action.js +217 -207
- package/dist/runtime/core/utils/base.d.ts +14 -0
- package/dist/runtime/core/utils/base.js +109 -0
- package/dist/runtime/core/utils/error.d.ts +21 -0
- package/dist/runtime/core/utils/error.js +36 -0
- package/dist/runtime/core/utils/model.d.ts +3 -11
- package/dist/runtime/core/utils/model.js +104 -110
- package/dist/runtime/core/utils/shape.d.ts +6 -3
- package/dist/runtime/core/utils/shape.js +218 -14
- package/dist/runtime/core/utils/store.d.ts +8 -0
- package/dist/runtime/core/utils/store.js +35 -0
- package/dist/runtime/core/utils/view.d.ts +3 -4
- package/dist/runtime/core/utils/view.js +35 -14
- package/dist/runtime/index.d.ts +14 -5
- package/dist/runtime/index.js +7 -10
- package/package.json +2 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export class ActionApiError extends Error {
|
|
2
|
+
name = "ActionApiError";
|
|
3
|
+
constructor(source) {
|
|
4
|
+
super(source.message || "API request failed");
|
|
5
|
+
this.status = source?.status ?? source?.response?.status ?? 500;
|
|
6
|
+
this.statusText = source?.statusText ?? source?.response?.statusText ?? "Internal Server Error";
|
|
7
|
+
this.data = source?.data ?? source?.response?._data ?? null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ActionHandlerError extends Error {
|
|
11
|
+
name = "ActionHandlerError";
|
|
12
|
+
constructor(source) {
|
|
13
|
+
super(source.message || "Action handler failed");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class ActionCommitError extends Error {
|
|
17
|
+
name = "ActionCommitError";
|
|
18
|
+
constructor(source) {
|
|
19
|
+
super(source.message || "Action commit failed");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class ActionConcurrentError extends Error {
|
|
23
|
+
name = "ActionConcurrentError";
|
|
24
|
+
constructor() {
|
|
25
|
+
super("Action is already pending");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function isError(error, ...types) {
|
|
29
|
+
return types.some((ErrorType) => error instanceof ErrorType);
|
|
30
|
+
}
|
|
31
|
+
export function toError(error, ErrorType) {
|
|
32
|
+
if (ErrorType) {
|
|
33
|
+
return new ErrorType(error);
|
|
34
|
+
}
|
|
35
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
36
|
+
}
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import type { Store as SourceStore, BaseState } from "@harlem/core";
|
|
2
|
-
import
|
|
3
|
-
import { type
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function createMutations<M extends Model>(source: SourceStore<BaseState>, model: M): Mutations<M>;
|
|
6
|
-
export declare function executeCommit<M extends Model>(definition: {
|
|
7
|
-
model: keyof M;
|
|
8
|
-
mode: ActionOneMode | ActionManyMode;
|
|
9
|
-
value?: unknown;
|
|
10
|
-
options?: MutationsOneOptions | MutationsManyOptions;
|
|
11
|
-
}, mutations: Mutations<M>, result?: unknown): void;
|
|
12
|
-
export declare function createCommitter<M extends Model>(mutations: Mutations<M>): ActionCommitter<M>;
|
|
2
|
+
import type { Shape } from "../types/shape.js";
|
|
3
|
+
import { type ModelDefinition, type ModelCall } from "../types/model.js";
|
|
4
|
+
export declare function createModel<S extends Shape>(definition: ModelDefinition<S>, source: SourceStore<BaseState>): ModelCall<S>;
|
|
@@ -1,67 +1,56 @@
|
|
|
1
1
|
import { defu } from "defu";
|
|
2
2
|
import { resolveShape } from "./shape.js";
|
|
3
3
|
import {
|
|
4
|
-
ModelKind
|
|
4
|
+
ModelKind,
|
|
5
|
+
ModelOneMode,
|
|
6
|
+
ModelManyMode
|
|
5
7
|
} from "../types/model.js";
|
|
6
|
-
|
|
7
|
-
export function initializeState(model) {
|
|
8
|
-
const state = {};
|
|
9
|
-
for (const [key, definition] of Object.entries(model)) {
|
|
10
|
-
if (definition.kind === ModelKind.OBJECT) {
|
|
11
|
-
state[key] = definition.options?.default ?? null;
|
|
12
|
-
} else {
|
|
13
|
-
state[key] = definition.options?.default ?? [];
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return state;
|
|
17
|
-
}
|
|
18
|
-
function getIdentifier(definition) {
|
|
8
|
+
function resolveIdentifier(definition, shape) {
|
|
19
9
|
if (definition.options?.identifier) {
|
|
20
10
|
return definition.options.identifier;
|
|
21
11
|
}
|
|
22
|
-
|
|
23
|
-
if (identifier) {
|
|
24
|
-
return identifier;
|
|
25
|
-
}
|
|
26
|
-
return "id";
|
|
12
|
+
return shape.identifier ?? "id";
|
|
27
13
|
}
|
|
28
|
-
function
|
|
29
|
-
const setOperation = source.mutation(`${key}:set`, (state, value) => {
|
|
30
|
-
state[key] = value;
|
|
14
|
+
function createOneCommit(definition, source) {
|
|
15
|
+
const setOperation = source.mutation(`${definition.key}:set`, (state, value) => {
|
|
16
|
+
state[definition.key] = value;
|
|
31
17
|
});
|
|
32
|
-
const resetOperation = source.mutation(`${key}:reset`, (state) => {
|
|
33
|
-
state[key] = definition.options?.default ?? null;
|
|
18
|
+
const resetOperation = source.mutation(`${definition.key}:reset`, (state) => {
|
|
19
|
+
state[definition.key] = definition.options?.default ?? null;
|
|
34
20
|
});
|
|
35
|
-
const patchOperation = source.mutation(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
21
|
+
const patchOperation = source.mutation(
|
|
22
|
+
`${definition.key}:patch`,
|
|
23
|
+
(state, payload) => {
|
|
24
|
+
if (state[definition.key] === null) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (payload.options?.deep) {
|
|
28
|
+
state[definition.key] = defu(payload.value, state[definition.key]);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
state[definition.key] = {
|
|
32
|
+
...state[definition.key],
|
|
33
|
+
...payload.value
|
|
34
|
+
};
|
|
42
35
|
}
|
|
43
|
-
|
|
44
|
-
...state[key],
|
|
45
|
-
...payload.value
|
|
46
|
-
};
|
|
47
|
-
});
|
|
36
|
+
);
|
|
48
37
|
function set(value) {
|
|
49
38
|
definition.logger?.debug("Model mutation", {
|
|
50
|
-
model: key,
|
|
39
|
+
model: definition.key,
|
|
51
40
|
mutation: "set"
|
|
52
41
|
});
|
|
53
42
|
setOperation(value);
|
|
54
43
|
}
|
|
55
44
|
function reset() {
|
|
56
45
|
definition.logger?.debug("Model mutation", {
|
|
57
|
-
model: key,
|
|
46
|
+
model: definition.key,
|
|
58
47
|
mutation: "reset"
|
|
59
48
|
});
|
|
60
49
|
resetOperation();
|
|
61
50
|
}
|
|
62
51
|
function patch(value, options) {
|
|
63
52
|
definition.logger?.debug("Model mutation", {
|
|
64
|
-
model: key,
|
|
53
|
+
model: definition.key,
|
|
65
54
|
mutation: "patch"
|
|
66
55
|
});
|
|
67
56
|
patchOperation({
|
|
@@ -75,20 +64,20 @@ function createOneMutations(source, definition, key) {
|
|
|
75
64
|
patch
|
|
76
65
|
};
|
|
77
66
|
}
|
|
78
|
-
function
|
|
79
|
-
const identifier =
|
|
80
|
-
const setOperation = source.mutation(`${key}:set`, (state, value) => {
|
|
81
|
-
state[key] = value;
|
|
67
|
+
function createManyCommit(definition, shape, source) {
|
|
68
|
+
const identifier = resolveIdentifier(definition, shape);
|
|
69
|
+
const setOperation = source.mutation(`${definition.key}:set`, (state, value) => {
|
|
70
|
+
state[definition.key] = value;
|
|
82
71
|
});
|
|
83
|
-
const resetOperation = source.mutation(`${key}:reset`, (state) => {
|
|
84
|
-
state[key] = definition.options?.default ?? [];
|
|
72
|
+
const resetOperation = source.mutation(`${definition.key}:reset`, (state) => {
|
|
73
|
+
state[definition.key] = definition.options?.default ?? [];
|
|
85
74
|
});
|
|
86
75
|
const patchOperation = source.mutation(
|
|
87
|
-
`${key}:patch`,
|
|
76
|
+
`${definition.key}:patch`,
|
|
88
77
|
(state, payload) => {
|
|
89
78
|
const items = Array.isArray(payload.value) ? payload.value : [payload.value];
|
|
90
79
|
const by = payload.options?.by ?? identifier;
|
|
91
|
-
state[key] = state[key].map((item) => {
|
|
80
|
+
state[definition.key] = state[definition.key].map((item) => {
|
|
92
81
|
const found = items.find((p) => {
|
|
93
82
|
return p[by] === item[by];
|
|
94
83
|
});
|
|
@@ -105,54 +94,60 @@ function createManyMutations(source, definition, key) {
|
|
|
105
94
|
});
|
|
106
95
|
}
|
|
107
96
|
);
|
|
108
|
-
const removeOperation = source.mutation(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
);
|
|
116
|
-
state[key] = state[key].filter((item) => {
|
|
117
|
-
return !ids.has(item[by]);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
const addOperation = source.mutation(`${key}:add`, (state, payload) => {
|
|
121
|
-
let items = Array.isArray(payload.value) ? payload.value : [payload.value];
|
|
122
|
-
if (payload.options?.unique) {
|
|
123
|
-
const by = payload.options.by ?? identifier;
|
|
124
|
-
const existingIds = new Set(
|
|
125
|
-
state[key].map((item) => {
|
|
97
|
+
const removeOperation = source.mutation(
|
|
98
|
+
`${definition.key}:remove`,
|
|
99
|
+
(state, payload) => {
|
|
100
|
+
const items = Array.isArray(payload.value) ? payload.value : [payload.value];
|
|
101
|
+
const by = payload.options?.by ?? identifier;
|
|
102
|
+
const ids = new Set(
|
|
103
|
+
items.map((item) => {
|
|
126
104
|
return item[by];
|
|
127
105
|
})
|
|
128
106
|
);
|
|
129
|
-
|
|
130
|
-
return !
|
|
107
|
+
state[definition.key] = state[definition.key].filter((item) => {
|
|
108
|
+
return !ids.has(item[by]);
|
|
131
109
|
});
|
|
132
110
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
111
|
+
);
|
|
112
|
+
const addOperation = source.mutation(
|
|
113
|
+
`${definition.key}:add`,
|
|
114
|
+
(state, payload) => {
|
|
115
|
+
let items = Array.isArray(payload.value) ? payload.value : [payload.value];
|
|
116
|
+
if (payload.options?.unique) {
|
|
117
|
+
const by = payload.options.by ?? identifier;
|
|
118
|
+
const existingIds = new Set(
|
|
119
|
+
state[definition.key].map((item) => {
|
|
120
|
+
return item[by];
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
items = items.filter((item) => {
|
|
124
|
+
return !existingIds.has(item[by]);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (payload.options?.prepend) {
|
|
128
|
+
state[definition.key] = [...items, ...state[definition.key]];
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
state[definition.key] = [...state[definition.key], ...items];
|
|
136
132
|
}
|
|
137
|
-
|
|
138
|
-
});
|
|
133
|
+
);
|
|
139
134
|
function set(value) {
|
|
140
135
|
definition.logger?.debug("Model mutation", {
|
|
141
|
-
model: key,
|
|
136
|
+
model: definition.key,
|
|
142
137
|
mutation: "set"
|
|
143
138
|
});
|
|
144
139
|
setOperation(value);
|
|
145
140
|
}
|
|
146
141
|
function reset() {
|
|
147
142
|
definition.logger?.debug("Model mutation", {
|
|
148
|
-
model: key,
|
|
143
|
+
model: definition.key,
|
|
149
144
|
mutation: "reset"
|
|
150
145
|
});
|
|
151
146
|
resetOperation();
|
|
152
147
|
}
|
|
153
148
|
function patch(value, options) {
|
|
154
149
|
definition.logger?.debug("Model mutation", {
|
|
155
|
-
model: key,
|
|
150
|
+
model: definition.key,
|
|
156
151
|
mutation: "patch"
|
|
157
152
|
});
|
|
158
153
|
patchOperation({
|
|
@@ -162,7 +157,7 @@ function createManyMutations(source, definition, key) {
|
|
|
162
157
|
}
|
|
163
158
|
function remove(value, options) {
|
|
164
159
|
definition.logger?.debug("Model mutation", {
|
|
165
|
-
model: key,
|
|
160
|
+
model: definition.key,
|
|
166
161
|
mutation: "remove"
|
|
167
162
|
});
|
|
168
163
|
removeOperation({
|
|
@@ -172,7 +167,7 @@ function createManyMutations(source, definition, key) {
|
|
|
172
167
|
}
|
|
173
168
|
function add(value, options) {
|
|
174
169
|
definition.logger?.debug("Model mutation", {
|
|
175
|
-
model: key,
|
|
170
|
+
model: definition.key,
|
|
176
171
|
mutation: "add"
|
|
177
172
|
});
|
|
178
173
|
addOperation({
|
|
@@ -188,40 +183,39 @@ function createManyMutations(source, definition, key) {
|
|
|
188
183
|
add
|
|
189
184
|
};
|
|
190
185
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
for (const [key, definition] of Object.entries(model)) {
|
|
194
|
-
definition.logger?.debug("Model registered", {
|
|
195
|
-
model: key,
|
|
196
|
-
kind: definition.kind
|
|
197
|
-
});
|
|
198
|
-
if (definition.kind === ModelKind.OBJECT) {
|
|
199
|
-
mutations[key] = createOneMutations(source, definition, key);
|
|
200
|
-
} else {
|
|
201
|
-
mutations[key] = createManyMutations(source, definition, key);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return mutations;
|
|
186
|
+
function isOneDefinition(definition) {
|
|
187
|
+
return definition.kind === ModelKind.OBJECT;
|
|
205
188
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
case ActionOneMode.RESET:
|
|
210
|
-
case ActionManyMode.RESET: {
|
|
211
|
-
handler();
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
default: {
|
|
215
|
-
handler(
|
|
216
|
-
definition.value === AUTO || definition.value === void 0 ? result : definition.value,
|
|
217
|
-
definition.options
|
|
218
|
-
);
|
|
219
|
-
}
|
|
189
|
+
function resolveCommit(definition, shape, source) {
|
|
190
|
+
if (isOneDefinition(definition)) {
|
|
191
|
+
return createOneCommit(definition, source);
|
|
220
192
|
}
|
|
193
|
+
return createManyCommit(definition, shape, source);
|
|
221
194
|
}
|
|
222
|
-
export function
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
195
|
+
export function createModel(definition, source) {
|
|
196
|
+
definition.logger?.debug("Registering model", {
|
|
197
|
+
model: definition.key,
|
|
198
|
+
kind: definition.kind
|
|
199
|
+
});
|
|
200
|
+
const shape = resolveShape(definition.shape);
|
|
201
|
+
const commit = resolveCommit(definition, shape, source);
|
|
202
|
+
const model = Object.assign(commit, {
|
|
203
|
+
commit(mode, value, options) {
|
|
204
|
+
const handler = commit[mode];
|
|
205
|
+
switch (mode) {
|
|
206
|
+
case ModelOneMode.RESET:
|
|
207
|
+
case ModelManyMode.RESET: {
|
|
208
|
+
handler();
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
default: {
|
|
212
|
+
handler(value, options);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
aliases() {
|
|
217
|
+
return shape.aliases;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return model;
|
|
227
221
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
1
|
+
import type { ShapeCall, ShapeDefinition, ShapeInfer, ShapeResolved, ShapeRawDefinition } from "../types/shape.js";
|
|
2
|
+
export declare function resolveShape(shape: ShapeDefinition): ShapeResolved;
|
|
3
|
+
export declare function resolveAliasInbound<T = unknown>(data: T, aliases?: Record<string, string>): T;
|
|
4
|
+
export declare function resolveAliasOutbound<T = unknown>(data: T, aliases?: Record<string, string>): T;
|
|
5
|
+
export declare function resolveDefaults<T extends ShapeDefinition>(shape: T, overrides?: Partial<ShapeInfer<T>>): ShapeInfer<T>;
|
|
6
|
+
export declare function createShape<T extends ShapeRawDefinition>(definition: T): ShapeCall<T>;
|
|
@@ -1,29 +1,233 @@
|
|
|
1
|
+
import { defu } from "defu";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { isPlainObject, isEmptyRecord } from "./base.js";
|
|
4
|
+
function resolveStringZeroValue() {
|
|
5
|
+
return "";
|
|
6
|
+
}
|
|
7
|
+
function resolveNumberZeroValue() {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
function resolveBooleanZeroValue() {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
function resolveBigintZeroValue() {
|
|
14
|
+
return BigInt(0);
|
|
15
|
+
}
|
|
16
|
+
function resolveDateZeroValue() {
|
|
17
|
+
return /* @__PURE__ */ new Date(0);
|
|
18
|
+
}
|
|
19
|
+
function resolveArrayZeroValue() {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
function resolveRecordZeroValue() {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
function resolveMapZeroValue() {
|
|
26
|
+
return /* @__PURE__ */ new Map();
|
|
27
|
+
}
|
|
28
|
+
function resolveSetZeroValue() {
|
|
29
|
+
return /* @__PURE__ */ new Set();
|
|
30
|
+
}
|
|
31
|
+
function resolveObjectZeroValue(definition) {
|
|
32
|
+
const output = {};
|
|
33
|
+
if (definition.shape) {
|
|
34
|
+
for (const [key, value] of Object.entries(definition.shape)) {
|
|
35
|
+
output[key] = resolveZeroValue(value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return output;
|
|
39
|
+
}
|
|
40
|
+
function resolveEnumZeroValue(definition) {
|
|
41
|
+
if (definition.entries) {
|
|
42
|
+
return Object.values(definition.entries)[0];
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
function resolveLiteralZeroValue(definition) {
|
|
47
|
+
if (definition.values) {
|
|
48
|
+
return definition.values[0];
|
|
49
|
+
}
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
function resolveTupleZeroValue(definition) {
|
|
53
|
+
if (definition.items) {
|
|
54
|
+
return definition.items.map(resolveZeroValue);
|
|
55
|
+
}
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
function resolveUnionZeroValue(definition) {
|
|
59
|
+
if (definition.options?.[0]) {
|
|
60
|
+
return resolveZeroValue(definition.options[0]);
|
|
61
|
+
}
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
function resolveDefaultZeroValue(definition) {
|
|
65
|
+
if (typeof definition.defaultValue === "function") {
|
|
66
|
+
return definition.defaultValue();
|
|
67
|
+
}
|
|
68
|
+
return definition.defaultValue;
|
|
69
|
+
}
|
|
70
|
+
function resolveInnerZeroValue(definition) {
|
|
71
|
+
if (definition.innerType) {
|
|
72
|
+
return resolveZeroValue(definition.innerType);
|
|
73
|
+
}
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
function resolveZeroValue(field) {
|
|
77
|
+
const definition = field.def;
|
|
78
|
+
if (!definition?.type) {
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
switch (definition.type) {
|
|
82
|
+
case "string": {
|
|
83
|
+
return resolveStringZeroValue();
|
|
84
|
+
}
|
|
85
|
+
case "number": {
|
|
86
|
+
return resolveNumberZeroValue();
|
|
87
|
+
}
|
|
88
|
+
case "boolean": {
|
|
89
|
+
return resolveBooleanZeroValue();
|
|
90
|
+
}
|
|
91
|
+
case "bigint": {
|
|
92
|
+
return resolveBigintZeroValue();
|
|
93
|
+
}
|
|
94
|
+
case "date": {
|
|
95
|
+
return resolveDateZeroValue();
|
|
96
|
+
}
|
|
97
|
+
case "array": {
|
|
98
|
+
return resolveArrayZeroValue();
|
|
99
|
+
}
|
|
100
|
+
case "record": {
|
|
101
|
+
return resolveRecordZeroValue();
|
|
102
|
+
}
|
|
103
|
+
case "map": {
|
|
104
|
+
return resolveMapZeroValue();
|
|
105
|
+
}
|
|
106
|
+
case "set": {
|
|
107
|
+
return resolveSetZeroValue();
|
|
108
|
+
}
|
|
109
|
+
case "object": {
|
|
110
|
+
return resolveObjectZeroValue(definition);
|
|
111
|
+
}
|
|
112
|
+
case "enum": {
|
|
113
|
+
return resolveEnumZeroValue(definition);
|
|
114
|
+
}
|
|
115
|
+
case "literal": {
|
|
116
|
+
return resolveLiteralZeroValue(definition);
|
|
117
|
+
}
|
|
118
|
+
case "tuple": {
|
|
119
|
+
return resolveTupleZeroValue(definition);
|
|
120
|
+
}
|
|
121
|
+
case "union": {
|
|
122
|
+
return resolveUnionZeroValue(definition);
|
|
123
|
+
}
|
|
124
|
+
case "default": {
|
|
125
|
+
return resolveDefaultZeroValue(definition);
|
|
126
|
+
}
|
|
127
|
+
case "optional":
|
|
128
|
+
case "nullable": {
|
|
129
|
+
return resolveInnerZeroValue(definition);
|
|
130
|
+
}
|
|
131
|
+
default: {
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
1
136
|
export function resolveShape(shape) {
|
|
2
|
-
const
|
|
137
|
+
const resolved = {
|
|
3
138
|
identifier: void 0,
|
|
4
139
|
defaults: {},
|
|
5
|
-
fields: []
|
|
140
|
+
fields: [],
|
|
141
|
+
aliases: {}
|
|
6
142
|
};
|
|
7
143
|
for (const [key, field] of Object.entries(shape.shape)) {
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
11
|
-
|
|
144
|
+
resolved.fields.push(key);
|
|
145
|
+
const fieldMeta = field.meta();
|
|
146
|
+
if (fieldMeta?.identifier) {
|
|
147
|
+
resolved.identifier = key;
|
|
148
|
+
}
|
|
149
|
+
if (fieldMeta?.alias) {
|
|
150
|
+
resolved.aliases[key] = fieldMeta.alias;
|
|
12
151
|
}
|
|
152
|
+
const fieldDefinition = field.def;
|
|
13
153
|
if (fieldDefinition?.defaultValue !== void 0) {
|
|
14
154
|
if (typeof fieldDefinition.defaultValue === "function") {
|
|
15
|
-
|
|
155
|
+
resolved.defaults[key] = fieldDefinition.defaultValue();
|
|
16
156
|
continue;
|
|
17
157
|
}
|
|
18
|
-
|
|
158
|
+
resolved.defaults[key] = fieldDefinition.defaultValue;
|
|
19
159
|
}
|
|
20
160
|
}
|
|
21
|
-
if (!
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
} else if (
|
|
25
|
-
|
|
161
|
+
if (!resolved.identifier) {
|
|
162
|
+
if (resolved.fields.includes("id")) {
|
|
163
|
+
resolved.identifier = "id";
|
|
164
|
+
} else if (resolved.fields.includes("_id")) {
|
|
165
|
+
resolved.identifier = "_id";
|
|
26
166
|
}
|
|
27
167
|
}
|
|
28
|
-
return
|
|
168
|
+
return resolved;
|
|
169
|
+
}
|
|
170
|
+
function resolveAliasObject(data, mapping) {
|
|
171
|
+
const output = {};
|
|
172
|
+
for (const [key, value] of Object.entries(data)) {
|
|
173
|
+
output[mapping[key] ?? key] = value;
|
|
174
|
+
}
|
|
175
|
+
return output;
|
|
176
|
+
}
|
|
177
|
+
export function resolveAliasInbound(data, aliases) {
|
|
178
|
+
if (isEmptyRecord(aliases)) {
|
|
179
|
+
return data;
|
|
180
|
+
}
|
|
181
|
+
const reverse = {};
|
|
182
|
+
for (const [shapeKey, aliasKey] of Object.entries(aliases)) {
|
|
183
|
+
reverse[aliasKey] = shapeKey;
|
|
184
|
+
}
|
|
185
|
+
if (Array.isArray(data)) {
|
|
186
|
+
return data.map((item) => {
|
|
187
|
+
if (isPlainObject(item)) {
|
|
188
|
+
return resolveAliasObject(item, reverse);
|
|
189
|
+
}
|
|
190
|
+
return item;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (isPlainObject(data)) {
|
|
194
|
+
return resolveAliasObject(data, reverse);
|
|
195
|
+
}
|
|
196
|
+
return data;
|
|
197
|
+
}
|
|
198
|
+
export function resolveAliasOutbound(data, aliases) {
|
|
199
|
+
if (isEmptyRecord(aliases)) {
|
|
200
|
+
return data;
|
|
201
|
+
}
|
|
202
|
+
if (Array.isArray(data)) {
|
|
203
|
+
return data.map((item) => {
|
|
204
|
+
if (isPlainObject(item)) {
|
|
205
|
+
return resolveAliasObject(item, aliases);
|
|
206
|
+
}
|
|
207
|
+
return item;
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
if (isPlainObject(data)) {
|
|
211
|
+
return resolveAliasObject(data, aliases);
|
|
212
|
+
}
|
|
213
|
+
return data;
|
|
214
|
+
}
|
|
215
|
+
export function resolveDefaults(shape, overrides) {
|
|
216
|
+
const output = {};
|
|
217
|
+
for (const [key, field] of Object.entries(shape.shape)) {
|
|
218
|
+
output[key] = resolveZeroValue(field);
|
|
219
|
+
}
|
|
220
|
+
if (overrides) {
|
|
221
|
+
return defu(overrides, output);
|
|
222
|
+
}
|
|
223
|
+
return output;
|
|
224
|
+
}
|
|
225
|
+
export function createShape(definition) {
|
|
226
|
+
const object = z.object(definition);
|
|
227
|
+
const shape = Object.assign(object, {
|
|
228
|
+
defaults(overrides) {
|
|
229
|
+
return resolveDefaults(object, overrides);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
return shape;
|
|
29
233
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { createStore as createSourceStore } from "@harlem/core";
|
|
2
|
+
import { type ModelDefinitions, type ModelDefinitionsInfer, type StoreModel } from "../types/model.js";
|
|
3
|
+
import type { ViewDefinitions, StoreView } from "../types/view.js";
|
|
4
|
+
import type { ActionDefinition, ActionDefinitions, StoreAction } from "../types/action.js";
|
|
5
|
+
export declare function createStoreState<MD extends ModelDefinitions>(modelDefinitions: MD): ModelDefinitionsInfer<MD>;
|
|
6
|
+
export declare function createStoreModel<MD extends ModelDefinitions>(modelDefinitions: MD, source: ReturnType<typeof createSourceStore>): StoreModel<MD>;
|
|
7
|
+
export declare function createStoreView<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>>(viewDefinitions: VD, source: ReturnType<typeof createSourceStore>): StoreView<MD, VD>;
|
|
8
|
+
export declare function createStoreAction<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>, AD extends ActionDefinitions<MD, VD>>(actionDefinitions: Record<string, ActionDefinition<MD, VD>>, model: StoreModel<MD>, view: StoreView<MD, VD>): StoreAction<MD, VD, AD>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createModel } from "./model.js";
|
|
2
|
+
import { createView } from "./view.js";
|
|
3
|
+
import { createAction } from "./action.js";
|
|
4
|
+
import { ModelKind } from "../types/model.js";
|
|
5
|
+
export function createStoreState(modelDefinitions) {
|
|
6
|
+
const output = {};
|
|
7
|
+
for (const [key, { options, kind }] of Object.entries(modelDefinitions)) {
|
|
8
|
+
output[key] = options?.default ?? (kind === ModelKind.OBJECT ? null : []);
|
|
9
|
+
}
|
|
10
|
+
return output;
|
|
11
|
+
}
|
|
12
|
+
export function createStoreModel(modelDefinitions, source) {
|
|
13
|
+
const output = {};
|
|
14
|
+
for (const [key, definition] of Object.entries(modelDefinitions)) {
|
|
15
|
+
definition.setKey(key);
|
|
16
|
+
output[key] = createModel(definition, source);
|
|
17
|
+
}
|
|
18
|
+
return output;
|
|
19
|
+
}
|
|
20
|
+
export function createStoreView(viewDefinitions, source) {
|
|
21
|
+
const output = {};
|
|
22
|
+
for (const [key, definition] of Object.entries(viewDefinitions)) {
|
|
23
|
+
definition.setKey(key);
|
|
24
|
+
output[key] = createView(definition, source);
|
|
25
|
+
}
|
|
26
|
+
return output;
|
|
27
|
+
}
|
|
28
|
+
export function createStoreAction(actionDefinitions, model, view) {
|
|
29
|
+
const output = {};
|
|
30
|
+
for (const [key, definition] of Object.entries(actionDefinitions)) {
|
|
31
|
+
definition.setKey(key);
|
|
32
|
+
output[key] = createAction(definition, model, view);
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Store as SourceStore, BaseState } from "@harlem/core";
|
|
2
|
-
import type {
|
|
3
|
-
import type
|
|
4
|
-
|
|
5
|
-
export declare function createView<M extends Model, VD extends ViewDefinitions<M>>(source: SourceStore<BaseState>, definitions: VD): StoreView<M, VD>;
|
|
2
|
+
import type { ModelDefinitions } from "../types/model.js";
|
|
3
|
+
import { type ViewDefinition, type ViewCall } from "../types/view.js";
|
|
4
|
+
export declare function createView<MD extends ModelDefinitions, R = unknown>(definition: ViewDefinition<MD>, source: SourceStore<BaseState>): ViewCall<R>;
|