diff --git a/.changeset/swift-eyes-dress.md b/.changeset/swift-eyes-dress.md new file mode 100644 index 00000000000..e4d09d95407 --- /dev/null +++ b/.changeset/swift-eyes-dress.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +new registry:file type diff --git a/apps/www/lib/registry.ts b/apps/www/lib/registry.ts index 390f87e688f..ba1243d1189 100644 --- a/apps/www/lib/registry.ts +++ b/apps/www/lib/registry.ts @@ -157,7 +157,7 @@ function getFileTarget(file: z.infer) { } } - return target + return target ?? "" } async function createTempSourceFile(filename: string) { diff --git a/apps/www/public/registry.json b/apps/www/public/registry.json index d5aab0a9882..ce32326b04e 100644 --- a/apps/www/public/registry.json +++ b/apps/www/public/registry.json @@ -14,7 +14,8 @@ "registry:ui", "registry:hook", "registry:theme", - "registry:page" + "registry:page", + "registry:file" ] }, "description": { diff --git a/apps/www/public/schema/registry-item.json b/apps/www/public/schema/registry-item.json index ee8c10b9148..8d4fd3e241c 100644 --- a/apps/www/public/schema/registry-item.json +++ b/apps/www/public/schema/registry-item.json @@ -14,7 +14,8 @@ "registry:ui", "registry:hook", "registry:theme", - "registry:page" + "registry:page", + "registry:file" ] }, "description": { @@ -64,14 +65,27 @@ "registry:ui", "registry:hook", "registry:theme", - "registry:page" + "registry:page", + "registry:file" ] }, "target": { "type": "string" } }, - "required": ["path", "type"] + "if": { + "properties": { + "type": { + "enum": ["registry:file", "registry:page"] + } + } + }, + "then": { + "required": ["path", "type", "target"] + }, + "else": { + "required": ["path", "type"] + } } }, "tailwind": { diff --git a/packages/shadcn/src/registry/schema.ts b/packages/shadcn/src/registry/schema.ts index c6ad858c134..e4a7cac21fa 100644 --- a/packages/shadcn/src/registry/schema.ts +++ b/packages/shadcn/src/registry/schema.ts @@ -9,21 +9,31 @@ export const registryItemTypeSchema = z.enum([ "registry:component", "registry:ui", "registry:hook", - "registry:theme", "registry:page", + "registry:file", // Internal use only + "registry:theme", "registry:example", "registry:style", "registry:internal", ]) -export const registryItemFileSchema = z.object({ - path: z.string(), - content: z.string().optional(), - type: registryItemTypeSchema, - target: z.string().optional(), -}) +export const registryItemFileSchema = z.discriminatedUnion("type", [ + // Target is required for registry:file and registry:page + z.object({ + path: z.string(), + content: z.string().optional(), + type: z.enum(["registry:file", "registry:page"]), + target: z.string(), + }), + z.object({ + path: z.string(), + content: z.string().optional(), + type: registryItemTypeSchema.exclude(["registry:file", "registry:page"]), + target: z.string().optional(), + }), +]) export const registryItemTailwindSchema = z.object({ config: z diff --git a/packages/shadcn/test/utils/updaters/update-files.test.ts b/packages/shadcn/test/utils/updaters/update-files.test.ts index c605c357896..d0f76c8bdc4 100644 --- a/packages/shadcn/test/utils/updaters/update-files.test.ts +++ b/packages/shadcn/test/utils/updaters/update-files.test.ts @@ -79,7 +79,7 @@ describe("resolveFilePath", () => { description: "should NOT use src directory for root files", file: { path: "hello-world/.env", - type: "registry:lib", + type: "registry:file", target: "~/.env", }, resolvedPath: "/foo/bar/.env", @@ -347,6 +347,26 @@ describe("resolveFilePath", () => { ).toBe("/foo/bar/src/hooks/use-foo.ts") }) + test("should resolve registry:file file types", () => { + expect( + resolveFilePath( + { + path: "hello-world/.env", + type: "registry:file", + target: "~/baz/.env", + }, + { + resolvedPaths: { + cwd: "/foo/bar", + }, + }, + { + isSrcDir: false, + } + ) + ).toBe("/foo/bar/baz/.env") + }) + test("should resolve nested files", () => { expect( resolveFilePath(