hackmud-script-manager 0.20.4-a5e6bcd → 0.20.4-a7d8309
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/bin/hsm.js +223 -253
- package/env.d.ts +315 -310
- package/generateTypeDeclaration.js +2 -1
- package/index.js +2 -1
- package/package.json +38 -38
- package/processScript/index.js +2 -2
- package/processScript/minify.js +5 -14
- package/processScript/preprocess.js +5 -3
- package/processScript/transform.js +87 -84
- package/push.js +4 -4
- package/watch.js +9 -7
package/README.md
CHANGED
@@ -20,6 +20,10 @@ You can read about how HSM works [in my blog post](https://samual.uk/blog/js-cod
|
|
20
20
|
> ```
|
21
21
|
> You will need to run `Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser` in PowerShell as an administrator. For more information, see [Microsoft's page about Execution Policies](https://learn.microsoft.com/en-gb/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4).
|
22
22
|
|
23
|
+

|
24
|
+

|
25
|
+

|
26
|
+
|
23
27
|
## Features
|
24
28
|
- Minification
|
25
29
|
- This includes auto quine cheating.
|
package/bin/hsm.js
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import {
|
2
|
+
import { AutoMap } from "@samual/lib/AutoMap"
|
3
3
|
import { assert } from "@samual/lib/assert"
|
4
4
|
import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
|
5
5
|
import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
|
6
6
|
import { writeFile, readFile } from "fs/promises"
|
7
7
|
import { homedir } from "os"
|
8
|
-
import { extname, basename,
|
8
|
+
import { resolve, extname, basename, dirname, relative } from "path"
|
9
9
|
import { supportedExtensions } from "../constants.js"
|
10
10
|
import { generateTypeDeclaration } from "../generateTypeDeclaration.js"
|
11
11
|
import { pull } from "../pull.js"
|
12
12
|
import { syncMacros } from "../syncMacros.js"
|
13
13
|
import "@samual/lib/readDirectoryWithStats"
|
14
|
+
import "path/posix"
|
14
15
|
import "@samual/lib/copyFilePersistent"
|
15
|
-
const
|
16
|
+
const formatOption = name => colourN(`-${1 == name.length ? "" : "-"}${name}`),
|
16
17
|
options = new Map(),
|
17
18
|
commands = [],
|
18
|
-
userColours = new
|
19
|
+
userColours = new AutoMap(user => {
|
19
20
|
let hash = 0
|
20
21
|
for (const char of user) hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
|
21
22
|
return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user)
|
@@ -36,10 +37,6 @@ for (const argument of process.argv.slice(2))
|
|
36
37
|
if ("-" == argument[1]) options.set(key.slice(2), value)
|
37
38
|
else for (const option of key.slice(1)) options.set(option, value)
|
38
39
|
} else commands.push(argument)
|
39
|
-
if ("v" == commands[0] || "version" == commands[0] || options.get("version") || options.get("v")) {
|
40
|
-
console.log(version)
|
41
|
-
process.exit()
|
42
|
-
}
|
43
40
|
const pushModule = import("../push.js"),
|
44
41
|
processScriptModule = import("../processScript/index.js"),
|
45
42
|
watchModule = import("../watch.js"),
|
@@ -49,6 +46,7 @@ const pushModule = import("../push.js"),
|
|
49
46
|
colourB = chalk.rgb(202, 202, 202),
|
50
47
|
colourC = chalk.rgb(155, 155, 155),
|
51
48
|
colourD = chalk.rgb(255, 0, 0),
|
49
|
+
colourF = chalk.rgb(255, 128, 0),
|
52
50
|
colourJ = chalk.rgb(255, 244, 4),
|
53
51
|
colourK = chalk.rgb(243, 249, 152),
|
54
52
|
colourL = chalk.rgb(30, 255, 0),
|
@@ -57,162 +55,180 @@ const pushModule = import("../push.js"),
|
|
57
55
|
colourS = chalk.rgb(122, 178, 244),
|
58
56
|
colourV = chalk.rgb(255, 0, 236),
|
59
57
|
colourW = chalk.rgb(255, 150, 224)
|
60
|
-
|
58
|
+
process.version.startsWith("v21.") &&
|
59
|
+
console.warn(
|
60
|
+
colourF(
|
61
|
+
`Warning: Support for Node.js 21 will be dropped in the next minor version of HSM\n Your current version of Node.js is ${chalk.bold(process.version)}\n You should update your version of Node.js\n https://nodejs.org/en/download/package-manager\n`
|
62
|
+
)
|
63
|
+
)
|
64
|
+
if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
|
65
|
+
console.log("0.20.4-a7d8309")
|
66
|
+
process.exit()
|
67
|
+
}
|
68
|
+
if (popOption("help", "h")?.value) {
|
61
69
|
logHelp()
|
62
70
|
process.exit()
|
63
71
|
}
|
64
72
|
let autoExit = !0
|
65
73
|
switch (commands[0]) {
|
66
74
|
case "push":
|
75
|
+
case "dev":
|
76
|
+
case "watch":
|
77
|
+
case "golf":
|
78
|
+
case "minify":
|
67
79
|
{
|
68
|
-
const
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
break
|
74
|
-
}
|
75
|
-
const scripts = commands.slice(2)
|
76
|
-
if (scripts.length) {
|
77
|
-
const invalidScript = scripts.find(
|
78
|
-
script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
|
79
|
-
)
|
80
|
-
if (invalidScript) {
|
81
|
-
logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
|
82
|
-
logHelp()
|
83
|
-
break
|
84
|
-
}
|
85
|
-
} else scripts.push("*.*")
|
86
|
-
const optionsHasNoMinify = options.has("no-minify")
|
87
|
-
if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
|
80
|
+
const noMinifyOption = popOption("no-minify", "skip-minify"),
|
81
|
+
mangleNamesOption = popOption("mangle-names"),
|
82
|
+
forceQuineCheatsOption = popOption("force-quine-cheats"),
|
83
|
+
noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
|
84
|
+
if (noMinifyOption && noMinifyIncompatibleOption) {
|
88
85
|
logError(
|
89
|
-
`Options ${
|
86
|
+
`Options ${formatOption(noMinifyOption.name)} and ${formatOption(noMinifyIncompatibleOption.name)} are incompatible\n`
|
90
87
|
)
|
91
88
|
logHelp()
|
92
|
-
|
89
|
+
process.exit(1)
|
93
90
|
}
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
91
|
+
noMinifyOption && assertOptionIsBoolean(noMinifyOption)
|
92
|
+
mangleNamesOption && assertOptionIsBoolean(mangleNamesOption)
|
93
|
+
forceQuineCheatsOption && assertOptionIsBoolean(forceQuineCheatsOption)
|
94
|
+
if ("golf" == commands[0] || "minify" == commands[0]) {
|
95
|
+
const watchOption = popOption("watch"),
|
96
|
+
target = commands[1]
|
97
|
+
if (!target) {
|
98
|
+
logError("Must provide target\n")
|
99
|
+
logHelp()
|
100
|
+
process.exit(1)
|
101
|
+
}
|
102
|
+
const fileExtension = extname(target)
|
103
|
+
if (!supportedExtensions.includes(fileExtension)) {
|
98
104
|
logError(
|
99
|
-
`
|
105
|
+
`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`
|
100
106
|
)
|
101
|
-
|
102
|
-
break
|
107
|
+
process.exit(1)
|
103
108
|
}
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
109
|
+
complainAboutUnrecognisedOptions()
|
110
|
+
const { processScript } = await processScriptModule,
|
111
|
+
fileBaseName = basename(target, fileExtension),
|
112
|
+
fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
|
113
|
+
scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName,
|
114
|
+
scriptUser =
|
115
|
+
(
|
116
|
+
"scripts" == basename(resolve(target, "..")) &&
|
117
|
+
"hackmud" == basename(resolve(target, "../../.."))
|
118
|
+
) ?
|
119
|
+
basename(resolve(target, "../.."))
|
120
|
+
: void 0
|
121
|
+
let outputPath =
|
122
|
+
commands[2] ||
|
123
|
+
resolve(
|
124
|
+
dirname(target),
|
125
|
+
fileBaseNameEndsWithDotSrc ? scriptName + ".js"
|
126
|
+
: ".js" == fileExtension ? fileBaseName + ".min.js"
|
127
|
+
: fileBaseName + ".js"
|
128
|
+
)
|
129
|
+
const golfFile = () =>
|
130
|
+
readFile(target, { encoding: "utf8" }).then(async source => {
|
131
|
+
const timeStart = performance.now(),
|
132
|
+
{ script, warnings } = await processScript(source, {
|
133
|
+
minify: noMinifyOption && !noMinifyOption.value,
|
134
|
+
scriptUser,
|
135
|
+
scriptName,
|
136
|
+
filePath: target,
|
137
|
+
mangleNames: mangleNamesOption?.value,
|
138
|
+
forceQuineCheats: forceQuineCheatsOption?.value
|
139
|
+
}),
|
140
|
+
timeTook = performance.now() - timeStart
|
141
|
+
for (const { message, line } of warnings)
|
142
|
+
log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
|
143
|
+
await writeFilePersistent(outputPath, script)
|
144
|
+
.catch(error => {
|
145
|
+
if (!commands[2] || "EISDIR" != error.code) throw error
|
146
|
+
outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
|
147
|
+
return writeFilePersistent(outputPath, script)
|
148
|
+
})
|
149
|
+
.then(() =>
|
150
|
+
log(
|
151
|
+
`Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
|
152
|
+
)
|
153
|
+
)
|
154
|
+
})
|
155
|
+
if (watchOption) {
|
156
|
+
const { watch: watchFile } = await chokidarModule
|
157
|
+
watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
|
158
|
+
.on("ready", () => log("Watching " + target))
|
159
|
+
.on("change", golfFile)
|
160
|
+
autoExit = !1
|
161
|
+
} else await golfFile()
|
162
|
+
} else {
|
163
|
+
const hackmudPath = getHackmudPath(),
|
164
|
+
sourcePath = commands[1]
|
165
|
+
if (!sourcePath) {
|
166
|
+
logError(`Must provide the directory to ${"push" == commands[0] ? "push from" : "watch"}\n`)
|
160
167
|
logHelp()
|
161
|
-
|
168
|
+
process.exit(1)
|
162
169
|
}
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
`Options ${colourN("--mangle-names")} and ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} are incompatible\n`
|
168
|
-
)
|
169
|
-
logHelp()
|
170
|
-
break
|
171
|
-
}
|
172
|
-
const shouldSkipMinify = options.get("no-minify") || options.get("skip-minify")
|
173
|
-
let shouldMinify
|
174
|
-
if (null != shouldSkipMinify) {
|
175
|
-
if ("boolean" != typeof shouldSkipMinify) {
|
176
|
-
logError(
|
177
|
-
`The value for ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} must be ${colourV("true")} or ${colourV("false")}\n`
|
170
|
+
const scripts = commands.slice(2)
|
171
|
+
if (scripts.length) {
|
172
|
+
const invalidScript = scripts.find(
|
173
|
+
script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
|
178
174
|
)
|
179
|
-
|
180
|
-
|
175
|
+
if (invalidScript) {
|
176
|
+
logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
|
177
|
+
logHelp()
|
178
|
+
process.exit(1)
|
179
|
+
}
|
180
|
+
} else scripts.push("*.*")
|
181
|
+
if ("push" == commands[0]) {
|
182
|
+
const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } = await pushModule
|
183
|
+
complainAboutUnrecognisedOptions()
|
184
|
+
const infos = await push(sourcePath, hackmudPath, {
|
185
|
+
scripts,
|
186
|
+
onPush: info => logInfo(info, hackmudPath),
|
187
|
+
minify: noMinifyOption && !noMinifyOption.value,
|
188
|
+
mangleNames: mangleNamesOption?.value,
|
189
|
+
forceQuineCheats: forceQuineCheatsOption?.value
|
190
|
+
})
|
191
|
+
if (infos instanceof Error) {
|
192
|
+
logError(infos.message)
|
193
|
+
if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
|
194
|
+
console.log()
|
195
|
+
logHelp()
|
196
|
+
} else
|
197
|
+
infos instanceof MissingHackmudFolderError &&
|
198
|
+
log(
|
199
|
+
`If this is not where your hackmud folder is, you can specify it with the\n${colourN("--hackmud-path")}=${colourB("<path>")} option or ${colourN("HSM_HACKMUD_PATH")} environment variable`
|
200
|
+
)
|
201
|
+
} else infos.length || logError("Could not find any scripts to push")
|
202
|
+
} else {
|
203
|
+
const dtsPathOption = popOption(
|
204
|
+
"dts-path",
|
205
|
+
"type-declaration-path",
|
206
|
+
"type-declaration",
|
207
|
+
"dts",
|
208
|
+
"gen-types"
|
209
|
+
)
|
210
|
+
dtsPathOption &&
|
211
|
+
"emit-dts" != dtsPathOption.name &&
|
212
|
+
"gen-dts" != dtsPathOption.name &&
|
213
|
+
console.warn(
|
214
|
+
colourF(
|
215
|
+
`Warning: ${colourN(dtsPathOption.name)} is being deprecated and will be removed in the\n next minor release of HSM\n You should switch to using its alias ${colourN("--dts-path")}\n`
|
216
|
+
)
|
217
|
+
)
|
218
|
+
complainAboutUnrecognisedOptions()
|
219
|
+
const { watch } = await watchModule
|
220
|
+
watch(sourcePath, hackmudPath, {
|
221
|
+
scripts,
|
222
|
+
onPush: info => logInfo(info, hackmudPath),
|
223
|
+
typeDeclarationPath: dtsPathOption?.value.toString(),
|
224
|
+
minify: noMinifyOption && !noMinifyOption.value,
|
225
|
+
mangleNames: mangleNamesOption?.value,
|
226
|
+
onReady: () => log("Watching"),
|
227
|
+
forceQuineCheats: forceQuineCheatsOption?.value
|
228
|
+
})
|
229
|
+
autoExit = !1
|
181
230
|
}
|
182
|
-
shouldMinify = !shouldSkipMinify
|
183
231
|
}
|
184
|
-
const shouldMangleNames = options.get("mangle-names")
|
185
|
-
if (null != shouldMangleNames && "boolean" != typeof shouldMangleNames) {
|
186
|
-
logError(
|
187
|
-
`The value for ${colourN("--mangle-names")} must be ${colourV("true")} or ${colourV("false")}\n`
|
188
|
-
)
|
189
|
-
logHelp()
|
190
|
-
break
|
191
|
-
}
|
192
|
-
const shouldforceQuineCheats = options.get("force-quine-cheats")
|
193
|
-
if (null != shouldforceQuineCheats && "boolean" != typeof shouldforceQuineCheats) {
|
194
|
-
logError(
|
195
|
-
`The value for ${colourN("--force-quine-cheats")} must be ${colourV("true")} or ${colourV("false")}\n`
|
196
|
-
)
|
197
|
-
logHelp()
|
198
|
-
break
|
199
|
-
}
|
200
|
-
const { watch } = await watchModule
|
201
|
-
watch(sourcePath, hackmudPath, {
|
202
|
-
scripts,
|
203
|
-
onPush: info => logInfo(info, hackmudPath),
|
204
|
-
typeDeclarationPath: (
|
205
|
-
options.get("type-declaration-path") ||
|
206
|
-
options.get("type-declaration") ||
|
207
|
-
options.get("dts") ||
|
208
|
-
options.get("gen-types")
|
209
|
-
)?.toString(),
|
210
|
-
minify: shouldMinify,
|
211
|
-
mangleNames: shouldMangleNames,
|
212
|
-
onReady: () => log("Watching"),
|
213
|
-
forceQuineCheats: shouldforceQuineCheats
|
214
|
-
})
|
215
|
-
autoExit = !1
|
216
232
|
}
|
217
233
|
break
|
218
234
|
case "pull":
|
@@ -222,8 +238,9 @@ switch (commands[0]) {
|
|
222
238
|
if (!script) {
|
223
239
|
logError("Must provide the script to pull\n")
|
224
240
|
logHelp()
|
225
|
-
|
241
|
+
process.exit(1)
|
226
242
|
}
|
243
|
+
complainAboutUnrecognisedOptions()
|
227
244
|
const sourcePath = commands[2] || "."
|
228
245
|
await pull(sourcePath, hackmudPath, script).catch(error => {
|
229
246
|
console.error(error)
|
@@ -233,8 +250,9 @@ switch (commands[0]) {
|
|
233
250
|
break
|
234
251
|
case "sync-macros":
|
235
252
|
{
|
236
|
-
const hackmudPath = getHackmudPath()
|
237
|
-
|
253
|
+
const hackmudPath = getHackmudPath()
|
254
|
+
complainAboutUnrecognisedOptions()
|
255
|
+
const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
|
238
256
|
log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
|
239
257
|
}
|
240
258
|
break
|
@@ -242,19 +260,29 @@ switch (commands[0]) {
|
|
242
260
|
case "gen-type-declaration":
|
243
261
|
case "gen-dts":
|
244
262
|
case "gen-types":
|
263
|
+
case "emit-dts":
|
245
264
|
{
|
246
|
-
|
265
|
+
"emit-dts" != commands[0] &&
|
266
|
+
"gen-dts" != commands[0] &&
|
267
|
+
console.warn(
|
268
|
+
colourF(
|
269
|
+
`Warning: ${colourC("hsm")} ${colourL(commands[0])} is being deprecated and will be removed\n in the next minor release of HSM\n You should switch to using its alias ${colourC("hsm")} ${colourL("emit-dts")}\n`
|
270
|
+
)
|
271
|
+
)
|
272
|
+
const hackmudPath = getHackmudPath(),
|
273
|
+
target = commands[1]
|
247
274
|
if (!target) {
|
248
275
|
logError("Must provide target directory\n")
|
249
276
|
logHelp()
|
250
|
-
|
277
|
+
process.exit(1)
|
251
278
|
}
|
279
|
+
complainAboutUnrecognisedOptions()
|
252
280
|
const sourcePath = resolve(target),
|
253
281
|
outputPath = commands[2] || "./player.d.ts",
|
254
|
-
typeDeclaration = await generateTypeDeclaration(sourcePath,
|
282
|
+
typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
|
255
283
|
let typeDeclarationPath = resolve(outputPath)
|
256
284
|
await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
|
257
|
-
assert(error instanceof Error, "src/bin/hsm.ts:
|
285
|
+
assert(error instanceof Error, "src/bin/hsm.ts:361:35")
|
258
286
|
if ("EISDIR" != error.code) throw error
|
259
287
|
typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
|
260
288
|
return writeFile(typeDeclarationPath, typeDeclaration)
|
@@ -263,102 +291,8 @@ switch (commands[0]) {
|
|
263
291
|
}
|
264
292
|
break
|
265
293
|
case "help":
|
266
|
-
case "h":
|
267
294
|
logHelp()
|
268
295
|
break
|
269
|
-
case "golf":
|
270
|
-
case "minify":
|
271
|
-
{
|
272
|
-
const target = commands[1]
|
273
|
-
if (!target) {
|
274
|
-
logError("Must provide target\n")
|
275
|
-
logHelp()
|
276
|
-
break
|
277
|
-
}
|
278
|
-
const fileExtension = extname(target)
|
279
|
-
if (!supportedExtensions.includes(fileExtension)) {
|
280
|
-
logError(
|
281
|
-
`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`
|
282
|
-
)
|
283
|
-
break
|
284
|
-
}
|
285
|
-
const { processScript } = await processScriptModule,
|
286
|
-
fileBaseName = basename(target, fileExtension),
|
287
|
-
fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
|
288
|
-
scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName,
|
289
|
-
scriptUser =
|
290
|
-
"scripts" == basename(resolve(target, "..")) && "hackmud" == basename(resolve(target, "../../..")) ?
|
291
|
-
basename(resolve(target, "../.."))
|
292
|
-
: void 0,
|
293
|
-
optionsHasNoMinify = options.has("no-minify")
|
294
|
-
if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
|
295
|
-
logError(
|
296
|
-
`Options ${colourN("--mangle-names")} and ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} are incompatible\n`
|
297
|
-
)
|
298
|
-
logHelp()
|
299
|
-
break
|
300
|
-
}
|
301
|
-
const mangleNames_ = options.get("mangle-names")
|
302
|
-
if (null != mangleNames_ && "boolean" != typeof mangleNames_) {
|
303
|
-
logError(
|
304
|
-
`The value for ${colourN("--mangle-names")} must be ${colourV("true")} or ${colourV("false")}\n`
|
305
|
-
)
|
306
|
-
logHelp()
|
307
|
-
break
|
308
|
-
}
|
309
|
-
const mangleNames = mangleNames_,
|
310
|
-
forceQuineCheats_ = options.get("force-quine-cheats")
|
311
|
-
if (null != forceQuineCheats_ && "boolean" != typeof forceQuineCheats_) {
|
312
|
-
logError(
|
313
|
-
`the value for ${colourN("--force-quine-cheats")} must be ${colourV("true")} or ${colourV("false")}\n`
|
314
|
-
)
|
315
|
-
logHelp()
|
316
|
-
break
|
317
|
-
}
|
318
|
-
const forceQuineCheats = forceQuineCheats_
|
319
|
-
let outputPath =
|
320
|
-
commands[2] ||
|
321
|
-
resolve(
|
322
|
-
dirname(target),
|
323
|
-
fileBaseNameEndsWithDotSrc ? scriptName + ".js"
|
324
|
-
: ".js" == fileExtension ? fileBaseName + ".min.js"
|
325
|
-
: fileBaseName + ".js"
|
326
|
-
)
|
327
|
-
const golfFile = () =>
|
328
|
-
readFile(target, { encoding: "utf8" }).then(async source => {
|
329
|
-
const timeStart = performance.now(),
|
330
|
-
{ script, warnings } = await processScript(source, {
|
331
|
-
minify: !(options.get("no-minify") || options.get("skip-minify")),
|
332
|
-
scriptUser,
|
333
|
-
scriptName,
|
334
|
-
filePath: target,
|
335
|
-
mangleNames,
|
336
|
-
forceQuineCheats
|
337
|
-
}),
|
338
|
-
timeTook = performance.now() - timeStart
|
339
|
-
for (const { message, line } of warnings)
|
340
|
-
log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
|
341
|
-
await writeFilePersistent(outputPath, script)
|
342
|
-
.catch(error => {
|
343
|
-
if (!commands[2] || "EISDIR" != error.code) throw error
|
344
|
-
outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
|
345
|
-
return writeFilePersistent(outputPath, script)
|
346
|
-
})
|
347
|
-
.then(() =>
|
348
|
-
log(
|
349
|
-
`Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
|
350
|
-
)
|
351
|
-
)
|
352
|
-
})
|
353
|
-
if (options.get("watch")) {
|
354
|
-
const { watch: watchFile } = await chokidarModule
|
355
|
-
watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
|
356
|
-
.on("ready", () => log("Watching " + target))
|
357
|
-
.on("change", golfFile)
|
358
|
-
autoExit = !1
|
359
|
-
} else await golfFile()
|
360
|
-
}
|
361
|
-
break
|
362
296
|
default:
|
363
297
|
commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
|
364
298
|
logHelp()
|
@@ -368,21 +302,20 @@ function logHelp() {
|
|
368
302
|
const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
|
369
303
|
forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`,
|
370
304
|
hackmudPathOption = `${colourN("--hackmud-path")}=${colourB("<path>")}\n Override hackmud path`
|
371
|
-
console.log(colourN("Version") + colourS(": ") + colourV(version))
|
372
305
|
switch (commands[0]) {
|
373
306
|
case "dev":
|
374
307
|
case "watch":
|
375
308
|
case "push":
|
376
309
|
console.log(
|
377
310
|
colourS(
|
378
|
-
|
311
|
+
`${colourJ("push" == commands[0] ? pushCommandDescription : "Watch a directory and push a script when modified")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB('<directory> ["<script user>.<script name>"...]')}\n\n${colourA("Arguments:")}\n${colourB("<directory>")}\n The source directory containing your scripts\n${colourB("<script user>")}\n A user to push script(s) to. Can be set to wild card (${colourV("*")}) which will try\n and discover users to push to\n${colourB("<script name>")}\n Name of a script to push. Can be set to wild card (${colourV("*")}) to find all scripts\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}\n${hackmudPathOption}\n${"push" == commands[0] ? "" : `${colourN("--dts-path")}=${colourB("<path>")}\n Path to generate a type declaration (.d.ts) file for the scripts\n`}\n${colourA("Examples:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")}\n Pushes all scripts found in ${colourV("src")} folder to all users\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")}\n Pushes a script named ${colourL("bar")} found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")} ${colourC("baz")}${colourV(".")}${colourL("qux")}\n Multiple can be specified\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("foo")}\n Pushes all scripts named ${colourL("foo")} found in ${colourV("src")} folder to all user\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to all users`
|
379
312
|
)
|
380
313
|
)
|
381
314
|
break
|
382
315
|
case "pull":
|
383
316
|
console.log(
|
384
317
|
colourS(
|
385
|
-
|
318
|
+
`${colourJ("Pull a script a from a hackmud user's script directory")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<script user>")}${colourV(".")}${colourB("<script name>")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
|
386
319
|
)
|
387
320
|
)
|
388
321
|
break
|
@@ -390,7 +323,7 @@ function logHelp() {
|
|
390
323
|
case "golf":
|
391
324
|
console.log(
|
392
325
|
colourS(
|
393
|
-
|
326
|
+
`${colourJ("Minify a script file on the spot")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<target> [output path]")}\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}\n${colourN("--watch")}\n Watch for changes`
|
394
327
|
)
|
395
328
|
)
|
396
329
|
break
|
@@ -398,6 +331,14 @@ function logHelp() {
|
|
398
331
|
case "gen-type-declaration":
|
399
332
|
case "gen-dts":
|
400
333
|
case "gen-types":
|
334
|
+
case "emit-dts":
|
335
|
+
"emit-dts" != commands[0] &&
|
336
|
+
"gen-dts" != commands[0] &&
|
337
|
+
console.warn(
|
338
|
+
colourF(
|
339
|
+
`Warning: ${colourC("hsm")} ${colourL(commands[0])} is being deprecated and will be removed\n in the next minor release of HSM\n You should switch to using its alias ${colourC("hsm")} ${colourL("emit-dts")}\n`
|
340
|
+
)
|
341
|
+
)
|
401
342
|
console.log(
|
402
343
|
colourS(
|
403
344
|
`${colourJ("Generate a type declaration file for a directory of scripts")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<directory> [output path]")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
|
@@ -407,14 +348,14 @@ function logHelp() {
|
|
407
348
|
case "sync-macros":
|
408
349
|
console.log(
|
409
350
|
colourS(
|
410
|
-
|
351
|
+
`${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
|
411
352
|
)
|
412
353
|
)
|
413
354
|
break
|
414
355
|
default:
|
415
356
|
console.log(
|
416
357
|
colourS(
|
417
|
-
|
358
|
+
`${colourJ("Hackmud Script Manager")}\n${colourN("Version") + colourS(": ") + colourV("0.20.4-a7d8309")}\n\n${colourA("Commands:")}\n${colourL("push")}\n ${pushCommandDescription}\n${colourL("dev")}\n Watch a directory and push a script when modified\n${colourL("minify")}\n Minify a script file on the spot\n${colourL("emit-dts")}\n Generate a type declaration file for a directory of scripts\n${colourL("sync-macros")}\n Sync macros across all hackmud users\n${colourL("pull")}\n Pull a script a from a hackmud user's script directory\n\n${colourA("Options:")}\n${colourN("--help")}\n Can be used on any command e.g. ${colourC("hsm")} ${colourL("push")} ${colourN("--help")} to show helpful information`
|
418
359
|
)
|
419
360
|
)
|
420
361
|
}
|
@@ -432,7 +373,7 @@ function logError(message) {
|
|
432
373
|
process.exitCode = 1
|
433
374
|
}
|
434
375
|
function getHackmudPath() {
|
435
|
-
const hackmudPathOption =
|
376
|
+
const hackmudPathOption = popOption("hackmud-path")?.value
|
436
377
|
if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
|
437
378
|
logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
|
438
379
|
logHelp()
|
@@ -444,3 +385,32 @@ function getHackmudPath() {
|
|
444
385
|
("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
|
445
386
|
)
|
446
387
|
}
|
388
|
+
function assertOptionIsBoolean(option) {
|
389
|
+
if ("boolean" != typeof option.value) {
|
390
|
+
logError(`The value for ${formatOption(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
|
391
|
+
logHelp()
|
392
|
+
process.exit(1)
|
393
|
+
}
|
394
|
+
}
|
395
|
+
function popOption(...names) {
|
396
|
+
const presentOptionNames = names.filter(name => options.has(name))
|
397
|
+
if (!presentOptionNames.length) return
|
398
|
+
const presentOptionNamesWithDashDash = presentOptionNames.map(formatOption)
|
399
|
+
if (presentOptionNames.length > 1) {
|
400
|
+
logError(
|
401
|
+
`The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
|
402
|
+
)
|
403
|
+
process.exit(1)
|
404
|
+
}
|
405
|
+
const value = options.get(presentOptionNames[0])
|
406
|
+
options.delete(presentOptionNames[0])
|
407
|
+
return { name: presentOptionNamesWithDashDash[0], value }
|
408
|
+
}
|
409
|
+
function complainAboutUnrecognisedOptions() {
|
410
|
+
if (options.size) {
|
411
|
+
logError(
|
412
|
+
`Unrecognised option${options.size > 1 ? "s" : ""}: ${[...options.keys()].map(formatOption).join(", ")}`
|
413
|
+
)
|
414
|
+
process.exit(1)
|
415
|
+
}
|
416
|
+
}
|