hackmud-script-manager 0.20.4-67aeb81 → 0.20.4-6815ce0
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 +214 -252
- package/env.d.ts +330 -276
- package/generateTypeDeclaration.js +2 -1
- package/index.js +2 -1
- package/package.json +38 -38
- package/processScript/index.js +3 -3
- package/processScript/minify.js +11 -17
- package/processScript/postprocess.d.ts +1 -1
- package/processScript/postprocess.js +3 -3
- package/processScript/preprocess.js +5 -3
- package/processScript/transform.js +99 -95
- 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,171 @@ 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-6815ce0")
|
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 typeDeclarationPathOption = popOption(
|
204
|
+
"type-declaration-path",
|
205
|
+
"type-declaration",
|
206
|
+
"dts",
|
207
|
+
"gen-types"
|
208
|
+
)
|
209
|
+
complainAboutUnrecognisedOptions()
|
210
|
+
const { watch } = await watchModule
|
211
|
+
watch(sourcePath, hackmudPath, {
|
212
|
+
scripts,
|
213
|
+
onPush: info => logInfo(info, hackmudPath),
|
214
|
+
typeDeclarationPath: typeDeclarationPathOption?.value.toString(),
|
215
|
+
minify: noMinifyOption && !noMinifyOption.value,
|
216
|
+
mangleNames: mangleNamesOption?.value,
|
217
|
+
onReady: () => log("Watching"),
|
218
|
+
forceQuineCheats: forceQuineCheatsOption?.value
|
219
|
+
})
|
220
|
+
autoExit = !1
|
181
221
|
}
|
182
|
-
shouldMinify = !shouldSkipMinify
|
183
222
|
}
|
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
223
|
}
|
217
224
|
break
|
218
225
|
case "pull":
|
@@ -222,8 +229,9 @@ switch (commands[0]) {
|
|
222
229
|
if (!script) {
|
223
230
|
logError("Must provide the script to pull\n")
|
224
231
|
logHelp()
|
225
|
-
|
232
|
+
process.exit(1)
|
226
233
|
}
|
234
|
+
complainAboutUnrecognisedOptions()
|
227
235
|
const sourcePath = commands[2] || "."
|
228
236
|
await pull(sourcePath, hackmudPath, script).catch(error => {
|
229
237
|
console.error(error)
|
@@ -233,8 +241,9 @@ switch (commands[0]) {
|
|
233
241
|
break
|
234
242
|
case "sync-macros":
|
235
243
|
{
|
236
|
-
const hackmudPath = getHackmudPath()
|
237
|
-
|
244
|
+
const hackmudPath = getHackmudPath()
|
245
|
+
complainAboutUnrecognisedOptions()
|
246
|
+
const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
|
238
247
|
log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
|
239
248
|
}
|
240
249
|
break
|
@@ -242,19 +251,29 @@ switch (commands[0]) {
|
|
242
251
|
case "gen-type-declaration":
|
243
252
|
case "gen-dts":
|
244
253
|
case "gen-types":
|
254
|
+
case "emit-dts":
|
245
255
|
{
|
246
|
-
|
256
|
+
"emit-dts" != commands[0] &&
|
257
|
+
"gen-dts" != commands[0] &&
|
258
|
+
console.warn(
|
259
|
+
colourF(
|
260
|
+
`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`
|
261
|
+
)
|
262
|
+
)
|
263
|
+
const hackmudPath = getHackmudPath(),
|
264
|
+
target = commands[1]
|
247
265
|
if (!target) {
|
248
266
|
logError("Must provide target directory\n")
|
249
267
|
logHelp()
|
250
|
-
|
268
|
+
process.exit(1)
|
251
269
|
}
|
270
|
+
complainAboutUnrecognisedOptions()
|
252
271
|
const sourcePath = resolve(target),
|
253
272
|
outputPath = commands[2] || "./player.d.ts",
|
254
|
-
typeDeclaration = await generateTypeDeclaration(sourcePath,
|
273
|
+
typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
|
255
274
|
let typeDeclarationPath = resolve(outputPath)
|
256
275
|
await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
|
257
|
-
assert(error instanceof Error, "src/bin/hsm.ts:
|
276
|
+
assert(error instanceof Error, "src/bin/hsm.ts:353:35")
|
258
277
|
if ("EISDIR" != error.code) throw error
|
259
278
|
typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
|
260
279
|
return writeFile(typeDeclarationPath, typeDeclaration)
|
@@ -266,99 +285,6 @@ switch (commands[0]) {
|
|
266
285
|
case "h":
|
267
286
|
logHelp()
|
268
287
|
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
288
|
default:
|
363
289
|
commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
|
364
290
|
logHelp()
|
@@ -368,21 +294,20 @@ function logHelp() {
|
|
368
294
|
const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
|
369
295
|
forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`,
|
370
296
|
hackmudPathOption = `${colourN("--hackmud-path")}=${colourB("<path>")}\n Override hackmud path`
|
371
|
-
console.log(colourN("Version") + colourS(": ") + colourV(version))
|
372
297
|
switch (commands[0]) {
|
373
298
|
case "dev":
|
374
299
|
case "watch":
|
375
300
|
case "push":
|
376
301
|
console.log(
|
377
302
|
colourS(
|
378
|
-
|
303
|
+
`${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("--type-declaration-path")}=${colourB("<path>")}\n Path to generate a type declaration 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
304
|
)
|
380
305
|
)
|
381
306
|
break
|
382
307
|
case "pull":
|
383
308
|
console.log(
|
384
309
|
colourS(
|
385
|
-
|
310
|
+
`${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
311
|
)
|
387
312
|
)
|
388
313
|
break
|
@@ -390,7 +315,7 @@ function logHelp() {
|
|
390
315
|
case "golf":
|
391
316
|
console.log(
|
392
317
|
colourS(
|
393
|
-
|
318
|
+
`${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
319
|
)
|
395
320
|
)
|
396
321
|
break
|
@@ -398,6 +323,14 @@ function logHelp() {
|
|
398
323
|
case "gen-type-declaration":
|
399
324
|
case "gen-dts":
|
400
325
|
case "gen-types":
|
326
|
+
case "emit-dts":
|
327
|
+
"emit-dts" != commands[0] &&
|
328
|
+
"gen-dts" != commands[0] &&
|
329
|
+
console.warn(
|
330
|
+
colourF(
|
331
|
+
`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`
|
332
|
+
)
|
333
|
+
)
|
401
334
|
console.log(
|
402
335
|
colourS(
|
403
336
|
`${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 +340,14 @@ function logHelp() {
|
|
407
340
|
case "sync-macros":
|
408
341
|
console.log(
|
409
342
|
colourS(
|
410
|
-
|
343
|
+
`${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
|
411
344
|
)
|
412
345
|
)
|
413
346
|
break
|
414
347
|
default:
|
415
348
|
console.log(
|
416
349
|
colourS(
|
417
|
-
|
350
|
+
`${colourJ("Hackmud Script Manager")}\n${colourN("Version") + colourS(": ") + colourV("0.20.4-6815ce0")}\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`
|
418
351
|
)
|
419
352
|
)
|
420
353
|
}
|
@@ -432,7 +365,7 @@ function logError(message) {
|
|
432
365
|
process.exitCode = 1
|
433
366
|
}
|
434
367
|
function getHackmudPath() {
|
435
|
-
const hackmudPathOption =
|
368
|
+
const hackmudPathOption = popOption("hackmud-path")?.value
|
436
369
|
if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
|
437
370
|
logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
|
438
371
|
logHelp()
|
@@ -444,3 +377,32 @@ function getHackmudPath() {
|
|
444
377
|
("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
|
445
378
|
)
|
446
379
|
}
|
380
|
+
function assertOptionIsBoolean(option) {
|
381
|
+
if ("boolean" != typeof option.value) {
|
382
|
+
logError(`The value for ${formatOption(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
|
383
|
+
logHelp()
|
384
|
+
process.exit(1)
|
385
|
+
}
|
386
|
+
}
|
387
|
+
function popOption(...names) {
|
388
|
+
const presentOptionNames = names.filter(name => options.has(name))
|
389
|
+
if (!presentOptionNames.length) return
|
390
|
+
const presentOptionNamesWithDashDash = presentOptionNames.map(formatOption)
|
391
|
+
if (presentOptionNames.length > 1) {
|
392
|
+
logError(
|
393
|
+
`The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
|
394
|
+
)
|
395
|
+
process.exit(1)
|
396
|
+
}
|
397
|
+
const value = options.get(presentOptionNames[0])
|
398
|
+
options.delete(presentOptionNames[0])
|
399
|
+
return { name: presentOptionNamesWithDashDash[0], value }
|
400
|
+
}
|
401
|
+
function complainAboutUnrecognisedOptions() {
|
402
|
+
if (options.size) {
|
403
|
+
logError(
|
404
|
+
`Unrecognised option${options.size > 1 ? "s" : ""}: ${[...options.keys()].map(formatOption).join(", ")}`
|
405
|
+
)
|
406
|
+
process.exit(1)
|
407
|
+
}
|
408
|
+
}
|