@ragable/sdk 0.6.24 → 0.7.6

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/index.mjs CHANGED
@@ -10,10 +10,6 @@ function bindFetch(custom) {
10
10
  };
11
11
  }
12
12
  var DEFAULT_RAGABLE_API_BASE = "https://ragable-341305259977.asia-southeast1.run.app/api";
13
- function resolveRagableApiBase(explicitBaseUrl) {
14
- const raw = typeof explicitBaseUrl === "string" && explicitBaseUrl.trim().length > 0 ? explicitBaseUrl.trim() : DEFAULT_RAGABLE_API_BASE.trim();
15
- return raw.replace(/\/+$/, "");
16
- }
17
13
  var RagableSdkError = class extends Error {
18
14
  constructor(message) {
19
15
  super(message);
@@ -142,7 +138,7 @@ var RagableRequestClient = class {
142
138
  __publicField(this, "fetchImpl");
143
139
  __publicField(this, "defaultHeaders");
144
140
  this.apiKey = options.apiKey;
145
- this.baseUrl = resolveRagableApiBase(options.baseUrl);
141
+ this.baseUrl = DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
146
142
  this.fetchImpl = bindFetch(options.fetch);
147
143
  this.defaultHeaders = options.headers;
148
144
  }
@@ -2166,7 +2162,7 @@ var RagableAuth = class {
2166
2162
  __publicField(this, "broadcast", null);
2167
2163
  __publicField(this, "visibilityHandler", null);
2168
2164
  __publicField(this, "initialized", false);
2169
- this.baseUrl = resolveRagableApiBase(config.baseUrl);
2165
+ this.baseUrl = DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
2170
2166
  this.authGroupId = config.authGroupId;
2171
2167
  this.fetchImpl = bindFetch(config.fetch);
2172
2168
  this.defaultHeaders = config.headers;
@@ -2535,8 +2531,8 @@ function decodeJwtExpiry(jwt) {
2535
2531
  }
2536
2532
 
2537
2533
  // src/browser.ts
2538
- function normalizeBrowserApiBase(explicitBaseUrl) {
2539
- return resolveRagableApiBase(explicitBaseUrl);
2534
+ function normalizeBrowserApiBase() {
2535
+ return DEFAULT_RAGABLE_API_BASE.replace(/\/+$/, "");
2540
2536
  }
2541
2537
  function effectiveDataAuth(options) {
2542
2538
  if (options.dataAuth) return options.dataAuth;
@@ -2827,7 +2823,6 @@ var RagableBrowserDatabaseClient = class {
2827
2823
  this.options = options;
2828
2824
  this.ragableAuth = ragableAuth;
2829
2825
  __publicField(this, "fetchImpl");
2830
- __publicField(this, "apiBase");
2831
2826
  __publicField(this, "_transport", null);
2832
2827
  __publicField(this, "collections");
2833
2828
  __publicField(this, "collection");
@@ -2851,7 +2846,7 @@ var RagableBrowserDatabaseClient = class {
2851
2846
  }
2852
2847
  const gid = requireAuthGroupId(opts);
2853
2848
  const token = await resolveDatabaseAuthBearer(opts, ragableAuth);
2854
- const apiBase = this.apiBase;
2849
+ const apiBase = normalizeBrowserApiBase();
2855
2850
  const qs = params.searchParams.toString();
2856
2851
  const url = `${apiBase}/auth-groups/${gid}/data/rest/${params.table}${qs ? `?${qs}` : ""}`;
2857
2852
  const headers = new Headers(opts.headers);
@@ -2966,7 +2961,6 @@ var RagableBrowserDatabaseClient = class {
2966
2961
  )
2967
2962
  });
2968
2963
  this.fetchImpl = bindFetch(options.fetch);
2969
- this.apiBase = resolveRagableApiBase(options.baseUrl);
2970
2964
  this.collections = new Proxy(
2971
2965
  {},
2972
2966
  {
@@ -2988,7 +2982,7 @@ var RagableBrowserDatabaseClient = class {
2988
2982
  this._transport = transport;
2989
2983
  }
2990
2984
  toUrl(path) {
2991
- return `${this.apiBase}${path.startsWith("/") ? path : `/${path}`}`;
2985
+ return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
2992
2986
  }
2993
2987
  async _requestCollection(method, path, body, databaseInstanceId) {
2994
2988
  const gid = requireAuthGroupId(this.options);
@@ -3079,7 +3073,7 @@ async function subscribeBrowserRealtime(options, ragableAuth, fetchImpl, params)
3079
3073
  headers.set("Authorization", `Bearer ${token}`);
3080
3074
  headers.set("Content-Type", "application/json");
3081
3075
  const response = await fetchImpl(
3082
- `${resolveRagableApiBase(options.baseUrl)}/auth-groups/${gid}/data/realtime/stream`,
3076
+ `${normalizeBrowserApiBase()}/auth-groups/${gid}/data/realtime/stream`,
3083
3077
  {
3084
3078
  method: "POST",
3085
3079
  headers,
@@ -3208,16 +3202,121 @@ async function subscribeBrowserRealtime(options, ragableAuth, fetchImpl, params)
3208
3202
  })();
3209
3203
  return subscription;
3210
3204
  }
3205
+ var BrowserStorageBucketClient = class {
3206
+ constructor(options, fetchImpl, bucketId) {
3207
+ this.options = options;
3208
+ this.fetchImpl = fetchImpl;
3209
+ this.bucketId = bucketId;
3210
+ }
3211
+ get authGroupId() {
3212
+ const id = this.options.authGroupId?.trim();
3213
+ if (!id) throw new RagableError("authGroupId is required for storage", 400, { code: "SDK_MISSING_AUTH_GROUP_ID" });
3214
+ return id;
3215
+ }
3216
+ base() {
3217
+ return `${normalizeBrowserApiBase()}/auth-groups/${this.authGroupId}/storage/buckets/${encodeURIComponent(this.bucketId)}`;
3218
+ }
3219
+ async bearerToken() {
3220
+ const staticKey = this.options.dataStaticKey?.trim() || (this.options.getDataStaticKey ? await this.options.getDataStaticKey() : null)?.trim() || null;
3221
+ if (staticKey) return staticKey;
3222
+ if (this.options.getAccessToken) {
3223
+ const tok = await this.options.getAccessToken();
3224
+ if (tok?.trim()) return tok.trim();
3225
+ }
3226
+ throw new RagableError("No auth token for storage. Provide dataStaticKey or getAccessToken.", 401, { code: "SDK_NO_ACCESS_TOKEN" });
3227
+ }
3228
+ async req(method, path, body) {
3229
+ const token = await this.bearerToken();
3230
+ const headers = new Headers(this.options.headers);
3231
+ headers.set("Authorization", `Bearer ${token}`);
3232
+ if (body !== void 0 && !(body instanceof FormData)) headers.set("Content-Type", "application/json");
3233
+ const res = await this.fetchImpl(`${this.base()}${path}`, {
3234
+ method,
3235
+ headers,
3236
+ body: body instanceof FormData ? body : body !== void 0 ? JSON.stringify(body) : void 0
3237
+ });
3238
+ const payload = await res.json().catch(() => ({}));
3239
+ if (!res.ok) throw new RagableError(payload?.error ?? res.statusText, res.status, payload);
3240
+ return payload;
3241
+ }
3242
+ list(params = {}) {
3243
+ const qs = new URLSearchParams();
3244
+ if (params.prefix) qs.set("prefix", params.prefix);
3245
+ if (params.delimiter) qs.set("delimiter", params.delimiter);
3246
+ if (params.maxResults != null) qs.set("maxResults", String(params.maxResults));
3247
+ if (params.pageToken) qs.set("pageToken", params.pageToken);
3248
+ const q = qs.toString();
3249
+ return this.req("GET", `/contents${q ? `?${q}` : ""}`);
3250
+ }
3251
+ async upload(params) {
3252
+ const token = await this.bearerToken();
3253
+ const headers = new Headers(this.options.headers);
3254
+ headers.set("Authorization", `Bearer ${token}`);
3255
+ const form = new FormData();
3256
+ const raw = params.file instanceof Blob ? params.file : new Blob([new Uint8Array(params.file instanceof ArrayBuffer ? params.file : params.file.buffer)], params.contentType ? { type: params.contentType } : {});
3257
+ const blob = raw;
3258
+ form.set("file", blob, params.fileName ?? "upload");
3259
+ form.set("objectPath", params.objectPath);
3260
+ if (params.cacheControl) form.set("cacheControl", params.cacheControl);
3261
+ const res = await this.fetchImpl(`${this.base()}/upload`, { method: "POST", headers, body: form });
3262
+ const payload = await res.json().catch(() => ({}));
3263
+ if (!res.ok) throw new RagableError(payload?.error ?? res.statusText, res.status, payload);
3264
+ return payload;
3265
+ }
3266
+ download(params) {
3267
+ const qs = new URLSearchParams({ objectPath: params.objectPath });
3268
+ if (params.asText != null) qs.set("asText", String(params.asText));
3269
+ if (params.maxTextBytes != null) qs.set("maxTextBytes", String(params.maxTextBytes));
3270
+ return this.req("GET", `/objects/download?${qs}`);
3271
+ }
3272
+ delete(objectPath) {
3273
+ return this.req("DELETE", "/objects", { objectPath });
3274
+ }
3275
+ bulkDelete(objectPaths) {
3276
+ return this.req("POST", "/objects/delete-bulk", { objectPaths });
3277
+ }
3278
+ getSignedUploadUrl(params) {
3279
+ return this.req("POST", "/signed-upload-url", params);
3280
+ }
3281
+ getSignedDownloadUrl(params) {
3282
+ const qs = new URLSearchParams({ objectPath: params.objectPath });
3283
+ if (params.expiresInSeconds != null) qs.set("expiresInSeconds", String(params.expiresInSeconds));
3284
+ return this.req("GET", `/signed-download-url?${qs}`);
3285
+ }
3286
+ copy(params) {
3287
+ return this.req("POST", "/objects/copy", params);
3288
+ }
3289
+ move(params) {
3290
+ return this.req("POST", "/objects/move", params);
3291
+ }
3292
+ createFolder(folderPath) {
3293
+ return this.req("POST", "/folders", { folderPath });
3294
+ }
3295
+ deleteFolder(folderPath) {
3296
+ return this.req("DELETE", "/folders", { folderPath });
3297
+ }
3298
+ getMetadata(objectPath) {
3299
+ const qs = new URLSearchParams({ objectPath });
3300
+ return this.req("GET", `/objects/metadata?${qs}`);
3301
+ }
3302
+ };
3303
+ var RagableBrowserStorageClient = class {
3304
+ constructor(options, fetchImpl) {
3305
+ this.options = options;
3306
+ this.fetchImpl = fetchImpl;
3307
+ }
3308
+ from(bucketId) {
3309
+ return new BrowserStorageBucketClient(this.options, this.fetchImpl, bucketId);
3310
+ }
3311
+ };
3211
3312
  var RagableBrowserAgentsClient = class {
3212
3313
  constructor(options) {
3213
3314
  this.options = options;
3214
3315
  __publicField(this, "fetchImpl");
3215
- __publicField(this, "apiBase");
3216
3316
  this.fetchImpl = bindFetch(options.fetch);
3217
- this.apiBase = resolveRagableApiBase(options.baseUrl);
3218
3317
  }
3219
3318
  toUrl(path) {
3220
- return `${this.apiBase}${path.startsWith("/") ? path : `/${path}`}`;
3319
+ return `${normalizeBrowserApiBase()}${path.startsWith("/") ? path : `/${path}`}`;
3221
3320
  }
3222
3321
  requireWebsiteId() {
3223
3322
  const websiteId = this.options.websiteId?.trim();
@@ -3403,6 +3502,7 @@ var RagableBrowser = class {
3403
3502
  __publicField(this, "auth");
3404
3503
  __publicField(this, "database");
3405
3504
  __publicField(this, "db");
3505
+ __publicField(this, "storage");
3406
3506
  __publicField(this, "transport");
3407
3507
  __publicField(this, "_ragableAuth");
3408
3508
  /** Delegates to `database.from()`. Kept for back-compat — prefer `database.from()`. */
@@ -3417,7 +3517,6 @@ var RagableBrowser = class {
3417
3517
  if (options.authGroupId) {
3418
3518
  this._ragableAuth = new RagableAuth({
3419
3519
  authGroupId: options.authGroupId,
3420
- baseUrl: options.baseUrl,
3421
3520
  fetch: options.fetch,
3422
3521
  headers: options.headers,
3423
3522
  auth: options.auth
@@ -3441,6 +3540,7 @@ var RagableBrowser = class {
3441
3540
  );
3442
3541
  this.database._setTransport(this.transport);
3443
3542
  this.db = this.database;
3543
+ this.storage = new RagableBrowserStorageClient(options, bindFetch(options.fetch));
3444
3544
  }
3445
3545
  destroy() {
3446
3546
  this._ragableAuth?.destroy();
@@ -3493,15 +3593,171 @@ function createRagPipeline(client, options) {
3493
3593
  };
3494
3594
  }
3495
3595
 
3596
+ // src/storage.ts
3597
+ function normalizeUploadFile2(file, contentType) {
3598
+ if (file instanceof Blob) return file;
3599
+ const u8 = file instanceof ArrayBuffer ? new Uint8Array(file) : new Uint8Array(file);
3600
+ return new Blob([u8.buffer], contentType ? { type: contentType } : {});
3601
+ }
3602
+ var StorageClient = class {
3603
+ constructor(client) {
3604
+ this.client = client;
3605
+ /**
3606
+ * Bucket-level CRUD — list, create and delete buckets for this organisation.
3607
+ */
3608
+ __publicField(this, "buckets");
3609
+ this.buckets = {
3610
+ list: async (params) => {
3611
+ const qs = new URLSearchParams();
3612
+ if (params?.q) qs.set("q", params.q);
3613
+ if (params?.status) qs.set("status", params.status);
3614
+ if (params?.sort) qs.set("sort", params.sort);
3615
+ const query = qs.toString();
3616
+ return this.client.request(
3617
+ `/v1/storage/buckets${query ? `?${query}` : ""}`
3618
+ );
3619
+ },
3620
+ create: async (name) => {
3621
+ return this.client.request("/v1/storage/buckets", {
3622
+ method: "POST",
3623
+ body: { name }
3624
+ });
3625
+ },
3626
+ delete: async (bucketId) => {
3627
+ return this.client.request(
3628
+ `/v1/storage/buckets/${encodeURIComponent(bucketId)}`,
3629
+ { method: "DELETE" }
3630
+ );
3631
+ }
3632
+ };
3633
+ }
3634
+ /**
3635
+ * Returns a {@link StorageBucketClient} scoped to the given bucket ID.
3636
+ *
3637
+ * All object operations (upload, download, list, copy, move, signed URLs, …)
3638
+ * are performed through the returned client.
3639
+ *
3640
+ * @param bucketId The Ragable bucket ID obtained from `buckets.list()` or `buckets.create()`.
3641
+ */
3642
+ from(bucketId) {
3643
+ const { client } = this;
3644
+ const base = `/v1/storage/buckets/${encodeURIComponent(bucketId)}`;
3645
+ return {
3646
+ list: async (params) => {
3647
+ const qs = new URLSearchParams();
3648
+ if (params?.prefix) qs.set("prefix", params.prefix);
3649
+ if (params?.delimiter) qs.set("delimiter", params.delimiter);
3650
+ if (params?.maxResults != null)
3651
+ qs.set("maxResults", String(params.maxResults));
3652
+ if (params?.pageToken) qs.set("pageToken", params.pageToken);
3653
+ const query = qs.toString();
3654
+ return client.request(
3655
+ `${base}/contents${query ? `?${query}` : ""}`
3656
+ );
3657
+ },
3658
+ createFolder: async (folderPath) => {
3659
+ return client.request(
3660
+ `${base}/folders`,
3661
+ { method: "POST", body: { folderPath } }
3662
+ );
3663
+ },
3664
+ deleteFolder: async (folderPath) => {
3665
+ return client.request(
3666
+ `${base}/folders`,
3667
+ { method: "DELETE", body: { folderPath } }
3668
+ );
3669
+ },
3670
+ upload: async (params) => {
3671
+ const formData = new FormData();
3672
+ const blob = normalizeUploadFile2(params.file, params.contentType);
3673
+ const fileName = params.fileName ?? "upload";
3674
+ formData.set("file", blob, fileName);
3675
+ formData.set("objectPath", params.objectPath);
3676
+ if (params.cacheControl) {
3677
+ formData.set("cacheControl", params.cacheControl);
3678
+ }
3679
+ return client.request(`${base}/upload`, {
3680
+ method: "POST",
3681
+ body: formData
3682
+ });
3683
+ },
3684
+ delete: async (objectPath) => {
3685
+ return client.request(
3686
+ `${base}/objects`,
3687
+ { method: "DELETE", body: { objectPath } }
3688
+ );
3689
+ },
3690
+ bulkDelete: async (objectPaths) => {
3691
+ return client.request(
3692
+ `${base}/objects/delete-bulk`,
3693
+ { method: "POST", body: { objectPaths } }
3694
+ );
3695
+ },
3696
+ getMetadata: async (objectPath) => {
3697
+ const qs = new URLSearchParams({ objectPath });
3698
+ return client.request(
3699
+ `${base}/objects/metadata?${qs}`
3700
+ );
3701
+ },
3702
+ updateMetadata: async (params) => {
3703
+ return client.request(
3704
+ `${base}/objects/metadata`,
3705
+ { method: "PATCH", body: params }
3706
+ );
3707
+ },
3708
+ download: async (params) => {
3709
+ const qs = new URLSearchParams({ objectPath: params.objectPath });
3710
+ if (params.asText != null) qs.set("asText", String(params.asText));
3711
+ if (params.maxTextBytes != null)
3712
+ qs.set("maxTextBytes", String(params.maxTextBytes));
3713
+ return client.request(
3714
+ `${base}/objects/download?${qs}`
3715
+ );
3716
+ },
3717
+ copy: async (params) => {
3718
+ return client.request(`${base}/objects/copy`, { method: "POST", body: params });
3719
+ },
3720
+ move: async (params) => {
3721
+ return client.request(`${base}/objects/move`, { method: "POST", body: params });
3722
+ },
3723
+ getSignedUploadUrl: async (params) => {
3724
+ return client.request(
3725
+ `${base}/signed-upload-url`,
3726
+ { method: "POST", body: params }
3727
+ );
3728
+ },
3729
+ getSignedDownloadUrl: async (params) => {
3730
+ const qs = new URLSearchParams({ objectPath: params.objectPath });
3731
+ if (params.expiresInSeconds != null)
3732
+ qs.set("expiresInSeconds", String(params.expiresInSeconds));
3733
+ return client.request(
3734
+ `${base}/signed-download-url?${qs}`
3735
+ );
3736
+ },
3737
+ getSettings: async () => {
3738
+ return client.request(`${base}/settings`);
3739
+ },
3740
+ updateSettings: async (params) => {
3741
+ return client.request(`${base}/settings`, {
3742
+ method: "PATCH",
3743
+ body: params
3744
+ });
3745
+ }
3746
+ };
3747
+ }
3748
+ };
3749
+
3496
3750
  // src/index.ts
3497
3751
  var Ragable = class {
3498
3752
  constructor(options) {
3499
3753
  __publicField(this, "shift");
3500
3754
  __publicField(this, "agents");
3755
+ __publicField(this, "storage");
3501
3756
  __publicField(this, "infrastructure");
3502
3757
  const client = new RagableRequestClient(options);
3503
3758
  this.shift = new ShiftClient(client);
3504
3759
  this.agents = new AgentsClient(client);
3760
+ this.storage = new StorageClient(client);
3505
3761
  this.infrastructure = {
3506
3762
  shift: this.shift
3507
3763
  };
@@ -3564,6 +3820,7 @@ export {
3564
3820
  RagableTimeoutError,
3565
3821
  SessionStorageAdapter,
3566
3822
  ShiftClient,
3823
+ StorageClient,
3567
3824
  Transport,
3568
3825
  asPostgrestResponse,
3569
3826
  assertPostgrestSuccess,
@@ -3592,7 +3849,6 @@ export {
3592
3849
  parseSseDataLine,
3593
3850
  parseTransportResponse,
3594
3851
  readSseStream,
3595
- resolveRagableApiBase,
3596
3852
  runAgentChatStream,
3597
3853
  runAgentChatStreamForUi,
3598
3854
  runAgentChatStreamLenient,