ci: add pull request quality gates
CI / install-and-build (pull_request) Successful in 1m29s
CI / format (pull_request) Successful in 51s
CI / typecheck-source (pull_request) Successful in 41s
CI / typecheck-tests (pull_request) Successful in 39s
CI / test (pull_request) Successful in 51s
CI / lint (pull_request) Successful in 21s

Co-Authored-By: gpt-5.6-terra <noreply@openai.com>
This commit was merged in pull request #12.
This commit is contained in:
2026-07-22 21:50:29 +00:00
co-authored by Codex
parent b9fa79ff1f
commit 31d4636dde
80 changed files with 2007 additions and 398 deletions
+19 -11
View File
@@ -3,7 +3,11 @@ import assert from "node:assert/strict";
import { createServer } from "node:http";
import type { AddressInfo } from "node:net";
import { ApiInterface } from "../../../src/db/api/ApiInterface.js";
import { apiProtocols, isApiUrl, parseApiUrl } from "../../../src/db/api/url.js";
import {
apiProtocols,
isApiUrl,
parseApiUrl,
} from "../../../src/db/api/url.js";
import {
NotFoundAbodeError,
NotAuthorizedAbodeError,
@@ -86,7 +90,7 @@ describe("parseApiUrl", () => {
it("extra query params become headers", () => {
const [, { headers }] = parseApiUrl(
"http://example.com?X-Custom-Header=value"
"http://example.com?X-Custom-Header=value",
);
assert.equal(headers["X-Custom-Header"], "value");
});
@@ -94,7 +98,7 @@ describe("parseApiUrl", () => {
it("throws for non-api protocol", () => {
assert.throws(
() => parseApiUrl("sqlite:///db.sqlite"),
/Not an \{abode\+,\}http\{s,\}: protocol/
/Not an \{abode\+,\}http\{s,\}: protocol/,
);
});
});
@@ -106,18 +110,22 @@ describe("ApiInterface HTTP error mapping", () => {
before(async () => {
let nextStatus = 500;
respondWith = (s) => { nextStatus = s; };
respondWith = (s) => {
nextStatus = s;
};
const server = createServer((req, res) => {
res.writeHead(nextStatus, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: false, error: "test" }));
});
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
await new Promise<void>((resolve) =>
server.listen(0, "127.0.0.1", resolve),
);
const { port } = server.address() as AddressInfo;
serverUrl = `http://127.0.0.1:${port}`;
closeServer = () =>
new Promise<void>((resolve, reject) =>
server.close((err) => (err ? reject(err) : resolve()))
server.close((err) => (err ? reject(err) : resolve())),
);
});
@@ -131,7 +139,7 @@ describe("ApiInterface HTTP error mapping", () => {
(err) => {
assert.ok(err instanceof NotFoundAbodeError);
return true;
}
},
);
});
@@ -143,7 +151,7 @@ describe("ApiInterface HTTP error mapping", () => {
(err) => {
assert.ok(err instanceof NotAuthorizedAbodeError);
return true;
}
},
);
});
@@ -155,7 +163,7 @@ describe("ApiInterface HTTP error mapping", () => {
(err) => {
assert.ok(err instanceof ReadonlyAbodeError);
return true;
}
},
);
});
@@ -167,7 +175,7 @@ describe("ApiInterface HTTP error mapping", () => {
(err) => {
assert.ok(err instanceof InvalidAbodeError);
return true;
}
},
);
});
@@ -179,7 +187,7 @@ describe("ApiInterface HTTP error mapping", () => {
(err) => {
assert.ok(err instanceof ConflictAbodeError);
return true;
}
},
);
});
});
+5 -1
View File
@@ -92,7 +92,11 @@ describe("api backend: auth over HTTP", async () => {
const self = await fetch(`${server.url}/auth/self`, {
headers: { Cookie: `abode_session=${cookie}` },
});
assert.equal(self.status, 401, "session was invalidated server-side, not just the cookie cleared");
assert.equal(
self.status,
401,
"session was invalidated server-side, not just the cookie cleared",
);
});
it("POST /auth/clear-sessions invalidates outstanding session cookies", async () => {