@rebasepro/client 0.10.0 → 0.10.1-canary.14e53ae

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/src/storage.ts CHANGED
@@ -12,6 +12,14 @@ import { Transport } from "./transport";
12
12
  export function createStorage(transport: Transport, storageId?: string): StorageSource {
13
13
  const urlsCache = new Map<string, { config: DownloadConfig; expiresAt?: number }>();
14
14
 
15
+ /**
16
+ * Base for URLs the *browser* will fetch on its own (file downloads,
17
+ * previews). API requests keep going to `baseUrl`; see
18
+ * {@link RebaseClientConfig.storageUrlOrigin} for why these can differ.
19
+ */
20
+ const fileUrlBase = (): string =>
21
+ `${transport.storageUrlOrigin ?? transport.baseUrl}${transport.apiPath}`;
22
+
15
23
  /** Append ?storageId=... to a path when multi-backend routing is active. */
16
24
  const withStorageId = (path: string): string => {
17
25
  if (!storageId) return path;
@@ -95,7 +103,7 @@ export function createStorage(transport: Transport, storageId?: string): Storage
95
103
  // token are needed — build the URL directly and cache it forever.
96
104
  if (isPublicStoragePath(filePath)) {
97
105
  const publicConfig: DownloadConfig = {
98
- url: withStorageId(`${transport.baseUrl}${transport.apiPath}/storage/file/${filePath}`)
106
+ url: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`)
99
107
  };
100
108
  urlsCache.set(cacheKey, { config: publicConfig }); // no expiry
101
109
  return publicConfig;
@@ -107,7 +115,7 @@ export function createStorage(transport: Transport, storageId?: string): Storage
107
115
  // Public object (server-confirmed): token-less permanent URL.
108
116
  if (result.data.public) {
109
117
  const publicConfig: DownloadConfig = {
110
- url: withStorageId(`${transport.baseUrl}${transport.apiPath}/storage/file/${filePath}`),
118
+ url: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`),
111
119
  metadata: result.data
112
120
  };
113
121
  urlsCache.set(cacheKey, { config: publicConfig }); // no expiry
@@ -125,7 +133,7 @@ export function createStorage(transport: Transport, storageId?: string): Storage
125
133
  // `withStorageId` picks `?` or `&` based on whether the token
126
134
  // query is already present, so the URL stays valid even when
127
135
  // there is no token.
128
- url: withStorageId(`${transport.baseUrl}${transport.apiPath}/storage/file/${filePath}${tokenQuery}`),
136
+ url: withStorageId(`${fileUrlBase()}/storage/file/${filePath}${tokenQuery}`),
129
137
  metadata: result.data
130
138
  };
131
139
 
package/src/transport.ts CHANGED
@@ -33,6 +33,20 @@ export interface RebaseClientConfig {
33
33
  * Defaults to `"/api"`; override only if the server mounts it elsewhere.
34
34
  */
35
35
  apiPath?: string;
36
+ /**
37
+ * Origin to use instead of {@link baseUrl} for URLs that are handed to the
38
+ * browser to fetch on its own — storage file downloads and previews.
39
+ *
40
+ * API *requests* always go to `baseUrl`; this only changes URLs the SDK
41
+ * *returns* (e.g. `storage.getSignedUrl`). It exists for proxied setups:
42
+ * when `baseUrl` routes through an authenticated middleman (the Rebase
43
+ * console's Studio proxy), a plain `<img src>` or a copied link cannot
44
+ * satisfy the middleman's auth — but the file route itself is reachable
45
+ * directly at the origin server and secured by its own scoped `?token=`.
46
+ * Set this to that server's public origin (no path; {@link apiPath} is
47
+ * appended) and returned file URLs point straight at it.
48
+ */
49
+ storageUrlOrigin?: string;
36
50
  fetch?: typeof globalThis.fetch;
37
51
  onUnauthorized?: () => Promise<boolean>;
38
52
  websocketUrl?: string; // Optional real-time WebSocket connection
@@ -107,6 +121,8 @@ export interface Transport {
107
121
  setOnUnauthorized: (handler: () => Promise<boolean>) => void;
108
122
  readonly baseUrl: string;
109
123
  readonly apiPath: string;
124
+ /** See {@link RebaseClientConfig.storageUrlOrigin}. Undefined = use `baseUrl`. */
125
+ readonly storageUrlOrigin?: string;
110
126
  readonly fetchFn: typeof globalThis.fetch;
111
127
  getHeaders: (init?: RequestInit) => Record<string, string>;
112
128
  resolveToken: () => Promise<string | null>;
@@ -266,6 +282,7 @@ headers: retryHeaders });
266
282
  setOnUnauthorized(handler: () => Promise<boolean>) { onUnauthorizedHandler = handler; },
267
283
  get baseUrl() { return resolveBaseUrl(config.baseUrl); },
268
284
  get apiPath() { return apiPath; },
285
+ get storageUrlOrigin() { return config.storageUrlOrigin?.replace(/\/$/, "") || undefined; },
269
286
  get fetchFn() { return fetchFn; },
270
287
  getHeaders: (init?: RequestInit) => getHeaders(token, init) as Record<string, string>,
271
288
  resolveToken: async () => {