convex-jotai 0.1.0-alpha.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/LICENSE +9 -0
- package/README.md +210 -0
- package/dist/index.d.mts +45 -0
- package/dist/index.mjs +108 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Grzegorz Dunin-Ślęczek (https://github.com/grzesiekgs)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# convex-jotai
|
|
2
|
+
|
|
3
|
+
A lightweight bridge between [Convex](https://www.convex.dev/) and [Jotai](https://jotai.org/) that lets you manage Convex queries, mutations, and actions through Jotai atoms.
|
|
4
|
+
In concept it's similar to [`jotai-tanstack-query`](https://github.com/jotaijs/jotai-tanstack-query), meaning that it allows to access and modify `convex` state within `jotai` atoms.
|
|
5
|
+
Effectively it's drop in replacement for `convex/react`.
|
|
6
|
+
|
|
7
|
+
# Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# or any bundler of your choice
|
|
11
|
+
bun add convex jotai convex-jotai
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Peer Dependencies
|
|
15
|
+
|
|
16
|
+
| Package | Version |
|
|
17
|
+
|---------|---------|
|
|
18
|
+
| `convex` | `>=1.31` |
|
|
19
|
+
| `jotai` | `>=2.6` |
|
|
20
|
+
|
|
21
|
+
These versions can be downgraded. I've selected latest version as of 06.01.2025. Create a GitHub issue if you would like to change this.
|
|
22
|
+
|
|
23
|
+
# Quick Start
|
|
24
|
+
|
|
25
|
+
## Set up the Convex client in your Jotai store
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { ConvexClient } from 'convex/browser';
|
|
29
|
+
import { createStore, Provider } from 'jotai';
|
|
30
|
+
import { convexClientAtom } from 'convex-jotai';
|
|
31
|
+
|
|
32
|
+
// Create the Convex client.
|
|
33
|
+
// Note that ConvexReactClient is wrapper around ConvexClient.
|
|
34
|
+
// It could be possible to use both convex/react and convex-jotai, but currently that would require ConvexReactClient to expose ConvexClient.
|
|
35
|
+
const convex = new ConvexClient(import.meta.env.VITE_CONVEX_URL);
|
|
36
|
+
// convexClientAtom has to be set before using any of convex atoms. It doesn't necessarily has to be set in module scope.
|
|
37
|
+
// Therefore it's possible to rely on default store provided by jotai Provider.
|
|
38
|
+
const store = createStore();
|
|
39
|
+
store.set(convexClientAtom, convex);
|
|
40
|
+
|
|
41
|
+
// Wrap your app with the Jotai Provider
|
|
42
|
+
const App: FC = () => {
|
|
43
|
+
return (
|
|
44
|
+
<Provider store={store}>
|
|
45
|
+
<YourApp />
|
|
46
|
+
</Provider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Define your atoms
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { convexQueryAtom, convexMutationAtom, convexActionAtom } from 'convex-jotai';
|
|
55
|
+
import { api } from '../convex/_generated/api';
|
|
56
|
+
|
|
57
|
+
const themeQueryAtom = convexQueryAtom(api.settings.get, () => ({ key: 'theme' }));
|
|
58
|
+
const settingsMutationAtom = convexMutationAtom(api.settings.set);
|
|
59
|
+
const eventActionAtom = convexActionAtom(api.actions.event);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Use atoms in your other atoms or components
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { atom, useAtomValue, useSetAtom } from 'jotai';
|
|
66
|
+
|
|
67
|
+
const backgroundColorAtom = atom((get) => {
|
|
68
|
+
const theme = get(themeQueryAtom);
|
|
69
|
+
// api.settings.get is still loading.
|
|
70
|
+
if (!theme) {
|
|
71
|
+
return '#FF0000';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (theme === 'light') {
|
|
75
|
+
return '#FFFFFF';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return '#000000';
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const Settings: FC = () => {
|
|
82
|
+
const backgroundColor = useAtomValue(backgroundColorAtom);
|
|
83
|
+
const settingsMutation = useSetAtom(settingsMutationAtom);
|
|
84
|
+
const runEventAction = useSetAtom(eventActionAtom);
|
|
85
|
+
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
runEventAction({ event: 'settings-viewed' });
|
|
88
|
+
}, [runEventAction])
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<div style={{ backgroundColor }}>
|
|
92
|
+
<button onClick={() => settingsMutation({ key: 'theme', value: 'dark' })}>
|
|
93
|
+
Set Dark Theme
|
|
94
|
+
</button>
|
|
95
|
+
<button onClick={() => settingsMutation({ key: 'theme', value: 'light' })}>
|
|
96
|
+
Set Light Theme
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
# Deep dive
|
|
103
|
+
More details about the implementation.
|
|
104
|
+
|
|
105
|
+
## More features
|
|
106
|
+
Find out what else `convex-jotai` can do.
|
|
107
|
+
|
|
108
|
+
### Dynamic query arguments
|
|
109
|
+
```tsx
|
|
110
|
+
const dynamicSettingsQueryAtom = convexQueryAtom(api.settings.get, (get) => {
|
|
111
|
+
const userSelectedKey = get(userSelectedKeyAtom);
|
|
112
|
+
|
|
113
|
+
return { key: userSelectedKey }
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Support for suspense
|
|
118
|
+
```tsx
|
|
119
|
+
const themeQueryPromiseAtom = convexQueryPromiseAtom(api.settings.get, () => ({ key: 'theme' }));
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Descriptive query result
|
|
123
|
+
```tsx
|
|
124
|
+
const themeQueryResultAtom = convexQueryResultAtom(api.settings.get, () => ({ key: 'theme' }));
|
|
125
|
+
|
|
126
|
+
const themeQueryResult = useAtomValue(themeQueryResultAtom);
|
|
127
|
+
|
|
128
|
+
if (themeQueryResult.status === 'loading') {
|
|
129
|
+
...
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (themeQueryResult.status === 'success') {
|
|
133
|
+
themeQueryResult.data
|
|
134
|
+
...
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (themeQueryResult.status === 'error') {
|
|
138
|
+
themeQueryResult.error
|
|
139
|
+
...
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## `convex/react` vs `convex-jotai`
|
|
144
|
+
|
|
145
|
+
### Provider Setup
|
|
146
|
+
```tsx
|
|
147
|
+
// convex/react
|
|
148
|
+
import { ConvexProvider, ConvexReactClient } from 'convex/react';
|
|
149
|
+
|
|
150
|
+
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
|
|
151
|
+
|
|
152
|
+
const App: FC = () => {
|
|
153
|
+
return (
|
|
154
|
+
<ConvexProvider client={convex}>
|
|
155
|
+
<YourApp />
|
|
156
|
+
</ConvexProvider>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// convex/jotai
|
|
161
|
+
import { ConvexClient } from 'convex/browser';
|
|
162
|
+
import { createStore, Provider } from 'jotai';
|
|
163
|
+
import { convexClientAtom } from 'convex-jotai';
|
|
164
|
+
|
|
165
|
+
const convex = new ConvexClient(import.meta.env.VITE_CONVEX_URL);
|
|
166
|
+
const store = createStore();
|
|
167
|
+
store.set(convexClientAtom, convex);
|
|
168
|
+
|
|
169
|
+
const App: FC = () => {
|
|
170
|
+
return (
|
|
171
|
+
<Provider store={store}>
|
|
172
|
+
<YourApp />
|
|
173
|
+
</Provider>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
### Queries, mutations and actions
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
// convex/react
|
|
183
|
+
import { useQuery, useMutation, useAction } from 'convex/react';
|
|
184
|
+
import { api } from '../convex/_generated/api';
|
|
185
|
+
|
|
186
|
+
const theme = useQuery(api.settings.get, { key: 'theme' });
|
|
187
|
+
const settingsMutation = useMutation(api.settings.set);
|
|
188
|
+
const runEventAction = useAction(api.actions.event);
|
|
189
|
+
|
|
190
|
+
// convex-jotai
|
|
191
|
+
import { convexQueryAtom } from 'convex-jotai';
|
|
192
|
+
import { useAtomValue, useSetAtom } from 'jotai';
|
|
193
|
+
import { api } from '../convex/_generated/api';
|
|
194
|
+
|
|
195
|
+
const themeQueryAtom = convexQueryAtom(api.settings.get, () => ({ key: 'theme' }));
|
|
196
|
+
const settingsMutationAtom = convexMutationAtom(api.settings.set);
|
|
197
|
+
const eventActionAtom = convexActionAtom(api.actions.event);
|
|
198
|
+
|
|
199
|
+
const theme = useAtomValue(themeQueryAtom);
|
|
200
|
+
const settingsMutation = useSetAtom(settingsMutationAtom);
|
|
201
|
+
const runEventAction = useSetAtom(eventActionAtom);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
# Example
|
|
205
|
+
|
|
206
|
+
See the [playground app](../../apps/playground/README.md) for a complete working example comparing `convex/react` and `convex-jotai` side-by-side.
|
|
207
|
+
|
|
208
|
+
# License
|
|
209
|
+
|
|
210
|
+
[MIT](./LICENSE)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as jotai0 from "jotai";
|
|
2
|
+
import { Atom, Getter, WritableAtom } from "jotai";
|
|
3
|
+
import { FunctionArgs, FunctionReference, FunctionReturnType } from "convex/server";
|
|
4
|
+
import { ConvexClient, OptimisticUpdate } from "convex/browser";
|
|
5
|
+
|
|
6
|
+
//#region src/types.d.ts
|
|
7
|
+
type ConvexQueryOptionsGetter<Query extends FunctionReference<'query'>> = (get: Getter) => FunctionArgs<Query>;
|
|
8
|
+
type ConvexQueryErrorResult = {
|
|
9
|
+
status: 'error';
|
|
10
|
+
data?: never;
|
|
11
|
+
error: Error;
|
|
12
|
+
};
|
|
13
|
+
type ConvexQueryLoadingResult = {
|
|
14
|
+
status: 'loading';
|
|
15
|
+
data?: never;
|
|
16
|
+
error?: never;
|
|
17
|
+
};
|
|
18
|
+
type ConvexQuerySuccessResult<T> = {
|
|
19
|
+
status: 'success';
|
|
20
|
+
data: T;
|
|
21
|
+
error?: never;
|
|
22
|
+
};
|
|
23
|
+
type ConvexQueryResult<T> = ConvexQueryErrorResult | ConvexQueryLoadingResult | ConvexQuerySuccessResult<T>;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/atoms/convexQueryResultAtom.d.ts
|
|
26
|
+
declare function convexQueryResultAtom<Query extends FunctionReference<'query'>>(query: Query, queryOptionsGetter: ConvexQueryOptionsGetter<Query>): Atom<ConvexQueryResult<FunctionReturnType<Query>>>;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/atoms/convexClientAtom.d.ts
|
|
29
|
+
declare const convexClientAtom: jotai0.PrimitiveAtom<ConvexClient | null> & {
|
|
30
|
+
init: ConvexClient | null;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/atoms/convexQueryPromiseAtom.d.ts
|
|
34
|
+
declare function convexQueryPromiseAtom<Query extends FunctionReference<'query'>>(query: Query, queryOptionsGetter: ConvexQueryOptionsGetter<Query>): Atom<Promise<FunctionReturnType<Query>>>;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/atoms/convexQueryAtom.d.ts
|
|
37
|
+
declare function convexQueryAtom<Query extends FunctionReference<'query'>>(query: Query, queryOptionsGetter: ConvexQueryOptionsGetter<Query>): Atom<FunctionReturnType<Query>>;
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/atoms/convexMutationAtom.d.ts
|
|
40
|
+
declare function convexMutationAtom<Mutation extends FunctionReference<'mutation'>>(mutation: Mutation, optimisticUpdate?: OptimisticUpdate<FunctionArgs<Mutation>>): WritableAtom<null, [FunctionArgs<Mutation>], FunctionReturnType<Mutation>>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/atoms/convexActionAtom.d.ts
|
|
43
|
+
declare function convexActionAtom<Action extends FunctionReference<'action'>>(action: Action): WritableAtom<null, [FunctionArgs<Action>], FunctionReturnType<Action>>;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ConvexQueryErrorResult, ConvexQueryLoadingResult, ConvexQueryOptionsGetter, ConvexQueryResult, ConvexQuerySuccessResult, convexActionAtom, convexClientAtom, convexMutationAtom, convexQueryAtom, convexQueryPromiseAtom, convexQueryResultAtom };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { atom } from "jotai";
|
|
2
|
+
import { getFunctionName } from "convex/server";
|
|
3
|
+
import { selectAtom } from "jotai/utils";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/getLocalConvexQueryResult.ts
|
|
6
|
+
function getLocalConvexQueryResult(convexClient, funcRef, queryOptions) {
|
|
7
|
+
try {
|
|
8
|
+
const result = convexClient.client.localQueryResult(getFunctionName(funcRef), queryOptions);
|
|
9
|
+
if (result === void 0) return { status: "loading" };
|
|
10
|
+
return {
|
|
11
|
+
status: "success",
|
|
12
|
+
data: result,
|
|
13
|
+
error: void 0
|
|
14
|
+
};
|
|
15
|
+
} catch (possiblyError) {
|
|
16
|
+
return {
|
|
17
|
+
status: "error",
|
|
18
|
+
error: possiblyError instanceof Error ? possiblyError : new Error(String(possiblyError))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/utils/assertConvexClient.ts
|
|
25
|
+
const assertConvexClient = (client) => {
|
|
26
|
+
if (typeof window === "undefined") throw new Error("convex-jotai: SSR is currently not supported.");
|
|
27
|
+
if (client === null) throw new Error("convex-jotai: convexClientAtom is not set. Follow the setup guide in the README.");
|
|
28
|
+
return client;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/atoms/convexClientAtom.ts
|
|
33
|
+
const convexClientAtom = atom(null);
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/atoms/convexQueryResultAtom.ts
|
|
37
|
+
function convexQueryResultAtom(query, queryOptionsGetter) {
|
|
38
|
+
const queryOptionsAtom = atom((get) => queryOptionsGetter(get));
|
|
39
|
+
const querySubscriptionAtom = atom((get) => {
|
|
40
|
+
const convexClient = assertConvexClient(get(convexClientAtom));
|
|
41
|
+
const queryOptions = get(queryOptionsAtom);
|
|
42
|
+
const queryResultAtom = atom(getLocalConvexQueryResult(convexClient, query, queryOptions));
|
|
43
|
+
queryResultAtom.onMount = (setValue) => {
|
|
44
|
+
return convexClient.onUpdate(query, queryOptions, (update) => setValue({
|
|
45
|
+
status: "success",
|
|
46
|
+
data: update
|
|
47
|
+
}), (error) => setValue({
|
|
48
|
+
status: "error",
|
|
49
|
+
error
|
|
50
|
+
}));
|
|
51
|
+
};
|
|
52
|
+
return queryResultAtom;
|
|
53
|
+
});
|
|
54
|
+
return atom((get) => {
|
|
55
|
+
return get(get(querySubscriptionAtom));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/atoms/convexQueryPromiseAtom.ts
|
|
61
|
+
function convexQueryPromiseAtom(query, queryOptionsGetter) {
|
|
62
|
+
const queryPromiseStateAtom = selectAtom(convexQueryResultAtom(query, queryOptionsGetter), (queryResult, prevState) => {
|
|
63
|
+
const state = prevState ?? {
|
|
64
|
+
promiseWithResolvers: Promise.withResolvers(),
|
|
65
|
+
resolved: false
|
|
66
|
+
};
|
|
67
|
+
if (queryResult.status === "loading") {
|
|
68
|
+
if (!state.resolved) return state;
|
|
69
|
+
return {
|
|
70
|
+
promiseWithResolvers: Promise.withResolvers(),
|
|
71
|
+
resolved: false
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
promiseWithResolvers: state.promiseWithResolvers,
|
|
76
|
+
resolved: true
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
return atom((get) => get(queryPromiseStateAtom).promiseWithResolvers.promise);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/atoms/convexQueryAtom.ts
|
|
84
|
+
function convexQueryAtom(query, queryOptionsGetter) {
|
|
85
|
+
const queryResultAtom = convexQueryResultAtom(query, queryOptionsGetter);
|
|
86
|
+
return atom((get) => {
|
|
87
|
+
return get(queryResultAtom).data;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/atoms/convexMutationAtom.ts
|
|
93
|
+
function convexMutationAtom(mutation, optimisticUpdate) {
|
|
94
|
+
return atom(null, (get, _set, args) => {
|
|
95
|
+
return assertConvexClient(get(convexClientAtom)).mutation(mutation, args, { optimisticUpdate });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/atoms/convexActionAtom.ts
|
|
101
|
+
function convexActionAtom(action) {
|
|
102
|
+
return atom(null, (get, _set, args) => {
|
|
103
|
+
return assertConvexClient(get(convexClientAtom)).action(action, args);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
export { convexActionAtom, convexClientAtom, convexMutationAtom, convexQueryAtom, convexQueryPromiseAtom, convexQueryResultAtom };
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "convex-jotai",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"description": "Jotai atoms for Convex queries, mutations, and actions",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"jotai",
|
|
11
|
+
"convex",
|
|
12
|
+
"react",
|
|
13
|
+
"state-management",
|
|
14
|
+
"realtime"
|
|
15
|
+
],
|
|
16
|
+
"author": "Grzegorz Dunin-Ślęczek <grzesiekgs@gmail.com>",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/grzesiekgs/jotai-convex.git",
|
|
20
|
+
"directory": "packages/convex-jotai"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/grzesiekgs/jotai-convex#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/grzesiekgs/jotai-convex/issues"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"main": "dist/index.mjs",
|
|
32
|
+
"module": "dist/index.mjs",
|
|
33
|
+
"types": "dist/index.d.mts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.mts",
|
|
37
|
+
"import": "./dist/index.mjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsdown",
|
|
42
|
+
"dev": "tsdown --watch",
|
|
43
|
+
"tsc": "tsc --noEmit"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"convex": ">=1.31",
|
|
47
|
+
"jotai": ">=2.6"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"tsdown": "0.18.4",
|
|
54
|
+
"typescript": "5.9.3"
|
|
55
|
+
}
|
|
56
|
+
}
|