Skip to content

Commit 624e334

Browse files
committed
chore: add deno task gen to generate mod.ts files
1 parent 06da9f8 commit 624e334

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

.scripts/gen-mod.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { fromFileUrl, globToRegExp, join, relative } from "@std/path";
2+
import { flatMap } from "@core/iterutil/async/flat-map";
3+
4+
const decoder = new TextDecoder();
5+
6+
const excludes = [
7+
"mod.ts",
8+
"*_test.ts",
9+
"*_bench.ts",
10+
"_*.ts",
11+
];
12+
13+
type DenoDocEntry = {
14+
name: string;
15+
location: {
16+
filename: string;
17+
};
18+
declarationKind: string;
19+
jsDoc: {
20+
doc: string;
21+
};
22+
kind: string;
23+
};
24+
25+
function isDenoDocEntry(x: unknown): x is DenoDocEntry {
26+
if (x == null || typeof x !== "object") return false;
27+
if (typeof (x as DenoDocEntry).name !== "string") return false;
28+
if (typeof (x as DenoDocEntry).location !== "object") return false;
29+
if (typeof (x as DenoDocEntry).location.filename !== "string") return false;
30+
if (typeof (x as DenoDocEntry).declarationKind !== "string") return false;
31+
if (typeof (x as DenoDocEntry).jsDoc !== "object") return false;
32+
if (typeof (x as DenoDocEntry).jsDoc.doc !== "string") return false;
33+
if (typeof (x as DenoDocEntry).kind !== "string") return false;
34+
return true;
35+
}
36+
37+
async function listDenoDocEntries(path: string): Promise<DenoDocEntry[]> {
38+
const cmd = new Deno.Command(Deno.execPath(), {
39+
args: ["doc", "--json", path],
40+
stdout: "piped",
41+
stderr: "piped",
42+
});
43+
const { success, stdout, stderr } = await cmd.output();
44+
if (!success) {
45+
throw new Error(decoder.decode(stderr));
46+
}
47+
const json = JSON.parse(decoder.decode(stdout));
48+
if (!Array.isArray(json)) {
49+
throw new Error(`Expected array but got ${JSON.stringify(json)}`);
50+
}
51+
return json.filter(isDenoDocEntry);
52+
}
53+
54+
async function* iterModules(path: string): AsyncIterable<string> {
55+
const patterns = excludes.map((p) => globToRegExp(p));
56+
for await (const entry of Deno.readDir(path)) {
57+
if (!entry.isFile || !entry.name.endsWith(".ts")) continue;
58+
if (patterns.some((p) => p.test(entry.name))) continue;
59+
yield join(path, entry.name);
60+
}
61+
}
62+
63+
async function generateModTs(
64+
namespace: string,
65+
): Promise<void> {
66+
const path = fromFileUrl(import.meta.resolve(`../${namespace}/`));
67+
const exports = (await Array.fromAsync(
68+
flatMap(iterModules(path), (x) => listDenoDocEntries(x)),
69+
))
70+
.filter((x) => x.kind === "function")
71+
.filter((x) => x.declarationKind === "export")
72+
.filter((x) => x.name.startsWith(namespace))
73+
.map((x) => ({
74+
path: relative(path, fromFileUrl(x.location.filename)),
75+
name: x.name,
76+
doc: x.jsDoc.doc,
77+
}))
78+
.toSorted((a, b) => a.name.localeCompare(b.name));
79+
const lines = [
80+
"// NOTE: This file is generated by gen-mod.ts",
81+
...exports.map((x) => {
82+
return `import { ${x.name} } from "./${x.path}";`;
83+
}),
84+
"",
85+
`export const ${namespace}: {`,
86+
...exports.flatMap((x) => {
87+
return [
88+
" /**",
89+
...x.doc.split("\n").map((line) => ` * ${line}`.trimEnd()),
90+
" */",
91+
` ${x.name.replace(namespace, "")}: typeof ${x.name};`.trimEnd(),
92+
];
93+
}),
94+
"} = {",
95+
...exports.flatMap((x) => {
96+
return [
97+
` ${x.name.replace(namespace, "")}: ${x.name},`.trimEnd(),
98+
];
99+
}),
100+
"};",
101+
];
102+
await Deno.writeTextFile(join(path, "mod.ts"), lines.join("\n") + "\n");
103+
}
104+
105+
async function main(): Promise<void> {
106+
await generateModTs("is");
107+
await generateModTs("as");
108+
}
109+
110+
if (import.meta.main) {
111+
main().catch((err) => {
112+
console.error(err);
113+
Deno.exit(1);
114+
});
115+
}

deno.jsonc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
]
6767
},
6868
"imports": {
69+
"@core/iterutil": "jsr:@core/iterutil@^0.3.0",
6970
"@core/unknownutil": "./mod.ts",
7071
"@deno/dnt": "jsr:@deno/dnt@^0.41.1",
7172
"@std/assert": "jsr:@std/assert@^0.221.0",
@@ -78,6 +79,7 @@
7879
"test": "deno test -A --doc --parallel --shuffle",
7980
"test:coverage": "deno task test --coverage=.coverage",
8081
"coverage": "deno coverage .coverage",
82+
"gen": "deno run --allow-run=deno --allow-read --allow-write=. .scripts/gen-mod.ts",
8183
"update": "deno run --allow-env --allow-read --allow-write=. --allow-run=git,deno --allow-net=jsr.io,registry.npmjs.org jsr:@molt/cli ./*.ts",
8284
"update:commit": "deno task -q update --commit --prefix deps: --pre-commit=fmt,lint"
8385
}

0 commit comments

Comments
 (0)