From 9f6ee2f7c58f0432822e45948278cd28f7adc2f9 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 09:51:11 +0100 Subject: [PATCH 1/6] Fix minimum version for CLIs --- .../src/cmds/init/initHandler.test.ts | 2 +- .../create-snap/src/cmds/init/initHandler.ts | 2 +- packages/snaps-cli/src/cli.test.ts | 27 +++---------------- packages/snaps-cli/src/cli.ts | 15 +++-------- 4 files changed, 9 insertions(+), 37 deletions(-) mode change 100755 => 100644 packages/snaps-cli/src/cli.ts diff --git a/packages/create-snap/src/cmds/init/initHandler.test.ts b/packages/create-snap/src/cmds/init/initHandler.test.ts index 9b6c8f3b47..f72f8a8471 100644 --- a/packages/create-snap/src/cmds/init/initHandler.test.ts +++ b/packages/create-snap/src/cmds/init/initHandler.test.ts @@ -212,7 +212,7 @@ describe('initialize', () => { }; await expect(initHandler({ ...getMockArgv() })).rejects.toThrow( - `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node >=18.6.0.`, + `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node >=18.16.0.`, ); }); diff --git a/packages/create-snap/src/cmds/init/initHandler.ts b/packages/create-snap/src/cmds/init/initHandler.ts index d1ff620d47..f30e4992b1 100644 --- a/packages/create-snap/src/cmds/init/initHandler.ts +++ b/packages/create-snap/src/cmds/init/initHandler.ts @@ -22,7 +22,7 @@ import { yarnInstall, } from './initUtils'; -const SATISFIED_VERSION = '>=18.6.0' as SemVerRange; +const SATISFIED_VERSION = '>=18.16.0' as SemVerRange; /** * Creates a new snap package, based on one of the provided templates. This diff --git a/packages/snaps-cli/src/cli.test.ts b/packages/snaps-cli/src/cli.test.ts index 01feb9602c..b564694f6b 100644 --- a/packages/snaps-cli/src/cli.test.ts +++ b/packages/snaps-cli/src/cli.test.ts @@ -28,7 +28,7 @@ const getMockArgv = (...args: string[]) => { const HELP_TEXT_REGEX = /^\s*Usage: .+ \[options\]/u; describe('checkNodeVersion', () => { - it.each(['16.17.0', '16.18.0', '18.6.0', '18.7.0', '20.0.0'])( + it.each(['18.16.0', '18.17.0', '20.0.0'])( 'does not exit if the Node version is %s', (version) => { const spy = jest.spyOn(process, 'exit').mockImplementation(); @@ -38,8 +38,8 @@ describe('checkNodeVersion', () => { }, ); - it.each(['14.0.0', '16.0.0', '16.16.1'])( - 'logs a message and exists if the Node version is %s', + it.each(['14.0.0', '16.0.0', '16.16.1', '18.0.0', '18.5.0'])( + 'logs a message and exits if the Node version is %s', (version) => { const spy = jest.spyOn(process, 'exit').mockImplementation(); const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); @@ -51,26 +51,7 @@ describe('checkNodeVersion', () => { expect(consoleErrorSpy).toHaveBeenCalledTimes(1); expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining( - `Node version ${version} is not supported. Please use Node 16.17.0 or later.`, - ), - ); - }, - ); - - it.each(['18.0.0', '18.5.0'])( - 'logs a message and exists if the Node version is %s', - (version) => { - const spy = jest.spyOn(process, 'exit').mockImplementation(); - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); - - checkNodeVersion(version); - - expect(spy).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledWith(1); - expect(consoleErrorSpy).toHaveBeenCalledTimes(1); - expect(consoleErrorSpy).toHaveBeenCalledWith( - expect.stringContaining( - `Node version ${version} is not supported. Please use Node 18.6.0 or later.`, + `Node version ${version} is not supported. Please use Node 18.16.0 or later.`, ), ); }, diff --git a/packages/snaps-cli/src/cli.ts b/packages/snaps-cli/src/cli.ts old mode 100755 new mode 100644 index 0a8b6567f8..b2c7e9b8a8 --- a/packages/snaps-cli/src/cli.ts +++ b/packages/snaps-cli/src/cli.ts @@ -6,8 +6,7 @@ import builders from './builders'; import { getConfigByArgv } from './config'; import { error, getYargsErrorMessage, sanitizeInputs } from './utils'; -const MINIMUM_NODE_16_VERSION = '16.17.0'; -const MINIMUM_NODE_18_VERSION = '18.6.0'; +const MINIMUM_NODE_18_VERSION = '18.16.0'; /** * Check the Node version. If the Node version is less than the minimum required @@ -19,17 +18,9 @@ export function checkNodeVersion( nodeVersion: string = process.version.slice(1), ) { const majorVersion = semver.major(nodeVersion); - const message = `Node version ${nodeVersion} is not supported. Please use Node ${MINIMUM_NODE_16_VERSION} or later.`; + const message = `Node version ${nodeVersion} is not supported. Please use Node ${MINIMUM_NODE_18_VERSION} or later.`; - if (majorVersion < 16) { - error(message); - // eslint-disable-next-line n/no-process-exit - process.exit(1); - } - - // Node 16 and 18 have a different minimum version requirement, so we need to - // check for both. - if (majorVersion === 16 && semver.lt(nodeVersion, MINIMUM_NODE_16_VERSION)) { + if (majorVersion < 18) { error(message); // eslint-disable-next-line n/no-process-exit process.exit(1); From 230bf870b51cc40eb3b2aebfa34d77f4753ee36f Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 10:45:17 +0100 Subject: [PATCH 2/6] Simplify --- packages/create-snap/package.json | 2 +- .../src/cmds/init/initHandler.test.ts | 24 +++++++++---------- .../create-snap/src/cmds/init/initHandler.ts | 17 +++++++------ packages/snaps-cli/src/cli.ts | 18 +++++--------- yarn.lock | 4 ++-- 5 files changed, 29 insertions(+), 36 deletions(-) diff --git a/packages/create-snap/package.json b/packages/create-snap/package.json index ff6d7f41d9..3ccb9a5df1 100644 --- a/packages/create-snap/package.json +++ b/packages/create-snap/package.json @@ -47,7 +47,7 @@ }, "dependencies": { "@metamask/snaps-utils": "workspace:^", - "@metamask/utils": "^8.3.0", + "semver": "^7.6.0", "yargs": "^17.7.1" }, "devDependencies": { diff --git a/packages/create-snap/src/cmds/init/initHandler.test.ts b/packages/create-snap/src/cmds/init/initHandler.test.ts index f72f8a8471..27262933f0 100644 --- a/packages/create-snap/src/cmds/init/initHandler.test.ts +++ b/packages/create-snap/src/cmds/init/initHandler.test.ts @@ -4,9 +4,9 @@ import { getMockSnapFiles, getMockSnapFilesWithUpdatedChecksum, } from '@metamask/snaps-utils/test-utils'; -import * as utils from '@metamask/utils'; import { promises as fs } from 'fs'; import pathUtils from 'path'; +import semver from 'semver'; import { resetFileSystem } from '../../test-utils'; import type { YargsArgs } from '../../types/yargs'; @@ -15,9 +15,9 @@ import * as initUtils from './initUtils'; jest.mock('fs'); -jest.mock('@metamask/utils', () => ({ - ...jest.requireActual('@metamask/utils'), - satisfiesVersionRange: jest.fn(), +jest.mock('semver', () => ({ + ...jest.requireActual('semver'), + satisfies: jest.fn(), })); jest.mock('@metamask/snaps-utils', () => ({ @@ -47,7 +47,7 @@ describe('initialize', () => { }); it('successfully initializes a Snap project in the current working directory', async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); jest.spyOn(initUtils, 'cloneTemplate').mockImplementation(); @@ -82,7 +82,7 @@ describe('initialize', () => { }); it('successfully initializes a Snap project in a given directory', async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); @@ -123,7 +123,7 @@ describe('initialize', () => { }); it("defaults to 'src/index.js' if there is no main entry in package.json", async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); jest.spyOn(initUtils, 'cloneTemplate').mockImplementation(); @@ -163,7 +163,7 @@ describe('initialize', () => { }); it("doesn't init if it's already in a git repo", async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); jest.spyOn(initUtils, 'cloneTemplate').mockImplementation(); @@ -212,12 +212,12 @@ describe('initialize', () => { }; await expect(initHandler({ ...getMockArgv() })).rejects.toThrow( - `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node >=18.16.0.`, + `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node 18.16.0 or later.`, ); }); it('fails if git is not installed', async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); const isGitInstalledMock = jest .spyOn(initUtils, 'isGitInstalled') @@ -231,7 +231,7 @@ describe('initialize', () => { }); it('fails if it can\t clone template and clean files', async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); @@ -249,7 +249,7 @@ describe('initialize', () => { }); it('fails if an error is thrown', async () => { - jest.spyOn(utils, 'satisfiesVersionRange').mockImplementation(() => true); + jest.spyOn(semver, 'satisfies').mockImplementation(() => true); jest.spyOn(initUtils, 'isGitInstalled').mockImplementation(() => true); diff --git a/packages/create-snap/src/cmds/init/initHandler.ts b/packages/create-snap/src/cmds/init/initHandler.ts index f30e4992b1..4afe7293d6 100644 --- a/packages/create-snap/src/cmds/init/initHandler.ts +++ b/packages/create-snap/src/cmds/init/initHandler.ts @@ -5,11 +5,12 @@ import { createSnapManifest, logInfo, } from '@metamask/snaps-utils/node'; -import type { SemVerRange, SemVerVersion } from '@metamask/utils'; -import { satisfiesVersionRange } from '@metamask/utils'; import { promises as fs } from 'fs'; import pathUtils from 'path'; +import type { SemVer } from 'semver'; +import semver from 'semver'; +import cliPackageJson from '../../../package.json'; import type { YargsArgs } from '../../types/yargs'; import { buildSnap, @@ -22,8 +23,6 @@ import { yarnInstall, } from './initUtils'; -const SATISFIED_VERSION = '>=18.16.0' as SemVerRange; - /** * Creates a new snap package, based on one of the provided templates. This * creates all the necessary files, like `package.json`, `snap.config.js`, etc. @@ -37,14 +36,14 @@ const SATISFIED_VERSION = '>=18.16.0' as SemVerRange; export async function initHandler(argv: YargsArgs) { const { directory } = argv; - const isVersionSupported = satisfiesVersionRange( - process.version as SemVerVersion, - SATISFIED_VERSION, - ); + const versionRange = cliPackageJson.engines.node; + const minimumVersion = (semver.minVersion(versionRange) as SemVer).format(); + + const isVersionSupported = semver.satisfies(process.version, versionRange); if (!isVersionSupported) { throw new Error( - `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node ${SATISFIED_VERSION}.`, + `Init Error: You are using an outdated version of Node (${process.version}). Please update to Node ${minimumVersion} or later.`, ); } diff --git a/packages/snaps-cli/src/cli.ts b/packages/snaps-cli/src/cli.ts index b2c7e9b8a8..228b459010 100644 --- a/packages/snaps-cli/src/cli.ts +++ b/packages/snaps-cli/src/cli.ts @@ -1,13 +1,13 @@ +import type { SemVer } from 'semver'; import semver from 'semver'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; +import packageJson from '../package.json'; import builders from './builders'; import { getConfigByArgv } from './config'; import { error, getYargsErrorMessage, sanitizeInputs } from './utils'; -const MINIMUM_NODE_18_VERSION = '18.16.0'; - /** * Check the Node version. If the Node version is less than the minimum required * version, this logs an error and exits the process. @@ -17,18 +17,12 @@ const MINIMUM_NODE_18_VERSION = '18.16.0'; export function checkNodeVersion( nodeVersion: string = process.version.slice(1), ) { - const majorVersion = semver.major(nodeVersion); - const message = `Node version ${nodeVersion} is not supported. Please use Node ${MINIMUM_NODE_18_VERSION} or later.`; - - if (majorVersion < 18) { - error(message); - // eslint-disable-next-line n/no-process-exit - process.exit(1); - } + const versionRange = packageJson.engines.node; + const minimumVersion = (semver.minVersion(versionRange) as SemVer).format(); - if (majorVersion === 18 && semver.lt(nodeVersion, MINIMUM_NODE_18_VERSION)) { + if (!semver.satisfies(nodeVersion, versionRange)) { error( - `Node version ${nodeVersion} is not supported. Please use Node ${MINIMUM_NODE_18_VERSION} or later.`, + `Node version ${nodeVersion} is not supported. Please use Node ${minimumVersion} or later.`, ); // eslint-disable-next-line n/no-process-exit process.exit(1); diff --git a/yarn.lock b/yarn.lock index da8e756902..2513628d55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4205,7 +4205,6 @@ __metadata: "@metamask/eslint-config-nodejs": ^12.1.0 "@metamask/eslint-config-typescript": ^12.1.0 "@metamask/snaps-utils": "workspace:^" - "@metamask/utils": ^8.3.0 "@swc/core": 1.3.78 "@swc/jest": ^0.2.26 "@types/jest": ^27.5.1 @@ -4230,6 +4229,7 @@ __metadata: prettier: ^2.7.1 prettier-plugin-packagejson: ^2.2.11 rimraf: ^4.1.2 + semver: ^7.6.0 ts-node: ^10.9.1 tsc-watch: ^4.5.0 tsup: ^8.0.1 @@ -20573,7 +20573,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: From be2bae53ccfdf788c0a831f65de6ebe7c157628f Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 10:50:01 +0100 Subject: [PATCH 3/6] Fix lint --- packages/create-snap/package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-snap/package.json b/packages/create-snap/package.json index 3ccb9a5df1..9c5320c28e 100644 --- a/packages/create-snap/package.json +++ b/packages/create-snap/package.json @@ -47,7 +47,7 @@ }, "dependencies": { "@metamask/snaps-utils": "workspace:^", - "semver": "^7.6.0", + "semver": "^7.5.4", "yargs": "^17.7.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 2513628d55..81981fb1dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4229,7 +4229,7 @@ __metadata: prettier: ^2.7.1 prettier-plugin-packagejson: ^2.2.11 rimraf: ^4.1.2 - semver: ^7.6.0 + semver: ^7.5.4 ts-node: ^10.9.1 tsc-watch: ^4.5.0 tsup: ^8.0.1 @@ -20573,7 +20573,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: From 68f99d1562deecf4f70098828fd8f7e9a0ce07b6 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 11:06:01 +0100 Subject: [PATCH 4/6] Fix imports --- packages/create-snap/src/cmds/init/initHandler.ts | 3 ++- packages/create-snap/tsup.config.ts | 1 + packages/snaps-cli/src/cli.ts | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/create-snap/src/cmds/init/initHandler.ts b/packages/create-snap/src/cmds/init/initHandler.ts index 4afe7293d6..afce4dc451 100644 --- a/packages/create-snap/src/cmds/init/initHandler.ts +++ b/packages/create-snap/src/cmds/init/initHandler.ts @@ -10,7 +10,8 @@ import pathUtils from 'path'; import type { SemVer } from 'semver'; import semver from 'semver'; -import cliPackageJson from '../../../package.json'; +// eslint-disable-next-line import/no-extraneous-dependencies +import cliPackageJson from '@metamask/create-snap/package.json'; import type { YargsArgs } from '../../types/yargs'; import { buildSnap, diff --git a/packages/create-snap/tsup.config.ts b/packages/create-snap/tsup.config.ts index eda54c1cae..d62dc9943a 100644 --- a/packages/create-snap/tsup.config.ts +++ b/packages/create-snap/tsup.config.ts @@ -9,6 +9,7 @@ const { default: baseConfig } = require('../../tsup.config'); const config: Options = { name: packageJson.name, + external: ['@metamask/create-snap'], platform: 'node', }; diff --git a/packages/snaps-cli/src/cli.ts b/packages/snaps-cli/src/cli.ts index 228b459010..c5e871e445 100644 --- a/packages/snaps-cli/src/cli.ts +++ b/packages/snaps-cli/src/cli.ts @@ -3,7 +3,8 @@ import semver from 'semver'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -import packageJson from '../package.json'; +// eslint-disable-next-line import/no-extraneous-dependencies +import packageJson from '@metamask/snaps-cli/package.json'; import builders from './builders'; import { getConfigByArgv } from './config'; import { error, getYargsErrorMessage, sanitizeInputs } from './utils'; From 12caa0c235c5df056547009f07498ad04a2c204a Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 11:11:26 +0100 Subject: [PATCH 5/6] Fix lint --- packages/create-snap/src/cmds/init/initHandler.ts | 4 ++-- packages/snaps-cli/src/cli.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-snap/src/cmds/init/initHandler.ts b/packages/create-snap/src/cmds/init/initHandler.ts index afce4dc451..ed55ffee78 100644 --- a/packages/create-snap/src/cmds/init/initHandler.ts +++ b/packages/create-snap/src/cmds/init/initHandler.ts @@ -1,3 +1,5 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import cliPackageJson from '@metamask/create-snap/package.json'; import type { NpmSnapPackageJson } from '@metamask/snaps-utils'; import { NpmSnapFileNames, @@ -10,8 +12,6 @@ import pathUtils from 'path'; import type { SemVer } from 'semver'; import semver from 'semver'; -// eslint-disable-next-line import/no-extraneous-dependencies -import cliPackageJson from '@metamask/create-snap/package.json'; import type { YargsArgs } from '../../types/yargs'; import { buildSnap, diff --git a/packages/snaps-cli/src/cli.ts b/packages/snaps-cli/src/cli.ts index c5e871e445..180c37ed20 100644 --- a/packages/snaps-cli/src/cli.ts +++ b/packages/snaps-cli/src/cli.ts @@ -1,10 +1,10 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import packageJson from '@metamask/snaps-cli/package.json'; import type { SemVer } from 'semver'; import semver from 'semver'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -// eslint-disable-next-line import/no-extraneous-dependencies -import packageJson from '@metamask/snaps-cli/package.json'; import builders from './builders'; import { getConfigByArgv } from './config'; import { error, getYargsErrorMessage, sanitizeInputs } from './utils'; From 2a2be1c679ae8491d8c71e8fe65bba150a4e734d Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 20 Mar 2024 11:21:18 +0100 Subject: [PATCH 6/6] Add create-snap to depcheck --- packages/create-snap/.depcheckrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/create-snap/.depcheckrc.json b/packages/create-snap/.depcheckrc.json index 15d64e734b..c075cbea8e 100644 --- a/packages/create-snap/.depcheckrc.json +++ b/packages/create-snap/.depcheckrc.json @@ -5,6 +5,7 @@ "@lavamoat/preinstall-always-fail", "@metamask/auto-changelog", "@metamask/eslint-*", + "@metamask/create-snap", "@types/*", "@typescript-eslint/*", "eslint-config-*",