hackmud-script-manager 0.20.4-03d5600 → 0.20.4-0dd1d9b

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -13,7 +13,8 @@ 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-03d5600",
16
+ const version = "0.20.4-0dd1d9b",
17
+ formatOption = name => colourN(`-${1 == name.length ? "" : "-"}${name}`),
17
18
  options = new Map(),
18
19
  commands = [],
19
20
  userColours = new Cache(user => {
@@ -46,6 +47,7 @@ const pushModule = import("../push.js"),
46
47
  colourB = chalk.rgb(202, 202, 202),
47
48
  colourC = chalk.rgb(155, 155, 155),
48
49
  colourD = chalk.rgb(255, 0, 0),
50
+ colourF = chalk.rgb(255, 128, 0),
49
51
  colourJ = chalk.rgb(255, 244, 4),
50
52
  colourK = chalk.rgb(243, 249, 152),
51
53
  colourL = chalk.rgb(30, 255, 0),
@@ -54,6 +56,12 @@ const pushModule = import("../push.js"),
54
56
  colourS = chalk.rgb(122, 178, 244),
55
57
  colourV = chalk.rgb(255, 0, 236),
56
58
  colourW = chalk.rgb(255, 150, 224)
59
+ process.version.startsWith("v21.") &&
60
+ console.warn(
61
+ colourF(
62
+ "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"
63
+ )
64
+ )
57
65
  if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
58
66
  console.log(version)
59
67
  process.exit()
@@ -76,7 +84,7 @@ switch (commands[0]) {
76
84
  noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
77
85
  if (noMinifyOption && noMinifyIncompatibleOption) {
78
86
  logError(
79
- `Options ${colourN(noMinifyOption.name)} and ${colourN(noMinifyIncompatibleOption.name)} are incompatible\n`
87
+ `Options ${formatOption(noMinifyOption.name)} and ${formatOption(noMinifyIncompatibleOption.name)} are incompatible\n`
80
88
  )
81
89
  logHelp()
82
90
  process.exit(1)
@@ -99,6 +107,7 @@ switch (commands[0]) {
99
107
  )
100
108
  process.exit(1)
101
109
  }
110
+ complainAboutUnrecognisedOptions()
102
111
  const { processScript } = await processScriptModule,
103
112
  fileBaseName = basename(target, fileExtension),
104
113
  fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
@@ -171,15 +180,15 @@ switch (commands[0]) {
171
180
  }
172
181
  } else scripts.push("*.*")
173
182
  if ("push" == commands[0]) {
174
- const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } =
175
- await pushModule,
176
- infos = await push(sourcePath, hackmudPath, {
177
- scripts,
178
- onPush: info => logInfo(info, hackmudPath),
179
- minify: noMinifyOption && !noMinifyOption.value,
180
- mangleNames: mangleNamesOption?.value,
181
- forceQuineCheats: forceQuineCheatsOption?.value
182
- })
183
+ const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } = await pushModule
184
+ complainAboutUnrecognisedOptions()
185
+ const infos = await push(sourcePath, hackmudPath, {
186
+ scripts,
187
+ onPush: info => logInfo(info, hackmudPath),
188
+ minify: noMinifyOption && !noMinifyOption.value,
189
+ mangleNames: mangleNamesOption?.value,
190
+ forceQuineCheats: forceQuineCheatsOption?.value
191
+ })
183
192
  if (infos instanceof Error) {
184
193
  logError(infos.message)
185
194
  if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
@@ -193,12 +202,13 @@ switch (commands[0]) {
193
202
  } else infos.length || logError("Could not find any scripts to push")
194
203
  } else {
195
204
  const typeDeclarationPathOption = popOption(
196
- "type-declaration-path",
197
- "type-declaration",
198
- "dts",
199
- "gen-types"
200
- ),
201
- { watch } = await watchModule
205
+ "type-declaration-path",
206
+ "type-declaration",
207
+ "dts",
208
+ "gen-types"
209
+ )
210
+ complainAboutUnrecognisedOptions()
211
+ const { watch } = await watchModule
202
212
  watch(sourcePath, hackmudPath, {
203
213
  scripts,
204
214
  onPush: info => logInfo(info, hackmudPath),
@@ -222,6 +232,7 @@ switch (commands[0]) {
222
232
  logHelp()
223
233
  process.exit(1)
224
234
  }
235
+ complainAboutUnrecognisedOptions()
225
236
  const sourcePath = commands[2] || "."
226
237
  await pull(sourcePath, hackmudPath, script).catch(error => {
227
238
  console.error(error)
@@ -231,8 +242,9 @@ switch (commands[0]) {
231
242
  break
232
243
  case "sync-macros":
233
244
  {
234
- const hackmudPath = getHackmudPath(),
235
- { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
245
+ const hackmudPath = getHackmudPath()
246
+ complainAboutUnrecognisedOptions()
247
+ const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
236
248
  log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
237
249
  }
238
250
  break
@@ -248,12 +260,13 @@ switch (commands[0]) {
248
260
  logHelp()
249
261
  process.exit(1)
250
262
  }
263
+ complainAboutUnrecognisedOptions()
251
264
  const sourcePath = resolve(target),
252
265
  outputPath = commands[2] || "./player.d.ts",
253
266
  typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
254
267
  let typeDeclarationPath = resolve(outputPath)
255
268
  await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
256
- assert(error instanceof Error, "src/bin/hsm.ts:321:35")
269
+ assert(error instanceof Error, "src/bin/hsm.ts:343:35")
257
270
  if ("EISDIR" != error.code) throw error
258
271
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
259
272
  return writeFile(typeDeclarationPath, typeDeclaration)
@@ -352,7 +365,7 @@ function getHackmudPath() {
352
365
  }
353
366
  function assertOptionIsBoolean(option) {
354
367
  if ("boolean" != typeof option.value) {
355
- logError(`The value for ${colourN(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
368
+ logError(`The value for ${formatOption(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
356
369
  logHelp()
357
370
  process.exit(1)
358
371
  }
@@ -360,9 +373,7 @@ function assertOptionIsBoolean(option) {
360
373
  function popOption(...names) {
361
374
  const presentOptionNames = names.filter(name => options.has(name))
362
375
  if (!presentOptionNames.length) return
363
- const presentOptionNamesWithDashDash = presentOptionNames.map(name =>
364
- colourN(`-${1 == name.length ? "" : "-"}${name}`)
365
- )
376
+ const presentOptionNamesWithDashDash = presentOptionNames.map(formatOption)
366
377
  if (presentOptionNames.length > 1) {
367
378
  logError(
368
379
  `The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
@@ -373,3 +384,11 @@ function popOption(...names) {
373
384
  options.delete(presentOptionNames[0])
374
385
  return { name: presentOptionNamesWithDashDash[0], value }
375
386
  }
387
+ function complainAboutUnrecognisedOptions() {
388
+ if (options.size) {
389
+ logError(
390
+ `Unrecognised option${options.size > 1 ? "s" : ""}: ${[...options.keys()].map(formatOption).join(", ")}`
391
+ )
392
+ process.exit(1)
393
+ }
394
+ }
package/env.d.ts CHANGED
@@ -3,13 +3,7 @@ type ScriptSuccess<T = object> = { ok: true } & T
3
3
  type ScriptFailure = { ok: false, msg?: string }
4
4
  type ScriptResponse<T = object> = ScriptSuccess<T> | ScriptFailure
5
5
  type ErrorScripts = Record<string, () => ScriptFailure>
6
-
7
- type AllOptional<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? true : false }[keyof T]
8
-
9
- type Scriptor<Args = unknown, Ret = unknown> = {
10
- name: string
11
- call: AllOptional<Args> extends true ? (args?: Args) => Ret : (args: Args) => Ret
12
- }
6
+ type Scriptor<TArgs extends any[] = any[]> = { name: string, call: (...args: TArgs) => unknown }
13
7
 
14
8
  type Subscripts = Record<string, Record<string, (...args: any) => any>> & {
15
9
  accts: ErrorScripts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.20.4-03d5600",
3
+ "version": "0.20.4-0dd1d9b",
4
4
  "description": "Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.",
5
5
  "keywords": [
6
6
  "api",
@@ -204,6 +204,7 @@ async function processScript(
204
204
  const bundle = await rollup({
205
205
  input: filePathResolved,
206
206
  plugins: [
207
+ rollupPluginJSON({ preferConst: !0 }),
207
208
  {
208
209
  name: "hackmud-script-manager",
209
210
  async transform(code, id) {
@@ -227,8 +228,7 @@ async function processScript(
227
228
  },
228
229
  babel({ babelHelpers: "bundled", plugins, configFile: !1, extensions: supportedExtensions }),
229
230
  rollupPluginCommonJS(),
230
- rollupPluginNodeResolve({ extensions: supportedExtensions }),
231
- rollupPluginJSON()
231
+ rollupPluginNodeResolve({ extensions: supportedExtensions })
232
232
  ],
233
233
  treeshake: { moduleSideEffects: !1 }
234
234
  }),
@@ -98,8 +98,10 @@ async function preprocess(code, { uniqueId = "00000000000" } = {}) {
98
98
  t.stringLiteral(resolve("proxy-polyfill/src/proxy.js", import.meta.url).slice(7))
99
99
  )
100
100
  )
101
- return 1 == program.node.body.length && "FunctionDeclaration" == program.node.body[0].type ?
102
- { code: "export default " + generate(file).code }
103
- : { code: generate(file).code }
101
+ if (1 == program.node.body.length && "FunctionDeclaration" == program.node.body[0].type)
102
+ throw Error(
103
+ "Scripts that only contain a single function declaration are no longer supported.\nPrefix the function declaration with `export default`."
104
+ )
105
+ return { code: generate(file).code }
104
106
  }
105
107
  export { preprocess }
@@ -22,9 +22,7 @@ const { default: traverse } = babelTraverse,
22
22
  "BigInt"
23
23
  ]
24
24
  function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scriptName, seclevel = 4 }) {
25
- const topFunctionName = `_${uniqueId}_SCRIPT_`,
26
- exports = new Map(),
27
- liveExports = new Map()
25
+ const topFunctionName = `_${uniqueId}_SCRIPT_`
28
26
  let program
29
27
  traverse(file, {
30
28
  Program(path) {
@@ -70,30 +68,30 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
70
68
  const referencePath = FunctionReferencePaths[0]
71
69
  assert(
72
70
  "MemberExpression" == referencePath.parent.type,
73
- "src/processScript/transform.ts:105:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
71
+ "src/processScript/transform.ts:103:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
74
72
  )
75
73
  assert(
76
74
  "Identifier" == referencePath.parent.property.type,
77
- "src/processScript/transform.ts:110:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
75
+ "src/processScript/transform.ts:108:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
78
76
  )
79
77
  assert(
80
78
  "prototype" == referencePath.parent.property.name,
81
- "src/processScript/transform.ts:115:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
79
+ "src/processScript/transform.ts:113:8 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
82
80
  )
83
81
  referencePath.parentPath.replaceWith(createGetFunctionPrototypeNode())
84
82
  } else {
85
83
  for (const referencePath of FunctionReferencePaths) {
86
84
  assert(
87
85
  "MemberExpression" == referencePath.parent.type,
88
- "src/processScript/transform.ts:123:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
86
+ "src/processScript/transform.ts:121:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
89
87
  )
90
88
  assert(
91
89
  "Identifier" == referencePath.parent.property.type,
92
- "src/processScript/transform.ts:128:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
90
+ "src/processScript/transform.ts:126:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
93
91
  )
94
92
  assert(
95
93
  "prototype" == referencePath.parent.property.name,
96
- "src/processScript/transform.ts:133:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
94
+ "src/processScript/transform.ts:131:9 `Function` isn't available in hackmud, only `Function.prototype` is accessible"
97
95
  )
98
96
  functionDotPrototypeIsReferencedMultipleTimes = !0
99
97
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_FUNCTION_DOT_PROTOTYPE_`))
@@ -129,12 +127,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
129
127
  const neededDbMethodLets = new Set()
130
128
  if (program.scope.hasGlobal("$db"))
131
129
  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")
130
+ assert("MemberExpression" == referencePath.parentPath.node.type, "src/processScript/transform.ts:185:69")
131
+ assert("Identifier" == referencePath.parentPath.node.property.type, "src/processScript/transform.ts:186:72")
134
132
  const databaseOpMethodName = referencePath.parentPath.node.property.name
135
133
  assert(
136
134
  validDBMethods.includes(databaseOpMethodName),
137
- `src/processScript/transform.ts:194:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
135
+ `src/processScript/transform.ts:192:8 invalid db method "${databaseOpMethodName}", valid db methods are "${validDBMethods.join('", "')}"`
138
136
  )
139
137
  if ("CallExpression" == referencePath.parentPath.parentPath?.type)
140
138
  referencePath.parentPath.replaceWith(t.identifier(`$${uniqueId}$DB$${databaseOpMethodName}$`))
@@ -168,7 +166,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
168
166
  if (program.scope.hasGlobal("Object"))
169
167
  for (const referencePath of getReferencePathsToGlobal("Object", program))
170
168
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
171
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:243:64")
169
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:241:64")
172
170
  if ("getPrototypeOf" == referencePath.parent.property.name) {
173
171
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_GET_PROTOTYPE_OF_`))
174
172
  needGetPrototypeOf = !0
@@ -178,7 +176,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
178
176
  if (program.scope.hasGlobal("console"))
179
177
  for (const referencePath of getReferencePathsToGlobal("console", program))
180
178
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
181
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:258:64")
179
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
182
180
  referencePath.parentPath.replaceWith(
183
181
  t.identifier(`_${uniqueId}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
184
182
  )
@@ -186,19 +184,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
186
184
  }
187
185
  const lastStatement = program.node.body.at(-1)
188
186
  let exportDefaultName
189
- assert(lastStatement, "src/processScript/transform.ts:272:27 program is empty")
187
+ assert(lastStatement, "src/processScript/transform.ts:270:27 program is empty")
190
188
  if ("ExportNamedDeclaration" == lastStatement.type) {
191
189
  program.node.body.pop()
192
190
  for (const specifier of lastStatement.specifiers) {
193
191
  assert(
194
192
  "ExportSpecifier" == specifier.type,
195
- `src/processScript/transform.ts:278:51 ${specifier.type} is currently unsupported`
193
+ `src/processScript/transform.ts:276:51 ${specifier.type} is currently unsupported`
196
194
  )
197
- const exportedName =
198
- "Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value
199
- "default" == exportedName ?
200
- (exportDefaultName = specifier.local.name)
201
- : exports.set(specifier.local.name, exportedName)
195
+ if (
196
+ "default" !=
197
+ ("Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value)
198
+ )
199
+ throw Error("Only default exports are supported")
200
+ exportDefaultName = specifier.local.name
202
201
  }
203
202
  }
204
203
  const globalBlock = t.blockStatement([])
@@ -224,10 +223,6 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
224
223
  t.returnStatement(t.callExpression(t.identifier(exportDefaultName), []))
225
224
  ])
226
225
  ))
227
- if ("const" != statement.kind && exports.has(identifierName)) {
228
- liveExports.set(identifierName, exports.get(identifierName))
229
- exports.delete(identifierName)
230
- }
231
226
  globalBlock.body.push(
232
227
  t.variableDeclaration("let", [t.variableDeclarator(t.identifier(identifierName))])
233
228
  )
@@ -292,34 +287,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
292
287
  }
293
288
  program.node.body = [mainFunction]
294
289
  if (globalBlock.body.length) {
295
- ;(exports.size || liveExports.size) &&
296
- mainFunction.body.body.push(
297
- t.returnStatement(
298
- t.objectExpression([
299
- ...[...exports].map(([local, exported]) =>
300
- t.objectProperty(t.identifier(exported), t.identifier(local))
301
- ),
302
- ...[...liveExports].map(([local, exported]) =>
303
- t.objectMethod(
304
- "get",
305
- t.identifier(exported),
306
- [],
307
- t.blockStatement([t.returnStatement(t.identifier(local))])
308
- )
309
- )
310
- ])
311
- )
312
- )
313
290
  program.scope.crawl()
314
291
  const globalBlockVariables = new Set()
315
292
  let hoistedGlobalBlockFunctions = 0
316
293
  for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
317
294
  if ("VariableDeclaration" == globalBlockStatement.type) {
318
- assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:412:59")
295
+ assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:390:59")
319
296
  const declarator = globalBlockStatement.declarations[0]
320
297
  assert(
321
298
  "Identifier" == declarator.id.type,
322
- `src/processScript/transform.ts:416:51 declarator.id.type was "${declarator.id.type}"`
299
+ `src/processScript/transform.ts:394:51 declarator.id.type was "${declarator.id.type}"`
323
300
  )
324
301
  program.scope.crawl()
325
302
  if (program.scope.hasGlobal(declarator.id.name)) {
@@ -334,9 +311,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
334
311
  Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
335
312
  ) {
336
313
  const binding = program.scope.getBinding(declarator.id.name)
337
- assert(binding, "src/processScript/transform.ts:435:23")
314
+ assert(binding, "src/processScript/transform.ts:413:23")
338
315
  for (const referencePath of binding.referencePaths) {
339
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:438:56")
316
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:416:56")
340
317
  referencePath.replaceWith(
341
318
  t.memberExpression(
342
319
  t.identifier(`_${uniqueId}_G_`),
@@ -384,16 +361,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
384
361
  } else globalBlockVariables.add(declarator.id.name)
385
362
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
386
363
  program.scope.crawl()
387
- assert(globalBlockStatement.id, "src/processScript/transform.ts:495:37")
364
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:473:37")
388
365
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
389
366
  globalBlock.body.splice(globalBlockIndex, 1)
390
367
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
391
368
  [globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
392
369
  program.scope.crawl()
393
370
  const binding = program.scope.getBinding(globalBlockStatement.id.name)
394
- assert(binding, "src/processScript/transform.ts:507:22")
371
+ assert(binding, "src/processScript/transform.ts:485:22")
395
372
  for (const referencePath of binding.referencePaths) {
396
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:510:55")
373
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:488:55")
397
374
  referencePath.replaceWith(
398
375
  t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(referencePath.node.name))
399
376
  )
@@ -423,11 +400,6 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
423
400
  needG = !0
424
401
  }
425
402
  }
426
- if (program.scope.hasGlobal("_EXPORTS"))
427
- for (const referencePath of getReferencePathsToGlobal("_EXPORTS", program))
428
- referencePath.replaceWith(
429
- t.arrayExpression([...exports.keys(), ...liveExports.keys()].map(name => t.stringLiteral(name)))
430
- )
431
403
  globalBlock.body.length &&
432
404
  mainFunction.body.body.splice(
433
405
  hoistedGlobalBlockFunctions,
@@ -565,7 +537,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
565
537
  }
566
538
  },
567
539
  ClassBody({ node: classBody, scope, parent }) {
568
- assert(t.isClass(parent), "src/processScript/transform.ts:688:30")
540
+ assert(t.isClass(parent), "src/processScript/transform.ts:658:30")
569
541
  let thisIsReferenced = !1
570
542
  for (const classMethod of classBody.body) {
571
543
  if ("ClassMethod" != classMethod.type) continue
@@ -657,39 +629,31 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
657
629
  })
658
630
  return { file, seclevel }
659
631
  function createGetFunctionPrototypeNode() {
660
- for (const globalFunction of globalFunctionsUnder7Characters)
661
- if (!program.scope.hasOwnBinding(globalFunction))
662
- return t.memberExpression(
663
- t.memberExpression(t.identifier(globalFunction), t.identifier("constructor")),
664
- t.identifier("prototype")
665
- )
632
+ const name = globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
666
633
  return t.memberExpression(
667
- t.memberExpression(
668
- t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
669
- t.identifier("constructor")
670
- ),
671
- t.identifier("prototype")
634
+ name ? t.identifier(name) : t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
635
+ t.identifier("__proto__")
672
636
  )
673
637
  }
674
638
  function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
675
639
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
676
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:804:60")
640
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:764:60")
677
641
  assert("Identifier" == referencePath.parent.property.type)
678
642
  assert(
679
643
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
680
- "src/processScript/transform.ts:806:81"
644
+ "src/processScript/transform.ts:766:81"
681
645
  )
682
646
  assert(
683
647
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
684
- "src/processScript/transform.ts:807:83"
648
+ "src/processScript/transform.ts:767:83"
685
649
  )
686
650
  assert(
687
651
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parent.property.name),
688
- `src/processScript/transform.ts:811:8 invalid user "${referencePath.parent.property.name}" in subscript`
652
+ `src/processScript/transform.ts:771:8 invalid user "${referencePath.parent.property.name}" in subscript`
689
653
  )
690
654
  assert(
691
655
  /^[_a-z][\d_a-z]{0,24}$/.test(referencePath.parentPath.parentPath.node.property.name),
692
- `src/processScript/transform.ts:816:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
656
+ `src/processScript/transform.ts:776:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
693
657
  )
694
658
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
695
659
  referencePath.parentPath.parentPath.replaceWith(
package/watch.js CHANGED
@@ -4,7 +4,7 @@ import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
4
4
  import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
5
5
  import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
6
6
  import { watch as watch$1 } from "chokidar"
7
- import { readFile, writeFile } from "fs/promises"
7
+ import { stat, readFile, writeFile } from "fs/promises"
8
8
  import { extname, basename, resolve } from "path"
9
9
  import { supportedExtensions } from "./constants.js"
10
10
  import { generateTypeDeclaration } from "./generateTypeDeclaration.js"
@@ -59,6 +59,7 @@ async function watch(
59
59
  } = {}
60
60
  ) {
61
61
  if (!scripts.length) throw Error("scripts option was an empty array")
62
+ if (!(await stat(sourceDirectory)).isDirectory()) throw Error("Target folder must be a folder")
62
63
  const scriptNamesToUsers = new Cache(_scriptName => new Set()),
63
64
  wildScriptUsers = new Set(),
64
65
  wildUserScripts = new Set()
@@ -136,7 +137,7 @@ async function watch(
136
137
  forceQuineCheats
137
138
  }))
138
139
  } catch (error) {
139
- assert(error instanceof Error, "src/watch.ts:141:36")
140
+ assert(error instanceof Error, "src/watch.ts:146:36")
140
141
  onPush?.({ path, users: [], characterCount: 0, error })
141
142
  return
142
143
  }
@@ -181,7 +182,7 @@ async function watch(
181
182
  forceQuineCheats
182
183
  }))
183
184
  } catch (error) {
184
- assert(error instanceof Error, "src/watch.ts:177:35")
185
+ assert(error instanceof Error, "src/watch.ts:182:35")
185
186
  onPush?.({ path, users: [], characterCount: 0, error })
186
187
  return
187
188
  }
@@ -196,7 +197,7 @@ async function watch(
196
197
  try {
197
198
  await writeFile(typeDeclarationPath, typeDeclaration)
198
199
  } catch (error) {
199
- assert(error instanceof Error, "src/watch.ts:210:35")
200
+ assert(error instanceof Error, "src/watch.ts:215:35")
200
201
  if ("EISDIR" != error.code) throw error
201
202
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
202
203
  await writeFile(typeDeclarationPath, typeDeclaration)