@rool-dev/svelte 0.9.0 → 0.10.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 CHANGED
@@ -56,7 +56,7 @@ The Svelte wrapper adds reactive state on top of the SDK:
56
56
  | `rool.connectionState` | SSE connection state |
57
57
  | `rool.userStorage` | User storage (cross-device preferences) |
58
58
  | `channel.interactions` | Channel interactions (auto-updates) |
59
- | `channel.objectIds` | All object IDs in the space (auto-updates on create/delete) |
59
+ | `channel.objectLocations` | All object locations in the space (auto-updates on create/delete/move) |
60
60
  | `channel.collections` | Collection names from the schema (auto-updates) |
61
61
  | `channel.conversations` | Conversations in this channel (auto-updates on create/delete/rename) |
62
62
  | `thread.interactions` | Interactions for a specific conversation (auto-updates) |
@@ -161,7 +161,7 @@ space.close();
161
161
 
162
162
  ### ReactiveChannel
163
163
 
164
- `space.openChannel()` returns a `ReactiveChannel` — the SDK's `RoolChannel` with reactive `interactions` and `objectIds`:
164
+ `space.openChannel()` returns a `ReactiveChannel` — the SDK's `RoolChannel` with reactive `interactions` and `objectLocations`:
165
165
 
166
166
  ```svelte
167
167
  <script>
@@ -189,7 +189,7 @@ space.close();
189
189
 
190
190
  ### Reactive Object
191
191
 
192
- Track a single object by ID with auto-updates:
192
+ Track a single object by location with auto-updates:
193
193
 
194
194
  ```svelte
195
195
  <script>
@@ -198,10 +198,10 @@ Track a single object by ID with auto-updates:
198
198
 
199
199
  let space = $state(null);
200
200
 
201
- async function open(spaceId, objectId) {
201
+ async function open(spaceId, location) {
202
202
  space = await rool.openSpace(spaceId);
203
203
  channel = await space.openChannel('main');
204
- item = channel.object(objectId);
204
+ item = channel.object(location); // e.g. '/space/article/welcome.json'
205
205
  }
206
206
  </script>
207
207
 
@@ -209,7 +209,7 @@ Track a single object by ID with auto-updates:
209
209
  {#if item.loading}
210
210
  <p>Loading...</p>
211
211
  {:else if item.data}
212
- <div>{item.data.title}</div>
212
+ <div>{item.data.body.title}</div>
213
213
  {:else}
214
214
  <p>Object not found</p>
215
215
  {/if}
@@ -242,7 +242,7 @@ Create auto-updating watches of objects filtered by field values:
242
242
  async function open(spaceId) {
243
243
  space = await rool.openSpace(spaceId);
244
244
  channel = await space.openChannel('main');
245
- // Create a reactive watch of all objects where type === 'article'
245
+ // Create a reactive watch of all objects in the 'article' collection
246
246
  articles = channel.watch({ collection: 'article' });
247
247
  }
248
248
  </script>
@@ -252,7 +252,7 @@ Create auto-updating watches of objects filtered by field values:
252
252
  <p>Loading...</p>
253
253
  {:else}
254
254
  {#each articles.objects as article}
255
- <div>{article.title}</div>
255
+ <div>{article.body.title}</div>
256
256
  {/each}
257
257
  {/if}
258
258
  {/if}
@@ -333,7 +333,7 @@ thread.interactions // $state<Interaction[]> — auto-updates via SSE
333
333
 
334
334
  // All conversation-scoped methods
335
335
  await thread.prompt('Hello')
336
- await thread.createObject({ data: { type: 'note', text: 'Note' } })
336
+ await thread.createObject('note', { text: 'Note' })
337
337
  await thread.setSystemInstruction('Respond in haiku')
338
338
  await thread.rename('Research Thread')
339
339
  thread.getInteractions() // Manual read
@@ -369,11 +369,13 @@ channel.name
369
369
  channel.role
370
370
  channel.channelId
371
371
 
372
- // Object operations
373
- await channel.getObject(id)
374
- await channel.createObject({ data: { type: 'note', text: 'Hello' } })
375
- await channel.updateObject(id, { data: { text: 'Updated' } })
376
- await channel.deleteObjects([id])
372
+ // Object operations — addressed by location (`/space/<collection>/<basename>.json`)
373
+ await channel.getObject(location)
374
+ await channel.createObject('note', { text: 'Hello' })
375
+ await channel.createObject('note', { text: 'Hello' }, { basename: 'welcome' })
376
+ await channel.updateObject(location, { data: { text: 'Updated' } })
377
+ await channel.moveObject(from, to)
378
+ await channel.deleteObjects([location])
377
379
  await channel.findObjects({ collection: 'note' })
378
380
 
379
381
  // AI
@@ -415,10 +417,15 @@ See the [SDK documentation](../sdk/README.md) for complete API details.
415
417
  ### Utilities
416
418
 
417
419
  ```typescript
418
- import { generateId } from '@rool-dev/svelte';
420
+ import { generateBasename, loc, parseLocation, normalizeLocation } from '@rool-dev/svelte';
419
421
 
420
- // Generate a 6-character alphanumeric ID
421
- const id = generateId();
422
+ // 6-character alphanumeric basename
423
+ const basename = generateBasename();
424
+
425
+ // Build / parse location strings
426
+ const location = loc('article', basename); // '/space/article/<basename>.json'
427
+ const parts = parseLocation(location); // { collection, basename }
428
+ const canonical = normalizeLocation('article/welcome'); // '/space/article/welcome.json'
422
429
  ```
423
430
 
424
431
  ## Exported Types
@@ -447,6 +454,7 @@ import type {
447
454
  PromptOptions,
448
455
  CreateObjectOptions,
449
456
  UpdateObjectOptions,
457
+ MoveObjectOptions,
450
458
  FieldType,
451
459
  FieldDef,
452
460
  CollectionDef,
@@ -6,7 +6,7 @@ import type { RoolChannel, RoolSpace, Interaction, RoolObject, ChannelInfo, Conv
6
6
  export interface WatchOptions {
7
7
  /** Field requirements for exact matching */
8
8
  where?: Record<string, unknown>;
9
- /** Filter by collection name. Returns objects whose `type` field equals the given name. */
9
+ /** Filter by collection name. */
10
10
  collection?: string;
11
11
  /** Maximum number of objects */
12
12
  limit?: number;
@@ -25,9 +25,6 @@ declare class ReactiveWatchImpl {
25
25
  * Re-fetch the watched objects from the channel.
26
26
  */
27
27
  refresh(): Promise<void>;
28
- /**
29
- * Stop listening for updates and clean up.
30
- */
31
28
  close(): void;
32
29
  }
33
30
  export type ReactiveWatch = ReactiveWatchImpl;
@@ -38,23 +35,11 @@ declare class ReactiveObjectImpl {
38
35
  #private;
39
36
  data: RoolObject | undefined;
40
37
  loading: boolean;
41
- constructor(channel: RoolChannel, objectId: string);
42
- /**
43
- * Re-fetch the object from the channel.
44
- */
38
+ constructor(channel: RoolChannel, location: string);
45
39
  refresh(): Promise<void>;
46
- /**
47
- * Stop listening for updates and clean up.
48
- */
49
40
  close(): void;
50
41
  }
51
42
  export type ReactiveObject = ReactiveObjectImpl;
52
- /**
53
- * A reactive conversation handle that auto-updates interactions when the
54
- * conversation changes. Wraps the SDK's ConversationHandle with $state.
55
- *
56
- * Call `close()` when done to stop listening for updates.
57
- */
58
43
  declare class ReactiveConversationHandleImpl {
59
44
  #private;
60
45
  interactions: Interaction[];
@@ -79,6 +64,10 @@ declare class ReactiveConversationHandleImpl {
79
64
  object: RoolObject;
80
65
  message: string;
81
66
  }>;
67
+ moveObject(...args: Parameters<ConversationHandle['moveObject']>): Promise<{
68
+ object: RoolObject;
69
+ message: string;
70
+ }>;
82
71
  deleteObjects(...args: Parameters<ConversationHandle['deleteObjects']>): Promise<void>;
83
72
  prompt(...args: Parameters<ConversationHandle['prompt']>): Promise<{
84
73
  message: string;
@@ -88,9 +77,6 @@ declare class ReactiveConversationHandleImpl {
88
77
  alterCollection(...args: Parameters<ConversationHandle['alterCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
89
78
  dropCollection(...args: Parameters<ConversationHandle['dropCollection']>): Promise<void>;
90
79
  setMetadata(...args: Parameters<ConversationHandle['setMetadata']>): void;
91
- /**
92
- * Stop listening for updates and clean up.
93
- */
94
80
  close(): void;
95
81
  }
96
82
  export type ReactiveConversationHandle = ReactiveConversationHandleImpl;
@@ -101,7 +87,7 @@ export type ReactiveConversationHandle = ReactiveConversationHandleImpl;
101
87
  declare class ReactiveChannelImpl {
102
88
  #private;
103
89
  interactions: Interaction[];
104
- objectIds: string[];
90
+ objectLocations: string[];
105
91
  collections: string[];
106
92
  conversations: ConversationInfo[];
107
93
  constructor(channel: RoolChannel);
@@ -123,7 +109,7 @@ declare class ReactiveChannelImpl {
123
109
  objects: RoolObject[];
124
110
  message: string;
125
111
  }>;
126
- getObjectIds(...args: Parameters<RoolChannel['getObjectIds']>): string[];
112
+ getObjectLocations(...args: Parameters<RoolChannel['getObjectLocations']>): string[];
127
113
  createObject(...args: Parameters<RoolChannel['createObject']>): Promise<{
128
114
  object: RoolObject;
129
115
  message: string;
@@ -132,6 +118,10 @@ declare class ReactiveChannelImpl {
132
118
  object: RoolObject;
133
119
  message: string;
134
120
  }>;
121
+ moveObject(...args: Parameters<RoolChannel['moveObject']>): Promise<{
122
+ object: RoolObject;
123
+ message: string;
124
+ }>;
135
125
  deleteObjects(...args: Parameters<RoolChannel['deleteObjects']>): Promise<void>;
136
126
  prompt(...args: Parameters<RoolChannel['prompt']>): Promise<{
137
127
  message: string;
@@ -159,23 +149,17 @@ declare class ReactiveChannelImpl {
159
149
  createCollection(...args: Parameters<RoolChannel['createCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
160
150
  alterCollection(...args: Parameters<RoolChannel['alterCollection']>): Promise<import("@rool-dev/sdk").CollectionDef>;
161
151
  dropCollection(...args: Parameters<RoolChannel['dropCollection']>): Promise<void>;
162
- uploadMedia(...args: Parameters<RoolChannel['uploadMedia']>): Promise<string>;
163
- fetchMedia(...args: Parameters<RoolChannel['fetchMedia']>): Promise<import("@rool-dev/sdk").MediaResponse>;
164
- deleteMedia(...args: Parameters<RoolChannel['deleteMedia']>): Promise<void>;
165
- listMedia(): Promise<import("@rool-dev/sdk").MediaInfo[]>;
166
152
  fetch(...args: Parameters<RoolChannel['fetch']>): Promise<Response>;
167
153
  rename(...args: Parameters<RoolChannel['rename']>): Promise<void>;
168
154
  conversation(conversationId: string): ReactiveConversationHandle;
169
155
  on(...args: Parameters<RoolChannel['on']>): () => void;
170
156
  off(...args: Parameters<RoolChannel['off']>): void;
171
157
  /**
172
- * Create a reactive object that auto-updates when the object changes.
173
- * Throws if the channel has been closed.
158
+ * Create a reactive object that auto-updates when the object at this location changes.
174
159
  */
175
- object(objectId: string): ReactiveObject;
160
+ object(location: string): ReactiveObject;
176
161
  /**
177
162
  * Create a reactive watch that auto-updates when matching objects change.
178
- * Throws if the channel has been closed.
179
163
  */
180
164
  watch(options: WatchOptions): ReactiveWatch;
181
165
  }
@@ -183,21 +167,13 @@ export declare function wrapChannel(channel: RoolChannel): ReactiveChannel;
183
167
  export type ReactiveChannel = ReactiveChannelImpl;
184
168
  /**
185
169
  * A reactive list of channels for a space that auto-updates via SSE events.
186
- * Can be constructed with a RoolSpace directly or a Promise<RoolSpace>
187
- * (starts with an empty list and loading=true until the space resolves).
188
170
  */
189
171
  declare class ReactiveChannelListImpl {
190
172
  #private;
191
173
  list: ChannelInfo[];
192
174
  loading: boolean;
193
175
  constructor(spaceOrPromise: RoolSpace | Promise<RoolSpace>);
194
- /**
195
- * Refresh the channel list from the space.
196
- */
197
176
  refresh(): Promise<void>;
198
- /**
199
- * Stop listening for updates and clean up.
200
- */
201
177
  close(): void;
202
178
  }
203
179
  export declare function createChannelList(spaceOrPromise: RoolSpace | Promise<RoolSpace>): ReactiveChannelList;
@@ -1 +1 @@
1
- {"version":3,"file":"channel.svelte.d.ts","sourceRoot":"","sources":["../src/channel.svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.svelte.d.ts","sourceRoot":"","sources":["../src/channel.svelte.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ class ReactiveWatchImpl {
5
5
  #channel;
6
6
  #options;
7
7
  #unsubscribers = [];
8
- #currentIds = new Set();
8
+ #currentLocations = new Set();
9
9
  // Reactive state
10
10
  objects = $state([]);
11
11
  loading = $state(true);
@@ -17,7 +17,6 @@ class ReactiveWatchImpl {
17
17
  #setup() {
18
18
  // Initial fetch
19
19
  this.refresh();
20
- // Subscribe to object events
21
20
  const onObjectCreated = ({ object }) => {
22
21
  if (this.#matches(object)) {
23
22
  this.refresh();
@@ -25,32 +24,38 @@ class ReactiveWatchImpl {
25
24
  };
26
25
  this.#channel.on('objectCreated', onObjectCreated);
27
26
  this.#unsubscribers.push(() => this.#channel.off('objectCreated', onObjectCreated));
28
- const onObjectUpdated = ({ objectId, object }) => {
29
- const wasInCollection = this.#currentIds.has(objectId);
27
+ const onObjectUpdated = ({ location, object }) => {
28
+ const wasInCollection = this.#currentLocations.has(location);
30
29
  const nowMatches = this.#matches(object);
31
30
  if (wasInCollection && nowMatches) {
32
31
  // Update in place (merge to preserve fields from partial optimistic updates)
33
- const index = this.objects.findIndex((o) => o.id === objectId);
32
+ const index = this.objects.findIndex((o) => o.location === location);
34
33
  if (index !== -1) {
35
- this.objects[index] = { ...this.objects[index], ...object };
34
+ this.objects[index] = {
35
+ ...this.objects[index],
36
+ ...object,
37
+ body: { ...this.objects[index].body, ...object.body },
38
+ };
36
39
  }
37
40
  }
38
41
  else if (wasInCollection && !nowMatches) {
39
- // Check if the mismatch is due to missing keys (partial optimistic update)
40
- // vs. genuinely changed values that no longer satisfy the filter.
42
+ // Check if the mismatch is due to missing keys in body (partial optimistic update)
41
43
  const where = this.#options.where;
42
- const isPartialUpdate = where && Object.keys(where).some((key) => !(key in object));
44
+ const isPartialUpdate = where && Object.keys(where).some((key) => !(key in object.body));
43
45
  if (isPartialUpdate) {
44
- // Partial update merge onto existing object instead of removing
45
- const index = this.objects.findIndex((o) => o.id === objectId);
46
+ const index = this.objects.findIndex((o) => o.location === location);
46
47
  if (index !== -1) {
47
- this.objects[index] = { ...this.objects[index], ...object };
48
+ this.objects[index] = {
49
+ ...this.objects[index],
50
+ ...object,
51
+ body: { ...this.objects[index].body, ...object.body },
52
+ };
48
53
  }
49
54
  }
50
55
  else {
51
56
  // Genuine mismatch — remove from collection
52
- this.objects = this.objects.filter((o) => o.id !== objectId);
53
- this.#currentIds.delete(objectId);
57
+ this.objects = this.objects.filter((o) => o.location !== location);
58
+ this.#currentLocations.delete(location);
54
59
  }
55
60
  }
56
61
  else if (!wasInCollection && nowMatches) {
@@ -60,31 +65,38 @@ class ReactiveWatchImpl {
60
65
  };
61
66
  this.#channel.on('objectUpdated', onObjectUpdated);
62
67
  this.#unsubscribers.push(() => this.#channel.off('objectUpdated', onObjectUpdated));
63
- const onObjectDeleted = ({ objectId }) => {
64
- if (this.#currentIds.has(objectId)) {
65
- this.objects = this.objects.filter((o) => o.id !== objectId);
66
- this.#currentIds.delete(objectId);
68
+ const onObjectDeleted = ({ location }) => {
69
+ if (this.#currentLocations.has(location)) {
70
+ this.objects = this.objects.filter((o) => o.location !== location);
71
+ this.#currentLocations.delete(location);
67
72
  }
68
73
  };
69
74
  this.#channel.on('objectDeleted', onObjectDeleted);
70
75
  this.#unsubscribers.push(() => this.#channel.off('objectDeleted', onObjectDeleted));
71
- // Handle full resets
76
+ const onObjectMoved = ({ from, object }) => {
77
+ const wasInCollection = this.#currentLocations.has(from);
78
+ const nowMatches = this.#matches(object);
79
+ if (wasInCollection || nowMatches) {
80
+ this.refresh();
81
+ }
82
+ };
83
+ this.#channel.on('objectMoved', onObjectMoved);
84
+ this.#unsubscribers.push(() => this.#channel.off('objectMoved', onObjectMoved));
72
85
  const onReset = () => this.refresh();
73
86
  this.#channel.on('reset', onReset);
74
87
  this.#unsubscribers.push(() => this.#channel.off('reset', onReset));
75
88
  }
76
89
  /**
77
- * Check if an object matches the `where` filter.
90
+ * Check if an object matches the filter (collection + where on body).
78
91
  */
79
92
  #matches(object) {
80
- // Collection filter matches by `type` field
81
- if (this.#options.collection && object.type !== this.#options.collection)
93
+ if (this.#options.collection && object.collection !== this.#options.collection)
82
94
  return false;
83
95
  const where = this.#options.where;
84
96
  if (!where)
85
97
  return true;
86
98
  for (const [key, value] of Object.entries(where)) {
87
- if (object[key] !== value)
99
+ if (object.body[key] !== value)
88
100
  return false;
89
101
  }
90
102
  return true;
@@ -100,19 +112,16 @@ class ReactiveWatchImpl {
100
112
  collection: this.#options.collection,
101
113
  limit: this.#options.limit,
102
114
  order: this.#options.order,
103
- ephemeral: true, // Don't pollute interaction history
115
+ ephemeral: true,
104
116
  };
105
117
  const { objects } = await this.#channel.findObjects(findOptions);
106
118
  this.objects = objects;
107
- this.#currentIds = new Set(objects.map((o) => o.id));
119
+ this.#currentLocations = new Set(objects.map((o) => o.location));
108
120
  }
109
121
  finally {
110
122
  this.loading = false;
111
123
  }
112
124
  }
113
- /**
114
- * Stop listening for updates and clean up.
115
- */
116
125
  close() {
117
126
  for (const unsub of this.#unsubscribers)
118
127
  unsub();
@@ -124,63 +133,63 @@ class ReactiveWatchImpl {
124
133
  */
125
134
  class ReactiveObjectImpl {
126
135
  #channel;
127
- #objectId;
136
+ #location;
128
137
  #unsubscribers = [];
129
138
  // Reactive state
130
139
  data = $state(undefined);
131
140
  loading = $state(true);
132
- constructor(channel, objectId) {
141
+ constructor(channel, location) {
133
142
  this.#channel = channel;
134
- this.#objectId = objectId;
143
+ this.#location = location;
135
144
  this.#setup();
136
145
  }
137
146
  #setup() {
138
- // Initial fetch
139
147
  this.refresh();
140
- // Listen for updates to this specific object
141
- const onObjectUpdated = ({ objectId, object }) => {
142
- if (objectId === this.#objectId) {
148
+ const onObjectUpdated = ({ location, object }) => {
149
+ if (location === this.#location) {
143
150
  this.data = object;
144
151
  }
145
152
  };
146
153
  this.#channel.on('objectUpdated', onObjectUpdated);
147
154
  this.#unsubscribers.push(() => this.#channel.off('objectUpdated', onObjectUpdated));
148
- // Listen for creation (in case object didn't exist initially)
149
- const onObjectCreated = ({ object }) => {
150
- if (object.id === this.#objectId) {
155
+ const onObjectCreated = ({ location, object }) => {
156
+ if (location === this.#location) {
151
157
  this.data = object;
152
158
  }
153
159
  };
154
160
  this.#channel.on('objectCreated', onObjectCreated);
155
161
  this.#unsubscribers.push(() => this.#channel.off('objectCreated', onObjectCreated));
156
- // Listen for deletion
157
- const onObjectDeleted = ({ objectId }) => {
158
- if (objectId === this.#objectId) {
162
+ const onObjectDeleted = ({ location }) => {
163
+ if (location === this.#location) {
159
164
  this.data = undefined;
160
165
  }
161
166
  };
162
167
  this.#channel.on('objectDeleted', onObjectDeleted);
163
168
  this.#unsubscribers.push(() => this.#channel.off('objectDeleted', onObjectDeleted));
164
- // Handle full resets
169
+ const onObjectMoved = ({ from, to, object }) => {
170
+ if (from === this.#location) {
171
+ // Object moved away from this location; data is gone.
172
+ this.data = undefined;
173
+ }
174
+ else if (to === this.#location) {
175
+ this.data = object;
176
+ }
177
+ };
178
+ this.#channel.on('objectMoved', onObjectMoved);
179
+ this.#unsubscribers.push(() => this.#channel.off('objectMoved', onObjectMoved));
165
180
  const onReset = () => this.refresh();
166
181
  this.#channel.on('reset', onReset);
167
182
  this.#unsubscribers.push(() => this.#channel.off('reset', onReset));
168
183
  }
169
- /**
170
- * Re-fetch the object from the channel.
171
- */
172
184
  async refresh() {
173
185
  this.loading = true;
174
186
  try {
175
- this.data = await this.#channel.getObject(this.#objectId);
187
+ this.data = await this.#channel.getObject(this.#location);
176
188
  }
177
189
  finally {
178
190
  this.loading = false;
179
191
  }
180
192
  }
181
- /**
182
- * Stop listening for updates and clean up.
183
- */
184
193
  close() {
185
194
  for (const unsub of this.#unsubscribers)
186
195
  unsub();
@@ -190,12 +199,6 @@ class ReactiveObjectImpl {
190
199
  // ---------------------------------------------------------------------------
191
200
  // ReactiveConversationHandle
192
201
  // ---------------------------------------------------------------------------
193
- /**
194
- * A reactive conversation handle that auto-updates interactions when the
195
- * conversation changes. Wraps the SDK's ConversationHandle with $state.
196
- *
197
- * Call `close()` when done to stop listening for updates.
198
- */
199
202
  class ReactiveConversationHandleImpl {
200
203
  #handle;
201
204
  #conversationId;
@@ -205,9 +208,7 @@ class ReactiveConversationHandleImpl {
205
208
  constructor(channel, conversationId) {
206
209
  this.#conversationId = conversationId;
207
210
  this.#handle = channel.conversation(conversationId);
208
- // Initial load
209
211
  this.interactions = this.#handle.getInteractions();
210
- // Listen for updates to this conversation
211
212
  const onConversationUpdated = (event) => {
212
213
  if (event.conversationId === this.#conversationId) {
213
214
  this.interactions = this.#handle.getInteractions();
@@ -215,7 +216,6 @@ class ReactiveConversationHandleImpl {
215
216
  };
216
217
  channel.on('conversationUpdated', onConversationUpdated);
217
218
  this.#unsubscribers.push(() => channel.off('conversationUpdated', onConversationUpdated));
218
- // Handle full resets
219
219
  const onReset = () => {
220
220
  this.interactions = this.#handle.getInteractions();
221
221
  };
@@ -235,6 +235,7 @@ class ReactiveConversationHandleImpl {
235
235
  findObjects(...args) { return this.#handle.findObjects(...args); }
236
236
  createObject(...args) { return this.#handle.createObject(...args); }
237
237
  updateObject(...args) { return this.#handle.updateObject(...args); }
238
+ moveObject(...args) { return this.#handle.moveObject(...args); }
238
239
  deleteObjects(...args) { return this.#handle.deleteObjects(...args); }
239
240
  // AI
240
241
  prompt(...args) { return this.#handle.prompt(...args); }
@@ -244,9 +245,6 @@ class ReactiveConversationHandleImpl {
244
245
  dropCollection(...args) { return this.#handle.dropCollection(...args); }
245
246
  // Metadata
246
247
  setMetadata(...args) { return this.#handle.setMetadata(...args); }
247
- /**
248
- * Stop listening for updates and clean up.
249
- */
250
248
  close() {
251
249
  for (const unsub of this.#unsubscribers)
252
250
  unsub();
@@ -263,36 +261,34 @@ class ReactiveChannelImpl {
263
261
  #closed = false;
264
262
  // Reactive state
265
263
  interactions = $state([]);
266
- objectIds = $state([]);
264
+ objectLocations = $state([]);
267
265
  collections = $state([]);
268
266
  conversations = $state([]);
269
267
  constructor(channel) {
270
268
  this.#channel = channel;
271
269
  this.interactions = channel.getInteractions();
272
- this.objectIds = channel.getObjectIds();
270
+ this.objectLocations = channel.getObjectLocations();
273
271
  this.collections = Object.keys(channel.getSchema());
274
272
  this.conversations = channel.getConversations();
275
- // Subscribe to channel updates → refresh interactions
276
273
  const onChannelUpdated = () => {
277
274
  this.interactions = channel.getInteractions();
278
275
  };
279
276
  channel.on('channelUpdated', onChannelUpdated);
280
277
  this.#unsubscribers.push(() => channel.off('channelUpdated', onChannelUpdated));
281
- // Subscribe to conversation updates → refresh conversations
282
278
  const onConversationUpdated = () => {
283
279
  this.conversations = channel.getConversations();
284
280
  };
285
281
  channel.on('conversationUpdated', onConversationUpdated);
286
282
  this.#unsubscribers.push(() => channel.off('conversationUpdated', onConversationUpdated));
287
- // Subscribe to object events for objectIds
288
- const refreshObjectIds = () => {
289
- this.objectIds = channel.getObjectIds();
283
+ const refreshObjectLocations = () => {
284
+ this.objectLocations = channel.getObjectLocations();
290
285
  };
291
- channel.on('objectCreated', refreshObjectIds);
292
- this.#unsubscribers.push(() => channel.off('objectCreated', refreshObjectIds));
293
- channel.on('objectDeleted', refreshObjectIds);
294
- this.#unsubscribers.push(() => channel.off('objectDeleted', refreshObjectIds));
295
- // Subscribe to schema updates for collections
286
+ channel.on('objectCreated', refreshObjectLocations);
287
+ this.#unsubscribers.push(() => channel.off('objectCreated', refreshObjectLocations));
288
+ channel.on('objectDeleted', refreshObjectLocations);
289
+ this.#unsubscribers.push(() => channel.off('objectDeleted', refreshObjectLocations));
290
+ channel.on('objectMoved', refreshObjectLocations);
291
+ this.#unsubscribers.push(() => channel.off('objectMoved', refreshObjectLocations));
296
292
  const onSchemaUpdated = () => {
297
293
  this.collections = Object.keys(channel.getSchema());
298
294
  };
@@ -300,7 +296,7 @@ class ReactiveChannelImpl {
300
296
  this.#unsubscribers.push(() => channel.off('schemaUpdated', onSchemaUpdated));
301
297
  const onReset = () => {
302
298
  this.interactions = channel.getInteractions();
303
- this.objectIds = channel.getObjectIds();
299
+ this.objectLocations = channel.getObjectLocations();
304
300
  this.collections = Object.keys(channel.getSchema());
305
301
  this.conversations = channel.getConversations();
306
302
  };
@@ -319,7 +315,6 @@ class ReactiveChannelImpl {
319
315
  get extensionUrl() { return this.#channel.extensionUrl; }
320
316
  get manifest() { return this.#channel.manifest; }
321
317
  get isClosed() { return this.#closed; }
322
- // Proxy all methods
323
318
  close() {
324
319
  if (this.#closed)
325
320
  return;
@@ -333,9 +328,10 @@ class ReactiveChannelImpl {
333
328
  getObject(...args) { return this.#channel.getObject(...args); }
334
329
  stat(...args) { return this.#channel.stat(...args); }
335
330
  findObjects(...args) { return this.#channel.findObjects(...args); }
336
- getObjectIds(...args) { return this.#channel.getObjectIds(...args); }
331
+ getObjectLocations(...args) { return this.#channel.getObjectLocations(...args); }
337
332
  createObject(...args) { return this.#channel.createObject(...args); }
338
333
  updateObject(...args) { return this.#channel.updateObject(...args); }
334
+ moveObject(...args) { return this.#channel.moveObject(...args); }
339
335
  deleteObjects(...args) { return this.#channel.deleteObjects(...args); }
340
336
  // AI
341
337
  prompt(...args) { return this.#channel.prompt(...args); }
@@ -365,11 +361,6 @@ class ReactiveChannelImpl {
365
361
  createCollection(...args) { return this.#channel.createCollection(...args); }
366
362
  alterCollection(...args) { return this.#channel.alterCollection(...args); }
367
363
  dropCollection(...args) { return this.#channel.dropCollection(...args); }
368
- // Media
369
- uploadMedia(...args) { return this.#channel.uploadMedia(...args); }
370
- fetchMedia(...args) { return this.#channel.fetchMedia(...args); }
371
- deleteMedia(...args) { return this.#channel.deleteMedia(...args); }
372
- listMedia() { return this.#channel.listMedia(); }
373
364
  // Proxied fetch
374
365
  fetch(...args) { return this.#channel.fetch(...args); }
375
366
  // Channel admin
@@ -385,17 +376,15 @@ class ReactiveChannelImpl {
385
376
  off(...args) { return this.#channel.off(...args); }
386
377
  // Reactive primitives
387
378
  /**
388
- * Create a reactive object that auto-updates when the object changes.
389
- * Throws if the channel has been closed.
379
+ * Create a reactive object that auto-updates when the object at this location changes.
390
380
  */
391
- object(objectId) {
381
+ object(location) {
392
382
  if (this.#closed)
393
383
  throw new Error('Cannot create reactive object: channel is closed');
394
- return new ReactiveObjectImpl(this.#channel, objectId);
384
+ return new ReactiveObjectImpl(this.#channel, location);
395
385
  }
396
386
  /**
397
387
  * Create a reactive watch that auto-updates when matching objects change.
398
- * Throws if the channel has been closed.
399
388
  */
400
389
  watch(options) {
401
390
  if (this.#closed)
@@ -408,8 +397,6 @@ export function wrapChannel(channel) {
408
397
  }
409
398
  /**
410
399
  * A reactive list of channels for a space that auto-updates via SSE events.
411
- * Can be constructed with a RoolSpace directly or a Promise<RoolSpace>
412
- * (starts with an empty list and loading=true until the space resolves).
413
400
  */
414
401
  class ReactiveChannelListImpl {
415
402
  #space = null;
@@ -431,7 +418,6 @@ class ReactiveChannelListImpl {
431
418
  this.#space = space;
432
419
  this.list = space.channels;
433
420
  this.loading = false;
434
- // Listen for channel lifecycle events on the space
435
421
  const onChannelCreated = (channel) => {
436
422
  this.list = [...this.list, channel];
437
423
  };
@@ -448,9 +434,6 @@ class ReactiveChannelListImpl {
448
434
  space.on('channelDeleted', onChannelDeleted);
449
435
  this.#unsubscribers.push(() => space.off('channelDeleted', onChannelDeleted));
450
436
  }
451
- /**
452
- * Refresh the channel list from the space.
453
- */
454
437
  async refresh() {
455
438
  if (!this.#space)
456
439
  return;
@@ -463,9 +446,6 @@ class ReactiveChannelListImpl {
463
446
  this.loading = false;
464
447
  }
465
448
  }
466
- /**
467
- * Stop listening for updates and clean up.
468
- */
469
449
  close() {
470
450
  for (const unsub of this.#unsubscribers)
471
451
  unsub();
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  export { createRool, generateId } from './rool.svelte.js';
2
+ export { loc, parseLocation, normalizeLocation, isLocation, generateBasename, resolveMachineResource, } from '@rool-dev/sdk';
3
+ export type { ParsedLocation, MachineResource } from '@rool-dev/sdk';
2
4
  export { wrapChannel } from './channel.svelte.js';
3
5
  export { wrapSpace } from './space.svelte.js';
4
6
  export type { Rool } from './rool.svelte.js';
5
7
  export type { ReactiveChannel, ReactiveConversationHandle, ReactiveObject, ReactiveWatch, ReactiveChannelList, WatchOptions } from './channel.svelte.js';
6
8
  export type { ReactiveSpace } from './space.svelte.js';
7
- export type { RoolClientConfig, RoolChannel, RoolSpace, RoolSpaceInfo, RoolObject, RoolObjectStat, RoolUserRole, ConnectionState, ChannelInfo, Conversation, ConversationInfo, CurrentUser, Interaction, FindObjectsOptions, PromptOptions, CreateObjectOptions, UpdateObjectOptions, FieldType, FieldDef, CollectionDef, SpaceSchema, SpaceMember, UserResult, RoolClient, ExtensionInfo, PublishedExtensionInfo, UploadExtensionOptions, ExtensionManifest, FindExtensionsOptions, RoolSpaceEvents, ProbeRequestEvent, OpenExtensionEvent, } from '@rool-dev/sdk';
9
+ export type { RoolClientConfig, RoolChannel, RoolSpace, RoolSpaceInfo, RoolObject, RoolObjectStat, RoolUserRole, ConnectionState, ChannelInfo, Conversation, ConversationInfo, CurrentUser, Interaction, FindObjectsOptions, PromptOptions, CreateObjectOptions, UpdateObjectOptions, MoveObjectOptions, FieldType, FieldDef, CollectionDef, SpaceSchema, SpaceMember, UserResult, RoolClient, ExtensionInfo, PublishedExtensionInfo, UploadExtensionOptions, ExtensionManifest, FindExtensionsOptions, RoolSpaceEvents, ProbeRequestEvent, OpenExtensionEvent, } from '@rool-dev/sdk';
8
10
  //# sourceMappingURL=index.d.ts.map
@@ -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,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,0BAA0B,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzJ,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,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,EACV,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
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,EACL,GAAG,EACH,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,0BAA0B,EAAE,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzJ,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,aAAa,EACb,UAAU,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // Main export
2
2
  export { createRool, generateId } from './rool.svelte.js';
3
+ // Location and machine-resource helpers — re-exported from the SDK for convenience
4
+ export { loc, parseLocation, normalizeLocation, isLocation, generateBasename, resolveMachineResource, } from '@rool-dev/sdk';
3
5
  // Reactive wrappers
4
6
  export { wrapChannel } from './channel.svelte.js';
5
7
  export { wrapSpace } from './space.svelte.js';
@@ -28,6 +28,9 @@ declare class ReactiveSpaceImpl {
28
28
  get role(): RoolUserRole;
29
29
  get linkAccess(): LinkAccess;
30
30
  get memberCount(): number;
31
+ get webdav(): import("@rool-dev/sdk").RoolWebDAV;
32
+ getStorageUsage(...args: Parameters<RoolSpace['getStorageUsage']>): Promise<import("@rool-dev/sdk").SpaceFileStorageUsage>;
33
+ fetchMachineResource(...args: Parameters<RoolSpace['fetchMachineResource']>): Promise<Response>;
31
34
  rename(newName: string): Promise<void>;
32
35
  delete(): Promise<void>;
33
36
  listUsers(): Promise<SpaceMember[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"space.svelte.d.ts","sourceRoot":"","sources":["../src/space.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAExE;;;;;;GAMG;AACH,cAAM,iBAAiB;;IAQrB,eAAe,kBAA2C;gBAE9C,KAAK,EAAE,SAAS;IAmB5B,IAAI,QAAQ,YAA2B;IAEvC;;;OAGG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAY9D;;;OAGG;IACH,KAAK,IAAI,IAAI;IAgBb,IAAI,QAAQ,IAAI,WAAW,EAAE,CAA8B;IAG3D,IAAI,EAAE,IAAI,MAAM,CAA2B;IAC3C,IAAI,IAAI,IAAI,MAAM,CAA6B;IAC/C,IAAI,IAAI,IAAI,YAAY,CAA6B;IACrD,IAAI,UAAU,IAAI,UAAU,CAAmC;IAC/D,IAAI,WAAW,IAAI,MAAM,CAAoC;IAG7D,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IACvB,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACjD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACzC,aAAa,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC7D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/C,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACzE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAGxB,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;CAC1C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAEzD;AAED,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC"}
1
+ {"version":3,"file":"space.svelte.d.ts","sourceRoot":"","sources":["../src/space.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpH,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAExE;;;;;;GAMG;AACH,cAAM,iBAAiB;;IAQrB,eAAe,kBAA2C;gBAE9C,KAAK,EAAE,SAAS;IAmB5B,IAAI,QAAQ,YAA2B;IAEvC;;;OAGG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAY9D;;;OAGG;IACH,KAAK,IAAI,IAAI;IAgBb,IAAI,QAAQ,IAAI,WAAW,EAAE,CAA8B;IAG3D,IAAI,EAAE,IAAI,MAAM,CAA2B;IAC3C,IAAI,IAAI,IAAI,MAAM,CAA6B;IAC/C,IAAI,IAAI,IAAI,YAAY,CAA6B;IACrD,IAAI,UAAU,IAAI,UAAU,CAAmC;IAC/D,IAAI,WAAW,IAAI,MAAM,CAAoC;IAC7D,IAAI,MAAM,uCAAiC;IAG3C,eAAe,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IACjE,oBAAoB,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAG3E,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IACvB,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACjD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACzC,aAAa,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC7D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/C,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACzE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAGxB,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;CAC1C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAEzD;AAED,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC"}
@@ -71,6 +71,10 @@ class ReactiveSpaceImpl {
71
71
  get role() { return this.#space.role; }
72
72
  get linkAccess() { return this.#space.linkAccess; }
73
73
  get memberCount() { return this.#space.memberCount; }
74
+ get webdav() { return this.#space.webdav; }
75
+ // Proxy resource methods
76
+ getStorageUsage(...args) { return this.#space.getStorageUsage(...args); }
77
+ fetchMachineResource(...args) { return this.#space.fetchMachineResource(...args); }
74
78
  // Proxy admin methods
75
79
  rename(newName) { return this.#space.rename(newName); }
76
80
  delete() { return this.#space.delete(); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rool-dev/svelte",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
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.9.0"
44
+ "@rool-dev/sdk": "0.10.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "svelte": "^5.0.0"
@@ -55,7 +55,7 @@
55
55
  "scripts": {
56
56
  "build": "svelte-package -i src -o dist",
57
57
  "dev": "svelte-package -i src -o dist --watch",
58
- "typecheck": "svelte-check --tsconfig ./tsconfig.json",
58
+ "typecheck": "pnpm --filter @rool-dev/sdk build && svelte-check --tsconfig ./tsconfig.json",
59
59
  "clean": "rm -rf dist"
60
60
  }
61
61
  }