hackmud-script-manager 0.19.0 → 0.19.1-4bde221

Sign up to get free protection for your applications and to get access to all the features.
package/watch.js CHANGED
@@ -1 +1,209 @@
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};
1
+ import { Cache } from "@samual/lib/Cache"
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
+ const watch = async (
47
+ sourceDirectory,
48
+ hackmudDirectory,
49
+ {
50
+ scripts = ["*.*"],
51
+ onPush,
52
+ minify = !0,
53
+ mangleNames = !1,
54
+ typeDeclarationPath: typeDeclarationPath_,
55
+ onReady,
56
+ forceQuineCheats
57
+ } = {}
58
+ ) => {
59
+ if (!scripts.length) throw Error("scripts option was an empty array")
60
+ const scriptNamesToUsers = new Cache(_scriptName => new Set()),
61
+ wildScriptUsers = new Set(),
62
+ wildUserScripts = new Set()
63
+ let pushEverything = !1
64
+ for (const fullScriptName of scripts) {
65
+ const [user, scriptName] = fullScriptName.split(".")
66
+ user && "*" != user ?
67
+ scriptName && "*" != scriptName ?
68
+ scriptNamesToUsers.get(scriptName).add(user)
69
+ : wildScriptUsers.add(user)
70
+ : scriptName && "*" != scriptName ? wildUserScripts.add(scriptName)
71
+ : (pushEverything = !0)
72
+ }
73
+ const watcher = watch$1(["*/*.ts", "*/*.js"], {
74
+ cwd: sourceDirectory,
75
+ awaitWriteFinish: { stabilityThreshold: 100 },
76
+ ignored: "*.d.ts"
77
+ }).on("change", async path => {
78
+ if (path.endsWith(".d.ts")) return
79
+ const extension = extname(path)
80
+ if (!supportedExtensions.includes(extension)) return
81
+ const scriptName = basename(path, extension)
82
+ if (path == basename(path)) {
83
+ if (
84
+ !(
85
+ pushEverything ||
86
+ wildScriptUsers.size ||
87
+ wildUserScripts.has(scriptName) ||
88
+ scriptNamesToUsers.has(scriptName)
89
+ )
90
+ )
91
+ return
92
+ const scriptNamesToUsersToSkip = new Cache(_scriptName => [])
93
+ await Promise.all(
94
+ (await readdir(sourceDirectory, { withFileTypes: !0 })).map(async dirent => {
95
+ if (dirent.isDirectory())
96
+ for (const file of await readdir(resolve(sourceDirectory, dirent.name), {
97
+ withFileTypes: !0
98
+ })) {
99
+ if (!file.isFile()) continue
100
+ const fileExtension = extname(file.name)
101
+ supportedExtensions.includes(fileExtension) &&
102
+ scriptNamesToUsersToSkip.get(basename(file.name, fileExtension)).push(dirent.name)
103
+ }
104
+ })
105
+ )
106
+ const usersToPushToSet = new Set()
107
+ if (pushEverything || wildUserScripts.has(scriptName)) {
108
+ for (const dirent of await readdir(resolve(sourceDirectory), { withFileTypes: !0 }))
109
+ dirent.isDirectory() && usersToPushToSet.add(dirent.name)
110
+ for (const dirent of await readdir(resolve(hackmudDirectory), { withFileTypes: !0 }))
111
+ dirent.isDirectory() ?
112
+ usersToPushToSet.add(dirent.name)
113
+ : dirent.isFile() && dirent.name.endsWith(".key") && usersToPushToSet.add(dirent.name.slice(0, -4))
114
+ for (const users of scriptNamesToUsers.values()) for (const user of users) usersToPushToSet.add(user)
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?.({ file: path, users: [], minLength: 0, error: Error("no users to push to") })
121
+ return
122
+ }
123
+ const uniqueID = Math.floor(Math.random() * 2 ** 52)
124
+ .toString(36)
125
+ .padStart(11, "0"),
126
+ filePath = resolve(sourceDirectory, path)
127
+ let minifiedCode
128
+ try {
129
+ ;({ script: minifiedCode } = await processScript(await readFile(filePath, { encoding: "utf-8" }), {
130
+ minify,
131
+ scriptUser: !0,
132
+ scriptName,
133
+ uniqueID,
134
+ filePath,
135
+ mangleNames,
136
+ forceQuineCheats
137
+ }))
138
+ } catch (error) {
139
+ assert(error instanceof Error)
140
+ onPush?.({ file: path, users: [], minLength: 0, error })
141
+ return
142
+ }
143
+ await Promise.all(
144
+ usersToPushTo.map(user =>
145
+ writeFilePersistent(
146
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
147
+ minifiedCode
148
+ .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
149
+ .replace(RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"), `${user}.${scriptName}`)
150
+ )
151
+ )
152
+ )
153
+ onPush?.({
154
+ file: path,
155
+ users: usersToPushTo,
156
+ minLength: countHackmudCharacters(minifiedCode),
157
+ error: void 0
158
+ })
159
+ return
160
+ }
161
+ const user = basename(resolve(path, ".."))
162
+ if (
163
+ !(
164
+ pushEverything ||
165
+ wildScriptUsers.size ||
166
+ wildUserScripts.has(scriptName) ||
167
+ scriptNamesToUsers.get(scriptName).has(user)
168
+ )
169
+ )
170
+ return
171
+ const filePath = resolve(sourceDirectory, path),
172
+ sourceCode = await readFile(filePath, { encoding: "utf-8" })
173
+ let script
174
+ try {
175
+ ;({ script } = await processScript(sourceCode, {
176
+ minify,
177
+ scriptUser: user,
178
+ scriptName,
179
+ filePath,
180
+ mangleNames,
181
+ forceQuineCheats
182
+ }))
183
+ } catch (error) {
184
+ assert(error instanceof Error)
185
+ onPush?.({ file: path, users: [], minLength: 0, error })
186
+ return
187
+ }
188
+ await writeFilePersistent(resolve(hackmudDirectory, user, "scripts", scriptName + ".js"), script)
189
+ onPush?.({ file: path, users: [user], minLength: countHackmudCharacters(script), error: void 0 })
190
+ })
191
+ onReady && watcher.on("ready", onReady)
192
+ if (!typeDeclarationPath_) return
193
+ let typeDeclarationPath = typeDeclarationPath_
194
+ const writeTypeDeclaration = async () => {
195
+ const typeDeclaration = await generateTypeDeclaration(sourceDirectory, hackmudDirectory)
196
+ try {
197
+ await writeFile(typeDeclarationPath, typeDeclaration)
198
+ } catch (error) {
199
+ assert(error instanceof Error)
200
+ if ("EISDIR" != error.code) throw error
201
+ typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
202
+ await writeFile(typeDeclarationPath, typeDeclaration)
203
+ }
204
+ }
205
+ await writeTypeDeclaration()
206
+ watcher.on("add", writeTypeDeclaration)
207
+ watcher.on("unlink", writeTypeDeclaration)
208
+ }
209
+ export { watch as default, watch }