hackmud-script-manager 0.20.3 → 0.20.4-06a037b

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.
@@ -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_`))
@@ -101,40 +99,40 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
101
99
  functionDotPrototypeIsReferencedMultipleTimes = !0
102
100
  }
103
101
  }
104
- const neededSubscriptLets = new Set()
102
+ const neededSubscriptLets = new Map()
105
103
  let detectedSeclevel = 4
106
104
  for (const fakeSubscriptObjectName of ["$fs", "$4s", "$s"])
107
- program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName)
105
+ program.scope.hasGlobal(fakeSubscriptObjectName) && processFakeSubscriptObject(fakeSubscriptObjectName, 4)
108
106
  for (const fakeSubscriptObjectName of ["$hs", "$3s"])
109
107
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
110
108
  detectedSeclevel = 3
111
- processFakeSubscriptObject(fakeSubscriptObjectName)
109
+ processFakeSubscriptObject(fakeSubscriptObjectName, 3)
112
110
  }
113
111
  for (const fakeSubscriptObjectName of ["$ms", "$2s"])
114
112
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
115
113
  detectedSeclevel = 2
116
- processFakeSubscriptObject(fakeSubscriptObjectName)
114
+ processFakeSubscriptObject(fakeSubscriptObjectName, 2)
117
115
  }
118
116
  for (const fakeSubscriptObjectName of ["$ls", "$1s"])
119
117
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
120
118
  detectedSeclevel = 1
121
- processFakeSubscriptObject(fakeSubscriptObjectName)
119
+ processFakeSubscriptObject(fakeSubscriptObjectName, 1)
122
120
  }
123
121
  for (const fakeSubscriptObjectName of ["$ns", "$0s"])
124
122
  if (program.scope.hasGlobal(fakeSubscriptObjectName)) {
125
123
  detectedSeclevel = 0
126
- processFakeSubscriptObject(fakeSubscriptObjectName)
124
+ processFakeSubscriptObject(fakeSubscriptObjectName, 0)
127
125
  }
128
126
  seclevel = Math.min(seclevel, detectedSeclevel)
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}$`))
@@ -157,27 +155,32 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
157
155
  if (program.scope.hasGlobal("$FMCL"))
158
156
  for (const referencePath of getReferencePathsToGlobal("$FMCL", program))
159
157
  referencePath.replaceWith(t.identifier(`$${uniqueId}$FMCL$`))
160
- if (program.scope.hasGlobal("$G"))
158
+ let needG = program.scope.hasGlobal("$G")
159
+ if (needG)
161
160
  for (const referencePath of getReferencePathsToGlobal("$G", program))
162
- referencePath.replaceWith(t.identifier(`$${uniqueId}$GLOBAL$`))
161
+ referencePath.replaceWith(t.identifier(`_${uniqueId}_G_`))
163
162
  if (program.scope.hasGlobal("_SECLEVEL"))
164
163
  for (const referencePath of getReferencePathsToGlobal("_SECLEVEL", program))
165
164
  referencePath.replaceWith(t.numericLiteral(seclevel))
166
- let needGetPrototypeOf = !1
165
+ let needGetPrototypeOf = !1,
166
+ needHasOwn = !1
167
167
  if (program.scope.hasGlobal("Object"))
168
168
  for (const referencePath of getReferencePathsToGlobal("Object", program))
169
169
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
170
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:241:64")
170
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:242:64")
171
171
  if ("getPrototypeOf" == referencePath.parent.property.name) {
172
172
  referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_GET_PROTOTYPE_OF_`))
173
173
  needGetPrototypeOf = !0
174
+ } else if ("hasOwn" == referencePath.parent.property.name) {
175
+ referencePath.parentPath.replaceWith(t.identifier(`_${uniqueId}_HAS_OWN_`))
176
+ needHasOwn = !0
174
177
  }
175
178
  }
176
179
  const consoleMethodsReferenced = new Set()
177
180
  if (program.scope.hasGlobal("console"))
178
181
  for (const referencePath of getReferencePathsToGlobal("console", program))
179
182
  if ("MemberExpression" == referencePath.parent.type && !referencePath.parent.computed) {
180
- assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:256:64")
183
+ assert("Identifier" == referencePath.parent.property.type, "src/processScript/transform.ts:260:64")
181
184
  referencePath.parentPath.replaceWith(
182
185
  t.identifier(`_${uniqueId}_CONSOLE_METHOD_${referencePath.parent.property.name}_`)
183
186
  )
@@ -185,19 +188,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
185
188
  }
186
189
  const lastStatement = program.node.body.at(-1)
187
190
  let exportDefaultName
188
- assert(lastStatement, "src/processScript/transform.ts:270:27 program is empty")
191
+ assert(lastStatement, "src/processScript/transform.ts:274:27 program is empty")
189
192
  if ("ExportNamedDeclaration" == lastStatement.type) {
190
193
  program.node.body.pop()
191
194
  for (const specifier of lastStatement.specifiers) {
192
195
  assert(
193
196
  "ExportSpecifier" == specifier.type,
194
- `src/processScript/transform.ts:276:51 ${specifier.type} is currently unsupported`
197
+ `src/processScript/transform.ts:280:51 ${specifier.type} is currently unsupported`
195
198
  )
196
- const exportedName =
197
- "Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value
198
- "default" == exportedName ?
199
- (exportDefaultName = specifier.local.name)
200
- : exports.set(specifier.local.name, exportedName)
199
+ if (
200
+ "default" !=
201
+ ("Identifier" == specifier.exported.type ? specifier.exported.name : specifier.exported.value)
202
+ )
203
+ throw Error("Only default exports are supported")
204
+ exportDefaultName = specifier.local.name
201
205
  }
202
206
  }
203
207
  const globalBlock = t.blockStatement([])
@@ -223,10 +227,6 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
223
227
  t.returnStatement(t.callExpression(t.identifier(exportDefaultName), []))
224
228
  ])
225
229
  ))
226
- if ("const" != statement.kind && exports.has(identifierName)) {
227
- liveExports.set(identifierName, exports.get(identifierName))
228
- exports.delete(identifierName)
229
- }
230
230
  globalBlock.body.push(
231
231
  t.variableDeclaration("let", [t.variableDeclarator(t.identifier(identifierName))])
232
232
  )
@@ -291,34 +291,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
291
291
  }
292
292
  program.node.body = [mainFunction]
293
293
  if (globalBlock.body.length) {
294
- ;(exports.size || liveExports.size) &&
295
- mainFunction.body.body.push(
296
- t.returnStatement(
297
- t.objectExpression([
298
- ...[...exports].map(([local, exported]) =>
299
- t.objectProperty(t.identifier(exported), t.identifier(local))
300
- ),
301
- ...[...liveExports].map(([local, exported]) =>
302
- t.objectMethod(
303
- "get",
304
- t.identifier(exported),
305
- [],
306
- t.blockStatement([t.returnStatement(t.identifier(local))])
307
- )
308
- )
309
- ])
310
- )
311
- )
312
294
  program.scope.crawl()
313
295
  const globalBlockVariables = new Set()
314
296
  let hoistedGlobalBlockFunctions = 0
315
297
  for (const [globalBlockIndex, globalBlockStatement] of [...globalBlock.body.entries()].reverse())
316
298
  if ("VariableDeclaration" == globalBlockStatement.type) {
317
- assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:410:59")
299
+ assert(1 == globalBlockStatement.declarations.length, "src/processScript/transform.ts:394:59")
318
300
  const declarator = globalBlockStatement.declarations[0]
319
301
  assert(
320
302
  "Identifier" == declarator.id.type,
321
- `src/processScript/transform.ts:414:51 declarator.id.type was "${declarator.id.type}"`
303
+ `src/processScript/transform.ts:398:51 declarator.id.type was "${declarator.id.type}"`
322
304
  )
323
305
  program.scope.crawl()
324
306
  if (program.scope.hasGlobal(declarator.id.name)) {
@@ -333,15 +315,16 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
333
315
  Object.keys(program.scope.globals).some(global => globalBlockVariables.has(global))
334
316
  ) {
335
317
  const binding = program.scope.getBinding(declarator.id.name)
336
- assert(binding, "src/processScript/transform.ts:433:23")
318
+ assert(binding, "src/processScript/transform.ts:417:23")
337
319
  for (const referencePath of binding.referencePaths) {
338
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:436:56")
320
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:420:56")
339
321
  referencePath.replaceWith(
340
322
  t.memberExpression(
341
- t.identifier(`$${uniqueId}$GLOBAL$`),
323
+ t.identifier(`_${uniqueId}_G_`),
342
324
  t.identifier(referencePath.node.name)
343
325
  )
344
326
  )
327
+ needG = !0
345
328
  }
346
329
  for (const referencePath of binding.constantViolations)
347
330
  if ("AssignmentExpression" == referencePath.node.type)
@@ -350,12 +333,13 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
350
333
  clearObject(node)
351
334
  Object.assign(
352
335
  node,
353
- t.memberExpression(t.identifier(`$${uniqueId}$GLOBAL$`), t.identifier(name))
336
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(name))
354
337
  )
338
+ needG = !0
355
339
  }
356
340
  globalBlockPath.remove()
357
341
  globalBlockStatementPath.remove()
358
- declarator.init &&
342
+ if (declarator.init) {
359
343
  globalBlock.body.splice(
360
344
  globalBlockIndex,
361
345
  0,
@@ -363,13 +347,15 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
363
347
  t.assignmentExpression(
364
348
  "=",
365
349
  t.memberExpression(
366
- t.identifier(`$${uniqueId}$GLOBAL$`),
350
+ t.identifier(`_${uniqueId}_G_`),
367
351
  t.identifier(declarator.id.name)
368
352
  ),
369
353
  declarator.init
370
354
  )
371
355
  )
372
356
  )
357
+ needG = !0
358
+ }
373
359
  } else {
374
360
  globalBlockPath.remove()
375
361
  globalBlockStatementPath.remove()
@@ -379,22 +365,20 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
379
365
  } else globalBlockVariables.add(declarator.id.name)
380
366
  } else if ("ClassDeclaration" == globalBlockStatement.type) {
381
367
  program.scope.crawl()
382
- assert(globalBlockStatement.id, "src/processScript/transform.ts:487:37")
368
+ assert(globalBlockStatement.id, "src/processScript/transform.ts:477:37")
383
369
  if (program.scope.hasGlobal(globalBlockStatement.id.name)) {
384
370
  globalBlock.body.splice(globalBlockIndex, 1)
385
371
  const [globalBlockPath] = program.unshiftContainer("body", globalBlock),
386
372
  [globalBlockStatementPath] = program.unshiftContainer("body", globalBlockStatement)
387
373
  program.scope.crawl()
388
374
  const binding = program.scope.getBinding(globalBlockStatement.id.name)
389
- assert(binding, "src/processScript/transform.ts:499:22")
375
+ assert(binding, "src/processScript/transform.ts:489:22")
390
376
  for (const referencePath of binding.referencePaths) {
391
- assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:502:55")
377
+ assert("Identifier" == referencePath.node.type, "src/processScript/transform.ts:492:55")
392
378
  referencePath.replaceWith(
393
- t.memberExpression(
394
- t.identifier(`$${uniqueId}$GLOBAL$`),
395
- t.identifier(referencePath.node.name)
396
- )
379
+ t.memberExpression(t.identifier(`_${uniqueId}_G_`), t.identifier(referencePath.node.name))
397
380
  )
381
+ needG = !0
398
382
  }
399
383
  globalBlockPath.remove()
400
384
  globalBlockStatementPath.remove()
@@ -405,7 +389,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
405
389
  t.assignmentExpression(
406
390
  "=",
407
391
  t.memberExpression(
408
- t.identifier(`$${uniqueId}$GLOBAL$`),
392
+ t.identifier(`_${uniqueId}_G_`),
409
393
  t.identifier(globalBlockStatement.id.name)
410
394
  ),
411
395
  t.classExpression(
@@ -417,13 +401,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
417
401
  )
418
402
  )
419
403
  )
404
+ needG = !0
420
405
  }
421
406
  }
422
- if (program.scope.hasGlobal("_EXPORTS"))
423
- for (const referencePath of getReferencePathsToGlobal("_EXPORTS", program))
424
- referencePath.replaceWith(
425
- t.arrayExpression([...exports.keys(), ...liveExports.keys()].map(name => t.stringLiteral(name)))
426
- )
427
407
  globalBlock.body.length &&
428
408
  mainFunction.body.body.splice(
429
409
  hoistedGlobalBlockFunctions,
@@ -472,6 +452,31 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
472
452
  )
473
453
  ])
474
454
  )
455
+ needHasOwn &&
456
+ mainFunction.body.body.unshift(
457
+ t.variableDeclaration("let", [
458
+ t.variableDeclarator(
459
+ t.identifier(`_${uniqueId}_HAS_OWN_`),
460
+ t.callExpression(
461
+ t.memberExpression(
462
+ t.memberExpression(
463
+ t.identifier(
464
+ globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
465
+ ),
466
+ t.identifier("call")
467
+ ),
468
+ t.identifier("bind")
469
+ ),
470
+ [
471
+ t.memberExpression(
472
+ t.memberExpression(t.identifier("Object"), t.identifier("prototype")),
473
+ t.identifier("hasOwnProperty")
474
+ )
475
+ ]
476
+ )
477
+ )
478
+ ])
479
+ )
475
480
  consoleMethodsReferenced.size &&
476
481
  mainFunction.body.body.unshift(
477
482
  t.variableDeclaration(
@@ -522,12 +527,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
522
527
  mainFunction.body.body.unshift(
523
528
  t.variableDeclaration(
524
529
  "let",
525
- [...neededSubscriptLets].map(name =>
530
+ [...neededSubscriptLets].map(([name, seclevel]) =>
526
531
  t.variableDeclarator(
527
532
  t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`),
528
533
  t.arrowFunctionExpression(
529
534
  [t.restElement(t.identifier("args"))],
530
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$${name}$`), [
535
+ t.callExpression(t.identifier(`$${uniqueId}$${seclevel}$SUBSCRIPT$${name}$`), [
531
536
  t.spreadElement(t.identifier("args"))
532
537
  ])
533
538
  )
@@ -535,6 +540,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
535
540
  )
536
541
  )
537
542
  )
543
+ needG &&
544
+ mainFunction.body.body.unshift(
545
+ t.variableDeclaration("let", [
546
+ t.variableDeclarator(t.identifier(`_${uniqueId}_G_`), t.identifier(`$${uniqueId}$GLOBAL$`))
547
+ ])
548
+ )
538
549
  traverse(file, {
539
550
  BlockStatement({ node: blockStatement }) {
540
551
  for (const [index, functionDeclaration] of blockStatement.body.entries())
@@ -555,7 +566,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
555
566
  }
556
567
  },
557
568
  ClassBody({ node: classBody, scope, parent }) {
558
- assert(t.isClass(parent), "src/processScript/transform.ts:669:30")
569
+ assert(t.isClass(parent), "src/processScript/transform.ts:687:30")
559
570
  let thisIsReferenced = !1
560
571
  for (const classMethod of classBody.body) {
561
572
  if ("ClassMethod" != classMethod.type) continue
@@ -631,7 +642,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
631
642
  VariableDeclaration({ node: variableDeclaration }) {
632
643
  "const" == variableDeclaration.kind && (variableDeclaration.kind = "let")
633
644
  },
634
- ThisExpression: path => path.replaceWith(t.identifier("undefined")),
645
+ ThisExpression: path => {
646
+ path.replaceWith(t.identifier("undefined"))
647
+ },
635
648
  BigIntLiteral(path) {
636
649
  const bigIntAsNumber = Number(path.node.value)
637
650
  path.replaceWith(
@@ -645,50 +658,43 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
645
658
  })
646
659
  return { file, seclevel }
647
660
  function createGetFunctionPrototypeNode() {
648
- for (const globalFunction of globalFunctionsUnder7Characters)
649
- if (!program.scope.hasOwnBinding(globalFunction))
650
- return t.memberExpression(
651
- t.memberExpression(t.identifier(globalFunction), t.identifier("constructor")),
652
- t.identifier("prototype")
653
- )
661
+ const name = globalFunctionsUnder7Characters.find(name => !program.scope.hasOwnBinding(name))
654
662
  return t.memberExpression(
655
- t.memberExpression(
656
- t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
657
- t.identifier("constructor")
658
- ),
659
- t.identifier("prototype")
663
+ name ? t.identifier(name) : t.arrowFunctionExpression([t.identifier("_")], t.identifier("_")),
664
+ t.identifier("__proto__")
660
665
  )
661
666
  }
662
- function processFakeSubscriptObject(fakeSubscriptObjectName) {
667
+ function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
663
668
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
664
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:783:60")
669
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:793:60")
665
670
  assert("Identifier" == referencePath.parent.property.type)
666
671
  assert(
667
672
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
668
- "src/processScript/transform.ts:785:81"
673
+ "src/processScript/transform.ts:795:81"
669
674
  )
670
675
  assert(
671
676
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
672
- "src/processScript/transform.ts:786:83"
677
+ "src/processScript/transform.ts:796:83"
673
678
  )
674
679
  assert(
675
680
  /^[_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`
681
+ `src/processScript/transform.ts:800:8 invalid user "${referencePath.parent.property.name}" in subscript`
677
682
  )
678
683
  assert(
679
684
  /^[_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`
685
+ `src/processScript/transform.ts:805:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
681
686
  )
682
687
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
683
688
  referencePath.parentPath.parentPath.replaceWith(
684
689
  t.identifier(
685
- `$${uniqueId}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
690
+ `$${uniqueId}$${seclevel}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
686
691
  )
687
692
  )
688
693
  else {
689
694
  const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
690
695
  referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
691
- neededSubscriptLets.add(name)
696
+ const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
697
+ neededSubscriptLets.set(name, maxSecLevel)
692
698
  }
693
699
  }
694
700
  }
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
@@ -1,4 +1,4 @@
1
- import { Cache } from "@samual/lib/Cache"
1
+ import { AutoMap } from "@samual/lib/AutoMap"
2
2
  import { ensure, assert } from "@samual/lib/assert"
3
3
  import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
4
4
  import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
@@ -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()),
66
- scriptNamesToUsers = new Cache(_scriptName => new Set())
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 AutoMap(_user => new Map()),
88
+ scriptNamesToUsers = new AutoMap(_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,8 +120,8 @@ 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`)
102
- const pathsToUsers = new Cache(_path => new Set())
123
+ return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
124
+ const pathsToUsers = new AutoMap(_path => new Set())
103
125
  for (const [user, scriptsToPush] of usersToScriptsToPush)
104
126
  for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
105
127
  const allInfo = []
@@ -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
@@ -1,14 +1,15 @@
1
- import { Cache } from "@samual/lib/Cache"
1
+ import { AutoMap } from "@samual/lib/AutoMap"
2
2
  import { assert } from "@samual/lib/assert"
3
3
  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"
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"
@@ -58,7 +59,8 @@ async function watch(
58
59
  } = {}
59
60
  ) {
60
61
  if (!scripts.length) throw Error("scripts option was an empty array")
61
- const scriptNamesToUsers = new Cache(_scriptName => new Set()),
62
+ if (!(await stat(sourceDirectory)).isDirectory()) throw Error("Target folder must be a folder")
63
+ const scriptNamesToUsers = new AutoMap(_scriptName => new Set()),
62
64
  wildScriptUsers = new Set(),
63
65
  wildUserScripts = new Set()
64
66
  let pushEverything = !1
@@ -90,7 +92,7 @@ async function watch(
90
92
  )
91
93
  )
92
94
  return
93
- const scriptNamesToUsersToSkip = new Cache(_scriptName => [])
95
+ const scriptNamesToUsersToSkip = new AutoMap(_scriptName => [])
94
96
  await Promise.all(
95
97
  (await readDirectoryWithStats(sourceDirectory)).map(async ({ stats, name, path }) => {
96
98
  if (stats.isDirectory())
@@ -135,7 +137,7 @@ async function watch(
135
137
  forceQuineCheats
136
138
  }))
137
139
  } catch (error) {
138
- assert(error instanceof Error, "src/watch.ts:141:36")
140
+ assert(error instanceof Error, "src/watch.ts:146:36")
139
141
  onPush?.({ path, users: [], characterCount: 0, error })
140
142
  return
141
143
  }
@@ -180,7 +182,7 @@ async function watch(
180
182
  forceQuineCheats
181
183
  }))
182
184
  } catch (error) {
183
- assert(error instanceof Error, "src/watch.ts:177:35")
185
+ assert(error instanceof Error, "src/watch.ts:182:35")
184
186
  onPush?.({ path, users: [], characterCount: 0, error })
185
187
  return
186
188
  }
@@ -195,7 +197,7 @@ async function watch(
195
197
  try {
196
198
  await writeFile(typeDeclarationPath, typeDeclaration)
197
199
  } catch (error) {
198
- assert(error instanceof Error, "src/watch.ts:210:35")
200
+ assert(error instanceof Error, "src/watch.ts:215:35")
199
201
  if ("EISDIR" != error.code) throw error
200
202
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
201
203
  await writeFile(typeDeclarationPath, typeDeclaration)