@rool-dev/svelte 0.2.0 → 0.3.0-dev.381ac43
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 +167 -54
- package/dist/channel.svelte.d.ts +144 -0
- package/dist/channel.svelte.d.ts.map +1 -0
- package/dist/channel.svelte.js +354 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/rool.svelte.d.ts +36 -16
- package/dist/rool.svelte.d.ts.map +1 -1
- package/dist/rool.svelte.js +58 -28
- package/package.json +2 -2
- package/dist/space.svelte.d.ts +0 -144
- package/dist/space.svelte.d.ts.map +0 -1
- package/dist/space.svelte.js +0 -311
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A reactive watch of objects that auto-updates when matching objects change.
|
|
3
|
+
*/
|
|
4
|
+
class ReactiveWatchImpl {
|
|
5
|
+
#channel;
|
|
6
|
+
#options;
|
|
7
|
+
#unsubscribers = [];
|
|
8
|
+
#currentIds = new Set();
|
|
9
|
+
// Reactive state
|
|
10
|
+
objects = $state([]);
|
|
11
|
+
loading = $state(true);
|
|
12
|
+
constructor(channel, options) {
|
|
13
|
+
this.#channel = channel;
|
|
14
|
+
this.#options = options;
|
|
15
|
+
this.#setup();
|
|
16
|
+
}
|
|
17
|
+
#setup() {
|
|
18
|
+
// Initial fetch
|
|
19
|
+
this.refresh();
|
|
20
|
+
// Subscribe to object events
|
|
21
|
+
const onObjectCreated = ({ object }) => {
|
|
22
|
+
if (this.#matches(object)) {
|
|
23
|
+
this.refresh();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
this.#channel.on('objectCreated', onObjectCreated);
|
|
27
|
+
this.#unsubscribers.push(() => this.#channel.off('objectCreated', onObjectCreated));
|
|
28
|
+
const onObjectUpdated = ({ objectId, object }) => {
|
|
29
|
+
const wasInCollection = this.#currentIds.has(objectId);
|
|
30
|
+
const nowMatches = this.#matches(object);
|
|
31
|
+
if (wasInCollection && nowMatches) {
|
|
32
|
+
// Update in place
|
|
33
|
+
const index = this.objects.findIndex((o) => o.id === objectId);
|
|
34
|
+
if (index !== -1) {
|
|
35
|
+
this.objects[index] = object;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (wasInCollection && !nowMatches) {
|
|
39
|
+
// Remove from collection
|
|
40
|
+
this.objects = this.objects.filter((o) => o.id !== objectId);
|
|
41
|
+
this.#currentIds.delete(objectId);
|
|
42
|
+
}
|
|
43
|
+
else if (!wasInCollection && nowMatches) {
|
|
44
|
+
// Add to collection (re-fetch to respect limit/order)
|
|
45
|
+
this.refresh();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
this.#channel.on('objectUpdated', onObjectUpdated);
|
|
49
|
+
this.#unsubscribers.push(() => this.#channel.off('objectUpdated', onObjectUpdated));
|
|
50
|
+
const onObjectDeleted = ({ objectId }) => {
|
|
51
|
+
if (this.#currentIds.has(objectId)) {
|
|
52
|
+
this.objects = this.objects.filter((o) => o.id !== objectId);
|
|
53
|
+
this.#currentIds.delete(objectId);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
this.#channel.on('objectDeleted', onObjectDeleted);
|
|
57
|
+
this.#unsubscribers.push(() => this.#channel.off('objectDeleted', onObjectDeleted));
|
|
58
|
+
// Handle full resets
|
|
59
|
+
const onReset = () => this.refresh();
|
|
60
|
+
this.#channel.on('reset', onReset);
|
|
61
|
+
this.#unsubscribers.push(() => this.#channel.off('reset', onReset));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if an object matches the `where` filter.
|
|
65
|
+
*/
|
|
66
|
+
#matches(object) {
|
|
67
|
+
const where = this.#options.where;
|
|
68
|
+
if (!where)
|
|
69
|
+
return true;
|
|
70
|
+
for (const [key, value] of Object.entries(where)) {
|
|
71
|
+
if (object[key] !== value)
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Re-fetch the watched objects from the channel.
|
|
78
|
+
*/
|
|
79
|
+
async refresh() {
|
|
80
|
+
this.loading = true;
|
|
81
|
+
try {
|
|
82
|
+
const findOptions = {
|
|
83
|
+
where: this.#options.where,
|
|
84
|
+
limit: this.#options.limit,
|
|
85
|
+
order: this.#options.order,
|
|
86
|
+
ephemeral: true, // Don't pollute interaction history
|
|
87
|
+
};
|
|
88
|
+
const { objects } = await this.#channel.findObjects(findOptions);
|
|
89
|
+
this.objects = objects;
|
|
90
|
+
this.#currentIds = new Set(objects.map((o) => o.id));
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.loading = false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Stop listening for updates and clean up.
|
|
98
|
+
*/
|
|
99
|
+
close() {
|
|
100
|
+
for (const unsub of this.#unsubscribers)
|
|
101
|
+
unsub();
|
|
102
|
+
this.#unsubscribers.length = 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A reactive single object that auto-updates when the object changes.
|
|
107
|
+
*/
|
|
108
|
+
class ReactiveObjectImpl {
|
|
109
|
+
#channel;
|
|
110
|
+
#objectId;
|
|
111
|
+
#unsubscribers = [];
|
|
112
|
+
// Reactive state
|
|
113
|
+
data = $state(undefined);
|
|
114
|
+
loading = $state(true);
|
|
115
|
+
constructor(channel, objectId) {
|
|
116
|
+
this.#channel = channel;
|
|
117
|
+
this.#objectId = objectId;
|
|
118
|
+
this.#setup();
|
|
119
|
+
}
|
|
120
|
+
#setup() {
|
|
121
|
+
// Initial fetch
|
|
122
|
+
this.refresh();
|
|
123
|
+
// Listen for updates to this specific object
|
|
124
|
+
const onObjectUpdated = ({ objectId, object }) => {
|
|
125
|
+
if (objectId === this.#objectId) {
|
|
126
|
+
this.data = object;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
this.#channel.on('objectUpdated', onObjectUpdated);
|
|
130
|
+
this.#unsubscribers.push(() => this.#channel.off('objectUpdated', onObjectUpdated));
|
|
131
|
+
// Listen for creation (in case object didn't exist initially)
|
|
132
|
+
const onObjectCreated = ({ object }) => {
|
|
133
|
+
if (object.id === this.#objectId) {
|
|
134
|
+
this.data = object;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
this.#channel.on('objectCreated', onObjectCreated);
|
|
138
|
+
this.#unsubscribers.push(() => this.#channel.off('objectCreated', onObjectCreated));
|
|
139
|
+
// Listen for deletion
|
|
140
|
+
const onObjectDeleted = ({ objectId }) => {
|
|
141
|
+
if (objectId === this.#objectId) {
|
|
142
|
+
this.data = undefined;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
this.#channel.on('objectDeleted', onObjectDeleted);
|
|
146
|
+
this.#unsubscribers.push(() => this.#channel.off('objectDeleted', onObjectDeleted));
|
|
147
|
+
// Handle full resets
|
|
148
|
+
const onReset = () => this.refresh();
|
|
149
|
+
this.#channel.on('reset', onReset);
|
|
150
|
+
this.#unsubscribers.push(() => this.#channel.off('reset', onReset));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Re-fetch the object from the channel.
|
|
154
|
+
*/
|
|
155
|
+
async refresh() {
|
|
156
|
+
this.loading = true;
|
|
157
|
+
try {
|
|
158
|
+
this.data = await this.#channel.getObject(this.#objectId);
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
this.loading = false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Stop listening for updates and clean up.
|
|
166
|
+
*/
|
|
167
|
+
close() {
|
|
168
|
+
for (const unsub of this.#unsubscribers)
|
|
169
|
+
unsub();
|
|
170
|
+
this.#unsubscribers.length = 0;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Minimal wrapper that adds reactive `interactions` to RoolChannel.
|
|
175
|
+
* All other properties and methods are proxied to the underlying channel.
|
|
176
|
+
*/
|
|
177
|
+
class ReactiveChannelImpl {
|
|
178
|
+
#channel;
|
|
179
|
+
#unsubscribers = [];
|
|
180
|
+
#closed = false;
|
|
181
|
+
// Reactive state
|
|
182
|
+
interactions = $state([]);
|
|
183
|
+
objectIds = $state([]);
|
|
184
|
+
constructor(channel) {
|
|
185
|
+
this.#channel = channel;
|
|
186
|
+
this.interactions = channel.getInteractions();
|
|
187
|
+
this.objectIds = channel.getObjectIds();
|
|
188
|
+
// Subscribe to channel updates
|
|
189
|
+
const onChannelUpdated = () => {
|
|
190
|
+
this.interactions = channel.getInteractions();
|
|
191
|
+
};
|
|
192
|
+
channel.on('channelUpdated', onChannelUpdated);
|
|
193
|
+
this.#unsubscribers.push(() => channel.off('channelUpdated', onChannelUpdated));
|
|
194
|
+
// Subscribe to object events for objectIds
|
|
195
|
+
const refreshObjectIds = () => {
|
|
196
|
+
this.objectIds = channel.getObjectIds();
|
|
197
|
+
};
|
|
198
|
+
channel.on('objectCreated', refreshObjectIds);
|
|
199
|
+
this.#unsubscribers.push(() => channel.off('objectCreated', refreshObjectIds));
|
|
200
|
+
channel.on('objectDeleted', refreshObjectIds);
|
|
201
|
+
this.#unsubscribers.push(() => channel.off('objectDeleted', refreshObjectIds));
|
|
202
|
+
const onReset = () => {
|
|
203
|
+
this.interactions = channel.getInteractions();
|
|
204
|
+
this.objectIds = channel.getObjectIds();
|
|
205
|
+
};
|
|
206
|
+
channel.on('reset', onReset);
|
|
207
|
+
this.#unsubscribers.push(() => channel.off('reset', onReset));
|
|
208
|
+
}
|
|
209
|
+
// Proxy read-only properties
|
|
210
|
+
get id() { return this.#channel.id; }
|
|
211
|
+
get name() { return this.#channel.name; }
|
|
212
|
+
get role() { return this.#channel.role; }
|
|
213
|
+
get userId() { return this.#channel.userId; }
|
|
214
|
+
get channelId() { return this.#channel.channelId; }
|
|
215
|
+
get isReadOnly() { return this.#channel.isReadOnly; }
|
|
216
|
+
get linkAccess() { return this.#channel.linkAccess; }
|
|
217
|
+
// Proxy all methods
|
|
218
|
+
close() {
|
|
219
|
+
this.#closed = true;
|
|
220
|
+
for (const unsub of this.#unsubscribers)
|
|
221
|
+
unsub();
|
|
222
|
+
this.#unsubscribers.length = 0;
|
|
223
|
+
this.#channel.close();
|
|
224
|
+
}
|
|
225
|
+
// Object operations
|
|
226
|
+
getObject(...args) { return this.#channel.getObject(...args); }
|
|
227
|
+
stat(...args) { return this.#channel.stat(...args); }
|
|
228
|
+
findObjects(...args) { return this.#channel.findObjects(...args); }
|
|
229
|
+
getObjectIds(...args) { return this.#channel.getObjectIds(...args); }
|
|
230
|
+
createObject(...args) { return this.#channel.createObject(...args); }
|
|
231
|
+
updateObject(...args) { return this.#channel.updateObject(...args); }
|
|
232
|
+
deleteObjects(...args) { return this.#channel.deleteObjects(...args); }
|
|
233
|
+
// AI
|
|
234
|
+
prompt(...args) { return this.#channel.prompt(...args); }
|
|
235
|
+
// Undo/redo
|
|
236
|
+
checkpoint(...args) { return this.#channel.checkpoint(...args); }
|
|
237
|
+
canUndo() { return this.#channel.canUndo(); }
|
|
238
|
+
canRedo() { return this.#channel.canRedo(); }
|
|
239
|
+
undo() { return this.#channel.undo(); }
|
|
240
|
+
redo() { return this.#channel.redo(); }
|
|
241
|
+
clearHistory() { return this.#channel.clearHistory(); }
|
|
242
|
+
// Metadata
|
|
243
|
+
setMetadata(...args) { return this.#channel.setMetadata(...args); }
|
|
244
|
+
getMetadata(...args) { return this.#channel.getMetadata(...args); }
|
|
245
|
+
getAllMetadata() { return this.#channel.getAllMetadata(); }
|
|
246
|
+
// Channel history
|
|
247
|
+
getInteractions() { return this.#channel.getInteractions(); }
|
|
248
|
+
getSystemInstruction() { return this.#channel.getSystemInstruction(); }
|
|
249
|
+
setSystemInstruction(...args) { return this.#channel.setSystemInstruction(...args); }
|
|
250
|
+
// Schema
|
|
251
|
+
getSchema() { return this.#channel.getSchema(); }
|
|
252
|
+
createCollection(...args) { return this.#channel.createCollection(...args); }
|
|
253
|
+
alterCollection(...args) { return this.#channel.alterCollection(...args); }
|
|
254
|
+
dropCollection(...args) { return this.#channel.dropCollection(...args); }
|
|
255
|
+
// Media
|
|
256
|
+
uploadMedia(...args) { return this.#channel.uploadMedia(...args); }
|
|
257
|
+
fetchMedia(...args) { return this.#channel.fetchMedia(...args); }
|
|
258
|
+
deleteMedia(...args) { return this.#channel.deleteMedia(...args); }
|
|
259
|
+
listMedia() { return this.#channel.listMedia(); }
|
|
260
|
+
// Channel admin
|
|
261
|
+
rename(...args) { return this.#channel.rename(...args); }
|
|
262
|
+
// Events
|
|
263
|
+
on(...args) { return this.#channel.on(...args); }
|
|
264
|
+
off(...args) { return this.#channel.off(...args); }
|
|
265
|
+
// Reactive primitives
|
|
266
|
+
/**
|
|
267
|
+
* Create a reactive object that auto-updates when the object changes.
|
|
268
|
+
* Throws if the channel has been closed.
|
|
269
|
+
*/
|
|
270
|
+
object(objectId) {
|
|
271
|
+
if (this.#closed)
|
|
272
|
+
throw new Error('Cannot create reactive object: channel is closed');
|
|
273
|
+
return new ReactiveObjectImpl(this.#channel, objectId);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Create a reactive watch that auto-updates when matching objects change.
|
|
277
|
+
* Throws if the channel has been closed.
|
|
278
|
+
*/
|
|
279
|
+
watch(options) {
|
|
280
|
+
if (this.#closed)
|
|
281
|
+
throw new Error('Cannot create reactive watch: channel is closed');
|
|
282
|
+
return new ReactiveWatchImpl(this.#channel, options);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
export function wrapChannel(channel) {
|
|
286
|
+
return new ReactiveChannelImpl(channel);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* A reactive list of channels for a space that auto-updates via SSE events.
|
|
290
|
+
*/
|
|
291
|
+
class ReactiveChannelListImpl {
|
|
292
|
+
#client;
|
|
293
|
+
#spaceId;
|
|
294
|
+
#unsubscribers = [];
|
|
295
|
+
// Reactive state
|
|
296
|
+
list = $state([]);
|
|
297
|
+
loading = $state(true);
|
|
298
|
+
constructor(client, spaceId) {
|
|
299
|
+
this.#client = client;
|
|
300
|
+
this.#spaceId = spaceId;
|
|
301
|
+
this.#setup();
|
|
302
|
+
}
|
|
303
|
+
#setup() {
|
|
304
|
+
// Initial fetch
|
|
305
|
+
this.refresh();
|
|
306
|
+
// Listen for channel lifecycle events
|
|
307
|
+
const onChannelCreated = (spaceId, channel) => {
|
|
308
|
+
if (spaceId !== this.#spaceId)
|
|
309
|
+
return;
|
|
310
|
+
this.list = [...this.list, channel];
|
|
311
|
+
};
|
|
312
|
+
this.#client.on('channelCreated', onChannelCreated);
|
|
313
|
+
this.#unsubscribers.push(() => this.#client.off('channelCreated', onChannelCreated));
|
|
314
|
+
const onChannelRenamed = (spaceId, channelId, newName) => {
|
|
315
|
+
if (spaceId !== this.#spaceId)
|
|
316
|
+
return;
|
|
317
|
+
this.list = this.list.map(ch => ch.id === channelId ? { ...ch, name: newName } : ch);
|
|
318
|
+
};
|
|
319
|
+
this.#client.on('channelRenamed', onChannelRenamed);
|
|
320
|
+
this.#unsubscribers.push(() => this.#client.off('channelRenamed', onChannelRenamed));
|
|
321
|
+
const onChannelDeleted = (spaceId, channelId) => {
|
|
322
|
+
if (spaceId !== this.#spaceId)
|
|
323
|
+
return;
|
|
324
|
+
this.list = this.list.filter(ch => ch.id !== channelId);
|
|
325
|
+
};
|
|
326
|
+
this.#client.on('channelDeleted', onChannelDeleted);
|
|
327
|
+
this.#unsubscribers.push(() => this.#client.off('channelDeleted', onChannelDeleted));
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Re-fetch the channel list from the server.
|
|
331
|
+
* Opens a lightweight space handle to get the channel list.
|
|
332
|
+
*/
|
|
333
|
+
async refresh() {
|
|
334
|
+
this.loading = true;
|
|
335
|
+
try {
|
|
336
|
+
const space = await this.#client.openSpace(this.#spaceId);
|
|
337
|
+
this.list = space.getChannels();
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
this.loading = false;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Stop listening for updates and clean up.
|
|
345
|
+
*/
|
|
346
|
+
close() {
|
|
347
|
+
for (const unsub of this.#unsubscribers)
|
|
348
|
+
unsub();
|
|
349
|
+
this.#unsubscribers.length = 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
export function createChannelList(client, spaceId) {
|
|
353
|
+
return new ReactiveChannelListImpl(client, spaceId);
|
|
354
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createRool, generateId } from './rool.svelte.js';
|
|
2
|
-
export {
|
|
2
|
+
export { wrapChannel } from './channel.svelte.js';
|
|
3
3
|
export type { Rool } from './rool.svelte.js';
|
|
4
|
-
export type {
|
|
5
|
-
export type { RoolClientConfig, RoolSpace, RoolSpaceInfo, RoolObject, RoolUserRole, ConnectionState,
|
|
4
|
+
export type { ReactiveChannel, ReactiveObject, ReactiveWatch, ReactiveChannelList, WatchOptions } from './channel.svelte.js';
|
|
5
|
+
export type { RoolClientConfig, RoolChannel, RoolSpace, RoolSpaceInfo, RoolObject, RoolObjectStat, RoolUserRole, ConnectionState, ChannelInfo, CurrentUser, Interaction, FindObjectsOptions, PromptOptions, CreateObjectOptions, UpdateObjectOptions, FieldType, FieldDef, CollectionDef, SpaceSchema, SpaceMember, UserResult, RoolClient, } from '@rool-dev/sdk';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAG7H,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EACT,QAAQ,EACR,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,GACX,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/rool.svelte.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type RoolSpaceInfo, type ConnectionState, type RoolClientConfig, type CurrentUser } from '@rool-dev/sdk';
|
|
2
|
-
import { type
|
|
1
|
+
import { RoolClient, type RoolSpace, type RoolSpaceInfo, type ConnectionState, type RoolClientConfig, type CurrentUser } from '@rool-dev/sdk';
|
|
2
|
+
import { type ReactiveChannel, type ReactiveChannelList } from './channel.svelte.js';
|
|
3
3
|
/**
|
|
4
4
|
* Rool client with reactive state for Svelte 5.
|
|
5
5
|
*
|
|
@@ -7,7 +7,7 @@ import { type ReactiveSpace } from './space.svelte.js';
|
|
|
7
7
|
* - Reactive auth state (`authenticated`)
|
|
8
8
|
* - Reactive spaces list (`spaces`)
|
|
9
9
|
* - Reactive user storage (`userStorage`)
|
|
10
|
-
* -
|
|
10
|
+
* - Channel-based access to spaces
|
|
11
11
|
*/
|
|
12
12
|
declare class RoolImpl {
|
|
13
13
|
#private;
|
|
@@ -19,6 +19,11 @@ declare class RoolImpl {
|
|
|
19
19
|
userStorage: Record<string, unknown>;
|
|
20
20
|
currentUser: CurrentUser | null;
|
|
21
21
|
constructor(config?: RoolClientConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Access the underlying RoolClient for low-level API calls
|
|
24
|
+
* (e.g., graphql(), fetch()) not covered by the reactive wrapper.
|
|
25
|
+
*/
|
|
26
|
+
get client(): RoolClient;
|
|
22
27
|
/**
|
|
23
28
|
* Initialize the client. Call on app startup.
|
|
24
29
|
* Returns true if authenticated, false otherwise.
|
|
@@ -29,21 +34,24 @@ declare class RoolImpl {
|
|
|
29
34
|
*/
|
|
30
35
|
login(appName: string): void;
|
|
31
36
|
/**
|
|
32
|
-
* Log out and close all open
|
|
37
|
+
* Log out and close all open channels.
|
|
33
38
|
*/
|
|
34
39
|
logout(): void;
|
|
35
40
|
/**
|
|
36
|
-
* Open
|
|
41
|
+
* Open a channel (space + channelId pair).
|
|
42
|
+
* Returns a ReactiveChannel with reactive `interactions`.
|
|
37
43
|
*/
|
|
38
|
-
|
|
39
|
-
conversationId?: string;
|
|
40
|
-
}): Promise<ReactiveSpace>;
|
|
44
|
+
openChannel(spaceId: string, channelId: string): Promise<ReactiveChannel>;
|
|
41
45
|
/**
|
|
42
|
-
*
|
|
46
|
+
* Open a space for admin operations.
|
|
47
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
43
48
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
openSpace(spaceId: string): Promise<RoolSpace>;
|
|
50
|
+
/**
|
|
51
|
+
* Create a new space.
|
|
52
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
53
|
+
*/
|
|
54
|
+
createSpace(name: string): Promise<RoolSpace>;
|
|
47
55
|
/**
|
|
48
56
|
* Manually refresh the spaces list.
|
|
49
57
|
*/
|
|
@@ -63,11 +71,9 @@ declare class RoolImpl {
|
|
|
63
71
|
searchUser(email: string): Promise<import("@rool-dev/sdk").UserResult | null>;
|
|
64
72
|
/**
|
|
65
73
|
* Import a space from a zip archive.
|
|
66
|
-
* Returns a
|
|
74
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
67
75
|
*/
|
|
68
|
-
importArchive(name: string, archive: Blob
|
|
69
|
-
conversationId?: string;
|
|
70
|
-
}): Promise<ReactiveSpace>;
|
|
76
|
+
importArchive(name: string, archive: Blob): Promise<RoolSpace>;
|
|
71
77
|
/**
|
|
72
78
|
* Get auth user info from JWT token.
|
|
73
79
|
*/
|
|
@@ -76,6 +82,20 @@ declare class RoolImpl {
|
|
|
76
82
|
* Get current user profile from server.
|
|
77
83
|
*/
|
|
78
84
|
getCurrentUser(): Promise<CurrentUser>;
|
|
85
|
+
/**
|
|
86
|
+
* Rename a channel in a space.
|
|
87
|
+
*/
|
|
88
|
+
renameChannel(spaceId: string, channelId: string, name: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Delete a channel from a space.
|
|
91
|
+
*/
|
|
92
|
+
deleteChannel(spaceId: string, channelId: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Create a reactive channel list for a space.
|
|
95
|
+
* Auto-updates when channels are created, renamed, or deleted.
|
|
96
|
+
* Call close() when done to stop listening.
|
|
97
|
+
*/
|
|
98
|
+
channels(spaceId: string): ReactiveChannelList;
|
|
79
99
|
/**
|
|
80
100
|
* Clean up resources.
|
|
81
101
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rool.svelte.d.ts","sourceRoot":"","sources":["../src/rool.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"rool.svelte.d.ts","sourceRoot":"","sources":["../src/rool.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9I,OAAO,EAAkC,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAErH;;;;;;;;GAQG;AACH,cAAM,QAAQ;;IAMZ,aAAa,iBAAgC;IAC7C,MAAM,8BAAkD;IACxD,aAAa,UAAiB;IAC9B,WAAW,eAA8B;IACzC,eAAe,kBAA2C;IAC1D,WAAW,0BAAuC;IAClD,WAAW,qBAAoC;gBAEnC,MAAM,CAAC,EAAE,gBAAgB;IAKrC;;;OAGG;IACH,IAAI,MAAM,IAAI,UAAU,CAEvB;IAwDD;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAW9B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,MAAM,IAAI,IAAI;IAQd;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO/E;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAI9C;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAI7C;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAKjD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM;IAIxB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC;IAI9D;;OAEG;IACH,IAAI,QAAQ,qCAEX;IAED;;OAEG;IACH,cAAc;IAId;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB;IAI9C;;OAEG;IACH,OAAO,IAAI,IAAI;CAahB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAE1D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,MAAM,MAAM,IAAI,GAAG,QAAQ,CAAC"}
|
package/dist/rool.svelte.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RoolClient } from '@rool-dev/sdk';
|
|
2
|
-
import {
|
|
2
|
+
import { wrapChannel, createChannelList } from './channel.svelte.js';
|
|
3
3
|
/**
|
|
4
4
|
* Rool client with reactive state for Svelte 5.
|
|
5
5
|
*
|
|
@@ -7,12 +7,12 @@ import { wrapSpace } from './space.svelte.js';
|
|
|
7
7
|
* - Reactive auth state (`authenticated`)
|
|
8
8
|
* - Reactive spaces list (`spaces`)
|
|
9
9
|
* - Reactive user storage (`userStorage`)
|
|
10
|
-
* -
|
|
10
|
+
* - Channel-based access to spaces
|
|
11
11
|
*/
|
|
12
12
|
class RoolImpl {
|
|
13
13
|
#client;
|
|
14
14
|
#unsubscribers = [];
|
|
15
|
-
#
|
|
15
|
+
#openChannels = new Set();
|
|
16
16
|
// Reactive state
|
|
17
17
|
authenticated = $state(null); // null = checking, false = not auth, true = auth
|
|
18
18
|
spaces = $state(undefined);
|
|
@@ -25,6 +25,13 @@ class RoolImpl {
|
|
|
25
25
|
this.#client = new RoolClient(config);
|
|
26
26
|
this.#setupEventListeners();
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Access the underlying RoolClient for low-level API calls
|
|
30
|
+
* (e.g., graphql(), fetch()) not covered by the reactive wrapper.
|
|
31
|
+
*/
|
|
32
|
+
get client() {
|
|
33
|
+
return this.#client;
|
|
34
|
+
}
|
|
28
35
|
#setupEventListeners() {
|
|
29
36
|
const onAuthStateChanged = (auth) => {
|
|
30
37
|
this.authenticated = auth;
|
|
@@ -97,32 +104,38 @@ class RoolImpl {
|
|
|
97
104
|
this.#client.login(appName);
|
|
98
105
|
}
|
|
99
106
|
/**
|
|
100
|
-
* Log out and close all open
|
|
107
|
+
* Log out and close all open channels.
|
|
101
108
|
*/
|
|
102
109
|
logout() {
|
|
103
|
-
for (const
|
|
104
|
-
|
|
110
|
+
for (const channel of this.#openChannels) {
|
|
111
|
+
channel.close();
|
|
105
112
|
}
|
|
106
|
-
this.#
|
|
113
|
+
this.#openChannels.clear();
|
|
107
114
|
this.#client.logout();
|
|
108
115
|
}
|
|
109
116
|
/**
|
|
110
|
-
* Open
|
|
117
|
+
* Open a channel (space + channelId pair).
|
|
118
|
+
* Returns a ReactiveChannel with reactive `interactions`.
|
|
119
|
+
*/
|
|
120
|
+
async openChannel(spaceId, channelId) {
|
|
121
|
+
const channel = await this.#client.openChannel(spaceId, channelId);
|
|
122
|
+
const reactiveChannel = wrapChannel(channel);
|
|
123
|
+
this.#openChannels.add(reactiveChannel);
|
|
124
|
+
return reactiveChannel;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Open a space for admin operations.
|
|
128
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
111
129
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const reactiveSpace = wrapSpace(space);
|
|
115
|
-
this.#openSpaces.add(reactiveSpace);
|
|
116
|
-
return reactiveSpace;
|
|
130
|
+
openSpace(spaceId) {
|
|
131
|
+
return this.#client.openSpace(spaceId);
|
|
117
132
|
}
|
|
118
133
|
/**
|
|
119
|
-
* Create a new space.
|
|
134
|
+
* Create a new space.
|
|
135
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
120
136
|
*/
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const reactiveSpace = wrapSpace(space);
|
|
124
|
-
this.#openSpaces.add(reactiveSpace);
|
|
125
|
-
return reactiveSpace;
|
|
137
|
+
createSpace(name) {
|
|
138
|
+
return this.#client.createSpace(name);
|
|
126
139
|
}
|
|
127
140
|
/**
|
|
128
141
|
* Manually refresh the spaces list.
|
|
@@ -152,13 +165,10 @@ class RoolImpl {
|
|
|
152
165
|
}
|
|
153
166
|
/**
|
|
154
167
|
* Import a space from a zip archive.
|
|
155
|
-
* Returns a
|
|
168
|
+
* Returns a lightweight RoolSpace handle (not reactive).
|
|
156
169
|
*/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const reactiveSpace = wrapSpace(space);
|
|
160
|
-
this.#openSpaces.add(reactiveSpace);
|
|
161
|
-
return reactiveSpace;
|
|
170
|
+
importArchive(name, archive) {
|
|
171
|
+
return this.#client.importArchive(name, archive);
|
|
162
172
|
}
|
|
163
173
|
/**
|
|
164
174
|
* Get auth user info from JWT token.
|
|
@@ -172,14 +182,34 @@ class RoolImpl {
|
|
|
172
182
|
getCurrentUser() {
|
|
173
183
|
return this.#client.getCurrentUser();
|
|
174
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Rename a channel in a space.
|
|
187
|
+
*/
|
|
188
|
+
renameChannel(spaceId, channelId, name) {
|
|
189
|
+
return this.#client.renameChannel(spaceId, channelId, name);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Delete a channel from a space.
|
|
193
|
+
*/
|
|
194
|
+
deleteChannel(spaceId, channelId) {
|
|
195
|
+
return this.#client.deleteChannel(spaceId, channelId);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Create a reactive channel list for a space.
|
|
199
|
+
* Auto-updates when channels are created, renamed, or deleted.
|
|
200
|
+
* Call close() when done to stop listening.
|
|
201
|
+
*/
|
|
202
|
+
channels(spaceId) {
|
|
203
|
+
return createChannelList(this.#client, spaceId);
|
|
204
|
+
}
|
|
175
205
|
/**
|
|
176
206
|
* Clean up resources.
|
|
177
207
|
*/
|
|
178
208
|
destroy() {
|
|
179
|
-
for (const
|
|
180
|
-
|
|
209
|
+
for (const channel of this.#openChannels) {
|
|
210
|
+
channel.close();
|
|
181
211
|
}
|
|
182
|
-
this.#
|
|
212
|
+
this.#openChannels.clear();
|
|
183
213
|
for (const unsub of this.#unsubscribers) {
|
|
184
214
|
unsub();
|
|
185
215
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rool-dev/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-dev.381ac43",
|
|
4
4
|
"description": "Svelte 5 runes for Rool Spaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@rool-dev/sdk": "0.
|
|
44
|
+
"@rool-dev/sdk": "0.3.0-dev.381ac43"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"svelte": "^5.0.0"
|