@instantdb/react-common 0.22.99-experimental.add-user-perm-rules.20792844601.1 → 0.22.99-experimental.add-user-perm-rules.20792984656.1

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.
@@ -1,13 +1,4 @@
1
1
  'use client';
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
12
3
  import { txInit, init as core_init, InstantError, } from '@instantdb/core';
13
4
  import { useCallback, useEffect, useRef, useState, useSyncExternalStore, } from 'react';
@@ -19,249 +10,16 @@ const defaultAuthState = {
19
10
  error: undefined,
20
11
  };
21
12
  export default class InstantReactAbstractDatabase {
13
+ tx = txInit();
14
+ auth;
15
+ storage;
16
+ core;
17
+ /** @deprecated use `core` instead */
18
+ _core;
19
+ static Storage;
20
+ static NetworkListener;
21
+ static EventSourceImpl;
22
22
  constructor(config, versions) {
23
- this.tx = txInit();
24
- /**
25
- * Returns a unique ID for a given `name`. It's stored in local storage,
26
- * so you will get the same ID across sessions.
27
- *
28
- * This is useful for generating IDs that could identify a local device or user.
29
- *
30
- * @example
31
- * const deviceId = await db.getLocalId('device');
32
- */
33
- this.getLocalId = (name) => {
34
- return this.core.getLocalId(name);
35
- };
36
- /**
37
- * A hook that returns a unique ID for a given `name`. localIds are
38
- * stored in local storage, so you will get the same ID across sessions.
39
- *
40
- * Initially returns `null`, and then loads the localId.
41
- *
42
- * @example
43
- * const deviceId = db.useLocalId('device');
44
- * if (!deviceId) return null; // loading
45
- * console.log('Device ID:', deviceId)
46
- */
47
- this.useLocalId = (name) => {
48
- const [localId, setLocalId] = useState(null);
49
- useEffect(() => {
50
- let mounted = true;
51
- const f = () => __awaiter(this, void 0, void 0, function* () {
52
- const id = yield this.getLocalId(name);
53
- if (!mounted)
54
- return;
55
- setLocalId(id);
56
- });
57
- f();
58
- return;
59
- }, [name]);
60
- return localId;
61
- };
62
- /**
63
- * Hooks for working with rooms
64
- *
65
- * @see https://instantdb.com/docs/presence-and-topics
66
- *
67
- * @example
68
- * const room = db.room('chat', roomId);
69
- * const { peers } = db.rooms.usePresence(room);
70
- * const publish = db.rooms.usePublishTopic(room, 'emoji');
71
- * // ...
72
- */
73
- this.rooms = rooms;
74
- /**
75
- * Use this to write data! You can create, update, delete, and link objects
76
- *
77
- * @see https://instantdb.com/docs/instaml
78
- *
79
- * @example
80
- * // Create a new object in the `goals` namespace
81
- * const goalId = id();
82
- * db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
83
- *
84
- * // Update the title
85
- * db.transact(db.tx.goals[goalId].update({title: "Get super fit"}))
86
- *
87
- * // Delete it
88
- * db.transact(db.tx.goals[goalId].delete())
89
- *
90
- * // Or create an association:
91
- * todoId = id();
92
- * db.transact([
93
- * db.tx.todos[todoId].update({ title: 'Go on a run' }),
94
- * db.tx.goals[goalId].link({todos: todoId}),
95
- * ])
96
- */
97
- this.transact = (chunks) => {
98
- return this.core.transact(chunks);
99
- };
100
- /**
101
- * Use this to query your data!
102
- *
103
- * @see https://instantdb.com/docs/instaql
104
- *
105
- * @example
106
- * // listen to all goals
107
- * const { isLoading, error, data } = db.useQuery({ goals: {} });
108
- *
109
- * // goals where the title is "Get Fit"
110
- * const { isLoading, error, data } = db.useQuery({
111
- * goals: { $: { where: { title: 'Get Fit' } } },
112
- * });
113
- *
114
- * // all goals, _alongside_ their todos
115
- * const { isLoading, error, data } = db.useQuery({
116
- * goals: { todos: {} },
117
- * });
118
- *
119
- * // skip if `user` is not logged in
120
- * const { isLoading, error, data } = db.useQuery(
121
- * auth.user ? { goals: {} } : null,
122
- * );
123
- */
124
- this.useQuery = (query, opts) => {
125
- return useQueryInternal(this.core, query, opts).state;
126
- };
127
- /**
128
- * Listen for the logged in state. This is useful
129
- * for deciding when to show a login screen.
130
- *
131
- * Check out the docs for an example `Login` component too!
132
- *
133
- * @see https://instantdb.com/docs/auth
134
- * @example
135
- * function App() {
136
- * const { isLoading, user, error } = db.useAuth()
137
- * if (isLoading) {
138
- * return <div>Loading...</div>
139
- * }
140
- * if (error) {
141
- * return <div>Uh oh! {error.message}</div>
142
- * }
143
- * if (user) {
144
- * return <Main user={user} />
145
- * }
146
- * return <Login />
147
- * }
148
- *
149
- */
150
- this.useAuth = () => {
151
- return this._useAuth();
152
- };
153
- /**
154
- * Subscribe to the currently logged in user.
155
- * If the user is not logged in, this hook with throw an Error.
156
- * You will want to protect any calls of this hook with a
157
- * <db.SignedIn> component, or your own logic based on db.useAuth()
158
- *
159
- * @see https://instantdb.com/docs/auth
160
- * @throws Error indicating user not signed in
161
- * @example
162
- * function UserDisplay() {
163
- * const user = db.useUser()
164
- * return <div>Logged in as: {user.email}</div>
165
- * }
166
- *
167
- * <db.SignedIn>
168
- * <UserDisplay />
169
- * </db.SignedIn>
170
- *
171
- */
172
- this.useUser = () => {
173
- const { user } = this.useAuth();
174
- if (!user) {
175
- throw new InstantError('useUser must be used within an auth-protected route');
176
- }
177
- return user;
178
- };
179
- /**
180
- * Listen for connection status changes to Instant. Use this for things like
181
- * showing connection state to users
182
- *
183
- * @see https://www.instantdb.com/docs/patterns#connection-status
184
- * @example
185
- * function App() {
186
- * const status = db.useConnectionStatus()
187
- * const connectionState =
188
- * status === 'connecting' || status === 'opened'
189
- * ? 'authenticating'
190
- * : status === 'authenticated'
191
- * ? 'connected'
192
- * : status === 'closed'
193
- * ? 'closed'
194
- * : status === 'errored'
195
- * ? 'errored'
196
- * : 'unexpected state';
197
- *
198
- * return <div>Connection state: {connectionState}</div>
199
- * }
200
- */
201
- this.useConnectionStatus = () => {
202
- const statusRef = useRef(this.core._reactor.status);
203
- const subscribe = useCallback((cb) => {
204
- const unsubscribe = this.core.subscribeConnectionStatus((newStatus) => {
205
- if (newStatus !== statusRef.current) {
206
- statusRef.current = newStatus;
207
- cb();
208
- }
209
- });
210
- return unsubscribe;
211
- }, []);
212
- const status = useSyncExternalStore(subscribe, () => statusRef.current,
213
- // For SSR, always return 'connecting' as the initial state
214
- () => 'connecting');
215
- return status;
216
- };
217
- /**
218
- * Use this for one-off queries.
219
- * Returns local data if available, otherwise fetches from the server.
220
- * Because we want to avoid stale data, this method will throw an error
221
- * if the user is offline or there is no active connection to the server.
222
- *
223
- * @see https://instantdb.com/docs/instaql
224
- *
225
- * @example
226
- *
227
- * const resp = await db.queryOnce({ goals: {} });
228
- * console.log(resp.data.goals)
229
- */
230
- this.queryOnce = (query, opts) => {
231
- return this.core.queryOnce(query, opts);
232
- };
233
- /**
234
- * Only render children if the user is signed in.
235
- * @see https://instantdb.com/docs/auth
236
- *
237
- * @example
238
- * <db.SignedIn>
239
- * <MyComponent />
240
- * </db.SignedIn>
241
- *
242
- */
243
- this.SignedIn = ({ children }) => {
244
- const auth = this.useAuth();
245
- if (auth.isLoading || auth.error || !auth.user)
246
- return null;
247
- return _jsx(_Fragment, { children: children });
248
- };
249
- /**
250
- * Only render children if the user is signed out.
251
- * @see https://instantdb.com/docs/auth
252
- *
253
- * @example
254
- * <db.SignedOut>
255
- * <MyComponent />
256
- * </db.SignedOut>
257
- *
258
- */
259
- this.SignedOut = ({ children }) => {
260
- const auth = this.useAuth();
261
- if (auth.isLoading || auth.error || auth.user)
262
- return null;
263
- return _jsx(_Fragment, { children: children });
264
- };
265
23
  this.core = core_init(config,
266
24
  // @ts-expect-error because TS can't resolve subclass statics
267
25
  this.constructor.Storage,
@@ -273,6 +31,44 @@ export default class InstantReactAbstractDatabase {
273
31
  this.auth = this.core.auth;
274
32
  this.storage = this.core.storage;
275
33
  }
34
+ /**
35
+ * Returns a unique ID for a given `name`. It's stored in local storage,
36
+ * so you will get the same ID across sessions.
37
+ *
38
+ * This is useful for generating IDs that could identify a local device or user.
39
+ *
40
+ * @example
41
+ * const deviceId = await db.getLocalId('device');
42
+ */
43
+ getLocalId = (name) => {
44
+ return this.core.getLocalId(name);
45
+ };
46
+ /**
47
+ * A hook that returns a unique ID for a given `name`. localIds are
48
+ * stored in local storage, so you will get the same ID across sessions.
49
+ *
50
+ * Initially returns `null`, and then loads the localId.
51
+ *
52
+ * @example
53
+ * const deviceId = db.useLocalId('device');
54
+ * if (!deviceId) return null; // loading
55
+ * console.log('Device ID:', deviceId)
56
+ */
57
+ useLocalId = (name) => {
58
+ const [localId, setLocalId] = useState(null);
59
+ useEffect(() => {
60
+ let mounted = true;
61
+ const f = async () => {
62
+ const id = await this.getLocalId(name);
63
+ if (!mounted)
64
+ return;
65
+ setLocalId(id);
66
+ };
67
+ f();
68
+ return;
69
+ }, [name]);
70
+ return localId;
71
+ };
276
72
  /**
277
73
  * Obtain a handle to a room, which allows you to listen to topics and presence data
278
74
  *
@@ -288,6 +84,97 @@ export default class InstantReactAbstractDatabase {
288
84
  room(type = '_defaultRoomType', id = '_defaultRoomId') {
289
85
  return new InstantReactRoom(this.core, type, id);
290
86
  }
87
+ /**
88
+ * Hooks for working with rooms
89
+ *
90
+ * @see https://instantdb.com/docs/presence-and-topics
91
+ *
92
+ * @example
93
+ * const room = db.room('chat', roomId);
94
+ * const { peers } = db.rooms.usePresence(room);
95
+ * const publish = db.rooms.usePublishTopic(room, 'emoji');
96
+ * // ...
97
+ */
98
+ rooms = rooms;
99
+ /**
100
+ * Use this to write data! You can create, update, delete, and link objects
101
+ *
102
+ * @see https://instantdb.com/docs/instaml
103
+ *
104
+ * @example
105
+ * // Create a new object in the `goals` namespace
106
+ * const goalId = id();
107
+ * db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
108
+ *
109
+ * // Update the title
110
+ * db.transact(db.tx.goals[goalId].update({title: "Get super fit"}))
111
+ *
112
+ * // Delete it
113
+ * db.transact(db.tx.goals[goalId].delete())
114
+ *
115
+ * // Or create an association:
116
+ * todoId = id();
117
+ * db.transact([
118
+ * db.tx.todos[todoId].update({ title: 'Go on a run' }),
119
+ * db.tx.goals[goalId].link({todos: todoId}),
120
+ * ])
121
+ */
122
+ transact = (chunks) => {
123
+ return this.core.transact(chunks);
124
+ };
125
+ /**
126
+ * Use this to query your data!
127
+ *
128
+ * @see https://instantdb.com/docs/instaql
129
+ *
130
+ * @example
131
+ * // listen to all goals
132
+ * const { isLoading, error, data } = db.useQuery({ goals: {} });
133
+ *
134
+ * // goals where the title is "Get Fit"
135
+ * const { isLoading, error, data } = db.useQuery({
136
+ * goals: { $: { where: { title: 'Get Fit' } } },
137
+ * });
138
+ *
139
+ * // all goals, _alongside_ their todos
140
+ * const { isLoading, error, data } = db.useQuery({
141
+ * goals: { todos: {} },
142
+ * });
143
+ *
144
+ * // skip if `user` is not logged in
145
+ * const { isLoading, error, data } = db.useQuery(
146
+ * auth.user ? { goals: {} } : null,
147
+ * );
148
+ */
149
+ useQuery = (query, opts) => {
150
+ return useQueryInternal(this.core, query, opts).state;
151
+ };
152
+ /**
153
+ * Listen for the logged in state. This is useful
154
+ * for deciding when to show a login screen.
155
+ *
156
+ * Check out the docs for an example `Login` component too!
157
+ *
158
+ * @see https://instantdb.com/docs/auth
159
+ * @example
160
+ * function App() {
161
+ * const { isLoading, user, error } = db.useAuth()
162
+ * if (isLoading) {
163
+ * return <div>Loading...</div>
164
+ * }
165
+ * if (error) {
166
+ * return <div>Uh oh! {error.message}</div>
167
+ * }
168
+ * if (user) {
169
+ * return <Main user={user} />
170
+ * }
171
+ * return <Login />
172
+ * }
173
+ *
174
+ */
175
+ useAuth = () => {
176
+ return this._useAuth();
177
+ };
291
178
  _useAuth() {
292
179
  // We use a ref to store the result of the query.
293
180
  // This is becuase `useSyncExternalStore` uses `Object.is`
@@ -299,7 +186,7 @@ export default class InstantReactAbstractDatabase {
299
186
  // if `subscribe` changes, so we use `useCallback` to memoize the function.
300
187
  const subscribe = useCallback((cb) => {
301
188
  const unsubscribe = this.core.subscribeAuth((auth) => {
302
- resultCacheRef.current = Object.assign({ isLoading: false }, auth);
189
+ resultCacheRef.current = { isLoading: false, ...auth };
303
190
  cb();
304
191
  });
305
192
  return unsubscribe;
@@ -307,6 +194,32 @@ export default class InstantReactAbstractDatabase {
307
194
  const state = useSyncExternalStore(subscribe, () => resultCacheRef.current, () => defaultAuthState);
308
195
  return state;
309
196
  }
197
+ /**
198
+ * Subscribe to the currently logged in user.
199
+ * If the user is not logged in, this hook with throw an Error.
200
+ * You will want to protect any calls of this hook with a
201
+ * <db.SignedIn> component, or your own logic based on db.useAuth()
202
+ *
203
+ * @see https://instantdb.com/docs/auth
204
+ * @throws Error indicating user not signed in
205
+ * @example
206
+ * function UserDisplay() {
207
+ * const user = db.useUser()
208
+ * return <div>Logged in as: {user.email}</div>
209
+ * }
210
+ *
211
+ * <db.SignedIn>
212
+ * <UserDisplay />
213
+ * </db.SignedIn>
214
+ *
215
+ */
216
+ useUser = () => {
217
+ const { user } = this.useAuth();
218
+ if (!user) {
219
+ throw new InstantError('useUser must be used within an auth-protected route');
220
+ }
221
+ return user;
222
+ };
310
223
  /**
311
224
  * One time query for the logged in state. This is useful
312
225
  * for scenarios where you want to know the current auth
@@ -320,5 +233,91 @@ export default class InstantReactAbstractDatabase {
320
233
  getAuth() {
321
234
  return this.core.getAuth();
322
235
  }
236
+ /**
237
+ * Listen for connection status changes to Instant. Use this for things like
238
+ * showing connection state to users
239
+ *
240
+ * @see https://www.instantdb.com/docs/patterns#connection-status
241
+ * @example
242
+ * function App() {
243
+ * const status = db.useConnectionStatus()
244
+ * const connectionState =
245
+ * status === 'connecting' || status === 'opened'
246
+ * ? 'authenticating'
247
+ * : status === 'authenticated'
248
+ * ? 'connected'
249
+ * : status === 'closed'
250
+ * ? 'closed'
251
+ * : status === 'errored'
252
+ * ? 'errored'
253
+ * : 'unexpected state';
254
+ *
255
+ * return <div>Connection state: {connectionState}</div>
256
+ * }
257
+ */
258
+ useConnectionStatus = () => {
259
+ const statusRef = useRef(this.core._reactor.status);
260
+ const subscribe = useCallback((cb) => {
261
+ const unsubscribe = this.core.subscribeConnectionStatus((newStatus) => {
262
+ if (newStatus !== statusRef.current) {
263
+ statusRef.current = newStatus;
264
+ cb();
265
+ }
266
+ });
267
+ return unsubscribe;
268
+ }, []);
269
+ const status = useSyncExternalStore(subscribe, () => statusRef.current,
270
+ // For SSR, always return 'connecting' as the initial state
271
+ () => 'connecting');
272
+ return status;
273
+ };
274
+ /**
275
+ * Use this for one-off queries.
276
+ * Returns local data if available, otherwise fetches from the server.
277
+ * Because we want to avoid stale data, this method will throw an error
278
+ * if the user is offline or there is no active connection to the server.
279
+ *
280
+ * @see https://instantdb.com/docs/instaql
281
+ *
282
+ * @example
283
+ *
284
+ * const resp = await db.queryOnce({ goals: {} });
285
+ * console.log(resp.data.goals)
286
+ */
287
+ queryOnce = (query, opts) => {
288
+ return this.core.queryOnce(query, opts);
289
+ };
290
+ /**
291
+ * Only render children if the user is signed in.
292
+ * @see https://instantdb.com/docs/auth
293
+ *
294
+ * @example
295
+ * <db.SignedIn>
296
+ * <MyComponent />
297
+ * </db.SignedIn>
298
+ *
299
+ */
300
+ SignedIn = ({ children }) => {
301
+ const auth = this.useAuth();
302
+ if (auth.isLoading || auth.error || !auth.user)
303
+ return null;
304
+ return _jsx(_Fragment, { children: children });
305
+ };
306
+ /**
307
+ * Only render children if the user is signed out.
308
+ * @see https://instantdb.com/docs/auth
309
+ *
310
+ * @example
311
+ * <db.SignedOut>
312
+ * <MyComponent />
313
+ * </db.SignedOut>
314
+ *
315
+ */
316
+ SignedOut = ({ children }) => {
317
+ const auth = this.useAuth();
318
+ if (auth.isLoading || auth.error || auth.user)
319
+ return null;
320
+ return _jsx(_Fragment, { children: children });
321
+ };
323
322
  }
324
323
  //# sourceMappingURL=InstantReactAbstractDatabase.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InstantReactAbstractDatabase.js","sourceRoot":"","sources":["../../src/InstantReactAbstractDatabase.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\nimport {\n // types\n Auth,\n Storage,\n txInit,\n type AuthState,\n type User,\n type ConnectionStatus,\n type TransactionChunk,\n type RoomSchemaShape,\n type InstaQLOptions,\n type InstantConfig,\n type PageInfoResponse,\n InstantCoreDatabase,\n init as core_init,\n InstaQLLifecycleState,\n InstaQLResponse,\n RoomsOf,\n InstantSchemaDef,\n IInstantDatabase,\n InstantError,\n ValidQuery,\n} from '@instantdb/core';\nimport {\n ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { useQueryInternal } from './useQuery.ts';\nimport { InstantReactRoom, rooms } from './InstantReactRoom.ts';\n\nconst defaultAuthState = {\n isLoading: true,\n user: undefined,\n error: undefined,\n};\n\nexport default abstract class InstantReactAbstractDatabase<\n // need to pull this schema out to another generic for query params, not sure why\n Schema extends InstantSchemaDef<any, any, any>,\n UseDates extends boolean = false,\n Config extends InstantConfig<Schema, boolean> = InstantConfig<\n Schema,\n UseDates\n >,\n Rooms extends RoomSchemaShape = RoomsOf<Schema>,\n> implements IInstantDatabase<Schema>\n{\n public tx = txInit<Schema>();\n\n public auth: Auth;\n public storage: Storage;\n public core: InstantCoreDatabase<Schema, UseDates>;\n\n /** @deprecated use `core` instead */\n public _core: InstantCoreDatabase<Schema, UseDates>;\n\n static Storage?: any;\n static NetworkListener?: any;\n static EventSourceImpl?: any;\n\n constructor(\n config: Omit<InstantConfig<Schema, UseDates>, 'useDateObjects'> & {\n useDateObjects?: UseDates;\n },\n versions?: { [key: string]: string },\n ) {\n this.core = core_init<Schema, UseDates>(\n config,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.Storage,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.NetworkListener,\n versions,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.EventSourceImpl,\n );\n this._core = this.core;\n this.auth = this.core.auth;\n this.storage = this.core.storage;\n }\n\n /**\n * Returns a unique ID for a given `name`. It's stored in local storage,\n * so you will get the same ID across sessions.\n *\n * This is useful for generating IDs that could identify a local device or user.\n *\n * @example\n * const deviceId = await db.getLocalId('device');\n */\n getLocalId = (name: string): Promise<string> => {\n return this.core.getLocalId(name);\n };\n\n /**\n * A hook that returns a unique ID for a given `name`. localIds are\n * stored in local storage, so you will get the same ID across sessions.\n *\n * Initially returns `null`, and then loads the localId.\n *\n * @example\n * const deviceId = db.useLocalId('device');\n * if (!deviceId) return null; // loading\n * console.log('Device ID:', deviceId)\n */\n useLocalId = (name: string): string | null => {\n const [localId, setLocalId] = useState<string | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const f = async () => {\n const id = await this.getLocalId(name);\n if (!mounted) return;\n setLocalId(id);\n };\n f();\n return;\n }, [name]);\n\n return localId;\n };\n\n /**\n * Obtain a handle to a room, which allows you to listen to topics and presence data\n *\n * If you don't provide a `type` or `id`, Instant will default to `_defaultRoomType` and `_defaultRoomId`\n * as the room type and id, respectively.\n *\n * @see https://instantdb.com/docs/presence-and-topics\n *\n * @example\n * const room = db.room('chat', roomId);\n * const { peers } = db.rooms.usePresence(room);\n */\n room<RoomType extends keyof Rooms>(\n type: RoomType = '_defaultRoomType' as RoomType,\n id: string = '_defaultRoomId',\n ) {\n return new InstantReactRoom<Schema, Rooms, RoomType>(this.core, type, id);\n }\n\n /**\n * Hooks for working with rooms\n *\n * @see https://instantdb.com/docs/presence-and-topics\n *\n * @example\n * const room = db.room('chat', roomId);\n * const { peers } = db.rooms.usePresence(room);\n * const publish = db.rooms.usePublishTopic(room, 'emoji');\n * // ...\n */\n rooms = rooms;\n\n /**\n * Use this to write data! You can create, update, delete, and link objects\n *\n * @see https://instantdb.com/docs/instaml\n *\n * @example\n * // Create a new object in the `goals` namespace\n * const goalId = id();\n * db.transact(db.tx.goals[goalId].update({title: \"Get fit\"}))\n *\n * // Update the title\n * db.transact(db.tx.goals[goalId].update({title: \"Get super fit\"}))\n *\n * // Delete it\n * db.transact(db.tx.goals[goalId].delete())\n *\n * // Or create an association:\n * todoId = id();\n * db.transact([\n * db.tx.todos[todoId].update({ title: 'Go on a run' }),\n * db.tx.goals[goalId].link({todos: todoId}),\n * ])\n */\n transact = (\n chunks: TransactionChunk<any, any> | TransactionChunk<any, any>[],\n ) => {\n return this.core.transact(chunks);\n };\n\n /**\n * Use this to query your data!\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n * // listen to all goals\n * const { isLoading, error, data } = db.useQuery({ goals: {} });\n *\n * // goals where the title is \"Get Fit\"\n * const { isLoading, error, data } = db.useQuery({\n * goals: { $: { where: { title: 'Get Fit' } } },\n * });\n *\n * // all goals, _alongside_ their todos\n * const { isLoading, error, data } = db.useQuery({\n * goals: { todos: {} },\n * });\n *\n * // skip if `user` is not logged in\n * const { isLoading, error, data } = db.useQuery(\n * auth.user ? { goals: {} } : null,\n * );\n */\n useQuery = <Q extends ValidQuery<Q, Schema>>(\n query: null | Q,\n opts?: InstaQLOptions,\n ): InstaQLLifecycleState<Schema, Q, UseDates> => {\n return useQueryInternal<Q, Schema, UseDates>(this.core, query, opts).state;\n };\n\n /**\n * Listen for the logged in state. This is useful\n * for deciding when to show a login screen.\n *\n * Check out the docs for an example `Login` component too!\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * function App() {\n * const { isLoading, user, error } = db.useAuth()\n * if (isLoading) {\n * return <div>Loading...</div>\n * }\n * if (error) {\n * return <div>Uh oh! {error.message}</div>\n * }\n * if (user) {\n * return <Main user={user} />\n * }\n * return <Login />\n * }\n *\n */\n useAuth = (): AuthState => {\n return this._useAuth();\n };\n\n protected _useAuth(): AuthState {\n // We use a ref to store the result of the query.\n // This is becuase `useSyncExternalStore` uses `Object.is`\n // to compare the previous and next state.\n // If we don't use a ref, the state will always be considered different, so\n // the component will always re-render.\n const resultCacheRef = useRef<AuthState>(\n this.core._reactor._currentUserCached,\n );\n\n // Similar to `resultCacheRef`, `useSyncExternalStore` will unsubscribe\n // if `subscribe` changes, so we use `useCallback` to memoize the function.\n const subscribe = useCallback((cb: Function) => {\n const unsubscribe = this.core.subscribeAuth((auth) => {\n resultCacheRef.current = { isLoading: false, ...auth };\n cb();\n });\n\n return unsubscribe;\n }, []);\n\n const state = useSyncExternalStore<AuthState>(\n subscribe,\n () => resultCacheRef.current,\n () => defaultAuthState,\n );\n return state;\n }\n\n /**\n * Subscribe to the currently logged in user.\n * If the user is not logged in, this hook with throw an Error.\n * You will want to protect any calls of this hook with a\n * <db.SignedIn> component, or your own logic based on db.useAuth()\n *\n * @see https://instantdb.com/docs/auth\n * @throws Error indicating user not signed in\n * @example\n * function UserDisplay() {\n * const user = db.useUser()\n * return <div>Logged in as: {user.email}</div>\n * }\n *\n * <db.SignedIn>\n * <UserDisplay />\n * </db.SignedIn>\n *\n */\n useUser = (): User => {\n const { user } = this.useAuth();\n if (!user) {\n throw new InstantError(\n 'useUser must be used within an auth-protected route',\n );\n }\n return user;\n };\n\n /**\n * One time query for the logged in state. This is useful\n * for scenarios where you want to know the current auth\n * state without subscribing to changes.\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * const user = await db.getAuth();\n * console.log('logged in as', user.email)\n */\n getAuth(): Promise<User | null> {\n return this.core.getAuth();\n }\n\n /**\n * Listen for connection status changes to Instant. Use this for things like\n * showing connection state to users\n *\n * @see https://www.instantdb.com/docs/patterns#connection-status\n * @example\n * function App() {\n * const status = db.useConnectionStatus()\n * const connectionState =\n * status === 'connecting' || status === 'opened'\n * ? 'authenticating'\n * : status === 'authenticated'\n * ? 'connected'\n * : status === 'closed'\n * ? 'closed'\n * : status === 'errored'\n * ? 'errored'\n * : 'unexpected state';\n *\n * return <div>Connection state: {connectionState}</div>\n * }\n */\n useConnectionStatus = (): ConnectionStatus => {\n const statusRef = useRef<ConnectionStatus>(\n this.core._reactor.status as ConnectionStatus,\n );\n\n const subscribe = useCallback((cb: Function) => {\n const unsubscribe = this.core.subscribeConnectionStatus((newStatus) => {\n if (newStatus !== statusRef.current) {\n statusRef.current = newStatus;\n cb();\n }\n });\n\n return unsubscribe;\n }, []);\n\n const status = useSyncExternalStore<ConnectionStatus>(\n subscribe,\n () => statusRef.current,\n // For SSR, always return 'connecting' as the initial state\n () => 'connecting',\n );\n\n return status;\n };\n\n /**\n * Use this for one-off queries.\n * Returns local data if available, otherwise fetches from the server.\n * Because we want to avoid stale data, this method will throw an error\n * if the user is offline or there is no active connection to the server.\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n *\n * const resp = await db.queryOnce({ goals: {} });\n * console.log(resp.data.goals)\n */\n queryOnce = <Q extends ValidQuery<Q, Schema>>(\n query: Q,\n opts?: InstaQLOptions,\n ): Promise<{\n data: InstaQLResponse<Schema, Q, UseDates>;\n pageInfo: PageInfoResponse<Q>;\n }> => {\n return this.core.queryOnce(query, opts);\n };\n\n /**\n * Only render children if the user is signed in.\n * @see https://instantdb.com/docs/auth\n *\n * @example\n * <db.SignedIn>\n * <MyComponent />\n * </db.SignedIn>\n *\n */\n SignedIn: React.FC<{\n children: ReactNode;\n }> = ({ children }) => {\n const auth = this.useAuth();\n if (auth.isLoading || auth.error || !auth.user) return null;\n\n return <>{children}</>;\n };\n\n /**\n * Only render children if the user is signed out.\n * @see https://instantdb.com/docs/auth\n *\n * @example\n * <db.SignedOut>\n * <MyComponent />\n * </db.SignedOut>\n *\n */\n SignedOut: React.FC<{\n children: ReactNode;\n }> = ({ children }) => {\n const auth = this.useAuth();\n if (auth.isLoading || auth.error || auth.user) return null;\n return <>{children}</>;\n };\n}\n"]}
1
+ {"version":3,"file":"InstantReactAbstractDatabase.js","sourceRoot":"","sources":["../../src/InstantReactAbstractDatabase.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\nimport {\n // types\n Auth,\n Storage,\n txInit,\n type AuthState,\n type User,\n type ConnectionStatus,\n type TransactionChunk,\n type RoomSchemaShape,\n type InstaQLOptions,\n type InstantConfig,\n type PageInfoResponse,\n InstantCoreDatabase,\n init as core_init,\n InstaQLLifecycleState,\n InstaQLResponse,\n RoomsOf,\n InstantSchemaDef,\n IInstantDatabase,\n InstantError,\n ValidQuery,\n} from '@instantdb/core';\nimport {\n ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { useQueryInternal } from './useQuery.ts';\nimport { InstantReactRoom, rooms } from './InstantReactRoom.ts';\n\nconst defaultAuthState = {\n isLoading: true,\n user: undefined,\n error: undefined,\n};\n\nexport default abstract class InstantReactAbstractDatabase<\n // need to pull this schema out to another generic for query params, not sure why\n Schema extends InstantSchemaDef<any, any, any>,\n UseDates extends boolean = false,\n Config extends InstantConfig<Schema, boolean> = InstantConfig<\n Schema,\n UseDates\n >,\n Rooms extends RoomSchemaShape = RoomsOf<Schema>,\n> implements IInstantDatabase<Schema>\n{\n public tx = txInit<Schema>();\n\n public auth: Auth;\n public storage: Storage;\n public core: InstantCoreDatabase<Schema, UseDates>;\n\n /** @deprecated use `core` instead */\n public _core: InstantCoreDatabase<Schema, UseDates>;\n\n static Storage?: any;\n static NetworkListener?: any;\n static EventSourceImpl?: any;\n\n constructor(\n config: Omit<InstantConfig<Schema, UseDates>, 'useDateObjects'> & {\n useDateObjects?: UseDates;\n },\n versions?: { [key: string]: string },\n ) {\n this.core = core_init<Schema, UseDates>(\n config,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.Storage,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.NetworkListener,\n versions,\n // @ts-expect-error because TS can't resolve subclass statics\n this.constructor.EventSourceImpl,\n );\n this._core = this.core;\n this.auth = this.core.auth;\n this.storage = this.core.storage;\n }\n\n /**\n * Returns a unique ID for a given `name`. It's stored in local storage,\n * so you will get the same ID across sessions.\n *\n * This is useful for generating IDs that could identify a local device or user.\n *\n * @example\n * const deviceId = await db.getLocalId('device');\n */\n getLocalId = (name: string): Promise<string> => {\n return this.core.getLocalId(name);\n };\n\n /**\n * A hook that returns a unique ID for a given `name`. localIds are\n * stored in local storage, so you will get the same ID across sessions.\n *\n * Initially returns `null`, and then loads the localId.\n *\n * @example\n * const deviceId = db.useLocalId('device');\n * if (!deviceId) return null; // loading\n * console.log('Device ID:', deviceId)\n */\n useLocalId = (name: string): string | null => {\n const [localId, setLocalId] = useState<string | null>(null);\n\n useEffect(() => {\n let mounted = true;\n const f = async () => {\n const id = await this.getLocalId(name);\n if (!mounted) return;\n setLocalId(id);\n };\n f();\n return;\n }, [name]);\n\n return localId;\n };\n\n /**\n * Obtain a handle to a room, which allows you to listen to topics and presence data\n *\n * If you don't provide a `type` or `id`, Instant will default to `_defaultRoomType` and `_defaultRoomId`\n * as the room type and id, respectively.\n *\n * @see https://instantdb.com/docs/presence-and-topics\n *\n * @example\n * const room = db.room('chat', roomId);\n * const { peers } = db.rooms.usePresence(room);\n */\n room<RoomType extends keyof Rooms>(\n type: RoomType = '_defaultRoomType' as RoomType,\n id: string = '_defaultRoomId',\n ) {\n return new InstantReactRoom<Schema, Rooms, RoomType>(this.core, type, id);\n }\n\n /**\n * Hooks for working with rooms\n *\n * @see https://instantdb.com/docs/presence-and-topics\n *\n * @example\n * const room = db.room('chat', roomId);\n * const { peers } = db.rooms.usePresence(room);\n * const publish = db.rooms.usePublishTopic(room, 'emoji');\n * // ...\n */\n rooms = rooms;\n\n /**\n * Use this to write data! You can create, update, delete, and link objects\n *\n * @see https://instantdb.com/docs/instaml\n *\n * @example\n * // Create a new object in the `goals` namespace\n * const goalId = id();\n * db.transact(db.tx.goals[goalId].update({title: \"Get fit\"}))\n *\n * // Update the title\n * db.transact(db.tx.goals[goalId].update({title: \"Get super fit\"}))\n *\n * // Delete it\n * db.transact(db.tx.goals[goalId].delete())\n *\n * // Or create an association:\n * todoId = id();\n * db.transact([\n * db.tx.todos[todoId].update({ title: 'Go on a run' }),\n * db.tx.goals[goalId].link({todos: todoId}),\n * ])\n */\n transact = (\n chunks: TransactionChunk<any, any> | TransactionChunk<any, any>[],\n ) => {\n return this.core.transact(chunks);\n };\n\n /**\n * Use this to query your data!\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n * // listen to all goals\n * const { isLoading, error, data } = db.useQuery({ goals: {} });\n *\n * // goals where the title is \"Get Fit\"\n * const { isLoading, error, data } = db.useQuery({\n * goals: { $: { where: { title: 'Get Fit' } } },\n * });\n *\n * // all goals, _alongside_ their todos\n * const { isLoading, error, data } = db.useQuery({\n * goals: { todos: {} },\n * });\n *\n * // skip if `user` is not logged in\n * const { isLoading, error, data } = db.useQuery(\n * auth.user ? { goals: {} } : null,\n * );\n */\n useQuery = <Q extends ValidQuery<Q, Schema>>(\n query: null | Q,\n opts?: InstaQLOptions,\n ): InstaQLLifecycleState<Schema, Q, UseDates> => {\n return useQueryInternal<Q, Schema, UseDates>(this.core, query, opts).state;\n };\n\n /**\n * Listen for the logged in state. This is useful\n * for deciding when to show a login screen.\n *\n * Check out the docs for an example `Login` component too!\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * function App() {\n * const { isLoading, user, error } = db.useAuth()\n * if (isLoading) {\n * return <div>Loading...</div>\n * }\n * if (error) {\n * return <div>Uh oh! {error.message}</div>\n * }\n * if (user) {\n * return <Main user={user} />\n * }\n * return <Login />\n * }\n *\n */\n useAuth = (): AuthState => {\n return this._useAuth();\n };\n\n protected _useAuth(): AuthState {\n // We use a ref to store the result of the query.\n // This is becuase `useSyncExternalStore` uses `Object.is`\n // to compare the previous and next state.\n // If we don't use a ref, the state will always be considered different, so\n // the component will always re-render.\n const resultCacheRef = useRef<AuthState>(\n this.core._reactor._currentUserCached,\n );\n\n // Similar to `resultCacheRef`, `useSyncExternalStore` will unsubscribe\n // if `subscribe` changes, so we use `useCallback` to memoize the function.\n const subscribe = useCallback((cb: Function) => {\n const unsubscribe = this.core.subscribeAuth((auth) => {\n resultCacheRef.current = { isLoading: false, ...auth };\n cb();\n });\n\n return unsubscribe;\n }, []);\n\n const state = useSyncExternalStore<AuthState>(\n subscribe,\n () => resultCacheRef.current,\n () => defaultAuthState,\n );\n return state;\n }\n\n /**\n * Subscribe to the currently logged in user.\n * If the user is not logged in, this hook with throw an Error.\n * You will want to protect any calls of this hook with a\n * <db.SignedIn> component, or your own logic based on db.useAuth()\n *\n * @see https://instantdb.com/docs/auth\n * @throws Error indicating user not signed in\n * @example\n * function UserDisplay() {\n * const user = db.useUser()\n * return <div>Logged in as: {user.email}</div>\n * }\n *\n * <db.SignedIn>\n * <UserDisplay />\n * </db.SignedIn>\n *\n */\n useUser = (): User => {\n const { user } = this.useAuth();\n if (!user) {\n throw new InstantError(\n 'useUser must be used within an auth-protected route',\n );\n }\n return user;\n };\n\n /**\n * One time query for the logged in state. This is useful\n * for scenarios where you want to know the current auth\n * state without subscribing to changes.\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * const user = await db.getAuth();\n * console.log('logged in as', user.email)\n */\n getAuth(): Promise<User | null> {\n return this.core.getAuth();\n }\n\n /**\n * Listen for connection status changes to Instant. Use this for things like\n * showing connection state to users\n *\n * @see https://www.instantdb.com/docs/patterns#connection-status\n * @example\n * function App() {\n * const status = db.useConnectionStatus()\n * const connectionState =\n * status === 'connecting' || status === 'opened'\n * ? 'authenticating'\n * : status === 'authenticated'\n * ? 'connected'\n * : status === 'closed'\n * ? 'closed'\n * : status === 'errored'\n * ? 'errored'\n * : 'unexpected state';\n *\n * return <div>Connection state: {connectionState}</div>\n * }\n */\n useConnectionStatus = (): ConnectionStatus => {\n const statusRef = useRef<ConnectionStatus>(\n this.core._reactor.status as ConnectionStatus,\n );\n\n const subscribe = useCallback((cb: Function) => {\n const unsubscribe = this.core.subscribeConnectionStatus((newStatus) => {\n if (newStatus !== statusRef.current) {\n statusRef.current = newStatus;\n cb();\n }\n });\n\n return unsubscribe;\n }, []);\n\n const status = useSyncExternalStore<ConnectionStatus>(\n subscribe,\n () => statusRef.current,\n // For SSR, always return 'connecting' as the initial state\n () => 'connecting',\n );\n\n return status;\n };\n\n /**\n * Use this for one-off queries.\n * Returns local data if available, otherwise fetches from the server.\n * Because we want to avoid stale data, this method will throw an error\n * if the user is offline or there is no active connection to the server.\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n *\n * const resp = await db.queryOnce({ goals: {} });\n * console.log(resp.data.goals)\n */\n queryOnce = <Q extends ValidQuery<Q, Schema>>(\n query: Q,\n opts?: InstaQLOptions,\n ): Promise<{\n data: InstaQLResponse<Schema, Q, UseDates>;\n pageInfo: PageInfoResponse<Q>;\n }> => {\n return this.core.queryOnce(query, opts);\n };\n\n /**\n * Only render children if the user is signed in.\n * @see https://instantdb.com/docs/auth\n *\n * @example\n * <db.SignedIn>\n * <MyComponent />\n * </db.SignedIn>\n *\n */\n SignedIn: React.FC<{\n children: ReactNode;\n }> = ({ children }) => {\n const auth = this.useAuth();\n if (auth.isLoading || auth.error || !auth.user) return null;\n\n return <>{children}</>;\n };\n\n /**\n * Only render children if the user is signed out.\n * @see https://instantdb.com/docs/auth\n *\n * @example\n * <db.SignedOut>\n * <MyComponent />\n * </db.SignedOut>\n *\n */\n SignedOut: React.FC<{\n children: ReactNode;\n }> = ({ children }) => {\n const auth = this.useAuth();\n if (auth.isLoading || auth.error || auth.user) return null;\n return <>{children}</>;\n };\n}\n"]}