+9
-26
@@ -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
|
||||
@@ -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,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",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
Reference in New Issue
Block a user