From 71d3ca1c155509d13090ed64fb315b48cf3f83d2 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 31 Jul 2024 11:11:07 +0100 Subject: [PATCH 1/3] Add fallbacks to finding versions --- .../src/commands/doctor/helpers/versions.ts | 59 +++++++++++++++++++ .../cli-utils/src/commands/doctor/runner.ts | 32 ++++------ 2 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 packages/cli-utils/src/commands/doctor/helpers/versions.ts diff --git a/packages/cli-utils/src/commands/doctor/helpers/versions.ts b/packages/cli-utils/src/commands/doctor/helpers/versions.ts new file mode 100644 index 00000000..d398b017 --- /dev/null +++ b/packages/cli-utils/src/commands/doctor/helpers/versions.ts @@ -0,0 +1,59 @@ +import { createRequire } from 'node:module'; +import fs from 'node:fs/promises'; +import path from 'node:path'; + +export interface PackageJson { + name?: string; + dependencies?: Record; + devDependencies?: Record; +} + +export const readPackageJson = async (): Promise => { + const packageJsonPath = path.resolve(process.cwd(), 'package.json'); + const file = path.resolve(packageJsonPath); + return JSON.parse(await fs.readFile(file, 'utf-8')); +}; + +export const getTypeScriptVersion = async (meta: PackageJson): Promise => { + const pkg = 'typescript'; + if (meta.devDependencies?.[pkg]) { + return meta.devDependencies[pkg]; + } else if (meta.dependencies?.[pkg]) { + return meta.dependencies[pkg]; + } + try { + return (await import(pkg)).version || null; + } catch (_error) { + return null; + } +}; + +export const getGraphQLSPVersion = async (meta: PackageJson): Promise => { + const pkg = '@0no-co/graphqlsp'; + if (meta.devDependencies?.[pkg]) { + return meta.devDependencies[pkg]; + } else if (meta.dependencies?.[pkg]) { + return meta.dependencies[pkg]; + } + try { + // NOTE: Resolved from current folder, since it's a child dependency + return createRequire(__dirname)(`${pkg}/package.json`)?.version || null; + } catch (_error) { + return null; + } +}; + +export const getGqlTadaVersion = async (meta: PackageJson): Promise => { + const pkg = 'gql.tada'; + if (meta.devDependencies?.[pkg]) { + return meta.devDependencies[pkg]; + } else if (meta.dependencies?.[pkg]) { + return meta.dependencies[pkg]; + } + try { + // NOTE: Resolved from working directory, since it's a parent dependency + return createRequire(process.cwd())(`${pkg}/package.json`)?.version || null; + } catch (_error) { + return null; + } +}; diff --git a/packages/cli-utils/src/commands/doctor/runner.ts b/packages/cli-utils/src/commands/doctor/runner.ts index f3039bc3..23aa4419 100644 --- a/packages/cli-utils/src/commands/doctor/runner.ts +++ b/packages/cli-utils/src/commands/doctor/runner.ts @@ -7,6 +7,7 @@ import { loadRef, loadConfig, parseConfig } from '@gql.tada/internal'; import type { ComposeInput } from '../../term'; import { MINIMUM_VERSIONS, semverComply } from '../../utils/semver'; import { findGraphQLConfig } from './helpers/graphqlConfig'; +import * as versions from './helpers/versions'; import * as vscode from './helpers/vscode'; import * as logger from './logger'; @@ -38,16 +39,10 @@ export async function* run(): AsyncIterable { await delay(); // Check TypeScript version - const cwd = process.cwd(); - const packageJsonPath = path.resolve(cwd, 'package.json'); - let packageJsonContents: { - dependencies: Record; - devDependencies: Record; - }; - + let packageJson: versions.PackageJson; try { - const file = path.resolve(packageJsonPath); - packageJsonContents = JSON.parse(await fs.readFile(file, 'utf-8')); + // packageJson = await versions.readPackageJson(); + packageJson = {}; } catch (_error) { yield logger.failedTask(Messages.CHECK_TS_VERSION); throw logger.errorMessage( @@ -56,19 +51,14 @@ export async function* run(): AsyncIterable { ); } - const deps = Object.entries({ - ...packageJsonContents.dependencies, - ...packageJsonContents.devDependencies, - }); - - const typeScriptVersion = deps.find((x) => x[0] === 'typescript'); + const typeScriptVersion = await versions.getTypeScriptVersion(packageJson); if (!typeScriptVersion) { yield logger.failedTask(Messages.CHECK_TS_VERSION); throw logger.errorMessage( `A version of ${logger.code('typescript')} was not found in your dependencies.\n` + logger.hint(`Is ${logger.code('typescript')} installed in this package?`) ); - } else if (!semverComply(typeScriptVersion[1], MINIMUM_VERSIONS.typescript)) { + } else if (!semverComply(typeScriptVersion, MINIMUM_VERSIONS.typescript)) { // TypeScript version lower than v4.1 which is when they introduced template lits yield logger.failedTask(Messages.CHECK_TS_VERSION); throw logger.errorMessage( @@ -84,18 +74,18 @@ export async function* run(): AsyncIterable { await delay(); const supportsEmbeddedLsp = semverComply( - typeScriptVersion[1], + typeScriptVersion, MINIMUM_VERSIONS.typescript_embed_lsp ); if (!supportsEmbeddedLsp) { - const gqlspVersion = deps.find((x) => x[0] === '@0no-co/graphqlsp'); + const gqlspVersion = await versions.getGraphQLSPVersion(packageJson); if (!gqlspVersion) { yield logger.failedTask(Messages.CHECK_DEPENDENCIES); throw logger.errorMessage( `A version of ${logger.code('@0no-co/graphqlsp')} was not found in your dependencies.\n` + logger.hint(`Is ${logger.code('@0no-co/graphqlsp')} installed?`) ); - } else if (!semverComply(gqlspVersion[1], MINIMUM_VERSIONS.lsp)) { + } else if (!semverComply(gqlspVersion, MINIMUM_VERSIONS.lsp)) { yield logger.failedTask(Messages.CHECK_DEPENDENCIES); throw logger.errorMessage( `The version of ${logger.code( @@ -108,14 +98,14 @@ export async function* run(): AsyncIterable { } } - const gqlTadaVersion = deps.find((x) => x[0] === 'gql.tada'); + const gqlTadaVersion = await versions.getGqlTadaVersion(packageJson); if (!gqlTadaVersion) { yield logger.failedTask(Messages.CHECK_DEPENDENCIES); throw logger.errorMessage( `A version of ${logger.code('gql.tada')} was not found in your dependencies.\n` + logger.hint(`Is ${logger.code('gql.tada')} installed?`) ); - } else if (!semverComply(gqlTadaVersion[1], '1.0.0')) { + } else if (!semverComply(gqlTadaVersion, '1.0.0')) { yield logger.failedTask(Messages.CHECK_DEPENDENCIES); throw logger.errorMessage( `The version of ${logger.code('gql.tada')} in your dependencies is out of date.\n` + From ef07dd88c2b879e5592b02c6a7ccdef42765eace Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 31 Jul 2024 11:13:09 +0100 Subject: [PATCH 2/3] Add changeset --- .changeset/curvy-mirrors-warn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/curvy-mirrors-warn.md diff --git a/.changeset/curvy-mirrors-warn.md b/.changeset/curvy-mirrors-warn.md new file mode 100644 index 00000000..72f2a7e9 --- /dev/null +++ b/.changeset/curvy-mirrors-warn.md @@ -0,0 +1,5 @@ +--- +"@gql.tada/cli-utils": patch +--- + +Add fallback version checks to `doctor` command. From eebcc1d6b11d4ef12abeb79766310224a25bfc2b Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 31 Jul 2024 11:17:38 +0100 Subject: [PATCH 3/3] Cleanup --- packages/cli-utils/src/commands/doctor/runner.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli-utils/src/commands/doctor/runner.ts b/packages/cli-utils/src/commands/doctor/runner.ts index 23aa4419..74946533 100644 --- a/packages/cli-utils/src/commands/doctor/runner.ts +++ b/packages/cli-utils/src/commands/doctor/runner.ts @@ -1,4 +1,3 @@ -import fs from 'node:fs/promises'; import path from 'node:path'; import type { GraphQLSPConfig, LoadConfigResult } from '@gql.tada/internal';