cogsbox-state 0.5.471 → 0.5.473

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 (46) hide show
  1. package/README.md +2 -5
  2. package/dist/CogsState.d.ts +105 -79
  3. package/dist/CogsState.d.ts.map +1 -1
  4. package/dist/CogsState.jsx +1082 -987
  5. package/dist/CogsState.jsx.map +1 -1
  6. package/dist/Components.d.ts.map +1 -1
  7. package/dist/Components.jsx +293 -243
  8. package/dist/Components.jsx.map +1 -1
  9. package/dist/PluginRunner.d.ts +10 -0
  10. package/dist/PluginRunner.d.ts.map +1 -0
  11. package/dist/PluginRunner.jsx +128 -0
  12. package/dist/PluginRunner.jsx.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +33 -26
  16. package/dist/index.js.map +1 -1
  17. package/dist/pluginStore.d.ts +43 -0
  18. package/dist/pluginStore.d.ts.map +1 -0
  19. package/dist/pluginStore.js +52 -0
  20. package/dist/pluginStore.js.map +1 -0
  21. package/dist/plugins.d.ts +1326 -0
  22. package/dist/plugins.d.ts.map +1 -0
  23. package/dist/plugins.js +76 -0
  24. package/dist/plugins.js.map +1 -0
  25. package/dist/store.d.ts +69 -26
  26. package/dist/store.d.ts.map +1 -1
  27. package/dist/store.js +436 -152
  28. package/dist/store.js.map +1 -1
  29. package/dist/utility.d.ts +1 -1
  30. package/dist/utility.d.ts.map +1 -1
  31. package/dist/utility.js +12 -12
  32. package/dist/utility.js.map +1 -1
  33. package/dist/validation.d.ts +7 -0
  34. package/dist/validation.d.ts.map +1 -0
  35. package/dist/validation.js +39 -0
  36. package/dist/validation.js.map +1 -0
  37. package/package.json +18 -13
  38. package/src/CogsState.tsx +719 -458
  39. package/src/Components.tsx +304 -180
  40. package/src/PluginRunner.tsx +208 -0
  41. package/src/index.ts +2 -0
  42. package/src/pluginStore.ts +159 -0
  43. package/src/plugins.ts +548 -0
  44. package/src/store.ts +881 -189
  45. package/src/utility.ts +31 -31
  46. package/src/validation.ts +84 -0
package/src/plugins.ts ADDED
@@ -0,0 +1,548 @@
1
+ import { z } from 'zod';
2
+ import type React from 'react';
3
+ import { StateObject, UpdateTypeDetail } from './CogsState';
4
+ import { getGlobalStore } from './store';
5
+
6
+ type Prettify<T> = { [K in keyof T]: T[K] } & {};
7
+
8
+ export type KeyedTypes<TMap extends Record<string, any>> = {
9
+ __key: 'keyed';
10
+ map: { [K in keyof TMap]: TMap[K] };
11
+ };
12
+
13
+ export const keyedSchema = <TMap extends Record<string, any>>() =>
14
+ z.object({
15
+ __key: z.literal('keyed'),
16
+ map: z.any(),
17
+ }) as z.ZodType<KeyedTypes<TMap>>;
18
+
19
+ // Helpers: turn a zod object shape into its inferred value shape
20
+ type InferZodObject<T extends Record<string, z.ZodTypeAny>> = {
21
+ [K in keyof T]: z.infer<T[K]>;
22
+ };
23
+ export type InferPerKeyValueMap<
24
+ TMap extends Record<string, Record<string, z.ZodTypeAny>>,
25
+ > = {
26
+ [K in keyof TMap]: InferZodObject<TMap[K]>;
27
+ };
28
+
29
+ // Deconstructed cogs methods (no TState)
30
+ type DeconstructedCogsMethods<TStateSlice = any> = {
31
+ initialiseState: (data: TStateSlice) => void;
32
+ initialiseShadowState: (data: any) => void;
33
+ applyOperation: (patch: any, meta?: { dontUpdate?: boolean }) => void;
34
+ addZodErrors: (errors: any[]) => void;
35
+ getState: () => TStateSlice;
36
+ setOptions: (options: any) => void;
37
+ };
38
+
39
+ export function toDeconstructedMethods(stateHandler: StateObject<any>) {
40
+ return {
41
+ initialiseState: (data: any) => {
42
+ stateHandler.$update(data);
43
+ },
44
+ initialiseShadowState: (data: any) => {
45
+ stateHandler.$initializeAndMergeShadowState(data);
46
+ },
47
+ applyOperation: (patch: any, meta?: { dontUpdate?: boolean }) =>
48
+ stateHandler.$applyOperation(patch, meta),
49
+ addZodErrors: (errors: any[]) => stateHandler.$addZodValidation(errors),
50
+ getState: () => stateHandler.$get(),
51
+ setOptions: (opts: any) => {
52
+ stateHandler.$setOptions(opts);
53
+ },
54
+ };
55
+ }
56
+
57
+ // Simplified: All params use the same TFieldMetaData type
58
+ export type UseHookParams<
59
+ TOptions,
60
+ TPluginMetaData,
61
+ TFieldMetaData,
62
+ TStateSlice = any,
63
+ > = DeconstructedCogsMethods<TStateSlice> & {
64
+ stateKey: string;
65
+
66
+ getPluginMetaData: () => TPluginMetaData | undefined;
67
+ setPluginMetaData: (data: Partial<TPluginMetaData>) => void;
68
+ removePluginMetaData: () => void;
69
+
70
+ getFieldMetaData: (path: string[]) => TFieldMetaData | undefined;
71
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) => void;
72
+ removeFieldMetaData: (path: string[]) => void;
73
+
74
+ options: TOptions;
75
+ pluginName: string;
76
+ isInitialMount: boolean;
77
+ };
78
+
79
+ export type TransformStateParams<
80
+ TOptions,
81
+ THookReturn,
82
+ TPluginMetaData,
83
+ TFieldMetaData,
84
+ TStateSlice = any,
85
+ > = DeconstructedCogsMethods<TStateSlice> & {
86
+ stateKey: string;
87
+
88
+ getPluginMetaData: () => TPluginMetaData | undefined;
89
+ setPluginMetaData: (data: Partial<TPluginMetaData>) => void;
90
+ removePluginMetaData: () => void;
91
+
92
+ getFieldMetaData: (path: string[]) => TFieldMetaData | undefined;
93
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) => void;
94
+ removeFieldMetaData: (path: string[]) => void;
95
+
96
+ options: TOptions;
97
+ hookData?: THookReturn;
98
+ previousState?: TStateSlice;
99
+ isInitialTransform: boolean;
100
+ pluginName: string;
101
+ };
102
+
103
+ export type OnUpdateParams<
104
+ TOptions,
105
+ THookReturn,
106
+ TPluginMetaData,
107
+ TFieldMetaData,
108
+ TStateSlice = any,
109
+ > = DeconstructedCogsMethods<TStateSlice> & {
110
+ stateKey: string;
111
+
112
+ getPluginMetaData: () => TPluginMetaData | undefined;
113
+ setPluginMetaData: (data: Partial<TPluginMetaData>) => void;
114
+ removePluginMetaData: () => void;
115
+
116
+ getFieldMetaData: (path: string[]) => TFieldMetaData | undefined;
117
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) => void;
118
+ removeFieldMetaData: (path: string[]) => void;
119
+
120
+ update: UpdateTypeDetail;
121
+ path?: string[];
122
+
123
+ options: TOptions;
124
+ hookData?: THookReturn;
125
+
126
+ previousValue?: any;
127
+ nextValue?: any;
128
+ updateSource?: 'user' | 'plugin' | 'system';
129
+
130
+ pluginName: string;
131
+ };
132
+
133
+ export type OnFormUpdateParams<
134
+ TOptions,
135
+ THookReturn,
136
+ TPluginMetaData,
137
+ TFieldMetaData,
138
+ TStateSlice = any,
139
+ > = DeconstructedCogsMethods<TStateSlice> & {
140
+ stateKey: string;
141
+
142
+ getPluginMetaData: () => TPluginMetaData | undefined;
143
+ setPluginMetaData: (data: Partial<TPluginMetaData>) => void;
144
+ removePluginMetaData: () => void;
145
+
146
+ getFieldMetaData: (path: string[]) => TFieldMetaData | undefined;
147
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) => void;
148
+ removeFieldMetaData: (path: string[]) => void;
149
+
150
+ path: string[];
151
+ event: {
152
+ type: 'focus' | 'blur' | 'input';
153
+ value?: any;
154
+ path: string[];
155
+ };
156
+
157
+ options: TOptions;
158
+ hookData?: THookReturn;
159
+
160
+ formState?: 'pristine' | 'dirty' | 'submitting' | 'submitted';
161
+ pluginName: string;
162
+ };
163
+
164
+ export type FormWrapperParams<
165
+ TOptions,
166
+ THookReturn,
167
+ TPluginMetaData,
168
+ TFieldMetaData,
169
+ TStateSlice = any,
170
+ > = {
171
+ element: React.ReactNode;
172
+ path: string[];
173
+ stateKey: string;
174
+ options: TOptions;
175
+ hookData?: THookReturn;
176
+ fieldType?: string;
177
+ wrapperDepth?: number;
178
+
179
+ // Deconstructed methods
180
+ initialiseState: (data: TStateSlice) => void;
181
+ initialiseShadowState: (data: any) => void;
182
+ applyOperation: (patch: any, meta?: { dontUpdate?: boolean }) => void;
183
+ addZodErrors: (errors: any[]) => void;
184
+ getState: () => TStateSlice;
185
+ setOptions: (options: any) => void;
186
+
187
+ getPluginMetaData: () => TPluginMetaData | undefined;
188
+ setPluginMetaData: (data: Partial<TPluginMetaData>) => void;
189
+ removePluginMetaData: () => void;
190
+
191
+ getFieldMetaData: (path: string[]) => TFieldMetaData | undefined;
192
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) => void;
193
+ removeFieldMetaData: (path: string[]) => void;
194
+
195
+ pluginName: string;
196
+ };
197
+
198
+ // Unified plugin definition
199
+ export type CogsPlugin<
200
+ TName extends string,
201
+ TOptions,
202
+ THookReturn,
203
+ TPluginMetaData,
204
+ TFieldMetaData,
205
+ > = {
206
+ name: TName;
207
+
208
+ useHook?: (
209
+ params: UseHookParams<TOptions, TPluginMetaData, TFieldMetaData, any>
210
+ ) => THookReturn;
211
+
212
+ transformState?: (
213
+ params: TransformStateParams<
214
+ TOptions,
215
+ THookReturn,
216
+ TPluginMetaData,
217
+ TFieldMetaData,
218
+ any
219
+ >
220
+ ) => void;
221
+
222
+ onUpdate?: (
223
+ params: OnUpdateParams<
224
+ TOptions,
225
+ THookReturn,
226
+ TPluginMetaData,
227
+ TFieldMetaData,
228
+ any
229
+ >
230
+ ) => void;
231
+
232
+ onFormUpdate?: (
233
+ params: OnFormUpdateParams<
234
+ TOptions,
235
+ THookReturn,
236
+ TPluginMetaData,
237
+ TFieldMetaData,
238
+ any
239
+ >
240
+ ) => void;
241
+
242
+ formWrapper?: (
243
+ params: FormWrapperParams<
244
+ TOptions,
245
+ THookReturn,
246
+ TPluginMetaData,
247
+ TFieldMetaData,
248
+ any
249
+ >
250
+ ) => React.ReactNode;
251
+ };
252
+
253
+ // Extract plugin options helper
254
+ export type ExtractPluginOptions<
255
+ TPlugins extends readonly CogsPlugin<any, any, any, any, any>[],
256
+ > = {
257
+ [P in TPlugins[number] as P['name']]?: P extends CogsPlugin<
258
+ any,
259
+ infer O,
260
+ any,
261
+ any,
262
+ any
263
+ >
264
+ ? O
265
+ : never;
266
+ };
267
+
268
+ // Metadata helpers
269
+ export function createMetadataContext<TPluginMetaData, TFieldMetaData>(
270
+ stateKey: string,
271
+ pluginName: string
272
+ ) {
273
+ return {
274
+ getPluginMetaData: (): TPluginMetaData | undefined =>
275
+ getGlobalStore
276
+ .getState()
277
+ .getPluginMetaDataMap(stateKey, [])
278
+ ?.get(pluginName) as TPluginMetaData | undefined,
279
+
280
+ setPluginMetaData: (data: Partial<TPluginMetaData>) =>
281
+ getGlobalStore
282
+ .getState()
283
+ .setPluginMetaData(stateKey, [], pluginName, data),
284
+
285
+ removePluginMetaData: () =>
286
+ getGlobalStore.getState().removePluginMetaData(stateKey, [], pluginName),
287
+
288
+ getFieldMetaData: (path: string[]): TFieldMetaData | undefined =>
289
+ getGlobalStore
290
+ .getState()
291
+ .getPluginMetaDataMap(stateKey, path)
292
+ ?.get(pluginName) as TFieldMetaData | undefined,
293
+
294
+ setFieldMetaData: (path: string[], data: Partial<TFieldMetaData>) =>
295
+ getGlobalStore
296
+ .getState()
297
+ .setPluginMetaData(stateKey, path, pluginName, data),
298
+
299
+ removeFieldMetaData: (path: string[]) =>
300
+ getGlobalStore
301
+ .getState()
302
+ .removePluginMetaData(stateKey, path, pluginName),
303
+ };
304
+ }
305
+
306
+ type ZodObjOutput<T extends z.ZodObject<any>> = {
307
+ [K in keyof T['shape']]: z.output<T['shape'][K]>;
308
+ };
309
+ type OutputOf<T extends z.ZodTypeAny> =
310
+ T extends z.ZodObject<any> ? Prettify<ZodObjOutput<T>> : z.output<T>;
311
+
312
+ export function createPluginContext<
313
+ O extends z.ZodTypeAny,
314
+ PM extends z.ZodTypeAny | undefined = undefined,
315
+ FM extends z.ZodTypeAny | undefined = undefined,
316
+ >(schemas: { options: O; pluginMetaData?: PM; fieldMetaData?: FM }) {
317
+ // Crucial: compute from the generic params, not from an object-indexed optional type
318
+ type Options = OutputOf<O>;
319
+ type PluginMetaData = PM extends z.ZodTypeAny ? OutputOf<PM> : unknown;
320
+ type FieldMetaData = FM extends z.ZodTypeAny ? OutputOf<FM> : unknown;
321
+
322
+ function createPlugin<TName extends string>(name: TName) {
323
+ type TransformFn<THookReturn> = (
324
+ params: TransformStateParams<
325
+ Options,
326
+ THookReturn,
327
+ PluginMetaData,
328
+ FieldMetaData
329
+ >
330
+ ) => void;
331
+
332
+ type UpdateFn<THookReturn> = (
333
+ params: OnUpdateParams<
334
+ Options,
335
+ THookReturn,
336
+ PluginMetaData,
337
+ FieldMetaData
338
+ >
339
+ ) => void;
340
+
341
+ type FormUpdateFn<THookReturn> = (
342
+ params: OnFormUpdateParams<
343
+ Options,
344
+ THookReturn,
345
+ PluginMetaData,
346
+ FieldMetaData
347
+ >
348
+ ) => void;
349
+
350
+ type FormWrapperFn<THookReturn> = (
351
+ params: FormWrapperParams<
352
+ Options,
353
+ THookReturn,
354
+ PluginMetaData,
355
+ FieldMetaData
356
+ >
357
+ ) => React.ReactNode;
358
+
359
+ type Plugin<THookReturn> = Prettify<
360
+ CogsPlugin<TName, Options, THookReturn, PluginMetaData, FieldMetaData>
361
+ >;
362
+
363
+ const createPluginObject = <THookReturn = never>(
364
+ hookFn?: (
365
+ params: UseHookParams<Options, PluginMetaData, FieldMetaData>
366
+ ) => THookReturn,
367
+ transformFn?: TransformFn<THookReturn>,
368
+ updateHandler?: UpdateFn<THookReturn>,
369
+ formUpdateHandler?: FormUpdateFn<THookReturn>,
370
+ formWrapper?: FormWrapperFn<THookReturn>
371
+ ): Plugin<THookReturn> => {
372
+ return {
373
+ name,
374
+ useHook: hookFn as any,
375
+ transformState: transformFn as any,
376
+ onUpdate: updateHandler as any,
377
+ onFormUpdate: formUpdateHandler as any,
378
+ formWrapper: formWrapper as any,
379
+ };
380
+ };
381
+
382
+ type BuildRet<
383
+ THookReturn,
384
+ HasTransform extends boolean,
385
+ HasUpdate extends boolean,
386
+ HasFormUpdate extends boolean,
387
+ HasWrapper extends boolean,
388
+ > = Plugin<THookReturn> &
389
+ (HasTransform extends true
390
+ ? {}
391
+ : {
392
+ transformState(
393
+ fn: TransformFn<THookReturn>
394
+ ): BuildRet<
395
+ THookReturn,
396
+ true,
397
+ HasUpdate,
398
+ HasFormUpdate,
399
+ HasWrapper
400
+ >;
401
+ }) &
402
+ (HasUpdate extends true
403
+ ? {}
404
+ : {
405
+ onUpdate(
406
+ fn: UpdateFn<THookReturn>
407
+ ): BuildRet<
408
+ THookReturn,
409
+ HasTransform,
410
+ true,
411
+ HasFormUpdate,
412
+ HasWrapper
413
+ >;
414
+ }) &
415
+ (HasFormUpdate extends true
416
+ ? {}
417
+ : {
418
+ onFormUpdate(
419
+ fn: FormUpdateFn<THookReturn>
420
+ ): BuildRet<THookReturn, HasTransform, HasUpdate, true, HasWrapper>;
421
+ }) &
422
+ (HasWrapper extends true
423
+ ? {}
424
+ : {
425
+ formWrapper(
426
+ fn: FormWrapperFn<THookReturn>
427
+ ): BuildRet<
428
+ THookReturn,
429
+ HasTransform,
430
+ HasUpdate,
431
+ HasFormUpdate,
432
+ true
433
+ >;
434
+ });
435
+
436
+ function createBuilder<
437
+ THookReturn = never,
438
+ HasTransform extends boolean = false,
439
+ HasUpdate extends boolean = false,
440
+ HasFormUpdate extends boolean = false,
441
+ HasWrapper extends boolean = false,
442
+ >(
443
+ hookFn?: (
444
+ params: UseHookParams<Options, PluginMetaData, FieldMetaData>
445
+ ) => THookReturn,
446
+ transformFn?: TransformFn<THookReturn>,
447
+ updateHandler?: UpdateFn<THookReturn>,
448
+ formUpdateHandler?: FormUpdateFn<THookReturn>,
449
+ formWrapper?: FormWrapperFn<THookReturn>
450
+ ): BuildRet<
451
+ THookReturn,
452
+ HasTransform,
453
+ HasUpdate,
454
+ HasFormUpdate,
455
+ HasWrapper
456
+ > {
457
+ const plugin = createPluginObject<THookReturn>(
458
+ hookFn,
459
+ transformFn,
460
+ updateHandler,
461
+ formUpdateHandler,
462
+ formWrapper
463
+ );
464
+
465
+ const methods = {} as Partial<
466
+ BuildRet<
467
+ THookReturn,
468
+ HasTransform,
469
+ HasUpdate,
470
+ HasFormUpdate,
471
+ HasWrapper
472
+ >
473
+ >;
474
+
475
+ if (!transformFn) {
476
+ (methods as any).transformState = (fn: TransformFn<THookReturn>) =>
477
+ createBuilder<
478
+ THookReturn,
479
+ true,
480
+ HasUpdate,
481
+ HasFormUpdate,
482
+ HasWrapper
483
+ >(hookFn, fn, updateHandler, formUpdateHandler, formWrapper);
484
+ }
485
+ if (!updateHandler) {
486
+ (methods as any).onUpdate = (fn: UpdateFn<THookReturn>) =>
487
+ createBuilder<
488
+ THookReturn,
489
+ HasTransform,
490
+ true,
491
+ HasFormUpdate,
492
+ HasWrapper
493
+ >(hookFn, transformFn, fn, formUpdateHandler, formWrapper);
494
+ }
495
+ if (!formUpdateHandler) {
496
+ (methods as any).onFormUpdate = (fn: FormUpdateFn<THookReturn>) =>
497
+ createBuilder<THookReturn, HasTransform, HasUpdate, true, HasWrapper>(
498
+ hookFn,
499
+ transformFn,
500
+ updateHandler,
501
+ fn,
502
+ formWrapper
503
+ );
504
+ }
505
+ if (!formWrapper) {
506
+ (methods as any).formWrapper = (fn: FormWrapperFn<THookReturn>) =>
507
+ createBuilder<
508
+ THookReturn,
509
+ HasTransform,
510
+ HasUpdate,
511
+ HasFormUpdate,
512
+ true
513
+ >(hookFn, transformFn, updateHandler, formUpdateHandler, fn);
514
+ }
515
+
516
+ return Object.assign(plugin, methods) as BuildRet<
517
+ THookReturn,
518
+ HasTransform,
519
+ HasUpdate,
520
+ HasFormUpdate,
521
+ HasWrapper
522
+ >;
523
+ }
524
+
525
+ const start = Object.assign(
526
+ createBuilder<never, false, false, false, false>(),
527
+ {
528
+ useHook<THookReturn>(
529
+ hookFn: (
530
+ params: UseHookParams<Options, PluginMetaData, FieldMetaData>
531
+ ) => THookReturn
532
+ ) {
533
+ return createBuilder<THookReturn, false, false, false, false>(hookFn);
534
+ },
535
+ }
536
+ ) as BuildRet<never, false, false, false, false> & {
537
+ useHook<THookReturn>(
538
+ hookFn: (
539
+ params: UseHookParams<Options, PluginMetaData, FieldMetaData>
540
+ ) => THookReturn
541
+ ): BuildRet<THookReturn, false, false, false, false>;
542
+ };
543
+
544
+ return start;
545
+ }
546
+
547
+ return { createPlugin };
548
+ }