refactor(cli): destinations

This commit is contained in:
shadcn
2024-08-18 11:44:19 +04:00
parent 76738a9187
commit 33595c7d21
10 changed files with 71 additions and 64 deletions

View File

@@ -60,7 +60,6 @@
"lodash.template": "^4.5.0",
"node-fetch": "^3.3.0",
"ora": "^6.1.2",
"prettier": "^2.8.8",
"prompts": "^2.4.2",
"recast": "^0.23.2",
"stringify-object": "^5.0.0",

View File

@@ -1,4 +1,4 @@
import { existsSync, promises as fs } from "fs"
import { promises as fs } from "fs"
import path from "path"
import {
DEFAULT_COMPONENTS,
@@ -10,9 +10,10 @@ import {
resolveConfigPaths,
type Config,
} from "@/src/utils/get-config"
import { getPackageManager } from "@/src/utils/get-package-manager"
import { getProjectConfig } from "@/src/utils/get-project-info"
import { handleError } from "@/src/utils/handle-error"
import { initializeDependencies } from "@/src/utils/initializers/initialize-dependencies"
import { initializeDestinations } from "@/src/utils/initializers/initialize-destinations"
import { initializeTailwindConfig } from "@/src/utils/initializers/initialize-tailwind-config"
import { initializeTailwindCss } from "@/src/utils/initializers/initialize-tailwind-css"
import { initializeUtils } from "@/src/utils/initializers/initialize-utils"
@@ -21,18 +22,10 @@ import { preFlight } from "@/src/utils/preflight"
import { getRegistryBaseColors, getRegistryStyles } from "@/src/utils/registry"
import chalk from "chalk"
import { Command } from "commander"
import { execa } from "execa"
import ora from "ora"
import prompts from "prompts"
import { z } from "zod"
const PROJECT_DEPENDENCIES = [
"tailwindcss-animate",
"class-variance-authority",
"clsx",
"tailwind-merge",
]
const initOptionsSchema = z.object({
cwd: z.string(),
yes: z.boolean(),
@@ -53,7 +46,7 @@ export const init = new Command()
try {
const options = initOptionsSchema.parse(opts)
const cwd = path.resolve(options.cwd)
const { errors, projectInfo } = await preFlight(cwd)
const { errors } = await preFlight(cwd)
if (Object.keys(errors).length > 0) {
logger.error(
@@ -70,7 +63,7 @@ export const init = new Command()
: // Otherwise, prompt for full config.
await promptForConfig(cwd, await getConfig(cwd), options.yes)
await runInit(cwd, config)
await runInit(config)
logger.info("")
logger.info(
@@ -300,27 +293,8 @@ export async function promptForMinimalConfig(
return await resolveConfigPaths(cwd, config)
}
export async function runInit(cwd: string, config: Config) {
// Ensure all resolved paths directories exist.
for (const [key, resolvedPath] of Object.entries(config.resolvedPaths)) {
// Determine if the path is a file or directory.
// TODO: is there a better way to do this?
let dirname = path.extname(resolvedPath)
? path.dirname(resolvedPath)
: resolvedPath
// If the utils alias is set to something like "@/lib/utils",
// assume this is a file and remove the "utils" file name.
// TODO: In future releases we should add support for individual utils.
if (key === "utils" && resolvedPath.endsWith("/utils")) {
// Remove /utils at the end.
dirname = dirname.replace(/\/utils$/, "")
}
if (!existsSync(dirname)) {
await fs.mkdir(dirname, { recursive: true })
}
}
export async function runInit(config: Config) {
await initializeDestinations(config)
// Run initializers.
const initializersSpinner = ora(`Initializing project...`)?.start()
@@ -331,20 +305,6 @@ export async function runInit(cwd: string, config: Config) {
// Install dependencies.
const dependenciesSpinner = ora(`Installing dependencies...`)?.start()
const packageManager = await getPackageManager(cwd)
// TODO: add support for other icon libraries.
const deps = [
...PROJECT_DEPENDENCIES,
config.style === "new-york" ? "@radix-ui/react-icons" : "lucide-react",
]
await execa(
packageManager,
[packageManager === "npm" ? "install" : "add", ...deps],
{
cwd,
}
)
await initializeDependencies(config)
dependenciesSpinner?.succeed()
}

View File

@@ -1,10 +0,0 @@
import prettier from "prettier"
export async function formatCode(code: string, filepath: string) {
const config = await prettier.resolveConfig(filepath)
return await prettier.format(code, {
...config,
filepath,
parser: "typescript",
})
}

View File

@@ -42,6 +42,7 @@ export type RawConfig = z.infer<typeof rawConfigSchema>
export const configSchema = rawConfigSchema.extend({
resolvedPaths: z.object({
cwd: z.string(),
tailwindConfig: z.string(),
tailwindCss: z.string(),
utils: z.string(),
@@ -77,6 +78,7 @@ export async function resolveConfigPaths(cwd: string, config: RawConfig) {
return configSchema.parse({
...config,
resolvedPaths: {
cwd,
tailwindConfig: path.resolve(cwd, config.tailwind.config),
tailwindCss: path.resolve(cwd, config.tailwind.css),
utils: await resolveImport(config.aliases["utils"], tsConfig),

View File

@@ -0,0 +1,29 @@
import { Config } from "@/src/utils/get-config"
import { getPackageManager } from "@/src/utils/get-package-manager"
import { execa } from "execa"
const PROJECT_DEPENDENCIES = [
"tailwindcss-animate",
"class-variance-authority",
"clsx",
"tailwind-merge",
]
export async function initializeDependencies(config: Config) {
const packageManager = await getPackageManager(config.resolvedPaths.cwd)
const dependencies = [
...PROJECT_DEPENDENCIES,
// TODO: add support for other icon libraries.
// TODO: remove this when we migrate new-york to lucide-react.
config.style === "new-york" ? "@radix-ui/react-icons" : "lucide-react",
]
await execa(
packageManager,
[packageManager === "npm" ? "install" : "add", ...dependencies],
{
cwd: config.resolvedPaths.cwd,
}
)
}

View File

@@ -0,0 +1,26 @@
import { existsSync, promises as fs } from "fs"
import path from "path"
import { Config } from "@/src/utils/get-config"
export async function initializeDestinations(config: Config) {
// Ensure all resolved paths directories exist.
for (const [key, resolvedPath] of Object.entries(config.resolvedPaths)) {
// Determine if the path is a file or directory.
// TODO: is there a better way to do this?
let dirname = path.extname(resolvedPath)
? path.dirname(resolvedPath)
: resolvedPath
// If the utils alias is set to something like "@/lib/utils",
// assume this is a file and remove the "utils" file name.
// TODO: In future releases we should add support for individual utils.
if (key === "utils" && resolvedPath.endsWith("/utils")) {
// Remove /utils at the end.
dirname = dirname.replace(/\/utils$/, "")
}
if (!existsSync(dirname)) {
await fs.mkdir(dirname, { recursive: true })
}
}
}

View File

@@ -31,7 +31,7 @@ test("init config-full", async () => {
const targetDir = path.resolve(__dirname, "../fixtures/config-full")
const config = await getConfig(targetDir)
await runInit(targetDir, config)
await runInit(config)
expect(mockMkdir).toHaveBeenNthCalledWith(
1,
@@ -95,7 +95,7 @@ test("init config-partial", async () => {
const targetDir = path.resolve(__dirname, "../fixtures/config-partial")
const config = await getConfig(targetDir)
await runInit(targetDir, config)
await runInit(config)
expect(mockMkdir).toHaveBeenNthCalledWith(
1,

View File

@@ -57,6 +57,7 @@ test("get config", async () => {
utils: "@/lib/utils",
},
resolvedPaths: {
cwd: path.resolve(__dirname, "../fixtures/config-partial"),
tailwindConfig: path.resolve(
__dirname,
"../fixtures/config-partial",
@@ -99,6 +100,7 @@ test("get config", async () => {
utils: "~/lib/utils",
},
resolvedPaths: {
cwd: path.resolve(__dirname, "../fixtures/config-full"),
tailwindConfig: path.resolve(
__dirname,
"../fixtures/config-full",
@@ -144,6 +146,7 @@ test("get config", async () => {
utils: "@/lib/utils",
},
resolvedPaths: {
cwd: path.resolve(__dirname, "../fixtures/config-jsx"),
tailwindConfig: path.resolve(
__dirname,
"../fixtures/config-jsx",

View File

@@ -3,6 +3,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"isolatedModules": false,
"resolveJsonModule": true,
"baseUrl": ".",
"paths": {
"@/*": ["./*"]

3
pnpm-lock.yaml generated
View File

@@ -424,9 +424,6 @@ importers:
ora:
specifier: ^6.1.2
version: 6.1.2
prettier:
specifier: ^2.8.8
version: 2.8.8
prompts:
specifier: ^2.4.2
version: 2.4.2