hackmud-script-manager 0.20.0-b71a8be → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -3
- package/bin/hsm.d.ts +0 -0
- package/bin/hsm.js +436 -1
- package/constants.js +3 -1
- package/env.d.ts +1657 -0
- package/generateTypeDeclaration.d.ts +1 -2
- package/generateTypeDeclaration.js +68 -1
- package/index.d.ts +2 -2
- package/index.js +51 -1
- package/package.json +41 -38
- package/processScript/index.d.ts +17 -26
- package/processScript/index.js +333 -1
- package/processScript/minify.d.ts +15 -21
- package/processScript/minify.js +444 -1
- package/processScript/postprocess.d.ts +1 -2
- package/processScript/postprocess.js +20 -1
- package/processScript/preprocess.d.ts +7 -10
- package/processScript/preprocess.js +105 -1
- package/processScript/shared.d.ts +2 -2
- package/processScript/shared.js +32 -1
- package/processScript/transform.d.ts +13 -18
- package/processScript/transform.js +696 -1
- package/pull.d.ts +5 -9
- package/pull.js +11 -1
- package/push.d.ts +24 -33
- package/push.js +138 -1
- package/syncMacros.d.ts +1 -2
- package/syncMacros.js +43 -1
- package/watch.d.ts +10 -16
- package/watch.js +208 -1
- package/tsconfig.tsbuildinfo +0 -1
package/processScript/index.js
CHANGED
@@ -1 +1,333 @@
|
|
1
|
-
import
|
1
|
+
import babelGenerator from "@babel/generator"
|
2
|
+
import { parse } from "@babel/parser"
|
3
|
+
import babelPluginProposalDecorators from "@babel/plugin-proposal-decorators"
|
4
|
+
import babelPluginProposalDestructuringPrivate from "@babel/plugin-proposal-destructuring-private"
|
5
|
+
import babelPluginProposalExplicitResourceManagement from "@babel/plugin-proposal-explicit-resource-management"
|
6
|
+
import babelPluginTransformClassProperties from "@babel/plugin-transform-class-properties"
|
7
|
+
import babelPluginTransformClassStaticBlock from "@babel/plugin-transform-class-static-block"
|
8
|
+
import babelPluginTransformExponentiationOperator from "@babel/plugin-transform-exponentiation-operator"
|
9
|
+
import babelPluginTransformJsonStrings from "@babel/plugin-transform-json-strings"
|
10
|
+
import babelPluginTransformLogicalAssignmentOperators from "@babel/plugin-transform-logical-assignment-operators"
|
11
|
+
import babelPluginTransformNullishCoalescingOperator from "@babel/plugin-transform-nullish-coalescing-operator"
|
12
|
+
import babelPluginTransformNumericSeparator from "@babel/plugin-transform-numeric-separator"
|
13
|
+
import babelPluginTransformObjectRestSpread from "@babel/plugin-transform-object-rest-spread"
|
14
|
+
import babelPluginTransformOptionalCatchBinding from "@babel/plugin-transform-optional-catch-binding"
|
15
|
+
import babelPluginTransformOptionalChaining from "@babel/plugin-transform-optional-chaining"
|
16
|
+
import babelPluginTransformPrivatePropertyInObject from "@babel/plugin-transform-private-property-in-object"
|
17
|
+
import babelPluginTransformUnicodeSetsRegex from "@babel/plugin-transform-unicode-sets-regex"
|
18
|
+
import babelTraverse from "@babel/traverse"
|
19
|
+
import t from "@babel/types"
|
20
|
+
import { babel } from "@rollup/plugin-babel"
|
21
|
+
import rollupPluginCommonJS from "@rollup/plugin-commonjs"
|
22
|
+
import rollupPluginJSON from "@rollup/plugin-json"
|
23
|
+
import rollupPluginNodeResolve from "@rollup/plugin-node-resolve"
|
24
|
+
import { assert } from "@samual/lib/assert"
|
25
|
+
import { resolve } from "path"
|
26
|
+
import prettier from "prettier"
|
27
|
+
import { rollup } from "rollup"
|
28
|
+
import { supportedExtensions } from "../constants.js"
|
29
|
+
import { minify } from "./minify.js"
|
30
|
+
import { postprocess } from "./postprocess.js"
|
31
|
+
import { preprocess } from "./preprocess.js"
|
32
|
+
import { getReferencePathsToGlobal, includesIllegalString, replaceUnsafeStrings } from "./shared.js"
|
33
|
+
import { transform } from "./transform.js"
|
34
|
+
import "@samual/lib/countHackmudCharacters"
|
35
|
+
import "@samual/lib/spliceString"
|
36
|
+
import "acorn"
|
37
|
+
import "terser"
|
38
|
+
import "import-meta-resolve"
|
39
|
+
import "@samual/lib/clearObject"
|
40
|
+
const { format } = prettier,
|
41
|
+
{ default: generate } = babelGenerator,
|
42
|
+
{ default: traverse } = babelTraverse
|
43
|
+
async function processScript(
|
44
|
+
code,
|
45
|
+
{
|
46
|
+
minify: shouldMinify = !0,
|
47
|
+
uniqueId = Math.floor(Math.random() * 2 ** 52)
|
48
|
+
.toString(36)
|
49
|
+
.padStart(11, "0"),
|
50
|
+
scriptUser,
|
51
|
+
scriptName,
|
52
|
+
filePath,
|
53
|
+
mangleNames = !1,
|
54
|
+
forceQuineCheats
|
55
|
+
}
|
56
|
+
) {
|
57
|
+
assert(/^\w{11}$/.exec(uniqueId), "src/processScript/index.ts:77:36")
|
58
|
+
const sourceCode = code
|
59
|
+
let autocomplete, statedSeclevel
|
60
|
+
const autocompleteMatch = /^function\s*\(.+\/\/(?<autocomplete>.+)/.exec(code)
|
61
|
+
if (autocompleteMatch) {
|
62
|
+
code = "export default " + code
|
63
|
+
;({ autocomplete } = autocompleteMatch.groups)
|
64
|
+
} else
|
65
|
+
for (const line of code.split("\n")) {
|
66
|
+
const comment = /^\s*\/\/(?<commentContent>.+)/.exec(line)
|
67
|
+
if (!comment) break
|
68
|
+
const commentContent = comment.groups.commentContent.trim()
|
69
|
+
if (commentContent.startsWith("@autocomplete ")) autocomplete = commentContent.slice(14).trimStart()
|
70
|
+
else if (commentContent.startsWith("@seclevel ")) {
|
71
|
+
const seclevelString = commentContent.slice(10).trimStart().toLowerCase()
|
72
|
+
switch (seclevelString) {
|
73
|
+
case "fullsec":
|
74
|
+
case "full":
|
75
|
+
case "fs":
|
76
|
+
case "4s":
|
77
|
+
case "f":
|
78
|
+
case "4":
|
79
|
+
statedSeclevel = 4
|
80
|
+
break
|
81
|
+
case "highsec":
|
82
|
+
case "high":
|
83
|
+
case "hs":
|
84
|
+
case "3s":
|
85
|
+
case "h":
|
86
|
+
case "3":
|
87
|
+
statedSeclevel = 3
|
88
|
+
break
|
89
|
+
case "midsec":
|
90
|
+
case "mid":
|
91
|
+
case "ms":
|
92
|
+
case "2s":
|
93
|
+
case "m":
|
94
|
+
case "2":
|
95
|
+
statedSeclevel = 2
|
96
|
+
break
|
97
|
+
case "lowsec":
|
98
|
+
case "low":
|
99
|
+
case "ls":
|
100
|
+
case "1s":
|
101
|
+
case "l":
|
102
|
+
case "1":
|
103
|
+
statedSeclevel = 1
|
104
|
+
break
|
105
|
+
case "nullsec":
|
106
|
+
case "null":
|
107
|
+
case "ns":
|
108
|
+
case "0s":
|
109
|
+
case "n":
|
110
|
+
case "0":
|
111
|
+
statedSeclevel = 0
|
112
|
+
break
|
113
|
+
default:
|
114
|
+
throw Error(`unrecognised seclevel "${seclevelString}"`)
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
assert(/^\w{11}$/.exec(uniqueId), "src/processScript/index.ts:158:36")
|
119
|
+
const plugins = [
|
120
|
+
[babelPluginProposalDecorators.default, { decoratorsBeforeExport: !0 }],
|
121
|
+
[babelPluginTransformClassProperties.default],
|
122
|
+
[babelPluginTransformClassStaticBlock.default],
|
123
|
+
[babelPluginTransformPrivatePropertyInObject.default],
|
124
|
+
[babelPluginTransformLogicalAssignmentOperators.default],
|
125
|
+
[babelPluginTransformNumericSeparator.default],
|
126
|
+
[babelPluginTransformNullishCoalescingOperator.default],
|
127
|
+
[babelPluginTransformOptionalChaining.default],
|
128
|
+
[babelPluginTransformOptionalCatchBinding.default],
|
129
|
+
[babelPluginTransformJsonStrings.default],
|
130
|
+
[babelPluginTransformObjectRestSpread.default],
|
131
|
+
[babelPluginTransformExponentiationOperator.default],
|
132
|
+
[babelPluginTransformUnicodeSetsRegex.default],
|
133
|
+
[babelPluginProposalDestructuringPrivate.default],
|
134
|
+
[babelPluginProposalExplicitResourceManagement.default]
|
135
|
+
]
|
136
|
+
let filePathResolved
|
137
|
+
if (filePath) {
|
138
|
+
filePathResolved = resolve(filePath)
|
139
|
+
if (filePath.endsWith(".ts"))
|
140
|
+
plugins.push([
|
141
|
+
(await import("@babel/plugin-transform-typescript")).default,
|
142
|
+
{ allowDeclareFields: !0, optimizeConstEnums: !0 }
|
143
|
+
])
|
144
|
+
else {
|
145
|
+
const [
|
146
|
+
babelPluginProposalDoExpressions,
|
147
|
+
babelPluginProposalFunctionBind,
|
148
|
+
babelPluginProposalFunctionSent,
|
149
|
+
babelPluginProposalPartialApplication,
|
150
|
+
babelPluginProposalPipelineOperator,
|
151
|
+
babelPluginProposalThrowExpressions,
|
152
|
+
babelPluginProposalRecordAndTuple
|
153
|
+
] = await Promise.all([
|
154
|
+
import("@babel/plugin-proposal-do-expressions"),
|
155
|
+
import("@babel/plugin-proposal-function-bind"),
|
156
|
+
import("@babel/plugin-proposal-function-sent"),
|
157
|
+
import("@babel/plugin-proposal-partial-application"),
|
158
|
+
import("@babel/plugin-proposal-pipeline-operator"),
|
159
|
+
import("@babel/plugin-proposal-throw-expressions"),
|
160
|
+
import("@babel/plugin-proposal-record-and-tuple")
|
161
|
+
])
|
162
|
+
plugins.push(
|
163
|
+
[babelPluginProposalDoExpressions.default],
|
164
|
+
[babelPluginProposalFunctionBind.default],
|
165
|
+
[babelPluginProposalFunctionSent.default],
|
166
|
+
[babelPluginProposalPartialApplication.default],
|
167
|
+
[babelPluginProposalPipelineOperator.default, { proposal: "hack", topicToken: "%" }],
|
168
|
+
[babelPluginProposalThrowExpressions.default],
|
169
|
+
[babelPluginProposalRecordAndTuple.default, { syntaxType: "hash", importPolyfill: !0 }]
|
170
|
+
)
|
171
|
+
}
|
172
|
+
} else {
|
173
|
+
filePathResolved = uniqueId + ".ts"
|
174
|
+
const [
|
175
|
+
babelPluginTransformTypescript,
|
176
|
+
babelPluginProposalDoExpressions,
|
177
|
+
babelPluginProposalFunctionBind,
|
178
|
+
babelPluginProposalFunctionSent,
|
179
|
+
babelPluginProposalPartialApplication,
|
180
|
+
babelPluginProposalPipelineOperator,
|
181
|
+
babelPluginProposalThrowExpressions,
|
182
|
+
babelPluginProposalRecordAndTuple
|
183
|
+
] = await Promise.all([
|
184
|
+
import("@babel/plugin-transform-typescript"),
|
185
|
+
import("@babel/plugin-proposal-do-expressions"),
|
186
|
+
import("@babel/plugin-proposal-function-bind"),
|
187
|
+
import("@babel/plugin-proposal-function-sent"),
|
188
|
+
import("@babel/plugin-proposal-partial-application"),
|
189
|
+
import("@babel/plugin-proposal-pipeline-operator"),
|
190
|
+
import("@babel/plugin-proposal-throw-expressions"),
|
191
|
+
import("@babel/plugin-proposal-record-and-tuple")
|
192
|
+
])
|
193
|
+
plugins.push(
|
194
|
+
[babelPluginTransformTypescript.default, { allowDeclareFields: !0, optimizeConstEnums: !0 }],
|
195
|
+
[babelPluginProposalDoExpressions.default],
|
196
|
+
[babelPluginProposalFunctionBind.default],
|
197
|
+
[babelPluginProposalFunctionSent.default],
|
198
|
+
[babelPluginProposalPartialApplication.default],
|
199
|
+
[babelPluginProposalPipelineOperator.default, { proposal: "hack", topicToken: "%" }],
|
200
|
+
[babelPluginProposalThrowExpressions.default],
|
201
|
+
[babelPluginProposalRecordAndTuple.default, { syntaxType: "hash", importPolyfill: !0 }]
|
202
|
+
)
|
203
|
+
}
|
204
|
+
const bundle = await rollup({
|
205
|
+
input: filePathResolved,
|
206
|
+
plugins: [
|
207
|
+
{
|
208
|
+
name: "hackmud-script-manager",
|
209
|
+
async transform(code, id) {
|
210
|
+
if (!id.includes("/node_modules/")) return (await preprocess(code, { uniqueId })).code
|
211
|
+
let program
|
212
|
+
traverse(parse(code, { sourceType: "module" }), {
|
213
|
+
Program(path) {
|
214
|
+
program = path
|
215
|
+
path.skip()
|
216
|
+
}
|
217
|
+
})
|
218
|
+
for (const referencePath of getReferencePathsToGlobal("JSON", program))
|
219
|
+
"MemberExpression" == referencePath.parentPath.node.type &&
|
220
|
+
"Identifier" == referencePath.parentPath.node.property.type &&
|
221
|
+
("parse" == referencePath.parentPath.node.property.name ?
|
222
|
+
(referencePath.parentPath.node.property.name = "oparse")
|
223
|
+
: "stringify" == referencePath.parentPath.node.property.name &&
|
224
|
+
(referencePath.parentPath.node.property.name = "ostringify"))
|
225
|
+
return generate(program.node).code
|
226
|
+
}
|
227
|
+
},
|
228
|
+
babel({ babelHelpers: "bundled", plugins, configFile: !1, extensions: supportedExtensions }),
|
229
|
+
rollupPluginCommonJS(),
|
230
|
+
rollupPluginNodeResolve({ extensions: supportedExtensions }),
|
231
|
+
rollupPluginJSON()
|
232
|
+
],
|
233
|
+
treeshake: { moduleSideEffects: !1 }
|
234
|
+
}),
|
235
|
+
seclevelNames = ["NULLSEC", "LOWSEC", "MIDSEC", "HIGHSEC", "FULLSEC"]
|
236
|
+
code = (await bundle.generate({})).output[0].code
|
237
|
+
const { file, seclevel } = transform(parse(code, { sourceType: "module" }), sourceCode, {
|
238
|
+
uniqueId,
|
239
|
+
scriptUser,
|
240
|
+
scriptName
|
241
|
+
})
|
242
|
+
if (null != statedSeclevel && seclevel < statedSeclevel)
|
243
|
+
throw Error(
|
244
|
+
`detected seclevel ${seclevelNames[seclevel]} is lower than stated seclevel ${seclevelNames[statedSeclevel]}`
|
245
|
+
)
|
246
|
+
code = generate(file).code
|
247
|
+
if (shouldMinify) code = await minify(file, { uniqueId, mangleNames, forceQuineCheats, autocomplete })
|
248
|
+
else {
|
249
|
+
traverse(file, {
|
250
|
+
MemberExpression({ node: memberExpression }) {
|
251
|
+
if (!memberExpression.computed) {
|
252
|
+
assert("Identifier" == memberExpression.property.type, "src/processScript/index.ts:321:60")
|
253
|
+
if ("prototype" == memberExpression.property.name) {
|
254
|
+
memberExpression.computed = !0
|
255
|
+
memberExpression.property = t.stringLiteral("prototype")
|
256
|
+
} else if ("__proto__" == memberExpression.property.name) {
|
257
|
+
memberExpression.computed = !0
|
258
|
+
memberExpression.property = t.stringLiteral("__proto__")
|
259
|
+
} else if (includesIllegalString(memberExpression.property.name)) {
|
260
|
+
memberExpression.computed = !0
|
261
|
+
memberExpression.property = t.stringLiteral(
|
262
|
+
replaceUnsafeStrings(uniqueId, memberExpression.property.name)
|
263
|
+
)
|
264
|
+
}
|
265
|
+
}
|
266
|
+
},
|
267
|
+
VariableDeclarator(path) {
|
268
|
+
const renameVariables = lValue => {
|
269
|
+
switch (lValue.type) {
|
270
|
+
case "Identifier":
|
271
|
+
includesIllegalString(lValue.name) &&
|
272
|
+
path.scope.rename(
|
273
|
+
lValue.name,
|
274
|
+
"$" +
|
275
|
+
Math.floor(Math.random() * 2 ** 52)
|
276
|
+
.toString(36)
|
277
|
+
.padStart(11, "0")
|
278
|
+
)
|
279
|
+
break
|
280
|
+
case "ObjectPattern":
|
281
|
+
for (const property of lValue.properties) {
|
282
|
+
assert("ObjectProperty" == property.type, "src/processScript/index.ts:351:51")
|
283
|
+
renameVariables(property.value)
|
284
|
+
}
|
285
|
+
break
|
286
|
+
case "ArrayPattern":
|
287
|
+
for (const element of lValue.elements) element && renameVariables(element)
|
288
|
+
break
|
289
|
+
default:
|
290
|
+
throw Error(`unknown lValue type "${lValue.type}"`)
|
291
|
+
}
|
292
|
+
}
|
293
|
+
renameVariables(path.node.id)
|
294
|
+
},
|
295
|
+
ObjectProperty({ node: objectProperty }) {
|
296
|
+
if ("Identifier" == objectProperty.key.type && includesIllegalString(objectProperty.key.name)) {
|
297
|
+
objectProperty.key = t.stringLiteral(replaceUnsafeStrings(uniqueId, objectProperty.key.name))
|
298
|
+
objectProperty.shorthand = !1
|
299
|
+
}
|
300
|
+
},
|
301
|
+
StringLiteral({ node }) {
|
302
|
+
node.value = replaceUnsafeStrings(uniqueId, node.value)
|
303
|
+
},
|
304
|
+
TemplateLiteral({ node }) {
|
305
|
+
for (const templateElement of node.quasis)
|
306
|
+
if (templateElement.value.cooked) {
|
307
|
+
templateElement.value.cooked = replaceUnsafeStrings(uniqueId, templateElement.value.cooked)
|
308
|
+
templateElement.value.raw = templateElement.value.cooked
|
309
|
+
.replaceAll("\\", "\\\\")
|
310
|
+
.replaceAll("`", "\\`")
|
311
|
+
.replaceAll("${", "$\\{")
|
312
|
+
} else templateElement.value.raw = replaceUnsafeStrings(uniqueId, templateElement.value.raw)
|
313
|
+
},
|
314
|
+
RegExpLiteral(path) {
|
315
|
+
path.node.pattern = replaceUnsafeStrings(uniqueId, path.node.pattern)
|
316
|
+
delete path.node.extra
|
317
|
+
}
|
318
|
+
})
|
319
|
+
code = await format(generate(file, { comments: !1 }).code, {
|
320
|
+
parser: "babel",
|
321
|
+
arrowParens: "avoid",
|
322
|
+
semi: !1,
|
323
|
+
trailingComma: "none"
|
324
|
+
})
|
325
|
+
}
|
326
|
+
code = postprocess(code, seclevel, uniqueId)
|
327
|
+
if (includesIllegalString(code))
|
328
|
+
throw Error(
|
329
|
+
'you found a weird edge case where I wasn\'t able to replace illegal strings like "SC$", please report thx'
|
330
|
+
)
|
331
|
+
return { script: code, warnings: [] }
|
332
|
+
}
|
333
|
+
export { minify, postprocess, preprocess, processScript, transform }
|
@@ -1,24 +1,18 @@
|
|
1
1
|
import type { File } from "@babel/types";
|
2
2
|
import type { LaxPartial } from "@samual/lib";
|
3
|
-
type MinifyOptions = {
|
4
|
-
/** 11 a-z 0-9 characters */
|
5
|
-
|
6
|
-
/**
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
*
|
13
|
-
* when left unset or set to `undefined`, automatically uses or doesn't use quine cheats based on character count
|
14
|
-
*/
|
3
|
+
type MinifyOptions = LaxPartial<{
|
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
|
+
*/
|
15
12
|
forceQuineCheats: boolean;
|
16
|
-
/** the comment inserted after the function signature */
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
*/
|
23
|
-
export declare const minify: (file: File, { uniqueID, mangleNames, forceQuineCheats, autocomplete }?: LaxPartial<MinifyOptions>) => Promise<string>;
|
24
|
-
export default minify;
|
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 }?: MinifyOptions): Promise<string>;
|
18
|
+
export {};
|