Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add import order sorting via prettier #1392

Merged
merged 26 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cli/.prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/** @type {import('prettier').Config} */
const config = {
...require("../.prettierrc.cjs"),
plugins: [require.resolve("prettier-plugin-tailwindcss")],
plugins: [
require.resolve("@ianvs/prettier-plugin-sort-imports"),
require.resolve("prettier-plugin-tailwindcss"),
],
tailwindConfig: "./template/extras/config/tailwind.config.ts",
};

Expand Down
5 changes: 3 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"start": "node dist/index.js",
"lint": "eslint . --report-unused-disable-directives",
"lint:fix": "pnpm lint --fix",
"format": "prettier --write --plugin-search-dir=. **/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern",
"format:check": "pnpm format --check",
"format": "pnpm format:check --write",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does --write override the --check in the :check script?

bit cursed but i'll allow it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

P much

"format:check": "pnpm prettier --check --plugin-search-dir=. **/*.{cjs,mjs,ts,tsx,md,json} --ignore-path ../.gitignore --ignore-unknown --no-error-on-unmatched-pattern",
"release": "changeset version",
"pub:beta": "pnpm build && npm publish --tag beta",
"pub:next": "pnpm build && npm publish --tag next",
Expand All @@ -51,6 +51,7 @@
"sort-package-json": "^2.4.1"
},
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^3.7.2",
"@prisma/client": "^4.11.0",
"@tanstack/react-query": "^4.28.0",
"@trpc/client": "^10.18.0",
Expand Down
15 changes: 13 additions & 2 deletions cli/src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { type AvailablePackages } from "~/installers/index.js";
import { availablePackages } from "~/installers/index.js";
import chalk from "chalk";
import { Command } from "commander";
import inquirer from "inquirer";
import { CREATE_T3_APP, DEFAULT_APP_NAME } from "~/consts.js";
import {
availablePackages,
type AvailablePackages,
} from "~/installers/index.js";
import { getVersion } from "~/utils/getT3Version.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";
import { logger } from "~/utils/logger.js";
Expand All @@ -15,6 +17,7 @@ interface CliFlags {
noInstall: boolean;
default: boolean;
importAlias: string;
strictEslintAndPrettier: boolean;

/** @internal Used in CI. */
CI: boolean;
Expand Down Expand Up @@ -47,6 +50,7 @@ const defaultOptions: CliResults = {
prisma: false,
nextAuth: false,
importAlias: "~/",
strictEslintAndPrettier: false,
},
};

Expand Down Expand Up @@ -114,6 +118,11 @@ export const runCli = async () => {
"Explicitly tell the CLI to use a custom import alias",
defaultOptions.flags.importAlias,
)
.option(
"-ep -eslint-pretteier",
"enable prettier and a strict eslint config",
defaultOptions.flags.strictEslintAndPrettier,
)
/** END CI-FLAGS */
.version(getVersion(), "-v, --version", "Display the version number")
.addHelpText(
Expand Down Expand Up @@ -153,6 +162,8 @@ export const runCli = async () => {
if (cliResults.flags.tailwind) cliResults.packages.push("tailwind");
if (cliResults.flags.prisma) cliResults.packages.push("prisma");
if (cliResults.flags.nextAuth) cliResults.packages.push("nextAuth");
if (cliResults.flags.strictEslintAndPrettier)
cliResults.packages.push("strictEslintAndPrettier");
}

// Explained below why this is in a try/catch block
Expand Down
2 changes: 1 addition & 1 deletion cli/src/helpers/createProject.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type PkgInstallerMap } from "~/installers/index.js";
import path from "path";
import { installPackages } from "~/helpers/installPackages.js";
import { scaffoldProject } from "~/helpers/scaffoldProject.js";
import { selectAppFile, selectIndexFile } from "~/helpers/selectBoilerplate.js";
import { type PkgInstallerMap } from "~/installers/index.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";

interface CreateProjectOptions {
Expand Down
4 changes: 2 additions & 2 deletions cli/src/helpers/installPackages.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import chalk from "chalk";
import ora from "ora";
import {
type InstallerOptions,
type PkgInstallerMap,
} from "~/installers/index.js";
import chalk from "chalk";
import ora from "ora";
import { logger } from "~/utils/logger.js";

type InstallPackagesOptions = {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/helpers/logNextSteps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type InstallerOptions } from "~/installers/index.js";
import { DEFAULT_APP_NAME } from "~/consts.js";
import { type InstallerOptions } from "~/installers/index.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";
import { logger } from "~/utils/logger.js";

Expand Down
2 changes: 1 addition & 1 deletion cli/src/helpers/scaffoldProject.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path from "path";
import chalk from "chalk";
import fs from "fs-extra";
import inquirer from "inquirer";
import ora from "ora";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { type InstallerOptions } from "~/installers/index.js";
import { logger } from "~/utils/logger.js";
Expand Down
4 changes: 2 additions & 2 deletions cli/src/helpers/selectBoilerplate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type InstallerOptions } from "~/installers/index.js";
import path from "path";
import fs from "fs-extra";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { type InstallerOptions } from "~/installers/index.js";

type SelectBoilerplateProps = Required<
Pick<InstallerOptions, "projectDir" | "packages">
Expand Down
29 changes: 15 additions & 14 deletions cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
#!/usr/bin/env node

import { type PackageJson } from "type-fest";
import path from "path";
import { installDependencies } from "./helpers/installDependencies.js";
import { getVersion } from "./utils/getT3Version.js";
import {
getNpmVersion,
renderVersionWarning,
} from "./utils/renderVersionWarning.js";
import fs from "fs-extra";
import path from "path";
import { type PackageJson } from "type-fest";
import { runCli } from "~/cli/index.js";
import { createProject } from "~/helpers/createProject.js";
import { initializeGit } from "~/helpers/git.js";
import { setImportAlias } from "~/helpers/setImportAlias.js";
import { logNextSteps } from "~/helpers/logNextSteps.js";
import { setImportAlias } from "~/helpers/setImportAlias.js";
import { buildPkgInstallerMap } from "~/installers/index.js";
import { logger } from "~/utils/logger.js";
import { parseNameAndPath } from "~/utils/parseNameAndPath.js";
import { renderTitle } from "~/utils/renderTitle.js";
import {
getNpmVersion,
renderVersionWarning,
} from "./utils/renderVersionWarning.js";
import { installDependencies } from "./helpers/installDependencies.js";
import { getVersion } from "./utils/getT3Version.js";

type CT3APackageJSON = PackageJson & {
ct3aMetadata?: {
Expand Down Expand Up @@ -68,10 +67,12 @@ const main = async () => {
}

// Rename _eslintrc.json to .eslintrc.json - we use _eslintrc.json to avoid conflicts with the monorepos linter
fs.renameSync(
path.join(projectDir, "_eslintrc.cjs"),
path.join(projectDir, ".eslintrc.cjs"),
);
if (fs.existsSync(path.join(projectDir, "_eslintrc.cjs"))) {
fs.renameSync(
path.join(projectDir, "_eslintrc.cjs"),
path.join(projectDir, ".eslintrc.cjs"),
);
}

if (!noGit) {
await initializeGit(projectDir);
Expand Down
3 changes: 3 additions & 0 deletions cli/src/installers/dependencyVersionMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,8 @@ export const dependencyVersionMap = {
"@trpc/next": "^10.18.0",
"@tanstack/react-query": "^4.28.0",
superjson: "1.12.2",

// strictEslintAndPrettier
"@ianvs/prettier-plugin-sort-imports": "^3.7.2",
} as const;
export type AvailableDependencies = keyof typeof dependencyVersionMap;
4 changes: 2 additions & 2 deletions cli/src/installers/envVars.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type Installer } from "~/installers/index.js";
import path from "path";
import fs from "fs-extra";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { type Installer } from "~/installers/index.js";

export const envVariablesInstaller: Installer = ({ projectDir, packages }) => {
const usingAuth = packages?.nextAuth.inUse;
Expand Down
8 changes: 7 additions & 1 deletion cli/src/installers/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { type PackageManager } from "~/utils/getUserPkgManager.js";
import { envVariablesInstaller } from "~/installers/envVars.js";
import { nextAuthInstaller } from "~/installers/nextAuth.js";
import { prismaInstaller } from "~/installers/prisma.js";
import { strictEsLintAndPrettier } from "~/installers/strictEslintAndPrettier.js";
import { tailwindInstaller } from "~/installers/tailwind.js";
import { trpcInstaller } from "~/installers/trpc.js";
import { type PackageManager } from "~/utils/getUserPkgManager.js";

// Turning this into a const allows the list to be iterated over for programatically creating prompt options
// Should increase extensability in the future
Expand All @@ -13,6 +14,7 @@ export const availablePackages = [
"tailwind",
"trpc",
"envVariables",
"strictEslintAndPrettier",
] as const;
export type AvailablePackages = (typeof availablePackages)[number];

Expand Down Expand Up @@ -56,4 +58,8 @@ export const buildPkgInstallerMap = (
inUse: true,
installer: envVariablesInstaller,
},
strictEslintAndPrettier: {
inUse: packages.includes("strictEslintAndPrettier"),
installer: strictEsLintAndPrettier,
},
});
6 changes: 3 additions & 3 deletions cli/src/installers/nextAuth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type Installer } from "~/installers/index.js";
import { type AvailableDependencies } from "~/installers/dependencyVersionMap.js";
import path from "path";
import fs from "fs-extra";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { type AvailableDependencies } from "~/installers/dependencyVersionMap.js";
import { type Installer } from "~/installers/index.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";

export const nextAuthInstaller: Installer = ({ projectDir, packages }) => {
Expand Down
6 changes: 3 additions & 3 deletions cli/src/installers/prisma.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type PackageJson } from "type-fest";
import { type Installer } from "~/installers/index.js";
import path from "path";
import fs from "fs-extra";
import path from "path";
import { type PackageJson } from "type-fest";
import { PKG_ROOT } from "~/consts.js";
import { type Installer } from "~/installers/index.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";

export const prismaInstaller: Installer = ({ projectDir, packages }) => {
Expand Down
41 changes: 41 additions & 0 deletions cli/src/installers/strictEslintAndPrettier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { type Installer } from "../installers/index.js";
import fs from "fs-extra";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";

export const strictEsLintAndPrettier: Installer = ({
projectDir,
packages,
}) => {
addPackageDependency({
projectDir,
dependencies: [
"prettier",
"@types/prettier",
"@ianvs/prettier-plugin-sort-imports",
],
devMode: true,
});

const configDir = path.join(PKG_ROOT, "template/extras/config");

fs.rmSync(path.join(projectDir, "_eslintrc.cjs"));
fs.copySync(
path.join(configDir, "_strict-eslintrc.cjs"),
path.join(projectDir, "_eslintrc.cjs"),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo we should have all or nothing, so if the installer isn't selected, no linter will be setup?


if (packages?.tailwind.inUse) {
// Include the congig with tailwind class ordering
fs.copySync(
path.join(configDir, "strict-prettier-with-tailwind.config.cjs"),
path.join(projectDir, "prettier.config.cjs"),
);
} else {
fs.copySync(
path.join(configDir, "_prettier.config.cjs"),
path.join(projectDir, "prettier.config.cjs"),
);
}
};
13 changes: 10 additions & 3 deletions cli/src/installers/tailwind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PKG_ROOT } from "~/consts.js";
import { type Installer } from "~/installers/index.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";

export const tailwindInstaller: Installer = ({ projectDir }) => {
export const tailwindInstaller: Installer = ({ projectDir, packages }) => {
addPackageDependency({
projectDir,
dependencies: [
Expand All @@ -26,7 +26,10 @@ export const tailwindInstaller: Installer = ({ projectDir }) => {
const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.cjs");
const postcssCfgDest = path.join(projectDir, "postcss.config.cjs");

const prettierSrc = path.join(extrasDir, "config/prettier.config.cjs");
const prettierSrc = path.join(
extrasDir,
"config/prettier-with-tailwind.config.cjs",
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can then remove prettier from here - keep all the prettier logic in the prettier-eslint installer.

const prettierDest = path.join(projectDir, "prettier.config.cjs");

const cssSrc = path.join(extrasDir, "src/styles/globals.css");
Expand All @@ -35,7 +38,11 @@ export const tailwindInstaller: Installer = ({ projectDir }) => {
fs.copySync(twCfgSrc, twCfgDest);
fs.copySync(postcssCfgSrc, postcssCfgDest);
fs.copySync(cssSrc, cssDest);
fs.copySync(prettierSrc, prettierDest);

// Let strictEslintAndPrettier install the prettier config
if (!packages?.strictEslintAndPrettier.inUse) {
fs.copySync(prettierSrc, prettierDest);
}

// Remove vanilla css file
const indexModuleCss = path.join(projectDir, "src/pages/index.module.css");
Expand Down
2 changes: 1 addition & 1 deletion cli/src/installers/trpc.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import fs from "fs-extra";
import path from "path";
import { PKG_ROOT } from "~/consts.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";
import { type Installer } from "~/installers/index.js";
import { addPackageDependency } from "~/utils/addPackageDependency.js";

export const trpcInstaller: Installer = ({ projectDir, packages }) => {
addPackageDependency({
Expand Down
4 changes: 2 additions & 2 deletions cli/src/utils/addPackageDependency.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import path from "path";
import fs from "fs-extra";
import path from "path";
import sortPackageJson from "sort-package-json";
import { type PackageJson } from "type-fest";
import {
dependencyVersionMap,
type AvailableDependencies,
} from "~/installers/dependencyVersionMap.js";
import sortPackageJson from "sort-package-json";

export const addPackageDependency = (opts: {
dependencies: AvailableDependencies[];
Expand Down
4 changes: 2 additions & 2 deletions cli/src/utils/getT3Version.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type PackageJson } from "type-fest";
import path from "path";
import fs from "fs-extra";
import path from "path";
import { type PackageJson } from "type-fest";
import { PKG_ROOT } from "~/consts.js";

export const getVersion = () => {
Expand Down
19 changes: 9 additions & 10 deletions cli/src/utils/renderVersionWarning.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { execSync } from "child_process";
import { getVersion } from "./getT3Version.js";
import { logger } from "./logger.js";
import { execSync } from "child_process";
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
* https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/LICENSE
*/
import https from "https";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wish import sorters didn't move imports when they are separated by actual code blocks...

is there a setting for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you can //prettier-ignore lines but thats about it :/


export const renderVersionWarning = (npmVersion: string) => {
const currentVersion = getVersion();
Expand Down Expand Up @@ -29,15 +37,6 @@ export const renderVersionWarning = (npmVersion: string) => {
console.log("");
};

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
* https://github.com/facebook/create-react-app/blob/main/packages/create-react-app/LICENSE
*/
import https from "https";

type DistTagsBody = {
latest: string;
};
Expand Down
Loading