@rool-dev/extension 0.4.0 → 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.
@@ -4556,16 +4556,25 @@ var BrowserAuthProvider = class {
4556
4556
  * Initiate login by redirecting to auth page.
4557
4557
  * @param appName - The name of the application requesting login (displayed on auth page)
4558
4558
  */
4559
- login(appName, options) {
4560
- const loginUrl = new URL(`${this.authBaseUrl}/`);
4559
+ login(appName) {
4560
+ this.redirectToAuth("login", appName);
4561
+ }
4562
+ /**
4563
+ * Initiate signup by redirecting to auth page.
4564
+ * @param appName - The name of the application requesting signup (displayed on auth page)
4565
+ */
4566
+ signup(appName) {
4567
+ this.redirectToAuth("signup", appName);
4568
+ }
4569
+ redirectToAuth(flow, appName) {
4570
+ const url = new URL(`${this.authBaseUrl}/${flow}`);
4561
4571
  const redirectTarget = window.location.origin + window.location.pathname + window.location.search;
4562
- loginUrl.searchParams.set("redirect_uri", redirectTarget);
4563
- loginUrl.searchParams.set("app_name", appName);
4564
- if (options?.signup) loginUrl.searchParams.set("signup", "true");
4572
+ url.searchParams.set("redirect_uri", redirectTarget);
4573
+ url.searchParams.set("app_name", appName);
4565
4574
  const state = this.generateState();
4566
4575
  this.storeState(state);
4567
- loginUrl.searchParams.set("state", state);
4568
- window.location.href = loginUrl.toString();
4576
+ url.searchParams.set("state", state);
4577
+ window.location.href = url.toString();
4569
4578
  }
4570
4579
  /**
4571
4580
  * Logout - clear all tokens and state.
@@ -4834,8 +4843,15 @@ var AuthManager = class {
4834
4843
  * Initiate login.
4835
4844
  * @param appName - The name of the application requesting login (displayed on auth page)
4836
4845
  */
4837
- login(appName, options) {
4838
- return this.provider.login(appName, options);
4846
+ login(appName) {
4847
+ return this.provider.login(appName);
4848
+ }
4849
+ /**
4850
+ * Initiate signup.
4851
+ * @param appName - The name of the application requesting signup (displayed on auth page)
4852
+ */
4853
+ signup(appName) {
4854
+ return this.provider.signup(appName);
4839
4855
  }
4840
4856
  /**
4841
4857
  * Logout - clear all tokens and state.
@@ -7184,19 +7200,10 @@ var MediaClient = class {
7184
7200
  }
7185
7201
  /**
7186
7202
  * Fetch an external URL via the server proxy (bypasses CORS).
7203
+ * Uses POST /fetch/:spaceId with cache-control hint for media.
7187
7204
  */
7188
7205
  async fetchViaProxy(spaceId, url) {
7189
- const tokens = await this.config.authManager.getTokens();
7190
- if (!tokens) throw new Error("Not authenticated");
7191
- const headers = {
7192
- Authorization: `Bearer ${tokens.accessToken}`,
7193
- "X-Rool-Token": tokens.roolToken
7194
- };
7195
- const proxyUrl = `${this.baseUrl(spaceId)}/proxy?url=${encodeURIComponent(url)}`;
7196
- const response = await fetch(proxyUrl, {
7197
- method: "GET",
7198
- headers
7199
- });
7206
+ const response = await this.proxyFetch(spaceId, url, { headers: { "Cache-Control": "private, max-age=3600" } });
7200
7207
  if (!response.ok) throw new Error(`Failed to fetch media via proxy: ${response.status} ${response.statusText}`);
7201
7208
  return response;
7202
7209
  }
@@ -7218,6 +7225,29 @@ var MediaClient = class {
7218
7225
  if (!response.ok && response.status !== 204) throw new Error(`Failed to delete media: ${response.status} ${response.statusText}`);
7219
7226
  }
7220
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
+ /**
7221
7251
  * Export a space as a zip archive containing data and media.
7222
7252
  * The archive includes data.json with objects, relations, metadata, and channels,
7223
7253
  * plus a media/ folder with all media files.
@@ -8099,6 +8129,17 @@ var RoolChannel = class extends EventEmitter {
8099
8129
  return this.mediaClient.delete(this._id, url);
8100
8130
  }
8101
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
+ /**
8102
8143
  * Register a collector that resolves when the object arrives via SSE.
8103
8144
  * If the object is already in the buffer (arrived before collector), resolves immediately.
8104
8145
  * @internal
@@ -8627,8 +8668,15 @@ var RoolClient = class extends EventEmitter {
8627
8668
  * Initiate login by redirecting to auth page.
8628
8669
  * @param appName - The name of the application requesting login (displayed on auth page)
8629
8670
  */
8630
- async login(appName, options) {
8631
- return this.authManager.login(appName, options);
8671
+ async login(appName) {
8672
+ return this.authManager.login(appName);
8673
+ }
8674
+ /**
8675
+ * Initiate signup by redirecting to auth page.
8676
+ * @param appName - The name of the application requesting signup (displayed on auth page)
8677
+ */
8678
+ async signup(appName) {
8679
+ return this.authManager.signup(appName);
8632
8680
  }
8633
8681
  /**
8634
8682
  * Logout - clear all tokens and state.
@@ -8654,12 +8702,12 @@ var RoolClient = class extends EventEmitter {
8654
8702
  }
8655
8703
  /**
8656
8704
  * Make an authenticated fetch request to the Rool API.
8657
- * 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.
8658
8706
  *
8659
8707
  * @param path - Path relative to the base URL (e.g., '/billing/usage')
8660
8708
  * @param init - Standard fetch RequestInit options. Authorization header is added automatically.
8661
8709
  */
8662
- async fetch(path, init) {
8710
+ async _api(path, init) {
8663
8711
  const tokens = await this.authManager.getTokens();
8664
8712
  if (!tokens) throw new Error("Not authenticated");
8665
8713
  const headers = new Headers(init?.headers);
@@ -8955,15 +9003,9 @@ var RoolClient = class extends EventEmitter {
8955
9003
  }
8956
9004
  /**
8957
9005
  * Execute an arbitrary GraphQL query or mutation.
8958
- * Use this escape hatch for app-specific operations not covered by the typed API.
8959
- *
8960
- * @example
8961
- * const result = await client.graphql<{ lastMessages: Message[] }>(
8962
- * `query trace($spaceId: String!) { trace(spaceId: $spaceId) }`,
8963
- * { spaceId: 'abc123' }
8964
- * );
9006
+ * @internal Not part of the public API use typed methods instead.
8965
9007
  */
8966
- async graphql(query, variables) {
9008
+ async _graphql(query, variables) {
8967
9009
  return this.graphqlClient.query(query, variables);
8968
9010
  }
8969
9011
  registerChannel(spaceId, channel) {
@@ -9117,7 +9159,8 @@ var ALLOWED_METHODS = new Set([
9117
9159
  "canRedo",
9118
9160
  "undo",
9119
9161
  "redo",
9120
- "clearHistory"
9162
+ "clearHistory",
9163
+ "fetch"
9121
9164
  ]);
9122
9165
  var CONVERSATION_METHODS = new Set([
9123
9166
  "getInteractions",
@@ -9218,6 +9261,20 @@ var BridgeHost = class {
9218
9261
  result = fn.apply(target, args);
9219
9262
  if (result instanceof Promise) result = await result;
9220
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
+ }
9221
9278
  this._postToApp({
9222
9279
  type: "rool:response",
9223
9280
  id,