@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.
Files changed (47) hide show
  1. package/README.md +30 -44
  2. package/dist/module.d.mts +5 -0
  3. package/dist/module.d.ts +5 -0
  4. package/dist/module.json +1 -1
  5. package/dist/runtime/composables/action.d.ts +16 -3
  6. package/dist/runtime/composables/action.js +47 -3
  7. package/dist/runtime/composables/model.d.ts +22 -0
  8. package/dist/runtime/composables/model.js +32 -0
  9. package/dist/runtime/composables/view.d.ts +33 -0
  10. package/dist/runtime/composables/view.js +54 -0
  11. package/dist/runtime/core/layers/action.d.ts +3 -2
  12. package/dist/runtime/core/layers/action.js +37 -69
  13. package/dist/runtime/core/layers/model.js +14 -0
  14. package/dist/runtime/core/layers/shape.d.ts +2 -2
  15. package/dist/runtime/core/layers/shape.js +3 -2
  16. package/dist/runtime/core/layers/view.d.ts +2 -2
  17. package/dist/runtime/core/layers/view.js +27 -5
  18. package/dist/runtime/core/store.d.ts +5 -23
  19. package/dist/runtime/core/store.js +8 -28
  20. package/dist/runtime/core/types/action.d.ts +79 -121
  21. package/dist/runtime/core/types/action.js +0 -16
  22. package/dist/runtime/core/types/base.d.ts +6 -0
  23. package/dist/runtime/core/types/base.js +0 -0
  24. package/dist/runtime/core/types/model.d.ts +47 -32
  25. package/dist/runtime/core/types/model.js +14 -0
  26. package/dist/runtime/core/types/shape.d.ts +30 -5
  27. package/dist/runtime/core/types/store.d.ts +14 -0
  28. package/dist/runtime/core/types/store.js +0 -0
  29. package/dist/runtime/core/types/view.d.ts +35 -24
  30. package/dist/runtime/core/types/view.js +5 -0
  31. package/dist/runtime/core/utils/action.d.ts +4 -4
  32. package/dist/runtime/core/utils/action.js +217 -207
  33. package/dist/runtime/core/utils/base.d.ts +14 -0
  34. package/dist/runtime/core/utils/base.js +109 -0
  35. package/dist/runtime/core/utils/error.d.ts +21 -0
  36. package/dist/runtime/core/utils/error.js +36 -0
  37. package/dist/runtime/core/utils/model.d.ts +3 -11
  38. package/dist/runtime/core/utils/model.js +104 -110
  39. package/dist/runtime/core/utils/shape.d.ts +6 -3
  40. package/dist/runtime/core/utils/shape.js +218 -14
  41. package/dist/runtime/core/utils/store.d.ts +8 -0
  42. package/dist/runtime/core/utils/store.js +35 -0
  43. package/dist/runtime/core/utils/view.d.ts +3 -4
  44. package/dist/runtime/core/utils/view.js +35 -14
  45. package/dist/runtime/index.d.ts +14 -5
  46. package/dist/runtime/index.js +7 -10
  47. 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 { type Model, type ModelStateOf, type MutationsOneOptions, type MutationsManyOptions, type Mutations } from "../types/model.js";
3
- import { type ActionCommitter, ActionOneMode, ActionManyMode } from "../types/action.js";
4
- export declare function initializeState<M extends Model>(model: M): ModelStateOf<M>;
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
- import { ActionOneMode, ActionManyMode, AUTO } from "../types/action.js";
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
- const { identifier } = resolveShape(definition.shape);
23
- if (identifier) {
24
- return identifier;
25
- }
26
- return "id";
12
+ return shape.identifier ?? "id";
27
13
  }
28
- function createOneMutations(source, definition, key) {
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(`${key}:patch`, (state, payload) => {
36
- if (state[key] === null) {
37
- return;
38
- }
39
- if (payload.options?.deep) {
40
- state[key] = defu(payload.value, state[key]);
41
- return;
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
- state[key] = {
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 createManyMutations(source, definition, key) {
79
- const identifier = getIdentifier(definition);
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(`${key}:remove`, (state, payload) => {
109
- const items = Array.isArray(payload.value) ? payload.value : [payload.value];
110
- const by = payload.options?.by ?? identifier;
111
- const ids = new Set(
112
- items.map((item) => {
113
- return item[by];
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
- items = items.filter((item) => {
130
- return !existingIds.has(item[by]);
107
+ state[definition.key] = state[definition.key].filter((item) => {
108
+ return !ids.has(item[by]);
131
109
  });
132
110
  }
133
- if (payload.options?.prepend) {
134
- state[key] = [...items, ...state[key]];
135
- return;
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
- state[key] = [...state[key], ...items];
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
- export function createMutations(source, model) {
192
- const mutations = {};
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
- export function executeCommit(definition, mutations, result) {
207
- const handler = mutations[definition.model][definition.mode];
208
- switch (definition.mode) {
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 createCommitter(mutations) {
223
- function committer(model, mode, value, options) {
224
- executeCommit({ model, mode, value, options }, mutations);
225
- }
226
- return committer;
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 { z } from "zod";
2
- import type { ShapeMeta } from "../types/shape.js";
3
- export declare function resolveShape(shape: z.ZodObject<z.ZodRawShape>): ShapeMeta;
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 meta = {
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
- meta.fields.push(key);
9
- const fieldDefinition = field.def;
10
- if (fieldDefinition?.meta?.identifier) {
11
- meta.identifier = key;
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
- meta.defaults[key] = fieldDefinition.defaultValue();
155
+ resolved.defaults[key] = fieldDefinition.defaultValue();
16
156
  continue;
17
157
  }
18
- meta.defaults[key] = fieldDefinition.defaultValue;
158
+ resolved.defaults[key] = fieldDefinition.defaultValue;
19
159
  }
20
160
  }
21
- if (!meta.identifier) {
22
- if (meta.fields.includes("id")) {
23
- meta.identifier = "id";
24
- } else if (meta.fields.includes("_id")) {
25
- meta.identifier = "_id";
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 meta;
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 { StoreView } from "../store.js";
3
- import type { Model } from "../types/model.js";
4
- import type { ViewDefinitions } from "../types/view.js";
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>;