diff --git a/Makefile b/Makefile index 66c58ea..233be48 100644 --- a/Makefile +++ b/Makefile @@ -7,5 +7,5 @@ test: tdd: bun test --watch -lint: +check: test bun lint \ No newline at end of file diff --git a/domain/AppProjections.ts b/domain/AppProjections.ts index 55cc1b0..baf23f0 100644 --- a/domain/AppProjections.ts +++ b/domain/AppProjections.ts @@ -1,3 +1,4 @@ +import type DomainProjection from "./DomainProjection"; import ApplicationUpdates from "./projections/ApplicationUpdates"; export default class AppProjections { diff --git a/domain/DomainEvent.ts b/domain/DomainEvent.ts index 708dfd2..3a63727 100644 --- a/domain/DomainEvent.ts +++ b/domain/DomainEvent.ts @@ -1,4 +1,4 @@ -interface DomainEvent { +export default interface DomainEvent { readonly type: string; readonly createdAt: Date; readonly payload: T; diff --git a/domain/DomainProjection.ts b/domain/DomainProjection.ts index b37bb18..8ba4b9b 100644 --- a/domain/DomainProjection.ts +++ b/domain/DomainProjection.ts @@ -1,3 +1,4 @@ -interface DomainProjection { +import type DomainEvent from "./DomainEvent"; +export default interface DomainProjection { handle(event: DomainEvent): void; } diff --git a/domain/EventStore.ts b/domain/EventStore.ts index 6edfdb1..394bb87 100644 --- a/domain/EventStore.ts +++ b/domain/EventStore.ts @@ -1,3 +1,6 @@ +import DomainEvent from "./DomainEvent"; +import DomainProjection from "./DomainProjection"; + export default interface EventStore { append(event: DomainEvent): void; subscribe(projection: DomainProjection): void; diff --git a/domain/events/ApplicationUpdateStarted.ts b/domain/events/ApplicationUpdateStarted.ts index b1ebf78..d053670 100644 --- a/domain/events/ApplicationUpdateStarted.ts +++ b/domain/events/ApplicationUpdateStarted.ts @@ -1,3 +1,5 @@ +import DomainEvent from "../DomainEvent"; + type ApplicationUpdateStartedPayload = { id: string; newVersion: string; diff --git a/domain/projections/ApplicationUpdates.ts b/domain/projections/ApplicationUpdates.ts index 8ceda41..984b745 100644 --- a/domain/projections/ApplicationUpdates.ts +++ b/domain/projections/ApplicationUpdates.ts @@ -1,3 +1,6 @@ +import DomainEvent from "../DomainEvent"; +import DomainProjection from "../DomainProjection"; + export type UpdateDefinition = { id: string; newVersion: string; diff --git a/domain/testing/TestApp.ts b/domain/testing/TestApp.ts index 6e6e8f9..243aa7e 100644 --- a/domain/testing/TestApp.ts +++ b/domain/testing/TestApp.ts @@ -1,5 +1,7 @@ import AppProjections from "../AppProjections"; import AppQueries from "../AppQueries"; +import DomainEvent from "../DomainEvent"; +import DomainProjection from "../DomainProjection"; import EventStore from "../EventStore"; export class TestApp { diff --git a/infrastructure/FileEventStore.ts b/infrastructure/FileEventStore.ts index a5d0bbc..a251626 100644 --- a/infrastructure/FileEventStore.ts +++ b/infrastructure/FileEventStore.ts @@ -1,6 +1,8 @@ import { appendFile } from "node:fs/promises"; import EventStore from "../domain/EventStore"; import { ApplicationUpdateStarted } from "../domain/events/ApplicationUpdateStarted"; +import DomainEvent from "../domain/DomainEvent"; +import DomainProjection from "../domain/DomainProjection"; export default class FileEventStore implements EventStore { private handlers: DomainProjection[] = []; diff --git a/joe.ts b/joe.ts index 2f39bc7..7842e77 100644 --- a/joe.ts +++ b/joe.ts @@ -15,6 +15,7 @@ const queries = new AppQueries(projections); projections.getAll().forEach((projection) => { eventStore.subscribe(projection); }); +// @ts-ignore Bun handles top-level await await eventStore.replay(); // External services diff --git a/package.json b/package.json index f5b2d56..0f79f80 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,7 @@ { + "scripts": { + "lint": "tsc --noEmit --skipLibCheck" + }, "devDependencies": { "bun-types": "^1.0.25", "msw": "latest" diff --git a/services/Caprover.test.ts b/services/Caprover.test.ts index 51bdfce..32c68e3 100644 --- a/services/Caprover.test.ts +++ b/services/Caprover.test.ts @@ -71,6 +71,7 @@ describe("Caprover", () => { describe("Initialization", () => { it("should throw an error when no domain is provided", () => { + // @ts-ignore toThrowError exists¯\_(ツ)_/¯ expect(() => new Caprover(new TestApp().eventStore, "")).toThrowError( "Missing domain or password" ); @@ -78,6 +79,7 @@ describe("Caprover", () => { it("should throw an error when no password is provided", () => { expect( () => new Caprover(new TestApp().eventStore, CAPROVER_TEST_DOMAIN) + // @ts-ignore toThrowError exists¯\_(ツ)_/¯ ).toThrowError("Missing domain or password"); }); }); @@ -125,6 +127,7 @@ describe("Caprover", () => { it("should throw an error when the application does not exist and not emit any event", async () => { await expect( caprover.updateApplication("unknown", "adminer:4.2.0") + // @ts-ignore toThrowError exists¯\_(ツ)_/¯ ).rejects.toThrowError(/Failed to update application unknown/); const events = app.eventStore.getAllEvents(); diff --git a/services/Caprover.ts b/services/Caprover.ts index d44f06a..eef782f 100644 --- a/services/Caprover.ts +++ b/services/Caprover.ts @@ -133,14 +133,15 @@ class Caprover { await this.authenticate(); console.debug("-> Caprover Fetching", options?.method, path); + + const headers = new Headers(options?.headers); + headers.set("Content-Type", "application/json"); + headers.set("x-namespace", "captain"); + headers.set("x-captain-auth", this.authToken); + return fetch(`${this.apiUrl}${path}`, { ...options, - headers: { - "Content-Type": "application/json", - ...(options?.headers || {}), - "x-namespace": "captain", - "x-captain-auth": this.authToken, - }, + headers: headers, }).then((res) => { console.debug( "\t<- Caprover Response", diff --git a/services/mocks/caproverServer.ts b/services/mocks/caproverServer.ts index a914f19..c59a414 100644 --- a/services/mocks/caproverServer.ts +++ b/services/mocks/caproverServer.ts @@ -1,5 +1,10 @@ +import { + http, + HttpResponse, + HttpResponseResolver, + PathParams +} from "msw"; import { setupServer } from "msw/node"; -import { http, HttpResponse, HttpResponseResolver, PathParams } from "msw"; import appsFixtures from "./apps.fixtures.json"; export const CAPROVER_TEST_DOMAIN = "caprover.test"; @@ -14,7 +19,7 @@ const withAuth = (resolver: HttpResponseResolver): HttpResponseResolver => { headers.get("x-namespace") !== "captain" || headers.get("x-captain-auth") !== TEST_TOKEN ) { - return new HttpResponse("", { status: 401 }); + return HttpResponse.json({}, { status: 401 }); } return resolver(input); };