entity-repository 0.2.1 → 0.3.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/react.d.ts +17 -4
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +23 -16
- package/package.json +2 -1
package/dist/react.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { type Observable } from "rxjs";
|
|
3
3
|
import type { ListQueryOptions, ListQueryState } from "./list-query";
|
|
4
|
-
import type { EntityConfig, EntityDefinitions, EntityIdTuple, RepositoryQuery } from "./types";
|
|
4
|
+
import type { EntityConfig, EntityDefinitions, EntityIdTuple, RepositoryConfig, RepositoryQuery } from "./types";
|
|
5
5
|
import { Repository } from "./repository";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Creates a typed entity repository plus the React hooks that operate on it.
|
|
8
|
+
*
|
|
9
|
+
* The factory OWNS the Repository instance — there's exactly one per call,
|
|
10
|
+
* and it's exposed as `repository` on the return. Consumers don't write
|
|
11
|
+
* `new Repository(...)`; they `import { repository }` and use it directly
|
|
12
|
+
* for code that runs outside React (e.g. seeding rows inside a fetcher
|
|
13
|
+
* closure). Components reach the same instance through the hooks.
|
|
14
|
+
*
|
|
15
|
+
* The `RepositoryProvider` is still emitted so a subtree can opt into a
|
|
16
|
+
* different repository for testing, but in normal use it's a passthrough
|
|
17
|
+
* — `useRepository()` returns the factory-owned singleton by default.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createRepositoryContext<Definitions extends EntityDefinitions, Config extends EntityConfig<Definitions> = EntityConfig<Definitions>>(config: RepositoryConfig<Definitions, Config>): {
|
|
20
|
+
repository: Repository<Definitions, Config>;
|
|
21
|
+
RepositoryProvider: ({ children }: {
|
|
9
22
|
children: ReactNode;
|
|
10
23
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
11
24
|
useRepository: () => Repository<Definitions, Config>;
|
package/dist/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,SAAS,EAA6E,MAAM,OAAO,CAAC;AAE5H,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,SAAS,EAA6E,MAAM,OAAO,CAAC;AAE5H,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACjH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,SAAS,iBAAiB,EACrC,MAAM,SAAS,YAAY,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,EACpE,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC;;uCAIH;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE;;yBAqCrC,KAAK,SAAS,MAAM,WAAW,SAClD,KAAK,MACR,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,WACpC,CAAC,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAC7F,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;6BA+CN,KAAK,SAAS,MAAM,WAAW,EAAE,KAAK,SAC7D,KAAK,SACL,KAAK,WACH,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,WACpC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,KACvD,cAAc,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;wBA/BV,KAAK,SAAS,MAAM,WAAW,EAAE,GAAG,SACtD,KAAK,OACP,GAAG,WACC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAC5C,WAAW,CAAC,KAAK,CAAC,EAAE;yBAtDK,KAAK,cAAc,UAAU,CAAC,KAAK,CAAC,eAAe,MAAM,KAAK;EA+G3F"}
|
package/dist/react.js
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
3
3
|
import { combineLatest, map } from "rxjs";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { Repository } from "./repository";
|
|
5
|
+
/**
|
|
6
|
+
* Creates a typed entity repository plus the React hooks that operate on it.
|
|
7
|
+
*
|
|
8
|
+
* The factory OWNS the Repository instance — there's exactly one per call,
|
|
9
|
+
* and it's exposed as `repository` on the return. Consumers don't write
|
|
10
|
+
* `new Repository(...)`; they `import { repository }` and use it directly
|
|
11
|
+
* for code that runs outside React (e.g. seeding rows inside a fetcher
|
|
12
|
+
* closure). Components reach the same instance through the hooks.
|
|
13
|
+
*
|
|
14
|
+
* The `RepositoryProvider` is still emitted so a subtree can opt into a
|
|
15
|
+
* different repository for testing, but in normal use it's a passthrough
|
|
16
|
+
* — `useRepository()` returns the factory-owned singleton by default.
|
|
17
|
+
*/
|
|
18
|
+
export function createRepositoryContext(config) {
|
|
19
|
+
const repository = new Repository(config);
|
|
20
|
+
const RepositoryReactContext = createContext(repository);
|
|
21
|
+
function RepositoryProvider({ children }) {
|
|
7
22
|
return (_jsx(RepositoryReactContext.Provider, { value: repository, children: children }));
|
|
8
23
|
}
|
|
9
24
|
function useRepository() {
|
|
10
|
-
|
|
11
|
-
if (!context) {
|
|
12
|
-
throw new Error("RepositoryProvider is missing.");
|
|
13
|
-
}
|
|
14
|
-
return context;
|
|
25
|
+
return useContext(RepositoryReactContext);
|
|
15
26
|
}
|
|
16
27
|
function useSubscribedState(observable, getSnapshot) {
|
|
17
28
|
const snapshotRef = useRef(getSnapshot());
|
|
@@ -32,9 +43,8 @@ export function createRepositoryContext() {
|
|
|
32
43
|
* query instance remains stable for a given `id`.
|
|
33
44
|
*/
|
|
34
45
|
function useRepositoryQuery(table, id, fetcher) {
|
|
35
|
-
const repository = useRepository();
|
|
36
46
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- table/fetcher intentionally ignored
|
|
37
|
-
const recordQuery = useMemo(() => repository.recordQuery(table, id, fetcher), [
|
|
47
|
+
const recordQuery = useMemo(() => repository.recordQuery(table, id, fetcher), [JSON.stringify(id)]);
|
|
38
48
|
return useSubscribedState(recordQuery.$state, () => recordQuery.$state.value);
|
|
39
49
|
}
|
|
40
50
|
/**
|
|
@@ -49,12 +59,9 @@ export function createRepositoryContext() {
|
|
|
49
59
|
* inputs, e.g. a task id).
|
|
50
60
|
*/
|
|
51
61
|
function useObservableList(table, key, options) {
|
|
52
|
-
const repository = useRepository();
|
|
53
62
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- table/options intentionally ignored (stable for a given key)
|
|
54
|
-
const observable = useMemo(() => repository.observableList(table, options), [
|
|
63
|
+
const observable = useMemo(() => repository.observableList(table, options), [JSON.stringify(key)]);
|
|
55
64
|
return useSubscribedState(observable, () => {
|
|
56
|
-
// Pull the current snapshot via a synchronous one-shot subscribe.
|
|
57
|
-
// observableList emits its first value synchronously.
|
|
58
65
|
let snapshot = [];
|
|
59
66
|
const sub = observable.subscribe((value) => {
|
|
60
67
|
snapshot = value;
|
|
@@ -70,9 +77,8 @@ export function createRepositoryContext() {
|
|
|
70
77
|
* list query instance remains stable for a given `param`.
|
|
71
78
|
*/
|
|
72
79
|
function useRepositoryListQuery(table, param, options, fetcher) {
|
|
73
|
-
const repository = useRepository();
|
|
74
80
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- table/options/fetcher intentionally ignored
|
|
75
|
-
const listQuery = useMemo(() => repository.listQuery(table, options, () => fetcher(param)), [
|
|
81
|
+
const listQuery = useMemo(() => repository.listQuery(table, options, () => fetcher(param)), [JSON.stringify(param)]);
|
|
76
82
|
useEffect(() => {
|
|
77
83
|
return () => listQuery.dispose();
|
|
78
84
|
}, [listQuery]);
|
|
@@ -80,6 +86,7 @@ export function createRepositoryContext() {
|
|
|
80
86
|
return useSubscribedState($state, () => ({ records: listQuery.$records.value, ...listQuery.$status.value }));
|
|
81
87
|
}
|
|
82
88
|
return {
|
|
89
|
+
repository,
|
|
83
90
|
RepositoryProvider,
|
|
84
91
|
useRepository,
|
|
85
92
|
useRepositoryQuery,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "entity-repository",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Type-safe entity caching and state management with RxJS and React",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^22.0.0",
|
|
56
56
|
"@types/react": "^19.2.8",
|
|
57
|
+
"react": "^19.0.0",
|
|
57
58
|
"tsx": "^4.19.0",
|
|
58
59
|
"typescript": "^5.9.3"
|
|
59
60
|
}
|