hackmud-script-manager 0.20.4-550e28d → 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 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
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/69a371fe-f8c8-43fe-b3c7-39f3735ce6fb)
24
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/08103f9e-74fa-4a56-a739-94858ba8c139)
25
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/25ccb86d-1fe3-4632-b703-ac47f5b32c9c)
26
+
23
27
  ## Features
24
28
  - Minification
25
29
  - This includes auto quine cheating.
package/bin/hsm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Cache } from "@samual/lib/Cache"
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"
@@ -13,10 +13,10 @@ import { syncMacros } from "../syncMacros.js"
13
13
  import "@samual/lib/readDirectoryWithStats"
14
14
  import "path/posix"
15
15
  import "@samual/lib/copyFilePersistent"
16
- const version = "0.20.4-550e28d",
16
+ const formatOption = name => colourN(`-${1 == name.length ? "" : "-"}${name}`),
17
17
  options = new Map(),
18
18
  commands = [],
19
- userColours = new Cache(user => {
19
+ userColours = new AutoMap(user => {
20
20
  let hash = 0
21
21
  for (const char of user) hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
22
22
  return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user)
@@ -58,11 +58,11 @@ const pushModule = import("../push.js"),
58
58
  process.version.startsWith("v21.") &&
59
59
  console.warn(
60
60
  colourF(
61
- "Warning: Support for Node.js 21 will be dropped in the next minor version of HSM\n You should update your version of Node.js\n https://nodejs.org/en/download/package-manager"
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
62
  )
63
63
  )
64
64
  if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
65
- console.log(version)
65
+ console.log("0.20.4-6815ce0")
66
66
  process.exit()
67
67
  }
68
68
  if (popOption("help", "h")?.value) {
@@ -83,7 +83,7 @@ switch (commands[0]) {
83
83
  noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
84
84
  if (noMinifyOption && noMinifyIncompatibleOption) {
85
85
  logError(
86
- `Options ${colourN(noMinifyOption.name)} and ${colourN(noMinifyIncompatibleOption.name)} are incompatible\n`
86
+ `Options ${formatOption(noMinifyOption.name)} and ${formatOption(noMinifyIncompatibleOption.name)} are incompatible\n`
87
87
  )
88
88
  logHelp()
89
89
  process.exit(1)
@@ -106,6 +106,7 @@ switch (commands[0]) {
106
106
  )
107
107
  process.exit(1)
108
108
  }
109
+ complainAboutUnrecognisedOptions()
109
110
  const { processScript } = await processScriptModule,
110
111
  fileBaseName = basename(target, fileExtension),
111
112
  fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
@@ -178,15 +179,15 @@ switch (commands[0]) {
178
179
  }
179
180
  } else scripts.push("*.*")
180
181
  if ("push" == commands[0]) {
181
- const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } =
182
- await pushModule,
183
- infos = await push(sourcePath, hackmudPath, {
184
- scripts,
185
- onPush: info => logInfo(info, hackmudPath),
186
- minify: noMinifyOption && !noMinifyOption.value,
187
- mangleNames: mangleNamesOption?.value,
188
- forceQuineCheats: forceQuineCheatsOption?.value
189
- })
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
+ })
190
191
  if (infos instanceof Error) {
191
192
  logError(infos.message)
192
193
  if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
@@ -200,12 +201,13 @@ switch (commands[0]) {
200
201
  } else infos.length || logError("Could not find any scripts to push")
201
202
  } else {
202
203
  const typeDeclarationPathOption = popOption(
203
- "type-declaration-path",
204
- "type-declaration",
205
- "dts",
206
- "gen-types"
207
- ),
208
- { watch } = await watchModule
204
+ "type-declaration-path",
205
+ "type-declaration",
206
+ "dts",
207
+ "gen-types"
208
+ )
209
+ complainAboutUnrecognisedOptions()
210
+ const { watch } = await watchModule
209
211
  watch(sourcePath, hackmudPath, {
210
212
  scripts,
211
213
  onPush: info => logInfo(info, hackmudPath),
@@ -229,6 +231,7 @@ switch (commands[0]) {
229
231
  logHelp()
230
232
  process.exit(1)
231
233
  }
234
+ complainAboutUnrecognisedOptions()
232
235
  const sourcePath = commands[2] || "."
233
236
  await pull(sourcePath, hackmudPath, script).catch(error => {
234
237
  console.error(error)
@@ -238,8 +241,9 @@ switch (commands[0]) {
238
241
  break
239
242
  case "sync-macros":
240
243
  {
241
- const hackmudPath = getHackmudPath(),
242
- { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
244
+ const hackmudPath = getHackmudPath()
245
+ complainAboutUnrecognisedOptions()
246
+ const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
243
247
  log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
244
248
  }
245
249
  break
@@ -247,7 +251,15 @@ switch (commands[0]) {
247
251
  case "gen-type-declaration":
248
252
  case "gen-dts":
249
253
  case "gen-types":
254
+ case "emit-dts":
250
255
  {
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
+ )
251
263
  const hackmudPath = getHackmudPath(),
252
264
  target = commands[1]
253
265
  if (!target) {
@@ -255,12 +267,13 @@ switch (commands[0]) {
255
267
  logHelp()
256
268
  process.exit(1)
257
269
  }
270
+ complainAboutUnrecognisedOptions()
258
271
  const sourcePath = resolve(target),
259
272
  outputPath = commands[2] || "./player.d.ts",
260
273
  typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
261
274
  let typeDeclarationPath = resolve(outputPath)
262
275
  await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
263
- assert(error instanceof Error, "src/bin/hsm.ts:330:35")
276
+ assert(error instanceof Error, "src/bin/hsm.ts:353:35")
264
277
  if ("EISDIR" != error.code) throw error
265
278
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
266
279
  return writeFile(typeDeclarationPath, typeDeclaration)
@@ -281,21 +294,20 @@ function logHelp() {
281
294
  const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
282
295
  forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`,
283
296
  hackmudPathOption = `${colourN("--hackmud-path")}=${colourB("<path>")}\n Override hackmud path`
284
- console.log(colourN("Version") + colourS(": ") + colourV(version))
285
297
  switch (commands[0]) {
286
298
  case "dev":
287
299
  case "watch":
288
300
  case "push":
289
301
  console.log(
290
302
  colourS(
291
- `\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 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`
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`
292
304
  )
293
305
  )
294
306
  break
295
307
  case "pull":
296
308
  console.log(
297
309
  colourS(
298
- `\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}`
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}`
299
311
  )
300
312
  )
301
313
  break
@@ -303,7 +315,7 @@ function logHelp() {
303
315
  case "golf":
304
316
  console.log(
305
317
  colourS(
306
- `\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`
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`
307
319
  )
308
320
  )
309
321
  break
@@ -311,6 +323,14 @@ function logHelp() {
311
323
  case "gen-type-declaration":
312
324
  case "gen-dts":
313
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
+ )
314
334
  console.log(
315
335
  colourS(
316
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}`
@@ -320,14 +340,14 @@ function logHelp() {
320
340
  case "sync-macros":
321
341
  console.log(
322
342
  colourS(
323
- `\n${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
343
+ `${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
324
344
  )
325
345
  )
326
346
  break
327
347
  default:
328
348
  console.log(
329
349
  colourS(
330
- `\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`
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`
331
351
  )
332
352
  )
333
353
  }
@@ -345,7 +365,7 @@ function logError(message) {
345
365
  process.exitCode = 1
346
366
  }
347
367
  function getHackmudPath() {
348
- const hackmudPathOption = popOption("hackmud-path")
368
+ const hackmudPathOption = popOption("hackmud-path")?.value
349
369
  if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
350
370
  logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
351
371
  logHelp()
@@ -359,7 +379,7 @@ function getHackmudPath() {
359
379
  }
360
380
  function assertOptionIsBoolean(option) {
361
381
  if ("boolean" != typeof option.value) {
362
- logError(`The value for ${colourN(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
382
+ logError(`The value for ${formatOption(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
363
383
  logHelp()
364
384
  process.exit(1)
365
385
  }
@@ -367,9 +387,7 @@ function assertOptionIsBoolean(option) {
367
387
  function popOption(...names) {
368
388
  const presentOptionNames = names.filter(name => options.has(name))
369
389
  if (!presentOptionNames.length) return
370
- const presentOptionNamesWithDashDash = presentOptionNames.map(name =>
371
- colourN(`-${1 == name.length ? "" : "-"}${name}`)
372
- )
390
+ const presentOptionNamesWithDashDash = presentOptionNames.map(formatOption)
373
391
  if (presentOptionNames.length > 1) {
374
392
  logError(
375
393
  `The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
@@ -380,3 +398,11 @@ function popOption(...names) {
380
398
  options.delete(presentOptionNames[0])
381
399
  return { name: presentOptionNamesWithDashDash[0], value }
382
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
+ }