cogsbox-state 0.5.458 → 0.5.460
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/CogsState.d.ts +29 -15
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.jsx +1218 -1221
- package/dist/CogsState.jsx.map +1 -1
- package/dist/TRPCValidationLink.d.ts.map +1 -1
- package/dist/TRPCValidationLink.js.map +1 -1
- package/dist/store.d.ts +0 -4
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +78 -133
- package/dist/store.js.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +138 -237
- package/src/TRPCValidationLink.ts +1 -0
- package/src/store.ts +0 -93
package/src/CogsState.tsx
CHANGED
|
@@ -251,7 +251,8 @@ export type ValidationError = {
|
|
|
251
251
|
};
|
|
252
252
|
type EffectFunction<T, R> = (state: T, deps: any[]) => R;
|
|
253
253
|
export type EndType<T, IsArrayElement = false> = {
|
|
254
|
-
|
|
254
|
+
addZodValidation: (errors: ValidationError[]) => void;
|
|
255
|
+
clearZodValidation: (paths?: string[]) => void;
|
|
255
256
|
applyJsonPatch: (patches: any[]) => void;
|
|
256
257
|
update: UpdateType<T>;
|
|
257
258
|
_path: string[];
|
|
@@ -297,7 +298,7 @@ export type StateObject<T> = (T extends any[]
|
|
|
297
298
|
getAllFormRefs: () => Map<string, React.RefObject<any>>;
|
|
298
299
|
_componentId: string | null;
|
|
299
300
|
getComponents: () => ComponentsType;
|
|
300
|
-
|
|
301
|
+
|
|
301
302
|
_initialState: T;
|
|
302
303
|
updateInitialState: (newState: T | null) => {
|
|
303
304
|
fetchId: (field: keyof T) => string | number;
|
|
@@ -375,12 +376,23 @@ type ValidationOptionsType = {
|
|
|
375
376
|
|
|
376
377
|
onBlur?: boolean;
|
|
377
378
|
};
|
|
379
|
+
type UseSyncType<T> = (state: T, a: SyncOptionsType<any>) => SyncApi;
|
|
380
|
+
type SyncOptionsType<TApiParams> = {
|
|
381
|
+
apiParams: TApiParams;
|
|
382
|
+
stateKey?: string;
|
|
383
|
+
stateRoom:
|
|
384
|
+
| number
|
|
385
|
+
| string
|
|
386
|
+
| (({ clientId }: { clientId: string }) => string | null);
|
|
387
|
+
connect?: boolean;
|
|
388
|
+
inMemoryState?: boolean;
|
|
389
|
+
};
|
|
378
390
|
export type OptionsType<T extends unknown = unknown, TApiParams = never> = {
|
|
379
391
|
log?: boolean;
|
|
380
392
|
componentId?: string;
|
|
381
|
-
|
|
382
|
-
validation?: ValidationOptionsType;
|
|
393
|
+
syncOptions?: SyncOptionsType<TApiParams>;
|
|
383
394
|
|
|
395
|
+
validation?: ValidationOptionsType;
|
|
384
396
|
serverState?: {
|
|
385
397
|
id?: string | number;
|
|
386
398
|
data?: T;
|
|
@@ -390,9 +402,10 @@ export type OptionsType<T extends unknown = unknown, TApiParams = never> = {
|
|
|
390
402
|
| boolean
|
|
391
403
|
| {
|
|
392
404
|
strategy: 'append' | 'prepend' | 'diff';
|
|
393
|
-
key?: string;
|
|
405
|
+
key?: string;
|
|
394
406
|
};
|
|
395
407
|
};
|
|
408
|
+
|
|
396
409
|
sync?: {
|
|
397
410
|
action: (state: T) => Promise<{
|
|
398
411
|
success: boolean;
|
|
@@ -481,7 +494,6 @@ function setAndMergeOptions(stateKey: string, newOptions: OptionsType<any>) {
|
|
|
481
494
|
...newOptions,
|
|
482
495
|
});
|
|
483
496
|
}
|
|
484
|
-
|
|
485
497
|
function setOptions<StateKey, Opt>({
|
|
486
498
|
stateKey,
|
|
487
499
|
options,
|
|
@@ -525,10 +537,19 @@ function setOptions<StateKey, Opt>({
|
|
|
525
537
|
}
|
|
526
538
|
}
|
|
527
539
|
|
|
540
|
+
// Always preserve syncOptions if it exists in mergedOptions but not in options
|
|
541
|
+
if (
|
|
542
|
+
mergedOptions.syncOptions &&
|
|
543
|
+
(!options || !options.hasOwnProperty('syncOptions'))
|
|
544
|
+
) {
|
|
545
|
+
needToAdd = true;
|
|
546
|
+
}
|
|
547
|
+
|
|
528
548
|
if (needToAdd) {
|
|
529
549
|
setInitialStateOptions(stateKey as string, mergedOptions);
|
|
530
550
|
}
|
|
531
551
|
}
|
|
552
|
+
|
|
532
553
|
export function addStateOptions<T extends unknown>(
|
|
533
554
|
initialState: T,
|
|
534
555
|
{ formElements, validation }: OptionsType<T>
|
|
@@ -551,11 +572,12 @@ export const createCogsState = <State extends Record<StateKeys, unknown>>(
|
|
|
551
572
|
validation?: ValidationOptionsType;
|
|
552
573
|
__fromSyncSchema?: boolean;
|
|
553
574
|
__syncNotifications?: Record<string, Function>;
|
|
554
|
-
__apiParamsMap?: Record<string, any>;
|
|
575
|
+
__apiParamsMap?: Record<string, any>;
|
|
576
|
+
__useSync?: UseSyncType<State>;
|
|
555
577
|
}
|
|
556
578
|
) => {
|
|
557
579
|
let newInitialState = initialState;
|
|
558
|
-
|
|
580
|
+
console.log('optsc', opt?.__useSync);
|
|
559
581
|
const [statePart, initialOptionsPart] =
|
|
560
582
|
transformStateFunc<State>(newInitialState);
|
|
561
583
|
|
|
@@ -626,17 +648,10 @@ export const createCogsState = <State extends Record<StateKeys, unknown>>(
|
|
|
626
648
|
options?: Prettify<OptionsType<(typeof statePart)[StateKey]>>
|
|
627
649
|
) => {
|
|
628
650
|
const [componentId] = useState(options?.componentId ?? uuidv4());
|
|
629
|
-
const apiParamsSchema = opt?.__apiParamsMap?.[stateKey as string];
|
|
630
|
-
|
|
631
|
-
// Merge apiParams into options
|
|
632
|
-
const enhancedOptions = {
|
|
633
|
-
...options,
|
|
634
|
-
apiParamsSchema, // Add the schema here
|
|
635
|
-
} as any;
|
|
636
651
|
|
|
637
652
|
setOptions({
|
|
638
653
|
stateKey,
|
|
639
|
-
options
|
|
654
|
+
options,
|
|
640
655
|
initialOptionsPart,
|
|
641
656
|
});
|
|
642
657
|
const thiState =
|
|
@@ -657,6 +672,8 @@ export const createCogsState = <State extends Record<StateKeys, unknown>>(
|
|
|
657
672
|
defaultState: options?.defaultState as any,
|
|
658
673
|
dependencies: options?.dependencies,
|
|
659
674
|
serverState: options?.serverState,
|
|
675
|
+
syncOptions: options?.syncOptions,
|
|
676
|
+
__useSync: opt?.__useSync as UseSyncType<(typeof statePart)[StateKey]>,
|
|
660
677
|
});
|
|
661
678
|
|
|
662
679
|
return updater;
|
|
@@ -677,21 +694,32 @@ export const createCogsState = <State extends Record<StateKeys, unknown>>(
|
|
|
677
694
|
|
|
678
695
|
return { useCogsState, setCogsOptions } as CogsApi<State>;
|
|
679
696
|
};
|
|
697
|
+
|
|
680
698
|
// Fix for UseCogsStateHook to support per-key apiParams
|
|
681
699
|
type UseCogsStateHook<
|
|
682
700
|
T extends Record<string, any>,
|
|
683
701
|
TApiParamsMap extends Record<string, any> = Record<string, never>,
|
|
684
|
-
> = <StateKey extends keyof TransformedStateType<T
|
|
702
|
+
> = <StateKey extends keyof TransformedStateType<T> & string>(
|
|
685
703
|
stateKey: StateKey,
|
|
686
704
|
options?: Prettify<
|
|
687
|
-
OptionsType<TransformedStateType<T>[StateKey]> &
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
705
|
+
OptionsType<TransformedStateType<T>[StateKey], TApiParamsMap[StateKey]> &
|
|
706
|
+
// This is the conditional part that solves the problem
|
|
707
|
+
([keyof TApiParamsMap] extends [never]
|
|
708
|
+
? // If TApiParamsMap has NO keys, intersect with an empty object.
|
|
709
|
+
// This means `syncOptions` is NOT a valid property.
|
|
710
|
+
{}
|
|
711
|
+
: // If TApiParamsMap HAS keys, intersect with a type that REQUIRES `syncOptions`.
|
|
712
|
+
{
|
|
713
|
+
syncOptions: Prettify<
|
|
714
|
+
SyncOptionsType<
|
|
715
|
+
StateKey extends keyof TApiParamsMap
|
|
716
|
+
? TApiParamsMap[StateKey]
|
|
717
|
+
: never
|
|
718
|
+
>
|
|
719
|
+
>;
|
|
720
|
+
})
|
|
692
721
|
>
|
|
693
722
|
) => StateObject<TransformedStateType<T>[StateKey]>;
|
|
694
|
-
|
|
695
723
|
// Updated CogsApi type
|
|
696
724
|
type CogsApi<
|
|
697
725
|
T extends Record<string, any>,
|
|
@@ -700,8 +728,12 @@ type CogsApi<
|
|
|
700
728
|
useCogsState: UseCogsStateHook<T, TApiParamsMap>;
|
|
701
729
|
setCogsOptions: SetCogsOptionsFunc<T>;
|
|
702
730
|
};
|
|
731
|
+
type GetParamType<SchemaEntry> = SchemaEntry extends {
|
|
732
|
+
api?: { queryData?: { _paramType?: infer P } };
|
|
733
|
+
}
|
|
734
|
+
? P
|
|
735
|
+
: never;
|
|
703
736
|
|
|
704
|
-
// Fixed createCogsStateFromSync return type
|
|
705
737
|
export function createCogsStateFromSync<
|
|
706
738
|
TSyncSchema extends {
|
|
707
739
|
schemas: Record<
|
|
@@ -717,19 +749,16 @@ export function createCogsStateFromSync<
|
|
|
717
749
|
notifications: Record<string, any>;
|
|
718
750
|
},
|
|
719
751
|
>(
|
|
720
|
-
syncSchema: TSyncSchema
|
|
752
|
+
syncSchema: TSyncSchema,
|
|
753
|
+
useSync: UseSyncType<any>
|
|
721
754
|
): CogsApi<
|
|
722
755
|
{
|
|
723
756
|
[K in keyof TSyncSchema['schemas']]: TSyncSchema['schemas'][K]['schemas']['defaultValues'];
|
|
724
757
|
},
|
|
725
758
|
{
|
|
726
|
-
[K in keyof TSyncSchema['schemas']]:
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
? Q extends { _paramType: infer P }
|
|
730
|
-
? P
|
|
731
|
-
: never
|
|
732
|
-
: never;
|
|
759
|
+
[K in keyof TSyncSchema['schemas']]: GetParamType<
|
|
760
|
+
TSyncSchema['schemas'][K]
|
|
761
|
+
>;
|
|
733
762
|
}
|
|
734
763
|
> {
|
|
735
764
|
const schemas = syncSchema.schemas;
|
|
@@ -747,20 +776,18 @@ export function createCogsStateFromSync<
|
|
|
747
776
|
}
|
|
748
777
|
}
|
|
749
778
|
|
|
750
|
-
// Pass the sync schema metadata to createCogsState
|
|
751
779
|
return createCogsState(initialState, {
|
|
752
780
|
__fromSyncSchema: true,
|
|
753
781
|
__syncNotifications: syncSchema.notifications,
|
|
754
782
|
__apiParamsMap: apiParamsMap,
|
|
783
|
+
__useSync: useSync,
|
|
755
784
|
}) as any;
|
|
756
785
|
}
|
|
757
786
|
const {
|
|
758
787
|
getInitialOptions,
|
|
759
|
-
|
|
788
|
+
|
|
760
789
|
setStateLog,
|
|
761
790
|
updateInitialStateGlobal,
|
|
762
|
-
addValidationError,
|
|
763
|
-
removeValidationError,
|
|
764
791
|
} = getGlobalStore.getState();
|
|
765
792
|
const saveToLocalStorage = <T,>(
|
|
766
793
|
state: T,
|
|
@@ -950,122 +977,6 @@ function markEntireStateAsServerSynced(
|
|
|
950
977
|
}
|
|
951
978
|
}
|
|
952
979
|
|
|
953
|
-
const _notifySubscribedComponents = (
|
|
954
|
-
stateKey: string,
|
|
955
|
-
path: string[],
|
|
956
|
-
updateType: 'update' | 'insert' | 'cut',
|
|
957
|
-
oldValue: any,
|
|
958
|
-
newValue: any
|
|
959
|
-
) => {
|
|
960
|
-
const store = getGlobalStore.getState();
|
|
961
|
-
const rootMeta = store.getShadowMetadata(stateKey, []);
|
|
962
|
-
if (!rootMeta?.components) {
|
|
963
|
-
return;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
const notifiedComponents = new Set<string>();
|
|
967
|
-
const shadowMeta = store.getShadowMetadata(stateKey, path);
|
|
968
|
-
|
|
969
|
-
// --- PASS 1: Notify specific subscribers based on update type ---
|
|
970
|
-
|
|
971
|
-
if (updateType === 'update') {
|
|
972
|
-
if (shadowMeta?.pathComponents) {
|
|
973
|
-
shadowMeta.pathComponents.forEach((componentId) => {
|
|
974
|
-
if (notifiedComponents.has(componentId)) return;
|
|
975
|
-
const component = rootMeta.components?.get(componentId);
|
|
976
|
-
if (component) {
|
|
977
|
-
const reactiveTypes = Array.isArray(component.reactiveType)
|
|
978
|
-
? component.reactiveType
|
|
979
|
-
: [component.reactiveType || 'component'];
|
|
980
|
-
if (!reactiveTypes.includes('none')) {
|
|
981
|
-
component.forceUpdate();
|
|
982
|
-
notifiedComponents.add(componentId);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
if (
|
|
989
|
-
newValue &&
|
|
990
|
-
typeof newValue === 'object' &&
|
|
991
|
-
!isArray(newValue) &&
|
|
992
|
-
oldValue &&
|
|
993
|
-
typeof oldValue === 'object' &&
|
|
994
|
-
!isArray(oldValue)
|
|
995
|
-
) {
|
|
996
|
-
const changedSubPaths = getDifferences(newValue, oldValue);
|
|
997
|
-
changedSubPaths.forEach((subPathString) => {
|
|
998
|
-
const subPath = subPathString.split('.');
|
|
999
|
-
const fullSubPath = [...path, ...subPath];
|
|
1000
|
-
const subPathMeta = store.getShadowMetadata(stateKey, fullSubPath);
|
|
1001
|
-
if (subPathMeta?.pathComponents) {
|
|
1002
|
-
subPathMeta.pathComponents.forEach((componentId) => {
|
|
1003
|
-
if (notifiedComponents.has(componentId)) return;
|
|
1004
|
-
const component = rootMeta.components?.get(componentId);
|
|
1005
|
-
if (component) {
|
|
1006
|
-
const reactiveTypes = Array.isArray(component.reactiveType)
|
|
1007
|
-
? component.reactiveType
|
|
1008
|
-
: [component.reactiveType || 'component'];
|
|
1009
|
-
if (!reactiveTypes.includes('none')) {
|
|
1010
|
-
component.forceUpdate();
|
|
1011
|
-
notifiedComponents.add(componentId);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
} else if (updateType === 'insert' || updateType === 'cut') {
|
|
1019
|
-
const parentArrayPath = updateType === 'insert' ? path : path.slice(0, -1);
|
|
1020
|
-
const parentMeta = store.getShadowMetadata(stateKey, parentArrayPath);
|
|
1021
|
-
if (parentMeta?.pathComponents) {
|
|
1022
|
-
parentMeta.pathComponents.forEach((componentId) => {
|
|
1023
|
-
if (!notifiedComponents.has(componentId)) {
|
|
1024
|
-
const component = rootMeta.components?.get(componentId);
|
|
1025
|
-
if (component) {
|
|
1026
|
-
component.forceUpdate();
|
|
1027
|
-
notifiedComponents.add(componentId);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
// --- PASS 2: Notify global subscribers ('all', 'deps') ---
|
|
1035
|
-
|
|
1036
|
-
rootMeta.components.forEach((component, componentId) => {
|
|
1037
|
-
if (notifiedComponents.has(componentId)) {
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
const reactiveTypes = Array.isArray(component.reactiveType)
|
|
1042
|
-
? component.reactiveType
|
|
1043
|
-
: [component.reactiveType || 'component'];
|
|
1044
|
-
|
|
1045
|
-
if (reactiveTypes.includes('all')) {
|
|
1046
|
-
component.forceUpdate();
|
|
1047
|
-
notifiedComponents.add(componentId);
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
if (reactiveTypes.includes('deps')) {
|
|
1052
|
-
if (component.depsFunction) {
|
|
1053
|
-
const currentState = store.getShadowValue(stateKey);
|
|
1054
|
-
const newDeps = component.depsFunction(currentState);
|
|
1055
|
-
let shouldUpdate = false;
|
|
1056
|
-
if (newDeps === true || !isDeepEqual(component.prevDeps, newDeps)) {
|
|
1057
|
-
if (Array.isArray(newDeps)) component.prevDeps = newDeps;
|
|
1058
|
-
shouldUpdate = true;
|
|
1059
|
-
}
|
|
1060
|
-
if (shouldUpdate) {
|
|
1061
|
-
component.forceUpdate();
|
|
1062
|
-
notifiedComponents.add(componentId);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
};
|
|
1068
|
-
|
|
1069
980
|
export function useCogsStateFn<TStateObject extends unknown>(
|
|
1070
981
|
stateObject: TStateObject,
|
|
1071
982
|
{
|
|
@@ -1080,12 +991,14 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1080
991
|
syncUpdate,
|
|
1081
992
|
dependencies,
|
|
1082
993
|
serverState,
|
|
1083
|
-
|
|
994
|
+
__useSync,
|
|
995
|
+
syncOptions,
|
|
1084
996
|
}: {
|
|
1085
997
|
stateKey?: string;
|
|
1086
998
|
componentId?: string;
|
|
1087
999
|
defaultState?: TStateObject;
|
|
1088
|
-
|
|
1000
|
+
__useSync?: UseSyncType<TStateObject>;
|
|
1001
|
+
syncOptions?: SyncOptionsType<any>;
|
|
1089
1002
|
} & OptionsType<TStateObject> = {}
|
|
1090
1003
|
) {
|
|
1091
1004
|
const [reactiveForce, forceUpdate] = useState({}); //this is the key to reactivity
|
|
@@ -1188,7 +1101,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1188
1101
|
.subscribeToPath(thisKey, (event) => {
|
|
1189
1102
|
if (event?.type === 'SERVER_STATE_UPDATE') {
|
|
1190
1103
|
const serverStateData = event.serverState;
|
|
1191
|
-
|
|
1104
|
+
console.log('SERVER_STATE_UPDATE', event);
|
|
1192
1105
|
if (
|
|
1193
1106
|
serverStateData?.status === 'success' &&
|
|
1194
1107
|
serverStateData.data !== undefined
|
|
@@ -1207,13 +1120,12 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1207
1120
|
.getState()
|
|
1208
1121
|
.getShadowValue(thisKey);
|
|
1209
1122
|
const incomingData = serverStateData.data;
|
|
1210
|
-
|
|
1211
1123
|
if (
|
|
1212
1124
|
mergeConfig &&
|
|
1213
1125
|
Array.isArray(currentState) &&
|
|
1214
1126
|
Array.isArray(incomingData)
|
|
1215
1127
|
) {
|
|
1216
|
-
const keyField = mergeConfig.key
|
|
1128
|
+
const keyField = mergeConfig.key;
|
|
1217
1129
|
const existingIds = new Set(
|
|
1218
1130
|
currentState.map((item: any) => item[keyField])
|
|
1219
1131
|
);
|
|
@@ -1655,11 +1567,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1655
1567
|
const newState = getGlobalStore.getState().getShadowValue(thisKey);
|
|
1656
1568
|
const rootMeta = getGlobalStore.getState().getShadowMetadata(thisKey, []);
|
|
1657
1569
|
const notifiedComponents = new Set<string>();
|
|
1658
|
-
|
|
1659
|
-
'rootMeta',
|
|
1660
|
-
thisKey,
|
|
1661
|
-
getGlobalStore.getState().shadowStateStore
|
|
1662
|
-
);
|
|
1570
|
+
|
|
1663
1571
|
if (!rootMeta?.components) {
|
|
1664
1572
|
return newState;
|
|
1665
1573
|
}
|
|
@@ -1894,9 +1802,14 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1894
1802
|
);
|
|
1895
1803
|
}, [thisKey, sessionId]);
|
|
1896
1804
|
|
|
1897
|
-
const cogsSyncFn =
|
|
1805
|
+
const cogsSyncFn = __useSync;
|
|
1806
|
+
const syncOpt = latestInitialOptionsRef.current?.syncOptions;
|
|
1807
|
+
|
|
1898
1808
|
if (cogsSyncFn) {
|
|
1899
|
-
syncApiRef.current = cogsSyncFn(
|
|
1809
|
+
syncApiRef.current = cogsSyncFn(
|
|
1810
|
+
updaterFinal as any,
|
|
1811
|
+
syncOpt ?? ({} as any)
|
|
1812
|
+
);
|
|
1900
1813
|
}
|
|
1901
1814
|
|
|
1902
1815
|
return updaterFinal;
|
|
@@ -2168,14 +2081,14 @@ function createProxyHandler<T>(
|
|
|
2168
2081
|
response.errors &&
|
|
2169
2082
|
validationKey
|
|
2170
2083
|
) {
|
|
2171
|
-
getGlobalStore.getState().removeValidationError(validationKey);
|
|
2172
|
-
response.errors.forEach((error) => {
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
});
|
|
2178
|
-
notifyComponents(stateKey);
|
|
2084
|
+
// getGlobalStore.getState().removeValidationError(validationKey);
|
|
2085
|
+
// response.errors.forEach((error) => {
|
|
2086
|
+
// const errorPath = [validationKey, ...error.path].join('.');
|
|
2087
|
+
// getGlobalStore
|
|
2088
|
+
// .getState()
|
|
2089
|
+
// .addValidationError(errorPath, error.message);
|
|
2090
|
+
// });
|
|
2091
|
+
// notifyComponents(stateKey);
|
|
2179
2092
|
}
|
|
2180
2093
|
|
|
2181
2094
|
if (response?.success) {
|
|
@@ -3565,18 +3478,61 @@ function createProxyHandler<T>(
|
|
|
3565
3478
|
return componentId;
|
|
3566
3479
|
}
|
|
3567
3480
|
if (path.length == 0) {
|
|
3568
|
-
if (prop === '
|
|
3569
|
-
return (
|
|
3481
|
+
if (prop === 'addZodValidation') {
|
|
3482
|
+
return (zodErrors: any[]) => {
|
|
3570
3483
|
const init = getGlobalStore
|
|
3571
3484
|
.getState()
|
|
3572
3485
|
.getInitialOptions(stateKey)?.validation;
|
|
3573
3486
|
if (!init?.key) throw new Error('Validation key not found');
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3487
|
+
|
|
3488
|
+
// For each error, set shadow metadata
|
|
3489
|
+
zodErrors.forEach((error) => {
|
|
3490
|
+
const currentMeta =
|
|
3491
|
+
getGlobalStore
|
|
3492
|
+
.getState()
|
|
3493
|
+
.getShadowMetadata(stateKey, error.path) || {};
|
|
3494
|
+
|
|
3495
|
+
getGlobalStore
|
|
3496
|
+
.getState()
|
|
3497
|
+
.setShadowMetadata(stateKey, error.path, {
|
|
3498
|
+
...currentMeta,
|
|
3499
|
+
validation: {
|
|
3500
|
+
status: 'VALIDATION_FAILED',
|
|
3501
|
+
message: error.message,
|
|
3502
|
+
validatedValue: undefined,
|
|
3503
|
+
},
|
|
3504
|
+
});
|
|
3505
|
+
getGlobalStore.getState().notifyPathSubscribers(error.path, {
|
|
3506
|
+
type: 'VALIDATION_FAILED',
|
|
3507
|
+
message: error.message,
|
|
3508
|
+
validatedValue: undefined,
|
|
3509
|
+
});
|
|
3578
3510
|
});
|
|
3579
|
-
|
|
3511
|
+
};
|
|
3512
|
+
}
|
|
3513
|
+
if (prop === 'clearZodValidation') {
|
|
3514
|
+
return (path?: string[]) => {
|
|
3515
|
+
// Clear specific paths
|
|
3516
|
+
if (!path) {
|
|
3517
|
+
throw new Error('clearZodValidation requires a path');
|
|
3518
|
+
return;
|
|
3519
|
+
}
|
|
3520
|
+
const currentMeta =
|
|
3521
|
+
getGlobalStore.getState().getShadowMetadata(stateKey, path) ||
|
|
3522
|
+
{};
|
|
3523
|
+
|
|
3524
|
+
if (currentMeta.validation) {
|
|
3525
|
+
getGlobalStore.getState().setShadowMetadata(stateKey, path, {
|
|
3526
|
+
...currentMeta,
|
|
3527
|
+
validation: undefined,
|
|
3528
|
+
});
|
|
3529
|
+
|
|
3530
|
+
getGlobalStore
|
|
3531
|
+
.getState()
|
|
3532
|
+
.notifyPathSubscribers([stateKey, ...path].join('.'), {
|
|
3533
|
+
type: 'VALIDATION_CLEARED',
|
|
3534
|
+
});
|
|
3535
|
+
}
|
|
3580
3536
|
};
|
|
3581
3537
|
}
|
|
3582
3538
|
if (prop === 'applyJsonPatch') {
|
|
@@ -3616,7 +3572,7 @@ function createProxyHandler<T>(
|
|
|
3616
3572
|
stateKey,
|
|
3617
3573
|
currentPath
|
|
3618
3574
|
);
|
|
3619
|
-
|
|
3575
|
+
|
|
3620
3576
|
if (pathMeta?.pathComponents) {
|
|
3621
3577
|
pathMeta.pathComponents.forEach((componentId) => {
|
|
3622
3578
|
if (!notifiedComponents.has(componentId)) {
|
|
@@ -3669,51 +3625,6 @@ function createProxyHandler<T>(
|
|
|
3669
3625
|
}
|
|
3670
3626
|
};
|
|
3671
3627
|
}
|
|
3672
|
-
if (prop === 'validateZodSchema') {
|
|
3673
|
-
return () => {
|
|
3674
|
-
const init = getGlobalStore
|
|
3675
|
-
.getState()
|
|
3676
|
-
.getInitialOptions(stateKey)?.validation;
|
|
3677
|
-
|
|
3678
|
-
// UPDATED: Select v4 schema, with a fallback to v3
|
|
3679
|
-
const zodSchema = init?.zodSchemaV4 || init?.zodSchemaV3;
|
|
3680
|
-
|
|
3681
|
-
if (!zodSchema || !init?.key) {
|
|
3682
|
-
throw new Error(
|
|
3683
|
-
'Zod schema (v3 or v4) or validation key not found'
|
|
3684
|
-
);
|
|
3685
|
-
}
|
|
3686
|
-
|
|
3687
|
-
removeValidationError(init.key);
|
|
3688
|
-
const thisObject = getGlobalStore
|
|
3689
|
-
.getState()
|
|
3690
|
-
.getShadowValue(stateKey);
|
|
3691
|
-
|
|
3692
|
-
// Use the selected schema for parsing
|
|
3693
|
-
const result = zodSchema.safeParse(thisObject);
|
|
3694
|
-
|
|
3695
|
-
if (!result.success) {
|
|
3696
|
-
// This logic already handles both v3 and v4 error types correctly
|
|
3697
|
-
if ('issues' in result.error) {
|
|
3698
|
-
// Zod v4 error
|
|
3699
|
-
result.error.issues.forEach((error) => {
|
|
3700
|
-
const fullErrorPath = [init.key, ...error.path].join('.');
|
|
3701
|
-
addValidationError(fullErrorPath, error.message);
|
|
3702
|
-
});
|
|
3703
|
-
} else {
|
|
3704
|
-
// Zod v3 error
|
|
3705
|
-
(result.error as any).errors.forEach((error: any) => {
|
|
3706
|
-
const fullErrorPath = [init.key, ...error.path].join('.');
|
|
3707
|
-
addValidationError(fullErrorPath, error.message);
|
|
3708
|
-
});
|
|
3709
|
-
}
|
|
3710
|
-
|
|
3711
|
-
notifyComponents(stateKey);
|
|
3712
|
-
return false;
|
|
3713
|
-
}
|
|
3714
|
-
return true;
|
|
3715
|
-
};
|
|
3716
|
-
}
|
|
3717
3628
|
|
|
3718
3629
|
if (prop === 'getComponents')
|
|
3719
3630
|
return () =>
|
|
@@ -3833,22 +3744,10 @@ function createProxyHandler<T>(
|
|
|
3833
3744
|
}
|
|
3834
3745
|
|
|
3835
3746
|
const baseObj = {
|
|
3836
|
-
removeValidation: (obj?: { validationKey?: string }) => {
|
|
3837
|
-
if (obj?.validationKey) {
|
|
3838
|
-
removeValidationError(obj.validationKey);
|
|
3839
|
-
}
|
|
3840
|
-
},
|
|
3841
3747
|
revertToInitialState: (obj?: { validationKey?: string }) => {
|
|
3842
3748
|
const init = getGlobalStore
|
|
3843
3749
|
.getState()
|
|
3844
3750
|
.getInitialOptions(stateKey)?.validation;
|
|
3845
|
-
if (init?.key) {
|
|
3846
|
-
removeValidationError(init.key);
|
|
3847
|
-
}
|
|
3848
|
-
|
|
3849
|
-
if (obj?.validationKey) {
|
|
3850
|
-
removeValidationError(obj.validationKey);
|
|
3851
|
-
}
|
|
3852
3751
|
|
|
3853
3752
|
const shadowMeta = getGlobalStore
|
|
3854
3753
|
.getState()
|
|
@@ -4485,6 +4384,7 @@ function FormElementWrapper({
|
|
|
4485
4384
|
validation: {
|
|
4486
4385
|
status: 'VALID_LIVE',
|
|
4487
4386
|
validatedValue: newValue,
|
|
4387
|
+
message: undefined,
|
|
4488
4388
|
},
|
|
4489
4389
|
});
|
|
4490
4390
|
}
|
|
@@ -4495,6 +4395,7 @@ function FormElementWrapper({
|
|
|
4495
4395
|
validation: {
|
|
4496
4396
|
status: 'VALID_LIVE',
|
|
4497
4397
|
validatedValue: newValue,
|
|
4398
|
+
message: undefined,
|
|
4498
4399
|
},
|
|
4499
4400
|
});
|
|
4500
4401
|
}
|