hackmud-script-manager 0.20.3 → 0.20.4-03d5600

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.
@@ -1,5 +1,6 @@
1
1
  import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
2
2
  import { basename, resolve } from "path"
3
+ import * as PathPosix from "path/posix"
3
4
  async function generateTypeDeclaration(sourceDirectory, hackmudPath) {
4
5
  const users = new Set()
5
6
  if (hackmudPath)
@@ -29,7 +30,7 @@ async function generateTypeDeclaration(sourceDirectory, hackmudPath) {
29
30
  }
30
31
  })
31
32
  )
32
- sourceDirectory = resolve(sourceDirectory)
33
+ sourceDirectory = PathPosix.resolve(sourceDirectory)
33
34
  let o = ""
34
35
  for (const script of wildScripts) o += `type $${script}$ = typeof import("${sourceDirectory}/${script}").default\n`
35
36
  o += "\n"
package/index.js CHANGED
@@ -7,6 +7,7 @@ export { syncMacros } from "./syncMacros.js"
7
7
  export { watch } from "./watch.js"
8
8
  import "@samual/lib/readDirectoryWithStats"
9
9
  import "path"
10
+ import "path/posix"
10
11
  import "@babel/generator"
11
12
  import "@babel/parser"
12
13
  import "@babel/plugin-proposal-decorators"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.20.3",
3
+ "version": "0.20.4-03d5600",
4
4
  "description": "Script manager for game hackmud, with minification, TypeScript support, and player script type definition generation.",
5
5
  "keywords": [
6
6
  "api",
@@ -20,7 +20,11 @@
20
20
  "homepage": "https://github.com/samualtnorman/hackmud-script-manager#readme",
21
21
  "bugs": "https://github.com/samualtnorman/hackmud-script-manager/issues",
22
22
  "license": "MIT",
23
- "author": "Samual Norman",
23
+ "author": "Samual Norman <me@samual.uk> (https://samual.uk/)",
24
+ "contributors": [
25
+ "Daniel Swann (https://github.com/danswann)",
26
+ "Longboyy"
27
+ ],
24
28
  "main": "index.js",
25
29
  "repository": {
26
30
  "type": "git",
@@ -323,7 +323,7 @@ async function processScript(
323
323
  trailingComma: "none"
324
324
  })
325
325
  }
326
- code = postprocess(code, seclevel, uniqueId)
326
+ code = postprocess(code, uniqueId)
327
327
  if (includesIllegalString(code))
328
328
  throw Error(
329
329
  'you found a weird edge case where I wasn\'t able to replace illegal strings like "SC$", please report thx'
@@ -43,15 +43,6 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
43
43
  )
44
44
  }
45
45
  }
46
- const hashGReferencePaths = getReferencePathsToGlobal(`$${uniqueId}$GLOBAL$`, program)
47
- if (hashGReferencePaths.length > 3) {
48
- for (const path of hashGReferencePaths) path.replaceWith(t.identifier(`_${uniqueId}_G_`))
49
- mainFunctionPath.node.body.body.unshift(
50
- t.variableDeclaration("let", [
51
- t.variableDeclarator(t.identifier(`_${uniqueId}_G_`), t.identifier(`$${uniqueId}$GLOBAL$`))
52
- ])
53
- )
54
- }
55
46
  const jsonValues = []
56
47
  let scriptBeforeJSONValueReplacement,
57
48
  comment,
@@ -61,7 +52,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
61
52
  traverse(fileBeforeJSONValueReplacement, {
62
53
  MemberExpression({ node: memberExpression }) {
63
54
  if (!memberExpression.computed) {
64
- assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:127:60")
55
+ assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:115:60")
65
56
  if ("prototype" == memberExpression.property.name) {
66
57
  memberExpression.computed = !0
67
58
  memberExpression.property = t.identifier(`_${uniqueId}_PROTOTYPE_PROPERTY_`)
@@ -136,7 +127,8 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
136
127
  const promises = []
137
128
  traverse(file, {
138
129
  FunctionDeclaration(path) {
139
- path.traverse({
130
+ const body = path.get("body")
131
+ body.traverse({
140
132
  Function(path) {
141
133
  "CallExpression" != path.parent.type && "callee" != path.parentKey && path.skip()
142
134
  },
@@ -152,7 +144,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
152
144
  path.replaceWith(t.identifier(`_${uniqueId}_JSON_VALUE_${jsonValues.push(o) - 1}_`))
153
145
  }
154
146
  })
155
- path.traverse({
147
+ body.traverse({
156
148
  TemplateLiteral(path) {
157
149
  if ("TaggedTemplateExpression" == path.parent.type) return
158
150
  const templateLiteral = path.node
@@ -172,7 +164,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
172
164
  },
173
165
  MemberExpression({ node: memberExpression }) {
174
166
  if (!memberExpression.computed) {
175
- assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:259:62")
167
+ assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:249:62")
176
168
  if (!(memberExpression.property.name.length < 3)) {
177
169
  memberExpression.computed = !0
178
170
  memberExpression.property = t.stringLiteral(memberExpression.property.name)
@@ -220,8 +212,10 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
220
212
  )
221
213
  },
222
214
  StringLiteral(path) {
223
- path.node.value = replaceUnsafeStrings(uniqueId, path.node.value)
224
- if (JSON.stringify(path.node.value).includes("\\u00") || path.toString().length < 4) return
215
+ if (JSON.stringify(path.node.value).includes("\\u00") || path.toString().length < 4) {
216
+ path.node.value = replaceUnsafeStrings(uniqueId, path.node.value)
217
+ return
218
+ }
225
219
  "key" == path.parentKey && "ObjectProperty" == path.parent.type && (path.parent.computed = !0)
226
220
  let jsonValueIndex = jsonValues.indexOf(path.node.value)
227
221
  ;-1 == jsonValueIndex && (jsonValueIndex += jsonValues.push(path.node.value))
@@ -244,7 +238,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
244
238
  })
245
239
  await Promise.all(promises)
246
240
  const functionDeclaration = file.program.body[0]
247
- assert("FunctionDeclaration" == functionDeclaration.type, "src/processScript/minify.ts:363:61")
241
+ assert("FunctionDeclaration" == functionDeclaration.type, "src/processScript/minify.ts:354:61")
248
242
  if (jsonValues.length) {
249
243
  hasComment = !0
250
244
  if (1 == jsonValues.length)
@@ -256,7 +250,10 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
256
250
  t.memberExpression(
257
251
  t.taggedTemplateExpression(
258
252
  t.memberExpression(
259
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
253
+ t.callExpression(
254
+ t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`),
255
+ []
256
+ ),
260
257
  t.identifier("split")
261
258
  ),
262
259
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -280,7 +277,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
280
277
  t.memberExpression(
281
278
  t.taggedTemplateExpression(
282
279
  t.memberExpression(
283
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
280
+ t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
284
281
  t.identifier("split")
285
282
  ),
286
283
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -305,7 +302,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
305
302
  t.memberExpression(
306
303
  t.taggedTemplateExpression(
307
304
  t.memberExpression(
308
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
305
+ t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
309
306
  t.identifier("split")
310
307
  ),
311
308
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -361,7 +358,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
361
358
  )
362
359
  }
363
360
  if (1 == forceQuineCheats) return code
364
- assert(scriptBeforeJSONValueReplacement, "src/processScript/minify.ts:494:43")
361
+ assert(scriptBeforeJSONValueReplacement, "src/processScript/minify.ts:485:43")
365
362
  return (
366
363
  countHackmudCharacters(scriptBeforeJSONValueReplacement) <=
367
364
  countHackmudCharacters(code) + Number(hasComment)
@@ -377,7 +374,7 @@ function parseObjectExpression(node, o) {
377
374
  "Identifier" == property.key.type ||
378
375
  "NumericLiteral" == property.key.type ||
379
376
  "StringLiteral" == property.key.type,
380
- "src/processScript/minify.ts:516:4"
377
+ "src/processScript/minify.ts:507:4"
381
378
  )
382
379
  if ("ArrayExpression" == property.value.type) {
383
380
  const childArray = []
@@ -1 +1 @@
1
- export declare const postprocess: (code: string, seclevel: number, uniqueId: string) => string;
1
+ export declare const postprocess: (code: string, uniqueId: string) => string;
@@ -1,12 +1,12 @@
1
- const postprocess = (code, seclevel, uniqueId) =>
1
+ const postprocess = (code, uniqueId) =>
2
2
  code
3
- .replace(/^function\s*\w+\(/, "function(")
3
+ .replace(/^function\s*[\w$]+\(/, "function(")
4
4
  .replace(RegExp(`\\$${uniqueId}\\$\\\\(?:\\\\)?\\$SC_DOLLAR\\$`, "g"), "S\\C$")
5
5
  .replace(RegExp(`\\$${uniqueId}\\$\\\\(?:\\\\)?\\$DB_DOLLAR\\$`, "g"), "D\\B$")
6
6
  .replace(RegExp(`\\$${uniqueId}\\$\\\\(?:\\\\)?\\$D\\$`, "g"), "_\\_D_S")
7
7
  .replace(RegExp(`\\$${uniqueId}\\$\\\\(?:\\\\)?\\$FMCL\\$`, "g"), "_\\_FMCL_")
8
8
  .replace(RegExp(`\\$${uniqueId}\\$\\\\(?:\\\\)?\\$G\\$`, "g"), "_\\_G_")
9
- .replace(RegExp(`\\$${uniqueId}\\$SUBSCRIPT\\$(\\w+)\\$(\\w+)\\$`, "g"), `#${"nlmhf"[seclevel]}s.$1.$2`)
9
+ .replace(RegExp(`\\$${uniqueId}\\$(\\d)\\$SUBSCRIPT\\$(\\w+)\\$(\\w+)\\$`, "g"), "#$1s.$2.$3")
10
10
  .replace(RegExp(`\\$${uniqueId}\\$DEBUG\\$`, "g"), "#D")
11
11
  .replace(RegExp(`\\$${uniqueId}\\$FMCL\\$`, "g"), "#FMCL")
12
12
  .replace(RegExp(`\\$${uniqueId}\\$GLOBAL\\$`, "g"), "#G")
@@ -101,29 +101,29 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
101
101
  functionDotPrototypeIsReferencedMultipleTimes = !0
102
102
  }
103
103
  }
104
- const neededSubscriptLets = new Set()
104
+ const neededSubscriptLets = new Map()
105
105
  let detectedSeclevel = 4
106
106
  for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
107
- program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
107
+ program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName, 4)
108
108
  for (const fakeSubscriptObjectName of ["$hs", "$3s"])
109
109
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
110
110
  detectedSeclevel = 3
111
- processFakeSubscriptObject(fakeSubscriptObjectName)
111
+ processFakeSubscriptObject(fakeSubscriptObjectName, 3)
112
112
  }
113
113
  for (const fakeSubscriptObjectName of ["$ms", "$2s"])
114
114
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
115
115
  detectedSeclevel = 2
116
- processFakeSubscriptObject(fakeSubscriptObjectName)
116
+ processFakeSubscriptObject(fakeSubscriptObjectName, 2)
117
117
  }
118
118
  for (const fakeSubscriptObjectName of ["$ls", "$1s"])
119
119
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
120
120
  detectedSeclevel = 1
121
- processFakeSubscriptObject(fakeSubscriptObjectName)
121
+ processFakeSubscriptObject(fakeSubscriptObjectName, 1)
122
122
  }
123
123
  for (const fakeSubscriptObjectName of ["$ns", "$0s"])
124
124
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
125
125
  detectedSeclevel = 0
126
- processFakeSubscriptObject(fakeSubscriptObjectName)
126
+ processFakeSubscriptObject(fakeSubscriptObjectName, 0)
127
127
  }
128
128
  seclevel = Math.min(seclevel, detectedSeclevel)
129
129
  const neededDbMethodLets = new Set()
@@ -157,9 +157,10 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
157
157
  if (program.scope.hasGlobal("$FMCL"))
158
158
  for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
159
159
  referencePath.replaceWith(t.identifier(`$${uniqueId}$FMCL$`))
160
- if (program.scope.hasGlobal("$G"))
160
+ let needG = program.scope.hasGlobal("$G")
161
+ if (needG)
161
162
  for (const referencePath of getReferencePathsToGlobal("$G", program))
162
- referencePath.replaceWith(t.identifier(`$${uniqueId}$GLOBAL$`))
163
+ referencePath.replaceWith(t.identifier(`_${uniqueId}_G_`))
163
164
  if (program.scope.hasGlobal("_SECLEVEL"))
164
165
  for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
165
166
  referencePath.replaceWith(t.numericLiteral(seclevel))
@@ -167,7 +168,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
167
168
  if (program.scope.hasGlobal("Object"))
168
169
  for (const referencePath of getReferencePathsToGlobal("Object", program))
169
170
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
170
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:241:64")
171
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:243:64")
171
172
  if ("getPrototypeOf" == referencePath.parent.property.name) {
172
173
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_GET_PROTOTYPE_OF_`))
173
174
  needGetPrototypeOf = !0
@@ -177,7 +178,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
177
178
  if (program.scope.hasGlobal("console"))
178
179
  for (const referencePath of getReferencePathsToGlobal("console", program))
179
180
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
180
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
181
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:258:64")
181
182
  referencePath.parentPath.replaceWith(
182
183
  t.identifier(`_${uniqueId}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
183
184
  )
@@ -185,13 +186,13 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
185
186
  }
186
187
  const lastStatement = program.node.body.at(-1)
187
188
  let exportDefaultName
188
- assert(lastStatement, "src/processScript/transform.ts:270:27 program is empty")
189
+ assert(lastStatement, "src/processScript/transform.ts:272:27 program is empty")
189
190
  if ("ExportNamedDeclaration" == lastStatement.type) {
190
191
  program.node.body.pop()
191
192
  for (const specifier of lastStatement.specifiers) {
192
193
  assert(
193
194
  "ExportSpecifier" == specifier.type,
194
- `src/processScript/transform.ts:276:51 ${specifier.type} is currently unsupported`
195
+ `src/processScript/transform.ts:278:51 ${specifier.type} is currently unsupported`
195
196
  )
196
197
  const exportedName =
197
198
  "Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value
@@ -314,11 +315,11 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
314
315
  let hoistedGlobalBlockFunctions = 0
315
316
  for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
316
317
  if ("VariableDeclaration" == globalBlockStatement.type) {
317
- assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:410:59")
318
+ assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:412:59")
318
319
  const declarator = globalBlockStatement.declarations[0]
319
320
  assert(
320
321
  "Identifier" == declarator.id.type,
321
- `src/processScript/transform.ts:414:51 declarator.id.type was "${declarator.id.type}"`
322
+ `src/processScript/transform.ts:416:51 declarator.id.type was "${declarator.id.type}"`
322
323
  )
323
324
  program.scope.crawl()
324
325
  if (program.scope.hasGlobal(declarator.id.name)) {
@@ -333,15 +334,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
333
334
  Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
334
335
  ) {
335
336
  const binding = program.scope.getBinding(declarator.id.name)
336
- assert(binding, "src/processScript/transform.ts:433:23")
337
+ assert(binding, "src/processScript/transform.ts:435:23")
337
338
  for (const referencePath of binding.referencePaths) {
338
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:436:56")
339
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:438:56")
339
340
  referencePath.replaceWith(
340
341
  t.memberExpression(
341
- t.identifier(`$${uniqueId}$GLOBAL$`),
342
+ t.identifier(`_${uniqueId}_G_`),
342
343
  t.identifier(referencePath.node.name)
343
344
  )
344
345
  )
346
+ needG = !0
345
347
  }
346
348
  for (const referencePath of binding.constantViolations)
347
349
  if ("AssignmentExpression" == referencePath.node.type)
@@ -350,12 +352,13 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
350
352
  clearObject(node)
351
353
  Object.assign(
352
354
  node,
353
- t.memberExpression(t.identifier(`$${uniqueId}$GLOBAL$`), t.identifier(name))
355
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(name))
354
356
  )
357
+ needG = !0
355
358
  }
356
359
  globalBlockPath.remove()
357
360
  globalBlockStatementPath.remove()
358
- declarator.init &&
361
+ if (declarator.init) {
359
362
  globalBlock.body.splice(
360
363
  globalBlockIndex,
361
364
  0,
@@ -363,13 +366,15 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
363
366
  t.assignmentExpression(
364
367
  "=",
365
368
  t.memberExpression(
366
- t.identifier(`$${uniqueId}$GLOBAL$`),
369
+ t.identifier(`_${uniqueId}_G_`),
367
370
  t.identifier(declarator.id.name)
368
371
  ),
369
372
  declarator.init
370
373
  )
371
374
  )
372
375
  )
376
+ needG = !0
377
+ }
373
378
  } else {
374
379
  globalBlockPath.remove()
375
380
  globalBlockStatementPath.remove()
@@ -379,22 +384,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
379
384
  } else globalBlockVariables.add(declarator.id.name)
380
385
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
381
386
  program.scope.crawl()
382
- assert(globalBlockStatement.id, "src/processScript/transform.ts:487:37")
387
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:495:37")
383
388
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
384
389
  globalBlock.body.splice(globalBlockIndex, 1)
385
390
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
386
391
  [globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
387
392
  program.scope.crawl()
388
393
  const binding = program.scope.getBinding(globalBlockStatement.id.name)
389
- assert(binding, "src/processScript/transform.ts:499:22")
394
+ assert(binding, "src/processScript/transform.ts:507:22")
390
395
  for (const referencePath of binding.referencePaths) {
391
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:502:55")
396
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:510:55")
392
397
  referencePath.replaceWith(
393
- t.memberExpression(
394
- t.identifier(`$${uniqueId}$GLOBAL$`),
395
- t.identifier(referencePath.node.name)
396
- )
398
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(referencePath.node.name))
397
399
  )
400
+ needG = !0
398
401
  }
399
402
  globalBlockPath.remove()
400
403
  globalBlockStatementPath.remove()
@@ -405,7 +408,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
405
408
  t.assignmentExpression(
406
409
  "=",
407
410
  t.memberExpression(
408
- t.identifier(`$${uniqueId}$GLOBAL$`),
411
+ t.identifier(`_${uniqueId}_G_`),
409
412
  t.identifier(globalBlockStatement.id.name)
410
413
  ),
411
414
  t.classExpression(
@@ -417,6 +420,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
417
420
  )
418
421
  )
419
422
  )
423
+ needG = !0
420
424
  }
421
425
  }
422
426
  if (program.scope.hasGlobal("_EXPORTS"))
@@ -522,12 +526,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
522
526
  mainFunction.body.body.unshift(
523
527
  t.variableDeclaration(
524
528
  "let",
525
- [...neededSubscriptLets].map(name =>
529
+ [...neededSubscriptLets].map(([name, seclevel]) =>
526
530
  t.variableDeclarator(
527
531
  t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`),
528
532
  t.arrowFunctionExpression(
529
533
  [t.restElement(t.identifier("args"))],
530
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$${name}$`), [
534
+ t.callExpression(t.identifier(`$${uniqueId}$${seclevel}$SUBSCRIPT$${name}$`), [
531
535
  t.spreadElement(t.identifier("args"))
532
536
  ])
533
537
  )
@@ -535,6 +539,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
535
539
  )
536
540
  )
537
541
  )
542
+ needG &&
543
+ mainFunction.body.body.unshift(
544
+ t.variableDeclaration("let", [
545
+ t.variableDeclarator(t.identifier(`_${uniqueId}_G_`), t.identifier(`$${uniqueId}$GLOBAL$`))
546
+ ])
547
+ )
538
548
  traverse(file, {
539
549
  BlockStatement({ node: blockStatement }) {
540
550
  for (const [index, functionDeclaration] of blockStatement.body.entries())
@@ -555,7 +565,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
555
565
  }
556
566
  },
557
567
  ClassBody({ node: classBody, scope, parent }) {
558
- assert(t.isClass(parent), "src/processScript/transform.ts:669:30")
568
+ assert(t.isClass(parent), "src/processScript/transform.ts:688:30")
559
569
  let thisIsReferenced = !1
560
570
  for (const classMethod of classBody.body) {
561
571
  if ("ClassMethod" != classMethod.type) continue
@@ -631,7 +641,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
631
641
  VariableDeclaration({ node: variableDeclaration }) {
632
642
  "const" == variableDeclaration.kind && (variableDeclaration.kind = "let")
633
643
  },
634
- ThisExpression: path => path.replaceWith(t.identifier("undefined")),
644
+ ThisExpression: path => {
645
+ path.replaceWith(t.identifier("undefined"))
646
+ },
635
647
  BigIntLiteral(path) {
636
648
  const bigIntAsNumber = Number(path.node.value)
637
649
  path.replaceWith(
@@ -659,36 +671,37 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
659
671
  t.identifier("prototype")
660
672
  )
661
673
  }
662
- function processFakeSubscriptObject(fakeSubscriptObjectName) {
674
+ function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
663
675
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
664
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:783:60")
676
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:804:60")
665
677
  assert("Identifier" == referencePath.parent.property.type)
666
678
  assert(
667
679
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
668
- "src/processScript/transform.ts:785:81"
680
+ "src/processScript/transform.ts:806:81"
669
681
  )
670
682
  assert(
671
683
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
672
- "src/processScript/transform.ts:786:83"
684
+ "src/processScript/transform.ts:807:83"
673
685
  )
674
686
  assert(
675
687
  /^[_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`
688
+ `src/processScript/transform.ts:811:8 invalid user "${referencePath.parent.property.name}" in subscript`
677
689
  )
678
690
  assert(
679
691
  /^[_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`
692
+ `src/processScript/transform.ts:816:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
681
693
  )
682
694
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
683
695
  referencePath.parentPath.parentPath.replaceWith(
684
696
  t.identifier(
685
- `$${uniqueId}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
697
+ `$${uniqueId}$${seclevel}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
686
698
  )
687
699
  )
688
700
  else {
689
701
  const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
690
702
  referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
691
- neededSubscriptLets.add(name)
703
+ const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
704
+ neededSubscriptLets.set(name, maxSecLevel)
692
705
  }
693
706
  }
694
707
  }
package/push.d.ts CHANGED
@@ -18,6 +18,14 @@ export type PushOptions = LaxPartial<{
18
18
  */
19
19
  forceQuineCheats: boolean;
20
20
  }>;
21
+ export declare class MissingSourceFolderError extends Error {
22
+ }
23
+ export declare class MissingHackmudFolderError extends Error {
24
+ }
25
+ export declare class NoUsersError extends Error {
26
+ }
27
+ export declare class NoScriptsError extends Error {
28
+ }
21
29
  /** Push scripts from a source directory to the hackmud directory.
22
30
  *
23
31
  * Pushes files directly in the source folder to all users
@@ -25,4 +33,4 @@ export type PushOptions = LaxPartial<{
25
33
  * @param hackmudPath directory created by hackmud containing user data including scripts
26
34
  * @param options {@link PushOptions details}
27
35
  * @returns array of info on pushed scripts */
28
- export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<Info[]>;
36
+ export declare function push(sourcePath: string, hackmudPath: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: PushOptions): Promise<MissingSourceFolderError | MissingHackmudFolderError | NoUsersError | NoScriptsError | Info[]>;
package/push.js CHANGED
@@ -42,32 +42,54 @@ import "./processScript/preprocess.js"
42
42
  import "import-meta-resolve"
43
43
  import "./processScript/transform.js"
44
44
  import "@samual/lib/clearObject"
45
+ class MissingSourceFolderError extends Error {}
46
+ Object.defineProperty(MissingSourceFolderError.prototype, "name", { value: "MissingSourceFolderError" })
47
+ class MissingHackmudFolderError extends Error {}
48
+ Object.defineProperty(MissingHackmudFolderError.prototype, "name", { value: "MissingHackmudFolderError" })
49
+ class NoUsersError extends Error {}
50
+ Object.defineProperty(NoUsersError.prototype, "name", { value: "NoUsersError" })
51
+ class NoScriptsError extends Error {}
52
+ Object.defineProperty(NoScriptsError.prototype, "name", { value: "NoScriptsError" })
45
53
  async function push(
46
54
  sourcePath,
47
55
  hackmudPath,
48
56
  { scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats } = {}
49
57
  ) {
50
58
  const [sourceFolder, hackmudFolder] = await Promise.all([
51
- readDirectoryWithStats(sourcePath),
52
- readDirectoryWithStats(hackmudPath)
53
- ]),
54
- sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
59
+ readDirectoryWithStats(sourcePath).catch(error => {
60
+ if (error && "ENOENT" == error.code)
61
+ return new MissingSourceFolderError("There is no folder at " + sourcePath)
62
+ throw error
63
+ }),
64
+ readDirectoryWithStats(hackmudPath).catch(error => {
65
+ if (error && "ENOENT" == error.code)
66
+ return new MissingHackmudFolderError("There is no folder at " + hackmudPath)
67
+ throw error
68
+ })
69
+ ])
70
+ if (sourceFolder instanceof Error) return sourceFolder
71
+ if (hackmudFolder instanceof Error) return hackmudFolder
72
+ const sourceFolderFolders = sourceFolder.filter(({ stats }) => stats.isDirectory()),
55
73
  allUsers = new Set([
56
74
  ...scripts
57
- .map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:52:65"))
75
+ .map(scriptName => ensure(scriptName.split(".")[0], "src/push.ts:82:65"))
58
76
  .filter(name => "*" != name),
59
77
  ...sourceFolderFolders.map(({ name }) => name),
60
78
  ...hackmudFolder.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
61
79
  ...hackmudFolder
62
80
  .filter(({ stats, name }) => stats.isFile() && name.endsWith(".key"))
63
81
  .map(({ name }) => name.slice(0, -4))
64
- ]),
65
- usersToScriptsToPush = new Cache(_user => new Map()),
82
+ ])
83
+ if (!allUsers.size)
84
+ return new NoUsersError(
85
+ "Could not find any users. Either provide the names of your users or log into a user in hackmud"
86
+ )
87
+ const usersToScriptsToPush = new Cache(_user => new Map()),
66
88
  scriptNamesToUsers = new Cache(_scriptName => new Set())
67
89
  for (const script of scripts) {
68
90
  const [user, scriptName] = script.split(".")
69
- assert(user, "src/push.ts:69:16")
70
- assert(scriptName, "src/push.ts:70:22")
91
+ assert(user, "src/push.ts:105:16")
92
+ assert(scriptName, "src/push.ts:106:22")
71
93
  "*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
72
94
  }
73
95
  const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
@@ -98,7 +120,7 @@ async function push(
98
120
  for (const [scriptName, users] of scriptNamesToUsers)
99
121
  for (const user of users)
100
122
  if (!usersToScriptsToPush.get(user).has(scriptName))
101
- throw Error(`Could not find script ${user}.${scriptName} to push`)
123
+ return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
102
124
  const pathsToUsers = new Cache(_path => new Set())
103
125
  for (const [user, scriptsToPush] of usersToScriptsToPush)
104
126
  for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
@@ -135,4 +157,4 @@ async function push(
135
157
  )
136
158
  return allInfo
137
159
  }
138
- export { push }
160
+ export { MissingHackmudFolderError, MissingSourceFolderError, NoScriptsError, NoUsersError, push }
package/syncMacros.js CHANGED
@@ -37,7 +37,7 @@ async function syncMacros(hackmudPath) {
37
37
  macroFile += `${name}\n${macro}\n`
38
38
  macrosSynced++
39
39
  }
40
- for (const user of users) writeFile(resolve(hackmudPath, user + ".macros"), macroFile)
40
+ await Promise.all(users.map(async user => writeFile(resolve(hackmudPath, user + ".macros"), macroFile)))
41
41
  return { macrosSynced, usersSynced: users.length }
42
42
  }
43
43
  export { syncMacros }
package/watch.js CHANGED
@@ -9,6 +9,7 @@ import { extname, basename, resolve } from "path"
9
9
  import { supportedExtensions } from "./constants.js"
10
10
  import { generateTypeDeclaration } from "./generateTypeDeclaration.js"
11
11
  import { processScript } from "./processScript/index.js"
12
+ import "path/posix"
12
13
  import "@babel/generator"
13
14
  import "@babel/parser"
14
15
  import "@babel/plugin-proposal-decorators"