mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-30 16:14:13 +00:00
refactor(cli): destinations
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
})
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": false,
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user