hackmud-script-manager 0.20.4-7caccd9 → 0.20.4-8b61cf2

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Hackmud Script Manager
2
- Command made for [hackmud-environment](https://github.com/samualtnorman/hackmud-environment), which is a scripting environment for hackmud with minification, autocompletes / intellisense, and TypeScript support.
2
+ Command made for [Hackmud Scripting Environment](https://github.com/samualtnorman/hackmud-environment), which is a scripting environment for hackmud with minification, autocompletes / intellisense, and TypeScript support.
3
3
 
4
4
  [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R0XN5CX)
5
5
 
package/bin/hsm.js CHANGED
@@ -12,7 +12,7 @@ import { pull } from "../pull.js"
12
12
  import { syncMacros } from "../syncMacros.js"
13
13
  import "@samual/lib/readDirectoryWithStats"
14
14
  import "@samual/lib/copyFilePersistent"
15
- const version = "0.20.4-7caccd9",
15
+ const version = "0.20.4-8b61cf2",
16
16
  options = new Map(),
17
17
  commands = [],
18
18
  userColours = new Cache(user => {
@@ -119,16 +119,25 @@ switch (commands[0]) {
119
119
  logHelp()
120
120
  break
121
121
  }
122
- const { push } = await pushModule
123
- ;(
124
- await push(sourcePath, hackmudPath, {
122
+ const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } = await pushModule,
123
+ infos = await push(sourcePath, hackmudPath, {
125
124
  scripts,
126
125
  onPush: info => logInfo(info, hackmudPath),
127
126
  minify: shouldMinify,
128
127
  mangleNames: shouldMangleNames,
129
128
  forceQuineCheats: shouldforceQuineCheats
130
129
  })
131
- ).length || logError("Could not find any scripts to push")
130
+ if (infos instanceof Error) {
131
+ logError(infos.message)
132
+ if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
133
+ console.log()
134
+ logHelp()
135
+ } else
136
+ infos instanceof MissingHackmudFolderError &&
137
+ log(
138
+ `If this is not where your hackmud folder is, you can specify it with the\n${colourN("--hackmud-path")}=${colourB("<path>")} option or ${colourN("HSM_HACKMUD_PATH")} environment variable`
139
+ )
140
+ } else infos.length || logError("Could not find any scripts to push")
132
141
  }
133
142
  break
134
143
  case "dev":
@@ -245,7 +254,7 @@ switch (commands[0]) {
245
254
  typeDeclaration = await generateTypeDeclaration(sourcePath, getHackmudPath())
246
255
  let typeDeclarationPath = resolve(outputPath)
247
256
  await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
248
- assert(error instanceof Error, "src/bin/hsm.ts:327:35")
257
+ assert(error instanceof Error, "src/bin/hsm.ts:340:35")
249
258
  if ("EISDIR" != error.code) throw error
250
259
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
251
260
  return writeFile(typeDeclarationPath, typeDeclaration)
package/env.d.ts CHANGED
@@ -1,18 +1,14 @@
1
- type Replace<T, R> = Omit<T, Extract<keyof R, keyof T>> & R
1
+ type Replace<A, B> = Omit<A, keyof B> & B
2
2
  type ScriptSuccess<T = object> = { ok: true } & T
3
3
  type ScriptFailure = { ok: false, msg?: string }
4
4
  type ScriptResponse<T = object> = ScriptSuccess<T> | ScriptFailure
5
5
  type ErrorScripts = Record<string, () => ScriptFailure>
6
6
 
7
- type AllOptional<T> = {
8
- [K in keyof T]-?: {} extends Pick<T, K> ? true : false
9
- }[keyof T]
7
+ type AllOptional<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? true : false }[keyof T]
10
8
 
11
9
  type Scriptor<Args = unknown, Ret = unknown> = {
12
- name: string,
13
- call: AllOptional<Args> extends true
14
- ? (args?: Args) => Ret
15
- : (args: Args) => Ret
10
+ name: string
11
+ call: AllOptional<Args> extends true ? (args?: Args) => Ret : (args: Args) => Ret
16
12
  }
17
13
 
18
14
  type Subscripts = Record<string, Record<string, (...args: any) => any>> & {
@@ -41,7 +37,7 @@ type UpgradeRarityString = "`0noob`" | "`1kiddie`" | "`2h4x0r`" | "`3h4rdc0r3`"
41
37
  type UpgradeRarityNumber = 0 | 1 | 2 | 3 | 4 | 5;
42
38
  type UpgradeRarity = UpgradeRarityString | UpgradeRarityNumber;
43
39
 
44
- type UpgradeCore = {
40
+ type UpgradeBase = {
45
41
  name: string
46
42
  type: "lock" | "script_space" | "chat" | "script" | "tool" | "bot_brain" | "glam"
47
43
  up_class?: -1 | 0 | 1 | 2 | 3
@@ -53,9 +49,9 @@ type UpgradeCore = {
53
49
  description: string
54
50
  }
55
51
 
56
- type Upgrade = UpgradeCore & Record<string, null | boolean | number | string>
52
+ type Upgrade = UpgradeBase & Record<string, null | boolean | number | string>
57
53
 
58
- type CLIUpgrade = Omit<UpgradeCore, `rarity`> & {
54
+ type CliUpgrade = Omit<UpgradeBase, `rarity`> & {
59
55
  [x: string]: null | boolean | number | string
60
56
  rarity: UpgradeRarityString
61
57
  }
@@ -155,7 +151,16 @@ type Fullsec = Subscripts & PlayerFullsec & {
155
151
  market: {
156
152
  /** **FULLSEC** */ browse: {
157
153
  (args:
158
- Partial<{ seller: string, listed_before: number, listed_after: number, cost: number | string } & Omit<CLIUpgrade, "rarity">>
154
+ Partial<{
155
+ seller: string | MongoQuerySelector<string>,
156
+ listed_before: number | MongoQuerySelector<number>,
157
+ listed_after: number,
158
+ cost: number | MongoQuerySelector<number> | string,
159
+ rarity: UpgradeRarityNumber | MongoQuerySelector<UpgradeRarityNumber>,
160
+ name: string | MongoQuerySelector<string>
161
+ } & Omit<{
162
+ [k in keyof CliUpgrade]: CliUpgrade[k] | MongoQuerySelector<CliUpgrade[k]>
163
+ }, "rarity">>
159
164
  ): { i: string, name: string, rarity: Upgrade["rarity"], cost: number }[] | ScriptFailure
160
165
 
161
166
  <I extends string>(args: { i: I }): {
@@ -357,7 +362,7 @@ type Fullsec = Subscripts & PlayerFullsec & {
357
362
  * const arr = [ 1, 2, 2, 3, 2 ]
358
363
  *
359
364
  * $D(uniq(arr)) // [ 1, 2, 3, 2 ] */
360
- uniq: (array: T[]) => T[]
365
+ uniq: <T>(array: T[]) => T[]
361
366
 
362
367
  /** Sorts an array of numbers or number-coercible strings in descending order. */
363
368
  u_sort_num_arr_desc: <T>(array: T[]) => T[]
@@ -424,17 +429,17 @@ type Fullsec = Subscripts & PlayerFullsec & {
424
429
  upgrades_of_owner: {
425
430
  <F extends Partial<Upgrade & { loaded: boolean }> = object>(args?: { filter?: F, full?: false }): (
426
431
  Omit<
427
- Pick<UpgradeCore, "tier" | "rarity" | "name" | "type" | "i" | "loaded">,
432
+ Pick<UpgradeBase, "tier" | "rarity" | "name" | "type" | "i" | "loaded">,
428
433
  keyof F
429
434
  > & Pick<F, "tier" | "rarity" | "name" | "type" | "i" | "loaded">
430
435
  )[] | ScriptFailure
431
436
 
432
437
  <F extends Partial<Upgrade & { loaded: boolean }> = object>(args: { filter?: F, full: true }): (
433
- Omit<UpgradeCore, keyof F> & F & Record<string, null | boolean | number | string>
438
+ Omit<UpgradeBase, keyof F> & F & Record<string, null | boolean | number | string>
434
439
  )[] | ScriptFailure
435
440
 
436
441
  <I extends number>(args: { i: I }): (
437
- Omit<UpgradeCore, "i"> & { [x: string]: null | boolean | number | string, i: I }
442
+ Omit<UpgradeBase, "i"> & { [x: string]: null | boolean | number | string, i: I }
438
443
  ) | ScriptFailure
439
444
  }
440
445
 
@@ -511,7 +516,7 @@ type Highsec = Fullsec & PlayerHighsec & {
511
516
  /** **HIGHSEC** */
512
517
  upgrades: {
513
518
  <I extends number>(args: { i: I }): (
514
- Omit<UpgradeCore, "i"> & { [x: string]: null | boolean | number | string, i: I }
519
+ Omit<UpgradeBase, "i"> & { [x: string]: null | boolean | number | string, i: I }
515
520
  ) | ScriptFailure
516
521
 
517
522
  <F extends Partial<Upgrade & { loaded: boolean }> = object>(args?: {
@@ -519,20 +524,20 @@ type Highsec = Fullsec & PlayerHighsec & {
519
524
  is_script?: true
520
525
  full?: false
521
526
  }): (
522
- Omit<Pick<UpgradeCore, "tier" | "rarity" | "name" | "type" | "i" | "loaded">, keyof F> & F &
527
+ Omit<Pick<UpgradeBase, "tier" | "rarity" | "name" | "type" | "i" | "loaded">, keyof F> & F &
523
528
  Record<string, null | boolean | number | string>
524
529
  )[] | ScriptFailure
525
530
 
526
531
  <F extends Partial<Upgrade & { loaded: boolean }> = object>(args?:
527
532
  { filter?: F, is_script?: true, full: true }
528
- ): (Omit<UpgradeCore, keyof F> & F & Record<string, null | boolean | number | string>)[] | ScriptFailure
533
+ ): (Omit<UpgradeBase, keyof F> & F & Record<string, null | boolean | number | string>)[] | ScriptFailure
529
534
 
530
535
  (args?: { filter?: Partial<Upgrade & { loaded: boolean }>, is_script: false, full?: false }):
531
536
  { msg: string, upgrades: string[] } | ScriptFailure
532
537
 
533
538
  <F extends Partial<Upgrade & { loaded: boolean }> = object>(
534
539
  args?: { filter?: F, is_script: false, full: true }
535
- ): (Omit<UpgradeCore, keyof F | `rarity`> & F & {
540
+ ): (Omit<UpgradeBase, keyof F | `rarity`> & F & {
536
541
  [x: string]: null | boolean | number | string
537
542
  rarity: UpgradeRarityString
538
543
  })[] | ScriptFailure
@@ -714,10 +719,50 @@ type Nullsec = Lowsec & PlayerNullsec & {
714
719
  }
715
720
  }
716
721
 
722
+ type MongoTypeString = "minKey" | "double" | "string" | "object" | "array" | "binData" | "undefined" | "objectId" |
723
+ "bool" | "date" | "null" | "regex" | "dbPointer" | "javascript" | "symbol" | "int" | "timestamp" | "long" | "decimal" | "maxKey";
724
+ type MongoTypeNumber = -1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 127;
725
+
717
726
  type MongoValue = string | number | boolean | Date | MongoValue[] | { [key: string]: MongoValue } | null
718
727
 
719
728
  type MongoCommandValue = string | number | boolean | Date | MongoCommandValue[] | { [key: string]: MongoCommandValue } |
720
- null | undefined
729
+ null | undefined
730
+
731
+ /**
732
+ * Currently unused
733
+ */
734
+ type MongoLogicalSelectors<T extends MongoValue = MongoValue> = {
735
+ $not: T | MongoComparisonSelectors<T> | MongoLogicalSelectors<T>
736
+ $nor: T[]
737
+ $or: T[]
738
+ $and: T[]
739
+ }
740
+
741
+ type MongoArraySelectors<T extends Array<MongoValue> = Array<MongoValue>> = {
742
+ $all: T
743
+ $elemMatch: T
744
+ $size: number
745
+ }
746
+
747
+ type MongoComparisonSelectors<T extends MongoValue = MongoValue> = {
748
+ $eq: T
749
+ $gt: T
750
+ $gte: T
751
+ $in: T[]
752
+ $lt: T
753
+ $lte: T
754
+ $ne: T
755
+ $nin: T[]
756
+ }
757
+
758
+ type MongoElementSelectors = {
759
+ $exists: boolean
760
+ $type: MongoTypeNumber | MongoTypeString
761
+ }
762
+
763
+ type MongoQuerySelector<T extends MongoValue = MongoValue> = Partial<T extends MongoValue[] ?
764
+ (MongoArraySelectors<T> & MongoElementSelectors & MongoComparisonSelectors<T>) :
765
+ (MongoElementSelectors & MongoComparisonSelectors<T>)>
721
766
 
722
767
  type Query = { [key: string]: MongoValue | Query } & { _id?: Id, $in?: MongoValue[] }
723
768
  type Projection = Record<string, boolean | 0 | 1>
@@ -766,7 +811,7 @@ type Cursor = {
766
811
  ObjectId: () => any
767
812
  }
768
813
 
769
- type CLIContext = {
814
+ type CliContext = {
770
815
  /** The name of the user who is calling the script. */ caller: string
771
816
  /** The name of this script. */ this_script: string
772
817
  /** The number of columns in the caller’s terminal. */ cols: number
@@ -774,17 +819,23 @@ type CLIContext = {
774
819
 
775
820
  /** The name of the script that directly called this script, or null if called on the command line or as a
776
821
  * scriptor. */ calling_script: null
822
+ is_scriptor?: undefined
823
+ is_brain?: undefined
777
824
  }
778
825
 
779
- type SubscriptContext = Replace<CLIContext, {
826
+ type SubscriptContext = Replace<CliContext, {
780
827
  /** The name of the script that directly called this script, or null if called on the command line or as a scriptor.
781
828
  */
782
829
  calling_script: string
783
830
  }>
784
831
 
785
- type ScriptorContext = CLIContext & { /** Whether the script is being run as a scriptor. */ is_scriptor: true }
786
- type BrainContext = CLIContext & { /** Whether the script is being run via a bot brain. */ is_brain: true }
787
- type Context = CLIContext | SubscriptContext | ScriptorContext | BrainContext
832
+ type ScriptorContext =
833
+ Replace<CliContext, { /** Whether the script is being run as a scriptor. */ is_scriptor: true }>
834
+
835
+ type BrainContext =
836
+ Replace<CliContext, { /** Whether the script is being run via a bot brain. */ is_brain: true }>
837
+
838
+ type Context = CliContext | SubscriptContext | ScriptorContext | BrainContext
788
839
 
789
840
  /** Subscript space that can call FULLSEC scripts. */ declare const $fs: Fullsec
790
841
 
@@ -827,6 +878,8 @@ declare const $0s: typeof $ns
827
878
  * } */
828
879
  declare const $s: Nullsec
829
880
 
881
+ type ObjectId = { $oid: string }
882
+
830
883
  declare const $db: {
831
884
  /** Insert a document or documents into a collection.
832
885
  * @param documents A document or array of documents to insert into the collection. */
@@ -920,6 +973,8 @@ declare const $db: {
920
973
  signature: { hash: "Undefined Conversion", keyId: "Undefined Conversion" }
921
974
  }
922
975
  }
976
+
977
+ ObjectId: () => ObjectId
923
978
  }
924
979
 
925
980
  /** Debug Log.
@@ -956,7 +1011,7 @@ declare const $FMCL: undefined | true
956
1011
  * @example
957
1012
  * if (!$G.dbCache)
958
1013
  * $G.dbCache = $db.f({ whatever: true }).first() */
959
- declare const $G: any
1014
+ declare const $G: Record<string | symbol, any>
960
1015
 
961
1016
  /** This contains a JS timestamp (not Date) set immediately before your code begins running.
962
1017
  * @example
@@ -1005,3 +1060,14 @@ declare const _FULL_SCRIPT_NAME: string
1005
1060
  *
1006
1061
  * In rare cases where it's not known at build time, it's `-1`. */
1007
1062
  declare const _SECLEVEL: -1 | 0 | 1 | 2 | 3 | 4
1063
+
1064
+ type DeepFreeze<T> = { readonly [P in keyof T]: DeepFreeze<T[P]> }
1065
+
1066
+ /** Recursively
1067
+ * [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
1068
+ * an object and its properties' objects and its properties' objects and so on.
1069
+ *
1070
+ * [Official Hackmud Wiki](https://wiki.hackmud.com/scripting/extensions/deep_freeze) */
1071
+ declare const DEEP_FREEZE: <T>(value: T) => DeepFreeze<T>
1072
+
1073
+ declare const _RUN_ID: string
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hackmud-script-manager",
3
- "version": "0.20.4-7caccd9",
3
+ "version": "0.20.4-8b61cf2",
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'
@@ -136,7 +136,8 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
136
136
  const promises = []
137
137
  traverse(file, {
138
138
  FunctionDeclaration(path) {
139
- path.traverse({
139
+ const body = path.get("body")
140
+ body.traverse({
140
141
  Function(path) {
141
142
  "CallExpression" != path.parent.type && "callee" != path.parentKey && path.skip()
142
143
  },
@@ -152,7 +153,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
152
153
  path.replaceWith(t.identifier(`_${uniqueId}_JSON_VALUE_${jsonValues.push(o) - 1}_`))
153
154
  }
154
155
  })
155
- path.traverse({
156
+ body.traverse({
156
157
  TemplateLiteral(path) {
157
158
  if ("TaggedTemplateExpression" == path.parent.type) return
158
159
  const templateLiteral = path.node
@@ -172,7 +173,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
172
173
  },
173
174
  MemberExpression({ node: memberExpression }) {
174
175
  if (!memberExpression.computed) {
175
- assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:259:62")
176
+ assert("Identifier" == memberExpression.property.type, "src/processScript/minify.ts:261:62")
176
177
  if (!(memberExpression.property.name.length < 3)) {
177
178
  memberExpression.computed = !0
178
179
  memberExpression.property = t.stringLiteral(memberExpression.property.name)
@@ -246,7 +247,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
246
247
  })
247
248
  await Promise.all(promises)
248
249
  const functionDeclaration = file.program.body[0]
249
- assert("FunctionDeclaration" == functionDeclaration.type, "src/processScript/minify.ts:364:61")
250
+ assert("FunctionDeclaration" == functionDeclaration.type, "src/processScript/minify.ts:366:61")
250
251
  if (jsonValues.length) {
251
252
  hasComment = !0
252
253
  if (1 == jsonValues.length)
@@ -258,7 +259,10 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
258
259
  t.memberExpression(
259
260
  t.taggedTemplateExpression(
260
261
  t.memberExpression(
261
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
262
+ t.callExpression(
263
+ t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`),
264
+ []
265
+ ),
262
266
  t.identifier("split")
263
267
  ),
264
268
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -282,7 +286,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
282
286
  t.memberExpression(
283
287
  t.taggedTemplateExpression(
284
288
  t.memberExpression(
285
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
289
+ t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
286
290
  t.identifier("split")
287
291
  ),
288
292
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -307,7 +311,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
307
311
  t.memberExpression(
308
312
  t.taggedTemplateExpression(
309
313
  t.memberExpression(
310
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
314
+ t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
311
315
  t.identifier("split")
312
316
  ),
313
317
  t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
@@ -363,7 +367,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ
363
367
  )
364
368
  }
365
369
  if (1 == forceQuineCheats) return code
366
- assert(scriptBeforeJSONValueReplacement, "src/processScript/minify.ts:495:43")
370
+ assert(scriptBeforeJSONValueReplacement, "src/processScript/minify.ts:497:43")
367
371
  return (
368
372
  countHackmudCharacters(scriptBeforeJSONValueReplacement) <=
369
373
  countHackmudCharacters(code) + Number(hasComment)
@@ -379,7 +383,7 @@ function parseObjectExpression(node, o) {
379
383
  "Identifier" == property.key.type ||
380
384
  "NumericLiteral" == property.key.type ||
381
385
  "StringLiteral" == property.key.type,
382
- "src/processScript/minify.ts:517:4"
386
+ "src/processScript/minify.ts:519:4"
383
387
  )
384
388
  if ("ArrayExpression" == property.value.type) {
385
389
  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()
@@ -522,12 +522,12 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
522
522
  mainFunction.body.body.unshift(
523
523
  t.variableDeclaration(
524
524
  "let",
525
- [...neededSubscriptLets].map(name =>
525
+ [...neededSubscriptLets].map(([name, seclevel]) =>
526
526
  t.variableDeclarator(
527
527
  t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`),
528
528
  t.arrowFunctionExpression(
529
529
  [t.restElement(t.identifier("args"))],
530
- t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$${name}$`), [
530
+ t.callExpression(t.identifier(`$${uniqueId}$${seclevel}$SUBSCRIPT$${name}$`), [
531
531
  t.spreadElement(t.identifier("args"))
532
532
  ])
533
533
  )
@@ -631,7 +631,9 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
631
631
  VariableDeclaration({ node: variableDeclaration }) {
632
632
  "const" == variableDeclaration.kind && (variableDeclaration.kind = "let")
633
633
  },
634
- ThisExpression: path => path.replaceWith(t.identifier("undefined")),
634
+ ThisExpression: path => {
635
+ path.replaceWith(t.identifier("undefined"))
636
+ },
635
637
  BigIntLiteral(path) {
636
638
  const bigIntAsNumber = Number(path.node.value)
637
639
  path.replaceWith(
@@ -659,36 +661,37 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr
659
661
  t.identifier("prototype")
660
662
  )
661
663
  }
662
- function processFakeSubscriptObject(fakeSubscriptObjectName) {
664
+ function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
663
665
  for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
664
- assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:783:60")
666
+ assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:785:60")
665
667
  assert("Identifier" == referencePath.parent.property.type)
666
668
  assert(
667
669
  "MemberExpression" == referencePath.parentPath.parentPath?.node.type,
668
- "src/processScript/transform.ts:785:81"
670
+ "src/processScript/transform.ts:787:81"
669
671
  )
670
672
  assert(
671
673
  "Identifier" == referencePath.parentPath.parentPath.node.property.type,
672
- "src/processScript/transform.ts:786:83"
674
+ "src/processScript/transform.ts:788:83"
673
675
  )
674
676
  assert(
675
677
  /^[_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`
678
+ `src/processScript/transform.ts:792:8 invalid user "${referencePath.parent.property.name}" in subscript`
677
679
  )
678
680
  assert(
679
681
  /^[_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`
682
+ `src/processScript/transform.ts:797:8 invalid script name "${referencePath.parentPath.parentPath.node.property.name}" in subscript`
681
683
  )
682
684
  if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
683
685
  referencePath.parentPath.parentPath.replaceWith(
684
686
  t.identifier(
685
- `$${uniqueId}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
687
+ `$${uniqueId}$${seclevel}$SUBSCRIPT$${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}$`
686
688
  )
687
689
  )
688
690
  else {
689
691
  const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
690
692
  referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
691
- neededSubscriptLets.add(name)
693
+ const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
694
+ neededSubscriptLets.set(name, maxSecLevel)
692
695
  }
693
696
  }
694
697
  }
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 }