@diphyx/harlemify 0.0.1 → 0.0.2

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 CHANGED
@@ -9,6 +9,7 @@ API state management for Nuxt powered by [Harlem](https://harlemjs.com/)
9
9
  - Zod schema validation with field metadata
10
10
  - Automatic API client with runtime config
11
11
  - CRUD operations with endpoint status tracking
12
+ - Type-safe endpoint URL parameters
12
13
  - SSR support via Harlem SSR plugin
13
14
 
14
15
  ## Installation
@@ -40,19 +41,29 @@ const UserSchema = z.object({
40
41
  indicator: true,
41
42
  }),
42
43
  name: z.string().meta({
43
- actions: [ApiAction.POST, ApiAction.PUT],
44
+ actions: [ApiAction.POST, ApiAction.PATCH],
44
45
  }),
45
46
  });
46
47
 
48
+ export type User = z.infer<typeof UserSchema>;
49
+
47
50
  export const userStore = createStore("user", UserSchema, {
48
51
  [Endpoint.GET_UNITS]: {
49
52
  action: ApiAction.GET,
50
53
  url: "/users",
51
54
  },
52
- [Endpoint.POST_UNIT]: {
55
+ [Endpoint.POST_UNITS]: {
53
56
  action: ApiAction.POST,
54
57
  url: "/users",
55
58
  },
59
+ [Endpoint.PATCH_UNITS]: {
60
+ action: ApiAction.PATCH,
61
+ url: (params) => `/users/${params.id}`,
62
+ },
63
+ [Endpoint.DELETE_UNITS]: {
64
+ action: ApiAction.DELETE,
65
+ url: (params) => `/users/${params.id}`,
66
+ },
56
67
  });
57
68
  ```
58
69
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0 || >=4.0.0"
6
6
  },
7
- "version": "0.0.1",
7
+ "version": "0.0.2",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "unknown"
@@ -1,12 +1,16 @@
1
1
  import { z } from "zod";
2
2
  import { type Extension, type BaseState } from "@harlem/core";
3
3
  import { Endpoint, type EndpointDefinition, type EndpointMemory } from "../utils/endpoint.js";
4
+ export declare enum StoreMemoryPosition {
5
+ FIRST = "first",
6
+ LAST = "last"
7
+ }
4
8
  import { ApiAction, type ApiActionOptions, type ApiOptions } from "./api.js";
5
- export declare function createStore<T extends z.ZodRawShape>(name: string, schema: z.ZodObject<T>, endpoints?: Partial<Record<Endpoint, EndpointDefinition>>, options?: {
9
+ export declare function createStore<T extends z.ZodRawShape, K extends keyof z.infer<z.ZodObject<T>> = "id" & keyof z.infer<z.ZodObject<T>>>(name: string, schema: z.ZodObject<T>, endpoints?: Partial<Record<Endpoint, EndpointDefinition<Partial<z.infer<z.ZodObject<T>>>>>>, options?: {
6
10
  api?: ApiOptions;
7
11
  extensions?: Extension<BaseState>[];
8
12
  }): {
9
- api: {
13
+ api: () => {
10
14
  get: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery>(url: string, options?: ApiActionOptions<ApiAction.GET, H, Q, never>) => Promise<T_1>;
11
15
  post: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery, B extends import("./api").ApiRequestBody = import("./api").ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.POST, H, Q, B>) => Promise<T_1>;
12
16
  put: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery, B extends import("./api").ApiRequestBody = import("./api").ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.PUT, H, Q, B>) => Promise<T_1>;
@@ -22,9 +26,7 @@ export declare function createStore<T extends z.ZodRawShape>(name: string, schem
22
26
  }>, never>;
23
27
  memorizedUnit: import("@vue/reactivity").ComputedRef<import("@vue/reactivity").DeepReadonly<z.core.$InferObjectOutput<T, {}>> | null>;
24
28
  memorizedUnits: import("@vue/reactivity").ComputedRef<readonly import("@vue/reactivity").DeepReadonly<z.core.$InferObjectOutput<T, {}>>[]>;
25
- hasMemorizedUnits: (...units: ({
26
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
27
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => Record<keyof z.core.$InferObjectOutput<T, {}>, boolean>;
29
+ hasMemorizedUnits: (...units: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => Record<string | number, boolean>;
28
30
  endpointsStatus: {
29
31
  getUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
30
32
  getUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
@@ -69,57 +71,36 @@ export declare function createStore<T extends z.ZodRawShape>(name: string, schem
69
71
  };
70
72
  setMemorizedUnit: import("@harlem/core").Mutation<z.core.$InferObjectOutput<T, {}> | null, void>;
71
73
  setMemorizedUnits: (payload: z.core.$InferObjectOutput<T, {}>[]) => void;
72
- editMemorizedUnit: import("@harlem/core").Mutation<{
73
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
74
- } & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
75
- editMemorizedUnits: (payload: ({
76
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
77
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
78
- dropMemorizedUnit: import("@harlem/core").Mutation<{
79
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
80
- } & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
81
- dropMemorizedUnits: (payload: ({
82
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
83
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
74
+ editMemorizedUnit: import("@harlem/core").Mutation<Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
75
+ editMemorizedUnits: (payload: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
76
+ dropMemorizedUnit: import("@harlem/core").Mutation<Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
77
+ dropMemorizedUnits: (payload: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
84
78
  patchEndpointMemory: (payload: {
85
79
  key: Endpoint;
86
80
  memory: EndpointMemory;
87
81
  }) => void;
88
82
  purgeEndpointMemory: (payload?: unknown) => void;
89
- getUnit: (unit: {
90
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
91
- } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.GET>, "body">) => Promise<z.core.$InferObjectOutput<T, {}>>;
83
+ getUnit: (unit?: Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.GET>, "body">) => Promise<z.core.$InferObjectOutput<T, {}>>;
92
84
  getUnits: (options?: Omit<ApiActionOptions<ApiAction.GET>, "body">) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
93
- postUnit: (unit: z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.POST> & {
85
+ postUnit: (unit: Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.POST> & {
94
86
  validate?: boolean;
95
- }) => Promise<z.core.$InferObjectOutput<T, {}>>;
96
- postUnits: (units: z.core.$InferObjectOutput<T, {}>[], options?: ApiActionOptions<ApiAction.POST> & {
87
+ }) => Promise<Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>>;
88
+ postUnits: (units: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>)[], options?: ApiActionOptions<ApiAction.POST> & {
97
89
  validate?: boolean;
98
- }) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
99
- putUnit: (unit: z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.PUT> & {
90
+ position?: StoreMemoryPosition;
91
+ }) => Promise<(Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>)[]>;
92
+ putUnit: (unit: Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.PUT> & {
100
93
  validate?: boolean;
101
- }) => Promise<z.core.$InferObjectOutput<T, {}>>;
102
- putUnits: (units: z.core.$InferObjectOutput<T, {}>[], options?: ApiActionOptions<ApiAction.PUT> & {
94
+ }) => Promise<Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>>;
95
+ putUnits: (units: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>)[], options?: ApiActionOptions<ApiAction.PUT> & {
103
96
  validate?: boolean;
104
- }) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
105
- patchUnit: (unit: {
106
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
107
- } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: ApiActionOptions<ApiAction.PATCH> & {
97
+ }) => Promise<(Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & z.core.$InferObjectOutput<T, {}>)[]>;
98
+ patchUnit: (unit: Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>, options?: ApiActionOptions<ApiAction.PATCH> & {
108
99
  validate?: boolean;
109
- }) => Promise<{
110
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
111
- } & Partial<z.core.$InferObjectOutput<T, {}>>>;
112
- patchUnits: (units: ({
113
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
114
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: ApiActionOptions<ApiAction.PATCH> & {
100
+ }) => Promise<Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>>;
101
+ patchUnits: (units: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: ApiActionOptions<ApiAction.PATCH> & {
115
102
  validate?: boolean;
116
- }) => Promise<({
117
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
118
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[]>;
119
- deleteUnit: (unit: {
120
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
121
- } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
122
- deleteUnits: (units: ({
123
- [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
124
- } & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
103
+ }) => Promise<(Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[]>;
104
+ deleteUnit: (unit: Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
105
+ deleteUnits: (units: (Required<Pick<z.core.$InferObjectOutput<T, {}>, K>> & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
125
106
  };
@@ -11,16 +11,27 @@ import {
11
11
  Endpoint,
12
12
  EndpointStatus
13
13
  } from "../utils/endpoint.js";
14
+ export var StoreMemoryPosition = /* @__PURE__ */ ((StoreMemoryPosition2) => {
15
+ StoreMemoryPosition2["FIRST"] = "first";
16
+ StoreMemoryPosition2["LAST"] = "last";
17
+ return StoreMemoryPosition2;
18
+ })(StoreMemoryPosition || {});
14
19
  import {
15
20
  createApi
16
21
  } from "./api.js";
17
22
  export function createStore(name, schema, endpoints, options) {
18
- const config = useRuntimeConfig();
19
- const api = createApi({
20
- ...config.public.harlemify.api,
21
- ...options?.api
22
- });
23
23
  const { indicator } = resolveSchema(schema);
24
+ let apiClient;
25
+ function api() {
26
+ if (!apiClient) {
27
+ const config = useRuntimeConfig();
28
+ apiClient = createApi({
29
+ ...config.public.harlemify?.api,
30
+ ...options?.api
31
+ });
32
+ }
33
+ return apiClient;
34
+ }
24
35
  const store = createHarlemStore(
25
36
  name,
26
37
  {
@@ -144,10 +155,10 @@ export function createStore(name, schema, endpoints, options) {
144
155
  status: EndpointStatus.PENDING
145
156
  });
146
157
  try {
147
- const resolvedUrl = resolveEndpointUrl(endpoint.url, {
148
- [indicator]: unit[indicator]
149
- });
150
- const response = await api.get(resolvedUrl, options2);
158
+ const response = await api().get(
159
+ resolveEndpointUrl(endpoint, unit),
160
+ options2
161
+ );
151
162
  setMemorizedUnit(response);
152
163
  patchEndpointMemoryTo(Endpoint.GET_UNIT, {
153
164
  status: EndpointStatus.SUCCESS
@@ -166,8 +177,10 @@ export function createStore(name, schema, endpoints, options) {
166
177
  status: EndpointStatus.PENDING
167
178
  });
168
179
  try {
169
- const resolvedUrl = resolveEndpointUrl(endpoint.url);
170
- const response = await api.get(resolvedUrl, options2);
180
+ const response = await api().get(
181
+ resolveEndpointUrl(endpoint),
182
+ options2
183
+ );
171
184
  setMemorizedUnits(response);
172
185
  patchEndpointMemoryTo(Endpoint.GET_UNITS, {
173
186
  status: EndpointStatus.SUCCESS
@@ -190,14 +203,17 @@ export function createStore(name, schema, endpoints, options) {
190
203
  status: EndpointStatus.PENDING
191
204
  });
192
205
  try {
193
- const resolvedUrl = resolveEndpointUrl(endpoint.url, {
194
- [indicator]: unit[indicator]
195
- });
196
- const response = await api.post(resolvedUrl, {
197
- ...options2,
198
- body: options2?.body ?? resolvedSchema.values
206
+ const response = await api().post(
207
+ resolveEndpointUrl(endpoint, unit),
208
+ {
209
+ ...options2,
210
+ body: options2?.body ?? resolvedSchema.values
211
+ }
212
+ );
213
+ setMemorizedUnit({
214
+ ...unit,
215
+ ...response
199
216
  });
200
- setMemorizedUnit(response);
201
217
  patchEndpointMemoryTo(Endpoint.POST_UNIT, {
202
218
  status: EndpointStatus.SUCCESS
203
219
  });
@@ -211,30 +227,46 @@ export function createStore(name, schema, endpoints, options) {
211
227
  }
212
228
  async function postUnits(units, options2) {
213
229
  const endpoint = getEndpoint(endpoints, Endpoint.POST_UNITS);
214
- const body = units.map((unit) => {
215
- const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
216
- if (options2?.validate) {
217
- schema.pick(resolvedSchema.keys).parse(unit);
218
- }
219
- return resolvedSchema.values;
220
- });
221
230
  patchEndpointMemoryTo(Endpoint.POST_UNITS, {
222
231
  status: EndpointStatus.PENDING
223
232
  });
224
233
  try {
225
- const resolvedUrl = resolveEndpointUrl(endpoint.url);
226
- const response = await api.post(resolvedUrl, {
227
- ...options2,
228
- body: options2?.body ?? body
229
- });
230
- setMemorizedUnits([
231
- ...memorizedUnits.value,
232
- ...response
233
- ]);
234
+ const responses = [];
235
+ for (const unit of units) {
236
+ const resolvedSchema = resolveSchema(
237
+ schema,
238
+ endpoint.action,
239
+ unit
240
+ );
241
+ if (options2?.validate) {
242
+ schema.pick(resolvedSchema.keys).parse(unit);
243
+ }
244
+ const response = await api().post(
245
+ resolveEndpointUrl(endpoint, unit),
246
+ {
247
+ ...options2,
248
+ body: options2?.body ?? resolvedSchema.values
249
+ }
250
+ );
251
+ const clonedUnits = [...memorizedUnits.value];
252
+ if (options2?.position === "last" /* LAST */) {
253
+ clonedUnits.push({
254
+ ...unit,
255
+ ...response
256
+ });
257
+ } else {
258
+ clonedUnits.unshift({
259
+ ...unit,
260
+ ...response
261
+ });
262
+ }
263
+ setMemorizedUnits(clonedUnits);
264
+ responses.push(response);
265
+ }
234
266
  patchEndpointMemoryTo(Endpoint.POST_UNITS, {
235
267
  status: EndpointStatus.SUCCESS
236
268
  });
237
- return response;
269
+ return responses;
238
270
  } catch (error) {
239
271
  patchEndpointMemoryTo(Endpoint.POST_UNITS, {
240
272
  status: EndpointStatus.FAILED
@@ -252,14 +284,17 @@ export function createStore(name, schema, endpoints, options) {
252
284
  status: EndpointStatus.PENDING
253
285
  });
254
286
  try {
255
- const resolvedUrl = resolveEndpointUrl(endpoint.url, {
256
- [indicator]: unit[indicator]
257
- });
258
- const response = await api.put(resolvedUrl, {
259
- ...options2,
260
- body: options2?.body ?? resolvedSchema.values
287
+ const response = await api().put(
288
+ resolveEndpointUrl(endpoint, unit),
289
+ {
290
+ ...options2,
291
+ body: options2?.body ?? resolvedSchema.values
292
+ }
293
+ );
294
+ setMemorizedUnit({
295
+ ...unit,
296
+ ...response
261
297
  });
262
- setMemorizedUnit(response);
263
298
  patchEndpointMemoryTo(Endpoint.PUT_UNIT, {
264
299
  status: EndpointStatus.SUCCESS
265
300
  });
@@ -273,27 +308,39 @@ export function createStore(name, schema, endpoints, options) {
273
308
  }
274
309
  async function putUnits(units, options2) {
275
310
  const endpoint = getEndpoint(endpoints, Endpoint.PUT_UNITS);
276
- const body = units.map((unit) => {
277
- const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
278
- if (options2?.validate) {
279
- schema.pick(resolvedSchema.keys).parse(unit);
280
- }
281
- return resolvedSchema.values;
282
- });
283
311
  patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
284
312
  status: EndpointStatus.PENDING
285
313
  });
286
314
  try {
287
- const resolvedUrl = resolveEndpointUrl(endpoint.url);
288
- const response = await api.put(resolvedUrl, {
289
- ...options2,
290
- body: options2?.body ?? body
291
- });
292
- setMemorizedUnits(response);
315
+ const responses = [];
316
+ for (const unit of units) {
317
+ const resolvedSchema = resolveSchema(
318
+ schema,
319
+ endpoint.action,
320
+ unit
321
+ );
322
+ if (options2?.validate) {
323
+ schema.pick(resolvedSchema.keys).parse(unit);
324
+ }
325
+ const response = await api().put(
326
+ resolveEndpointUrl(endpoint, unit),
327
+ {
328
+ ...options2,
329
+ body: options2?.body ?? resolvedSchema.values
330
+ }
331
+ );
332
+ editMemorizedUnits([
333
+ {
334
+ ...unit,
335
+ ...response
336
+ }
337
+ ]);
338
+ responses.push(response);
339
+ }
293
340
  patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
294
341
  status: EndpointStatus.SUCCESS
295
342
  });
296
- return response;
343
+ return responses;
297
344
  } catch (error) {
298
345
  patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
299
346
  status: EndpointStatus.FAILED
@@ -311,17 +358,14 @@ export function createStore(name, schema, endpoints, options) {
311
358
  status: EndpointStatus.PENDING
312
359
  });
313
360
  try {
314
- const resolvedUrl = resolveEndpointUrl(endpoint.url, {
315
- [indicator]: unit[indicator]
361
+ const response = await api().patch(resolveEndpointUrl(endpoint, unit), {
362
+ ...options2,
363
+ body: options2?.body ?? resolvedSchema.values
364
+ });
365
+ editMemorizedUnit({
366
+ ...unit,
367
+ ...response
316
368
  });
317
- const response = await api.patch(
318
- resolvedUrl,
319
- {
320
- ...options2,
321
- body: options2?.body ?? resolvedSchema.values
322
- }
323
- );
324
- editMemorizedUnit(response);
325
369
  patchEndpointMemoryTo(Endpoint.PATCH_UNIT, {
326
370
  status: EndpointStatus.SUCCESS
327
371
  });
@@ -335,27 +379,36 @@ export function createStore(name, schema, endpoints, options) {
335
379
  }
336
380
  async function patchUnits(units, options2) {
337
381
  const endpoint = getEndpoint(endpoints, Endpoint.PATCH_UNITS);
338
- const body = units.map((unit) => {
339
- const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
340
- if (options2?.validate) {
341
- schema.pick(resolvedSchema.keys).partial().parse(unit);
342
- }
343
- return resolvedSchema.values;
344
- });
345
382
  patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
346
383
  status: EndpointStatus.PENDING
347
384
  });
348
385
  try {
349
- const resolvedUrl = resolveEndpointUrl(endpoint.url);
350
- const response = await api.patch(resolvedUrl, {
351
- ...options2,
352
- body: options2?.body ?? body
353
- });
354
- editMemorizedUnits(response);
386
+ const responses = [];
387
+ for (const unit of units) {
388
+ const resolvedSchema = resolveSchema(
389
+ schema,
390
+ endpoint.action,
391
+ unit
392
+ );
393
+ if (options2?.validate) {
394
+ schema.pick(resolvedSchema.keys).partial().parse(unit);
395
+ }
396
+ const response = await api().patch(resolveEndpointUrl(endpoint, unit), {
397
+ ...options2,
398
+ body: options2?.body ?? resolvedSchema.values
399
+ });
400
+ editMemorizedUnits([
401
+ {
402
+ ...unit,
403
+ ...response
404
+ }
405
+ ]);
406
+ responses.push(response);
407
+ }
355
408
  patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
356
409
  status: EndpointStatus.SUCCESS
357
410
  });
358
- return response;
411
+ return responses;
359
412
  } catch (error) {
360
413
  patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
361
414
  status: EndpointStatus.FAILED
@@ -369,11 +422,8 @@ export function createStore(name, schema, endpoints, options) {
369
422
  status: EndpointStatus.PENDING
370
423
  });
371
424
  try {
372
- const resolvedUrl = resolveEndpointUrl(endpoint.url, {
373
- [indicator]: unit[indicator]
374
- });
375
- await api.del(
376
- resolvedUrl,
425
+ await api().del(
426
+ resolveEndpointUrl(endpoint, unit),
377
427
  options2
378
428
  );
379
429
  dropMemorizedUnit(unit);
@@ -394,12 +444,13 @@ export function createStore(name, schema, endpoints, options) {
394
444
  status: EndpointStatus.PENDING
395
445
  });
396
446
  try {
397
- const resolvedUrl = resolveEndpointUrl(endpoint.url);
398
- await api.del(
399
- resolvedUrl,
400
- options2
401
- );
402
- dropMemorizedUnits(units);
447
+ for (const unit of units) {
448
+ await api().del(
449
+ resolveEndpointUrl(endpoint, unit),
450
+ options2
451
+ );
452
+ dropMemorizedUnits([unit]);
453
+ }
403
454
  patchEndpointMemoryTo(Endpoint.DELETE_UNITS, {
404
455
  status: EndpointStatus.SUCCESS
405
456
  });
@@ -2,4 +2,4 @@ export { z } from "zod";
2
2
  export { ApiAction, ApiResponseType, ApiErrorSource, type ApiRequestHeader, type ApiRequestQuery, type ApiRequestBody, type ApiRequestOptions, type ApiOptions, type ApiActionOptions, type ApiErrorOptions, createApi, ApiError, ApiRequestError, ApiResponseError, } from "./core/api.js";
3
3
  export { Endpoint, EndpointStatus, type EndpointDefinition, type EndpointMemory, } from "./utils/endpoint.js";
4
4
  export { type SchemaMeta, getMeta, resolveSchema } from "./utils/schema.js";
5
- export { createStore } from "./core/store.js";
5
+ export { createStore, StoreMemoryPosition } from "./core/store.js";
@@ -13,4 +13,4 @@ export {
13
13
  EndpointStatus
14
14
  } from "./utils/endpoint.js";
15
15
  export { getMeta, resolveSchema } from "./utils/schema.js";
16
- export { createStore } from "./core/store.js";
16
+ export { createStore, StoreMemoryPosition } from "./core/store.js";
@@ -1,20 +1,26 @@
1
1
  import { createVuePlugin } from "@harlem/core";
2
2
  import {
3
+ createServerSSRPlugin,
3
4
  createClientSSRPlugin,
4
- createServerSSRPlugin
5
+ getBridgingScript
5
6
  } from "@harlem/plugin-ssr";
6
7
  export default defineNuxtPlugin((nuxtApp) => {
7
8
  const plugins = [];
8
- if (nuxtApp.payload.serverRendered) {
9
- if (import.meta.server) {
10
- plugins.push(createServerSSRPlugin());
11
- }
12
- if (import.meta.client) {
13
- plugins.push(createClientSSRPlugin());
14
- }
9
+ if (import.meta.server) {
10
+ plugins.push(createServerSSRPlugin());
11
+ }
12
+ if (import.meta.client) {
13
+ plugins.push(createClientSSRPlugin());
15
14
  }
16
15
  const harlem = createVuePlugin({
17
16
  plugins
18
17
  });
19
18
  nuxtApp.vueApp.use(harlem);
19
+ useHead({
20
+ script: [
21
+ {
22
+ innerHTML: getBridgingScript()
23
+ }
24
+ ]
25
+ });
20
26
  });
@@ -18,16 +18,18 @@ export declare enum EndpointStatus {
18
18
  SUCCESS = "success",
19
19
  FAILED = "failed"
20
20
  }
21
- export interface EndpointDefinition {
21
+ export interface EndpointDefinition<T = Record<string, unknown>> {
22
22
  action: ApiAction;
23
- url: string | ((keys: Record<PropertyKey, unknown>) => string);
23
+ url: string | ((params: T) => string);
24
24
  }
25
25
  export interface EndpointMemory {
26
26
  status: EndpointStatus;
27
27
  }
28
28
  export declare function makeEndpointStatusKey<K extends Endpoint, S extends EndpointStatus>(key: K, status: S): `${K}Is${Capitalize<S>}`;
29
- export declare function getEndpoint(endpoints: Partial<Record<Endpoint, EndpointDefinition>> | undefined, key: Endpoint): EndpointDefinition;
30
- export declare function resolveEndpointUrl<T extends Record<PropertyKey, unknown>>(url: string | ((parameters: T) => string), parameters?: T): string;
29
+ export declare function getEndpoint<T = Record<string, unknown>>(endpoints: Partial<Record<Endpoint, EndpointDefinition<T>>> | undefined, key: Endpoint): EndpointDefinition<T>;
30
+ export declare function resolveEndpointUrl<T>(endpoint: EndpointDefinition<T>, params?: {
31
+ [key: string]: unknown;
32
+ }): string;
31
33
  export declare function makeEndpointsStatus<T>(getter: (name: string, fn: (state: BaseState) => boolean) => T): {
32
34
  getUnitIsIdle: T;
33
35
  getUnitIsPending: T;
@@ -28,11 +28,11 @@ export function getEndpoint(endpoints, key) {
28
28
  }
29
29
  return endpoint;
30
30
  }
31
- export function resolveEndpointUrl(url, parameters = {}) {
32
- if (typeof url === "function") {
33
- return url(parameters);
31
+ export function resolveEndpointUrl(endpoint, params) {
32
+ if (typeof endpoint.url === "function") {
33
+ return endpoint.url(params);
34
34
  }
35
- return url;
35
+ return endpoint.url;
36
36
  }
37
37
  export function makeEndpointsStatus(getter) {
38
38
  const output = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diphyx/harlemify",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "API state management for Nuxt powered by Harlem",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -37,14 +37,13 @@
37
37
  "dist"
38
38
  ],
39
39
  "dependencies": {
40
- "@nuxt/kit": "^3.14.0",
41
40
  "@harlem/core": "^3.0.0",
42
41
  "@harlem/plugin-ssr": "^3.0.0",
42
+ "@nuxt/kit": "^3.14.0",
43
43
  "defu": "^6.0.0",
44
44
  "zod": "^4.0.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@nuxt/devtools": "^1.6.0",
48
47
  "@nuxt/eslint-config": "^0.6.0",
49
48
  "@nuxt/module-builder": "^0.8.0",
50
49
  "@nuxt/schema": "^3.14.0",
@@ -56,9 +55,9 @@
56
55
  "vitest": "^2.0.0"
57
56
  },
58
57
  "scripts": {
59
- "postinstall": "nuxi prepare playground",
58
+ "cleanup": "pnpm nuxt cleanup && pnpm nuxt cleanup playground",
59
+ "dev": "pnpm nuxt dev playground",
60
60
  "build": "nuxt-module-build build",
61
- "dev": "nuxi dev playground",
62
61
  "lint": "eslint . --fix",
63
62
  "test": "vitest run"
64
63
  }