@fidscript/instant-solidjs 0.1.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.
Files changed (43) hide show
  1. package/.tshy/build.json +8 -0
  2. package/.tshy/commonjs.json +16 -0
  3. package/.tshy/esm.json +15 -0
  4. package/dist/commonjs/InstantSolidDatabase.d.ts +185 -0
  5. package/dist/commonjs/InstantSolidDatabase.d.ts.map +1 -0
  6. package/dist/commonjs/InstantSolidDatabase.js +329 -0
  7. package/dist/commonjs/InstantSolidDatabase.js.map +1 -0
  8. package/dist/commonjs/InstantSolidRoom.d.ts +97 -0
  9. package/dist/commonjs/InstantSolidRoom.d.ts.map +1 -0
  10. package/dist/commonjs/InstantSolidRoom.js +209 -0
  11. package/dist/commonjs/InstantSolidRoom.js.map +1 -0
  12. package/dist/commonjs/index.d.ts +6 -0
  13. package/dist/commonjs/index.d.ts.map +1 -0
  14. package/dist/commonjs/index.js +23 -0
  15. package/dist/commonjs/index.js.map +1 -0
  16. package/dist/commonjs/package.json +3 -0
  17. package/dist/commonjs/version.d.ts +3 -0
  18. package/dist/commonjs/version.d.ts.map +1 -0
  19. package/dist/commonjs/version.js +5 -0
  20. package/dist/commonjs/version.js.map +1 -0
  21. package/dist/esm/InstantSolidDatabase.d.ts +185 -0
  22. package/dist/esm/InstantSolidDatabase.d.ts.map +1 -0
  23. package/dist/esm/InstantSolidDatabase.js +321 -0
  24. package/dist/esm/InstantSolidDatabase.js.map +1 -0
  25. package/dist/esm/InstantSolidRoom.d.ts +97 -0
  26. package/dist/esm/InstantSolidRoom.d.ts.map +1 -0
  27. package/dist/esm/InstantSolidRoom.js +200 -0
  28. package/dist/esm/InstantSolidRoom.js.map +1 -0
  29. package/dist/esm/index.d.ts +6 -0
  30. package/dist/esm/index.d.ts.map +1 -0
  31. package/dist/esm/index.js +18 -0
  32. package/dist/esm/index.js.map +1 -0
  33. package/dist/esm/package.json +3 -0
  34. package/dist/esm/version.d.ts +3 -0
  35. package/dist/esm/version.d.ts.map +1 -0
  36. package/dist/esm/version.js +3 -0
  37. package/dist/esm/version.js.map +1 -0
  38. package/package.json +47 -0
  39. package/src/InstantSolidDatabase.ts +463 -0
  40. package/src/InstantSolidRoom.ts +330 -0
  41. package/src/index.ts +204 -0
  42. package/src/version.ts +2 -0
  43. package/tsconfig.json +45 -0
@@ -0,0 +1,321 @@
1
+ import { txInit, init as core_init, coerceQuery, getInfiniteQueryInitialSnapshot, InstantError, } from '@fidscript/instant-sdk';
2
+ import { createSignal, createEffect, onCleanup, createMemo } from 'solid-js';
3
+ import { InstantSolidRoom, rooms } from './InstantSolidRoom.js';
4
+ import version from './version.js';
5
+ const defaultState = {
6
+ isLoading: true,
7
+ data: undefined,
8
+ pageInfo: undefined,
9
+ error: undefined,
10
+ };
11
+ const defaultAuthState = {
12
+ isLoading: true,
13
+ user: undefined,
14
+ error: undefined,
15
+ };
16
+ function stateForResult(result) {
17
+ return {
18
+ isLoading: !Boolean(result),
19
+ data: undefined,
20
+ pageInfo: undefined,
21
+ error: undefined,
22
+ ...(result ? result : {}),
23
+ };
24
+ }
25
+ export class InstantSolidDatabase {
26
+ tx = txInit();
27
+ auth;
28
+ storage;
29
+ streams;
30
+ core;
31
+ constructor(core) {
32
+ this.core = core;
33
+ this.auth = this.core.auth;
34
+ this.storage = this.core.storage;
35
+ this.streams = this.core.streams;
36
+ }
37
+ /**
38
+ * Returns a unique ID for a given `name`. It's stored in local storage,
39
+ * so you will get the same ID across sessions.
40
+ *
41
+ * @example
42
+ * const deviceId = await db.getLocalId('device');
43
+ */
44
+ getLocalId = (name) => {
45
+ return this.core.getLocalId(name);
46
+ };
47
+ /**
48
+ * Use this to write data! You can create, update, delete, and link objects
49
+ *
50
+ * @see https://instantdb.com/docs/instaml
51
+ *
52
+ * @example
53
+ * const goalId = id();
54
+ * db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
55
+ */
56
+ transact = (chunks) => {
57
+ return this.core.transact(chunks);
58
+ };
59
+ /**
60
+ * One time query for the logged in state.
61
+ *
62
+ * @see https://instantdb.com/docs/auth
63
+ * @example
64
+ * const user = await db.getAuth();
65
+ * console.log('logged in as', user.email)
66
+ */
67
+ getAuth() {
68
+ return this.core.getAuth();
69
+ }
70
+ /**
71
+ * Use this for one-off queries.
72
+ * Returns local data if available, otherwise fetches from the server.
73
+ *
74
+ * @see https://instantdb.com/docs/instaql
75
+ *
76
+ * @example
77
+ * const resp = await db.queryOnce({ goals: {} });
78
+ * console.log(resp.data.goals)
79
+ */
80
+ queryOnce = (query, opts) => {
81
+ return this.core.queryOnce(query, opts);
82
+ };
83
+ // -----------
84
+ // Solid reactive hooks
85
+ /**
86
+ * Use this to query your data!
87
+ *
88
+ * @see https://instantdb.com/docs/instaql
89
+ *
90
+ * @example
91
+ * const state = db.useQuery({ goals: {} });
92
+ * // state().isLoading, state().error, state().data
93
+ */
94
+ useQuery = (query, opts) => {
95
+ const [state, setState] = createSignal(defaultState);
96
+ createEffect(() => {
97
+ const resolvedQuery = typeof query === 'function' ? query() : query;
98
+ if (!resolvedQuery) {
99
+ setState(() => defaultState);
100
+ return;
101
+ }
102
+ let q = resolvedQuery;
103
+ if (opts && 'ruleParams' in opts) {
104
+ q = { $$ruleParams: opts['ruleParams'], ...q };
105
+ }
106
+ const coerced = coerceQuery(q);
107
+ const prev = this.core._reactor.getPreviousResult(coerced);
108
+ if (prev) {
109
+ setState(() => stateForResult(prev));
110
+ }
111
+ const unsub = this.core.subscribeQuery(coerced, (result) => {
112
+ setState(() => Object.assign({
113
+ isLoading: false,
114
+ data: undefined,
115
+ pageInfo: undefined,
116
+ error: undefined,
117
+ }, result));
118
+ });
119
+ onCleanup(unsub);
120
+ });
121
+ return state;
122
+ };
123
+ /**
124
+ * Subscribe to a query and incrementally load more items.
125
+ *
126
+ * Only one top level namespace in the query is allowed.
127
+ *
128
+ * @see https://instantdb.com/docs/instaql
129
+ *
130
+ * @example
131
+ * const state = db.useInfiniteQuery({
132
+ * posts: {
133
+ * $: {
134
+ * limit: 20,
135
+ * order: { createdAt: 'desc' },
136
+ * },
137
+ * },
138
+ * });
139
+ * // state().data, state().isLoading, state().error,
140
+ * // state().canLoadNextPage, state().loadNextPage()
141
+ */
142
+ useInfiniteQuery = (query, opts) => {
143
+ let sub = null;
144
+ const loadNextPage = () => sub?.loadNextPage();
145
+ const [state, setState] = createSignal({
146
+ isLoading: true,
147
+ error: undefined,
148
+ data: undefined,
149
+ canLoadNextPage: false,
150
+ loadNextPage,
151
+ });
152
+ createEffect(() => {
153
+ const resolvedQuery = typeof query === 'function' ? query() : query;
154
+ if (!resolvedQuery) {
155
+ sub = null;
156
+ setState(() => ({
157
+ isLoading: true,
158
+ error: undefined,
159
+ data: undefined,
160
+ canLoadNextPage: false,
161
+ loadNextPage,
162
+ }));
163
+ return;
164
+ }
165
+ const snapshot = getInfiniteQueryInitialSnapshot(this.core, resolvedQuery, opts);
166
+ setState(() => ({
167
+ ...snapshot,
168
+ isLoading: !snapshot.data && !snapshot.error,
169
+ loadNextPage,
170
+ }));
171
+ sub = this.core.subscribeInfiniteQuery(resolvedQuery, (resp) => {
172
+ setState(() => ({
173
+ ...resp,
174
+ isLoading: false,
175
+ loadNextPage,
176
+ }));
177
+ }, opts);
178
+ onCleanup(() => {
179
+ sub?.unsubscribe();
180
+ sub = null;
181
+ });
182
+ });
183
+ return state;
184
+ };
185
+ /**
186
+ * Listen for the logged in state. This is useful
187
+ * for deciding when to show a login screen.
188
+ *
189
+ * @see https://instantdb.com/docs/auth
190
+ * @example
191
+ * function App() {
192
+ * const auth = db.useAuth();
193
+ * // auth().isLoading, auth().user, auth().error
194
+ * }
195
+ */
196
+ useAuth = () => {
197
+ const [state, setState] = createSignal(this.core._reactor._currentUserCached ?? defaultAuthState);
198
+ createEffect(() => {
199
+ const unsub = this.core.subscribeAuth((auth) => {
200
+ setState({ isLoading: false, ...auth });
201
+ });
202
+ onCleanup(unsub);
203
+ });
204
+ return state;
205
+ };
206
+ /**
207
+ * Subscribe to the currently logged in user.
208
+ * If the user is not logged in, this will throw an Error.
209
+ *
210
+ * @see https://instantdb.com/docs/auth
211
+ * @example
212
+ * function UserDisplay() {
213
+ * const user = db.useUser();
214
+ * return <div>Logged in as: {user().email}</div>
215
+ * }
216
+ */
217
+ useUser = () => {
218
+ const auth = this.useAuth();
219
+ return createMemo(() => {
220
+ const { user } = auth();
221
+ if (!user) {
222
+ throw new InstantError('useUser must be used within an auth-protected route');
223
+ }
224
+ return user;
225
+ });
226
+ };
227
+ /**
228
+ * Listen for connection status changes to Instant.
229
+ *
230
+ * @see https://www.instantdb.com/docs/patterns#connection-status
231
+ * @example
232
+ * function App() {
233
+ * const status = db.useConnectionStatus();
234
+ * return <div>Connection state: {status()}</div>
235
+ * }
236
+ */
237
+ useConnectionStatus = () => {
238
+ const [status, setStatus] = createSignal(this.core._reactor.status);
239
+ createEffect(() => {
240
+ const unsub = this.core.subscribeConnectionStatus((newStatus) => {
241
+ setStatus(() => newStatus);
242
+ });
243
+ onCleanup(unsub);
244
+ });
245
+ return status;
246
+ };
247
+ /**
248
+ * A hook that returns a unique ID for a given `name`. localIds are
249
+ * stored in local storage, so you will get the same ID across sessions.
250
+ *
251
+ * Initially returns `null`, and then loads the localId.
252
+ *
253
+ * @example
254
+ * const deviceId = db.useLocalId('device');
255
+ * // deviceId() is null initially, then the ID string
256
+ */
257
+ useLocalId = (name) => {
258
+ const [localId, setLocalId] = createSignal(null);
259
+ createEffect(() => {
260
+ let mounted = true;
261
+ this.getLocalId(name).then((id) => {
262
+ if (mounted) {
263
+ setLocalId(() => id);
264
+ }
265
+ });
266
+ onCleanup(() => {
267
+ mounted = false;
268
+ });
269
+ });
270
+ return localId;
271
+ };
272
+ /**
273
+ * Obtain a handle to a room, which allows you to listen to topics and presence data
274
+ *
275
+ * @see https://instantdb.com/docs/presence-and-topics
276
+ *
277
+ * @example
278
+ * const room = db.room('chat', roomId);
279
+ * const presence = db.rooms.usePresence(room);
280
+ */
281
+ room(type = '_defaultRoomType', id = '_defaultRoomId') {
282
+ return new InstantSolidRoom(this.core, type, id);
283
+ }
284
+ /**
285
+ * Hooks for working with rooms
286
+ *
287
+ * @see https://instantdb.com/docs/presence-and-topics
288
+ *
289
+ * @example
290
+ * const room = db.room('chat', roomId);
291
+ * const presence = db.rooms.usePresence(room);
292
+ * const publish = db.rooms.usePublishTopic(room, 'emoji');
293
+ */
294
+ rooms = rooms;
295
+ }
296
+ // -----------
297
+ // init
298
+ /**
299
+ * The first step: init your application!
300
+ *
301
+ * Visit https://instantdb.com/dash to get your `appId` :)
302
+ *
303
+ * @example
304
+ * import { init } from "@instantdb/solidjs"
305
+ *
306
+ * const db = init({ appId: "my-app-id" })
307
+ *
308
+ * // You can also provide a schema for type safety and editor autocomplete!
309
+ *
310
+ * import { init } from "@instantdb/solidjs"
311
+ * import schema from "../instant.schema.ts";
312
+ *
313
+ * const db = init({ appId: "my-app-id", schema })
314
+ */
315
+ export function init(config) {
316
+ const coreDb = core_init(config, undefined, undefined, {
317
+ '@instantdb/solidjs': version,
318
+ });
319
+ return new InstantSolidDatabase(coreDb);
320
+ }
321
+ //# sourceMappingURL=InstantSolidDatabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstantSolidDatabase.js","sourceRoot":"","sources":["../../src/InstantSolidDatabase.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n // types\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 type InstaQLLifecycleState,\n type InstaQLResponse,\n type InfiniteQuerySubscription,\n type ValidQuery,\n // classes\n Auth,\n Storage,\n Streams,\n txInit,\n InstantCoreDatabase,\n init as core_init,\n coerceQuery,\n getInfiniteQueryInitialSnapshot,\n InstantSchemaDef,\n RoomsOf,\n InstantError,\n IInstantDatabase,\n} from '@fidscript/instant-sdk';\n\nimport { createSignal, createEffect, onCleanup, createMemo } from 'solid-js';\nimport type { Accessor } from 'solid-js';\n\nimport { InstantSolidRoom, rooms } from './InstantSolidRoom.js';\nimport version from './version.js';\n\nconst defaultState = {\n isLoading: true,\n data: undefined,\n pageInfo: undefined,\n error: undefined,\n} as const;\n\nexport type InfiniteQueryState<\n Schema extends InstantSchemaDef<any, any, any>,\n Q extends ValidQuery<Q, Schema>,\n UseDates extends boolean,\n> = {\n isLoading: boolean;\n error: { message: string } | undefined;\n data: InstaQLResponse<Schema, Q, UseDates> | undefined;\n canLoadNextPage: boolean;\n loadNextPage: () => void;\n};\n\nconst defaultAuthState: AuthState = {\n isLoading: true,\n user: undefined,\n error: undefined,\n};\n\nfunction stateForResult(result: any) {\n return {\n isLoading: !Boolean(result),\n data: undefined,\n pageInfo: undefined,\n error: undefined,\n ...(result ? result : {}),\n };\n}\n\nexport class InstantSolidDatabase<\n Schema extends InstantSchemaDef<any, any, any>,\n UseDates extends boolean = false,\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 streams: Streams;\n public core: InstantCoreDatabase<Schema, UseDates>;\n\n constructor(core: InstantCoreDatabase<Schema, UseDates>) {\n this.core = core;\n this.auth = this.core.auth;\n this.storage = this.core.storage;\n this.streams = this.core.streams;\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 * @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 * 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 * const goalId = id();\n * db.transact(db.tx.goals[goalId].update({title: \"Get fit\"}))\n */\n transact = (\n chunks: TransactionChunk<any, any> | TransactionChunk<any, any>[],\n ) => {\n return this.core.transact(chunks);\n };\n\n /**\n * One time query for the logged in state.\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 * Use this for one-off queries.\n * Returns local data if available, otherwise fetches from the server.\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\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 // Solid reactive hooks\n\n /**\n * Use this to query your data!\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n * const state = db.useQuery({ goals: {} });\n * // state().isLoading, state().error, state().data\n */\n useQuery = <Q extends ValidQuery<Q, Schema>>(\n query: (() => null | Q) | null | Q,\n opts?: InstaQLOptions,\n ): Accessor<InstaQLLifecycleState<Schema, Q, UseDates>> => {\n const [state, setState] = createSignal<\n InstaQLLifecycleState<Schema, Q, UseDates>\n >(defaultState as InstaQLLifecycleState<Schema, Q, UseDates>);\n\n createEffect(() => {\n const resolvedQuery = typeof query === 'function' ? query() : query;\n\n if (!resolvedQuery) {\n setState(\n () => defaultState as InstaQLLifecycleState<Schema, Q, UseDates>,\n );\n return;\n }\n\n let q = resolvedQuery;\n if (opts && 'ruleParams' in opts) {\n q = { $$ruleParams: (opts as any)['ruleParams'], ...q };\n }\n\n const coerced = coerceQuery(q);\n const prev = this.core._reactor.getPreviousResult(coerced);\n if (prev) {\n setState(\n () =>\n stateForResult(prev) as InstaQLLifecycleState<Schema, Q, UseDates>,\n );\n }\n\n const unsub = this.core.subscribeQuery<Q, UseDates>(coerced, (result) => {\n setState(\n () =>\n Object.assign(\n {\n isLoading: false,\n data: undefined,\n pageInfo: undefined,\n error: undefined,\n },\n result,\n ) as InstaQLLifecycleState<Schema, Q, UseDates>,\n );\n });\n\n onCleanup(unsub);\n });\n\n return state;\n };\n\n /**\n * Subscribe to a query and incrementally load more items.\n *\n * Only one top level namespace in the query is allowed.\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n * const state = db.useInfiniteQuery({\n * posts: {\n * $: {\n * limit: 20,\n * order: { createdAt: 'desc' },\n * },\n * },\n * });\n * // state().data, state().isLoading, state().error,\n * // state().canLoadNextPage, state().loadNextPage()\n */\n useInfiniteQuery = <Q extends ValidQuery<Q, Schema>>(\n query: (() => null | Q) | null | Q,\n opts?: InstaQLOptions,\n ): Accessor<InfiniteQueryState<Schema, Q, UseDates>> => {\n let sub: InfiniteQuerySubscription | null = null;\n const loadNextPage = () => sub?.loadNextPage();\n\n const [state, setState] = createSignal<\n InfiniteQueryState<Schema, Q, UseDates>\n >({\n isLoading: true,\n error: undefined,\n data: undefined,\n canLoadNextPage: false,\n loadNextPage,\n });\n\n createEffect(() => {\n const resolvedQuery = typeof query === 'function' ? query() : query;\n\n if (!resolvedQuery) {\n sub = null;\n setState(() => ({\n isLoading: true,\n error: undefined,\n data: undefined,\n canLoadNextPage: false,\n loadNextPage,\n }));\n return;\n }\n\n const snapshot = getInfiniteQueryInitialSnapshot<Schema, Q, UseDates>(\n this.core,\n resolvedQuery,\n opts,\n );\n setState(() => ({\n ...snapshot,\n isLoading: !snapshot.data && !snapshot.error,\n loadNextPage,\n }));\n\n sub = this.core.subscribeInfiniteQuery<Q>(\n resolvedQuery,\n (resp) => {\n setState(() => ({\n ...resp,\n isLoading: false,\n loadNextPage,\n }));\n },\n opts,\n );\n\n onCleanup(() => {\n sub?.unsubscribe();\n sub = null;\n });\n });\n\n return 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 * @see https://instantdb.com/docs/auth\n * @example\n * function App() {\n * const auth = db.useAuth();\n * // auth().isLoading, auth().user, auth().error\n * }\n */\n useAuth = (): Accessor<AuthState> => {\n const [state, setState] = createSignal<AuthState>(\n this.core._reactor._currentUserCached ?? defaultAuthState,\n );\n\n createEffect(() => {\n const unsub = this.core.subscribeAuth((auth) => {\n setState({ isLoading: false, ...auth });\n });\n\n onCleanup(unsub);\n });\n\n return state;\n };\n\n /**\n * Subscribe to the currently logged in user.\n * If the user is not logged in, this will throw an Error.\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * function UserDisplay() {\n * const user = db.useUser();\n * return <div>Logged in as: {user().email}</div>\n * }\n */\n useUser = (): Accessor<User> => {\n const auth = this.useAuth();\n return createMemo(() => {\n const { user } = auth();\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 /**\n * Listen for connection status changes to Instant.\n *\n * @see https://www.instantdb.com/docs/patterns#connection-status\n * @example\n * function App() {\n * const status = db.useConnectionStatus();\n * return <div>Connection state: {status()}</div>\n * }\n */\n useConnectionStatus = (): Accessor<ConnectionStatus> => {\n const [status, setStatus] = createSignal<ConnectionStatus>(\n this.core._reactor.status as ConnectionStatus,\n );\n\n createEffect(() => {\n const unsub = this.core.subscribeConnectionStatus((newStatus) => {\n setStatus(() => newStatus);\n });\n\n onCleanup(unsub);\n });\n\n return status;\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 * // deviceId() is null initially, then the ID string\n */\n useLocalId = (name: string): Accessor<string | null> => {\n const [localId, setLocalId] = createSignal<string | null>(null);\n\n createEffect(() => {\n let mounted = true;\n this.getLocalId(name).then((id) => {\n if (mounted) {\n setLocalId(() => id);\n }\n });\n onCleanup(() => {\n mounted = false;\n });\n });\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 * @see https://instantdb.com/docs/presence-and-topics\n *\n * @example\n * const room = db.room('chat', roomId);\n * const presence = 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 InstantSolidRoom<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 presence = db.rooms.usePresence(room);\n * const publish = db.rooms.usePublishTopic(room, 'emoji');\n */\n rooms = rooms;\n}\n\n// -----------\n// init\n\n/**\n * The first step: init your application!\n *\n * Visit https://instantdb.com/dash to get your `appId` :)\n *\n * @example\n * import { init } from \"@instantdb/solidjs\"\n *\n * const db = init({ appId: \"my-app-id\" })\n *\n * // You can also provide a schema for type safety and editor autocomplete!\n *\n * import { init } from \"@instantdb/solidjs\"\n * import schema from \"../instant.schema.ts\";\n *\n * const db = init({ appId: \"my-app-id\", schema })\n */\nexport function init<\n Schema extends InstantSchemaDef<any, any, any>,\n UseDates extends boolean = false,\n>(\n config: Omit<InstantConfig<Schema, UseDates>, 'useDateObjects'> & {\n useDateObjects?: UseDates;\n },\n): InstantSolidDatabase<Schema, UseDates> {\n const coreDb = core_init<Schema, UseDates>(config, undefined, undefined, {\n '@instantdb/solidjs': version,\n });\n return new InstantSolidDatabase<Schema, UseDates>(coreDb);\n}\n"]}
@@ -0,0 +1,97 @@
1
+ import { type PresenceOpts, type PresenceResponse, type RoomSchemaShape, InstantCoreDatabase, InstantSchemaDef } from '@fidscript/instant-sdk';
2
+ import type { Accessor } from 'solid-js';
3
+ export type PresenceHandle<PresenceShape, Keys extends keyof PresenceShape> = PresenceResponse<PresenceShape, Keys> & {
4
+ publishPresence: (data: Partial<PresenceShape>) => void;
5
+ };
6
+ export type TypingIndicatorOpts = {
7
+ timeout?: number | null;
8
+ stopOnEnter?: boolean;
9
+ writeOnly?: boolean;
10
+ };
11
+ export type TypingIndicatorHandle<PresenceShape> = {
12
+ active: Accessor<PresenceShape[]>;
13
+ setActive(active: boolean): void;
14
+ inputProps: {
15
+ onKeyDown: (e: KeyboardEvent) => void;
16
+ onBlur: () => void;
17
+ };
18
+ };
19
+ export declare const defaultActivityStopTimeout = 1000;
20
+ /**
21
+ * Listen for broadcasted events given a room and topic.
22
+ *
23
+ * @see https://instantdb.com/docs/presence-and-topics
24
+ * @example
25
+ * function App({ roomId }) {
26
+ * const room = db.room('chats', roomId);
27
+ * db.rooms.useTopicEffect(room, 'emoji', (message, peer) => {
28
+ * console.log(peer.name, 'sent', message);
29
+ * });
30
+ * // ...
31
+ * }
32
+ */
33
+ export declare function useTopicEffect<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, TopicType extends keyof RoomSchema[RoomType]['topics']>(room: InstantSolidRoom<any, RoomSchema, RoomType>, topic: TopicType, onEvent: (event: RoomSchema[RoomType]['topics'][TopicType], peer: RoomSchema[RoomType]['presence']) => any): void;
34
+ /**
35
+ * Broadcast an event to a room.
36
+ *
37
+ * @see https://instantdb.com/docs/presence-and-topics
38
+ * @example
39
+ * function App({ roomId }) {
40
+ * const room = db.room('chat', roomId);
41
+ * const publishTopic = db.rooms.usePublishTopic(room, "emoji");
42
+ *
43
+ * return (
44
+ * <button onClick={() => publishTopic({ emoji: "🔥" })}>Send emoji</button>
45
+ * );
46
+ * }
47
+ *
48
+ */
49
+ export declare function usePublishTopic<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, TopicType extends keyof RoomSchema[RoomType]['topics']>(room: InstantSolidRoom<any, RoomSchema, RoomType>, topic: TopicType): (data: RoomSchema[RoomType]['topics'][TopicType]) => void;
50
+ /**
51
+ * Listen for peer's presence data in a room, and publish the current user's presence.
52
+ *
53
+ * @see https://instantdb.com/docs/presence-and-topics
54
+ * @example
55
+ * function App({ roomId }) {
56
+ * const presence = db.rooms.usePresence(room, { keys: ["name", "avatar"] });
57
+ * // presence().peers, presence().isLoading, presence().publishPresence
58
+ * }
59
+ */
60
+ export declare function usePresence<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, Keys extends keyof RoomSchema[RoomType]['presence']>(room: InstantSolidRoom<any, RoomSchema, RoomType>, opts?: PresenceOpts<RoomSchema[RoomType]['presence'], Keys>): Accessor<PresenceHandle<RoomSchema[RoomType]['presence'], Keys>>;
61
+ /**
62
+ * Publishes presence data to a room
63
+ *
64
+ * @see https://instantdb.com/docs/presence-and-topics
65
+ * @example
66
+ * function App({ roomId, nickname }) {
67
+ * const room = db.room('chat', roomId);
68
+ * db.rooms.useSyncPresence(room, { nickname });
69
+ * }
70
+ */
71
+ export declare function useSyncPresence<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema>(room: InstantSolidRoom<any, RoomSchema, RoomType>, data: Partial<RoomSchema[RoomType]['presence']>, deps?: any[]): void;
72
+ /**
73
+ * Manage typing indicator state
74
+ *
75
+ * @see https://instantdb.com/docs/presence-and-topics
76
+ * @example
77
+ * function App({ roomId }) {
78
+ * const room = db.room('chat', roomId);
79
+ * const typing = db.rooms.useTypingIndicator(room, "chat-input");
80
+ * // typing.active(), typing.setActive(bool), typing.inputProps
81
+ * }
82
+ */
83
+ export declare function useTypingIndicator<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema>(room: InstantSolidRoom<any, RoomSchema, RoomType>, inputName: string, opts?: TypingIndicatorOpts): TypingIndicatorHandle<RoomSchema[RoomType]['presence']>;
84
+ export declare const rooms: {
85
+ useTopicEffect: typeof useTopicEffect;
86
+ usePublishTopic: typeof usePublishTopic;
87
+ usePresence: typeof usePresence;
88
+ useSyncPresence: typeof useSyncPresence;
89
+ useTypingIndicator: typeof useTypingIndicator;
90
+ };
91
+ export declare class InstantSolidRoom<Schema extends InstantSchemaDef<any, any, any>, RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema> {
92
+ core: InstantCoreDatabase<Schema, boolean>;
93
+ type: RoomType;
94
+ id: string;
95
+ constructor(core: InstantCoreDatabase<Schema, boolean>, type: RoomType, id: string);
96
+ }
97
+ //# sourceMappingURL=InstantSolidRoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InstantSolidRoom.d.ts","sourceRoot":"","sources":["../../src/InstantSolidRoom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ import { createSignal, createEffect, onCleanup, createMemo } from 'solid-js';
2
+ export const defaultActivityStopTimeout = 1_000;
3
+ // ------
4
+ // Topics
5
+ /**
6
+ * Listen for broadcasted events given a room and topic.
7
+ *
8
+ * @see https://instantdb.com/docs/presence-and-topics
9
+ * @example
10
+ * function App({ roomId }) {
11
+ * const room = db.room('chats', roomId);
12
+ * db.rooms.useTopicEffect(room, 'emoji', (message, peer) => {
13
+ * console.log(peer.name, 'sent', message);
14
+ * });
15
+ * // ...
16
+ * }
17
+ */
18
+ export function useTopicEffect(room, topic, onEvent) {
19
+ createEffect(() => {
20
+ const unsub = room.core._reactor.subscribeTopic(room.type, room.id, topic, (event, peer) => {
21
+ onEvent(event, peer);
22
+ });
23
+ onCleanup(unsub);
24
+ });
25
+ }
26
+ /**
27
+ * Broadcast an event to a room.
28
+ *
29
+ * @see https://instantdb.com/docs/presence-and-topics
30
+ * @example
31
+ * function App({ roomId }) {
32
+ * const room = db.room('chat', roomId);
33
+ * const publishTopic = db.rooms.usePublishTopic(room, "emoji");
34
+ *
35
+ * return (
36
+ * <button onClick={() => publishTopic({ emoji: "🔥" })}>Send emoji</button>
37
+ * );
38
+ * }
39
+ *
40
+ */
41
+ export function usePublishTopic(room, topic) {
42
+ createEffect(() => {
43
+ const unsub = room.core._reactor.joinRoom(room.type, room.id);
44
+ onCleanup(unsub);
45
+ });
46
+ return (data) => {
47
+ room.core._reactor.publishTopic({
48
+ roomType: room.type,
49
+ roomId: room.id,
50
+ topic,
51
+ data,
52
+ });
53
+ };
54
+ }
55
+ // ---------
56
+ // Presence
57
+ /**
58
+ * Listen for peer's presence data in a room, and publish the current user's presence.
59
+ *
60
+ * @see https://instantdb.com/docs/presence-and-topics
61
+ * @example
62
+ * function App({ roomId }) {
63
+ * const presence = db.rooms.usePresence(room, { keys: ["name", "avatar"] });
64
+ * // presence().peers, presence().isLoading, presence().publishPresence
65
+ * }
66
+ */
67
+ export function usePresence(room, opts = {}) {
68
+ const [state, setState] = createSignal((room.core._reactor.getPresence(room.type, room.id, opts) ?? {
69
+ peers: {},
70
+ isLoading: true,
71
+ }));
72
+ createEffect(() => {
73
+ const unsub = room.core._reactor.subscribePresence(room.type, room.id, opts, (data) => {
74
+ setState(data);
75
+ });
76
+ onCleanup(unsub);
77
+ });
78
+ const publishPresence = (data) => {
79
+ room.core._reactor.publishPresence(room.type, room.id, data);
80
+ };
81
+ return createMemo(() => ({
82
+ ...state(),
83
+ publishPresence,
84
+ }));
85
+ }
86
+ /**
87
+ * Publishes presence data to a room
88
+ *
89
+ * @see https://instantdb.com/docs/presence-and-topics
90
+ * @example
91
+ * function App({ roomId, nickname }) {
92
+ * const room = db.room('chat', roomId);
93
+ * db.rooms.useSyncPresence(room, { nickname });
94
+ * }
95
+ */
96
+ export function useSyncPresence(room, data, deps) {
97
+ createEffect(() => {
98
+ const unsub = room.core._reactor.joinRoom(room.type, room.id, data);
99
+ onCleanup(unsub);
100
+ });
101
+ createEffect(() => {
102
+ // Track deps if provided, otherwise track serialized data
103
+ if (deps) {
104
+ deps.forEach((d) => (typeof d === 'function' ? d() : d));
105
+ }
106
+ else {
107
+ JSON.stringify(data);
108
+ }
109
+ room.core._reactor.publishPresence(room.type, room.id, data);
110
+ });
111
+ }
112
+ // -----------------
113
+ // Typing Indicator
114
+ /**
115
+ * Manage typing indicator state
116
+ *
117
+ * @see https://instantdb.com/docs/presence-and-topics
118
+ * @example
119
+ * function App({ roomId }) {
120
+ * const room = db.room('chat', roomId);
121
+ * const typing = db.rooms.useTypingIndicator(room, "chat-input");
122
+ * // typing.active(), typing.setActive(bool), typing.inputProps
123
+ * }
124
+ */
125
+ export function useTypingIndicator(room, inputName, opts = {}) {
126
+ let timeoutId = null;
127
+ const presence = rooms.usePresence(room, {
128
+ keys: [inputName],
129
+ });
130
+ const active = createMemo(() => {
131
+ if (opts?.writeOnly)
132
+ return [];
133
+ // Access presence to track it
134
+ presence();
135
+ const presenceSnapshot = room.core._reactor.getPresence(room.type, room.id);
136
+ return Object.values(presenceSnapshot?.peers ?? {}).filter((p) => p[inputName] === true);
137
+ });
138
+ const setActive = (isActive) => {
139
+ room.core._reactor.publishPresence(room.type, room.id, {
140
+ [inputName]: isActive ? true : null,
141
+ });
142
+ if (timeoutId) {
143
+ clearTimeout(timeoutId);
144
+ timeoutId = null;
145
+ }
146
+ if (!isActive)
147
+ return;
148
+ if (opts?.timeout === null || opts?.timeout === 0)
149
+ return;
150
+ timeoutId = setTimeout(() => {
151
+ room.core._reactor.publishPresence(room.type, room.id, {
152
+ [inputName]: null,
153
+ });
154
+ }, opts?.timeout ?? defaultActivityStopTimeout);
155
+ };
156
+ onCleanup(() => {
157
+ if (timeoutId) {
158
+ clearTimeout(timeoutId);
159
+ timeoutId = null;
160
+ }
161
+ // Ensure we don't leave a sticky typing state behind on unmount,
162
+ // even when opts.timeout is null/0 (i.e. no auto-timeout).
163
+ setActive(false);
164
+ });
165
+ const onKeyDown = (e) => {
166
+ const isEnter = opts?.stopOnEnter && e.key === 'Enter';
167
+ const isActive = !isEnter;
168
+ setActive(isActive);
169
+ };
170
+ const onBlur = () => {
171
+ setActive(false);
172
+ };
173
+ return {
174
+ active,
175
+ setActive,
176
+ inputProps: { onKeyDown, onBlur },
177
+ };
178
+ }
179
+ // --------------
180
+ // Hooks namespace
181
+ export const rooms = {
182
+ useTopicEffect,
183
+ usePublishTopic,
184
+ usePresence,
185
+ useSyncPresence,
186
+ useTypingIndicator,
187
+ };
188
+ // ------------
189
+ // Class
190
+ export class InstantSolidRoom {
191
+ core;
192
+ type;
193
+ id;
194
+ constructor(core, type, id) {
195
+ this.core = core;
196
+ this.type = type;
197
+ this.id = id;
198
+ }
199
+ }
200
+ //# sourceMappingURL=InstantSolidRoom.js.map