Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: auto update field name in package.json #5763

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fast-ligers-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-astro": patch
---

Update `package.json` `name` field according to project name
3 changes: 3 additions & 0 deletions packages/create-astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"ora": "^6.1.0",
"prompts": "^2.4.2",
"strip-ansi": "^7.0.1",
"validate-npm-package-name": "^5.0.0",
"which-pm-runs": "^1.1.0",
"yargs-parser": "^21.0.1"
},
Expand All @@ -46,10 +47,12 @@
"@types/degit": "^2.8.3",
"@types/mocha": "^9.1.1",
"@types/prompts": "^2.0.14",
"@types/validate-npm-package-name": "^4.0.0",
"@types/which-pm-runs": "^1.0.0",
"@types/yargs-parser": "^21.0.0",
"astro-scripts": "workspace:*",
"chai": "^4.3.6",
"cli-prompts-test": "^0.3.0",
"mocha": "^9.2.2",
"uvu": "^0.5.3"
},
Expand Down
68 changes: 64 additions & 4 deletions packages/create-astro/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ora from 'ora';
import { platform } from 'os';
import path from 'path';
import prompts from 'prompts';
import validate from 'validate-npm-package-name';
import detectPackageManager from 'which-pm-runs';
import yargs from 'yargs-parser';
import { loadWithRocketGradient, rocketAscii } from './gradient.js';
Expand Down Expand Up @@ -89,6 +90,19 @@ function isValidProjectDirectory(dirPath: string) {
return conflicts.length === 0;
}

async function validatePackageName(pkgName: string) {
const isValidPackageName = await validate(pkgName);
const isValid = isValidPackageName.validForNewPackages
const notices: string[] = []
if (!isValid) {
notices.push(...[
...isValidPackageName.warnings || [],
...isValidPackageName.errors || []
]);
}
return { isValid, notices }
}

const FILES_TO_REMOVE = ['.stackblitzrc', 'sandbox.config.json', 'CHANGELOG.md']; // some files are only needed for online editors when using astro.new. Remove for create-astro installs.

// Please also update the installation instructions in the docs at https://github.com/withastro/docs/blob/main/src/pages/en/install/auto.md if you make any changes to the flow or wording here.
Expand All @@ -97,6 +111,11 @@ export async function main() {
const [username, version] = await Promise.all([getName(), getVersion()]);

logger.debug('Verbose logging turned on');

if (args.dryRun) {
ora().info('Running in dry mode');
}

if (!args.skipHouston) {
await say(
[
Expand Down Expand Up @@ -154,6 +173,8 @@ export async function main() {
process.exit(1);
}

let projectDir = path.relative(process.cwd(), cwd);

const options = await prompts(
[
{
Expand Down Expand Up @@ -208,10 +229,50 @@ export async function main() {
}
})
);
}

templateSpinner.text = green('Template copied!');
templateSpinner.succeed();
templateSpinner.text = green('Template copied!');
templateSpinner.succeed();

const printIgnoreUpdatingPkgNameMsg = () => info('Opps', 'You have to update the NPM package name manually.');
// Validate and update the NPM package name
let pkgName: string = projectDir;
if (args.package) {
pkgName = args.package;
}

const validatePackageNameResult = await validatePackageName(pkgName);
if (!validatePackageNameResult.isValid) {
const pkgNameResponse = await prompts(
{
type: 'text',
name: 'package',
message: 'What is the new NPM package name?',
initial: generateProjectName(),
async validate(value) {
const { isValid, notices } = await validatePackageName(value);
if (!isValid) {
const errorMsg = `"${bold(value)}" is an invalid NPM package name`;
const errors = notices.join(', ');
return `${errorMsg}: ${errors}`;
}
return true;
},
},
{ onCancel: printIgnoreUpdatingPkgNameMsg }
);
pkgName = pkgNameResponse.package as string;
}

if (typeof pkgName === 'string' && !!pkgName) {
// Change project name in package.json
try {
await execaCommand(`${pkgManager} pkg set name=${pkgName}`, { cwd });
await info('Sounds good!', `The NPM package name was updated to ${bold(pkgName)}.`);
} catch(error) {
printIgnoreUpdatingPkgNameMsg();
}
}
}

const installResponse = await prompts(
{
Expand Down Expand Up @@ -346,7 +407,6 @@ export async function main() {
ora().succeed('TypeScript settings applied!');
}

let projectDir = path.relative(process.cwd(), cwd);
const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`;
await nextSteps({ projectDir, devCmd });

Expand Down
154 changes: 154 additions & 0 deletions packages/create-astro/test/package-step.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import runTest, { ENTER } from "cli-prompts-test";
import { expect } from 'chai';
import { deleteSync } from 'del';
import { existsSync, mkdirSync, readdirSync, readFileSync } from 'fs';
import path from 'path';
import { PROMPT_MESSAGES, testDir, timeout } from './utils.js';
import stripAnsi from 'strip-ansi';

const cliPath = path.join(testDir, "../create-astro.mjs");

const inputs = {
emptyDir: './fixtures/update-package-name/empty-dir',
};

function isEmpty(dirPath) {
return !existsSync(dirPath) || readdirSync(dirPath).length === 0;
}

function ensureEmptyDir() {
const dirPath = path.resolve(testDir, inputs.emptyDir);
if (!existsSync(dirPath)) {
mkdirSync(dirPath, { recursive: true });
} else if (!isEmpty(dirPath)) {
const globPath = path.resolve(dirPath, '*');
deleteSync(globPath, { dot: true });
}
}

function getPackageJson(installDir) {
const filePath = path.resolve(testDir, installDir, 'package.json');
return JSON.parse(readFileSync(filePath, 'utf-8'));
}

const testArgs = [
inputs.emptyDir,
'--skip-houston',
'--install',
'0',
'--git',
'0',
'--typescript',
'strict',
];

describe('[create-astro] update package name', function () {
this.timeout(30000);

beforeEach(ensureEmptyDir);

afterEach(ensureEmptyDir);

it('should the package name is changed if no value is given by the user', async function () {
const template = 'minimal';
const args = [
...testArgs,
...['--template', template]
]
const { exitCode, stdout } = await runTest([cliPath].concat(args), [
ENTER,
], {
testPath: testDir,
timeout,
});

await expect(exitCode).to.equal(0);
// TODO: This should true, so we have to fix the implementation
// await expect(stripAnsi(stderr).trim()).to.be.empty;
await expect(stripAnsi(stdout).trim()).to.contain(PROMPT_MESSAGES.packageSucceed);

const packageJson = getPackageJson(inputs.emptyDir);
const pkgName = packageJson.name;
await expect(pkgName).to.not.equal(`@example/${template}`);
});

it('should the package name is not changed if the user cancels the operation', async function () {
const template = 'minimal';
const args = [
...testArgs,
...[
'--template',
template,
]
]
const { exitCode, stdout } = await runTest([cliPath].concat(args), [
"\x1B", // ESC hex code
], {
testPath: testDir,
timeout,
});

await expect(exitCode).to.equal(0);
// TODO: This should true, so we have to fix the implementation
// await expect(stripAnsi(stderr).trim()).to.be.empty;
await expect(stripAnsi(stdout).trim()).to.contain(PROMPT_MESSAGES.packageIgnored);

const packageJson = getPackageJson(inputs.emptyDir);
const pkgName = packageJson.name;
await expect(pkgName).to.equal(`@example/${template}`);
});

it('should the package name matches the passed argument --package', async function () {
const expectedPkgName = 'astro-test';
const args = [
...testArgs,
...[
'--template',
'minimal',
'--package',
expectedPkgName,
]
]
const { exitCode, stdout } = await runTest([cliPath].concat(args), [
ENTER,
], {
testPath: testDir,
timeout,
});

await expect(exitCode).to.equal(0);
// TODO: This should true, so we have to fix the implementation
// await expect(stripAnsi(stderr).trim()).to.be.empty;
await expect(stripAnsi(stdout).trim()).to.contain(PROMPT_MESSAGES.packageSucceed);

const packageJson = getPackageJson(inputs.emptyDir);
const pkgName = packageJson.name;
await expect(pkgName).to.equal(expectedPkgName);
});

it('should the package name matches the user input', async function () {
const expectedPkgName = 'astro-test';
const args = [
...testArgs,
...[
'--template',
'minimal',
]
]
const { exitCode, stdout } = await runTest([cliPath].concat(args), [
`${expectedPkgName}${ENTER}`,
], {
testPath: testDir,
timeout,
});

await expect(exitCode).to.equal(0);
// TODO: This should true, so we have to fix the implementation
// await expect(stripAnsi(stderr).trim()).to.be.empty;
await expect(stripAnsi(stdout).trim()).to.contain(PROMPT_MESSAGES.packageSucceed);

const packageJson = getPackageJson(inputs.emptyDir);
const pkgName = packageJson.name;
await expect(pkgName).to.equal(expectedPkgName);
});
});
2 changes: 2 additions & 0 deletions packages/create-astro/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export function promiseWithTimeout(testFn) {
export const PROMPT_MESSAGES = {
directory: 'Where would you like to create your new project?',
template: 'How would you like to setup your new project?',
packageSucceed: 'Sounds good! The NPM package name was updated',
packageIgnored: 'You have to update the NPM package name manually.',
typescript: 'How would you like to setup TypeScript?',
typescriptSucceed: 'next',
};
Expand Down
Loading