0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

Adds create-astro fallback values for package versions (#10255)

* fix(create-astro): add fallback when registry fails to return the current package version

* feat(create-astro): inline most current package versions as fallback

* test(create-astro): update typescript tests to check for undefined

* test(create-astro): properly reset fixtures

* refactor: read dependencies from workspace root

* refactor: error on missing values
This commit is contained in:
Nate Moore 2024-03-07 12:14:48 -06:00 committed by GitHub
parent bad9b583a2
commit 2aec2cdc21
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 69 additions and 17 deletions

View file

@ -0,0 +1,5 @@
---
"create-astro": patch
---
Fixes an issue where TypeScript and `@astrojs/check` versions would occassionally print as `undefined`.

View file

@ -93,7 +93,7 @@ export async function getContext(argv: string[]): Promise<Context> {
prompt, prompt,
packageManager, packageManager,
username: getName(), username: getName(),
version: getVersion(packageManager, 'astro'), version: getVersion(packageManager, 'astro', process.env.ASTRO_VERSION),
skipHouston, skipHouston,
fancy, fancy,
dryRun, dryRun,

View file

@ -101,8 +101,8 @@ const FILES_TO_UPDATE = {
} }
const [astroCheckVersion, typescriptVersion] = await Promise.all([ const [astroCheckVersion, typescriptVersion] = await Promise.all([
getVersion(options.ctx.packageManager, '@astrojs/check'), getVersion(options.ctx.packageManager, '@astrojs/check', process.env.ASTRO_CHECK_VERSION),
getVersion(options.ctx.packageManager, 'typescript'), getVersion(options.ctx.packageManager, 'typescript', process.env.TYPESCRIPT_VERSION),
]); ]);
parsedPackageJson.dependencies ??= {}; parsedPackageJson.dependencies ??= {};
parsedPackageJson.dependencies['@astrojs/check'] = `^${astroCheckVersion}`; parsedPackageJson.dependencies['@astrojs/check'] = `^${astroCheckVersion}`;

View file

@ -65,10 +65,9 @@ export const getVersion = (packageManager: string, packageName: string, fallback
let registry = await getRegistry(packageManager); let registry = await getRegistry(packageManager);
const { version } = await fetch(`${registry}/${packageName}/latest`, { const { version } = await fetch(`${registry}/${packageName}/latest`, {
redirect: 'follow', redirect: 'follow',
}).then( })
(res) => res.json(), .then((res) => res.json())
() => ({ version: fallback }) .catch(() => ({ version: fallback }))
);
return resolve(version); return resolve(version);
}); });

View file

@ -3,7 +3,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"build": "astro check && astro build", "build": "astro build",
"preview": "astro preview" "preview": "astro preview"
} }
} }

View file

@ -1,3 +1 @@
{ {}
"extends": "astro/tsconfigs/strictest"
}

View file

@ -1,6 +1,6 @@
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import fs from 'node:fs'; import fs from 'node:fs';
import { beforeEach, describe, it } from 'node:test'; import { after, beforeEach, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import { setupTypeScript, typescript } from '../dist/index.js'; import { setupTypeScript, typescript } from '../dist/index.js';
@ -81,6 +81,7 @@ describe('typescript', async () => {
describe('typescript: setup tsconfig', async () => { describe('typescript: setup tsconfig', async () => {
beforeEach(() => resetFixtures()); beforeEach(() => resetFixtures());
after(() => resetFixtures());
it('none', async () => { it('none', async () => {
const root = new URL('./fixtures/empty/', import.meta.url); const root = new URL('./fixtures/empty/', import.meta.url);
@ -104,6 +105,7 @@ describe('typescript: setup tsconfig', async () => {
describe('typescript: setup package', async () => { describe('typescript: setup package', async () => {
beforeEach(() => resetFixtures()); beforeEach(() => resetFixtures());
after(() => resetFixtures());
it('none', async () => { it('none', async () => {
const root = new URL('./fixtures/empty/', import.meta.url); const root = new URL('./fixtures/empty/', import.meta.url);
@ -122,7 +124,7 @@ describe('typescript: setup package', async () => {
); );
await setupTypeScript('strictest', { cwd: fileURLToPath(root), install: false }); await setupTypeScript('strictest', { cwd: fileURLToPath(root), install: false });
const { scripts } = JSON.parse(fs.readFileSync(packageJson, { encoding: 'utf-8' })); const { scripts, dependencies } = JSON.parse(fs.readFileSync(packageJson, { encoding: 'utf-8' }));
assert.deepEqual( assert.deepEqual(
Object.keys(scripts), Object.keys(scripts),
@ -130,6 +132,10 @@ describe('typescript: setup package', async () => {
'does not override existing scripts' 'does not override existing scripts'
); );
for (const value of Object.values(dependencies)) {
assert.doesNotMatch(value, /undefined$/, 'does not include undefined values')
}
assert.equal(scripts.build, 'astro check && astro build', 'prepends astro check command'); assert.equal(scripts.build, 'astro check && astro build', 'prepends astro check command');
}); });
}); });

View file

@ -48,6 +48,7 @@ const resetNotEmptyFixture = async () => {
build: 'astro build', build: 'astro build',
preview: 'astro preview', preview: 'astro preview',
}, },
dependencies: undefined
}); });
return Promise.all([ return Promise.all([

View file

@ -55,11 +55,13 @@ export default async function build(...args) {
const { const {
type = 'module', type = 'module',
version,
dependencies = {}, dependencies = {},
} = await fs.readFile('./package.json').then((res) => JSON.parse(res.toString())); } = await readPackageJSON('./package.json');
// expose PACKAGE_VERSION on process.env for CLI utils
config.define = { 'process.env.PACKAGE_VERSION': JSON.stringify(version) }; config.define = {};
for (const [key, value] of await getDefinedEntries()) {
config.define[`process.env.${key}`] = JSON.stringify(value);
}
const format = type === 'module' && !forceCJS ? 'esm' : 'cjs'; const format = type === 'module' && !forceCJS ? 'esm' : 'cjs';
const outdir = 'dist'; const outdir = 'dist';
@ -138,3 +140,44 @@ async function clean(outdir) {
onlyFiles: true, onlyFiles: true,
}); });
} }
/**
* Contextual `define` values to statically replace in the built JS output.
* Available to all packages, but mostly useful for CLIs like `create-astro`.
*/
async function getDefinedEntries() {
const define = {
/** The current version (at the time of building) for the current package, such as `astro` or `@astrojs/sitemap` */
PACKAGE_VERSION: await getInternalPackageVersion('./package.json'),
/** The current version (at the time of building) for `astro` */
ASTRO_VERSION: await getInternalPackageVersion(new URL('../../packages/astro/package.json', import.meta.url)),
/** The current version (at the time of building) for `@astrojs/check` */
ASTRO_CHECK_VERSION: await getWorkspacePackageVersion('@astrojs/check'),
/** The current version (at the time of building) for `typescript` */
TYPESCRIPT_VERSION: await getWorkspacePackageVersion('typescript'),
}
for (const [key, value] of Object.entries(define)) {
if (value === undefined) {
delete define[key];
}
}
return Object.entries(define);
}
async function readPackageJSON(path) {
return await fs.readFile(path, { encoding: 'utf8' }).then((res) => JSON.parse(res));
}
async function getInternalPackageVersion(path) {
return readPackageJSON(path).then(res => res.version);
}
async function getWorkspacePackageVersion(packageName) {
const { dependencies, devDependencies } = await readPackageJSON(new URL('../../package.json', import.meta.url));
const deps = { ...dependencies, ...devDependencies };
const version = deps[packageName];
if (!version) {
throw new Error(`Unable to resolve "${packageName}". Is it a depdendency of the workspace root?`)
}
return version.replace(/^\D+/, '');
}