Skip to content

Commit ac31323

Browse files
Rel1cxCopilot
andauthored
refactor(scripts): migrate scripts to effect and effect-platform (#1190)
Signed-off-by: REL1CX <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 7d06bfd commit ac31323

File tree

4 files changed

+128
-68
lines changed

4 files changed

+128
-68
lines changed

scripts/update-readme.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1-
import fs from "fs";
1+
import * as NodeContext from "@effect/platform-node/NodeContext";
2+
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3+
import * as FileSystem from "@effect/platform/FileSystem";
4+
import * as Effect from "effect/Effect";
25

3-
fs.copyFileSync("README.md", "packages/plugins/eslint-plugin/README.md");
6+
const program = Effect.gen(function*() {
7+
const fs = yield* FileSystem.FileSystem;
8+
const source = "README.md";
9+
const destination = "packages/plugins/eslint-plugin/README.md";
10+
11+
// Ensure the destination directory exists
12+
yield* fs.makeDirectory("packages/plugins/eslint-plugin", { recursive: true });
13+
14+
// Copy the README file
15+
yield* fs.copyFile(source, destination);
16+
17+
yield* Effect.log(`Copied ${source} to ${destination}`);
18+
});
19+
20+
program.pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);

scripts/update-version.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem";
1+
import * as NodeContext from "@effect/platform-node/NodeContext";
22
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
33
import * as FileSystem from "@effect/platform/FileSystem";
44
import ansis from "ansis";
@@ -47,4 +47,4 @@ const program = Effect.gen(function*() {
4747
return yield* Effect.all(packageJsonFiles.map(update), { concurrency: 8 });
4848
});
4949

50-
program.pipe(Effect.provide(NodeFileSystem.layer), NodeRuntime.runMain);
50+
program.pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);

scripts/update-website.ts

Lines changed: 102 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,118 @@
1-
import fs from "node:fs";
2-
import path from "node:path";
1+
import * as NodeContext from "@effect/platform-node/NodeContext";
2+
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3+
import * as FileSystem from "@effect/platform/FileSystem";
4+
import * as Path from "@effect/platform/Path";
5+
import ansis from "ansis";
6+
import * as Effect from "effect/Effect";
37

48
import { glob } from "./utils/glob";
59

610
/**
711
* Build script for processing and copying documentation to the website
812
*
9-
* This script:
13+
* This script (Effect version):
1014
* 1. Collects rule documentation from ESLint Plugins
1115
* 2. Copies them to the website with proper naming
1216
* 3. Processes the changelog
13-
* 4. Sets up dependencies for the website build
17+
* 4. (TODO) Generates meta.json / rules data
1418
*/
1519

16-
// Find all rule documentation markdown files from the various plugins
17-
const docs = glob(["packages/plugins/eslint-plugin-react-*/src/rules/*.md"]);
18-
19-
// TODO: Generate the meta.json file as well
20-
// Process each documentation file:
21-
// - Extract plugin name and rule name
22-
// - Format destination path and rule title
23-
// - Build arrays of file paths and rule metadata
24-
const [
25-
files,
26-
// rules, // Currently commented out but would contain rule metadata
27-
] = Array.from(docs).reduce<readonly [[string, string][], [string, string][]]>(
28-
([files, rules], doc) => {
20+
const DOCS_GLOB = ["packages/plugins/eslint-plugin-react-*/src/rules/*.md"];
21+
22+
interface RuleMeta {
23+
name: string;
24+
title: string;
25+
destination: string;
26+
source: string;
27+
}
28+
29+
const collectDocs = Effect.gen(function*() {
30+
const path = yield* Path.Path;
31+
const docs = yield* Effect.sync(() => glob(DOCS_GLOB));
32+
return docs.map<RuleMeta>((doc) => {
2933
const catename = /^packages\/plugins\/eslint-plugin-react-([^/]+)/u.exec(doc)?.[1] ?? "";
3034
const basename = path.parse(path.basename(doc)).name;
3135

32-
// Special handling for "react-x" plugin (the core plugin)
3336
const isPluginX = catename === "x";
3437

35-
// Format the rule name differently based on which plugin it belongs to
36-
const name = isPluginX
37-
? basename // For react-x plugin: just use the rule name
38-
: `${catename}-${basename}`; // For other plugins: prefix with category
39-
40-
// Format the rule title for display purposes
41-
const title = isPluginX
42-
? basename // For react-x plugin: just use the rule name
43-
: `${catename}/${basename}`; // For other plugins: use category/rule format
44-
45-
// Define destination path in the website content directory
46-
const dest = path.join("apps", "website", "content", "docs", "rules", `${name}.mdx`);
47-
48-
// Add to our accumulator arrays
49-
return [[...files, [doc, dest]], [...rules, [name, title]]] as const;
50-
},
51-
[[], []],
52-
);
53-
54-
// Copy all documentation files to their respective destinations in parallel
55-
files.map(([src, dest]) => fs.copyFileSync(src, dest));
56-
57-
// Write rule metadata to a JSON file for the website
58-
// fs.writeFileSync(path.join("apps", "website", "content", "docs", "rules", "data.json"), JSON.stringify(rules, null, 2));
59-
60-
// Process the changelog file by adding frontmatter for the documentation system
61-
const changelog = [
62-
"---",
63-
"title: Changelog",
64-
"---",
65-
"",
66-
fs.readFileSync("CHANGELOG.md", "utf-8"),
67-
].join("\n");
68-
69-
// Write the processed changelog to the website content directory
70-
fs.writeFileSync(path.join("apps", "website", "content", "docs", "changelog.md"), changelog);
38+
const name = isPluginX ? basename : `${catename}-${basename}`;
39+
const title = isPluginX ? basename : `${catename}/${basename}`;
40+
41+
const destination = path.join("apps", "website", "content", "docs", "rules", `${name}.mdx`);
42+
43+
return {
44+
name,
45+
title,
46+
destination,
47+
source: doc,
48+
};
49+
});
50+
});
51+
52+
function copyRuleDoc(meta: RuleMeta) {
53+
return Effect.gen(function*() {
54+
const fs = yield* FileSystem.FileSystem;
55+
const path = yield* Path.Path;
56+
const dir = path.dirname(meta.destination);
57+
// Ensure destination directory exists
58+
yield* fs.makeDirectory(dir, { recursive: true });
59+
const content = yield* fs.readFileString(meta.source, "utf8");
60+
yield* fs.writeFileString(meta.destination, content);
61+
yield* Effect.log(ansis.green(`Copied ${meta.source} -> ${meta.destination}`));
62+
return meta;
63+
});
64+
}
65+
66+
const processChangelog = Effect.gen(function*() {
67+
const fs = yield* FileSystem.FileSystem;
68+
const path = yield* Path.Path;
69+
const changelogPath = "CHANGELOG.md";
70+
const targetPath = path.join("apps", "website", "content", "docs", "changelog.md");
71+
72+
const source = yield* fs.readFileString(changelogPath, "utf8");
73+
const wrapped = [
74+
"---",
75+
"title: Changelog",
76+
"---",
77+
"",
78+
source,
79+
].join("\n");
80+
81+
const dir = path.dirname(targetPath);
82+
yield* fs.makeDirectory(dir, { recursive: true });
83+
yield* fs.writeFileString(targetPath, wrapped);
84+
yield* Effect.log(ansis.cyan(`Processed changelog -> ${targetPath}`));
85+
});
86+
87+
const program = Effect.gen(function*() {
88+
yield* Effect.log(ansis.bold("Processing rule documentation..."));
89+
90+
const metas = yield* collectDocs;
91+
92+
yield* Effect.log(
93+
metas.length === 0
94+
? ansis.yellow("No documentation files found.")
95+
: `Found ${ansis.bold(metas.length.toString())} rule documentation file(s).`,
96+
);
97+
98+
// Copy in parallel with limited concurrency (adjust if needed)
99+
yield* Effect.forEach(metas, copyRuleDoc, { concurrency: 8 });
100+
101+
// (Optional) Generate rules metadata JSON (still TODO)
102+
// const rulesData = metas.map(({ name, title }) => ({ name, title }));
103+
// const rulesDataPath = path.join("apps", "website", "content", "docs", "rules", "data.json");
104+
// yield* FileSystem.FileSystem.flatMap(fs =>
105+
// fs.makeDirectory(path.dirname(rulesDataPath), { recursive: true }).pipe(
106+
// Effect.zipRight(
107+
// fs.writeFileString(rulesDataPath, JSON.stringify(rulesData, null, 2) + "\n")
108+
// ),
109+
// Effect.tap(() => Effect.log(ansis.magenta(`Generated ${rulesDataPath}`)))
110+
// )
111+
// );
112+
113+
yield* processChangelog;
114+
115+
yield* Effect.log(ansis.bold.green("Documentation processing completed."));
116+
});
117+
118+
program.pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);

scripts/verify-lockfile.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Command, CommandExecutor } from "@effect/platform";
2-
import { NodeCommandExecutor, NodeFileSystem, NodeRuntime } from "@effect/platform-node";
1+
import * as NodeContext from "@effect/platform-node/NodeContext";
2+
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
3+
import * as Command from "@effect/platform/Command";
4+
import * as CommandExecutor from "@effect/platform/CommandExecutor";
35
import { Effect } from "effect";
4-
import * as Fn from "effect/Function";
5-
import * as Layer from "effect/Layer";
66

77
const command = Command.make("git", "diff", "HEAD@{1}", "--stat", "--", "./pnpm-lock.yaml");
88
const program = Effect.gen(function*() {
@@ -15,9 +15,4 @@ const program = Effect.gen(function*() {
1515
yield* Effect.logWarning("Please run `pnpm install --fix-lockfile && pnpm dedupe` to update local dependencies.");
1616
});
1717

18-
const MainLive = Fn.pipe(
19-
NodeCommandExecutor.layer,
20-
Layer.provideMerge(NodeFileSystem.layer),
21-
);
22-
23-
program.pipe(Effect.provide(MainLive), NodeRuntime.runMain);
18+
program.pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);

0 commit comments

Comments
 (0)