hackmud-script-manager 0.19.1-bd545f5 → 0.19.1-cb8d65f

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/bin/hsm.js CHANGED
@@ -1,7 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { Cache } from "@samual/lib/Cache"
3
3
  import { assert } from "@samual/lib/assert"
4
+ import { catchError } from "@samual/lib/catchError"
4
5
  import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
6
+ import { getDeepObjectProperty } from "@samual/lib/getDeepObjectProperty"
7
+ import { isRecord } from "@samual/lib/isRecord"
8
+ import { setDeepObjectProperty } from "@samual/lib/setDeepObjectProperty"
5
9
  import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
6
10
  import { readFile, writeFile, mkdir, rmdir } from "fs/promises"
7
11
  import { homedir } from "os"
@@ -21,119 +25,7 @@ const configDirectoryPath = resolve(homedir(), ".config"),
21
25
  for (const char of user) hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
22
26
  return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user)
23
27
  }),
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
- mangleNamesOptionDescription =
33
- "Reduce character count further but lose function names in error call stacks",
34
- forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off.`
35
- console.log(colourN("Version") + colourS(": ") + colourV("0.19.1-bd545f5"))
36
- switch (commands[0]) {
37
- case "config":
38
- switch (commands[1]) {
39
- case "get":
40
- console.log(
41
- `\n${colourJ("Retrieve a value from the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key>")}`
42
- )
43
- break
44
- case "set":
45
- console.log(
46
- `\n${colourJ("Assign a value to the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key> <value>")}`
47
- )
48
- break
49
- case "delete":
50
- console.log(
51
- `\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>")}`
52
- )
53
- break
54
- default:
55
- console.log(
56
- colourS(
57
- `${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`
58
- )
59
- )
60
- }
61
- break
62
- case "push":
63
- console.log(
64
- colourS(
65
- `\n${colourJ(pushCommandDescription)}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<directory> [<script user>.<script name>...]")}\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n ${mangleNamesOptionDescription}\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}`
66
- )
67
- )
68
- break
69
- case "dev":
70
- case "watch":
71
- console.log(
72
- colourS(
73
- `\n${colourJ("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("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n ${mangleNamesOptionDescription}\n${colourN("--type-declaration-path")}=${colourB("<path>")}\n Path to generate a type declaration file for the scripts\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}`
74
- )
75
- )
76
- break
77
- case "pull":
78
- console.log(
79
- colourS(
80
- `\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>")}`
81
- )
82
- )
83
- break
84
- case "minify":
85
- case "golf":
86
- console.log(
87
- colourS(
88
- `\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 ${mangleNamesOptionDescription}\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}\n${colourN("--watch")}\n Watch for changes`
89
- )
90
- )
91
- break
92
- case "generate-type-declaration":
93
- case "gen-type-declaration":
94
- case "gen-dts":
95
- case "gen-types":
96
- console.log(
97
- colourS(
98
- `${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]")}`
99
- )
100
- )
101
- break
102
- case "sync-macros":
103
- console.log("\n" + colourJ("Sync macros across all hackmud users"))
104
- break
105
- default:
106
- console.log(
107
- colourS(
108
- `\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`
109
- )
110
- )
111
- }
112
- },
113
- exploreObject = (object, keys, createPath = !1) => {
114
- for (const key of keys)
115
- object =
116
- createPath ?
117
- "object" == typeof object[key] ?
118
- object[key]
119
- : (object[key] = {})
120
- : object?.[key]
121
- return object
122
- },
123
- logInfo = ({ file, users, minLength, error }, hackmudPath) => {
124
- error ?
125
- logError(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`)
126
- : console.log(
127
- `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")}`
128
- )
129
- },
130
- log = message => {
131
- console.log(colourS(message))
132
- },
133
- logError = message => {
134
- console.error(colourD(message))
135
- process.exitCode = 1
136
- }
28
+ log = message => console.log(colourS(message))
137
29
  for (const argument of process.argv.slice(2))
138
30
  if ("-" == argument[0]) {
139
31
  const [key, valueRaw] = argument.split("=")
@@ -150,20 +42,14 @@ for (const argument of process.argv.slice(2))
150
42
  else for (const option of key.slice(1)) options.set(option, value)
151
43
  } else commands.push(argument)
152
44
  if ("v" == commands[0] || "version" == commands[0] || options.get("version") || options.get("v")) {
153
- console.log("0.19.1-bd545f5")
45
+ console.log("0.19.1-cb8d65f")
154
46
  process.exit()
155
47
  }
156
48
  let configDidNotExist = !1
157
49
  const configPromise = readFile(configFilePath, { encoding: "utf-8" }).then(
158
50
  configFile => {
159
- let temporaryConfig
160
- try {
161
- temporaryConfig = JSON.parse(configFile)
162
- } catch {
163
- log("Config file was corrupted, resetting")
164
- return {}
165
- }
166
- if (!temporaryConfig || "object" != typeof temporaryConfig) {
51
+ const [temporaryConfig, error] = catchError(() => JSON.parse(configFile))
52
+ if (error || !isRecord(temporaryConfig)) {
167
53
  log("Config file was corrupted, resetting")
168
54
  return {}
169
55
  }
@@ -200,15 +86,13 @@ if (options.get("help") || options.get("h")) {
200
86
  process.exit()
201
87
  }
202
88
  let autoExit = !0
89
+ const getDefaultHackmudPath = () =>
90
+ "win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud")
203
91
  switch (commands[0]) {
204
92
  case "push":
205
93
  {
206
- const { hackmudPath } = await configPromise
207
- if (!hackmudPath) {
208
- logNeedHackmudPathMessage()
209
- break
210
- }
211
- const sourcePath = commands[1]
94
+ const { hackmudPath = getDefaultHackmudPath() } = await configPromise,
95
+ sourcePath = commands[1]
212
96
  if (!sourcePath) {
213
97
  logError("Must provide the directory to push from\n")
214
98
  logHelp()
@@ -276,12 +160,8 @@ switch (commands[0]) {
276
160
  case "dev":
277
161
  case "watch":
278
162
  {
279
- const { hackmudPath } = await configPromise
280
- if (!hackmudPath) {
281
- logNeedHackmudPathMessage()
282
- break
283
- }
284
- const sourcePath = commands[1]
163
+ const { hackmudPath = getDefaultHackmudPath() } = await configPromise,
164
+ sourcePath = commands[1]
285
165
  if (!sourcePath) {
286
166
  logError("Must provide the directory to watch\n")
287
167
  logHelp()
@@ -354,34 +234,24 @@ switch (commands[0]) {
354
234
  break
355
235
  case "pull":
356
236
  {
357
- const { hackmudPath } = await configPromise
358
- if (!hackmudPath) {
359
- logNeedHackmudPathMessage()
360
- break
361
- }
362
- const script = commands[1]
237
+ const { hackmudPath = getDefaultHackmudPath() } = await configPromise,
238
+ script = commands[1]
363
239
  if (!script) {
364
240
  logError("Must provide the script to pull\n")
365
241
  logHelp()
366
242
  break
367
243
  }
368
244
  const sourcePath = commands[2] || "."
369
- try {
370
- await pull(sourcePath, hackmudPath, script)
371
- } catch (error) {
245
+ await pull(sourcePath, hackmudPath, script).catch(error => {
372
246
  console.error(error)
373
247
  logError(`Something went wrong, did you forget to ${colourC("#down")} the script?`)
374
- }
248
+ })
375
249
  }
376
250
  break
377
251
  case "sync-macros":
378
252
  {
379
- const { hackmudPath } = await configPromise
380
- if (!hackmudPath) {
381
- logNeedHackmudPathMessage()
382
- break
383
- }
384
- const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
253
+ const { hackmudPath = getDefaultHackmudPath() } = await configPromise,
254
+ { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
385
255
  log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
386
256
  }
387
257
  break
@@ -398,16 +268,17 @@ switch (commands[0]) {
398
268
  }
399
269
  const sourcePath = resolve(target),
400
270
  outputPath = commands[2] || "./player.d.ts",
401
- typeDeclaration = await generateTypeDeclaration(sourcePath, (await configPromise).hackmudPath)
271
+ typeDeclaration = await generateTypeDeclaration(
272
+ sourcePath,
273
+ (await configPromise).hackmudPath || getDefaultHackmudPath()
274
+ )
402
275
  let typeDeclarationPath = resolve(outputPath)
403
- try {
404
- await writeFile(typeDeclarationPath, typeDeclaration)
405
- } catch (error) {
406
- assert(error instanceof Error)
276
+ await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
277
+ assert(error instanceof Error, "src/bin/hsm.ts:365:35")
407
278
  if ("EISDIR" != error.code) throw error
408
279
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
409
- await writeFile(typeDeclarationPath, typeDeclaration)
410
- }
280
+ return writeFile(typeDeclarationPath, typeDeclaration)
281
+ })
411
282
  log("Wrote type declaration to " + chalk.bold(typeDeclarationPath))
412
283
  }
413
284
  break
@@ -415,8 +286,14 @@ switch (commands[0]) {
415
286
  switch (commands[1]) {
416
287
  case "get":
417
288
  {
418
- const key = commands[2]
419
- key ? log(exploreObject(await configPromise, key.split("."))) : console.log(await configPromise)
289
+ const key = commands[2],
290
+ config = await configPromise
291
+ if (key) {
292
+ const [value, error] = catchError(() => getDeepObjectProperty(config, key.split(".")))
293
+ error ? logError("Could not get key " + colourV(key))
294
+ : "string" == typeof value ? log(value)
295
+ : console.log(value)
296
+ } else console.log(config)
420
297
  }
421
298
  break
422
299
  case "delete":
@@ -427,14 +304,16 @@ switch (commands[0]) {
427
304
  logHelp()
428
305
  break
429
306
  }
430
- const keyParts = key.split("."),
431
- pathName = keyParts
432
- .map(name => (/^[a-z_$][\w$]*$/i.test(name) ? name : JSON.stringify(name)))
433
- .join("."),
434
- lastKey = keyParts.pop(),
435
- config = await configPromise
436
- delete exploreObject(config, keyParts)?.[lastKey]
437
- log(`Removed ${colourV(pathName)} from config file`)
307
+ const keys = key.split("."),
308
+ lastKey = keys.pop(),
309
+ config = await configPromise,
310
+ object = getDeepObjectProperty(config, keys)
311
+ if (isRecord(object)) {
312
+ delete object[lastKey]
313
+ await updateConfig(config)
314
+ log(`Removed ${colourV(key)} from config file:`)
315
+ console.log(config)
316
+ } else log("Could not delete " + colourV(key))
438
317
  }
439
318
  break
440
319
  case "set":
@@ -446,49 +325,20 @@ switch (commands[0]) {
446
325
  logHelp()
447
326
  break
448
327
  }
449
- const keys = key.split("."),
450
- pathName = keys
451
- .map(name => (/^[a-z_$][\w$]*$/i.test(name) ? name : JSON.stringify(name)))
452
- .join(".")
453
328
  if (!value) {
454
- logError(`Must provide a value for the key ${pathName}\n`)
329
+ logError(`Must provide a value for the key ${colourV(key)}\n`)
455
330
  logHelp()
456
331
  break
457
332
  }
458
- const lastKey = keys.pop(),
459
- config = await configPromise
460
- if (keys.length || "hackmudPath" != lastKey) {
461
- let object = config
462
- for (const key of keys)
463
- if ("object" == typeof object[key]) object = object[key]
464
- else {
465
- object[key] = {}
466
- object = object[key]
467
- }
468
- object[lastKey] = value
469
- } else config.hackmudPath = resolve(value.startsWith("~/") ? homedir() + value.slice(1) : value)
333
+ const config = await configPromise
334
+ setDeepObjectProperty(config, key.split("."), value)
335
+ log(`Set ${colourV(key)} to ${colourV(value)}:`)
470
336
  console.log(config)
471
- await (async config => {
472
- const json = JSON.stringify(config, void 0, "\t")
473
- configDidNotExist && log("Creating config file at " + configFilePath)
474
- await writeFile(configFilePath, json).catch(async error => {
475
- switch (error.code) {
476
- case "EISDIR":
477
- await rmdir(configFilePath)
478
- break
479
- case "ENOENT":
480
- await mkdir(configDirectoryPath)
481
- break
482
- default:
483
- throw error
484
- }
485
- await writeFile(configFilePath, json)
486
- })
487
- })(config)
337
+ await updateConfig(config)
488
338
  }
489
339
  break
490
340
  default:
491
- commands[1] && logError(`Unknown command: ${JSON.stringify(commands[1])}\n`)
341
+ commands[1] && logError(`Unknown command: ${colourL(commands[1])}\n`)
492
342
  logHelp()
493
343
  }
494
344
  break
@@ -555,36 +405,31 @@ switch (commands[0]) {
555
405
  : fileBaseName + ".js"
556
406
  )
557
407
  const golfFile = () =>
558
- readFile(target, { encoding: "utf-8" }).then(
559
- async source => {
560
- const timeStart = performance.now(),
561
- { script, warnings } = await processScript(source, {
562
- minify: !(options.get("no-minify") || options.get("skip-minify")),
563
- scriptUser,
564
- scriptName,
565
- filePath: target,
566
- mangleNames,
567
- forceQuineCheats
568
- }),
569
- timeTook = performance.now() - timeStart
570
- for (const { message, line } of warnings)
571
- log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
572
- await writeFilePersistent(outputPath, script)
573
- .catch(async error => {
574
- if (!commands[2] || "EISDIR" != error.code) throw error
575
- outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
576
- await writeFilePersistent(outputPath, script)
577
- })
578
- .then(
579
- () =>
580
- log(
581
- `Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
582
- ),
583
- error => logError(error.message)
408
+ readFile(target, { encoding: "utf-8" }).then(async source => {
409
+ const timeStart = performance.now(),
410
+ { script, warnings } = await processScript(source, {
411
+ minify: !(options.get("no-minify") || options.get("skip-minify")),
412
+ scriptUser,
413
+ scriptName,
414
+ filePath: target,
415
+ mangleNames,
416
+ forceQuineCheats
417
+ }),
418
+ timeTook = performance.now() - timeStart
419
+ for (const { message, line } of warnings)
420
+ log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
421
+ await writeFilePersistent(outputPath, script)
422
+ .catch(error => {
423
+ if (!commands[2] || "EISDIR" != error.code) throw error
424
+ outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
425
+ return writeFilePersistent(outputPath, script)
426
+ })
427
+ .then(() =>
428
+ log(
429
+ `Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
584
430
  )
585
- },
586
- error => logError(error.message)
587
- )
431
+ )
432
+ })
588
433
  if (options.get("watch")) {
589
434
  const { watch: watchFile } = await chokidarModule
590
435
  watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
@@ -595,7 +440,110 @@ switch (commands[0]) {
595
440
  }
596
441
  break
597
442
  default:
598
- commands[0] && logError(`Unknown command: ${JSON.stringify(commands[0])}\n`)
443
+ commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
599
444
  logHelp()
600
445
  }
601
446
  autoExit && process.exit()
447
+ function logHelp() {
448
+ const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
449
+ forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`
450
+ console.log(colourN("Version") + colourS(": ") + colourV("0.19.1-cb8d65f"))
451
+ switch (commands[0]) {
452
+ case "config":
453
+ switch (commands[1]) {
454
+ case "get":
455
+ console.log(
456
+ `\n${colourJ("Retrieve a value from the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key>")}`
457
+ )
458
+ break
459
+ case "set":
460
+ console.log(
461
+ `\n${colourJ("Assign a value to the config file")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB("<key> <value>")}`
462
+ )
463
+ break
464
+ case "delete":
465
+ console.log(
466
+ `\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>")}`
467
+ )
468
+ break
469
+ default:
470
+ console.log(
471
+ colourS(
472
+ `${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`
473
+ )
474
+ )
475
+ }
476
+ break
477
+ case "dev":
478
+ case "watch":
479
+ case "push":
480
+ console.log(
481
+ colourS(
482
+ `\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`
483
+ )
484
+ )
485
+ break
486
+ case "pull":
487
+ console.log(
488
+ colourS(
489
+ `\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>")}`
490
+ )
491
+ )
492
+ break
493
+ case "minify":
494
+ case "golf":
495
+ console.log(
496
+ colourS(
497
+ `\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`
498
+ )
499
+ )
500
+ break
501
+ case "generate-type-declaration":
502
+ case "gen-type-declaration":
503
+ case "gen-dts":
504
+ case "gen-types":
505
+ console.log(
506
+ colourS(
507
+ `${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]")}`
508
+ )
509
+ )
510
+ break
511
+ case "sync-macros":
512
+ console.log("\n" + colourJ("Sync macros across all hackmud users"))
513
+ break
514
+ default:
515
+ console.log(
516
+ colourS(
517
+ `\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`
518
+ )
519
+ )
520
+ }
521
+ }
522
+ async function updateConfig(config) {
523
+ const json = JSON.stringify(config, void 0, "\t")
524
+ configDidNotExist && log("Creating config file at " + configFilePath)
525
+ await writeFile(configFilePath, json).catch(async error => {
526
+ switch (error.code) {
527
+ case "EISDIR":
528
+ await rmdir(configFilePath)
529
+ break
530
+ case "ENOENT":
531
+ await mkdir(configDirectoryPath)
532
+ break
533
+ default:
534
+ throw error
535
+ }
536
+ await writeFile(configFilePath, json)
537
+ })
538
+ }
539
+ function logInfo({ file, users, minLength, error }, hackmudPath) {
540
+ error ?
541
+ logError(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`)
542
+ : console.log(
543
+ `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")}`
544
+ )
545
+ }
546
+ function logError(message) {
547
+ console.error(colourD(message))
548
+ process.exitCode = 1
549
+ }
@@ -1,6 +1,6 @@
1
1
  import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
2
2
  import { basename, resolve } from "path"
3
- const generateTypeDeclaration = async (sourceDirectory, hackmudPath) => {
3
+ async function generateTypeDeclaration(sourceDirectory, hackmudPath) {
4
4
  const users = new Set()
5
5
  if (hackmudPath)
6
6
  for (const { stats, name } of await readDirectoryWithStats(hackmudPath))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.19.1-bd545f5",
3
+ "version": "0.19.1-cb8d65f",
4
4
  "description": "Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.",
5
5
  "keywords": [
6
6
  "api",
@@ -59,7 +59,7 @@
59
59
  "@rollup/plugin-commonjs": "^25.0.7",
60
60
  "@rollup/plugin-json": "^6.1.0",
61
61
  "@rollup/plugin-node-resolve": "^15.2.3",
62
- "@samual/lib": "0.10.2-5919775",
62
+ "@samual/lib": "0.10.2-e64c5bc",
63
63
  "acorn": "^8.11.3",
64
64
  "chalk": "^5.3.0",
65
65
  "chokidar": "^3.6.0",
@@ -69,17 +69,12 @@
69
69
  "rollup": "^4.14.2",
70
70
  "terser": "^5.30.3"
71
71
  },
72
- "engines": {
73
- "node": "^18 || >=20",
74
- "pnpm": "^9.0.1"
75
- },
76
72
  "type": "module",
77
73
  "exports": {
78
74
  "./*": "./*.js",
79
75
  "./*.js": "./*.js"
80
76
  },
81
- "bin": {
82
- "hsm.d": "bin/hsm.d.ts",
83
- "hsm": "bin/hsm.js"
77
+ "engines": {
78
+ "node": "^18 || >=20"
84
79
  }
85
80
  }