@supacloud/lite 0.28.0 → 0.28.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/CHANGELOG.md +7 -0
- package/RELEASING.md +9 -0
- package/dist/cli.js +26 -19
- package/dist/index.js +26 -19
- package/dist/runtime/rest/handler.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.28.1](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.28.0...supacloud-lite-v0.28.1) (2026-10-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **lite:** roll back rejected singular REST writes ([#1925](https://github.com/vibeunion/supacloud/issues/1925)) ([0af235d](https://github.com/vibeunion/supacloud/commit/0af235d55a3619ffd150e4b16751a27a32d1f2e0))
|
|
9
|
+
|
|
3
10
|
## [0.28.0](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.27.1...supacloud-lite-v0.28.0) (2026-10-14)
|
|
4
11
|
|
|
5
12
|
|
package/RELEASING.md
CHANGED
|
@@ -30,6 +30,15 @@ bun run build:standalone:host
|
|
|
30
30
|
bun run test:standalone
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
针对本地 Auth 的聚焦回归,只构建 host 产物并运行单个脚本的 Auth 入口:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun run build:standalone:host
|
|
37
|
+
bun run scripts/standalone-smoke.ts --auth-only
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
该入口在不含 Bun/Node/npm 的子进程 `PATH` 下启动二进制,通过真实 HTTP 和 `supabase-js` 验证注册、密码登录、刷新轮换、退出撤销,以及进程重启后的会话恢复、刷新与撤销保留。成功标记为 `standalone-auth-smoke-ok`。可用 `SUPACLOUD_LITE_STANDALONE_BINARY` 指定待验收产物。它不执行 Functions、扩展、升级、快照或恢复,不能替代完整发布验收;默认完整 smoke 也会在升级和快照恢复阶段验证同一 Auth 状态。
|
|
41
|
+
|
|
33
42
|
Release workflow 为 Linux x64 baseline/arm64、macOS x64/arm64 和 Windows x64 baseline 构建独立产物。Linux x64 产物必须在发布 runner 上完成真实黑盒测试;其他交叉编译产物在具备对应原生 runner 前只视为已构建,不能替代平台验收。
|
|
34
43
|
|
|
35
44
|
Lite release 会同时上传 `SHA256SUMS`、项目自身的 `SUPACLOUD-LITE-APACHE-2.0.txt`、`NOTICE`、`THIRD_PARTY_NOTICES.md` 和 `LICENSES/*.txt`,并为发布资产生成 provenance。正式对外分发 macOS 或 Windows 产物前,还应按项目发布策略完成代码签名;构建成功不代表已经签名或公证。
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { dirname as dirname8, join as join10, resolve as resolve6 } from "path";
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "@supacloud/lite",
|
|
11
|
-
version: "0.28.
|
|
11
|
+
version: "0.28.1",
|
|
12
12
|
description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
13
13
|
type: "module",
|
|
14
14
|
license: "Apache-2.0",
|
|
@@ -8620,7 +8620,10 @@ class RestHandler {
|
|
|
8620
8620
|
const { rows, affected } = await this.db.withContext(ctx, async (query) => {
|
|
8621
8621
|
const res = await query(built.sql, built.params);
|
|
8622
8622
|
if (opts.queryReturning) {
|
|
8623
|
-
|
|
8623
|
+
const rows = res.rows[0].body;
|
|
8624
|
+
if (opts.wantsObject && !opts.wantsCsv)
|
|
8625
|
+
assertObjectCardinality(rows);
|
|
8626
|
+
return { rows, affected: null };
|
|
8624
8627
|
}
|
|
8625
8628
|
return { rows: null, affected: res.affectedRows ?? 0 };
|
|
8626
8629
|
});
|
|
@@ -8652,14 +8655,7 @@ class RestHandler {
|
|
|
8652
8655
|
return new Response(opts.head ? null : rowsToCsv(rows), { status: opts.status, headers });
|
|
8653
8656
|
}
|
|
8654
8657
|
if (opts.wantsObject) {
|
|
8655
|
-
|
|
8656
|
-
return jsonResponse(406, {
|
|
8657
|
-
code: "PGRST116",
|
|
8658
|
-
message: "JSON object requested, multiple (or no) rows returned",
|
|
8659
|
-
details: `The result contains ${rows.length} rows`,
|
|
8660
|
-
hint: null
|
|
8661
|
-
});
|
|
8662
|
-
}
|
|
8658
|
+
assertObjectCardinality(rows);
|
|
8663
8659
|
headers["content-type"] = `${OBJECT_MEDIA}; charset=utf-8`;
|
|
8664
8660
|
return new Response(opts.head ? null : JSON.stringify(rows[0]), {
|
|
8665
8661
|
status: opts.status,
|
|
@@ -8756,17 +8752,18 @@ class RestHandler {
|
|
|
8756
8752
|
const where = conds.length > 0 ? ` where ${conds.join(" and ")}` : "";
|
|
8757
8753
|
const order = builder.renderOrder([], alias);
|
|
8758
8754
|
const limitOffset = builder.renderLimitOffset("");
|
|
8759
|
-
const
|
|
8760
|
-
const
|
|
8761
|
-
const
|
|
8755
|
+
const wantsCount = prefer.count !== undefined;
|
|
8756
|
+
const resultSource = wantsCount ? quoteIdent("_rpc_result") : call;
|
|
8757
|
+
const core = `select ${exprs.join(", ")} from ${resultSource} as ${quoteIdent(alias)}${where}${order}${limitOffset}`;
|
|
8758
|
+
const bodySql = `select coalesce(json_agg(row_to_json(_r)), '[]'::json) as body from (${core}) _r`;
|
|
8759
|
+
const sql = wantsCount ? `with ${quoteIdent("_rpc_result")} as (select * from ${call}) select (${bodySql}) as body, (select count(*)::int from ${resultSource} as ${quoteIdent(alias)}${where}) as count` : bodySql;
|
|
8762
8760
|
const { rows, count } = await this.db.withContext(ctx, async (query) => {
|
|
8763
8761
|
const res = await query(sql, []);
|
|
8764
|
-
|
|
8765
|
-
if (
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
}
|
|
8769
|
-
return { rows: res.rows[0].body, count };
|
|
8762
|
+
const rows = res.rows[0].body;
|
|
8763
|
+
if (wantsObject && !wantsCsv)
|
|
8764
|
+
assertObjectCardinality(rows);
|
|
8765
|
+
const count = wantsCount ? res.rows[0].count : null;
|
|
8766
|
+
return { rows, count };
|
|
8770
8767
|
});
|
|
8771
8768
|
return this.dataResponse(rows, {
|
|
8772
8769
|
status: 200,
|
|
@@ -8778,6 +8775,16 @@ class RestHandler {
|
|
|
8778
8775
|
});
|
|
8779
8776
|
}
|
|
8780
8777
|
}
|
|
8778
|
+
function assertObjectCardinality(rows) {
|
|
8779
|
+
if (rows.length !== 1) {
|
|
8780
|
+
throw new ApiError(406, {
|
|
8781
|
+
code: "PGRST116",
|
|
8782
|
+
message: "JSON object requested, multiple (or no) rows returned",
|
|
8783
|
+
details: `The result contains ${rows.length} rows`,
|
|
8784
|
+
hint: null
|
|
8785
|
+
});
|
|
8786
|
+
}
|
|
8787
|
+
}
|
|
8781
8788
|
function pickOverload(fns, providedNames) {
|
|
8782
8789
|
const provided = new Set(providedNames);
|
|
8783
8790
|
let best = null;
|
package/dist/index.js
CHANGED
|
@@ -88,7 +88,7 @@ function randomToken(bytes = 32) {
|
|
|
88
88
|
// package.json
|
|
89
89
|
var package_default = {
|
|
90
90
|
name: "@supacloud/lite",
|
|
91
|
-
version: "0.28.
|
|
91
|
+
version: "0.28.1",
|
|
92
92
|
description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
93
93
|
type: "module",
|
|
94
94
|
license: "Apache-2.0",
|
|
@@ -8614,7 +8614,10 @@ class RestHandler {
|
|
|
8614
8614
|
const { rows, affected } = await this.db.withContext(ctx, async (query) => {
|
|
8615
8615
|
const res = await query(built.sql, built.params);
|
|
8616
8616
|
if (opts.queryReturning) {
|
|
8617
|
-
|
|
8617
|
+
const rows = res.rows[0].body;
|
|
8618
|
+
if (opts.wantsObject && !opts.wantsCsv)
|
|
8619
|
+
assertObjectCardinality(rows);
|
|
8620
|
+
return { rows, affected: null };
|
|
8618
8621
|
}
|
|
8619
8622
|
return { rows: null, affected: res.affectedRows ?? 0 };
|
|
8620
8623
|
});
|
|
@@ -8646,14 +8649,7 @@ class RestHandler {
|
|
|
8646
8649
|
return new Response(opts.head ? null : rowsToCsv(rows), { status: opts.status, headers });
|
|
8647
8650
|
}
|
|
8648
8651
|
if (opts.wantsObject) {
|
|
8649
|
-
|
|
8650
|
-
return jsonResponse(406, {
|
|
8651
|
-
code: "PGRST116",
|
|
8652
|
-
message: "JSON object requested, multiple (or no) rows returned",
|
|
8653
|
-
details: `The result contains ${rows.length} rows`,
|
|
8654
|
-
hint: null
|
|
8655
|
-
});
|
|
8656
|
-
}
|
|
8652
|
+
assertObjectCardinality(rows);
|
|
8657
8653
|
headers["content-type"] = `${OBJECT_MEDIA}; charset=utf-8`;
|
|
8658
8654
|
return new Response(opts.head ? null : JSON.stringify(rows[0]), {
|
|
8659
8655
|
status: opts.status,
|
|
@@ -8750,17 +8746,18 @@ class RestHandler {
|
|
|
8750
8746
|
const where = conds.length > 0 ? ` where ${conds.join(" and ")}` : "";
|
|
8751
8747
|
const order = builder.renderOrder([], alias);
|
|
8752
8748
|
const limitOffset = builder.renderLimitOffset("");
|
|
8753
|
-
const
|
|
8754
|
-
const
|
|
8755
|
-
const
|
|
8749
|
+
const wantsCount = prefer.count !== undefined;
|
|
8750
|
+
const resultSource = wantsCount ? quoteIdent("_rpc_result") : call;
|
|
8751
|
+
const core = `select ${exprs.join(", ")} from ${resultSource} as ${quoteIdent(alias)}${where}${order}${limitOffset}`;
|
|
8752
|
+
const bodySql = `select coalesce(json_agg(row_to_json(_r)), '[]'::json) as body from (${core}) _r`;
|
|
8753
|
+
const sql = wantsCount ? `with ${quoteIdent("_rpc_result")} as (select * from ${call}) select (${bodySql}) as body, (select count(*)::int from ${resultSource} as ${quoteIdent(alias)}${where}) as count` : bodySql;
|
|
8756
8754
|
const { rows, count } = await this.db.withContext(ctx, async (query) => {
|
|
8757
8755
|
const res = await query(sql, []);
|
|
8758
|
-
|
|
8759
|
-
if (
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
}
|
|
8763
|
-
return { rows: res.rows[0].body, count };
|
|
8756
|
+
const rows = res.rows[0].body;
|
|
8757
|
+
if (wantsObject && !wantsCsv)
|
|
8758
|
+
assertObjectCardinality(rows);
|
|
8759
|
+
const count = wantsCount ? res.rows[0].count : null;
|
|
8760
|
+
return { rows, count };
|
|
8764
8761
|
});
|
|
8765
8762
|
return this.dataResponse(rows, {
|
|
8766
8763
|
status: 200,
|
|
@@ -8772,6 +8769,16 @@ class RestHandler {
|
|
|
8772
8769
|
});
|
|
8773
8770
|
}
|
|
8774
8771
|
}
|
|
8772
|
+
function assertObjectCardinality(rows) {
|
|
8773
|
+
if (rows.length !== 1) {
|
|
8774
|
+
throw new ApiError(406, {
|
|
8775
|
+
code: "PGRST116",
|
|
8776
|
+
message: "JSON object requested, multiple (or no) rows returned",
|
|
8777
|
+
details: `The result contains ${rows.length} rows`,
|
|
8778
|
+
hint: null
|
|
8779
|
+
});
|
|
8780
|
+
}
|
|
8781
|
+
}
|
|
8775
8782
|
function pickOverload(fns, providedNames) {
|
|
8776
8783
|
const provided = new Set(providedNames);
|
|
8777
8784
|
let best = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/rest/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAA4B,KAAK,QAAQ,EAAqB,MAAM,mBAAmB,CAAA;AAC9F,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAyF3D,oFAAoF;AACpF,qBAAa,WAAW;IAOpB,OAAO,CAAC,EAAE;IANZ,8FAA8F;IAC9F,OAAO,CAAC,cAAc,CAAU;IAChC,8EAA8E;IAC9E,OAAO,CAAC,OAAO,CAAC,CAAQ;gBAGd,EAAE,EAAE,QAAQ,EACpB,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAMxD,4FAA4F;IACtF,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YAmC9D,WAAW;YAsHX,WAAW;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/rest/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAA4B,KAAK,QAAQ,EAAqB,MAAM,mBAAmB,CAAA;AAC9F,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAyF3D,oFAAoF;AACpF,qBAAa,WAAW;IAOpB,OAAO,CAAC,EAAE;IANZ,8FAA8F;IAC9F,OAAO,CAAC,cAAc,CAAU;IAChC,8EAA8E;IAC9E,OAAO,CAAC,OAAO,CAAC,CAAQ;gBAGd,EAAE,EAAE,QAAQ,EACpB,IAAI,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAMxD,4FAA4F;IACtF,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YAmC9D,WAAW;YAsHX,WAAW;IAgDzB,OAAO,CAAC,YAAY;YAqCN,SAAS;YAqET,MAAM;CAqFrB"}
|