mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-02 08:58:36 +00:00
feat: add v0 handling
This commit is contained in:
@@ -8,6 +8,7 @@ import { handleError } from "@/src/utils/handle-error"
|
||||
import { highlighter } from "@/src/utils/highlighter"
|
||||
import { logger } from "@/src/utils/logger"
|
||||
import { getRegistryIndex } from "@/src/utils/registry"
|
||||
import { updateAppIndex } from "@/src/utils/update-app-index"
|
||||
import { Command } from "commander"
|
||||
import prompts from "prompts"
|
||||
import { z } from "zod"
|
||||
@@ -102,6 +103,7 @@ export const add = new Command()
|
||||
})
|
||||
}
|
||||
|
||||
let shouldUpdateAppIndex = false
|
||||
if (errors[ERRORS.MISSING_DIR_OR_EMPTY_PROJECT]) {
|
||||
const { projectPath } = await createProject({
|
||||
cwd: options.cwd,
|
||||
@@ -122,6 +124,10 @@ export const add = new Command()
|
||||
silent: true,
|
||||
isNewProject: true,
|
||||
})
|
||||
|
||||
shouldUpdateAppIndex =
|
||||
options.components?.length === 1 &&
|
||||
!!options.components[0].match(/\/chat\/b\//)
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
@@ -131,6 +137,12 @@ export const add = new Command()
|
||||
}
|
||||
|
||||
await addComponents(options.components, config, options)
|
||||
|
||||
// If we're adding a single component and it's from the v0 registry,
|
||||
// let's update the app/page.tsx file to import the component.
|
||||
if (shouldUpdateAppIndex) {
|
||||
await updateAppIndex(options.components[0], config)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.break()
|
||||
handleError(error)
|
||||
|
||||
@@ -71,7 +71,9 @@ export async function createProject(
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const createSpinner = spinner(`Creating a new Next.js project.`).start()
|
||||
const createSpinner = spinner(
|
||||
`Creating a new Next.js project. This may take a few minutes.`
|
||||
).start()
|
||||
|
||||
// Note: pnpm fails here. Fallback to npx with --use-PACKAGE-MANAGER.
|
||||
const args = [
|
||||
@@ -100,7 +102,7 @@ export async function createProject(
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
createSpinner?.succeed()
|
||||
createSpinner?.succeed("Creating a new Next.js project.")
|
||||
|
||||
return {
|
||||
projectPath,
|
||||
|
||||
@@ -364,6 +364,12 @@ export async function registryGetTheme(name: string, config: Config) {
|
||||
|
||||
function getRegistryUrl(path: string) {
|
||||
if (isUrl(path)) {
|
||||
// If the url contains /chat/b/, we assume it's the v0 registry.
|
||||
// We need to add the /json suffix if it's missing.
|
||||
if (path.match(/\/chat\/b\//) && !path.endsWith("/json")) {
|
||||
path = `${path}/json`
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ export const registryItemSchema = z.object({
|
||||
files: z.array(registryItemFileSchema).optional(),
|
||||
tailwind: registryItemTailwindSchema.optional(),
|
||||
cssVars: registryItemCssVarsSchema.optional(),
|
||||
meta: z.record(z.string(), z.any()).optional(),
|
||||
})
|
||||
|
||||
export type RegistryItem = z.infer<typeof registryItemSchema>
|
||||
|
||||
24
packages/cli/src/utils/update-app-index.ts
Normal file
24
packages/cli/src/utils/update-app-index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { getRegistryItem } from "@/src/utils/registry"
|
||||
|
||||
export async function updateAppIndex(component: string, config: Config) {
|
||||
const indexPath = path.join(config.resolvedPaths.cwd, "app/page.tsx")
|
||||
|
||||
if (!(await fs.stat(indexPath)).isFile()) {
|
||||
return
|
||||
}
|
||||
|
||||
const registryItem = await getRegistryItem(component, config.style)
|
||||
if (
|
||||
!registryItem?.meta?.importSpecifier ||
|
||||
!registryItem?.meta?.moduleSpecifier
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// Overwrite the index file with the new import.
|
||||
const content = `import { ${registryItem?.meta?.importSpecifier} } from "${registryItem.meta.moduleSpecifier}"\n\nexport default function Page() {\n return <${registryItem?.meta?.importSpecifier} />\n}`
|
||||
await fs.writeFile(indexPath, content, "utf8")
|
||||
}
|
||||
Reference in New Issue
Block a user