hackmud-script-manager 0.19.0-50a29ed → 0.19.0-7c69a3b

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.
@@ -1 +1,313 @@
1
- import e from"@babel/generator";import{parse as o}from"@babel/parser";import r from"@babel/plugin-proposal-class-properties";import t from"@babel/plugin-proposal-class-static-block";import a from"@babel/plugin-proposal-decorators";import p from"@babel/plugin-proposal-json-strings";import s from"@babel/plugin-proposal-logical-assignment-operators";import l from"@babel/plugin-proposal-nullish-coalescing-operator";import i from"@babel/plugin-proposal-numeric-separator";import n from"@babel/plugin-proposal-object-rest-spread";import m from"@babel/plugin-proposal-optional-catch-binding";import c from"@babel/plugin-proposal-optional-chaining";import u from"@babel/plugin-proposal-private-property-in-object";import f from"@babel/plugin-transform-exponentiation-operator";import d from"@babel/traverse";import b from"@babel/types";import g from"@rollup/plugin-babel";import h from"@rollup/plugin-commonjs";import y from"@rollup/plugin-json";import w from"@rollup/plugin-node-resolve";import{resolve as k}from"path";import x from"prettier";import{rollup as j}from"rollup";import{s as v}from"../constants-9bb78688.js";import{minify as C}from"./minify.js";export{minify}from"./minify.js";import{postprocess as E}from"./postprocess.js";export{postprocess}from"./postprocess.js";import{preprocess as S}from"./preprocess.js";export{preprocess}from"./preprocess.js";import{includesIllegalString as L,replaceUnsafeStrings as $}from"./shared.js";import{transform as N}from"./transform.js";export{transform}from"./transform.js";import{a as I}from"../assert-22a7ef8a.js";import"acorn";import"terser";import"../spliceString-0e6b5d6d.js";import"../countHackmudCharacters-a08a265f.js";import"import-meta-resolve";const{default:P}=g,{format:D}=x,{default:_}=e,{default:M}=d,processScript=async(e,{minify:d=!0,uniqueID:g=Math.floor(Math.random()*2**52).toString(36).padStart(11,"0"),scriptUser:x="UNKNOWN",scriptName:O="UNKNOWN",filePath:T,mangleNames:U=!1,forceQuineCheats:W}={})=>{I(/^\w{11}$/.exec(g));const q=e;let F,H;const z=/^function\s*\(.+\/\/(?<autocomplete>.+)/.exec(e);if(z)e=`export default ${e}`,({autocomplete:F}=z.groups);else for(const o of e.split("\n")){const e=/^\s*\/\/(?<commentContent>.+)/.exec(o);if(!e)break;const r=e.groups.commentContent.trim();if(r.startsWith("@autocomplete "))F=r.slice(14).trimStart();else if(r.startsWith("@seclevel ")){const e=r.slice(10).trimStart().toLowerCase();switch(e){case"fullsec":case"full":case"fs":case"4s":case"f":case"4":H=4;break;case"highsec":case"high":case"hs":case"3s":case"h":case"3":H=3;break;case"midsec":case"mid":case"ms":case"2s":case"m":case"2":H=2;break;case"lowsec":case"low":case"ls":case"1s":case"l":case"1":H=1;break;case"nullsec":case"null":case"ns":case"0s":case"n":case"0":H=0;break;default:throw new Error(`unrecognised seclevel "${e}"`)}}}I(/^\w{11}$/.exec(g));const K=[[a.default,{decoratorsBeforeExport:!0}],[r.default],[t.default],[u.default],[s.default],[i.default],[l.default],[c.default],[m.default],[p.default],[n.default],[f.default]];let Q;if(T)if(Q=k(T),T.endsWith(".ts"))K.push([(await import("@babel/plugin-transform-typescript")).default,{allowDeclareFields:!0,optimizeConstEnums:!0}]);else{const[e,o,r,t,a,p,s]=await Promise.all([import("@babel/plugin-proposal-do-expressions"),import("@babel/plugin-proposal-function-bind"),import("@babel/plugin-proposal-function-sent"),import("@babel/plugin-proposal-partial-application"),import("@babel/plugin-proposal-pipeline-operator"),import("@babel/plugin-proposal-throw-expressions"),import("@babel/plugin-proposal-record-and-tuple")]);K.push([e.default],[o.default],[r.default],[t.default],[a.default,{proposal:"hack",topicToken:"%"}],[p.default],[s.default,{syntaxType:"hash",importPolyfill:!0}])}else{Q=`${g}.ts`;const[e,o,r,t,a,p,s,l]=await Promise.all([import("@babel/plugin-transform-typescript"),import("@babel/plugin-proposal-do-expressions"),import("@babel/plugin-proposal-function-bind"),import("@babel/plugin-proposal-function-sent"),import("@babel/plugin-proposal-partial-application"),import("@babel/plugin-proposal-pipeline-operator"),import("@babel/plugin-proposal-throw-expressions"),import("@babel/plugin-proposal-record-and-tuple")]);K.push([e.default,{allowDeclareFields:!0,optimizeConstEnums:!0}],[o.default],[r.default],[t.default],[a.default],[p.default,{proposal:"hack",topicToken:"%"}],[s.default],[l.default,{syntaxType:"hash",importPolyfill:!0}])}const V=await j({input:Q,plugins:[{name:"hackmud-script-manager",transform:async e=>(await S(e,{uniqueID:g})).code},P({babelHelpers:"bundled",plugins:K,configFile:!1,extensions:v}),h(),w({extensions:v}),y()],treeshake:{moduleSideEffects:!1}}),A=["NULLSEC","LOWSEC","MIDSEC","HIGHSEC","FULLSEC"];e=(await V.generate({})).output[0].code;const{file:B,seclevel:G}=N(o(e,{sourceType:"module"}),q,{uniqueID:g,scriptUser:x,scriptName:O});if(null!=H&&G<H)throw new Error(`detected seclevel ${A[G]} is lower than stated seclevel ${A[H]}`);if(e=_(B).code,d?e=await C(B,{uniqueID:g,mangleNames:U,forceQuineCheats:W,autocomplete:F}):(M(B,{MemberExpression({node:e}){e.computed||(I("Identifier"==e.property.type),"prototype"==e.property.name?(e.computed=!0,e.property=b.stringLiteral("prototype")):"__proto__"==e.property.name?(e.computed=!0,e.property=b.stringLiteral("__proto__")):L(e.property.name)&&(e.computed=!0,e.property=b.stringLiteral($(g,e.property.name))))},VariableDeclarator(e){const renameVariables=o=>{switch(o.type){case"Identifier":L(o.name)&&e.scope.rename(o.name,`$${Math.floor(Math.random()*2**52).toString(36).padStart(11,"0")}`);break;case"ObjectPattern":for(const e of o.properties)I("ObjectProperty"==e.type),renameVariables(e.value);break;case"ArrayPattern":for(const e of o.elements)e&&renameVariables(e);break;default:throw new Error(`unknown lValue type "${o.type}"`)}};renameVariables(e.node.id)},ObjectProperty({node:e}){"Identifier"==e.key.type&&L(e.key.name)&&(e.key=b.stringLiteral($(g,e.key.name)),e.shorthand=!1)},StringLiteral({node:e}){e.value=$(g,e.value)},TemplateLiteral({node:e}){for(const o of e.quasis)o.value.cooked?(o.value.cooked=$(g,o.value.cooked),o.value.raw=o.value.cooked.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"$\\{")):o.value.raw=$(g,o.value.raw)},RegExpLiteral(e){e.node.pattern=$(g,e.node.pattern),delete e.node.extra}}),e=D(_(B,{comments:!1}).code,{parser:"babel",arrowParens:"avoid",semi:!1,trailingComma:"none"})),e=E(e,G,g),L(e))throw new Error('you found a weird edge case where I wasn\'t able to replace illegal strings like "SC$", please report thx');return{script:e,warnings:[]}};export{processScript as default,processScript};
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 { 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
+
41
+ const {
42
+ format
43
+ } = prettier;
44
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
45
+ const {
46
+ default: generate
47
+ } = babelGenerator;
48
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
49
+ const {
50
+ default: traverse
51
+ } = babelTraverse;
52
+ /**
53
+ * Minifies a given script
54
+ *
55
+ * @param code JavaScript or TypeScript code
56
+ * @param options {@link ProcessOptions details}
57
+ */
58
+ const processScript = async (code, {
59
+ minify: shouldMinify = true,
60
+ uniqueID = Math.floor(Math.random() * 2 ** 52).toString(36).padStart(11, `0`),
61
+ scriptUser = `UNKNOWN`,
62
+ scriptName = `UNKNOWN`,
63
+ filePath,
64
+ mangleNames = false,
65
+ forceQuineCheats
66
+ } = {}) => {
67
+ assert(/^\w{11}$/.exec(uniqueID));
68
+ const sourceCode = code;
69
+ let autocomplete;
70
+ let statedSeclevel;
71
+
72
+ // TODO do seclevel detection and verification per module
73
+
74
+ const autocompleteMatch = /^function\s*\(.+\/\/(?<autocomplete>.+)/.exec(code);
75
+ if (autocompleteMatch) {
76
+ code = `export default ${code}`;
77
+ ({
78
+ autocomplete
79
+ } = autocompleteMatch.groups);
80
+ } else {
81
+ for (const line of code.split(`\n`)) {
82
+ const comment = /^\s*\/\/(?<commentContent>.+)/.exec(line);
83
+ if (!comment) break;
84
+ const commentContent = comment.groups.commentContent.trim();
85
+ if (commentContent.startsWith(`@autocomplete `)) autocomplete = commentContent.slice(14).trimStart();else if (commentContent.startsWith(`@seclevel `)) {
86
+ const seclevelString = commentContent.slice(10).trimStart().toLowerCase();
87
+ switch (seclevelString) {
88
+ case `fullsec`:
89
+ case `full`:
90
+ case `fs`:
91
+ case `4s`:
92
+ case `f`:
93
+ case `4`:
94
+ {
95
+ statedSeclevel = 4;
96
+ }
97
+ break;
98
+ case `highsec`:
99
+ case `high`:
100
+ case `hs`:
101
+ case `3s`:
102
+ case `h`:
103
+ case `3`:
104
+ {
105
+ statedSeclevel = 3;
106
+ }
107
+ break;
108
+ case `midsec`:
109
+ case `mid`:
110
+ case `ms`:
111
+ case `2s`:
112
+ case `m`:
113
+ case `2`:
114
+ {
115
+ statedSeclevel = 2;
116
+ }
117
+ break;
118
+ case `lowsec`:
119
+ case `low`:
120
+ case `ls`:
121
+ case `1s`:
122
+ case `l`:
123
+ case `1`:
124
+ {
125
+ statedSeclevel = 1;
126
+ }
127
+ break;
128
+ case `nullsec`:
129
+ case `null`:
130
+ case `ns`:
131
+ case `0s`:
132
+ case `n`:
133
+ case `0`:
134
+ {
135
+ statedSeclevel = 0;
136
+ }
137
+ break;
138
+ default:
139
+ // TODO turn into warning when I get round to those
140
+ throw new Error(`unrecognised seclevel "${seclevelString}"`);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ assert(/^\w{11}$/.exec(uniqueID));
146
+ const plugins = [[babelPluginProposalDecorators.default, {
147
+ decoratorsBeforeExport: true
148
+ }], [babelPluginTransformClassProperties.default], [babelPluginTransformClassStaticBlock.default], [babelPluginTransformPrivatePropertyInObject.default], [babelPluginTransformLogicalAssignmentOperators.default], [babelPluginTransformNumericSeparator.default], [babelPluginTransformNullishCoalescingOperator.default], [babelPluginTransformOptionalChaining.default], [babelPluginTransformOptionalCatchBinding.default], [babelPluginTransformJsonStrings.default], [babelPluginTransformObjectRestSpread.default], [babelPluginTransformExponentiationOperator.default], [babelPluginTransformUnicodeSetsRegex.default], [babelPluginProposalDestructuringPrivate.default], [babelPluginProposalExplicitResourceManagement.default]];
149
+ let filePathResolved;
150
+ if (filePath) {
151
+ filePathResolved = resolve(filePath);
152
+ if (filePath.endsWith(`.ts`)) plugins.push([(await import('@babel/plugin-transform-typescript')).default, {
153
+ allowDeclareFields: true,
154
+ optimizeConstEnums: true
155
+ }]);else {
156
+ const [babelPluginProposalDoExpressions, babelPluginProposalFunctionBind, babelPluginProposalFunctionSent, babelPluginProposalPartialApplication, babelPluginProposalPipelineOperator, babelPluginProposalThrowExpressions, babelPluginProposalRecordAndTuple] = await Promise.all([import('@babel/plugin-proposal-do-expressions'), import('@babel/plugin-proposal-function-bind'), import('@babel/plugin-proposal-function-sent'), import('@babel/plugin-proposal-partial-application'), import('@babel/plugin-proposal-pipeline-operator'), import('@babel/plugin-proposal-throw-expressions'), import('@babel/plugin-proposal-record-and-tuple')]);
157
+ plugins.push([babelPluginProposalDoExpressions.default], [babelPluginProposalFunctionBind.default], [babelPluginProposalFunctionSent.default], [babelPluginProposalPartialApplication.default], [babelPluginProposalPipelineOperator.default, {
158
+ proposal: `hack`,
159
+ topicToken: `%`
160
+ }], [babelPluginProposalThrowExpressions.default], [babelPluginProposalRecordAndTuple.default, {
161
+ syntaxType: `hash`,
162
+ importPolyfill: true
163
+ }]);
164
+ }
165
+ } else {
166
+ filePathResolved = `${uniqueID}.ts`;
167
+ const [babelPluginTransformTypescript, babelPluginProposalDoExpressions, babelPluginProposalFunctionBind, babelPluginProposalFunctionSent, babelPluginProposalPartialApplication, babelPluginProposalPipelineOperator, babelPluginProposalThrowExpressions, babelPluginProposalRecordAndTuple] = await Promise.all([import('@babel/plugin-transform-typescript'), import('@babel/plugin-proposal-do-expressions'), import('@babel/plugin-proposal-function-bind'), import('@babel/plugin-proposal-function-sent'), import('@babel/plugin-proposal-partial-application'), import('@babel/plugin-proposal-pipeline-operator'), import('@babel/plugin-proposal-throw-expressions'), import('@babel/plugin-proposal-record-and-tuple')]);
168
+ plugins.push([babelPluginTransformTypescript.default, {
169
+ allowDeclareFields: true,
170
+ optimizeConstEnums: true
171
+ }], [babelPluginProposalDoExpressions.default], [babelPluginProposalFunctionBind.default], [babelPluginProposalFunctionSent.default], [babelPluginProposalPartialApplication.default], [babelPluginProposalPipelineOperator.default, {
172
+ proposal: `hack`,
173
+ topicToken: `%`
174
+ }], [babelPluginProposalThrowExpressions.default], [babelPluginProposalRecordAndTuple.default, {
175
+ syntaxType: `hash`,
176
+ importPolyfill: true
177
+ }]);
178
+ }
179
+ const bundle = await rollup({
180
+ input: filePathResolved,
181
+ plugins: [{
182
+ name: `hackmud-script-manager`,
183
+ transform: async code => (await preprocess(code, {
184
+ uniqueID
185
+ })).code
186
+ }, babel({
187
+ babelHelpers: `bundled`,
188
+ plugins,
189
+ configFile: false,
190
+ extensions: supportedExtensions
191
+ }), rollupPluginCommonJS(), rollupPluginNodeResolve({
192
+ extensions: supportedExtensions
193
+ }), rollupPluginJSON()],
194
+ treeshake: {
195
+ moduleSideEffects: false
196
+ }
197
+ });
198
+ const seclevelNames = [`NULLSEC`, `LOWSEC`, `MIDSEC`, `HIGHSEC`, `FULLSEC`];
199
+ code = (await bundle.generate({})).output[0].code;
200
+ const {
201
+ file,
202
+ seclevel
203
+ } = transform(parse(code, {
204
+ sourceType: `module`
205
+ }), sourceCode, {
206
+ uniqueID,
207
+ scriptUser,
208
+ scriptName
209
+ });
210
+ if (statedSeclevel != undefined && seclevel < statedSeclevel)
211
+ // TODO replace with a warning and build script anyway
212
+ throw new Error(`detected seclevel ${seclevelNames[seclevel]} is lower than stated seclevel ${seclevelNames[statedSeclevel]}`);
213
+ code = generate(file).code;
214
+ if (shouldMinify) code = await minify(file, {
215
+ uniqueID,
216
+ mangleNames,
217
+ forceQuineCheats,
218
+ autocomplete
219
+ });else {
220
+ traverse(file, {
221
+ MemberExpression({
222
+ node: memberExpression
223
+ }) {
224
+ if (memberExpression.computed) return;
225
+ assert(memberExpression.property.type == `Identifier`);
226
+ if (memberExpression.property.name == `prototype`) {
227
+ memberExpression.computed = true;
228
+ memberExpression.property = t.stringLiteral(`prototype`);
229
+ } else if (memberExpression.property.name == `__proto__`) {
230
+ memberExpression.computed = true;
231
+ memberExpression.property = t.stringLiteral(`__proto__`);
232
+ } else if (includesIllegalString(memberExpression.property.name)) {
233
+ memberExpression.computed = true;
234
+ memberExpression.property = t.stringLiteral(replaceUnsafeStrings(uniqueID, memberExpression.property.name));
235
+ }
236
+ },
237
+ VariableDeclarator(path) {
238
+ const renameVariables = lValue => {
239
+ switch (lValue.type) {
240
+ case `Identifier`:
241
+ {
242
+ if (includesIllegalString(lValue.name)) path.scope.rename(lValue.name, `$${Math.floor(Math.random() * 2 ** 52).toString(36).padStart(11, `0`)}`);
243
+ }
244
+ break;
245
+ case `ObjectPattern`:
246
+ {
247
+ for (const property of lValue.properties) {
248
+ assert(property.type == `ObjectProperty`);
249
+ renameVariables(property.value);
250
+ }
251
+ }
252
+ break;
253
+ case `ArrayPattern`:
254
+ {
255
+ for (const element of lValue.elements) {
256
+ if (element) renameVariables(element);
257
+ }
258
+ }
259
+ break;
260
+ default:
261
+ throw new Error(`unknown lValue type "${lValue.type}"`);
262
+ }
263
+ };
264
+ renameVariables(path.node.id);
265
+ },
266
+ ObjectProperty({
267
+ node: objectProperty
268
+ }) {
269
+ if (objectProperty.key.type == `Identifier` && includesIllegalString(objectProperty.key.name)) {
270
+ objectProperty.key = t.stringLiteral(replaceUnsafeStrings(uniqueID, objectProperty.key.name));
271
+ objectProperty.shorthand = false;
272
+ }
273
+ },
274
+ StringLiteral({
275
+ node
276
+ }) {
277
+ node.value = replaceUnsafeStrings(uniqueID, node.value);
278
+ },
279
+ TemplateLiteral({
280
+ node
281
+ }) {
282
+ for (const templateElement of node.quasis) {
283
+ if (templateElement.value.cooked) {
284
+ templateElement.value.cooked = replaceUnsafeStrings(uniqueID, templateElement.value.cooked);
285
+ templateElement.value.raw = templateElement.value.cooked.replaceAll(`\\`, `\\\\`).replaceAll(`\``, `\\\``).replaceAll(`\${`, `$\\{`);
286
+ } else templateElement.value.raw = replaceUnsafeStrings(uniqueID, templateElement.value.raw);
287
+ }
288
+ },
289
+ RegExpLiteral(path) {
290
+ path.node.pattern = replaceUnsafeStrings(uniqueID, path.node.pattern);
291
+ delete path.node.extra;
292
+ }
293
+ });
294
+
295
+ // we can't have comments because they may contain illegal strings
296
+ code = await format(generate(file, {
297
+ comments: false
298
+ }).code, {
299
+ parser: `babel`,
300
+ arrowParens: `avoid`,
301
+ semi: false,
302
+ trailingComma: `none`
303
+ });
304
+ }
305
+ code = postprocess(code, seclevel, uniqueID);
306
+ if (includesIllegalString(code)) throw new Error(`you found a weird edge case where I wasn't able to replace illegal strings like "SC$", please report thx`);
307
+ return {
308
+ script: code,
309
+ warnings: []
310
+ };
311
+ };
312
+
313
+ export { processScript as default, minify, postprocess, preprocess, processScript, transform };
@@ -1,6 +1,6 @@
1
- import { File } from "@babel/types";
2
- import { LaxPartial } from "@samual/lib";
3
- declare type MinifyOptions = {
1
+ import type { File } from "@babel/types";
2
+ import type { LaxPartial } from "@samual/lib";
3
+ type MinifyOptions = {
4
4
  /** 11 a-z 0-9 characters */
5
5
  uniqueID: string;
6
6
  /** whether to mangle function and class names (defaults to `false`) */