hackmud-script-manager 0.13.0-a60a7a2 → 0.13.0-c461329

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.
Files changed (55) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/workflows/codeql-analysis.yml +39 -0
  3. package/.github/workflows/publish.yml +42 -0
  4. package/.vscode/settings.json +6 -0
  5. package/babel.config.json +6 -0
  6. package/package.json +12 -21
  7. package/rollup.config.js +110 -0
  8. package/scripts/build-package-json.js +36 -0
  9. package/scripts/jsconfig.json +5 -0
  10. package/scripts/version-dev.js +25 -0
  11. package/src/bin/hsm.ts +505 -0
  12. package/src/constants.json +3 -0
  13. package/src/generateTypings.ts +116 -0
  14. package/src/index.ts +19 -0
  15. package/src/modules.d.ts +5 -0
  16. package/src/processScript/index.ts +198 -0
  17. package/src/processScript/minify.ts +529 -0
  18. package/src/processScript/postprocess.ts +38 -0
  19. package/src/processScript/preprocess.ts +146 -0
  20. package/src/processScript/transform.ts +760 -0
  21. package/src/pull.ts +16 -0
  22. package/src/push.ts +314 -0
  23. package/src/syncMacros.ts +52 -0
  24. package/src/test.ts +59 -0
  25. package/src/tsconfig.json +20 -0
  26. package/src/watch.ts +156 -0
  27. package/tsconfig.json +12 -0
  28. package/assert-1b7dada8.js +0 -1
  29. package/bin/hsm.d.ts +0 -2
  30. package/bin/hsm.js +0 -2
  31. package/generateTypings.d.ts +0 -2
  32. package/generateTypings.js +0 -1
  33. package/index.d.ts +0 -15
  34. package/index.js +0 -1
  35. package/processScript/compile.d.ts +0 -17
  36. package/processScript/compile.js +0 -1
  37. package/processScript/index.d.ts +0 -30
  38. package/processScript/index.js +0 -1
  39. package/processScript/minify.d.ts +0 -7
  40. package/processScript/minify.js +0 -1
  41. package/processScript/postProcess.d.ts +0 -2
  42. package/processScript/postProcess.js +0 -1
  43. package/processScript/preProcess.d.ts +0 -15
  44. package/processScript/preProcess.js +0 -1
  45. package/pull.d.ts +0 -9
  46. package/pull.js +0 -1
  47. package/push.d.ts +0 -26
  48. package/push.js +0 -1
  49. package/spliceString-2c6f214f.js +0 -1
  50. package/syncMacros.d.ts +0 -5
  51. package/syncMacros.js +0 -1
  52. package/test.d.ts +0 -6
  53. package/test.js +0 -1
  54. package/watch.d.ts +0 -14
  55. package/watch.js +0 -1
package/src/bin/hsm.ts ADDED
@@ -0,0 +1,505 @@
1
+ #!/usr/bin/env node
2
+ import { countHackmudCharacters, DynamicMap, writeFilePersistent } from "@samual/lib"
3
+ import chalk from "chalk"
4
+ import fs from "fs"
5
+ import { homedir as getHomeDirectory } from "os"
6
+ import { basename as getBaseName, dirname as getPathDirectory, extname as getFileExtension, relative as relativePath, resolve as resolvePath } from "path"
7
+ import { generateTypings, Info, processScript, pull, push, syncMacros, test, watch } from ".."
8
+ import { version as moduleVersion } from "../../package.json"
9
+ import { supportedExtensions } from "../constants.json"
10
+
11
+ const { readFile, rmdir: removeDirectory, writeFile, mkdir: makeDirectory } = fs.promises
12
+
13
+ type ArgValue = boolean | number | string/* | ArgValue[]*/
14
+
15
+ const configDirPath = resolvePath(getHomeDirectory(), ".config")
16
+ const configFilePath = resolvePath(configDirPath, "hsm.json")
17
+
18
+ const options = new Map<string, ArgValue>()
19
+ const commands: string[] = []
20
+
21
+ let config: Record<string, any> & Partial<{
22
+ hackmudPath: string
23
+ defaultUser: string
24
+ users: Record<string, {
25
+ colour: string
26
+ }>
27
+ }> | undefined
28
+
29
+ const colourJ = chalk.rgb(0xFF, 0xF4, 0x04)
30
+ const colourK = chalk.rgb(0xF3, 0xF9, 0x98)
31
+ const colourM = chalk.rgb(0xB3, 0xFF, 0x9B)
32
+ const colourW = chalk.rgb(0xFF, 0x96, 0xE0)
33
+ const colourL = chalk.rgb(0x1E, 0xFF, 0x00)
34
+ const colourB = chalk.rgb(0xCA, 0xCA, 0xCA)
35
+
36
+ const userColours = new DynamicMap<string, string>(user => {
37
+ let hash = 0
38
+
39
+ for (const char of user)
40
+ hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
41
+
42
+ return [ colourJ, colourK, colourM, colourW, colourL, colourB ][hash % 6](user)
43
+ })
44
+
45
+ for (const arg of process.argv.slice(2)) {
46
+ if (arg[0] == "-") {
47
+ const [ key, valueRaw ] = arg.split("=")
48
+ let value: ArgValue = valueRaw
49
+
50
+ if (value) {
51
+ if (value == "true")
52
+ value = true
53
+ else if (value == "false")
54
+ value = false
55
+ else {
56
+ const number = Number(value)
57
+
58
+ if (isFinite(number))
59
+ value = number
60
+ }
61
+ } else
62
+ value = true
63
+
64
+ if (arg[1] == "-")
65
+ options.set(key.slice(2), value)
66
+ else {
67
+ for (const option of key.slice(1))
68
+ options.set(option, value)
69
+ }
70
+ } else
71
+ commands.push(arg)
72
+ }
73
+
74
+ (async () => {
75
+ if (options.get("version") || options.get("v")) {
76
+ version()
77
+ return
78
+ }
79
+
80
+ if (options.get("help") || options.get("h")) {
81
+ help()
82
+ return
83
+ }
84
+
85
+ switch (commands[0]) {
86
+ case "push": {
87
+ const config = await getConfig()
88
+
89
+ if (!config.hackmudPath) {
90
+ console.log("you need to set hackmudPath in config before you can use this command")
91
+ break
92
+ }
93
+
94
+ const srcPath = commands[1] || "."
95
+ const hackmudPath = config.hackmudPath
96
+ const scripts = commands.slice(2)
97
+
98
+ if (!scripts.length)
99
+ scripts.push("*.*")
100
+
101
+ const infos = await push(
102
+ srcPath,
103
+ hackmudPath,
104
+ {
105
+ scripts,
106
+ onPush: onPushLogger,
107
+ minify: !options.get("skip-minify")
108
+ }
109
+ )
110
+
111
+ if (!infos.length)
112
+ console.warn("couldn't find any scripts to push")
113
+
114
+ updateConfig()
115
+ } break
116
+
117
+ case "dev":
118
+ case "watch": {
119
+ const config = await getConfig()
120
+
121
+ if (!config.hackmudPath) {
122
+ console.log("you need to set hackmudPath in config before you can use this command")
123
+ break
124
+ }
125
+
126
+ const srcPath = commands[1] || "."
127
+ const hackmudPath = config.hackmudPath
128
+ const users = options.get("users")?.toString().split(",") || []
129
+ const scripts = options.get("scripts")?.toString().split(",") || []
130
+ const genTypes = options.get("gen-types")?.toString()
131
+
132
+ watch(srcPath, hackmudPath, users, scripts, onPushLogger, { genTypes })
133
+ } break
134
+
135
+ case "pull": {
136
+ const config = await getConfig()
137
+
138
+ if (!config.hackmudPath) {
139
+ console.log("you need to set hackmudPath in config before you can use this command")
140
+ break
141
+ }
142
+
143
+ const script = commands[1]
144
+
145
+ if (!script) {
146
+ help()
147
+ break
148
+ }
149
+
150
+ const srcPath = commands[2] || "."
151
+ const hackmudPath = config.hackmudPath
152
+
153
+ try {
154
+ await pull(srcPath, hackmudPath, script)
155
+ } catch (error) {
156
+ console.log("something went wrong, did you forget to #down the script?")
157
+ }
158
+ } break
159
+
160
+ case "sync-macros": {
161
+ const { hackmudPath } = await getConfig()
162
+
163
+ if (!hackmudPath) {
164
+ console.log("you need to set hackmudPath in config before you can use this command")
165
+ break
166
+ }
167
+
168
+ const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
169
+ console.log(`synced ${macrosSynced} macros to ${usersSynced} users`)
170
+ } break
171
+
172
+ case "test": {
173
+ const srcPath = resolvePath(commands[1] || ".")
174
+ let errors = 0
175
+
176
+ console.log(`testing scripts in ${chalk.bold(srcPath)}\n`)
177
+
178
+ for (const { file, line, message } of await test(srcPath)) {
179
+ console.log(`error "${chalk.bold(message)}" in ${chalk.bold(file)} on line ${chalk.bold(String(line))}`)
180
+ errors++
181
+ }
182
+
183
+ if (!errors) {
184
+ console.log("no errors found")
185
+ break
186
+ }
187
+
188
+ if (errors) {
189
+ process.exitCode = 1
190
+ console.log(`\nencountered ${chalk.bold(String(errors))} errors`)
191
+ break
192
+ }
193
+
194
+ console.log("no errors found")
195
+ } break
196
+
197
+ case "gen-types": {
198
+ const srcPath = resolvePath(commands[1] || ".")
199
+ let targetPath: string
200
+
201
+ if (commands[2])
202
+ targetPath = resolvePath(commands[2])
203
+ else
204
+ targetPath = resolvePath(srcPath, "../player.d.ts")
205
+
206
+ generateTypings(srcPath, targetPath, (await getConfig()).hackmudPath)
207
+ } break
208
+
209
+ case "config":
210
+ switch (commands[1]) {
211
+ case "get": {
212
+ console.log(exploreObject(await getConfig(), commands[2].split(".")))
213
+ } break
214
+
215
+ case "delete": {
216
+ const keys = commands[2].split(".")
217
+
218
+ if (!keys.length) {
219
+ help()
220
+ break
221
+ }
222
+
223
+ const config = await getConfig()
224
+
225
+ delete exploreObject(config, keys)?.[commands[3]]
226
+
227
+ console.log(config)
228
+ } break
229
+
230
+ case "set": {
231
+ const keys = commands[2].split(".")
232
+
233
+ if (!keys.length) {
234
+ help()
235
+ break
236
+ }
237
+
238
+ const config = await getConfig()
239
+ let object = config
240
+
241
+ for (let key of keys.slice(0, -1))
242
+ object = typeof object[key] == "object" ? object[key] : object[key] = {}
243
+
244
+ object[keys.slice(-1)[0]] = commands[3]
245
+
246
+ if (config.hackmudPath)
247
+ config.hackmudPath = resolvePath(config.hackmudPath)
248
+
249
+ console.log(config)
250
+ } break
251
+
252
+ default: {
253
+ if (commands[1])
254
+ console.log("unknown command")
255
+
256
+ help()
257
+ }
258
+ } break
259
+
260
+ case "help":
261
+ case "h": {
262
+ help()
263
+ } break
264
+
265
+ case "version":
266
+ case "v": {
267
+ version()
268
+ } break
269
+
270
+ case "golf":
271
+ case "minify": {
272
+ // TODO `--watch` option
273
+
274
+ if (!commands[1]) {
275
+ console.log(`Target required\nUsage: ${getBaseName(process.argv[1])} ${commands[0]} <target> [output]`)
276
+ break
277
+ }
278
+
279
+ const fileExtension = getFileExtension(commands[1])
280
+
281
+ if (!supportedExtensions.includes(fileExtension)) {
282
+ console.log(`Unsupported file extension "${chalk.bold(fileExtension)}"\nSupported extensions are "${supportedExtensions.map(extension => chalk.bold(extension)).join('", "')}"`)
283
+ break
284
+ }
285
+
286
+ await readFile(commands[1], { encoding: "utf-8" }).then(
287
+ async source => {
288
+ const fileBaseName = getBaseName(commands[1], fileExtension)
289
+ const fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src")
290
+
291
+ const scriptName = fileBaseNameEndsWithDotSrc
292
+ ? fileBaseName.slice(0, -4)
293
+ : fileBaseName
294
+
295
+ let scriptUser = "UNKNOWN"
296
+
297
+ if (getBaseName(resolvePath(commands[1], "..")) == "scripts" && getBaseName(resolvePath(commands[1], "../../..")) == "hackmud")
298
+ scriptUser = getBaseName(resolvePath(commands[1], "../.."))
299
+
300
+ const minify = !options.get("skip-minify")
301
+ const mangleNames = Boolean(options.get("mangle-names"))
302
+
303
+ if (!minify && mangleNames)
304
+ console.warn("warning: `--mangle-names` has no effect while `--skip-minify` is active")
305
+
306
+ const { script, srcLength, warnings, timeTook } = await processScript(
307
+ source,
308
+ {
309
+ minify,
310
+ scriptUser,
311
+ scriptName,
312
+ filePath: commands[1],
313
+ mangleNames
314
+ }
315
+ )
316
+
317
+ for (const { message, line } of warnings)
318
+ console.log(`warning "${chalk.bold(message)}" on line ${chalk.bold(String(line))}`)
319
+
320
+ let outputPath: string
321
+
322
+ if (commands[2])
323
+ outputPath = commands[2]
324
+ else {
325
+ outputPath = resolvePath(
326
+ getPathDirectory(commands[1]),
327
+
328
+ fileBaseNameEndsWithDotSrc
329
+ ? `${scriptName}.js` :
330
+ fileExtension == ".js"
331
+ ? `${fileBaseName}.min.js`
332
+ : `${fileBaseName}.js`
333
+ )
334
+ }
335
+
336
+ const scriptLength = countHackmudCharacters(script)
337
+
338
+ await writeFilePersistent(outputPath, script)
339
+ .catch(async (error: NodeJS.ErrnoException) => {
340
+ if (!commands[2] || error.code != "EISDIR")
341
+ throw error
342
+
343
+ outputPath = resolvePath(outputPath, `${getBaseName(commands[1], fileExtension)}.js`)
344
+
345
+ await writeFilePersistent(outputPath, script)
346
+ })
347
+ .then(
348
+ () => console.log(`wrote ${chalk.bold(scriptLength)} chars to ${chalk.bold(relativePath(".", outputPath))} | saved ${chalk.bold(srcLength - scriptLength)} chars | took ${Math.round(timeTook * 100) / 100}ms`),
349
+ (error: NodeJS.ErrnoException) => console.log(error.message)
350
+ )
351
+ },
352
+ (error: NodeJS.ErrnoException) => console.log(error.message)
353
+ )
354
+ } break
355
+
356
+ default: {
357
+ if (commands[0])
358
+ console.log("unknown command")
359
+
360
+ help()
361
+ }
362
+ }
363
+
364
+ updateConfig()
365
+ })()
366
+
367
+ function help() {
368
+ switch (commands[0]) {
369
+ case "config": {
370
+ switch (commands[1]) {
371
+ case "get": {
372
+ console.log("hsm config get <key>")
373
+ } break
374
+
375
+ case "set": {
376
+ console.log("hsm config set <key> <value>")
377
+ } break
378
+
379
+ case "delete": {
380
+ console.log("hsm config delete <key>")
381
+ } break
382
+
383
+ default: {
384
+ console.log("hsm config <get, delete, set>")
385
+ }
386
+ }
387
+ } break
388
+
389
+ case "push": {
390
+ console.log("hsm push [<dir> [...\"<script user>.<script name>\"]]")
391
+ } break
392
+
393
+ case "watch": {
394
+ console.log("hsm watch [dir]")
395
+ } break
396
+
397
+ case "pull": {
398
+ console.log("hsm pull <script user>.<script name>")
399
+ } break
400
+
401
+ case "minify":
402
+ case "golf": {
403
+ console.log(`${getBaseName(process.argv[1])} ${commands[0]} <target> [output]`)
404
+ } break
405
+
406
+ default: {
407
+ console.log("hsm <push, watch, pull, config, golf>")
408
+ }
409
+ }
410
+ }
411
+
412
+ async function version() {
413
+ console.log(moduleVersion)
414
+ }
415
+
416
+ async function getConfig() {
417
+ if (config)
418
+ return config
419
+
420
+ return config = await readFile(configFilePath, { encoding: "utf-8" })
421
+ .then(configFile => {
422
+ let tempConfig
423
+
424
+ try {
425
+ tempConfig = JSON.parse(configFile)
426
+ } catch {
427
+ // TODO log to error log file
428
+ console.log("config file was corrupted, resetting")
429
+ return {}
430
+ }
431
+
432
+ if (!tempConfig || typeof tempConfig != "object") {
433
+ console.log("config file was corrupted, resetting")
434
+ return {}
435
+ }
436
+
437
+ return tempConfig
438
+ }, () => {
439
+ console.log(`creating config file at ${configFilePath}`)
440
+ return {}
441
+ })
442
+ }
443
+
444
+ function exploreObject(object: any, keys: string[], createPath = false) {
445
+ for (const key of keys) {
446
+ if (createPath)
447
+ object = typeof object[key] == "object" ? object[key] : object[key] = {}
448
+ else
449
+ object = object?.[key]
450
+ }
451
+
452
+ return object
453
+ }
454
+
455
+ function updateConfig() {
456
+ if (config) {
457
+ const json = JSON.stringify(config)
458
+
459
+ writeFile(configFilePath, json).catch(async error => {
460
+ switch (error.code) {
461
+ case "EISDIR": {
462
+ await removeDirectory(configFilePath)
463
+ } break
464
+
465
+ case "ENOENT": {
466
+ await makeDirectory(configDirPath)
467
+ } break
468
+
469
+ default: {
470
+ throw error
471
+ }
472
+ }
473
+
474
+ writeFile(configFilePath, json)
475
+ })
476
+ }
477
+ }
478
+
479
+ function onPushLogger({ file, users, srcLength, minLength, error }: Info) {
480
+ if (!users.length)
481
+ return
482
+
483
+ if (error) {
484
+ console.log(`error "${chalk.bold(error.message)}" in ${chalk.bold(file)}`)
485
+ return
486
+ }
487
+
488
+ console.log(
489
+ `pushed ${
490
+ chalk.bold(file)
491
+ } to ${
492
+ users.map(user => chalk.bold(userColours.get(user))).join(", ")
493
+ } | ${
494
+ chalk.bold(String(minLength))
495
+ } chars from ${
496
+ chalk.bold(String(srcLength))
497
+ } | saved ${
498
+ chalk.bold(String(srcLength - minLength))
499
+ } (${
500
+ chalk.bold(`${Math.round((1 - (minLength / srcLength)) * 100)}%`)
501
+ }) | ${
502
+ chalk.bold(`${resolvePath(config!.hackmudPath!, users[0], "scripts", getBaseName(file, getFileExtension(file)))}.js`)
503
+ }`
504
+ )
505
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "supportedExtensions": [ ".js", ".ts" ]
3
+ }
@@ -0,0 +1,116 @@
1
+ import fs from "fs"
2
+ import { basename as getBaseName, extname as getFileExtension, resolve as resolvePath } from "path"
3
+
4
+ const { readdir: readDirectory, writeFile } = fs.promises
5
+
6
+ export async function generateTypings(srcDir: string, target: string, hackmudPath?: string) {
7
+ const users = new Set<string>()
8
+
9
+ if (hackmudPath) {
10
+ for (const dirent of await readDirectory(hackmudPath, { withFileTypes: true })) {
11
+ if (dirent.isFile() && getFileExtension(dirent.name) == ".key")
12
+ users.add(getBaseName(dirent.name, ".key"))
13
+ }
14
+ }
15
+
16
+ const wildScripts: string[] = []
17
+ const wildAnyScripts: string[] = []
18
+ const allScripts: Record<string, string[]> = {}
19
+ const allAnyScripts: Record<string, string[]> = {}
20
+
21
+ for (const dirent of await readDirectory(srcDir, { withFileTypes: true })) {
22
+ if (dirent.isFile()) {
23
+ if (getFileExtension(dirent.name) == ".ts")
24
+ wildScripts.push(getBaseName(dirent.name, ".ts"))
25
+ else if (getFileExtension(dirent.name) == ".js")
26
+ wildAnyScripts.push(getBaseName(dirent.name, ".js"))
27
+ } else if (dirent.isDirectory()) {
28
+ const scripts: string[] = allScripts[dirent.name] = []
29
+ const anyScripts: string[] = allAnyScripts[dirent.name] = []
30
+
31
+ users.add(dirent.name)
32
+
33
+ for (const file of await readDirectory(resolvePath(srcDir, dirent.name), { withFileTypes: true })) {
34
+ if (file.isFile()) {
35
+ if (getFileExtension(file.name) == ".ts")
36
+ scripts.push(getBaseName(file.name, ".ts"))
37
+ else if (getFileExtension(file.name) == ".js")
38
+ anyScripts.push(getBaseName(file.name, ".js"))
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ let o = ""
45
+
46
+ for (const script of wildScripts)
47
+ o += `import { script as $${script}$ } from "./src/${script}"\n`
48
+
49
+ o += "\n"
50
+
51
+ for (const user in allScripts) {
52
+ const scripts = allScripts[user]
53
+
54
+ for (const script of scripts)
55
+ o += `import { script as $${user}$${script}$ } from "./src/${user}/${script}"\n`
56
+ }
57
+
58
+ // TODO detect security level and generate apropriate code
59
+
60
+ // TODO accurate function signatures
61
+ // currently I lose the generic-ness of my functions when I wrap them
62
+ // just regexing isn't enough and it looks like I'm going to need to parse the files in TypeScript to extract the signature
63
+
64
+ o += `
65
+ type ArrayRemoveFirst<A> = A extends [ infer FirstItem, ...infer Rest ] ? Rest : never
66
+
67
+ type Subscript<T extends (...args: any) => any> =
68
+ (...args: ArrayRemoveFirst<Parameters<T>>) => ReturnType<T> | ScriptFailure
69
+
70
+ type WildFullsec = Record<string, () => ScriptFailure> & {
71
+ `
72
+
73
+ for (const script of wildScripts)
74
+ o += `\t${script}: Subscript<typeof $${script}$>\n`
75
+
76
+ for (const script of wildAnyScripts)
77
+ o += `\t${script}: (...args: any) => any\n`
78
+
79
+ o += "}\n\ndeclare global {\n\tinterface PlayerFullsec {"
80
+
81
+ let lastWasMultiLine = true
82
+
83
+ for (const user of users) {
84
+ const scripts = allScripts[user]
85
+ const anyScripts = allAnyScripts[user]
86
+
87
+ if ((scripts && scripts.length) || (anyScripts && anyScripts.length)) {
88
+ lastWasMultiLine = true
89
+
90
+ o += `\n\t\t${user}: WildFullsec & {\n`
91
+
92
+ for (const script of scripts)
93
+ o += `\t\t\t${script}: Subscript<typeof $${user}$${script}$>\n`
94
+
95
+ for (const script of anyScripts)
96
+ o += `\t\t\t${script}: (...args: any) => any\n`
97
+
98
+ o += "\t\t}"
99
+ } else {
100
+ if (lastWasMultiLine) {
101
+ o += "\n"
102
+ lastWasMultiLine = false
103
+ }
104
+
105
+ o += `\t\t${user}: WildFullsec`
106
+ }
107
+
108
+ o += "\n"
109
+ }
110
+
111
+ o += "\t}\n}\n"
112
+
113
+ await writeFile(target, o)
114
+ }
115
+
116
+ export default generateTypings
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ export { supportedExtensions } from "./constants.json"
2
+ export { generateTypings } from "./generateTypings"
3
+ export { processScript } from "./processScript"
4
+ export { pull } from "./pull"
5
+ export { push } from "./push"
6
+ export { syncMacros } from "./syncMacros"
7
+ export { test } from "./test"
8
+ export { watch } from "./watch"
9
+
10
+ // TODO `clean()` function that delete all scripts in hackmud directory #70
11
+ // TODO optional argument (defaults to false) for `clean()` that makes it only remove scripts without a source file #70
12
+
13
+ export interface Info {
14
+ file: string
15
+ users: string[]
16
+ srcLength: number
17
+ minLength: number
18
+ error: Error | null
19
+ }
@@ -0,0 +1,5 @@
1
+ declare module "@babel/plugin-*" {
2
+ export default {
3
+ default: (...args: any[]) => any
4
+ }
5
+ }