Skip to content

Commit

Permalink
feat: doctor add pnpm setup check
Browse files Browse the repository at this point in the history
  • Loading branch information
winchesHe committed Mar 31, 2024
1 parent 2aa7ff9 commit eca2452
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 1 deletion.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@
"chalk": "5.3.0",
"commander": "11.0.0",
"fast-glob": "3.3.2",
"find-up": "7.0.0",
"gradient-string": "2.0.2",
"ora": "8.0.1",
"prompts": "2.4.2",
"tar": "6.2.1"
},
"devDependencies": {
"@nextui-org/button": "2.0.26",
"@commitlint/cli": "17.7.1",
"@commitlint/config-conventional": "17.7.0",
"@types/gradient-string": "1.1.3",
Expand Down
48 changes: 48 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion src/actions/doctor-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ import chalk from 'chalk';

import {
checkApp,
checkPnpm,
checkRequiredContentInstalled,
checkTailwind,
combineProblemRecord
} from '@helpers/check';
import {detect} from '@helpers/detect';
import {Logger, type PrefixLogType} from '@helpers/logger';
import {getPackageInfo} from '@helpers/package';
import {findFiles} from '@helpers/utils';
import {resolver} from 'src/constants/path';
import {DOCS_TAILWINDCSS_SETUP} from 'src/constants/required';
import {DOCS_PNPM_SETUP, DOCS_TAILWINDCSS_SETUP} from 'src/constants/required';

interface DoctorActionOptions {
packagePath?: string;
tailwindPath?: string;
appPath?: string;
checkApp?: boolean;
checkTailwind?: boolean;
checkPnpm?: boolean;
}

export interface ProblemRecord {
Expand All @@ -30,6 +33,7 @@ export async function doctorAction(options: DoctorActionOptions) {
const {
appPath = findFiles('**/app.tsx')[0],
checkApp: enableCheckApp = true,
checkPnpm: enableCheckPnpm = true,
checkTailwind: enableCheckTailwind = true,
packagePath = resolver('package.json'),
tailwindPath = findFiles('**/tailwind.config.js')
Expand Down Expand Up @@ -159,6 +163,32 @@ export async function doctorAction(options: DoctorActionOptions) {
}
}

/** ======================== Check whether Pnpm setup is correct ======================== */
if (enableCheckPnpm) {
const currentPkgManager = await detect();

if (currentPkgManager === 'pnpm') {
const [isCorrect, ...errorInfo] = checkPnpm();

if (!isCorrect) {
problemRecord.push({
level: 'error',
name: 'incorrectPnpm',
outputFn: () => {
Logger.error('Your pnpm setup is incorrect');
Logger.newLine();
Logger.info('The missing part is:');
errorInfo.forEach((info) => {
Logger.info(`- need added ${info}`);
});
Logger.newLine();
Logger.error(`Please check the detail in the NextUI document: ${DOCS_PNPM_SETUP}`);
}
});
}
}
}

/** ======================== Return when there is no problem ======================== */
if (!problemRecord.length) {
Logger.success('🌟Congratulation no problem found in your project');
Expand Down
5 changes: 5 additions & 0 deletions src/constants/required.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const DOCS_INSTALLED = 'https://nextui.org/docs/guide/installation#global
export const DOCS_TAILWINDCSS_SETUP =
'https://nextui.org/docs/guide/installation#tailwind-css-setup';
export const DOCS_APP_SETUP = 'https://nextui.org/docs/guide/installation#provider-setup';
export const DOCS_PNPM_SETUP = 'https://nextui.org/docs/guide/installation#setup-pnpm-optional';

// Record the required content of tailwind.config.js
export const tailwindRequired = {
Expand Down Expand Up @@ -38,3 +39,7 @@ export const individualTailwindRequired = {
export const appRequired = {
import: 'NextUIProvider'
} as const;

export const pnpmRequired = {
content: 'public-hoist-pattern[]=*@nextui-org/*'
} as const;
30 changes: 30 additions & 0 deletions src/helpers/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {NextUIComponents} from 'src/constants/component';

import {readFileSync} from 'fs';

import {resolver} from 'src/constants/path';
import {
DOCS_APP_SETUP,
DOCS_INSTALLED,
Expand All @@ -14,6 +15,7 @@ import {
THEME_UI,
appRequired,
individualTailwindRequired,
pnpmRequired,
tailwindRequired
} from 'src/constants/required';

Expand Down Expand Up @@ -68,6 +70,7 @@ export function combineProblemRecord<T extends CombineType = CombineType>(
errorInfo.forEach((info) => {
Logger.info(`- need added ${info}`);
});
Logger.newLine();
Logger.error(`Please check the detail in the NextUI document: ${DOCS_APP_SETUP}`);
}
};
Expand All @@ -82,6 +85,7 @@ export function combineProblemRecord<T extends CombineType = CombineType>(
errorInfo.forEach((info) => {
Logger.info(`- need added ${info}`);
});
Logger.newLine();
Logger.error(`Please check the detail in the NextUI document: ${DOCS_INSTALLED}`);
}
};
Expand Down Expand Up @@ -210,3 +214,29 @@ export function checkApp(type: CheckType, appPath: string): CheckResult {

return [false, ...result];
}

export function checkPnpm(): CheckResult {
const result = [] as unknown as CheckResult;
const npmrcPath = resolver('.npmrc');

let content: string;

if (npmrcPath) {
try {
content = readFileSync(npmrcPath, 'utf-8');
const isPnpmCorrect = content.includes(pnpmRequired.content);

if (isPnpmCorrect) {
return [true];
}

!isPnpmCorrect && result.push(pnpmRequired.content);
} catch (error) {
result.push(`Error reading .npmrc file: ${npmrcPath} \nError: ${error}`);
}

return [false, ...result];
}

return [false, ...result];
}
36 changes: 36 additions & 0 deletions src/helpers/detect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type {SAFE_ANY} from './type';

import path from 'node:path';

import {findUp} from 'find-up';

import {ROOT} from 'src/constants/path';

type TupleToUnion<T extends readonly SAFE_ANY[]> = T[number];

export const AGENTS = ['npm', 'bun', 'pnpm', 'yarn'] as const;

export type Agent = TupleToUnion<typeof AGENTS>;

export const agents = AGENTS;

// the order here matters, more specific one comes first
export const LOCKS: Record<string, Agent> = {
'bun.lockb': 'bun',
'npm-shrinkwrap.json': 'npm',
'package-lock.json': 'npm',
'pnpm-lock.yaml': 'pnpm',
'yarn.lock': 'yarn'
};

export async function detect(cwd = ROOT) {
let agent: Agent | null = null;
const lockPath = await findUp(Object.keys(LOCKS), {cwd});

// detect based on lock
if (!agent && lockPath) {
agent = LOCKS[path.basename(lockPath)]!;
}

return agent;
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ nextui
.option('-app --appPath [string]', 'The path to the app.tsx file')
.option('-ca --checkApp [boolean]', 'Open check App', true)
.option('-ct --checkTailwind [boolean]', 'Open check tailwind.config.js', true)
.option('-cp --checkPnpm [boolean]', 'Open check Pnpm', true)
.action(doctorAction);

nextui.parseAsync(process.argv).catch(async (reason) => {
Expand Down

0 comments on commit eca2452

Please sign in to comment.