From 8dd5c7eaec64b0975463261e30a1a2d4c9bb66ef Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 20 Dec 2024 15:54:14 +0100 Subject: [PATCH 1/8] fix: spaces in project name --- src/utils/prompt-for-missing-options.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/prompt-for-missing-options.ts b/src/utils/prompt-for-missing-options.ts index 18cee780d..b2e03c666 100644 --- a/src/utils/prompt-for-missing-options.ts +++ b/src/utils/prompt-for-missing-options.ts @@ -23,7 +23,11 @@ export async function promptForMissingOptions( name: "project", message: "Your project name:", default: defaultOptions.project, - validate: (value: string) => value.length > 0, + validate: (value: string) => { + if (value.length === 0) return "Project name cannot be empty"; + if (/\s/.test(value)) return "Project name cannot contain whitespace (spaces, tabs, etc)"; + return true; + }, }, { type: "list", From a541db49e98a543cacb486fb19ecdea12a9f2a11 Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 20 Dec 2024 17:29:45 +0100 Subject: [PATCH 2/8] fix: restrict only spaces at the end --- src/utils/parse-arguments-into-options.ts | 7 ++++++- src/utils/prompt-for-missing-options.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index aaabaef1d..7eea67ce3 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -84,7 +84,7 @@ export async function parseArgumentsIntoOptions( const help = args["--help"] ?? false; - const project = args._[0] ?? null; + let project: string | null = args._[0] ?? null; // use the original extension arg const extensionName = args["--extension"] && rawArgs.slice(2).find(a => a.toLowerCase() === args["--extension"]); @@ -101,6 +101,11 @@ export async function parseArgumentsIntoOptions( ); } + if (project && /\s$/.test(project)) { + project = null; + console.log(chalk.yellow(" Project name cannot end with whitespace. Enter a valid project name.")); + } + let solidityFrameworkChoices = [ SOLIDITY_FRAMEWORKS.HARDHAT, SOLIDITY_FRAMEWORKS.FOUNDRY, diff --git a/src/utils/prompt-for-missing-options.ts b/src/utils/prompt-for-missing-options.ts index b2e03c666..726af1aa1 100644 --- a/src/utils/prompt-for-missing-options.ts +++ b/src/utils/prompt-for-missing-options.ts @@ -25,7 +25,7 @@ export async function promptForMissingOptions( default: defaultOptions.project, validate: (value: string) => { if (value.length === 0) return "Project name cannot be empty"; - if (/\s/.test(value)) return "Project name cannot contain whitespace (spaces, tabs, etc)"; + if (/\s$/.test(value)) return "Project name cannot end with whitespace"; return true; }, }, From f99426a0c50e88cecdeccd465e5d2c312c32687e Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 27 Dec 2024 10:33:55 +0100 Subject: [PATCH 3/8] chore: move regex to const --- src/utils/parse-arguments-into-options.ts | 3 ++- src/utils/prompt-for-missing-options.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index 7eea67ce3..b417fd240 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -12,6 +12,7 @@ import { validateFoundryUp } from "./system-validation"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; +import { HAS_TRAILING_WHITESPACE_REGEX } from "./prompt-for-missing-options"; const validateExternalExtension = async ( extensionName: string, @@ -101,7 +102,7 @@ export async function parseArgumentsIntoOptions( ); } - if (project && /\s$/.test(project)) { + if (project && HAS_TRAILING_WHITESPACE_REGEX.test(project)) { project = null; console.log(chalk.yellow(" Project name cannot end with whitespace. Enter a valid project name.")); } diff --git a/src/utils/prompt-for-missing-options.ts b/src/utils/prompt-for-missing-options.ts index 726af1aa1..0fc45a0c4 100644 --- a/src/utils/prompt-for-missing-options.ts +++ b/src/utils/prompt-for-missing-options.ts @@ -2,6 +2,8 @@ import { Options, RawOptions, SolidityFrameworkChoices } from "../types"; import inquirer from "inquirer"; import { SOLIDITY_FRAMEWORKS } from "./consts"; +export const HAS_TRAILING_WHITESPACE_REGEX = /\s$/; + // default values for unspecified args const defaultOptions: RawOptions = { project: "my-dapp-example", @@ -25,7 +27,7 @@ export async function promptForMissingOptions( default: defaultOptions.project, validate: (value: string) => { if (value.length === 0) return "Project name cannot be empty"; - if (/\s$/.test(value)) return "Project name cannot end with whitespace"; + if (HAS_TRAILING_WHITESPACE_REGEX.test(value)) return "Project name cannot end with whitespace"; return true; }, }, From 5b371ec3c87b3c40ffe0467337b5f7536aecb7d3 Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 27 Dec 2024 10:43:37 +0100 Subject: [PATCH 4/8] chore: changeset --- .changeset/bright-pigs-deliver.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/bright-pigs-deliver.md diff --git a/.changeset/bright-pigs-deliver.md b/.changeset/bright-pigs-deliver.md new file mode 100644 index 000000000..1158fab44 --- /dev/null +++ b/.changeset/bright-pigs-deliver.md @@ -0,0 +1,5 @@ +--- +"create-eth": patch +--- + +restrict trailing whitespace in the project name From bb077658f2dda2f0a7f94d820cea5e1ccb1a661b Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 3 Jan 2025 17:56:53 +0100 Subject: [PATCH 5/8] feat: use validate-npm-name --- package.json | 4 +++- src/utils/parse-arguments-into-options.ts | 17 ++++++++++++----- src/utils/prompt-for-missing-options.ts | 14 ++++++++------ src/utils/validate-name.ts | 23 +++++++++++++++++++++++ yarn.lock | 16 ++++++++++++++++ 5 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 src/utils/validate-name.ts diff --git a/package.json b/package.json index ef5a95f92..77a49e0f1 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@types/inquirer": "9.0.3", "@types/ncp": "2.0.5", "@types/node": "18.16.0", + "@types/validate-npm-package-name": "4.0.2", "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", @@ -58,7 +59,8 @@ "inquirer": "9.2.0", "listr2": "^8.2.1", "merge-packages": "^0.1.6", - "ncp": "2.0.0" + "ncp": "2.0.0", + "validate-npm-package-name": "6.0.0" }, "packageManager": "yarn@3.5.0" } diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index b417fd240..3d9b631e0 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -12,7 +12,7 @@ import { validateFoundryUp } from "./system-validation"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; -import { HAS_TRAILING_WHITESPACE_REGEX } from "./prompt-for-missing-options"; +import { validateNpmName } from "./validate-name"; const validateExternalExtension = async ( extensionName: string, @@ -75,7 +75,7 @@ export async function parseArgumentsIntoOptions( "-h": "--help", }, { - argv: rawArgs.slice(2).map(a => a.toLowerCase()), + argv: rawArgs.slice(2), }, ); @@ -102,9 +102,16 @@ export async function parseArgumentsIntoOptions( ); } - if (project && HAS_TRAILING_WHITESPACE_REGEX.test(project)) { - project = null; - console.log(chalk.yellow(" Project name cannot end with whitespace. Enter a valid project name.")); + if (project) { + const validation = validateNpmName(project); + if (!validation.valid) { + console.error( + `Could not create a project called ${chalk.yellow(`"${project}"`)} because of naming restrictions:`, + ); + + validation.problems.forEach(p => console.error(`${chalk.red(">>")} Project ${p}`)); + project = null; + } } let solidityFrameworkChoices = [ diff --git a/src/utils/prompt-for-missing-options.ts b/src/utils/prompt-for-missing-options.ts index 0fc45a0c4..7c5242dfa 100644 --- a/src/utils/prompt-for-missing-options.ts +++ b/src/utils/prompt-for-missing-options.ts @@ -1,8 +1,8 @@ import { Options, RawOptions, SolidityFrameworkChoices } from "../types"; import inquirer from "inquirer"; import { SOLIDITY_FRAMEWORKS } from "./consts"; - -export const HAS_TRAILING_WHITESPACE_REGEX = /\s$/; +import { validateNpmName } from "./validate-name"; +import { basename, resolve } from "path"; // default values for unspecified args const defaultOptions: RawOptions = { @@ -25,10 +25,12 @@ export async function promptForMissingOptions( name: "project", message: "Your project name:", default: defaultOptions.project, - validate: (value: string) => { - if (value.length === 0) return "Project name cannot be empty"; - if (HAS_TRAILING_WHITESPACE_REGEX.test(value)) return "Project name cannot end with whitespace"; - return true; + validate: (name: string) => { + const validation = validateNpmName(basename(resolve(name))); + if (validation.valid) { + return true; + } + return "Project " + validation.problems[0]; }, }, { diff --git a/src/utils/validate-name.ts b/src/utils/validate-name.ts new file mode 100644 index 000000000..e720ae4f6 --- /dev/null +++ b/src/utils/validate-name.ts @@ -0,0 +1,23 @@ +import validateProjectName from "validate-npm-package-name"; + +type ValidateNpmNameResult = + | { + valid: true; + } + | { + valid: false; + problems: string[]; + }; + +export function validateNpmName(name: string): ValidateNpmNameResult { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + const nameValidation = validateProjectName(name); + if (nameValidation.validForNewPackages) { + return { valid: true }; + } + + return { + valid: false, + problems: [...(nameValidation.errors || []), ...(nameValidation.warnings || [])], + }; +} diff --git a/yarn.lock b/yarn.lock index 6155ceba7..5f7eadad7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -668,6 +668,13 @@ __metadata: languageName: node linkType: hard +"@types/validate-npm-package-name@npm:4.0.2": + version: 4.0.2 + resolution: "@types/validate-npm-package-name@npm:4.0.2" + checksum: 3f35a3cc8ddd919b456843f36d55a4f1df5f03d5d9b6494b4d8f5f3b24e3f24a11c922772d9970a67f1249214da18c157776e9c6d2e72227799459849dfd9c76 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:8.15.0": version: 8.15.0 resolution: "@typescript-eslint/eslint-plugin@npm:8.15.0" @@ -1389,6 +1396,7 @@ __metadata: "@types/inquirer": 9.0.3 "@types/ncp": 2.0.5 "@types/node": 18.16.0 + "@types/validate-npm-package-name": 4.0.2 arg: 5.0.2 chalk: 5.2.0 eslint: ^9.15.0 @@ -1406,6 +1414,7 @@ __metadata: tslib: 2.5.0 typescript: ^5.6.3 typescript-eslint: ^8.15.0 + validate-npm-package-name: 6.0.0 bin: create-eth: bin/create-dapp-se2.js languageName: unknown @@ -5026,6 +5035,13 @@ __metadata: languageName: node linkType: hard +"validate-npm-package-name@npm:6.0.0": + version: 6.0.0 + resolution: "validate-npm-package-name@npm:6.0.0" + checksum: 4d018c4fa07f95534a5fea667adc653b1ef52f08bf56aff066c28394499d0a6949c0b00edbd7077c4dc1e041da9220af7c742ced67d7d2d6a1b07d10cbe91b29 + languageName: node + linkType: hard + "wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" From f31e6d70f15fbebdabb931011bd94b32d6fb1fa6 Mon Sep 17 00:00:00 2001 From: Rinat Date: Fri, 3 Jan 2025 18:00:20 +0100 Subject: [PATCH 6/8] fix: lint --- src/utils/validate-name.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/validate-name.ts b/src/utils/validate-name.ts index e720ae4f6..d88ed40dd 100644 --- a/src/utils/validate-name.ts +++ b/src/utils/validate-name.ts @@ -10,7 +10,6 @@ type ValidateNpmNameResult = }; export function validateNpmName(name: string): ValidateNpmNameResult { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call const nameValidation = validateProjectName(name); if (nameValidation.validForNewPackages) { return { valid: true }; From 0a23e06ca4232b5ae90335d259cd45b9d19fa444 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Mon, 6 Jan 2025 13:55:39 +0530 Subject: [PATCH 7/8] update changeset --- .changeset/bright-pigs-deliver.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/bright-pigs-deliver.md b/.changeset/bright-pigs-deliver.md index 1158fab44..fe5344d4d 100644 --- a/.changeset/bright-pigs-deliver.md +++ b/.changeset/bright-pigs-deliver.md @@ -2,4 +2,4 @@ "create-eth": patch --- -restrict trailing whitespace in the project name +validate project name for invalid characters From d982b3b16817f7fd570675016d4cf0f066bc8bac Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Mon, 6 Jan 2025 13:56:33 +0530 Subject: [PATCH 8/8] update changeset --- .changeset/bright-pigs-deliver.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/bright-pigs-deliver.md b/.changeset/bright-pigs-deliver.md index fe5344d4d..5e2dd8f01 100644 --- a/.changeset/bright-pigs-deliver.md +++ b/.changeset/bright-pigs-deliver.md @@ -2,4 +2,4 @@ "create-eth": patch --- -validate project name for invalid characters +validate project name inline with npm name rules