Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-papayas-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"shadcn-svelte": patch
---

fix: display correct path for utils file during init
11 changes: 11 additions & 0 deletions packages/cli/src/utils/add-registry-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export async function addRegistryItems(opts: AddRegistryItemsProps) {
: `Adding ${highlight(item.name)}`,
// @ts-expect-error this is intentional since we don't want to return a string during `init`
async task() {
let firstFilePath: string | undefined;
for (const file of item.files) {
let filePath = registry.resolveItemFilePath(opts.config, item, file);

Expand All @@ -135,6 +136,11 @@ export async function addRegistryItems(opts: AddRegistryItemsProps) {
filePath = filePath.replace(".ts", ".js");
}
await fs.writeFile(filePath, content, "utf8");

// Track the first file path for display purposes
if (!firstFilePath) {
firstFilePath = filePath;
}
}

if (item.cssVars) {
Expand All @@ -149,6 +155,11 @@ export async function addRegistryItems(opts: AddRegistryItemsProps) {
const itemPath = path.relative(cwd, opts.config.resolvedPaths.tailwindCss);
return `${highlight(item.name)} installed at ${color.gray(itemPath)}`;
}
// Use the actual file path that was written
if (item.name === "utils" && firstFilePath) {
const itemPath = path.relative(cwd, firstFilePath);
return `${highlight(item.name)} installed at ${color.gray(itemPath)}`;
}
const aliasDir = registry.getItemAliasDir(opts.config, item.type);
const itemPath = path.relative(cwd, path.resolve(aliasDir, item.name));
return `${highlight(item.name)} installed at ${color.gray(itemPath)}`;
Expand Down
59 changes: 59 additions & 0 deletions packages/cli/test/utils/add-registry-items.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
import * as registry from "../../src/utils/registry/index.js";
import { addRegistryItems } from "../../src/utils/add-registry-items.js";
import type { ResolvedConfig } from "../../src/utils/get-config";
import { toPosixPath } from "./test-helpers.js";

vi.mock("node:fs", () => ({
existsSync: vi.fn(),
Expand Down Expand Up @@ -184,4 +185,62 @@ describe("addRegistryItems", () => {
])
);
});

it("should display correct path for utils with custom location", async () => {
const utilsItem = {
name: "utils",
type: "registry:lib",
files: [
{ target: "utils.ts", type: "registry:lib", content: "export const cn = () => {}" },
],
} satisfies ResolvedRegistryItem;

// Mock config with custom utils path
const customConfig = {
...mockConfig,
resolvedPaths: {
...mockConfig.resolvedPaths,
utils: "/test/custom/path/shadcn-utils",
},
};

vi.mocked(existsSync).mockReturnValue(false);

vi.mocked(registry.resolveRegistryItems).mockResolvedValue([utilsItem]);
vi.mocked(registry.fetchRegistryItems).mockResolvedValue([utilsItem]);

// Simulate the actual behavior of resolveItemFilePath for utils
vi.mocked(registry.resolveItemFilePath).mockImplementation((config, item, _file) => {
if (item.name === "utils") {
const utils = config.resolvedPaths.utils;
if (utils.match(/.*\.(ts|js)$/)) return utils;
else return `${utils}.ts`;
}
return "/default/path";
});
vi.mocked(registry.getItemAliasDir).mockReturnValue("/test/lib");

// Capture the task that gets executed
let taskResult: string | undefined;
vi.mocked(p.tasks).mockImplementation(async (tasks) => {
for (const task of tasks) {
if (typeof task.task === "function") {
taskResult = await task.task();
}
}
});

await addRegistryItems({
selectedItems: ["utils"],
config: customConfig,
overwrite: false,
deps: true,
});

// Verify that the displayed path matches the actual file path written
// Normalize paths for cross-platform compatibility
expect(toPosixPath(taskResult ?? "")).toContain("custom/path/shadcn-utils.ts");
// Verify it doesn't use the default lib path
expect(toPosixPath(taskResult ?? "")).not.toContain("lib/utils");
});
});