@metamask/snaps-cli 0.7.0 → 0.10.0

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 (51) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/README.md +67 -25
  3. package/dist/builders.d.ts +16 -8
  4. package/dist/builders.js +66 -41
  5. package/dist/builders.js.map +1 -1
  6. package/dist/cli.js +5 -4
  7. package/dist/cli.js.map +1 -1
  8. package/dist/cmds/build/buildHandler.js +1 -1
  9. package/dist/cmds/build/buildHandler.js.map +1 -1
  10. package/dist/cmds/build/bundle.d.ts +9 -7
  11. package/dist/cmds/build/bundle.js +35 -31
  12. package/dist/cmds/build/bundle.js.map +1 -1
  13. package/dist/cmds/build/index.js +10 -4
  14. package/dist/cmds/build/index.js.map +1 -1
  15. package/dist/cmds/build/utils.d.ts +59 -0
  16. package/dist/cmds/build/utils.js +152 -0
  17. package/dist/cmds/build/utils.js.map +1 -0
  18. package/dist/cmds/eval/evalHandler.d.ts +1 -1
  19. package/dist/cmds/eval/evalHandler.js +1 -2
  20. package/dist/cmds/eval/evalHandler.js.map +1 -1
  21. package/dist/cmds/eval/index.d.ts +1 -1
  22. package/dist/cmds/index.d.ts +2 -7
  23. package/dist/cmds/init/init-template.json +2 -2
  24. package/dist/cmds/init/initHandler.d.ts +2 -0
  25. package/dist/cmds/init/initHandler.js +11 -6
  26. package/dist/cmds/init/initHandler.js.map +1 -1
  27. package/dist/cmds/init/initUtils.js +4 -4
  28. package/dist/cmds/init/initUtils.js.map +1 -1
  29. package/dist/cmds/manifest/index.js +1 -1
  30. package/dist/cmds/manifest/index.js.map +1 -1
  31. package/dist/cmds/serve/index.js +2 -2
  32. package/dist/cmds/serve/index.js.map +1 -1
  33. package/dist/cmds/watch/index.js +11 -1
  34. package/dist/cmds/watch/index.js.map +1 -1
  35. package/dist/cmds/watch/watchHandler.js +32 -19
  36. package/dist/cmds/watch/watchHandler.js.map +1 -1
  37. package/dist/utils/fs.js +1 -1
  38. package/dist/utils/fs.js.map +1 -1
  39. package/dist/utils/misc.d.ts +10 -1
  40. package/dist/utils/misc.js +27 -4
  41. package/dist/utils/misc.js.map +1 -1
  42. package/dist/utils/snap-config.__GENERATED__.d.ts +2 -0
  43. package/dist/utils/snap-config.__GENERATED__.js +18 -0
  44. package/dist/utils/snap-config.__GENERATED__.js.map +1 -0
  45. package/dist/utils/snap-config.d.ts +8 -1
  46. package/dist/utils/snap-config.js +39 -32
  47. package/dist/utils/snap-config.js.map +1 -1
  48. package/package.json +11 -7
  49. package/dist/cmds/build/bundleUtils.d.ts +0 -42
  50. package/dist/cmds/build/bundleUtils.js +0 -95
  51. package/dist/cmds/build/bundleUtils.js.map +0 -1
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  const builders_1 = __importDefault(require("../../builders"));
6
+ const utils_1 = require("../build/utils");
6
7
  const watchHandler_1 = require("./watchHandler");
7
8
  module.exports = {
8
9
  command: ['watch', 'w'],
@@ -10,10 +11,19 @@ module.exports = {
10
11
  builder: (yarg) => {
11
12
  yarg
12
13
  .option('src', builders_1.default.src)
14
+ .option('eval', builders_1.default.eval)
13
15
  .option('dist', builders_1.default.dist)
14
16
  .option('outfileName', builders_1.default.outfileName)
15
17
  .option('sourceMaps', builders_1.default.sourceMaps)
16
- .option('stripComments', builders_1.default.stripComments);
18
+ .option('stripComments', builders_1.default.stripComments)
19
+ .option('transformHtmlComments', builders_1.default.transformHtmlComments)
20
+ .option('transpilationMode', builders_1.default.transpilationMode)
21
+ .option('depsToTranspile', builders_1.default.depsToTranspile)
22
+ .option('manifest', builders_1.default.manifest)
23
+ .option('writeManifest', builders_1.default.writeManifest)
24
+ .implies('writeManifest', 'manifest')
25
+ .implies('depsToTranspile', 'transpilationMode')
26
+ .middleware((argv) => utils_1.processInvalidTranspilation(argv));
17
27
  },
18
28
  handler: (argv) => watchHandler_1.watch(argv),
19
29
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cmds/watch/index.ts"],"names":[],"mappings":";;;;AACA,8DAAsC;AAEtC,iDAAuC;AAEvC,iBAAS;IACP,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC;IACvB,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,CAAC,IAAgB,EAAE,EAAE;QAC5B,IAAI;aACD,MAAM,CAAC,KAAK,EAAE,kBAAQ,CAAC,GAAG,CAAC;aAC3B,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,IAAI,CAAC;aAC7B,MAAM,CAAC,aAAa,EAAE,kBAAQ,CAAC,WAAW,CAAC;aAC3C,MAAM,CAAC,YAAY,EAAE,kBAAQ,CAAC,UAAU,CAAC;aACzC,MAAM,CAAC,eAAe,EAAE,kBAAQ,CAAC,aAAa,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,CAAC,IAAe,EAAE,EAAE,CAAC,oBAAK,CAAC,IAAI,CAAC;CAC1C,CAAC","sourcesContent":["import yargs from 'yargs';\nimport builders from '../../builders';\nimport { YargsArgs } from '../../types/yargs';\nimport { watch } from './watchHandler';\n\nexport = {\n command: ['watch', 'w'],\n desc: 'Build Snap on change',\n builder: (yarg: yargs.Argv) => {\n yarg\n .option('src', builders.src)\n .option('dist', builders.dist)\n .option('outfileName', builders.outfileName)\n .option('sourceMaps', builders.sourceMaps)\n .option('stripComments', builders.stripComments);\n },\n handler: (argv: YargsArgs) => watch(argv),\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cmds/watch/index.ts"],"names":[],"mappings":";;;;AACA,8DAAsC;AAEtC,0CAA6D;AAC7D,iDAAuC;AAEvC,iBAAS;IACP,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC;IACvB,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,CAAC,IAAgB,EAAE,EAAE;QAC5B,IAAI;aACD,MAAM,CAAC,KAAK,EAAE,kBAAQ,CAAC,GAAG,CAAC;aAC3B,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,IAAI,CAAC;aAC7B,MAAM,CAAC,MAAM,EAAE,kBAAQ,CAAC,IAAI,CAAC;aAC7B,MAAM,CAAC,aAAa,EAAE,kBAAQ,CAAC,WAAW,CAAC;aAC3C,MAAM,CAAC,YAAY,EAAE,kBAAQ,CAAC,UAAU,CAAC;aACzC,MAAM,CAAC,eAAe,EAAE,kBAAQ,CAAC,aAAa,CAAC;aAC/C,MAAM,CAAC,uBAAuB,EAAE,kBAAQ,CAAC,qBAAqB,CAAC;aAC/D,MAAM,CAAC,mBAAmB,EAAE,kBAAQ,CAAC,iBAAiB,CAAC;aACvD,MAAM,CAAC,iBAAiB,EAAE,kBAAQ,CAAC,eAAe,CAAC;aACnD,MAAM,CAAC,UAAU,EAAE,kBAAQ,CAAC,QAAQ,CAAC;aACrC,MAAM,CAAC,eAAe,EAAE,kBAAQ,CAAC,aAAa,CAAC;aAC/C,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC;aACpC,OAAO,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;aAC/C,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mCAA2B,CAAC,IAAW,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,CAAC,IAAe,EAAE,EAAE,CAAC,oBAAK,CAAC,IAAI,CAAC;CAC1C,CAAC","sourcesContent":["import yargs from 'yargs';\nimport builders from '../../builders';\nimport { YargsArgs } from '../../types/yargs';\nimport { processInvalidTranspilation } from '../build/utils';\nimport { watch } from './watchHandler';\n\nexport = {\n command: ['watch', 'w'],\n desc: 'Build Snap on change',\n builder: (yarg: yargs.Argv) => {\n yarg\n .option('src', builders.src)\n .option('eval', builders.eval)\n .option('dist', builders.dist)\n .option('outfileName', builders.outfileName)\n .option('sourceMaps', builders.sourceMaps)\n .option('stripComments', builders.stripComments)\n .option('transformHtmlComments', builders.transformHtmlComments)\n .option('transpilationMode', builders.transpilationMode)\n .option('depsToTranspile', builders.depsToTranspile)\n .option('manifest', builders.manifest)\n .option('writeManifest', builders.writeManifest)\n .implies('writeManifest', 'manifest')\n .implies('depsToTranspile', 'transpilationMode')\n .middleware((argv) => processInvalidTranspilation(argv as any));\n },\n handler: (argv: YargsArgs) => watch(argv),\n};\n"]}
@@ -5,8 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.watch = void 0;
7
7
  const chokidar_1 = __importDefault(require("chokidar"));
8
- const bundle_1 = require("../build/bundle");
9
8
  const utils_1 = require("../../utils");
9
+ const bundle_1 = require("../build/bundle");
10
+ const evalHandler_1 = require("../eval/evalHandler");
11
+ const manifestHandler_1 = require("../manifest/manifestHandler");
10
12
  /**
11
13
  * Watch a directory and its subdirectories for changes, and build when files
12
14
  * are added or changed.
@@ -20,7 +22,7 @@ const utils_1 = require("../../utils");
20
22
  * @param argv.'outfileName' - The output file name
21
23
  */
22
24
  async function watch(argv) {
23
- const { src, dist, outfileName } = argv;
25
+ const { dist, eval: shouldEval, manifest, outfileName, src } = argv;
24
26
  if (outfileName) {
25
27
  utils_1.validateOutfileName(outfileName);
26
28
  }
@@ -28,7 +30,27 @@ async function watch(argv) {
28
30
  await utils_1.validateDirPath(dist, true);
29
31
  const rootDir = src.indexOf('/') === -1 ? '.' : src.substring(0, src.lastIndexOf('/') + 1);
30
32
  const outfilePath = utils_1.getOutfilePath(dist, outfileName);
31
- const watcher = chokidar_1.default.watch(rootDir, {
33
+ const buildSnap = async (path, logMessage) => {
34
+ if (logMessage !== undefined) {
35
+ console.log(logMessage);
36
+ }
37
+ try {
38
+ await bundle_1.bundle(src, outfilePath, argv, utils_1.loadConfig().bundlerCustomizer);
39
+ if (manifest) {
40
+ await manifestHandler_1.manifestHandler(argv);
41
+ }
42
+ if (shouldEval) {
43
+ await evalHandler_1.snapEval(Object.assign(Object.assign({}, argv), { bundle: outfilePath }));
44
+ }
45
+ }
46
+ catch (error) {
47
+ utils_1.logError(`Error ${path === undefined
48
+ ? 'during initial build'
49
+ : `while processing "${path}"`}.`, error);
50
+ }
51
+ };
52
+ chokidar_1.default
53
+ .watch(rootDir, {
32
54
  ignoreInitial: true,
33
55
  ignored: [
34
56
  '**/node_modules/**',
@@ -40,24 +62,15 @@ async function watch(argv) {
40
62
  /* istanbul ignore next */
41
63
  (str) => str !== '.' && str.startsWith('.'),
42
64
  ],
43
- });
44
- watcher
45
- .on('ready', () => {
46
- bundle_1.bundle(src, outfilePath, argv);
47
- })
48
- .on('add', (path) => {
49
- console.log(`File added: ${path}`);
50
- bundle_1.bundle(src, outfilePath, argv);
51
- })
52
- .on('change', (path) => {
53
- console.log(`File changed: ${path}`);
54
- bundle_1.bundle(src, outfilePath, argv);
55
65
  })
66
+ .on('ready', buildSnap)
67
+ .on('add', (path) => buildSnap(path, `File added: ${path}`))
68
+ .on('change', (path) => buildSnap(path, `File changed: ${path}`))
56
69
  .on('unlink', (path) => console.log(`File removed: ${path}`))
57
- .on('error', (err) => {
58
- utils_1.logError(`Watcher error: ${err.message}`, err);
59
- });
60
- watcher.add(`${rootDir}`);
70
+ .on('error', (error) => {
71
+ utils_1.logError(`Watcher error: ${error.message}`, error);
72
+ })
73
+ .add(rootDir);
61
74
  console.log(`Watching '${rootDir}' for changes...`);
62
75
  }
63
76
  exports.watch = watch;
@@ -1 +1 @@
1
- {"version":3,"file":"watchHandler.js","sourceRoot":"","sources":["../../../src/cmds/watch/watchHandler.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAEhC,4CAAyC;AACzC,uCAMqB;AAErB;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,KAAK,CAAC,IAAe;IACzC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACxC,IAAI,WAAW,EAAE;QACf,2BAAmB,CAAC,WAAqB,CAAC,CAAC;KAC5C;IACD,MAAM,wBAAgB,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,uBAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GACX,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,sBAAc,CAAC,IAAI,EAAE,WAAqB,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAG,kBAAQ,CAAC,KAAK,CAAC,OAAO,EAAE;QACtC,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE;YACP,oBAAoB;YACpB,MAAM,IAAI,KAAK;YACf,YAAY;YACZ,aAAa;YACb,cAAc;YACd,cAAc;YACd,0BAA0B;YAC1B,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;SACpD;KACF,CAAC,CAAC;IAEH,OAAO;SACJ,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAChB,eAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC;SACD,EAAE,CAAC,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QACnC,eAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACrC,eAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC;SACD,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;SACpE,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;QAC1B,gBAAQ,CAAC,kBAAkB,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,kBAAkB,CAAC,CAAC;AACtD,CAAC;AA5CD,sBA4CC","sourcesContent":["import chokidar from 'chokidar';\nimport { YargsArgs } from '../../types/yargs';\nimport { bundle } from '../build/bundle';\nimport {\n logError,\n getOutfilePath,\n validateDirPath,\n validateFilePath,\n validateOutfileName,\n} from '../../utils';\n\n/**\n * Watch a directory and its subdirectories for changes, and build when files\n * are added or changed.\n *\n * Ignores 'node_modules' and dotfiles.\n * Creates destination directory if it doesn't exist.\n *\n * @param argv - arguments as an object generated by yargs\n * @param argv.src - The source file path\n * @param argv.dist - The output directory path\n * @param argv.'outfileName' - The output file name\n */\nexport async function watch(argv: YargsArgs): Promise<void> {\n const { src, dist, outfileName } = argv;\n if (outfileName) {\n validateOutfileName(outfileName as string);\n }\n await validateFilePath(src);\n await validateDirPath(dist, true);\n const rootDir =\n src.indexOf('/') === -1 ? '.' : src.substring(0, src.lastIndexOf('/') + 1);\n const outfilePath = getOutfilePath(dist, outfileName as string);\n\n const watcher = chokidar.watch(rootDir, {\n ignoreInitial: true,\n ignored: [\n '**/node_modules/**',\n `**/${dist}/**`,\n `**/test/**`,\n `**/tests/**`,\n `**/*.test.js`,\n `**/*.test.ts`,\n /* istanbul ignore next */\n (str: string) => str !== '.' && str.startsWith('.'),\n ],\n });\n\n watcher\n .on('ready', () => {\n bundle(src, outfilePath, argv);\n })\n .on('add', (path: string) => {\n console.log(`File added: ${path}`);\n bundle(src, outfilePath, argv);\n })\n .on('change', (path: string) => {\n console.log(`File changed: ${path}`);\n bundle(src, outfilePath, argv);\n })\n .on('unlink', (path: string) => console.log(`File removed: ${path}`))\n .on('error', (err: Error) => {\n logError(`Watcher error: ${err.message}`, err);\n });\n\n watcher.add(`${rootDir}`);\n console.log(`Watching '${rootDir}' for changes...`);\n}\n"]}
1
+ {"version":3,"file":"watchHandler.js","sourceRoot":"","sources":["../../../src/cmds/watch/watchHandler.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAEhC,uCAOqB;AACrB,4CAAyC;AACzC,qDAA+C;AAC/C,iEAA8D;AAE9D;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,KAAK,CAAC,IAAe;IACzC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACpE,IAAI,WAAW,EAAE;QACf,2BAAmB,CAAC,WAAqB,CAAC,CAAC;KAC5C;IACD,MAAM,wBAAgB,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,uBAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GACX,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,sBAAc,CAAC,IAAI,EAAE,WAAqB,CAAC,CAAC;IAEhE,MAAM,SAAS,GAAG,KAAK,EAAE,IAAa,EAAE,UAAmB,EAAE,EAAE;QAC7D,IAAI,UAAU,KAAK,SAAS,EAAE;YAC5B,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;SACzB;QAED,IAAI;YACF,MAAM,eAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,kBAAU,EAAE,CAAC,iBAAiB,CAAC,CAAC;YAErE,IAAI,QAAQ,EAAE;gBACZ,MAAM,iCAAe,CAAC,IAAI,CAAC,CAAC;aAC7B;YAED,IAAI,UAAU,EAAE;gBACd,MAAM,sBAAQ,iCAAM,IAAI,KAAE,MAAM,EAAE,WAAW,IAAG,CAAC;aAClD;SACF;QAAC,OAAO,KAAK,EAAE;YACd,gBAAQ,CACN,SACE,IAAI,KAAK,SAAS;gBAChB,CAAC,CAAC,sBAAsB;gBACxB,CAAC,CAAC,qBAAqB,IAAI,GAC/B,GAAG,EACH,KAAK,CACN,CAAC;SACH;IACH,CAAC,CAAC;IAEF,kBAAQ;SACL,KAAK,CAAC,OAAO,EAAE;QACd,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE;YACP,oBAAoB;YACpB,MAAM,IAAI,KAAK;YACf,YAAY;YACZ,aAAa;YACb,cAAc;YACd,cAAc;YACd,0BAA0B;YAC1B,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;SACpD;KACF,CAAC;SAED,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;SACtB,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC;SAC3D,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;SAChE,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;SAC5D,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;QAC5B,gBAAQ,CAAC,kBAAkB,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC;SAED,GAAG,CAAC,OAAO,CAAC,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,kBAAkB,CAAC,CAAC;AACtD,CAAC;AAhED,sBAgEC","sourcesContent":["import chokidar from 'chokidar';\nimport { YargsArgs } from '../../types/yargs';\nimport {\n getOutfilePath,\n loadConfig,\n logError,\n validateDirPath,\n validateFilePath,\n validateOutfileName,\n} from '../../utils';\nimport { bundle } from '../build/bundle';\nimport { snapEval } from '../eval/evalHandler';\nimport { manifestHandler } from '../manifest/manifestHandler';\n\n/**\n * Watch a directory and its subdirectories for changes, and build when files\n * are added or changed.\n *\n * Ignores 'node_modules' and dotfiles.\n * Creates destination directory if it doesn't exist.\n *\n * @param argv - arguments as an object generated by yargs\n * @param argv.src - The source file path\n * @param argv.dist - The output directory path\n * @param argv.'outfileName' - The output file name\n */\nexport async function watch(argv: YargsArgs): Promise<void> {\n const { dist, eval: shouldEval, manifest, outfileName, src } = argv;\n if (outfileName) {\n validateOutfileName(outfileName as string);\n }\n await validateFilePath(src);\n await validateDirPath(dist, true);\n const rootDir =\n src.indexOf('/') === -1 ? '.' : src.substring(0, src.lastIndexOf('/') + 1);\n const outfilePath = getOutfilePath(dist, outfileName as string);\n\n const buildSnap = async (path?: string, logMessage?: string) => {\n if (logMessage !== undefined) {\n console.log(logMessage);\n }\n\n try {\n await bundle(src, outfilePath, argv, loadConfig().bundlerCustomizer);\n\n if (manifest) {\n await manifestHandler(argv);\n }\n\n if (shouldEval) {\n await snapEval({ ...argv, bundle: outfilePath });\n }\n } catch (error) {\n logError(\n `Error ${\n path === undefined\n ? 'during initial build'\n : `while processing \"${path}\"`\n }.`,\n error,\n );\n }\n };\n\n chokidar\n .watch(rootDir, {\n ignoreInitial: true,\n ignored: [\n '**/node_modules/**',\n `**/${dist}/**`,\n `**/test/**`,\n `**/tests/**`,\n `**/*.test.js`,\n `**/*.test.ts`,\n /* istanbul ignore next */\n (str: string) => str !== '.' && str.startsWith('.'),\n ],\n })\n\n .on('ready', buildSnap)\n .on('add', (path) => buildSnap(path, `File added: ${path}`))\n .on('change', (path) => buildSnap(path, `File changed: ${path}`))\n .on('unlink', (path) => console.log(`File removed: ${path}`))\n .on('error', (error: Error) => {\n logError(`Watcher error: ${error.message}`, error);\n })\n\n .add(rootDir);\n\n console.log(`Watching '${rootDir}' for changes...`);\n}\n"]}
package/dist/utils/fs.js CHANGED
@@ -27,7 +27,7 @@ async function isDirectory(pathString, createDir) {
27
27
  }
28
28
  catch (mkdirError) {
29
29
  misc_1.logError(`Directory '${pathString}' could not be created.`, mkdirError);
30
- process.exit(1);
30
+ throw mkdirError;
31
31
  }
32
32
  }
33
33
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":";;;AAAA,2BAAoC;AAEpC,iCAAkC;AAElC;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,UAAkB,EAClB,SAAkB;IAElB,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;KAC5B;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YAC3B,IAAI,CAAC,SAAS,EAAE;gBACd,OAAO,KAAK,CAAC;aACd;YAED,IAAI;gBACF,MAAM,aAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC3B,OAAO,IAAI,CAAC;aACb;YAAC,OAAO,UAAU,EAAE;gBACnB,eAAQ,CAAC,cAAc,UAAU,yBAAyB,EAAE,UAAU,CAAC,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACjB;SACF;QACD,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAvBD,kCAuBC;AAED;;;;;GAKG;AACI,KAAK,UAAU,MAAM,CAAC,UAAkB;IAC7C,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;KACvB;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAPD,wBAOC;AAED;;;;;GAKG;AACI,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;KAC/D;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,aAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3D,CAAC;AAND,oCAMC","sourcesContent":["import { promises as fs } from 'fs';\nimport type { Json } from '@metamask/snap-controllers';\nimport { logError } from './misc';\n\n/**\n * Checks whether the given path string resolves to an existing directory, and\n * optionally creates the directory if it doesn't exist.\n *\n * @param pathString - The path string to check\n * @param createDir - Whether to create the directory if it doesn't exist\n * @returns - Whether the given path is an existing directory\n */\nexport async function isDirectory(\n pathString: string,\n createDir: boolean,\n): Promise<boolean> {\n try {\n const stats = await fs.stat(pathString);\n return stats.isDirectory();\n } catch (error) {\n if (error.code === 'ENOENT') {\n if (!createDir) {\n return false;\n }\n\n try {\n await fs.mkdir(pathString);\n return true;\n } catch (mkdirError) {\n logError(`Directory '${pathString}' could not be created.`, mkdirError);\n process.exit(1);\n }\n }\n return false;\n }\n}\n\n/**\n * Checks whether the given path string resolves to an existing file.\n *\n * @param pathString - The path string to check\n * @returns Whether the given path is an existing file\n */\nexport async function isFile(pathString: string): Promise<boolean> {\n try {\n const stats = await fs.stat(pathString);\n return stats.isFile();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Reads a `.json` file, parses its contents, and returns them.\n *\n * @param pathString - The path to the JSON file.\n * @returns The parsed contents of the JSON file.\n */\nexport async function readJsonFile(pathString: string): Promise<Json> {\n if (!pathString.endsWith('.json')) {\n throw new Error('The specified file must be a \".json\" file.');\n }\n\n return JSON.parse(await fs.readFile(pathString, 'utf8'));\n}\n"]}
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":";;;AAAA,2BAAoC;AAEpC,iCAAkC;AAElC;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,UAAkB,EAClB,SAAkB;IAElB,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;KAC5B;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;YAC3B,IAAI,CAAC,SAAS,EAAE;gBACd,OAAO,KAAK,CAAC;aACd;YAED,IAAI;gBACF,MAAM,aAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC3B,OAAO,IAAI,CAAC;aACb;YAAC,OAAO,UAAU,EAAE;gBACnB,eAAQ,CAAC,cAAc,UAAU,yBAAyB,EAAE,UAAU,CAAC,CAAC;gBACxE,MAAM,UAAU,CAAC;aAClB;SACF;QACD,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAvBD,kCAuBC;AAED;;;;;GAKG;AACI,KAAK,UAAU,MAAM,CAAC,UAAkB;IAC7C,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,aAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;KACvB;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAPD,wBAOC;AAED;;;;;GAKG;AACI,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;KAC/D;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,aAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3D,CAAC;AAND,oCAMC","sourcesContent":["import { promises as fs } from 'fs';\nimport type { Json } from '@metamask/snap-controllers';\nimport { logError } from './misc';\n\n/**\n * Checks whether the given path string resolves to an existing directory, and\n * optionally creates the directory if it doesn't exist.\n *\n * @param pathString - The path string to check\n * @param createDir - Whether to create the directory if it doesn't exist\n * @returns - Whether the given path is an existing directory\n */\nexport async function isDirectory(\n pathString: string,\n createDir: boolean,\n): Promise<boolean> {\n try {\n const stats = await fs.stat(pathString);\n return stats.isDirectory();\n } catch (error) {\n if (error.code === 'ENOENT') {\n if (!createDir) {\n return false;\n }\n\n try {\n await fs.mkdir(pathString);\n return true;\n } catch (mkdirError) {\n logError(`Directory '${pathString}' could not be created.`, mkdirError);\n throw mkdirError;\n }\n }\n return false;\n }\n}\n\n/**\n * Checks whether the given path string resolves to an existing file.\n *\n * @param pathString - The path string to check\n * @returns Whether the given path is an existing file\n */\nexport async function isFile(pathString: string): Promise<boolean> {\n try {\n const stats = await fs.stat(pathString);\n return stats.isFile();\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Reads a `.json` file, parses its contents, and returns them.\n *\n * @param pathString - The path to the JSON file.\n * @returns The parsed contents of the JSON file.\n */\nexport async function readJsonFile(pathString: string): Promise<Json> {\n if (!pathString.endsWith('.json')) {\n throw new Error('The specified file must be a \".json\" file.');\n }\n\n return JSON.parse(await fs.readFile(pathString, 'utf8'));\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { Arguments } from 'yargs';
2
2
  export declare const deepClone: <T>(input: T) => T;
3
3
  export declare const permRequestKeys: string[];
4
- export declare const CONFIG_FILE = "snap.config.json";
4
+ export declare const CONFIG_FILE = "snap.config.js";
5
5
  /**
6
6
  * Sets global variable snaps which tracks user settings:
7
7
  * watch mode activation, verbose errors messages, and whether to suppress warnings.
@@ -9,6 +9,15 @@ export declare const CONFIG_FILE = "snap.config.json";
9
9
  * @param argv - arguments as an object generated by yargs
10
10
  */
11
11
  export declare function setSnapGlobals(argv: Arguments): void;
12
+ /**
13
+ * Attempts to convert a string to a boolean and throws if the value is invalid.
14
+ *
15
+ * @param value - The value to convert to a boolean.
16
+ * @return `true` if the value is the string `"true"`, `false` if it is the
17
+ * string `"false"`, the value if it is already a boolean, or an error
18
+ * otherwise.
19
+ */
20
+ export declare function booleanStringToBoolean(value: unknown): boolean;
12
21
  /**
13
22
  * Sanitizes inputs. Currently normalizes "./" paths to ".".
14
23
  * Yargs handles other path normalization as specified in builders.
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.trimPathString = exports.writeError = exports.logWarning = exports.logError = exports.sanitizeInputs = exports.setSnapGlobals = exports.CONFIG_FILE = exports.permRequestKeys = exports.deepClone = void 0;
6
+ exports.trimPathString = exports.writeError = exports.logWarning = exports.logError = exports.sanitizeInputs = exports.booleanStringToBoolean = exports.setSnapGlobals = exports.CONFIG_FILE = exports.permRequestKeys = exports.deepClone = void 0;
7
7
  const fs_1 = require("fs");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const rfdc_1 = __importDefault(require("rfdc"));
@@ -17,7 +17,7 @@ exports.permRequestKeys = [
17
17
  'caveats',
18
18
  'proof',
19
19
  ];
20
- exports.CONFIG_FILE = 'snap.config.json';
20
+ exports.CONFIG_FILE = 'snap.config.js';
21
21
  // CLI arguments whose values are file paths
22
22
  const pathArguments = new Set([
23
23
  'src',
@@ -43,13 +43,34 @@ function setSnapGlobals(argv) {
43
43
  global.snaps.isWatching = false;
44
44
  }
45
45
  if (Object.prototype.hasOwnProperty.call(argv, 'verboseErrors')) {
46
- global.snaps.verboseErrors = Boolean(argv.verboseErrors);
46
+ global.snaps.verboseErrors = booleanStringToBoolean(argv.verboseErrors);
47
47
  }
48
48
  if (Object.prototype.hasOwnProperty.call(argv, 'suppressWarnings')) {
49
- global.snaps.suppressWarnings = Boolean(argv.suppressWarnings);
49
+ global.snaps.suppressWarnings = booleanStringToBoolean(argv.suppressWarnings);
50
50
  }
51
51
  }
52
52
  exports.setSnapGlobals = setSnapGlobals;
53
+ /**
54
+ * Attempts to convert a string to a boolean and throws if the value is invalid.
55
+ *
56
+ * @param value - The value to convert to a boolean.
57
+ * @return `true` if the value is the string `"true"`, `false` if it is the
58
+ * string `"false"`, the value if it is already a boolean, or an error
59
+ * otherwise.
60
+ */
61
+ function booleanStringToBoolean(value) {
62
+ if (typeof value === 'boolean') {
63
+ return value;
64
+ }
65
+ else if (value === 'true') {
66
+ return true;
67
+ }
68
+ else if (value === 'false') {
69
+ return false;
70
+ }
71
+ throw new Error(`Expected a boolean or the strings "true" or "false". Received: "${value}"`);
72
+ }
73
+ exports.booleanStringToBoolean = booleanStringToBoolean;
53
74
  /**
54
75
  * Sanitizes inputs. Currently normalizes "./" paths to ".".
55
76
  * Yargs handles other path normalization as specified in builders.
@@ -122,6 +143,8 @@ async function writeError(prefix, msg, err, destFilePath) {
122
143
  }
123
144
  // unless the watcher is active, exit
124
145
  if (!global.snaps.isWatching) {
146
+ // TODO(ritave): Remove process exit and change into collapse of functions
147
+ // https://github.com/MetaMask/snaps-skunkworks/issues/81
125
148
  process.exit(1);
126
149
  }
127
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/utils/misc.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as filesystem } from 'fs';\nimport path from 'path';\nimport rfdc from 'rfdc';\nimport { Arguments } from 'yargs';\n\nexport const deepClone = rfdc({ proto: false, circles: false });\n\nexport const permRequestKeys = [\n '@context',\n 'id',\n 'parentCapability',\n 'invoker',\n 'date',\n 'caveats',\n 'proof',\n];\n\nexport const CONFIG_FILE = 'snap.config.json';\n\n// CLI arguments whose values are file paths\nconst pathArguments = new Set([\n 'src',\n 's',\n 'dist',\n 'd',\n 'bundle',\n 'b',\n 'root',\n 'r',\n]);\n\n/**\n * Sets global variable snaps which tracks user settings:\n * watch mode activation, verbose errors messages, and whether to suppress warnings.\n *\n * @param argv - arguments as an object generated by yargs\n */\nexport function setSnapGlobals(argv: Arguments) {\n if (['w', 'watch'].includes(argv._[0] as string)) {\n global.snaps.isWatching = true;\n } else {\n global.snaps.isWatching = false;\n }\n\n if (Object.prototype.hasOwnProperty.call(argv, 'verboseErrors')) {\n global.snaps.verboseErrors = Boolean(argv.verboseErrors);\n }\n\n if (Object.prototype.hasOwnProperty.call(argv, 'suppressWarnings')) {\n global.snaps.suppressWarnings = Boolean(argv.suppressWarnings);\n }\n}\n\n/**\n * Sanitizes inputs. Currently normalizes \"./\" paths to \".\".\n * Yargs handles other path normalization as specified in builders.\n *\n * @param argv - arguments as an object generated by yargs\n */\nexport function sanitizeInputs(argv: Arguments) {\n Object.keys(argv).forEach((key) => {\n if (typeof argv[key] === 'string') {\n // Node's path.normalize() does not do this\n if (argv[key] === './') {\n argv[key] = '.';\n }\n\n if (pathArguments.has(key)) {\n argv[key] = path.normalize(argv[key] as string);\n }\n }\n });\n}\n\n/**\n * Logs an error message to console. Logs original error if it exists and\n * the verboseErrors global is true.\n *\n * @param msg - The error message\n * @param err - The original error\n */\nexport function logError(msg: string, err?: Error): void {\n console.error(msg);\n if (err && global.snaps.verboseErrors) {\n console.error(err);\n }\n}\n\n/**\n * Logs a warning message to console.\n *\n * @param msg - The warning message\n */\nexport function logWarning(msg: string, error?: Error): void {\n if (msg && !global.snaps.suppressWarnings) {\n console.warn(msg);\n if (error && global.snaps.verboseErrors) {\n console.error(error);\n }\n }\n}\n\n/**\n * Logs an error, attempts to unlink the destination file, and exits.\n *\n * @param prefix - The message prefix\n * @param msg - The error message\n * @param err - The original error\n * @param destFilePath - The output file path\n */\nexport async function writeError(\n prefix: string,\n msg: string,\n err: Error,\n destFilePath?: string,\n): Promise<void> {\n let processedPrefix = prefix;\n if (!prefix.endsWith(' ')) {\n processedPrefix += ' ';\n }\n\n logError(processedPrefix + msg, err);\n try {\n if (destFilePath) {\n await filesystem.unlink(destFilePath);\n }\n } catch (unlinkError) {\n logError(`${processedPrefix}Failed to unlink mangled file.`, unlinkError);\n }\n\n // unless the watcher is active, exit\n if (!global.snaps.isWatching) {\n process.exit(1);\n }\n}\n\n/**\n * Trims leading and trailing periods \".\" and forward slashes \"/\" from the\n * given path string.\n *\n * @param pathString - The path string to trim.\n * @returns - The trimmed path string.\n */\nexport function trimPathString(pathString: string): string {\n return pathString.replace(/^[./]+|[./]+$/gu, '');\n}\n"]}
1
+ {"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/utils/misc.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as filesystem } from 'fs';\nimport path from 'path';\nimport rfdc from 'rfdc';\nimport { Arguments } from 'yargs';\n\nexport const deepClone = rfdc({ proto: false, circles: false });\n\nexport const permRequestKeys = [\n '@context',\n 'id',\n 'parentCapability',\n 'invoker',\n 'date',\n 'caveats',\n 'proof',\n];\n\nexport const CONFIG_FILE = 'snap.config.js';\n\n// CLI arguments whose values are file paths\nconst pathArguments = new Set([\n 'src',\n 's',\n 'dist',\n 'd',\n 'bundle',\n 'b',\n 'root',\n 'r',\n]);\n\n/**\n * Sets global variable snaps which tracks user settings:\n * watch mode activation, verbose errors messages, and whether to suppress warnings.\n *\n * @param argv - arguments as an object generated by yargs\n */\nexport function setSnapGlobals(argv: Arguments) {\n if (['w', 'watch'].includes(argv._[0] as string)) {\n global.snaps.isWatching = true;\n } else {\n global.snaps.isWatching = false;\n }\n\n if (Object.prototype.hasOwnProperty.call(argv, 'verboseErrors')) {\n global.snaps.verboseErrors = booleanStringToBoolean(argv.verboseErrors);\n }\n\n if (Object.prototype.hasOwnProperty.call(argv, 'suppressWarnings')) {\n global.snaps.suppressWarnings = booleanStringToBoolean(\n argv.suppressWarnings,\n );\n }\n}\n\n/**\n * Attempts to convert a string to a boolean and throws if the value is invalid.\n *\n * @param value - The value to convert to a boolean.\n * @return `true` if the value is the string `\"true\"`, `false` if it is the\n * string `\"false\"`, the value if it is already a boolean, or an error\n * otherwise.\n */\nexport function booleanStringToBoolean(value: unknown): boolean {\n if (typeof value === 'boolean') {\n return value;\n } else if (value === 'true') {\n return true;\n } else if (value === 'false') {\n return false;\n }\n\n throw new Error(\n `Expected a boolean or the strings \"true\" or \"false\". Received: \"${value}\"`,\n );\n}\n\n/**\n * Sanitizes inputs. Currently normalizes \"./\" paths to \".\".\n * Yargs handles other path normalization as specified in builders.\n *\n * @param argv - arguments as an object generated by yargs\n */\nexport function sanitizeInputs(argv: Arguments) {\n Object.keys(argv).forEach((key) => {\n if (typeof argv[key] === 'string') {\n // Node's path.normalize() does not do this\n if (argv[key] === './') {\n argv[key] = '.';\n }\n\n if (pathArguments.has(key)) {\n argv[key] = path.normalize(argv[key] as string);\n }\n }\n });\n}\n\n/**\n * Logs an error message to console. Logs original error if it exists and\n * the verboseErrors global is true.\n *\n * @param msg - The error message\n * @param err - The original error\n */\nexport function logError(msg: string, err?: Error): void {\n console.error(msg);\n if (err && global.snaps.verboseErrors) {\n console.error(err);\n }\n}\n\n/**\n * Logs a warning message to console.\n *\n * @param msg - The warning message\n */\nexport function logWarning(msg: string, error?: Error): void {\n if (msg && !global.snaps.suppressWarnings) {\n console.warn(msg);\n if (error && global.snaps.verboseErrors) {\n console.error(error);\n }\n }\n}\n\n/**\n * Logs an error, attempts to unlink the destination file, and exits.\n *\n * @param prefix - The message prefix\n * @param msg - The error message\n * @param err - The original error\n * @param destFilePath - The output file path\n */\nexport async function writeError(\n prefix: string,\n msg: string,\n err: Error,\n destFilePath?: string,\n): Promise<void> {\n let processedPrefix = prefix;\n if (!prefix.endsWith(' ')) {\n processedPrefix += ' ';\n }\n\n logError(processedPrefix + msg, err);\n try {\n if (destFilePath) {\n await filesystem.unlink(destFilePath);\n }\n } catch (unlinkError) {\n logError(`${processedPrefix}Failed to unlink mangled file.`, unlinkError);\n }\n\n // unless the watcher is active, exit\n if (!global.snaps.isWatching) {\n // TODO(ritave): Remove process exit and change into collapse of functions\n // https://github.com/MetaMask/snaps-skunkworks/issues/81\n process.exit(1);\n }\n}\n\n/**\n * Trims leading and trailing periods \".\" and forward slashes \"/\" from the\n * given path string.\n *\n * @param pathString - The path string to trim.\n * @returns - The trimmed path string.\n */\nexport function trimPathString(pathString: string): string {\n return pathString.replace(/^[./]+|[./]+$/gu, '');\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { SnapConfig } from "./snap-config";
2
+ export declare function isSnapConfig(obj: any, _argumentName?: string): obj is SnapConfig;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSnapConfig = void 0;
4
+ function isSnapConfig(obj, _argumentName) {
5
+ return ((obj !== null &&
6
+ typeof obj === "object" ||
7
+ typeof obj === "function") &&
8
+ (typeof obj.cliOptions === "undefined" ||
9
+ (obj.cliOptions !== null &&
10
+ typeof obj.cliOptions === "object" ||
11
+ typeof obj.cliOptions === "function") &&
12
+ Object.entries(obj.cliOptions)
13
+ .every(([key, _value]) => (typeof key === "string"))) &&
14
+ (typeof obj.bundlerCustomizer === "undefined" ||
15
+ typeof obj.bundlerCustomizer === "function"));
16
+ }
17
+ exports.isSnapConfig = isSnapConfig;
18
+ //# sourceMappingURL=snap-config.__GENERATED__.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap-config.__GENERATED__.js","sourceRoot":"","sources":["../../src/utils/snap-config.__GENERATED__.ts"],"names":[],"mappings":";;;AAMA,SAAgB,YAAY,CAAC,GAAQ,EAAE,aAAsB;IACzD,OAAO,CACH,CAAC,GAAG,KAAK,IAAI;QACT,OAAO,GAAG,KAAK,QAAQ;QACvB,OAAO,GAAG,KAAK,UAAU,CAAC;QAC9B,CAAC,OAAO,GAAG,CAAC,UAAU,KAAK,WAAW;YAClC,CAAC,GAAG,CAAC,UAAU,KAAK,IAAI;gBACpB,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;gBAClC,OAAO,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC;gBACzC,MAAM,CAAC,OAAO,CAAM,GAAG,CAAC,UAAU,CAAC;qBAC9B,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC;QAC7D,CAAC,OAAO,GAAG,CAAC,iBAAiB,KAAK,WAAW;YACzC,OAAO,GAAG,CAAC,iBAAiB,KAAK,UAAU,CAAC,CACnD,CAAA;AACL,CAAC;AAdD,oCAcC","sourcesContent":["/*\n * Generated type guards for \"snap-config.ts\".\n * WARNING: Do not manually change this file.\n */\nimport { SnapConfig } from \"./snap-config\";\n\nexport function isSnapConfig(obj: any, _argumentName?: string): obj is SnapConfig {\n return (\n (obj !== null &&\n typeof obj === \"object\" ||\n typeof obj === \"function\") &&\n (typeof obj.cliOptions === \"undefined\" ||\n (obj.cliOptions !== null &&\n typeof obj.cliOptions === \"object\" ||\n typeof obj.cliOptions === \"function\") &&\n Object.entries<any>(obj.cliOptions)\n .every(([key, _value]) => (typeof key === \"string\"))) &&\n (typeof obj.bundlerCustomizer === \"undefined\" ||\n typeof obj.bundlerCustomizer === \"function\")\n )\n}\n"]}
@@ -1,5 +1,12 @@
1
+ import type browserify from 'browserify';
1
2
  import { Arguments } from 'yargs';
2
3
  import yargs from 'yargs/yargs';
4
+ /** @see {isSnapConfig} ts-auto-guard:type-guard */
5
+ export declare type SnapConfig = {
6
+ cliOptions?: Record<string, unknown>;
7
+ bundlerCustomizer?: (bundler: browserify.BrowserifyObject) => void;
8
+ };
9
+ export declare function loadConfig(cached?: boolean): SnapConfig;
3
10
  /**
4
11
  * Attempts to read configuration options for package.json and the config file,
5
12
  * and apply them to argv if they weren't already set.
@@ -7,4 +14,4 @@ import yargs from 'yargs/yargs';
7
14
  * Arguments are only set per the snap-cli config file if they were not specified
8
15
  * on the command line.
9
16
  */
10
- export declare function applyConfig(processArgv: string[], yargsArgv: Arguments, yargsInstance: typeof yargs): void;
17
+ export declare function applyConfig(snapConfig: SnapConfig, processArgv: string[], yargsArgv: Arguments, yargsInstance: typeof yargs): void;
@@ -3,12 +3,38 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.applyConfig = void 0;
7
- const fs_1 = require("fs");
6
+ exports.applyConfig = exports.loadConfig = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
8
  const yargs_parser_1 = __importDefault(require("yargs-parser"));
9
9
  const builders_1 = __importDefault(require("../builders"));
10
10
  const misc_1 = require("./misc");
11
- const _1 = require(".");
11
+ const snap_config___GENERATED__1 = require("./snap-config.__GENERATED__");
12
+ let snapConfigCache;
13
+ function loadConfig(cached = true) {
14
+ if (snapConfigCache !== undefined && cached === true) {
15
+ return snapConfigCache;
16
+ }
17
+ let config;
18
+ try {
19
+ // eslint-disable-next-line node/global-require, import/no-dynamic-require, @typescript-eslint/no-require-imports
20
+ config = require(path_1.default.resolve(process.cwd(), misc_1.CONFIG_FILE));
21
+ }
22
+ catch (err) {
23
+ if (err.code === 'MODULE_NOT_FOUND') {
24
+ snapConfigCache = {};
25
+ return snapConfigCache;
26
+ }
27
+ misc_1.logError(`Error during parsing of ${misc_1.CONFIG_FILE}`, err);
28
+ return process.exit(1);
29
+ }
30
+ if (!snap_config___GENERATED__1.isSnapConfig(config)) {
31
+ misc_1.logError(`Can't validate ${misc_1.CONFIG_FILE}. Ensure it's a proper javascript file and abides with the structure of a snap configuration file`);
32
+ return process.exit(1);
33
+ }
34
+ snapConfigCache = config;
35
+ return config;
36
+ }
37
+ exports.loadConfig = loadConfig;
12
38
  // Note that the below function is necessary because yarg's .config() function
13
39
  // leaves much to be desired.
14
40
  //
@@ -21,7 +47,7 @@ const _1 = require(".");
21
47
  * Arguments are only set per the snap-cli config file if they were not specified
22
48
  * on the command line.
23
49
  */
24
- function applyConfig(processArgv, yargsArgv, yargsInstance) {
50
+ function applyConfig(snapConfig, processArgv, yargsArgv, yargsInstance) {
25
51
  // Instances of yargs has a number of undocumented functions, including
26
52
  // getOptions. This function returns an object with properties "key" and
27
53
  // "alias", which specify the options associated with the current command and
@@ -43,36 +69,17 @@ function applyConfig(processArgv, yargsArgv, yargsInstance) {
43
69
  return (commandOptions.has(key) &&
44
70
  !Object.prototype.hasOwnProperty.call(parsedProcessArgv, key));
45
71
  };
46
- // Now, we attempt to read and apply config from the config file, if any.
47
- let cfg = {};
48
- try {
49
- cfg = JSON.parse(fs_1.readFileSync(_1.CONFIG_FILE, 'utf8'));
50
- }
51
- catch (err) {
52
- if (err.code === 'ENOENT') {
53
- // If there's no config file, we're done here.
54
- return;
55
- }
56
- misc_1.logError(`Error: "${_1.CONFIG_FILE}" exists but could not be parsed. Ensure your config file is valid JSON and try again.`, err);
57
- process.exit(1);
58
- }
59
- if (cfg && typeof cfg === 'object' && !Array.isArray(cfg)) {
60
- for (const key of Object.keys(cfg)) {
61
- if (Object.hasOwnProperty.call(builders_1.default, key)) {
62
- if (shouldSetArg(key)) {
63
- yargsArgv[key] = cfg[key];
64
- }
65
- }
66
- else {
67
- misc_1.logError(`Error: Encountered unrecognized config property "${key}" in config file "${_1.CONFIG_FILE}". Remove the property and try again.`);
68
- process.exit(1);
72
+ const cfg = snapConfig.cliOptions || {};
73
+ for (const key of Object.keys(cfg)) {
74
+ if (Object.hasOwnProperty.call(builders_1.default, key)) {
75
+ if (shouldSetArg(key)) {
76
+ yargsArgv[key] = cfg[key];
69
77
  }
70
78
  }
71
- }
72
- else {
73
- const cfgType = cfg === null ? 'null' : typeof cfg;
74
- misc_1.logError(`Error: The config file must consist of a top-level JSON object. Received "${cfgType}" from "${_1.CONFIG_FILE}". Fix your config file and try again.`);
75
- process.exit(1);
79
+ else {
80
+ misc_1.logError(`Error: Encountered unrecognized config property "options.${key}" in config file "${misc_1.CONFIG_FILE}". Remove the property and try again.`);
81
+ process.exit(1);
82
+ }
76
83
  }
77
84
  }
78
85
  exports.applyConfig = applyConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"snap-config.js","sourceRoot":"","sources":["../../src/utils/snap-config.ts"],"names":[],"mappings":";;;;;;AAAA,2BAAkC;AAGlC,gEAAsC;AACtC,2DAAmC;AACnC,iCAAkC;AAClC,wBAAgC;AAEhC,8EAA8E;AAC9E,6BAA6B;AAC7B,EAAE;AACF,wEAAwE;AACxE,4DAA4D;AAE5D;;;;;;GAMG;AACH,SAAgB,WAAW,CACzB,WAAqB,EACrB,SAAoB,EACpB,aAA2B;IAE3B,uEAAuE;IACvE,wEAAwE;IACxE,6EAA6E;IAC7E,+BAA+B;IAC/B,EAAE;IACF,8EAA8E;IAC9E,2EAA2E;IAC3E,oBAAoB;IACpB,EAAE;IACF,6EAA6E;IAC7E,qBAAqB;IACrB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GACpC,aACD,CAAC,UAAU,EAGX,CAAC;IAEF,MAAM,iBAAiB,GAAG,sBAAU,CAAC,WAAW,EAAE;QAChD,KAAK,EAAE,OAAO;KACf,CAA4B,CAAC;IAC9B,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,mCAAmC;IAE/D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,CAAC,GAAW,EAAW,EAAE;QAC5C,OAAO,CACL,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC;YACvB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAC9D,CAAC;IACJ,CAAC,CAAC;IAEF,yEAAyE;IACzE,IAAI,GAAG,GAA4B,EAAE,CAAC;IACtC,IAAI;QACF,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAY,CAAC,cAAW,EAAE,MAAM,CAAC,CAAC,CAAC;KACrD;IAAC,OAAO,GAAG,EAAE;QACZ,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE;YACzB,8CAA8C;YAC9C,OAAO;SACR;QAED,eAAQ,CACN,WAAW,cAAW,wFAAwF,EAC9G,GAAG,CACJ,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;IAED,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACzD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAClC,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAQ,EAAE,GAAG,CAAC,EAAE;gBAC7C,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE;oBACrB,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;iBAC3B;aACF;iBAAM;gBACL,eAAQ,CACN,oDAAoD,GAAG,qBAAqB,cAAW,uCAAuC,CAC/H,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACjB;SACF;KACF;SAAM;QACL,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC;QAEnD,eAAQ,CACN,6EAA6E,OAAO,WAAW,cAAW,wCAAwC,CACnJ,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjB;AACH,CAAC;AA3ED,kCA2EC","sourcesContent":["import { readFileSync } from 'fs';\nimport { Arguments } from 'yargs';\nimport yargs from 'yargs/yargs';\nimport yargsParse from 'yargs-parser';\nimport builders from '../builders';\nimport { logError } from './misc';\nimport { CONFIG_FILE } from '.';\n\n// Note that the below function is necessary because yarg's .config() function\n// leaves much to be desired.\n//\n// In particular, it will set all properties included in the config file\n// regardless of the command, which fails during validation.\n\n/**\n * Attempts to read configuration options for package.json and the config file,\n * and apply them to argv if they weren't already set.\n *\n * Arguments are only set per the snap-cli config file if they were not specified\n * on the command line.\n */\nexport function applyConfig(\n processArgv: string[],\n yargsArgv: Arguments,\n yargsInstance: typeof yargs,\n): void {\n // Instances of yargs has a number of undocumented functions, including\n // getOptions. This function returns an object with properties \"key\" and\n // \"alias\", which specify the options associated with the current command and\n // their aliases, respectively.\n //\n // We leverage this to ensure that the config is only applied to args that are\n // valid for the current command, and that weren't specified by the user on\n // the command line.\n //\n // If we set args that aren't valid for the current command, yargs will error\n // during validation.\n const { alias: aliases, key: options } = (\n yargsInstance as any\n ).getOptions() as {\n alias: Record<string, string[]>;\n key: Record<string, unknown>;\n };\n\n const parsedProcessArgv = yargsParse(processArgv, {\n alias: aliases,\n }) as Record<string, unknown>;\n delete parsedProcessArgv._; // irrelevant yargs parser artifact\n\n const commandOptions = new Set(Object.keys(options));\n\n const shouldSetArg = (key: string): boolean => {\n return (\n commandOptions.has(key) &&\n !Object.prototype.hasOwnProperty.call(parsedProcessArgv, key)\n );\n };\n\n // Now, we attempt to read and apply config from the config file, if any.\n let cfg: Record<string, unknown> = {};\n try {\n cfg = JSON.parse(readFileSync(CONFIG_FILE, 'utf8'));\n } catch (err) {\n if (err.code === 'ENOENT') {\n // If there's no config file, we're done here.\n return;\n }\n\n logError(\n `Error: \"${CONFIG_FILE}\" exists but could not be parsed. Ensure your config file is valid JSON and try again.`,\n err,\n );\n process.exit(1);\n }\n\n if (cfg && typeof cfg === 'object' && !Array.isArray(cfg)) {\n for (const key of Object.keys(cfg)) {\n if (Object.hasOwnProperty.call(builders, key)) {\n if (shouldSetArg(key)) {\n yargsArgv[key] = cfg[key];\n }\n } else {\n logError(\n `Error: Encountered unrecognized config property \"${key}\" in config file \"${CONFIG_FILE}\". Remove the property and try again.`,\n );\n process.exit(1);\n }\n }\n } else {\n const cfgType = cfg === null ? 'null' : typeof cfg;\n\n logError(\n `Error: The config file must consist of a top-level JSON object. Received \"${cfgType}\" from \"${CONFIG_FILE}\". Fix your config file and try again.`,\n );\n process.exit(1);\n }\n}\n"]}
1
+ {"version":3,"file":"snap-config.js","sourceRoot":"","sources":["../../src/utils/snap-config.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAGxB,gEAAsC;AAEtC,2DAAmC;AACnC,iCAA+C;AAC/C,0EAA2D;AAQ3D,IAAI,eAAuC,CAAC;AAE5C,SAAgB,UAAU,CAAC,MAAM,GAAG,IAAI;IACtC,IAAI,eAAe,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE;QACpD,OAAO,eAAe,CAAC;KACxB;IAED,IAAI,MAAW,CAAC;IAChB,IAAI;QACF,iHAAiH;QACjH,MAAM,GAAG,OAAO,CAAC,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAW,CAAC,CAAC,CAAC;KAC5D;IAAC,OAAO,GAAQ,EAAE;QACjB,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE;YACnC,eAAe,GAAG,EAAE,CAAC;YACrB,OAAO,eAAe,CAAC;SACxB;QACD,eAAQ,CAAC,2BAA2B,kBAAW,EAAE,EAAE,GAAG,CAAC,CAAC;QACxD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACxB;IAED,IAAI,CAAC,uCAAY,CAAC,MAAM,CAAC,EAAE;QACzB,eAAQ,CACN,kBAAkB,kBAAW,mGAAmG,CACjI,CAAC;QACF,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACxB;IACD,eAAe,GAAG,MAAM,CAAC;IACzB,OAAO,MAAM,CAAC;AAChB,CAAC;AA1BD,gCA0BC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,EAAE;AACF,wEAAwE;AACxE,4DAA4D;AAE5D;;;;;;GAMG;AACH,SAAgB,WAAW,CACzB,UAAsB,EACtB,WAAqB,EACrB,SAAoB,EACpB,aAA2B;IAE3B,uEAAuE;IACvE,wEAAwE;IACxE,6EAA6E;IAC7E,+BAA+B;IAC/B,EAAE;IACF,8EAA8E;IAC9E,2EAA2E;IAC3E,oBAAoB;IACpB,EAAE;IACF,6EAA6E;IAC7E,qBAAqB;IACrB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GACpC,aACD,CAAC,UAAU,EAGX,CAAC;IAEF,MAAM,iBAAiB,GAAG,sBAAU,CAAC,WAAW,EAAE;QAChD,KAAK,EAAE,OAAO;KACf,CAA4B,CAAC;IAC9B,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC,mCAAmC;IAE/D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,CAAC,GAAW,EAAW,EAAE;QAC5C,OAAO,CACL,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC;YACvB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAC9D,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,GAAG,GAA4B,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAQ,EAAE,GAAG,CAAC,EAAE;YAC7C,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE;gBACrB,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;aAC3B;SACF;aAAM;YACL,eAAQ,CACN,4DAA4D,GAAG,qBAAqB,kBAAW,uCAAuC,CACvI,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjB;KACF;AACH,CAAC;AAnDD,kCAmDC","sourcesContent":["import path from 'path';\nimport type browserify from 'browserify';\nimport { Arguments } from 'yargs';\nimport yargsParse from 'yargs-parser';\nimport yargs from 'yargs/yargs';\nimport builders from '../builders';\nimport { CONFIG_FILE, logError } from './misc';\nimport { isSnapConfig } from './snap-config.__GENERATED__';\n\n/** @see {isSnapConfig} ts-auto-guard:type-guard */\nexport type SnapConfig = {\n cliOptions?: Record<string, unknown>;\n bundlerCustomizer?: (bundler: browserify.BrowserifyObject) => void;\n};\n\nlet snapConfigCache: SnapConfig | undefined;\n\nexport function loadConfig(cached = true): SnapConfig {\n if (snapConfigCache !== undefined && cached === true) {\n return snapConfigCache;\n }\n\n let config: any;\n try {\n // eslint-disable-next-line node/global-require, import/no-dynamic-require, @typescript-eslint/no-require-imports\n config = require(path.resolve(process.cwd(), CONFIG_FILE));\n } catch (err: any) {\n if (err.code === 'MODULE_NOT_FOUND') {\n snapConfigCache = {};\n return snapConfigCache;\n }\n logError(`Error during parsing of ${CONFIG_FILE}`, err);\n return process.exit(1);\n }\n\n if (!isSnapConfig(config)) {\n logError(\n `Can't validate ${CONFIG_FILE}. Ensure it's a proper javascript file and abides with the structure of a snap configuration file`,\n );\n return process.exit(1);\n }\n snapConfigCache = config;\n return config;\n}\n\n// Note that the below function is necessary because yarg's .config() function\n// leaves much to be desired.\n//\n// In particular, it will set all properties included in the config file\n// regardless of the command, which fails during validation.\n\n/**\n * Attempts to read configuration options for package.json and the config file,\n * and apply them to argv if they weren't already set.\n *\n * Arguments are only set per the snap-cli config file if they were not specified\n * on the command line.\n */\nexport function applyConfig(\n snapConfig: SnapConfig,\n processArgv: string[],\n yargsArgv: Arguments,\n yargsInstance: typeof yargs,\n): void {\n // Instances of yargs has a number of undocumented functions, including\n // getOptions. This function returns an object with properties \"key\" and\n // \"alias\", which specify the options associated with the current command and\n // their aliases, respectively.\n //\n // We leverage this to ensure that the config is only applied to args that are\n // valid for the current command, and that weren't specified by the user on\n // the command line.\n //\n // If we set args that aren't valid for the current command, yargs will error\n // during validation.\n const { alias: aliases, key: options } = (\n yargsInstance as any\n ).getOptions() as {\n alias: Record<string, string[]>;\n key: Record<string, unknown>;\n };\n\n const parsedProcessArgv = yargsParse(processArgv, {\n alias: aliases,\n }) as Record<string, unknown>;\n delete parsedProcessArgv._; // irrelevant yargs parser artifact\n\n const commandOptions = new Set(Object.keys(options));\n\n const shouldSetArg = (key: string): boolean => {\n return (\n commandOptions.has(key) &&\n !Object.prototype.hasOwnProperty.call(parsedProcessArgv, key)\n );\n };\n\n const cfg: Record<string, unknown> = snapConfig.cliOptions || {};\n for (const key of Object.keys(cfg)) {\n if (Object.hasOwnProperty.call(builders, key)) {\n if (shouldSetArg(key)) {\n yargsArgv[key] = cfg[key];\n }\n } else {\n logError(\n `Error: Encountered unrecognized config property \"options.${key}\" in config file \"${CONFIG_FILE}\". Remove the property and try again.`,\n );\n process.exit(1);\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-cli",
3
- "version": "0.7.0",
3
+ "version": "0.10.0",
4
4
  "description": "A CLI for developing MetaMask Snaps.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,14 +17,16 @@
17
17
  "setup": "yarn install && yarn allow-scripts",
18
18
  "shasum": "node ./scripts/computeSnapShasum.js",
19
19
  "build:init-template": "node ./scripts/createInitTemplate.js && yarn prettier --check src/cmds/init/init-template.json",
20
- "build:typescript": "tsc --project ./tsconfig.local.json",
20
+ "build:guards": "ts-auto-guard --guard-file-name=__GENERATED__ ./src/utils/snap-config.ts",
21
+ "build:tsc": "tsc --project ./tsconfig.local.json",
21
22
  "build:chmod": "chmod +x ./dist/main.js",
22
- "build": "yarn build:init-template && yarn build:typescript && yarn build:chmod",
23
- "build:pre-tsc": "echo 'N/A'",
24
- "build:post-tsc": "yarn build:init-template && yarn build:chmod",
23
+ "build:readme": "node ./scripts/updateReadme.js",
24
+ "build": "yarn build:pre-tsc && yarn build:tsc && yarn build:post-tsc",
25
+ "build:pre-tsc": "yarn build:init-template && yarn build:guards",
26
+ "build:post-tsc": "yarn build:chmod && yarn build:readme",
25
27
  "build:clean": "yarn clean && yarn build",
26
28
  "build:watch": "tsc-watch --onSuccess 'yarn build:chmod'",
27
- "clean": "rimraf dist/*",
29
+ "clean": "rimraf dist/* src/**/*__GENERATED__*",
28
30
  "test": "yarn build:init-template && jest",
29
31
  "test:watch": "yarn test --watch",
30
32
  "test:ci": "yarn test",
@@ -43,7 +45,7 @@
43
45
  "@babel/plugin-proposal-optional-chaining": "^7.16.7",
44
46
  "@babel/plugin-transform-runtime": "^7.16.7",
45
47
  "@babel/preset-env": "^7.16.7",
46
- "@metamask/snap-controllers": "^0.7.0",
48
+ "@metamask/snap-controllers": "^0.10.0",
47
49
  "@nodefactory/strip-comments": "^1.0.2",
48
50
  "babelify": "^10.0.0",
49
51
  "browserify": "^17.0.0",
@@ -84,10 +86,12 @@
84
86
  "eslint-plugin-jest": "^24.4.0",
85
87
  "eslint-plugin-node": "^11.1.0",
86
88
  "eslint-plugin-prettier": "^3.4.0",
89
+ "execa": "^5.1.1",
87
90
  "jest": "^26.6.3",
88
91
  "patch-package": "^6.4.7",
89
92
  "prettier": "^2.3.2",
90
93
  "rimraf": "^3.0.2",
94
+ "ts-auto-guard": "^2.3.0",
91
95
  "ts-jest": "^26.5.6",
92
96
  "ts-node": "^9.1.1",
93
97
  "tsc-watch": "^4.5.0",
@@ -1,42 +0,0 @@
1
- /// <reference types="node" />
2
- import { Option, YargsArgs } from '../../types/yargs';
3
- /**
4
- * Opens a stream to write the destination file path.
5
- *
6
- * @param dest - The output file path
7
- * @returns - The stream
8
- */
9
- export declare function createBundleStream(dest: string): NodeJS.WritableStream;
10
- declare type CloseStreamArgs = {
11
- bundleError: Error;
12
- bundleBuffer: Buffer;
13
- bundleStream: NodeJS.WritableStream;
14
- src: string;
15
- dest: string;
16
- resolve: (value: boolean) => void;
17
- argv: YargsArgs;
18
- };
19
- /**
20
- * Postprocesses the bundle string and closes the write stream.
21
- *
22
- * @param stream - The write stream
23
- * @param bundleString - The bundle string
24
- * @param options - post process options
25
- * @param options.stripComments
26
- */
27
- export declare function closeBundleStream({ bundleError, bundleBuffer, bundleStream, src, dest, resolve, argv, }: CloseStreamArgs): Promise<void>;
28
- /**
29
- * Postprocesses a JavaScript bundle string such that it can be evaluated in SES.
30
- * Currently:
31
- * - converts certain dot notation to string notation (for indexing)
32
- * - makes all direct calls to eval indirect
33
- * - wraps original bundle in anonymous function
34
- * - handles certain Babel-related edge cases
35
- *
36
- * @param bundleString - The bundle string
37
- * @param options - post process options
38
- * @param options.stripComments
39
- * @returns - The postprocessed bundle string
40
- */
41
- export declare function postProcess(bundleString: string | null, options?: Partial<Option>): string | null;
42
- export {};