isaacscript 1.1.55 → 1.1.59

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.
Files changed (78) hide show
  1. package/.cspell.json +1 -3
  2. package/.eslintrc.js +1 -15
  3. package/.vscode/extensions.json +1 -0
  4. package/.vscode/settings.json +4 -0
  5. package/dist/package.json +8 -6
  6. package/dist/src/checkForWindowsTerminalBugs.js +20 -52
  7. package/dist/src/checkForWindowsTerminalBugs.js.map +1 -1
  8. package/dist/src/commands/init/checkIfProjectPathExists.js +3 -7
  9. package/dist/src/commands/init/checkIfProjectPathExists.js.map +1 -1
  10. package/dist/src/commands/init/checkModTargetDirectory.js +3 -8
  11. package/dist/src/commands/init/checkModTargetDirectory.js.map +1 -1
  12. package/dist/src/commands/init/createMod.js +85 -11
  13. package/dist/src/commands/init/createMod.js.map +1 -1
  14. package/dist/src/commands/init/getModsDir.js +6 -13
  15. package/dist/src/commands/init/getModsDir.js.map +1 -1
  16. package/dist/src/commands/init/getProjectPath.js +4 -17
  17. package/dist/src/commands/init/getProjectPath.js.map +1 -1
  18. package/dist/src/commands/init/init.js +18 -15
  19. package/dist/src/commands/init/init.js.map +1 -1
  20. package/dist/src/commands/init/promptSaveSlot.js +4 -14
  21. package/dist/src/commands/init/promptSaveSlot.js.map +1 -1
  22. package/dist/src/commands/init/promptVSCode.js +3 -8
  23. package/dist/src/commands/init/promptVSCode.js.map +1 -1
  24. package/dist/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js +0 -1
  25. package/dist/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js.map +1 -1
  26. package/dist/src/commands/monitor/monitor.js +10 -4
  27. package/dist/src/commands/monitor/monitor.js.map +1 -1
  28. package/dist/src/commands/monitor/saveDatWriter/saveDatWriter.js +0 -1
  29. package/dist/src/commands/monitor/saveDatWriter/saveDatWriter.js.map +1 -1
  30. package/dist/src/commands/publish/publish.js +4 -4
  31. package/dist/src/commands/publish/publish.js.map +1 -1
  32. package/dist/src/constants.js +5 -1
  33. package/dist/src/constants.js.map +1 -1
  34. package/dist/src/main.js +2 -0
  35. package/dist/src/main.js.map +1 -1
  36. package/dist/src/monkeyPatch.js +2 -1
  37. package/dist/src/monkeyPatch.js.map +1 -1
  38. package/dist/src/parseArgs.js +62 -58
  39. package/dist/src/parseArgs.js.map +1 -1
  40. package/dist/src/plugins/addCrashDebugStatements.js +31 -0
  41. package/dist/src/plugins/addCrashDebugStatements.js.map +1 -0
  42. package/dist/src/prompt.js +90 -0
  43. package/dist/src/prompt.js.map +1 -0
  44. package/dist/src/types/GitHubCLIHostsYAML.js +3 -0
  45. package/dist/src/types/GitHubCLIHostsYAML.js.map +1 -0
  46. package/dist/src/util.js +6 -26
  47. package/dist/src/util.js.map +1 -1
  48. package/file-templates/dynamic/README.md +2 -2
  49. package/file-templates/dynamic/main.ts +4 -2
  50. package/file-templates/dynamic/metadata.xml +3 -3
  51. package/file-templates/dynamic/package.json +1 -1
  52. package/file-templates/static/.github/workflows/ci.yml +3 -0
  53. package/file-templates/static/.vscode/extensions.json +1 -0
  54. package/file-templates/static/.vscode/settings.json +4 -0
  55. package/file-templates/static/lint.sh +16 -9
  56. package/lint.sh +6 -10
  57. package/package.json +8 -6
  58. package/src/checkForWindowsTerminalBugs.ts +35 -73
  59. package/src/commands/init/checkIfProjectPathExists.ts +4 -7
  60. package/src/commands/init/checkModTargetDirectory.ts +7 -9
  61. package/src/commands/init/createMod.ts +132 -13
  62. package/src/commands/init/getModsDir.ts +8 -14
  63. package/src/commands/init/getProjectPath.ts +7 -19
  64. package/src/commands/init/init.ts +25 -13
  65. package/src/commands/init/promptSaveSlot.ts +6 -13
  66. package/src/commands/init/promptVSCode.ts +5 -9
  67. package/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.ts +0 -2
  68. package/src/commands/monitor/monitor.ts +13 -4
  69. package/src/commands/monitor/saveDatWriter/saveDatWriter.ts +0 -2
  70. package/src/commands/publish/publish.ts +4 -4
  71. package/src/constants.ts +5 -0
  72. package/src/main.ts +2 -0
  73. package/src/monkeyPatch.ts +2 -1
  74. package/src/parseArgs.ts +34 -28
  75. package/src/plugins/addCrashDebugStatements.ts +29 -0
  76. package/src/prompt.ts +110 -0
  77. package/src/types/GitHubCLIHostsYAML.ts +7 -0
  78. package/src/util.ts +6 -28
@@ -1,4 +1,7 @@
1
+ import chalk from "chalk";
2
+ import commandExists from "command-exists";
1
3
  import path from "path";
4
+ import yaml from "yaml";
2
5
  import * as configFile from "../../configFile";
3
6
  import {
4
7
  GITIGNORE,
@@ -16,15 +19,18 @@ import {
16
19
  TEMPLATES_STATIC_DIR,
17
20
  } from "../../constants";
18
21
  import * as file from "../../file";
19
- import { execShell, snakeKebabToCamel } from "../../util";
22
+ import { getInputString, getInputYesNo } from "../../prompt";
23
+ import { GitHubCLIHostsYAML } from "../../types/GitHubCLIHostsYAML";
24
+ import { execShell } from "../../util";
20
25
 
21
- export function createMod(
26
+ export async function createMod(
22
27
  projectName: string,
23
28
  projectPath: string,
24
29
  createNewDir: boolean,
25
30
  modsDirectory: string,
26
31
  saveSlot: number,
27
- ): void {
32
+ skipNPMInstall: boolean,
33
+ ): Promise<void> {
28
34
  if (createNewDir) {
29
35
  file.makeDir(projectPath);
30
36
  }
@@ -37,7 +43,10 @@ export function createMod(
37
43
  copyStaticFiles(projectPath);
38
44
  copyDynamicFiles(projectName, projectPath, targetModDirectory);
39
45
  updateNodeModules(projectPath);
40
- installNodeModules(projectPath);
46
+ await initGitRepository(projectPath, projectName);
47
+ installNodeModules(projectPath, skipNPMInstall);
48
+
49
+ console.log(`Successfully created mod: ${chalk.green(projectName)}`);
41
50
  }
42
51
 
43
52
  function makeSubdirectories(projectPath: string) {
@@ -91,7 +100,7 @@ function copyDynamicFiles(
91
100
  const fileName = PACKAGE_JSON;
92
101
  const templatePath = PACKAGE_JSON_TEMPLATE_PATH;
93
102
  const template = file.read(templatePath);
94
- const packageJSON = template.replace(/MOD_NAME/g, projectName);
103
+ const packageJSON = template.replace(/MOD_NAME_TO_REPLACE/g, projectName);
95
104
  const destinationPath = path.join(projectPath, fileName);
96
105
  file.write(destinationPath, packageJSON);
97
106
  }
@@ -101,7 +110,7 @@ function copyDynamicFiles(
101
110
  const fileName = README_MD;
102
111
  const templatePath = README_MD_TEMPLATES_PATH;
103
112
  const template = file.read(templatePath);
104
- const readmeMD = template.replace(/MOD_NAME/g, projectName);
113
+ const readmeMD = template.replace(/MOD_NAME_TO_REPLACE/g, projectName);
105
114
  const destinationPath = path.join(projectPath, fileName);
106
115
  file.write(destinationPath, readmeMD);
107
116
  }
@@ -111,7 +120,7 @@ function copyDynamicFiles(
111
120
  const fileName = METADATA_XML;
112
121
  const templatePath = METADATA_XML_TEMPLATE_PATH;
113
122
  const template = file.read(templatePath);
114
- const metadataXML = template.replace(/MOD_NAME/g, projectName);
123
+ const metadataXML = template.replace(/MOD_NAME_TO_REPLACE/g, projectName);
115
124
  const modPath = path.join(projectPath, "mod");
116
125
  const destinationPath = path.join(modPath, fileName);
117
126
  file.write(destinationPath, metadataXML);
@@ -133,20 +142,126 @@ function copyDynamicFiles(
133
142
  // Convert snake_case and kebab-case to camelCase
134
143
  // (kebab-case in particular will make the example TypeScript file fail to compile)
135
144
  const srcPath = path.join(projectPath, "src");
136
- const camelCaseProjectName = snakeKebabToCamel(projectName);
137
145
  const fileName = MAIN_TS;
138
146
  const templatePath = MAIN_TS_TEMPLATE_PATH;
139
147
  const template = file.read(templatePath);
140
- const mainTS = template
141
- .replace(/MOD_NAME initialized/g, `${projectName} initialized`)
142
- .replace(/MOD_NAME/g, camelCaseProjectName);
148
+ const mainTS = template.replace(/MOD_NAME_TO_REPLACE/g, projectName);
143
149
  const destinationPath = path.join(srcPath, fileName);
144
150
  file.write(destinationPath, mainTS);
145
151
  }
146
152
  }
147
153
 
154
+ async function initGitRepository(projectPath: string, projectName: string) {
155
+ if (!commandExists.sync("git")) {
156
+ console.log(
157
+ 'Git does not seem to be installed. (The "git" command is not in the path.) Skipping Git-related things.',
158
+ );
159
+ return;
160
+ }
161
+
162
+ const remoteURL = await getGitRemoteURL(projectName);
163
+ if (remoteURL === "") {
164
+ return;
165
+ }
166
+
167
+ execShell("git", ["init"], false, projectPath);
168
+ execShell("git", ["branch", "-M", "main"], false, projectPath);
169
+ execShell("git", ["remote", "add", "origin", remoteURL], false, projectPath);
170
+ if (isGitNameAndEmailConfigured()) {
171
+ execShell("git", ["add", "--all"], false, projectPath);
172
+ execShell(
173
+ "git",
174
+ ["commit", "--message", "IsaacScript template"],
175
+ false,
176
+ projectPath,
177
+ );
178
+ }
179
+ }
180
+
181
+ async function getGitRemoteURL(projectName: string) {
182
+ const guessedRemoteURL = guessRemoteURL(projectName);
183
+ if (guessedRemoteURL !== undefined) {
184
+ const shouldUseGuessedURL = await getInputYesNo(
185
+ `Do you want to use a Git remote URL of: ${chalk.green(
186
+ guessedRemoteURL,
187
+ )}`,
188
+ );
189
+ if (shouldUseGuessedURL) {
190
+ return guessedRemoteURL;
191
+ }
192
+ }
193
+
194
+ return getInputString(`Paste in the remote Git URL for your project.
195
+ For example, if you have an SSH key, it would be something like:
196
+ ${chalk.green("git@github.com:Alice/green-candle.git")}
197
+ If you don't have an SSH key, it would be something like:
198
+ ${chalk.green("https://github.com/Alice/green-candle.git")}
199
+ If you don't want to initialize a Git repository for this project, press enter to skip.
200
+ `);
201
+ }
202
+
203
+ function guessRemoteURL(projectName: string) {
204
+ const gitHubUsername = getGitHubUsername();
205
+ if (gitHubUsername === undefined) {
206
+ return undefined;
207
+ }
208
+
209
+ return `git@github.com:${gitHubUsername}/${projectName}.git`;
210
+ }
211
+
212
+ function getGitHubUsername() {
213
+ // If the GitHub CLI is installed, we can derive the user's GitHub username
214
+ if (
215
+ !commandExists.sync("gh") ||
216
+ process.env.APPDATA === undefined ||
217
+ process.env.APPDATA === ""
218
+ ) {
219
+ return undefined;
220
+ }
221
+
222
+ const githubCLIHostsPath = path.join(
223
+ process.env.APPDATA,
224
+ "GitHub CLI",
225
+ "hosts.yml",
226
+ );
227
+ if (!file.exists(githubCLIHostsPath)) {
228
+ return undefined;
229
+ }
230
+
231
+ const configYAMLRaw = file.read(githubCLIHostsPath);
232
+ const configYAML = yaml.parse(configYAMLRaw) as GitHubCLIHostsYAML;
233
+
234
+ const githubCom = configYAML["github.com"];
235
+ if (githubCom === undefined) {
236
+ return undefined;
237
+ }
238
+
239
+ const { user } = githubCom;
240
+ if (user === "") {
241
+ return undefined;
242
+ }
243
+
244
+ return user;
245
+ }
246
+
247
+ function isGitNameAndEmailConfigured() {
248
+ const [nameExitStatus] = execShell(
249
+ "git",
250
+ ["config", "--global", "user.name"],
251
+ true,
252
+ );
253
+
254
+ const [emailExitStatus] = execShell(
255
+ "git",
256
+ ["config", "--global", "user.email"],
257
+ true,
258
+ );
259
+
260
+ return nameExitStatus === 0 && emailExitStatus === 0;
261
+ }
262
+
148
263
  function updateNodeModules(projectPath: string) {
149
- console.log("Updating node modules...");
264
+ console.log("Finding out the latest versions of the IsaacScript packages...");
150
265
  execShell(
151
266
  "npx",
152
267
  ["npm-check-updates", "--upgrade", "--packageFile", "package.json"],
@@ -155,7 +270,11 @@ function updateNodeModules(projectPath: string) {
155
270
  );
156
271
  }
157
272
 
158
- function installNodeModules(projectPath: string) {
273
+ function installNodeModules(projectPath: string, skipNPMInstall: boolean) {
274
+ if (skipNPMInstall) {
275
+ return;
276
+ }
277
+
159
278
  console.log("Installing node modules... (This can take a long time.)");
160
279
  execShell("npm", ["install"], false, projectPath);
161
280
  }
@@ -1,13 +1,10 @@
1
1
  import chalk from "chalk";
2
- import os from "os";
3
2
  import path from "path";
4
- import prompts from "prompts";
3
+ import { HOME_DIR } from "../../constants";
5
4
  import * as file from "../../file";
5
+ import { getInputString } from "../../prompt";
6
6
  import { error } from "../../util";
7
7
 
8
- // https://stackoverflow.com/questions/9080085/node-js-find-home-directory-in-platform-agnostic-way
9
- const homeDir = os.homedir();
10
-
11
8
  const MODS = "mods";
12
9
 
13
10
  const DEFAULT_MODS_PATH_WINDOWS = path.join(
@@ -22,7 +19,7 @@ const DEFAULT_MODS_PATH_WINDOWS = path.join(
22
19
 
23
20
  // This is a subdirectory of $HOME
24
21
  const DEFAULT_MODS_PATH_LINUX = path.join(
25
- homeDir,
22
+ HOME_DIR,
26
23
  ".local",
27
24
  "share",
28
25
  "Steam",
@@ -50,16 +47,13 @@ export async function getModsDir(
50
47
  console.error(
51
48
  `Failed to find your mods directory at: ${chalk.green(defaultModsPath)}`,
52
49
  );
53
- const response = await prompts({
54
- type: "text",
55
- name: "modsDir",
56
- message: `Enter the full path to the "${MODS}" directory on your system, which should be next to your "isaac-ng.exe" program:`,
57
- });
50
+ const modsDir = await getInputString(
51
+ `Enter the full path to the "${MODS}" directory on your system, which should be next to your "isaac-ng.exe" program:`,
52
+ );
58
53
 
59
- if (typeof response.modsDir !== "string") {
60
- error("Error: The response was not a string.");
54
+ if (modsDir === "") {
55
+ error("Error: You did not provide a response; exiting.");
61
56
  }
62
- const modsDir = response.modsDir.trim();
63
57
 
64
58
  if (!file.exists(modsDir)) {
65
59
  error(
@@ -1,8 +1,8 @@
1
1
  import chalk from "chalk";
2
2
  import path from "path";
3
- import prompts from "prompts";
4
3
  import { CURRENT_DIRECTORY_NAME, CWD } from "../../constants";
5
- import { error, hasWhiteSpace } from "../../util";
4
+ import { getInputString, getInputYesNo } from "../../prompt";
5
+ import { hasWhiteSpace } from "../../util";
6
6
 
7
7
  // From: https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3
8
8
  const ILLEGAL_CHARACTERS_FOR_WINDOWS_FILENAMES = [
@@ -54,29 +54,17 @@ function getProjectNameFromCommandLineArgument(
54
54
 
55
55
  async function getNewProjectName(): Promise<[string, string, boolean]> {
56
56
  console.log("You did not specify a project name as a command-line argument.");
57
- const response1 = await prompts({
58
- type: "confirm",
59
- name: "useCurrentDir",
60
- message: `Would you like to create a new project using the current directory "${chalk.green(
57
+ const shouldUseCurrentDir = await getInputYesNo(
58
+ `Would you like to create a new project using the current directory "${chalk.green(
61
59
  CURRENT_DIRECTORY_NAME,
62
60
  )}" as the root?`,
63
- initial: true,
64
- });
61
+ );
65
62
 
66
- if (response1.useCurrentDir === true) {
63
+ if (shouldUseCurrentDir) {
67
64
  return [CURRENT_DIRECTORY_NAME, CWD, false];
68
65
  }
69
66
 
70
- const response2 = await prompts({
71
- type: "text",
72
- name: "projectName",
73
- message: "Enter the name of the project:",
74
- });
75
-
76
- if (typeof response2.projectName !== "string") {
77
- error("Error: The response was not a string.");
78
- }
79
- const projectName = response2.projectName.trim();
67
+ const projectName = await getInputString("Enter the name of the project:");
80
68
  const projectPath = path.join(CWD, projectName);
81
69
 
82
70
  return [projectName, projectPath, true];
@@ -21,28 +21,31 @@ export async function init(argv: Record<string, unknown>): Promise<void> {
21
21
  const projectName = path.basename(projectPath);
22
22
  await checkModTargetDirectory(modsDirectory, projectName);
23
23
  const saveSlot = await promptSaveSlot(argv);
24
+ const skipNPMInstall = argv.skipNpmInstall === true;
24
25
 
25
- // Begin the creation of the new mod
26
- createMod(projectName, projectPath, createNewDir, modsDirectory, saveSlot);
27
- console.log(`Successfully created mod: ${chalk.green(projectName)}`);
26
+ await createMod(
27
+ projectName,
28
+ projectPath,
29
+ createNewDir,
30
+ modsDirectory,
31
+ saveSlot,
32
+ skipNPMInstall,
33
+ );
34
+ await openVSCode(projectPath, argv);
35
+ printFinishMessage(projectPath, projectName);
36
+ }
28
37
 
38
+ async function openVSCode(projectPath: string, argv: Record<string, unknown>) {
29
39
  const VSCodeCommand = getVSCodeCommand();
30
40
  if (VSCodeCommand === null) {
31
41
  console.log(
32
42
  'VSCode does not seem to be installed. (The "code" command is not in the path.) Skipping VSCode-related things.',
33
43
  );
34
- } else {
35
- installVSCodeExtensions(projectPath, VSCodeCommand);
36
- await promptVSCode(projectPath, argv, VSCodeCommand);
44
+ return;
37
45
  }
38
46
 
39
- // Finished
40
- let commandsToType = "";
41
- if (projectPath !== CWD) {
42
- commandsToType += `"${chalk.green(`cd ${projectName}`)}" and `;
43
- }
44
- commandsToType += `"${chalk.green("npx isaacscript")}"`;
45
- console.log(`Now, start IsaacScript by typing ${commandsToType}.`);
47
+ installVSCodeExtensions(projectPath, VSCodeCommand);
48
+ await promptVSCode(projectPath, argv, VSCodeCommand);
46
49
  }
47
50
 
48
51
  function getVSCodeCommand() {
@@ -54,3 +57,12 @@ function getVSCodeCommand() {
54
57
 
55
58
  return null;
56
59
  }
60
+
61
+ function printFinishMessage(projectPath: string, projectName: string) {
62
+ let commandsToType = "";
63
+ if (projectPath !== CWD) {
64
+ commandsToType += `"${chalk.green(`cd ${projectName}`)}" and `;
65
+ }
66
+ commandsToType += `"${chalk.green("npx isaacscript")}"`;
67
+ console.log(`Now, start IsaacScript by typing ${commandsToType}.`);
68
+ }
@@ -1,4 +1,4 @@
1
- import prompts from "prompts";
1
+ import { getInputInt } from "../../prompt";
2
2
  import { error } from "../../util";
3
3
 
4
4
  export async function promptSaveSlot(
@@ -10,20 +10,13 @@ export async function promptSaveSlot(
10
10
  return argv.saveSlot as number;
11
11
  }
12
12
 
13
- const response = await prompts({
14
- type: "number",
15
- name: "saveSlot",
16
- message: "In-game, will you test your mod on save slot 1, 2, or 3?",
17
- initial: 1,
18
- });
13
+ const saveSlot = await getInputInt(
14
+ "In-game, will you test your mod on save slot 1, 2, or 3?",
15
+ );
19
16
 
20
- if (
21
- response.saveSlot !== 1 &&
22
- response.saveSlot !== 2 &&
23
- response.saveSlot !== 3
24
- ) {
17
+ if (saveSlot !== 1 && saveSlot !== 2 && saveSlot !== 3) {
25
18
  error("Error: You must choose a number between 1 and 3.");
26
19
  }
27
20
 
28
- return response.saveSlot as number;
21
+ return saveSlot;
29
22
  }
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
- import prompts from "prompts";
3
2
  import { MAIN_TS } from "../../constants";
3
+ import { getInputYesNo } from "../../prompt";
4
4
  import { execShell } from "../../util";
5
5
 
6
6
  export async function promptVSCode(
@@ -15,14 +15,10 @@ export async function promptVSCode(
15
15
  return;
16
16
  }
17
17
 
18
- const response = await prompts({
19
- type: "confirm",
20
- name: "VSCode",
21
- message: "Do you want to open your new project in VSCode now?",
22
- initial: true,
23
- });
24
-
25
- if (response.VSCode === true) {
18
+ const shouldOpenVSCode = await getInputYesNo(
19
+ "Do you want to open your new project in VSCode now?",
20
+ );
21
+ if (shouldOpenVSCode) {
26
22
  openVSCode(projectPath, VSCodeCommand);
27
23
  }
28
24
  }
@@ -1,5 +1,3 @@
1
- /* eslint-disable import/no-unused-modules */
2
-
3
1
  import path from "path";
4
2
  import syncDirectory from "sync-directory";
5
3
  import { FILE_SYNCED_MESSAGE, MAIN_LUA } from "../../../constants";
@@ -37,7 +37,7 @@ export function monitor(argv: Record<string, unknown>, config: Config): void {
37
37
  spawnModDirectorySyncer(config);
38
38
 
39
39
  // Subprocess #3 - tstl --watch (to automatically convert TypeScript to Lua)
40
- spawnTSTLWatcher();
40
+ spawnTSTLWatcher(argv);
41
41
 
42
42
  // Also, start constantly pinging the watcher mod
43
43
  setInterval(() => {
@@ -91,8 +91,17 @@ function spawnModDirectorySyncer(config: Config) {
91
91
  });
92
92
  }
93
93
 
94
- function spawnTSTLWatcher() {
94
+ function spawnTSTLWatcher(argv: Record<string, unknown>) {
95
95
  const processDescription = "tstl";
96
+ const crashDebug = argv.crashDebug === true;
97
+
98
+ const tstlArgs = ["--watch", "--preserveWatchOutput"];
99
+ if (crashDebug) {
100
+ tstlArgs.push("--luaPlugins");
101
+ tstlArgs.push(
102
+ '\'{ "name": "./node_modules/isaacscript/src/plugins/addCrashDebugStatements.ts" }\'',
103
+ );
104
+ }
96
105
 
97
106
  let tstl: ChildProcessWithoutNullStreams;
98
107
  if (runningFromLocalPath()) {
@@ -105,12 +114,12 @@ function spawnTSTLWatcher() {
105
114
  "dist",
106
115
  "tstl.js",
107
116
  );
108
- tstl = spawn("node", [tstlPath, "--watch", "--preserveWatchOutput"], {
117
+ tstl = spawn("node", [tstlPath, ...tstlArgs], {
109
118
  shell: true,
110
119
  cwd: CWD,
111
120
  });
112
121
  } else {
113
- tstl = spawn("npx", ["tstl", "--watch", "--preserveWatchOutput"], {
122
+ tstl = spawn("npx", ["tstl", ...tstlArgs], {
114
123
  shell: true,
115
124
  });
116
125
  }
@@ -1,5 +1,3 @@
1
- /* eslint-disable import/no-unused-modules */
2
-
3
1
  import chalk from "chalk";
4
2
  import * as JSONC from "jsonc-parser";
5
3
  import path from "path";
@@ -24,9 +24,9 @@ const UPDATE_SCRIPT_NAME = "update.sh";
24
24
 
25
25
  export function publish(argv: Record<string, unknown>, config: Config): void {
26
26
  const skipVersionIncrement = argv.skip === true;
27
- const setVersion = argv.setversion as string | undefined;
28
- const dryRun = argv.dryrun === true;
29
- const onlyUpload = argv.onlyupload === true;
27
+ const setVersion = argv.setVersion as string | undefined;
28
+ const dryRun = argv.dryRun === true;
29
+ const onlyUpload = argv.onlyUpload === true;
30
30
 
31
31
  const modTargetDirectoryName = getModTargetDirectoryName(config);
32
32
  const modTargetPath = path.join(config.modsDirectory, modTargetDirectoryName);
@@ -96,7 +96,7 @@ function updateDeps() {
96
96
  );
97
97
  }
98
98
 
99
- execShell(UPDATE_SCRIPT_NAME);
99
+ execShell("bash", [UPDATE_SCRIPT_NAME]);
100
100
  }
101
101
 
102
102
  function getVersionFromPackageJSON() {
package/src/constants.ts CHANGED
@@ -1,10 +1,15 @@
1
+ import os from "os";
1
2
  import path from "path";
2
3
 
3
4
  const cwd = process.cwd();
4
5
 
6
+ // https://stackoverflow.com/questions/9080085/node-js-find-home-directory-in-platform-agnostic-way
7
+ const homeDir = os.homedir();
8
+
5
9
  // Miscellaneous
6
10
  export const CURRENT_DIRECTORY_NAME = path.basename(cwd);
7
11
  export const CWD = cwd;
12
+ export const HOME_DIR = homeDir;
8
13
  export const FILE_SYNCED_MESSAGE = "File synced:";
9
14
 
10
15
  // isaacscript
package/src/main.ts CHANGED
@@ -15,6 +15,7 @@ import { publish } from "./commands/publish/publish";
15
15
  import * as configFile from "./configFile";
16
16
  import { CWD } from "./constants";
17
17
  import { parseArgs } from "./parseArgs";
18
+ import { promptInit } from "./prompt";
18
19
  import { Command, DEFAULT_COMMAND } from "./types/Command";
19
20
  import { Config } from "./types/Config";
20
21
  import { ensureAllCases, error } from "./util";
@@ -28,6 +29,7 @@ main().catch((err) => {
28
29
 
29
30
  async function main(): Promise<void> {
30
31
  sourceMapSupport.install();
32
+ promptInit();
31
33
  validateNodeVersion();
32
34
  validateOS();
33
35
 
@@ -39,13 +39,14 @@ export function monkeyPatchMainLua(targetModDirectory: string): void {
39
39
  const mainLuaPath = path.join(targetModDirectory, MAIN_LUA);
40
40
  let mainLua = file.read(mainLuaPath);
41
41
 
42
- mainLua = patchInformationalHeader(mainLua);
42
+ // mainLua = patchInformationalHeader(mainLua);
43
43
  mainLua = patchGlobalObjects(mainLua);
44
44
 
45
45
  file.write(mainLuaPath, mainLua);
46
46
  }
47
47
 
48
48
  // Add an informational header for people who happen to be browsing the Lua output
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
49
50
  function patchInformationalHeader(mainLua: string) {
50
51
  return INFORMATIONAL_HEADER + mainLua;
51
52
  }
package/src/parseArgs.ts CHANGED
@@ -6,27 +6,28 @@ export function parseArgs() {
6
6
  .usage("usage: isaacscript <command> [options]")
7
7
  .scriptName("isaacscript")
8
8
 
9
- .command(
10
- "monitor",
11
- "Monitor a project for changes. (default)",
12
- (builder) => {
13
- return builder
14
- .option("mods-directory", {
15
- alias: "m",
16
- type: "string",
17
- description: "The directory where Isaac mods live on your system",
18
- })
19
- .option("save-slot", {
20
- alias: "s",
21
- type: "number",
22
- choices: [1, 2, 3],
23
- description: "The save slot in-game that you use",
24
- });
25
- },
9
+ .command("monitor", "Monitor a project for changes. (default)", (builder) =>
10
+ builder
11
+ .option("mods-directory", {
12
+ alias: "m",
13
+ type: "string",
14
+ description: "The directory where Isaac mods live on your system",
15
+ })
16
+ .option("save-slot", {
17
+ alias: "s",
18
+ type: "number",
19
+ choices: [1, 2, 3],
20
+ description: "The save slot in-game that you use",
21
+ })
22
+ .option("crash-debug", {
23
+ alias: "c",
24
+ type: "boolean",
25
+ description: "Enable crash debugging",
26
+ }),
26
27
  )
27
28
 
28
- .command("init [name]", "Initialize a new IsaacScript mod.", (builder) => {
29
- return builder
29
+ .command("init [name]", "Initialize a new IsaacScript mod.", (builder) =>
30
+ builder
30
31
  .option("use-current-dir", {
31
32
  alias: "u",
32
33
  type: "boolean",
@@ -47,39 +48,44 @@ export function parseArgs() {
47
48
  alias: "c",
48
49
  type: "boolean",
49
50
  description: "Open the project in VSCode after initialization",
50
- });
51
- })
51
+ })
52
+ .option("skip-npm-install", {
53
+ alias: "i",
54
+ type: "boolean",
55
+ description:
56
+ 'Don\'t automatically run "npm install" after initializing the project',
57
+ }),
58
+ )
52
59
 
53
60
  .command("copy", "Only compile & copy the mod.")
54
61
 
55
62
  .command(
56
63
  "publish",
57
64
  "Bump the version & automatically publish the new files using the steamcmd tool.",
58
- (builder) => {
59
- return builder
65
+ (builder) =>
66
+ builder
60
67
  .option("skip", {
61
68
  alias: "s",
62
69
  type: "boolean",
63
70
  description: "skip incrementing the version number",
64
71
  })
65
- .option("setversion", {
72
+ .option("set-version", {
66
73
  alias: "t",
67
74
  type: "string",
68
75
  description:
69
76
  "specify the version number instead of incrementing it",
70
77
  })
71
- .option("dryrun", {
78
+ .option("dry-run", {
72
79
  alias: "d",
73
80
  type: "boolean",
74
81
  description: "skip invoking steamcmd",
75
82
  })
76
- .option("onlyupload", {
83
+ .option("only-upload", {
77
84
  alias: "u",
78
85
  type: "boolean",
79
86
  description:
80
87
  "only upload the mod to the Steam Workshop (without doing anything else)",
81
- });
82
- },
88
+ }),
83
89
  )
84
90
 
85
91
  .alias("h", "help") // By default, only "--help" is enabled