hackmud-script-manager 0.20.4-abe4703 → 0.20.4-b779329
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.
- package/bin/hsm.js +170 -233
 - package/env.d.ts +102 -21
 - package/package.json +1 -1
 - package/processScript/index.js +1 -1
 - package/processScript/minify.js +6 -3
 - package/processScript/postprocess.d.ts +1 -1
 - package/processScript/postprocess.js +3 -3
 - package/processScript/transform.js +12 -11
 - package/push.d.ts +9 -1
 - package/push.js +30 -10
 
    
        package/bin/hsm.js
    CHANGED
    
    | 
         @@ -5,14 +5,14 @@ import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters" 
     | 
|
| 
       5 
5 
     | 
    
         
             
            import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
         
     | 
| 
       6 
6 
     | 
    
         
             
            import { writeFile, readFile } from "fs/promises"
         
     | 
| 
       7 
7 
     | 
    
         
             
            import { homedir } from "os"
         
     | 
| 
       8 
     | 
    
         
            -
            import { extname, basename,  
     | 
| 
      
 8 
     | 
    
         
            +
            import { resolve, extname, basename, dirname, relative } from "path"
         
     | 
| 
       9 
9 
     | 
    
         
             
            import { supportedExtensions } from "../constants.js"
         
     | 
| 
       10 
10 
     | 
    
         
             
            import { generateTypeDeclaration } from "../generateTypeDeclaration.js"
         
     | 
| 
       11 
11 
     | 
    
         
             
            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- 
     | 
| 
      
 15 
     | 
    
         
            +
            const version = "0.20.4-b779329",
         
     | 
| 
       16 
16 
     | 
    
         
             
            	options = new Map(),
         
     | 
| 
       17 
17 
     | 
    
         
             
            	commands = [],
         
     | 
| 
       18 
18 
     | 
    
         
             
            	userColours = new Cache(user => {
         
     | 
| 
         @@ -36,10 +36,6 @@ for (const argument of process.argv.slice(2)) 
     | 
|
| 
       36 
36 
     | 
    
         
             
            		if ("-" == argument[1]) options.set(key.slice(2), value)
         
     | 
| 
       37 
37 
     | 
    
         
             
            		else for (const option of key.slice(1)) options.set(option, value)
         
     | 
| 
       38 
38 
     | 
    
         
             
            	} else commands.push(argument)
         
     | 
| 
       39 
     | 
    
         
            -
            if ("v" == commands[0] || "version" == commands[0] || options.get("version") || options.get("v")) {
         
     | 
| 
       40 
     | 
    
         
            -
            	console.log(version)
         
     | 
| 
       41 
     | 
    
         
            -
            	process.exit()
         
     | 
| 
       42 
     | 
    
         
            -
            }
         
     | 
| 
       43 
39 
     | 
    
         
             
            const pushModule = import("../push.js"),
         
     | 
| 
       44 
40 
     | 
    
         
             
            	processScriptModule = import("../processScript/index.js"),
         
     | 
| 
       45 
41 
     | 
    
         
             
            	watchModule = import("../watch.js"),
         
     | 
| 
         @@ -57,153 +53,163 @@ const pushModule = import("../push.js"), 
     | 
|
| 
       57 
53 
     | 
    
         
             
            	colourS = chalk.rgb(122, 178, 244),
         
     | 
| 
       58 
54 
     | 
    
         
             
            	colourV = chalk.rgb(255, 0, 236),
         
     | 
| 
       59 
55 
     | 
    
         
             
            	colourW = chalk.rgb(255, 150, 224)
         
     | 
| 
       60 
     | 
    
         
            -
            if ( 
     | 
| 
      
 56 
     | 
    
         
            +
            if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
         
     | 
| 
      
 57 
     | 
    
         
            +
            	console.log(version)
         
     | 
| 
      
 58 
     | 
    
         
            +
            	process.exit()
         
     | 
| 
      
 59 
     | 
    
         
            +
            }
         
     | 
| 
      
 60 
     | 
    
         
            +
            if (popOption("help", "h")?.value) {
         
     | 
| 
       61 
61 
     | 
    
         
             
            	logHelp()
         
     | 
| 
       62 
62 
     | 
    
         
             
            	process.exit()
         
     | 
| 
       63 
63 
     | 
    
         
             
            }
         
     | 
| 
       64 
64 
     | 
    
         
             
            let autoExit = !0
         
     | 
| 
       65 
65 
     | 
    
         
             
            switch (commands[0]) {
         
     | 
| 
       66 
66 
     | 
    
         
             
            	case "push":
         
     | 
| 
      
 67 
     | 
    
         
            +
            	case "dev":
         
     | 
| 
      
 68 
     | 
    
         
            +
            	case "watch":
         
     | 
| 
      
 69 
     | 
    
         
            +
            	case "golf":
         
     | 
| 
      
 70 
     | 
    
         
            +
            	case "minify":
         
     | 
| 
       67 
71 
     | 
    
         
             
            		{
         
     | 
| 
       68 
     | 
    
         
            -
            			const  
     | 
| 
       69 
     | 
    
         
            -
            				 
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
            				 
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
            				break
         
     | 
| 
       74 
     | 
    
         
            -
            			}
         
     | 
| 
       75 
     | 
    
         
            -
            			const scripts = commands.slice(2)
         
     | 
| 
       76 
     | 
    
         
            -
            			if (scripts.length) {
         
     | 
| 
       77 
     | 
    
         
            -
            				const invalidScript = scripts.find(
         
     | 
| 
       78 
     | 
    
         
            -
            					script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
         
     | 
| 
       79 
     | 
    
         
            -
            				)
         
     | 
| 
       80 
     | 
    
         
            -
            				if (invalidScript) {
         
     | 
| 
       81 
     | 
    
         
            -
            					logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
         
     | 
| 
       82 
     | 
    
         
            -
            					logHelp()
         
     | 
| 
       83 
     | 
    
         
            -
            					break
         
     | 
| 
       84 
     | 
    
         
            -
            				}
         
     | 
| 
       85 
     | 
    
         
            -
            			} else scripts.push("*.*")
         
     | 
| 
       86 
     | 
    
         
            -
            			const optionsHasNoMinify = options.has("no-minify")
         
     | 
| 
       87 
     | 
    
         
            -
            			if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
         
     | 
| 
      
 72 
     | 
    
         
            +
            			const noMinifyOption = popOption("no-minify", "skip-minify"),
         
     | 
| 
      
 73 
     | 
    
         
            +
            				mangleNamesOption = popOption("mangle-names"),
         
     | 
| 
      
 74 
     | 
    
         
            +
            				forceQuineCheatsOption = popOption("force-quine-cheats"),
         
     | 
| 
      
 75 
     | 
    
         
            +
            				noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
         
     | 
| 
      
 76 
     | 
    
         
            +
            			if (noMinifyOption && noMinifyIncompatibleOption) {
         
     | 
| 
       88 
77 
     | 
    
         
             
            				logError(
         
     | 
| 
       89 
     | 
    
         
            -
            					`Options ${colourN( 
     | 
| 
      
 78 
     | 
    
         
            +
            					`Options ${colourN(noMinifyOption.name)} and ${colourN(noMinifyIncompatibleOption.name)} are incompatible\n`
         
     | 
| 
       90 
79 
     | 
    
         
             
            				)
         
     | 
| 
       91 
80 
     | 
    
         
             
            				logHelp()
         
     | 
| 
       92 
     | 
    
         
            -
            				 
     | 
| 
      
 81 
     | 
    
         
            +
            				process.exit(1)
         
     | 
| 
       93 
82 
     | 
    
         
             
            			}
         
     | 
| 
       94 
     | 
    
         
            -
            			 
     | 
| 
       95 
     | 
    
         
            -
            			 
     | 
| 
       96 
     | 
    
         
            -
            			 
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
      
 83 
     | 
    
         
            +
            			noMinifyOption && assertOptionIsBoolean(noMinifyOption)
         
     | 
| 
      
 84 
     | 
    
         
            +
            			mangleNamesOption && assertOptionIsBoolean(mangleNamesOption)
         
     | 
| 
      
 85 
     | 
    
         
            +
            			forceQuineCheatsOption && assertOptionIsBoolean(forceQuineCheatsOption)
         
     | 
| 
      
 86 
     | 
    
         
            +
            			if ("golf" == commands[0] || "minify" == commands[0]) {
         
     | 
| 
      
 87 
     | 
    
         
            +
            				const watchOption = popOption("watch"),
         
     | 
| 
      
 88 
     | 
    
         
            +
            					target = commands[1]
         
     | 
| 
      
 89 
     | 
    
         
            +
            				if (!target) {
         
     | 
| 
      
 90 
     | 
    
         
            +
            					logError("Must provide target\n")
         
     | 
| 
      
 91 
     | 
    
         
            +
            					logHelp()
         
     | 
| 
      
 92 
     | 
    
         
            +
            					process.exit(1)
         
     | 
| 
      
 93 
     | 
    
         
            +
            				}
         
     | 
| 
      
 94 
     | 
    
         
            +
            				const fileExtension = extname(target)
         
     | 
| 
      
 95 
     | 
    
         
            +
            				if (!supportedExtensions.includes(fileExtension)) {
         
     | 
| 
       98 
96 
     | 
    
         
             
            					logError(
         
     | 
| 
       99 
     | 
    
         
            -
            						` 
     | 
| 
      
 97 
     | 
    
         
            +
            						`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`
         
     | 
| 
       100 
98 
     | 
    
         
             
            					)
         
     | 
| 
       101 
     | 
    
         
            -
            					 
     | 
| 
       102 
     | 
    
         
            -
            					break
         
     | 
| 
      
 99 
     | 
    
         
            +
            					process.exit(1)
         
     | 
| 
       103 
100 
     | 
    
         
             
            				}
         
     | 
| 
       104 
     | 
    
         
            -
            				 
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
            					 
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
            				if ( 
     | 
| 
       150 
     | 
    
         
            -
            					 
     | 
| 
      
 101 
     | 
    
         
            +
            				const { processScript } = await processScriptModule,
         
     | 
| 
      
 102 
     | 
    
         
            +
            					fileBaseName = basename(target, fileExtension),
         
     | 
| 
      
 103 
     | 
    
         
            +
            					fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
         
     | 
| 
      
 104 
     | 
    
         
            +
            					scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName,
         
     | 
| 
      
 105 
     | 
    
         
            +
            					scriptUser =
         
     | 
| 
      
 106 
     | 
    
         
            +
            						(
         
     | 
| 
      
 107 
     | 
    
         
            +
            							"scripts" == basename(resolve(target, "..")) &&
         
     | 
| 
      
 108 
     | 
    
         
            +
            							"hackmud" == basename(resolve(target, "../../.."))
         
     | 
| 
      
 109 
     | 
    
         
            +
            						) ?
         
     | 
| 
      
 110 
     | 
    
         
            +
            							basename(resolve(target, "../.."))
         
     | 
| 
      
 111 
     | 
    
         
            +
            						:	void 0
         
     | 
| 
      
 112 
     | 
    
         
            +
            				let outputPath =
         
     | 
| 
      
 113 
     | 
    
         
            +
            					commands[2] ||
         
     | 
| 
      
 114 
     | 
    
         
            +
            					resolve(
         
     | 
| 
      
 115 
     | 
    
         
            +
            						dirname(target),
         
     | 
| 
      
 116 
     | 
    
         
            +
            						fileBaseNameEndsWithDotSrc ? scriptName + ".js"
         
     | 
| 
      
 117 
     | 
    
         
            +
            						: ".js" == fileExtension ? fileBaseName + ".min.js"
         
     | 
| 
      
 118 
     | 
    
         
            +
            						: fileBaseName + ".js"
         
     | 
| 
      
 119 
     | 
    
         
            +
            					)
         
     | 
| 
      
 120 
     | 
    
         
            +
            				const golfFile = () =>
         
     | 
| 
      
 121 
     | 
    
         
            +
            					readFile(target, { encoding: "utf8" }).then(async source => {
         
     | 
| 
      
 122 
     | 
    
         
            +
            						const timeStart = performance.now(),
         
     | 
| 
      
 123 
     | 
    
         
            +
            							{ script, warnings } = await processScript(source, {
         
     | 
| 
      
 124 
     | 
    
         
            +
            								minify: noMinifyOption && !noMinifyOption.value,
         
     | 
| 
      
 125 
     | 
    
         
            +
            								scriptUser,
         
     | 
| 
      
 126 
     | 
    
         
            +
            								scriptName,
         
     | 
| 
      
 127 
     | 
    
         
            +
            								filePath: target,
         
     | 
| 
      
 128 
     | 
    
         
            +
            								mangleNames: mangleNamesOption?.value,
         
     | 
| 
      
 129 
     | 
    
         
            +
            								forceQuineCheats: forceQuineCheatsOption?.value
         
     | 
| 
      
 130 
     | 
    
         
            +
            							}),
         
     | 
| 
      
 131 
     | 
    
         
            +
            							timeTook = performance.now() - timeStart
         
     | 
| 
      
 132 
     | 
    
         
            +
            						for (const { message, line } of warnings)
         
     | 
| 
      
 133 
     | 
    
         
            +
            							log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
         
     | 
| 
      
 134 
     | 
    
         
            +
            						await writeFilePersistent(outputPath, script)
         
     | 
| 
      
 135 
     | 
    
         
            +
            							.catch(error => {
         
     | 
| 
      
 136 
     | 
    
         
            +
            								if (!commands[2] || "EISDIR" != error.code) throw error
         
     | 
| 
      
 137 
     | 
    
         
            +
            								outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
         
     | 
| 
      
 138 
     | 
    
         
            +
            								return writeFilePersistent(outputPath, script)
         
     | 
| 
      
 139 
     | 
    
         
            +
            							})
         
     | 
| 
      
 140 
     | 
    
         
            +
            							.then(() =>
         
     | 
| 
      
 141 
     | 
    
         
            +
            								log(
         
     | 
| 
      
 142 
     | 
    
         
            +
            									`Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
         
     | 
| 
      
 143 
     | 
    
         
            +
            								)
         
     | 
| 
      
 144 
     | 
    
         
            +
            							)
         
     | 
| 
      
 145 
     | 
    
         
            +
            					})
         
     | 
| 
      
 146 
     | 
    
         
            +
            				if (watchOption) {
         
     | 
| 
      
 147 
     | 
    
         
            +
            					const { watch: watchFile } = await chokidarModule
         
     | 
| 
      
 148 
     | 
    
         
            +
            					watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
         
     | 
| 
      
 149 
     | 
    
         
            +
            						.on("ready", () => log("Watching " + target))
         
     | 
| 
      
 150 
     | 
    
         
            +
            						.on("change", golfFile)
         
     | 
| 
      
 151 
     | 
    
         
            +
            					autoExit = !1
         
     | 
| 
      
 152 
     | 
    
         
            +
            				} else await golfFile()
         
     | 
| 
      
 153 
     | 
    
         
            +
            			} else {
         
     | 
| 
      
 154 
     | 
    
         
            +
            				const hackmudPath = getHackmudPath(),
         
     | 
| 
      
 155 
     | 
    
         
            +
            					sourcePath = commands[1]
         
     | 
| 
      
 156 
     | 
    
         
            +
            				if (!sourcePath) {
         
     | 
| 
      
 157 
     | 
    
         
            +
            					logError(`Must provide the directory to ${"push" == commands[0] ? "push from" : "watch"}\n`)
         
     | 
| 
       151 
158 
     | 
    
         
             
            					logHelp()
         
     | 
| 
       152 
     | 
    
         
            -
            					 
     | 
| 
      
 159 
     | 
    
         
            +
            					process.exit(1)
         
     | 
| 
       153 
160 
     | 
    
         
             
            				}
         
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
            					`Options ${colourN("--mangle-names")} and ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} are incompatible\n`
         
     | 
| 
       159 
     | 
    
         
            -
            				)
         
     | 
| 
       160 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       161 
     | 
    
         
            -
            				break
         
     | 
| 
       162 
     | 
    
         
            -
            			}
         
     | 
| 
       163 
     | 
    
         
            -
            			const shouldSkipMinify = options.get("no-minify") || options.get("skip-minify")
         
     | 
| 
       164 
     | 
    
         
            -
            			let shouldMinify
         
     | 
| 
       165 
     | 
    
         
            -
            			if (null != shouldSkipMinify) {
         
     | 
| 
       166 
     | 
    
         
            -
            				if ("boolean" != typeof shouldSkipMinify) {
         
     | 
| 
       167 
     | 
    
         
            -
            					logError(
         
     | 
| 
       168 
     | 
    
         
            -
            						`The value for ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} must be ${colourV("true")} or ${colourV("false")}\n`
         
     | 
| 
      
 161 
     | 
    
         
            +
            				const scripts = commands.slice(2)
         
     | 
| 
      
 162 
     | 
    
         
            +
            				if (scripts.length) {
         
     | 
| 
      
 163 
     | 
    
         
            +
            					const invalidScript = scripts.find(
         
     | 
| 
      
 164 
     | 
    
         
            +
            						script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script)
         
     | 
| 
       169 
165 
     | 
    
         
             
            					)
         
     | 
| 
       170 
     | 
    
         
            -
            					 
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
      
 166 
     | 
    
         
            +
            					if (invalidScript) {
         
     | 
| 
      
 167 
     | 
    
         
            +
            						logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`)
         
     | 
| 
      
 168 
     | 
    
         
            +
            						logHelp()
         
     | 
| 
      
 169 
     | 
    
         
            +
            						process.exit(1)
         
     | 
| 
      
 170 
     | 
    
         
            +
            					}
         
     | 
| 
      
 171 
     | 
    
         
            +
            				} else scripts.push("*.*")
         
     | 
| 
      
 172 
     | 
    
         
            +
            				if ("push" == commands[0]) {
         
     | 
| 
      
 173 
     | 
    
         
            +
            					const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } =
         
     | 
| 
      
 174 
     | 
    
         
            +
            							await pushModule,
         
     | 
| 
      
 175 
     | 
    
         
            +
            						infos = await push(sourcePath, hackmudPath, {
         
     | 
| 
      
 176 
     | 
    
         
            +
            							scripts,
         
     | 
| 
      
 177 
     | 
    
         
            +
            							onPush: info => logInfo(info, hackmudPath),
         
     | 
| 
      
 178 
     | 
    
         
            +
            							minify: noMinifyOption && !noMinifyOption.value,
         
     | 
| 
      
 179 
     | 
    
         
            +
            							mangleNames: mangleNamesOption?.value,
         
     | 
| 
      
 180 
     | 
    
         
            +
            							forceQuineCheats: forceQuineCheatsOption?.value
         
     | 
| 
      
 181 
     | 
    
         
            +
            						})
         
     | 
| 
      
 182 
     | 
    
         
            +
            					if (infos instanceof Error) {
         
     | 
| 
      
 183 
     | 
    
         
            +
            						logError(infos.message)
         
     | 
| 
      
 184 
     | 
    
         
            +
            						if (infos instanceof MissingSourceFolderError || infos instanceof NoUsersError) {
         
     | 
| 
      
 185 
     | 
    
         
            +
            							console.log()
         
     | 
| 
      
 186 
     | 
    
         
            +
            							logHelp()
         
     | 
| 
      
 187 
     | 
    
         
            +
            						} else
         
     | 
| 
      
 188 
     | 
    
         
            +
            							infos instanceof MissingHackmudFolderError &&
         
     | 
| 
      
 189 
     | 
    
         
            +
            								log(
         
     | 
| 
      
 190 
     | 
    
         
            +
            									`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`
         
     | 
| 
      
 191 
     | 
    
         
            +
            								)
         
     | 
| 
      
 192 
     | 
    
         
            +
            					} else infos.length || logError("Could not find any scripts to push")
         
     | 
| 
      
 193 
     | 
    
         
            +
            				} else {
         
     | 
| 
      
 194 
     | 
    
         
            +
            					const typeDeclarationPathOption = popOption(
         
     | 
| 
      
 195 
     | 
    
         
            +
            							"type-declaration-path",
         
     | 
| 
      
 196 
     | 
    
         
            +
            							"type-declaration",
         
     | 
| 
      
 197 
     | 
    
         
            +
            							"dts",
         
     | 
| 
      
 198 
     | 
    
         
            +
            							"gen-types"
         
     | 
| 
      
 199 
     | 
    
         
            +
            						),
         
     | 
| 
      
 200 
     | 
    
         
            +
            						{ watch } = await watchModule
         
     | 
| 
      
 201 
     | 
    
         
            +
            					watch(sourcePath, hackmudPath, {
         
     | 
| 
      
 202 
     | 
    
         
            +
            						scripts,
         
     | 
| 
      
 203 
     | 
    
         
            +
            						onPush: info => logInfo(info, hackmudPath),
         
     | 
| 
      
 204 
     | 
    
         
            +
            						typeDeclarationPath: typeDeclarationPathOption?.value.toString(),
         
     | 
| 
      
 205 
     | 
    
         
            +
            						minify: noMinifyOption && !noMinifyOption.value,
         
     | 
| 
      
 206 
     | 
    
         
            +
            						mangleNames: mangleNamesOption?.value,
         
     | 
| 
      
 207 
     | 
    
         
            +
            						onReady: () => log("Watching"),
         
     | 
| 
      
 208 
     | 
    
         
            +
            						forceQuineCheats: forceQuineCheatsOption?.value
         
     | 
| 
      
 209 
     | 
    
         
            +
            					})
         
     | 
| 
      
 210 
     | 
    
         
            +
            					autoExit = !1
         
     | 
| 
       172 
211 
     | 
    
         
             
            				}
         
     | 
| 
       173 
     | 
    
         
            -
            				shouldMinify = !shouldSkipMinify
         
     | 
| 
       174 
212 
     | 
    
         
             
            			}
         
     | 
| 
       175 
     | 
    
         
            -
            			const shouldMangleNames = options.get("mangle-names")
         
     | 
| 
       176 
     | 
    
         
            -
            			if (null != shouldMangleNames && "boolean" != typeof shouldMangleNames) {
         
     | 
| 
       177 
     | 
    
         
            -
            				logError(
         
     | 
| 
       178 
     | 
    
         
            -
            					`The value for ${colourN("--mangle-names")} must be ${colourV("true")} or ${colourV("false")}\n`
         
     | 
| 
       179 
     | 
    
         
            -
            				)
         
     | 
| 
       180 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       181 
     | 
    
         
            -
            				break
         
     | 
| 
       182 
     | 
    
         
            -
            			}
         
     | 
| 
       183 
     | 
    
         
            -
            			const shouldforceQuineCheats = options.get("force-quine-cheats")
         
     | 
| 
       184 
     | 
    
         
            -
            			if (null != shouldforceQuineCheats && "boolean" != typeof shouldforceQuineCheats) {
         
     | 
| 
       185 
     | 
    
         
            -
            				logError(
         
     | 
| 
       186 
     | 
    
         
            -
            					`The value for ${colourN("--force-quine-cheats")} must be ${colourV("true")} or ${colourV("false")}\n`
         
     | 
| 
       187 
     | 
    
         
            -
            				)
         
     | 
| 
       188 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       189 
     | 
    
         
            -
            				break
         
     | 
| 
       190 
     | 
    
         
            -
            			}
         
     | 
| 
       191 
     | 
    
         
            -
            			const { watch } = await watchModule
         
     | 
| 
       192 
     | 
    
         
            -
            			watch(sourcePath, hackmudPath, {
         
     | 
| 
       193 
     | 
    
         
            -
            				scripts,
         
     | 
| 
       194 
     | 
    
         
            -
            				onPush: info => logInfo(info, hackmudPath),
         
     | 
| 
       195 
     | 
    
         
            -
            				typeDeclarationPath: (
         
     | 
| 
       196 
     | 
    
         
            -
            					options.get("type-declaration-path") ||
         
     | 
| 
       197 
     | 
    
         
            -
            					options.get("type-declaration") ||
         
     | 
| 
       198 
     | 
    
         
            -
            					options.get("dts") ||
         
     | 
| 
       199 
     | 
    
         
            -
            					options.get("gen-types")
         
     | 
| 
       200 
     | 
    
         
            -
            				)?.toString(),
         
     | 
| 
       201 
     | 
    
         
            -
            				minify: shouldMinify,
         
     | 
| 
       202 
     | 
    
         
            -
            				mangleNames: shouldMangleNames,
         
     | 
| 
       203 
     | 
    
         
            -
            				onReady: () => log("Watching"),
         
     | 
| 
       204 
     | 
    
         
            -
            				forceQuineCheats: shouldforceQuineCheats
         
     | 
| 
       205 
     | 
    
         
            -
            			})
         
     | 
| 
       206 
     | 
    
         
            -
            			autoExit = !1
         
     | 
| 
       207 
213 
     | 
    
         
             
            		}
         
     | 
| 
       208 
214 
     | 
    
         
             
            		break
         
     | 
| 
       209 
215 
     | 
    
         
             
            	case "pull":
         
     | 
| 
         @@ -213,7 +219,7 @@ switch (commands[0]) { 
     | 
|
| 
       213 
219 
     | 
    
         
             
            			if (!script) {
         
     | 
| 
       214 
220 
     | 
    
         
             
            				logError("Must provide the script to pull\n")
         
     | 
| 
       215 
221 
     | 
    
         
             
            				logHelp()
         
     | 
| 
       216 
     | 
    
         
            -
            				 
     | 
| 
      
 222 
     | 
    
         
            +
            				process.exit(1)
         
     | 
| 
       217 
223 
     | 
    
         
             
            			}
         
     | 
| 
       218 
224 
     | 
    
         
             
            			const sourcePath = commands[2] || "."
         
     | 
| 
       219 
225 
     | 
    
         
             
            			await pull(sourcePath, hackmudPath, script).catch(error => {
         
     | 
| 
         @@ -234,18 +240,19 @@ switch (commands[0]) { 
     | 
|
| 
       234 
240 
     | 
    
         
             
            	case "gen-dts":
         
     | 
| 
       235 
241 
     | 
    
         
             
            	case "gen-types":
         
     | 
| 
       236 
242 
     | 
    
         
             
            		{
         
     | 
| 
       237 
     | 
    
         
            -
            			const  
     | 
| 
      
 243 
     | 
    
         
            +
            			const hackmudPath = getHackmudPath(),
         
     | 
| 
      
 244 
     | 
    
         
            +
            				target = commands[1]
         
     | 
| 
       238 
245 
     | 
    
         
             
            			if (!target) {
         
     | 
| 
       239 
246 
     | 
    
         
             
            				logError("Must provide target directory\n")
         
     | 
| 
       240 
247 
     | 
    
         
             
            				logHelp()
         
     | 
| 
       241 
     | 
    
         
            -
            				 
     | 
| 
      
 248 
     | 
    
         
            +
            				process.exit(1)
         
     | 
| 
       242 
249 
     | 
    
         
             
            			}
         
     | 
| 
       243 
250 
     | 
    
         
             
            			const sourcePath = resolve(target),
         
     | 
| 
       244 
251 
     | 
    
         
             
            				outputPath = commands[2] || "./player.d.ts",
         
     | 
| 
       245 
     | 
    
         
            -
            				typeDeclaration = await generateTypeDeclaration(sourcePath,  
     | 
| 
      
 252 
     | 
    
         
            +
            				typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
         
     | 
| 
       246 
253 
     | 
    
         
             
            			let typeDeclarationPath = resolve(outputPath)
         
     | 
| 
       247 
254 
     | 
    
         
             
            			await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
         
     | 
| 
       248 
     | 
    
         
            -
            				assert(error instanceof Error, "src/bin/hsm.ts: 
     | 
| 
      
 255 
     | 
    
         
            +
            				assert(error instanceof Error, "src/bin/hsm.ts:321:35")
         
     | 
| 
       249 
256 
     | 
    
         
             
            				if ("EISDIR" != error.code) throw error
         
     | 
| 
       250 
257 
     | 
    
         
             
            				typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
         
     | 
| 
       251 
258 
     | 
    
         
             
            				return writeFile(typeDeclarationPath, typeDeclaration)
         
     | 
| 
         @@ -257,99 +264,6 @@ switch (commands[0]) { 
     | 
|
| 
       257 
264 
     | 
    
         
             
            	case "h":
         
     | 
| 
       258 
265 
     | 
    
         
             
            		logHelp()
         
     | 
| 
       259 
266 
     | 
    
         
             
            		break
         
     | 
| 
       260 
     | 
    
         
            -
            	case "golf":
         
     | 
| 
       261 
     | 
    
         
            -
            	case "minify":
         
     | 
| 
       262 
     | 
    
         
            -
            		{
         
     | 
| 
       263 
     | 
    
         
            -
            			const target = commands[1]
         
     | 
| 
       264 
     | 
    
         
            -
            			if (!target) {
         
     | 
| 
       265 
     | 
    
         
            -
            				logError("Must provide target\n")
         
     | 
| 
       266 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       267 
     | 
    
         
            -
            				break
         
     | 
| 
       268 
     | 
    
         
            -
            			}
         
     | 
| 
       269 
     | 
    
         
            -
            			const fileExtension = extname(target)
         
     | 
| 
       270 
     | 
    
         
            -
            			if (!supportedExtensions.includes(fileExtension)) {
         
     | 
| 
       271 
     | 
    
         
            -
            				logError(
         
     | 
| 
       272 
     | 
    
         
            -
            					`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`
         
     | 
| 
       273 
     | 
    
         
            -
            				)
         
     | 
| 
       274 
     | 
    
         
            -
            				break
         
     | 
| 
       275 
     | 
    
         
            -
            			}
         
     | 
| 
       276 
     | 
    
         
            -
            			const { processScript } = await processScriptModule,
         
     | 
| 
       277 
     | 
    
         
            -
            				fileBaseName = basename(target, fileExtension),
         
     | 
| 
       278 
     | 
    
         
            -
            				fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
         
     | 
| 
       279 
     | 
    
         
            -
            				scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName,
         
     | 
| 
       280 
     | 
    
         
            -
            				scriptUser =
         
     | 
| 
       281 
     | 
    
         
            -
            					"scripts" == basename(resolve(target, "..")) && "hackmud" == basename(resolve(target, "../../..")) ?
         
     | 
| 
       282 
     | 
    
         
            -
            						basename(resolve(target, "../.."))
         
     | 
| 
       283 
     | 
    
         
            -
            					:	void 0,
         
     | 
| 
       284 
     | 
    
         
            -
            				optionsHasNoMinify = options.has("no-minify")
         
     | 
| 
       285 
     | 
    
         
            -
            			if ((optionsHasNoMinify || options.has("skip-minify")) && options.has("mangle-names")) {
         
     | 
| 
       286 
     | 
    
         
            -
            				logError(
         
     | 
| 
       287 
     | 
    
         
            -
            					`Options ${colourN("--mangle-names")} and ${colourN(optionsHasNoMinify ? "--no-minify" : "--skip-minify")} are incompatible\n`
         
     | 
| 
       288 
     | 
    
         
            -
            				)
         
     | 
| 
       289 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       290 
     | 
    
         
            -
            				break
         
     | 
| 
       291 
     | 
    
         
            -
            			}
         
     | 
| 
       292 
     | 
    
         
            -
            			const mangleNames_ = options.get("mangle-names")
         
     | 
| 
       293 
     | 
    
         
            -
            			if (null != mangleNames_ && "boolean" != typeof mangleNames_) {
         
     | 
| 
       294 
     | 
    
         
            -
            				logError(
         
     | 
| 
       295 
     | 
    
         
            -
            					`The value for ${colourN("--mangle-names")} must be ${colourV("true")} or ${colourV("false")}\n`
         
     | 
| 
       296 
     | 
    
         
            -
            				)
         
     | 
| 
       297 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       298 
     | 
    
         
            -
            				break
         
     | 
| 
       299 
     | 
    
         
            -
            			}
         
     | 
| 
       300 
     | 
    
         
            -
            			const mangleNames = mangleNames_,
         
     | 
| 
       301 
     | 
    
         
            -
            				forceQuineCheats_ = options.get("force-quine-cheats")
         
     | 
| 
       302 
     | 
    
         
            -
            			if (null != forceQuineCheats_ && "boolean" != typeof forceQuineCheats_) {
         
     | 
| 
       303 
     | 
    
         
            -
            				logError(
         
     | 
| 
       304 
     | 
    
         
            -
            					`the value for ${colourN("--force-quine-cheats")} must be ${colourV("true")} or ${colourV("false")}\n`
         
     | 
| 
       305 
     | 
    
         
            -
            				)
         
     | 
| 
       306 
     | 
    
         
            -
            				logHelp()
         
     | 
| 
       307 
     | 
    
         
            -
            				break
         
     | 
| 
       308 
     | 
    
         
            -
            			}
         
     | 
| 
       309 
     | 
    
         
            -
            			const forceQuineCheats = forceQuineCheats_
         
     | 
| 
       310 
     | 
    
         
            -
            			let outputPath =
         
     | 
| 
       311 
     | 
    
         
            -
            				commands[2] ||
         
     | 
| 
       312 
     | 
    
         
            -
            				resolve(
         
     | 
| 
       313 
     | 
    
         
            -
            					dirname(target),
         
     | 
| 
       314 
     | 
    
         
            -
            					fileBaseNameEndsWithDotSrc ? scriptName + ".js"
         
     | 
| 
       315 
     | 
    
         
            -
            					: ".js" == fileExtension ? fileBaseName + ".min.js"
         
     | 
| 
       316 
     | 
    
         
            -
            					: fileBaseName + ".js"
         
     | 
| 
       317 
     | 
    
         
            -
            				)
         
     | 
| 
       318 
     | 
    
         
            -
            			const golfFile = () =>
         
     | 
| 
       319 
     | 
    
         
            -
            				readFile(target, { encoding: "utf8" }).then(async source => {
         
     | 
| 
       320 
     | 
    
         
            -
            					const timeStart = performance.now(),
         
     | 
| 
       321 
     | 
    
         
            -
            						{ script, warnings } = await processScript(source, {
         
     | 
| 
       322 
     | 
    
         
            -
            							minify: !(options.get("no-minify") || options.get("skip-minify")),
         
     | 
| 
       323 
     | 
    
         
            -
            							scriptUser,
         
     | 
| 
       324 
     | 
    
         
            -
            							scriptName,
         
     | 
| 
       325 
     | 
    
         
            -
            							filePath: target,
         
     | 
| 
       326 
     | 
    
         
            -
            							mangleNames,
         
     | 
| 
       327 
     | 
    
         
            -
            							forceQuineCheats
         
     | 
| 
       328 
     | 
    
         
            -
            						}),
         
     | 
| 
       329 
     | 
    
         
            -
            						timeTook = performance.now() - timeStart
         
     | 
| 
       330 
     | 
    
         
            -
            					for (const { message, line } of warnings)
         
     | 
| 
       331 
     | 
    
         
            -
            						log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(line + "")}`)
         
     | 
| 
       332 
     | 
    
         
            -
            					await writeFilePersistent(outputPath, script)
         
     | 
| 
       333 
     | 
    
         
            -
            						.catch(error => {
         
     | 
| 
       334 
     | 
    
         
            -
            							if (!commands[2] || "EISDIR" != error.code) throw error
         
     | 
| 
       335 
     | 
    
         
            -
            							outputPath = resolve(outputPath, basename(target, fileExtension) + ".js")
         
     | 
| 
       336 
     | 
    
         
            -
            							return writeFilePersistent(outputPath, script)
         
     | 
| 
       337 
     | 
    
         
            -
            						})
         
     | 
| 
       338 
     | 
    
         
            -
            						.then(() =>
         
     | 
| 
       339 
     | 
    
         
            -
            							log(
         
     | 
| 
       340 
     | 
    
         
            -
            								`Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(".", outputPath))} | took ${Math.round(100 * timeTook) / 100}ms`
         
     | 
| 
       341 
     | 
    
         
            -
            							)
         
     | 
| 
       342 
     | 
    
         
            -
            						)
         
     | 
| 
       343 
     | 
    
         
            -
            				})
         
     | 
| 
       344 
     | 
    
         
            -
            			if (options.get("watch")) {
         
     | 
| 
       345 
     | 
    
         
            -
            				const { watch: watchFile } = await chokidarModule
         
     | 
| 
       346 
     | 
    
         
            -
            				watchFile(target, { awaitWriteFinish: { stabilityThreshold: 100 } })
         
     | 
| 
       347 
     | 
    
         
            -
            					.on("ready", () => log("Watching " + target))
         
     | 
| 
       348 
     | 
    
         
            -
            					.on("change", golfFile)
         
     | 
| 
       349 
     | 
    
         
            -
            				autoExit = !1
         
     | 
| 
       350 
     | 
    
         
            -
            			} else await golfFile()
         
     | 
| 
       351 
     | 
    
         
            -
            		}
         
     | 
| 
       352 
     | 
    
         
            -
            		break
         
     | 
| 
       353 
267 
     | 
    
         
             
            	default:
         
     | 
| 
       354 
268 
     | 
    
         
             
            		commands[0] && logError(`Unknown command: ${colourL(commands[0])}\n`)
         
     | 
| 
       355 
269 
     | 
    
         
             
            		logHelp()
         
     | 
| 
         @@ -423,7 +337,7 @@ function logError(message) { 
     | 
|
| 
       423 
337 
     | 
    
         
             
            	process.exitCode = 1
         
     | 
| 
       424 
338 
     | 
    
         
             
            }
         
     | 
| 
       425 
339 
     | 
    
         
             
            function getHackmudPath() {
         
     | 
| 
       426 
     | 
    
         
            -
            	const hackmudPathOption =  
     | 
| 
      
 340 
     | 
    
         
            +
            	const hackmudPathOption = popOption("hackmud-path")
         
     | 
| 
       427 
341 
     | 
    
         
             
            	if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
         
     | 
| 
       428 
342 
     | 
    
         
             
            		logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
         
     | 
| 
       429 
343 
     | 
    
         
             
            		logHelp()
         
     | 
| 
         @@ -435,3 +349,26 @@ function getHackmudPath() { 
     | 
|
| 
       435 
349 
     | 
    
         
             
            		("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
         
     | 
| 
       436 
350 
     | 
    
         
             
            	)
         
     | 
| 
       437 
351 
     | 
    
         
             
            }
         
     | 
| 
      
 352 
     | 
    
         
            +
            function assertOptionIsBoolean(option) {
         
     | 
| 
      
 353 
     | 
    
         
            +
            	if ("boolean" != typeof option.value) {
         
     | 
| 
      
 354 
     | 
    
         
            +
            		logError(`The value for ${colourN(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
         
     | 
| 
      
 355 
     | 
    
         
            +
            		logHelp()
         
     | 
| 
      
 356 
     | 
    
         
            +
            		process.exit(1)
         
     | 
| 
      
 357 
     | 
    
         
            +
            	}
         
     | 
| 
      
 358 
     | 
    
         
            +
            }
         
     | 
| 
      
 359 
     | 
    
         
            +
            function popOption(...names) {
         
     | 
| 
      
 360 
     | 
    
         
            +
            	const presentOptionNames = names.filter(name => options.has(name))
         
     | 
| 
      
 361 
     | 
    
         
            +
            	if (!presentOptionNames.length) return
         
     | 
| 
      
 362 
     | 
    
         
            +
            	const presentOptionNamesWithDashDash = presentOptionNames.map(name =>
         
     | 
| 
      
 363 
     | 
    
         
            +
            		colourN(`-${1 == name.length ? "" : "-"}${name}`)
         
     | 
| 
      
 364 
     | 
    
         
            +
            	)
         
     | 
| 
      
 365 
     | 
    
         
            +
            	if (presentOptionNames.length > 1) {
         
     | 
| 
      
 366 
     | 
    
         
            +
            		logError(
         
     | 
| 
      
 367 
     | 
    
         
            +
            			`The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
         
     | 
| 
      
 368 
     | 
    
         
            +
            		)
         
     | 
| 
      
 369 
     | 
    
         
            +
            		process.exit(1)
         
     | 
| 
      
 370 
     | 
    
         
            +
            	}
         
     | 
| 
      
 371 
     | 
    
         
            +
            	const value = options.get(presentOptionNames[0])
         
     | 
| 
      
 372 
     | 
    
         
            +
            	options.delete(presentOptionNames[0])
         
     | 
| 
      
 373 
     | 
    
         
            +
            	return { name: presentOptionNamesWithDashDash[0], value }
         
     | 
| 
      
 374 
     | 
    
         
            +
            }
         
     | 
    
        package/env.d.ts
    CHANGED
    
    | 
         @@ -4,6 +4,13 @@ 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> = { [K in keyof T]-?: {} extends Pick<T, K> ? true : false }[keyof T]
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            type Scriptor<Args = unknown, Ret = unknown> = {
         
     | 
| 
      
 10 
     | 
    
         
            +
            	name: string
         
     | 
| 
      
 11 
     | 
    
         
            +
            	call: AllOptional<Args> extends true ? (args?: Args) => Ret : (args: Args) => Ret
         
     | 
| 
      
 12 
     | 
    
         
            +
            }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
       7 
14 
     | 
    
         
             
            type Subscripts = Record<string, Record<string, (...args: any) => any>> & {
         
     | 
| 
       8 
15 
     | 
    
         
             
            	accts: ErrorScripts
         
     | 
| 
       9 
16 
     | 
    
         
             
            	autos: ErrorScripts
         
     | 
| 
         @@ -26,23 +33,27 @@ interface PlayerMidsec {} 
     | 
|
| 
       26 
33 
     | 
    
         
             
            interface PlayerLowsec {}
         
     | 
| 
       27 
34 
     | 
    
         
             
            interface PlayerNullsec {}
         
     | 
| 
       28 
35 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
            type  
     | 
| 
      
 36 
     | 
    
         
            +
            type UpgradeRarityString = "`0noob`" | "`1kiddie`" | "`2h4x0r`" | "`3h4rdc0r3`" | "`4|_|b3|2`" | "`531337`"
         
     | 
| 
      
 37 
     | 
    
         
            +
            type UpgradeRarityNumber = 0 | 1 | 2 | 3 | 4 | 5;
         
     | 
| 
      
 38 
     | 
    
         
            +
            type UpgradeRarity = UpgradeRarityString | UpgradeRarityNumber;
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            type UpgradeBase = {
         
     | 
| 
       30 
41 
     | 
    
         
             
            	name: string
         
     | 
| 
       31 
42 
     | 
    
         
             
            	type: "lock" | "script_space" | "chat" | "script" | "tool" | "bot_brain" | "glam"
         
     | 
| 
       32 
43 
     | 
    
         
             
            	up_class?: -1 | 0 | 1 | 2 | 3
         
     | 
| 
       33 
44 
     | 
    
         
             
            	tier: 1 | 2 | 3 | 4
         
     | 
| 
       34 
     | 
    
         
            -
            	rarity:  
     | 
| 
      
 45 
     | 
    
         
            +
            	rarity: UpgradeRarityNumber
         
     | 
| 
       35 
46 
     | 
    
         
             
            	i: number
         
     | 
| 
       36 
47 
     | 
    
         
             
            	loaded: boolean
         
     | 
| 
       37 
48 
     | 
    
         
             
            	sn: string
         
     | 
| 
       38 
49 
     | 
    
         
             
            	description: string
         
     | 
| 
       39 
50 
     | 
    
         
             
            }
         
     | 
| 
       40 
51 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
            type Upgrade =  
     | 
| 
      
 52 
     | 
    
         
            +
            type Upgrade = UpgradeBase & Record<string, null | boolean | number | string>
         
     | 
| 
       42 
53 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
            type  
     | 
| 
      
 54 
     | 
    
         
            +
            type CliUpgrade = Omit<UpgradeBase, `rarity`> & {
         
     | 
| 
       44 
55 
     | 
    
         
             
            	[x: string]: null | boolean | number | string
         
     | 
| 
       45 
     | 
    
         
            -
            	rarity:  
     | 
| 
      
 56 
     | 
    
         
            +
            	rarity: UpgradeRarityString
         
     | 
| 
       46 
57 
     | 
    
         
             
            }
         
     | 
| 
       47 
58 
     | 
    
         | 
| 
       48 
59 
     | 
    
         
             
            type UsersTopItem<R> = { rank: R, name: string, last_activity: string, balance: string }
         
     | 
| 
         @@ -140,7 +151,16 @@ type Fullsec = Subscripts & PlayerFullsec & { 
     | 
|
| 
       140 
151 
     | 
    
         
             
            	market: {
         
     | 
| 
       141 
152 
     | 
    
         
             
            		/** **FULLSEC** */ browse: {
         
     | 
| 
       142 
153 
     | 
    
         
             
            			(args:
         
     | 
| 
       143 
     | 
    
         
            -
            				Partial<{ 
     | 
| 
      
 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">>
         
     | 
| 
       144 
164 
     | 
    
         
             
            			): { i: string, name: string, rarity: Upgrade["rarity"], cost: number }[] | ScriptFailure
         
     | 
| 
       145 
165 
     | 
    
         | 
| 
       146 
166 
     | 
    
         
             
            			<I extends string>(args: { i: I }): {
         
     | 
| 
         @@ -409,17 +429,17 @@ type Fullsec = Subscripts & PlayerFullsec & { 
     | 
|
| 
       409 
429 
     | 
    
         
             
            		upgrades_of_owner: {
         
     | 
| 
       410 
430 
     | 
    
         
             
            			<F extends Partial<Upgrade & { loaded: boolean }> = object>(args?: { filter?: F, full?: false }): (
         
     | 
| 
       411 
431 
     | 
    
         
             
            				Omit<
         
     | 
| 
       412 
     | 
    
         
            -
            					Pick< 
     | 
| 
      
 432 
     | 
    
         
            +
            					Pick<UpgradeBase, "tier" | "rarity" | "name" | "type" | "i" | "loaded">,
         
     | 
| 
       413 
433 
     | 
    
         
             
            					keyof F
         
     | 
| 
       414 
434 
     | 
    
         
             
            				> & Pick<F, "tier" | "rarity" | "name" | "type" | "i" | "loaded">
         
     | 
| 
       415 
435 
     | 
    
         
             
            			)[] | ScriptFailure
         
     | 
| 
       416 
436 
     | 
    
         | 
| 
       417 
437 
     | 
    
         
             
            			<F extends Partial<Upgrade & { loaded: boolean }> = object>(args: { filter?: F, full: true }): (
         
     | 
| 
       418 
     | 
    
         
            -
            				Omit< 
     | 
| 
      
 438 
     | 
    
         
            +
            				Omit<UpgradeBase, keyof F> & F & Record<string, null | boolean | number | string>
         
     | 
| 
       419 
439 
     | 
    
         
             
            			)[] | ScriptFailure
         
     | 
| 
       420 
440 
     | 
    
         | 
| 
       421 
441 
     | 
    
         
             
            			<I extends number>(args: { i: I }): (
         
     | 
| 
       422 
     | 
    
         
            -
            				Omit< 
     | 
| 
      
 442 
     | 
    
         
            +
            				Omit<UpgradeBase, "i"> & { [x: string]: null | boolean | number | string, i: I }
         
     | 
| 
       423 
443 
     | 
    
         
             
            			) | ScriptFailure
         
     | 
| 
       424 
444 
     | 
    
         
             
            		}
         
     | 
| 
       425 
445 
     | 
    
         | 
| 
         @@ -496,7 +516,7 @@ type Highsec = Fullsec & PlayerHighsec & { 
     | 
|
| 
       496 
516 
     | 
    
         
             
            		/** **HIGHSEC** */
         
     | 
| 
       497 
517 
     | 
    
         
             
            		upgrades: {
         
     | 
| 
       498 
518 
     | 
    
         
             
            			<I extends number>(args: { i: I }): (
         
     | 
| 
       499 
     | 
    
         
            -
            				Omit< 
     | 
| 
      
 519 
     | 
    
         
            +
            				Omit<UpgradeBase, "i"> & { [x: string]: null | boolean | number | string, i: I }
         
     | 
| 
       500 
520 
     | 
    
         
             
            			) | ScriptFailure
         
     | 
| 
       501 
521 
     | 
    
         | 
| 
       502 
522 
     | 
    
         
             
            			<F extends Partial<Upgrade & { loaded: boolean }> = object>(args?: {
         
     | 
| 
         @@ -504,22 +524,22 @@ type Highsec = Fullsec & PlayerHighsec & { 
     | 
|
| 
       504 
524 
     | 
    
         
             
            				is_script?: true
         
     | 
| 
       505 
525 
     | 
    
         
             
            				full?: false
         
     | 
| 
       506 
526 
     | 
    
         
             
            			}): (
         
     | 
| 
       507 
     | 
    
         
            -
            				Omit<Pick< 
     | 
| 
      
 527 
     | 
    
         
            +
            				Omit<Pick<UpgradeBase, "tier" | "rarity" | "name" | "type" | "i" | "loaded">, keyof F> & F &
         
     | 
| 
       508 
528 
     | 
    
         
             
            					Record<string, null | boolean | number | string>
         
     | 
| 
       509 
529 
     | 
    
         
             
            			)[] | ScriptFailure
         
     | 
| 
       510 
530 
     | 
    
         | 
| 
       511 
531 
     | 
    
         
             
            			<F extends Partial<Upgrade & { loaded: boolean }> = object>(args?:
         
     | 
| 
       512 
532 
     | 
    
         
             
            				{ filter?: F, is_script?: true, full: true }
         
     | 
| 
       513 
     | 
    
         
            -
            			): (Omit< 
     | 
| 
      
 533 
     | 
    
         
            +
            			): (Omit<UpgradeBase, keyof F> & F & Record<string, null | boolean | number | string>)[] | ScriptFailure
         
     | 
| 
       514 
534 
     | 
    
         | 
| 
       515 
535 
     | 
    
         
             
            			(args?: { filter?: Partial<Upgrade & { loaded: boolean }>, is_script: false, full?: false }):
         
     | 
| 
       516 
536 
     | 
    
         
             
            				{ msg: string, upgrades: string[] } | ScriptFailure
         
     | 
| 
       517 
537 
     | 
    
         | 
| 
       518 
538 
     | 
    
         
             
            			<F extends Partial<Upgrade & { loaded: boolean }> = object>(
         
     | 
| 
       519 
539 
     | 
    
         
             
            				args?: { filter?: F, is_script: false, full: true }
         
     | 
| 
       520 
     | 
    
         
            -
            			): (Omit< 
     | 
| 
      
 540 
     | 
    
         
            +
            			): (Omit<UpgradeBase, keyof F | `rarity`> & F & {
         
     | 
| 
       521 
541 
     | 
    
         
             
            				[x: string]: null | boolean | number | string
         
     | 
| 
       522 
     | 
    
         
            -
            				rarity:  
     | 
| 
      
 542 
     | 
    
         
            +
            				rarity: UpgradeRarityString
         
     | 
| 
       523 
543 
     | 
    
         
             
            			})[] | ScriptFailure
         
     | 
| 
       524 
544 
     | 
    
         
             
            		}
         
     | 
| 
       525 
545 
     | 
    
         
             
            	}
         
     | 
| 
         @@ -699,10 +719,50 @@ type Nullsec = Lowsec & PlayerNullsec & { 
     | 
|
| 
       699 
719 
     | 
    
         
             
            	}
         
     | 
| 
       700 
720 
     | 
    
         
             
            }
         
     | 
| 
       701 
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 
     | 
    
         
            +
             
     | 
| 
       702 
726 
     | 
    
         
             
            type MongoValue = string | number | boolean | Date | MongoValue[] | { [key: string]: MongoValue } | null
         
     | 
| 
       703 
727 
     | 
    
         | 
| 
       704 
728 
     | 
    
         
             
            type MongoCommandValue = string | number | boolean | Date | MongoCommandValue[] | { [key: string]: MongoCommandValue } |
         
     | 
| 
       705 
     | 
    
         
            -
             
     | 
| 
      
 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>)>
         
     | 
| 
       706 
766 
     | 
    
         | 
| 
       707 
767 
     | 
    
         
             
            type Query = { [key: string]: MongoValue | Query } & { _id?: Id, $in?: MongoValue[] }
         
     | 
| 
       708 
768 
     | 
    
         
             
            type Projection = Record<string, boolean | 0 | 1>
         
     | 
| 
         @@ -751,7 +811,7 @@ type Cursor = { 
     | 
|
| 
       751 
811 
     | 
    
         
             
            	ObjectId: () => any
         
     | 
| 
       752 
812 
     | 
    
         
             
            }
         
     | 
| 
       753 
813 
     | 
    
         | 
| 
       754 
     | 
    
         
            -
            type  
     | 
| 
      
 814 
     | 
    
         
            +
            type CliContext = {
         
     | 
| 
       755 
815 
     | 
    
         
             
            	/** The name of the user who is calling the script. */ caller: string
         
     | 
| 
       756 
816 
     | 
    
         
             
            	/** The name of this script. */ this_script: string
         
     | 
| 
       757 
817 
     | 
    
         
             
            	/** The number of columns in the caller’s terminal. */ cols: number
         
     | 
| 
         @@ -759,17 +819,23 @@ type CLIContext = { 
     | 
|
| 
       759 
819 
     | 
    
         | 
| 
       760 
820 
     | 
    
         
             
            	/** The name of the script that directly called this script, or null if called on the command line or as a
         
     | 
| 
       761 
821 
     | 
    
         
             
            	  * scriptor. */ calling_script: null
         
     | 
| 
      
 822 
     | 
    
         
            +
            	is_scriptor?: undefined
         
     | 
| 
      
 823 
     | 
    
         
            +
            	is_brain?: undefined
         
     | 
| 
       762 
824 
     | 
    
         
             
            }
         
     | 
| 
       763 
825 
     | 
    
         | 
| 
       764 
     | 
    
         
            -
            type SubscriptContext = Replace< 
     | 
| 
      
 826 
     | 
    
         
            +
            type SubscriptContext = Replace<CliContext, {
         
     | 
| 
       765 
827 
     | 
    
         
             
            	/** The name of the script that directly called this script, or null if called on the command line or as a scriptor.
         
     | 
| 
       766 
828 
     | 
    
         
             
            	  */
         
     | 
| 
       767 
829 
     | 
    
         
             
            	calling_script: string
         
     | 
| 
       768 
830 
     | 
    
         
             
            }>
         
     | 
| 
       769 
831 
     | 
    
         | 
| 
       770 
     | 
    
         
            -
            type ScriptorContext = 
     | 
| 
       771 
     | 
    
         
            -
             
     | 
| 
       772 
     | 
    
         
            -
             
     | 
| 
      
 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
         
     | 
| 
       773 
839 
     | 
    
         | 
| 
       774 
840 
     | 
    
         
             
            /** Subscript space that can call FULLSEC scripts. */ declare const $fs: Fullsec
         
     | 
| 
       775 
841 
     | 
    
         | 
| 
         @@ -812,6 +878,8 @@ declare const $0s: typeof $ns 
     | 
|
| 
       812 
878 
     | 
    
         
             
              * } */
         
     | 
| 
       813 
879 
     | 
    
         
             
            declare const $s: Nullsec
         
     | 
| 
       814 
880 
     | 
    
         | 
| 
      
 881 
     | 
    
         
            +
            type ObjectId = { $oid: string }
         
     | 
| 
      
 882 
     | 
    
         
            +
             
     | 
| 
       815 
883 
     | 
    
         
             
            declare const $db: {
         
     | 
| 
       816 
884 
     | 
    
         
             
            	/** Insert a document or documents into a collection.
         
     | 
| 
       817 
885 
     | 
    
         
             
            	  * @param documents A document or array of documents to insert into the collection. */
         
     | 
| 
         @@ -905,6 +973,8 @@ declare const $db: { 
     | 
|
| 
       905 
973 
     | 
    
         
             
            			signature: { hash: "Undefined Conversion", keyId: "Undefined Conversion" }
         
     | 
| 
       906 
974 
     | 
    
         
             
            		}
         
     | 
| 
       907 
975 
     | 
    
         
             
            	}
         
     | 
| 
      
 976 
     | 
    
         
            +
             
     | 
| 
      
 977 
     | 
    
         
            +
            	ObjectId: () => ObjectId
         
     | 
| 
       908 
978 
     | 
    
         
             
            }
         
     | 
| 
       909 
979 
     | 
    
         | 
| 
       910 
980 
     | 
    
         
             
            /** Debug Log.
         
     | 
| 
         @@ -941,7 +1011,7 @@ declare const $FMCL: undefined | true 
     | 
|
| 
       941 
1011 
     | 
    
         
             
              * @example
         
     | 
| 
       942 
1012 
     | 
    
         
             
              * if (!$G.dbCache)
         
     | 
| 
       943 
1013 
     | 
    
         
             
              * 	$G.dbCache = $db.f({ whatever: true }).first() */
         
     | 
| 
       944 
     | 
    
         
            -
            declare const $G: any
         
     | 
| 
      
 1014 
     | 
    
         
            +
            declare const $G: Record<string | symbol, any>
         
     | 
| 
       945 
1015 
     | 
    
         | 
| 
       946 
1016 
     | 
    
         
             
            /** This contains a JS timestamp (not Date) set immediately before your code begins running.
         
     | 
| 
       947 
1017 
     | 
    
         
             
              * @example
         
     | 
| 
         @@ -990,3 +1060,14 @@ declare const _FULL_SCRIPT_NAME: string 
     | 
|
| 
       990 
1060 
     | 
    
         
             
              *
         
     | 
| 
       991 
1061 
     | 
    
         
             
              * In rare cases where it's not known at build time, it's `-1`. */
         
     | 
| 
       992 
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
    
    
    
        package/processScript/index.js
    CHANGED
    
    | 
         @@ -323,7 +323,7 @@ async function processScript( 
     | 
|
| 
       323 
323 
     | 
    
         
             
            			trailingComma: "none"
         
     | 
| 
       324 
324 
     | 
    
         
             
            		})
         
     | 
| 
       325 
325 
     | 
    
         
             
            	}
         
     | 
| 
       326 
     | 
    
         
            -
            	code = postprocess(code,  
     | 
| 
      
 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'
         
     | 
    
        package/processScript/minify.js
    CHANGED
    
    | 
         @@ -259,7 +259,10 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ 
     | 
|
| 
       259 
259 
     | 
    
         
             
            								t.memberExpression(
         
     | 
| 
       260 
260 
     | 
    
         
             
            									t.taggedTemplateExpression(
         
     | 
| 
       261 
261 
     | 
    
         
             
            										t.memberExpression(
         
     | 
| 
       262 
     | 
    
         
            -
            											t.callExpression( 
     | 
| 
      
 262 
     | 
    
         
            +
            											t.callExpression(
         
     | 
| 
      
 263 
     | 
    
         
            +
            												t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`),
         
     | 
| 
      
 264 
     | 
    
         
            +
            												[]
         
     | 
| 
      
 265 
     | 
    
         
            +
            											),
         
     | 
| 
       263 
266 
     | 
    
         
             
            											t.identifier("split")
         
     | 
| 
       264 
267 
     | 
    
         
             
            										),
         
     | 
| 
       265 
268 
     | 
    
         
             
            										t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
         
     | 
| 
         @@ -283,7 +286,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ 
     | 
|
| 
       283 
286 
     | 
    
         
             
            							t.memberExpression(
         
     | 
| 
       284 
287 
     | 
    
         
             
            								t.taggedTemplateExpression(
         
     | 
| 
       285 
288 
     | 
    
         
             
            									t.memberExpression(
         
     | 
| 
       286 
     | 
    
         
            -
            										t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
         
     | 
| 
      
 289 
     | 
    
         
            +
            										t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
         
     | 
| 
       287 
290 
     | 
    
         
             
            										t.identifier("split")
         
     | 
| 
       288 
291 
     | 
    
         
             
            									),
         
     | 
| 
       289 
292 
     | 
    
         
             
            									t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
         
     | 
| 
         @@ -308,7 +311,7 @@ async function minify(file, { uniqueId = "00000000000", mangleNames = !1, forceQ 
     | 
|
| 
       308 
311 
     | 
    
         
             
            							t.memberExpression(
         
     | 
| 
       309 
312 
     | 
    
         
             
            								t.taggedTemplateExpression(
         
     | 
| 
       310 
313 
     | 
    
         
             
            									t.memberExpression(
         
     | 
| 
       311 
     | 
    
         
            -
            										t.callExpression(t.identifier(`$${uniqueId}$SUBSCRIPT$scripts$quine$`), []),
         
     | 
| 
      
 314 
     | 
    
         
            +
            										t.callExpression(t.identifier(`$${uniqueId}$4$SUBSCRIPT$scripts$quine$`), []),
         
     | 
| 
       312 
315 
     | 
    
         
             
            										t.identifier("split")
         
     | 
| 
       313 
316 
     | 
    
         
             
            									),
         
     | 
| 
       314 
317 
     | 
    
         
             
            									t.templateLiteral([t.templateElement({ raw: "\t", cooked: "\t" }, !0)], [])
         
     | 
| 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            export declare const postprocess: (code: string,  
     | 
| 
      
 1 
     | 
    
         
            +
            export declare const postprocess: (code: string, uniqueId: string) => string;
         
     | 
| 
         @@ -1,12 +1,12 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            const postprocess = (code,  
     | 
| 
      
 1 
     | 
    
         
            +
            const postprocess = (code, uniqueId) =>
         
     | 
| 
       2 
2 
     | 
    
         
             
            	code
         
     | 
| 
       3 
     | 
    
         
            -
            		.replace(/^function\s 
     | 
| 
      
 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"),  
     | 
| 
      
 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  
     | 
| 
      
 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 
     | 
    
         
             
            						)
         
     | 
| 
         @@ -661,7 +661,7 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr 
     | 
|
| 
       661 
661 
     | 
    
         
             
            			t.identifier("prototype")
         
     | 
| 
       662 
662 
     | 
    
         
             
            		)
         
     | 
| 
       663 
663 
     | 
    
         
             
            	}
         
     | 
| 
       664 
     | 
    
         
            -
            	function processFakeSubscriptObject(fakeSubscriptObjectName) {
         
     | 
| 
      
 664 
     | 
    
         
            +
            	function processFakeSubscriptObject(fakeSubscriptObjectName, seclevel) {
         
     | 
| 
       665 
665 
     | 
    
         
             
            		for (const referencePath of getReferencePathsToGlobal(fakeSubscriptObjectName, program)) {
         
     | 
| 
       666 
666 
     | 
    
         
             
            			assert("MemberExpression" == referencePath.parent.type, "src/processScript/transform.ts:785:60")
         
     | 
| 
       667 
667 
     | 
    
         
             
            			assert("Identifier" == referencePath.parent.property.type)
         
     | 
| 
         @@ -684,13 +684,14 @@ function transform(file, sourceCode, { uniqueId = "00000000000", scriptUser, scr 
     | 
|
| 
       684 
684 
     | 
    
         
             
            			if ("CallExpression" == referencePath.parentPath.parentPath.parentPath?.type)
         
     | 
| 
       685 
685 
     | 
    
         
             
            				referencePath.parentPath.parentPath.replaceWith(
         
     | 
| 
       686 
686 
     | 
    
         
             
            					t.identifier(
         
     | 
| 
       687 
     | 
    
         
            -
            						`$${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}$`
         
     | 
| 
       688 
688 
     | 
    
         
             
            					)
         
     | 
| 
       689 
689 
     | 
    
         
             
            				)
         
     | 
| 
       690 
690 
     | 
    
         
             
            			else {
         
     | 
| 
       691 
691 
     | 
    
         
             
            				const name = `${referencePath.parent.property.name}$${referencePath.parentPath.parentPath.node.property.name}`
         
     | 
| 
       692 
692 
     | 
    
         
             
            				referencePath.parentPath.parentPath.replaceWith(t.identifier(`_${uniqueId}_SUBSCRIPT_${name}_`))
         
     | 
| 
       693 
     | 
    
         
            -
            				neededSubscriptLets. 
     | 
| 
      
 693 
     | 
    
         
            +
            				const maxSecLevel = Math.max(neededSubscriptLets.get(name) || 0, seclevel)
         
     | 
| 
      
 694 
     | 
    
         
            +
            				neededSubscriptLets.set(name, maxSecLevel)
         
     | 
| 
       694 
695 
     | 
    
         
             
            			}
         
     | 
| 
       695 
696 
     | 
    
         
             
            		}
         
     | 
| 
       696 
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,19 +42,37 @@ 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 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
            			 
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 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: 
     | 
| 
      
 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),
         
     | 
| 
         @@ -63,13 +81,15 @@ async function push( 
     | 
|
| 
       63 
81 
     | 
    
         
             
            				.map(({ name }) => name.slice(0, -4))
         
     | 
| 
       64 
82 
     | 
    
         
             
            		])
         
     | 
| 
       65 
83 
     | 
    
         
             
            	if (!allUsers.size)
         
     | 
| 
       66 
     | 
    
         
            -
            		 
     | 
| 
      
 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 
     | 
    
         
            +
            		)
         
     | 
| 
       67 
87 
     | 
    
         
             
            	const usersToScriptsToPush = new Cache(_user => new Map()),
         
     | 
| 
       68 
88 
     | 
    
         
             
            		scriptNamesToUsers = new Cache(_scriptName => new Set())
         
     | 
| 
       69 
89 
     | 
    
         
             
            	for (const script of scripts) {
         
     | 
| 
       70 
90 
     | 
    
         
             
            		const [user, scriptName] = script.split(".")
         
     | 
| 
       71 
     | 
    
         
            -
            		assert(user, "src/push.ts: 
     | 
| 
       72 
     | 
    
         
            -
            		assert(scriptName, "src/push.ts: 
     | 
| 
      
 91 
     | 
    
         
            +
            		assert(user, "src/push.ts:105:16")
         
     | 
| 
      
 92 
     | 
    
         
            +
            		assert(scriptName, "src/push.ts:106:22")
         
     | 
| 
       73 
93 
     | 
    
         
             
            		"*" == user ? scriptNamesToUsers.set(scriptName, allUsers) : scriptNamesToUsers.get(scriptName).add(user)
         
     | 
| 
       74 
94 
     | 
    
         
             
            	}
         
     | 
| 
       75 
95 
     | 
    
         
             
            	const sourceFolderFiles = sourceFolder.filter(({ stats }) => stats.isFile()),
         
     | 
| 
         @@ -100,7 +120,7 @@ async function push( 
     | 
|
| 
       100 
120 
     | 
    
         
             
            	for (const [scriptName, users] of scriptNamesToUsers)
         
     | 
| 
       101 
121 
     | 
    
         
             
            		for (const user of users)
         
     | 
| 
       102 
122 
     | 
    
         
             
            			if (!usersToScriptsToPush.get(user).has(scriptName))
         
     | 
| 
       103 
     | 
    
         
            -
            				 
     | 
| 
      
 123 
     | 
    
         
            +
            				return new NoScriptsError(`Could not find script ${user}.${scriptName} to push`)
         
     | 
| 
       104 
124 
     | 
    
         
             
            	const pathsToUsers = new Cache(_path => new Set())
         
     | 
| 
       105 
125 
     | 
    
         
             
            	for (const [user, scriptsToPush] of usersToScriptsToPush)
         
     | 
| 
       106 
126 
     | 
    
         
             
            		for (const path of scriptsToPush.values()) pathsToUsers.get(path).add(user)
         
     | 
| 
         @@ -137,4 +157,4 @@ async function push( 
     | 
|
| 
       137 
157 
     | 
    
         
             
            	)
         
     | 
| 
       138 
158 
     | 
    
         
             
            	return allInfo
         
     | 
| 
       139 
159 
     | 
    
         
             
            }
         
     | 
| 
       140 
     | 
    
         
            -
            export { push }
         
     | 
| 
      
 160 
     | 
    
         
            +
            export { MissingHackmudFolderError, MissingSourceFolderError, NoScriptsError, NoUsersError, push }
         
     |