@dxos/echo-react 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.0
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/lib/index.mjs +10 -6
- package/dist/lib/index.mjs.map +1 -1
- package/dist/types/src/index.d.ts +4 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/useObject.d.ts +9 -1
- package/dist/types/src/useObject.d.ts.map +1 -1
- package/dist/types/src/usePagination.d.ts +1 -5
- package/dist/types/src/usePagination.d.ts.map +1 -1
- package/dist/types/src/useQuery.d.ts +2 -1
- package/dist/types/src/useQuery.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/index.ts +4 -4
- package/src/useObject.test.tsx +2 -2
- package/src/useObject.ts +26 -5
- package/src/usePagination.test.tsx +1 -1
- package/src/usePagination.ts +1 -5
- package/src/useQuery.test.tsx +1 -1
- package/src/useQuery.ts +3 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/echo-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "React integration for ECHO.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@effect/atom-react": "4.0.0
|
|
29
|
-
"@dxos/echo": "0.
|
|
28
|
+
"@effect/atom-react": "4.0.0",
|
|
29
|
+
"@dxos/echo": "0.13.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@testing-library/react": "^16.3.2",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@types/react-dom": "~19.2.3",
|
|
35
35
|
"react": "~19.2.7",
|
|
36
36
|
"react-dom": "~19.2.7",
|
|
37
|
-
"@dxos/echo-client": "0.
|
|
37
|
+
"@dxos/echo-client": "0.13.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"react": "~19.2.7"
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export * from './useQuery';
|
|
6
|
-
export * from './usePagination';
|
|
7
|
-
export * from './useType';
|
|
8
|
-
export * from './useObject';
|
|
5
|
+
export * from './useQuery.ts';
|
|
6
|
+
export * from './usePagination.ts';
|
|
7
|
+
export * from './useType.ts';
|
|
8
|
+
export * from './useObject.ts';
|
package/src/useObject.test.tsx
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { RegistryContext } from '@effect/atom-react/RegistryContext';
|
|
6
6
|
import { renderHook, waitFor } from '@testing-library/react';
|
|
7
|
-
import * as AtomRegistry from 'effect/
|
|
7
|
+
import * as AtomRegistry from 'effect/reactivity/AtomRegistry';
|
|
8
8
|
import React, { type PropsWithChildren } from 'react';
|
|
9
9
|
import { describe, expect, test } from 'vitest';
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ import { Obj, Ref } from '@dxos/echo';
|
|
|
12
12
|
import { createObject } from '@dxos/echo-client';
|
|
13
13
|
import { TestSchema } from '@dxos/echo/testing';
|
|
14
14
|
|
|
15
|
-
import { useObject } from './useObject';
|
|
15
|
+
import { useObject } from './useObject.ts';
|
|
16
16
|
|
|
17
17
|
const createWrapper = (registry: AtomRegistry.AtomRegistry) => {
|
|
18
18
|
return ({ children }: PropsWithChildren) => (
|
package/src/useObject.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { useAtomValue } from '@effect/atom-react/Hooks';
|
|
6
|
-
import * as Atom from 'effect/
|
|
6
|
+
import * as Atom from 'effect/reactivity/Atom';
|
|
7
7
|
import { useCallback, useMemo } from 'react';
|
|
8
8
|
|
|
9
9
|
import { Obj, Ref } from '@dxos/echo';
|
|
@@ -46,6 +46,18 @@ export const useObject: {
|
|
|
46
46
|
*/
|
|
47
47
|
<T extends Obj.Unknown>(ref: Ref.Ref<T> | undefined): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Hook to subscribe to a Ref's target object, resolving a target that has been deleted.
|
|
51
|
+
*
|
|
52
|
+
* @param ref - The Ref to dereference and subscribe to
|
|
53
|
+
* @param options - `{ deleted: 'include' }` keeps a tombstoned target instead of reading it as undefined
|
|
54
|
+
* @returns The current target snapshot (or undefined if not loaded) and update callback
|
|
55
|
+
*/
|
|
56
|
+
<T extends Obj.Unknown>(
|
|
57
|
+
ref: Ref.Ref<T> | undefined,
|
|
58
|
+
options: Ref.LoadOptions,
|
|
59
|
+
): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
|
|
60
|
+
|
|
49
61
|
/**
|
|
50
62
|
* Hook to subscribe to an entire Echo object.
|
|
51
63
|
* Returns a snapshot of the current object value and automatically re-renders when the object changes.
|
|
@@ -117,7 +129,13 @@ export const useObject: {
|
|
|
117
129
|
* @returns The current property value (or undefined) and update callback
|
|
118
130
|
*/
|
|
119
131
|
<T, K extends keyof T>(ref: Ref.Ref<T> | undefined, property: K): [T[K] | undefined, ObjectPropUpdateCallback<T[K]>];
|
|
120
|
-
} = (<T extends Obj.Unknown, K extends keyof T>(
|
|
132
|
+
} = (<T extends Obj.Unknown, K extends keyof T>(
|
|
133
|
+
objOrRef: T | Ref.Ref<T> | undefined,
|
|
134
|
+
propertyOrOptions?: K | Ref.LoadOptions,
|
|
135
|
+
): any => {
|
|
136
|
+
const isOptions = typeof propertyOrOptions === 'object' && propertyOrOptions !== null;
|
|
137
|
+
const property = isOptions ? undefined : propertyOrOptions;
|
|
138
|
+
const options = isOptions ? propertyOrOptions : undefined;
|
|
121
139
|
const isRef = Ref.isRef(objOrRef);
|
|
122
140
|
const liveObj = useResolveRef(objOrRef);
|
|
123
141
|
|
|
@@ -151,7 +169,7 @@ export const useObject: {
|
|
|
151
169
|
if (property !== undefined) {
|
|
152
170
|
return [useObjectProperty(liveObj, property), callback];
|
|
153
171
|
} else {
|
|
154
|
-
return [useObjectValue(objOrRef), callback];
|
|
172
|
+
return [useObjectValue(objOrRef, options), callback];
|
|
155
173
|
}
|
|
156
174
|
}) as any;
|
|
157
175
|
|
|
@@ -160,19 +178,22 @@ export const useObject: {
|
|
|
160
178
|
*/
|
|
161
179
|
export const useObjectValue = <T extends Obj.Unknown | Obj.Snapshot>(
|
|
162
180
|
objOrRef: T | Ref.Ref<T> | undefined,
|
|
181
|
+
options?: Ref.LoadOptions,
|
|
163
182
|
): T extends Obj.Snapshot ? T : Obj.Snapshot<T & Obj.Unknown> | undefined => {
|
|
183
|
+
const deleted = options?.deleted;
|
|
164
184
|
const atom = useMemo(() => {
|
|
165
185
|
if (objOrRef == null) {
|
|
166
186
|
return Atom.make<Obj.Snapshot<T & Obj.Unknown> | undefined>(() => undefined);
|
|
167
187
|
}
|
|
168
188
|
if (Ref.isRef(objOrRef)) {
|
|
169
|
-
return Obj.atom(objOrRef);
|
|
189
|
+
return Obj.atom(objOrRef, { deleted });
|
|
170
190
|
}
|
|
171
191
|
if (Obj.isSnapshot(objOrRef)) {
|
|
172
192
|
return Atom.make<T>(() => objOrRef);
|
|
173
193
|
}
|
|
174
194
|
return Obj.atom(objOrRef as T & Obj.Unknown);
|
|
175
|
-
|
|
195
|
+
// Keyed on the option's value: an inline options object is a new identity on every render.
|
|
196
|
+
}, [objOrRef, deleted]);
|
|
176
197
|
return useAtomValue(atom as any);
|
|
177
198
|
};
|
|
178
199
|
|
|
@@ -9,7 +9,7 @@ import { Aggregate, Database, Feed, Filter, Obj, Order, Query } from '@dxos/echo
|
|
|
9
9
|
import { EchoTestBuilder } from '@dxos/echo-client/testing';
|
|
10
10
|
import { TestSchema } from '@dxos/echo/testing';
|
|
11
11
|
|
|
12
|
-
import { usePagination } from './usePagination';
|
|
12
|
+
import { usePagination } from './usePagination.ts';
|
|
13
13
|
|
|
14
14
|
describe('usePagination', () => {
|
|
15
15
|
let builder: EchoTestBuilder;
|
package/src/usePagination.ts
CHANGED
|
@@ -39,12 +39,8 @@ export type PaginationResult<T> = {
|
|
|
39
39
|
/** Reactive snapshot handed to React by `useSyncExternalStore`; a fresh object only on real change. */
|
|
40
40
|
type Snapshot<O> = { items: O[]; skip: number; limit: number; isLoading: boolean };
|
|
41
41
|
|
|
42
|
-
/**
|
|
43
|
-
* The element type a paginated query yields: the flat record for an aggregate query (branded with
|
|
44
|
-
* {@link Query.AggregateResult}), otherwise the query's entity type. Mirrors `useQuery`'s overloads.
|
|
45
|
-
*/
|
|
46
42
|
type PaginationElement<Q extends Query.Any> =
|
|
47
|
-
Query.Type<Q> extends Query.
|
|
43
|
+
Query.Type<Q> extends Query.RecordResult ? Query.Type<Q> : Entity.Entity<Query.Type<Q>>;
|
|
48
44
|
|
|
49
45
|
/**
|
|
50
46
|
* Builds the external store backing `usePagination` for one query identity (filter/order/page
|
package/src/useQuery.test.tsx
CHANGED
|
@@ -9,7 +9,7 @@ import { Aggregate, Filter, Obj, Query } from '@dxos/echo';
|
|
|
9
9
|
import { EchoTestBuilder } from '@dxos/echo-client/testing';
|
|
10
10
|
import { TestSchema } from '@dxos/echo/testing';
|
|
11
11
|
|
|
12
|
-
import { useQuery } from './useQuery';
|
|
12
|
+
import { useQuery } from './useQuery.ts';
|
|
13
13
|
|
|
14
14
|
describe('useQuery', () => {
|
|
15
15
|
let builder: EchoTestBuilder;
|
package/src/useQuery.ts
CHANGED
|
@@ -11,9 +11,8 @@ const EMPTY_ARRAY: never[] = [];
|
|
|
11
11
|
const noop = () => {};
|
|
12
12
|
|
|
13
13
|
interface UseQueryFn {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<R extends Query.AggregateResult>(resource: Database.Queryable | undefined, query: Query.Query<R>): R[];
|
|
14
|
+
<R extends Query.RecordResult>(resource: Database.Queryable | undefined, query: Query.Query<R>): R[];
|
|
15
|
+
<R extends Query.RecordResult>(resource: Database.Queryable | undefined, filter: Filter.Filter<R>): R[];
|
|
17
16
|
|
|
18
17
|
<Q extends Query.Any, O extends Entity.Entity<Query.Type<Q>> = Entity.Entity<Query.Type<Q>>>(
|
|
19
18
|
resource: Database.Queryable | undefined,
|
|
@@ -32,7 +31,7 @@ interface UseQueryFn {
|
|
|
32
31
|
* @param queryOrFilter - The query or filter to apply. Query is memoized based on the AST. No need to call useMemo.
|
|
33
32
|
*/
|
|
34
33
|
// The overloaded public signature returns `O[]` (entities) or the flat record `R[]` (aggregate
|
|
35
|
-
//
|
|
34
|
+
// rows and changes) depending on the query shape; the implementation forwards whatever the query result
|
|
36
35
|
// produces, so — as with any implementation of a multi-signature overloaded function type — it is
|
|
37
36
|
// typed as `any[]` here rather than picking one of the mutually-incompatible overload return shapes.
|
|
38
37
|
export const useQuery: UseQueryFn = (
|