isaacscript 2.0.4 → 2.0.7
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/dist/src/commands/init/createMod.js +9 -9
- package/dist/src/commands/init/git.js +3 -3
- package/dist/src/commands/init/init.js +2 -2
- package/dist/src/commands/monitor/monitor.js +13 -13
- package/dist/src/commands/monitor/saveDatWriter/saveDatWriter.js +2 -2
- package/dist/src/configFile.js +1 -1
- package/dist/src/constants.js +12 -9
- package/dist/src/file.js +1 -1
- package/dist/src/main.js +3 -3
- package/dist/src/utils.js +5 -5
- package/dist/src/validateInIsaacScriptProject.js +1 -1
- package/package.json +11 -6
- package/.cspell-base.json +0 -38
- package/.cspell-check-unused.json +0 -7
- package/.cspell.json +0 -53
- package/.eslintrc.js +0 -28
- package/.gitattributes +0 -9
- package/.github/workflows/ci.yml +0 -47
- package/.prettierignore +0 -5
- package/.prettierrc.js +0 -42
- package/.vscode/extensions.json +0 -9
- package/.vscode/settings.json +0 -73
- package/build.sh +0 -30
- package/check-file-updates.sh +0 -57
- package/check-gitignore.sh +0 -26
- package/check-orphaned-words.sh +0 -53
- package/dist/package.json +0 -50
- package/dist/src/checkForWindowsTerminalBugs.js.map +0 -1
- package/dist/src/commands/copy/copy.js.map +0 -1
- package/dist/src/commands/init/checkIfProjectPathExists.js.map +0 -1
- package/dist/src/commands/init/checkModSubdirectory.js.map +0 -1
- package/dist/src/commands/init/checkModTargetDirectory.js.map +0 -1
- package/dist/src/commands/init/createMod.js.map +0 -1
- package/dist/src/commands/init/getModsDir.js.map +0 -1
- package/dist/src/commands/init/getProjectPath.js.map +0 -1
- package/dist/src/commands/init/git.js.map +0 -1
- package/dist/src/commands/init/init.js.map +0 -1
- package/dist/src/commands/init/installVSCodeExtensions.js.map +0 -1
- package/dist/src/commands/init/promptSaveSlot.js.map +0 -1
- package/dist/src/commands/init/promptVSCode.js.map +0 -1
- package/dist/src/commands/monitor/copyWatcherMod.js.map +0 -1
- package/dist/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js.map +0 -1
- package/dist/src/commands/monitor/monitor.js.map +0 -1
- package/dist/src/commands/monitor/notifyGame.js.map +0 -1
- package/dist/src/commands/monitor/saveDatWriter/saveDatWriter.js.map +0 -1
- package/dist/src/commands/monitor/saveDatWriter/types.js.map +0 -1
- package/dist/src/commands/monitor/spawnSaveDatWriter.js.map +0 -1
- package/dist/src/commands/monitor/touchWatcherSaveDatFiles.js.map +0 -1
- package/dist/src/commands/publish/publish.js.map +0 -1
- package/dist/src/configFile.js.map +0 -1
- package/dist/src/constants.js.map +0 -1
- package/dist/src/exec.js.map +0 -1
- package/dist/src/file.js.map +0 -1
- package/dist/src/main.js.map +0 -1
- package/dist/src/parseArgs.js.map +0 -1
- package/dist/src/prompt.js.map +0 -1
- package/dist/src/types/Command.js.map +0 -1
- package/dist/src/types/Config.js.map +0 -1
- package/dist/src/types/GitHubCLIHostsYAML.js.map +0 -1
- package/dist/src/utils.js.map +0 -1
- package/dist/src/validateInIsaacScriptProject.js.map +0 -1
- package/dist/src/validateNodeVersion.js.map +0 -1
- package/dist/src/validateOS.js.map +0 -1
- package/eslint-debug.sh +0 -11
- package/file-templates/dynamic/README.md +0 -3
- package/file-templates/dynamic/gitignore +0 -144
- package/file-templates/dynamic/main.ts +0 -19
- package/file-templates/dynamic/metadata.vdf +0 -6
- package/file-templates/dynamic/metadata.xml +0 -10
- package/file-templates/dynamic/package.json +0 -19
- package/file-templates/static/.cspell-check-unused.json +0 -9
- package/file-templates/static/.cspell.json.template +0 -9
- package/file-templates/static/.env_template +0 -2
- package/file-templates/static/.eslintrc.js +0 -24
- package/file-templates/static/.gitattributes +0 -9
- package/file-templates/static/.github/workflows/ci.yml +0 -53
- package/file-templates/static/.prettierignore +0 -14
- package/file-templates/static/.prettierrc.js +0 -42
- package/file-templates/static/.vscode/extensions.json +0 -10
- package/file-templates/static/.vscode/settings.json +0 -76
- package/file-templates/static/LICENSE +0 -674
- package/file-templates/static/build.sh +0 -15
- package/file-templates/static/check-orphaned-words.sh +0 -53
- package/file-templates/static/lint.sh +0 -39
- package/file-templates/static/nuke.sh +0 -18
- package/file-templates/static/plugins/addCrashDebugStatements.ts +0 -40
- package/file-templates/static/plugins/addIsaacScriptCommentHeader.ts +0 -37
- package/file-templates/static/plugins/noExtendedEnums.ts +0 -66
- package/file-templates/static/publish.sh +0 -10
- package/file-templates/static/run.sh +0 -10
- package/file-templates/static/src/bundleEntry.ts +0 -10
- package/file-templates/static/tsconfig.eslint.json +0 -11
- package/file-templates/static/tsconfig.json +0 -33
- package/file-templates/static/update.sh +0 -21
- package/file-templates/static-alt/.cspell-base.json +0 -38
- package/file-templates/static-alt/.cspell-check-unused-base.json +0 -7
- package/file-templates/static-alt/.prettierignore-base +0 -5
- package/file-templates/static-alt/.prettierrc-base.js +0 -30
- package/file-templates/static-alt/.vscode/extensions-typescript.json +0 -9
- package/file-templates/static-alt/.vscode/settings-typescript.json +0 -63
- package/isaacscript-watcher/.luacheckrc +0 -96
- package/isaacscript-watcher/README.md +0 -8
- package/isaacscript-watcher/main.lua +0 -270
- package/isaacscript-watcher/metadata.xml +0 -7
- package/isaacscript-watcher/resources/gfx/logo.anm2 +0 -27
- package/isaacscript-watcher/resources/gfx/logo.png +0 -0
- package/lint.sh +0 -38
- package/misc/logo.png +0 -0
- package/misc/mouseover.png +0 -0
- package/nuke.sh +0 -18
- package/publish.sh +0 -11
- package/src/checkForWindowsTerminalBugs.ts +0 -106
- package/src/commands/copy/copy.ts +0 -41
- package/src/commands/init/checkIfProjectPathExists.ts +0 -34
- package/src/commands/init/checkModSubdirectory.ts +0 -20
- package/src/commands/init/checkModTargetDirectory.ts +0 -42
- package/src/commands/init/createMod.ts +0 -196
- package/src/commands/init/getModsDir.ts +0 -107
- package/src/commands/init/getProjectPath.ts +0 -111
- package/src/commands/init/git.ts +0 -249
- package/src/commands/init/init.ts +0 -93
- package/src/commands/init/installVSCodeExtensions.ts +0 -47
- package/src/commands/init/promptSaveSlot.ts +0 -27
- package/src/commands/init/promptVSCode.ts +0 -33
- package/src/commands/monitor/copyWatcherMod.ts +0 -54
- package/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.ts +0 -67
- package/src/commands/monitor/monitor.ts +0 -180
- package/src/commands/monitor/notifyGame.ts +0 -59
- package/src/commands/monitor/saveDatWriter/saveDatWriter.ts +0 -145
- package/src/commands/monitor/saveDatWriter/types.ts +0 -6
- package/src/commands/monitor/spawnSaveDatWriter.ts +0 -36
- package/src/commands/monitor/touchWatcherSaveDatFiles.ts +0 -20
- package/src/commands/publish/publish.ts +0 -392
- package/src/configFile.ts +0 -80
- package/src/constants.ts +0 -85
- package/src/exec.ts +0 -125
- package/src/file.ts +0 -235
- package/src/main.ts +0 -131
- package/src/parseArgs.ts +0 -127
- package/src/prompt.ts +0 -109
- package/src/types/Command.ts +0 -3
- package/src/types/Config.ts +0 -23
- package/src/types/GitHubCLIHostsYAML.ts +0 -7
- package/src/utils.ts +0 -92
- package/src/validateInIsaacScriptProject.ts +0 -35
- package/src/validateNodeVersion.ts +0 -29
- package/src/validateOS.ts +0 -20
- package/tsconfig.eslint.json +0 -11
- package/tsconfig.json +0 -21
- package/update.sh +0 -21
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import * as configFile from "../../configFile";
|
|
4
|
-
import {
|
|
5
|
-
GITIGNORE,
|
|
6
|
-
GITIGNORE_TEMPLATE_PATH,
|
|
7
|
-
MAIN_TS,
|
|
8
|
-
MAIN_TS_TEMPLATE_PATH,
|
|
9
|
-
METADATA_VDF,
|
|
10
|
-
METADATA_VDF_TEMPLATE_PATH,
|
|
11
|
-
METADATA_XML,
|
|
12
|
-
METADATA_XML_TEMPLATE_PATH,
|
|
13
|
-
PACKAGE_JSON,
|
|
14
|
-
PACKAGE_JSON_TEMPLATE_PATH,
|
|
15
|
-
README_MD,
|
|
16
|
-
README_MD_TEMPLATES_PATH,
|
|
17
|
-
TEMPLATES_STATIC_DIR,
|
|
18
|
-
} from "../../constants";
|
|
19
|
-
import { execShell } from "../../exec";
|
|
20
|
-
import * as file from "../../file";
|
|
21
|
-
import { initGitRepository } from "./git";
|
|
22
|
-
|
|
23
|
-
export function createMod(
|
|
24
|
-
projectName: string,
|
|
25
|
-
projectPath: string,
|
|
26
|
-
createNewDir: boolean,
|
|
27
|
-
modsDirectory: string,
|
|
28
|
-
saveSlot: number,
|
|
29
|
-
gitRemoteURL: string | undefined,
|
|
30
|
-
skipNPMInstall: boolean,
|
|
31
|
-
verbose: boolean,
|
|
32
|
-
): void {
|
|
33
|
-
if (createNewDir) {
|
|
34
|
-
file.makeDir(projectPath, verbose);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const config = configFile.createObject(modsDirectory, saveSlot);
|
|
38
|
-
configFile.createFile(projectPath, config, verbose);
|
|
39
|
-
const targetModDirectory = path.join(config.modsDirectory, projectName);
|
|
40
|
-
|
|
41
|
-
makeSubdirectories(projectPath, verbose);
|
|
42
|
-
copyStaticFiles(projectPath, verbose);
|
|
43
|
-
copyDynamicFiles(projectName, projectPath, targetModDirectory, verbose);
|
|
44
|
-
updateNodeModules(projectPath, verbose);
|
|
45
|
-
installNodeModules(projectPath, skipNPMInstall, verbose);
|
|
46
|
-
formatFiles(projectPath, verbose);
|
|
47
|
-
|
|
48
|
-
// Only make the initial commit once all of the files have been copied and formatted
|
|
49
|
-
initGitRepository(projectPath, gitRemoteURL, verbose);
|
|
50
|
-
|
|
51
|
-
console.log(`Successfully created mod: ${chalk.green(projectName)}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function makeSubdirectories(projectPath: string, verbose: boolean) {
|
|
55
|
-
// The "src" directory is created during copying of static files.
|
|
56
|
-
for (const subdirectory of ["mod"]) {
|
|
57
|
-
const srcPath = path.join(projectPath, subdirectory);
|
|
58
|
-
file.makeDir(srcPath, verbose);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Copy static files, like ".eslintrc.js", "tsconfig.json", etc. */
|
|
63
|
-
function copyStaticFiles(projectPath: string, verbose: boolean) {
|
|
64
|
-
const staticFileList = file.getDirList(TEMPLATES_STATIC_DIR, verbose);
|
|
65
|
-
staticFileList.forEach((fileName: string) => {
|
|
66
|
-
const templateFilePath = path.join(TEMPLATES_STATIC_DIR, fileName);
|
|
67
|
-
const destinationFilePath = path.join(projectPath, fileName);
|
|
68
|
-
if (!file.exists(destinationFilePath, verbose)) {
|
|
69
|
-
file.copy(templateFilePath, destinationFilePath, verbose);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Rename ".cspell.json.template" to ".cspell.json.template". (If it is kept as ".cspell.json",
|
|
74
|
-
// then local spell checking will fail.)
|
|
75
|
-
const cSpellConfigPath = path.join(projectPath, ".cspell.json.template");
|
|
76
|
-
const correctCSpellConfigPath = path.join(projectPath, ".cspell.json");
|
|
77
|
-
file.rename(cSpellConfigPath, correctCSpellConfigPath, verbose);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Copy files that need to have text replaced inside of them. */
|
|
81
|
-
function copyDynamicFiles(
|
|
82
|
-
projectName: string,
|
|
83
|
-
projectPath: string,
|
|
84
|
-
targetModDirectory: string,
|
|
85
|
-
verbose: boolean,
|
|
86
|
-
) {
|
|
87
|
-
// ".gitignore"
|
|
88
|
-
{
|
|
89
|
-
const fileName = GITIGNORE;
|
|
90
|
-
const templatePath = GITIGNORE_TEMPLATE_PATH;
|
|
91
|
-
const template = file.read(templatePath, verbose);
|
|
92
|
-
|
|
93
|
-
// Prepend a header with the project name
|
|
94
|
-
let separatorLine = "# ";
|
|
95
|
-
for (let i = 0; i < projectName.length; i++) {
|
|
96
|
-
separatorLine += "-";
|
|
97
|
-
}
|
|
98
|
-
separatorLine += "\n";
|
|
99
|
-
const gitignoreHeader = `${separatorLine}# ${projectName}\n${separatorLine}\n`;
|
|
100
|
-
const gitignore = gitignoreHeader + template;
|
|
101
|
-
|
|
102
|
-
const destinationPath = path.join(projectPath, `.${fileName}`); // We need to prepend a period
|
|
103
|
-
file.write(destinationPath, gitignore, verbose);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// "package.json"
|
|
107
|
-
{
|
|
108
|
-
// Modify and copy the file
|
|
109
|
-
const fileName = PACKAGE_JSON;
|
|
110
|
-
const templatePath = PACKAGE_JSON_TEMPLATE_PATH;
|
|
111
|
-
const template = file.read(templatePath, verbose);
|
|
112
|
-
const packageJSON = template.replace(/MOD-NAME-TO-REPLACE/g, projectName);
|
|
113
|
-
const destinationPath = path.join(projectPath, fileName);
|
|
114
|
-
file.write(destinationPath, packageJSON, verbose);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// "README.md"
|
|
118
|
-
{
|
|
119
|
-
const fileName = README_MD;
|
|
120
|
-
const templatePath = README_MD_TEMPLATES_PATH;
|
|
121
|
-
const template = file.read(templatePath, verbose);
|
|
122
|
-
const readmeMD = template.replace(/MOD-NAME-TO-REPLACE/g, projectName);
|
|
123
|
-
const destinationPath = path.join(projectPath, fileName);
|
|
124
|
-
file.write(destinationPath, readmeMD, verbose);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// "mod/metadata.xml"
|
|
128
|
-
{
|
|
129
|
-
const fileName = METADATA_XML;
|
|
130
|
-
const templatePath = METADATA_XML_TEMPLATE_PATH;
|
|
131
|
-
const template = file.read(templatePath, verbose);
|
|
132
|
-
const metadataXML = template.replace(/MOD-NAME-TO-REPLACE/g, projectName);
|
|
133
|
-
const modPath = path.join(projectPath, "mod");
|
|
134
|
-
const destinationPath = path.join(modPath, fileName);
|
|
135
|
-
file.write(destinationPath, metadataXML, verbose);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// "mod/metadata.vdf"
|
|
139
|
-
{
|
|
140
|
-
const fileName = METADATA_VDF;
|
|
141
|
-
const templatePath = METADATA_VDF_TEMPLATE_PATH;
|
|
142
|
-
const template = file.read(templatePath, verbose);
|
|
143
|
-
const metadataVDF = template.replace(/MOD-TARGET-DIR/g, targetModDirectory);
|
|
144
|
-
const modPath = path.join(projectPath, "mod");
|
|
145
|
-
const destinationPath = path.join(modPath, fileName);
|
|
146
|
-
file.write(destinationPath, metadataVDF, verbose);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// "src/main.ts"
|
|
150
|
-
{
|
|
151
|
-
// Convert snake_case and kebab-case to camelCase. (Kebab-case in particular will make the
|
|
152
|
-
// example TypeScript file fail to compile.)
|
|
153
|
-
const srcPath = path.join(projectPath, "src");
|
|
154
|
-
const fileName = MAIN_TS;
|
|
155
|
-
const templatePath = MAIN_TS_TEMPLATE_PATH;
|
|
156
|
-
const template = file.read(templatePath, verbose);
|
|
157
|
-
const mainTS = template.replace(/MOD-NAME-TO-REPLACE/g, projectName);
|
|
158
|
-
const destinationPath = path.join(srcPath, fileName);
|
|
159
|
-
file.write(destinationPath, mainTS, verbose);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** The "package.json" file has to be copied first before this step. */
|
|
164
|
-
function updateNodeModules(projectPath: string, verbose: boolean) {
|
|
165
|
-
console.log("Finding out the latest versions of the NPM packages...");
|
|
166
|
-
execShell(
|
|
167
|
-
"npx",
|
|
168
|
-
["npm-check-updates", "--upgrade", "--packageFile", "package.json"],
|
|
169
|
-
verbose,
|
|
170
|
-
false,
|
|
171
|
-
projectPath,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function installNodeModules(
|
|
176
|
-
projectPath: string,
|
|
177
|
-
skipNPMInstall: boolean,
|
|
178
|
-
verbose: boolean,
|
|
179
|
-
) {
|
|
180
|
-
if (skipNPMInstall) {
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
console.log("Installing node modules... (This can take a long time.)");
|
|
185
|
-
execShell("npm", ["install"], verbose, false, projectPath);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function formatFiles(projectPath: string, verbose: boolean) {
|
|
189
|
-
execShell(
|
|
190
|
-
"npx",
|
|
191
|
-
["prettier", "--write", projectPath],
|
|
192
|
-
verbose,
|
|
193
|
-
false,
|
|
194
|
-
projectPath,
|
|
195
|
-
);
|
|
196
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { HOME_DIR } from "../../constants";
|
|
4
|
-
import * as file from "../../file";
|
|
5
|
-
import { getInputString } from "../../prompt";
|
|
6
|
-
import { error } from "../../utils";
|
|
7
|
-
|
|
8
|
-
const MODS = "mods";
|
|
9
|
-
|
|
10
|
-
const DEFAULT_MODS_PATH_WINDOWS = path.join(
|
|
11
|
-
"C:",
|
|
12
|
-
"Program Files (x86)",
|
|
13
|
-
"Steam",
|
|
14
|
-
"steamapps",
|
|
15
|
-
"common",
|
|
16
|
-
"The Binding of Isaac Rebirth",
|
|
17
|
-
MODS,
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
/** This is a subdirectory of `$HOME`. */
|
|
21
|
-
const DEFAULT_MODS_PATH_LINUX = path.join(
|
|
22
|
-
HOME_DIR,
|
|
23
|
-
".local",
|
|
24
|
-
"share",
|
|
25
|
-
"Steam",
|
|
26
|
-
"steamapps",
|
|
27
|
-
"common",
|
|
28
|
-
"The Binding of Isaac Rebirth",
|
|
29
|
-
MODS,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
export async function getModsDir(
|
|
33
|
-
argv: Record<string, unknown>,
|
|
34
|
-
verbose: boolean,
|
|
35
|
-
): Promise<string> {
|
|
36
|
-
if (argv["modsDirectory"] !== undefined) {
|
|
37
|
-
// They specified the "--mods-directory" command-line flag, so there is no need to prompt the
|
|
38
|
-
// user for it.
|
|
39
|
-
return argv["modsDirectory"] as string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const defaultModsPath = getDefaultModsPath(process.platform);
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
file.exists(defaultModsPath, verbose) &&
|
|
46
|
-
file.isDir(defaultModsPath, verbose)
|
|
47
|
-
) {
|
|
48
|
-
return defaultModsPath;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
console.error(
|
|
52
|
-
`Failed to find your mods directory at: ${chalk.green(defaultModsPath)}`,
|
|
53
|
-
);
|
|
54
|
-
const modsDir = await getInputString(
|
|
55
|
-
`Enter the full path to the "${MODS}" directory on your system, which should be next to your "isaac-ng.exe" program:`,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
if (modsDir === "") {
|
|
59
|
-
error("Error: You did not provide a response; exiting.");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!file.exists(modsDir, verbose)) {
|
|
63
|
-
error(
|
|
64
|
-
`Error: The directory of "${chalk.green(
|
|
65
|
-
modsDir,
|
|
66
|
-
)}" does not exist. Exiting.`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!file.isDir(modsDir, verbose)) {
|
|
71
|
-
error(
|
|
72
|
-
`Error: The path of "${chalk.green(
|
|
73
|
-
modsDir,
|
|
74
|
-
)}" is not a directory. Exiting.`,
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (path.basename(modsDir) !== MODS) {
|
|
79
|
-
error(
|
|
80
|
-
`Error: You entered a path of "${chalk.green(
|
|
81
|
-
modsDir,
|
|
82
|
-
)}", but you need to input a directory with a name of "${MODS}" at the end. Exiting.`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return modsDir;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function getDefaultModsPath(platform: string) {
|
|
90
|
-
switch (platform) {
|
|
91
|
-
case "win32": {
|
|
92
|
-
return DEFAULT_MODS_PATH_WINDOWS;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
case "linux": {
|
|
96
|
-
return DEFAULT_MODS_PATH_LINUX;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
default: {
|
|
100
|
-
return error(
|
|
101
|
-
`There does not exist a default mod path for the platform of: ${chalk.green(
|
|
102
|
-
platform,
|
|
103
|
-
)}`,
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { CURRENT_DIRECTORY_NAME, CWD } from "../../constants";
|
|
4
|
-
import { getInputString, getInputYesNo } from "../../prompt";
|
|
5
|
-
import { error, hasWhiteSpace, isKebabCase } from "../../utils";
|
|
6
|
-
|
|
7
|
-
// From: https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3
|
|
8
|
-
const ILLEGAL_CHARACTERS_FOR_WINDOWS_FILENAMES = [
|
|
9
|
-
"<",
|
|
10
|
-
">",
|
|
11
|
-
":",
|
|
12
|
-
'"',
|
|
13
|
-
"/",
|
|
14
|
-
"\\",
|
|
15
|
-
"|",
|
|
16
|
-
"?",
|
|
17
|
-
"*",
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
export async function getProjectPath(
|
|
21
|
-
argv: Record<string, unknown>,
|
|
22
|
-
useCurrentDir: boolean,
|
|
23
|
-
yes: boolean,
|
|
24
|
-
forceName: boolean,
|
|
25
|
-
): Promise<[string, boolean]> {
|
|
26
|
-
let projectName = getProjectNameFromCommandLineArgument(argv);
|
|
27
|
-
let projectPath: string;
|
|
28
|
-
let createNewDir: boolean;
|
|
29
|
-
if (useCurrentDir) {
|
|
30
|
-
// The "--use-current-dir" command-line flag was specified, so there is no need to prompt the
|
|
31
|
-
// user.
|
|
32
|
-
projectName = CURRENT_DIRECTORY_NAME;
|
|
33
|
-
projectPath = CWD;
|
|
34
|
-
createNewDir = false;
|
|
35
|
-
} else if (projectName !== undefined) {
|
|
36
|
-
// The project name was specified on the command-line.
|
|
37
|
-
projectPath = path.join(CWD, projectName);
|
|
38
|
-
createNewDir = true;
|
|
39
|
-
} else if (yes) {
|
|
40
|
-
// The "--yes" command-line flag was specified and the project name was not specified on the
|
|
41
|
-
// command-line, so default to using the current directory.
|
|
42
|
-
projectName = CURRENT_DIRECTORY_NAME;
|
|
43
|
-
projectPath = CWD;
|
|
44
|
-
createNewDir = false;
|
|
45
|
-
} else {
|
|
46
|
-
// The project name was not specified on the command-line, so prompt the user for it.
|
|
47
|
-
[projectName, projectPath, createNewDir] = await getNewProjectName();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
validateProjectName(projectName, forceName);
|
|
51
|
-
|
|
52
|
-
console.log(`Using a project name of: ${chalk.green(projectName)}`);
|
|
53
|
-
return [projectPath, createNewDir];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function getProjectNameFromCommandLineArgument(
|
|
57
|
-
argv: Record<string, unknown>,
|
|
58
|
-
): string | undefined {
|
|
59
|
-
const name = argv["name"];
|
|
60
|
-
return typeof name === "string" && name !== "" ? name : undefined;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function getNewProjectName(): Promise<[string, string, boolean]> {
|
|
64
|
-
console.log("You did not specify a project name as a command-line argument.");
|
|
65
|
-
const shouldUseCurrentDir = await getInputYesNo(
|
|
66
|
-
`Would you like to create a new project using the current directory "${chalk.green(
|
|
67
|
-
CURRENT_DIRECTORY_NAME,
|
|
68
|
-
)}" as the root?`,
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
if (shouldUseCurrentDir) {
|
|
72
|
-
return [CURRENT_DIRECTORY_NAME, CWD, false];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const projectName = await getInputString("Enter the name of the project:");
|
|
76
|
-
const projectPath = path.join(CWD, projectName);
|
|
77
|
-
|
|
78
|
-
return [projectName, projectPath, true];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function validateProjectName(projectName: string, forceName: boolean) {
|
|
82
|
-
if (projectName === "") {
|
|
83
|
-
error("Error: You cannot have a blank project name.");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (process.platform === "win32") {
|
|
87
|
-
for (const character of ILLEGAL_CHARACTERS_FOR_WINDOWS_FILENAMES) {
|
|
88
|
-
if (projectName.includes(character)) {
|
|
89
|
-
error(
|
|
90
|
-
`Error: The "${character}" character is not allowed in a Windows file name.`,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (forceName) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (hasWhiteSpace(projectName)) {
|
|
101
|
-
error(
|
|
102
|
-
'Error: The project name has whitespace in it, which is not allowed. Use kebab-case for your project name. (e.g. "green-candle")',
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (!isKebabCase(projectName)) {
|
|
107
|
-
error(
|
|
108
|
-
'Error: The project name is not in kebab-case. (Kebab-case is the style of using all lowercase letters, with words separated by hyphens.) Project names must use kebab-case to match GitHub repository standards. If necessary, you can override this check with the "--force-name" flag.',
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
package/src/commands/init/git.ts
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import commandExists from "command-exists";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import yaml from "yaml";
|
|
5
|
-
import { PROJECT_NAME } from "../../constants";
|
|
6
|
-
import { execShell } from "../../exec";
|
|
7
|
-
import * as file from "../../file";
|
|
8
|
-
import { getInputString, getInputYesNo } from "../../prompt";
|
|
9
|
-
import { GitHubCLIHostsYAML } from "../../types/GitHubCLIHostsYAML";
|
|
10
|
-
import { error, parseSemVer } from "../../utils";
|
|
11
|
-
|
|
12
|
-
const REQUIRED_GIT_MAJOR_VERSION = 2;
|
|
13
|
-
const REQUIRED_GIT_MINOR_VERSION = 30;
|
|
14
|
-
|
|
15
|
-
export async function promptGitHubRepoOrGitRemoteURL(
|
|
16
|
-
projectName: string,
|
|
17
|
-
yes: boolean,
|
|
18
|
-
verbose: boolean,
|
|
19
|
-
): Promise<string | undefined> {
|
|
20
|
-
// We do not need to prompt the user if they do not have Git installed
|
|
21
|
-
if (!commandExists.sync("git")) {
|
|
22
|
-
console.log(
|
|
23
|
-
'Git does not seem to be installed. (The "git" command is not in the path.) Skipping Git-related things.',
|
|
24
|
-
);
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
validateNewGitVersion(verbose);
|
|
29
|
-
|
|
30
|
-
const gitHubUsername = getGitHubUsername(verbose);
|
|
31
|
-
if (gitHubUsername !== undefined) {
|
|
32
|
-
const [exitStatus] = execShell(
|
|
33
|
-
"gh",
|
|
34
|
-
["repo", "view", projectName],
|
|
35
|
-
verbose,
|
|
36
|
-
true,
|
|
37
|
-
);
|
|
38
|
-
const gitHubRepoExists = exitStatus === 0;
|
|
39
|
-
const url = `https://github.com/${gitHubUsername}/${projectName}`;
|
|
40
|
-
|
|
41
|
-
if (gitHubRepoExists) {
|
|
42
|
-
console.log(
|
|
43
|
-
`Detected an existing GitHub repository at: ${chalk.green(url)}`,
|
|
44
|
-
);
|
|
45
|
-
const guessedRemoteURL = getGitRemoteURL(projectName, gitHubUsername);
|
|
46
|
-
|
|
47
|
-
if (yes) {
|
|
48
|
-
console.log(
|
|
49
|
-
`Using a Git remote URL of: ${chalk.green(guessedRemoteURL)}`,
|
|
50
|
-
);
|
|
51
|
-
return guessedRemoteURL;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const shouldUseGuessedURL = await getInputYesNo(
|
|
55
|
-
`Do you want to use a Git remote URL of: ${chalk.green(
|
|
56
|
-
guessedRemoteURL,
|
|
57
|
-
)}`,
|
|
58
|
-
);
|
|
59
|
-
if (shouldUseGuessedURL) {
|
|
60
|
-
return guessedRemoteURL;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Assume that since they do not want to connect this project to the existing GitHub
|
|
64
|
-
// repository, they do not want to initialize a remote Git URL at all.
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (yes) {
|
|
69
|
-
execShell("gh", ["repo", "create", projectName, "--public"]);
|
|
70
|
-
console.log(`Created a new GitHub repository at: ${chalk.green(url)}`);
|
|
71
|
-
return getGitRemoteURL(projectName, gitHubUsername);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const createNewGitHubRepo = await getInputYesNo(
|
|
75
|
-
`Would you like to create a new GitHub repository at: ${chalk.green(
|
|
76
|
-
url,
|
|
77
|
-
)}`,
|
|
78
|
-
);
|
|
79
|
-
if (createNewGitHubRepo) {
|
|
80
|
-
execShell("gh", ["repo", "create", projectName, "--public"]);
|
|
81
|
-
console.log("Successfully created a new GitHub repository.");
|
|
82
|
-
return getGitRemoteURL(projectName, gitHubUsername);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Assume that since they do not want to create a new GitHub repository, they do not want to
|
|
86
|
-
// initialize a remote Git URL at all.
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const gitRemoteURL =
|
|
91
|
-
await getInputString(`Paste in the remote Git URL for your project.
|
|
92
|
-
For example, if you have an SSH key, it would be something like:
|
|
93
|
-
${chalk.green("git@github.com:Alice/green-candle.git")}
|
|
94
|
-
If you don't have an SSH key, it would be something like:
|
|
95
|
-
${chalk.green("https://github.com/Alice/green-candle.git")}
|
|
96
|
-
If you don't want to initialize a Git repository for this project, press enter to skip.
|
|
97
|
-
`);
|
|
98
|
-
|
|
99
|
-
return gitRemoteURL === "" ? undefined : gitRemoteURL;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function validateNewGitVersion(verbose: boolean) {
|
|
103
|
-
const [, stdout] = execShell("git", ["--version"], verbose);
|
|
104
|
-
|
|
105
|
-
const outputPrefix = "git version ";
|
|
106
|
-
if (!stdout.startsWith(outputPrefix)) {
|
|
107
|
-
error(
|
|
108
|
-
`Failed to parse the output from the "git --version" command: ${stdout}`,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const gitVersionString = stdout.slice(outputPrefix.length);
|
|
113
|
-
const [majorVersion, minorVersion] = parseSemVer(gitVersionString);
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
majorVersion >= REQUIRED_GIT_MAJOR_VERSION &&
|
|
117
|
-
minorVersion >= REQUIRED_GIT_MINOR_VERSION
|
|
118
|
-
) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
console.error(`Your Git version is: ${chalk.red(gitVersionString)}`);
|
|
123
|
-
console.error(
|
|
124
|
-
`${PROJECT_NAME} requires a Git version of ${chalk.red(
|
|
125
|
-
`${REQUIRED_GIT_MAJOR_VERSION}.${REQUIRED_GIT_MINOR_VERSION}.0`,
|
|
126
|
-
)} or greater.`,
|
|
127
|
-
);
|
|
128
|
-
console.error(
|
|
129
|
-
`Please upgrade your version of Git before using ${PROJECT_NAME}.`,
|
|
130
|
-
);
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function getGitHubUsername(verbose: boolean) {
|
|
135
|
-
// If the GitHub CLI is installed, we can derive the user's GitHub username
|
|
136
|
-
if (!commandExists.sync("gh")) {
|
|
137
|
-
return undefined;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const appData = process.env["APPDATA"];
|
|
141
|
-
if (appData === undefined || appData === "") {
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const githubCLIHostsPath = path.join(appData, "GitHub CLI", "hosts.yml");
|
|
146
|
-
if (!file.exists(githubCLIHostsPath, verbose)) {
|
|
147
|
-
return undefined;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const configYAMLRaw = file.read(githubCLIHostsPath, verbose);
|
|
151
|
-
const configYAML = yaml.parse(configYAMLRaw) as GitHubCLIHostsYAML;
|
|
152
|
-
|
|
153
|
-
const githubCom = configYAML["github.com"];
|
|
154
|
-
if (githubCom === undefined) {
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const { user } = githubCom;
|
|
159
|
-
if (user === undefined || user === "") {
|
|
160
|
-
return undefined;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return user;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function getGitRemoteURL(projectName: string, gitHubUsername: string) {
|
|
167
|
-
return `git@github.com:${gitHubUsername}/${projectName}.git`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function initGitRepository(
|
|
171
|
-
projectPath: string,
|
|
172
|
-
gitRemoteURL: string | undefined,
|
|
173
|
-
verbose: boolean,
|
|
174
|
-
): void {
|
|
175
|
-
if (!commandExists.sync("git")) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (gitRemoteURL === undefined) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
execShell("git", ["init"], verbose, false, projectPath);
|
|
184
|
-
execShell("git", ["branch", "-M", "main"], verbose, false, projectPath);
|
|
185
|
-
|
|
186
|
-
if (isGitNameAndEmailConfigured(verbose)) {
|
|
187
|
-
execShell("git", ["add", "--all"], verbose, false, projectPath);
|
|
188
|
-
execShell(
|
|
189
|
-
"git",
|
|
190
|
-
["commit", "--message", `${PROJECT_NAME} template`],
|
|
191
|
-
verbose,
|
|
192
|
-
false,
|
|
193
|
-
projectPath,
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (gitRemoteURL !== undefined) {
|
|
198
|
-
execShell(
|
|
199
|
-
"git",
|
|
200
|
-
["remote", "add", "origin", gitRemoteURL],
|
|
201
|
-
verbose,
|
|
202
|
-
false,
|
|
203
|
-
projectPath,
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function isGitNameAndEmailConfigured(verbose: boolean) {
|
|
209
|
-
const [nameExitStatus] = execShell(
|
|
210
|
-
"git",
|
|
211
|
-
["config", "--global", "user.name"],
|
|
212
|
-
verbose,
|
|
213
|
-
true,
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
const [emailExitStatus] = execShell(
|
|
217
|
-
"git",
|
|
218
|
-
["config", "--global", "user.email"],
|
|
219
|
-
verbose,
|
|
220
|
-
true,
|
|
221
|
-
);
|
|
222
|
-
|
|
223
|
-
return nameExitStatus === 0 && emailExitStatus === 0;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export function isGitDirty(verbose: boolean): boolean {
|
|
227
|
-
// From: https://remarkablemark.org/blog/2017/10/12/check-git-dirty/
|
|
228
|
-
const [, stdout] = execShell("git", ["status", "--porcelain"], verbose);
|
|
229
|
-
return stdout !== "";
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
export function gitCommitIfChanges(version: string, verbose: boolean): void {
|
|
233
|
-
// Throw an error if this is not a git repository
|
|
234
|
-
execShell("git", ["status"], verbose);
|
|
235
|
-
|
|
236
|
-
if (!isGitDirty(verbose)) {
|
|
237
|
-
console.log("There are no changes to commit.");
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const commitMessage = `v${version}`;
|
|
242
|
-
execShell("git", ["add", "-A"], verbose);
|
|
243
|
-
execShell("git", ["commit", "-m", commitMessage], verbose);
|
|
244
|
-
execShell("git", ["push"], verbose);
|
|
245
|
-
|
|
246
|
-
console.log(
|
|
247
|
-
`Committed and pushed to the git repository with a message of: ${commitMessage}`,
|
|
248
|
-
);
|
|
249
|
-
}
|