Skip to content

Commit

Permalink
Adds create-astro fallback values for package versions (#10255)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
natemoo-re authored Mar 7, 2024
1 parent bad9b58 commit 2aec2cd
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-bees-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-astro": patch
---

Fixes an issue where TypeScript and `@astrojs/check` versions would occassionally print as `undefined`.
2 changes: 1 addition & 1 deletion packages/create-astro/src/actions/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export async function getContext(argv: string[]): Promise<Context> {
prompt,
packageManager,
username: getName(),
version: getVersion(packageManager, 'astro'),
version: getVersion(packageManager, 'astro', process.env.ASTRO_VERSION),
skipHouston,
fancy,
dryRun,
Expand Down
4 changes: 2 additions & 2 deletions packages/create-astro/src/actions/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ const FILES_TO_UPDATE = {
}

const [astroCheckVersion, typescriptVersion] = await Promise.all([
getVersion(options.ctx.packageManager, '@astrojs/check'),
getVersion(options.ctx.packageManager, 'typescript'),
getVersion(options.ctx.packageManager, '@astrojs/check', process.env.ASTRO_CHECK_VERSION),
getVersion(options.ctx.packageManager, 'typescript', process.env.TYPESCRIPT_VERSION),
]);
parsedPackageJson.dependencies ??= {};
parsedPackageJson.dependencies['@astrojs/check'] = `^${astroCheckVersion}`;
Expand Down
7 changes: 3 additions & 4 deletions packages/create-astro/src/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,9 @@ export const getVersion = (packageManager: string, packageName: string, fallback
let registry = await getRegistry(packageManager);
const { version } = await fetch(`${registry}/${packageName}/latest`, {
redirect: 'follow',
}).then(
(res) => res.json(),
() => ({ version: fallback })
);
})
.then((res) => res.json())
.catch(() => ({ version: fallback }))
return resolve(version);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/create-astro/test/fixtures/not-empty/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"private": true,
"scripts": {
"dev": "astro dev",
"build": "astro check && astro build",
"build": "astro build",
"preview": "astro preview"
}
}
4 changes: 1 addition & 3 deletions packages/create-astro/test/fixtures/not-empty/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
{
"extends": "astro/tsconfigs/strictest"
}
{}
10 changes: 8 additions & 2 deletions packages/create-astro/test/typescript.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert from 'node:assert/strict';
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 { setupTypeScript, typescript } from '../dist/index.js';
Expand Down Expand Up @@ -81,6 +81,7 @@ describe('typescript', async () => {

describe('typescript: setup tsconfig', async () => {
beforeEach(() => resetFixtures());
after(() => resetFixtures());

it('none', async () => {
const root = new URL('./fixtures/empty/', import.meta.url);
Expand All @@ -104,6 +105,7 @@ describe('typescript: setup tsconfig', async () => {

describe('typescript: setup package', async () => {
beforeEach(() => resetFixtures());
after(() => resetFixtures());

it('none', async () => {
const root = new URL('./fixtures/empty/', import.meta.url);
Expand All @@ -122,14 +124,18 @@ describe('typescript: setup package', async () => {
);

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(
Object.keys(scripts),
['dev', 'build', 'preview'],
'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');
});
});
1 change: 1 addition & 0 deletions packages/create-astro/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const resetNotEmptyFixture = async () => {
build: 'astro build',
preview: 'astro preview',
},
dependencies: undefined
});

return Promise.all([
Expand Down
51 changes: 47 additions & 4 deletions scripts/cmd/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ export default async function build(...args) {

const {
type = 'module',
version,
dependencies = {},
} = await fs.readFile('./package.json').then((res) => JSON.parse(res.toString()));
// expose PACKAGE_VERSION on process.env for CLI utils
config.define = { 'process.env.PACKAGE_VERSION': JSON.stringify(version) };
} = await readPackageJSON('./package.json');

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 outdir = 'dist';
Expand Down Expand Up @@ -138,3 +140,44 @@ async function clean(outdir) {
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+/, '');
}

0 comments on commit 2aec2cd

Please sign in to comment.