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