hackmud-script-manager 0.20.3 → 0.20.4-03d5600

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"