@supacloud/lite 0.5.7 → 0.5.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.8](https://github.com/zuohuadong/supacloud/compare/supacloud-lite-v0.5.7...supacloud-lite-v0.5.8) (2026-08-05)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **lite:** actionable hint when storage upload is denied by RLS ([2de9601](https://github.com/zuohuadong/supacloud/commit/2de96016c802f43a588e22e4dacc91d4efdaa1f3))
9
+
3
10
  ## [0.5.7](https://github.com/zuohuadong/supacloud/compare/supacloud-lite-v0.5.6...supacloud-lite-v0.5.7) (2026-08-05)
4
11
 
5
12
 
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import { dirname as dirname5, join as join9, resolve as resolve4 } from "path";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@supacloud/lite",
11
- version: "0.5.7",
11
+ version: "0.5.8",
12
12
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite",
13
13
  type: "module",
14
14
  license: "Apache-2.0",
@@ -6002,6 +6002,29 @@ function invalidObjectKey(key) {
6002
6002
  function storageError(status, error, message) {
6003
6003
  return json3(status, { statusCode: String(status), error, message });
6004
6004
  }
6005
+ var RLS_POLICY_HINT = "Upload denied by storage.objects RLS. Create a policy in supabase/migrations, e.g. " + "`create policy \"objects insert\" on storage.objects for insert to authenticated with check (bucket_id = '<bucket>');`. " + "Without a policy, RLS blocks every write by default.";
6006
+
6007
+ class RlsPolicyError extends Error {
6008
+ cause;
6009
+ constructor(cause) {
6010
+ super("storage.objects row-level security policy denied the write");
6011
+ this.cause = cause;
6012
+ this.name = "RlsPolicyError";
6013
+ }
6014
+ }
6015
+ function rlsDeniedResponse() {
6016
+ return storageError(403, "Unauthorized", RLS_POLICY_HINT);
6017
+ }
6018
+ function isRlsDenied(error) {
6019
+ if (!error)
6020
+ return false;
6021
+ const pg = error;
6022
+ if (pg.code === "42501")
6023
+ return true;
6024
+ if (error instanceof Error && /row-level security|permission denied/i.test(error.message))
6025
+ return true;
6026
+ return false;
6027
+ }
6005
6028
  function json3(status, body) {
6006
6029
  return new Response(JSON.stringify(body), {
6007
6030
  status,
@@ -6287,6 +6310,8 @@ class StorageHandler {
6287
6310
  const id = await this.persistObject(ctx, bucketId, key, bytes, contentType, cacheControl, upsert);
6288
6311
  return json3(200, { Key: `${bucketId}/${key}`, Id: id });
6289
6312
  } catch (e) {
6313
+ if (e instanceof RlsPolicyError)
6314
+ return rlsDeniedResponse();
6290
6315
  const pg = e;
6291
6316
  if (pg.code === "23505") {
6292
6317
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6324,6 +6349,12 @@ class StorageHandler {
6324
6349
  values ($1, $2, $3, $4, $5::jsonb, $6) ${conflictClause} returning *`, [objectId, bucketId, key, ctx.claims?.sub ?? null, JSON.stringify(metadata), version]));
6325
6350
  inserted = result.rows[0];
6326
6351
  } catch (error) {
6352
+ if (isRlsDenied(error)) {
6353
+ try {
6354
+ await this.driver.delete(stagedKey);
6355
+ } catch {}
6356
+ throw new RlsPolicyError(error);
6357
+ }
6327
6358
  await this.discardStagedBytes(stagedKey, error);
6328
6359
  }
6329
6360
  if (!inserted)
@@ -6381,6 +6412,8 @@ class StorageHandler {
6381
6412
  try {
6382
6413
  await this.persistObject(ctx, bucketId, key, new Uint8Array, contentType, meta.cacheControl ?? "no-cache", upsert);
6383
6414
  } catch (error) {
6415
+ if (error instanceof RlsPolicyError)
6416
+ return rlsDeniedResponse();
6384
6417
  const pg = error;
6385
6418
  if (pg.code === "23505")
6386
6419
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6511,6 +6544,8 @@ class StorageHandler {
6511
6544
  await this.persistObject(upload.ctx, upload.bucketId, upload.key, data, upload.contentType, upload.cacheControl, upload.upsert);
6512
6545
  } catch (e) {
6513
6546
  this.tusUploads.delete(id);
6547
+ if (e instanceof RlsPolicyError)
6548
+ return rlsDeniedResponse();
6514
6549
  const pg = e;
6515
6550
  if (pg.code === "23505")
6516
6551
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6556,7 +6591,7 @@ class StorageHandler {
6556
6591
  if (pg.code === "23505")
6557
6592
  return storageError(409, "Duplicate", "The resource already exists");
6558
6593
  if (pg.code === "42501" || error instanceof Error && /row-level security|permission denied/i.test(error.message)) {
6559
- return storageError(403, "Unauthorized", "new row violates row-level security policy");
6594
+ return rlsDeniedResponse();
6560
6595
  }
6561
6596
  throw error;
6562
6597
  }
package/dist/index.js CHANGED
@@ -71,7 +71,7 @@ function randomToken(bytes = 32) {
71
71
  // package.json
72
72
  var package_default = {
73
73
  name: "@supacloud/lite",
74
- version: "0.5.7",
74
+ version: "0.5.8",
75
75
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite",
76
76
  type: "module",
77
77
  license: "Apache-2.0",
@@ -6007,6 +6007,29 @@ function invalidObjectKey(key) {
6007
6007
  function storageError(status, error, message) {
6008
6008
  return json3(status, { statusCode: String(status), error, message });
6009
6009
  }
6010
+ var RLS_POLICY_HINT = "Upload denied by storage.objects RLS. Create a policy in supabase/migrations, e.g. " + "`create policy \"objects insert\" on storage.objects for insert to authenticated with check (bucket_id = '<bucket>');`. " + "Without a policy, RLS blocks every write by default.";
6011
+
6012
+ class RlsPolicyError extends Error {
6013
+ cause;
6014
+ constructor(cause) {
6015
+ super("storage.objects row-level security policy denied the write");
6016
+ this.cause = cause;
6017
+ this.name = "RlsPolicyError";
6018
+ }
6019
+ }
6020
+ function rlsDeniedResponse() {
6021
+ return storageError(403, "Unauthorized", RLS_POLICY_HINT);
6022
+ }
6023
+ function isRlsDenied(error) {
6024
+ if (!error)
6025
+ return false;
6026
+ const pg = error;
6027
+ if (pg.code === "42501")
6028
+ return true;
6029
+ if (error instanceof Error && /row-level security|permission denied/i.test(error.message))
6030
+ return true;
6031
+ return false;
6032
+ }
6010
6033
  function json3(status, body) {
6011
6034
  return new Response(JSON.stringify(body), {
6012
6035
  status,
@@ -6292,6 +6315,8 @@ class StorageHandler {
6292
6315
  const id = await this.persistObject(ctx, bucketId, key, bytes, contentType, cacheControl, upsert);
6293
6316
  return json3(200, { Key: `${bucketId}/${key}`, Id: id });
6294
6317
  } catch (e) {
6318
+ if (e instanceof RlsPolicyError)
6319
+ return rlsDeniedResponse();
6295
6320
  const pg = e;
6296
6321
  if (pg.code === "23505") {
6297
6322
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6329,6 +6354,12 @@ class StorageHandler {
6329
6354
  values ($1, $2, $3, $4, $5::jsonb, $6) ${conflictClause} returning *`, [objectId, bucketId, key, ctx.claims?.sub ?? null, JSON.stringify(metadata), version]));
6330
6355
  inserted = result.rows[0];
6331
6356
  } catch (error) {
6357
+ if (isRlsDenied(error)) {
6358
+ try {
6359
+ await this.driver.delete(stagedKey);
6360
+ } catch {}
6361
+ throw new RlsPolicyError(error);
6362
+ }
6332
6363
  await this.discardStagedBytes(stagedKey, error);
6333
6364
  }
6334
6365
  if (!inserted)
@@ -6386,6 +6417,8 @@ class StorageHandler {
6386
6417
  try {
6387
6418
  await this.persistObject(ctx, bucketId, key, new Uint8Array, contentType, meta.cacheControl ?? "no-cache", upsert);
6388
6419
  } catch (error) {
6420
+ if (error instanceof RlsPolicyError)
6421
+ return rlsDeniedResponse();
6389
6422
  const pg = error;
6390
6423
  if (pg.code === "23505")
6391
6424
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6516,6 +6549,8 @@ class StorageHandler {
6516
6549
  await this.persistObject(upload.ctx, upload.bucketId, upload.key, data, upload.contentType, upload.cacheControl, upload.upsert);
6517
6550
  } catch (e) {
6518
6551
  this.tusUploads.delete(id);
6552
+ if (e instanceof RlsPolicyError)
6553
+ return rlsDeniedResponse();
6519
6554
  const pg = e;
6520
6555
  if (pg.code === "23505")
6521
6556
  return storageError(409, "Duplicate", "The resource already exists");
@@ -6561,7 +6596,7 @@ class StorageHandler {
6561
6596
  if (pg.code === "23505")
6562
6597
  return storageError(409, "Duplicate", "The resource already exists");
6563
6598
  if (pg.code === "42501" || error instanceof Error && /row-level security|permission denied/i.test(error.message)) {
6564
- return storageError(403, "Unauthorized", "new row violates row-level security policy");
6599
+ return rlsDeniedResponse();
6565
6600
  }
6566
6601
  throw error;
6567
6602
  }
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAQjD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE5E,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB,0GAA0G;IAC1G,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,uFAAuF;IACvF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAqGD,qEAAqE;AACrE,qBAAa,cAAc;IAKvB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAoB;gBAG9B,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa;IAG/B,4FAA4F;IACtF,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD,8GAA8G;IACxG,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YA6G9D,YAAY;IAgB1B,OAAO,CAAC,cAAc;YAOR,YAAY;YA2BZ,WAAW;YAKX,SAAS;YAMT,YAAY;YAqBZ,YAAY;YAYZ,WAAW;YAUX,UAAU;YAKV,MAAM;YAyDN,sBAAsB;IAgBpC,gFAAgF;YAClE,aAAa;YA2Cb,SAAS;IA6KvB,2EAA2E;YAC7D,SAAS;IA0CvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,sBAAsB;YAMhB,oBAAoB;YA2CpB,QAAQ;YASR,cAAc;YAYd,WAAW;YAoBX,aAAa;YAeb,SAAS;YAUT,UAAU;YAuEV,gBAAgB;YAUhB,kBAAkB;YASlB,eAAe;YAKf,iBAAiB;YAcjB,WAAW;YAsDX,UAAU;YAyBV,OAAO;YAmBP,QAAQ;YAiBR,eAAe;YAef,aAAa;YAab,kBAAkB;IAehC,OAAO,CAAC,aAAa;CAUtB;AAsHD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAqCnF"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAQjD,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE5E,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB,0GAA0G;IAC1G,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,uFAAuF;IACvF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAmID,qEAAqE;AACrE,qBAAa,cAAc;IAKvB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAoB;gBAG9B,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa;IAG/B,4FAA4F;IACtF,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD,8GAA8G;IACxG,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YA6G9D,YAAY;IAgB1B,OAAO,CAAC,cAAc;YAOR,YAAY;YA2BZ,WAAW;YAKX,SAAS;YAMT,YAAY;YAqBZ,YAAY;YAYZ,WAAW;YAUX,UAAU;YAKV,MAAM;YA0DN,sBAAsB;IAgBpC,gFAAgF;YAClE,aAAa;YAiDb,SAAS;IA8KvB,2EAA2E;YAC7D,SAAS;IA2CvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,sBAAsB;YAMhB,oBAAoB;YA2CpB,QAAQ;YASR,cAAc;YAYd,WAAW;YAoBX,aAAa;YAeb,SAAS;YAUT,UAAU;YAuEV,gBAAgB;YAUhB,kBAAkB;YASlB,eAAe;YAKf,iBAAiB;YAcjB,WAAW;YAsDX,UAAU;YAyBV,OAAO;YAmBP,QAAQ;YAiBR,eAAe;YAef,aAAa;YAab,kBAAkB;IAehC,OAAO,CAAC,aAAa;CAUtB;AAsHD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAqCnF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/lite",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Bun-native, single-project Supabase-compatible backend powered by PGlite",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",