@cluerise/tools 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/dist/bin/cluenar-tools.sh +10 -0
- package/dist/configs/.editorconfig +10 -0
- package/dist/configs/.eslintignore +47 -0
- package/dist/configs/.eslintrc.cjs +114 -0
- package/dist/configs/.nvmrc +1 -0
- package/dist/configs/.prettierignore +37 -0
- package/dist/configs/_gitignore +23 -0
- package/dist/configs/_npmrc +1 -0
- package/dist/configs/commitlint.config.ts +31 -0
- package/dist/configs/hooks/commit-msg +1 -0
- package/dist/configs/hooks/post-commit +1 -0
- package/dist/configs/hooks/pre-commit +1 -0
- package/dist/configs/hooks/prepare-commit-msg +1 -0
- package/dist/configs/lint-staged.config.js +31 -0
- package/dist/configs/prettier.config.js +13 -0
- package/dist/configs/release.config.js +119 -0
- package/dist/configs/tsconfig.json +27 -0
- package/dist/scripts/check-heroku-node-version/main.js +138 -0
- package/dist/scripts/create-commit-message/main.js +149 -0
- package/dist/scripts/format-commit-message/main.js +130 -0
- package/dist/scripts/init/main.js +386 -0
- package/dist/scripts/lint/main.js +161 -0
- package/dist/scripts/release/main.js +230 -0
- package/dist/scripts/update-node-versions/main.js +162 -0
- package/package.json +45 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { z, ZodError } from "zod";
|
|
2
|
+
import ChildProcess from "child_process";
|
|
3
|
+
import { ESLint } from "eslint";
|
|
4
|
+
import FileSystem from "fs/promises";
|
|
5
|
+
import { glob } from "glob";
|
|
6
|
+
import * as Prettier from "prettier";
|
|
7
|
+
import "@commitlint/load";
|
|
8
|
+
const enginesSchema = z.object({
|
|
9
|
+
node: z.string()
|
|
10
|
+
});
|
|
11
|
+
const repositoryObjectSchema = z.object({
|
|
12
|
+
type: z.string(),
|
|
13
|
+
url: z.string(),
|
|
14
|
+
directory: z.ostring()
|
|
15
|
+
});
|
|
16
|
+
const repositorySchema = z.union([z.string(), repositoryObjectSchema]);
|
|
17
|
+
z.object({
|
|
18
|
+
name: z.string(),
|
|
19
|
+
version: z.string(),
|
|
20
|
+
description: z.string(),
|
|
21
|
+
engines: enginesSchema.optional(),
|
|
22
|
+
repository: repositorySchema.optional()
|
|
23
|
+
});
|
|
24
|
+
const runMain = (main2) => {
|
|
25
|
+
main2(process.argv.slice(2)).then((exitCode) => {
|
|
26
|
+
process.exit(exitCode);
|
|
27
|
+
}).catch((error) => {
|
|
28
|
+
console.error(error);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const createResultMessage = (exitCode) => {
|
|
33
|
+
if (exitCode === null) {
|
|
34
|
+
return "Done";
|
|
35
|
+
}
|
|
36
|
+
return exitCode === 0 ? "OK" : "Failed";
|
|
37
|
+
};
|
|
38
|
+
const createStatusConsole = (command) => ({
|
|
39
|
+
printBegin: (arg) => console.info(`${command} ${arg}...`),
|
|
40
|
+
printEnd: (arg, exitCode = null) => console.info(`${command} ${arg}... ${createResultMessage(exitCode)}`)
|
|
41
|
+
});
|
|
42
|
+
const lintCommit = (args) => {
|
|
43
|
+
const { status } = ChildProcess.spawnSync("commitlint", args, { stdio: "inherit" });
|
|
44
|
+
return status ?? 0;
|
|
45
|
+
};
|
|
46
|
+
const lintFilesScopeShortcutSchema = z.union([z.literal("all"), z.literal("code")]);
|
|
47
|
+
const scopePatterns = {
|
|
48
|
+
all: ["**"],
|
|
49
|
+
code: ["src/**"]
|
|
50
|
+
};
|
|
51
|
+
const scopeShortcuts = Object.keys(scopePatterns);
|
|
52
|
+
const isScopeShortcut = (scope) => scopeShortcuts.includes(scope);
|
|
53
|
+
const resolveScope = (scope) => {
|
|
54
|
+
if (Array.isArray(scope)) {
|
|
55
|
+
return scope;
|
|
56
|
+
}
|
|
57
|
+
if (isScopeShortcut(scope)) {
|
|
58
|
+
return scopePatterns[scope];
|
|
59
|
+
}
|
|
60
|
+
return [scope];
|
|
61
|
+
};
|
|
62
|
+
const formatWithPrettier = async (patterns) => {
|
|
63
|
+
const eslint = new ESLint();
|
|
64
|
+
const configPath = await Prettier.resolveConfigFile();
|
|
65
|
+
if (!configPath) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const config = await Prettier.resolveConfig(configPath);
|
|
69
|
+
if (!config) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const paths = await glob(patterns, {
|
|
73
|
+
nodir: true,
|
|
74
|
+
ignore: "node_modules/**"
|
|
75
|
+
});
|
|
76
|
+
await Promise.all(
|
|
77
|
+
paths.map(async (path) => {
|
|
78
|
+
if (await eslint.isPathIgnored(path)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const prevContent = (await FileSystem.readFile(path)).toString();
|
|
82
|
+
const nextContent = await Prettier.format(prevContent, {
|
|
83
|
+
...config,
|
|
84
|
+
filepath: path
|
|
85
|
+
});
|
|
86
|
+
await FileSystem.writeFile(path, nextContent);
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
const lintFiles = async (scope, options) => {
|
|
91
|
+
const patterns = resolveScope(scope);
|
|
92
|
+
if (options == null ? void 0 : options.fix) {
|
|
93
|
+
await formatWithPrettier(patterns);
|
|
94
|
+
}
|
|
95
|
+
const eslint = new ESLint({
|
|
96
|
+
fix: options == null ? void 0 : options.fix
|
|
97
|
+
});
|
|
98
|
+
const results = await eslint.lintFiles(patterns);
|
|
99
|
+
const problemCount = results.reduce((sum, result) => sum + result.errorCount + result.warningCount, 0);
|
|
100
|
+
if (options == null ? void 0 : options.fix) {
|
|
101
|
+
await ESLint.outputFixes(results);
|
|
102
|
+
}
|
|
103
|
+
if (problemCount > 0) {
|
|
104
|
+
const formatter = await eslint.loadFormatter("stylish");
|
|
105
|
+
const resultText = formatter.format(results);
|
|
106
|
+
console.error(resultText);
|
|
107
|
+
const errorMessage = `Linting failed with ${problemCount} problem${problemCount === 1 ? "" : "s"}.`;
|
|
108
|
+
throw new Error(errorMessage);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const lintStaged = (args) => {
|
|
112
|
+
const { status } = ChildProcess.spawnSync("lint-staged", args, { stdio: "inherit" });
|
|
113
|
+
return status ?? 0;
|
|
114
|
+
};
|
|
115
|
+
const LintCommands = {
|
|
116
|
+
lintFiles,
|
|
117
|
+
lintCommit,
|
|
118
|
+
lintStaged
|
|
119
|
+
};
|
|
120
|
+
const lintScopeArgSchema = z.union([lintFilesScopeShortcutSchema, z.literal("commit"), z.literal("staged")]);
|
|
121
|
+
const parseLintArgs = ([scopeArg]) => {
|
|
122
|
+
const scope = lintScopeArgSchema.parse(scopeArg);
|
|
123
|
+
return {
|
|
124
|
+
scope
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const lintingConsole = createStatusConsole("Linting");
|
|
128
|
+
const main = async (args) => {
|
|
129
|
+
try {
|
|
130
|
+
const { scope } = parseLintArgs(args);
|
|
131
|
+
lintingConsole.printBegin(scope);
|
|
132
|
+
if (scope === "commit") {
|
|
133
|
+
const exitCode = LintCommands.lintCommit(args.slice(1));
|
|
134
|
+
lintingConsole.printEnd(scope, exitCode);
|
|
135
|
+
return exitCode;
|
|
136
|
+
}
|
|
137
|
+
if (scope === "staged") {
|
|
138
|
+
const exitCode = LintCommands.lintStaged(args.slice(1));
|
|
139
|
+
lintingConsole.printEnd(scope, exitCode);
|
|
140
|
+
return exitCode;
|
|
141
|
+
}
|
|
142
|
+
await LintCommands.lintFiles(scope);
|
|
143
|
+
lintingConsole.printEnd(scope);
|
|
144
|
+
return 0;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error instanceof ZodError) {
|
|
147
|
+
const firstIssue = error.issues[0];
|
|
148
|
+
if ((firstIssue == null ? void 0 : firstIssue.code) === "invalid_union") {
|
|
149
|
+
console.error("Invalid scope");
|
|
150
|
+
return 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (error instanceof Error) {
|
|
154
|
+
console.error(error.message);
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
console.error(error);
|
|
158
|
+
return 1;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
runMain(main);
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import * as ActionsCore from "@actions/core";
|
|
2
|
+
import { z, ZodError } from "zod";
|
|
3
|
+
import ChildProcess from "child_process";
|
|
4
|
+
import FileSystem from "fs/promises";
|
|
5
|
+
import Path from "path";
|
|
6
|
+
import semanticRelease from "semantic-release";
|
|
7
|
+
import { ESLint } from "eslint";
|
|
8
|
+
import { glob } from "glob";
|
|
9
|
+
import * as Prettier from "prettier";
|
|
10
|
+
import "@commitlint/load";
|
|
11
|
+
import OS from "os";
|
|
12
|
+
const enginesSchema = z.object({
|
|
13
|
+
node: z.string()
|
|
14
|
+
});
|
|
15
|
+
const repositoryObjectSchema = z.object({
|
|
16
|
+
type: z.string(),
|
|
17
|
+
url: z.string(),
|
|
18
|
+
directory: z.ostring()
|
|
19
|
+
});
|
|
20
|
+
const repositorySchema = z.union([z.string(), repositoryObjectSchema]);
|
|
21
|
+
z.object({
|
|
22
|
+
name: z.string(),
|
|
23
|
+
version: z.string(),
|
|
24
|
+
description: z.string(),
|
|
25
|
+
engines: enginesSchema.optional(),
|
|
26
|
+
repository: repositorySchema.optional()
|
|
27
|
+
});
|
|
28
|
+
const runMain = (main2) => {
|
|
29
|
+
main2(process.argv.slice(2)).then((exitCode) => {
|
|
30
|
+
process.exit(exitCode);
|
|
31
|
+
}).catch((error) => {
|
|
32
|
+
console.error(error);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
const lintCommit = (args) => {
|
|
37
|
+
const { status } = ChildProcess.spawnSync("commitlint", args, { stdio: "inherit" });
|
|
38
|
+
return status ?? 0;
|
|
39
|
+
};
|
|
40
|
+
z.union([z.literal("all"), z.literal("code")]);
|
|
41
|
+
const scopePatterns = {
|
|
42
|
+
all: ["**"],
|
|
43
|
+
code: ["src/**"]
|
|
44
|
+
};
|
|
45
|
+
const scopeShortcuts = Object.keys(scopePatterns);
|
|
46
|
+
const isScopeShortcut = (scope) => scopeShortcuts.includes(scope);
|
|
47
|
+
const resolveScope = (scope) => {
|
|
48
|
+
if (Array.isArray(scope)) {
|
|
49
|
+
return scope;
|
|
50
|
+
}
|
|
51
|
+
if (isScopeShortcut(scope)) {
|
|
52
|
+
return scopePatterns[scope];
|
|
53
|
+
}
|
|
54
|
+
return [scope];
|
|
55
|
+
};
|
|
56
|
+
const formatWithPrettier = async (patterns) => {
|
|
57
|
+
const eslint = new ESLint();
|
|
58
|
+
const configPath = await Prettier.resolveConfigFile();
|
|
59
|
+
if (!configPath) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const config = await Prettier.resolveConfig(configPath);
|
|
63
|
+
if (!config) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const paths = await glob(patterns, {
|
|
67
|
+
nodir: true,
|
|
68
|
+
ignore: "node_modules/**"
|
|
69
|
+
});
|
|
70
|
+
await Promise.all(
|
|
71
|
+
paths.map(async (path) => {
|
|
72
|
+
if (await eslint.isPathIgnored(path)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const prevContent = (await FileSystem.readFile(path)).toString();
|
|
76
|
+
const nextContent = await Prettier.format(prevContent, {
|
|
77
|
+
...config,
|
|
78
|
+
filepath: path
|
|
79
|
+
});
|
|
80
|
+
await FileSystem.writeFile(path, nextContent);
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
const lintFiles = async (scope, options) => {
|
|
85
|
+
const patterns = resolveScope(scope);
|
|
86
|
+
if (options == null ? void 0 : options.fix) {
|
|
87
|
+
await formatWithPrettier(patterns);
|
|
88
|
+
}
|
|
89
|
+
const eslint = new ESLint({
|
|
90
|
+
fix: options == null ? void 0 : options.fix
|
|
91
|
+
});
|
|
92
|
+
const results = await eslint.lintFiles(patterns);
|
|
93
|
+
const problemCount = results.reduce((sum, result) => sum + result.errorCount + result.warningCount, 0);
|
|
94
|
+
if (options == null ? void 0 : options.fix) {
|
|
95
|
+
await ESLint.outputFixes(results);
|
|
96
|
+
}
|
|
97
|
+
if (problemCount > 0) {
|
|
98
|
+
const formatter = await eslint.loadFormatter("stylish");
|
|
99
|
+
const resultText = formatter.format(results);
|
|
100
|
+
console.error(resultText);
|
|
101
|
+
const errorMessage = `Linting failed with ${problemCount} problem${problemCount === 1 ? "" : "s"}.`;
|
|
102
|
+
throw new Error(errorMessage);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const lintStaged = (args) => {
|
|
106
|
+
const { status } = ChildProcess.spawnSync("lint-staged", args, { stdio: "inherit" });
|
|
107
|
+
return status ?? 0;
|
|
108
|
+
};
|
|
109
|
+
const LintCommands = {
|
|
110
|
+
lintFiles,
|
|
111
|
+
lintCommit,
|
|
112
|
+
lintStaged
|
|
113
|
+
};
|
|
114
|
+
const releaseConfigFilename = "release.config.js";
|
|
115
|
+
const releaseNotesPath = "CHANGELOG.md";
|
|
116
|
+
const findLastReleaseTitle = (releaseNotes, lastRelease) => {
|
|
117
|
+
const lastReleaseTitleLink = `## [${lastRelease.version}](`;
|
|
118
|
+
if (releaseNotes.includes(lastReleaseTitleLink)) {
|
|
119
|
+
return lastReleaseTitleLink;
|
|
120
|
+
}
|
|
121
|
+
const lastReleaseTitle = `## ${lastRelease.version}`;
|
|
122
|
+
if (releaseNotes.includes(lastReleaseTitle)) {
|
|
123
|
+
return lastReleaseTitle;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
};
|
|
127
|
+
const prependReleaseNotes = (releaseNotes, lastRelease, nextRelease) => {
|
|
128
|
+
var _a;
|
|
129
|
+
const nextReleaseNotes = ((_a = nextRelease.notes) == null ? void 0 : _a.trim()) ?? "";
|
|
130
|
+
if (releaseNotes.length === 0) {
|
|
131
|
+
return nextReleaseNotes;
|
|
132
|
+
}
|
|
133
|
+
const lastReleaseTitle = findLastReleaseTitle(releaseNotes, lastRelease);
|
|
134
|
+
if (!lastReleaseTitle) {
|
|
135
|
+
return nextReleaseNotes;
|
|
136
|
+
}
|
|
137
|
+
return releaseNotes.replace(lastReleaseTitle, `${nextReleaseNotes}
|
|
138
|
+
|
|
139
|
+
${lastReleaseTitle}`);
|
|
140
|
+
};
|
|
141
|
+
const createRelease = async () => {
|
|
142
|
+
const releaseConfigPath = Path.join(process.cwd(), releaseConfigFilename);
|
|
143
|
+
const { default: releaseConfig } = await import(`file://${releaseConfigPath}`);
|
|
144
|
+
const result = await semanticRelease(releaseConfig);
|
|
145
|
+
if (!result) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const { lastRelease, nextRelease } = result;
|
|
149
|
+
const oldReleaseNotes = (await FileSystem.readFile(releaseNotesPath, {
|
|
150
|
+
flag: FileSystem.constants.O_CREAT
|
|
151
|
+
})).toString();
|
|
152
|
+
const newReleaseNotes = prependReleaseNotes(oldReleaseNotes, lastRelease, nextRelease);
|
|
153
|
+
await FileSystem.writeFile(releaseNotesPath, newReleaseNotes);
|
|
154
|
+
await LintCommands.lintFiles(releaseNotesPath, {
|
|
155
|
+
fix: true
|
|
156
|
+
});
|
|
157
|
+
ChildProcess.execFileSync("npm", [
|
|
158
|
+
"version",
|
|
159
|
+
nextRelease.version,
|
|
160
|
+
"--message",
|
|
161
|
+
"release: Version %s",
|
|
162
|
+
"--no-git-tag-version"
|
|
163
|
+
]);
|
|
164
|
+
return nextRelease;
|
|
165
|
+
};
|
|
166
|
+
const releaseSeparator = /^## /gm;
|
|
167
|
+
const extractChangelog = async () => {
|
|
168
|
+
const content = (await FileSystem.readFile("CHANGELOG.md")).toString();
|
|
169
|
+
const [, latestReleaseChangelog] = content.split(releaseSeparator);
|
|
170
|
+
if (!latestReleaseChangelog) {
|
|
171
|
+
throw new Error("No release found");
|
|
172
|
+
}
|
|
173
|
+
const indexOfFirstEOL = latestReleaseChangelog.indexOf(OS.EOL);
|
|
174
|
+
if (indexOfFirstEOL === -1) {
|
|
175
|
+
throw new Error("Header not found");
|
|
176
|
+
}
|
|
177
|
+
const body = latestReleaseChangelog.slice(indexOfFirstEOL).trim();
|
|
178
|
+
const changelog = {
|
|
179
|
+
body
|
|
180
|
+
};
|
|
181
|
+
return changelog;
|
|
182
|
+
};
|
|
183
|
+
const ReleaseCommands = {
|
|
184
|
+
createRelease,
|
|
185
|
+
extractChangelog
|
|
186
|
+
};
|
|
187
|
+
const commandNameArgSchema = z.union([z.literal("create"), z.literal("extract-changelog")]);
|
|
188
|
+
const parseReleaseArgs = ([commandArg]) => {
|
|
189
|
+
const command = commandNameArgSchema.parse(commandArg);
|
|
190
|
+
return {
|
|
191
|
+
command
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const main = async (args) => {
|
|
195
|
+
try {
|
|
196
|
+
const { command } = parseReleaseArgs(args);
|
|
197
|
+
if (command === "create") {
|
|
198
|
+
const release = await ReleaseCommands.createRelease();
|
|
199
|
+
if (!release) {
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
203
|
+
ActionsCore.setOutput("version", release.version);
|
|
204
|
+
}
|
|
205
|
+
} else if (command === "extract-changelog") {
|
|
206
|
+
const changelog = await ReleaseCommands.extractChangelog();
|
|
207
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
208
|
+
ActionsCore.setOutput("changelog", changelog.body);
|
|
209
|
+
} else {
|
|
210
|
+
console.log(changelog.body);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return 0;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (error instanceof ZodError) {
|
|
216
|
+
const firstIssue = error.issues[0];
|
|
217
|
+
if ((firstIssue == null ? void 0 : firstIssue.code) === "invalid_union") {
|
|
218
|
+
console.error("Invalid command name");
|
|
219
|
+
return 1;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (error instanceof Error) {
|
|
223
|
+
console.error(error.message);
|
|
224
|
+
return 1;
|
|
225
|
+
}
|
|
226
|
+
console.error(error);
|
|
227
|
+
return 1;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
runMain(main);
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import * as ActionsCore from "@actions/core";
|
|
2
|
+
import FileSystem from "fs/promises";
|
|
3
|
+
import SemVer from "semver";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
class ParseGitRepositoryError extends Error {
|
|
6
|
+
}
|
|
7
|
+
const gitProviderOrigins = {
|
|
8
|
+
github: "https://github.com"
|
|
9
|
+
};
|
|
10
|
+
const gitProviderNames = Object.keys(gitProviderOrigins);
|
|
11
|
+
const isGitProviderName = (name) => gitProviderNames.includes(name);
|
|
12
|
+
const parseRepositoryUrl = (urlString) => {
|
|
13
|
+
const urlValue = urlString.includes(":") ? urlString : `https://${urlString}`;
|
|
14
|
+
const url = new URL(urlValue);
|
|
15
|
+
const scheme = url.protocol.slice(0, -1);
|
|
16
|
+
if (isGitProviderName(scheme)) {
|
|
17
|
+
const [owner, repositoryName] = url.pathname.split("/");
|
|
18
|
+
if (!owner || !repositoryName) {
|
|
19
|
+
throw new ParseGitRepositoryError("Unknown owner or repositoryName");
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
origin: gitProviderOrigins[scheme],
|
|
23
|
+
owner,
|
|
24
|
+
repositoryName
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (scheme === "https") {
|
|
28
|
+
const [, owner, repositoryName] = url.pathname.split("/");
|
|
29
|
+
if (!owner || !repositoryName) {
|
|
30
|
+
throw new ParseGitRepositoryError("Unknown owner or repositoryName");
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
origin: url.origin,
|
|
34
|
+
owner,
|
|
35
|
+
repositoryName: repositoryName.endsWith(".git") ? repositoryName.slice(0, -4) : repositoryName
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
throw new ParseGitRepositoryError("Unsupported repository URL");
|
|
39
|
+
};
|
|
40
|
+
const parsePackageJsonRepository = (repository) => {
|
|
41
|
+
if (typeof repository === "string") {
|
|
42
|
+
return parseRepositoryUrl(repository);
|
|
43
|
+
}
|
|
44
|
+
return parseRepositoryUrl(repository.url);
|
|
45
|
+
};
|
|
46
|
+
const enginesSchema = z.object({
|
|
47
|
+
node: z.string()
|
|
48
|
+
});
|
|
49
|
+
const repositoryObjectSchema = z.object({
|
|
50
|
+
type: z.string(),
|
|
51
|
+
url: z.string(),
|
|
52
|
+
directory: z.ostring()
|
|
53
|
+
});
|
|
54
|
+
const repositorySchema = z.union([z.string(), repositoryObjectSchema]);
|
|
55
|
+
const packageJsonSchema = z.object({
|
|
56
|
+
name: z.string(),
|
|
57
|
+
version: z.string(),
|
|
58
|
+
description: z.string(),
|
|
59
|
+
engines: enginesSchema.optional(),
|
|
60
|
+
repository: repositorySchema.optional()
|
|
61
|
+
});
|
|
62
|
+
const readPackageJson = async () => {
|
|
63
|
+
const packageJsonData = await FileSystem.readFile("package.json", { encoding: "utf8" });
|
|
64
|
+
const packageJson = JSON.parse(packageJsonData);
|
|
65
|
+
const parseResult = packageJsonSchema.safeParse(packageJson);
|
|
66
|
+
if (!parseResult.success) {
|
|
67
|
+
throw parseResult.error;
|
|
68
|
+
}
|
|
69
|
+
return packageJson;
|
|
70
|
+
};
|
|
71
|
+
const CoreCommands = {
|
|
72
|
+
readPackageJson,
|
|
73
|
+
parsePackageJsonRepository
|
|
74
|
+
};
|
|
75
|
+
const runMain = (main2) => {
|
|
76
|
+
main2(process.argv.slice(2)).then((exitCode) => {
|
|
77
|
+
process.exit(exitCode);
|
|
78
|
+
}).catch((error) => {
|
|
79
|
+
console.error(error);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const nodeReleasesUrl = "https://nodejs.org/dist/index.json";
|
|
84
|
+
const nodeReleaseSchema = z.object({
|
|
85
|
+
version: z.string(),
|
|
86
|
+
// 'v20.5.1',
|
|
87
|
+
date: z.string(),
|
|
88
|
+
// '2023-08-09',
|
|
89
|
+
files: z.array(z.string()),
|
|
90
|
+
npm: z.ostring(),
|
|
91
|
+
// '9.8.0',
|
|
92
|
+
v8: z.string(),
|
|
93
|
+
// '11.3.244.8',
|
|
94
|
+
uv: z.ostring(),
|
|
95
|
+
// '1.46.0',
|
|
96
|
+
zlib: z.ostring(),
|
|
97
|
+
// '1.2.13.1-motley',
|
|
98
|
+
openssl: z.ostring(),
|
|
99
|
+
// '3.0.10+quic',
|
|
100
|
+
modules: z.ostring(),
|
|
101
|
+
// '115',
|
|
102
|
+
lts: z.union([z.boolean(), z.string()]),
|
|
103
|
+
// false, 'Argon',
|
|
104
|
+
security: z.boolean()
|
|
105
|
+
});
|
|
106
|
+
const nodeReleasesSchema = z.array(nodeReleaseSchema);
|
|
107
|
+
const fetchNodeReleases = async () => {
|
|
108
|
+
const response = await fetch(nodeReleasesUrl);
|
|
109
|
+
const data = await response.json();
|
|
110
|
+
return nodeReleasesSchema.parse(data);
|
|
111
|
+
};
|
|
112
|
+
const fetchLatestNodeRelease = async () => {
|
|
113
|
+
const [latestRelease] = await fetchNodeReleases();
|
|
114
|
+
return latestRelease;
|
|
115
|
+
};
|
|
116
|
+
const NodeJsCommands = {
|
|
117
|
+
fetchLatestNodeRelease,
|
|
118
|
+
fetchNodeReleases
|
|
119
|
+
};
|
|
120
|
+
const updateNvmrc = (version) => FileSystem.writeFile(".nvmrc", `v${version}
|
|
121
|
+
`);
|
|
122
|
+
const updatePackageJson = async (version) => {
|
|
123
|
+
var _a;
|
|
124
|
+
const packageJson = await CoreCommands.readPackageJson();
|
|
125
|
+
if (!packageJson.engines) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const nodeVersion = packageJson.engines.node;
|
|
129
|
+
if (!nodeVersion || nodeVersion === version) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const coerceNodeVersion = (_a = SemVer.coerce(nodeVersion)) == null ? void 0 : _a.version;
|
|
133
|
+
if (!coerceNodeVersion) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
packageJson.engines.node = nodeVersion.replace(coerceNodeVersion, version);
|
|
137
|
+
const nextContent = JSON.stringify(packageJson, null, 2) + "\n";
|
|
138
|
+
return FileSystem.writeFile("package.json", nextContent);
|
|
139
|
+
};
|
|
140
|
+
const main = async () => {
|
|
141
|
+
try {
|
|
142
|
+
const nodeRelease = await NodeJsCommands.fetchLatestNodeRelease();
|
|
143
|
+
const nodeVersion = nodeRelease == null ? void 0 : nodeRelease.version;
|
|
144
|
+
const versionNumber = (nodeVersion == null ? void 0 : nodeVersion.startsWith("v")) ? nodeVersion.slice(1) : nodeVersion;
|
|
145
|
+
if (!versionNumber) {
|
|
146
|
+
console.error("Error: Unknown latest Node.js version number");
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
console.info(`Info: Trying to update Node.js versions to ${versionNumber}`);
|
|
150
|
+
await updateNvmrc(versionNumber);
|
|
151
|
+
await updatePackageJson(versionNumber);
|
|
152
|
+
console.info("Info: Update successful");
|
|
153
|
+
if (process.env.GITHUB_ACTIONS === "true") {
|
|
154
|
+
ActionsCore.setOutput("version", versionNumber);
|
|
155
|
+
}
|
|
156
|
+
return 0;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.log(JSON.stringify(error, null, 2));
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
runMain(main);
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cluerise/tools",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Tools for maintaining TypeScript projects.",
|
|
5
|
+
"author": "Branislav Holý <brano@holy.am>",
|
|
6
|
+
"repository": "github:cluerise/tools",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/cluerise/tools/issues"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/cluerise/tools#readme",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"bin": {
|
|
14
|
+
"cluerise-tools": "./dist/bin/cluerise-tools.sh"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"./dist/"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@actions/core": "1.10.1",
|
|
21
|
+
"@commitlint/cli": "19.3.0",
|
|
22
|
+
"@commitlint/load": "19.2.0",
|
|
23
|
+
"@commitlint/types": "19.0.3",
|
|
24
|
+
"@html-eslint/eslint-plugin": "0.24.1",
|
|
25
|
+
"@html-eslint/parser": "0.24.1",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "7.8.0",
|
|
27
|
+
"@typescript-eslint/parser": "7.8.0",
|
|
28
|
+
"conventional-changelog-conventionalcommits": "7.0.2",
|
|
29
|
+
"eslint": "8.57.0",
|
|
30
|
+
"eslint-config-prettier": "9.1.0",
|
|
31
|
+
"eslint-plugin-import": "2.29.1",
|
|
32
|
+
"eslint-plugin-json": "3.1.0",
|
|
33
|
+
"eslint-plugin-markdown": "5.0.0",
|
|
34
|
+
"eslint-plugin-prettier": "5.1.3",
|
|
35
|
+
"eslint-plugin-simple-import-sort": "12.1.0",
|
|
36
|
+
"eslint-plugin-yml": "1.14.0",
|
|
37
|
+
"glob": "10.3.14",
|
|
38
|
+
"lint-staged": "15.2.2",
|
|
39
|
+
"prettier": "3.2.5",
|
|
40
|
+
"semantic-release": "23.0.8",
|
|
41
|
+
"semver": "7.6.2",
|
|
42
|
+
"smol-toml": "1.1.4",
|
|
43
|
+
"zod": "3.23.8"
|
|
44
|
+
}
|
|
45
|
+
}
|