hackmud-script-manager 0.19.0-7c69a3b → 0.19.0-b5e2c0b

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