@upleveled/preflight 1.23.8 → 2.1.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ import { sep } from 'node:path';
2
+ import { execaCommand } from 'execa';
3
+ import { LintResult } from 'stylelint';
4
+
5
+ const errorKey = 'errored' as const;
6
+
7
+ export const supportedStylelintFileExtensions = [
8
+ 'css',
9
+ 'sass',
10
+ 'scss',
11
+ 'less',
12
+ 'js',
13
+ 'tsx',
14
+ 'jsx',
15
+ ];
16
+
17
+ export const title = 'Stylelint';
18
+
19
+ export default async function stylelintCheck() {
20
+ try {
21
+ await execaCommand(
22
+ `pnpm stylelint **/*.{${supportedStylelintFileExtensions.join(
23
+ ',',
24
+ )}} --max-warnings 0 --formatter json`,
25
+ );
26
+ } catch (error) {
27
+ const { stdout } = error as { stdout: string };
28
+
29
+ // If no Stylelint errors detected, throw the error
30
+ if (!new RegExp(`"${errorKey}":`).test(stdout)) {
31
+ throw error;
32
+ }
33
+
34
+ throw new Error(
35
+ `Stylelint problems found in the following files:
36
+ ${(JSON.parse(stdout) as LintResult[])
37
+ .filter((stylelintResult) => stylelintResult[errorKey] === true)
38
+ // Make paths relative to the project:
39
+ // before: /home/projects/random-color-generator-react-app/src/index.css
40
+ // after: src/index.css
41
+ .map(({ source }) => source!.replace(`${process.cwd()}${sep}`, ''))
42
+ .join('\n')}
43
+
44
+ Open these files in your editor - there should be problems to fix
45
+ `,
46
+ );
47
+ }
48
+ }
@@ -0,0 +1,92 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { execaCommand } from 'execa';
4
+ import readdirp from 'readdirp';
5
+ import semver from 'semver';
6
+ import { supportedStylelintFileExtensions } from './stylelint';
7
+
8
+ const require = createRequire(`${process.cwd()}/`);
9
+
10
+ export const title = 'Stylelint config is latest version';
11
+
12
+ export default async function stylelintConfigIsValid() {
13
+ const { stdout: remoteVersion } = await execaCommand(
14
+ 'npm show stylelint-config-upleveled version',
15
+ );
16
+
17
+ let localVersion;
18
+
19
+ try {
20
+ const stylelintConfigPackageJsonPath = require.resolve(
21
+ 'stylelint-config-upleveled/package.json',
22
+ );
23
+
24
+ localVersion = JSON.parse(
25
+ await fs.readFile(stylelintConfigPackageJsonPath, 'utf-8'),
26
+ ).version;
27
+ } catch (err) {}
28
+
29
+ if (typeof localVersion === 'undefined') {
30
+ throw new Error(
31
+ `The UpLeveled Stylelint Config has not been installed - please install using the instructions on https://www.npmjs.com/package/eslint-config-upleveled
32
+ `,
33
+ );
34
+ }
35
+
36
+ if (semver.gt(remoteVersion, localVersion)) {
37
+ throw new Error(
38
+ `Your current version of the UpLeveled Stylelint Config (${localVersion}) is older than the latest version ${remoteVersion} - upgrade by running:
39
+
40
+ pnpm add stylelint-config-upleveled@${remoteVersion}`,
41
+ );
42
+ }
43
+
44
+ let stylelintConfigMatches;
45
+
46
+ try {
47
+ stylelintConfigMatches =
48
+ (await fs.readFile('./stylelint.config.cjs', 'utf-8')).trim() ===
49
+ `/** @type { import('stylelint').Config } */
50
+ const config = {
51
+ extends: ['stylelint-config-upleveled'],
52
+ };
53
+
54
+ module.exports = config;`;
55
+ } catch (err) {
56
+ throw new Error(
57
+ `Error reading your stylelint.config.cjs file - please delete the file if it exists and reinstall the config using the instructions on https://www.npmjs.com/package/eslint-config-upleveled
58
+ `,
59
+ );
60
+ }
61
+
62
+ if (!stylelintConfigMatches) {
63
+ throw new Error(
64
+ `Your stylelint.config.cjs file does not match the configuration file template - please delete the file and reinstall the config using the instructions on https://www.npmjs.com/package/eslint-config-upleveled
65
+ `,
66
+ );
67
+ }
68
+
69
+ const stylelintDisableOccurrences = [];
70
+
71
+ for await (const { path } of readdirp('.', {
72
+ directoryFilter: ['!.git', '!.next', '!node_modules'],
73
+ fileFilter: supportedStylelintFileExtensions.map(
74
+ (fileExtension) => `*.${fileExtension}`,
75
+ ),
76
+ })) {
77
+ const fileContents = await fs.readFile(path, 'utf-8');
78
+ if (fileContents.includes('stylelint-disable')) {
79
+ stylelintDisableOccurrences.push(path);
80
+ }
81
+ }
82
+
83
+ if (stylelintDisableOccurrences.length > 0) {
84
+ throw new Error(
85
+ `Stylelint has been disabled in the following files:
86
+ ${stylelintDisableOccurrences.join('\n')}
87
+
88
+ Remove all comments disabling or modifying Stylelint rule configuration (eg. stylelint-disable and stylelint-disable-next-line comments) and fix the problems
89
+ `,
90
+ );
91
+ }
92
+ }
@@ -4,11 +4,13 @@ import commandExample from '../util/commandExample';
4
4
  export const title = 'Use single package manager';
5
5
 
6
6
  export default async function useSinglePackageManager() {
7
- const { stdout } = await execaCommand('git ls-files package-lock.json');
7
+ const { stdout } = await execaCommand(
8
+ 'git ls-files package-lock.json yarn.lock',
9
+ );
8
10
 
9
11
  if (stdout !== '') {
10
12
  throw new Error(
11
- `package-lock.json file committed to Git. Remove it with:
13
+ `package-lock.json or yarn.lock file committed to Git. Remove it with:
12
14
 
13
15
  ${commandExample('git rm --cached <filename>')}
14
16
 
@@ -16,9 +18,9 @@ export default async function useSinglePackageManager() {
16
18
 
17
19
  ${commandExample('rm <filename>')}
18
20
 
19
- The presence of this file indicates that npm was incorrectly used in addition to Yarn (eg. an "npm install" command was run). In order to avoid issues with the state of the yarn.lock file, we suggest also forcing regeneration this file with the following command:
21
+ The presence of this file indicates that another package manager was used in addition to pnpm (eg. "npm install" or "yarn add" was run). In order to avoid issues with the state of the pnpm-lock.yaml file, we suggest also forcing regeneration this file with the following command:
20
22
 
21
- ${commandExample('yarn --force')}
23
+ ${commandExample('pnpm install --force')}
22
24
  `,
23
25
  );
24
26
  }
package/src/index.ts CHANGED
@@ -12,6 +12,8 @@ import * as noSecretsCommittedToGit from './checks/noSecretsCommittedToGit.js';
12
12
  import * as preflightIsLatestVersion from './checks/preflightIsLatestVersion.js';
13
13
  import * as prettier from './checks/prettier.js';
14
14
  import * as projectFolderNameMatchesCorrectFormat from './checks/projectFolderNameMatchesCorrectFormat.js';
15
+ import * as stylelint from './checks/stylelint.js';
16
+ import * as stylelintConfigIsValid from './checks/stylelintConfigIsValid.js';
15
17
  import * as useSinglePackageManager from './checks/useSinglePackageManager.js';
16
18
  import { CtxParam } from './types/CtxParam.js';
17
19
  import { TaskParam } from './types/TaskParam.js';
@@ -20,6 +22,8 @@ import {
20
22
  projectPackageJson,
21
23
  } from './util/packageJson.js';
22
24
 
25
+ const projectDependencies = projectPackageJson.dependencies || {};
26
+
23
27
  console.log(`🚀 UpLeveled Preflight v${preflightPackageJson.version}`);
24
28
 
25
29
  const listrTasks = [
@@ -42,8 +46,7 @@ const listrTasks = [
42
46
  title: 'No dependency problems',
43
47
  task: (ctx: CtxParam, task: TaskParam): Listr =>
44
48
  task.newListr([
45
- ...(!projectPackageJson.dependencies ||
46
- !Object.keys(projectPackageJson.dependencies).includes('next')
49
+ ...(!Object.keys(projectDependencies).includes('next')
47
50
  ? []
48
51
  : [
49
52
  {
@@ -67,10 +70,22 @@ const listrTasks = [
67
70
 
68
71
  // Linting
69
72
  eslint,
73
+ ...(!(
74
+ '@upleveled/react-scripts' in projectDependencies ||
75
+ 'next' in projectDependencies
76
+ )
77
+ ? []
78
+ : [stylelint]),
70
79
  prettier,
71
80
 
72
81
  // Version and configuration checks
73
82
  eslintConfigIsValid,
83
+ ...(!(
84
+ '@upleveled/react-scripts' in projectDependencies ||
85
+ 'next' in projectDependencies
86
+ )
87
+ ? []
88
+ : [stylelintConfigIsValid]),
74
89
  preflightIsLatestVersion,
75
90
  ].map((module) => {
76
91
  if ('task' in module) return module;
@@ -2,7 +2,7 @@ import { dirname } from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { execaCommand } from 'execa';
4
4
 
5
- const { stdout: preflightBinPath } = await execaCommand(`yarn bin`, {
5
+ const { stdout: preflightBinPath } = await execaCommand(`pnpm bin`, {
6
6
  cwd: dirname(fileURLToPath(import.meta.url)),
7
7
  });
8
8
 
@@ -1,2 +0,0 @@
1
- export default App;
2
- declare function App(): JSX.Element;
@@ -1,2 +0,0 @@
1
- export default reportWebVitals;
2
- declare function reportWebVitals(onPerfEntry: import('web-vitals').ReportCallback | undefined): void;
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};