hackmud-script-manager 0.20.4-b0ca7f9 → 0.20.4-b779329

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.
Files changed (2) hide show
  1. package/bin/hsm.js +170 -242
  2. package/package.json +1 -1
package/bin/hsm.js CHANGED
@@ -5,14 +5,14 @@ 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, resolve, dirname, relative } from "path"
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
14
  import "@samual/lib/copyFilePersistent"
15
- const version = "0.20.4-b0ca7f9",
15
+ const version = "0.20.4-b779329",
16
16
  options = new Map(),
17
17
  commands = [],
18
18
  userColours = new Cache(user => {
@@ -36,10 +36,6 @@ for (const argument of process.argv.slice(2))
36
36
  if ("-" == argument[1]) options.set(key.slice(2), value)
37
37
  else for (const option of key.slice(1)) options.set(option, value)
38
38
  } 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
39
  const pushModule = import("../push.js"),
44
40
  processScriptModule = import("../processScript/index.js"),
45
41
  watchModule = import("../watch.js"),
@@ -57,162 +53,163 @@ const pushModule = import("../push.js"),
57
53
  colourS = chalk.rgb(122, 178, 244),
58
54
  colourV = chalk.rgb(255, 0, 236),
59
55
  colourW = chalk.rgb(255, 150, 224)
60
- if (options.get("help") || options.get("h")) {
56
+ if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
57
+ console.log(version)
58
+ process.exit()
59
+ }
60
+ if (popOption("help", "h")?.value) {
61
61
  logHelp()
62
62
  process.exit()
63
63
  }
64
64
  let autoExit = !0
65
65
  switch (commands[0]) {
66
66
  case "push":
67
+ case "dev":
68
+ case "watch":
69
+ case "golf":
70
+ case "minify":
67
71
  {
68
- const hackmudPath = getHackmudPath(),
69
- sourcePath = commands[1]
70
- if (!sourcePath) {
71
- logError("Must provide the directory to push from\n")
72
- logHelp()
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")) {
72
+ const noMinifyOption = popOption("no-minify", "skip-minify"),
73
+ mangleNamesOption = popOption("mangle-names"),
74
+ forceQuineCheatsOption = popOption("force-quine-cheats"),
75
+ noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
76
+ if (noMinifyOption && noMinifyIncompatibleOption) {
88
77
  logError(
89
- `Options ${colourN("--mangle-names")} and ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} are incompatible\n`
78
+ `Options ${colourN(noMinifyOption.name)} and ${colourN(noMinifyIncompatibleOption.name)} are incompatible\n`
90
79
  )
91
80
  logHelp()
92
- break
81
+ process.exit(1)
93
82
  }
94
- const shouldSkipMinify = options.get("no-minify") || options.get("skip-minify")
95
- let shouldMinify
96
- if (null != shouldSkipMinify) {
97
- if ("boolean" != typeof shouldSkipMinify) {
83
+ noMinifyOption && assertOptionIsBoolean(noMinifyOption)
84
+ mangleNamesOption && assertOptionIsBoolean(mangleNamesOption)
85
+ forceQuineCheatsOption && assertOptionIsBoolean(forceQuineCheatsOption)
86
+ if ("golf" == commands[0] || "minify" == commands[0]) {
87
+ const watchOption = popOption("watch"),
88
+ target = commands[1]
89
+ if (!target) {
90
+ logError("Must provide target\n")
91
+ logHelp()
92
+ process.exit(1)
93
+ }
94
+ const fileExtension = extname(target)
95
+ if (!supportedExtensions.includes(fileExtension)) {
98
96
  logError(
99
- `The value for ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} must be ${colourV("true")} or ${colourV("false")}\n`
97
+ `Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`
100
98
  )
101
- logHelp()
102
- break
99
+ process.exit(1)
103
100
  }
104
- shouldMinify = !shouldSkipMinify
105
- }
106
- const shouldMangleNames = options.get("mangle-names")
107
- if (null != shouldMangleNames && "boolean" != typeof shouldMangleNames) {
108
- logError(
109
- `The value for ${colourN("--mangle-names")} must be ${colourV("true")} or ${colourV("false")}\n`
110
- )
111
- logHelp()
112
- break
113
- }
114
- const shouldforceQuineCheats = options.get("force-quine-cheats")
115
- if (null != shouldforceQuineCheats && "boolean" != typeof shouldforceQuineCheats) {
116
- logError(
117
- `The value for ${colourN("--force-quine-cheats")} must be ${colourV("true")} or ${colourV("false")}\n`
118
- )
119
- logHelp()
120
- break
121
- }
122
- const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } = await pushModule,
123
- infos = await push(sourcePath, hackmudPath, {
124
- scripts,
125
- onPush: info => logInfo(info, hackmudPath),
126
- minify: shouldMinify,
127
- mangleNames: shouldMangleNames,
128
- forceQuineCheats: shouldforceQuineCheats
129
- })
130
- if (infos instanceof Error) {
131
- logError(infos.message)
132
- if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
133
- console.log()
134
- logHelp()
135
- } else
136
- infos instanceof MissingHackmudFolderError &&
137
- log(
138
- `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`
139
- )
140
- } else infos.length || logError("Could not find any scripts to push")
141
- }
142
- break
143
- case "dev":
144
- case "watch":
145
- {
146
- const hackmudPath = getHackmudPath(),
147
- sourcePath = commands[1]
148
- if (!sourcePath) {
149
- logError("Must provide the directory to watch\n")
150
- logHelp()
151
- break
152
- }
153
- const scripts = commands.slice(2)
154
- if (scripts.length) {
155
- const invalidScript = scripts.find(
156
- script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
157
- )
158
- if (invalidScript) {
159
- logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
101
+ const { processScript } = await processScriptModule,
102
+ fileBaseName = basename(target, fileExtension),
103
+ fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
104
+ scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName,
105
+ scriptUser =
106
+ (
107
+ "scripts" == basename(resolve(target, "..")) &&
108
+ "hackmud" == basename(resolve(target, "../../.."))
109
+ ) ?
110
+ basename(resolve(target, "../.."))
111
+ : void 0
112
+ let outputPath =
113
+ commands[2] ||
114
+ resolve(
115
+ dirname(target),
116
+ fileBaseNameEndsWithDotSrc ? scriptName + ".js"
117
+ : ".js" == fileExtension ? fileBaseName + ".min.js"
118
+ : fileBaseName + ".js"
119
+ )
120
+ const golfFile = () =>
121
+ readFile(target, { encoding: "utf8" }).then(async source => {
122
+ const timeStart = performance.now(),
123
+ { script, warnings } = await processScript(source, {
124
+ minify: noMinifyOption && !noMinifyOption.value,
125
+ scriptUser,
126
+ scriptName,
127
+ filePath: target,
128
+ mangleNames: mangleNamesOption?.value,
129
+ forceQuineCheats: forceQuineCheatsOption?.value
130
+ }),
131
+ timeTook = performance.now() - timeStart
132
+ for (const { message, line } of warnings)
133
+ log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
134
+ await writeFilePersistent(outputPath, script)
135
+ .catch(error => {
136
+ if (!commands[2] || "EISDIR" != error.code) throw error
137
+ outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
138
+ return writeFilePersistent(outputPath, script)
139
+ })
140
+ .then(() =>
141
+ log(
142
+ `Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
143
+ )
144
+ )
145
+ })
146
+ if (watchOption) {
147
+ const { watch: watchFile } = await chokidarModule
148
+ watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
149
+ .on("ready", () => log("Watching " + target))
150
+ .on("change", golfFile)
151
+ autoExit = !1
152
+ } else await golfFile()
153
+ } else {
154
+ const hackmudPath = getHackmudPath(),
155
+ sourcePath = commands[1]
156
+ if (!sourcePath) {
157
+ logError(`Must provide the directory to ${"push" == commands[0] ? "push from" : "watch"}\n`)
160
158
  logHelp()
161
- break
159
+ process.exit(1)
162
160
  }
163
- } else scripts.push("*.*")
164
- const optionsHasNoMinify = options.has("no-minify")
165
- if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
166
- logError(
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`
161
+ const scripts = commands.slice(2)
162
+ if (scripts.length) {
163
+ const invalidScript = scripts.find(
164
+ script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
178
165
  )
179
- logHelp()
180
- break
166
+ if (invalidScript) {
167
+ logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
168
+ logHelp()
169
+ process.exit(1)
170
+ }
171
+ } else scripts.push("*.*")
172
+ if ("push" == commands[0]) {
173
+ const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } =
174
+ await pushModule,
175
+ infos = await push(sourcePath, hackmudPath, {
176
+ scripts,
177
+ onPush: info => logInfo(info, hackmudPath),
178
+ minify: noMinifyOption && !noMinifyOption.value,
179
+ mangleNames: mangleNamesOption?.value,
180
+ forceQuineCheats: forceQuineCheatsOption?.value
181
+ })
182
+ if (infos instanceof Error) {
183
+ logError(infos.message)
184
+ if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
185
+ console.log()
186
+ logHelp()
187
+ } else
188
+ infos instanceof MissingHackmudFolderError &&
189
+ log(
190
+ `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`
191
+ )
192
+ } else infos.length || logError("Could not find any scripts to push")
193
+ } else {
194
+ const typeDeclarationPathOption = popOption(
195
+ "type-declaration-path",
196
+ "type-declaration",
197
+ "dts",
198
+ "gen-types"
199
+ ),
200
+ { watch } = await watchModule
201
+ watch(sourcePath, hackmudPath, {
202
+ scripts,
203
+ onPush: info => logInfo(info, hackmudPath),
204
+ typeDeclarationPath: typeDeclarationPathOption?.value.toString(),
205
+ minify: noMinifyOption && !noMinifyOption.value,
206
+ mangleNames: mangleNamesOption?.value,
207
+ onReady: () => log("Watching"),
208
+ forceQuineCheats: forceQuineCheatsOption?.value
209
+ })
210
+ autoExit = !1
181
211
  }
182
- shouldMinify = !shouldSkipMinify
183
- }
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
212
  }
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
213
  }
217
214
  break
218
215
  case "pull":
@@ -222,7 +219,7 @@ switch (commands[0]) {
222
219
  if (!script) {
223
220
  logError("Must provide the script to pull\n")
224
221
  logHelp()
225
- break
222
+ process.exit(1)
226
223
  }
227
224
  const sourcePath = commands[2] || "."
228
225
  await pull(sourcePath, hackmudPath, script).catch(error => {
@@ -243,18 +240,19 @@ switch (commands[0]) {
243
240
  case "gen-dts":
244
241
  case "gen-types":
245
242
  {
246
- const target = commands[1]
243
+ const hackmudPath = getHackmudPath(),
244
+ target = commands[1]
247
245
  if (!target) {
248
246
  logError("Must provide target directory\n")
249
247
  logHelp()
250
- break
248
+ process.exit(1)
251
249
  }
252
250
  const sourcePath = resolve(target),
253
251
  outputPath = commands[2] || "./player.d.ts",
254
- typeDeclaration = await generateTypeDeclaration(sourcePath, getHackmudPath())
252
+ typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
255
253
  let typeDeclarationPath = resolve(outputPath)
256
254
  await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
257
- assert(error instanceof Error, "src/bin/hsm.ts:340:35")
255
+ assert(error instanceof Error, "src/bin/hsm.ts:321:35")
258
256
  if ("EISDIR" != error.code) throw error
259
257
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
260
258
  return writeFile(typeDeclarationPath, typeDeclaration)
@@ -266,99 +264,6 @@ switch (commands[0]) {
266
264
  case "h":
267
265
  logHelp()
268
266
  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
267
  default:
363
268
  commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
364
269
  logHelp()
@@ -432,7 +337,7 @@ function logError(message) {
432
337
  process.exitCode = 1
433
338
  }
434
339
  function getHackmudPath() {
435
- const hackmudPathOption = options.get("hackmud-path")
340
+ const hackmudPathOption = popOption("hackmud-path")
436
341
  if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
437
342
  logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
438
343
  logHelp()
@@ -444,3 +349,26 @@ function getHackmudPath() {
444
349
  ("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
445
350
  )
446
351
  }
352
+ function assertOptionIsBoolean(option) {
353
+ if ("boolean" != typeof option.value) {
354
+ logError(`The value for ${colourN(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
355
+ logHelp()
356
+ process.exit(1)
357
+ }
358
+ }
359
+ function popOption(...names) {
360
+ const presentOptionNames = names.filter(name => options.has(name))
361
+ if (!presentOptionNames.length) return
362
+ const presentOptionNamesWithDashDash = presentOptionNames.map(name =>
363
+ colourN(`-${1 == name.length ? "" : "-"}${name}`)
364
+ )
365
+ if (presentOptionNames.length > 1) {
366
+ logError(
367
+ `The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
368
+ )
369
+ process.exit(1)
370
+ }
371
+ const value = options.get(presentOptionNames[0])
372
+ options.delete(presentOptionNames[0])
373
+ return { name: presentOptionNamesWithDashDash[0], value }
374
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.20.4-b0ca7f9",
3
+ "version": "0.20.4-b779329",
4
4
  "description": "Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.",
5
5
  "keywords": [
6
6
  "api",