@diphyx/harlemify 6.2.0 → 6.3.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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.14.0 || ^4.0.0"
6
6
  },
7
- "version": "6.2.0",
7
+ "version": "6.3.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "unknown"
@@ -1,5 +1,5 @@
1
- import type { ConsolaInstance } from "consola";
1
+ import type { Logger } from "../types/base.js";
2
2
  import type { ModelDefinitions } from "../types/model.js";
3
3
  import type { ViewDefinitions } from "../types/view.js";
4
4
  import { type RuntimeActionConfig, type ActionFactory } from "../types/action.js";
5
- export declare function createActionFactory<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>>(config?: RuntimeActionConfig, logger?: ConsolaInstance): ActionFactory<MD, VD>;
5
+ export declare function createActionFactory<MD extends ModelDefinitions, VD extends ViewDefinitions<MD>>(config?: RuntimeActionConfig, logger?: Logger): ActionFactory<MD, VD>;
@@ -1,3 +1,3 @@
1
- import type { ConsolaInstance } from "consola";
1
+ import type { Logger } from "../types/base.js";
2
2
  import { type RuntimeModelConfig, type ModelFactory } from "../types/model.js";
3
- export declare function createModelFactory(config?: RuntimeModelConfig, logger?: ConsolaInstance): ModelFactory;
3
+ export declare function createModelFactory(config?: RuntimeModelConfig, logger?: Logger): ModelFactory;
@@ -1,4 +1,4 @@
1
- import type { ConsolaInstance } from "consola";
1
+ import type { Logger } from "../types/base.js";
2
2
  import type { ModelDefinitions } from "../types/model.js";
3
3
  import type { RuntimeViewConfig, ViewFactory } from "../types/view.js";
4
- export declare function createViewFactory<MD extends ModelDefinitions>(config?: RuntimeViewConfig, logger?: ConsolaInstance): ViewFactory<MD>;
4
+ export declare function createViewFactory<MD extends ModelDefinitions>(config?: RuntimeViewConfig, logger?: Logger): ViewFactory<MD>;
@@ -1,5 +1,4 @@
1
1
  import { effectScope } from "vue";
2
- import { createConsola } from "consola";
3
2
  import { createStore as createStoreSource } from "@harlem/core";
4
3
  import { runtimeConfig } from "../config.js";
5
4
  import { createModelFactory } from "./layers/model.js";
@@ -7,14 +6,10 @@ import { createViewFactory } from "./layers/view.js";
7
6
  import { createActionFactory } from "./layers/action.js";
8
7
  import { createStoreState, createStoreModel, createStoreView, createStoreAction } from "./utils/store.js";
9
8
  import { createStoreCompose } from "./utils/compose.js";
9
+ import { createLogger } from "./utils/logger.js";
10
10
  export function createStore(config) {
11
11
  function init() {
12
- const logger = createConsola({
13
- level: runtimeConfig.logger,
14
- defaults: {
15
- tag: `harlemify:${config.name}`
16
- }
17
- });
12
+ const logger = createLogger(`harlemify:${config.name}`, runtimeConfig.logger);
18
13
  logger.info("Creating store");
19
14
  const modelFactory = createModelFactory(runtimeConfig.model, logger);
20
15
  const viewFactory = createViewFactory(runtimeConfig.view, logger);
@@ -1,5 +1,10 @@
1
- import type { ConsolaInstance } from "consola";
1
+ export interface Logger {
2
+ info(message: string, ...args: unknown[]): void;
3
+ debug(message: string, ...args: unknown[]): void;
4
+ warn(message: string, ...args: unknown[]): void;
5
+ error(message: string, ...args: unknown[]): void;
6
+ }
2
7
  export interface BaseDefinition {
3
8
  key: string;
4
- logger?: ConsolaInstance;
9
+ logger?: Logger;
5
10
  }
@@ -31,15 +31,19 @@ export type ModelDefaultIdentifier<S extends Shape> = "id" extends keyof S ? "id
31
31
  export type AtLeastOne<S extends Shape> = {
32
32
  [K in keyof S]: Pick<S, K>;
33
33
  }[keyof S];
34
- export interface ModelDefinitionOptions {
35
- pre?: () => void;
36
- post?: () => void;
34
+ export type ModelHookContext<T> = {
35
+ mode: ModelOneMode | ModelManyMode;
36
+ state: T;
37
+ };
38
+ export interface ModelDefinitionOptions<T = unknown> {
39
+ pre?: (context: ModelHookContext<T>) => void;
40
+ post?: (context: ModelHookContext<T>) => void;
37
41
  }
38
42
  export interface ModelOneDefinition<S extends Shape> extends BaseDefinition {
39
43
  shape: ShapeType<S>;
40
44
  type: ModelType.ONE;
41
45
  default: () => S;
42
- options?: ModelDefinitionOptions;
46
+ options?: ModelDefinitionOptions<S>;
43
47
  }
44
48
  export interface ModelManyDefinition<S extends Shape, I extends keyof S = ModelDefaultIdentifier<S>, T extends ModelManyKind = ModelManyKind.LIST> extends BaseDefinition {
45
49
  shape: ShapeType<S>;
@@ -47,7 +51,7 @@ export interface ModelManyDefinition<S extends Shape, I extends keyof S = ModelD
47
51
  kind: T;
48
52
  identifier: [T] extends [ModelManyKind.LIST] ? I : never;
49
53
  default: () => [T] extends [ModelManyKind.LIST] ? S[] : Record<string, S[]>;
50
- options?: ModelDefinitionOptions;
54
+ options?: ModelDefinitionOptions<[T] extends [ModelManyKind.LIST] ? S[] : Record<string, S[]>>;
51
55
  }
52
56
  export type ModelDefinition<S extends Shape> = ModelOneDefinition<S> | ModelManyDefinition<S, any, any>;
53
57
  export type ModelDefinitions = Record<string, ModelDefinition<any>>;
@@ -59,10 +63,10 @@ export type ModelDefinitionsInfer<MD extends ModelDefinitions> = {
59
63
  [K in keyof MD]: ModelDefinitionInfer<MD, K>;
60
64
  };
61
65
  export interface ModelFactory {
62
- one<S extends Shape>(shape: ShapeType<S>, options?: ModelDefinitionOptions & {
66
+ one<S extends Shape>(shape: ShapeType<S>, options?: ModelDefinitionOptions<S> & {
63
67
  default?: () => S;
64
68
  }): ModelOneDefinition<S>;
65
- many<S extends Shape, I extends keyof S = ModelDefaultIdentifier<S>, T extends ModelManyKind = ModelManyKind.LIST>(shape: ShapeType<S>, options?: ModelDefinitionOptions & {
69
+ many<S extends Shape, I extends keyof S = ModelDefaultIdentifier<S>, T extends ModelManyKind = ModelManyKind.LIST>(shape: ShapeType<S>, options?: ModelDefinitionOptions<[T] extends [ModelManyKind.LIST] ? S[] : Record<string, S[]>> & {
66
70
  kind?: T;
67
71
  identifier?: [T] extends [ModelManyKind.LIST] ? I : never;
68
72
  default?: () => [T] extends [ModelManyKind.LIST] ? S[] : Record<string, S[]>;
@@ -1,4 +1,3 @@
1
- import { defu } from "defu";
2
1
  import { ref, computed, readonly, toValue, nextTick } from "vue";
3
2
  import {
4
3
  ActionApiMethod,
@@ -6,7 +5,7 @@ import {
6
5
  ActionStatus,
7
6
  ActionConcurrent
8
7
  } from "../types/action.js";
9
- import { trimStart, trimEnd, isEmptyRecord, isPlainObject } from "./base.js";
8
+ import { trimStart, trimEnd, isEmptyRecord, isPlainObject, merge } from "./base.js";
10
9
  import {
11
10
  ActionApiError,
12
11
  ActionHandlerError,
@@ -38,12 +37,12 @@ function resolveApiUrl(definition, view, options) {
38
37
  function resolveApiHeaders(definition, view, options) {
39
38
  const initial = resolveValue(definition.request.headers, view, {});
40
39
  const custom = options?.headers ?? {};
41
- return defu(custom, initial);
40
+ return merge(custom, initial);
42
41
  }
43
42
  function resolveApiQuery(definition, view, options) {
44
43
  const initial = resolveValue(definition.request.query, view, {});
45
44
  const custom = options?.query ?? {};
46
- return defu(custom, initial);
45
+ return merge(custom, initial);
47
46
  }
48
47
  function resolveApiBody(definition, view, target, options) {
49
48
  if (definition.request.method === ActionApiMethod.GET || definition.request.method === ActionApiMethod.HEAD) {
@@ -51,7 +50,7 @@ function resolveApiBody(definition, view, target, options) {
51
50
  }
52
51
  const initial = resolveValue(definition.request.body, view, {});
53
52
  const custom = options?.body ?? {};
54
- const body = defu(custom, initial);
53
+ const body = merge(custom, initial);
55
54
  if (!isPlainObject(body)) {
56
55
  return body;
57
56
  }
@@ -1,4 +1,5 @@
1
1
  import type { BaseDefinition } from "../types/base.js";
2
+ export declare function snapshot<T>(value: T): T;
2
3
  export declare function wrapBaseDefinition<T extends Omit<BaseDefinition, "key">>(definition: T): T & BaseDefinition;
3
4
  export declare function trimStart(value: string, char: string): string;
4
5
  export declare function trimEnd(value: string, char: string): string;
@@ -6,5 +7,6 @@ export declare function ensureArray<T>(value: T | T[]): T[];
6
7
  export declare function isObject(value: unknown): value is object;
7
8
  export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
8
9
  export declare function isEmptyRecord(record: Record<string, unknown> | undefined): record is undefined;
10
+ export declare function merge<T>(priority: unknown, base: T): T;
9
11
  export declare function debounce<T extends (...args: any[]) => any>(callback: T, delay: number): T;
10
12
  export declare function throttle<T extends (...args: any[]) => any>(callback: T, delay: number): T;
@@ -1,3 +1,7 @@
1
+ import { objectClone, typeIsObject } from "@harlem/utilities";
2
+ export function snapshot(value) {
3
+ return objectClone(value);
4
+ }
1
5
  export function wrapBaseDefinition(definition) {
2
6
  let key = "";
3
7
  return Object.defineProperties(definition, {
@@ -23,16 +27,10 @@ export function ensureArray(value) {
23
27
  return Array.isArray(value) ? value : [value];
24
28
  }
25
29
  export function isObject(value) {
26
- return value != null && typeof value === "object";
30
+ return typeIsObject(value);
27
31
  }
28
32
  export function isPlainObject(value) {
29
- if (!isObject(value)) {
30
- return false;
31
- }
32
- if (Array.isArray(value)) {
33
- return false;
34
- }
35
- return true;
33
+ return isObject(value);
36
34
  }
37
35
  export function isEmptyRecord(record) {
38
36
  if (!record) {
@@ -43,6 +41,20 @@ export function isEmptyRecord(record) {
43
41
  }
44
42
  return false;
45
43
  }
44
+ export function merge(priority, base) {
45
+ if (!isPlainObject(priority) || !isPlainObject(base)) {
46
+ return priority;
47
+ }
48
+ const output = { ...base };
49
+ for (const key of Object.keys(priority)) {
50
+ const value = priority[key];
51
+ if (value === null || value === void 0) {
52
+ continue;
53
+ }
54
+ output[key] = merge(value, output[key]);
55
+ }
56
+ return output;
57
+ }
46
58
  export function debounce(callback, delay) {
47
59
  let timer = null;
48
60
  return (...args) => {
@@ -1,3 +1,3 @@
1
- import type { ConsolaInstance } from "consola";
1
+ import type { Logger } from "../types/base.js";
2
2
  import type { ComposeDefinitions, StoreCompose } from "../types/compose.js";
3
- export declare function createStoreCompose<CD extends ComposeDefinitions>(composeConfig: ((...args: any[]) => CD) | undefined, context: Record<string, unknown>, logger?: ConsolaInstance): StoreCompose<CD>;
3
+ export declare function createStoreCompose<CD extends ComposeDefinitions>(composeConfig: ((...args: any[]) => CD) | undefined, context: Record<string, unknown>, logger?: Logger): StoreCompose<CD>;
@@ -0,0 +1,2 @@
1
+ import type { Logger } from "../types/base.js";
2
+ export declare function createLogger(tag: string, level?: number): Logger;
@@ -0,0 +1,22 @@
1
+ const LEVELS = {
2
+ error: 0,
3
+ warn: 1,
4
+ info: 3,
5
+ debug: 4
6
+ };
7
+ export function createLogger(tag, level = -999) {
8
+ function report(method, sink) {
9
+ return (message, ...args) => {
10
+ if (LEVELS[method] > level) {
11
+ return;
12
+ }
13
+ sink(`[${tag}]`, message, ...args);
14
+ };
15
+ }
16
+ return {
17
+ info: report("info", console.info),
18
+ debug: report("debug", console.debug),
19
+ warn: report("warn", console.warn),
20
+ error: report("error", console.error)
21
+ };
22
+ }
@@ -1,5 +1,4 @@
1
- import { defu } from "defu";
2
- import { ensureArray } from "./base.js";
1
+ import { ensureArray, snapshot, merge } from "./base.js";
3
2
  import { resolveShapeAliases } from "./shape.js";
4
3
  import {
5
4
  ModelType,
@@ -8,12 +7,17 @@ import {
8
7
  ModelManyMode,
9
8
  ModelSilent
10
9
  } from "../types/model.js";
11
- function callHook(definition, hook, silent) {
10
+ function callHook(definition, source, hook, mode, silent) {
12
11
  if (silent === true || silent === hook) {
13
12
  return;
14
13
  }
14
+ const handler = definition.options?.[hook];
15
+ if (!handler) {
16
+ return;
17
+ }
15
18
  try {
16
- definition.options?.[hook]?.();
19
+ const state = snapshot(source.state[definition.key]);
20
+ handler({ mode, state });
17
21
  } catch (error) {
18
22
  definition.logger?.error(`Model ${hook} hook error`, {
19
23
  model: definition.key,
@@ -21,14 +25,14 @@ function callHook(definition, hook, silent) {
21
25
  });
22
26
  }
23
27
  }
24
- function wrapOperation(definition, mutation, operation, silent) {
28
+ function wrapOperation(definition, source, mode, operation, silent) {
25
29
  definition.logger?.debug("Model mutation", {
26
30
  model: definition.key,
27
- mutation
31
+ mutation: mode
28
32
  });
29
- callHook(definition, ModelSilent.PRE, silent);
33
+ callHook(definition, source, ModelSilent.PRE, mode, silent);
30
34
  operation();
31
- callHook(definition, ModelSilent.POST, silent);
35
+ callHook(definition, source, ModelSilent.POST, mode, silent);
32
36
  }
33
37
  function createOneCommit(definition, source) {
34
38
  const setOperation = source.mutation(`${definition.key}:set`, (state, { payload }) => {
@@ -39,7 +43,7 @@ function createOneCommit(definition, source) {
39
43
  });
40
44
  const patchOperation = source.mutation(`${definition.key}:patch`, (state, { payload, options }) => {
41
45
  if (options?.deep) {
42
- state[definition.key] = defu(payload, state[definition.key]);
46
+ state[definition.key] = merge(payload, state[definition.key]);
43
47
  return;
44
48
  }
45
49
  state[definition.key] = {
@@ -49,13 +53,19 @@ function createOneCommit(definition, source) {
49
53
  });
50
54
  return {
51
55
  set(payload, options) {
52
- wrapOperation(definition, "set", () => setOperation({ payload }), options?.silent);
56
+ wrapOperation(definition, source, ModelOneMode.SET, () => setOperation({ payload }), options?.silent);
53
57
  },
54
58
  reset(options) {
55
- wrapOperation(definition, "reset", () => resetOperation(), options?.silent);
59
+ wrapOperation(definition, source, ModelOneMode.RESET, () => resetOperation(), options?.silent);
56
60
  },
57
61
  patch(payload, options) {
58
- wrapOperation(definition, "patch", () => patchOperation({ payload, options }), options?.silent);
62
+ wrapOperation(
63
+ definition,
64
+ source,
65
+ ModelOneMode.PATCH,
66
+ () => patchOperation({ payload, options }),
67
+ options?.silent
68
+ );
59
69
  }
60
70
  };
61
71
  }
@@ -77,7 +87,7 @@ function createManyListCommit(definition, source) {
77
87
  return item;
78
88
  }
79
89
  if (options?.deep) {
80
- return defu(found, item);
90
+ return merge(found, item);
81
91
  }
82
92
  return {
83
93
  ...item,
@@ -120,19 +130,37 @@ function createManyListCommit(definition, source) {
120
130
  });
121
131
  return {
122
132
  set(payload, options) {
123
- wrapOperation(definition, "set", () => setOperation({ payload }), options?.silent);
133
+ wrapOperation(definition, source, ModelManyMode.SET, () => setOperation({ payload }), options?.silent);
124
134
  },
125
135
  reset(options) {
126
- wrapOperation(definition, "reset", () => resetOperation(), options?.silent);
136
+ wrapOperation(definition, source, ModelManyMode.RESET, () => resetOperation(), options?.silent);
127
137
  },
128
138
  patch(payload, options) {
129
- wrapOperation(definition, "patch", () => patchOperation({ payload, options }), options?.silent);
139
+ wrapOperation(
140
+ definition,
141
+ source,
142
+ ModelManyMode.PATCH,
143
+ () => patchOperation({ payload, options }),
144
+ options?.silent
145
+ );
130
146
  },
131
147
  remove(payload, options) {
132
- wrapOperation(definition, "remove", () => removeOperation({ payload }), options?.silent);
148
+ wrapOperation(
149
+ definition,
150
+ source,
151
+ ModelManyMode.REMOVE,
152
+ () => removeOperation({ payload }),
153
+ options?.silent
154
+ );
133
155
  },
134
156
  add(payload, options) {
135
- wrapOperation(definition, "add", () => addOperation({ payload, options }), options?.silent);
157
+ wrapOperation(
158
+ definition,
159
+ source,
160
+ ModelManyMode.ADD,
161
+ () => addOperation({ payload, options }),
162
+ options?.silent
163
+ );
136
164
  }
137
165
  };
138
166
  }
@@ -145,7 +173,7 @@ function createManyRecordCommit(definition, source) {
145
173
  });
146
174
  const patchOperation = source.mutation(`${definition.key}:patch`, (state, { payload, options }) => {
147
175
  if (options?.deep) {
148
- state[definition.key] = defu(payload, state[definition.key]);
176
+ state[definition.key] = merge(payload, state[definition.key]);
149
177
  return;
150
178
  }
151
179
  state[definition.key] = {
@@ -170,19 +198,31 @@ function createManyRecordCommit(definition, source) {
170
198
  });
171
199
  return {
172
200
  set(payload, options) {
173
- wrapOperation(definition, "set", () => setOperation({ payload }), options?.silent);
201
+ wrapOperation(definition, source, ModelManyMode.SET, () => setOperation({ payload }), options?.silent);
174
202
  },
175
203
  reset(options) {
176
- wrapOperation(definition, "reset", () => resetOperation(), options?.silent);
204
+ wrapOperation(definition, source, ModelManyMode.RESET, () => resetOperation(), options?.silent);
177
205
  },
178
206
  patch(payload, options) {
179
- wrapOperation(definition, "patch", () => patchOperation({ payload, options }), options?.silent);
207
+ wrapOperation(
208
+ definition,
209
+ source,
210
+ ModelManyMode.PATCH,
211
+ () => patchOperation({ payload, options }),
212
+ options?.silent
213
+ );
180
214
  },
181
215
  remove(payload, options) {
182
- wrapOperation(definition, "remove", () => removeOperation({ payload }), options?.silent);
216
+ wrapOperation(
217
+ definition,
218
+ source,
219
+ ModelManyMode.REMOVE,
220
+ () => removeOperation({ payload }),
221
+ options?.silent
222
+ );
183
223
  },
184
224
  add(payload, options) {
185
- wrapOperation(definition, "add", () => addOperation({ payload }), options?.silent);
225
+ wrapOperation(definition, source, ModelManyMode.ADD, () => addOperation({ payload }), options?.silent);
186
226
  }
187
227
  };
188
228
  }
@@ -1,6 +1,5 @@
1
- import { defu } from "defu";
2
1
  import { z } from "zod";
3
- import { isPlainObject, isEmptyRecord } from "./base.js";
2
+ import { isPlainObject, isEmptyRecord, merge } from "./base.js";
4
3
  function resolveShapeFields(shape) {
5
4
  if (!("shape" in shape) || typeof shape.shape !== "object" || !shape.shape) {
6
5
  return void 0;
@@ -183,7 +182,7 @@ export function decorateShape(object) {
183
182
  defaults(overrides) {
184
183
  const zero = resolveZeroValues(object);
185
184
  if (overrides) {
186
- return defu(overrides, zero);
185
+ return merge(overrides, zero);
187
186
  }
188
187
  return zero;
189
188
  }
@@ -1,10 +1,11 @@
1
+ import { snapshot } from "./base.js";
1
2
  import { ViewClone } from "../types/view.js";
2
3
  function resolveClonedValue(definition, value) {
3
4
  if (!definition.options?.clone) {
4
5
  return value;
5
6
  }
6
7
  if (definition.options.clone === ViewClone.DEEP) {
7
- return JSON.parse(JSON.stringify(value));
8
+ return snapshot(value);
8
9
  }
9
10
  if (Array.isArray(value)) {
10
11
  return [...value];
@@ -8,7 +8,7 @@ export { ViewClone } from "./core/types/view.js";
8
8
  export type { ViewDefinitionOptions } from "./core/types/view.js";
9
9
  export { ActionStatus, ActionConcurrent, ActionType, ActionApiMethod } from "./core/types/action.js";
10
10
  export type { ActionCall, ActionApiCall, ActionApiCommitContext, ActionHandlerCall, ActionCallOptions, ActionCallBaseOptions, ActionApiCallOptions, ActionHandlerCallOptions, ActionCallTransformerOptions, ActionCallBindOptions, ActionCallCommitOptions, ActionHandlerOptions, ActionResolvedApi, } from "./core/types/action.js";
11
- export { ActionApiError, ActionHandlerError, ActionCommitError, ActionConcurrentError, isError, toError } from "./core/utils/error.js";
11
+ export { ActionApiError, ActionHandlerError, ActionCommitError, ActionConcurrentError, isError, toError, } from "./core/utils/error.js";
12
12
  export type { ComposeCallback, ComposeCall, ComposeDefinitions, ComposeContext, StoreCompose, } from "./core/types/compose.js";
13
13
  export { useStoreCompose } from "./composables/compose.js";
14
14
  export type { UseStoreCompose } from "./composables/compose.js";
@@ -3,7 +3,14 @@ export { shape } from "./core/layers/shape.js";
3
3
  export { ModelType, ModelManyKind, ModelOneMode, ModelManyMode, ModelSilent } from "./core/types/model.js";
4
4
  export { ViewClone } from "./core/types/view.js";
5
5
  export { ActionStatus, ActionConcurrent, ActionType, ActionApiMethod } from "./core/types/action.js";
6
- export { ActionApiError, ActionHandlerError, ActionCommitError, ActionConcurrentError, isError, toError } from "./core/utils/error.js";
6
+ export {
7
+ ActionApiError,
8
+ ActionHandlerError,
9
+ ActionCommitError,
10
+ ActionConcurrentError,
11
+ isError,
12
+ toError
13
+ } from "./core/utils/error.js";
7
14
  export { useStoreCompose } from "./composables/compose.js";
8
15
  export { useIsolatedActionStatus, useIsolatedActionError, useStoreAction } from "./composables/action.js";
9
16
  export { useStoreModel } from "./composables/model.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diphyx/harlemify",
3
- "version": "6.2.0",
3
+ "version": "6.3.0",
4
4
  "description": "API state management for Nuxt powered by Harlem",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -45,7 +45,8 @@
45
45
  "prepare": "pnpm nuxt prepare && pnpm nuxt prepare playground",
46
46
  "dev": "pnpm nuxt dev playground",
47
47
  "build": "nuxt-module-build build",
48
- "lint": "eslint . --fix",
48
+ "lint": "eslint ./ --fix",
49
+ "format": "prettier ./ --write",
49
50
  "test": "vitest run",
50
51
  "test:e2e": "playwright test"
51
52
  },
@@ -54,9 +55,8 @@
54
55
  },
55
56
  "dependencies": {
56
57
  "@harlem/core": "^3.1.8",
57
- "@nuxt/kit": "^4.4.6",
58
- "consola": "^3.4.2",
59
- "defu": "^6.1.7"
58
+ "@harlem/utilities": "^3.1.8",
59
+ "@nuxt/kit": "^4.4.6"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@nuxt/eslint-config": "^0.6.2",
@@ -68,9 +68,10 @@
68
68
  "@vitest/coverage-v8": "^2.1.9",
69
69
  "eslint": "^9.39.4",
70
70
  "nuxt": "^4.4.6",
71
+ "prettier": "^3.8.3",
71
72
  "typescript": "^5.9.3",
72
73
  "vitest": "^2.1.9",
73
- "vue": "^3.5.34",
74
+ "vue": "^3.5.35",
74
75
  "zod": "^4.4.3"
75
76
  }
76
77
  }