@motherbase/client 1.0.1 → 1.1.1

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/dist/realtime.js CHANGED
@@ -1,32 +1,73 @@
1
+ import { contractPath, normalizeRealtimeModel, REALTIME_SOCKET_EVENTS, REALTIME_TOPIC_EVENTS, } from '@motherbase/contracts';
1
2
  /**
2
3
  * Lazy wrapper over socket.io-client. The dependency is optional: it is only
3
4
  * imported when `connect()` is called, so apps that never use realtime do not
4
5
  * need to install it.
5
6
  */
6
7
  export class RealtimeModule {
7
- constructor(baseUrl, store) {
8
+ constructor(baseUrl, store, fetchImpl = globalThis.fetch,
9
+ /** Inject a socket factory (tests / custom transports). Falls back to socket.io-client. */
10
+ ioFactory) {
8
11
  this.baseUrl = baseUrl;
9
12
  this.store = store;
13
+ this.fetchImpl = fetchImpl;
14
+ this.ioFactory = ioFactory;
10
15
  this.socket = null;
16
+ this.status = 'idle';
17
+ this.statusListeners = new Set();
18
+ this.pollers = new Map();
19
+ this.tableSubscriptionRefs = new Map();
20
+ this.pollerSeq = 0;
21
+ this.channelsByTopic = new Map();
22
+ this.topicRouterBound = false;
11
23
  }
12
- async connect() {
24
+ /** True once a socket is connected. */
25
+ get connected() {
26
+ return Boolean(this.socket?.connected);
27
+ }
28
+ getStatus() {
29
+ return this.status;
30
+ }
31
+ onStatusChange(listener) {
32
+ this.statusListeners.add(listener);
33
+ listener(this.status);
34
+ return () => this.statusListeners.delete(listener);
35
+ }
36
+ async connect(options = {}) {
13
37
  if (this.socket?.connected)
14
38
  return;
39
+ this.setStatus('connecting');
15
40
  let io;
16
- try {
17
- // socket.io-client is an optional peer dependency; resolved at runtime only.
18
- // @ts-ignore -- the module may not be installed at build time
19
- ({ io } = (await import('socket.io-client')));
41
+ if (this.ioFactory) {
42
+ io = this.ioFactory;
20
43
  }
21
- catch {
22
- throw new Error('Realtime requires the optional dependency "socket.io-client". Install it: npm i socket.io-client');
44
+ else {
45
+ try {
46
+ // socket.io-client is an optional peer dependency; resolved at runtime only.
47
+ // @ts-expect-error -- optional peer dependency resolved only when realtime connects
48
+ ({ io } = (await import('socket.io-client')));
49
+ }
50
+ catch {
51
+ if (options.fallbackPolling) {
52
+ this.setStatus('polling');
53
+ return;
54
+ }
55
+ this.setStatus('error', 'socket.io-client is not installed');
56
+ throw new Error('Realtime requires the optional dependency "socket.io-client". Install it: npm i socket.io-client');
57
+ }
23
58
  }
24
59
  const token = this.store.get()?.accessToken;
25
- this.socket = io(this.baseUrl, {
60
+ const socket = io(this.baseUrl, {
26
61
  path: '/ws',
27
62
  transports: ['websocket'],
63
+ reconnection: true,
28
64
  auth: token ? { token } : {},
29
65
  });
66
+ this.socket = socket;
67
+ this.bindSocketStatus(socket);
68
+ this.topicRouterBound = false;
69
+ this.bindTopicRouter();
70
+ await this.waitForConnect(socket, options.timeoutMs ?? 5000, Boolean(options.fallbackPolling));
30
71
  }
31
72
  on(event, cb) {
32
73
  this.socket?.on(event, cb);
@@ -37,9 +78,263 @@ export class RealtimeModule {
37
78
  emit(event, ...args) {
38
79
  this.socket?.emit(event, ...args);
39
80
  }
81
+ /**
82
+ * @deprecated Legacy low-level table watcher. Prefer the Supabase-shaped
83
+ * `client.channel(topic).on('postgres_changes', { event, schema, table, filter }, cb)`.
84
+ * Kept for backwards compatibility; scheduled for removal.
85
+ *
86
+ * Subscribe to create/update/delete events for a model table.
87
+ *
88
+ * Events are filtered server-side: you will only receive events for rows
89
+ * your session is authorized to see (based on REST API SELECT policies).
90
+ * Anonymous sessions receive only public rows; authenticated sessions receive
91
+ * rows matching their access policies (e.g. owner-only rows they own).
92
+ *
93
+ * Falls back to polling the REST endpoint at subscribe time if the WebSocket
94
+ * is not yet connected (polling does not auto-start on later disconnects).
95
+ */
96
+ watchTable(model, cb, options = {}) {
97
+ const normalizedModel = normalizeRealtimeModel(model);
98
+ if (!normalizedModel)
99
+ throw new Error('Invalid realtime model: ' + model);
100
+ const handlers = [];
101
+ const baseEvent = normalizedModel;
102
+ for (const type of ['created', 'updated', 'deleted']) {
103
+ const event = contractPath.realtime(baseEvent, type);
104
+ const handler = (payload) => cb({ type, source: 'socket', payload: payload });
105
+ handlers.push({ event, handler });
106
+ this.socket?.on(event, handler);
107
+ }
108
+ this.retainTableSubscription(normalizedModel);
109
+ const shouldPoll = options.polling !== false && (!this.socket?.connected || this.status === 'polling');
110
+ const pollerId = shouldPoll ? this.startPolling(model, cb, options) : null;
111
+ return () => {
112
+ for (const item of handlers)
113
+ this.socket?.off(item.event, item.handler);
114
+ this.releaseTableSubscription(normalizedModel);
115
+ if (pollerId !== null)
116
+ this.stopPolling(pollerId);
117
+ };
118
+ }
40
119
  disconnect() {
120
+ for (const id of Array.from(this.pollers.keys()))
121
+ this.stopPolling(id);
41
122
  this.socket?.disconnect();
42
123
  this.socket = null;
124
+ this.topicRouterBound = false;
125
+ this.setStatus('disconnected');
126
+ }
127
+ /** Register a channel so incoming rt:msg envelopes for its topic are routed to it. */
128
+ registerChannel(topic, channel) {
129
+ this.channelsByTopic.set(topic, channel);
130
+ this.bindTopicRouter();
131
+ }
132
+ unregisterChannel(topic) {
133
+ this.channelsByTopic.delete(topic);
134
+ }
135
+ /** Emit rt:join and resolve the server ack (or a timeout/error ack). */
136
+ joinTopic(topic, config, timeoutMs = 10000) {
137
+ if (!this.socket?.connected)
138
+ return Promise.resolve({ status: 'error', error: 'not-connected' });
139
+ const socket = this.socket;
140
+ return new Promise(resolve => {
141
+ let settled = false;
142
+ const timer = setTimeout(() => {
143
+ if (settled)
144
+ return;
145
+ settled = true;
146
+ resolve({ status: 'error', error: 'timeout' });
147
+ }, timeoutMs);
148
+ socket.emit(REALTIME_TOPIC_EVENTS.join, { topic, config }, (ack) => {
149
+ if (settled)
150
+ return;
151
+ settled = true;
152
+ clearTimeout(timer);
153
+ resolve(ack ?? { status: 'error', error: 'no-ack' });
154
+ });
155
+ });
156
+ }
157
+ leaveTopic(topic) {
158
+ this.socket?.emit(REALTIME_TOPIC_EVENTS.leave, { topic });
159
+ }
160
+ sendTopic(topic, type, event, payload) {
161
+ this.socket?.emit(REALTIME_TOPIC_EVENTS.message, { topic, type, event, payload });
162
+ }
163
+ /** Emit an rt:msg and wait for the server ack (or resolve 'timed out'/'error'). */
164
+ sendTopicWithAck(topic, type, event, payload, timeoutMs = 10000) {
165
+ if (!this.socket?.connected)
166
+ return Promise.resolve('error');
167
+ const socket = this.socket;
168
+ return new Promise(resolve => {
169
+ let settled = false;
170
+ const timer = setTimeout(() => {
171
+ if (settled)
172
+ return;
173
+ settled = true;
174
+ resolve('timed out');
175
+ }, timeoutMs);
176
+ socket.emit(REALTIME_TOPIC_EVENTS.message, { topic, type, event, payload }, (result) => {
177
+ if (settled)
178
+ return;
179
+ settled = true;
180
+ clearTimeout(timer);
181
+ resolve(result === 'ok' ? 'ok' : 'error');
182
+ });
183
+ });
184
+ }
185
+ bindTopicRouter() {
186
+ if (this.topicRouterBound || !this.socket)
187
+ return;
188
+ this.topicRouterBound = true;
189
+ this.socket.on(REALTIME_TOPIC_EVENTS.message, (env) => {
190
+ const envelope = env;
191
+ if (!envelope || typeof envelope.topic !== 'string')
192
+ return;
193
+ this.channelsByTopic.get(envelope.topic)?._receive(envelope);
194
+ });
195
+ }
196
+ retainTableSubscription(model) {
197
+ const refs = this.tableSubscriptionRefs.get(model) ?? 0;
198
+ this.tableSubscriptionRefs.set(model, refs + 1);
199
+ if (refs === 0 && this.socket?.connected)
200
+ this.socket.emit(REALTIME_SOCKET_EVENTS.subscribe, model);
201
+ }
202
+ releaseTableSubscription(model) {
203
+ const refs = this.tableSubscriptionRefs.get(model) ?? 0;
204
+ if (refs > 1) {
205
+ this.tableSubscriptionRefs.set(model, refs - 1);
206
+ return;
207
+ }
208
+ this.tableSubscriptionRefs.delete(model);
209
+ if (refs === 1 && this.socket?.connected)
210
+ this.socket.emit(REALTIME_SOCKET_EVENTS.unsubscribe, model);
211
+ }
212
+ resubscribeTables() {
213
+ if (!this.socket?.connected)
214
+ return;
215
+ for (const model of this.tableSubscriptionRefs.keys()) {
216
+ this.socket.emit(REALTIME_SOCKET_EVENTS.subscribe, model);
217
+ }
218
+ }
219
+ bindSocketStatus(socket) {
220
+ socket.on('connect', () => {
221
+ this.setStatus('connected');
222
+ this.resubscribeTables();
223
+ });
224
+ socket.on('disconnect', () => this.setStatus(this.pollers.size ? 'polling' : 'disconnected'));
225
+ socket.on('connect_error', error => this.setStatus('error', error));
226
+ socket.on('reconnect_attempt', () => this.setStatus('reconnecting'));
227
+ socket.on('reconnect', () => this.setStatus('connected'));
228
+ }
229
+ waitForConnect(socket, timeoutMs, fallbackPolling) {
230
+ if (socket.connected) {
231
+ this.setStatus('connected');
232
+ this.resubscribeTables();
233
+ return Promise.resolve();
234
+ }
235
+ return new Promise((resolve, reject) => {
236
+ let settled = false;
237
+ const cleanup = () => {
238
+ socket.off('connect', onConnect);
239
+ socket.off('connect_error', onError);
240
+ clearTimeout(timer);
241
+ };
242
+ const settle = (fn) => {
243
+ if (settled)
244
+ return;
245
+ settled = true;
246
+ cleanup();
247
+ fn();
248
+ };
249
+ const onConnect = () => settle(() => {
250
+ this.setStatus('connected');
251
+ resolve();
252
+ });
253
+ const onError = (error) => {
254
+ if (fallbackPolling) {
255
+ settle(() => {
256
+ this.setStatus('polling', error);
257
+ resolve();
258
+ });
259
+ return;
260
+ }
261
+ settle(() => {
262
+ this.setStatus('error', error);
263
+ reject(error instanceof Error ? error : new Error(String(error)));
264
+ });
265
+ };
266
+ const timer = setTimeout(() => {
267
+ if (fallbackPolling) {
268
+ settle(() => {
269
+ this.setStatus('polling');
270
+ resolve();
271
+ });
272
+ return;
273
+ }
274
+ settle(() => {
275
+ const error = new Error('Realtime connection timeout');
276
+ this.setStatus('error', error);
277
+ reject(error);
278
+ });
279
+ }, timeoutMs);
280
+ socket.on('connect', onConnect);
281
+ socket.on('connect_error', onError);
282
+ });
283
+ }
284
+ startPolling(model, cb, options) {
285
+ if (!this.fetchImpl)
286
+ throw new Error('Realtime polling requires a fetch implementation.');
287
+ const id = ++this.pollerSeq;
288
+ let last = '';
289
+ let stopped = false;
290
+ const run = async () => {
291
+ if (stopped)
292
+ return;
293
+ const rows = await this.fetchRows(model, options.query);
294
+ const snapshot = JSON.stringify(rows);
295
+ if (snapshot !== last) {
296
+ last = snapshot;
297
+ cb({ type: 'snapshot', source: 'polling', rows });
298
+ }
299
+ };
300
+ const timer = setInterval(() => {
301
+ run().catch(error => this.setStatus('error', error));
302
+ }, options.intervalMs ?? 5000);
303
+ this.pollers.set(id, {
304
+ timer,
305
+ stop: () => {
306
+ stopped = true;
307
+ clearInterval(timer);
308
+ },
309
+ });
310
+ this.setStatus(this.socket?.connected ? 'connected' : 'polling');
311
+ run().catch(error => this.setStatus('error', error));
312
+ return id;
313
+ }
314
+ stopPolling(id) {
315
+ const poller = this.pollers.get(id);
316
+ if (!poller)
317
+ return;
318
+ poller.stop();
319
+ this.pollers.delete(id);
320
+ if (!this.socket?.connected && this.pollers.size === 0)
321
+ this.setStatus('disconnected');
322
+ }
323
+ async fetchRows(model, query) {
324
+ const path = `${contractPath.rest(model)}${query ? (query.startsWith('?') ? query : `?${query}`) : ''}`;
325
+ const headers = {};
326
+ const token = this.store.get()?.accessToken;
327
+ if (token)
328
+ headers.Authorization = `Bearer ${token}`;
329
+ const res = await this.fetchImpl(`${this.baseUrl}${path}`, { headers });
330
+ if (!res.ok)
331
+ throw new Error(`Realtime polling failed with ${res.status}`);
332
+ return (await res.json());
333
+ }
334
+ setStatus(status, detail) {
335
+ this.status = status;
336
+ for (const listener of this.statusListeners)
337
+ listener(status, detail);
43
338
  }
44
339
  }
45
340
  //# sourceMappingURL=realtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAGzB,YAA6B,OAAe,EAAmB,KAAmB;QAArD,YAAO,GAAP,OAAO,CAAQ;QAAmB,UAAK,GAAL,KAAK,CAAc;QAF1E,WAAM,GAAsB,IAAI,CAAC;IAE4C,CAAC;IAEtF,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS;YAAE,OAAO;QACnC,IAAI,EAAa,CAAC;QAClB,IAAI,CAAC;YACH,6EAA6E;YAC7E,8DAA8D;YAC9D,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAiC,CAAC,CAAC;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,kGAAkG,CACnG,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE;YAC7B,IAAI,EAAE,KAAK;YACX,UAAU,EAAE,CAAC,WAAW,CAAC;YACzB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,EAAgC;QAChD,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,EAAiC;QAClD,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,GAAG,IAAe;QACpC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,UAAU;QACR,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}
package/dist/storage.d.ts CHANGED
@@ -1,29 +1,55 @@
1
1
  import type { HttpClient } from './http.js';
2
- import type { FileObject, FileVisibility } from './types.js';
3
- import type { UploadInput } from './profile.js';
4
- interface UploadOptions {
2
+ import type { FileObject, FileVisibility, MotherbaseResponse, StorageRemoveResponse, UploadInput } from './types.js';
3
+ export interface UploadOptions {
4
+ /** Object visibility. Defaults to the backend's default (private). */
5
5
  visibility?: FileVisibility;
6
- bucket?: string;
6
+ /** Passed through to the backend as the content type hint. */
7
+ contentType?: string;
8
+ upsert?: boolean;
7
9
  }
8
- interface PresignParams {
9
- filename: string;
10
- mime?: string;
11
- visibility?: FileVisibility;
12
- bucket?: string;
10
+ export interface UploadResult {
11
+ /** Stable object key. In this backend the key equals the created file id. */
12
+ path: string;
13
+ /** The created file's id (identical to `path`). */
14
+ id: string;
15
+ /** `bucket/id` convenience path. */
16
+ fullPath: string;
17
+ }
18
+ /**
19
+ * Supabase-compatible storage bucket handle. Maps onto the authenticated
20
+ * `/api/files` endpoints. NOTE: in this backend an object's identity is the
21
+ * server-issued file **id**, so the Supabase `path` argument to `download`,
22
+ * `remove`, `getPublicUrl` and `createSignedUrl` is the id returned by `upload`.
23
+ */
24
+ export declare class StorageBucket {
25
+ private readonly http;
26
+ private readonly baseUrl;
27
+ private readonly bucket;
28
+ constructor(http: HttpClient, baseUrl: string, bucket: string);
29
+ upload(path: string, file: UploadInput, options?: UploadOptions): Promise<MotherbaseResponse<UploadResult>>;
30
+ download(path: string): Promise<MotherbaseResponse<Blob>>;
31
+ remove(paths: string[]): Promise<MotherbaseResponse<StorageRemoveResponse[]>>;
32
+ /**
33
+ * Not supported: the backend exposes no per-bucket object listing endpoint.
34
+ * Returns an error rather than throwing, for drop-in compatibility.
35
+ */
36
+ list(_prefix?: string): Promise<MotherbaseResponse<FileObject[]>>;
37
+ /** Synchronous public URL (Supabase parity). Serves through the public bucket endpoint. */
38
+ getPublicUrl(path: string): {
39
+ data: {
40
+ publicUrl: string;
41
+ };
42
+ };
43
+ /** A (possibly signed) download URL for the object. */
44
+ createSignedUrl(path: string, _expiresIn?: number): Promise<MotherbaseResponse<{
45
+ signedUrl: string;
46
+ }>>;
13
47
  }
14
- export declare class StorageModule {
48
+ /** Supabase-compatible storage client: `client.storage.from(bucket)`. */
49
+ export declare class StorageClient {
15
50
  private readonly http;
16
- constructor(http: HttpClient);
17
- /** Multipart upload through the API (field name: "file"). */
18
- upload(file: UploadInput, options?: UploadOptions): Promise<FileObject>;
19
- /** Request a presigned PUT URL for direct-to-storage upload (S3 driver). */
20
- presign(params: PresignParams): Promise<{
21
- url: string;
22
- [k: string]: unknown;
23
- }>;
24
- /** Get a (possibly signed) download URL for a stored file. */
25
- getUrl(id: string): Promise<string>;
26
- remove(id: string): Promise<unknown>;
51
+ private readonly baseUrl;
52
+ constructor(http: HttpClient, baseUrl: string);
53
+ from(bucket: string): StorageBucket;
27
54
  }
28
- export {};
29
55
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,UAAU,aAAa;IACrB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,6DAA6D;IAC7D,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;IAS3E,4EAA4E;IAC5E,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAI9E,8DAA8D;IACxD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKzC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGrC"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EAErB,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAwBtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IASzD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAanF;;;OAGG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC;IAOvE,2FAA2F;IAC3F,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE;YAAE,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;IAS3D,uDAAuD;IACjD,eAAe,CACnB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAQtD;AAED,yEAAyE;AACzE,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAc,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAA1C,IAAI,EAAE,UAAU,EAAmB,OAAO,EAAE,MAAM;IAE/E,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa;CAGpC"}
package/dist/storage.js CHANGED
@@ -1,31 +1,99 @@
1
- export class StorageModule {
2
- constructor(http) {
1
+ import { toError } from './http.js';
2
+ import { HTTP_ROUTES, contractPath } from '@motherbase/contracts';
3
+ /**
4
+ * Supabase-compatible storage bucket handle. Maps onto the authenticated
5
+ * `/api/files` endpoints. NOTE: in this backend an object's identity is the
6
+ * server-issued file **id**, so the Supabase `path` argument to `download`,
7
+ * `remove`, `getPublicUrl` and `createSignedUrl` is the id returned by `upload`.
8
+ */
9
+ export class StorageBucket {
10
+ constructor(http, baseUrl, bucket) {
3
11
  this.http = http;
12
+ this.baseUrl = baseUrl;
13
+ this.bucket = bucket;
4
14
  }
5
- /** Multipart upload through the API (field name: "file"). */
6
- upload(file, options = {}) {
7
- const form = new FormData();
8
- if (typeof Blob !== 'undefined' && file instanceof Blob)
9
- form.append('file', file);
10
- else
11
- form.append('file', file);
12
- if (options.visibility)
13
- form.append('visibility', options.visibility);
14
- if (options.bucket)
15
- form.append('bucket', options.bucket);
16
- return this.http.request('/api/files/', { method: 'POST', form });
17
- }
18
- /** Request a presigned PUT URL for direct-to-storage upload (S3 driver). */
19
- presign(params) {
20
- return this.http.request('/api/files/presign', { method: 'POST', body: params });
21
- }
22
- /** Get a (possibly signed) download URL for a stored file. */
23
- async getUrl(id) {
24
- const res = await this.http.request(`/api/files/${id}/url`);
25
- return res.url;
26
- }
27
- remove(id) {
28
- return this.http.request(`/api/files/${id}`, { method: 'DELETE' });
15
+ async upload(path, file, options = {}) {
16
+ try {
17
+ const form = new FormData();
18
+ if (typeof Blob !== 'undefined' && file instanceof Blob) {
19
+ form.append('file', file, path);
20
+ }
21
+ else {
22
+ form.append('file', file);
23
+ }
24
+ if (options.visibility)
25
+ form.append('visibility', options.visibility);
26
+ form.append('bucket', this.bucket);
27
+ const created = await this.http.request(`${HTTP_ROUTES.files}/`, { method: 'POST', form });
28
+ return {
29
+ data: {
30
+ path: created.file.id,
31
+ id: created.file.id,
32
+ fullPath: `${this.bucket}/${created.file.id}`,
33
+ },
34
+ error: null,
35
+ };
36
+ }
37
+ catch (err) {
38
+ return { data: null, error: toError(err) };
39
+ }
40
+ }
41
+ async download(path) {
42
+ try {
43
+ const res = await this.http.requestRaw(contractPath.file(path, 'raw'));
44
+ return { data: await res.blob(), error: null };
45
+ }
46
+ catch (err) {
47
+ return { data: null, error: toError(err) };
48
+ }
49
+ }
50
+ async remove(paths) {
51
+ try {
52
+ const removed = await Promise.all(paths.map(p => this.http.request(contractPath.file(p), { method: 'DELETE' })));
53
+ return { data: removed, error: null };
54
+ }
55
+ catch (err) {
56
+ return { data: null, error: toError(err) };
57
+ }
58
+ }
59
+ /**
60
+ * Not supported: the backend exposes no per-bucket object listing endpoint.
61
+ * Returns an error rather than throwing, for drop-in compatibility.
62
+ */
63
+ async list(_prefix) {
64
+ return {
65
+ data: null,
66
+ error: { message: 'storage.list is not supported by the Motherbase backend' },
67
+ };
68
+ }
69
+ /** Synchronous public URL (Supabase parity). Serves through the public bucket endpoint. */
70
+ getPublicUrl(path) {
71
+ const base = this.baseUrl.replace(/\/$/, '');
72
+ return {
73
+ data: {
74
+ publicUrl: `${base}/api/storage/${encodeURIComponent(this.bucket)}/files/${encodeURIComponent(path)}`,
75
+ },
76
+ };
77
+ }
78
+ /** A (possibly signed) download URL for the object. */
79
+ async createSignedUrl(path, _expiresIn) {
80
+ try {
81
+ const res = await this.http.request(contractPath.file(path, 'url'));
82
+ return { data: { signedUrl: res.url }, error: null };
83
+ }
84
+ catch (err) {
85
+ return { data: null, error: toError(err) };
86
+ }
87
+ }
88
+ }
89
+ /** Supabase-compatible storage client: `client.storage.from(bucket)`. */
90
+ export class StorageClient {
91
+ constructor(http, baseUrl) {
92
+ this.http = http;
93
+ this.baseUrl = baseUrl;
94
+ }
95
+ from(bucket) {
96
+ return new StorageBucket(this.http, this.baseUrl, bucket);
29
97
  }
30
98
  }
31
99
  //# sourceMappingURL=storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,aAAa;IACxB,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,6DAA6D;IAC7D,MAAM,CAAC,IAAiB,EAAE,UAAyB,EAAE;QACnD,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI,YAAY,IAAI;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;;YAC9E,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAuB,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACtE,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAa,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,4EAA4E;IAC5E,OAAO,CAAC,MAAqB;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAkB,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7E,OAAO,GAAG,CAAC,GAAG,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;CACF"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}