|
| 1 | +import { test } from "@cross/test"; |
| 2 | +import { assertArrayIncludes } from "@std/assert"; |
| 3 | +import { basename, globToRegExp, join } from "@std/path"; |
| 4 | +import { ensure, is } from "@core/unknownutil"; |
| 5 | +import { parse } from "@std/jsonc"; |
| 6 | + |
| 7 | +const excludes = [ |
| 8 | + "mod.ts", |
| 9 | + "_*.ts", |
| 10 | + "*_test.ts", |
| 11 | + "*_bench.ts", |
| 12 | +]; |
| 13 | + |
| 14 | +test("mod.ts must exports all exports in public modules", async () => { |
| 15 | + const modExports = await listModExports("./mod.ts"); |
| 16 | + const pubExports = []; |
| 17 | + for await (const name of iterPublicModules(".")) { |
| 18 | + pubExports.push(...await listModExports(`./${name}.ts`)); |
| 19 | + } |
| 20 | + assertArrayIncludes(modExports, pubExports); |
| 21 | +}, { skip: !("Deno" in globalThis) }); |
| 22 | + |
| 23 | +test("JSR exports must have all exports in mod.ts", async () => { |
| 24 | + const jsrExportEntries = await listJsrExportEntries(); |
| 25 | + const modExportEntries: [string, string][] = []; |
| 26 | + for await (const name of iterPublicModules(".")) { |
| 27 | + modExportEntries.push([`./${name.replaceAll("_", "-")}`, `./${name}.ts`]); |
| 28 | + } |
| 29 | + assertArrayIncludes(jsrExportEntries, modExportEntries); |
| 30 | +}, { skip: !("Deno" in globalThis) }); |
| 31 | + |
| 32 | +async function* iterPublicModules(relpath: string): AsyncIterable<string> { |
| 33 | + const patterns = excludes.map((p) => globToRegExp(p)); |
| 34 | + const root = join(import.meta.dirname!, relpath); |
| 35 | + for await (const entry of Deno.readDir(root)) { |
| 36 | + if (!entry.isFile || !entry.name.endsWith(".ts")) continue; |
| 37 | + if (patterns.some((p) => p.test(entry.name))) continue; |
| 38 | + yield basename(entry.name, ".ts"); |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +async function listModExports(path: string): Promise<string[]> { |
| 43 | + const mod = await import(import.meta.resolve(path)); |
| 44 | + return Array.from(Object.keys(mod)); |
| 45 | +} |
| 46 | + |
| 47 | +async function listJsrExportEntries(): Promise<[string, string][]> { |
| 48 | + const text = await Deno.readTextFile( |
| 49 | + new URL(import.meta.resolve("./deno.jsonc")), |
| 50 | + ); |
| 51 | + const json = ensure( |
| 52 | + parse(text), |
| 53 | + is.ObjectOf({ |
| 54 | + exports: is.RecordOf(is.String, is.String), |
| 55 | + }), |
| 56 | + ); |
| 57 | + return Object.entries(json.exports); |
| 58 | +} |
0 commit comments