hackmud-script-manager 0.19.1-98e81f8 → 0.19.1-bf4dc4a
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 +74 -81
- package/generateTypeDeclaration.js +17 -17
- package/index.js +2 -1
- package/package.json +3 -3
- package/processScript/index.js +19 -2
- package/processScript/minify.js +2 -2
- package/processScript/preprocess.js +1 -1
- package/processScript/transform.js +121 -109
- package/push.js +43 -37
- package/syncMacros.js +4 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/watch.js +14 -15
@@ -111,39 +111,34 @@ const { default: traverse } = babelTraverse,
|
|
111
111
|
}
|
112
112
|
}
|
113
113
|
let detectedSeclevel = 4
|
114
|
-
const
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
assert(
|
125
|
-
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
|
126
|
-
`invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
|
127
|
-
)
|
128
|
-
"CallExpression" == referencePath.parentPath.parentPath.parentPath?.type ?
|
129
|
-
referencePath.parentPath.parentPath.replaceWith(
|
130
|
-
t.identifier(
|
131
|
-
`$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
|
132
|
-
)
|
114
|
+
const neededSubscriptLets = new Set(),
|
115
|
+
processFakeSubscriptObject = fakeSubscriptObjectName => {
|
116
|
+
for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
|
117
|
+
assert("MemberExpression" == referencePath.parent.type)
|
118
|
+
assert("Identifier" == referencePath.parent.property.type)
|
119
|
+
assert("MemberExpression" == referencePath.parentPath.parentPath?.node.type)
|
120
|
+
assert("Identifier" == referencePath.parentPath.parentPath.node.property.type)
|
121
|
+
assert(
|
122
|
+
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
|
123
|
+
`invalid user "${referencePath.parent.property.name}" in subscript`
|
133
124
|
)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
125
|
+
assert(
|
126
|
+
/^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
|
127
|
+
`invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
|
128
|
+
)
|
129
|
+
if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
|
130
|
+
referencePath.parentPath.parentPath.replaceWith(
|
131
|
+
t.identifier(
|
132
|
+
`$${uniqueID}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
|
142
133
|
)
|
143
134
|
)
|
144
|
-
|
135
|
+
else {
|
136
|
+
const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
|
137
|
+
referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueID}_SUBSCRIPT_${name}_`))
|
138
|
+
neededSubscriptLets.add(name)
|
139
|
+
}
|
140
|
+
}
|
145
141
|
}
|
146
|
-
}
|
147
142
|
for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
|
148
143
|
program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
|
149
144
|
for (const fakeSubscriptObjectName of ["$hs", "$3s"])
|
@@ -167,6 +162,7 @@ const { default: traverse } = babelTraverse,
|
|
167
162
|
processFakeSubscriptObject(fakeSubscriptObjectName)
|
168
163
|
}
|
169
164
|
seclevel = Math.min(seclevel, detectedSeclevel)
|
165
|
+
const neededDbMethodLets = new Set()
|
170
166
|
if (program.scope.hasGlobal("$db"))
|
171
167
|
for (const referencePath of getReferencePathsToGlobal("$db", program)) {
|
172
168
|
assert("MemberExpression" == referencePath.parentPath.node.type)
|
@@ -176,44 +172,24 @@ const { default: traverse } = babelTraverse,
|
|
176
172
|
validDBMethods.includes(databaseOpMethodName),
|
177
173
|
`invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
|
178
174
|
)
|
179
|
-
"CallExpression" == referencePath.parentPath.parentPath?.type
|
175
|
+
if ("CallExpression" == referencePath.parentPath.parentPath?.type)
|
180
176
|
referencePath.parentPath.replaceWith(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`))
|
181
|
-
|
182
|
-
referencePath.parentPath.replaceWith(
|
183
|
-
t.arrowFunctionExpression(
|
184
|
-
[],
|
185
|
-
t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [])
|
186
|
-
)
|
187
|
-
)
|
188
|
-
: "i" == databaseOpMethodName || "r" == databaseOpMethodName ?
|
177
|
+
else {
|
189
178
|
referencePath.parentPath.replaceWith(
|
190
|
-
t.
|
191
|
-
[t.identifier("a")],
|
192
|
-
t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [
|
193
|
-
t.identifier("a")
|
194
|
-
])
|
195
|
-
)
|
196
|
-
)
|
197
|
-
: referencePath.parentPath.replaceWith(
|
198
|
-
t.arrowFunctionExpression(
|
199
|
-
[t.identifier("a"), t.identifier("b")],
|
200
|
-
t.callExpression(t.identifier(`$${uniqueID}$DB$${databaseOpMethodName}$`), [
|
201
|
-
t.identifier("a"),
|
202
|
-
t.identifier("b")
|
203
|
-
])
|
204
|
-
)
|
179
|
+
t.identifier(`_${uniqueID}_CONSOLE_METHOD_${databaseOpMethodName}_`)
|
205
180
|
)
|
181
|
+
neededDbMethodLets.add(databaseOpMethodName)
|
182
|
+
}
|
206
183
|
}
|
184
|
+
let needDebugLet = !1
|
207
185
|
if (program.scope.hasGlobal("$D"))
|
208
186
|
for (const referencePath of getReferencePathsToGlobal("$D", program))
|
209
|
-
"CallExpression" == referencePath.parentPath.type
|
187
|
+
if ("CallExpression" == referencePath.parentPath.type)
|
210
188
|
referencePath.replaceWith(t.identifier(`$${uniqueID}$DEBUG$`))
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
)
|
216
|
-
)
|
189
|
+
else {
|
190
|
+
referencePath.replaceWith(t.identifier(`_${uniqueID}_DEBUG_`))
|
191
|
+
needDebugLet = !0
|
192
|
+
}
|
217
193
|
if (program.scope.hasGlobal("$FMCL"))
|
218
194
|
for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
|
219
195
|
referencePath.replaceWith(t.identifier(`$${uniqueID}$FMCL$`))
|
@@ -223,8 +199,7 @@ const { default: traverse } = babelTraverse,
|
|
223
199
|
if (program.scope.hasGlobal("_SECLEVEL"))
|
224
200
|
for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
|
225
201
|
referencePath.replaceWith(t.numericLiteral(seclevel))
|
226
|
-
let needGetPrototypeOf = !1
|
227
|
-
needSetPrototypeOf = !1
|
202
|
+
let needGetPrototypeOf = !1
|
228
203
|
if (program.scope.hasGlobal("Object"))
|
229
204
|
for (const referencePath of getReferencePathsToGlobal("Object", program))
|
230
205
|
if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
|
@@ -232,11 +207,18 @@ const { default: traverse } = babelTraverse,
|
|
232
207
|
if ("getPrototypeOf" == referencePath.parent.property.name) {
|
233
208
|
referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`))
|
234
209
|
needGetPrototypeOf = !0
|
235
|
-
} else if ("setPrototypeOf" == referencePath.parent.property.name) {
|
236
|
-
referencePath.parentPath.replaceWith(t.identifier(`_${uniqueID}_SET_PROTOTYPE_OF_`))
|
237
|
-
needSetPrototypeOf = !0
|
238
210
|
}
|
239
211
|
}
|
212
|
+
const consoleMethodsReferenced = new Set()
|
213
|
+
if (program.scope.hasGlobal("console"))
|
214
|
+
for (const referencePath of getReferencePathsToGlobal("console", program))
|
215
|
+
if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
|
216
|
+
assert("Identifier" == referencePath.parent.property.type)
|
217
|
+
referencePath.parentPath.replaceWith(
|
218
|
+
t.identifier(`_${uniqueID}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
|
219
|
+
)
|
220
|
+
consoleMethodsReferenced.add(referencePath.parent.property.name)
|
221
|
+
}
|
240
222
|
const lastStatement = program.node.body.at(-1)
|
241
223
|
let exportDefaultName
|
242
224
|
assert(lastStatement, "program is empty")
|
@@ -410,7 +392,7 @@ const { default: traverse } = babelTraverse,
|
|
410
392
|
} else globalBlockVariables.add(declarator.id.name)
|
411
393
|
} else if ("ClassDeclaration" == globalBlockStatement.type) {
|
412
394
|
program.scope.crawl()
|
413
|
-
assert(globalBlockStatement.id, "src/processScript/transform.ts:
|
395
|
+
assert(globalBlockStatement.id, "src/processScript/transform.ts:544:37")
|
414
396
|
if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
|
415
397
|
globalBlock.body.splice(globalBlockIndex, 1)
|
416
398
|
const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
|
@@ -471,29 +453,31 @@ const { default: traverse } = babelTraverse,
|
|
471
453
|
)
|
472
454
|
])
|
473
455
|
)
|
474
|
-
|
456
|
+
needGetPrototypeOf &&
|
475
457
|
mainFunction.body.body.unshift(
|
476
458
|
t.variableDeclaration("let", [
|
477
459
|
t.variableDeclarator(
|
478
|
-
t.
|
460
|
+
t.objectPattern([
|
461
|
+
t.objectProperty(t.identifier("get"), t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`))
|
462
|
+
]),
|
479
463
|
t.callExpression(
|
480
|
-
t.memberExpression(
|
481
|
-
|
482
|
-
t.identifier("
|
483
|
-
|
484
|
-
|
464
|
+
t.memberExpression(t.identifier("Object"), t.identifier("getOwnPropertyDescriptor")),
|
465
|
+
[
|
466
|
+
t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
|
467
|
+
t.stringLiteral("__proto__")
|
468
|
+
]
|
485
469
|
)
|
486
|
-
)
|
487
|
-
])
|
488
|
-
)
|
489
|
-
needGetPrototypeOf &&
|
490
|
-
mainFunction.body.body.unshift(
|
491
|
-
t.variableDeclaration("let", [
|
470
|
+
),
|
492
471
|
t.variableDeclarator(
|
493
472
|
t.identifier(`_${uniqueID}_GET_PROTOTYPE_OF_`),
|
494
473
|
t.callExpression(
|
495
474
|
t.memberExpression(
|
496
|
-
t.memberExpression(
|
475
|
+
t.memberExpression(
|
476
|
+
t.identifier(
|
477
|
+
globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
|
478
|
+
),
|
479
|
+
t.identifier("call")
|
480
|
+
),
|
497
481
|
t.identifier("bind")
|
498
482
|
),
|
499
483
|
[t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)]
|
@@ -501,41 +485,69 @@ const { default: traverse } = babelTraverse,
|
|
501
485
|
)
|
502
486
|
])
|
503
487
|
)
|
504
|
-
|
488
|
+
consoleMethodsReferenced.size &&
|
489
|
+
mainFunction.body.body.unshift(
|
490
|
+
t.variableDeclaration(
|
491
|
+
"let",
|
492
|
+
[...consoleMethodsReferenced].map(name =>
|
493
|
+
t.variableDeclarator(
|
494
|
+
t.identifier(`_${uniqueID}_CONSOLE_METHOD_${name}_`),
|
495
|
+
t.arrowFunctionExpression(
|
496
|
+
[t.restElement(t.identifier("args"))],
|
497
|
+
t.unaryExpression(
|
498
|
+
"void",
|
499
|
+
t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier("args")])
|
500
|
+
)
|
501
|
+
)
|
502
|
+
)
|
503
|
+
)
|
504
|
+
)
|
505
|
+
)
|
506
|
+
neededDbMethodLets.size &&
|
507
|
+
mainFunction.body.body.unshift(
|
508
|
+
t.variableDeclaration(
|
509
|
+
"let",
|
510
|
+
[...neededDbMethodLets].map(name => {
|
511
|
+
const getArgs = () =>
|
512
|
+
"ObjectId" == name ? []
|
513
|
+
: "i" == name || "r" == name ? [t.identifier("a")]
|
514
|
+
: [t.identifier("a"), t.identifier("b")]
|
515
|
+
return t.variableDeclarator(
|
516
|
+
t.identifier(`_${uniqueID}_CONSOLE_METHOD_${name}_`),
|
517
|
+
t.arrowFunctionExpression(
|
518
|
+
getArgs(),
|
519
|
+
t.callExpression(t.identifier(`$${uniqueID}$DB$${name}$`), getArgs())
|
520
|
+
)
|
521
|
+
)
|
522
|
+
})
|
523
|
+
)
|
524
|
+
)
|
525
|
+
needDebugLet &&
|
505
526
|
mainFunction.body.body.unshift(
|
506
527
|
t.variableDeclaration("let", [
|
507
528
|
t.variableDeclarator(
|
508
|
-
t.
|
509
|
-
|
510
|
-
needSetPrototypeOf ?
|
511
|
-
[
|
512
|
-
t.objectProperty(
|
513
|
-
t.identifier("get"),
|
514
|
-
t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)
|
515
|
-
),
|
516
|
-
t.objectProperty(
|
517
|
-
t.identifier("set"),
|
518
|
-
t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`)
|
519
|
-
)
|
520
|
-
]
|
521
|
-
: [
|
522
|
-
t.objectProperty(
|
523
|
-
t.identifier("get"),
|
524
|
-
t.identifier(`_${uniqueID}_DUNDER_PROTO_GETTER_`)
|
525
|
-
)
|
526
|
-
]
|
527
|
-
: [t.objectProperty(t.identifier("set"), t.identifier(`_${uniqueID}_DUNDER_PROTO_SETTER_`))]
|
528
|
-
),
|
529
|
-
t.callExpression(
|
530
|
-
t.memberExpression(t.identifier("Object"), t.identifier("getOwnPropertyDescriptor")),
|
531
|
-
[
|
532
|
-
t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
|
533
|
-
t.stringLiteral("__proto__")
|
534
|
-
]
|
535
|
-
)
|
529
|
+
t.identifier(`_${uniqueID}_DEBUG_`),
|
530
|
+
t.callExpression(t.identifier(`$${uniqueID}$DEBUG$`), [t.identifier("a")])
|
536
531
|
)
|
537
532
|
])
|
538
533
|
)
|
534
|
+
neededSubscriptLets.size &&
|
535
|
+
mainFunction.body.body.unshift(
|
536
|
+
t.variableDeclaration(
|
537
|
+
"let",
|
538
|
+
[...neededSubscriptLets].map(name =>
|
539
|
+
t.variableDeclarator(
|
540
|
+
t.identifier(`_${uniqueID}_SUBSCRIPT_${name}_`),
|
541
|
+
t.arrowFunctionExpression(
|
542
|
+
[t.restElement(t.identifier("args"))],
|
543
|
+
t.callExpression(t.identifier(`$${uniqueID}$SUBSCRIPT$${name}$`), [
|
544
|
+
t.spreadElement(t.identifier("args"))
|
545
|
+
])
|
546
|
+
)
|
547
|
+
)
|
548
|
+
)
|
549
|
+
)
|
550
|
+
)
|
539
551
|
traverse(file, {
|
540
552
|
BlockStatement({ node: blockStatement }) {
|
541
553
|
for (const [index, functionDeclaration] of blockStatement.body.entries())
|
package/push.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import { Cache } from "@samual/lib/Cache"
|
2
2
|
import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
|
3
|
+
import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
|
3
4
|
import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
|
4
|
-
import {
|
5
|
-
import { resolve, extname
|
5
|
+
import { readFile } from "fs/promises"
|
6
|
+
import { basename, resolve, extname } from "path"
|
6
7
|
import { supportedExtensions } from "./constants.js"
|
7
8
|
import { processScript } from "./processScript/index.js"
|
8
9
|
import "@babel/generator"
|
@@ -64,18 +65,20 @@ const push = async (
|
|
64
65
|
scriptNamesAlreadyPushedByUser = new Cache(_user => new Set())
|
65
66
|
let sourceDirectoryDirents
|
66
67
|
if (wildUserScripts.size || pushEverything) {
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
+
])
|
79
82
|
if (pushEverything) for (const user of allUsers) wildScriptUsers.add(user)
|
80
83
|
else
|
81
84
|
for (const user of allUsers) {
|
@@ -85,28 +88,27 @@ const push = async (
|
|
85
88
|
}
|
86
89
|
await Promise.all(
|
87
90
|
[...wildScriptUsers].map(async user => {
|
88
|
-
await
|
89
|
-
async
|
91
|
+
await readDirectoryWithStats(resolve(sourceDirectory, user)).then(
|
92
|
+
async entries => {
|
90
93
|
await Promise.all(
|
91
|
-
|
92
|
-
if (
|
93
|
-
const extension = extname(
|
94
|
-
if (
|
95
|
-
const scriptName = basename(
|
96
|
-
filePath = resolve(sourceDirectory, user, dirent.name),
|
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),
|
97
99
|
{ script: minifiedCode } = await processScript(
|
98
|
-
await readFile(
|
100
|
+
await readFile(path, { encoding: "utf-8" }),
|
99
101
|
{
|
100
102
|
minify,
|
101
103
|
scriptUser: user,
|
102
104
|
scriptName,
|
103
|
-
filePath,
|
105
|
+
filePath: path,
|
104
106
|
mangleNames,
|
105
107
|
forceQuineCheats
|
106
108
|
}
|
107
109
|
),
|
108
110
|
info = {
|
109
|
-
file: `${user}/${
|
111
|
+
file: `${user}/${name}`,
|
110
112
|
users: [user],
|
111
113
|
minLength: countHackmudCharacters(minifiedCode),
|
112
114
|
error: void 0
|
@@ -170,12 +172,12 @@ const push = async (
|
|
170
172
|
)
|
171
173
|
await (wildScriptUsers.size ?
|
172
174
|
Promise.all(
|
173
|
-
(sourceDirectoryDirents || (await
|
174
|
-
async
|
175
|
-
if (
|
176
|
-
const extension = extname(
|
177
|
-
if (!
|
178
|
-
const scriptName = basename(
|
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),
|
179
181
|
usersToPushTo = [...wildScriptUsers, ...usersByGlobalScriptsToPush.get(scriptName)].filter(
|
180
182
|
user => !scriptNamesAlreadyPushedByUser.get(user).has(scriptName)
|
181
183
|
)
|
@@ -183,13 +185,17 @@ const push = async (
|
|
183
185
|
const uniqueID = Math.floor(Math.random() * 2 ** 52)
|
184
186
|
.toString(36)
|
185
187
|
.padStart(11, "0"),
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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
|
+
}),
|
191
197
|
info = {
|
192
|
-
file:
|
198
|
+
file: name,
|
193
199
|
users: usersToPushTo,
|
194
200
|
minLength: countHackmudCharacters(minifiedCode),
|
195
201
|
error: void 0
|
package/syncMacros.js
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
|
2
|
+
import { readFile, stat, writeFile } from "fs/promises"
|
2
3
|
import { extname, basename, resolve } from "path"
|
3
4
|
const syncMacros = async hackmudPath => {
|
4
|
-
const files = await
|
5
|
+
const files = await readDirectoryWithStats(hackmudPath),
|
5
6
|
macros = new Map(),
|
6
7
|
users = []
|
7
8
|
await Promise.all(
|
8
9
|
files.map(async file => {
|
9
|
-
if (file.isFile())
|
10
|
+
if (file.stats.isFile())
|
10
11
|
switch (extname(file.name)) {
|
11
12
|
case ".macros":
|
12
13
|
{
|