@livestore/react 0.2.0 → 0.3.0-dev.11

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.
Files changed (87) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/LiveStoreContext.d.ts +5 -3
  3. package/dist/LiveStoreContext.d.ts.map +1 -1
  4. package/dist/LiveStoreContext.js +7 -3
  5. package/dist/LiveStoreContext.js.map +1 -1
  6. package/dist/LiveStoreProvider.d.ts +6 -4
  7. package/dist/LiveStoreProvider.d.ts.map +1 -1
  8. package/dist/LiveStoreProvider.js +47 -45
  9. package/dist/LiveStoreProvider.js.map +1 -1
  10. package/dist/LiveStoreProvider.test.js +8 -2
  11. package/dist/LiveStoreProvider.test.js.map +1 -1
  12. package/dist/__tests__/fixture.d.ts +7 -10
  13. package/dist/__tests__/fixture.d.ts.map +1 -1
  14. package/dist/__tests__/fixture.js +10 -15
  15. package/dist/__tests__/fixture.js.map +1 -1
  16. package/dist/experimental/components/LiveList.d.ts +2 -2
  17. package/dist/experimental/components/LiveList.d.ts.map +1 -1
  18. package/dist/experimental/components/LiveList.js +5 -4
  19. package/dist/experimental/components/LiveList.js.map +1 -1
  20. package/dist/mod.d.ts +0 -1
  21. package/dist/mod.d.ts.map +1 -1
  22. package/dist/mod.js +0 -1
  23. package/dist/mod.js.map +1 -1
  24. package/dist/useAtom.d.ts +4 -2
  25. package/dist/useAtom.d.ts.map +1 -1
  26. package/dist/useAtom.js +32 -28
  27. package/dist/useAtom.js.map +1 -1
  28. package/dist/useQuery.d.ts +26 -3
  29. package/dist/useQuery.d.ts.map +1 -1
  30. package/dist/useQuery.js +60 -45
  31. package/dist/useQuery.js.map +1 -1
  32. package/dist/useQuery.test.js +70 -16
  33. package/dist/useQuery.test.js.map +1 -1
  34. package/dist/useRcRef.d.ts +72 -0
  35. package/dist/useRcRef.d.ts.map +1 -0
  36. package/dist/useRcRef.js +146 -0
  37. package/dist/useRcRef.js.map +1 -0
  38. package/dist/useRcRef.test.d.ts +2 -0
  39. package/dist/useRcRef.test.d.ts.map +1 -0
  40. package/dist/useRcRef.test.js +128 -0
  41. package/dist/useRcRef.test.js.map +1 -0
  42. package/dist/useRcResource.d.ts +76 -0
  43. package/dist/useRcResource.d.ts.map +1 -0
  44. package/dist/useRcResource.js +150 -0
  45. package/dist/useRcResource.js.map +1 -0
  46. package/dist/useRcResource.test.d.ts +2 -0
  47. package/dist/useRcResource.test.d.ts.map +1 -0
  48. package/dist/useRcResource.test.js +122 -0
  49. package/dist/useRcResource.test.js.map +1 -0
  50. package/dist/useRow.d.ts +10 -7
  51. package/dist/useRow.d.ts.map +1 -1
  52. package/dist/useRow.js +16 -19
  53. package/dist/useRow.js.map +1 -1
  54. package/dist/useRow.test.js +74 -97
  55. package/dist/useRow.test.js.map +1 -1
  56. package/dist/useScopedQuery.d.ts +10 -4
  57. package/dist/useScopedQuery.d.ts.map +1 -1
  58. package/dist/useScopedQuery.js +97 -52
  59. package/dist/useScopedQuery.js.map +1 -1
  60. package/dist/useScopedQuery.test.js +13 -12
  61. package/dist/useScopedQuery.test.js.map +1 -1
  62. package/dist/utils/useStateRefWithReactiveInput.d.ts +1 -1
  63. package/dist/utils/useStateRefWithReactiveInput.d.ts.map +1 -1
  64. package/dist/utils/useStateRefWithReactiveInput.js.map +1 -1
  65. package/package.json +18 -17
  66. package/src/LiveStoreContext.ts +10 -6
  67. package/src/LiveStoreProvider.test.tsx +13 -2
  68. package/src/LiveStoreProvider.tsx +69 -53
  69. package/src/__snapshots__/useQuery.test.tsx.snap +2011 -0
  70. package/src/__snapshots__/useRow.test.tsx.snap +347 -151
  71. package/src/__tests__/fixture.tsx +11 -19
  72. package/src/experimental/components/LiveList.tsx +8 -7
  73. package/src/mod.ts +0 -1
  74. package/src/useAtom.ts +22 -11
  75. package/src/useQuery.test.tsx +165 -67
  76. package/src/useQuery.ts +84 -54
  77. package/src/useRcResource.test.tsx +167 -0
  78. package/src/useRcResource.ts +180 -0
  79. package/src/useRow.test.tsx +130 -164
  80. package/src/useRow.ts +32 -35
  81. package/src/utils/useStateRefWithReactiveInput.ts +1 -1
  82. package/dist/useTemporaryQuery.d.ts +0 -22
  83. package/dist/useTemporaryQuery.d.ts.map +0 -1
  84. package/dist/useTemporaryQuery.js +0 -75
  85. package/dist/useTemporaryQuery.js.map +0 -1
  86. package/src/useScopedQuery.test.tsx +0 -96
  87. package/src/useScopedQuery.ts +0 -142
@@ -0,0 +1,122 @@
1
+ import * as ReactTesting from '@testing-library/react';
2
+ import * as React from 'react';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { __resetUseRcResourceCache, useRcResource } from './useRcResource.js';
5
+ describe.each([{ strictMode: true }, { strictMode: false }])('useRcResource (strictMode=%s)', ({ strictMode }) => {
6
+ beforeEach(() => {
7
+ __resetUseRcResourceCache();
8
+ });
9
+ const wrapper = strictMode ? React.StrictMode : React.Fragment;
10
+ it('should create a stateful entity using make and call cleanup on unmount', () => {
11
+ const makeSpy = vi.fn(() => Symbol('statefulResource'));
12
+ const cleanupSpy = vi.fn();
13
+ const { result, unmount } = ReactTesting.renderHook(() => useRcResource('key-1', makeSpy, cleanupSpy), { wrapper });
14
+ expect(makeSpy).toHaveBeenCalledTimes(1);
15
+ expect(result.current).toBeDefined();
16
+ expect(cleanupSpy).toHaveBeenCalledTimes(0);
17
+ unmount();
18
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
19
+ });
20
+ it('should reuse the same entity when the key remains unchanged', () => {
21
+ const makeSpy = vi.fn(() => Symbol('statefulResource'));
22
+ const cleanupSpy = vi.fn();
23
+ const { result, rerender, unmount } = ReactTesting.renderHook(({ key }) => useRcResource(key, makeSpy, cleanupSpy), { initialProps: { key: 'consistent-key' }, wrapper });
24
+ const instance1 = result.current;
25
+ // Re-render with the same key
26
+ rerender({ key: 'consistent-key' });
27
+ const instance2 = result.current;
28
+ expect(instance1).toBe(instance2);
29
+ expect(makeSpy).toHaveBeenCalledTimes(1);
30
+ unmount();
31
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
32
+ });
33
+ it('should dispose the previous instance when the key changes', () => {
34
+ const makeSpy = vi.fn(() => Symbol('statefulResource'));
35
+ const cleanupSpy = vi.fn();
36
+ const { result, rerender, unmount } = ReactTesting.renderHook(({ key }) => useRcResource(key, makeSpy, cleanupSpy), { initialProps: { key: 'a' }, wrapper });
37
+ const instanceA = result.current;
38
+ // Change the key; this should trigger the disposal of the 'a' instance
39
+ rerender({ key: 'b' });
40
+ const instanceB = result.current;
41
+ expect(instanceA).not.toBe(instanceB);
42
+ expect(makeSpy).toHaveBeenCalledTimes(2);
43
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
44
+ unmount();
45
+ expect(cleanupSpy).toHaveBeenCalledTimes(2);
46
+ });
47
+ it('should not dispose the entity until all consumers unmount', () => {
48
+ const makeSpy = vi.fn(() => Symbol('statefulResource'));
49
+ const cleanupSpy = vi.fn();
50
+ // Simulate two consumers using the same key independently.
51
+ const { unmount: unmount1 } = ReactTesting.renderHook(() => useRcResource('shared-key', makeSpy, cleanupSpy), {
52
+ wrapper,
53
+ });
54
+ const { unmount: unmount2, result } = ReactTesting.renderHook(() => useRcResource('shared-key', makeSpy, cleanupSpy), {
55
+ wrapper,
56
+ });
57
+ expect(result.current).toBeDefined();
58
+ expect(makeSpy).toHaveBeenCalledTimes(1);
59
+ // Unmount first consumer; the entity should remain active.
60
+ unmount1();
61
+ expect(cleanupSpy).not.toHaveBeenCalled();
62
+ // Unmount second consumer; now the entity is disposed.
63
+ unmount2();
64
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
65
+ });
66
+ it('should handle rapid key changes correctly', () => {
67
+ const makeSpy = vi.fn(() => Symbol('statefulResource'));
68
+ const cleanupSpy = vi.fn();
69
+ const { rerender, unmount } = ReactTesting.renderHook(({ key }) => useRcResource(key, makeSpy, cleanupSpy), {
70
+ initialProps: { key: '1' },
71
+ wrapper,
72
+ });
73
+ // Rapid sequence of key changes.
74
+ rerender({ key: '2' });
75
+ rerender({ key: '3' });
76
+ // Expect three creations: one each for keys '1', '2', '3'
77
+ expect(makeSpy).toHaveBeenCalledTimes(3);
78
+ // Cleanup should have been triggered for key '1' and key '2'
79
+ expect(cleanupSpy).toHaveBeenCalledTimes(2);
80
+ unmount();
81
+ // Unmounting the final consumer disposes the key '3' instance.
82
+ expect(cleanupSpy).toHaveBeenCalledTimes(3);
83
+ });
84
+ });
85
+ // This code was useful to better understand the hook behaviour with and without strict mode
86
+ // describe('debug', () => {
87
+ // const useStrictTest = (key: string) => {
88
+ // const id = React.useId()
89
+ // console.log(key, 'id', id)
90
+ // const x = React.useMemo(() => {
91
+ // console.log('useMemo', key)
92
+ // return 'hi' + key
93
+ // }, [key])
94
+ // React.useEffect(() => {
95
+ // console.log('useEffect', key)
96
+ // return () => {
97
+ // console.log('unmount', key)
98
+ // }
99
+ // }, [])
100
+ // return x
101
+ // }
102
+ // it('strict mode component', () => {
103
+ // console.log('strict mode component')
104
+ // const Root = () => {
105
+ // useStrictTest('a')
106
+ // return null
107
+ // }
108
+ // const { unmount } = ReactTesting.render(
109
+ // <React.StrictMode>
110
+ // <Root />
111
+ // </React.StrictMode>,
112
+ // )
113
+ // unmount()
114
+ // })
115
+ // it('strict mode hook', () => {
116
+ // console.log('strict mode hook')
117
+ // const wrapper: React.FC<{ children: React.ReactNode }> = React.StrictMode
118
+ // const { unmount } = ReactTesting.renderHook(() => useStrictTest('b'), { wrapper })
119
+ // unmount()
120
+ // })
121
+ // })
122
+ //# sourceMappingURL=useRcResource.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRcResource.test.js","sourceRoot":"","sources":["../src/useRcResource.test.tsx"],"names":[],"mappings":"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"}
package/dist/useRow.d.ts CHANGED
@@ -1,15 +1,12 @@
1
1
  import type { QueryInfo, RowQuery } from '@livestore/common';
2
2
  import { SessionIdSymbol } from '@livestore/common';
3
3
  import { DbSchema } from '@livestore/common/schema';
4
- import type { LiveQuery, ReactivityGraph } from '@livestore/livestore';
4
+ import type { LiveQuery, Store } from '@livestore/livestore';
5
5
  export type UseRowResult<TTableDef extends DbSchema.TableDefBase> = [
6
6
  row: RowQuery.Result<TTableDef>,
7
7
  setRow: StateSetters<TTableDef>,
8
8
  query$: LiveQuery<RowQuery.Result<TTableDef>, QueryInfo>
9
9
  ];
10
- export type UseRowOptionsBase = {
11
- reactivityGraph?: ReactivityGraph;
12
- };
13
10
  /**
14
11
  * Similar to `React.useState` but returns a tuple of `[row, setRow, query$]` for a given table where ...
15
12
  *
@@ -25,20 +22,26 @@ export declare const useRow: {
25
22
  deriveMutations: {
26
23
  enabled: true;
27
24
  };
28
- }>>(table: TTableDef, options?: UseRowOptionsBase): UseRowResult<TTableDef>;
25
+ }>>(table: TTableDef, options?: {
26
+ store?: Store;
27
+ }): UseRowResult<TTableDef>;
29
28
  <TTableDef extends DbSchema.TableDef<DbSchema.DefaultSqliteTableDef, DbSchema.TableOptions & {
30
29
  isSingleton: false;
31
30
  requiredInsertColumnNames: 'id';
32
31
  deriveMutations: {
33
32
  enabled: true;
34
33
  };
35
- }>>(table: TTableDef, id: string | SessionIdSymbol, options?: UseRowOptionsBase & Partial<RowQuery.RequiredColumnsOptions<TTableDef>>): UseRowResult<TTableDef>;
34
+ }>>(table: TTableDef, id: string | SessionIdSymbol, options?: Partial<RowQuery.RequiredColumnsOptions<TTableDef>> & {
35
+ store?: Store;
36
+ }): UseRowResult<TTableDef>;
36
37
  <TTableDef extends DbSchema.TableDef<DbSchema.DefaultSqliteTableDef, DbSchema.TableOptions & {
37
38
  isSingleton: false;
38
39
  deriveMutations: {
39
40
  enabled: true;
40
41
  };
41
- }>>(table: TTableDef, id: string | SessionIdSymbol, options: UseRowOptionsBase & RowQuery.RequiredColumnsOptions<TTableDef>): UseRowResult<TTableDef>;
42
+ }>>(table: TTableDef, id: string | SessionIdSymbol, options: RowQuery.RequiredColumnsOptions<TTableDef> & {
43
+ store?: Store;
44
+ }): UseRowResult<TTableDef>;
42
45
  };
43
46
  export type Dispatch<A> = (action: A) => void;
44
47
  export type SetStateAction<S> = S | ((previousValue: S) => S);
@@ -1 +1 @@
1
- {"version":3,"file":"useRow.d.ts","sourceRoot":"","sources":["../src/useRow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useRow.d.ts","sourceRoot":"","sources":["../src/useRow.ts"],"names":[],"mappings":"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"}
package/dist/useRow.js CHANGED
@@ -6,7 +6,6 @@ import { ReadonlyRecord } from '@livestore/utils/effect';
6
6
  import React from 'react';
7
7
  import { useStore } from './LiveStoreContext.js';
8
8
  import { useQueryRef } from './useQuery.js';
9
- import { useMakeScopedQuery } from './useScopedQuery.js';
10
9
  /**
11
10
  * Similar to `React.useState` but returns a tuple of `[row, setRow, query$]` for a given table where ...
12
11
  *
@@ -20,12 +19,12 @@ export const useRow = (table, idOrOptions, options_) => {
20
19
  const sqliteTableDef = table.sqliteDef;
21
20
  const id = typeof idOrOptions === 'string' || idOrOptions === SessionIdSymbol ? idOrOptions : undefined;
22
21
  const options = typeof idOrOptions === 'string' || idOrOptions === SessionIdSymbol ? options_ : idOrOptions;
23
- const { insertValues, reactivityGraph } = options ?? {};
22
+ const { insertValues } = options ?? {};
24
23
  const tableName = table.sqliteDef.name;
25
24
  if (DbSchema.tableHasDerivedMutations(table) === false) {
26
25
  shouldNeverHappen(`useRow called on table "${tableName}" which does not have 'deriveMutations: true' set`);
27
26
  }
28
- const { store } = useStore();
27
+ const { store } = useStore({ store: options?.store });
29
28
  if (store.schema.tables.has(table.sqliteDef.name) === false &&
30
29
  table.sqliteDef.name.startsWith('__livestore') === false) {
31
30
  shouldNeverHappen(`Table "${table.sqliteDef.name}" not found in schema`);
@@ -33,20 +32,18 @@ export const useRow = (table, idOrOptions, options_) => {
33
32
  // console.debug('useRow', tableName, id)
34
33
  const idStr = id === SessionIdSymbol ? 'session' : id;
35
34
  const rowQuery = table.query.row;
36
- const { query$, otelContext } = useMakeScopedQuery((otelContext) => DbSchema.tableIsSingleton(table)
37
- ? queryDb(rowQuery(), { reactivityGraph, otelContext })
38
- : queryDb(rowQuery(id, { insertValues: insertValues }), { reactivityGraph, otelContext }), [idStr, tableName], {
39
- otel: {
40
- spanName: `LiveStore:useRow:${tableName}${idStr === undefined ? '' : `:${idStr}`}`,
41
- attributes: { id: idStr },
42
- },
35
+ const queryDef = React.useMemo(() => DbSchema.tableIsSingleton(table)
36
+ ? queryDb(rowQuery(), {})
37
+ : queryDb(rowQuery(id, { insertValues: insertValues }), { deps: idStr }), [id, insertValues, rowQuery, table, idStr]);
38
+ const queryRef = useQueryRef(queryDef, {
39
+ otelSpanName: `LiveStore:useRow:${tableName}${idStr === undefined ? '' : `:${idStr}`}`,
40
+ store: options?.store,
43
41
  });
44
- const query$Ref = useQueryRef(query$, otelContext);
45
42
  const setState = React.useMemo(() => {
46
43
  if (table.options.isSingleColumn) {
47
44
  return (newValueOrFn) => {
48
- const newValue = typeof newValueOrFn === 'function' ? newValueOrFn(query$Ref.current) : newValueOrFn;
49
- if (query$Ref.current === newValue)
45
+ const newValue = typeof newValueOrFn === 'function' ? newValueOrFn(queryRef.valueRef.current) : newValueOrFn;
46
+ if (queryRef.valueRef.current === newValue)
50
47
  return;
51
48
  // NOTE we need to account for the short-hand syntax for single-column+singleton tables
52
49
  if (table.options.isSingleton) {
@@ -63,10 +60,10 @@ export const useRow = (table, idOrOptions, options_) => {
63
60
  ReadonlyRecord.map(sqliteTableDef.columns, (column, columnName) => (newValueOrFn) => {
64
61
  const newValue =
65
62
  // @ts-expect-error TODO fix typing
66
- typeof newValueOrFn === 'function' ? newValueOrFn(query$Ref.current[columnName]) : newValueOrFn;
63
+ typeof newValueOrFn === 'function' ? newValueOrFn(queryRef.valueRef.current[columnName]) : newValueOrFn;
67
64
  // Don't update the state if it's the same as the value already seen in the component
68
65
  // @ts-expect-error TODO fix typing
69
- if (query$Ref.current[columnName] === newValue)
66
+ if (queryRef.valueRef.current[columnName] === newValue)
70
67
  return;
71
68
  store.mutate(table.update({ where: { id: id ?? 'singleton' }, values: { [columnName]: newValue } }));
72
69
  // store.mutate(updateMutationForQueryInfo(query$.queryInfo!, { [columnName]: newValue }))
@@ -74,12 +71,12 @@ export const useRow = (table, idOrOptions, options_) => {
74
71
  setState.setMany = (columnValuesOrFn) => {
75
72
  const columnValues =
76
73
  // @ts-expect-error TODO fix typing
77
- typeof columnValuesOrFn === 'function' ? columnValuesOrFn(query$Ref.current) : columnValuesOrFn;
74
+ typeof columnValuesOrFn === 'function' ? columnValuesOrFn(queryRef.valueRef.current) : columnValuesOrFn;
78
75
  // TODO use hashing instead
79
76
  // Don't update the state if it's the same as the value already seen in the component
80
77
  if (
81
78
  // @ts-expect-error TODO fix typing
82
- Object.entries(columnValues).every(([columnName, value]) => query$Ref.current[columnName] === value)) {
79
+ Object.entries(columnValues).every(([columnName, value]) => queryRef.valueRef.current[columnName] === value)) {
83
80
  return;
84
81
  }
85
82
  store.mutate(table.update({ where: { id: id ?? 'singleton' }, values: columnValues }));
@@ -87,7 +84,7 @@ export const useRow = (table, idOrOptions, options_) => {
87
84
  };
88
85
  return setState;
89
86
  }
90
- }, [id, query$Ref, sqliteTableDef.columns, store, table]);
91
- return [query$Ref.current, setState, query$];
87
+ }, [id, queryRef.valueRef, sqliteTableDef.columns, store, table]);
88
+ return [queryRef.valueRef.current, setState, queryRef.queryRcRef.value];
92
89
  };
93
90
  //# sourceMappingURL=useRow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRow.js","sourceRoot":"","sources":["../src/useRow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useRow.js","sourceRoot":"","sources":["../src/useRow.ts"],"names":[],"mappings":"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"}
@@ -1,85 +1,77 @@
1
1
  import * as LiveStore from '@livestore/livestore';
2
2
  import { getSimplifiedRootSpan } from '@livestore/livestore/internal/testing-utils';
3
3
  import { Effect, ReadonlyRecord, Schema } from '@livestore/utils/effect';
4
+ import { Vitest } from '@livestore/utils/node-vitest';
4
5
  import * as otel from '@opentelemetry/api';
5
6
  import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
6
- import { render, renderHook } from '@testing-library/react';
7
+ import * as ReactTesting from '@testing-library/react';
7
8
  import React from 'react';
8
- import { describe, expect, it } from 'vitest';
9
- import { AppComponentSchema, AppRouterSchema, makeTodoMvcReact, tables, todos } from './__tests__/fixture.js';
9
+ import { beforeEach, expect, it } from 'vitest';
10
+ import { AppRouterSchema, makeTodoMvcReact, tables, todos } from './__tests__/fixture.js';
10
11
  import * as LiveStoreReact from './mod.js';
12
+ import { __resetUseRcResourceCache } from './useRcResource.js';
13
+ // const strictMode = process.env.REACT_STRICT_MODE !== undefined
11
14
  // NOTE running tests concurrently doesn't work with the default global db graph
12
- describe('useRow', () => {
13
- it('should update the data based on component key', () => Effect.gen(function* () {
14
- const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
15
- useGlobalReactivityGraph: false,
16
- });
17
- const renderCount = makeRenderCount();
18
- const { result, rerender } = renderHook((userId) => {
15
+ Vitest.describe('useRow', () => {
16
+ beforeEach(() => {
17
+ __resetUseRcResourceCache();
18
+ });
19
+ Vitest.scopedLive('should update the data based on component key', () => Effect.gen(function* () {
20
+ const { wrapper, store, renderCount } = yield* makeTodoMvcReact({});
21
+ const { result, rerender } = ReactTesting.renderHook((userId) => {
19
22
  renderCount.inc();
20
- const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
23
+ const [state, setState] = LiveStoreReact.useRow(tables.userInfo, userId);
21
24
  return { state, setState };
22
25
  }, { wrapper, initialProps: 'u1' });
23
26
  expect(result.current.state.id).toBe('u1');
24
27
  expect(result.current.state.username).toBe('');
25
28
  expect(renderCount.val).toBe(1);
26
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
27
- sql: LiveStore.sql `INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
28
- })));
29
+ expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
30
+ store.mutate(tables.userInfo.insert({ id: 'u2', username: 'username_u2' }));
29
31
  rerender('u2');
32
+ expect(store.reactivityGraph.getSnapshot({ includeResults: true })).toMatchSnapshot();
30
33
  expect(result.current.state.id).toBe('u2');
31
34
  expect(result.current.state.username).toBe('username_u2');
32
35
  expect(renderCount.val).toBe(2);
33
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
36
+ }));
34
37
  // TODO add a test that makes sure React doesn't re-render when a setter is used to set the same value
35
- it('should update the data reactively - via setState', () => Effect.gen(function* () {
36
- const { wrapper, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
37
- useGlobalReactivityGraph: false,
38
- });
39
- const renderCount = makeRenderCount();
40
- const { result } = renderHook((userId) => {
38
+ Vitest.scopedLive('should update the data reactively - via setState', () => Effect.gen(function* () {
39
+ const { wrapper, renderCount } = yield* makeTodoMvcReact({});
40
+ const { result } = ReactTesting.renderHook((userId) => {
41
41
  renderCount.inc();
42
- const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
42
+ const [state, setState] = LiveStoreReact.useRow(tables.userInfo, userId);
43
43
  return { state, setState };
44
44
  }, { wrapper, initialProps: 'u1' });
45
45
  expect(result.current.state.id).toBe('u1');
46
46
  expect(result.current.state.username).toBe('');
47
47
  expect(renderCount.val).toBe(1);
48
- React.act(() => result.current.setState.username('username_u1_hello'));
48
+ ReactTesting.act(() => result.current.setState.username('username_u1_hello'));
49
49
  expect(result.current.state.id).toBe('u1');
50
50
  expect(result.current.state.username).toBe('username_u1_hello');
51
51
  expect(renderCount.val).toBe(2);
52
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
53
- it('should update the data reactively - via raw store mutation', () => Effect.gen(function* () {
54
- const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
55
- useGlobalReactivityGraph: false,
56
- });
57
- const renderCount = makeRenderCount();
58
- const { result } = renderHook((userId) => {
52
+ }));
53
+ Vitest.scopedLive('should update the data reactively - via raw store mutation', () => Effect.gen(function* () {
54
+ const { wrapper, store, renderCount } = yield* makeTodoMvcReact({});
55
+ const { result } = ReactTesting.renderHook((userId) => {
59
56
  renderCount.inc();
60
- const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
57
+ const [state, setState] = LiveStoreReact.useRow(tables.userInfo, userId);
61
58
  return { state, setState };
62
59
  }, { wrapper, initialProps: 'u1' });
63
60
  expect(result.current.state.id).toBe('u1');
64
61
  expect(result.current.state.username).toBe('');
65
62
  expect(renderCount.val).toBe(1);
66
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
67
- sql: LiveStore.sql `UPDATE UserInfo SET username = 'username_u1_hello' WHERE id = 'u1';`,
68
- })));
63
+ ReactTesting.act(() => store.mutate(tables.userInfo.update({ where: { id: 'u1' }, values: { username: 'username_u1_hello' } })));
69
64
  expect(result.current.state.id).toBe('u1');
70
65
  expect(result.current.state.username).toBe('username_u1_hello');
71
66
  expect(renderCount.val).toBe(2);
72
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
73
- it('should work for a larger app', () => Effect.gen(function* () {
74
- const { wrapper, store, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
75
- useGlobalReactivityGraph: false,
76
- });
77
- const allTodos$ = LiveStore.queryDb({ query: `select * from todos`, schema: Schema.Array(tables.todos.schema) }, { label: 'allTodos', reactivityGraph });
78
- const appRouterRenderCount = makeRenderCount();
67
+ }));
68
+ Vitest.scopedLive('should work for a larger app', () => Effect.gen(function* () {
69
+ const { wrapper, store, renderCount } = yield* makeTodoMvcReact({});
70
+ const allTodos$ = LiveStore.queryDb({ query: `select * from todos`, schema: Schema.Array(tables.todos.schema) }, { label: 'allTodos' });
79
71
  let globalSetState;
80
72
  const AppRouter = () => {
81
- appRouterRenderCount.inc();
82
- const [state, setState] = LiveStoreReact.useRow(AppRouterSchema, { reactivityGraph });
73
+ renderCount.inc();
74
+ const [state, setState] = LiveStoreReact.useRow(AppRouterSchema);
83
75
  globalSetState = setState;
84
76
  return (React.createElement("div", null,
85
77
  React.createElement(TasksList, { setTaskId: setState.currentTaskId }),
@@ -93,94 +85,85 @@ describe('useRow', () => {
93
85
  return (React.createElement("div", null, allTodos.map((_) => (React.createElement("div", { key: _.id, onClick: () => setTaskId(_.id) }, _.id)))));
94
86
  };
95
87
  const TaskDetails = ({ id }) => {
96
- const [todo] = LiveStoreReact.useRow(todos, id, { reactivityGraph });
88
+ const [todo] = LiveStoreReact.useRow(todos, id);
97
89
  return React.createElement("div", { role: "content" }, JSON.stringify(todo));
98
90
  };
99
- const renderResult = render(React.createElement(AppRouter, null), { wrapper });
100
- expect(appRouterRenderCount.val).toBe(1);
101
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
91
+ const renderResult = ReactTesting.render(React.createElement(AppRouter, null), { wrapper });
92
+ expect(renderCount.val).toBe(1);
93
+ ReactTesting.act(() => store.mutate(LiveStore.rawSqlMutation({
102
94
  sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t1', 'buy milk', 0)`,
103
95
  })));
104
- expect(appRouterRenderCount.val).toBe(1);
96
+ expect(renderCount.val).toBe(1);
105
97
  expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: -"');
106
- React.act(() => globalSetState.currentTaskId('t1'));
107
- expect(appRouterRenderCount.val).toBe(2);
98
+ ReactTesting.act(() => globalSetState.currentTaskId('t1'));
99
+ expect(renderCount.val).toBe(2);
108
100
  expect(renderResult.getByRole('content').innerHTML).toMatchInlineSnapshot(`"{"id":"t1","text":"buy milk","completed":false}"`);
109
101
  expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: t1"');
110
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
102
+ ReactTesting.act(() => store.mutate(LiveStore.rawSqlMutation({
111
103
  sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t2', 'buy eggs', 0)`,
112
104
  }), AppRouterSchema.update({ where: { id: 'singleton' }, values: { currentTaskId: 't2' } }), LiveStore.rawSqlMutation({
113
105
  sql: LiveStore.sql `INSERT INTO todos (id, text, completed) VALUES ('t3', 'buy bread', 0)`,
114
106
  })));
115
- expect(appRouterRenderCount.val).toBe(3);
107
+ expect(renderCount.val).toBe(3);
116
108
  expect(renderResult.getByRole('current-id').innerHTML).toMatchInlineSnapshot('"Current Task Id: t2"');
117
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
118
- it('should work for a useRow query chained with a useTemporary query', () => Effect.gen(function* () {
119
- const { store, wrapper, reactivityGraph, makeRenderCount } = yield* makeTodoMvcReact({
120
- useGlobalReactivityGraph: false,
121
- });
122
- const renderCount = makeRenderCount();
109
+ }));
110
+ Vitest.scopedLive('should work for a useRow query chained with a useTemporary query', () => Effect.gen(function* () {
111
+ const { store, wrapper, renderCount } = yield* makeTodoMvcReact({});
123
112
  store.mutate(todos.insert({ id: 't1', text: 'buy milk', completed: false }), todos.insert({ id: 't2', text: 'buy bread', completed: false }));
124
- const { result, unmount, rerender } = renderHook((userId) => {
113
+ const { result, unmount, rerender } = ReactTesting.renderHook((userId) => {
125
114
  renderCount.inc();
126
- const [_row, _setRow, rowState$] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
127
- const todos = LiveStoreReact.useScopedQuery(() => LiveStore.queryDb((get) => ({
128
- query: LiveStore.sql `select * from todos where text like '%${get(rowState$).text}%'`,
129
- schema: Schema.Array(tables.todos.schema),
130
- }), { reactivityGraph, label: 'todosFiltered' }), userId);
115
+ const [_row, _setRow, rowState$] = LiveStoreReact.useRow(tables.userInfo, userId);
116
+ const todos = LiveStoreReact.useQuery(LiveStore.queryDb((get) => tables.todos.query.where('text', 'LIKE', `%${get(rowState$).text}%`),
117
+ // TODO find a way where explicit `userId` is not needed here
118
+ // possibly by automatically understanding the `get(rowState$)` dependency
119
+ { label: 'todosFiltered', deps: userId }));
131
120
  return { todos };
132
121
  }, { wrapper, initialProps: 'u1' });
133
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
134
- sql: LiveStore.sql `INSERT INTO UserInfo (id, username, text) VALUES ('u2', 'username_u2', 'milk')`,
135
- })));
122
+ ReactTesting.act(() => store.mutate(tables.userInfo.insert({ id: 'u2', username: 'username_u2', text: 'milk' })));
136
123
  expect(result.current.todos.length).toBe(2);
137
- // expect(result.current.state.username).toBe('')
138
124
  expect(renderCount.val).toBe(1);
139
125
  rerender('u2');
140
126
  expect(result.current.todos.length).toBe(1);
141
127
  expect(renderCount.val).toBe(2);
142
128
  unmount();
143
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise));
144
- let cachedProvider;
145
- describe('otel', () => {
146
- const exporter = new InMemorySpanExporter();
147
- const provider = cachedProvider ?? new BasicTracerProvider();
148
- cachedProvider = provider;
149
- provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
129
+ }));
130
+ Vitest.describe('otel', () => {
131
+ const provider = new BasicTracerProvider({});
150
132
  provider.register();
151
- const otelTracer = otel.trace.getTracer('test');
152
- const span = otelTracer.startSpan('test');
153
- const otelContext = otel.trace.setSpan(otel.context.active(), span);
154
- it('should update the data based on component key', async () => {
155
- const { strictMode } = await Effect.gen(function* () {
156
- const { wrapper, store, reactivityGraph, makeRenderCount, strictMode } = yield* makeTodoMvcReact({
157
- useGlobalReactivityGraph: false,
133
+ it.each([{ strictMode: true }, { strictMode: false }])('should update the data based on component key strictMode=%s', async ({ strictMode }) => {
134
+ const exporter = new InMemorySpanExporter();
135
+ // const provider = cachedProvider ?? new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] })
136
+ provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
137
+ const otelTracer = otel.trace.getTracer(`testing-${strictMode ? 'strict' : 'non-strict'}`);
138
+ const span = otelTracer.startSpan('test-root');
139
+ const otelContext = otel.trace.setSpan(otel.context.active(), span);
140
+ await Effect.gen(function* () {
141
+ const { wrapper, store, renderCount } = yield* makeTodoMvcReact({
158
142
  otelContext,
159
143
  otelTracer,
144
+ strictMode,
160
145
  });
161
- const renderCount = makeRenderCount();
162
- const { result, rerender, unmount } = renderHook((userId) => {
146
+ const { result, rerender, unmount } = ReactTesting.renderHook((userId) => {
163
147
  renderCount.inc();
164
- const [state, setState] = LiveStoreReact.useRow(AppComponentSchema, userId, { reactivityGraph });
148
+ const [state, setState] = LiveStoreReact.useRow(tables.userInfo, userId);
165
149
  return { state, setState };
166
150
  }, { wrapper, initialProps: 'u1' });
167
151
  expect(result.current.state.id).toBe('u1');
168
152
  expect(result.current.state.username).toBe('');
169
153
  expect(renderCount.val).toBe(1);
170
- React.act(() => store.mutate(LiveStore.rawSqlMutation({
171
- sql: LiveStore.sql `INSERT INTO UserInfo (id, username) VALUES ('u2', 'username_u2')`,
172
- })));
154
+ // For u2 we'll make sure that the row already exists,
155
+ // so the lazy `insert` will be skipped
156
+ ReactTesting.act(() => store.mutate(tables.userInfo.insert({ id: 'u2', username: 'username_u2' })));
173
157
  rerender('u2');
174
158
  expect(result.current.state.id).toBe('u2');
175
159
  expect(result.current.state.username).toBe('username_u2');
176
160
  expect(renderCount.val).toBe(2);
177
161
  unmount();
178
162
  span.end();
179
- return { strictMode };
180
163
  }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.runPromise);
181
164
  const mapAttributes = (attributes) => {
182
165
  return ReadonlyRecord.map(attributes, (val, key) => {
183
- if (key === 'stackInfo') {
166
+ if (key === 'firstStackInfo') {
184
167
  const stackInfo = JSON.parse(val);
185
168
  // stackInfo.frames.shift() // Removes `renderHook.wrapper` from the stack
186
169
  stackInfo.frames.forEach((_) => {
@@ -194,13 +177,7 @@ describe('useRow', () => {
194
177
  return val;
195
178
  });
196
179
  };
197
- // TODO improve testing setup so "obsolete" warning is avoided
198
- if (strictMode) {
199
- expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=true');
200
- }
201
- else {
202
- expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot('strictMode=false');
203
- }
180
+ expect(getSimplifiedRootSpan(exporter, mapAttributes)).toMatchSnapshot();
204
181
  });
205
182
  });
206
183
  });