From e29f8f5780fe67da66b8fcec7c46a270866fef16 Mon Sep 17 00:00:00 2001 From: Aidan Bleser <117548273+ieedan@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:43:06 -0600 Subject: [PATCH] fix(next): Update command doesn't update component code (#1421) Co-authored-by: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> fixes #1368 --- .changeset/loud-flies-smoke.md | 5 + .changeset/tricky-trains-suffer.md | 5 + packages/cli/src/commands/update.ts | 18 +++- packages/cli/src/utils/registry/index.ts | 12 +-- .../cli/test/utils/registry/index.spec.ts | 94 +++++++++++++++++++ 5 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 .changeset/loud-flies-smoke.md create mode 100644 .changeset/tricky-trains-suffer.md create mode 100644 packages/cli/test/utils/registry/index.spec.ts diff --git a/.changeset/loud-flies-smoke.md b/.changeset/loud-flies-smoke.md new file mode 100644 index 000000000..4cc299cae --- /dev/null +++ b/.changeset/loud-flies-smoke.md @@ -0,0 +1,5 @@ +--- +"shadcn-svelte": patch +--- + +fix: Ensure `utils.(js|ts)` is not fetched from the registry on `update` command diff --git a/.changeset/tricky-trains-suffer.md b/.changeset/tricky-trains-suffer.md new file mode 100644 index 000000000..f26db5150 --- /dev/null +++ b/.changeset/tricky-trains-suffer.md @@ -0,0 +1,5 @@ +--- +"shadcn-svelte": patch +--- + +fix: `update` command now properly updates components diff --git a/packages/cli/src/commands/update.ts b/packages/cli/src/commands/update.ts index 8712b3f57..81bc72e2e 100644 --- a/packages/cli/src/commands/update.ts +++ b/packages/cli/src/commands/update.ts @@ -149,8 +149,14 @@ async function runUpdate(cwd: string, config: cliConfig.Config, options: UpdateO if (p.isCancel(proceed) || proceed === false) cancel(); } + const tasks: p.Task[] = []; + + const utils = selectedComponents.find((item) => item.name === "utils"); // `update utils` - update the utils.(ts|js) file - if (selectedComponents.find((item) => item.name === "utils")) { + if (utils) { + // remove utils so that it isn't fetched from the registry + selectedComponents = selectedComponents.filter((item) => item !== utils); + const extension = config.typescript ? ".ts" : ".js"; const utilsPath = config.resolvedPaths.utils + extension; @@ -158,8 +164,13 @@ async function runUpdate(cwd: string, config: cliConfig.Config, options: UpdateO throw error(`Failed to find ${highlight("utils")} at ${color.cyan(utilsPath)}`); } - // utils.(ts|js) is not in the registry, it is a template, so we'll just overwrite it - await fs.writeFile(utilsPath, config.typescript ? UTILS : UTILS_JS); + tasks.push({ + title: `Updating ${highlight(utilsPath)}`, + async task() { + // utils.(ts|js) is not in the registry, it is a template, so we'll just overwrite it + await fs.writeFile(utilsPath, config.typescript ? UTILS : UTILS_JS); + }, + }); } const tree = await registry.resolveTree({ @@ -173,7 +184,6 @@ async function runUpdate(cwd: string, config: cliConfig.Config, options: UpdateO const componentsToRemove: Record = {}; const dependencies = new Set(); - const tasks: p.Task[] = []; for (const item of payload) { const targetDir = registry.getItemTargetPath(config, item); if (!targetDir) { diff --git a/packages/cli/src/utils/registry/index.ts b/packages/cli/src/utils/registry/index.ts index 7c9dd4cab..10ecc24b8 100644 --- a/packages/cli/src/utils/registry/index.ts +++ b/packages/cli/src/utils/registry/index.ts @@ -121,7 +121,7 @@ export async function fetchTree(config: Config, tree: RegistryIndex) { export function getItemTargetPath( config: Config, - item: Pick, "type">, + item: v.InferOutput, override?: string ) { // Allow overrides for all items but ui. @@ -129,14 +129,10 @@ export function getItemTargetPath( return override; } - const [parent, type] = item.type.split(":"); - if (!parent || !type) return null; + const [, type] = item.type.split(":"); + if (!type || !(type in config.resolvedPaths)) return null; - if (!(parent in config.resolvedPaths)) { - return null; - } - - return path.join(config.resolvedPaths[parent as keyof typeof config.resolvedPaths], type); + return path.join(config.resolvedPaths[type as keyof typeof config.resolvedPaths]); } async function fetchRegistry(paths: string[]) { diff --git a/packages/cli/test/utils/registry/index.spec.ts b/packages/cli/test/utils/registry/index.spec.ts new file mode 100644 index 000000000..ed2e91991 --- /dev/null +++ b/packages/cli/test/utils/registry/index.spec.ts @@ -0,0 +1,94 @@ +import { describe, expect, it } from "vitest"; +import { getItemTargetPath } from "../../../src/utils/registry/index"; +import { SITE_BASE_URL } from "../../../src/constants"; + +const config = { + style: "new-york", + tailwind: { + config: "tailwind.config.js", + css: "src/app.pcss", + baseColor: "zinc", + }, + aliases: { + utils: "$lib/utils", + components: "$lib/components", + hooks: "$lib/hooks", + ui: "$lib/components/ui", + }, + // not how they will look in the end but works for the tests + resolvedPaths: { + components: "./src/lib/components", + tailwindConfig: "./tailwind.config.js", + tailwindCss: "./src/app.pcss", + utils: "./src/lib/utils", + cwd: "./", + hooks: "./src/lib/hooks", + ui: "./src/lib/components/ui", + }, + typescript: true, + registry: `${SITE_BASE_URL}/registry`, +}; + +describe("getItemTargetPath", () => { + it("returns null if invalid type missing `:`", async () => { + expect( + getItemTargetPath(config, { + name: "label", + dependencies: ["bits-ui@next"], + registryDependencies: [], + files: [ + //... snip this since it doesn't matter + ], + // @ts-expect-error Comes from over the wire in prod + type: "registry", + }) + ).toEqual(null); + }); + + it("returns null if `item.type` has invalid `:`", async () => { + expect( + getItemTargetPath(config, { + name: "label", + dependencies: ["bits-ui@next"], + registryDependencies: [], + files: [ + //... snip this since it doesn't matter + ], + // @ts-expect-error Comes from over the wire in prod + type: "registry:foo", + }) + ).toEqual(null); + }); + + it("disallows overrides for `registry:ui`", async () => { + expect( + getItemTargetPath( + config, + { + name: "label", + dependencies: ["bits-ui@next"], + registryDependencies: [], + files: [ + //... snip this since it doesn't matter + ], + type: "registry:ui", + }, + "./override-path" + ) + ).toEqual("src/lib/components/ui"); + }); + + it("resolves item target path", async () => { + expect( + getItemTargetPath(config, { + name: "label", + dependencies: ["bits-ui@next"], + registryDependencies: [], + files: [ + //... snip this since it doesn't matter + ], + type: "registry:ui", + }) + ).toEqual("src/lib/components/ui"); + }); +});