@contember/bindx-react 0.1.4 → 0.1.10

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.
@@ -12,6 +12,7 @@ import type {
12
12
  CommonEntity,
13
13
  EntityForRoles,
14
14
  RoleNames,
15
+ EntityAccessor,
15
16
  } from '@contember/bindx'
16
17
  import {
17
18
  EntityHandle,
@@ -51,165 +52,62 @@ export interface UseEntityOptions {
51
52
  // ============================================================================
52
53
 
53
54
  /**
54
- * Loading state for entity accessor
55
+ * Common properties on every UseEntityResult state.
56
+ * All prefixed with $ to avoid collision with entity field names.
55
57
  */
56
- export interface LoadingEntityAccessor {
57
- readonly status: 'loading'
58
- readonly isLoading: true
59
- readonly isError: false
60
- readonly isNotFound: false
61
- readonly isPersisting: false
62
- readonly isDirty: false
63
- readonly id: string
64
- readonly fields: never
65
- readonly data: never
66
- persist(): Promise<void>
67
- reset(): void
58
+ interface UseEntityResultBase {
59
+ $persist(): Promise<void>
60
+ $reset(): void
68
61
  }
69
62
 
70
- /**
71
- * Error state for entity accessor
72
- */
73
- export interface ErrorEntityAccessor {
74
- readonly status: 'error'
75
- readonly isLoading: false
76
- readonly isError: true
77
- readonly isNotFound: false
78
- readonly error: FieldError
79
- readonly isPersisting: false
80
- readonly isDirty: false
63
+ export type LoadingEntityResult = UseEntityResultBase & {
64
+ readonly $status: 'loading'
65
+ readonly $isLoading: true
66
+ readonly $isError: false
67
+ readonly $isNotFound: false
68
+ readonly $error: null
81
69
  readonly id: string
82
- readonly fields: never
83
- readonly data: never
84
- persist(): Promise<void>
85
- reset(): void
86
70
  }
87
71
 
88
- /**
89
- * Not found state for entity accessor
90
- */
91
- export interface NotFoundEntityAccessor {
92
- readonly status: 'not_found'
93
- readonly isLoading: false
94
- readonly isError: false
95
- readonly isNotFound: true
96
- readonly isPersisting: false
97
- readonly isDirty: false
72
+ export type ErrorEntityResult = UseEntityResultBase & {
73
+ readonly $status: 'error'
74
+ readonly $isLoading: false
75
+ readonly $isError: true
76
+ readonly $isNotFound: false
77
+ readonly $error: FieldError
98
78
  readonly id: string
99
- readonly fields: never
100
- readonly data: never
101
- persist(): Promise<void>
102
- reset(): void
103
79
  }
104
80
 
105
- /**
106
- * Ready state base interface for entity accessor
107
- */
108
- export interface ReadyEntityAccessorBase<TEntity extends object, TSelected extends object = TEntity> {
109
- readonly status: 'ready'
110
- readonly isLoading: false
111
- readonly isError: false
112
- readonly isNotFound: false
113
- readonly isPersisting: boolean
114
- readonly isDirty: boolean
81
+ export type NotFoundEntityResult = UseEntityResultBase & {
82
+ readonly $status: 'not_found'
83
+ readonly $isLoading: false
84
+ readonly $isError: false
85
+ readonly $isNotFound: true
86
+ readonly $error: null
115
87
  readonly id: string
116
- readonly fields: SelectedEntityFields<TEntity, TSelected>
117
- readonly data: TSelected
118
- persist(): Promise<void>
119
- reset(): void
120
88
  }
121
89
 
122
90
  /**
123
- * Ready state for entity accessor with direct field access via Proxy.
91
+ * Ready state — full EntityAccessor with status metadata.
124
92
  */
125
- export type ReadyEntityAccessor<TEntity extends object, TSelected extends object = TEntity> =
126
- ReadyEntityAccessorBase<TEntity, TSelected> & SelectedEntityFields<TEntity, TSelected>
93
+ export type ReadyEntityResult<TEntity extends object, TSelected extends object = TEntity> =
94
+ UseEntityResultBase & EntityAccessor<TEntity, TSelected> & {
95
+ readonly $status: 'ready'
96
+ readonly $isLoading: false
97
+ readonly $isError: false
98
+ readonly $isNotFound: false
99
+ readonly $error: null
100
+ }
127
101
 
128
102
  /**
129
- * Union of all entity accessor states
103
+ * Union of all useEntity return states.
104
+ * Discriminated on $status.
130
105
  */
131
- export type EntityAccessorResult<TEntity extends object, TSelected extends object = TEntity> =
132
- | LoadingEntityAccessor
133
- | ErrorEntityAccessor
134
- | NotFoundEntityAccessor
135
- | ReadyEntityAccessor<TEntity, TSelected>
136
-
137
- // ============================================================================
138
- // Internal helpers
139
- // ============================================================================
140
-
141
- function createLoadingAccessor(id: string): LoadingEntityAccessor {
142
- return {
143
- status: 'loading',
144
- isLoading: true,
145
- isError: false,
146
- isNotFound: false,
147
- isPersisting: false,
148
- isDirty: false,
149
- id,
150
- get fields(): never {
151
- throw new Error('Cannot access fields while loading')
152
- },
153
- get data(): never {
154
- throw new Error('Cannot access data while loading')
155
- },
156
- async persist() {
157
- // No-op while loading
158
- },
159
- reset() {
160
- // No-op while loading
161
- },
162
- }
163
- }
164
-
165
- function createErrorAccessor(id: string, error: FieldError): ErrorEntityAccessor {
166
- return {
167
- status: 'error',
168
- isLoading: false,
169
- isError: true,
170
- isNotFound: false,
171
- error,
172
- isPersisting: false,
173
- isDirty: false,
174
- id,
175
- get fields(): never {
176
- throw new Error('Cannot access fields after error')
177
- },
178
- get data(): never {
179
- throw new Error('Cannot access data after error')
180
- },
181
- async persist() {
182
- // No-op after error
183
- },
184
- reset() {
185
- // No-op after error
186
- },
187
- }
188
- }
189
-
190
- function createNotFoundAccessor(id: string): NotFoundEntityAccessor {
191
- return {
192
- status: 'not_found',
193
- isLoading: false,
194
- isError: false,
195
- isNotFound: true,
196
- isPersisting: false,
197
- isDirty: false,
198
- id,
199
- get fields(): never {
200
- throw new Error('Cannot access fields — entity not found')
201
- },
202
- get data(): never {
203
- throw new Error('Cannot access data — entity not found')
204
- },
205
- async persist() {
206
- // No-op for not found
207
- },
208
- reset() {
209
- // No-op for not found
210
- },
211
- }
212
- }
106
+ export type UseEntityResult<TEntity extends object, TSelected extends object = TEntity> =
107
+ | LoadingEntityResult
108
+ | ErrorEntityResult
109
+ | NotFoundEntityResult
110
+ | ReadyEntityResult<TEntity, TSelected>
213
111
 
214
112
  // ============================================================================
215
113
  // Hook overloads
@@ -217,11 +115,6 @@ function createNotFoundAccessor(id: string): NotFoundEntityAccessor {
217
115
 
218
116
  /**
219
117
  * Hook to fetch and manage a single entity with role-expanded type inference.
220
- *
221
- * @example
222
- * ```tsx
223
- * const article = useEntity(schema.Article, { by: { id }, roles: ['admin'] }, e => e.title().internalNotes())
224
- * ```
225
118
  */
226
119
  export function useEntity<
227
120
  TRoleMap extends Record<string, object>,
@@ -231,16 +124,15 @@ export function useEntity<
231
124
  entity: EntityDef<TRoleMap>,
232
125
  options: UseEntityOptions & { roles: readonly TRoles[] },
233
126
  definer: SelectionInput<EntityForRoles<TRoleMap, TRoles>, TResult>,
234
- ): EntityAccessorResult<EntityForRoles<TRoleMap, TRoles>, TResult>
127
+ ): UseEntityResult<EntityForRoles<TRoleMap, TRoles>, TResult>
235
128
 
236
129
  /**
237
130
  * Hook to fetch and manage a single entity with full type inference.
238
- * Uses the common (narrowest) entity type when no roles are specified.
239
131
  *
240
132
  * @example
241
133
  * ```tsx
242
134
  * const article = useEntity(schema.Article, { by: { id } }, e => e.title().content())
243
- * if (article.status !== 'ready') return <Loading />
135
+ * if (article.$status !== 'ready') return <Loading />
244
136
  * return <input value={article.title.value} onChange={...} />
245
137
  * ```
246
138
  */
@@ -248,31 +140,26 @@ export function useEntity<TRoleMap extends Record<string, object>, TResult exten
248
140
  entity: EntityDef<TRoleMap>,
249
141
  options: UseEntityOptions,
250
142
  definer: SelectionInput<CommonEntity<TRoleMap>, TResult>,
251
- ): EntityAccessorResult<CommonEntity<TRoleMap>, TResult>
143
+ ): UseEntityResult<CommonEntity<TRoleMap>, TResult>
252
144
 
253
145
  /**
254
146
  * Hook to fetch and manage a single entity with pre-resolved selection.
255
- *
256
147
  * Used internally by Entity component that collects selection from JSX.
257
148
  */
258
149
  export function useEntity(
259
150
  entity: EntityDef,
260
151
  options: UseEntityOptions & { selection: SelectionMeta },
261
- ): EntityAccessorResult<object, object>
152
+ ): UseEntityResult<object, object>
262
153
 
263
154
  // ============================================================================
264
155
  // Implementation
265
156
  // ============================================================================
266
157
 
267
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
268
158
  export function useEntity(
269
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
270
159
  entity: EntityDef<any>,
271
160
  options: UseEntityOptions,
272
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
273
161
  definer?: SelectionInput<any, any>,
274
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
275
- ): EntityAccessorResult<any, any> {
162
+ ): UseEntityResult<any, any> {
276
163
  const schemaRegistry = useSchemaRegistry()
277
164
  const entityType = entity.$name
278
165
  const { store, dispatcher, batcher, batchPersister } = useBindxContext()
@@ -409,81 +296,83 @@ export function useEntity(
409
296
  }, [entityType, id, byKey, effectiveQueryKey, options.cache, batcher, store, dispatcher, selectionMeta])
410
297
 
411
298
  // --- EntityHandle ---
412
- // Include snapshot in deps so handle reference changes when entity data changes.
413
- // This ensures memo-wrapped children that receive individual field handles re-render.
414
- const handle = useMemo(
415
- () => EntityHandle.create(id, entityType, store, dispatcher, schemaRegistry as SchemaRegistry<Record<string, object>>),
299
+ const rawHandle = useMemo(
300
+ () => EntityHandle.createRaw(id, entityType, store, dispatcher, schemaRegistry as SchemaRegistry<Record<string, object>>),
416
301
  [id, entityType, store, dispatcher, schemaRegistry, snapshot],
417
302
  )
418
303
 
304
+ const handle = useMemo(
305
+ () => EntityHandle.wrapProxy(rawHandle),
306
+ [rawHandle],
307
+ )
308
+
419
309
  useEffect(() => {
420
310
  return () => {
421
- handle.dispose()
311
+ rawHandle.dispose()
422
312
  }
423
- }, [handle])
313
+ }, [rawHandle])
314
+
315
+ // --- Persist & reset callbacks ---
316
+ const persist = useCallback(async () => {
317
+ await batchPersister.persist(entityType, id)
318
+ }, [batchPersister, entityType, id])
424
319
 
425
- // --- Build accessor ---
426
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
427
- const accessor = useMemo((): EntityAccessorResult<any, any> => {
428
- if (!loadState || loadState.status === 'loading') {
429
- return createLoadingAccessor(id)
320
+ const reset = useCallback(() => {
321
+ rawHandle.reset()
322
+ }, [rawHandle])
323
+
324
+ // --- Build result ---
325
+ const result = useMemo((): UseEntityResult<any, any> => {
326
+ if (!loadState || loadState.status === 'loading' || (!snapshot && loadState.status === 'success')) {
327
+ return { $status: 'loading', $isLoading: true, $isError: false, $isNotFound: false, $error: null, id, $persist: persist, $reset: reset }
430
328
  }
431
329
 
432
330
  if (loadState.status === 'error') {
433
- return createErrorAccessor(id, loadState.error!)
331
+ return { $status: 'error', $isLoading: false, $isError: true, $isNotFound: false, $error: loadState.error!, id, $persist: persist, $reset: reset }
434
332
  }
435
333
 
436
334
  if (loadState.status === 'not_found') {
437
- return createNotFoundAccessor(id)
335
+ return { $status: 'not_found', $isLoading: false, $isError: false, $isNotFound: true, $error: null, id, $persist: persist, $reset: reset }
438
336
  }
439
337
 
440
- if (!snapshot) {
441
- return createLoadingAccessor(id)
442
- }
338
+ // Ready — layer status metadata on top of EntityHandle proxy
339
+ return createReadyResult(handle, persist, reset)
340
+ }, [snapshot, loadState, isPersisting, id, handle, persist, reset])
443
341
 
444
- // Ready state
445
- const realId = (snapshot.data as Record<string, unknown>)?.['id'] as string | undefined ?? id
446
-
447
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
- const baseAccessor: ReadyEntityAccessorBase<any, any> = {
449
- status: 'ready',
450
- isLoading: false,
451
- isError: false,
452
- isNotFound: false,
453
- isPersisting,
454
- get isDirty() {
455
- return handle.$isDirty
456
- },
457
- id: realId,
458
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
459
- fields: handle.$fields as any,
460
- data: snapshot.data,
461
- async persist() {
462
- await batchPersister.persist(entityType, realId)
463
- },
464
- reset() {
465
- handle.reset()
466
- },
467
- }
342
+ return result
343
+ }
468
344
 
469
- // Wrap in Proxy for direct field access
470
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
471
- return new Proxy(baseAccessor as any, {
472
- get(target: Record<string, unknown>, prop: string | symbol, receiver: unknown) {
473
- if (prop in target) {
474
- return Reflect.get(target, prop, receiver)
475
- }
476
- if (typeof prop === 'string') {
477
- const fields = target['fields'] as Record<string, unknown>
478
- const fieldValue = fields[prop]
479
- if (fieldValue !== undefined) {
480
- return fieldValue
481
- }
482
- }
483
- return undefined
484
- },
485
- })
486
- }, [snapshot, loadState, isPersisting, id, handle, batchPersister, entityType])
345
+ // ============================================================================
346
+ // Result factories
347
+ // ============================================================================
348
+
349
+ function createReadyResult(
350
+ handle: EntityAccessor<object, object>,
351
+ persist: () => Promise<void>,
352
+ reset: () => void,
353
+ ): ReadyEntityResult<any, any> {
354
+ const meta = {
355
+ $status: 'ready' as const,
356
+ $isLoading: false as const,
357
+ $isError: false as const,
358
+ $isNotFound: false as const,
359
+ $error: null,
360
+ $persist: persist,
361
+ $reset: reset,
362
+ }
487
363
 
488
- return accessor
364
+ return new Proxy(handle as any, {
365
+ get(target, prop, receiver) {
366
+ if (typeof prop === 'string' && prop in meta) {
367
+ return (meta as any)[prop]
368
+ }
369
+ return Reflect.get(target, prop, receiver)
370
+ },
371
+ has(target, prop) {
372
+ if (typeof prop === 'string' && prop in meta) {
373
+ return true
374
+ }
375
+ return Reflect.has(target, prop)
376
+ },
377
+ }) as any
489
378
  }
@@ -34,106 +34,66 @@ export interface UseEntityListOptions {
34
34
  // Result types
35
35
  // ============================================================================
36
36
 
37
- /**
38
- * Loading state for entity list accessor
39
- */
40
- export interface LoadingEntityListAccessor {
41
- readonly status: 'loading'
42
- readonly isLoading: true
43
- readonly isError: false
44
- readonly isDirty: false
45
- readonly items: never
46
- readonly length: 0
47
- add(data?: unknown): string
48
- remove(key: string): void
49
- move(fromIndex: number, toIndex: number): void
37
+ interface EntityListResultBase {
38
+ $add(data?: unknown): string
39
+ $remove(key: string): void
40
+ $move(fromIndex: number, toIndex: number): void
50
41
  }
51
42
 
52
- /**
53
- * Error state for entity list accessor
54
- */
55
- export interface ErrorEntityListAccessor {
56
- readonly status: 'error'
57
- readonly isLoading: false
58
- readonly isError: true
59
- readonly error: FieldError
60
- readonly isDirty: false
61
- readonly items: never
62
- readonly length: 0
63
- add(data?: unknown): string
64
- remove(key: string): void
65
- move(fromIndex: number, toIndex: number): void
43
+ export type LoadingEntityListResult = EntityListResultBase & {
44
+ readonly $status: 'loading'
45
+ readonly $isLoading: true
46
+ readonly $isError: false
47
+ readonly $error: null
66
48
  }
67
49
 
68
- /**
69
- * Ready state for entity list accessor
70
- */
71
- export interface ReadyEntityListAccessor<T extends object> {
72
- readonly status: 'ready'
73
- readonly isLoading: false
74
- readonly isError: false
75
- readonly isDirty: boolean
50
+ export type ErrorEntityListResult = EntityListResultBase & {
51
+ readonly $status: 'error'
52
+ readonly $isLoading: false
53
+ readonly $isError: true
54
+ readonly $error: FieldError
55
+ }
56
+
57
+ export type ReadyEntityListResult<T extends object> = EntityListResultBase & {
58
+ readonly $status: 'ready'
59
+ readonly $isLoading: false
60
+ readonly $isError: false
61
+ readonly $error: null
62
+ readonly $isDirty: boolean
76
63
  readonly items: Array<EntityAccessor<T>>
77
64
  readonly length: number
78
- add(data?: Partial<T>): string
79
- remove(key: string): void
80
- move(fromIndex: number, toIndex: number): void
81
65
  }
82
66
 
83
- /**
84
- * Union of all entity list accessor states
85
- */
86
- export type EntityListAccessorResult<T extends object> =
87
- | LoadingEntityListAccessor
88
- | ErrorEntityListAccessor
89
- | ReadyEntityListAccessor<T>
67
+ export type UseEntityListResult<T extends object> =
68
+ | LoadingEntityListResult
69
+ | ErrorEntityListResult
70
+ | ReadyEntityListResult<T>
90
71
 
91
72
  // ============================================================================
92
73
  // Internal helpers
93
74
  // ============================================================================
94
75
 
95
- function createLoadingListAccessor(): LoadingEntityListAccessor {
76
+ function createLoadingListResult(): LoadingEntityListResult {
96
77
  return {
97
- status: 'loading',
98
- isLoading: true,
99
- isError: false,
100
- isDirty: false,
101
- get items(): never {
102
- throw new Error('Cannot access items while loading')
103
- },
104
- length: 0,
105
- add() {
106
- throw new Error('Cannot add items while loading')
107
- },
108
- remove() {
109
- throw new Error('Cannot remove items while loading')
110
- },
111
- move() {
112
- throw new Error('Cannot move items while loading')
113
- },
78
+ $status: 'loading',
79
+ $isLoading: true,
80
+ $isError: false,
81
+ $error: null,
82
+ $add() { throw new Error('Cannot add items while loading') },
83
+ $remove() { throw new Error('Cannot remove items while loading') },
84
+ $move() { throw new Error('Cannot move items while loading') },
114
85
  }
115
86
  }
116
87
 
117
- function createErrorListAccessor(error: FieldError): ErrorEntityListAccessor {
88
+ function createErrorListResult(error: FieldError): ErrorEntityListResult {
118
89
  return {
119
- status: 'error',
120
- isLoading: false,
121
- isError: true,
122
- error,
123
- isDirty: false,
124
- get items(): never {
125
- throw new Error('Cannot access items after error')
126
- },
127
- length: 0,
128
- add() {
129
- throw new Error('Cannot add items after error')
130
- },
131
- remove() {
132
- throw new Error('Cannot remove items after error')
133
- },
134
- move() {
135
- throw new Error('Cannot move items after error')
136
- },
90
+ $status: 'error',
91
+ $isLoading: false,
92
+ $isError: true,
93
+ $error: error,
94
+ $add() { throw new Error('Cannot add items after error') },
95
+ $remove() { throw new Error('Cannot remove items after error') },
96
+ $move() { throw new Error('Cannot move items after error') },
137
97
  }
138
98
  }
139
99
 
@@ -157,7 +117,7 @@ export function useEntityList<
157
117
  entity: EntityDef<TRoleMap>,
158
118
  options: UseEntityListOptions & { roles: readonly TRoles[] },
159
119
  definer: SelectionInput<EntityForRoles<TRoleMap, TRoles>, TResult>,
160
- ): EntityListAccessorResult<TResult>
120
+ ): UseEntityListResult<TResult>
161
121
 
162
122
  /**
163
123
  * Hook to fetch and manage a list of entities with full type inference.
@@ -174,7 +134,7 @@ export function useEntityList<TRoleMap extends Record<string, object>, TResult e
174
134
  entity: EntityDef<TRoleMap>,
175
135
  options: UseEntityListOptions,
176
136
  definer: SelectionInput<CommonEntity<TRoleMap>, TResult>,
177
- ): EntityListAccessorResult<TResult>
137
+ ): UseEntityListResult<TResult>
178
138
 
179
139
  /**
180
140
  * Hook to fetch and manage a list of entities with pre-resolved selection.
@@ -185,7 +145,7 @@ export function useEntityList<TRoleMap extends Record<string, object>, TResult e
185
145
  export function useEntityList(
186
146
  entity: EntityDef,
187
147
  options: UseEntityListOptions & { selection: SelectionMeta },
188
- ): EntityListAccessorResult<object>
148
+ ): UseEntityListResult<object>
189
149
 
190
150
  // ============================================================================
191
151
  // Implementation
@@ -197,7 +157,7 @@ export function useEntityList(
197
157
  options: UseEntityListOptions,
198
158
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
159
  definer?: SelectionInput<any, any>,
200
- ): EntityListAccessorResult<any> {
160
+ ): UseEntityListResult<any> {
201
161
  const schemaRegistry = useSchemaRegistry()
202
162
  const entityType = entity.$name
203
163
  const { store, dispatcher, batcher } = useBindxContext()
@@ -250,7 +210,7 @@ export function useEntityList(
250
210
  version: number
251
211
  storeVersion: number
252
212
  status: string
253
- result: EntityListAccessorResult<object>
213
+ result: UseEntityListResult<any>
254
214
  } | null>(null)
255
215
 
256
216
  // --- Store subscription ---
@@ -310,7 +270,7 @@ export function useEntityList(
310
270
  )
311
271
 
312
272
  // --- Snapshot ---
313
- const getSnapshot = useCallback((): EntityListAccessorResult<object> => {
273
+ const getSnapshot = useCallback((): UseEntityListResult<any> => {
314
274
  const state = listStateRef.current
315
275
  const version = versionRef.current
316
276
  const storeVersion = store.getVersion()
@@ -320,12 +280,12 @@ export function useEntityList(
320
280
  return cache.result
321
281
  }
322
282
 
323
- let result: EntityListAccessorResult<object>
283
+ let result: UseEntityListResult<any>
324
284
 
325
285
  if (state.status === 'loading') {
326
- result = createLoadingListAccessor()
286
+ result = createLoadingListResult()
327
287
  } else if (state.status === 'error') {
328
- result = createErrorListAccessor(state.error!)
288
+ result = createErrorListResult(state.error!)
329
289
  } else {
330
290
  const items = state.items.map((item) => {
331
291
  return EntityHandle.create<object>(
@@ -334,19 +294,20 @@ export function useEntityList(
334
294
  store,
335
295
  dispatcher,
336
296
  schemaRegistry as SchemaRegistry<Record<string, object>>,
337
- ) as unknown as EntityAccessor<object>
297
+ ) as unknown as EntityAccessor<any>
338
298
  })
339
299
 
340
300
  result = {
341
- status: 'ready',
342
- isLoading: false,
343
- isError: false,
344
- isDirty: false,
301
+ $status: 'ready',
302
+ $isLoading: false,
303
+ $isError: false,
304
+ $error: null,
305
+ $isDirty: false,
345
306
  items,
346
307
  length: items.length,
347
- add: addItem,
348
- remove: removeItem,
349
- move: moveItem,
308
+ $add: addItem,
309
+ $remove: removeItem,
310
+ $move: moveItem,
350
311
  }
351
312
  }
352
313
 
@@ -361,7 +322,7 @@ export function useEntityList(
361
322
  }, [entityType, store, dispatcher, schemaRegistry, addItem, removeItem, moveItem])
362
323
 
363
324
  const isEqual = useCallback(
364
- (a: EntityListAccessorResult<object>, b: EntityListAccessorResult<object>): boolean => {
325
+ (a: UseEntityListResult<any>, b: UseEntityListResult<any>): boolean => {
365
326
  return a === b
366
327
  },
367
328
  [],