cogsbox-state 0.5.486 → 0.5.488
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 +70 -7
- package/dist/CogsState.d.ts +35 -4
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.js +727 -659
- package/dist/CogsState.js.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +166 -26
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -58,11 +58,26 @@ import { ZodType } from 'zod/v4';
|
|
|
58
58
|
|
|
59
59
|
export type Prettify<T> = T extends any ? { [K in keyof T]: T[K] } : never;
|
|
60
60
|
|
|
61
|
-
export type SyncInfo = {
|
|
62
|
-
timeStamp: number;
|
|
63
|
-
userId: number;
|
|
64
|
-
};
|
|
65
|
-
|
|
61
|
+
export type SyncInfo = {
|
|
62
|
+
timeStamp: number;
|
|
63
|
+
userId: number;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type ValidationFieldSummary = {
|
|
67
|
+
status: ValidationStatus;
|
|
68
|
+
severity: ValidationSeverity;
|
|
69
|
+
hasErrors: boolean;
|
|
70
|
+
hasWarnings: boolean;
|
|
71
|
+
message: string;
|
|
72
|
+
errors: string[];
|
|
73
|
+
warnings: string[];
|
|
74
|
+
allErrors: Array<ValidationError & { path: string[] }>;
|
|
75
|
+
path: string[];
|
|
76
|
+
getData: () => unknown;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
type ValidationSummaryArray = ValidationFieldSummary[];
|
|
80
|
+
|
|
66
81
|
export type FormElementParams<T> = StateObject<T> & {
|
|
67
82
|
$inputProps: {
|
|
68
83
|
ref?: RefObject<any>;
|
|
@@ -193,8 +208,14 @@ export type EndType<
|
|
|
193
208
|
$$derive: <R>(fn: EffectFunction<T, R>) => R;
|
|
194
209
|
$_status: 'fresh' | 'dirty' | 'synced' | 'restored' | 'unknown';
|
|
195
210
|
$getStatus: () => 'fresh' | 'dirty' | 'synced' | 'restored' | 'unknown';
|
|
196
|
-
$showValidationErrors: () => string[];
|
|
197
|
-
$
|
|
211
|
+
$showValidationErrors: () => string[];
|
|
212
|
+
$validationErrors: {
|
|
213
|
+
(): ValidationSummaryArray;
|
|
214
|
+
<K extends Extract<keyof NonNullable<T>, string>>(
|
|
215
|
+
keys: readonly K[]
|
|
216
|
+
): ValidationSummaryArray;
|
|
217
|
+
};
|
|
218
|
+
$setValidation: (ctx: string) => void;
|
|
198
219
|
$removeValidation: (ctx: string) => void;
|
|
199
220
|
$isSelected: boolean;
|
|
200
221
|
$setSelected: (value: boolean) => void;
|
|
@@ -362,7 +383,21 @@ export type StateObject<
|
|
|
362
383
|
: {}) & // Fallback to {} since we intersect EndType below anyway
|
|
363
384
|
EndType<T, TPlugins> & {
|
|
364
385
|
$toggle: NonNullable<T> extends boolean ? () => void : never;
|
|
365
|
-
$validate:
|
|
386
|
+
$validate: {
|
|
387
|
+
(): { success: boolean; data?: T; error?: any };
|
|
388
|
+
<K extends Extract<keyof NonNullable<T>, string>>(
|
|
389
|
+
keys: readonly K[]
|
|
390
|
+
): {
|
|
391
|
+
success: boolean;
|
|
392
|
+
results: Array<{
|
|
393
|
+
key: K;
|
|
394
|
+
path: string[];
|
|
395
|
+
success: boolean;
|
|
396
|
+
data?: unknown;
|
|
397
|
+
error?: any;
|
|
398
|
+
}>;
|
|
399
|
+
};
|
|
400
|
+
};
|
|
366
401
|
$_componentId: string | null;
|
|
367
402
|
$getComponents: () => ComponentsType;
|
|
368
403
|
$_initialState: T;
|
|
@@ -2558,14 +2593,75 @@ function createProxyHandler<
|
|
|
2558
2593
|
setShadowMetadata(stateKey, path, { ...currentMeta, isRaw: true });
|
|
2559
2594
|
effectiveSetState(value, path, { updateType: 'update' });
|
|
2560
2595
|
};
|
|
2561
|
-
}
|
|
2562
|
-
|
|
2563
|
-
if (prop === '$validate') {
|
|
2564
|
-
return () => {
|
|
2565
|
-
const store = getGlobalStore.getState();
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
if (prop === '$validate') {
|
|
2599
|
+
return (keys?: readonly string[]) => {
|
|
2600
|
+
const store = getGlobalStore.getState();
|
|
2601
|
+
|
|
2602
|
+
if (keys) {
|
|
2603
|
+
const results = keys.map((key) => {
|
|
2604
|
+
const targetPath = [...path, key];
|
|
2605
|
+
const targetValue = store.getShadowValue(stateKey, targetPath);
|
|
2606
|
+
const currentMeta =
|
|
2607
|
+
store.getShadowMetadata(stateKey, targetPath) || {};
|
|
2608
|
+
const fieldSchema = currentMeta.typeInfo?.schema;
|
|
2609
|
+
|
|
2610
|
+
if (!fieldSchema) {
|
|
2611
|
+
return {
|
|
2612
|
+
key,
|
|
2613
|
+
path: targetPath,
|
|
2614
|
+
success: true,
|
|
2615
|
+
data: targetValue,
|
|
2616
|
+
};
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
const result = (fieldSchema as any).safeParse(targetValue);
|
|
2620
|
+
const zodErrors =
|
|
2621
|
+
result.error?.issues || result.error?.errors || [];
|
|
2622
|
+
|
|
2623
|
+
store.setShadowMetadata(stateKey, targetPath, {
|
|
2624
|
+
...currentMeta,
|
|
2625
|
+
validation: {
|
|
2626
|
+
status: result.success ? 'VALID' : 'INVALID',
|
|
2627
|
+
errors: result.success
|
|
2628
|
+
? []
|
|
2629
|
+
: [
|
|
2630
|
+
{
|
|
2631
|
+
source: 'client',
|
|
2632
|
+
message:
|
|
2633
|
+
zodErrors[0]?.message || 'Invalid value',
|
|
2634
|
+
severity: 'error',
|
|
2635
|
+
code: zodErrors[0]?.code,
|
|
2636
|
+
},
|
|
2637
|
+
],
|
|
2638
|
+
lastValidated: Date.now(),
|
|
2639
|
+
validatedValue: targetValue,
|
|
2640
|
+
},
|
|
2641
|
+
});
|
|
2642
|
+
store.notifyPathSubscribers([stateKey, ...targetPath].join('.'), {
|
|
2643
|
+
type: 'VALIDATION_UPDATE',
|
|
2644
|
+
});
|
|
2645
|
+
|
|
2646
|
+
return {
|
|
2647
|
+
key,
|
|
2648
|
+
path: targetPath,
|
|
2649
|
+
success: result.success,
|
|
2650
|
+
data: result.success ? result.data : undefined,
|
|
2651
|
+
error: result.success ? undefined : result.error,
|
|
2652
|
+
};
|
|
2653
|
+
});
|
|
2654
|
+
|
|
2655
|
+
notifyComponents(stateKey);
|
|
2656
|
+
|
|
2657
|
+
return {
|
|
2658
|
+
success: results.every((result) => result.success),
|
|
2659
|
+
results,
|
|
2660
|
+
};
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
// 1. Get Data & Schema
|
|
2664
|
+
const { value } = getScopedData(stateKey, path, meta);
|
|
2569
2665
|
const opts = store.getInitialOptions(stateKey);
|
|
2570
2666
|
const schema =
|
|
2571
2667
|
opts?.validation?.zodSchemaV4 || opts?.validation?.zodSchemaV3;
|
|
@@ -2623,11 +2719,11 @@ function createProxyHandler<
|
|
|
2623
2719
|
return result;
|
|
2624
2720
|
};
|
|
2625
2721
|
}
|
|
2626
|
-
if (prop === '$showValidationErrors') {
|
|
2627
|
-
return () => {
|
|
2628
|
-
const { shadowMeta } = getScopedData(stateKey, path, meta);
|
|
2629
|
-
if (
|
|
2630
|
-
shadowMeta?.validation?.status === 'INVALID' &&
|
|
2722
|
+
if (prop === '$showValidationErrors') {
|
|
2723
|
+
return () => {
|
|
2724
|
+
const { shadowMeta } = getScopedData(stateKey, path, meta);
|
|
2725
|
+
if (
|
|
2726
|
+
shadowMeta?.validation?.status === 'INVALID' &&
|
|
2631
2727
|
shadowMeta.validation.errors.length > 0
|
|
2632
2728
|
) {
|
|
2633
2729
|
// Return only error-severity messages (not warnings)
|
|
@@ -2635,11 +2731,55 @@ function createProxyHandler<
|
|
|
2635
2731
|
.filter((err) => err.severity === 'error')
|
|
2636
2732
|
.map((err) => err.message);
|
|
2637
2733
|
}
|
|
2638
|
-
return [];
|
|
2639
|
-
};
|
|
2640
|
-
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2734
|
+
return [];
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
if (prop === '$validationErrors') {
|
|
2738
|
+
return (keys?: readonly string[]) => {
|
|
2739
|
+
const store = getGlobalStore.getState();
|
|
2740
|
+
const summarizePath = (targetPath: string[]) => {
|
|
2741
|
+
const validationState =
|
|
2742
|
+
store.getShadowMetadata(stateKey, targetPath)?.validation;
|
|
2743
|
+
const allErrors = (validationState?.errors || []).map((err) => ({
|
|
2744
|
+
...err,
|
|
2745
|
+
path: targetPath,
|
|
2746
|
+
}));
|
|
2747
|
+
const errors = allErrors.filter((err) => err.severity === 'error');
|
|
2748
|
+
const warnings = allErrors.filter(
|
|
2749
|
+
(err) => err.severity === 'warning'
|
|
2750
|
+
);
|
|
2751
|
+
const severity: ValidationSeverity =
|
|
2752
|
+
errors.length > 0
|
|
2753
|
+
? 'error'
|
|
2754
|
+
: warnings.length > 0
|
|
2755
|
+
? 'warning'
|
|
2756
|
+
: undefined;
|
|
2757
|
+
|
|
2758
|
+
return {
|
|
2759
|
+
status: validationState?.status || 'NOT_VALIDATED',
|
|
2760
|
+
severity,
|
|
2761
|
+
hasErrors: errors.length > 0,
|
|
2762
|
+
hasWarnings: warnings.length > 0,
|
|
2763
|
+
message: errors[0]?.message || warnings[0]?.message || '',
|
|
2764
|
+
errors: errors.map((err) => err.message),
|
|
2765
|
+
warnings: warnings.map((err) => err.message),
|
|
2766
|
+
allErrors,
|
|
2767
|
+
path: targetPath,
|
|
2768
|
+
getData: () => store.getShadowValue(stateKey, targetPath),
|
|
2769
|
+
} satisfies ValidationFieldSummary;
|
|
2770
|
+
};
|
|
2771
|
+
|
|
2772
|
+
const childKeys =
|
|
2773
|
+
keys ??
|
|
2774
|
+
Object.keys(store.getShadowNode(stateKey, path) ?? {}).filter(
|
|
2775
|
+
(key) => key !== '_meta'
|
|
2776
|
+
);
|
|
2777
|
+
|
|
2778
|
+
return childKeys.map((key) => summarizePath([...path, key]));
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
if (prop === '$getSelected') {
|
|
2643
2783
|
return () => {
|
|
2644
2784
|
const arrayKey = [stateKey, ...path].join('.');
|
|
2645
2785
|
registerComponentDependency(stateKey, componentId, [
|