@diphyx/harlemify 3.0.0 → 4.0.1

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 (59) hide show
  1. package/README.md +51 -32
  2. package/dist/module.d.mts +24 -13
  3. package/dist/module.d.ts +24 -13
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +8 -10
  6. package/dist/runtime/composables/action.d.ts +4 -0
  7. package/dist/runtime/composables/action.js +8 -0
  8. package/dist/runtime/config.d.ts +10 -0
  9. package/dist/runtime/config.js +7 -0
  10. package/dist/runtime/core/layers/action.d.ts +4 -0
  11. package/dist/runtime/core/layers/action.js +102 -0
  12. package/dist/runtime/core/layers/model.d.ts +3 -0
  13. package/dist/runtime/core/layers/model.js +31 -0
  14. package/dist/runtime/core/layers/shape.d.ts +45 -0
  15. package/dist/runtime/core/layers/shape.js +56 -0
  16. package/dist/runtime/core/layers/view.d.ts +4 -0
  17. package/dist/runtime/core/layers/view.js +21 -0
  18. package/dist/runtime/core/store.d.ts +20 -66
  19. package/dist/runtime/core/store.js +46 -574
  20. package/dist/runtime/core/types/action.d.ts +163 -0
  21. package/dist/runtime/core/types/action.js +39 -0
  22. package/dist/runtime/core/types/model.d.ts +70 -0
  23. package/dist/runtime/core/types/model.js +5 -0
  24. package/dist/runtime/core/types/shape.d.ts +46 -0
  25. package/dist/runtime/core/types/shape.js +0 -0
  26. package/dist/runtime/core/types/view.d.ts +29 -0
  27. package/dist/runtime/core/types/view.js +0 -0
  28. package/dist/runtime/core/utils/action.d.ts +4 -0
  29. package/dist/runtime/core/utils/action.js +294 -0
  30. package/dist/runtime/core/utils/model.d.ts +12 -0
  31. package/dist/runtime/core/utils/model.js +227 -0
  32. package/dist/runtime/core/utils/shape.d.ts +3 -0
  33. package/dist/runtime/core/utils/shape.js +29 -0
  34. package/dist/runtime/core/utils/view.d.ts +5 -0
  35. package/dist/runtime/core/utils/view.js +19 -0
  36. package/dist/runtime/index.d.ts +8 -16
  37. package/dist/runtime/index.js +11 -7
  38. package/dist/runtime/plugin.js +2 -5
  39. package/package.json +2 -1
  40. package/dist/runtime/composables/use.d.ts +0 -22
  41. package/dist/runtime/composables/use.js +0 -14
  42. package/dist/runtime/core/api.d.ts +0 -37
  43. package/dist/runtime/core/api.js +0 -56
  44. package/dist/runtime/shared.d.ts +0 -9
  45. package/dist/runtime/shared.js +0 -3
  46. package/dist/runtime/utils/adapter.d.ts +0 -24
  47. package/dist/runtime/utils/adapter.js +0 -35
  48. package/dist/runtime/utils/cache.d.ts +0 -10
  49. package/dist/runtime/utils/cache.js +0 -26
  50. package/dist/runtime/utils/endpoint.d.ts +0 -38
  51. package/dist/runtime/utils/endpoint.js +0 -56
  52. package/dist/runtime/utils/errors.d.ts +0 -22
  53. package/dist/runtime/utils/errors.js +0 -33
  54. package/dist/runtime/utils/memory.d.ts +0 -40
  55. package/dist/runtime/utils/memory.js +0 -87
  56. package/dist/runtime/utils/schema.d.ts +0 -23
  57. package/dist/runtime/utils/schema.js +0 -58
  58. package/dist/runtime/utils/transform.d.ts +0 -6
  59. package/dist/runtime/utils/transform.js +0 -22
@@ -1,581 +1,53 @@
1
- import { defu } from "defu";
2
- import { createStore as createHarlemStore } from "@harlem/core";
3
- import { createApi } from "./api.js";
4
- import { sharedConfig } from "../shared.js";
5
- import { createCache } from "../utils/cache.js";
6
- import { defineApiAdapter } from "../utils/adapter.js";
7
- import { pluralize } from "../utils/transform.js";
8
- import { resolveSchema } from "../utils/schema.js";
9
- import { EndpointMethod, EndpointStatus, resolveEndpointUrl } from "../utils/endpoint.js";
10
- function getDefaultMutation(method, target) {
11
- const defaults = {
12
- [EndpointMethod.GET]: {
13
- unit: "set",
14
- units: "set"
15
- },
16
- [EndpointMethod.POST]: {
17
- unit: "set",
18
- units: "add"
19
- },
20
- [EndpointMethod.PUT]: {
21
- unit: "set",
22
- units: "edit"
23
- },
24
- [EndpointMethod.PATCH]: {
25
- unit: "edit",
26
- units: "edit"
27
- },
28
- [EndpointMethod.DELETE]: {
29
- unit: "drop",
30
- units: "drop"
31
- }
32
- };
33
- return defaults[method][target];
1
+ import { createConsola } from "consola";
2
+ import { createStore as createSourceStore } from "@harlem/core";
3
+ import { runtimeConfig } from "../config.js";
4
+ import { createModelFactory } from "./layers/model.js";
5
+ import { createViewFactory } from "./layers/view.js";
6
+ import { createActionFactory } from "./layers/action.js";
7
+ import { initializeState, createMutations, createCommitter } from "./utils/model.js";
8
+ import { createView } from "./utils/view.js";
9
+ import { createAction } from "./utils/action.js";
10
+ import {
11
+ DEFINITION
12
+ } from "./types/action.js";
13
+ function createStoreModel(mutations) {
14
+ return createCommitter(mutations);
34
15
  }
35
- function setNestedValue(object, path, value) {
36
- if (path.length === 0) {
37
- return;
38
- }
39
- let current = object;
40
- for (let index = 0; index < path.length - 1; index++) {
41
- if (current[path[index]] === void 0) {
42
- current[path[index]] = {};
43
- }
44
- current = current[path[index]];
45
- }
46
- current[path[path.length - 1]] = value;
16
+ function createStoreView(source, viewDefinitions) {
17
+ return createView(source, viewDefinitions);
47
18
  }
48
- function editNestedValue(object, path, value, deep) {
49
- if (path.length === 0) {
50
- return;
51
- }
52
- let current = object;
53
- for (let index = 0; index < path.length - 1; index++) {
54
- if (current[path[index]] === void 0) {
55
- return;
56
- }
57
- current = current[path[index]];
19
+ function createStoreAction(actionDefinitions, view, mutations) {
20
+ const actions = {};
21
+ for (const [key, chain] of Object.entries(actionDefinitions)) {
22
+ actions[key] = createAction(chain[DEFINITION], mutations, view, key);
58
23
  }
59
- const key = path[path.length - 1];
60
- if (current[key] === void 0) {
61
- current[key] = value;
62
- return;
63
- }
64
- if (deep) {
65
- current[key] = defu(value, current[key]);
66
- return;
67
- }
68
- Object.assign(current[key], value);
24
+ return actions;
69
25
  }
70
- export function createStore(entity, schema, actions, options) {
71
- const resolvedSchema = resolveSchema(schema, {
72
- indicator: options?.indicator
73
- });
74
- const indicator = resolvedSchema.indicator;
75
- const indexCache = createCache();
76
- const schemaCache = createCache();
77
- for (const actionName in actions) {
78
- const actionSchema = resolveSchema(schema, {
79
- indicator,
80
- action: actionName
81
- });
82
- schemaCache.set(actionName, {
83
- keys: actionSchema.keys,
84
- fields: Object.keys(actionSchema.keys)
85
- });
86
- }
87
- let apiClient;
88
- function api() {
89
- if (!apiClient) {
90
- apiClient = createApi({
91
- headers: sharedConfig.api?.headers,
92
- query: sharedConfig.api?.query,
93
- adapter: options?.adapter ?? defineApiAdapter(sharedConfig.api?.adapter)
94
- });
95
- }
96
- return apiClient;
97
- }
98
- const state = {
99
- memory: {
100
- unit: null,
101
- units: []
102
- },
103
- status: {}
104
- };
105
- for (const actionName in actions) {
106
- state.status[actionName] = EndpointStatus.IDLE;
107
- }
108
- const store = createHarlemStore(entity, state, {
109
- extensions: options?.extensions ?? []
110
- });
111
- const alias = {
112
- unit: entity,
113
- units: pluralize(entity)
114
- };
115
- const memorizedUnit = store.getter("memorizedUnit", (state2) => {
116
- return state2.memory.unit;
117
- });
118
- const memorizedUnits = store.getter("memorizedUnits", (state2) => {
119
- return state2.memory.units;
120
- });
121
- const setMemorizedUnit = store.mutation("setMemorizedUnit", (state2, unit = null) => {
122
- state2.memory.unit = unit;
123
- });
124
- const setMemorizedUnits = store.mutation("setMemorizedUnits", (state2, units = []) => {
125
- state2.memory.units = units;
126
- indexCache.clear();
127
- if (units && Array.isArray(units)) {
128
- for (let index = 0; index < units.length; index++) {
129
- if (units[index]) {
130
- indexCache.set(units[index][indicator], index);
131
- }
132
- }
133
- }
134
- });
135
- const editMemorizedUnit = store.mutation(
136
- "editMemorizedUnit",
137
- (state2, payload) => {
138
- if (state2.memory.unit?.[indicator] !== payload.unit[indicator]) {
139
- return;
140
- }
141
- if (payload.deep) {
142
- state2.memory.unit = defu(payload.unit, state2.memory.unit);
143
- return;
144
- }
145
- Object.assign(state2.memory.unit, payload.unit);
146
- }
147
- );
148
- const editMemorizedUnits = store.mutation(
149
- "editMemorizedUnits",
150
- (state2, payload) => {
151
- const tempIndex = /* @__PURE__ */ new Map();
152
- for (let index = 0; index < state2.memory.units.length; index++) {
153
- tempIndex.set(state2.memory.units[index][indicator], index);
154
- }
155
- for (const unit of payload.units) {
156
- let unitIndex = indexCache.get(unit[indicator]);
157
- if (unitIndex === void 0 || unitIndex >= state2.memory.units.length || state2.memory.units[unitIndex]?.[indicator] !== unit[indicator]) {
158
- const foundIndex = tempIndex.get(unit[indicator]);
159
- if (foundIndex !== void 0) {
160
- unitIndex = foundIndex;
161
- indexCache.set(unit[indicator], foundIndex);
162
- } else {
163
- unitIndex = void 0;
164
- }
165
- }
166
- if (unitIndex === void 0) {
167
- continue;
168
- }
169
- if (payload.deep) {
170
- state2.memory.units[unitIndex] = defu(unit, state2.memory.units[unitIndex]);
171
- continue;
172
- }
173
- Object.assign(state2.memory.units[unitIndex], unit);
174
- }
175
- }
176
- );
177
- const dropMemorizedUnit = store.mutation("dropMemorizedUnit", (state2, unit) => {
178
- if (state2.memory.unit?.[indicator] === unit[indicator]) {
179
- state2.memory.unit = null;
180
- }
181
- });
182
- const dropMemorizedUnits = store.mutation(
183
- "dropMemorizedUnits",
184
- (state2, units) => {
185
- const dropSet = new Set(
186
- units.map((unit) => {
187
- return unit[indicator];
188
- })
189
- );
190
- for (const unit of units) {
191
- indexCache.delete(unit[indicator]);
192
- }
193
- state2.memory.units = state2.memory.units.filter((memorizedUnit2) => {
194
- return !dropSet.has(memorizedUnit2[indicator]);
195
- });
196
- }
197
- );
198
- const addMemorizedUnits = store.mutation(
199
- "addMemorizedUnits",
200
- (state2, payload) => {
201
- if (payload.prepend) {
202
- indexCache.clear();
203
- for (let index = 0; index < payload.units.length; index++) {
204
- indexCache.set(payload.units[index][indicator], index);
205
- }
206
- for (let index = 0; index < state2.memory.units.length; index++) {
207
- indexCache.set(state2.memory.units[index][indicator], index + payload.units.length);
208
- }
209
- state2.memory.units = [...payload.units, ...state2.memory.units];
210
- return;
211
- }
212
- for (let index = 0; index < payload.units.length; index++) {
213
- indexCache.set(payload.units[index][indicator], state2.memory.units.length + index);
214
- }
215
- state2.memory.units = [...state2.memory.units, ...payload.units];
216
- }
217
- );
218
- const setNestedUnit = store.mutation("setNestedUnit", (state2, payload) => {
219
- if (!state2.memory.unit) {
220
- return;
221
- }
222
- setNestedValue(state2.memory.unit, payload.path, payload.value);
223
- });
224
- const editNestedUnit = store.mutation(
225
- "editNestedUnit",
226
- (state2, payload) => {
227
- if (!state2.memory.unit) {
228
- return;
229
- }
230
- editNestedValue(state2.memory.unit, payload.path, payload.value, payload.deep);
231
- }
232
- );
233
- const dropNestedUnit = store.mutation("dropNestedUnit", (state2, payload) => {
234
- if (!state2.memory.unit || payload.path.length === 0) {
235
- return;
236
- }
237
- setNestedValue(state2.memory.unit, payload.path, null);
238
- });
239
- const patchStatus = store.mutation(
240
- "patchStatus",
241
- (state2, payload) => {
242
- state2.status[payload.action] = payload.status;
243
- }
244
- );
245
- function createActionStatus(actionName) {
246
- const current = store.getter(
247
- `${actionName}:current`,
248
- (state2) => state2.status[actionName] ?? EndpointStatus.IDLE
249
- );
250
- const pending = store.getter(
251
- `${actionName}:pending`,
252
- (state2) => state2.status[actionName] === EndpointStatus.PENDING
253
- );
254
- const success = store.getter(
255
- `${actionName}:success`,
256
- (state2) => state2.status[actionName] === EndpointStatus.SUCCESS
257
- );
258
- const failed = store.getter(
259
- `${actionName}:failed`,
260
- (state2) => state2.status[actionName] === EndpointStatus.FAILED
261
- );
262
- const idle = store.getter(
263
- `${actionName}:idle`,
264
- (state2) => state2.status[actionName] === EndpointStatus.IDLE
265
- );
266
- return {
267
- current() {
268
- return current.value;
269
- },
270
- pending() {
271
- return pending.value;
272
- },
273
- success() {
274
- return success.value;
275
- },
276
- failed() {
277
- return failed.value;
278
- },
279
- idle() {
280
- return idle.value;
281
- }
282
- };
283
- }
284
- const monitor = {};
285
- for (const actionName in actions) {
286
- monitor[actionName] = createActionStatus(actionName);
287
- }
288
- async function withStatus(actionName, operation) {
289
- await options?.hooks?.before?.();
290
- if (store.state.status[actionName] === EndpointStatus.PENDING) {
291
- throw new Error(`Action "${actionName}" is already pending`);
292
- }
293
- patchStatus({
294
- action: actionName,
295
- status: EndpointStatus.PENDING
296
- });
297
- try {
298
- const result = await operation();
299
- patchStatus({
300
- action: actionName,
301
- status: EndpointStatus.SUCCESS
302
- });
303
- await options?.hooks?.after?.();
304
- return result;
305
- } catch (error) {
306
- patchStatus({
307
- action: actionName,
308
- status: EndpointStatus.FAILED
309
- });
310
- await options?.hooks?.after?.(error);
311
- throw error;
312
- }
313
- }
314
- function applyMemoryOperation(memoryDefinition, method, response, params) {
315
- if (!memoryDefinition) {
316
- return;
317
- }
318
- const mutation = memoryDefinition.mutation ?? getDefaultMutation(method, memoryDefinition.on);
319
- if (memoryDefinition.on === "unit") {
320
- if (memoryDefinition.path.length > 0) {
321
- switch (mutation) {
322
- case "set": {
323
- setNestedUnit({
324
- path: memoryDefinition.path,
325
- value: response
326
- });
327
- break;
328
- }
329
- case "edit": {
330
- editNestedUnit({
331
- path: memoryDefinition.path,
332
- value: response,
333
- deep: memoryDefinition.deep
334
- });
335
- break;
336
- }
337
- case "drop": {
338
- dropNestedUnit({
339
- path: memoryDefinition.path
340
- });
341
- break;
342
- }
343
- }
344
- return;
345
- }
346
- switch (mutation) {
347
- case "set": {
348
- setMemorizedUnit(response);
349
- break;
350
- }
351
- case "edit": {
352
- const editData = {
353
- ...params,
354
- ...response
355
- };
356
- editMemorizedUnit({
357
- unit: editData,
358
- deep: memoryDefinition.deep
359
- });
360
- editMemorizedUnits({
361
- units: [editData],
362
- deep: memoryDefinition.deep
363
- });
364
- break;
365
- }
366
- case "drop": {
367
- dropMemorizedUnit(params);
368
- break;
369
- }
370
- }
371
- return;
372
- }
373
- if (Array.isArray(response)) {
374
- switch (mutation) {
375
- case "set": {
376
- setMemorizedUnits(response);
377
- break;
378
- }
379
- case "edit": {
380
- editMemorizedUnits({
381
- units: response.map((item) => {
382
- return {
383
- ...params,
384
- ...item
385
- };
386
- }),
387
- deep: memoryDefinition.deep
388
- });
389
- break;
390
- }
391
- case "drop": {
392
- if (params) {
393
- dropMemorizedUnits([params]);
394
- break;
395
- }
396
- dropMemorizedUnits(response);
397
- break;
398
- }
399
- case "add": {
400
- addMemorizedUnits({
401
- units: response,
402
- prepend: memoryDefinition.prepend
403
- });
404
- break;
405
- }
406
- }
407
- return;
408
- }
409
- switch (mutation) {
410
- case "set": {
411
- setMemorizedUnits([response]);
412
- break;
413
- }
414
- case "edit": {
415
- editMemorizedUnits({
416
- units: [
417
- {
418
- ...params,
419
- ...response
420
- }
421
- ],
422
- deep: memoryDefinition.deep
423
- });
424
- break;
425
- }
426
- case "drop": {
427
- if (params) {
428
- dropMemorizedUnits([params]);
429
- break;
430
- }
431
- dropMemorizedUnits([response]);
432
- break;
433
- }
434
- case "add": {
435
- addMemorizedUnits({
436
- units: [response],
437
- prepend: memoryDefinition.prepend
438
- });
439
- break;
440
- }
441
- }
442
- }
443
- function resolveRequestBody(actionName, params, actionOptions) {
444
- if (actionOptions?.body) {
445
- return actionOptions.body;
446
- }
447
- const cached = schemaCache.get(actionName);
448
- if (cached && cached.fields.length > 0 && params) {
449
- return cached.fields.reduce((accumulator, key) => {
450
- if (key in params) {
451
- accumulator[key] = params[key];
452
- }
453
- return accumulator;
454
- }, {});
455
- }
456
- return params;
457
- }
458
- function validateRequestBody(actionName, params, partial) {
459
- const cached = schemaCache.get(actionName);
460
- if (!cached || cached.fields.length === 0) {
461
- return;
462
- }
463
- if (partial) {
464
- schema.pick(cached.keys).partial().parse(params);
465
- return;
466
- }
467
- schema.pick(cached.keys).parse(params);
468
- }
469
- function createActionFunction(actionName, actionDefinition) {
470
- return async (params, actionOptions) => {
471
- return withStatus(actionName, async () => {
472
- const url = resolveEndpointUrl(actionDefinition.endpoint, params);
473
- const body = resolveRequestBody(actionName, params, actionOptions);
474
- const adapter = actionOptions?.adapter ?? actionDefinition.endpoint.adapter;
475
- const baseOptions = {
476
- query: actionOptions?.query,
477
- headers: actionOptions?.headers,
478
- signal: actionOptions?.signal,
479
- ...adapter && { adapter }
480
- };
481
- let response;
482
- switch (actionDefinition.endpoint.method) {
483
- case EndpointMethod.GET: {
484
- response = await api().get(url, baseOptions);
485
- break;
486
- }
487
- case EndpointMethod.POST: {
488
- if (actionOptions?.validate) {
489
- validateRequestBody(actionName, params);
490
- }
491
- response = await api().post(url, {
492
- ...baseOptions,
493
- body
494
- });
495
- break;
496
- }
497
- case EndpointMethod.PUT: {
498
- if (actionOptions?.validate) {
499
- validateRequestBody(actionName, params);
500
- }
501
- response = await api().put(url, {
502
- ...baseOptions,
503
- body
504
- });
505
- break;
506
- }
507
- case EndpointMethod.PATCH: {
508
- if (actionOptions?.validate) {
509
- validateRequestBody(actionName, params, true);
510
- }
511
- response = await api().patch(url, {
512
- ...baseOptions,
513
- body
514
- });
515
- break;
516
- }
517
- case EndpointMethod.DELETE: {
518
- await api().del(url, baseOptions);
519
- response = true;
520
- break;
521
- }
522
- }
523
- applyMemoryOperation(actionDefinition.memory, actionDefinition.endpoint.method, response, params);
524
- return response;
525
- });
526
- };
527
- }
528
- const storeActions = {};
529
- for (const actionName in actions) {
530
- storeActions[actionName] = createActionFunction(actionName, actions[actionName]);
531
- }
532
- const memory = {
533
- set(data) {
534
- if (Array.isArray(data)) {
535
- setMemorizedUnits(data);
536
- return;
537
- }
538
- setMemorizedUnit(data);
539
- },
540
- edit(data, editOptions) {
541
- if (Array.isArray(data)) {
542
- editMemorizedUnit({
543
- unit: data[0],
544
- deep: editOptions?.deep
545
- });
546
- editMemorizedUnits({
547
- units: data,
548
- deep: editOptions?.deep
549
- });
550
- return;
551
- }
552
- editMemorizedUnit({
553
- unit: data,
554
- deep: editOptions?.deep
555
- });
556
- editMemorizedUnits({
557
- units: [data],
558
- deep: editOptions?.deep
559
- });
560
- },
561
- drop(data) {
562
- if (Array.isArray(data)) {
563
- dropMemorizedUnit(data[0]);
564
- dropMemorizedUnits(data);
565
- return;
566
- }
567
- dropMemorizedUnit(data);
568
- dropMemorizedUnits([data]);
569
- }
570
- };
26
+ export function createStore(config) {
27
+ const logger = createConsola({
28
+ level: runtimeConfig.logger,
29
+ defaults: {
30
+ tag: `harlemify:${config.name}`
31
+ }
32
+ });
33
+ const modelFactory = createModelFactory(runtimeConfig.model, logger);
34
+ const viewFactory = createViewFactory(runtimeConfig.view, logger);
35
+ const actionFactory = createActionFactory(runtimeConfig.action, logger);
36
+ logger.info("Creating store");
37
+ const modelDefinitions = config.model(modelFactory);
38
+ const viewDefinitions = config.view(viewFactory);
39
+ const actionDefinitions = config.action(actionFactory);
40
+ logger.debug("Initializing store");
41
+ const state = initializeState(modelDefinitions);
42
+ const source = createSourceStore(config.name, state);
43
+ const mutations = createMutations(source, modelDefinitions);
44
+ const model = createStoreModel(mutations);
45
+ const view = createStoreView(source, viewDefinitions);
46
+ const action = createStoreAction(actionDefinitions, view, mutations);
47
+ logger.info("Store created");
571
48
  return {
572
- store,
573
- alias,
574
- indicator,
575
- unit: memorizedUnit,
576
- units: memorizedUnits,
577
- action: storeActions,
578
- memory,
579
- monitor
49
+ model,
50
+ view,
51
+ action
580
52
  };
581
53
  }