isaacscript 3.16.0 → 3.16.1-dev.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.
Files changed (214) hide show
  1. package/dist/checkForWindowsTerminalBugs.js +57 -0
  2. package/{src → dist}/classes/Config.js +1 -6
  3. package/dist/classes/ValidatedConfig.js +1 -0
  4. package/{src → dist}/commands/check/check.js +60 -68
  5. package/dist/commands/check/check.test.js +86 -0
  6. package/dist/commands/copy/copy.js +29 -0
  7. package/dist/commands/init/checkIfProjectPathExists.js +21 -0
  8. package/dist/commands/init/checkModSubdirectory.js +9 -0
  9. package/dist/commands/init/checkModTargetDirectory.js +24 -0
  10. package/dist/commands/init/createProject.js +199 -0
  11. package/dist/commands/init/getAuthorName.js +22 -0
  12. package/dist/commands/init/getModsDir.js +48 -0
  13. package/dist/commands/init/getProjectPath.js +84 -0
  14. package/dist/commands/init/init.js +73 -0
  15. package/dist/commands/init/installVSCodeExtensions.js +27 -0
  16. package/dist/commands/init/promptSaveSlot.js +17 -0
  17. package/{src → dist}/commands/init/promptVSCode.js +5 -10
  18. package/dist/commands/monitor/copyWatcherMod.js +31 -0
  19. package/dist/commands/monitor/modDirectorySyncer/modDirectorySyncer.js +44 -0
  20. package/dist/commands/monitor/monitor.js +154 -0
  21. package/{src → dist}/commands/monitor/notifyGame.js +14 -22
  22. package/{src → dist}/commands/monitor/saveDatWriter/saveDatWriter.js +24 -27
  23. package/dist/commands/monitor/saveDatWriter/types.js +1 -0
  24. package/dist/commands/monitor/spawnModDirectorySyncer.js +31 -0
  25. package/dist/commands/monitor/spawnSaveDatWriter.js +29 -0
  26. package/dist/commands/monitor/spawnTSTLWatcher.js +74 -0
  27. package/dist/commands/monitor/touchWatcherSaveDatFiles.js +15 -0
  28. package/dist/commands/publish/isaacscriptMod.js +90 -0
  29. package/dist/commands/publish/prePublish.js +105 -0
  30. package/dist/commands/publish/publish.js +39 -0
  31. package/dist/commands/publish/validate.js +46 -0
  32. package/dist/common.js +65 -0
  33. package/dist/configFile.js +54 -0
  34. package/dist/constants.js +61 -0
  35. package/dist/customStage.js +298 -0
  36. package/dist/dev.js +10 -0
  37. package/{src/enums → dist/enums/copied}/DoorSlot.js +5 -6
  38. package/dist/enums/copied/DoorSlotFlag.js +35 -0
  39. package/{src/enums → dist/enums/copied}/RoomShape.js +5 -6
  40. package/{src → dist}/exec.js +19 -28
  41. package/dist/git.js +133 -0
  42. package/dist/interfaces/GitHubCLIHostsYAML.js +1 -0
  43. package/dist/interfaces/IsaacScriptTSConfig.js +1 -0
  44. package/dist/interfaces/ShadersXML.js +1 -0
  45. package/dist/interfaces/copied/CustomStageTSConfig.js +4 -0
  46. package/dist/interfaces/copied/JSONRoomsFile.js +4 -0
  47. package/dist/main.js +132 -0
  48. package/dist/objects/copied/doorSlotToDoorSlotFlag.js +16 -0
  49. package/dist/objects/copied/roomShapeToDoorSlotCoordinates.js +112 -0
  50. package/dist/packageManager.js +68 -0
  51. package/{src → dist}/parseArgs.js +36 -15
  52. package/dist/prompt.js +79 -0
  53. package/dist/tsconfig.js +98 -0
  54. package/dist/types/Command.js +4 -0
  55. package/dist/utils.js +8 -0
  56. package/dist/validateInIsaacScriptProject.js +29 -0
  57. package/dist/validateNodeVersion.js +20 -0
  58. package/file-templates/dynamic/.github/workflows/setup/action.yml +21 -0
  59. package/file-templates/dynamic/README.mod.md +4 -3
  60. package/file-templates/dynamic/_gitignore +0 -2
  61. package/file-templates/dynamic/package.mod.json +8 -0
  62. package/file-templates/dynamic/package.ts.json +5 -1
  63. package/file-templates/{dynamic → static}/.github/workflows/ci.yml +10 -38
  64. package/file-templates/static/scripts/tsconfig.json +28 -0
  65. package/file-templates/static-mod/.vscode/settings.json +1 -1
  66. package/file-templates/static-mod/{_cspell.json → _cspell.jsonc} +2 -2
  67. package/file-templates/static-mod/_eslintrc.cjs +1 -1
  68. package/file-templates/static-mod/prettier.config.mjs +6 -1
  69. package/file-templates/static-mod/scripts/lint.ts +36 -0
  70. package/file-templates/static-mod/tsconfig.json +5 -5
  71. package/file-templates/static-ts/.vscode/settings.json +1 -1
  72. package/file-templates/static-ts/{_cspell.json → _cspell.jsonc} +5 -5
  73. package/file-templates/static-ts/_eslintrc.cjs +1 -1
  74. package/file-templates/static-ts/knip.jsonc +6 -0
  75. package/file-templates/static-ts/prettier.config.mjs +6 -1
  76. package/file-templates/static-ts/scripts/lint.ts +30 -0
  77. package/file-templates/static-ts/tsconfig.json +3 -3
  78. package/package.json +27 -9
  79. package/plugins/addCrashDebugStatements.cjs +56 -0
  80. package/plugins/addCrashDebugStatements.ts +39 -0
  81. package/{src/plugins/addIsaacScriptCommentHeader.js → plugins/addIsaacScriptCommentHeader.cjs} +1 -1
  82. package/plugins/addIsaacScriptCommentHeader.ts +42 -0
  83. package/{src/plugins/addIsaacScriptCommentHeaderCommon.js → plugins/addIsaacScriptCommentHeaderCommon.cjs} +6 -4
  84. package/plugins/addIsaacScriptCommentHeaderCommon.ts +59 -0
  85. package/{src/plugins/noExtendedEnums.js → plugins/noExtendedEnums.cjs} +25 -4
  86. package/plugins/noExtendedEnums.ts +83 -0
  87. package/plugins/tsconfig.json +28 -0
  88. package/schemas/tsconfig-isaacscript-section-schema.json +1 -0
  89. package/file-templates/static/nuke.sh +0 -53
  90. package/file-templates/static/update.sh +0 -26
  91. package/file-templates/static-mod/build.sh +0 -22
  92. package/file-templates/static-mod/lint.sh +0 -43
  93. package/file-templates/static-mod/publish.sh +0 -10
  94. package/file-templates/static-mod/run.sh +0 -10
  95. package/file-templates/static-ts/build.sh +0 -53
  96. package/file-templates/static-ts/lint.sh +0 -35
  97. package/file-templates/static-ts/publish.sh +0 -10
  98. package/file-templates/static-ts/run.sh +0 -42
  99. package/src/checkForWindowsTerminalBugs.js +0 -71
  100. package/src/checkForWindowsTerminalBugs.js.map +0 -1
  101. package/src/classes/Config.js.map +0 -1
  102. package/src/classes/ValidatedConfig.js +0 -3
  103. package/src/classes/ValidatedConfig.js.map +0 -1
  104. package/src/commands/check/check.js.map +0 -1
  105. package/src/commands/check/check.test.js +0 -87
  106. package/src/commands/check/check.test.js.map +0 -1
  107. package/src/commands/copy/copy.js +0 -38
  108. package/src/commands/copy/copy.js.map +0 -1
  109. package/src/commands/init/checkIfProjectPathExists.js +0 -28
  110. package/src/commands/init/checkIfProjectPathExists.js.map +0 -1
  111. package/src/commands/init/checkModSubdirectory.js +0 -16
  112. package/src/commands/init/checkModSubdirectory.js.map +0 -1
  113. package/src/commands/init/checkModTargetDirectory.js +0 -31
  114. package/src/commands/init/checkModTargetDirectory.js.map +0 -1
  115. package/src/commands/init/createProject.js +0 -220
  116. package/src/commands/init/createProject.js.map +0 -1
  117. package/src/commands/init/getAuthorName.js +0 -27
  118. package/src/commands/init/getAuthorName.js.map +0 -1
  119. package/src/commands/init/getModsDir.js +0 -58
  120. package/src/commands/init/getModsDir.js.map +0 -1
  121. package/src/commands/init/getProjectPath.js +0 -89
  122. package/src/commands/init/getProjectPath.js.map +0 -1
  123. package/src/commands/init/init.js +0 -78
  124. package/src/commands/init/init.js.map +0 -1
  125. package/src/commands/init/installVSCodeExtensions.js +0 -35
  126. package/src/commands/init/installVSCodeExtensions.js.map +0 -1
  127. package/src/commands/init/promptSaveSlot.js +0 -22
  128. package/src/commands/init/promptSaveSlot.js.map +0 -1
  129. package/src/commands/init/promptVSCode.js.map +0 -1
  130. package/src/commands/monitor/copyWatcherMod.js +0 -39
  131. package/src/commands/monitor/copyWatcherMod.js.map +0 -1
  132. package/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js +0 -47
  133. package/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js.map +0 -1
  134. package/src/commands/monitor/monitor.js +0 -263
  135. package/src/commands/monitor/monitor.js.map +0 -1
  136. package/src/commands/monitor/notifyGame.js.map +0 -1
  137. package/src/commands/monitor/saveDatWriter/saveDatWriter.js.map +0 -1
  138. package/src/commands/monitor/saveDatWriter/types.js +0 -3
  139. package/src/commands/monitor/saveDatWriter/types.js.map +0 -1
  140. package/src/commands/monitor/spawnSaveDatWriter.js +0 -35
  141. package/src/commands/monitor/spawnSaveDatWriter.js.map +0 -1
  142. package/src/commands/monitor/touchWatcherSaveDatFiles.js +0 -21
  143. package/src/commands/monitor/touchWatcherSaveDatFiles.js.map +0 -1
  144. package/src/commands/publish/isaacscriptMod.js +0 -97
  145. package/src/commands/publish/isaacscriptMod.js.map +0 -1
  146. package/src/commands/publish/prePublish.js +0 -120
  147. package/src/commands/publish/prePublish.js.map +0 -1
  148. package/src/commands/publish/publish.js +0 -42
  149. package/src/commands/publish/publish.js.map +0 -1
  150. package/src/commands/publish/validate.js +0 -58
  151. package/src/commands/publish/validate.js.map +0 -1
  152. package/src/common.js +0 -69
  153. package/src/common.js.map +0 -1
  154. package/src/configFile.js +0 -64
  155. package/src/configFile.js.map +0 -1
  156. package/src/constants.js +0 -67
  157. package/src/constants.js.map +0 -1
  158. package/src/customStage.js +0 -304
  159. package/src/customStage.js.map +0 -1
  160. package/src/dev.js +0 -19
  161. package/src/dev.js.map +0 -1
  162. package/src/enums/DoorSlot.js.map +0 -1
  163. package/src/enums/DoorSlotFlag.js +0 -37
  164. package/src/enums/DoorSlotFlag.js.map +0 -1
  165. package/src/enums/PackageManager.js +0 -10
  166. package/src/enums/PackageManager.js.map +0 -1
  167. package/src/enums/RoomShape.js.map +0 -1
  168. package/src/exec.js.map +0 -1
  169. package/src/file.js +0 -247
  170. package/src/file.js.map +0 -1
  171. package/src/git.js +0 -154
  172. package/src/git.js.map +0 -1
  173. package/src/interfaces/GitHubCLIHostsYAML.js +0 -3
  174. package/src/interfaces/GitHubCLIHostsYAML.js.map +0 -1
  175. package/src/interfaces/IsaacScriptTSConfig.js +0 -3
  176. package/src/interfaces/IsaacScriptTSConfig.js.map +0 -1
  177. package/src/interfaces/ShadersXML.js +0 -3
  178. package/src/interfaces/ShadersXML.js.map +0 -1
  179. package/src/interfaces/copied/CustomStageTSConfig.js +0 -4
  180. package/src/interfaces/copied/CustomStageTSConfig.js.map +0 -1
  181. package/src/interfaces/copied/JSONRoomsFile.js +0 -4
  182. package/src/interfaces/copied/JSONRoomsFile.js.map +0 -1
  183. package/src/isaacScriptCommonTS.js +0 -233
  184. package/src/isaacScriptCommonTS.js.map +0 -1
  185. package/src/json.js +0 -42
  186. package/src/json.js.map +0 -1
  187. package/src/main.js +0 -127
  188. package/src/main.js.map +0 -1
  189. package/src/objects/doorSlotToDoorSlotFlag.js +0 -17
  190. package/src/objects/doorSlotToDoorSlotFlag.js.map +0 -1
  191. package/src/objects/roomShapeDoorToSlotCoordinates.js +0 -115
  192. package/src/objects/roomShapeDoorToSlotCoordinates.js.map +0 -1
  193. package/src/packageManager.js +0 -153
  194. package/src/packageManager.js.map +0 -1
  195. package/src/parseArgs.js.map +0 -1
  196. package/src/plugins/addCrashDebugStatements.js +0 -32
  197. package/src/plugins/addCrashDebugStatements.js.map +0 -1
  198. package/src/plugins/addIsaacScriptCommentHeader.js.map +0 -1
  199. package/src/plugins/addIsaacScriptCommentHeaderCommon.js.map +0 -1
  200. package/src/plugins/noExtendedEnums.js.map +0 -1
  201. package/src/prompt.js +0 -87
  202. package/src/prompt.js.map +0 -1
  203. package/src/tsconfig.js +0 -103
  204. package/src/tsconfig.js.map +0 -1
  205. package/src/types/Command.js +0 -9
  206. package/src/types/Command.js.map +0 -1
  207. package/src/utils.js +0 -15
  208. package/src/utils.js.map +0 -1
  209. package/src/validateInIsaacScriptProject.js +0 -36
  210. package/src/validateInIsaacScriptProject.js.map +0 -1
  211. package/src/validateNodeVersion.js +0 -29
  212. package/src/validateNodeVersion.js.map +0 -1
  213. package/src/version.js +0 -20
  214. package/src/version.js.map +0 -1
@@ -0,0 +1,154 @@
1
+ import chalk from "chalk";
2
+ import { PACKAGE_JSON, PackageManager, deleteFileOrDirectory, dirName, fatalError, getJSONC, getPackageJSONDependencies, getPackageManagerAddCommand, getPackageManagerAddDevCommand, getPackageManagerInstallCommand, isDirectory, isLink, touch, } from "isaacscript-common-node";
3
+ import path from "node:path";
4
+ import { CWD, MOD_SOURCE_PATH, PACKAGE_JSON_PATH } from "../../constants.js";
5
+ import { prepareCustomStages } from "../../customStage.js";
6
+ import { getAndValidateIsaacScriptMonorepoDirectory } from "../../dev.js";
7
+ import { execShell, execShellString } from "../../exec.js";
8
+ import { PACKAGE_MANAGER_USED_FOR_ISAACSCRIPT, getPackageManagerUsedForExistingProject, } from "../../packageManager.js";
9
+ import { getFirstTSConfigIncludePath } from "../../tsconfig.js";
10
+ import { getModTargetDirectoryName } from "../../utils.js";
11
+ import { copyWatcherMod } from "./copyWatcherMod.js";
12
+ import * as notifyGame from "./notifyGame.js";
13
+ import { spawnModDirectorySyncer } from "./spawnModDirectorySyncer.js";
14
+ import { spawnSaveDatWriter } from "./spawnSaveDatWriter.js";
15
+ import { spawnTSTLWatcher } from "./spawnTSTLWatcher.js";
16
+ import { touchWatcherSaveDatFiles } from "./touchWatcherSaveDatFiles.js";
17
+ const __dirname = dirName();
18
+ const REQUIRED_PACKAGE_JSON_DEPENDENCIES = [
19
+ "isaac-typescript-definitions",
20
+ // - "isaacscript-common" is not required.
21
+ ];
22
+ /**
23
+ * We want "typescript" and some of the other dependencies to be in "devDependencies" instead of
24
+ * "dependencies" because it prevents their functions from being placed into the list of
25
+ * auto-complete functions.
26
+ */
27
+ const REQUIRED_PACKAGE_JSON_DEV_DEPENDENCIES = [
28
+ "isaacscript",
29
+ // - "isaacscript-lint" is not required.
30
+ // - "isaacscript-spell" is not required.
31
+ // - "isaacscript-tsconfig" is not required.
32
+ "typescript",
33
+ "typescript-to-lua",
34
+ ];
35
+ export async function monitor(args, config) {
36
+ const verbose = args.verbose === true;
37
+ const skipProjectChecks = args.skipProjectChecks === true;
38
+ const packageManager = getPackageManagerUsedForExistingProject(args);
39
+ // If they specified some command-line flags, override the values found in the config file.
40
+ if (args.modsDirectory !== undefined) {
41
+ config.modsDirectory = args.modsDirectory; // eslint-disable-line no-param-reassign
42
+ }
43
+ if (args.saveSlot !== undefined) {
44
+ config.saveSlot = args.saveSlot; // eslint-disable-line no-param-reassign
45
+ }
46
+ if (args.dev !== undefined) {
47
+ config.isaacScriptCommonDev = args.dev; // eslint-disable-line no-param-reassign
48
+ }
49
+ // Pre-flight checks
50
+ if (!skipProjectChecks) {
51
+ validatePackageJSONDependencies(args);
52
+ }
53
+ // Read the "tsconfig.json" file.
54
+ const tsConfigInclude = getFirstTSConfigIncludePath();
55
+ const resolvedIncludePath = path.resolve(CWD, tsConfigInclude);
56
+ const modTargetDirectoryName = getModTargetDirectoryName(config);
57
+ const modTargetPath = path.join(config.modsDirectory, modTargetDirectoryName);
58
+ // Prepare the IsaacScript watcher mod.
59
+ copyWatcherMod(config);
60
+ touchWatcherSaveDatFiles(config);
61
+ // Perform the steps to link to a development version of "isaacscript-common", if necessary. (This
62
+ // has to be before preparing custom stages.)
63
+ if (config.isaacScriptCommonDev === true) {
64
+ linkDevelopmentIsaacScriptCommon(CWD, packageManager, verbose);
65
+ }
66
+ else {
67
+ warnIfIsaacScriptCommonLinkExists(CWD, packageManager);
68
+ }
69
+ // Prepare the custom stages feature, if necessary.
70
+ await prepareCustomStages(packageManager, verbose);
71
+ // Delete and re-copy the mod every time IsaacScript starts. This ensures that it is always the
72
+ // latest version.
73
+ deleteFileOrDirectory(modTargetPath);
74
+ // Subprocess #1 - The "save#.dat" file writer.
75
+ spawnSaveDatWriter(config);
76
+ // Subprocess #2 - The mod directory syncer.
77
+ spawnModDirectorySyncer(config);
78
+ // Subprocess #3 - `tstl --watch` (to automatically convert TypeScript to Lua).
79
+ spawnTSTLWatcher(config, CWD, packageManager);
80
+ // Subprocess #4 - `tstl --watch` (for the development version of `isaacscript-common`).
81
+ if (config.isaacScriptCommonDev === true) {
82
+ const isaacScriptMonorepoDirectory = getAndValidateIsaacScriptMonorepoDirectory(CWD);
83
+ const isaacScriptCommonDirectory = path.join(isaacScriptMonorepoDirectory, "packages", "isaacscript-common");
84
+ if (!isDirectory(isaacScriptCommonDirectory)) {
85
+ console.error(`The "isaacscript-common" directory does not exist at: ${isaacScriptCommonDirectory}`);
86
+ fatalError('Please make sure that the IsaacScript repository is placed next to this one. If you do not want to test a local version of "isaacscript-common", then set the "isaacScriptCommonDev" field to false in your "isaacscript.json" file.');
87
+ }
88
+ spawnTSTLWatcher(config, isaacScriptCommonDirectory, packageManager, CWD);
89
+ }
90
+ // Also, start constantly pinging the watcher mod.
91
+ setInterval(() => {
92
+ notifyGame.ping();
93
+ }, 1000); // Every second
94
+ console.log("Automatically monitoring the following for changes:");
95
+ console.log(`1) your TypeScript code: ${chalk.green(resolvedIncludePath)}`);
96
+ console.log(`2) the source mod directory: ${chalk.green(MOD_SOURCE_PATH)}`);
97
+ console.log("");
98
+ console.log(`Copying files to: ${chalk.green(modTargetPath)}`);
99
+ console.log("");
100
+ // (The process will now continue indefinitely for as long as the subprocesses exist.)
101
+ }
102
+ function validatePackageJSONDependencies(args) {
103
+ const packageJSON = getJSONC(PACKAGE_JSON_PATH);
104
+ validatePackageJSONNormalDependencies(packageJSON, args);
105
+ validatePackageJSONDevDependencies(packageJSON, args);
106
+ }
107
+ function validatePackageJSONNormalDependencies(packageJSON, args) {
108
+ const dependencies = getPackageJSONDependencies(packageJSON, "dependencies") ?? {};
109
+ const dependenciesArray = Object.keys(dependencies);
110
+ for (const dependency of REQUIRED_PACKAGE_JSON_DEPENDENCIES) {
111
+ if (!dependenciesArray.includes(dependency)) {
112
+ const packageManager = getPackageManagerUsedForExistingProject(args);
113
+ const addCommand = getPackageManagerAddCommand(packageManager, dependency);
114
+ fatalError(`${chalk.red(`IsaacScript projects require a dependency of "${dependency}" in the "${PACKAGE_JSON}" file. You can add it with the following command:`)} ${chalk.green(addCommand)}`);
115
+ }
116
+ }
117
+ }
118
+ function validatePackageJSONDevDependencies(packageJSON, args) {
119
+ const devDependencies = getPackageJSONDependencies(packageJSON, "devDependencies") ?? {};
120
+ const devDependenciesArray = Object.keys(devDependencies);
121
+ for (const devDependency of REQUIRED_PACKAGE_JSON_DEV_DEPENDENCIES) {
122
+ if (!devDependenciesArray.includes(devDependency)) {
123
+ const packageManager = getPackageManagerUsedForExistingProject(args);
124
+ const addDevCommand = getPackageManagerAddDevCommand(packageManager, devDependency);
125
+ fatalError(`${chalk.red(`IsaacScript projects require a development dependency of "${devDependency}" in the "${PACKAGE_JSON}" file. You can add it with the following command:`)} ${chalk.green(addDevCommand)}`);
126
+ }
127
+ }
128
+ }
129
+ function linkDevelopmentIsaacScriptCommon(projectPath, packageManager, verbose) {
130
+ if (packageManager !== PACKAGE_MANAGER_USED_FOR_ISAACSCRIPT) {
131
+ fatalError(`If you want to use this mod to develop/test "isaacscript-common", then the mod must be set up using the ${PACKAGE_MANAGER_USED_FOR_ISAACSCRIPT} package manager instead of: ${packageManager}`);
132
+ }
133
+ const isaacScriptMonorepoDirectory = getAndValidateIsaacScriptMonorepoDirectory(projectPath);
134
+ console.log('Building "isaacscript-common"...');
135
+ // Run "yarn install" at the root of the monorepo.
136
+ const installCommand = getPackageManagerInstallCommand(packageManager);
137
+ execShellString(installCommand, verbose, false, isaacScriptMonorepoDirectory);
138
+ // Build "isaacscript-common".
139
+ const iscPackagePath = path.join(isaacScriptMonorepoDirectory, "packages", "isaacscript-common");
140
+ const buildCommand = "npm run build";
141
+ execShellString(buildCommand, verbose, false, iscPackagePath);
142
+ console.log('Linking this repository to the development version of "isaacscript-common"...');
143
+ const yarnLockPath = path.join(iscPackagePath, "yarn.lock");
144
+ touch(yarnLockPath);
145
+ execShell(PACKAGE_MANAGER_USED_FOR_ISAACSCRIPT, ["link", iscPackagePath], verbose, false, projectPath);
146
+ }
147
+ function warnIfIsaacScriptCommonLinkExists(projectPath, packageManager) {
148
+ const isaacScriptCommonPath = path.join(projectPath, "node_modules", "isaacscript-common");
149
+ if (isLink(isaacScriptCommonPath) &&
150
+ packageManager !== PackageManager.pnpm // pnpm uses links, so it will cause a false positive.
151
+ ) {
152
+ fatalError(`Your "node_modules/isaacscript-common" directory is linked, but you do not have "isaacScriptCommonDev" set to true in your "isaacscript.json" file. You must either set it to true or remove the link via: ${PACKAGE_MANAGER_USED_FOR_ISAACSCRIPT} unlink isaacscript-common`);
153
+ }
154
+ }
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ping = exports.command = exports.msg = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const constants_js_1 = require("../../constants.js");
7
- const utils_js_1 = require("../../utils.js");
8
- const spawnSaveDatWriter_js_1 = require("./spawnSaveDatWriter.js");
9
- function msg(data) {
1
+ import chalk from "chalk";
2
+ import { COMPILATION_SUCCESSFUL_MESSAGE } from "../../constants.js";
3
+ import { getTime } from "../../utils.js";
4
+ import { sendMsgToSaveDatWriter } from "./spawnSaveDatWriter.js";
5
+ export function msg(data) {
10
6
  const formattedData = data
11
7
  .replaceAll("/\r\n", "\n") // Replace Windows newlines with Unix newlines
12
8
  .trim(); // Trim whitespace
@@ -20,8 +16,8 @@ function msg(data) {
20
16
  return;
21
17
  }
22
18
  // Add a time prefix.
23
- const formattedLine = `[${(0, utils_js_1.getTime)()}] ${trimmedLine}`;
24
- (0, spawnSaveDatWriter_js_1.sendMsgToSaveDatWriter)({
19
+ const formattedLine = `[${getTime()}] ${trimmedLine}`;
20
+ sendMsgToSaveDatWriter({
25
21
  type: "msg",
26
22
  data: formattedLine,
27
23
  });
@@ -30,29 +26,25 @@ function msg(data) {
30
26
  printMsgToStandardOut(formattedLine);
31
27
  }
32
28
  }
33
- exports.msg = msg;
34
29
  function printMsgToStandardOut(data) {
35
30
  let coloredData = data;
36
- if (data.includes(constants_js_1.COMPILATION_SUCCESSFUL_MESSAGE)) {
37
- coloredData = chalk_1.default.green(data);
31
+ if (data.includes(COMPILATION_SUCCESSFUL_MESSAGE)) {
32
+ coloredData = chalk.green(data);
38
33
  }
39
34
  else if (data.match(/error/g) !== null) {
40
- coloredData = chalk_1.default.red(data);
35
+ coloredData = chalk.red(data);
41
36
  }
42
37
  console.log(coloredData);
43
38
  }
44
- function command(data) {
45
- (0, spawnSaveDatWriter_js_1.sendMsgToSaveDatWriter)({
39
+ export function command(data) {
40
+ sendMsgToSaveDatWriter({
46
41
  type: "command",
47
42
  data,
48
43
  });
49
44
  }
50
- exports.command = command;
51
- function ping() {
52
- (0, spawnSaveDatWriter_js_1.sendMsgToSaveDatWriter)({
45
+ export function ping() {
46
+ sendMsgToSaveDatWriter({
53
47
  type: "ping",
54
48
  data: "",
55
49
  });
56
50
  }
57
- exports.ping = ping;
58
- //# sourceMappingURL=notifyGame.js.map
@@ -1,27 +1,24 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const JSONC = tslib_1.__importStar(require("jsonc-parser"));
5
- const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
- const constants_js_1 = require("../../../constants.js");
7
- const file_js_1 = require("../../../file.js");
8
- const isaacScriptCommonTS_js_1 = require("../../../isaacScriptCommonTS.js");
1
+ import { getArgs, isFile, makeDirectory, readFile, } from "isaacscript-common-node";
2
+ import { assertDefined } from "isaacscript-common-ts";
3
+ import * as JSONC from "jsonc-parser";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { PROJECT_NAME } from "../../../constants.js";
9
7
  const SUBPROCESS_NAME = "save#.dat writer";
10
8
  const MAX_MESSAGES = 100;
11
- const VERBOSE = false;
12
9
  let saveDatPath;
13
10
  let saveDatFileName;
14
- init(VERBOSE);
15
- function init(verbose) {
16
- const args = process.argv.slice(2);
11
+ init();
12
+ function init() {
13
+ const args = getArgs();
17
14
  const firstArg = args[0];
18
- (0, isaacScriptCommonTS_js_1.assertDefined)(firstArg, `The ${SUBPROCESS_NAME} process did not get a valid first argument.`);
15
+ assertDefined(firstArg, `The ${SUBPROCESS_NAME} process did not get a valid first argument.`);
19
16
  saveDatPath = firstArg;
20
- saveDatFileName = node_path_1.default.basename(saveDatPath);
17
+ saveDatFileName = path.basename(saveDatPath);
21
18
  // Check to see if the data directory exists.
22
- const watcherModDataPath = node_path_1.default.dirname(saveDatPath);
23
- if (!(0, file_js_1.fileExists)(watcherModDataPath, verbose)) {
24
- (0, file_js_1.makeDir)(watcherModDataPath, verbose);
19
+ const watcherModDataPath = path.dirname(saveDatPath);
20
+ if (!isFile(watcherModDataPath)) {
21
+ makeDirectory(watcherModDataPath);
25
22
  }
26
23
  // Listen for messages from the parent process.
27
24
  process.on("message", (msg) => {
@@ -29,7 +26,7 @@ function init(verbose) {
29
26
  });
30
27
  }
31
28
  function onMessage(type, data, numRetries = 0) {
32
- const saveDat = readSaveDatFromDisk(VERBOSE);
29
+ const saveDat = readSaveDatFromDisk();
33
30
  if (saveDat.length > MAX_MESSAGES) {
34
31
  // If IsaacScript is running and:
35
32
  // - the game is not open
@@ -41,12 +38,12 @@ function onMessage(type, data, numRetries = 0) {
41
38
  return;
42
39
  }
43
40
  addMessageToSaveDat(type, saveDat, data); // Mutates saveDat
44
- writeSaveDatToDisk(type, data, saveDat, numRetries, VERBOSE);
41
+ writeSaveDatToDisk(type, data, saveDat, numRetries);
45
42
  }
46
- function readSaveDatFromDisk(verbose) {
43
+ function readSaveDatFromDisk() {
47
44
  let saveDat;
48
- if ((0, file_js_1.fileExists)(saveDatPath, verbose)) {
49
- const saveDatRaw = (0, file_js_1.readFile)(saveDatPath, verbose);
45
+ if (isFile(saveDatPath)) {
46
+ const saveDatRaw = readFile(saveDatPath);
50
47
  try {
51
48
  saveDat = JSONC.parse(saveDatRaw);
52
49
  }
@@ -85,14 +82,15 @@ function addMessageToSaveDat(type, saveDat, data) {
85
82
  }
86
83
  }
87
84
  }
88
- function writeSaveDatToDisk(type, data, saveDat, numRetries, verbose) {
89
- const saveDatRaw = JSON.stringify(saveDat, undefined, 2);
85
+ function writeSaveDatToDisk(type, data, saveDat, numRetries) {
86
+ const saveDatRaw = `${JSON.stringify(saveDat, undefined, 2)}\n`; // Prettify it for easier debugging.
90
87
  try {
91
- (0, file_js_1.writeFileTry)(saveDatPath, saveDatRaw, verbose);
88
+ // We don't use the "writeFile" helper function here, since we want to allow for failure.
89
+ fs.writeFileSync(saveDatPath, saveDatRaw);
92
90
  }
93
91
  catch (error) {
94
92
  if (numRetries > 4) {
95
- send(`Failed to write to the ${saveDatFileName} for 5 times in a row. Maybe the file got locked somehow. ${constants_js_1.PROJECT_NAME} will now exit.\nThe writing error is as follows: ${error}`);
93
+ send(`Failed to write to the ${saveDatFileName} for 5 times in a row. Maybe the file got locked somehow. ${PROJECT_NAME} will now exit.\nThe writing error is as follows: ${error}`);
96
94
  process.exit(1);
97
95
  }
98
96
  send(`Writing to "${saveDatFileName}" failed. (The number of retries so far is ${numRetries}.) Trying again in 0.1 seconds...`);
@@ -106,4 +104,3 @@ function send(msg) {
106
104
  process.send(msg);
107
105
  }
108
106
  }
109
- //# sourceMappingURL=saveDatWriter.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import { dirName, fatalError } from "isaacscript-common-node";
2
+ import { fork } from "node:child_process";
3
+ import path from "node:path";
4
+ import { FILE_SYNCED_MESSAGE, MAIN_LUA, MOD_SOURCE_PATH, } from "../../constants.js";
5
+ import { getModTargetDirectoryName } from "../../utils.js";
6
+ import * as notifyGame from "./notifyGame.js";
7
+ const __dirname = dirName();
8
+ const SUBPROCESS_NAME = "modDirectorySyncer";
9
+ const SUBPROCESS_DESCRIPTION = "Directory syncer";
10
+ export function spawnModDirectorySyncer(config) {
11
+ const processPath = path.join(__dirname, SUBPROCESS_NAME, SUBPROCESS_NAME);
12
+ const modTargetName = getModTargetDirectoryName(config);
13
+ const modTargetPath = path.join(config.modsDirectory, modTargetName);
14
+ const directorySyncer = fork(processPath, [MOD_SOURCE_PATH, modTargetPath]);
15
+ directorySyncer.on("message", (msg) => {
16
+ notifyGame.msg(msg);
17
+ // If the "main.lua" file was successfully copied over, we also have to tell isaacscript-watcher
18
+ // to reload the mod. Look for something like: "File synced: \main.lua"
19
+ if (msg === `${FILE_SYNCED_MESSAGE} ${path.sep}${MAIN_LUA}`) {
20
+ notifyGame.command(`luamod ${modTargetName}`);
21
+ notifyGame.command("restart");
22
+ notifyGame.msg("Reloaded the mod.");
23
+ }
24
+ });
25
+ directorySyncer.on("close", (code) => {
26
+ fatalError(`Error: ${SUBPROCESS_DESCRIPTION} subprocess closed with code: ${code}`);
27
+ });
28
+ directorySyncer.on("exit", (code) => {
29
+ fatalError(`Error: ${SUBPROCESS_DESCRIPTION} subprocess exited with code: ${code}`);
30
+ });
31
+ }
@@ -0,0 +1,29 @@
1
+ import { dirName, fatalError } from "isaacscript-common-node";
2
+ import { fork } from "node:child_process";
3
+ import path from "node:path";
4
+ import { WATCHER_MOD_NAME } from "../../constants.js";
5
+ const __dirname = dirName();
6
+ const SUBPROCESS_NAME = "saveDatWriter";
7
+ const SUBPROCESS_DESCRIPTION = "save#.dat writer";
8
+ let saveDatWriter;
9
+ export function spawnSaveDatWriter(config) {
10
+ const processPath = path.join(__dirname, SUBPROCESS_NAME, SUBPROCESS_NAME);
11
+ const modsDataPath = path.join(config.modsDirectory, "..", "data");
12
+ const watcherModDataPath = path.join(modsDataPath, WATCHER_MOD_NAME);
13
+ const saveDatFileName = `save${config.saveSlot}.dat`;
14
+ const saveDatPath = path.join(watcherModDataPath, saveDatFileName);
15
+ saveDatWriter = fork(processPath, [saveDatPath], {
16
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
17
+ });
18
+ saveDatWriter.on("close", (code) => {
19
+ fatalError(`Error: ${SUBPROCESS_DESCRIPTION} subprocess closed with code: ${code}`);
20
+ });
21
+ saveDatWriter.on("exit", (code) => {
22
+ fatalError(`Error: ${SUBPROCESS_DESCRIPTION} subprocess exited with code: ${code}`);
23
+ });
24
+ }
25
+ export function sendMsgToSaveDatWriter(msg) {
26
+ if (saveDatWriter !== undefined) {
27
+ saveDatWriter.send(msg);
28
+ }
29
+ }
@@ -0,0 +1,74 @@
1
+ import { appendFile, fatalError, getPackageManagerExecCommand, isFile, } from "isaacscript-common-node";
2
+ import { spawn } from "node:child_process";
3
+ import path from "node:path";
4
+ import { COMPILATION_SUCCESSFUL_MESSAGE, PROJECT_NAME, } from "../../constants.js";
5
+ import * as notifyGame from "./notifyGame.js";
6
+ let compilationStartTime = new Date();
7
+ export function spawnTSTLWatcher(config, cwd, packageManager, modCWD) {
8
+ const processDescription = "tstl";
9
+ const command = getPackageManagerExecCommand(packageManager);
10
+ const tstl = spawn(command, ["tstl", "--watch", "--preserveWatchOutput"], {
11
+ shell: true,
12
+ cwd,
13
+ });
14
+ tstl.stdout.on("data", (data) => {
15
+ const msg = data.toString().trim();
16
+ const suffix = getMonitorMessageSuffix(config, cwd);
17
+ if (msg.includes("Starting compilation in watch mode...")) {
18
+ const newMsg1 = `${PROJECT_NAME} is now watching for future changes${suffix}.`;
19
+ notifyGame.msg(newMsg1);
20
+ const target = suffix.includes("isaacscript-common")
21
+ ? '"isaacscript-common"'
22
+ : "the mod";
23
+ const newMsg2 = `Compiling ${target} for the first time...`;
24
+ notifyGame.msg(newMsg2);
25
+ }
26
+ else if (msg.includes("File change detected. Starting incremental compilation...")) {
27
+ compilationStartTime = new Date();
28
+ const newMsg = `TypeScript change detected${suffix}. Compiling...`;
29
+ notifyGame.msg(newMsg);
30
+ }
31
+ else if (msg.includes("Found 0 errors. Watching for file changes.")) {
32
+ const compilationFinishTime = new Date();
33
+ const elapsedTimeMilliseconds = compilationFinishTime.getTime() - compilationStartTime.getTime();
34
+ const elapsedTimeSeconds = elapsedTimeMilliseconds / 1000;
35
+ const newMsg = `${COMPILATION_SUCCESSFUL_MESSAGE} (in ${elapsedTimeSeconds} seconds)${suffix}`;
36
+ notifyGame.msg(newMsg);
37
+ // Successful compilation of "isaacscript-common" will not trigger a recompilation in the mod.
38
+ // Thus, we must arbitrarily change a file to trigger a mod recompilation.
39
+ if (modCWD !== undefined) {
40
+ const bundleEntryTSPath = path.join(modCWD, "src", "bundleEntry.ts");
41
+ if (isFile(bundleEntryTSPath)) {
42
+ appendFile(bundleEntryTSPath, "// isaacscript-common dev forced recompilation\n");
43
+ }
44
+ }
45
+ }
46
+ else {
47
+ notifyGame.msg(msg);
48
+ }
49
+ });
50
+ tstl.stderr.on("data", (data) => {
51
+ const msg = data.toString().trim();
52
+ if (msg === "^C") {
53
+ // Hide the line that appears when you cancel the program with `Ctrl + c`.
54
+ return;
55
+ }
56
+ notifyGame.msg(`Error: ${msg}`);
57
+ });
58
+ tstl.on("close", (code) => {
59
+ fatalError(`Error: ${processDescription} subprocess exited with code: ${code}`);
60
+ });
61
+ tstl.on("exit", (code) => {
62
+ fatalError(`Error: ${processDescription} subprocess exited with code: ${code}`);
63
+ });
64
+ }
65
+ function getMonitorMessageSuffix(config, cwd) {
66
+ if (config.isaacScriptCommonDev === false ||
67
+ config.isaacScriptCommonDev === undefined) {
68
+ return "";
69
+ }
70
+ const baseName = path.basename(cwd);
71
+ return baseName === "isaacscript-common"
72
+ ? ' (in "isaacscript-common")'
73
+ : " (in this mod)";
74
+ }
@@ -0,0 +1,15 @@
1
+ import { isDirectory, isFile, makeDirectory, touch, } from "isaacscript-common-node";
2
+ import path from "node:path";
3
+ import { WATCHER_MOD_NAME } from "../../constants.js";
4
+ export function touchWatcherSaveDatFiles(config) {
5
+ const modsDataPath = path.join(config.modsDirectory, "..", "data");
6
+ const watcherModDataPath = path.join(modsDataPath, WATCHER_MOD_NAME);
7
+ if (!isDirectory(watcherModDataPath)) {
8
+ makeDirectory(watcherModDataPath);
9
+ }
10
+ const saveDatFileName = `save${config.saveSlot}.dat`;
11
+ const saveDatPath = path.join(watcherModDataPath, saveDatFileName);
12
+ if (!isFile(saveDatPath)) {
13
+ touch(saveDatPath);
14
+ }
15
+ }
@@ -0,0 +1,90 @@
1
+ import chalk from "chalk";
2
+ import { deleteFileOrDirectory, getFileNamesInDirectory, getPackageJSONVersion, isDirectory, isFile, readFile, writeFile, } from "isaacscript-common-node";
3
+ import path from "node:path";
4
+ import { CONSTANTS_TS_PATH, CWD, MOD_SOURCE_PATH, MOD_UPLOADER_PATH, PUBLISH_POST_COPY_PY_PATH, PUBLISH_PRE_COPY_PY_PATH, } from "../../constants.js";
5
+ import { execExe, execShell, execShellString } from "../../exec.js";
6
+ import { getReleaseGitCommitMessage, gitCommitAllAndPush } from "../../git.js";
7
+ import { getPackageManagerUsedForExistingProject } from "../../packageManager.js";
8
+ import { getModTargetDirectoryName } from "../../utils.js";
9
+ import { compileAndCopy } from "../copy/copy.js";
10
+ export async function publishIsaacScriptMod(args, config) {
11
+ const dryRun = args.dryRun === true;
12
+ const verbose = args.verbose === true;
13
+ const packageManager = getPackageManagerUsedForExistingProject(args);
14
+ const modTargetDirectoryName = getModTargetDirectoryName(config);
15
+ const modTargetPath = path.join(config.modsDirectory, modTargetDirectoryName);
16
+ const version = getPackageJSONVersion(undefined);
17
+ unsetDevelopmentConstant();
18
+ runReleaseScriptPreCopy(verbose);
19
+ await compileAndCopy(MOD_SOURCE_PATH, modTargetPath, packageManager, verbose);
20
+ purgeRoomXMLs(modTargetPath);
21
+ runReleaseScriptPostCopy(verbose);
22
+ if (dryRun) {
23
+ execShellString("git reset --hard", verbose); // Revert the version changes.
24
+ }
25
+ else {
26
+ const releaseGitCommitMessage = getReleaseGitCommitMessage(version);
27
+ gitCommitAllAndPush(releaseGitCommitMessage, verbose);
28
+ uploadMod(modTargetPath, verbose);
29
+ }
30
+ const dryRunSuffix = dryRun ? " (dry run)" : "";
31
+ console.log(`\nPublished version ${version} successfully${dryRunSuffix}.`);
32
+ }
33
+ function unsetDevelopmentConstant() {
34
+ if (!isFile(CONSTANTS_TS_PATH)) {
35
+ return;
36
+ }
37
+ const constantsTS = readFile(CONSTANTS_TS_PATH);
38
+ const newConstantsTS = constantsTS.replace("const IS_DEV = true", "const IS_DEV = false");
39
+ writeFile(CONSTANTS_TS_PATH, newConstantsTS);
40
+ }
41
+ function runReleaseScriptPreCopy(verbose) {
42
+ if (!isFile(PUBLISH_PRE_COPY_PY_PATH)) {
43
+ return;
44
+ }
45
+ console.log(`Running the "${PUBLISH_PRE_COPY_PY_PATH}" script.`);
46
+ const { stdout } = execShell("python", [PUBLISH_PRE_COPY_PY_PATH], verbose);
47
+ if (stdout !== "") {
48
+ console.log(stdout);
49
+ }
50
+ }
51
+ function runReleaseScriptPostCopy(verbose) {
52
+ if (!isFile(PUBLISH_POST_COPY_PY_PATH)) {
53
+ return;
54
+ }
55
+ console.log(`Running the "${PUBLISH_POST_COPY_PY_PATH}" script.`);
56
+ const { stdout } = execShell("python", [PUBLISH_POST_COPY_PY_PATH], verbose);
57
+ if (stdout !== "") {
58
+ console.log(stdout);
59
+ }
60
+ }
61
+ function purgeRoomXMLs(modTargetPath) {
62
+ const roomsPath = path.join(modTargetPath, "resources", "rooms");
63
+ if (!isDirectory(roomsPath)) {
64
+ return;
65
+ }
66
+ const fileNames = getFileNamesInDirectory(roomsPath);
67
+ const xmlFileNames = fileNames.filter((fileName) => path.extname(fileName) === ".xml");
68
+ for (const xmlFileName of xmlFileNames) {
69
+ const roomFilePath = path.join(roomsPath, xmlFileName);
70
+ deleteFileOrDirectory(roomFilePath);
71
+ }
72
+ }
73
+ function uploadMod(modTargetPath, verbose) {
74
+ if (hasIsaacSteamWorkshopUploadGitHubAction()) {
75
+ // CI will automatically upload the new version to the Steam Workshop, so there is no need to
76
+ // open the mod uploader program.
77
+ return;
78
+ }
79
+ console.log(`The "isaac-steam-workshop-upload" action was not found in the "${chalk.green("ci.yml")}" file; assuming that we want to use the "ModUploader.exe" tool.`);
80
+ execExe(MOD_UPLOADER_PATH, [], verbose, modTargetPath);
81
+ }
82
+ function hasIsaacSteamWorkshopUploadGitHubAction() {
83
+ const ciYMLPath = path.join(CWD, ".github", "workflows", "ci.yml");
84
+ if (!isFile(ciYMLPath)) {
85
+ return false;
86
+ }
87
+ const ciYML = readFile(ciYMLPath);
88
+ const lines = ciYML.split("\n");
89
+ return lines.some((line) => line.match(/^\s*uses: IsaacScript\/isaac-steam-workshop-upload/) !== null);
90
+ }