1import * as NodeFsPromises from "node:fs/promises";
2import * as NodePath from "node:path";
3import { describe, expect, it } from "vitest";
4
5const GENERIC_MODULES = ["Vocs.ts", "Target.ts", "index.ts"];
6const FORBIDDEN = [
7 /^@alchemy\.run\/cloudflare-runtime/,
8 /^@cloudflare\//,
9 /cloudflare:/,
10 /(^|\/)cloudflare(\.ts|\.js)?$/,
11 /\.\.\/waku\/cloudflare\.ts$/,
12];
13
14const importSpecifiers = (source: string): Array<string> => {
15 const specifiers: Array<string> = [];
16 for (const pattern of [
17 /(?:^|\n)\s*(?:import|export)\s[^;]*?from\s*["']([^"']+)["']/g,
18 /(?:^|\n)\s*import\s*["']([^"']+)["']/g,
19 /import\s*\(\s*["']([^"']+)["']\s*\)/g,
20 ]) {
21 for (const match of source.matchAll(pattern)) specifiers.push(match[1]!);
22 }
23 return specifiers;
24};
25
26describe("Vocs target decoupling", () => {
27 for (const module of GENERIC_MODULES) {
28 it(`${module} imports nothing Cloudflare-specific`, async () => {
29 const source = await NodeFsPromises.readFile(
30 NodePath.resolve(import.meta.dirname, "..", module),
31 "utf8",
32 );
33 const offending = importSpecifiers(source).filter((specifier) =>
34 FORBIDDEN.some((pattern) => pattern.test(specifier)),
35 );
36 expect(offending).toEqual([]);
37 });
38 }
39
40 it("cloudflare.ts owns the Waku Cloudflare target composition", async () => {
41 const source = await NodeFsPromises.readFile(
42 NodePath.resolve(import.meta.dirname, "../cloudflare.ts"),
43 "utf8",
44 );
45 expect(importSpecifiers(source)).toContain("../waku/cloudflare.ts");
46 });
47});