hackmud-script-manager 0.19.0-f21e319 → 0.19.0-fa82f73
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 +1 -0
- package/bin/hsm.js +1 -687
- package/constants.js +1 -4
- package/generateTypeDeclaration.js +1 -94
- package/index.js +1 -47
- package/package.json +40 -39
- package/processScript/index.js +1 -310
- package/processScript/minify.js +1 -376
- package/processScript/postprocess.js +1 -5
- package/processScript/preprocess.js +1 -84
- package/processScript/shared.js +1 -18
- package/processScript/transform.js +1 -394
- package/pull.js +1 -17
- package/push.js +1 -251
- package/syncMacros.js +1 -53
- package/tsconfig.tsbuildinfo +1 -1
- package/watch.js +1 -228
package/watch.js
CHANGED
@@ -1,228 +1 @@
|
|
1
|
-
import
|
2
|
-
import { assert } from '@samual/lib/assert';
|
3
|
-
import { countHackmudCharacters } from '@samual/lib/countHackmudCharacters';
|
4
|
-
import { writeFilePersistent } from '@samual/lib/writeFilePersistent';
|
5
|
-
import { watch as watch$1 } from 'chokidar';
|
6
|
-
import { readdir, readFile, writeFile } from 'fs/promises';
|
7
|
-
import { extname, basename, resolve } from 'path';
|
8
|
-
import { supportedExtensions } from './constants.js';
|
9
|
-
import { generateTypeDeclaration } from './generateTypeDeclaration.js';
|
10
|
-
import { processScript } from './processScript/index.js';
|
11
|
-
import '@babel/generator';
|
12
|
-
import '@babel/parser';
|
13
|
-
import '@babel/plugin-proposal-class-properties';
|
14
|
-
import '@babel/plugin-proposal-class-static-block';
|
15
|
-
import '@babel/plugin-proposal-decorators';
|
16
|
-
import '@babel/plugin-proposal-json-strings';
|
17
|
-
import '@babel/plugin-proposal-logical-assignment-operators';
|
18
|
-
import '@babel/plugin-proposal-nullish-coalescing-operator';
|
19
|
-
import '@babel/plugin-proposal-numeric-separator';
|
20
|
-
import '@babel/plugin-proposal-object-rest-spread';
|
21
|
-
import '@babel/plugin-proposal-optional-catch-binding';
|
22
|
-
import '@babel/plugin-proposal-optional-chaining';
|
23
|
-
import '@babel/plugin-proposal-private-property-in-object';
|
24
|
-
import '@babel/plugin-transform-exponentiation-operator';
|
25
|
-
import '@babel/traverse';
|
26
|
-
import '@babel/types';
|
27
|
-
import '@rollup/plugin-babel';
|
28
|
-
import '@rollup/plugin-commonjs';
|
29
|
-
import '@rollup/plugin-json';
|
30
|
-
import '@rollup/plugin-node-resolve';
|
31
|
-
import 'prettier';
|
32
|
-
import 'rollup';
|
33
|
-
import './processScript/minify.js';
|
34
|
-
import '@samual/lib/spliceString';
|
35
|
-
import 'acorn';
|
36
|
-
import 'terser';
|
37
|
-
import './processScript/shared.js';
|
38
|
-
import './processScript/postprocess.js';
|
39
|
-
import './processScript/preprocess.js';
|
40
|
-
import 'import-meta-resolve';
|
41
|
-
import './processScript/transform.js';
|
42
|
-
import '@samual/lib/clearObject';
|
43
|
-
|
44
|
-
/**
|
45
|
-
* Watches target file or folder for updates and builds and pushes updated file.
|
46
|
-
*
|
47
|
-
* @param sourceDirectory path to folder containing source files
|
48
|
-
* @param hackmudDirectory path to hackmud directory
|
49
|
-
* @param options {@link WatchOptions details} and {@link PushOptions more details}
|
50
|
-
*/
|
51
|
-
const watch = async (sourceDirectory, hackmudDirectory, {
|
52
|
-
scripts = [`*.*`],
|
53
|
-
onPush,
|
54
|
-
minify = true,
|
55
|
-
mangleNames = false,
|
56
|
-
typeDeclarationPath: typeDeclarationPath_,
|
57
|
-
onReady,
|
58
|
-
forceQuineCheats
|
59
|
-
} = {}) => {
|
60
|
-
if (!scripts.length) throw new Error(`scripts option was an empty array`);
|
61
|
-
const scriptNamesToUsers = new DynamicMap(_scriptName => new Set());
|
62
|
-
const wildScriptUsers = new Set();
|
63
|
-
const wildUserScripts = new Set();
|
64
|
-
let pushEverything = false;
|
65
|
-
for (const fullScriptName of scripts) {
|
66
|
-
const [user, scriptName] = fullScriptName.split(`.`);
|
67
|
-
if (!user || user == `*`) {
|
68
|
-
if (!scriptName || scriptName == `*`) pushEverything = true;else wildUserScripts.add(scriptName);
|
69
|
-
} else if (!scriptName || scriptName == `*`) wildScriptUsers.add(user);else scriptNamesToUsers.get(scriptName).add(user);
|
70
|
-
}
|
71
|
-
const watcher = watch$1([`*.ts`, `*.js`], {
|
72
|
-
depth: 1,
|
73
|
-
cwd: sourceDirectory,
|
74
|
-
awaitWriteFinish: {
|
75
|
-
stabilityThreshold: 100
|
76
|
-
},
|
77
|
-
ignored: `*.d.ts`
|
78
|
-
}).on(`change`, async path => {
|
79
|
-
if (path.endsWith(`.d.ts`)) return;
|
80
|
-
const extension = extname(path);
|
81
|
-
if (!supportedExtensions.includes(extension)) return;
|
82
|
-
const scriptName = basename(path, extension);
|
83
|
-
|
84
|
-
// if the path is still the same after getting just the base, it means it's directly in the source directory (global)
|
85
|
-
if (path == basename(path)) {
|
86
|
-
if (!pushEverything && !wildScriptUsers.size && !wildUserScripts.has(scriptName) && !scriptNamesToUsers.has(scriptName)) return;
|
87
|
-
const scriptNamesToUsersToSkip = new DynamicMap(_scriptName => []);
|
88
|
-
await Promise.all((await readdir(sourceDirectory, {
|
89
|
-
withFileTypes: true
|
90
|
-
})).map(async dirent => {
|
91
|
-
if (!dirent.isDirectory()) return;
|
92
|
-
for (const file of await readdir(resolve(sourceDirectory, dirent.name), {
|
93
|
-
withFileTypes: true
|
94
|
-
})) {
|
95
|
-
if (!file.isFile()) continue;
|
96
|
-
const fileExtension = extname(file.name);
|
97
|
-
if (supportedExtensions.includes(fileExtension)) scriptNamesToUsersToSkip.get(basename(file.name, fileExtension)).push(dirent.name);
|
98
|
-
}
|
99
|
-
}));
|
100
|
-
const usersToPushToSet = new Set();
|
101
|
-
if (pushEverything || wildUserScripts.has(scriptName)) {
|
102
|
-
for (const dirent of await readdir(resolve(sourceDirectory), {
|
103
|
-
withFileTypes: true
|
104
|
-
})) {
|
105
|
-
if (dirent.isDirectory()) usersToPushToSet.add(dirent.name);
|
106
|
-
}
|
107
|
-
for (const dirent of await readdir(resolve(hackmudDirectory), {
|
108
|
-
withFileTypes: true
|
109
|
-
})) {
|
110
|
-
if (dirent.isDirectory()) usersToPushToSet.add(dirent.name);else if (dirent.isFile() && dirent.name.endsWith(`.key`)) usersToPushToSet.add(dirent.name.slice(0, -4));
|
111
|
-
}
|
112
|
-
for (const users of scriptNamesToUsers.values()) {
|
113
|
-
for (const user of users) usersToPushToSet.add(user);
|
114
|
-
}
|
115
|
-
}
|
116
|
-
for (const user of wildScriptUsers) usersToPushToSet.add(user);
|
117
|
-
for (const user of scriptNamesToUsers.get(scriptName)) usersToPushToSet.add(user);
|
118
|
-
const usersToPushTo = [...usersToPushToSet].filter(user => !scriptNamesToUsersToSkip.has(user));
|
119
|
-
if (!usersToPushTo.length) {
|
120
|
-
onPush === null || onPush === void 0 ? void 0 : onPush({
|
121
|
-
file: path,
|
122
|
-
users: [],
|
123
|
-
minLength: 0,
|
124
|
-
error: new Error(`no users to push to`)
|
125
|
-
});
|
126
|
-
return;
|
127
|
-
}
|
128
|
-
const uniqueID = Math.floor(Math.random() * 2 ** 52).toString(36).padStart(11, `0`);
|
129
|
-
const filePath = resolve(sourceDirectory, path);
|
130
|
-
let minifiedCode;
|
131
|
-
try {
|
132
|
-
({
|
133
|
-
script: minifiedCode
|
134
|
-
} = await processScript(await readFile(filePath, {
|
135
|
-
encoding: `utf-8`
|
136
|
-
}), {
|
137
|
-
minify,
|
138
|
-
scriptUser: true,
|
139
|
-
scriptName,
|
140
|
-
uniqueID,
|
141
|
-
filePath,
|
142
|
-
mangleNames,
|
143
|
-
forceQuineCheats
|
144
|
-
}));
|
145
|
-
} catch (error) {
|
146
|
-
assert(error instanceof Error);
|
147
|
-
onPush === null || onPush === void 0 ? void 0 : onPush({
|
148
|
-
file: path,
|
149
|
-
users: [],
|
150
|
-
minLength: 0,
|
151
|
-
error
|
152
|
-
});
|
153
|
-
return;
|
154
|
-
}
|
155
|
-
await Promise.all(usersToPushTo.map(user => writeFilePersistent(resolve(hackmudDirectory, user, `scripts/${scriptName}.js`), minifiedCode.replace(new RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, `g`), user).replace(new RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, `g`), `${user}.${scriptName}`))));
|
156
|
-
onPush === null || onPush === void 0 ? void 0 : onPush({
|
157
|
-
file: path,
|
158
|
-
users: usersToPushTo,
|
159
|
-
minLength: countHackmudCharacters(minifiedCode),
|
160
|
-
error: undefined
|
161
|
-
});
|
162
|
-
return;
|
163
|
-
}
|
164
|
-
const user = basename(resolve(path, `..`));
|
165
|
-
if (!pushEverything && !wildScriptUsers.size && !wildUserScripts.has(scriptName) && !scriptNamesToUsers.get(scriptName).has(user)) return;
|
166
|
-
const filePath = resolve(sourceDirectory, path);
|
167
|
-
const sourceCode = await readFile(filePath, {
|
168
|
-
encoding: `utf-8`
|
169
|
-
});
|
170
|
-
let script;
|
171
|
-
try {
|
172
|
-
({
|
173
|
-
script
|
174
|
-
} = await processScript(sourceCode, {
|
175
|
-
minify,
|
176
|
-
scriptUser: user,
|
177
|
-
scriptName,
|
178
|
-
filePath,
|
179
|
-
mangleNames,
|
180
|
-
forceQuineCheats
|
181
|
-
}));
|
182
|
-
} catch (error) {
|
183
|
-
assert(error instanceof Error);
|
184
|
-
onPush === null || onPush === void 0 ? void 0 : onPush({
|
185
|
-
file: path,
|
186
|
-
users: [],
|
187
|
-
minLength: 0,
|
188
|
-
error
|
189
|
-
});
|
190
|
-
return;
|
191
|
-
}
|
192
|
-
await writeFilePersistent(resolve(hackmudDirectory, user, `scripts`, `${scriptName}.js`), script);
|
193
|
-
onPush === null || onPush === void 0 ? void 0 : onPush({
|
194
|
-
file: path,
|
195
|
-
users: [user],
|
196
|
-
minLength: countHackmudCharacters(script),
|
197
|
-
error: undefined
|
198
|
-
});
|
199
|
-
});
|
200
|
-
if (onReady) watcher.on(`ready`, onReady);
|
201
|
-
if (!typeDeclarationPath_) return;
|
202
|
-
let typeDeclarationPath = typeDeclarationPath_;
|
203
|
-
|
204
|
-
/*
|
205
|
-
this currently works because the generated type declaration effectively
|
206
|
-
just connects things and doesn't actually read the scripts it's
|
207
|
-
generating type declarations for
|
208
|
-
if I ever change `generateTypings()` to actually read the scripts to
|
209
|
-
grab their types, this will need to change
|
210
|
-
*/
|
211
|
-
|
212
|
-
const writeTypeDeclaration = async () => {
|
213
|
-
const typeDeclaration = await generateTypeDeclaration(sourceDirectory, hackmudDirectory);
|
214
|
-
try {
|
215
|
-
await writeFile(typeDeclarationPath, typeDeclaration);
|
216
|
-
} catch (error) {
|
217
|
-
assert(error instanceof Error);
|
218
|
-
if (!(error.code == `EISDIR`)) throw error;
|
219
|
-
typeDeclarationPath = resolve(typeDeclarationPath, `player.d.ts`);
|
220
|
-
await writeFile(typeDeclarationPath, typeDeclaration);
|
221
|
-
}
|
222
|
-
};
|
223
|
-
await writeTypeDeclaration();
|
224
|
-
watcher.on(`add`, writeTypeDeclaration);
|
225
|
-
watcher.on(`unlink`, writeTypeDeclaration);
|
226
|
-
};
|
227
|
-
|
228
|
-
export { watch as default, watch };
|
1
|
+
import{DynamicMap as r}from"@samual/lib/DynamicMap";import{assert as t}from"@samual/lib/assert";import{countHackmudCharacters as e}from"@samual/lib/countHackmudCharacters";import{writeFilePersistent as i}from"@samual/lib/writeFilePersistent";import{watch as o}from"chokidar";import{readdir as a,readFile as s,writeFile as n}from"fs/promises";import{extname as p,basename as l,resolve as m}from"path";import{supportedExtensions as c}from"./constants.js";import{generateTypeDeclaration as f}from"./generateTypeDeclaration.js";import{processScript as u}from"./processScript/index.js";import"@babel/generator";import"@babel/parser";import"@babel/plugin-proposal-decorators";import"@babel/plugin-proposal-destructuring-private";import"@babel/plugin-proposal-explicit-resource-management";import"@babel/plugin-transform-class-properties";import"@babel/plugin-transform-class-static-block";import"@babel/plugin-transform-exponentiation-operator";import"@babel/plugin-transform-json-strings";import"@babel/plugin-transform-logical-assignment-operators";import"@babel/plugin-transform-nullish-coalescing-operator";import"@babel/plugin-transform-numeric-separator";import"@babel/plugin-transform-object-rest-spread";import"@babel/plugin-transform-optional-catch-binding";import"@babel/plugin-transform-optional-chaining";import"@babel/plugin-transform-private-property-in-object";import"@babel/plugin-transform-unicode-sets-regex";import"@babel/traverse";import"@babel/types";import"@rollup/plugin-babel";import"@rollup/plugin-commonjs";import"@rollup/plugin-json";import"@rollup/plugin-node-resolve";import"prettier";import"rollup";import"./processScript/minify.js";import"@samual/lib/spliceString";import"acorn";import"terser";import"./processScript/shared.js";import"./processScript/postprocess.js";import"./processScript/preprocess.js";import"import-meta-resolve";import"./processScript/transform.js";import"@samual/lib/clearObject";const watch=async(d,g,{scripts:b=["*.*"],onPush:h,minify:w=!0,mangleNames:y=!1,typeDeclarationPath:j,onReady:S,forceQuineCheats:v}={})=>{if(!b.length)throw new Error("scripts option was an empty array");const $=new r((r=>new Set)),E=new Set,F=new Set;let P=!1;for(const r of b){const[t,e]=r.split(".");t&&"*"!=t?e&&"*"!=e?$.get(e).add(t):E.add(t):e&&"*"!=e?F.add(e):P=!0}const D=o(["*/*.ts","*/*.js"],{cwd:d,awaitWriteFinish:{stabilityThreshold:100},ignored:"*.d.ts"}).on("change",(async o=>{if(o.endsWith(".d.ts"))return;const n=p(o);if(!c.includes(n))return;const f=l(o,n);if(o==l(o)){if(!(P||E.size||F.has(f)||$.has(f)))return;const n=new r((r=>[]));await Promise.all((await a(d,{withFileTypes:!0})).map((async r=>{if(r.isDirectory())for(const t of await a(m(d,r.name),{withFileTypes:!0})){if(!t.isFile())continue;const e=p(t.name);c.includes(e)&&n.get(l(t.name,e)).push(r.name)}})));const b=new Set;if(P||F.has(f)){for(const r of await a(m(d),{withFileTypes:!0}))r.isDirectory()&&b.add(r.name);for(const r of await a(m(g),{withFileTypes:!0}))r.isDirectory()?b.add(r.name):r.isFile()&&r.name.endsWith(".key")&&b.add(r.name.slice(0,-4));for(const r of $.values())for(const t of r)b.add(t)}for(const r of E)b.add(r);for(const r of $.get(f))b.add(r);const j=[...b].filter((r=>!n.has(r)));if(!j.length)return void h?.({file:o,users:[],minLength:0,error:new Error("no users to push to")});const S=Math.floor(Math.random()*2**52).toString(36).padStart(11,"0"),D=m(d,o);let T;try{({script:T}=await u(await s(D,{encoding:"utf-8"}),{minify:w,scriptUser:!0,scriptName:f,uniqueID:S,filePath:D,mangleNames:y,forceQuineCheats:v}))}catch(r){return t(r instanceof Error),void h?.({file:o,users:[],minLength:0,error:r})}return await Promise.all(j.map((r=>i(m(g,r,`scripts/${f}.js`),T.replace(new RegExp(`\\$${S}\\$SCRIPT_USER\\$`,"g"),r).replace(new RegExp(`\\$${S}\\$FULL_SCRIPT_NAME\\$`,"g"),`${r}.${f}`))))),void h?.({file:o,users:j,minLength:e(T),error:void 0})}const b=l(m(o,".."));if(!(P||E.size||F.has(f)||$.get(f).has(b)))return;const j=m(d,o),S=await s(j,{encoding:"utf-8"});let D;try{({script:D}=await u(S,{minify:w,scriptUser:b,scriptName:f,filePath:j,mangleNames:y,forceQuineCheats:v}))}catch(r){return t(r instanceof Error),void h?.({file:o,users:[],minLength:0,error:r})}await i(m(g,b,"scripts",`${f}.js`),D),h?.({file:o,users:[b],minLength:e(D),error:void 0})}));if(S&&D.on("ready",S),!j)return;let T=j;const writeTypeDeclaration=async()=>{const r=await f(d,g);try{await n(T,r)}catch(e){if(t(e instanceof Error),"EISDIR"!=e.code)throw e;T=m(T,"player.d.ts"),await n(T,r)}};await writeTypeDeclaration(),D.on("add",writeTypeDeclaration),D.on("unlink",writeTypeDeclaration)};export{watch as default,watch};
|