entity-repository 0.1.3 → 0.2.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 CHANGED
@@ -11,6 +11,7 @@ export declare function createRepositoryContext<Definitions extends EntityDefini
11
11
  useRepository: () => Repository<Definitions, Config>;
12
12
  useRepositoryQuery: <Table extends keyof Definitions>(table: Table, id: EntityIdTuple<Definitions, Config, Table>, fetcher: (id: EntityIdTuple<Definitions, Config, Table>) => Promise<Definitions[Table] | null>) => RepositoryQuery<Definitions[Table]>;
13
13
  useRepositoryListQuery: <Table extends keyof Definitions, Param>(table: Table, param: Param, options: ListQueryOptions<Definitions[Table]>, fetcher: (param: Param) => Promise<Definitions[Table][]>) => ListQueryState<Definitions[Table]>;
14
+ useObservableList: <Table extends keyof Definitions, Key>(table: Table, key: Key, options: ListQueryOptions<Definitions[Table]>) => Definitions[Table][];
14
15
  useSubscribedState: <Value>(observable: Observable<Value>, getSnapshot: () => Value) => Value;
15
16
  };
16
17
  //# sourceMappingURL=react.d.ts.map
@@ -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;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wBAAgB,uBAAuB,CACrC,WAAW,SAAS,iBAAiB,EACrC,MAAM,SAAS,YAAY,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC;oDAOjE;QACD,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC5C,QAAQ,EAAE,SAAS,CAAC;KACrB;;yBAyC2B,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;6BAiBN,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;yBAnDT,KAAK,cAAc,UAAU,CAAC,KAAK,CAAC,eAAe,MAAM,KAAK;EAgF3F"}
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;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wBAAgB,uBAAuB,CACrC,WAAW,SAAS,iBAAiB,EACrC,MAAM,SAAS,YAAY,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC;oDAOjE;QACD,UAAU,EAAE,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC5C,QAAQ,EAAE,SAAS,CAAC;KACrB;;yBAyC2B,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;6BAmDN,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;wBAlCV,KAAK,SAAS,MAAM,WAAW,EAAE,GAAG,SACtD,KAAK,OACP,GAAG,WACC,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAC5C,WAAW,CAAC,KAAK,CAAC,EAAE;yBAvDK,KAAK,cAAc,UAAU,CAAC,KAAK,CAAC,eAAe,MAAM,KAAK;EAmH3F"}
package/dist/react.js CHANGED
@@ -37,6 +37,32 @@ export function createRepositoryContext() {
37
37
  const recordQuery = useMemo(() => repository.recordQuery(table, id, fetcher), [repository, JSON.stringify(id)]);
38
38
  return useSubscribedState(recordQuery.$state, () => recordQuery.$state.value);
39
39
  }
40
+ /**
41
+ * Subscribes to a filtered/ordered observable view of the cache. Reads the
42
+ * current matching snapshot on mount, then re-emits whenever an
43
+ * insert/update/delete on the table changes the matching set. Unlike
44
+ * useRepositoryListQuery, there's no fetcher — this hook is the
45
+ * cold-start-safe read for data that's seeded elsewhere (typically by a
46
+ * sibling listQuery).
47
+ *
48
+ * `key` keys the memoization (use any value derived from the filter
49
+ * inputs, e.g. a task id).
50
+ */
51
+ function useObservableList(table, key, options) {
52
+ const repository = useRepository();
53
+ // 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), [repository, JSON.stringify(key)]);
55
+ return useSubscribedState(observable, () => {
56
+ // Pull the current snapshot via a synchronous one-shot subscribe.
57
+ // observableList emits its first value synchronously.
58
+ let snapshot = [];
59
+ const sub = observable.subscribe((value) => {
60
+ snapshot = value;
61
+ });
62
+ sub.unsubscribe();
63
+ return snapshot;
64
+ });
65
+ }
40
66
  /**
41
67
  * Subscribes to a list query keyed only by `param`.
42
68
  *
@@ -58,6 +84,7 @@ export function createRepositoryContext() {
58
84
  useRepository,
59
85
  useRepositoryQuery,
60
86
  useRepositoryListQuery,
87
+ useObservableList,
61
88
  useSubscribedState,
62
89
  };
63
90
  }
@@ -1,4 +1,4 @@
1
- import { BehaviorSubject, Subject } from "rxjs";
1
+ import { BehaviorSubject, Observable, Subject } from "rxjs";
2
2
  import type { EntityConfig, EntityDefinitions, EntityEvent, EntityIdTuple, RepositoryConfig } from "./types";
3
3
  import { ListQuery, type ListQueryOptions } from "./list-query";
4
4
  import { RecordQuery } from "./record-query";
@@ -12,6 +12,21 @@ export declare class Repository<Definitions extends EntityDefinitions, Config ex
12
12
  fetch<Table extends keyof Definitions>(table: Table, id: EntityIdTuple<Definitions, Config, Table>, fetcher: (id: EntityIdTuple<Definitions, Config, Table>) => Promise<Definitions[Table] | null>): Promise<Definitions[Table] | null>;
13
13
  getObservable<Table extends keyof Definitions>(table: Table, id: EntityIdTuple<Definitions, Config, Table>): BehaviorSubject<Definitions[Table] | null>;
14
14
  getEvents<Table extends keyof Definitions>(table: Table): Subject<EntityEvent<Definitions[Table]>>;
15
+ /**
16
+ * Observable view of the cache for `table`, optionally filtered and
17
+ * ordered. On subscribe, emits the current matching snapshot
18
+ * synchronously (no cold-start race against a non-replaying event
19
+ * Subject), then emits a new array whenever an insert/update/delete on
20
+ * the table changes the matching set.
21
+ *
22
+ * Use this when a subscriber needs to mount AFTER the data may already
23
+ * have been seeded — e.g. a per-row tag query mounted when the parent
24
+ * task row renders, where the parent's fetch already filled the cache.
25
+ *
26
+ * Returned arrays are immutable snapshots — each emission is a fresh
27
+ * array, so React subscribers can compare by reference.
28
+ */
29
+ observableList<Table extends keyof Definitions>(table: Table, options?: ListQueryOptions<Definitions[Table]>): Observable<Definitions[Table][]>;
15
30
  recordQuery<Table extends keyof Definitions>(table: Table, id: EntityIdTuple<Definitions, Config, Table>, fetcher: (id: EntityIdTuple<Definitions, Config, Table>) => Promise<Definitions[Table] | null>): RecordQuery<Definitions, Config, Table>;
16
31
  getCacheKey<Table extends keyof Definitions>(table: Table, id: EntityIdTuple<Definitions, Config, Table>): string;
17
32
  getEntityKey<Table extends keyof Definitions>(table: Table, entity: Definitions[Table]): string;
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE5D,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,gBAAgB,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAS7C,qBAAa,UAAU,CACrB,WAAW,SAAS,iBAAiB,EACrC,MAAM,SAAS,YAAY,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC;IAEpE,OAAO,CAAC,MAAM,CAAqD;IACnE,OAAO,CAAC,MAAM,CAAwC;gBAE1C,MAAM,EAAE,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC;IAIzD,GAAG,CAAC,KAAK,SAAS,MAAM,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC;IA4B7E,GAAG,CAAC,KAAK,SAAS,MAAM,WAAW,EACjC,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC;IAsB/C,GAAG,CAAC,KAAK,SAAS,MAAM,WAAW,EACjC,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,GAC5C,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI;IAQtB,KAAK,CAAC,KAAK,SAAS,MAAM,WAAW,EACzC,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAC7C,OAAO,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAC7F,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IA+BrC,aAAa,CAAC,KAAK,SAAS,MAAM,WAAW,EAC3C,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,GAC5C,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAgB7C,SAAS,CAAC,KAAK,SAAS,MAAM,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAKlG;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,KAAK,SAAS,MAAM,WAAW,EAC5C,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAM,GACjD,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;IAsDnC,WAAW,CAAC,KAAK,SAAS,MAAM,WAAW,EACzC,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAC7C,OAAO,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAC7F,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC;IAI1C,WAAW,CAAC,KAAK,SAAS,MAAM,WAAW,EACzC,KAAK,EAAE,KAAK,EACZ,EAAE,EAAE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,GAC5C,MAAM;IAIT,YAAY,CAAC,KAAK,SAAS,MAAM,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,MAAM;IAI/F,SAAS,CAAC,KAAK,SAAS,MAAM,WAAW,EACvC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAC7C,OAAO,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,GAC3C,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC;IAIxC,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,qBAAqB;CAa9B"}
@@ -1,4 +1,4 @@
1
- import { BehaviorSubject, Subject } from "rxjs";
1
+ import { BehaviorSubject, Observable, Subject } from "rxjs";
2
2
  import { ListQuery } from "./list-query";
3
3
  import { RecordQuery } from "./record-query";
4
4
  export class Repository {
@@ -95,6 +95,69 @@ export class Repository {
95
95
  const store = this.getStore(table);
96
96
  return store.events$;
97
97
  }
98
+ /**
99
+ * Observable view of the cache for `table`, optionally filtered and
100
+ * ordered. On subscribe, emits the current matching snapshot
101
+ * synchronously (no cold-start race against a non-replaying event
102
+ * Subject), then emits a new array whenever an insert/update/delete on
103
+ * the table changes the matching set.
104
+ *
105
+ * Use this when a subscriber needs to mount AFTER the data may already
106
+ * have been seeded — e.g. a per-row tag query mounted when the parent
107
+ * task row renders, where the parent's fetch already filled the cache.
108
+ *
109
+ * Returned arrays are immutable snapshots — each emission is a fresh
110
+ * array, so React subscribers can compare by reference.
111
+ */
112
+ observableList(table, options = {}) {
113
+ const store = this.getStore(table);
114
+ const filterFn = options.filter ?? (() => true);
115
+ const orderFn = options.order ?? null;
116
+ const applyOrder = (records) => orderFn ? [...records].sort(orderFn) : records;
117
+ return new Observable((subscriber) => {
118
+ let current = applyOrder(Array.from(store.records.values()).filter(filterFn));
119
+ subscriber.next(current);
120
+ const eventsSub = store.events$.subscribe((event) => {
121
+ switch (event.type) {
122
+ case "insert":
123
+ case "update": {
124
+ const passes = filterFn(event.new);
125
+ const key = this.getEntityKey(table, event.new);
126
+ const index = current.findIndex((record) => this.getEntityKey(table, record) === key);
127
+ if (!passes) {
128
+ if (index === -1)
129
+ return;
130
+ const next = current.slice();
131
+ next.splice(index, 1);
132
+ current = applyOrder(next);
133
+ subscriber.next(current);
134
+ return;
135
+ }
136
+ const next = current.slice();
137
+ if (index === -1)
138
+ next.push(event.new);
139
+ else
140
+ next[index] = event.new;
141
+ current = applyOrder(next);
142
+ subscriber.next(current);
143
+ return;
144
+ }
145
+ case "delete": {
146
+ const key = this.getEntityKey(table, event.old);
147
+ const index = current.findIndex((record) => this.getEntityKey(table, record) === key);
148
+ if (index === -1)
149
+ return;
150
+ const next = current.slice();
151
+ next.splice(index, 1);
152
+ current = applyOrder(next);
153
+ subscriber.next(current);
154
+ return;
155
+ }
156
+ }
157
+ });
158
+ return () => eventsSub.unsubscribe();
159
+ });
160
+ }
98
161
  recordQuery(table, id, fetcher) {
99
162
  return new RecordQuery(this, table, id, fetcher);
100
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "entity-repository",
3
- "version": "0.1.3",
3
+ "version": "0.2.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",
@@ -17,6 +17,8 @@
17
17
  "scripts": {
18
18
  "build": "tsc",
19
19
  "clean": "rm -rf dist",
20
+ "test": "node --import tsx --test tests/*.test.ts",
21
+ "prepare": "npm run build",
20
22
  "prepublishOnly": "npm run clean && npm run build"
21
23
  },
22
24
  "keywords": [
@@ -50,7 +52,9 @@
50
52
  }
51
53
  },
52
54
  "devDependencies": {
55
+ "@types/node": "^22.0.0",
53
56
  "@types/react": "^19.2.8",
57
+ "tsx": "^4.19.0",
54
58
  "typescript": "^5.9.3"
55
59
  }
56
60
  }