Skip to content

Commit 0bb0526

Browse files
committed
Prototype a webpack plugin that makes the output files executable
1 parent d8ea470 commit 0bb0526

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

workspaces/fetch-leetcode-problem-list/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"type": "module",
1616
"exports": "./src/main.ts",
1717
"scripts": {
18-
"build": "cross-env NODE_OPTIONS=\"--import tsx\" webpack && chmod +x dist/fetch-leetcode-problem-list.cjs",
18+
"build": "cross-env NODE_OPTIONS=\"--import tsx\" webpack",
1919
"format": "prettier --color --write .",
2020
"lint": "eslint --color --max-warnings=0 .",
2121
"start": "tsx src/main.ts",

workspaces/fetch-leetcode-problem-list/webpack.config.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { chmod } from "node:fs/promises";
12
import { builtinModules } from "node:module";
23
import path from "node:path";
34

45
import webpack, {
6+
type Compiler,
57
type Configuration,
68
type ExternalItemFunctionData,
79
} from "webpack";
@@ -11,6 +13,32 @@ import { stripPrefixOrThrow } from "@code-chronicles/util/stripPrefixOrThrow";
1113

1214
import packageJson from "./package.json" with { type: "json" };
1315

16+
class WebpackMakeOutputExecutablePLugin {
17+
// eslint-disable-next-line class-methods-use-this -- This is the interface expected by webpack.
18+
apply(compiler: Compiler): void {
19+
compiler.hooks.afterEmit.tapAsync("WebpackMakeOutputExecutablePLugin", async (compilation) => {
20+
const promises: Promise<void>[] = [];
21+
22+
for (const chunk of compilation.chunks) {
23+
if (!chunk.canBeInitial()) {
24+
continue;
25+
}
26+
27+
for (const file of chunk.files) {
28+
promises.push(
29+
chmod(
30+
path.join(compilation.outputOptions.path ?? ".", file),
31+
0o755,
32+
),
33+
);
34+
}
35+
}
36+
37+
await Promise.all(promises);
38+
});
39+
}
40+
}
41+
1442
const config: Configuration = {
1543
target: "node",
1644
entry: path.resolve(__dirname, packageJson.exports),
@@ -58,6 +86,8 @@ const config: Configuration = {
5886
raw: true,
5987
entryOnly: true,
6088
}),
89+
90+
new WebpackMakeOutputExecutablePLugin(),
6191
],
6292
};
6393

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import invariant from "invariant";
2+
import nullthrows from "nullthrows";
3+
4+
export function onlyIterable<T>(iterable: Iterable<T>): T {
5+
let elementBag: { element: T } | null = null;
6+
for (const element of iterable) {
7+
invariant(elementBag == null, "Iterable had multiple elements!");
8+
elementBag = { element };
9+
}
10+
11+
return nullthrows(elementBag, "Empty iterable!").element;
12+
}

0 commit comments

Comments
 (0)