standalone@2.1.3: fix #163, fix #164

This commit is contained in:
tiago
2026-01-27 17:51:00 +00:00
parent bd3014dd9c
commit a53cedff86
5 changed files with 50 additions and 34 deletions
+9 -26
View File
@@ -1,34 +1,17 @@
# Contributing
# contributing
Thanks for your interest in contributing to Cap!
## development setup
## Development setup
- you need to have the latest version of [Bun](https://bun.com/) installed for building the widget, server, standalone, solver and docs, and Rust for WASM
**Notes**:
- zed is the recommended IDE for working on Cap, but VSCode also works well.
- You need to have the latest release version of [Bun](https://bun.com/) installed. For WASM, Rust is also required.
- for writing docs, make sure to place them inside of `docs/guide` and make sure to update the sidebar in `docs/.vitepress/config.mjs`.
- VSCode is the recommended IDE for working on Cap.
run `bun install` in each Bun package you want to work on to install dependencies.
- For writing docs, make sure to place them inside of `docs/guide` and make sure to update the sidebar in `docs/.vitepress/config.mjs`.
## tips
Run `bun install` in each Bun package you want to work on to install dependencies.
- we recommend [Biome](https://biomejs.dev/) for formatting and linting. please fix all errors and warnings before submitting a PR
## Tips
- Formatting uses [Biome](https://biomejs.dev/). Make sure there are no warnings or errors before submitting a PR.
- We prefer conventional commits, but they are not enforced. See [here](https://www.conventionalcommits.org/en/v1.0.0/) for reference.
- No AI-generated code please. AI autocomplete is fine, but not fully AI code. If you submit AI-generated code without making it clear, it may be rejected.
- Type files are auto-generated from JSDoc comments
## Code of Conduct
* Be respectful to others. Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
* Any spamming, trolling, flaming, or baiting is not welcome.
* Keep contributions constructive and in good faith.
- [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) are preferred
+5 -1
View File
@@ -58,4 +58,8 @@ If you would like to use a different database, you can set the `DB_URL` environm
We recommend keeping this to the default value, which is `sqlite://./.data/db.sqlite.`. However, using Postgres, MySQL, or any other database supported by Bun SQL might be possible, even though not officially supported or tested:
- `postgres://user:pass@localhost:5432/mydb`
- `mysql://user:password@localhost:3306/database`
- `mysql://user:password@localhost:3306/database`
## Error messages
Error messages are redacted by default and instead logged to the console. To disable error logging, set `DISABLE_ERROR_LOGGING=true`. To disable error message redaction, set `SHOW_ERRORS=true`.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cap-standalone",
"version": "2.1.2",
"version": "2.1.3",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "bun run --watch src/index.js",
+29
View File
@@ -60,6 +60,35 @@ new Elysia({
.onBeforeHandle(({ set }) => {
set.headers["X-Powered-By"] = "Cap Standalone";
})
.onError(({ error, code }) => {
if (["VALIDATION", "NOT_FOUND"].includes(code)) {
return {
success: false,
error: error.code || "Internal server error",
detail: error
}
}
const errorId = Bun.randomUUIDv7().split("-").pop();
console.error(`[${error.code || "ERR"} ${errorId}]`, JSON.stringify({
timestamp: new Date().toISOString(),
error,
env: {
bun: process.versions.bun,
platform: process.platform,
mem: process.memoryUsage()
}
}));
return {
success: false,
error: error.code || "Internal server error",
detail: {
troubleshooting: "http://capjs.js.org/guide/standalone/options.html#error-messages",
id: errorId
}
}
})
.use(staticPlugin())
.get("/", async ({ cookie }) => {
return file(
+6 -6
View File
@@ -38,7 +38,7 @@ export const siteverifyServer = new Elysia({
set.headers["X-RateLimit-Limit"] = "1";
set.headers["X-RateLimit-Remaining"] = "0";
set.headers["X-RateLimit-Reset"] = Math.ceil(unblockTime / 1000).toString();
return { error: "You were temporarily for using an invalid secret key. Please try again later." };
return { "success":false, error: "You were temporarily blocked for using an invalid secret key. Please try again later." };
}
const sitekey = params.siteKey;
@@ -46,14 +46,14 @@ export const siteverifyServer = new Elysia({
if (!sitekey || !secret || !response) {
set.status = 400;
return { error: "Missing required parameters" };
return { "success":false, error: "Missing required parameters" };
}
const [keyData] = await db`SELECT * FROM keys WHERE siteKey = ${sitekey}`;
const keyHash = keyData?.secretHash;
if (!keyHash || !secret) {
set.status = 404;
return { error: "Invalid site key or secret" };
return { "success":false, error: "Invalid site key or secret" };
}
const isValidSecret = await Bun.password.verify(secret, keyHash);
@@ -61,20 +61,20 @@ export const siteverifyServer = new Elysia({
if (!isValidSecret) {
blockedIPs.set(ip, now + 250);
set.status = 403;
return { error: "Invalid site key or secret" };
return { "success":false, error: "Invalid site key or secret" };
}
const [token] = await db`SELECT * FROM tokens WHERE siteKey = ${params.siteKey} AND token = ${response}`;
if (!token) {
set.status = 404;
return { error: "Token not found" };
return { "success":false, error: "Token not found" };
}
if (token.expires < Date.now()) {
await db`DELETE FROM tokens WHERE siteKey = ${params.siteKey} AND token = ${response}`;
set.status = 403;
return { error: "Token expired" };
return { "success":false,error: "Token expired" };
}
await db`DELETE FROM tokens WHERE siteKey = ${params.siteKey} AND token = ${response}`;