@instantdb/vue 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/InstantVueDatabase.d.ts +189 -0
- package/dist/InstantVueDatabase.d.ts.map +1 -0
- package/dist/InstantVueDatabase.js +265 -0
- package/dist/InstantVueDatabase.js.map +1 -0
- package/dist/InstantVueRoom.d.ts +84 -0
- package/dist/InstantVueRoom.d.ts.map +1 -0
- package/dist/InstantVueRoom.js +180 -0
- package/dist/InstantVueRoom.js.map +1 -0
- package/dist/chunks/Cursor.vue_vue_type_script_setup_true_lang-DeM0moKd.js +32 -0
- package/dist/chunks/Cursor.vue_vue_type_script_setup_true_lang-DeM0moKd.js.map +1 -0
- package/dist/chunks/Cursors.vue_vue_type_script_setup_true_lang-C6eE1KRI.js +128 -0
- package/dist/chunks/Cursors.vue_vue_type_script_setup_true_lang-C6eE1KRI.js.map +1 -0
- package/dist/chunks/SignedIn.vue_vue_type_script_setup_true_lang-MJrQPE2B.js +18 -0
- package/dist/chunks/SignedIn.vue_vue_type_script_setup_true_lang-MJrQPE2B.js.map +1 -0
- package/dist/chunks/SignedOut.vue_vue_type_script_setup_true_lang-CcoDHmXu.js +18 -0
- package/dist/chunks/SignedOut.vue_vue_type_script_setup_true_lang-CcoDHmXu.js.map +1 -0
- package/dist/components/Cursor.js +5 -0
- package/dist/components/Cursor.js.map +1 -0
- package/dist/components/Cursor.vue.d.ts +6 -0
- package/dist/components/Cursor.vue.d.ts.map +1 -0
- package/dist/components/Cursors.js +5 -0
- package/dist/components/Cursors.js.map +1 -0
- package/dist/components/Cursors.vue.d.ts +32 -0
- package/dist/components/Cursors.vue.d.ts.map +1 -0
- package/dist/components/SignedIn.js +5 -0
- package/dist/components/SignedIn.js.map +1 -0
- package/dist/components/SignedIn.vue.d.ts +18 -0
- package/dist/components/SignedIn.vue.d.ts.map +1 -0
- package/dist/components/SignedOut.js +5 -0
- package/dist/components/SignedOut.js.map +1 -0
- package/dist/components/SignedOut.vue.d.ts +18 -0
- package/dist/components/SignedOut.vue.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/useInfiniteQuery.d.ts +25 -0
- package/dist/useInfiniteQuery.d.ts.map +1 -0
- package/dist/useInfiniteQuery.js +57 -0
- package/dist/useInfiniteQuery.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +12 -0
- package/dist/utils.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://instantdb.com">
|
|
3
|
+
<img alt="Shows the Instant logo" src="https://instantdb.com/img/icon/android-chrome-512x512.png" width="10%">
|
|
4
|
+
</a>
|
|
5
|
+
<h1 align="center">@instantdb/vue</h1>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a
|
|
10
|
+
href="https://discord.com/invite/VU53p7uQcE" >
|
|
11
|
+
<img height=20 src="https://img.shields.io/discord/1031957483243188235" />
|
|
12
|
+
</a>
|
|
13
|
+
<img src="https://img.shields.io/github/stars/instantdb/instant" alt="stars">
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://instantdb.com/dash">Get Started</a> ·
|
|
18
|
+
<a href="https://instantdb.com/examples">Examples</a> ·
|
|
19
|
+
<a href="https://instantdb.com/docs">Docs</a> ·
|
|
20
|
+
<a href="https://discord.com/invite/VU53p7uQcE">Discord</a>
|
|
21
|
+
<p>
|
|
22
|
+
|
|
23
|
+
Welcome to [Instant's](http://instantdb.com) Vue SDK.
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
<!-- ༼ つ ◕_◕ ༽つ Real-time Chat -->
|
|
27
|
+
<!-- ---------------------------------- -->
|
|
28
|
+
<!-- * Updates instantly -->
|
|
29
|
+
<!-- * Multiplayer -->
|
|
30
|
+
<!-- * Works offline -->
|
|
31
|
+
|
|
32
|
+
<script setup>
|
|
33
|
+
import { init, id } from '@instantdb/vue';
|
|
34
|
+
|
|
35
|
+
const db = init({
|
|
36
|
+
appId: import.meta.env.VITE_INSTANT_APP_ID,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// 1. Read
|
|
40
|
+
const { isLoading, error, data } = db.useQuery({
|
|
41
|
+
messages: {},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 2. Write
|
|
45
|
+
const addMessage = (message) => {
|
|
46
|
+
db.transact(db.tx.messages[id()].update(message));
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<!-- 3. Render! -->
|
|
52
|
+
<UI :data="data" @add="addMessage" />
|
|
53
|
+
</template>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
# Get Started
|
|
57
|
+
|
|
58
|
+
Follow the [getting started](https://www.instantdb.com/docs/start-vue) tutorial to set up a live Vue app in under 5 minutes!
|
|
59
|
+
|
|
60
|
+
# Questions?
|
|
61
|
+
|
|
62
|
+
If you have any questions, feel free to drop us a line on our [Discord](https://discord.com/invite/VU53p7uQcE)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { type User, type ConnectionStatus, type TransactionChunk, type RoomSchemaShape, type InstaQLOptions, type InstantConfig, type PageInfoResponse, type InstaQLResponse, type ValidQuery, Auth, Storage, InstantCoreDatabase, InstantSchemaDef, RoomsOf, IInstantDatabase } from '@instantdb/core';
|
|
2
|
+
import type { Ref, ShallowRef, ComputedRef, MaybeRefOrGetter } from 'vue';
|
|
3
|
+
import { InstantVueRoom } from './InstantVueRoom.js';
|
|
4
|
+
import type { InfiniteQueryResult } from './useInfiniteQuery.js';
|
|
5
|
+
export type UseQueryReturn<Schema extends InstantSchemaDef<any, any, any>, Q extends ValidQuery<Q, Schema>, UseDates extends boolean> = {
|
|
6
|
+
isLoading: Ref<boolean>;
|
|
7
|
+
data: ShallowRef<InstaQLResponse<Schema, Q, UseDates> | undefined>;
|
|
8
|
+
pageInfo: ShallowRef<PageInfoResponse<Q> | undefined>;
|
|
9
|
+
error: ShallowRef<{
|
|
10
|
+
message: string;
|
|
11
|
+
} | undefined>;
|
|
12
|
+
};
|
|
13
|
+
export type UseAuthReturn = {
|
|
14
|
+
isLoading: Ref<boolean>;
|
|
15
|
+
user: ShallowRef<User | null | undefined>;
|
|
16
|
+
error: ShallowRef<{
|
|
17
|
+
message: string;
|
|
18
|
+
} | undefined>;
|
|
19
|
+
};
|
|
20
|
+
export declare class InstantVueDatabase<Schema extends InstantSchemaDef<any, any, any>, UseDates extends boolean = false, Rooms extends RoomSchemaShape = RoomsOf<Schema>> implements IInstantDatabase<Schema> {
|
|
21
|
+
tx: import("@instantdb/core").TxChunk<Schema>;
|
|
22
|
+
auth: Auth;
|
|
23
|
+
storage: Storage;
|
|
24
|
+
core: InstantCoreDatabase<Schema, UseDates>;
|
|
25
|
+
constructor(core: InstantCoreDatabase<Schema, UseDates>);
|
|
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
|
+
* @example
|
|
31
|
+
* const deviceId = await db.getLocalId('device');
|
|
32
|
+
*/
|
|
33
|
+
getLocalId: (name: string) => Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Use this to write data! You can create, update, delete, and link objects
|
|
36
|
+
*
|
|
37
|
+
* @see https://instantdb.com/docs/instaml
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const goalId = id();
|
|
41
|
+
* db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
|
|
42
|
+
*/
|
|
43
|
+
transact: (chunks: TransactionChunk<any, any> | TransactionChunk<any, any>[]) => Promise<import("@instantdb/core").TransactionResult>;
|
|
44
|
+
/**
|
|
45
|
+
* One time query for the logged in state.
|
|
46
|
+
*
|
|
47
|
+
* @see https://instantdb.com/docs/auth
|
|
48
|
+
* @example
|
|
49
|
+
* const user = await db.getAuth();
|
|
50
|
+
* console.log('logged in as', user.email)
|
|
51
|
+
*/
|
|
52
|
+
getAuth(): Promise<User | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Use this for one-off queries.
|
|
55
|
+
* Returns local data if available, otherwise fetches from the server.
|
|
56
|
+
*
|
|
57
|
+
* @see https://instantdb.com/docs/instaql
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const resp = await db.queryOnce({ goals: {} });
|
|
61
|
+
* console.log(resp.data.goals)
|
|
62
|
+
*/
|
|
63
|
+
queryOnce: <Q extends ValidQuery<Q, Schema>>(query: Q, opts?: InstaQLOptions) => Promise<{
|
|
64
|
+
data: InstaQLResponse<Schema, Q, UseDates>;
|
|
65
|
+
pageInfo: PageInfoResponse<Q>;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Use this to query your data!
|
|
69
|
+
*
|
|
70
|
+
* @see https://instantdb.com/docs/instaql
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // basic query — refs auto-unwrap in templates
|
|
74
|
+
* const { isLoading, error, data } = db.useQuery({ goals: {} });
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // reactive query — pass a getter that returns null to skip
|
|
78
|
+
* const { user } = db.useAuth();
|
|
79
|
+
* const { data } = db.useQuery(() =>
|
|
80
|
+
* user.value ? { todos: { $: { where: { 'owner.id': user.value.id } } } } : null,
|
|
81
|
+
* );
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // pass a ref directly
|
|
85
|
+
* const query = ref<{ todos: {} } | null>({ todos: {} });
|
|
86
|
+
* const { data } = db.useQuery(query);
|
|
87
|
+
*/
|
|
88
|
+
useQuery: <Q extends ValidQuery<Q, Schema>>(query: MaybeRefOrGetter<Q | null>, opts?: MaybeRefOrGetter<InstaQLOptions | null | undefined>) => UseQueryReturn<Schema, Q, UseDates>;
|
|
89
|
+
/**
|
|
90
|
+
* Subscribe to a query and incrementally load more items.
|
|
91
|
+
*
|
|
92
|
+
* Only one top-level namespace in the query is allowed.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const { data, isLoading, error, loadNextPage, canLoadNextPage } =
|
|
96
|
+
* db.useInfiniteQuery({
|
|
97
|
+
* posts: { $: { limit: 20, order: { createdAt: 'desc' } } },
|
|
98
|
+
* });
|
|
99
|
+
*/
|
|
100
|
+
useInfiniteQuery: <Q extends ValidQuery<Q, Schema>>(query: MaybeRefOrGetter<Q | null>, opts?: MaybeRefOrGetter<InstaQLOptions | undefined>) => InfiniteQueryResult<Schema, Q, UseDates>;
|
|
101
|
+
/**
|
|
102
|
+
* Listen for the logged in state. This is useful
|
|
103
|
+
* for deciding when to show a login screen.
|
|
104
|
+
*
|
|
105
|
+
* @see https://instantdb.com/docs/auth
|
|
106
|
+
* @example
|
|
107
|
+
* const { isLoading, user, error } = db.useAuth();
|
|
108
|
+
*/
|
|
109
|
+
useAuth: () => UseAuthReturn;
|
|
110
|
+
/**
|
|
111
|
+
* Subscribe to the currently logged in user. Throws if the user isn't
|
|
112
|
+
* signed in when `.value` is accessed — wrap callers with `<SignedIn>` or
|
|
113
|
+
* a `useAuth` check.
|
|
114
|
+
*
|
|
115
|
+
* @see https://instantdb.com/docs/auth
|
|
116
|
+
* @example
|
|
117
|
+
* const user = db.useUser();
|
|
118
|
+
* // user.value.email
|
|
119
|
+
*/
|
|
120
|
+
useUser: () => ComputedRef<User>;
|
|
121
|
+
/**
|
|
122
|
+
* Listen for connection status changes to Instant.
|
|
123
|
+
*
|
|
124
|
+
* @see https://www.instantdb.com/docs/patterns#connection-status
|
|
125
|
+
* @example
|
|
126
|
+
* const status = db.useConnectionStatus();
|
|
127
|
+
* // status.value
|
|
128
|
+
*/
|
|
129
|
+
useConnectionStatus: () => Ref<ConnectionStatus>;
|
|
130
|
+
/**
|
|
131
|
+
* A hook that returns a unique ID for a given `name`. localIds are stored in
|
|
132
|
+
* local storage, so you get the same ID across sessions.
|
|
133
|
+
*
|
|
134
|
+
* Returns `null` initially, then the loaded ID.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* const deviceId = db.useLocalId('device');
|
|
138
|
+
* // deviceId.value is null initially, then the ID string
|
|
139
|
+
*/
|
|
140
|
+
useLocalId: (name: MaybeRefOrGetter<string>) => Ref<string | null>;
|
|
141
|
+
/**
|
|
142
|
+
* Obtain a handle to a room, which allows you to listen to topics and presence data
|
|
143
|
+
*
|
|
144
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* const room = db.room('chat', roomId);
|
|
148
|
+
* const { peers } = db.rooms.usePresence(room);
|
|
149
|
+
*/
|
|
150
|
+
room<RoomType extends string & keyof Rooms>(type?: MaybeRefOrGetter<RoomType | undefined>, id?: MaybeRefOrGetter<string | undefined>): InstantVueRoom<Schema, Rooms, RoomType>;
|
|
151
|
+
/**
|
|
152
|
+
* Hooks for working with rooms
|
|
153
|
+
*
|
|
154
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* const room = db.room('chat', roomId);
|
|
158
|
+
* const { peers } = db.rooms.usePresence(room);
|
|
159
|
+
* const publish = db.rooms.usePublishTopic(room, 'emoji');
|
|
160
|
+
*/
|
|
161
|
+
rooms: {
|
|
162
|
+
useTopicEffect: typeof import("./InstantVueRoom.js").useTopicEffect;
|
|
163
|
+
usePublishTopic: typeof import("./InstantVueRoom.js").usePublishTopic;
|
|
164
|
+
usePresence: typeof import("./InstantVueRoom.js").usePresence;
|
|
165
|
+
useSyncPresence: typeof import("./InstantVueRoom.js").useSyncPresence;
|
|
166
|
+
useTypingIndicator: typeof import("./InstantVueRoom.js").useTypingIndicator;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The first step: init your application!
|
|
171
|
+
*
|
|
172
|
+
* Visit https://instantdb.com/dash to get your `appId` :)
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* import { init } from "@instantdb/vue"
|
|
176
|
+
*
|
|
177
|
+
* const db = init({ appId: "my-app-id" })
|
|
178
|
+
*
|
|
179
|
+
* // You can also provide a schema for type safety and editor autocomplete!
|
|
180
|
+
*
|
|
181
|
+
* import { init } from "@instantdb/vue"
|
|
182
|
+
* import schema from "../instant.schema.ts";
|
|
183
|
+
*
|
|
184
|
+
* const db = init({ appId: "my-app-id", schema })
|
|
185
|
+
*/
|
|
186
|
+
export declare function init<Schema extends InstantSchemaDef<any, any, any>, UseDates extends boolean = false>(config: Omit<InstantConfig<Schema, UseDates>, 'useDateObjects'> & {
|
|
187
|
+
useDateObjects?: UseDates;
|
|
188
|
+
}): InstantVueDatabase<Schema, UseDates>;
|
|
189
|
+
//# sourceMappingURL=InstantVueDatabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstantVueDatabase.d.ts","sourceRoot":"","sources":["../src/InstantVueDatabase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { init as init$1, txInit, coerceQuery, weakHash, InstantError } from "@instantdb/core";
|
|
5
|
+
import { ref, shallowRef, computed, toValue, watch } from "vue";
|
|
6
|
+
import { InstantVueRoom, rooms } from "./InstantVueRoom.js";
|
|
7
|
+
import { tryOnScopeDispose } from "./utils.js";
|
|
8
|
+
import { useInfiniteQuery } from "./useInfiniteQuery.js";
|
|
9
|
+
import { version } from "@instantdb/version";
|
|
10
|
+
class InstantVueDatabase {
|
|
11
|
+
constructor(core) {
|
|
12
|
+
__publicField(this, "tx", txInit());
|
|
13
|
+
__publicField(this, "auth");
|
|
14
|
+
__publicField(this, "storage");
|
|
15
|
+
__publicField(this, "core");
|
|
16
|
+
/**
|
|
17
|
+
* Returns a unique ID for a given `name`. It's stored in local storage,
|
|
18
|
+
* so you will get the same ID across sessions.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const deviceId = await db.getLocalId('device');
|
|
22
|
+
*/
|
|
23
|
+
__publicField(this, "getLocalId", (name) => {
|
|
24
|
+
return this.core.getLocalId(name);
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Use this to write data! You can create, update, delete, and link objects
|
|
28
|
+
*
|
|
29
|
+
* @see https://instantdb.com/docs/instaml
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const goalId = id();
|
|
33
|
+
* db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
|
|
34
|
+
*/
|
|
35
|
+
__publicField(this, "transact", (chunks) => {
|
|
36
|
+
return this.core.transact(chunks);
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Use this for one-off queries.
|
|
40
|
+
* Returns local data if available, otherwise fetches from the server.
|
|
41
|
+
*
|
|
42
|
+
* @see https://instantdb.com/docs/instaql
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const resp = await db.queryOnce({ goals: {} });
|
|
46
|
+
* console.log(resp.data.goals)
|
|
47
|
+
*/
|
|
48
|
+
__publicField(this, "queryOnce", (query, opts) => {
|
|
49
|
+
return this.core.queryOnce(query, opts);
|
|
50
|
+
});
|
|
51
|
+
// -----------
|
|
52
|
+
// Vue reactive hooks
|
|
53
|
+
/**
|
|
54
|
+
* Use this to query your data!
|
|
55
|
+
*
|
|
56
|
+
* @see https://instantdb.com/docs/instaql
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // basic query — refs auto-unwrap in templates
|
|
60
|
+
* const { isLoading, error, data } = db.useQuery({ goals: {} });
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // reactive query — pass a getter that returns null to skip
|
|
64
|
+
* const { user } = db.useAuth();
|
|
65
|
+
* const { data } = db.useQuery(() =>
|
|
66
|
+
* user.value ? { todos: { $: { where: { 'owner.id': user.value.id } } } } : null,
|
|
67
|
+
* );
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // pass a ref directly
|
|
71
|
+
* const query = ref<{ todos: {} } | null>({ todos: {} });
|
|
72
|
+
* const { data } = db.useQuery(query);
|
|
73
|
+
*/
|
|
74
|
+
__publicField(this, "useQuery", (query, opts) => {
|
|
75
|
+
const isLoading = ref(true);
|
|
76
|
+
const data = shallowRef(
|
|
77
|
+
void 0
|
|
78
|
+
);
|
|
79
|
+
const pageInfo = shallowRef(void 0);
|
|
80
|
+
const error = shallowRef(void 0);
|
|
81
|
+
const resolvedQuery = computed(() => {
|
|
82
|
+
const q = toValue(query);
|
|
83
|
+
if (!q) return null;
|
|
84
|
+
const o = toValue(opts);
|
|
85
|
+
const withParams = o && "ruleParams" in o ? { $$ruleParams: o.ruleParams, ...q } : q;
|
|
86
|
+
return coerceQuery(withParams);
|
|
87
|
+
});
|
|
88
|
+
const queryHash = computed(() => weakHash(resolvedQuery.value));
|
|
89
|
+
const stop = watch(
|
|
90
|
+
queryHash,
|
|
91
|
+
(_, __, onCleanup) => {
|
|
92
|
+
const q = resolvedQuery.value;
|
|
93
|
+
const cached = q ? this.core._reactor.getPreviousResult(q) : null;
|
|
94
|
+
isLoading.value = !cached;
|
|
95
|
+
data.value = cached == null ? void 0 : cached.data;
|
|
96
|
+
pageInfo.value = cached == null ? void 0 : cached.pageInfo;
|
|
97
|
+
error.value = cached == null ? void 0 : cached.error;
|
|
98
|
+
if (!q) return;
|
|
99
|
+
const unsub = this.core.subscribeQuery(q, (r) => {
|
|
100
|
+
isLoading.value = false;
|
|
101
|
+
data.value = r.data;
|
|
102
|
+
pageInfo.value = r.pageInfo;
|
|
103
|
+
error.value = r.error;
|
|
104
|
+
});
|
|
105
|
+
onCleanup(unsub);
|
|
106
|
+
},
|
|
107
|
+
{ immediate: true }
|
|
108
|
+
);
|
|
109
|
+
tryOnScopeDispose(stop);
|
|
110
|
+
return { isLoading, data, pageInfo, error };
|
|
111
|
+
});
|
|
112
|
+
/**
|
|
113
|
+
* Subscribe to a query and incrementally load more items.
|
|
114
|
+
*
|
|
115
|
+
* Only one top-level namespace in the query is allowed.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* const { data, isLoading, error, loadNextPage, canLoadNextPage } =
|
|
119
|
+
* db.useInfiniteQuery({
|
|
120
|
+
* posts: { $: { limit: 20, order: { createdAt: 'desc' } } },
|
|
121
|
+
* });
|
|
122
|
+
*/
|
|
123
|
+
__publicField(this, "useInfiniteQuery", (query, opts) => {
|
|
124
|
+
return useInfiniteQuery(this.core, query, opts);
|
|
125
|
+
});
|
|
126
|
+
/**
|
|
127
|
+
* Listen for the logged in state. This is useful
|
|
128
|
+
* for deciding when to show a login screen.
|
|
129
|
+
*
|
|
130
|
+
* @see https://instantdb.com/docs/auth
|
|
131
|
+
* @example
|
|
132
|
+
* const { isLoading, user, error } = db.useAuth();
|
|
133
|
+
*/
|
|
134
|
+
__publicField(this, "useAuth", () => {
|
|
135
|
+
const cached = this.core._reactor._currentUserCached;
|
|
136
|
+
const isLoading = ref((cached == null ? void 0 : cached.isLoading) ?? true);
|
|
137
|
+
const user = shallowRef(cached == null ? void 0 : cached.user);
|
|
138
|
+
const error = shallowRef(cached == null ? void 0 : cached.error);
|
|
139
|
+
const unsub = this.core.subscribeAuth((auth) => {
|
|
140
|
+
isLoading.value = false;
|
|
141
|
+
user.value = auth.user ?? null;
|
|
142
|
+
error.value = auth.error;
|
|
143
|
+
});
|
|
144
|
+
tryOnScopeDispose(unsub);
|
|
145
|
+
return { isLoading, user, error };
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* Subscribe to the currently logged in user. Throws if the user isn't
|
|
149
|
+
* signed in when `.value` is accessed — wrap callers with `<SignedIn>` or
|
|
150
|
+
* a `useAuth` check.
|
|
151
|
+
*
|
|
152
|
+
* @see https://instantdb.com/docs/auth
|
|
153
|
+
* @example
|
|
154
|
+
* const user = db.useUser();
|
|
155
|
+
* // user.value.email
|
|
156
|
+
*/
|
|
157
|
+
__publicField(this, "useUser", () => {
|
|
158
|
+
const { user } = this.useAuth();
|
|
159
|
+
return computed(() => {
|
|
160
|
+
if (!user.value) {
|
|
161
|
+
throw new InstantError(
|
|
162
|
+
"useUser must be used within an auth-protected route"
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
return user.value;
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
/**
|
|
169
|
+
* Listen for connection status changes to Instant.
|
|
170
|
+
*
|
|
171
|
+
* @see https://www.instantdb.com/docs/patterns#connection-status
|
|
172
|
+
* @example
|
|
173
|
+
* const status = db.useConnectionStatus();
|
|
174
|
+
* // status.value
|
|
175
|
+
*/
|
|
176
|
+
__publicField(this, "useConnectionStatus", () => {
|
|
177
|
+
const status = ref(
|
|
178
|
+
this.core._reactor.status
|
|
179
|
+
);
|
|
180
|
+
const unsub = this.core.subscribeConnectionStatus((newStatus) => {
|
|
181
|
+
status.value = newStatus;
|
|
182
|
+
});
|
|
183
|
+
tryOnScopeDispose(unsub);
|
|
184
|
+
return status;
|
|
185
|
+
});
|
|
186
|
+
/**
|
|
187
|
+
* A hook that returns a unique ID for a given `name`. localIds are stored in
|
|
188
|
+
* local storage, so you get the same ID across sessions.
|
|
189
|
+
*
|
|
190
|
+
* Returns `null` initially, then the loaded ID.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* const deviceId = db.useLocalId('device');
|
|
194
|
+
* // deviceId.value is null initially, then the ID string
|
|
195
|
+
*/
|
|
196
|
+
__publicField(this, "useLocalId", (name) => {
|
|
197
|
+
const localId = ref(null);
|
|
198
|
+
const stop = watch(
|
|
199
|
+
() => toValue(name),
|
|
200
|
+
(currentName) => {
|
|
201
|
+
this.getLocalId(currentName).then((id) => {
|
|
202
|
+
if (toValue(name) === currentName) {
|
|
203
|
+
localId.value = id;
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
},
|
|
207
|
+
{ immediate: true }
|
|
208
|
+
);
|
|
209
|
+
tryOnScopeDispose(stop);
|
|
210
|
+
return localId;
|
|
211
|
+
});
|
|
212
|
+
/**
|
|
213
|
+
* Hooks for working with rooms
|
|
214
|
+
*
|
|
215
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* const room = db.room('chat', roomId);
|
|
219
|
+
* const { peers } = db.rooms.usePresence(room);
|
|
220
|
+
* const publish = db.rooms.usePublishTopic(room, 'emoji');
|
|
221
|
+
*/
|
|
222
|
+
__publicField(this, "rooms", rooms);
|
|
223
|
+
this.core = core;
|
|
224
|
+
this.auth = this.core.auth;
|
|
225
|
+
this.storage = this.core.storage;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* One time query for the logged in state.
|
|
229
|
+
*
|
|
230
|
+
* @see https://instantdb.com/docs/auth
|
|
231
|
+
* @example
|
|
232
|
+
* const user = await db.getAuth();
|
|
233
|
+
* console.log('logged in as', user.email)
|
|
234
|
+
*/
|
|
235
|
+
getAuth() {
|
|
236
|
+
return this.core.getAuth();
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Obtain a handle to a room, which allows you to listen to topics and presence data
|
|
240
|
+
*
|
|
241
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* const room = db.room('chat', roomId);
|
|
245
|
+
* const { peers } = db.rooms.usePresence(room);
|
|
246
|
+
*/
|
|
247
|
+
room(type, id) {
|
|
248
|
+
const _type = computed(
|
|
249
|
+
() => toValue(type) ?? "_defaultRoomType"
|
|
250
|
+
);
|
|
251
|
+
const _id = computed(() => toValue(id) ?? "_defaultRoomId");
|
|
252
|
+
return new InstantVueRoom(this.core, _type, _id);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function init(config) {
|
|
256
|
+
const coreDb = init$1(config, void 0, void 0, {
|
|
257
|
+
"@instantdb/vue": version
|
|
258
|
+
});
|
|
259
|
+
return new InstantVueDatabase(coreDb);
|
|
260
|
+
}
|
|
261
|
+
export {
|
|
262
|
+
InstantVueDatabase,
|
|
263
|
+
init
|
|
264
|
+
};
|
|
265
|
+
//# sourceMappingURL=InstantVueDatabase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstantVueDatabase.js","sources":["../src/InstantVueDatabase.ts"],"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 InstaQLResponse,\n type ValidQuery,\n // classes\n Auth,\n Storage,\n txInit,\n InstantCoreDatabase,\n init as core_init,\n coerceQuery,\n weakHash,\n InstantSchemaDef,\n RoomsOf,\n InstantError,\n IInstantDatabase,\n} from '@instantdb/core';\n\nimport { ref, shallowRef, computed, watch, toValue } from 'vue';\nimport type { Ref, ShallowRef, ComputedRef, MaybeRefOrGetter } from 'vue';\n\nimport { InstantVueRoom, rooms } from './InstantVueRoom.js';\nimport { tryOnScopeDispose } from './utils.js';\nimport { useInfiniteQuery } from './useInfiniteQuery.js';\nimport type { InfiniteQueryResult } from './useInfiniteQuery.js';\nimport version from './version.js';\n\n// ------\n// Types\n\nexport type UseQueryReturn<\n Schema extends InstantSchemaDef<any, any, any>,\n Q extends ValidQuery<Q, Schema>,\n UseDates extends boolean,\n> = {\n isLoading: Ref<boolean>;\n data: ShallowRef<InstaQLResponse<Schema, Q, UseDates> | undefined>;\n pageInfo: ShallowRef<PageInfoResponse<Q> | undefined>;\n error: ShallowRef<{ message: string } | undefined>;\n};\n\nexport type UseAuthReturn = {\n isLoading: Ref<boolean>;\n user: ShallowRef<User | null | undefined>;\n error: ShallowRef<{ message: string } | undefined>;\n};\n\nexport class InstantVueDatabase<\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 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 }\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 // Vue reactive hooks\n\n /**\n * Use this to query your data!\n *\n * @see https://instantdb.com/docs/instaql\n *\n * @example\n * // basic query — refs auto-unwrap in templates\n * const { isLoading, error, data } = db.useQuery({ goals: {} });\n *\n * @example\n * // reactive query — pass a getter that returns null to skip\n * const { user } = db.useAuth();\n * const { data } = db.useQuery(() =>\n * user.value ? { todos: { $: { where: { 'owner.id': user.value.id } } } } : null,\n * );\n *\n * @example\n * // pass a ref directly\n * const query = ref<{ todos: {} } | null>({ todos: {} });\n * const { data } = db.useQuery(query);\n */\n useQuery = <Q extends ValidQuery<Q, Schema>>(\n query: MaybeRefOrGetter<Q | null>,\n opts?: MaybeRefOrGetter<InstaQLOptions | null | undefined>,\n ): UseQueryReturn<Schema, Q, UseDates> => {\n const isLoading = ref(true);\n const data = shallowRef<InstaQLResponse<Schema, Q, UseDates> | undefined>(\n undefined,\n );\n const pageInfo = shallowRef<PageInfoResponse<Q> | undefined>(undefined);\n const error = shallowRef<{ message: string } | undefined>(undefined);\n\n const resolvedQuery = computed(() => {\n const q = toValue(query);\n if (!q) return null;\n const o = toValue(opts);\n const withParams =\n o && 'ruleParams' in o\n ? ({ $$ruleParams: (o as any).ruleParams, ...q } as Q)\n : q;\n return coerceQuery(withParams);\n });\n\n const queryHash = computed(() => weakHash(resolvedQuery.value));\n\n const stop = watch(\n queryHash,\n (_, __, onCleanup) => {\n const q = resolvedQuery.value;\n const cached: any = q ? this.core._reactor.getPreviousResult(q) : null;\n isLoading.value = !cached;\n data.value = cached?.data;\n pageInfo.value = cached?.pageInfo;\n error.value = cached?.error;\n\n if (!q) return;\n\n const unsub = this.core.subscribeQuery<Q, UseDates>(q, (r: any) => {\n isLoading.value = false;\n data.value = r.data;\n pageInfo.value = r.pageInfo;\n error.value = r.error;\n });\n onCleanup(unsub);\n },\n { immediate: true },\n );\n\n tryOnScopeDispose(stop);\n\n return { isLoading, data, pageInfo, error } as UseQueryReturn<\n Schema,\n Q,\n UseDates\n >;\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 * @example\n * const { data, isLoading, error, loadNextPage, canLoadNextPage } =\n * db.useInfiniteQuery({\n * posts: { $: { limit: 20, order: { createdAt: 'desc' } } },\n * });\n */\n useInfiniteQuery = <Q extends ValidQuery<Q, Schema>>(\n query: MaybeRefOrGetter<Q | null>,\n opts?: MaybeRefOrGetter<InstaQLOptions | undefined>,\n ): InfiniteQueryResult<Schema, Q, UseDates> => {\n return useInfiniteQuery<Schema, Q, UseDates>(this.core, query, opts);\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 * const { isLoading, user, error } = db.useAuth();\n */\n useAuth = (): UseAuthReturn => {\n const cached = this.core._reactor._currentUserCached as\n | AuthState\n | undefined;\n\n const isLoading = ref(cached?.isLoading ?? true);\n const user = shallowRef<User | null | undefined>(cached?.user);\n const error = shallowRef<{ message: string } | undefined>(cached?.error);\n\n const unsub = this.core.subscribeAuth((auth: any) => {\n isLoading.value = false;\n user.value = auth.user ?? null;\n error.value = auth.error;\n });\n\n tryOnScopeDispose(unsub);\n\n return { isLoading, user, error };\n };\n\n /**\n * Subscribe to the currently logged in user. Throws if the user isn't\n * signed in when `.value` is accessed — wrap callers with `<SignedIn>` or\n * a `useAuth` check.\n *\n * @see https://instantdb.com/docs/auth\n * @example\n * const user = db.useUser();\n * // user.value.email\n */\n useUser = (): ComputedRef<User> => {\n const { user } = this.useAuth();\n return computed(() => {\n if (!user.value) {\n throw new InstantError(\n 'useUser must be used within an auth-protected route',\n );\n }\n return user.value;\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 * const status = db.useConnectionStatus();\n * // status.value\n */\n useConnectionStatus = (): Ref<ConnectionStatus> => {\n const status = ref<ConnectionStatus>(\n this.core._reactor.status as ConnectionStatus,\n );\n\n const unsub = this.core.subscribeConnectionStatus((newStatus) => {\n status.value = newStatus;\n });\n\n tryOnScopeDispose(unsub);\n\n return status;\n };\n\n /**\n * A hook that returns a unique ID for a given `name`. localIds are stored in\n * local storage, so you get the same ID across sessions.\n *\n * Returns `null` initially, then the loaded ID.\n *\n * @example\n * const deviceId = db.useLocalId('device');\n * // deviceId.value is null initially, then the ID string\n */\n useLocalId = (name: MaybeRefOrGetter<string>): Ref<string | null> => {\n const localId = ref<string | null>(null);\n\n const stop = watch(\n () => toValue(name),\n (currentName) => {\n this.getLocalId(currentName).then((id) => {\n // Drop a late resolve if `name` has since changed.\n if (toValue(name) === currentName) {\n localId.value = id;\n }\n });\n },\n { immediate: true },\n );\n\n tryOnScopeDispose(stop);\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 { peers } = db.rooms.usePresence(room);\n */\n room<RoomType extends string & keyof Rooms>(\n type?: MaybeRefOrGetter<RoomType | undefined>,\n id?: MaybeRefOrGetter<string | undefined>,\n ) {\n const _type = computed(\n () => (toValue(type) ?? '_defaultRoomType') as RoomType,\n );\n const _id = computed(() => toValue(id) ?? '_defaultRoomId');\n return new InstantVueRoom<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 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/vue\"\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/vue\"\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): InstantVueDatabase<Schema, UseDates> {\n const coreDb = core_init<Schema, UseDates>(config, undefined, undefined, {\n '@instantdb/vue': version,\n });\n return new InstantVueDatabase<Schema, UseDates>(coreDb);\n}\n"],"names":["core_init"],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { type PresenceOpts, type PresenceResponse, type RoomSchemaShape, InstantCoreDatabase, InstantSchemaDef } from '@instantdb/core';
|
|
2
|
+
import type { Ref, ShallowRef, MaybeRefOrGetter, ComputedRef } from 'vue';
|
|
3
|
+
export type PresenceHandle<PresenceShape, Keys extends keyof PresenceShape> = {
|
|
4
|
+
[K in keyof PresenceResponse<PresenceShape, Keys>]: ShallowRef<PresenceResponse<PresenceShape, Keys>[K]>;
|
|
5
|
+
} & {
|
|
6
|
+
publishPresence: (data: Partial<PresenceShape>) => void;
|
|
7
|
+
};
|
|
8
|
+
export type TypingIndicatorOpts = {
|
|
9
|
+
timeout?: number | null;
|
|
10
|
+
stopOnEnter?: boolean;
|
|
11
|
+
writeOnly?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type TypingIndicatorHandle<PresenceShape> = {
|
|
14
|
+
active: Ref<PresenceShape[]>;
|
|
15
|
+
setActive(active: boolean): void;
|
|
16
|
+
inputProps: {
|
|
17
|
+
onKeyDown: (e: KeyboardEvent) => void;
|
|
18
|
+
onBlur: () => void;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare const defaultActivityStopTimeout = 1000;
|
|
22
|
+
/**
|
|
23
|
+
* Listen for broadcasted events given a room and topic.
|
|
24
|
+
*
|
|
25
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
26
|
+
* @example
|
|
27
|
+
* const room = db.room('chats', roomId);
|
|
28
|
+
* db.rooms.useTopicEffect(room, 'emoji', (message, peer) => {
|
|
29
|
+
* console.log(peer.name, 'sent', message);
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
export declare function useTopicEffect<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, TopicType extends keyof RoomSchema[RoomType]['topics']>(room: InstantVueRoom<any, RoomSchema, RoomType>, topic: TopicType, onEvent: (event: RoomSchema[RoomType]['topics'][TopicType], peer: RoomSchema[RoomType]['presence']) => any): void;
|
|
33
|
+
/**
|
|
34
|
+
* Broadcast an event to a room.
|
|
35
|
+
*
|
|
36
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
37
|
+
* @example
|
|
38
|
+
* const room = db.room('chat', roomId);
|
|
39
|
+
* const publishTopic = db.rooms.usePublishTopic(room, 'emoji');
|
|
40
|
+
* publishTopic({ emoji: "🔥" });
|
|
41
|
+
*/
|
|
42
|
+
export declare function usePublishTopic<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, TopicType extends keyof RoomSchema[RoomType]['topics']>(room: InstantVueRoom<any, RoomSchema, RoomType>, topic: TopicType): (data: RoomSchema[RoomType]['topics'][TopicType]) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Listen for peer's presence data in a room, and publish the current user's presence.
|
|
45
|
+
*
|
|
46
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
47
|
+
* @example
|
|
48
|
+
* const room = db.room('chat', roomId);
|
|
49
|
+
* const { peers, isLoading, publishPresence } = db.rooms.usePresence(room, { keys: ["name", "avatar"] });
|
|
50
|
+
*/
|
|
51
|
+
export declare function usePresence<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema, Keys extends keyof RoomSchema[RoomType]['presence']>(room: InstantVueRoom<any, RoomSchema, RoomType>, opts?: PresenceOpts<RoomSchema[RoomType]['presence'], Keys>): PresenceHandle<RoomSchema[RoomType]['presence'], Keys>;
|
|
52
|
+
/**
|
|
53
|
+
* Publishes presence data to a room
|
|
54
|
+
*
|
|
55
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
56
|
+
* @example
|
|
57
|
+
* const room = db.room('chat', roomId);
|
|
58
|
+
* db.rooms.useSyncPresence(room, { nickname });
|
|
59
|
+
*/
|
|
60
|
+
export declare function useSyncPresence<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema>(room: InstantVueRoom<any, RoomSchema, RoomType>, data: MaybeRefOrGetter<Partial<RoomSchema[RoomType]['presence']>>): void;
|
|
61
|
+
/**
|
|
62
|
+
* Manage typing indicator state
|
|
63
|
+
*
|
|
64
|
+
* @see https://instantdb.com/docs/presence-and-topics
|
|
65
|
+
* @example
|
|
66
|
+
* const room = db.room('chat', roomId);
|
|
67
|
+
* const typing = db.rooms.useTypingIndicator(room, 'chat-input');
|
|
68
|
+
* // typing.active.value, typing.setActive(bool), typing.inputProps
|
|
69
|
+
*/
|
|
70
|
+
export declare function useTypingIndicator<RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema>(room: InstantVueRoom<any, RoomSchema, RoomType>, inputName: string, opts?: TypingIndicatorOpts): TypingIndicatorHandle<RoomSchema[RoomType]['presence']>;
|
|
71
|
+
export declare const rooms: {
|
|
72
|
+
useTopicEffect: typeof useTopicEffect;
|
|
73
|
+
usePublishTopic: typeof usePublishTopic;
|
|
74
|
+
usePresence: typeof usePresence;
|
|
75
|
+
useSyncPresence: typeof useSyncPresence;
|
|
76
|
+
useTypingIndicator: typeof useTypingIndicator;
|
|
77
|
+
};
|
|
78
|
+
export declare class InstantVueRoom<Schema extends InstantSchemaDef<any, any, any>, RoomSchema extends RoomSchemaShape, RoomType extends keyof RoomSchema> {
|
|
79
|
+
core: InstantCoreDatabase<Schema, boolean>;
|
|
80
|
+
type: ComputedRef<RoomType> | RoomType;
|
|
81
|
+
id: ComputedRef<string> | string;
|
|
82
|
+
constructor(core: InstantCoreDatabase<Schema, boolean>, type: ComputedRef<RoomType> | RoomType, id: ComputedRef<string> | string);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=InstantVueRoom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstantVueRoom.d.ts","sourceRoot":"","sources":["../src/InstantVueRoom.ts"],"names":[],"mappings":"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"}
|