Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { expect, test } from "@playwright/test";
/**
* Stage-7 closure smoke — proves that the four Stage-7 engines
* (`api-graphql-yoga`, `api-graphql-apollo`, `api-ws-bun`,
* `api-sse-bun`) coexist on a single Bun.serve host without route
* collision, and that GraphQL federation across two plugins works
* identically through both engines.
*/
const FED_QUERY = `
query Federated {
pluginA
pluginB
bothA
bothB
}
`;
interface GraphqlResponse {
readonly data?: Record<string, unknown> | null;
readonly errors?: ReadonlyArray<{ readonly message: string }>;
}
test.describe("foundation-stack-engines — Stage-7 coexistence", () => {
test("1. yoga federates GraphQL across plugin-a + plugin-b", async ({
request,
}) => {
const res = await request.post("/graphql/yoga", {
data: { query: FED_QUERY, operationName: "Federated" },
});
expect(res.status()).toBe(200);
const body = (await res.json()) as GraphqlResponse;
expect(body.errors).toBeUndefined();
expect(body.data).toEqual({
pluginA: "from plugin-a",
pluginB: "from plugin-b",
bothA: "A-half-of-both",
bothB: "B-half-of-both",
});
});
test("2. apollo federates the same SDL across plugin-a + plugin-b", async ({
request,
}) => {
const res = await request.post("/graphql/apollo", {
data: { query: FED_QUERY, operationName: "Federated" },
});
expect(res.status()).toBe(200);
const body = (await res.json()) as GraphqlResponse;
expect(body.errors).toBeUndefined();
expect(body.data).toEqual({
pluginA: "from plugin-a",
pluginB: "from plugin-b",
bothA: "A-half-of-both",
bothB: "B-half-of-both",
});
});
});

View File

@@ -0,0 +1,33 @@
import { expect, test } from "@playwright/test";
/**
* Stage-7 closure smoke — proves all four engines are mounted on the
* SAME Bun.serve listener at distinct routes (no path collision).
*/
interface EngineDescriptor {
readonly name: string;
readonly path: string;
readonly method: string;
}
test.describe("foundation-stack-engines — all engines mounted", () => {
test("5. /internal/engines lists yoga + apollo + ws-bun + sse-bun", async ({
request,
}) => {
const res = await request.get("/internal/engines");
expect(res.status()).toBe(200);
const body = (await res.json()) as {
engines: ReadonlyArray<EngineDescriptor>;
host: { wsConnections: number };
};
const names = body.engines.map((e) => e.name).sort();
expect(names).toEqual(["apollo", "sse-bun", "ws-bun", "yoga"]);
const paths = body.engines.map((e) => e.path);
expect(new Set(paths).size).toBe(paths.length); // no collisions
expect(paths).toContain("/graphql/yoga");
expect(paths).toContain("/graphql/apollo");
expect(paths).toContain("/ws");
expect(paths).toContain("/sse");
});
});

View File

@@ -0,0 +1,87 @@
import { expect, test } from "@playwright/test";
/**
* Stage-7 closure smoke — `api-sse-bun` event stream.
*
* Opens a real `fetch` against `/sse` to attach as an SSE subscriber,
* then publishes via `/sse/publish` and asserts that the stream body
* carries the expected `data:` frame.
*/
async function readUntilEvent(
body: ReadableStream<Uint8Array>,
pattern: RegExp,
timeoutMs = 5000
): Promise<string> {
const reader = body.getReader();
const decoder = new TextDecoder();
let buffer = "";
const deadline = Date.now() + timeoutMs;
try {
while (Date.now() < deadline) {
const { value, done } = await reader.read();
if (done) break;
if (value !== undefined) {
buffer += decoder.decode(value, { stream: true });
if (pattern.test(buffer)) {
return buffer;
}
}
}
} finally {
try {
await reader.cancel();
} catch {
/* idempotent */
}
}
throw new Error(
`sse stream did not yield ${pattern} within ${timeoutMs}ms; got: ${buffer}`
);
}
test.describe("foundation-stack-engines — sse-bun stream", () => {
test("4. sse subscriber receives a published event", async ({
request,
baseURL,
}) => {
const ac = new AbortController();
const url = `${baseURL}/sse?tenant=tenant-a&topic=ticker`;
const sseResponse = await fetch(url, {
method: "GET",
headers: {
accept: "text/event-stream",
"accept-encoding": "identity",
},
signal: ac.signal,
});
expect(sseResponse.status).toBe(200);
expect(sseResponse.headers.get("content-type")).toContain(
"text/event-stream"
);
expect(sseResponse.body).not.toBeNull();
// Give the handshake pipeline a moment to register the
// subscription on the engine's bus.
await new Promise<void>((resolve) => setTimeout(resolve, 200));
const pub = await request.post("/sse/publish", {
data: {
topic: "ticker",
tenant: "tenant-a",
data: "hello-sse",
id: "evt-1",
},
});
expect(pub.status()).toBe(200);
const pubBody = (await pub.json()) as { delivered: number };
expect(pubBody.delivered).toBeGreaterThanOrEqual(1);
const stream = sseResponse.body as ReadableStream<Uint8Array>;
const seen = await readUntilEvent(stream, /data:\s*hello-sse/);
expect(seen).toContain("data: hello-sse");
expect(seen).toContain("id: evt-1");
ac.abort();
});
});

View File

@@ -0,0 +1,122 @@
import { expect, test } from "@playwright/test";
/**
* Stage-7 closure smoke — `api-ws-bun` tenant-scoped broadcast.
*
* Two clients connect to `/ws` on different tenants (`tenant-a` /
* `tenant-b`) and subscribe to the SAME topic (`updates`). A publish
* scoped to `tenant-a` MUST reach only the tenant-a client; the
* tenant-b client MUST NOT see it. This proves the
* `SubscriptionBus.broadcast` tenant key — design §11.4 — is honoured
* by the engine's `broadcast(...)` helper.
*/
interface WsConnection {
readonly ws: WebSocket;
readonly received: unknown[];
close(): void;
}
async function openWs(
baseURL: string,
tenant: string,
topic: string
): Promise<WsConnection> {
const wsUrl = baseURL.replace(/^http/, "ws");
const ws = new WebSocket(
`${wsUrl}/ws?tenant=${encodeURIComponent(tenant)}&topic=${encodeURIComponent(topic)}`
);
const received: unknown[] = [];
ws.addEventListener("message", (ev) => {
try {
received.push(JSON.parse(String(ev.data)));
} catch {
received.push(ev.data);
}
});
await new Promise<void>((resolve, reject) => {
const timer = setTimeout(
() => reject(new Error("ws open timeout")),
5000
);
ws.addEventListener(
"open",
() => {
clearTimeout(timer);
resolve();
},
{ once: true }
);
ws.addEventListener(
"error",
(e) => {
clearTimeout(timer);
reject(new Error(`ws error: ${String(e)}`));
},
{ once: true }
);
});
return {
ws,
received,
close() {
try {
ws.close();
} catch {
/* idempotent */
}
},
};
}
async function settle(ms = 200): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, ms));
}
test.describe("foundation-stack-engines — ws-bun tenant isolation", () => {
test("3. tenant-A broadcast reaches only tenant-A subscriber, never tenant-B", async ({
request,
baseURL,
}) => {
expect(baseURL).toBeDefined();
const clientA = await openWs(baseURL as string, "tenant-a", "updates");
const clientB = await openWs(baseURL as string, "tenant-b", "updates");
try {
// Let the engine.attach + subscribe calls settle.
await settle(150);
const publish = await request.post("/ws/publish", {
data: {
topic: "updates",
tenant: "tenant-a",
payload: { hello: "from-tenant-a" },
},
});
expect(publish.status()).toBe(200);
const pBody = (await publish.json()) as { delivered: number };
// Exactly one subscriber (the tenant-a client) should match.
expect(pBody.delivered).toBe(1);
// Allow the send pipeline to flush over the socket.
await settle(300);
expect(clientA.received.length).toBe(1);
const env = clientA.received[0] as {
type?: string;
topic?: string;
payload?: Record<string, unknown>;
};
expect(env.type).toBe("broadcast");
expect(env.topic).toBe("updates");
expect(env.payload).toEqual({ hello: "from-tenant-a" });
// Tenant-B subscriber must NOT have received the tenant-A
// broadcast — proves cross-tenant isolation.
expect(clientB.received.length).toBe(0);
} finally {
clientA.close();
clientB.close();
}
});
});