checkpoints/express: initial release!
This commit is contained in:
+1
-1
@@ -9,4 +9,4 @@
|
||||
- Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or an employee of Oven immediately. Whether you’re a regular contributor or a newcomer, we care about making this community a safe place for you and we’ve got your back.
|
||||
- Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
|
||||
|
||||
This code of conduct is adapted from the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct).
|
||||
This code of conduct is mostly stolen from the [Bun Code of Conduct](https://github.com/oven-sh/bun/blob/main/CODE_OF_CONDUCT.md).
|
||||
@@ -38,6 +38,7 @@ There are also some other helpful packages:
|
||||
We also provide a middleware for a Cloudflare browser checkpoint-like experience:
|
||||
|
||||
- [@cap.js/checkpoint-hono](https://capjs.js.org/guide/middleware/hono.html)
|
||||
- [@cap.js/checkpoint-express](https://capjs.js.org/guide/middleware/express.html)
|
||||
- [@cap.js/middleware-elysia](https://capjs.js.org/guide/middleware/elysia.html)
|
||||
- more coming soon!
|
||||
|
||||
@@ -116,4 +117,4 @@ Cap is licensed under the Apache License 2.0.
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "@cap.js/checkpoint-hono",
|
||||
"dependencies": {
|
||||
"@cap.js/server": "^1.0.15",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@cap.js/server": ["@cap.js/server@1.0.15", "", { "dependencies": { "@types/node": "^22.14.1", "typescript": "^5.8.3" } }, "sha512-mcDbHAL4ar5O4gnDE+62ZPeXhLXxd1KKHzJCsZfn81HY8Fgo5ousxYCnzhsLfki5sH6sO6jpNtS4MZXlKDq+fA=="],
|
||||
|
||||
"@types/node": ["@types/node@22.15.28", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-I0okKVDmyKR281I0UIFV7EWAWRnR0gkuSKob5wVcByyyhr7Px/slhkQapcYX4u00ekzNWaS1gznKZnuzxwo4pw=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Verifying you are a human…</title>
|
||||
<meta name="title" content="Verifying you are a human…" />
|
||||
<meta
|
||||
name="description"
|
||||
content="A preview of this link is unavailable while a browser check is in progress."
|
||||
/>
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Verifying you are a human…" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A preview of this link is unavailable while a browser check is in progress."
|
||||
/>
|
||||
|
||||
<meta property="twitter:title" content="Verifying you are a human…" />
|
||||
<meta
|
||||
property="twitter:description"
|
||||
content="A preview of this link is unavailable while a browser check is in progress."
|
||||
/>
|
||||
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
max-width: 690px;
|
||||
margin: 3em auto;
|
||||
padding: 18px;
|
||||
font-family: system-ui;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 26px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
h2 {
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
margin-top: 7px;
|
||||
margin-bottom: 1.5em;
|
||||
color: #171717;
|
||||
}
|
||||
cap-widget {
|
||||
margin-bottom: 4em;
|
||||
}
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #dddddd8f;
|
||||
margin: 2em 0;
|
||||
}
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
p {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
margin-top: 10px;
|
||||
color: #171717;
|
||||
}
|
||||
footer {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
footer .credit {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
color: #171717;
|
||||
}
|
||||
footer .credit:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
footer .credit img {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
footer .date {
|
||||
font-size: 15px;
|
||||
color: #888;
|
||||
margin: 0px;
|
||||
margin-left: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Checking your browser...</h1>
|
||||
<script>
|
||||
document.querySelector("h1").innerText = location.host;
|
||||
</script>
|
||||
<h2>Verifying you are a human before proceeding...</h2>
|
||||
|
||||
<cap-widget id="cap" data-cap-api-endpoint="/__cap_clearance/"></cap-widget>
|
||||
|
||||
<noscript>
|
||||
<style>
|
||||
.info {
|
||||
display: none;
|
||||
}
|
||||
a {
|
||||
color: #0a91e7;
|
||||
}
|
||||
h3 {
|
||||
line-height: 1.3;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
<h3>
|
||||
JavaScript is disabled and we were unable to verify you. To access this
|
||||
page, please
|
||||
<a
|
||||
href="https://www.whatismybrowser.com/guides/how-to-enable-javascript/auto"
|
||||
target="_blank"
|
||||
rel="nofollow noopener"
|
||||
>
|
||||
enable JavaScript
|
||||
</a>
|
||||
</h3>
|
||||
<hr />
|
||||
</noscript>
|
||||
|
||||
<div class="info">
|
||||
<hr />
|
||||
|
||||
<h3>Why am I seeing this page?</h3>
|
||||
<p>
|
||||
To keep our site secure, we need to confirm you're a human and not a
|
||||
robot. This quick check helps stop spam and abuse.
|
||||
</p>
|
||||
|
||||
<h3>What should I do?</h3>
|
||||
<p>
|
||||
No action is required on your end. Once verified, you'll continue to
|
||||
your destination. If you're stuck, try refreshing the page or checking
|
||||
your connection.
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<a
|
||||
href="https://capjs.js.org/"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="credit"
|
||||
>
|
||||
<img
|
||||
src="data:image/webp;base64,UklGRnwEAABXRUJQVlA4WAoAAAAQAAAATwAATwAAQUxQSDcCAAABkAXZtmk7+73Ytm3btm3btm3btvNn206ebfsdzvCcvfe6f6lURcQEsH/Ui3Sb2quAA0k7zU2D9qFb9rwF8ufOms6Z3hgVv0d+dHF3+/b6ztn1oxsXSkUoa+svsB/vfnFS5dQ0Ss99FgfOIRd7ZpWv7DpviFQe9s8oV87ZnhCtXK8jU9P7JiQMGJ9GlrTTQiCnsj2rHNm2q5D2cDYZchyHzAcyist0BFIbK1OISrnGlAvx/UUNToTsLuXElHOF/MfSiEh1CAQTuotoGUMBD7PzS30OJPUR/OpG0sCzHNzWgqg+hFeON1RwJxOnxnFkkjpymga6p1NycT5BKLgql2zPCGEpl1JelN7m4tEggpLSjUfnBEo47sxhkEIqem/XAk52RmukAOX7gR75rY3TiQFQv+1qn9PCFIMegKQ3q+ql/9M00yEAiLoxprBjAcxvs7I6FsC8VJhNNki5HP9sWgLOZR6rE3JfVNyp4Jh7CZaShw5XyYRsLM1+z9z2SIAFnOmbbC86VoqEU7Wd2F9TlJ/zJP4vR9rH2wi7Obtus4MBwoxH3dMw61la7ficBMCvdd1wC7rftSnV0jPGnCsufqcKcZmSg3HM22bBtlUNnIq7/ynqzZ7+pdOwv+fucyGEm//akkxkxntAxOvDY2plZ3ZTV5n7MJaH75bKTPDMgLXVszkxvpkbLb4TqFmKvD+rnBMTnaGMMxOZvly3hcfuvnPxcHl7Y8+YmpmYQ3RKlz1foXzZ0rD/AwMAVlA4IB4CAABwDwCdASpQAFAAPok6lUelI6IhL1auwKARCWgAyJAhz7eq/ihjJ3OI5P5V3p3mJ/ar10vRB/298A5832YAmiLa0mutah4B6eOgBjpWeAPuDnTJNdrbbJGDv05E/kTVtFErBAMEp9Sdw2xY7Adta5Ru6IDt1ffejnz6tUPNbgJLZIFBZHAA/vz4VF/Qshf/4bK2z23dL/pV2OnhttId5Jomv/wz7rSmfFojRqvMm0mkOsKUbevn1KAeivy2swXV7qG8yi6ZCW/0Be54wB4Y5ZvU3j/AJTo2YSp/T5twW6LjpC9FfJJ99yn0GjUbICt2Rs1Fh+k7CQ5ze4+AHDqQ+1vxZ+itKOvFDB6CfDAqpTpqtdPaJlqFvq1bwvulRC44jnvPvhuyS04lhAJYP2iOQEh5lydE+sXpBfX+N3RCMY4KNY/8ubEOok/6+so2trq8Tc67BTprcrZ5sy0gYjn7XL5Jceobj+a8X+qaXc31i61vBeUpVO1eHth1iA9BXz3QBrRY0ahjBc3Fl9J8ouV6/svohQze+Xv4r47H18ryTUSTVDWnw6TuHgfYgtZQM98u1OqzLlB3Jz9AjlflcsnuakRtmeMGkkxiVuoPb3S36krL+oTNPGlyL6TcUTgeLl0ZZPRGdlmCbnR9JcEnKOqK7KwVYegLD5vlXrZwACMgve4dHJ8OEkf9ppwm6OGGGwG/1uHEJeN1zIOxgTCxqAAAAA=="
|
||||
aria-hidden="true"
|
||||
title="Cap logo"
|
||||
alt="Cap logo"
|
||||
/>
|
||||
<span>Cap</span>
|
||||
</a>
|
||||
<p class="date">{{TIME}}</p>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@cap.js/widget"></script>
|
||||
<script>
|
||||
window.CAP_CUSTOM_FETCH = function (url, options) {
|
||||
console.log(url);
|
||||
if (url.endsWith("/challenge")) {
|
||||
return {
|
||||
json: () => {
|
||||
return window.CAP_CHALLENGE;
|
||||
},
|
||||
};
|
||||
}
|
||||
return fetch(url, options);
|
||||
};
|
||||
|
||||
const widget = document.querySelector("cap-widget");
|
||||
|
||||
widget.addEventListener("solve", (event) => {
|
||||
document.querySelector("h2").innerText =
|
||||
"Continuing to your destination...";
|
||||
|
||||
document.cookie = `__cap_clearance=${
|
||||
event.detail.token
|
||||
}; path=/; max-age=${
|
||||
window.TOKEN_VALIDITY_HOURS * 3_600
|
||||
}; SameSite=Strict`;
|
||||
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 300);
|
||||
});
|
||||
|
||||
widget.solve();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,160 @@
|
||||
import Cap from "@cap.js/server";
|
||||
import fs from "fs/promises";
|
||||
import crypto from "crypto";
|
||||
|
||||
import { dirname, join } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
export const capCheckpoint = function (userOptions) {
|
||||
const options = {
|
||||
token_validity_hours: 32,
|
||||
tokens_store_path: ".data/middlewareTokens.json",
|
||||
token_size: 16,
|
||||
verification_template_path: join(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
"./index.html"
|
||||
),
|
||||
...userOptions,
|
||||
};
|
||||
|
||||
const cap = new Cap({
|
||||
noFSState: true,
|
||||
});
|
||||
|
||||
let tokensCache = null;
|
||||
let cacheLastModified = 0;
|
||||
|
||||
fs.mkdir(dirname(options.tokens_store_path), { recursive: true });
|
||||
|
||||
async function loadCustomTokens() {
|
||||
try {
|
||||
const stats = await fs.stat(options.tokens_store_path);
|
||||
|
||||
if (tokensCache && stats.mtime.getTime() <= cacheLastModified) {
|
||||
return tokensCache;
|
||||
}
|
||||
|
||||
tokensCache = JSON.parse(
|
||||
await fs.readFile(options.tokens_store_path, "utf-8")
|
||||
);
|
||||
cacheLastModified = Date.now();
|
||||
|
||||
return tokensCache;
|
||||
} catch {
|
||||
tokensCache = {};
|
||||
cacheLastModified = Date.now();
|
||||
|
||||
return tokensCache;
|
||||
}
|
||||
}
|
||||
|
||||
async function saveCustomTokens(tokens) {
|
||||
await fs.writeFile(options.tokens_store_path, JSON.stringify(tokens));
|
||||
tokensCache = tokens;
|
||||
cacheLastModified = Date.now();
|
||||
}
|
||||
|
||||
async function storeCustomToken(token) {
|
||||
const tokens = await loadCustomTokens();
|
||||
|
||||
tokens[token] = Date.now() + options.token_validity_hours * 60 * 60 * 1000;
|
||||
await saveCustomTokens(tokens);
|
||||
return token;
|
||||
}
|
||||
|
||||
async function validateCustomToken(token) {
|
||||
const tokens = await loadCustomTokens();
|
||||
const tokenData = tokens[token];
|
||||
|
||||
if (!tokenData) return { success: false };
|
||||
|
||||
if (Date.now() > tokenData) {
|
||||
delete tokens[token];
|
||||
await saveCustomTokens(tokens);
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async function cleanupExpiredTokens() {
|
||||
const tokens = await loadCustomTokens();
|
||||
const now = Date.now();
|
||||
let hasChanges = false;
|
||||
|
||||
for (const [token, data] of Object.entries(tokens)) {
|
||||
if (now > data) {
|
||||
delete tokens[token];
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChanges) {
|
||||
await saveCustomTokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
return async (req, res, next) => {
|
||||
const { path, method } = req;
|
||||
|
||||
if (method === "POST" && path === "/__cap_clearance/redeem") {
|
||||
const { token, solutions } = req.body;
|
||||
|
||||
if (!token || !solutions) {
|
||||
return res.status(400).json({ success: false });
|
||||
}
|
||||
|
||||
const challengeResult = await cap.redeemChallenge({ token, solutions });
|
||||
|
||||
cap.validateToken(challengeResult.token);
|
||||
|
||||
if (challengeResult.success) {
|
||||
const customToken = crypto
|
||||
.randomBytes(options.token_size)
|
||||
.toString("hex");
|
||||
await storeCustomToken(customToken);
|
||||
|
||||
await cleanupExpiredTokens();
|
||||
|
||||
res.cookie("__cap_clearance", customToken, {
|
||||
maxAge: options.token_validity_hours * 60 * 60 * 1000,
|
||||
sameSite: "Strict",
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
token: customToken,
|
||||
expires: challengeResult.expires,
|
||||
});
|
||||
}
|
||||
|
||||
return res.json(challengeResult);
|
||||
}
|
||||
|
||||
const customToken = req.cookies?.__cap_clearance;
|
||||
if (customToken) {
|
||||
const validation = await validateCustomToken(customToken);
|
||||
if (validation.success) {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
const challenge = cap.createChallenge();
|
||||
|
||||
const html = (
|
||||
await fs.readFile(options.verification_template_path, "utf-8")
|
||||
)
|
||||
.replace("window.CAP_CHALLENGE", JSON.stringify(challenge))
|
||||
.replace("window.TOKEN_VALIDITY_HOURS", options.token_validity_hours)
|
||||
.replace(
|
||||
"{{TIME}}",
|
||||
new Date()
|
||||
.toISOString()
|
||||
.replace("T", " ")
|
||||
.replace(/\.\d+Z$/, "Z")
|
||||
);
|
||||
|
||||
res.setHeader("Content-Type", "text/html");
|
||||
res.send(html);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@cap.js/checkpoint-express",
|
||||
"version": "0.0.1",
|
||||
"description": "Express Cloudflare-like checkpoint for Cap, a lightweight, modern open-source CAPTCHA alternative designed using SHA-256 PoW.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tiagorangel1/cap.git"
|
||||
},
|
||||
"keywords": [
|
||||
"security",
|
||||
"detection",
|
||||
"prevention",
|
||||
"defense",
|
||||
"protection",
|
||||
"anti-abuse",
|
||||
"anti-automation",
|
||||
"anti-bot",
|
||||
"anti-ddos",
|
||||
"anti-dos",
|
||||
"anti-exploitation",
|
||||
"anti-spam",
|
||||
"anti-scraping",
|
||||
"attack-mitigation",
|
||||
"protocol",
|
||||
"client-server",
|
||||
"computational-puzzle",
|
||||
"complexity",
|
||||
"puzzle",
|
||||
"crypto",
|
||||
"cryptographic",
|
||||
"algorithm",
|
||||
"cybersecurity",
|
||||
"ddos",
|
||||
"hashcash",
|
||||
"hcaptcha",
|
||||
"captcha-alternative",
|
||||
"verification",
|
||||
"invisible",
|
||||
"pow",
|
||||
"proof-of-work",
|
||||
"recaptcha",
|
||||
"spam",
|
||||
"bots",
|
||||
"filtering",
|
||||
"turing-test"
|
||||
],
|
||||
"author": "Tiago",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tiagorangel1/cap/issues"
|
||||
},
|
||||
"homepage": "https://github.com/tiagorangel1/cap#readme",
|
||||
"dependencies": {
|
||||
"@cap.js/server": "^1.0.15"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@cap.js/server": "latest",
|
||||
"elysia": "^1.3.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@cap.js/server": ["@cap.js/server@1.0.15", "", { "dependencies": { "@types/node": "^22.14.1", "typescript": "^5.8.3" } }, "sha512-mcDbHAL4ar5O4gnDE+62ZPeXhLXxd1KKHzJCsZfn81HY8Fgo5ousxYCnzhsLfki5sH6sO6jpNtS4MZXlKDq+fA=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.34.33", "", {}, "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g=="],
|
||||
|
||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
|
||||
|
||||
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
|
||||
|
||||
"@types/node": ["@types/node@22.15.29", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ=="],
|
||||
|
||||
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"elysia": ["elysia@1.3.3", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": "^0.34.33", "openapi-types": "^12.1.3" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-x6a89d4h0xX9TB0CSGkUuKNqIK776HBJw0WHtK1B3ViQqZijsLnOor6be/7TwVl8MG6m59NHGHbmbBS6lnCXSw=="],
|
||||
|
||||
"exact-mirror": ["exact-mirror@0.1.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-wFCPCDLmHbKGUb8TOi/IS7jLsgR8WVDGtDK3CzcB4Guf/weq7G+I+DkXiRSZfbemBFOxOINKpraM6ml78vo8Zw=="],
|
||||
|
||||
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
|
||||
|
||||
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
||||
|
||||
"file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
|
||||
|
||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"peek-readable": ["peek-readable@7.0.0", "", {}, "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ=="],
|
||||
|
||||
"strtok3": ["strtok3@10.2.2", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^7.0.0" } }, "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg=="],
|
||||
|
||||
"token-types": ["token-types@6.0.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@cap.js/server": "latest",
|
||||
"elysia": "^1.3.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@cap.js/server": "latest",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"express": "^5.1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@cap.js/server": ["@cap.js/server@1.0.15", "", { "dependencies": { "@types/node": "^22.14.1", "typescript": "^5.8.3" } }, "sha512-mcDbHAL4ar5O4gnDE+62ZPeXhLXxd1KKHzJCsZfn81HY8Fgo5ousxYCnzhsLfki5sH6sO6jpNtS4MZXlKDq+fA=="],
|
||||
|
||||
"@types/node": ["@types/node@22.15.29", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ=="],
|
||||
|
||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||
|
||||
"body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="],
|
||||
|
||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||
|
||||
"content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="],
|
||||
|
||||
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||
|
||||
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||
|
||||
"cookie-parser": ["cookie-parser@1.4.7", "", { "dependencies": { "cookie": "0.7.2", "cookie-signature": "1.0.6" } }, "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw=="],
|
||||
|
||||
"cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="],
|
||||
|
||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||
|
||||
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
||||
|
||||
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
||||
|
||||
"express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="],
|
||||
|
||||
"finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="],
|
||||
|
||||
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
||||
|
||||
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
||||
|
||||
"is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||
|
||||
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
||||
|
||||
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
"mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||
|
||||
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
||||
|
||||
"path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="],
|
||||
|
||||
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||
|
||||
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
|
||||
|
||||
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
||||
|
||||
"raw-body": ["raw-body@3.0.0", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.6.3", "unpipe": "1.0.0" } }, "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g=="],
|
||||
|
||||
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="],
|
||||
|
||||
"serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="],
|
||||
|
||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||
|
||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||
|
||||
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
||||
|
||||
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||
|
||||
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||
|
||||
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
|
||||
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||
|
||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"express/cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import express from "express";
|
||||
import cookieParser from "cookie-parser";
|
||||
import path from "path";
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { capCheckpoint } from "../../../checkpoints/express/index";
|
||||
// import { capCheckpoint } from "@cap.js/checkpoint-express";
|
||||
|
||||
const app = express();
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
app.use(express.json());
|
||||
app.use(cookieParser());
|
||||
|
||||
app.use(
|
||||
capCheckpoint({
|
||||
/*
|
||||
token_validity_hours: 32,
|
||||
tokens_store_path: ".data/tokensList.json",
|
||||
token_size: 16,
|
||||
verification_template_path: join(__dirname, "./index.html"),
|
||||
*/
|
||||
})
|
||||
);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "success.html"));
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log(`Server running on http://localhost:3000`);
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@cap.js/server": "latest",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"express": "^5.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Success!</title>
|
||||
<meta charset="UTF-8" />
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
p {
|
||||
max-width: 250px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
button {
|
||||
background-color: transparent;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>🎉</h1>
|
||||
<p>You have successfully passed Cap's checkpoint.</p>
|
||||
<button>Try again</button>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
document.querySelector("button").addEventListener("click", () => {
|
||||
document.cookie =
|
||||
"__cap_clearance=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/";
|
||||
location.reload();
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
@@ -3,7 +3,7 @@
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @cap.js/middleware-elysia
|
||||
bun add elysia @cap.js/middleware-elysia
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Express checkpoint
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add express cookie-parser @cap.js/middleware-express
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
import express from "express";
|
||||
import cookieParser from "cookie-parser";
|
||||
import path from "path";
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { capCheckpoint } from "@cap.js/checkpoint-express";
|
||||
|
||||
const app = express();
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
app.use(express.json());
|
||||
app.use(cookieParser());
|
||||
|
||||
app.use(
|
||||
capCheckpoint({
|
||||
/*
|
||||
token_validity_hours: 32,
|
||||
tokens_store_path: ".data/tokensList.json",
|
||||
token_size: 16,
|
||||
verification_template_path: join(__dirname, "./index.html"),
|
||||
*/
|
||||
})
|
||||
);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "success.html"));
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log(`Server running on http://localhost:3000`);
|
||||
});
|
||||
```
|
||||
|
||||
That's it! You can now use the middleware to protect your routes.
|
||||
@@ -3,7 +3,7 @@
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
bun add @cap.js/checkpoint-hono
|
||||
bun add hono @cap.js/checkpoint-hono
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -70,6 +70,7 @@ There are also some other helpful packages:
|
||||
We also provide a middleware for a Cloudflare browser checkpoint-like experience:
|
||||
|
||||
- [@cap.js/checkpoint-hono](https://capjs.js.org/guide/middleware/hono.html)
|
||||
- [@cap.js/checkpoint-express](https://capjs.js.org/guide/middleware/express.html)
|
||||
- [@cap.js/middleware-elysia](https://capjs.js.org/guide/middleware/elysia.html)
|
||||
- more coming soon!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user