@livestore/solid 0.4.0-dev.21 → 0.4.0-dev.23

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 (94) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/StoreRegistryContext.d.ts +56 -0
  3. package/dist/StoreRegistryContext.d.ts.map +1 -0
  4. package/dist/StoreRegistryContext.jsx +60 -0
  5. package/dist/StoreRegistryContext.jsx.map +1 -0
  6. package/dist/__tests__/fixture.d.ts +14 -0
  7. package/dist/__tests__/fixture.d.ts.map +1 -0
  8. package/dist/__tests__/fixture.jsx +13 -0
  9. package/dist/__tests__/fixture.jsx.map +1 -0
  10. package/dist/experimental/components/LiveList.d.ts +24 -0
  11. package/dist/experimental/components/LiveList.d.ts.map +1 -0
  12. package/dist/experimental/components/LiveList.jsx +24 -0
  13. package/dist/experimental/components/LiveList.jsx.map +1 -0
  14. package/dist/experimental/mod.d.ts +2 -0
  15. package/dist/experimental/mod.d.ts.map +1 -0
  16. package/dist/experimental/mod.js +2 -0
  17. package/dist/experimental/mod.js.map +1 -0
  18. package/dist/mod.d.ts +6 -2
  19. package/dist/mod.d.ts.map +1 -1
  20. package/dist/mod.js +4 -2
  21. package/dist/mod.js.map +1 -1
  22. package/dist/useClientDocument.client.test.d.ts +2 -0
  23. package/dist/useClientDocument.client.test.d.ts.map +1 -0
  24. package/dist/useClientDocument.client.test.jsx +177 -0
  25. package/dist/useClientDocument.client.test.jsx.map +1 -0
  26. package/dist/useClientDocument.d.ts +71 -0
  27. package/dist/useClientDocument.d.ts.map +1 -0
  28. package/dist/useClientDocument.js +74 -0
  29. package/dist/useClientDocument.js.map +1 -0
  30. package/dist/useClientDocument.server.test.d.ts +6 -0
  31. package/dist/useClientDocument.server.test.d.ts.map +1 -0
  32. package/dist/useClientDocument.server.test.jsx +76 -0
  33. package/dist/useClientDocument.server.test.jsx.map +1 -0
  34. package/dist/useQuery.client.test.d.ts +2 -0
  35. package/dist/useQuery.client.test.d.ts.map +1 -0
  36. package/dist/useQuery.client.test.jsx +165 -0
  37. package/dist/useQuery.client.test.jsx.map +1 -0
  38. package/dist/useQuery.d.ts +32 -0
  39. package/dist/useQuery.d.ts.map +1 -0
  40. package/dist/useQuery.js +64 -0
  41. package/dist/useQuery.js.map +1 -0
  42. package/dist/useQuery.server.test.d.ts +6 -0
  43. package/dist/useQuery.server.test.d.ts.map +1 -0
  44. package/dist/useQuery.server.test.jsx +88 -0
  45. package/dist/useQuery.server.test.jsx.map +1 -0
  46. package/dist/useStore.client.test.d.ts +2 -0
  47. package/dist/useStore.client.test.d.ts.map +1 -0
  48. package/dist/useStore.client.test.jsx +438 -0
  49. package/dist/useStore.client.test.jsx.map +1 -0
  50. package/dist/useStore.d.ts +91 -0
  51. package/dist/useStore.d.ts.map +1 -0
  52. package/dist/useStore.js +94 -0
  53. package/dist/useStore.js.map +1 -0
  54. package/dist/useStore.server.test.d.ts +6 -0
  55. package/dist/useStore.server.test.d.ts.map +1 -0
  56. package/dist/useStore.server.test.jsx +56 -0
  57. package/dist/useStore.server.test.jsx.map +1 -0
  58. package/dist/utils.d.ts +4 -0
  59. package/dist/utils.d.ts.map +1 -0
  60. package/dist/utils.js +7 -0
  61. package/dist/utils.js.map +1 -0
  62. package/dist/whenever.d.ts +32 -0
  63. package/dist/whenever.d.ts.map +1 -0
  64. package/dist/whenever.js +51 -0
  65. package/dist/whenever.js.map +1 -0
  66. package/package.json +65 -17
  67. package/src/StoreRegistryContext.tsx +70 -0
  68. package/src/__snapshots__/useClientDocument.client.test.tsx.snap +570 -0
  69. package/src/__snapshots__/useQuery.client.test.tsx.snap +1550 -0
  70. package/src/__tests__/fixture.tsx +42 -0
  71. package/src/experimental/components/LiveList.tsx +54 -0
  72. package/src/experimental/mod.ts +1 -0
  73. package/src/mod.ts +6 -2
  74. package/src/useClientDocument.client.test.tsx +299 -0
  75. package/src/useClientDocument.server.test.tsx +107 -0
  76. package/src/useClientDocument.ts +146 -0
  77. package/src/useQuery.client.test.tsx +293 -0
  78. package/src/useQuery.server.test.tsx +128 -0
  79. package/src/useQuery.ts +115 -0
  80. package/src/useStore.client.test.tsx +632 -0
  81. package/src/useStore.server.test.tsx +70 -0
  82. package/src/useStore.ts +179 -0
  83. package/src/utils.ts +10 -0
  84. package/src/whenever.ts +80 -0
  85. package/dist/query.d.ts +0 -4
  86. package/dist/query.d.ts.map +0 -1
  87. package/dist/query.js +0 -15
  88. package/dist/query.js.map +0 -1
  89. package/dist/store.d.ts +0 -6
  90. package/dist/store.d.ts.map +0 -1
  91. package/dist/store.js +0 -99
  92. package/dist/store.js.map +0 -1
  93. package/src/query.ts +0 -22
  94. package/src/store.ts +0 -196
@@ -0,0 +1,94 @@
1
+ import * as Solid from 'solid-js';
2
+ import { useStoreRegistry } from "./StoreRegistryContext.jsx";
3
+ import { useClientDocument } from "./useClientDocument.js";
4
+ import { useQuery } from "./useQuery.js";
5
+ import { resolve } from "./utils.js";
6
+ import { every, when } from "./whenever.js";
7
+ /**
8
+ * Returns a store resource that suspends until the store is loaded.
9
+ * The store is cached by its `storeId` in the `StoreRegistry`.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * import { Suspense } from 'solid-js'
14
+ *
15
+ * function Issue(props: { issueId: string }) {
16
+ * const store = useStore(issueStoreOptions(props.issueId))
17
+ * const issues = store()?.useQuery(queryDb(tables.issue.select()))
18
+ *
19
+ * return (
20
+ * <Show when={store()}>
21
+ * {(s) => <IssueView store={s()} />}
22
+ * </Show>
23
+ * )
24
+ * }
25
+ *
26
+ * // With Suspense boundary
27
+ * function App() {
28
+ * return (
29
+ * <Suspense fallback={<div>Loading...</div>}>
30
+ * <Issue issueId="abc123" />
31
+ * </Suspense>
32
+ * )
33
+ * }
34
+ * ```
35
+ *
36
+ * @remarks
37
+ * - Suspends until the store is loaded when used within a Suspense boundary.
38
+ * - Store is cached by its `storeId` in the `StoreRegistry`. Multiple calls with the same `storeId` return the same store instance.
39
+ * - Store is cached as long as it's being used, and after `unusedCacheTime` expires (default `60_000` ms in browser, `Infinity` in non-browser)
40
+ * - Default store options can be configured in `StoreRegistry` constructor.
41
+ * - Store options are only applied when the store is loaded. Subsequent calls with different options will not affect the store if it's already loaded and cached in the registry.
42
+ *
43
+ * @typeParam TSchema - The schema type for the store
44
+ * @typeParam TContext - User-defined context attached to the store
45
+ * @typeParam TSyncPayloadSchema - Schema for the sync payload sent to the backend
46
+ * @returns A Resource that resolves to the loaded store instance augmented with Solid hooks
47
+ */
48
+ export const useStore = (options) => {
49
+ const storeRegistry = useStoreRegistry();
50
+ const [storeResource] = Solid.createResource(() => resolve(options), (opts) => {
51
+ const release = storeRegistry.retain(opts);
52
+ Solid.onCleanup(release);
53
+ return storeRegistry.getOrLoadPromise(opts);
54
+ });
55
+ return withSolidApi(storeResource);
56
+ };
57
+ /**
58
+ * Augments a Store instance with Solid-specific methods (`useQuery`, `useClientDocument`).
59
+ *
60
+ * This is called automatically by `useStore()`. You typically don't need to call it
61
+ * directly unless you're building custom integrations.
62
+ *
63
+ * @internal
64
+ */
65
+ export const withSolidApi = (store) => {
66
+ return Object.assign(store, {
67
+ useQuery(queryDef) {
68
+ const memo = Solid.createMemo(when(store, (store) => useQuery(queryDef, { store })));
69
+ return () => memo()?.();
70
+ },
71
+ useClientDocument(table, id, options) {
72
+ const [localState, setLocalState] = Solid.createSignal();
73
+ const getClient = Solid.createMemo(when(every(store, table), ([store, table]) => {
74
+ const client = useClientDocument(table, id, options, { store: store });
75
+ const _localState = Solid.untrack(localState);
76
+ if (_localState !== undefined) {
77
+ client[1](_localState);
78
+ setLocalState(undefined);
79
+ }
80
+ return client;
81
+ }, (previous) => previous));
82
+ // State accessor: return store state if available, otherwise local buffer
83
+ const state = when(getClient, ([state]) => state(), localState);
84
+ // Setter: update store if ready, otherwise buffer locally
85
+ const setState = when(getClient, ([, set], value) => set(value), setLocalState);
86
+ // ID accessor
87
+ const idAccessor = when(getClient, ([, , id]) => id());
88
+ // Query accessor
89
+ const queryAccessor = when(getClient, ([, , , query]) => query());
90
+ return [state, setState, idAccessor, queryAccessor];
91
+ },
92
+ });
93
+ };
94
+ //# sourceMappingURL=useStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStore.js","sourceRoot":"","sources":["../src/useStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * SSR tests for useStore
3
+ * These tests run in node environment with SSR JSX transform using renderToString.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=useStore.server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStore.server.test.d.ts","sourceRoot":"","sources":["../src/useStore.server.test.tsx"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * SSR tests for useStore
3
+ * These tests run in node environment with SSR JSX transform using renderToString.
4
+ */
5
+ import { isServer, renderToString } from 'solid-js/web';
6
+ import { describe, expect, it } from 'vitest';
7
+ import { makeInMemoryAdapter } from '@livestore/adapter-web';
8
+ import { provideOtel } from '@livestore/common';
9
+ import { createStore } from '@livestore/livestore';
10
+ import { Effect } from '@livestore/utils/effect';
11
+ import { schema, tables } from "./__tests__/fixture.jsx";
12
+ import { withSolidApi } from "./useStore.js";
13
+ describe('environment', () => {
14
+ it('runs on server', () => {
15
+ // Use 'window' in globalThis to avoid TypeScript error without DOM lib
16
+ expect('window' in globalThis).toBe(false);
17
+ expect(isServer).toBe(true);
18
+ });
19
+ });
20
+ describe('useStore SSR', () => {
21
+ it('renders component with pre-created store to string', async () => {
22
+ await Effect.gen(function* () {
23
+ const store = yield* createStore({
24
+ schema,
25
+ storeId: 'ssr-store-test',
26
+ adapter: makeInMemoryAdapter(),
27
+ debug: { instanceId: 'ssr-store-test' },
28
+ });
29
+ const storeWithSolidApi = withSolidApi(store);
30
+ const StoreStatus = () => {
31
+ return <div>Store ID: {storeWithSolidApi.storeId}</div>;
32
+ };
33
+ const html = renderToString(() => <StoreStatus />);
34
+ expect(html).toContain('Store ID:');
35
+ expect(html).toContain('ssr-store-test');
36
+ }).pipe(provideOtel({}), Effect.scoped, Effect.runPromise);
37
+ });
38
+ it('renders component using store queries to string', async () => {
39
+ await Effect.gen(function* () {
40
+ const store = yield* createStore({
41
+ schema,
42
+ storeId: 'ssr-store-query-test',
43
+ adapter: makeInMemoryAdapter(),
44
+ debug: { instanceId: 'ssr-store-query-test' },
45
+ });
46
+ const storeWithSolidApi = withSolidApi(store);
47
+ const [state] = storeWithSolidApi.useClientDocument(tables.userInfo, 'u1');
48
+ const UserInfo = () => {
49
+ return <div>User: {state().username || 'anonymous'}</div>;
50
+ };
51
+ const html = renderToString(() => <UserInfo />);
52
+ expect(html).toContain('User:');
53
+ }).pipe(provideOtel({}), Effect.scoped, Effect.runPromise);
54
+ });
55
+ });
56
+ //# sourceMappingURL=useStore.server.test.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStore.server.test.jsx","sourceRoot":"","sources":["../src/useStore.server.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Accessor } from 'solid-js';
2
+ export type AccessorMaybe<T> = Accessor<T> | T;
3
+ export declare const resolve: <T>(value: AccessorMaybe<T>) => T;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAE9C,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,OAAO,aAAa,CAAC,CAAC,CAAC,KAAG,CAKpD,CAAA"}
package/dist/utils.js ADDED
@@ -0,0 +1,7 @@
1
+ export const resolve = (value) => {
2
+ if (typeof value === 'function') {
3
+ return value();
4
+ }
5
+ return value;
6
+ };
7
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,KAAuB,EAAK,EAAE;IACvD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,OAAQ,KAAqB,EAAE,CAAA;IACjC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Reactive utilities to ease working with nullable signals.
3
+ * Inlined from @bigmistqke/solid-whenever to reduce external dependencies.
4
+ */
5
+ import { type AccessorMaybe } from './utils.ts';
6
+ type NonNullable<T> = Exclude<T, null | undefined | false | 0 | ''>;
7
+ type InferNonNullable<T> = T extends AccessorMaybe<infer TValue> | undefined ? NonNullable<TValue> : never;
8
+ type InferNonNullableTuple<TAccessors extends Array<AccessorMaybe<any>>> = {
9
+ [TKey in keyof TAccessors]: InferNonNullable<TAccessors[TKey]>;
10
+ };
11
+ /**
12
+ * Returns a function that conditionally executes a callback based on the truthiness of an accessor's value,
13
+ * suitable for use in reactive programming contexts.
14
+ * @param accessor - The value or function returning a value that is checked for truthiness
15
+ * @param callback - The callback function to be executed if the accessor's value is truthy
16
+ * @param fallback - Optional callback function to be executed if the accessor's value is falsy
17
+ * @returns A function that conditionally executes the callback or fallback based on the accessor's value
18
+ */
19
+ export declare const when: {
20
+ <Args extends any[], TValue, TResult>(accessor: AccessorMaybe<TValue>, callback: (value: NonNullable<TValue>, ...args: Args) => TResult): (...args: Args) => TResult | undefined;
21
+ <Args extends any[], TValue, TResult, TFallbackResult>(accessor: AccessorMaybe<TValue>, callback: (value: NonNullable<TValue>, ...args: Args) => TResult, fallback: (...args: Args) => TFallbackResult): (...args: Args) => TResult | TFallbackResult;
22
+ };
23
+ /**
24
+ * Returns a function that conditionally executes and aggregates results from multiple accessors if all values are truthy.
25
+ *
26
+ * @param accessors Multiple accessors to be checked for truthiness.
27
+ * @returns A function that can be called to conditionally execute based on the truthiness of all accessor values,
28
+ * returning their results as an array or undefined if any are not truthy.
29
+ */
30
+ export declare const every: <TAccessors extends Array<AccessorMaybe<any>>>(...accessors: TAccessors) => (() => InferNonNullableTuple<TAccessors> | undefined);
31
+ export {};
32
+ //# sourceMappingURL=whenever.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whenever.d.ts","sourceRoot":"","sources":["../src/whenever.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAW,MAAM,YAAY,CAAA;AAExD,KAAK,WAAW,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,KAAK,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;AACnE,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,KAAK,CAAA;AAC1G,KAAK,qBAAqB,CAAC,UAAU,SAAS,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI;KACxE,IAAI,IAAI,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;CAC/D,CAAA;AAsBD;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,EAAE;IACjB,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAClC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,GAC/D,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,GAAG,SAAS,CAAA;IACzC,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EACnD,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,EAChE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,eAAe,GAC3C,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,GAAG,eAAe,CAAA;CAQhD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,UAAU,SAAS,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAChE,GAAG,WAAW,UAAU,KACvB,CAAC,MAAM,qBAAqB,CAAC,UAAU,CAAC,GAAG,SAAS,CAUtD,CAAA"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Reactive utilities to ease working with nullable signals.
3
+ * Inlined from @bigmistqke/solid-whenever to reduce external dependencies.
4
+ */
5
+ import { resolve } from "./utils.js";
6
+ /**
7
+ * Checks if the accessor's value is truthy and executes a callback with that value.
8
+ * @param accessor - The value or function returning a value to check for truthiness
9
+ * @param callback - The callback function to execute if the value is truthy
10
+ * @param fallback - Optional callback function to execute if the value is falsy
11
+ * @returns The result of the callback if truthy, fallback result if falsy, or undefined if no fallback
12
+ */
13
+ const check = (accessor, callback, fallback) => {
14
+ const value = resolve(accessor);
15
+ return Boolean(value) === true
16
+ ? callback(value)
17
+ : fallback !== undefined
18
+ ? fallback()
19
+ : undefined;
20
+ };
21
+ /**
22
+ * Returns a function that conditionally executes a callback based on the truthiness of an accessor's value,
23
+ * suitable for use in reactive programming contexts.
24
+ * @param accessor - The value or function returning a value that is checked for truthiness
25
+ * @param callback - The callback function to be executed if the accessor's value is truthy
26
+ * @param fallback - Optional callback function to be executed if the accessor's value is falsy
27
+ * @returns A function that conditionally executes the callback or fallback based on the accessor's value
28
+ */
29
+ export const when = (accessor, callback, fallback) => {
30
+ return (...args) => check(accessor, (value) => callback(value, ...args), fallback !== undefined ? () => fallback(...args) : undefined);
31
+ };
32
+ /**
33
+ * Returns a function that conditionally executes and aggregates results from multiple accessors if all values are truthy.
34
+ *
35
+ * @param accessors Multiple accessors to be checked for truthiness.
36
+ * @returns A function that can be called to conditionally execute based on the truthiness of all accessor values,
37
+ * returning their results as an array or undefined if any are not truthy.
38
+ */
39
+ export const every = (...accessors) => {
40
+ return () => {
41
+ const values = new Array(accessors.length);
42
+ for (let i = 0; i < accessors.length; i++) {
43
+ const _value = resolve(accessors[i]);
44
+ if (_value == null)
45
+ return undefined;
46
+ values[i] = _value;
47
+ }
48
+ return values;
49
+ };
50
+ };
51
+ //# sourceMappingURL=whenever.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whenever.js","sourceRoot":"","sources":["../src/whenever.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAsB,OAAO,EAAE,MAAM,YAAY,CAAA;AAQxD;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,CACZ,QAA+B,EAC/B,QAAiD,EACjD,QAAgC,EACO,EAAE;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/B,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI;QAC5B,CAAC,CAAC,QAAQ,CAAC,KAA4B,CAAC;QACxC,CAAC,CAAC,QAAQ,KAAK,SAAS;YACtB,CAAC,CAAC,QAAQ,EAAE;YACZ,CAAC,CAAC,SAAS,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAUb,CACF,QAA+B,EAC/B,QAAgE,EAChE,QAA6C,EACe,EAAE;IAC9D,OAAO,CAAC,GAAG,IAAU,EAAE,EAAE,CACvB,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;AACtH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,GAAG,SAAqB,EAC+B,EAAE;IACzD,OAAO,GAAG,EAAE;QACV,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,CAAsC,CAAA;QAC/E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;YACpC,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,SAAS,CAAA;YACpC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAA;QACpB,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;AACH,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,35 +1,83 @@
1
1
  {
2
2
  "name": "@livestore/solid",
3
- "version": "0.4.0-dev.21",
3
+ "version": "0.4.0-dev.23",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/livestorejs/livestore.git"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "package.json",
12
+ "src"
13
+ ],
4
14
  "type": "module",
15
+ "sideEffects": false,
5
16
  "exports": {
6
17
  ".": "./dist/mod.js"
7
18
  },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
8
22
  "dependencies": {
9
23
  "@opentelemetry/api": "1.9.0",
10
- "@livestore/utils": "0.4.0-dev.21",
11
- "@livestore/livestore": "0.4.0-dev.21",
12
- "@livestore/common": "0.4.0-dev.21"
24
+ "@livestore/common": "^0.4.0-dev.23",
25
+ "@livestore/framework-toolkit": "^0.4.0-dev.23",
26
+ "@livestore/livestore": "^0.4.0-dev.23",
27
+ "@livestore/utils": "^0.4.0-dev.23"
13
28
  },
14
29
  "devDependencies": {
15
- "@opentelemetry/sdk-trace-base": "2.0.1",
16
- "jsdom": "^26.1.0",
30
+ "@opentelemetry/sdk-trace-base": "2.2.0",
31
+ "@solidjs/testing-library": "0.8.10",
32
+ "@testing-library/jest-dom": "6.6.3",
33
+ "jsdom": "26.1.0",
17
34
  "solid-js": "1.9.10",
18
- "typescript": "5.9.2",
19
- "vite": "7.2.4",
20
- "vitest": "3.2.4"
35
+ "typescript": "5.9.3",
36
+ "vite": "7.3.1",
37
+ "vite-plugin-solid": "2.11.10",
38
+ "vitest": "3.2.4",
39
+ "@livestore/adapter-web": "^0.4.0-dev.23",
40
+ "@livestore/utils-dev": "^0.4.0-dev.23"
21
41
  },
22
- "files": [
23
- "package.json",
24
- "src",
25
- "dist"
26
- ],
27
- "license": "Apache-2.0",
28
42
  "peerDependencies": {
43
+ "@effect/ai": "^0.35.0",
44
+ "@effect/cli": "^0.75.1",
45
+ "@effect/cluster": "^0.58.2",
46
+ "@effect/experimental": "^0.60.0",
47
+ "@effect/opentelemetry": "^0.63.0",
48
+ "@effect/platform": "^0.96.1",
49
+ "@effect/platform-browser": "^0.76.0",
50
+ "@effect/platform-bun": "^0.89.0",
51
+ "@effect/platform-node": "^0.106.0",
52
+ "@effect/printer": "^0.49.0",
53
+ "@effect/printer-ansi": "^0.49.0",
54
+ "@effect/rpc": "^0.75.1",
55
+ "@effect/sql": "^0.51.1",
56
+ "@effect/typeclass": "^0.40.0",
57
+ "@effect/vitest": "^0.29.0",
58
+ "@opentelemetry/api": "^1.9.0",
59
+ "@opentelemetry/resources": "^2.2.0",
60
+ "@standard-schema/spec": "^1.1.0",
61
+ "effect": "^3.21.2",
29
62
  "solid-js": "^1.9.10"
30
63
  },
31
- "publishConfig": {
32
- "access": "public"
64
+ "$genie": {
65
+ "source": "package.json.genie.ts",
66
+ "warning": "DO NOT EDIT - changes will be overwritten",
67
+ "workspaceClosureDirs": [
68
+ "packages/@livestore/adapter-web",
69
+ "packages/@livestore/common",
70
+ "packages/@livestore/common-cf",
71
+ "packages/@livestore/devtools-web-common",
72
+ "packages/@livestore/framework-toolkit",
73
+ "packages/@livestore/livestore",
74
+ "packages/@livestore/solid",
75
+ "packages/@livestore/sqlite-wasm",
76
+ "packages/@livestore/utils",
77
+ "packages/@livestore/utils-dev",
78
+ "packages/@livestore/wa-sqlite",
79
+ "packages/@livestore/webmesh"
80
+ ]
33
81
  },
34
82
  "scripts": {
35
83
  "build": "tsc",
@@ -0,0 +1,70 @@
1
+ import * as Solid from 'solid-js'
2
+
3
+ import type { StoreRegistry } from '@livestore/livestore'
4
+
5
+ export const StoreRegistryContext = Solid.createContext<StoreRegistry | undefined>(undefined)
6
+
7
+ export type StoreRegistryProviderProps = {
8
+ storeRegistry: StoreRegistry
9
+ children: Solid.JSX.Element
10
+ }
11
+
12
+ /**
13
+ * Solid context provider that makes a {@link StoreRegistry} available to descendant components.
14
+ *
15
+ * Wrap your application (or a subtree) with this provider to enable {@link useStore} and
16
+ * {@link useStoreRegistry} hooks within that tree.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * import { StoreRegistry } from '@livestore/livestore'
21
+ * import { StoreRegistryProvider } from '@livestore/solid'
22
+ * import { batch } from 'solid-js'
23
+ *
24
+ * const storeRegistry = new StoreRegistry({
25
+ * defaultOptions: { batchUpdates: batch }
26
+ * })
27
+ *
28
+ * function App() {
29
+ * return (
30
+ * <StoreRegistryProvider storeRegistry={storeRegistry}>
31
+ * <MyComponent />
32
+ * </StoreRegistryProvider>
33
+ * )
34
+ * }
35
+ * ```
36
+ */
37
+ export const StoreRegistryProvider = (props: StoreRegistryProviderProps): Solid.JSX.Element => {
38
+ return <StoreRegistryContext.Provider value={props.storeRegistry}>{props.children}</StoreRegistryContext.Provider>
39
+ }
40
+
41
+ /**
42
+ * Hook to access the {@link StoreRegistry} from context. Useful for advanced operations like preloading.
43
+ *
44
+ * @param override - Optional registry to use instead of the context value.
45
+ * When provided, skips context lookup entirely.
46
+ * @returns The registry provided by the nearest {@link StoreRegistryProvider} ancestor, or the `override` if provided.
47
+ * @throws Error if called outside a {@link StoreRegistryProvider} and no override is provided
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * function PreloadButton(props: { issueId: string }) {
52
+ * const storeRegistry = useStoreRegistry()
53
+ *
54
+ * const handleMouseEnter = () => {
55
+ * storeRegistry.preload(issueStoreOptions(props.issueId))
56
+ * }
57
+ *
58
+ * return <button onMouseEnter={handleMouseEnter}>View Issue</button>
59
+ * }
60
+ * ```
61
+ */
62
+ export const useStoreRegistry = (override?: StoreRegistry): StoreRegistry => {
63
+ if (override !== undefined) return override
64
+
65
+ const storeRegistry = Solid.useContext(StoreRegistryContext)
66
+
67
+ if (storeRegistry == null) throw new Error('useStoreRegistry() must be used within <StoreRegistryProvider>')
68
+
69
+ return storeRegistry
70
+ }