hackmud-script-manager 0.19.1-b3a477d → 0.19.1-b80922d

Sign up to get free protection for your applications and to get access to all the features.
package/bin/hsm.js CHANGED
@@ -12,7 +12,7 @@ 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.19.1-b3a477d",
15
+ const version = "0.19.1-b80922d",
16
16
  options = new Map(),
17
17
  commands = [],
18
18
  userColours = new Cache(user => {
@@ -316,7 +316,7 @@ switch (commands[0]) {
316
316
  : fileBaseName + ".js"
317
317
  )
318
318
  const golfFile = () =>
319
- readFile(target, { encoding: "utf8" }).then(async source => {
319
+ readFile(target, { encoding: "utf-8" }).then(async source => {
320
320
  const timeStart = performance.now(),
321
321
  { script, warnings } = await processScript(source, {
322
322
  minify: !(options.get("no-minify") || options.get("skip-minify")),
@@ -410,12 +410,11 @@ function logHelp() {
410
410
  )
411
411
  }
412
412
  }
413
- function logInfo({ path, users, characterCount, error }, hackmudPath) {
414
- path = relative(".", path)
413
+ function logInfo({ file, users, minLength, error }, hackmudPath) {
415
414
  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")}`
415
+ logError(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`)
416
+ : console.log(
417
+ `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")}`
419
418
  )
420
419
  }
421
420
  function logError(message) {
package/index.d.ts CHANGED
@@ -6,8 +6,8 @@ export { push } from "./push";
6
6
  export { syncMacros } from "./syncMacros";
7
7
  export { watch } from "./watch";
8
8
  export type Info = {
9
- path: string;
9
+ file: string;
10
10
  users: string[];
11
- characterCount: number;
11
+ minLength: number;
12
12
  error: Error | undefined;
13
13
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.19.1-b3a477d",
3
+ "version": "0.19.1-b80922d",
4
4
  "description": "Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.",
5
5
  "keywords": [
6
6
  "api",
@@ -51,18 +51,13 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
51
51
  referencePath.replaceWith(t.stringLiteral(1 == scriptName ? `$${uniqueID}$SCRIPT_NAME$` : scriptName))
52
52
  if (program.scope.hasGlobal("_FULL_SCRIPT_NAME"))
53
53
  for (const referencePath of getReferencePathsToGlobal("_FULL_SCRIPT_NAME", program))
54
- if (1 == scriptUser || 1 == scriptName)
55
- referencePath.replaceWith(t.stringLiteral(`$${uniqueID}$FULL_SCRIPT_NAME$`))
56
- else if (null == scriptUser) {
57
- uniqueIdScriptUserNeeded = !0
58
- referencePath.replaceWith(
59
- t.binaryExpression(
60
- "+",
61
- t.identifier(`_${uniqueID}_SCRIPT_USER_`),
62
- t.stringLiteral("." + scriptName)
63
- )
54
+ referencePath.replaceWith(
55
+ t.stringLiteral(
56
+ 1 == scriptUser || 1 == scriptName ?
57
+ `$${uniqueID}$FULL_SCRIPT_NAME$`
58
+ : `${scriptUser}.${scriptName}`
64
59
  )
65
- } else referencePath.replaceWith(t.stringLiteral(`${scriptUser}.${scriptName}`))
60
+ )
66
61
  let functionDotPrototypeIsReferencedMultipleTimes = !1
67
62
  if (program.scope.hasGlobal("Function")) {
68
63
  const FunctionReferencePaths = getReferencePathsToGlobal("Function", program)
@@ -70,30 +65,30 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
70
65
  const referencePath = FunctionReferencePaths[0]
71
66
  assert(
72
67
  "MemberExpression" == referencePath.parent.type,
73
- "src/processScript/transform.ts:105:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
68
+ "src/processScript/transform.ts:98:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
74
69
  )
75
70
  assert(
76
71
  "Identifier" == referencePath.parent.property.type,
77
- "src/processScript/transform.ts:110:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
72
+ "src/processScript/transform.ts:103:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
78
73
  )
79
74
  assert(
80
75
  "prototype" == referencePath.parent.property.name,
81
- "src/processScript/transform.ts:115:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
76
+ "src/processScript/transform.ts:108:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
82
77
  )
83
78
  referencePath.parentPath.replaceWith(createGetFunctionPrototypeNode())
84
79
  } else {
85
80
  for (const referencePath of FunctionReferencePaths) {
86
81
  assert(
87
82
  "MemberExpression" == referencePath.parent.type,
88
- "src/processScript/transform.ts:123:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
83
+ "src/processScript/transform.ts:116:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
89
84
  )
90
85
  assert(
91
86
  "Identifier" == referencePath.parent.property.type,
92
- "src/processScript/transform.ts:128:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
87
+ "src/processScript/transform.ts:121:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
93
88
  )
94
89
  assert(
95
90
  "prototype" == referencePath.parent.property.name,
96
- "src/processScript/transform.ts:133:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
91
+ "src/processScript/transform.ts:126:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
97
92
  )
98
93
  functionDotPrototypeIsReferencedMultipleTimes = !0
99
94
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_FUNCTION_DOT_PROTOTYPE_`))
@@ -129,12 +124,12 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
129
124
  const neededDbMethodLets = new Set()
130
125
  if (program.scope.hasGlobal("$db"))
131
126
  for (const referencePath of getReferencePathsToGlobal("$db", program)) {
132
- assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:187:69")
133
- assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:188:72")
127
+ assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:180:69")
128
+ assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:181:72")
134
129
  const databaseOpMethodName = referencePath.parentPath.node.property.name
135
130
  assert(
136
131
  validDBMethods.includes(databaseOpMethodName),
137
- `src/processScript/transform.ts:194:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
132
+ `src/processScript/transform.ts:187:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
138
133
  )
139
134
  if ("CallExpression" == referencePath.parentPath.parentPath?.type)
140
135
  referencePath.parentPath.replaceWith(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`))
@@ -167,7 +162,7 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
167
162
  if (program.scope.hasGlobal("Object"))
168
163
  for (const referencePath of getReferencePathsToGlobal("Object", program))
169
164
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
170
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:241:64")
165
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:234:64")
171
166
  if ("getPrototypeOf" == referencePath.parent.property.name) {
172
167
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`))
173
168
  needGetPrototypeOf = !0
@@ -177,7 +172,7 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
177
172
  if (program.scope.hasGlobal("console"))
178
173
  for (const referencePath of getReferencePathsToGlobal("console", program))
179
174
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
180
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
175
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:249:64")
181
176
  referencePath.parentPath.replaceWith(
182
177
  t.identifier(`_${uniqueID}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
183
178
  )
@@ -185,13 +180,13 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
185
180
  }
186
181
  const lastStatement = program.node.body.at(-1)
187
182
  let exportDefaultName
188
- assert(lastStatement, "src/processScript/transform.ts:270:27 program is empty")
183
+ assert(lastStatement, "src/processScript/transform.ts:263:27 program is empty")
189
184
  if ("ExportNamedDeclaration" == lastStatement.type) {
190
185
  program.node.body.pop()
191
186
  for (const specifier of lastStatement.specifiers) {
192
187
  assert(
193
188
  "ExportSpecifier" == specifier.type,
194
- `src/processScript/transform.ts:276:51 ${specifier.type} is currently unsupported`
189
+ `src/processScript/transform.ts:269:51 ${specifier.type} is currently unsupported`
195
190
  )
196
191
  const exportedName =
197
192
  "Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value
@@ -314,11 +309,11 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
314
309
  let hoistedGlobalBlockFunctions = 0
315
310
  for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
316
311
  if ("VariableDeclaration" == globalBlockStatement.type) {
317
- assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:410:59")
312
+ assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:403:59")
318
313
  const declarator = globalBlockStatement.declarations[0]
319
314
  assert(
320
315
  "Identifier" == declarator.id.type,
321
- `src/processScript/transform.ts:414:51 declarator.id.type was "${declarator.id.type}"`
316
+ `src/processScript/transform.ts:407:51 declarator.id.type was "${declarator.id.type}"`
322
317
  )
323
318
  program.scope.crawl()
324
319
  if (program.scope.hasGlobal(declarator.id.name)) {
@@ -333,9 +328,9 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
333
328
  Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
334
329
  ) {
335
330
  const binding = program.scope.getBinding(declarator.id.name)
336
- assert(binding, "src/processScript/transform.ts:433:23")
331
+ assert(binding, "src/processScript/transform.ts:426:23")
337
332
  for (const referencePath of binding.referencePaths) {
338
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:436:56")
333
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:429:56")
339
334
  referencePath.replaceWith(
340
335
  t.memberExpression(
341
336
  t.identifier(`$${uniqueID}$GLOBAL$`),
@@ -379,16 +374,16 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
379
374
  } else globalBlockVariables.add(declarator.id.name)
380
375
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
381
376
  program.scope.crawl()
382
- assert(globalBlockStatement.id, "src/processScript/transform.ts:487:37")
377
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:480:37")
383
378
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
384
379
  globalBlock.body.splice(globalBlockIndex, 1)
385
380
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
386
381
  [globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
387
382
  program.scope.crawl()
388
383
  const binding = program.scope.getBinding(globalBlockStatement.id.name)
389
- assert(binding, "src/processScript/transform.ts:499:22")
384
+ assert(binding, "src/processScript/transform.ts:492:22")
390
385
  for (const referencePath of binding.referencePaths) {
391
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:502:55")
386
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:495:55")
392
387
  referencePath.replaceWith(
393
388
  t.memberExpression(
394
389
  t.identifier(`$${uniqueID}$GLOBAL$`),
@@ -555,7 +550,7 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
555
550
  }
556
551
  },
557
552
  ClassBody({ node: classBody, scope, parent }) {
558
- assert(t.isClass(parent), "src/processScript/transform.ts:669:30")
553
+ assert(t.isClass(parent), "src/processScript/transform.ts:662:30")
559
554
  let thisIsReferenced = !1
560
555
  for (const classMethod of classBody.body) {
561
556
  if ("ClassMethod" != classMethod.type) continue
@@ -661,23 +656,23 @@ function transform(file, sourceCode, { uniqueID = "00000000000", scriptUser, scr
661
656
  }
662
657
  function processFakeSubscriptObject(fakeSubscriptObjectName) {
663
658
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
664
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:783:60")
659
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:776:60")
665
660
  assert("Identifier" == referencePath.parent.property.type)
666
661
  assert(
667
662
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
668
- "src/processScript/transform.ts:785:81"
663
+ "src/processScript/transform.ts:778:81"
669
664
  )
670
665
  assert(
671
666
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
672
- "src/processScript/transform.ts:786:83"
667
+ "src/processScript/transform.ts:779:83"
673
668
  )
674
669
  assert(
675
670
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
676
- `src/processScript/transform.ts:790:8 invalid user "${referencePath.parent.property.name}" in subscript`
671
+ `src/processScript/transform.ts:783:8 invalid user "${referencePath.parent.property.name}" in subscript`
677
672
  )
678
673
  assert(
679
674
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
680
- `src/processScript/transform.ts:795:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
675
+ `src/processScript/transform.ts:788:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
681
676
  )
682
677
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
683
678
  referencePath.parentPath.parentPath.replaceWith(
package/push.d.ts CHANGED
@@ -21,8 +21,8 @@ export type PushOptions = LaxPartial<{
21
21
  /** Push scripts from a source directory to the hackmud directory.
22
22
  *
23
23
  * Pushes files directly in the source folder to all users
24
- * @param sourcePath directory containing source code
25
- * @param hackmudPath directory created by hackmud containing user data including scripts
24
+ * @param sourceDirectory directory containing source code
25
+ * @param hackmudDirectory directory created by hackmud containing user data including scripts
26
26
  * @param options {@link PushOptions details}
27
27
  * @returns array of info on pushed scripts */
28
- export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<Info[]>;
28
+ export declare function push(sourceDirectory: string, hackmudDirectory: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<Info[]>;
package/push.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { Cache } from "@samual/lib/Cache"
2
- import { ensure, assert } from "@samual/lib/assert"
3
2
  import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
4
3
  import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
5
4
  import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
6
5
  import { readFile } from "fs/promises"
7
- import { basename, resolve } from "path"
6
+ import { basename, resolve, extname } from "path"
7
+ import { supportedExtensions } from "./constants.js"
8
8
  import { processScript } from "./processScript/index.js"
9
9
  import "@babel/generator"
10
10
  import "@babel/parser"
@@ -29,9 +29,9 @@ import "@rollup/plugin-babel"
29
29
  import "@rollup/plugin-commonjs"
30
30
  import "@rollup/plugin-json"
31
31
  import "@rollup/plugin-node-resolve"
32
+ import "@samual/lib/assert"
32
33
  import "prettier"
33
34
  import "rollup"
34
- import "./constants.js"
35
35
  import "./processScript/minify.js"
36
36
  import "@samual/lib/spliceString"
37
37
  import "acorn"
@@ -43,96 +43,227 @@ import "import-meta-resolve"
43
43
  import "./processScript/transform.js"
44
44
  import "@samual/lib/clearObject"
45
45
  async function push(
46
- sourcePath,
47
- hackmudPath,
46
+ sourceDirectory,
47
+ hackmudDirectory,
48
48
  { scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats } = {}
49
49
  ) {
50
- const [sourceFolder, hackmudFolder] = await Promise.all([
51
- readDirectoryWithStats(sourcePath),
52
- readDirectoryWithStats(hackmudPath)
53
- ]),
54
- sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
55
- allUsers = new Set([
56
- ...scripts
57
- .map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:52:65"))
58
- .filter(name => "*" != name),
59
- ...sourceFolderFolders.map(({ name }) => name),
60
- ...hackmudFolder.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
61
- ...hackmudFolder
62
- .filter(({ stats, name }) => stats.isFile() && name.endsWith(".key"))
63
- .map(({ name }) => name.slice(0, -4))
64
- ]),
65
- usersToScriptsToPush = new Cache(_user => new Map()),
66
- scriptNamesToUsers = new Cache(_scriptName => new Set())
67
- for (const script of scripts) {
68
- const [user, scriptName] = script.split(".")
69
- assert(user, "src/push.ts:69:16")
70
- assert(scriptName, "src/push.ts:70:22")
71
- "*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
50
+ const scriptNamesByUser = new Cache(_user => new Set()),
51
+ wildScriptUsers = new Set(),
52
+ wildUserScripts = new Set()
53
+ let pushEverything = !1
54
+ for (const fullScriptName of scripts) {
55
+ const [user, scriptName] = fullScriptName.split(".")
56
+ user && "*" != user ?
57
+ scriptName && "*" != scriptName ?
58
+ scriptNamesByUser.get(user).add(scriptName)
59
+ : wildScriptUsers.add(user)
60
+ : scriptName && "*" != scriptName ? wildUserScripts.add(scriptName)
61
+ : (pushEverything = !0)
72
62
  }
73
- const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
74
- wildScriptUsers_ = scriptNamesToUsers.get("*")
75
- scriptNamesToUsers.delete("*")
76
- for (const { name, path } of [
77
- ...sourceFolderFiles.filter(({ name }) => name.endsWith(".js")),
78
- ...sourceFolderFiles.filter(({ name }) => name.endsWith(".ts"))
79
- ]) {
80
- const scriptName = name.slice(0, -3)
81
- for (const user of [...wildScriptUsers_, ...scriptNamesToUsers.get(scriptName)])
82
- usersToScriptsToPush.get(user).set(scriptName, path)
63
+ const usersByGlobalScriptsToPush = new Cache(_user => new Set()),
64
+ allInfo = [],
65
+ scriptNamesAlreadyPushedByUser = new Cache(_user => new Set())
66
+ let sourceDirectoryDirents
67
+ if (wildUserScripts.size || pushEverything) {
68
+ let hackmudDirectoryEntries
69
+ ;[hackmudDirectoryEntries, sourceDirectoryDirents] = await Promise.all([
70
+ readDirectoryWithStats(hackmudDirectory),
71
+ readDirectoryWithStats(sourceDirectory)
72
+ ])
73
+ const allUsers = new Set([
74
+ ...sourceDirectoryDirents.filter(({ stats }) => stats.isDirectory()).map(({ path }) => basename(path)),
75
+ ...hackmudDirectoryEntries.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
76
+ ...hackmudDirectoryEntries
77
+ .filter(({ name, stats }) => stats.isFile() && name.endsWith(".key"))
78
+ .map(({ name }) => name.slice(0, -4)),
79
+ ...scriptNamesByUser.keys(),
80
+ ...wildScriptUsers
81
+ ])
82
+ if (pushEverything) for (const user of allUsers) wildScriptUsers.add(user)
83
+ else
84
+ for (const user of allUsers) {
85
+ const scriptNames = scriptNamesByUser.get(user)
86
+ for (const scriptName of wildUserScripts) scriptNames.add(scriptName)
87
+ }
83
88
  }
84
89
  await Promise.all(
85
- sourceFolderFolders.map(async ({ name: user, path }) => {
86
- const files = (await readDirectoryWithStats(path)).filter(({ stats }) => stats.isFile()),
87
- scriptFiles = [
88
- ...files.filter(({ name }) => name.endsWith(".js")),
89
- ...files.filter(({ name }) => name.endsWith(".ts"))
90
- ]
91
- for (const { name, path } of scriptFiles) {
92
- const scriptName = name.slice(0, -3)
93
- ;[...wildScriptUsers_, ...scriptNamesToUsers.get(scriptName)].includes(user) &&
94
- usersToScriptsToPush.get(user).set(scriptName, path)
95
- }
90
+ [...wildScriptUsers].map(async user => {
91
+ await readDirectoryWithStats(resolve(sourceDirectory, user)).then(
92
+ async entries => {
93
+ await Promise.all(
94
+ entries.map(async ({ stats, name, path }) => {
95
+ if (name.endsWith(".d.ts")) return
96
+ const extension = extname(name)
97
+ if (stats.isFile() && supportedExtensions.includes(extension)) {
98
+ const scriptName = basename(name, extension),
99
+ { script: minifiedCode } = await processScript(
100
+ await readFile(path, { encoding: "utf-8" }),
101
+ {
102
+ minify,
103
+ scriptUser: user,
104
+ scriptName,
105
+ filePath: path,
106
+ mangleNames,
107
+ forceQuineCheats
108
+ }
109
+ ),
110
+ info = {
111
+ file: `${user}/${name}`,
112
+ users: [user],
113
+ minLength: countHackmudCharacters(minifiedCode),
114
+ error: void 0
115
+ }
116
+ scriptNamesAlreadyPushedByUser.get(user).add(scriptName)
117
+ allInfo.push(info)
118
+ await writeFilePersistent(
119
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
120
+ minifiedCode
121
+ )
122
+ onPush(info)
123
+ }
124
+ })
125
+ )
126
+ },
127
+ error => {
128
+ if ("ENOENT" != error.code) throw error
129
+ }
130
+ )
96
131
  })
97
132
  )
98
- for (const [scriptName, users] of scriptNamesToUsers)
99
- for (const user of users)
100
- if (!usersToScriptsToPush.get(user).has(scriptName))
101
- throw Error(`Could not find script ${user}.${scriptName} to push`)
102
- const pathsToUsers = new Cache(_path => new Set())
103
- for (const [user, scriptsToPush] of usersToScriptsToPush)
104
- for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
105
- const allInfo = []
106
133
  await Promise.all(
107
- [...pathsToUsers].map(async ([path, [...users]]) => {
108
- const scriptName = basename(path.slice(0, -3)),
109
- uniqueID = Math.floor(Math.random() * 2 ** 52)
110
- .toString(36)
111
- .padStart(11, "0"),
112
- { script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf8" }), {
113
- minify,
114
- scriptUser: !0,
115
- scriptName,
116
- uniqueID,
117
- filePath: path,
118
- mangleNames,
119
- forceQuineCheats
120
- }),
121
- info = { path, users, characterCount: countHackmudCharacters(minifiedCode), error: void 0 }
122
- await Promise.all(
123
- users.map(user =>
124
- writeFilePersistent(
125
- resolve(hackmudPath, user, `scripts/${scriptName}.js`),
126
- minifiedCode
127
- .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
128
- .replace(RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"), `${user}.${scriptName}`)
129
- )
130
- )
131
- )
132
- allInfo.push(info)
133
- onPush(info)
134
+ [...scriptNamesByUser].map(async ([user, scripts]) => {
135
+ wildScriptUsers.has(user) ||
136
+ (await Promise.all(
137
+ [...scripts].map(async scriptName => {
138
+ let code, fileName, filePath
139
+ for (const extension of supportedExtensions)
140
+ try {
141
+ fileName = `${scriptName}${extension}`
142
+ code = await readFile((filePath = resolve(sourceDirectory, user, fileName)), {
143
+ encoding: "utf-8"
144
+ })
145
+ break
146
+ } catch {}
147
+ if (code) {
148
+ const { script: minifiedCode } = await processScript(code, {
149
+ minify,
150
+ scriptUser: user,
151
+ scriptName,
152
+ filePath,
153
+ mangleNames,
154
+ forceQuineCheats
155
+ }),
156
+ info = {
157
+ file: `${user}/${fileName}`,
158
+ users: [user],
159
+ minLength: countHackmudCharacters(minifiedCode),
160
+ error: void 0
161
+ }
162
+ allInfo.push(info)
163
+ await writeFilePersistent(
164
+ resolve(hackmudDirectory, user, "scripts", scriptName + ".js"),
165
+ minifiedCode
166
+ )
167
+ onPush(info)
168
+ } else usersByGlobalScriptsToPush.get(scriptName).add(user)
169
+ })
170
+ ))
134
171
  })
135
172
  )
173
+ await (wildScriptUsers.size ?
174
+ Promise.all(
175
+ (sourceDirectoryDirents || (await readDirectoryWithStats(sourceDirectory))).map(
176
+ async ({ path, stats, name }) => {
177
+ if (name.endsWith(".d.ts")) return
178
+ const extension = extname(name)
179
+ if (!stats.isFile() || !supportedExtensions.includes(extension)) return
180
+ const scriptName = basename(name, extension),
181
+ usersToPushTo = [...wildScriptUsers, ...usersByGlobalScriptsToPush.get(scriptName)].filter(
182
+ user => !scriptNamesAlreadyPushedByUser.get(user).has(scriptName)
183
+ )
184
+ if (!usersToPushTo.length) return
185
+ const uniqueID = Math.floor(Math.random() * 2 ** 52)
186
+ .toString(36)
187
+ .padStart(11, "0"),
188
+ { script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf-8" }), {
189
+ minify,
190
+ scriptUser: !0,
191
+ scriptName,
192
+ uniqueID,
193
+ filePath: path,
194
+ mangleNames,
195
+ forceQuineCheats
196
+ }),
197
+ info = {
198
+ file: name,
199
+ users: usersToPushTo,
200
+ minLength: countHackmudCharacters(minifiedCode),
201
+ error: void 0
202
+ }
203
+ await Promise.all(
204
+ usersToPushTo.map(user =>
205
+ writeFilePersistent(
206
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
207
+ minifiedCode
208
+ .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
209
+ .replace(
210
+ RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"),
211
+ `${user}.${scriptName}`
212
+ )
213
+ )
214
+ )
215
+ )
216
+ allInfo.push(info)
217
+ onPush(info)
218
+ }
219
+ )
220
+ )
221
+ : Promise.all(
222
+ [...usersByGlobalScriptsToPush].map(async ([scriptName, users]) => {
223
+ let code, fileName, filePath
224
+ for (const extension of supportedExtensions)
225
+ try {
226
+ fileName = `${scriptName}${extension}`
227
+ code = await readFile((filePath = resolve(sourceDirectory, fileName)), { encoding: "utf-8" })
228
+ break
229
+ } catch {}
230
+ if (code) {
231
+ const uniqueID = Math.floor(Math.random() * 2 ** 52)
232
+ .toString(36)
233
+ .padStart(11, "0"),
234
+ { script: minifiedCode } = await processScript(code, {
235
+ minify,
236
+ scriptUser: !0,
237
+ scriptName,
238
+ uniqueID,
239
+ filePath,
240
+ mangleNames,
241
+ forceQuineCheats
242
+ }),
243
+ info = {
244
+ file: fileName,
245
+ users: [...users],
246
+ minLength: countHackmudCharacters(minifiedCode),
247
+ error: void 0
248
+ }
249
+ await Promise.all(
250
+ [...users].map(user =>
251
+ writeFilePersistent(
252
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
253
+ minifiedCode
254
+ .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
255
+ .replace(
256
+ RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"),
257
+ `${user}.${scriptName}`
258
+ )
259
+ )
260
+ )
261
+ )
262
+ allInfo.push(info)
263
+ onPush(info)
264
+ }
265
+ })
266
+ ))
136
267
  return allInfo
137
268
  }
138
269
  export { push }
package/syncMacros.js CHANGED
@@ -12,7 +12,7 @@ async function syncMacros(hackmudPath) {
12
12
  case ".macros":
13
13
  {
14
14
  const [lines, date] = await Promise.all([
15
- readFile(resolve(hackmudPath, file.name), { encoding: "utf8" }).then(file =>
15
+ readFile(resolve(hackmudPath, file.name), { encoding: "utf-8" }).then(file =>
16
16
  file.split("\n")
17
17
  ),
18
18
  stat(resolve(hackmudPath, file.name)).then(({ mtime }) => mtime)
package/watch.js CHANGED
@@ -116,7 +116,7 @@ async function watch(
116
116
  for (const user of scriptNamesToUsers.get(scriptName)) usersToPushToSet.add(user)
117
117
  const usersToPushTo = [...usersToPushToSet].filter(user => !scriptNamesToUsersToSkip.has(user))
118
118
  if (!usersToPushTo.length) {
119
- onPush?.({ path, users: [], characterCount: 0, error: Error("no users to push to") })
119
+ onPush?.({ file: path, users: [], minLength: 0, error: Error("no users to push to") })
120
120
  return
121
121
  }
122
122
  const uniqueID = Math.floor(Math.random() * 2 ** 52)
@@ -125,7 +125,7 @@ async function watch(
125
125
  filePath = resolve(sourceDirectory, path)
126
126
  let minifiedCode
127
127
  try {
128
- ;({ script: minifiedCode } = await processScript(await readFile(filePath, { encoding: "utf8" }), {
128
+ ;({ script: minifiedCode } = await processScript(await readFile(filePath, { encoding: "utf-8" }), {
129
129
  minify,
130
130
  scriptUser: !0,
131
131
  scriptName,
@@ -136,7 +136,7 @@ async function watch(
136
136
  }))
137
137
  } catch (error) {
138
138
  assert(error instanceof Error, "src/watch.ts:141:36")
139
- onPush?.({ path, users: [], characterCount: 0, error })
139
+ onPush?.({ file: path, users: [], minLength: 0, error })
140
140
  return
141
141
  }
142
142
  await Promise.all(
@@ -150,9 +150,9 @@ async function watch(
150
150
  )
151
151
  )
152
152
  onPush?.({
153
- path,
153
+ file: path,
154
154
  users: usersToPushTo,
155
- characterCount: countHackmudCharacters(minifiedCode),
155
+ minLength: countHackmudCharacters(minifiedCode),
156
156
  error: void 0
157
157
  })
158
158
  return
@@ -168,7 +168,7 @@ async function watch(
168
168
  )
169
169
  return
170
170
  const filePath = resolve(sourceDirectory, path),
171
- sourceCode = await readFile(filePath, { encoding: "utf8" })
171
+ sourceCode = await readFile(filePath, { encoding: "utf-8" })
172
172
  let script
173
173
  try {
174
174
  ;({ script } = await processScript(sourceCode, {
@@ -181,11 +181,11 @@ async function watch(
181
181
  }))
182
182
  } catch (error) {
183
183
  assert(error instanceof Error, "src/watch.ts:177:35")
184
- onPush?.({ path, users: [], characterCount: 0, error })
184
+ onPush?.({ file: path, users: [], minLength: 0, error })
185
185
  return
186
186
  }
187
187
  await writeFilePersistent(resolve(hackmudDirectory, user, "scripts", scriptName + ".js"), script)
188
- onPush?.({ path, users: [user], characterCount: countHackmudCharacters(script), error: void 0 })
188
+ onPush?.({ file: path, users: [user], minLength: countHackmudCharacters(script), error: void 0 })
189
189
  })
190
190
  onReady && watcher.on("ready", onReady)
191
191
  if (!typeDeclarationPath_) return