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/watch.js CHANGED
@@ -1,228 +1 @@
1
- import { DynamicMap } from '@samual/lib/DynamicMap';
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};