diff --git a/package.json b/package.json index ca84f8d2a..51812e7af 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@babel/plugin-transform-typescript": "^7.10.5", "@babel/preset-env": "^7.4.5", "@babel/preset-react": "^7.0.0", + "@npmcli/arborist": "^9.1.1", "ansi-styles": "^4.0.0", "autoprefixer": "^10.0.1", "babel-jest": "^28.1.0", @@ -76,6 +77,7 @@ "minimist": "^1.2.0", "mkdirp": "^1.0.3", "node-fetch": "2.6.7", + "npm-packlist": "^10.0.0", "postcss": "^8.1.2", "postcss-loader": "^4.0.4", "prettier": "^2.0.1", diff --git a/src/lint/checkDiff.ts b/src/lint/checkDiff.ts index 7ced49d98..55bf46eaa 100644 --- a/src/lint/checkDiff.ts +++ b/src/lint/checkDiff.ts @@ -1,10 +1,11 @@ import { getProjectPath } from '../utils/projectHelper'; -import fs from 'fs'; import { join } from 'path'; import chalk from 'chalk'; import fetch from 'node-fetch'; import readline from 'readline'; import minimist from 'minimist'; +import Arborist from '@npmcli/arborist'; +import packlist from 'npm-packlist'; const argv = minimist(process.argv.slice(2)); @@ -41,27 +42,68 @@ export default function ( const mergedVersion = getMajorVersion(packageVersion, argv.version); console.log(chalk.cyan(`Fetching latest version file list...${packageName}${mergedVersion}`)); - fetch(`https://unpkg.com/${packageName}${mergedVersion}/?meta`) - .then(res => { - const version = getVersionFromURL(res.url, packageName); - return res.json().then((json: object) => ({ version, ...json })); + function getLatestVersionFileList() { + return fetch(`https://unpkg.com/${packageName}${mergedVersion}/?meta`) + .then(res => { + const version = getVersionFromURL(res.url, packageName); + return res.json().then((json: object) => ({ version, ...json })); + }) + .then(({ version, files: pkgFiles }: { version: string; files: FileItem[] }) => { + function flattenPath(files: FileItem[], fileList: string[] = []): string[] { + (files || []).forEach(({ path, files: subFiles }) => { + const realPath = argv.path ? join(argv.path, path) : path + fileList.push(realPath); + flattenPath(subFiles, fileList); + }); + return fileList; + } + return { version, fileList: flattenPath(pkgFiles) }; + }) + } + + function getLocalVersionFileList() { + const arborist = new Arborist({ path: getProjectPath() }); + return arborist.loadActual().then(packlist) as Promise; + } + + + Promise.all([ + getLocalVersionFileList(), + getLatestVersionFileList(), + ]) + .then(([localFiles, { version, fileList }]) => { + const localSet = new Set(localFiles); + const remoteSet = new Set(fileList); + + const missingFiles: string[] = []; + const addedFiles: string[] = []; + + const allFiles = new Set([...fileList, ...localFiles]); + allFiles.forEach(filePath => { + if (!localSet.has(filePath)) { + missingFiles.push(filePath); + } else if (!remoteSet.has(filePath)) { + addedFiles.push(filePath); + } + }); + return { missingFiles, addedFiles, version }; }) - .then(({ version, files: pkgFiles }: { version: string; files: FileItem[] }) => { - function flattenPath(files: FileItem[], fileList: string[] = []): string[] { - (files || []).forEach(({ path, files: subFiles }) => { - fileList.push(path); - flattenPath(subFiles, fileList); + .then(({ missingFiles, addedFiles, version }) => { + + + if (addedFiles.length) { + console.log( + chalk.yellow(`⚠️ Some file added in current build (last version: ${version}):`) + ); + addedFiles.forEach(filePath => { + console.log(` + ${filePath}`); }); - return fileList; - } - return { version, fileList: flattenPath(pkgFiles) }; - }) - .then(({ version, fileList }) => { - const missingFiles = fileList.filter(filePath => { - const concatFilePath = argv.path ? join(argv.path, filePath) : filePath; - return !fs.existsSync(getProjectPath(concatFilePath)); - }); + // Separator + console.log(); + console.log(chalk.gray(`-`.repeat(process.stdout.columns || 64))); + console.log(); + } if (missingFiles.length) { console.log( @@ -70,12 +112,18 @@ export default function ( missingFiles.forEach(filePath => { console.log(` - ${filePath}`); }); - return Promise.reject('Please double confirm with files.'); } + const total = missingFiles.length + addedFiles.length; + + if (total) { + return Promise.reject( + new Error(`Please double confirm with files. ${missingFiles.length} missing, ${addedFiles.length} added.`) + ); + } console.log( chalk.green('✅ Nothing missing compare to latest version:'), - chalk.yellow(version) + chalk.gray(version) ); return 0; })