hackmud-script-manager 0.19.1-64ab3ba → 0.19.1-6d8d544

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Hackmud Script Manager
2
2
  Command made for [hackmud-environment](https://github.com/samualtnorman/hackmud-environment), which is a scripting environment for hackmud with minification, autocompletes / intellisense, and TypeScript support.
3
3
 
4
- Install with `npm install hackmud-script-manager -g` to make the `hsm` command available everywhere.
4
+ Install with `npm install -g hackmud-script-manager` to make the `hsm` command available everywhere.
5
5
 
6
6
  ## Features
7
7
  - Minification
package/bin/hsm.d.ts CHANGED
File without changes
package/bin/hsm.js CHANGED
@@ -3,17 +3,16 @@ import { Cache } from "@samual/lib/Cache"
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
- import { readFile, writeFile, mkdir, rmdir } from "fs/promises"
6
+ import { writeFile, readFile } from "fs/promises"
7
7
  import { homedir } from "os"
8
- import { resolve, extname, basename, dirname, relative } from "path"
8
+ import { extname, basename, resolve, 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
14
  import "@samual/lib/copyFilePersistent"
15
- const configDirectoryPath = resolve(homedir(), ".config"),
16
- configFilePath = resolve(configDirectoryPath, "hsm.json"),
15
+ const version = "0.19.1-6d8d544",
17
16
  options = new Map(),
18
17
  commands = [],
19
18
  userColours = new Cache(user => {
@@ -21,111 +20,7 @@ const configDirectoryPath = resolve(homedir(), ".config"),
21
20
  for (const char of user) hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
22
21
  return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user)
23
22
  }),
24
- logNeedHackmudPathMessage = () =>
25
- console.error(
26
- colourS(
27
- `${colourD("You need to set hackmudPath in config before you can use this command")}\n\n${colourA("To fix this:")}\nOpen hackmud and run "${colourC("#dir")}"\nThis will open a file browser and print your hackmud user's script directory\nGo up 2 directories and then copy the path\nThen in a terminal run "${colourC("hsm")} ${colourL("config set")} ${colourV("hackmudPath")} ${colourB("<the path you copied>")}"`
28
- )
29
- ),
30
- logHelp = () => {
31
- const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
32
- forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`
33
- console.log(colourN("Version") + colourS(": ") + colourV("0.19.1-64ab3ba"))
34
- switch (commands[0]) {
35
- case "config":
36
- switch (commands[1]) {
37
- case "get":
38
- console.log(
39
- `\n${colourJ("Retrieve a value from the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key>")}`
40
- )
41
- break
42
- case "set":
43
- console.log(
44
- `\n${colourJ("Assign a value to the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key> <value>")}`
45
- )
46
- break
47
- case "delete":
48
- console.log(
49
- `\n${colourJ("Remove a key and value from the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key>")}`
50
- )
51
- break
52
- default:
53
- console.log(
54
- colourS(
55
- `${colourN("Config path")}: ${colourV(configFilePath)}\n\n${colourJ("Modify the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0] + " get")} ${colourB("<key>")}\n Retrieve a value from the config file\n${colourC("hsm")} ${colourL(commands[0] + " set")} ${colourB("<key> <value>")}\n Assign a value to the config file\n${colourC("hsm")} ${colourL(commands[0] + " delete")} ${colourB("<key>")}\n Remove a key and value from the config file`
56
- )
57
- )
58
- }
59
- break
60
- case "dev":
61
- case "watch":
62
- case "push":
63
- console.log(
64
- colourS(
65
- `\n${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${"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\tPushes 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\tPushes 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\tPushes 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\tPushes all scripts found in ${colourV("src")} folder to all users`
66
- )
67
- )
68
- break
69
- case "pull":
70
- console.log(
71
- colourS(
72
- `\n${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>")}`
73
- )
74
- )
75
- break
76
- case "minify":
77
- case "golf":
78
- console.log(
79
- colourS(
80
- `\n${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`
81
- )
82
- )
83
- break
84
- case "generate-type-declaration":
85
- case "gen-type-declaration":
86
- case "gen-dts":
87
- case "gen-types":
88
- console.log(
89
- colourS(
90
- `${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]")}`
91
- )
92
- )
93
- break
94
- case "sync-macros":
95
- console.log("\n" + colourJ("Sync macros across all hackmud users"))
96
- break
97
- default:
98
- console.log(
99
- colourS(
100
- `\n${colourJ("Hackmud Script Manager")}\n\n${colourA("Commands:")}\n${colourL("push")}\n ${pushCommandDescription}\n${colourL("dev")}\n Watch a directory and push a script when modified\n${colourL("golf")}\n Minify a script file on the spot\n${colourL("gen-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("config")}\n Modify and view the config file\n${colourL("pull")}\n Pull a script a from a hackmud user's script directory`
101
- )
102
- )
103
- }
104
- },
105
- exploreObject = (object, keys, createPath = !1) => {
106
- for (const key of keys)
107
- object =
108
- createPath ?
109
- "object" == typeof object[key] ?
110
- object[key]
111
- : (object[key] = {})
112
- : object?.[key]
113
- return object
114
- },
115
- logInfo = ({ file, users, minLength, error }, hackmudPath) => {
116
- error ?
117
- logError(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`)
118
- : console.log(
119
- `pushed ${chalk.bold(file)} to ${users.map(user => chalk.bold(userColours.get(user))).join(", ")} | ${chalk.bold(minLength + "")} chars | ${chalk.bold(resolve(hackmudPath, users[0], "scripts", basename(file, extname(file))) + ".js")}`
120
- )
121
- },
122
- log = message => {
123
- console.log(colourS(message))
124
- },
125
- logError = message => {
126
- console.error(colourD(message))
127
- process.exitCode = 1
128
- }
23
+ log = message => console.log(colourS(message))
129
24
  for (const argument of process.argv.slice(2))
130
25
  if ("-" == argument[0]) {
131
26
  const [key, valueRaw] = argument.split("=")
@@ -142,35 +37,10 @@ for (const argument of process.argv.slice(2))
142
37
  else for (const option of key.slice(1)) options.set(option, value)
143
38
  } else commands.push(argument)
144
39
  if ("v" == commands[0] || "version" == commands[0] || options.get("version") || options.get("v")) {
145
- console.log("0.19.1-64ab3ba")
40
+ console.log(version)
146
41
  process.exit()
147
42
  }
148
- let configDidNotExist = !1
149
- const configPromise = readFile(configFilePath, { encoding: "utf-8" }).then(
150
- configFile => {
151
- let temporaryConfig
152
- try {
153
- temporaryConfig = JSON.parse(configFile)
154
- } catch {
155
- log("Config file was corrupted, resetting")
156
- return {}
157
- }
158
- if (!temporaryConfig || "object" != typeof temporaryConfig) {
159
- log("Config file was corrupted, resetting")
160
- return {}
161
- }
162
- if ("hackmudPath" in temporaryConfig && "string" != typeof temporaryConfig.hackmudPath) {
163
- log('Property "hackmudPath" of config file was corrupted, removing')
164
- delete temporaryConfig.hackmudPath
165
- }
166
- return temporaryConfig
167
- },
168
- () => {
169
- configDidNotExist = !0
170
- return {}
171
- }
172
- ),
173
- pushModule = import("../push.js"),
43
+ const pushModule = import("../push.js"),
174
44
  processScriptModule = import("../processScript/index.js"),
175
45
  watchModule = import("../watch.js"),
176
46
  chokidarModule = import("chokidar"),
@@ -195,12 +65,8 @@ let autoExit = !0
195
65
  switch (commands[0]) {
196
66
  case "push":
197
67
  {
198
- const { hackmudPath } = await configPromise
199
- if (!hackmudPath) {
200
- logNeedHackmudPathMessage()
201
- break
202
- }
203
- const sourcePath = commands[1]
68
+ const hackmudPath = getHackmudPath(),
69
+ sourcePath = commands[1]
204
70
  if (!sourcePath) {
205
71
  logError("Must provide the directory to push from\n")
206
72
  logHelp()
@@ -268,12 +134,8 @@ switch (commands[0]) {
268
134
  case "dev":
269
135
  case "watch":
270
136
  {
271
- const { hackmudPath } = await configPromise
272
- if (!hackmudPath) {
273
- logNeedHackmudPathMessage()
274
- break
275
- }
276
- const sourcePath = commands[1]
137
+ const hackmudPath = getHackmudPath(),
138
+ sourcePath = commands[1]
277
139
  if (!sourcePath) {
278
140
  logError("Must provide the directory to watch\n")
279
141
  logHelp()
@@ -346,34 +208,24 @@ switch (commands[0]) {
346
208
  break
347
209
  case "pull":
348
210
  {
349
- const { hackmudPath } = await configPromise
350
- if (!hackmudPath) {
351
- logNeedHackmudPathMessage()
352
- break
353
- }
354
- const script = commands[1]
211
+ const hackmudPath = getHackmudPath(),
212
+ script = commands[1]
355
213
  if (!script) {
356
214
  logError("Must provide the script to pull\n")
357
215
  logHelp()
358
216
  break
359
217
  }
360
218
  const sourcePath = commands[2] || "."
361
- try {
362
- await pull(sourcePath, hackmudPath, script)
363
- } catch (error) {
219
+ await pull(sourcePath, hackmudPath, script).catch(error => {
364
220
  console.error(error)
365
221
  logError(`Something went wrong, did you forget to ${colourC("#down")} the script?`)
366
- }
222
+ })
367
223
  }
368
224
  break
369
225
  case "sync-macros":
370
226
  {
371
- const { hackmudPath } = await configPromise
372
- if (!hackmudPath) {
373
- logNeedHackmudPathMessage()
374
- break
375
- }
376
- const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
227
+ const hackmudPath = getHackmudPath(),
228
+ { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
377
229
  log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
378
230
  }
379
231
  break
@@ -390,100 +242,17 @@ switch (commands[0]) {
390
242
  }
391
243
  const sourcePath = resolve(target),
392
244
  outputPath = commands[2] || "./player.d.ts",
393
- typeDeclaration = await generateTypeDeclaration(sourcePath, (await configPromise).hackmudPath)
245
+ typeDeclaration = await generateTypeDeclaration(sourcePath, getHackmudPath())
394
246
  let typeDeclarationPath = resolve(outputPath)
395
- try {
396
- await writeFile(typeDeclarationPath, typeDeclaration)
397
- } catch (error) {
398
- assert(error instanceof Error)
247
+ await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
248
+ assert(error instanceof Error, "src/bin/hsm.ts:327:35")
399
249
  if ("EISDIR" != error.code) throw error
400
250
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
401
- await writeFile(typeDeclarationPath, typeDeclaration)
402
- }
251
+ return writeFile(typeDeclarationPath, typeDeclaration)
252
+ })
403
253
  log("Wrote type declaration to " + chalk.bold(typeDeclarationPath))
404
254
  }
405
255
  break
406
- case "config":
407
- switch (commands[1]) {
408
- case "get":
409
- {
410
- const key = commands[2]
411
- key ? log(exploreObject(await configPromise, key.split("."))) : console.log(await configPromise)
412
- }
413
- break
414
- case "delete":
415
- {
416
- const key = commands[2]
417
- if (!key) {
418
- logError("Must provide a key to delete\n")
419
- logHelp()
420
- break
421
- }
422
- const keyParts = key.split("."),
423
- pathName = keyParts
424
- .map(name => (/^[a-z_$][\w$]*$/i.test(name) ? name : JSON.stringify(name)))
425
- .join("."),
426
- lastKey = keyParts.pop(),
427
- config = await configPromise
428
- delete exploreObject(config, keyParts)?.[lastKey]
429
- log(`Removed ${colourV(pathName)} from config file`)
430
- }
431
- break
432
- case "set":
433
- {
434
- const key = commands[2],
435
- value = commands[3]
436
- if (!key) {
437
- logError("Must provide a key and value\n")
438
- logHelp()
439
- break
440
- }
441
- const keys = key.split("."),
442
- pathName = keys
443
- .map(name => (/^[a-z_$][\w$]*$/i.test(name) ? name : JSON.stringify(name)))
444
- .join(".")
445
- if (!value) {
446
- logError(`Must provide a value for the key ${pathName}\n`)
447
- logHelp()
448
- break
449
- }
450
- const lastKey = keys.pop(),
451
- config = await configPromise
452
- if (keys.length || "hackmudPath" != lastKey) {
453
- let object = config
454
- for (const key of keys)
455
- if ("object" == typeof object[key]) object = object[key]
456
- else {
457
- object[key] = {}
458
- object = object[key]
459
- }
460
- object[lastKey] = value
461
- } else config.hackmudPath = resolve(value.startsWith("~/") ? homedir() + value.slice(1) : value)
462
- console.log(config)
463
- await (async config => {
464
- const json = JSON.stringify(config, void 0, "\t")
465
- configDidNotExist && log("Creating config file at " + configFilePath)
466
- await writeFile(configFilePath, json).catch(async error => {
467
- switch (error.code) {
468
- case "EISDIR":
469
- await rmdir(configFilePath)
470
- break
471
- case "ENOENT":
472
- await mkdir(configDirectoryPath)
473
- break
474
- default:
475
- throw error
476
- }
477
- await writeFile(configFilePath, json)
478
- })
479
- })(config)
480
- }
481
- break
482
- default:
483
- commands[1] && logError(`Unknown command: ${JSON.stringify(commands[1])}\n`)
484
- logHelp()
485
- }
486
- break
487
256
  case "help":
488
257
  case "h":
489
258
  logHelp()
@@ -511,7 +280,7 @@ switch (commands[0]) {
511
280
  scriptUser =
512
281
  "scripts" == basename(resolve(target, "..")) && "hackmud" == basename(resolve(target, "../../..")) ?
513
282
  basename(resolve(target, "../.."))
514
- : "UNKNOWN",
283
+ : void 0,
515
284
  optionsHasNoMinify = options.has("no-minify")
516
285
  if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
517
286
  logError(
@@ -547,36 +316,31 @@ switch (commands[0]) {
547
316
  : fileBaseName + ".js"
548
317
  )
549
318
  const golfFile = () =>
550
- readFile(target, { encoding: "utf-8" }).then(
551
- async source => {
552
- const timeStart = performance.now(),
553
- { script, warnings } = await processScript(source, {
554
- minify: !(options.get("no-minify") || options.get("skip-minify")),
555
- scriptUser,
556
- scriptName,
557
- filePath: target,
558
- mangleNames,
559
- forceQuineCheats
560
- }),
561
- timeTook = performance.now() - timeStart
562
- for (const { message, line } of warnings)
563
- log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
564
- await writeFilePersistent(outputPath, script)
565
- .catch(async error => {
566
- if (!commands[2] || "EISDIR" != error.code) throw error
567
- outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
568
- await writeFilePersistent(outputPath, script)
569
- })
570
- .then(
571
- () =>
572
- log(
573
- `Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
574
- ),
575
- error => logError(error.message)
319
+ readFile(target, { encoding: "utf8" }).then(async source => {
320
+ const timeStart = performance.now(),
321
+ { script, warnings } = await processScript(source, {
322
+ minify: !(options.get("no-minify") || options.get("skip-minify")),
323
+ scriptUser,
324
+ scriptName,
325
+ filePath: target,
326
+ mangleNames,
327
+ forceQuineCheats
328
+ }),
329
+ timeTook = performance.now() - timeStart
330
+ for (const { message, line } of warnings)
331
+ log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
332
+ await writeFilePersistent(outputPath, script)
333
+ .catch(error => {
334
+ if (!commands[2] || "EISDIR" != error.code) throw error
335
+ outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
336
+ return writeFilePersistent(outputPath, script)
337
+ })
338
+ .then(() =>
339
+ log(
340
+ `Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
576
341
  )
577
- },
578
- error => logError(error.message)
579
- )
342
+ )
343
+ })
580
344
  if (options.get("watch")) {
581
345
  const { watch: watchFile } = await chokidarModule
582
346
  watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
@@ -587,7 +351,87 @@ switch (commands[0]) {
587
351
  }
588
352
  break
589
353
  default:
590
- commands[0] && logError(`Unknown command: ${JSON.stringify(commands[0])}\n`)
354
+ commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
591
355
  logHelp()
592
356
  }
593
357
  autoExit && process.exit()
358
+ function logHelp() {
359
+ const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
360
+ forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`,
361
+ hackmudPathOption = `${colourN("--hackmud-path")}=${colourB("<path>")}\n Override hackmud path`
362
+ console.log(colourN("Version") + colourS(": ") + colourV(version))
363
+ switch (commands[0]) {
364
+ case "dev":
365
+ case "watch":
366
+ case "push":
367
+ console.log(
368
+ colourS(
369
+ `\n${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\tPushes 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\tPushes 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\tPushes 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\tPushes all scripts found in ${colourV("src")} folder to all users`
370
+ )
371
+ )
372
+ break
373
+ case "pull":
374
+ console.log(
375
+ colourS(
376
+ `\n${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}`
377
+ )
378
+ )
379
+ break
380
+ case "minify":
381
+ case "golf":
382
+ console.log(
383
+ colourS(
384
+ `\n${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`
385
+ )
386
+ )
387
+ break
388
+ case "generate-type-declaration":
389
+ case "gen-type-declaration":
390
+ case "gen-dts":
391
+ case "gen-types":
392
+ console.log(
393
+ colourS(
394
+ `${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}`
395
+ )
396
+ )
397
+ break
398
+ case "sync-macros":
399
+ console.log(
400
+ colourS(
401
+ `\n${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
402
+ )
403
+ )
404
+ break
405
+ default:
406
+ console.log(
407
+ colourS(
408
+ `\n${colourJ("Hackmud Script Manager")}\n\n${colourA("Commands:")}\n${colourL("push")}\n ${pushCommandDescription}\n${colourL("dev")}\n Watch a directory and push a script when modified\n${colourL("golf")}\n Minify a script file on the spot\n${colourL("gen-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`
409
+ )
410
+ )
411
+ }
412
+ }
413
+ function logInfo({ path, users, characterCount, error }, hackmudPath) {
414
+ path = relative(".", path)
415
+ error ?
416
+ logError(`Error "${chalk.bold(error.message)}" in ${chalk.bold(path)}`)
417
+ : log(
418
+ `Pushed ${chalk.bold(path)} to ${users.map(user => chalk.bold(userColours.get(user))).join(", ")} | ${chalk.bold(characterCount + "")} chars | ${chalk.bold(resolve(hackmudPath, users[0], "scripts", basename(path, extname(path))) + ".js")}`
419
+ )
420
+ }
421
+ function logError(message) {
422
+ console.error(colourD(message))
423
+ process.exitCode = 1
424
+ }
425
+ function getHackmudPath() {
426
+ const hackmudPathOption = options.get("hackmud-path")
427
+ if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
428
+ logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
429
+ logHelp()
430
+ process.exit(1)
431
+ }
432
+ return (
433
+ hackmudPathOption ||
434
+ process.env.HSM_HACKMUD_PATH ||
435
+ ("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
436
+ )
437
+ }