hackmud-script-manager 0.19.0-50a29ed → 0.19.0-cd5548c
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -674
- package/bin/hsm.d.ts +0 -1
- package/bin/hsm.js +687 -1
- package/constants.d.ts +2 -0
- package/constants.js +4 -0
- package/generateTypeDeclaration.js +94 -1
- package/index.d.ts +2 -2
- package/index.js +47 -1
- package/package.json +37 -79
- package/processScript/index.d.ts +2 -2
- package/processScript/index.js +310 -1
- package/processScript/minify.d.ts +3 -3
- package/processScript/minify.js +376 -1
- package/processScript/postprocess.js +5 -1
- package/processScript/preprocess.d.ts +1 -1
- package/processScript/preprocess.js +84 -1
- package/processScript/shared.d.ts +3 -3
- package/processScript/shared.js +18 -1
- package/processScript/transform.d.ts +3 -3
- package/processScript/transform.js +394 -1
- package/pull.js +17 -1
- package/push.d.ts +3 -3
- package/push.js +251 -1
- package/syncMacros.js +53 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/watch.d.ts +3 -3
- package/watch.js +228 -1
- package/assert-22a7ef8a.js +0 -1
- package/constants-9bb78688.js +0 -1
- package/countHackmudCharacters-a08a265f.js +0 -1
- package/spliceString-0e6b5d6d.js +0 -1
- package/writeFilePersistent-ee9c9bfd.js +0 -1
package/bin/hsm.js
CHANGED
@@ -1,2 +1,688 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
-
import{readFile as e,writeFile as t,mkdir as n,rmdir as a}from"fs/promises";import{homedir as s}from"os";import{s as o}from"../constants-9bb78688.js";import{generateTypeDeclaration as i}from"../generateTypeDeclaration.js";import{pull as r}from"../pull.js";import{syncMacros as c}from"../syncMacros.js";import{resolve as l,extname as f,basename as $,dirname as p,relative as h}from"path";import{D as m,w as d}from"../writeFilePersistent-ee9c9bfd.js";import{a as g}from"../assert-22a7ef8a.js";import{c as u}from"../countHackmudCharacters-a08a265f.js";import"fs";const y=l(s(),".config"),b=l(y,"hsm.json"),k=new Map,w=[],v=new m((e=>{let t=0;for(const n of e)t+=(t>>1)+t+"xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(n)+1;return[W,_,I,D,x,q][t%6](e)})),logNeedHackmudPathMessage=()=>console.error(R(`${C("You need to set hackmudPath in config before you can use this command")}\n\n${T("To fix this:")}\nOpen hackmud and run "${z("#dir")}"\nThis will open a file browser and print your hackmud user's script directory\nGo up 2 directories and then copy the path\nThen in a terminal run "${z("hsm")} ${x("config set")} ${A("hackmudPath")} ${q("<the path you copied>")}"`)),logHelp=()=>{const e="Push scripts from a directory to hackmud user's scripts directories",t="Watch a directory and push a script when modified",n="Minify a script file on the spot",a="Generate a type declaration file for a directory of scripts",s="Sync macros across all hackmud users",o="Retrieve a value from the config file",i="Assign a value to the config file",r="Remove a key and value from the config file",c="Pull a script a from a hackmud user's script directory",l="Skip minification to produce a readable script",f="Reduce character count further but lose function names in error call stacks",$="Force quine cheats even if the character count is higher";switch(console.log(J("Version")+R(": ")+A("0.19.0-50a29ed")),w[0]){case"config":switch(w[1]){case"get":console.log(`\n${W(o)}\n\n${T("Usage:")}\n${z("hsm")} ${x(`${w[0]} ${w[1]}`)} ${q("<key>")}`);break;case"set":console.log(`\n${W(i)}\n\n${T("Usage:")}\n${z("hsm")} ${x(`${w[0]} ${w[1]}`)} ${q("<key> <value>")}`);break;case"delete":console.log(`\n${W(r)}\n\n${T("Usage:")}\n${z("hsm")} ${x(`${w[0]} ${w[1]}`)} ${q("<key>")}`);break;default:console.log(R(`${J("Config path")}: ${A(b)}\n\n${W("Modify the config file")}\n\n${T("Usage:")}\n${z("hsm")} ${x(`${w[0]} get`)} ${q("<key>")}\n ${o}\n${z("hsm")} ${x(`${w[0]} set`)} ${q("<key> <value>")}\n ${i}\n${z("hsm")} ${x(`${w[0]} delete`)} ${q("<key>")}\n ${r}`))}break;case"push":console.log(R(`\n${W(e)}\n\n${T("Usage:")}\n${z("hsm")} ${x(w[0])} ${q("<directory> [<script user>.<script name>...]")}\n\n${T("Options:")}\n${J("--skip-minify")}\n ${l}\n${J("--mangle-names")}\n ${f}\n${J("--force-quine-cheats")}\n ${$}`));break;case"dev":case"watch":console.log(R(`${J("Aliases")}: ${A("watch, dev")}\n\n${W(t)}\n\n${T("Usage:")}\n${z("hsm")} ${x(w[0])} ${q("<directory> [<script user>.<script name>...]")}\n\n${T("Options:")}\n${J("--skip-minify")}\n ${l}\n${J("--mangle-names")}\n ${f}\n${J("--type-declaration-path")}=${q("<path>")}\n Path to generate a type declaration file for the scripts\n${J("--force-quine-cheats")}\n ${$}`));break;case"pull":console.log(R(`\n${W(c)}\n\n${T("Usage:")}\n${z("hsm")} ${x(w[0])} ${q("<script user>")}${A(".")}${q("<script name>")}`));break;case"minify":case"golf":console.log(R(`${J("Aliases")}: ${A("minify, golf")}\n\n${W(n)}\n\n${T("Usage:")}\n${z("hsm")} ${x(w[0])} ${q("<target> [output path]")}\n\n${T("Options:")}\n${J("--skip-minify")}\n ${l}\n${J("--mangle-names")}\n ${f}\n${J("--force-quine-cheats")}\n ${$}\n${J("--watch")}\n Watch for changes`));break;case"generate-type-declaration":case"gen-type-declaration":case"gen-dts":case"gen-types":console.log(R(`${J("Aliases")}: ${A("generate-type-declaration, gen-type-declaration, gen-types, gen-dts")}\n\n${W(a)}\n\n${T("Usage:")}\n${z("hsm")} ${x(w[0])} ${q("<directory> [output path]")}`));break;case"sync-macros":console.log(`\n${W(s)}`);break;default:console.log(R(`\n${W("Hackmud Script Manager")}\n\n${T("Commands:")}\n${x("push")}\n ${e}\n${x("watch")}, ${x("dev")}\n ${t}\n${x("minify")}, ${x("golf")}\n ${n}\n${x("generate-type-declaration")}, ${x("gen-type-declaration")}, ${x("gen-types")}, ${x("gen-dts")}\n ${a}\n${x("sync-macros")}\n ${s}\n${x("config")}\n Modify and view the config file\n${x("pull")}\n ${c}`))}},exploreObject=(e,t,n=!1)=>{for(const s of t){var a;e=n?"object"==typeof e[s]?e[s]:e[s]={}:null===(a=e)||void 0===a?void 0:a[s]}return e},logInfo=({file:e,users:t,minLength:n,error:a},s)=>{a?logError(`error "${U.bold(a.message)}" in ${U.bold(e)}`):console.log(`pushed ${U.bold(e)} to ${t.map((e=>U.bold(v.get(e)))).join(", ")} | ${U.bold(String(n))} chars | ${U.bold(`${l(s,t[0],"scripts",$(e,f(e)))}.js`)}`)},log=e=>{console.log(R(e))},logError=e=>{console.error(C(e)),process.exitCode=1};for(const e of process.argv.slice(2))if("-"==e[0]){const[t,n]=e.split("=");let a=n;if(a)if("true"==a)a=!0;else if("false"==a)a=!1;else{const e=Number(a);isFinite(e)&&(a=e)}else a=!0;if("-"==e[1])k.set(t.slice(2),a);else for(const e of t.slice(1))k.set(e,a)}else w.push(e);("v"==w[0]||"version"==w[0]||k.get("version")||k.get("v"))&&(console.log("0.19.0-50a29ed"),process.exit());let j=!1;const S=e(b,{encoding:"utf-8"}).then((e=>{let t;try{t=JSON.parse(e)}catch{return log("Config file was corrupted, resetting"),{}}return t&&"object"==typeof t?("hackmudPath"in t&&"string"!=typeof t.hackmudPath&&(log('Property "hackmudPath" of config file was corrupted, removing'),delete t.hackmudPath),t):(log("Config file was corrupted, resetting"),{})}),(()=>(j=!0,{}))),P=import("../push.js"),N=import("../processScript/index.js"),O=import("../watch.js"),M=import("chokidar"),{default:U}=await import("chalk"),T=U.rgb(255,255,255),q=U.rgb(202,202,202),z=U.rgb(155,155,155),C=U.rgb(255,0,0),W=U.rgb(255,244,4),_=U.rgb(243,249,152),x=U.rgb(30,255,0),I=U.rgb(179,255,155),J=U.rgb(0,255,255),R=U.rgb(122,178,244),A=U.rgb(255,0,236),D=U.rgb(255,150,224);(k.get("help")||k.get("h"))&&(logHelp(),process.exit());let E=!0;switch(w[0]){case"push":{const{hackmudPath:e}=await S;if(!e){logNeedHackmudPathMessage();break}const t=w[1];if(!t){logError("Must provide the directory to push from\n"),logHelp();break}const n=w.slice(2);if(n.length){const e=n.find((e=>!/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(e)));if(e){logError(`Invalid script name: ${JSON.stringify(e)}\n`),logHelp();break}}else n.push("*.*");if(k.has("skip-minify")&&k.has("mangle-names")){logError(`Option ${J("--mangle-names")} is not compatible with ${J("--skip-minify")}\n`),logHelp();break}const a=k.get("skip-minify");let s;if(null!=a){if("boolean"!=typeof a){logError(`The value for ${J("--skip-minify")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}s=!a}const o=k.get("mangle-names");if(null!=o&&"boolean"!=typeof o){logError(`The value for ${J("--mangle-names")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const i=k.get("force-quine-cheats");if(null!=i&&"boolean"!=typeof i){logError(`The value for ${J("--force-quine-cheats")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const{push:r}=await P;(await r(t,e,{scripts:n,onPush:t=>logInfo(t,e),minify:s,mangleNames:o,forceQuineCheats:i})).length||logError("Could not find any scripts to push")}break;case"dev":case"watch":{var F;const{hackmudPath:e}=await S;if(!e){logNeedHackmudPathMessage();break}const t=w[1];if(!t){logError("Must provide the directory to watch\n"),logHelp();break}const n=w.slice(2);if(n.length){const e=n.find((e=>!/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(e)));if(e){logError(`Invalid script name: ${JSON.stringify(e)}\n`),logHelp();break}}else n.push("*.*");if(k.has("skip-minify")&&k.has("mangle-names")){logError(`Option ${J("--mangle-names")} is not compatible with ${J("--skip-minify")}\n`),logHelp();break}const a=k.get("skip-minify");let s;if(null!=a){if("boolean"!=typeof a){logError(`The value for ${J("--skip-minify")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}s=!a}const o=k.get("mangle-names");if(null!=o&&"boolean"!=typeof o){logError(`The value for ${J("--mangle-names")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const i=k.get("force-quine-cheats");if(null!=i&&"boolean"!=typeof i){logError(`The value for ${J("--force-quine-cheats")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const{watch:r}=await O;r(t,e,{scripts:n,onPush:t=>logInfo(t,e),typeDeclarationPath:null===(F=k.get("type-declaration-path")||k.get("type-declaration")||k.get("dts")||k.get("gen-types"))||void 0===F?void 0:F.toString(),minify:s,mangleNames:o,onReady:()=>log("Watching"),forceQuineCheats:i}),E=!1}break;case"pull":{const{hackmudPath:e}=await S;if(!e){logNeedHackmudPathMessage();break}const t=w[1];if(!t){logError("Must provide the script to pull\n"),logHelp();break}const n=w[2]||".";try{await r(n,e,t)}catch(e){console.error(e),logError(`Something went wrong, did you forget to ${z("#down")} the script?`)}}break;case"sync-macros":{const{hackmudPath:e}=await S;if(!e){logNeedHackmudPathMessage();break}const{macrosSynced:t,usersSynced:n}=await c(e);log(`Synced ${t} macros to ${n} users`)}break;case"generate-type-declaration":case"gen-type-declaration":case"gen-dts":case"gen-types":{const e=w[1];if(!e){logError("Must provide target directory\n"),logHelp();break}const n=l(e),a=w[2]||"./player.d.ts",s=await i(n,(await S).hackmudPath);let o=l(a);try{await t(o,s)}catch(e){if(g(e instanceof Error),"EISDIR"!=e.code)throw e;o=l(o,"player.d.ts"),await t(o,s)}log(`Wrote type declaration to ${U.bold(o)}`)}break;case"config":switch(w[1]){case"get":{const e=w[2];e?log(exploreObject(await S,e.split("."))):console.log(await S)}break;case"delete":{var Q;const e=w[2];if(!e){logError("Must provide a key to delete\n"),logHelp();break}const t=e.split("."),n=t.map((e=>/^[A-Za-z_$][\w$]*$/.test(e)?e:JSON.stringify(e))).join("."),a=t.pop();null===(Q=exploreObject(await S,t))||void 0===Q||delete Q[a],log(`Removed ${A(n)} from config file`)}break;case"set":{const e=w[2],o=w[3];if(!e){logError("Must provide a key and value\n"),logHelp();break}const i=e.split("."),r=i.map((e=>/^[A-Za-z_$][\w$]*$/.test(e)?e:JSON.stringify(e))).join(".");if(!o){logError(`Must provide a value for the key ${r}\n`),logHelp();break}const c=i.pop(),f=await S;if(i.length||"hackmudPath"!=c){let e=f;for(const t of i)"object"==typeof e[t]||(e[t]={}),e=e[t];e[c]=o}else f.hackmudPath=l(o.startsWith("~/")?s()+o.slice(1):o);console.log(f),await(async e=>{const s=JSON.stringify(e,void 0,"\t");j&&log(`Creating config file at ${b}`),await t(b,s).catch((async e=>{switch(e.code){case"EISDIR":await a(b);break;case"ENOENT":await n(y);break;default:throw e}await t(b,s)}))})(f)}break;default:w[1]&&logError(`Unknown command: ${JSON.stringify(w[1])}\n`),logHelp()}break;case"help":case"h":logHelp();break;case"golf":case"minify":{const t=w[1];if(!t){logError("Must provide target\n"),logHelp();break}const n=f(t);if(!o.includes(n)){logError(`Unsupported file extension "${U.bold(n)}"\nSupported extensions are "${o.map((e=>U.bold(e))).join('", "')}"`);break}const{processScript:a}=await N,s=$(t,n),i=s.endsWith(".src"),r=i?s.slice(0,-4):s,c="scripts"==$(l(t,".."))&&"hackmud"==$(l(t,"../../.."))?$(l(t,"../..")):"UNKNOWN",m=!k.get("skip-minify");if(k.has("skip-minify")&&k.has("mangle-names")){logError(`Option ${J("--mangle-names")} would have no effect if minification is skipped\n`),logHelp();break}const g=k.get("mangle-names");if(null!=g&&"boolean"!=typeof g){logError(`The value for ${J("--mangle-names")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const y=g,b=k.get("force-quine-cheats");if(null!=b&&"boolean"!=typeof b){logError(`the value for ${J("--force-quine-cheats")} must be ${A("true")} or ${A("false")}\n`),logHelp();break}const v=b;let j=w[2]||l(p(t),i?`${r}.js`:".js"==n?`${s}.min.js`:`${s}.js`);const golfFile=()=>e(t,{encoding:"utf-8"}).then((async e=>{const s=performance.now(),{script:o,warnings:i}=await a(e,{minify:m,scriptUser:c,scriptName:r,filePath:t,mangleNames:y,forceQuineCheats:v}),f=performance.now()-s;for(const{message:e,line:t}of i)log(`Warning "${U.bold(e)}" on line ${U.bold(String(t))}`);await d(j,o).catch((async e=>{if(!w[2]||"EISDIR"!=e.code)throw e;j=l(j,`${$(t,n)}.js`),await d(j,o)})).then((()=>log(`Wrote ${U.bold(u(o))} chars to ${U.bold(h(".",j))} | took ${Math.round(100*f)/100}ms`)),(e=>logError(e.message)))}),(e=>logError(e.message)));if(k.get("watch")){const{watch:e}=await M;e(t,{awaitWriteFinish:{stabilityThreshold:100}}).on("ready",(()=>log(`Watching ${t}`))).on("change",golfFile),E=!1}else await golfFile()}break;default:w[0]&&logError(`Unknown command: ${JSON.stringify(w[0])}\n`),logHelp()}E&&process.exit();
|
2
|
+
import { DynamicMap } from '@samual/lib/DynamicMap';
|
3
|
+
import { assert } from '@samual/lib/assert';
|
4
|
+
import { countHackmudCharacters } from '@samual/lib/countHackmudCharacters';
|
5
|
+
import { writeFilePersistent } from '@samual/lib/writeFilePersistent';
|
6
|
+
import { readFile, writeFile, mkdir, rmdir } from 'fs/promises';
|
7
|
+
import { homedir } from 'os';
|
8
|
+
import { supportedExtensions } from '../constants.js';
|
9
|
+
import { generateTypeDeclaration } from '../generateTypeDeclaration.js';
|
10
|
+
import { pull } from '../pull.js';
|
11
|
+
import { syncMacros } from '../syncMacros.js';
|
12
|
+
import { resolve, extname, basename, dirname, relative } from 'path';
|
13
|
+
import '@samual/lib/copyFilePersistent';
|
14
|
+
|
15
|
+
var version = "0.19.0-cd5548c";
|
16
|
+
|
17
|
+
/* eslint-disable unicorn/no-process-exit */
|
18
|
+
|
19
|
+
/* | ArgValue[]*/
|
20
|
+
|
21
|
+
const configDirectoryPath = resolve(homedir(), `.config`);
|
22
|
+
const configFilePath = resolve(configDirectoryPath, `hsm.json`);
|
23
|
+
const options = new Map();
|
24
|
+
const commands = [];
|
25
|
+
const userColours = new DynamicMap(user => {
|
26
|
+
let hash = 0;
|
27
|
+
for (const char of user) hash += (hash >> 1) + hash + `xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj`.indexOf(char) + 1;
|
28
|
+
return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user);
|
29
|
+
});
|
30
|
+
const logNeedHackmudPathMessage = () => console.error(colourS(`\
|
31
|
+
${colourD(`You need to set hackmudPath in config before you can use this command`)}
|
32
|
+
|
33
|
+
${colourA(`To fix this:`)}
|
34
|
+
Open hackmud and run "${colourC(`#dir`)}"
|
35
|
+
This will open a file browser and print your hackmud user's script directory
|
36
|
+
Go up 2 directories and then copy the path
|
37
|
+
Then in a terminal run "${colourC(`hsm`)} ${colourL(`config set`)} ${colourV(`hackmudPath`)} ${colourB(`<the path you copied>`)}"`));
|
38
|
+
const logHelp = () => {
|
39
|
+
const pushCommandDescription = `Push scripts from a directory to hackmud user's scripts directories`;
|
40
|
+
const watchCommandDescription = `Watch a directory and push a script when modified`;
|
41
|
+
const minifyCommandDescription = `Minify a script file on the spot`;
|
42
|
+
const generateTypeDeclarationCommandDescription = `Generate a type declaration file for a directory of scripts`;
|
43
|
+
const syncMacrosCommandDescription = `Sync macros across all hackmud users`;
|
44
|
+
const configCommandDescription = `Modify and view the config file`;
|
45
|
+
const configGetCommandDescription = `Retrieve a value from the config file`;
|
46
|
+
const configSetCommandDescription = `Assign a value to the config file`;
|
47
|
+
const configDeleteCommandDescription = `Remove a key and value from the config file`;
|
48
|
+
const pullCommandDescription = `Pull a script a from a hackmud user's script directory`;
|
49
|
+
const skipMinifyOptionDescription = `Skip minification to produce a readable script`;
|
50
|
+
const mangleNamesOptionDescription = `Reduce character count further but lose function names in error call stacks`;
|
51
|
+
const forceQuineCheatsOptionDescription = `Force quine cheats even if the character count is higher`;
|
52
|
+
console.log(colourN(`Version`) + colourS(`: `) + colourV(version));
|
53
|
+
switch (commands[0]) {
|
54
|
+
case `config`:
|
55
|
+
{
|
56
|
+
switch (commands[1]) {
|
57
|
+
case `get`:
|
58
|
+
{
|
59
|
+
console.log(`
|
60
|
+
${colourJ(configGetCommandDescription)}
|
61
|
+
|
62
|
+
${colourA(`Usage:`)}
|
63
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB(`<key>`)}`);
|
64
|
+
}
|
65
|
+
break;
|
66
|
+
case `set`:
|
67
|
+
{
|
68
|
+
console.log(`
|
69
|
+
${colourJ(configSetCommandDescription)}
|
70
|
+
|
71
|
+
${colourA(`Usage:`)}
|
72
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB(`<key> <value>`)}`);
|
73
|
+
}
|
74
|
+
break;
|
75
|
+
case `delete`:
|
76
|
+
{
|
77
|
+
console.log(`
|
78
|
+
${colourJ(configDeleteCommandDescription)}
|
79
|
+
|
80
|
+
${colourA(`Usage:`)}
|
81
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} ${commands[1]}`)} ${colourB(`<key>`)}`);
|
82
|
+
}
|
83
|
+
break;
|
84
|
+
default:
|
85
|
+
{
|
86
|
+
console.log(colourS(`\
|
87
|
+
${colourN(`Config path`)}: ${colourV(configFilePath)}
|
88
|
+
|
89
|
+
${colourJ(`Modify the config file`)}
|
90
|
+
|
91
|
+
${colourA(`Usage:`)}
|
92
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} get`)} ${colourB(`<key>`)}
|
93
|
+
${configGetCommandDescription}
|
94
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} set`)} ${colourB(`<key> <value>`)}
|
95
|
+
${configSetCommandDescription}
|
96
|
+
${colourC(`hsm`)} ${colourL(`${commands[0]} delete`)} ${colourB(`<key>`)}
|
97
|
+
${configDeleteCommandDescription}`));
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
break;
|
102
|
+
case `push`:
|
103
|
+
{
|
104
|
+
console.log(colourS(`
|
105
|
+
${colourJ(pushCommandDescription)}
|
106
|
+
|
107
|
+
${colourA(`Usage:`)}
|
108
|
+
${colourC(`hsm`)} ${colourL(commands[0])} ${colourB(`<directory> [<script user>.<script name>...]`)}
|
109
|
+
|
110
|
+
${colourA(`Options:`)}
|
111
|
+
${colourN(`--skip-minify`)}
|
112
|
+
${skipMinifyOptionDescription}
|
113
|
+
${colourN(`--mangle-names`)}
|
114
|
+
${mangleNamesOptionDescription}
|
115
|
+
${colourN(`--force-quine-cheats`)}
|
116
|
+
${forceQuineCheatsOptionDescription}`));
|
117
|
+
}
|
118
|
+
break;
|
119
|
+
case `dev`:
|
120
|
+
case `watch`:
|
121
|
+
{
|
122
|
+
console.log(colourS(`\
|
123
|
+
${colourN(`Aliases`)}: ${colourV(`watch, dev`)}
|
124
|
+
|
125
|
+
${colourJ(watchCommandDescription)}
|
126
|
+
|
127
|
+
${colourA(`Usage:`)}
|
128
|
+
${colourC(`hsm`)} ${colourL(commands[0])} ${colourB(`<directory> [<script user>.<script name>...]`)}
|
129
|
+
|
130
|
+
${colourA(`Options:`)}
|
131
|
+
${colourN(`--skip-minify`)}
|
132
|
+
${skipMinifyOptionDescription}
|
133
|
+
${colourN(`--mangle-names`)}
|
134
|
+
${mangleNamesOptionDescription}
|
135
|
+
${colourN(`--type-declaration-path`)}=${colourB(`<path>`)}
|
136
|
+
Path to generate a type declaration file for the scripts
|
137
|
+
${colourN(`--force-quine-cheats`)}
|
138
|
+
${forceQuineCheatsOptionDescription}`));
|
139
|
+
}
|
140
|
+
break;
|
141
|
+
case `pull`:
|
142
|
+
{
|
143
|
+
console.log(colourS(`
|
144
|
+
${colourJ(pullCommandDescription)}
|
145
|
+
|
146
|
+
${colourA(`Usage:`)}
|
147
|
+
${colourC(`hsm`)} ${colourL(commands[0])} ${colourB(`<script user>`)}${colourV(`.`)}${colourB(`<script name>`)}`));
|
148
|
+
}
|
149
|
+
break;
|
150
|
+
case `minify`:
|
151
|
+
case `golf`:
|
152
|
+
{
|
153
|
+
console.log(colourS(`\
|
154
|
+
${colourN(`Aliases`)}: ${colourV(`minify, golf`)}
|
155
|
+
|
156
|
+
${colourJ(minifyCommandDescription)}
|
157
|
+
|
158
|
+
${colourA(`Usage:`)}
|
159
|
+
${colourC(`hsm`)} ${colourL(commands[0])} ${colourB(`<target> [output path]`)}
|
160
|
+
|
161
|
+
${colourA(`Options:`)}
|
162
|
+
${colourN(`--skip-minify`)}
|
163
|
+
${skipMinifyOptionDescription}
|
164
|
+
${colourN(`--mangle-names`)}
|
165
|
+
${mangleNamesOptionDescription}
|
166
|
+
${colourN(`--force-quine-cheats`)}
|
167
|
+
${forceQuineCheatsOptionDescription}
|
168
|
+
${colourN(`--watch`)}
|
169
|
+
Watch for changes`));
|
170
|
+
}
|
171
|
+
break;
|
172
|
+
case `generate-type-declaration`:
|
173
|
+
case `gen-type-declaration`:
|
174
|
+
case `gen-dts`:
|
175
|
+
case `gen-types`:
|
176
|
+
{
|
177
|
+
console.log(colourS(`\
|
178
|
+
${colourN(`Aliases`)}: ${colourV(`generate-type-declaration, gen-type-declaration, gen-types, gen-dts`)}
|
179
|
+
|
180
|
+
${colourJ(generateTypeDeclarationCommandDescription)}
|
181
|
+
|
182
|
+
${colourA(`Usage:`)}
|
183
|
+
${colourC(`hsm`)} ${colourL(commands[0])} ${colourB(`<directory> [output path]`)}`));
|
184
|
+
}
|
185
|
+
break;
|
186
|
+
case `sync-macros`:
|
187
|
+
{
|
188
|
+
console.log(`\n${colourJ(syncMacrosCommandDescription)}`);
|
189
|
+
}
|
190
|
+
break;
|
191
|
+
default:
|
192
|
+
{
|
193
|
+
console.log(colourS(`
|
194
|
+
${colourJ(`Hackmud Script Manager`)}
|
195
|
+
|
196
|
+
${colourA(`Commands:`)}
|
197
|
+
${colourL(`push`)}
|
198
|
+
${pushCommandDescription}
|
199
|
+
${colourL(`watch`)}, ${colourL(`dev`)}
|
200
|
+
${watchCommandDescription}
|
201
|
+
${colourL(`minify`)}, ${colourL(`golf`)}
|
202
|
+
${minifyCommandDescription}
|
203
|
+
${colourL(`generate-type-declaration`)}, ${colourL(`gen-type-declaration`)}, ${colourL(`gen-types`)}, ${colourL(`gen-dts`)}
|
204
|
+
${generateTypeDeclarationCommandDescription}
|
205
|
+
${colourL(`sync-macros`)}
|
206
|
+
${syncMacrosCommandDescription}
|
207
|
+
${colourL(`config`)}
|
208
|
+
${configCommandDescription}
|
209
|
+
${colourL(`pull`)}
|
210
|
+
${pullCommandDescription}`));
|
211
|
+
}
|
212
|
+
}
|
213
|
+
};
|
214
|
+
const exploreObject = (object, keys, createPath = false) => {
|
215
|
+
for (const key of keys) {
|
216
|
+
var _object;
|
217
|
+
if (createPath) object = typeof object[key] == `object` ? object[key] : object[key] = {};else object = (_object = object) === null || _object === void 0 ? void 0 : _object[key];
|
218
|
+
}
|
219
|
+
return object;
|
220
|
+
};
|
221
|
+
const updateConfig = async config => {
|
222
|
+
const json = JSON.stringify(config, undefined, `\t`);
|
223
|
+
if (configDidNotExist) log(`Creating config file at ${configFilePath}`);
|
224
|
+
await writeFile(configFilePath, json).catch(async error => {
|
225
|
+
switch (error.code) {
|
226
|
+
case `EISDIR`:
|
227
|
+
{
|
228
|
+
await rmdir(configFilePath);
|
229
|
+
}
|
230
|
+
break;
|
231
|
+
case `ENOENT`:
|
232
|
+
{
|
233
|
+
await mkdir(configDirectoryPath);
|
234
|
+
}
|
235
|
+
break;
|
236
|
+
default:
|
237
|
+
throw error;
|
238
|
+
}
|
239
|
+
await writeFile(configFilePath, json);
|
240
|
+
});
|
241
|
+
};
|
242
|
+
const logInfo = ({
|
243
|
+
file,
|
244
|
+
users,
|
245
|
+
minLength,
|
246
|
+
error
|
247
|
+
}, hackmudPath) => {
|
248
|
+
if (error) {
|
249
|
+
logError(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`);
|
250
|
+
return;
|
251
|
+
}
|
252
|
+
console.log(`pushed ${chalk.bold(file)} to ${users.map(user => chalk.bold(userColours.get(user))).join(`, `)} | ${chalk.bold(String(minLength))} chars | ${chalk.bold(`${resolve(hackmudPath, users[0], `scripts`, basename(file, extname(file)))}.js`)}`);
|
253
|
+
};
|
254
|
+
const log = message => {
|
255
|
+
console.log(colourS(message));
|
256
|
+
};
|
257
|
+
const logError = message => {
|
258
|
+
console.error(colourD(message));
|
259
|
+
process.exitCode = 1;
|
260
|
+
};
|
261
|
+
for (const argument of process.argv.slice(2)) {
|
262
|
+
if (argument[0] == `-`) {
|
263
|
+
const [key, valueRaw] = argument.split(`=`);
|
264
|
+
let value = valueRaw;
|
265
|
+
if (value) {
|
266
|
+
if (value == `true`) value = true;else if (value == `false`) value = false;else {
|
267
|
+
const number = Number(value);
|
268
|
+
if (isFinite(number)) value = number;
|
269
|
+
}
|
270
|
+
} else value = true;
|
271
|
+
if (argument[1] == `-`) options.set(key.slice(2), value);else {
|
272
|
+
for (const option of key.slice(1)) options.set(option, value);
|
273
|
+
}
|
274
|
+
} else commands.push(argument);
|
275
|
+
}
|
276
|
+
if (commands[0] == `v` || commands[0] == `version` || options.get(`version`) || options.get(`v`)) {
|
277
|
+
console.log(version);
|
278
|
+
process.exit();
|
279
|
+
}
|
280
|
+
let configDidNotExist = false;
|
281
|
+
const configPromise = readFile(configFilePath, {
|
282
|
+
encoding: `utf-8`
|
283
|
+
}).then(configFile => {
|
284
|
+
let temporaryConfig;
|
285
|
+
try {
|
286
|
+
temporaryConfig = JSON.parse(configFile);
|
287
|
+
} catch {
|
288
|
+
// TODO log to error log file
|
289
|
+
log(`Config file was corrupted, resetting`);
|
290
|
+
return {};
|
291
|
+
}
|
292
|
+
if (!temporaryConfig || typeof temporaryConfig != `object`) {
|
293
|
+
log(`Config file was corrupted, resetting`);
|
294
|
+
return {};
|
295
|
+
}
|
296
|
+
if (`hackmudPath` in temporaryConfig && typeof temporaryConfig.hackmudPath != `string`) {
|
297
|
+
log(`Property "hackmudPath" of config file was corrupted, removing`);
|
298
|
+
delete temporaryConfig.hackmudPath;
|
299
|
+
}
|
300
|
+
return temporaryConfig;
|
301
|
+
}, () => {
|
302
|
+
configDidNotExist = true;
|
303
|
+
return {};
|
304
|
+
});
|
305
|
+
const pushModule = import('../push.js');
|
306
|
+
const processScriptModule = import('../processScript/index.js');
|
307
|
+
const watchModule = import('../watch.js');
|
308
|
+
const chokidarModule = import('chokidar');
|
309
|
+
const {
|
310
|
+
default: chalk
|
311
|
+
} = await import('chalk');
|
312
|
+
const colourA = chalk.rgb(0xFF, 0xFF, 0xFF);
|
313
|
+
const colourB = chalk.rgb(0xCA, 0xCA, 0xCA);
|
314
|
+
const colourC = chalk.rgb(0x9B, 0x9B, 0x9B);
|
315
|
+
const colourD = chalk.rgb(0xFF, 0x00, 0x00);
|
316
|
+
const colourJ = chalk.rgb(0xFF, 0xF4, 0x04);
|
317
|
+
const colourK = chalk.rgb(0xF3, 0xF9, 0x98);
|
318
|
+
const colourL = chalk.rgb(0x1E, 0xFF, 0x00);
|
319
|
+
const colourM = chalk.rgb(0xB3, 0xFF, 0x9B);
|
320
|
+
const colourN = chalk.rgb(0x00, 0xFF, 0xFF);
|
321
|
+
const colourS = chalk.rgb(0x7A, 0xB2, 0xF4);
|
322
|
+
const colourV = chalk.rgb(0xFF, 0x00, 0xEC);
|
323
|
+
const colourW = chalk.rgb(0xFF, 0x96, 0xE0);
|
324
|
+
if (options.get(`help`) || options.get(`h`)) {
|
325
|
+
logHelp();
|
326
|
+
process.exit();
|
327
|
+
}
|
328
|
+
let autoExit = true;
|
329
|
+
switch (commands[0]) {
|
330
|
+
case `push`:
|
331
|
+
{
|
332
|
+
const {
|
333
|
+
hackmudPath
|
334
|
+
} = await configPromise;
|
335
|
+
if (!hackmudPath) {
|
336
|
+
logNeedHackmudPathMessage();
|
337
|
+
break;
|
338
|
+
}
|
339
|
+
const sourcePath = commands[1];
|
340
|
+
if (!sourcePath) {
|
341
|
+
logError(`Must provide the directory to push from\n`);
|
342
|
+
logHelp();
|
343
|
+
break;
|
344
|
+
}
|
345
|
+
const scripts = commands.slice(2);
|
346
|
+
if (scripts.length) {
|
347
|
+
const invalidScript = scripts.find(script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script));
|
348
|
+
if (invalidScript) {
|
349
|
+
logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`);
|
350
|
+
logHelp();
|
351
|
+
break;
|
352
|
+
}
|
353
|
+
} else scripts.push(`*.*`);
|
354
|
+
if (options.has(`skip-minify`) && options.has(`mangle-names`)) {
|
355
|
+
logError(`Option ${colourN(`--mangle-names`)} is not compatible with ${colourN(`--skip-minify`)}\n`);
|
356
|
+
logHelp();
|
357
|
+
break;
|
358
|
+
}
|
359
|
+
const shouldSkipMinify = options.get(`skip-minify`);
|
360
|
+
let shouldMinify;
|
361
|
+
if (shouldSkipMinify != undefined) {
|
362
|
+
if (typeof shouldSkipMinify != `boolean`) {
|
363
|
+
logError(`The value for ${colourN(`--skip-minify`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
364
|
+
logHelp();
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
shouldMinify = !shouldSkipMinify;
|
368
|
+
}
|
369
|
+
const shouldMangleNames = options.get(`mangle-names`);
|
370
|
+
if (shouldMangleNames != undefined && typeof shouldMangleNames != `boolean`) {
|
371
|
+
logError(`The value for ${colourN(`--mangle-names`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
372
|
+
logHelp();
|
373
|
+
break;
|
374
|
+
}
|
375
|
+
const shouldforceQuineCheats = options.get(`force-quine-cheats`);
|
376
|
+
if (shouldforceQuineCheats != undefined && typeof shouldforceQuineCheats != `boolean`) {
|
377
|
+
logError(`The value for ${colourN(`--force-quine-cheats`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
378
|
+
logHelp();
|
379
|
+
break;
|
380
|
+
}
|
381
|
+
const {
|
382
|
+
push
|
383
|
+
} = await pushModule;
|
384
|
+
const infos = await push(sourcePath, hackmudPath, {
|
385
|
+
scripts,
|
386
|
+
onPush: info => logInfo(info, hackmudPath),
|
387
|
+
minify: shouldMinify,
|
388
|
+
mangleNames: shouldMangleNames,
|
389
|
+
forceQuineCheats: shouldforceQuineCheats
|
390
|
+
});
|
391
|
+
if (!infos.length) logError(`Could not find any scripts to push`);
|
392
|
+
}
|
393
|
+
break;
|
394
|
+
case `dev`:
|
395
|
+
case `watch`:
|
396
|
+
{
|
397
|
+
var _ref;
|
398
|
+
const {
|
399
|
+
hackmudPath
|
400
|
+
} = await configPromise;
|
401
|
+
if (!hackmudPath) {
|
402
|
+
logNeedHackmudPathMessage();
|
403
|
+
break;
|
404
|
+
}
|
405
|
+
const sourcePath = commands[1];
|
406
|
+
if (!sourcePath) {
|
407
|
+
logError(`Must provide the directory to watch\n`);
|
408
|
+
logHelp();
|
409
|
+
break;
|
410
|
+
}
|
411
|
+
const scripts = commands.slice(2);
|
412
|
+
if (scripts.length) {
|
413
|
+
const invalidScript = scripts.find(script => !/^(?:[a-z_][a-z\d_]{0,24}|\*)\.(?:[a-z_][a-z\d_]{0,24}|\*)$/.test(script));
|
414
|
+
if (invalidScript) {
|
415
|
+
logError(`Invalid script name: ${JSON.stringify(invalidScript)}\n`);
|
416
|
+
logHelp();
|
417
|
+
break;
|
418
|
+
}
|
419
|
+
} else scripts.push(`*.*`);
|
420
|
+
if (options.has(`skip-minify`) && options.has(`mangle-names`)) {
|
421
|
+
logError(`Option ${colourN(`--mangle-names`)} is not compatible with ${colourN(`--skip-minify`)}\n`);
|
422
|
+
logHelp();
|
423
|
+
break;
|
424
|
+
}
|
425
|
+
const shouldSkipMinify = options.get(`skip-minify`);
|
426
|
+
let shouldMinify;
|
427
|
+
if (shouldSkipMinify != undefined) {
|
428
|
+
if (typeof shouldSkipMinify != `boolean`) {
|
429
|
+
logError(`The value for ${colourN(`--skip-minify`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
430
|
+
logHelp();
|
431
|
+
break;
|
432
|
+
}
|
433
|
+
shouldMinify = !shouldSkipMinify;
|
434
|
+
}
|
435
|
+
const shouldMangleNames = options.get(`mangle-names`);
|
436
|
+
if (shouldMangleNames != undefined && typeof shouldMangleNames != `boolean`) {
|
437
|
+
logError(`The value for ${colourN(`--mangle-names`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
438
|
+
logHelp();
|
439
|
+
break;
|
440
|
+
}
|
441
|
+
const shouldforceQuineCheats = options.get(`force-quine-cheats`);
|
442
|
+
if (shouldforceQuineCheats != undefined && typeof shouldforceQuineCheats != `boolean`) {
|
443
|
+
logError(`The value for ${colourN(`--force-quine-cheats`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
444
|
+
logHelp();
|
445
|
+
break;
|
446
|
+
}
|
447
|
+
const {
|
448
|
+
watch
|
449
|
+
} = await watchModule;
|
450
|
+
watch(sourcePath, hackmudPath, {
|
451
|
+
scripts,
|
452
|
+
onPush: info => logInfo(info, hackmudPath),
|
453
|
+
typeDeclarationPath: (_ref = options.get(`type-declaration-path`) || options.get(`type-declaration`) || options.get(`dts`) || options.get(`gen-types`)) === null || _ref === void 0 ? void 0 : _ref.toString(),
|
454
|
+
minify: shouldMinify,
|
455
|
+
mangleNames: shouldMangleNames,
|
456
|
+
onReady: () => log(`Watching`),
|
457
|
+
forceQuineCheats: shouldforceQuineCheats
|
458
|
+
});
|
459
|
+
autoExit = false;
|
460
|
+
}
|
461
|
+
break;
|
462
|
+
case `pull`:
|
463
|
+
{
|
464
|
+
const {
|
465
|
+
hackmudPath
|
466
|
+
} = await configPromise;
|
467
|
+
if (!hackmudPath) {
|
468
|
+
logNeedHackmudPathMessage();
|
469
|
+
break;
|
470
|
+
}
|
471
|
+
const script = commands[1];
|
472
|
+
if (!script) {
|
473
|
+
logError(`Must provide the script to pull\n`);
|
474
|
+
logHelp();
|
475
|
+
break;
|
476
|
+
}
|
477
|
+
const sourcePath = commands[2] || `.`;
|
478
|
+
try {
|
479
|
+
await pull(sourcePath, hackmudPath, script);
|
480
|
+
} catch (error) {
|
481
|
+
console.error(error);
|
482
|
+
logError(`Something went wrong, did you forget to ${colourC(`#down`)} the script?`);
|
483
|
+
}
|
484
|
+
}
|
485
|
+
break;
|
486
|
+
case `sync-macros`:
|
487
|
+
{
|
488
|
+
const {
|
489
|
+
hackmudPath
|
490
|
+
} = await configPromise;
|
491
|
+
if (!hackmudPath) {
|
492
|
+
logNeedHackmudPathMessage();
|
493
|
+
break;
|
494
|
+
}
|
495
|
+
const {
|
496
|
+
macrosSynced,
|
497
|
+
usersSynced
|
498
|
+
} = await syncMacros(hackmudPath);
|
499
|
+
log(`Synced ${macrosSynced} macros to ${usersSynced} users`);
|
500
|
+
}
|
501
|
+
break;
|
502
|
+
case `generate-type-declaration`:
|
503
|
+
case `gen-type-declaration`:
|
504
|
+
case `gen-dts`:
|
505
|
+
case `gen-types`:
|
506
|
+
{
|
507
|
+
const target = commands[1];
|
508
|
+
if (!target) {
|
509
|
+
logError(`Must provide target directory\n`);
|
510
|
+
logHelp();
|
511
|
+
break;
|
512
|
+
}
|
513
|
+
const sourcePath = resolve(target);
|
514
|
+
const outputPath = commands[2] || `./player.d.ts`;
|
515
|
+
const typeDeclaration = await generateTypeDeclaration(sourcePath, (await configPromise).hackmudPath);
|
516
|
+
let typeDeclarationPath = resolve(outputPath);
|
517
|
+
try {
|
518
|
+
await writeFile(typeDeclarationPath, typeDeclaration);
|
519
|
+
} catch (error) {
|
520
|
+
assert(error instanceof Error);
|
521
|
+
if (!(error.code == `EISDIR`)) throw error;
|
522
|
+
typeDeclarationPath = resolve(typeDeclarationPath, `player.d.ts`);
|
523
|
+
await writeFile(typeDeclarationPath, typeDeclaration);
|
524
|
+
}
|
525
|
+
log(`Wrote type declaration to ${chalk.bold(typeDeclarationPath)}`);
|
526
|
+
}
|
527
|
+
break;
|
528
|
+
case `config`:
|
529
|
+
{
|
530
|
+
switch (commands[1]) {
|
531
|
+
case `get`:
|
532
|
+
{
|
533
|
+
const key = commands[2];
|
534
|
+
if (key) log(exploreObject(await configPromise, key.split(`.`)));else console.log(await configPromise);
|
535
|
+
}
|
536
|
+
break;
|
537
|
+
case `delete`:
|
538
|
+
{
|
539
|
+
var _exploreObject;
|
540
|
+
const key = commands[2];
|
541
|
+
if (!key) {
|
542
|
+
logError(`Must provide a key to delete\n`);
|
543
|
+
logHelp();
|
544
|
+
break;
|
545
|
+
}
|
546
|
+
const keyParts = key.split(`.`);
|
547
|
+
const pathName = keyParts.map(name => /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name)).join(`.`);
|
548
|
+
const lastKey = keyParts.pop();
|
549
|
+
const config = await configPromise;
|
550
|
+
(_exploreObject = exploreObject(config, keyParts)) === null || _exploreObject === void 0 || delete _exploreObject[lastKey];
|
551
|
+
log(`Removed ${colourV(pathName)} from config file`);
|
552
|
+
}
|
553
|
+
break;
|
554
|
+
case `set`:
|
555
|
+
{
|
556
|
+
const key = commands[2];
|
557
|
+
const value = commands[3];
|
558
|
+
if (!key) {
|
559
|
+
logError(`Must provide a key and value\n`);
|
560
|
+
logHelp();
|
561
|
+
break;
|
562
|
+
}
|
563
|
+
const keys = key.split(`.`);
|
564
|
+
const pathName = keys.map(name => /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name)).join(`.`);
|
565
|
+
if (!value) {
|
566
|
+
logError(`Must provide a value for the key ${pathName}\n`);
|
567
|
+
logHelp();
|
568
|
+
break;
|
569
|
+
}
|
570
|
+
const lastKey = keys.pop();
|
571
|
+
const config = await configPromise;
|
572
|
+
if (!keys.length && lastKey == `hackmudPath`) config.hackmudPath = resolve(value.startsWith(`~/`) ? homedir() + value.slice(1) : value);else {
|
573
|
+
let object = config;
|
574
|
+
for (const key of keys) {
|
575
|
+
if (typeof object[key] == `object`) object = object[key];else {
|
576
|
+
object[key] = {};
|
577
|
+
object = object[key];
|
578
|
+
}
|
579
|
+
}
|
580
|
+
object[lastKey] = value;
|
581
|
+
}
|
582
|
+
console.log(config);
|
583
|
+
await updateConfig(config);
|
584
|
+
}
|
585
|
+
break;
|
586
|
+
default:
|
587
|
+
{
|
588
|
+
if (commands[1]) logError(`Unknown command: ${JSON.stringify(commands[1])}\n`);
|
589
|
+
logHelp();
|
590
|
+
}
|
591
|
+
}
|
592
|
+
}
|
593
|
+
break;
|
594
|
+
case `help`:
|
595
|
+
case `h`:
|
596
|
+
{
|
597
|
+
logHelp();
|
598
|
+
}
|
599
|
+
break;
|
600
|
+
case `golf`:
|
601
|
+
case `minify`:
|
602
|
+
{
|
603
|
+
const target = commands[1];
|
604
|
+
if (!target) {
|
605
|
+
logError(`Must provide target\n`);
|
606
|
+
logHelp();
|
607
|
+
break;
|
608
|
+
}
|
609
|
+
const fileExtension = extname(target);
|
610
|
+
if (!supportedExtensions.includes(fileExtension)) {
|
611
|
+
logError(`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join(`", "`)}"`);
|
612
|
+
break;
|
613
|
+
}
|
614
|
+
const {
|
615
|
+
processScript
|
616
|
+
} = await processScriptModule;
|
617
|
+
const fileBaseName = basename(target, fileExtension);
|
618
|
+
// eslint-disable-next-line unicorn/prevent-abbreviations -- the file extension is `src` not `source`
|
619
|
+
const fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(`.src`);
|
620
|
+
const scriptName = fileBaseNameEndsWithDotSrc ? fileBaseName.slice(0, -4) : fileBaseName;
|
621
|
+
const scriptUser = basename(resolve(target, `..`)) == `scripts` && basename(resolve(target, `../../..`)) == `hackmud` ? basename(resolve(target, `../..`)) : `UNKNOWN`;
|
622
|
+
const minify = !options.get(`skip-minify`);
|
623
|
+
if (options.has(`skip-minify`) && options.has(`mangle-names`)) {
|
624
|
+
logError(`Option ${colourN(`--mangle-names`)} would have no effect if minification is skipped\n`);
|
625
|
+
logHelp();
|
626
|
+
break;
|
627
|
+
}
|
628
|
+
const mangleNames_ = options.get(`mangle-names`);
|
629
|
+
if (mangleNames_ != undefined && typeof mangleNames_ != `boolean`) {
|
630
|
+
logError(`The value for ${colourN(`--mangle-names`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
631
|
+
logHelp();
|
632
|
+
break;
|
633
|
+
}
|
634
|
+
const mangleNames = mangleNames_;
|
635
|
+
const forceQuineCheats_ = options.get(`force-quine-cheats`);
|
636
|
+
if (forceQuineCheats_ != undefined && typeof forceQuineCheats_ != `boolean`) {
|
637
|
+
logError(`the value for ${colourN(`--force-quine-cheats`)} must be ${colourV(`true`)} or ${colourV(`false`)}\n`);
|
638
|
+
logHelp();
|
639
|
+
break;
|
640
|
+
}
|
641
|
+
const forceQuineCheats = forceQuineCheats_;
|
642
|
+
let outputPath = commands[2] || resolve(dirname(target), fileBaseNameEndsWithDotSrc ? `${scriptName}.js` : fileExtension == `.js` ? `${fileBaseName}.min.js` : `${fileBaseName}.js`);
|
643
|
+
const golfFile = () => readFile(target, {
|
644
|
+
encoding: `utf-8`
|
645
|
+
}).then(async source => {
|
646
|
+
const timeStart = performance.now();
|
647
|
+
const {
|
648
|
+
script,
|
649
|
+
warnings
|
650
|
+
} = await processScript(source, {
|
651
|
+
minify,
|
652
|
+
scriptUser,
|
653
|
+
scriptName,
|
654
|
+
filePath: target,
|
655
|
+
mangleNames,
|
656
|
+
forceQuineCheats
|
657
|
+
});
|
658
|
+
const timeTook = performance.now() - timeStart;
|
659
|
+
for (const {
|
660
|
+
message,
|
661
|
+
line
|
662
|
+
} of warnings) log(`Warning "${chalk.bold(message)}" on line ${chalk.bold(String(line))}`);
|
663
|
+
await writeFilePersistent(outputPath, script).catch(async error => {
|
664
|
+
if (!commands[2] || error.code != `EISDIR`) throw error;
|
665
|
+
outputPath = resolve(outputPath, `${basename(target, fileExtension)}.js`);
|
666
|
+
await writeFilePersistent(outputPath, script);
|
667
|
+
}).then(() => log(`Wrote ${chalk.bold(countHackmudCharacters(script))} chars to ${chalk.bold(relative(`.`, outputPath))} | took ${Math.round(timeTook * 100) / 100}ms`), error => logError(error.message));
|
668
|
+
}, error => logError(error.message));
|
669
|
+
if (options.get(`watch`)) {
|
670
|
+
const {
|
671
|
+
watch: watchFile
|
672
|
+
} = await chokidarModule;
|
673
|
+
watchFile(target, {
|
674
|
+
awaitWriteFinish: {
|
675
|
+
stabilityThreshold: 100
|
676
|
+
}
|
677
|
+
}).on(`ready`, () => log(`Watching ${target}`)).on(`change`, golfFile);
|
678
|
+
autoExit = false;
|
679
|
+
} else await golfFile();
|
680
|
+
}
|
681
|
+
break;
|
682
|
+
default:
|
683
|
+
{
|
684
|
+
if (commands[0]) logError(`Unknown command: ${JSON.stringify(commands[0])}\n`);
|
685
|
+
logHelp();
|
686
|
+
}
|
687
|
+
}
|
688
|
+
if (autoExit) process.exit();
|