hackmud-script-manager 0.19.0 → 0.19.1-07fc9cb

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/README.md +0 -2
  2. package/bin/hsm.js +435 -1
  3. package/constants.js +3 -1
  4. package/generateTypeDeclaration.js +68 -1
  5. package/index.js +51 -1
  6. package/package.json +38 -39
  7. package/processScript/index.js +333 -1
  8. package/processScript/minify.js +444 -1
  9. package/processScript/postprocess.js +20 -1
  10. package/processScript/preprocess.js +105 -1
  11. package/processScript/shared.js +32 -1
  12. package/processScript/transform.js +668 -1
  13. package/pull.js +11 -1
  14. package/push.js +269 -1
  15. package/{bin → src/bin}/hsm.d.ts +0 -0
  16. package/src/generateTypeDeclaration.d.ts +2 -0
  17. package/src/processScript/index.d.ts +31 -0
  18. package/src/processScript/minify.d.ts +18 -0
  19. package/src/processScript/preprocess.d.ts +9 -0
  20. package/{processScript → src/processScript}/shared.d.ts +1 -1
  21. package/src/processScript/transform.d.ts +18 -0
  22. package/src/pull.d.ts +6 -0
  23. package/src/push.d.ts +29 -0
  24. package/{syncMacros.d.ts → src/syncMacros.d.ts} +1 -1
  25. package/src/watch.d.ts +15 -0
  26. package/syncMacros.js +43 -1
  27. package/watch.js +208 -1
  28. package/generateTypeDeclaration.d.ts +0 -2
  29. package/processScript/index.d.ts +0 -40
  30. package/processScript/minify.d.ts +0 -24
  31. package/processScript/preprocess.d.ts +0 -12
  32. package/processScript/transform.d.ts +0 -24
  33. package/pull.d.ts +0 -9
  34. package/push.d.ts +0 -37
  35. package/tsconfig.tsbuildinfo +0 -1
  36. package/watch.d.ts +0 -20
  37. /package/{constants.d.ts → src/constants.d.ts} +0 -0
  38. /package/{index.d.ts → src/index.d.ts} +0 -0
  39. /package/{processScript → src/processScript}/postprocess.d.ts +0 -0
package/pull.js CHANGED
@@ -1 +1,11 @@
1
- import{copyFilePersistent as t}from"@samual/lib/copyFilePersistent";import{resolve as r}from"path";const pull=async(s,a,i)=>{const[o,e]=i.split(".");if(!o||!e)throw new Error('`script` argument must be in "user.name" format');await t(r(a,o,"scripts",`${e}.js`),r(s,o,`${e}.js`))};export{pull as default,pull};
1
+ import { copyFilePersistent } from "@samual/lib/copyFilePersistent"
2
+ import { resolve } from "path"
3
+ async function pull(sourceFolderPath, hackmudPath, script) {
4
+ const [user, name] = script.split(".")
5
+ if (!user || !name) throw Error('`script` argument must be in "user.name" format')
6
+ await copyFilePersistent(
7
+ resolve(hackmudPath, user, "scripts", name + ".js"),
8
+ resolve(sourceFolderPath, user, name + ".js")
9
+ )
10
+ }
11
+ export { pull as default, pull }
package/push.js CHANGED
@@ -1 +1,269 @@
1
- import{DynamicMap as e}from"@samual/lib/DynamicMap";import{countHackmudCharacters as t}from"@samual/lib/countHackmudCharacters";import{writeFilePersistent as r}from"@samual/lib/writeFilePersistent";import{readdir as i,readFile as a}from"fs/promises";import{resolve as s,extname as o,basename as n}from"path";import{supportedExtensions as p}from"./constants.js";import{processScript as m}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"@samual/lib/assert";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 push=async(l,c,{scripts:f=["*.*"],onPush:u=(()=>{}),minify:g=!0,mangleNames:b=!1,forceQuineCheats:d}={})=>{const h=new e((e=>new Set)),w=new Set,$=new Set;let y=!1;for(const e of f){const[t,r]=e.split(".");t&&"*"!=t?r&&"*"!=r?h.get(t).add(r):w.add(t):r&&"*"!=r?$.add(r):y=!0}const S=new e((e=>new Set)),P=[],j=new e((e=>new Set));let N;if($.size||y){const e=await i(s(c),{withFileTypes:!0}),t=new Set([...(N=await i(s(l),{withFileTypes:!0})).filter((e=>e.isDirectory())).map((e=>e.name)),...e.filter((e=>e.isDirectory())).map((e=>e.name)),...e.filter((e=>e.isFile()&&e.name.endsWith(".key"))).map((e=>e.name.slice(0,-4))),...h.keys(),...w]);if(y)for(const e of t)w.add(e);else for(const e of t){const t=h.get(e);for(const e of $)t.add(e)}}return await Promise.all([...w].map((async e=>{await i(s(l,e),{withFileTypes:!0}).then((async i=>{await Promise.all(i.map((async i=>{if(i.name.endsWith(".d.ts"))return;const f=o(i.name);if(i.isFile()&&p.includes(f)){const o=n(i.name,f),p=s(l,e,i.name),{script:h}=await m(await a(p,{encoding:"utf-8"}),{minify:g,scriptUser:e,scriptName:o,filePath:p,mangleNames:b,forceQuineCheats:d}),w={file:`${e}/${i.name}`,users:[e],minLength:t(h),error:void 0};j.get(e).add(o),P.push(w),await r(s(c,e,`scripts/${o}.js`),h),u(w)}})))}),(e=>{if("ENOENT"!=e.code)throw e}))}))),await Promise.all([...h].map((async([e,i])=>{w.has(e)||await Promise.all([...i].map((async i=>{let o,n,f;for(const t of p)try{n=`${i}${t}`,o=await a(f=s(l,e,n),{encoding:"utf-8"});break}catch{}if(o){const{script:a}=await m(o,{minify:g,scriptUser:e,scriptName:i,filePath:f,mangleNames:b,forceQuineCheats:d}),p={file:`${e}/${n}`,users:[e],minLength:t(a),error:void 0};P.push(p),await r(s(c,e,"scripts",`${i}.js`),a),u(p)}else S.get(i).add(e)})))}))),await(w.size?Promise.all((N||await i(s(l),{withFileTypes:!0})).map((async e=>{if(e.name.endsWith(".d.ts"))return;const i=o(e.name);if(!e.isFile()||!p.includes(i))return;const f=n(e.name,i),h=[...w,...S.get(f)].filter((e=>!j.get(e).has(f)));if(!h.length)return;const $=Math.floor(Math.random()*2**52).toString(36).padStart(11,"0"),y=s(l,e.name),{script:N}=await m(await a(y,{encoding:"utf-8"}),{minify:g,scriptUser:!0,scriptName:f,uniqueID:$,filePath:y,mangleNames:b,forceQuineCheats:d}),C={file:e.name,users:h,minLength:t(N),error:void 0};await Promise.all(h.map((e=>r(s(c,e,`scripts/${f}.js`),N.replace(new RegExp(`\\$${$}\\$SCRIPT_USER\\$`,"g"),e).replace(new RegExp(`\\$${$}\\$FULL_SCRIPT_NAME\\$`,"g"),`${e}.${f}`))))),P.push(C),u(C)}))):Promise.all([...S].map((async([e,i])=>{let o,n,f;for(const t of p)try{n=`${e}${t}`,o=await a(f=s(l,n),{encoding:"utf-8"});break}catch{}if(o){const a=Math.floor(Math.random()*2**52).toString(36).padStart(11,"0"),{script:p}=await m(o,{minify:g,scriptUser:!0,scriptName:e,uniqueID:a,filePath:f,mangleNames:b,forceQuineCheats:d}),l={file:n,users:[...i],minLength:t(p),error:void 0};await Promise.all([...i].map((t=>r(s(c,t,`scripts/${e}.js`),p.replace(new RegExp(`\\$${a}\\$SCRIPT_USER\\$`,"g"),t).replace(new RegExp(`\\$${a}\\$FULL_SCRIPT_NAME\\$`,"g"),`${t}.${e}`))))),P.push(l),u(l)}})))),P};export{push as default,push};
1
+ import { Cache } from "@samual/lib/Cache"
2
+ import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
3
+ import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
4
+ import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
5
+ import { readFile } from "fs/promises"
6
+ import { basename, resolve, extname } from "path"
7
+ import { supportedExtensions } from "./constants.js"
8
+ import { processScript } from "./processScript/index.js"
9
+ import "@babel/generator"
10
+ import "@babel/parser"
11
+ import "@babel/plugin-proposal-decorators"
12
+ import "@babel/plugin-proposal-destructuring-private"
13
+ import "@babel/plugin-proposal-explicit-resource-management"
14
+ import "@babel/plugin-transform-class-properties"
15
+ import "@babel/plugin-transform-class-static-block"
16
+ import "@babel/plugin-transform-exponentiation-operator"
17
+ import "@babel/plugin-transform-json-strings"
18
+ import "@babel/plugin-transform-logical-assignment-operators"
19
+ import "@babel/plugin-transform-nullish-coalescing-operator"
20
+ import "@babel/plugin-transform-numeric-separator"
21
+ import "@babel/plugin-transform-object-rest-spread"
22
+ import "@babel/plugin-transform-optional-catch-binding"
23
+ import "@babel/plugin-transform-optional-chaining"
24
+ import "@babel/plugin-transform-private-property-in-object"
25
+ import "@babel/plugin-transform-unicode-sets-regex"
26
+ import "@babel/traverse"
27
+ import "@babel/types"
28
+ import "@rollup/plugin-babel"
29
+ import "@rollup/plugin-commonjs"
30
+ import "@rollup/plugin-json"
31
+ import "@rollup/plugin-node-resolve"
32
+ import "@samual/lib/assert"
33
+ import "prettier"
34
+ import "rollup"
35
+ import "./processScript/minify.js"
36
+ import "@samual/lib/spliceString"
37
+ import "acorn"
38
+ import "terser"
39
+ import "./processScript/shared.js"
40
+ import "./processScript/postprocess.js"
41
+ import "./processScript/preprocess.js"
42
+ import "import-meta-resolve"
43
+ import "./processScript/transform.js"
44
+ import "@samual/lib/clearObject"
45
+ async function push(
46
+ sourceDirectory,
47
+ hackmudDirectory,
48
+ { scripts = ["*.*"], onPush = () => {}, minify = !0, mangleNames = !1, forceQuineCheats } = {}
49
+ ) {
50
+ const scriptNamesByUser = new Cache(_user => new Set()),
51
+ wildScriptUsers = new Set(),
52
+ wildUserScripts = new Set()
53
+ let pushEverything = !1
54
+ for (const fullScriptName of scripts) {
55
+ const [user, scriptName] = fullScriptName.split(".")
56
+ user && "*" != user ?
57
+ scriptName && "*" != scriptName ?
58
+ scriptNamesByUser.get(user).add(scriptName)
59
+ : wildScriptUsers.add(user)
60
+ : scriptName && "*" != scriptName ? wildUserScripts.add(scriptName)
61
+ : (pushEverything = !0)
62
+ }
63
+ const usersByGlobalScriptsToPush = new Cache(_user => new Set()),
64
+ allInfo = [],
65
+ scriptNamesAlreadyPushedByUser = new Cache(_user => new Set())
66
+ let sourceDirectoryDirents
67
+ if (wildUserScripts.size || pushEverything) {
68
+ let hackmudDirectoryEntries
69
+ ;[hackmudDirectoryEntries, sourceDirectoryDirents] = await Promise.all([
70
+ readDirectoryWithStats(hackmudDirectory),
71
+ readDirectoryWithStats(sourceDirectory)
72
+ ])
73
+ const allUsers = new Set([
74
+ ...sourceDirectoryDirents.filter(({ stats }) => stats.isDirectory()).map(({ path }) => basename(path)),
75
+ ...hackmudDirectoryEntries.filter(({ stats }) => stats.isDirectory()).map(({ name }) => name),
76
+ ...hackmudDirectoryEntries
77
+ .filter(({ name, stats }) => stats.isFile() && name.endsWith(".key"))
78
+ .map(({ name }) => name.slice(0, -4)),
79
+ ...scriptNamesByUser.keys(),
80
+ ...wildScriptUsers
81
+ ])
82
+ if (pushEverything) for (const user of allUsers) wildScriptUsers.add(user)
83
+ else
84
+ for (const user of allUsers) {
85
+ const scriptNames = scriptNamesByUser.get(user)
86
+ for (const scriptName of wildUserScripts) scriptNames.add(scriptName)
87
+ }
88
+ }
89
+ await Promise.all(
90
+ [...wildScriptUsers].map(async user => {
91
+ await readDirectoryWithStats(resolve(sourceDirectory, user)).then(
92
+ async entries => {
93
+ await Promise.all(
94
+ entries.map(async ({ stats, name, path }) => {
95
+ if (name.endsWith(".d.ts")) return
96
+ const extension = extname(name)
97
+ if (stats.isFile() && supportedExtensions.includes(extension)) {
98
+ const scriptName = basename(name, extension),
99
+ { script: minifiedCode } = await processScript(
100
+ await readFile(path, { encoding: "utf-8" }),
101
+ {
102
+ minify,
103
+ scriptUser: user,
104
+ scriptName,
105
+ filePath: path,
106
+ mangleNames,
107
+ forceQuineCheats
108
+ }
109
+ ),
110
+ info = {
111
+ file: `${user}/${name}`,
112
+ users: [user],
113
+ minLength: countHackmudCharacters(minifiedCode),
114
+ error: void 0
115
+ }
116
+ scriptNamesAlreadyPushedByUser.get(user).add(scriptName)
117
+ allInfo.push(info)
118
+ await writeFilePersistent(
119
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
120
+ minifiedCode
121
+ )
122
+ onPush(info)
123
+ }
124
+ })
125
+ )
126
+ },
127
+ error => {
128
+ if ("ENOENT" != error.code) throw error
129
+ }
130
+ )
131
+ })
132
+ )
133
+ await Promise.all(
134
+ [...scriptNamesByUser].map(async ([user, scripts]) => {
135
+ wildScriptUsers.has(user) ||
136
+ (await Promise.all(
137
+ [...scripts].map(async scriptName => {
138
+ let code, fileName, filePath
139
+ for (const extension of supportedExtensions)
140
+ try {
141
+ fileName = `${scriptName}${extension}`
142
+ code = await readFile((filePath = resolve(sourceDirectory, user, fileName)), {
143
+ encoding: "utf-8"
144
+ })
145
+ break
146
+ } catch {}
147
+ if (code) {
148
+ const { script: minifiedCode } = await processScript(code, {
149
+ minify,
150
+ scriptUser: user,
151
+ scriptName,
152
+ filePath,
153
+ mangleNames,
154
+ forceQuineCheats
155
+ }),
156
+ info = {
157
+ file: `${user}/${fileName}`,
158
+ users: [user],
159
+ minLength: countHackmudCharacters(minifiedCode),
160
+ error: void 0
161
+ }
162
+ allInfo.push(info)
163
+ await writeFilePersistent(
164
+ resolve(hackmudDirectory, user, "scripts", scriptName + ".js"),
165
+ minifiedCode
166
+ )
167
+ onPush(info)
168
+ } else usersByGlobalScriptsToPush.get(scriptName).add(user)
169
+ })
170
+ ))
171
+ })
172
+ )
173
+ await (wildScriptUsers.size ?
174
+ Promise.all(
175
+ (sourceDirectoryDirents || (await readDirectoryWithStats(sourceDirectory))).map(
176
+ async ({ path, stats, name }) => {
177
+ if (name.endsWith(".d.ts")) return
178
+ const extension = extname(name)
179
+ if (!stats.isFile() || !supportedExtensions.includes(extension)) return
180
+ const scriptName = basename(name, extension),
181
+ usersToPushTo = [...wildScriptUsers, ...usersByGlobalScriptsToPush.get(scriptName)].filter(
182
+ user => !scriptNamesAlreadyPushedByUser.get(user).has(scriptName)
183
+ )
184
+ if (!usersToPushTo.length) return
185
+ const uniqueID = Math.floor(Math.random() * 2 ** 52)
186
+ .toString(36)
187
+ .padStart(11, "0"),
188
+ { script: minifiedCode } = await processScript(await readFile(path, { encoding: "utf-8" }), {
189
+ minify,
190
+ scriptUser: !0,
191
+ scriptName,
192
+ uniqueID,
193
+ filePath: path,
194
+ mangleNames,
195
+ forceQuineCheats
196
+ }),
197
+ info = {
198
+ file: name,
199
+ users: usersToPushTo,
200
+ minLength: countHackmudCharacters(minifiedCode),
201
+ error: void 0
202
+ }
203
+ await Promise.all(
204
+ usersToPushTo.map(user =>
205
+ writeFilePersistent(
206
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
207
+ minifiedCode
208
+ .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
209
+ .replace(
210
+ RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"),
211
+ `${user}.${scriptName}`
212
+ )
213
+ )
214
+ )
215
+ )
216
+ allInfo.push(info)
217
+ onPush(info)
218
+ }
219
+ )
220
+ )
221
+ : Promise.all(
222
+ [...usersByGlobalScriptsToPush].map(async ([scriptName, users]) => {
223
+ let code, fileName, filePath
224
+ for (const extension of supportedExtensions)
225
+ try {
226
+ fileName = `${scriptName}${extension}`
227
+ code = await readFile((filePath = resolve(sourceDirectory, fileName)), { encoding: "utf-8" })
228
+ break
229
+ } catch {}
230
+ if (code) {
231
+ const uniqueID = Math.floor(Math.random() * 2 ** 52)
232
+ .toString(36)
233
+ .padStart(11, "0"),
234
+ { script: minifiedCode } = await processScript(code, {
235
+ minify,
236
+ scriptUser: !0,
237
+ scriptName,
238
+ uniqueID,
239
+ filePath,
240
+ mangleNames,
241
+ forceQuineCheats
242
+ }),
243
+ info = {
244
+ file: fileName,
245
+ users: [...users],
246
+ minLength: countHackmudCharacters(minifiedCode),
247
+ error: void 0
248
+ }
249
+ await Promise.all(
250
+ [...users].map(user =>
251
+ writeFilePersistent(
252
+ resolve(hackmudDirectory, user, `scripts/${scriptName}.js`),
253
+ minifiedCode
254
+ .replace(RegExp(`\\$${uniqueID}\\$SCRIPT_USER\\$`, "g"), user)
255
+ .replace(
256
+ RegExp(`\\$${uniqueID}\\$FULL_SCRIPT_NAME\\$`, "g"),
257
+ `${user}.${scriptName}`
258
+ )
259
+ )
260
+ )
261
+ )
262
+ allInfo.push(info)
263
+ onPush(info)
264
+ }
265
+ })
266
+ ))
267
+ return allInfo
268
+ }
269
+ export { push as default, push }
File without changes
@@ -0,0 +1,2 @@
1
+ export declare function generateTypeDeclaration(sourceDirectory: string, hackmudPath?: string): Promise<string>;
2
+ export default generateTypeDeclaration;
@@ -0,0 +1,31 @@
1
+ import type { LaxPartial } from "@samual/lib";
2
+ export { minify } from "./minify";
3
+ export { postprocess } from "./postprocess";
4
+ export { preprocess } from "./preprocess";
5
+ export { transform } from "./transform";
6
+ export type ProcessOptions = {
7
+ /** whether to minify the given code */ minify: boolean;
8
+ /** 11 a-z 0-9 characters */ uniqueID: string;
9
+ /** the user going to be hosting this script (or set to `true` if not yet known) */ scriptUser: string | true;
10
+ /** the name of this script (or set to `true` if not yet known) */ scriptName: string | true;
11
+ filePath: string;
12
+ /** whether to mangle function and class names (defaults to `false`) */ mangleNames: boolean;
13
+ /** when set to `true` forces use of quine cheats
14
+ *
15
+ * when set to `false` forces quine cheats not to be used
16
+ *
17
+ * when left unset or set to `undefined`, automatically uses or doesn't use quine cheats based on character count
18
+ */
19
+ forceQuineCheats: boolean;
20
+ };
21
+ /** Minifies a given script
22
+ * @param code JavaScript or TypeScript code
23
+ * @param options {@link ProcessOptions details} */
24
+ export declare function processScript(code: string, { minify: shouldMinify, uniqueID, scriptUser, scriptName, filePath, mangleNames, forceQuineCheats }?: LaxPartial<ProcessOptions>): Promise<{
25
+ script: string;
26
+ warnings: {
27
+ message: string;
28
+ line: number;
29
+ }[];
30
+ }>;
31
+ export default processScript;
@@ -0,0 +1,18 @@
1
+ import type { File } from "@babel/types";
2
+ import type { LaxPartial } from "@samual/lib";
3
+ type MinifyOptions = {
4
+ /** 11 a-z 0-9 characters */ uniqueID: string;
5
+ /** whether to mangle function and class names (defaults to `false`) */ mangleNames: boolean;
6
+ /** when set to `true` forces use of quine cheats
7
+ *
8
+ * when set to `false` forces quine cheats not to be used
9
+ *
10
+ * when left unset or set to `undefined`, automatically uses or doesn't use quine cheats based on character count
11
+ */
12
+ forceQuineCheats: boolean;
13
+ /** the comment inserted after the function signature */ autocomplete: string;
14
+ };
15
+ /** @param file babel ast node representing a file containing transformed code
16
+ * @param options {@link MinifyOptions details} */
17
+ export declare function minify(file: File, { uniqueID, mangleNames, forceQuineCheats, autocomplete }?: LaxPartial<MinifyOptions>): Promise<string>;
18
+ export default minify;
@@ -0,0 +1,9 @@
1
+ export type PreprocessOptions = {
2
+ /** 11 a-z 0-9 characters */ uniqueID: string;
3
+ };
4
+ /** @param code source code for preprocessing
5
+ * @param options {@link PreprocessOptions details} */
6
+ export declare function preprocess(code: string, { uniqueID }?: Partial<PreprocessOptions>): Promise<{
7
+ code: string;
8
+ }>;
9
+ export default preprocess;
@@ -1,5 +1,5 @@
1
1
  import type { NodePath } from "@babel/traverse";
2
2
  import type { Identifier, Program } from "@babel/types";
3
- export declare const getReferencePathsToGlobal: (name: string, program: NodePath<Program>) => NodePath<Identifier>[];
3
+ export declare function getReferencePathsToGlobal(name: string, program: NodePath<Program>): NodePath<Identifier>[];
4
4
  export declare const includesIllegalString: (toCheck: string) => boolean;
5
5
  export declare const replaceUnsafeStrings: (uniqueID: string, toReplace: string) => string;
@@ -0,0 +1,18 @@
1
+ import type { File } from "@babel/types";
2
+ export type TransformOptions = {
3
+ /** 11 a-z 0-9 characters */ uniqueID: string;
4
+ /** the user going to be hosting this script (or set to `true` if not yet known) */ scriptUser: string | true;
5
+ /** the name of this script (or set to `true` if not yet known) */ scriptName: string | true;
6
+ seclevel: number;
7
+ };
8
+ /** transform a given babel `File` to be hackmud compatible
9
+ *
10
+ * (returned File will need `postprocess()`ing)
11
+ * @param file babel ast node representing a file containing preprocessed code
12
+ * @param sourceCode the original untouched source code
13
+ * @param options {@link TransformOptions details} */
14
+ export declare function transform(file: File, sourceCode: string, { uniqueID, scriptUser, scriptName, seclevel }?: Partial<TransformOptions>): {
15
+ file: File;
16
+ seclevel: number;
17
+ };
18
+ export default transform;
package/src/pull.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /** Copies script from hackmud to local source folder.
2
+ * @param sourceFolderPath path to folder containing source files
3
+ * @param hackmudPath path to hackmud directory
4
+ * @param script to pull in `user.name` format */
5
+ export declare function pull(sourceFolderPath: string, hackmudPath: string, script: string): Promise<void>;
6
+ export default pull;
package/src/push.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import type { LaxPartial } from "@samual/lib";
2
+ import type { Info } from ".";
3
+ export type PushOptions = {
4
+ /** whether to do the minify step (defaults to `true`) */ minify: boolean;
5
+ /** whether to mangle function and class names (defaults to `false`) */ mangleNames: boolean;
6
+ /** array of scripts in the format `foo.bar`
7
+ *
8
+ * also accepts wild card (`*`) e.g. `*.bar` or `foo.*`
9
+ *
10
+ * pushes everything by default (`*.*`) */
11
+ scripts: string[];
12
+ /** callback called on script push */ onPush: (info: Info) => void;
13
+ /** when set to `true` forces use of quine cheats
14
+ *
15
+ * when set to `false` forces quine cheats not to be used
16
+ *
17
+ * when left unset or set to `undefined`, automatically uses or doesn't use quine cheats based on character count
18
+ */
19
+ forceQuineCheats: boolean;
20
+ };
21
+ /** Push scripts from a source directory to the hackmud directory.
22
+ *
23
+ * Pushes files directly in the source folder to all users
24
+ * @param sourceDirectory directory containing source code
25
+ * @param hackmudDirectory directory created by hackmud containing user data including scripts
26
+ * @param options {@link PushOptions details}
27
+ * @returns array of info on pushed scripts */
28
+ export declare function push(sourceDirectory: string, hackmudDirectory: string, { scripts, onPush, minify, mangleNames, forceQuineCheats }?: LaxPartial<PushOptions>): Promise<Info[]>;
29
+ export default push;
@@ -1,4 +1,4 @@
1
- export declare const syncMacros: (hackmudPath: string) => Promise<{
1
+ export declare function syncMacros(hackmudPath: string): Promise<{
2
2
  macrosSynced: number;
3
3
  usersSynced: number;
4
4
  }>;
package/src/watch.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { LaxPartial } from "@samual/lib";
2
+ import type { PushOptions } from "./push";
3
+ export type WatchOptions = PushOptions & {
4
+ /** if provided, will write typescript type declarations for all the scripts on every change detected
5
+ *
6
+ * writing the type declarations enables interscript type checking and autocompletetes for the args */
7
+ typeDeclarationPath: string;
8
+ onReady: () => void;
9
+ };
10
+ /** Watches target file or folder for updates and builds and pushes updated file.
11
+ * @param sourceDirectory path to folder containing source files
12
+ * @param hackmudDirectory path to hackmud directory
13
+ * @param options {@link WatchOptions details} and {@link PushOptions more details} */
14
+ export declare function watch(sourceDirectory: string, hackmudDirectory: string, { scripts, onPush, minify, mangleNames, typeDeclarationPath: typeDeclarationPath_, onReady, forceQuineCheats }?: LaxPartial<WatchOptions>): Promise<void>;
15
+ export default watch;
package/syncMacros.js CHANGED
@@ -1 +1,43 @@
1
- import{readdir as e,readFile as t,stat as a,writeFile as s}from"fs/promises";import{extname as o,basename as n,resolve as r}from"path";const syncMacros=async c=>{const m=await e(c,{withFileTypes:!0}),i=new Map,l=[];await Promise.all(m.map((async e=>{if(e.isFile())switch(o(e.name)){case".macros":{const[s,o]=await Promise.all([t(r(c,e.name),{encoding:"utf-8"}).then((e=>e.split("\n"))),a(r(c,e.name)).then((({mtime:e})=>e))]);for(let e=0;e<s.length/2-1;e++){const t=s[2*e],a=i.get(t);(!a||o>a.date)&&i.set(t,{date:o,macro:s[2*e+1]})}}break;case".key":l.push(n(e.name,".key"))}})));let f="",p=0;for(const[e,{macro:t}]of[...i].sort((([e],[t])=>(e>t)-(e<t))))t[0]==t[0].toLowerCase()&&(f+=`${e}\n${t}\n`,p++);for(const e of l)s(r(c,`${e}.macros`),f);return{macrosSynced:p,usersSynced:l.length}};export{syncMacros as default,syncMacros};
1
+ import { readDirectoryWithStats } from "@samual/lib/readDirectoryWithStats"
2
+ import { readFile, stat, writeFile } from "fs/promises"
3
+ import { extname, basename, resolve } from "path"
4
+ async function syncMacros(hackmudPath) {
5
+ const files = await readDirectoryWithStats(hackmudPath),
6
+ macros = new Map(),
7
+ users = []
8
+ await Promise.all(
9
+ files.map(async file => {
10
+ if (file.stats.isFile())
11
+ switch (extname(file.name)) {
12
+ case ".macros":
13
+ {
14
+ const [lines, date] = await Promise.all([
15
+ readFile(resolve(hackmudPath, file.name), { encoding: "utf-8" }).then(file =>
16
+ file.split("\n")
17
+ ),
18
+ stat(resolve(hackmudPath, file.name)).then(({ mtime }) => mtime)
19
+ ])
20
+ for (let index = 0; index < lines.length / 2 - 1; index++) {
21
+ const macroName = lines[2 * index],
22
+ currentMacro = macros.get(macroName)
23
+ ;(!currentMacro || date > currentMacro.date) &&
24
+ macros.set(macroName, { date, macro: lines[2 * index + 1] })
25
+ }
26
+ }
27
+ break
28
+ case ".key":
29
+ users.push(basename(file.name, ".key"))
30
+ }
31
+ })
32
+ )
33
+ let macroFile = "",
34
+ macrosSynced = 0
35
+ for (const [name, { macro }] of [...macros].sort(([a], [b]) => (a > b) - (a < b)))
36
+ if (macro[0] == macro[0].toLowerCase()) {
37
+ macroFile += `${name}\n${macro}\n`
38
+ macrosSynced++
39
+ }
40
+ for (const user of users) writeFile(resolve(hackmudPath, user + ".macros"), macroFile)
41
+ return { macrosSynced, usersSynced: users.length }
42
+ }
43
+ export { syncMacros as default, syncMacros }