cogsbox-state 0.5.489 → 0.5.491

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/src/CogsState.tsx CHANGED
@@ -57,32 +57,30 @@ import { runValidation } from './validation';
57
57
  import { ZodType } from 'zod/v4';
58
58
 
59
59
  export type Prettify<T> = T extends any ? { [K in keyof T]: T[K] } : never;
60
+ type IsAny<T> = 0 extends 1 & T ? true : false;
61
+
62
+ // Removed: SyncInfo is now owned by Shape Plugin
63
+
64
+ export type ValidationFieldSummary = {
65
+ status: ValidationStatus;
66
+ severity: ValidationSeverity;
67
+ hasErrors: boolean;
68
+ hasWarnings: boolean;
69
+ message: string;
70
+ errors: string[];
71
+ warnings: string[];
72
+ allErrors: Array<ValidationError & { path: string[] }>;
73
+ path: string[];
74
+ getData: () => unknown;
75
+ };
76
+
77
+ type ValidationSummaryArray = ValidationFieldSummary[];
60
78
 
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
-
81
- export type FormElementParams<T> = StateObject<T> & {
82
- $inputProps: {
83
- ref?: RefObject<any>;
84
- value?: T extends boolean ? never : T;
85
- onChange?: (
79
+ export type FormElementParams<T> = StateObject<T> & {
80
+ $inputProps: {
81
+ ref?: RefObject<any>;
82
+ value?: T extends boolean ? never : T;
83
+ onChange?: (
86
84
  event: ChangeEvent<
87
85
  HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
88
86
  >
@@ -90,17 +88,17 @@ export type FormElementParams<T> = StateObject<T> & {
90
88
  onBlur?: (
91
89
  event: FocusEvent<
92
90
  HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
93
- >
94
- ) => void;
95
- };
96
- status: ValidationStatus;
97
- severity: ValidationSeverity;
98
- hasErrors: boolean;
99
- hasWarnings: boolean;
100
- allErrors: ValidationError[];
101
- message: string;
102
- getData: () => T;
103
- };
91
+ >
92
+ ) => void;
93
+ };
94
+ status: ValidationStatus;
95
+ severity: ValidationSeverity;
96
+ hasErrors: boolean;
97
+ hasWarnings: boolean;
98
+ allErrors: ValidationError[];
99
+ message: string;
100
+ getData: () => T;
101
+ };
104
102
 
105
103
  export type StateKeys = string;
106
104
 
@@ -206,16 +204,15 @@ export type EndType<
206
204
  $get: () => T;
207
205
  $$get: () => T;
208
206
  $$derive: <R>(fn: EffectFunction<T, R>) => R;
209
- $_status: 'fresh' | 'dirty' | 'synced' | 'restored' | 'unknown';
210
- $getStatus: () => 'fresh' | 'dirty' | 'synced' | 'restored' | 'unknown';
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;
207
+ // Removed: $_status and $getStatus are now owned by Shape Plugin
208
+ $showValidationErrors: () => string[];
209
+ $validationErrors: {
210
+ (): ValidationSummaryArray;
211
+ <K extends Extract<keyof NonNullable<T>, string>>(
212
+ keys: readonly K[]
213
+ ): ValidationSummaryArray;
214
+ };
215
+ $setValidation: (ctx: string) => void;
219
216
  $removeValidation: (ctx: string) => void;
220
217
  $isSelected: boolean;
221
218
  $setSelected: (value: boolean) => void;
@@ -230,7 +227,7 @@ export type EndType<
230
227
  };
231
228
  $removeStorage: () => void;
232
229
  $setRaw: (value: T) => void;
233
- $sync: () => void;
230
+ // Removed: $sync is now owned by Shape Plugin
234
231
  $validationWrapper: ({
235
232
  children,
236
233
  hideMessage,
@@ -238,7 +235,7 @@ export type EndType<
238
235
  children: ReactNode;
239
236
  hideMessage?: boolean;
240
237
  }) => JSX.Element;
241
- $lastSynced?: SyncInfo;
238
+ // Removed: $lastSynced is now owned by Shape Plugin
242
239
  };
243
240
 
244
241
  // Helper type for element returned from array methods
@@ -374,30 +371,35 @@ export type StateObject<
374
371
  > = {
375
372
  (): T;
376
373
  (newValue: T | ((prev: T) => T)): void;
377
- } & ([NonNullable<T>] extends [any[]] // <-- Wrap in brackets
378
- ? ArrayEndType<T, TPlugins>
379
- : [NonNullable<T>] extends [Record<string, unknown> | object] // <-- Wrap in brackets
380
- ? {
381
- [K in keyof NonNullable<T>]-?: StateObject<NonNullable<T>[K], TPlugins>;
382
- }
383
- : {}) & // Fallback to {} since we intersect EndType below anyway
374
+ } & (IsAny<T> extends true
375
+ ? {}
376
+ : [NonNullable<T>] extends [any[]] // <-- Wrap in brackets
377
+ ? ArrayEndType<T, TPlugins>
378
+ : [NonNullable<T>] extends [Record<string, unknown> | object] // <-- Wrap in brackets
379
+ ? {
380
+ [K in keyof NonNullable<T>]-?: StateObject<
381
+ NonNullable<T>[K],
382
+ TPlugins
383
+ >;
384
+ }
385
+ : {}) & // Fallback to {} since we intersect EndType below anyway
384
386
  EndType<T, TPlugins> & {
385
387
  $toggle: NonNullable<T> extends boolean ? () => void : never;
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
- };
388
+ $validate: {
389
+ (): { success: boolean; data?: T; error?: any };
390
+ <K extends Extract<keyof NonNullable<T>, string>>(
391
+ keys: readonly K[]
392
+ ): {
393
+ success: boolean;
394
+ results: Array<{
395
+ key: K;
396
+ path: string[];
397
+ success: boolean;
398
+ data?: unknown;
399
+ error?: any;
400
+ }>;
401
+ };
402
+ };
401
403
  $_componentId: string | null;
402
404
  $getComponents: () => ComponentsType;
403
405
  $_initialState: T;
@@ -405,8 +407,6 @@ export type StateObject<
405
407
  fetchId: (field: keyof NonNullable<T>) => string | number;
406
408
  };
407
409
  $initializeAndMergeShadowState: (newState: any | null) => void;
408
- $_isLoading: boolean;
409
- $_serverState: T;
410
410
  $revertToInitialState: (obj?: { validationKey?: string }) => T;
411
411
  $middleware: (
412
412
  middles: ({
@@ -526,34 +526,6 @@ export type OptionsType<
526
526
  > = CreateStateOptionsType & {
527
527
  log?: boolean;
528
528
  componentId?: string;
529
- syncOptions?: SyncOptionsType<TApiParams>;
530
-
531
- serverState?: {
532
- id?: string | number;
533
- data?: T;
534
- status?: 'pending' | 'error' | 'success' | 'loading';
535
- timestamp?: number;
536
- merge?:
537
- | boolean
538
- | {
539
- strategy: 'append' | 'prepend' | 'diff';
540
- key?: string;
541
- };
542
- };
543
-
544
- sync?: {
545
- action: (state: T) => Promise<{
546
- success: boolean;
547
- data?: any;
548
- error?: any;
549
- errors?: Array<{
550
- path: (string | number)[];
551
- message: string;
552
- }>;
553
- }>;
554
- onSuccess?: (data: any) => void;
555
- onError?: (error: any) => void;
556
- };
557
529
  middleware?: ({ update }: { update: UpdateTypeDetail }) => void;
558
530
 
559
531
  localStorage?: {
@@ -563,7 +535,6 @@ export type OptionsType<
563
535
 
564
536
  reactiveDeps?: (state: T) => any[] | true;
565
537
  reactiveType?: ReactivityType;
566
- syncUpdate?: Partial<UpdateTypeDetail>;
567
538
 
568
539
  defaultState?: T;
569
540
 
@@ -632,13 +603,10 @@ const {
632
603
  insertManyShadowArrayElements,
633
604
  removeShadowArrayElement,
634
605
  setInitialStateOptions,
635
- setServerStateUpdate,
636
- markAsDirty,
637
606
  addPathComponent,
638
607
  clearSelectedIndexesForState,
639
608
  addStateLog,
640
609
  clearSelectedIndex,
641
- getSyncInfo,
642
610
  notifyPathSubscribers,
643
611
  getPluginMetaDataMap,
644
612
  setPluginMetaData,
@@ -914,7 +882,7 @@ type CreateCogsStateReturn<
914
882
  PluginOptionsMap<TPlugins>,
915
883
  StateKey
916
884
  >
917
- ) => StateObject<CogsFullState<State, TPlugins>[StateKey], TPlugins>;
885
+ ) => StateObject<CogsFullState<State, TPlugins>[StateKey], TPlugins>;
918
886
  setCogsOptionsByKey: <StateKey extends keyof CogsFullState<State, TPlugins>>(
919
887
  stateKey: StateKey,
920
888
  options: CreateStateOptionsType<
@@ -1030,7 +998,7 @@ export const createCogsState = <
1030
998
  OptionsType<StateSlice<StateKey>, never> &
1031
999
  PluginOptionsForState<PluginOptions, StateKey>
1032
1000
  >
1033
- ): StateObject<StateSlice<StateKey>, TPlugins> => {
1001
+ ): StateObject<StateSlice<StateKey>, TPlugins> => {
1034
1002
  const [componentId] = useState(options?.componentId ?? uuidv4());
1035
1003
 
1036
1004
  const currentOptions = setOptions({
@@ -1048,7 +1016,6 @@ export const createCogsState = <
1048
1016
 
1049
1017
  const updater = useCogsStateFn<StateSlice<StateKey>>(thiState, {
1050
1018
  stateKey: stateKey as string,
1051
- syncUpdate: options?.syncUpdate,
1052
1019
  componentId,
1053
1020
  localStorage: options?.localStorage,
1054
1021
  middleware: options?.middleware,
@@ -1056,7 +1023,6 @@ export const createCogsState = <
1056
1023
  reactiveDeps: options?.reactiveDeps,
1057
1024
  defaultState: options?.defaultState as any,
1058
1025
  dependencies: options?.dependencies,
1059
- serverState: options?.serverState,
1060
1026
  });
1061
1027
 
1062
1028
  useLayoutEffect(() => {
@@ -1086,8 +1052,8 @@ export const createCogsState = <
1086
1052
  }
1087
1053
  });
1088
1054
 
1089
- return updater as StateObject<StateSlice<StateKey>, TPlugins>;
1090
- };
1055
+ return updater as StateObject<StateSlice<StateKey>, TPlugins>;
1056
+ };
1091
1057
 
1092
1058
  function setCogsOptionsByKey<StateKey extends StateKeys>(
1093
1059
  stateKey: StateKey,
@@ -1183,8 +1149,6 @@ const saveToLocalStorage = <T,>(
1183
1149
  state,
1184
1150
  lastUpdated: Date.now(),
1185
1151
  lastSyncedWithServer: lastSyncedWithServer ?? existingLastSynced,
1186
- stateSource: shadowMeta?.stateSource,
1187
- baseServerState: shadowMeta?.baseServerState,
1188
1152
  };
1189
1153
 
1190
1154
  // Use SuperJSON serialize to get the json part only
@@ -1251,8 +1215,6 @@ type LocalStorageData<T> = {
1251
1215
  state: T;
1252
1216
  lastUpdated: number;
1253
1217
  lastSyncedWithServer?: number;
1254
- baseServerState?: T; // Keep reference to what server state this is based on
1255
- stateSource?: 'default' | 'server' | 'localStorage'; // Track origin
1256
1218
  };
1257
1219
 
1258
1220
  const notifyComponents = (thisKey: string) => {
@@ -1278,49 +1240,6 @@ const notifyComponents = (thisKey: string) => {
1278
1240
  });
1279
1241
  };
1280
1242
 
1281
- function markEntireStateAsServerSynced(
1282
- stateKey: string,
1283
- path: string[],
1284
- data: any,
1285
- timestamp: number
1286
- ) {
1287
- // Mark current path as synced
1288
- const currentMeta = getShadowMetadata(stateKey, path);
1289
- setShadowMetadata(stateKey, path, {
1290
- ...currentMeta,
1291
- isDirty: false,
1292
- stateSource: 'server',
1293
- lastServerSync: timestamp || Date.now(),
1294
- });
1295
-
1296
- // If it's an array, mark each item as synced
1297
- if (Array.isArray(data)) {
1298
- const arrayMeta = getShadowMetadata(stateKey, path);
1299
- if (arrayMeta?.arrayKeys) {
1300
- arrayMeta.arrayKeys.forEach((itemKey, index) => {
1301
- // Fix: Don't split the itemKey, just use it directly
1302
- const itemPath = [...path, itemKey];
1303
- const itemData = data[index];
1304
- if (itemData !== undefined) {
1305
- markEntireStateAsServerSynced(
1306
- stateKey,
1307
- itemPath,
1308
- itemData,
1309
- timestamp
1310
- );
1311
- }
1312
- });
1313
- }
1314
- }
1315
- // If it's an object, mark each field as synced
1316
- else if (data && typeof data === 'object' && data.constructor === Object) {
1317
- Object.keys(data).forEach((key) => {
1318
- const fieldPath = [...path, key];
1319
- const fieldData = data[key];
1320
- markEntireStateAsServerSynced(stateKey, fieldPath, fieldData, timestamp);
1321
- });
1322
- }
1323
- }
1324
1243
  // 5. Batch queue
1325
1244
  let updateBatchQueue: any[] = [];
1326
1245
  let isFlushScheduled = false;
@@ -1508,12 +1427,8 @@ function handleUpdate(
1508
1427
  return null; // <-- Abort the update
1509
1428
  }
1510
1429
 
1511
- // ✅ FIX: The new `updateShadowAtPath` handles metadata preservation automatically.
1512
- // The manual loop has been removed.
1513
1430
  updateShadowAtPath(stateKey, path, newValue);
1514
1431
 
1515
- markAsDirty(stateKey, path, { bubble: true });
1516
-
1517
1432
  // Return the metadata of the node *after* the update.
1518
1433
  const newShadowMeta = getShadowMetadata(stateKey, path);
1519
1434
 
@@ -1534,10 +1449,8 @@ function handleInsertMany(
1534
1449
  shadowMeta: any;
1535
1450
  path: string[];
1536
1451
  } {
1537
- // Use the existing, optimized global store function to perform the state update
1538
1452
  insertManyShadowArrayElements(stateKey, path, payload);
1539
1453
 
1540
- markAsDirty(stateKey, path, { bubble: true });
1541
1454
  const updatedMeta = getShadowMetadata(stateKey, path);
1542
1455
 
1543
1456
  return {
@@ -1578,10 +1491,6 @@ function handleInsert(
1578
1491
  index,
1579
1492
  itemId
1580
1493
  );
1581
- //console.timeEnd('insertShadowArrayElement');
1582
-
1583
- markAsDirty(stateKey, path, { bubble: true });
1584
-
1585
1494
  const updatedMeta = getShadowMetadata(stateKey, path);
1586
1495
 
1587
1496
  let insertAfterId: string | undefined;
@@ -1606,7 +1515,6 @@ function handleCut(
1606
1515
  const parentArrayPath = path.slice(0, -1);
1607
1516
  const oldValue = getShadowValue(stateKey, path);
1608
1517
  removeShadowArrayElement(stateKey, path);
1609
- markAsDirty(stateKey, parentArrayPath, { bubble: true });
1610
1518
  return { type: 'cut', oldValue: oldValue, parentPath: parentArrayPath };
1611
1519
  }
1612
1520
 
@@ -1759,12 +1667,10 @@ export function useCogsStateFn<
1759
1667
  componentId,
1760
1668
  defaultState,
1761
1669
  dependencies,
1762
- serverState,
1763
1670
  }: {
1764
1671
  stateKey?: string;
1765
1672
  componentId?: string;
1766
1673
  defaultState?: TStateObject;
1767
- syncOptions?: SyncOptionsType<any>;
1768
1674
  } & OptionsType<TStateObject> = {}
1769
1675
  ): StateObject<TStateObject, TPlugins> {
1770
1676
  const [reactiveForce, forceUpdate] = useState({}); //this is the key to reactivity
@@ -1783,10 +1689,9 @@ export function useCogsStateFn<
1783
1689
  overrideOptions?: OptionsType<TStateObject>
1784
1690
  ): {
1785
1691
  value: TStateObject;
1786
- source: 'default' | 'server' | 'localStorage';
1692
+ source: 'default' | 'localStorage';
1787
1693
  timestamp: number;
1788
1694
  } => {
1789
- // If we pass in options, use them. Otherwise, get from the global store.
1790
1695
  const optionsToUse = overrideOptions
1791
1696
  ? { ...getInitialOptions(thisKey as string), ...overrideOptions }
1792
1697
  : getInitialOptions(thisKey as string);
@@ -1795,19 +1700,7 @@ export function useCogsStateFn<
1795
1700
  const finalDefaultState =
1796
1701
  currentOptions?.defaultState || defaultState || stateObject;
1797
1702
 
1798
- // 1. Check server state
1799
- const hasValidServerData =
1800
- currentOptions?.serverState?.status === 'success' &&
1801
- currentOptions?.serverState?.data !== undefined;
1802
-
1803
- if (hasValidServerData) {
1804
- return {
1805
- value: currentOptions.serverState!.data! as any,
1806
- source: 'server',
1807
- timestamp: currentOptions.serverState!.timestamp || Date.now(),
1808
- };
1809
- }
1810
- // 2. Check localStorage
1703
+ // Check localStorage
1811
1704
  if (currentOptions?.localStorage?.key && sessionId) {
1812
1705
  const localKey = isFunction(currentOptions.localStorage.key)
1813
1706
  ? currentOptions.localStorage.key(finalDefaultState)
@@ -1817,10 +1710,7 @@ export function useCogsStateFn<
1817
1710
  `${sessionId}-${thisKey}-${localKey}`
1818
1711
  );
1819
1712
 
1820
- if (
1821
- localData &&
1822
- localData.lastUpdated > (currentOptions?.serverState?.timestamp || 0)
1823
- ) {
1713
+ if (localData) {
1824
1714
  return {
1825
1715
  value: localData.state,
1826
1716
  source: 'localStorage',
@@ -1829,7 +1719,7 @@ export function useCogsStateFn<
1829
1719
  }
1830
1720
  }
1831
1721
 
1832
- // 3. Use default state
1722
+ // Use default state
1833
1723
  return {
1834
1724
  value: finalDefaultState || (stateObject as any),
1835
1725
  source: 'default',
@@ -1839,111 +1729,8 @@ export function useCogsStateFn<
1839
1729
  [thisKey, defaultState, stateObject, sessionId]
1840
1730
  );
1841
1731
 
1842
- // Effect 1: When this component's serverState prop changes, broadcast it
1843
- useEffect(() => {
1844
- if (!serverState) return;
1845
-
1846
- // Only broadcast if we have valid server data
1847
- if (serverState.status === 'success' && serverState.data !== undefined) {
1848
- setServerStateUpdate(thisKey, serverState);
1849
- }
1850
- }, [serverState, thisKey]);
1851
- // Effect 2: Listen for server state updates from ANY component
1852
- useEffect(() => {
1853
- const unsubscribe = getGlobalStore
1854
- .getState()
1855
- .subscribeToPath(thisKey, (event) => {
1856
- if (event?.type === 'SERVER_STATE_UPDATE') {
1857
- const serverStateData = event.serverState;
1858
-
1859
- if (
1860
- serverStateData?.status !== 'success' ||
1861
- serverStateData.data === undefined
1862
- ) {
1863
- return; // Ignore if no valid data
1864
- }
1865
-
1866
- // Store the server state in options for future reference
1867
- setAndMergeOptions(thisKey, { serverState: serverStateData });
1868
-
1869
- const mergeConfig =
1870
- typeof serverStateData.merge === 'object'
1871
- ? serverStateData.merge
1872
- : serverStateData.merge === true
1873
- ? { strategy: 'append' as const, key: 'id' }
1874
- : null;
1875
-
1876
- const currentState = getShadowValue(thisKey, []);
1877
- const incomingData = serverStateData.data;
1878
-
1879
- if (
1880
- mergeConfig &&
1881
- mergeConfig.strategy === 'append' &&
1882
- 'key' in mergeConfig &&
1883
- Array.isArray(currentState) &&
1884
- Array.isArray(incomingData)
1885
- ) {
1886
- const keyField = mergeConfig.key;
1887
- if (!keyField) {
1888
- console.error(
1889
- "CogsState: Merge strategy 'append' requires a 'key' field."
1890
- );
1891
- return;
1892
- }
1893
-
1894
- // Get existing IDs to check for duplicates
1895
- const existingIds = new Set(
1896
- currentState.map((item: any) => item[keyField])
1897
- );
1898
-
1899
- // Filter out duplicates from incoming data
1900
- const newUniqueItems = incomingData.filter(
1901
- (item: any) => !existingIds.has(item[keyField])
1902
- );
1903
-
1904
- if (newUniqueItems.length > 0) {
1905
- // Insert only the new unique items
1906
- insertManyShadowArrayElements(thisKey, [], newUniqueItems);
1907
- }
1908
-
1909
- // Mark the entire merged state as synced
1910
- const finalState = getShadowValue(thisKey, []);
1911
- markEntireStateAsServerSynced(
1912
- thisKey,
1913
- [],
1914
- finalState,
1915
- serverStateData.timestamp || Date.now()
1916
- );
1917
- } else {
1918
- // Replace strategy (default) - completely replace the state
1919
- initializeShadowState(thisKey, incomingData);
1920
-
1921
- // Mark as synced from server
1922
- markEntireStateAsServerSynced(
1923
- thisKey,
1924
- [],
1925
- incomingData,
1926
- serverStateData.timestamp || Date.now()
1927
- );
1928
- }
1929
-
1930
- // Notify all components subscribed to this state
1931
- notifyComponents(thisKey);
1932
- }
1933
- });
1934
-
1935
- return unsubscribe;
1936
- }, [thisKey]);
1732
+ // Removed: Server state effects are now owned by Shape Plugin
1937
1733
  useEffect(() => {
1938
- const existingMeta = getGlobalStore
1939
- .getState()
1940
- .getShadowMetadata(thisKey, []);
1941
-
1942
- // Skip if already initialized
1943
- if (existingMeta && existingMeta.stateSource) {
1944
- return;
1945
- }
1946
-
1947
1734
  const options = getInitialOptions(thisKey as string);
1948
1735
 
1949
1736
  const features = {
@@ -1951,7 +1738,6 @@ export function useCogsStateFn<
1951
1738
  };
1952
1739
 
1953
1740
  setShadowMetadata(thisKey, [], {
1954
- ...existingMeta,
1955
1741
  features,
1956
1742
  });
1957
1743
 
@@ -1964,7 +1750,7 @@ export function useCogsStateFn<
1964
1750
  }
1965
1751
  }
1966
1752
 
1967
- const { value: resolvedState, source, timestamp } = resolveInitialState();
1753
+ const { value: resolvedState } = resolveInitialState();
1968
1754
  initializeShadowState(thisKey, resolvedState);
1969
1755
 
1970
1756
  const validation = getInitialOptions(thisKey as string)?.validation;
@@ -1974,17 +1760,6 @@ export function useCogsStateFn<
1974
1760
  updateShadowTypeInfo(thisKey as string, validation.zodSchemaV3, 'zod3');
1975
1761
  }
1976
1762
 
1977
- setShadowMetadata(thisKey, [], {
1978
- stateSource: source,
1979
- lastServerSync: source === 'server' ? timestamp : undefined,
1980
- isDirty: source === 'server' ? false : undefined,
1981
- baseServerState: source === 'server' ? resolvedState : undefined,
1982
- });
1983
-
1984
- if (source === 'server' && serverState) {
1985
- setServerStateUpdate(thisKey, serverState);
1986
- }
1987
-
1988
1763
  notifyComponents(thisKey);
1989
1764
  }, [thisKey, ...(dependencies || [])]);
1990
1765
 
@@ -2089,7 +1864,6 @@ type MetaData = {
2089
1864
  fn: Function;
2090
1865
  path: string[]; // Which array this transform applies to
2091
1866
  }>;
2092
- serverStateIsUpStream?: boolean;
2093
1867
  };
2094
1868
 
2095
1869
  const applyTransforms = (
@@ -2270,6 +2044,31 @@ function setFieldDisabledForPath(
2270
2044
  });
2271
2045
  }
2272
2046
 
2047
+ function pluginMetaDependencyPath(
2048
+ path: string[],
2049
+ pluginName: string,
2050
+ scope = 'default'
2051
+ ) {
2052
+ return [...path, '$pluginMeta', pluginName, scope];
2053
+ }
2054
+
2055
+ function notifyPluginMetaDependency(
2056
+ stateKey: string,
2057
+ path: string[],
2058
+ pluginName: string,
2059
+ scope?: string
2060
+ ) {
2061
+ const rootMeta = getShadowMetadata(stateKey, []);
2062
+ const dependencyMeta = getShadowMetadata(
2063
+ stateKey,
2064
+ pluginMetaDependencyPath(path, pluginName, scope)
2065
+ );
2066
+
2067
+ dependencyMeta?.pathComponents?.forEach((componentId) => {
2068
+ rootMeta?.components?.get(componentId)?.forceUpdate();
2069
+ });
2070
+ }
2071
+
2273
2072
  function createProxyHandler<
2274
2073
  T,
2275
2074
  const TPlugins extends readonly CogsPlugin<
@@ -2395,186 +2194,95 @@ function createProxyHandler<
2395
2194
  });
2396
2195
  }
2397
2196
 
2398
- const nextPath = [...path, prop];
2399
- return rebuildStateShape({
2400
- path: nextPath,
2401
- componentId: componentId!,
2402
- meta,
2403
- });
2404
- }
2405
- if (typeof prop === 'string' && prop.startsWith('$')) {
2406
- const methodName = prop.slice(1);
2407
- const { value } = getScopedData(stateKey, path, meta);
2408
- const registeredPlugins = pluginStore.getState().registeredPlugins;
2409
- for (const plugin of registeredPlugins) {
2410
- const chainMethod = (plugin.chainMethods as any)?.[methodName];
2411
- if (!chainMethod) continue;
2412
- if (!pathMatchesPattern(path, chainMethod.pathPattern)) continue;
2413
- if (!valueMatchesChainTarget(value, chainMethod.target)) continue;
2414
-
2415
- return (...args: any[]) => {
2416
- const store = pluginStore.getState();
2417
- const options = store.pluginOptions
2418
- .get(stateKey)
2419
- ?.get(plugin.name);
2420
- const hookData = store.getHookResult(stateKey, plugin.name);
2421
-
2422
- return chainMethod.handler(
2423
- {
2424
- stateKey,
2425
- path,
2426
- pluginName: plugin.name,
2427
- options,
2428
- hookData,
2429
- $get: () => getScopedData(stateKey, path, meta).value,
2430
- $update: (payload: any) => {
2431
- effectiveSetState(payload, path, {
2432
- updateType: 'update',
2433
- });
2434
-
2435
- return {
2436
- synced: () => {
2437
- const shadowMeta = getGlobalStore
2438
- .getState()
2439
- .getShadowMetadata(stateKey, path);
2440
-
2441
- setShadowMetadata(stateKey, path, {
2442
- ...shadowMeta,
2443
- isDirty: false,
2444
- stateSource: 'server',
2445
- lastServerSync: Date.now(),
2446
- });
2447
- },
2448
- };
2449
- },
2450
- $applyOperation: (
2451
- operation: UpdateTypeDetail,
2452
- metaData?: Record<string, any>
2453
- ) => {
2454
- effectiveSetState(operation.newValue, operation.path, {
2455
- updateType: operation.updateType,
2456
- itemId: operation.itemId,
2457
- metaData,
2458
- });
2459
- },
2460
- getFieldMetaData: () =>
2461
- getPluginMetaDataMap(stateKey, path)?.get(plugin.name),
2462
- setFieldMetaData: (data: Record<string, any>) =>
2463
- setPluginMetaData(stateKey, path, plugin.name, data),
2464
- removeFieldMetaData: () =>
2465
- removePluginMetaData(stateKey, path, plugin.name),
2466
- getFieldRefs: () => getFieldRefsForPath(stateKey, path),
2467
- getFieldElements: () =>
2468
- getFieldElementsForPath(stateKey, path),
2469
- setFieldDisabled: (disabled: boolean) =>
2470
- setFieldDisabledForPath(stateKey, path, disabled),
2471
- },
2472
- ...args
2473
- );
2474
- };
2475
- }
2476
- }
2477
- if (prop === '$_rebuildStateShape') {
2478
- return rebuildStateShape;
2479
- }
2480
-
2481
- if (prop === '$sync' && path.length === 0) {
2482
- return async function () {
2483
- const options = getGlobalStore
2484
- .getState()
2485
- .getInitialOptions(stateKey);
2486
- const sync = options?.sync;
2487
-
2488
- if (!sync) {
2489
- console.error(`No mutation defined for state key "${stateKey}"`);
2490
- return { success: false, error: `No mutation defined` };
2491
- }
2492
-
2493
- const state = getGlobalStore
2494
- .getState()
2495
- .getShadowValue(stateKey, []);
2496
- const validationKey = options?.validation?.key;
2497
-
2498
- try {
2499
- const response = await sync.action(state);
2500
- if (
2501
- response &&
2502
- !response.success &&
2503
- response.errors &&
2504
- validationKey
2505
- ) {
2506
- // getGlobalStore.getState().removeValidationError(validationKey);
2507
- // response.errors.forEach((error) => {
2508
- // const errorPath = [validationKey, ...error.path].join('.');
2509
- // getGlobalStore
2510
- // .getState()
2511
- // .addValidationError(errorPath, error.message);
2512
- // });
2513
- // notifyComponents(stateKey);
2514
- }
2515
-
2516
- if (response?.success) {
2517
- // Mark as synced and not dirty
2518
- const shadowMeta = getGlobalStore
2519
- .getState()
2520
- .getShadowMetadata(stateKey, []);
2521
- setShadowMetadata(stateKey, [], {
2522
- ...shadowMeta,
2523
- isDirty: false,
2524
- lastServerSync: Date.now(),
2525
- stateSource: 'server',
2526
- baseServerState: state, // Update base server state
2527
- });
2528
-
2529
- if (sync.onSuccess) {
2530
- sync.onSuccess(response.data);
2531
- }
2532
- } else if (!response?.success && sync.onError)
2533
- sync.onError(response.error);
2534
-
2535
- return response;
2536
- } catch (error) {
2537
- if (sync.onError) sync.onError(error);
2538
- return { success: false, error };
2539
- }
2540
- };
2197
+ const nextPath = [...path, prop];
2198
+ return rebuildStateShape({
2199
+ path: nextPath,
2200
+ componentId: componentId!,
2201
+ meta,
2202
+ });
2541
2203
  }
2542
- // Fixed getStatus function in createProxyHandler
2543
- if (prop === '$_status' || prop === '$getStatus') {
2544
- const getStatusFunc = () => {
2545
- // Use the optimized helper to get all data in one efficient call
2546
- const { shadowMeta, value } = getScopedData(stateKey, path, meta);
2547
-
2548
- if (shadowMeta?.isDirty === true) {
2549
- return 'dirty';
2550
- }
2551
-
2552
- if (
2553
- shadowMeta?.stateSource === 'server' ||
2554
- shadowMeta?.isDirty === false
2555
- ) {
2556
- return 'synced';
2557
- }
2558
-
2559
- if (shadowMeta?.stateSource === 'localStorage') {
2560
- return 'restored';
2561
- }
2562
-
2563
- if (shadowMeta?.stateSource === 'default') {
2564
- return 'fresh';
2565
- }
2566
-
2567
- if (value !== undefined) {
2568
- return 'fresh';
2569
- }
2570
-
2571
- // Fallback if no other condition is met.
2572
- return 'unknown';
2573
- };
2574
-
2575
- // This part remains the same
2576
- return prop === '$_status' ? getStatusFunc() : getStatusFunc;
2204
+ if (typeof prop === 'string' && prop.startsWith('$')) {
2205
+ const methodName = prop.slice(1);
2206
+ const { value } = getScopedData(stateKey, path, meta);
2207
+ const registeredPlugins = pluginStore.getState().registeredPlugins;
2208
+ for (const plugin of registeredPlugins) {
2209
+ const chainMethod = (plugin.chainMethods as any)?.[methodName];
2210
+ if (!chainMethod) continue;
2211
+ if (!pathMatchesPattern(path, chainMethod.pathPattern)) continue;
2212
+ if (!valueMatchesChainTarget(value, chainMethod.target)) continue;
2213
+
2214
+ return (...args: any[]) => {
2215
+ const store = pluginStore.getState();
2216
+ const options = store.pluginOptions
2217
+ .get(stateKey)
2218
+ ?.get(plugin.name);
2219
+ const hookData = store.getHookResult(stateKey, plugin.name);
2220
+
2221
+ return chainMethod.handler(
2222
+ {
2223
+ stateKey,
2224
+ path,
2225
+ pluginName: plugin.name,
2226
+ options,
2227
+ hookData,
2228
+ $get: () => getScopedData(stateKey, path, meta).value,
2229
+ $update: (payload: any) => {
2230
+ effectiveSetState(payload, path, {
2231
+ updateType: 'update',
2232
+ });
2233
+
2234
+ return {
2235
+ syned: () => {
2236
+ // Removed: sync status tracking is now owned by Shape Plugin
2237
+ },
2238
+ };
2239
+ },
2240
+ $applyOperation: (
2241
+ operation: UpdateTypeDetail,
2242
+ metaData?: Record<string, any>
2243
+ ) => {
2244
+ effectiveSetState(operation.newValue, operation.path, {
2245
+ updateType: operation.updateType,
2246
+ itemId: operation.itemId,
2247
+ metaData,
2248
+ });
2249
+ },
2250
+ getFieldMetaData: () =>
2251
+ getPluginMetaDataMap(stateKey, path)?.get(plugin.name),
2252
+ setFieldMetaData: (data: Record<string, any>) =>
2253
+ setPluginMetaData(stateKey, path, plugin.name, data),
2254
+ removeFieldMetaData: () =>
2255
+ removePluginMetaData(stateKey, path, plugin.name),
2256
+ watchPluginMeta: (scope?: string) =>
2257
+ registerComponentDependency(
2258
+ stateKey,
2259
+ componentId,
2260
+ pluginMetaDependencyPath(path, plugin.name, scope)
2261
+ ),
2262
+ notifyPluginMeta: (scope?: string) =>
2263
+ notifyPluginMetaDependency(
2264
+ stateKey,
2265
+ path,
2266
+ plugin.name,
2267
+ scope
2268
+ ),
2269
+ getFieldRefs: () => getFieldRefsForPath(stateKey, path),
2270
+ getFieldElements: () =>
2271
+ getFieldElementsForPath(stateKey, path),
2272
+ setFieldDisabled: (disabled: boolean) =>
2273
+ setFieldDisabledForPath(stateKey, path, disabled),
2274
+ },
2275
+ ...args
2276
+ );
2277
+ };
2278
+ }
2279
+ }
2280
+ if (prop === '$_rebuildStateShape') {
2281
+ return rebuildStateShape;
2577
2282
  }
2283
+
2284
+ // Removed: $sync is now owned by Shape Plugin
2285
+ // Removed: $_status and $getStatus are now owned by Shape Plugin
2578
2286
  if (prop === '$removeStorage') {
2579
2287
  return () => {
2580
2288
  const initialState =
@@ -2596,75 +2304,75 @@ function createProxyHandler<
2596
2304
  setShadowMetadata(stateKey, path, { ...currentMeta, isRaw: true });
2597
2305
  effectiveSetState(value, path, { updateType: 'update' });
2598
2306
  };
2599
- }
2600
-
2601
- if (prop === '$validate') {
2602
- return (keys?: readonly string[]) => {
2603
- const store = getGlobalStore.getState();
2604
-
2605
- if (keys) {
2606
- const results = keys.map((key) => {
2607
- const targetPath = [...path, key];
2608
- const targetValue = store.getShadowValue(stateKey, targetPath);
2609
- const currentMeta =
2610
- store.getShadowMetadata(stateKey, targetPath) || {};
2611
- const fieldSchema = currentMeta.typeInfo?.schema;
2612
-
2613
- if (!fieldSchema) {
2614
- return {
2615
- key,
2616
- path: targetPath,
2617
- success: true,
2618
- data: targetValue,
2619
- };
2620
- }
2621
-
2622
- const result = (fieldSchema as any).safeParse(targetValue);
2623
- const zodErrors =
2624
- result.error?.issues || result.error?.errors || [];
2625
-
2626
- store.setShadowMetadata(stateKey, targetPath, {
2627
- ...currentMeta,
2628
- validation: {
2629
- status: result.success ? 'VALID' : 'INVALID',
2630
- errors: result.success
2631
- ? []
2632
- : [
2633
- {
2634
- source: 'client',
2635
- message:
2636
- zodErrors[0]?.message || 'Invalid value',
2637
- severity: 'error',
2638
- code: zodErrors[0]?.code,
2639
- },
2640
- ],
2641
- lastValidated: Date.now(),
2642
- validatedValue: targetValue,
2643
- },
2644
- });
2645
- store.notifyPathSubscribers([stateKey, ...targetPath].join('.'), {
2646
- type: 'VALIDATION_UPDATE',
2647
- });
2648
-
2649
- return {
2650
- key,
2651
- path: targetPath,
2652
- success: result.success,
2653
- data: result.success ? result.data : undefined,
2654
- error: result.success ? undefined : result.error,
2655
- };
2656
- });
2657
-
2658
- notifyComponents(stateKey);
2659
-
2660
- return {
2661
- success: results.every((result) => result.success),
2662
- results,
2663
- };
2664
- }
2665
-
2666
- // 1. Get Data & Schema
2667
- const { value } = getScopedData(stateKey, path, meta);
2307
+ }
2308
+
2309
+ if (prop === '$validate') {
2310
+ return (keys?: readonly string[]) => {
2311
+ const store = getGlobalStore.getState();
2312
+
2313
+ if (keys) {
2314
+ const results = keys.map((key) => {
2315
+ const targetPath = [...path, key];
2316
+ const targetValue = store.getShadowValue(stateKey, targetPath);
2317
+ const currentMeta =
2318
+ store.getShadowMetadata(stateKey, targetPath) || {};
2319
+ const fieldSchema = currentMeta.typeInfo?.schema;
2320
+
2321
+ if (!fieldSchema) {
2322
+ return {
2323
+ key,
2324
+ path: targetPath,
2325
+ success: true,
2326
+ data: targetValue,
2327
+ };
2328
+ }
2329
+
2330
+ const result = (fieldSchema as any).safeParse(targetValue);
2331
+ const zodErrors =
2332
+ result.error?.issues || result.error?.errors || [];
2333
+
2334
+ store.setShadowMetadata(stateKey, targetPath, {
2335
+ ...currentMeta,
2336
+ validation: {
2337
+ status: result.success ? 'VALID' : 'INVALID',
2338
+ errors: result.success
2339
+ ? []
2340
+ : [
2341
+ {
2342
+ source: 'client',
2343
+ message:
2344
+ zodErrors[0]?.message || 'Invalid value',
2345
+ severity: 'error',
2346
+ code: zodErrors[0]?.code,
2347
+ },
2348
+ ],
2349
+ lastValidated: Date.now(),
2350
+ validatedValue: targetValue,
2351
+ },
2352
+ });
2353
+ store.notifyPathSubscribers([stateKey, ...targetPath].join('.'), {
2354
+ type: 'VALIDATION_UPDATE',
2355
+ });
2356
+
2357
+ return {
2358
+ key,
2359
+ path: targetPath,
2360
+ success: result.success,
2361
+ data: result.success ? result.data : undefined,
2362
+ error: result.success ? undefined : result.error,
2363
+ };
2364
+ });
2365
+
2366
+ notifyComponents(stateKey);
2367
+
2368
+ return {
2369
+ success: results.every((result) => result.success),
2370
+ results,
2371
+ };
2372
+ }
2373
+
2374
+ // 1. Get Data & Schema
2375
+ const { value } = getScopedData(stateKey, path, meta);
2668
2376
  const opts = store.getInitialOptions(stateKey);
2669
2377
  const schema =
2670
2378
  opts?.validation?.zodSchemaV4 || opts?.validation?.zodSchemaV3;
@@ -2722,11 +2430,11 @@ function createProxyHandler<
2722
2430
  return result;
2723
2431
  };
2724
2432
  }
2725
- if (prop === '$showValidationErrors') {
2726
- return () => {
2727
- const { shadowMeta } = getScopedData(stateKey, path, meta);
2728
- if (
2729
- shadowMeta?.validation?.status === 'INVALID' &&
2433
+ if (prop === '$showValidationErrors') {
2434
+ return () => {
2435
+ const { shadowMeta } = getScopedData(stateKey, path, meta);
2436
+ if (
2437
+ shadowMeta?.validation?.status === 'INVALID' &&
2730
2438
  shadowMeta.validation.errors.length > 0
2731
2439
  ) {
2732
2440
  // Return only error-severity messages (not warnings)
@@ -2734,55 +2442,55 @@ function createProxyHandler<
2734
2442
  .filter((err) => err.severity === 'error')
2735
2443
  .map((err) => err.message);
2736
2444
  }
2737
- return [];
2738
- };
2739
- }
2740
- if (prop === '$validationErrors') {
2741
- return (keys?: readonly string[]) => {
2742
- const store = getGlobalStore.getState();
2743
- const summarizePath = (targetPath: string[]) => {
2744
- const validationState =
2745
- store.getShadowMetadata(stateKey, targetPath)?.validation;
2746
- const allErrors = (validationState?.errors || []).map((err) => ({
2747
- ...err,
2748
- path: targetPath,
2749
- }));
2750
- const errors = allErrors.filter((err) => err.severity === 'error');
2751
- const warnings = allErrors.filter(
2752
- (err) => err.severity === 'warning'
2753
- );
2754
- const severity: ValidationSeverity =
2755
- errors.length > 0
2756
- ? 'error'
2757
- : warnings.length > 0
2758
- ? 'warning'
2759
- : undefined;
2760
-
2761
- return {
2762
- status: validationState?.status || 'NOT_VALIDATED',
2763
- severity,
2764
- hasErrors: errors.length > 0,
2765
- hasWarnings: warnings.length > 0,
2766
- message: errors[0]?.message || warnings[0]?.message || '',
2767
- errors: errors.map((err) => err.message),
2768
- warnings: warnings.map((err) => err.message),
2769
- allErrors,
2770
- path: targetPath,
2771
- getData: () => store.getShadowValue(stateKey, targetPath),
2772
- } satisfies ValidationFieldSummary;
2773
- };
2774
-
2775
- const childKeys =
2776
- keys ??
2777
- Object.keys(store.getShadowNode(stateKey, path) ?? {}).filter(
2778
- (key) => key !== '_meta'
2779
- );
2780
-
2781
- return childKeys.map((key) => summarizePath([...path, key]));
2782
- };
2783
- }
2784
-
2785
- if (prop === '$getSelected') {
2445
+ return [];
2446
+ };
2447
+ }
2448
+ if (prop === '$validationErrors') {
2449
+ return (keys?: readonly string[]) => {
2450
+ const store = getGlobalStore.getState();
2451
+ const summarizePath = (targetPath: string[]) => {
2452
+ const validationState =
2453
+ store.getShadowMetadata(stateKey, targetPath)?.validation;
2454
+ const allErrors = (validationState?.errors || []).map((err) => ({
2455
+ ...err,
2456
+ path: targetPath,
2457
+ }));
2458
+ const errors = allErrors.filter((err) => err.severity === 'error');
2459
+ const warnings = allErrors.filter(
2460
+ (err) => err.severity === 'warning'
2461
+ );
2462
+ const severity: ValidationSeverity =
2463
+ errors.length > 0
2464
+ ? 'error'
2465
+ : warnings.length > 0
2466
+ ? 'warning'
2467
+ : undefined;
2468
+
2469
+ return {
2470
+ status: validationState?.status || 'NOT_VALIDATED',
2471
+ severity,
2472
+ hasErrors: errors.length > 0,
2473
+ hasWarnings: warnings.length > 0,
2474
+ message: errors[0]?.message || warnings[0]?.message || '',
2475
+ errors: errors.map((err) => err.message),
2476
+ warnings: warnings.map((err) => err.message),
2477
+ allErrors,
2478
+ path: targetPath,
2479
+ getData: () => store.getShadowValue(stateKey, targetPath),
2480
+ } satisfies ValidationFieldSummary;
2481
+ };
2482
+
2483
+ const childKeys =
2484
+ keys ??
2485
+ Object.keys(store.getShadowNode(stateKey, path) ?? {}).filter(
2486
+ (key) => key !== '_meta'
2487
+ );
2488
+
2489
+ return childKeys.map((key) => summarizePath([...path, key]));
2490
+ };
2491
+ }
2492
+
2493
+ if (prop === '$getSelected') {
2786
2494
  return () => {
2787
2495
  const arrayKey = [stateKey, ...path].join('.');
2788
2496
  registerComponentDependency(stateKey, componentId, [
@@ -3048,9 +2756,7 @@ function createProxyHandler<
3048
2756
  e.type === 'INSERT' ||
3049
2757
  e.type === 'INSERT_MANY' ||
3050
2758
  e.type === 'REMOVE' ||
3051
- e.type === 'CLEAR_SELECTION' ||
3052
- (e.type === 'SERVER_STATE_UPDATE' &&
3053
- !meta?.serverStateIsUpStream)
2759
+ e.type === 'CLEAR_SELECTION'
3054
2760
  ) {
3055
2761
  forceUpdate({});
3056
2762
  }
@@ -3387,10 +3093,6 @@ function createProxyHandler<
3387
3093
  $cogsSignal({ _stateKey: stateKey, _path: path, _meta: meta });
3388
3094
  }
3389
3095
 
3390
- if (prop === '$lastSynced') {
3391
- const syncKey = `${stateKey}:${path.join('.')}`;
3392
- return getSyncInfo(syncKey);
3393
- }
3394
3096
  if (prop == 'getLocalStorage') {
3395
3097
  return (key: string) =>
3396
3098
  loadFromLocalStorage(sessionId + '-' + stateKey + '-' + key);
@@ -3662,8 +3364,6 @@ function createProxyHandler<
3662
3364
  };
3663
3365
  store.updateShadowAtPath(stateKey, relativePath, value);
3664
3366
 
3665
- store.markAsDirty(stateKey, relativePath, { bubble: true });
3666
-
3667
3367
  // Bubble up - notify components at this path and all parent paths
3668
3368
  let currentPath = [...relativePath];
3669
3369
  while (true) {
@@ -3693,7 +3393,6 @@ function createProxyHandler<
3693
3393
  case 'remove': {
3694
3394
  const parentPath = relativePath.slice(0, -1);
3695
3395
  store.removeShadowArrayElement(stateKey, relativePath);
3696
- store.markAsDirty(stateKey, parentPath, { bubble: true });
3697
3396
 
3698
3397
  // Bubble up from parent path
3699
3398
  let currentPath = [...parentPath];
@@ -3757,22 +3456,7 @@ function createProxyHandler<
3757
3456
 
3758
3457
  return {
3759
3458
  synced: () => {
3760
- const shadowMeta = getGlobalStore
3761
- .getState()
3762
- .getShadowMetadata(stateKey, path);
3763
-
3764
- setShadowMetadata(stateKey, path, {
3765
- ...shadowMeta,
3766
- isDirty: false,
3767
- stateSource: 'server',
3768
- lastServerSync: Date.now(),
3769
- });
3770
-
3771
- const fullPath = [stateKey, ...path].join('.');
3772
- notifyPathSubscribers(fullPath, {
3773
- type: 'SYNC_STATUS_CHANGE',
3774
- isDirty: false,
3775
- });
3459
+ // Removed: sync status tracking is now owned by Shape Plugin
3776
3460
  },
3777
3461
  };
3778
3462
  };
@@ -3855,16 +3539,8 @@ function createProxyHandler<
3855
3539
  // ... (rest of the function: rootLevelMethods, returnShape, etc.)
3856
3540
  const rootLevelMethods = {
3857
3541
  $revertToInitialState: (obj?: { validationKey?: string }) => {
3858
- const shadowMeta = getGlobalStore
3859
- .getState()
3860
- .getShadowMetadata(stateKey, []);
3861
- let revertState;
3862
-
3863
- if (shadowMeta?.stateSource === 'server' && shadowMeta.baseServerState) {
3864
- revertState = shadowMeta.baseServerState;
3865
- } else {
3866
- revertState = getGlobalStore.getState().initialStateGlobal[stateKey];
3867
- }
3542
+ const revertState =
3543
+ getGlobalStore.getState().initialStateGlobal[stateKey];
3868
3544
 
3869
3545
  clearSelectedIndexesForState(stateKey);
3870
3546
  initializeShadowState(stateKey, revertState);