@rool-dev/extension 0.4.1-dev.4b63014 → 0.4.1-dev.5b1d180

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.
@@ -7200,19 +7200,10 @@ var MediaClient = class {
7200
7200
  }
7201
7201
  /**
7202
7202
  * Fetch an external URL via the server proxy (bypasses CORS).
7203
+ * Uses POST /fetch/:spaceId with cache-control hint for media.
7203
7204
  */
7204
7205
  async fetchViaProxy(spaceId, url) {
7205
- const tokens = await this.config.authManager.getTokens();
7206
- if (!tokens) throw new Error("Not authenticated");
7207
- const headers = {
7208
- Authorization: `Bearer ${tokens.accessToken}`,
7209
- "X-Rool-Token": tokens.roolToken
7210
- };
7211
- const proxyUrl = `${this.baseUrl(spaceId)}/proxy?url=${encodeURIComponent(url)}`;
7212
- const response = await fetch(proxyUrl, {
7213
- method: "GET",
7214
- headers
7215
- });
7206
+ const response = await this.proxyFetch(spaceId, url, { headers: { "Cache-Control": "private, max-age=3600" } });
7216
7207
  if (!response.ok) throw new Error(`Failed to fetch media via proxy: ${response.status} ${response.statusText}`);
7217
7208
  return response;
7218
7209
  }
@@ -7234,6 +7225,29 @@ var MediaClient = class {
7234
7225
  if (!response.ok && response.status !== 204) throw new Error(`Failed to delete media: ${response.status} ${response.statusText}`);
7235
7226
  }
7236
7227
  /**
7228
+ * Proxied fetch — execute an HTTP request via the server, bypassing CORS.
7229
+ * Uses POST /fetch/:spaceId on the backend.
7230
+ */
7231
+ async proxyFetch(spaceId, url, init) {
7232
+ const tokens = await this.config.authManager.getTokens();
7233
+ if (!tokens) throw new Error("Not authenticated");
7234
+ const fetchUrl = `${this.config.backendOrigin}/fetch/${encodeURIComponent(spaceId)}`;
7235
+ return await fetch(fetchUrl, {
7236
+ method: "POST",
7237
+ headers: {
7238
+ "Content-Type": "application/json",
7239
+ Authorization: `Bearer ${tokens.accessToken}`,
7240
+ "X-Rool-Token": tokens.roolToken
7241
+ },
7242
+ body: JSON.stringify({
7243
+ url,
7244
+ method: init?.method,
7245
+ headers: init?.headers,
7246
+ body: init?.body
7247
+ })
7248
+ });
7249
+ }
7250
+ /**
7237
7251
  * Export a space as a zip archive containing data and media.
7238
7252
  * The archive includes data.json with objects, relations, metadata, and channels,
7239
7253
  * plus a media/ folder with all media files.
@@ -8115,6 +8129,17 @@ var RoolChannel = class extends EventEmitter {
8115
8129
  return this.mediaClient.delete(this._id, url);
8116
8130
  }
8117
8131
  /**
8132
+ * Fetch an external URL via the server proxy, bypassing CORS restrictions.
8133
+ * Requires editor role or above. Blocked for private/internal IP ranges (SSRF protection).
8134
+ *
8135
+ * @param url - The URL to fetch
8136
+ * @param init - Optional method, headers, and body
8137
+ * @returns The proxied Response
8138
+ */
8139
+ async fetch(url, init) {
8140
+ return this.mediaClient.proxyFetch(this._id, url, init);
8141
+ }
8142
+ /**
8118
8143
  * Register a collector that resolves when the object arrives via SSE.
8119
8144
  * If the object is already in the buffer (arrived before collector), resolves immediately.
8120
8145
  * @internal
@@ -8677,12 +8702,12 @@ var RoolClient = class extends EventEmitter {
8677
8702
  }
8678
8703
  /**
8679
8704
  * Make an authenticated fetch request to the Rool API.
8680
- * Use this escape hatch for app-specific endpoints not covered by the typed API.
8705
+ * @internal Not part of the public API use typed methods instead.
8681
8706
  *
8682
8707
  * @param path - Path relative to the base URL (e.g., '/billing/usage')
8683
8708
  * @param init - Standard fetch RequestInit options. Authorization header is added automatically.
8684
8709
  */
8685
- async fetch(path, init) {
8710
+ async _api(path, init) {
8686
8711
  const tokens = await this.authManager.getTokens();
8687
8712
  if (!tokens) throw new Error("Not authenticated");
8688
8713
  const headers = new Headers(init?.headers);
@@ -8978,15 +9003,9 @@ var RoolClient = class extends EventEmitter {
8978
9003
  }
8979
9004
  /**
8980
9005
  * Execute an arbitrary GraphQL query or mutation.
8981
- * Use this escape hatch for app-specific operations not covered by the typed API.
8982
- *
8983
- * @example
8984
- * const result = await client.graphql<{ lastMessages: Message[] }>(
8985
- * `query trace($spaceId: String!) { trace(spaceId: $spaceId) }`,
8986
- * { spaceId: 'abc123' }
8987
- * );
9006
+ * @internal Not part of the public API use typed methods instead.
8988
9007
  */
8989
- async graphql(query, variables) {
9008
+ async _graphql(query, variables) {
8990
9009
  return this.graphqlClient.query(query, variables);
8991
9010
  }
8992
9011
  registerChannel(spaceId, channel) {
@@ -9140,7 +9159,8 @@ var ALLOWED_METHODS = new Set([
9140
9159
  "canRedo",
9141
9160
  "undo",
9142
9161
  "redo",
9143
- "clearHistory"
9162
+ "clearHistory",
9163
+ "fetch"
9144
9164
  ]);
9145
9165
  var CONVERSATION_METHODS = new Set([
9146
9166
  "getInteractions",
@@ -9241,6 +9261,20 @@ var BridgeHost = class {
9241
9261
  result = fn.apply(target, args);
9242
9262
  if (result instanceof Promise) result = await result;
9243
9263
  } else result = fn;
9264
+ if (method === "fetch" && result instanceof Response) {
9265
+ const response = result;
9266
+ const headers = {};
9267
+ response.headers.forEach((v, k) => {
9268
+ headers[k] = v;
9269
+ });
9270
+ const body = await response.arrayBuffer();
9271
+ result = {
9272
+ status: response.status,
9273
+ statusText: response.statusText,
9274
+ headers,
9275
+ body
9276
+ };
9277
+ }
9244
9278
  this._postToApp({
9245
9279
  type: "rool:response",
9246
9280
  id,