From 46bab3ca3b9b65a4a7b5a260235e36ed961c80d2 Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Mon, 17 Feb 2025 09:29:54 -0600 Subject: [PATCH 01/11] chore(cli): Add peerDependency precondition to CLI --- packages/cli/package.json | 4 ++- packages/cli/src/commands/add.ts | 3 ++ packages/cli/src/commands/init.ts | 3 ++ packages/cli/src/commands/update.ts | 3 ++ packages/cli/src/utils/preconditions.ts | 41 +++++++++++++++++++++++++ pnpm-lock.yaml | 14 +++++++++ 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/utils/preconditions.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index 1bf06c981..02faa2f52 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -45,10 +45,12 @@ "commander": "^10.0.1", "execa": "^7.2.0", "is-unicode-supported": "^2.0.0", - "node-fetch-native": "^1.6.4" + "node-fetch-native": "^1.6.4", + "semver": "^7.7.1" }, "devDependencies": { "@types/node": "^18.19.22", + "@types/semver": "^7.5.8", "cross-env": "^7.0.3", "get-tsconfig": "^4.7.3", "ignore": "^5.3.1", diff --git a/packages/cli/src/commands/add.ts b/packages/cli/src/commands/add.ts index ded26e2e8..28fed83d6 100644 --- a/packages/cli/src/commands/add.ts +++ b/packages/cli/src/commands/add.ts @@ -14,6 +14,7 @@ import * as p from "../utils/prompts.js"; import * as registry from "../utils/registry/index.js"; import { transformImports } from "../utils/transformers.js"; import { resolveCommand } from "package-manager-detector/commands"; +import { checkPreconditions } from "../utils/preconditions.js"; const highlight = (...args: unknown[]) => color.bold.cyan(...args); @@ -64,6 +65,8 @@ export const add = new Command() registry.setRegistry(config.registry); + await checkPreconditions(cwd); + await runAdd(cwd, config, options); p.outro(`${color.green("Success!")} Component installation completed.`); diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index e35ee37e6..74715c01f 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -22,6 +22,7 @@ import { syncSvelteKit } from "../utils/sveltekit.js"; import * as templates from "../utils/templates.js"; import { resolveCommand } from "package-manager-detector/commands"; import { SITE_BASE_URL } from "../constants.js"; +import { checkPreconditions } from "../utils/preconditions.js"; const PROJECT_DEPENDENCIES = [ "tailwind-variants", @@ -80,6 +81,8 @@ export const init = new Command() throw error(`The path ${color.cyan(cwd)} does not exist. Please try again.`); } + await checkPreconditions(cwd); + // Read config. const existingConfig = await cliConfig.getConfig(cwd); const config = await promptForConfig(cwd, existingConfig, options); diff --git a/packages/cli/src/commands/update.ts b/packages/cli/src/commands/update.ts index 81bc72e2e..c8da94077 100644 --- a/packages/cli/src/commands/update.ts +++ b/packages/cli/src/commands/update.ts @@ -15,6 +15,7 @@ import * as registry from "../utils/registry/index.js"; import { UTILS, UTILS_JS } from "../utils/templates.js"; import { transformImports } from "../utils/transformers.js"; import { resolveCommand } from "package-manager-detector/commands"; +import { checkPreconditions } from "../utils/preconditions.js"; const highlight = (msg: string) => color.bold.cyan(msg); @@ -60,6 +61,8 @@ export const update = new Command() registry.setRegistry(config.registry); + await checkPreconditions(cwd); + await runUpdate(cwd, config, options); p.note( diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts new file mode 100644 index 000000000..164df6a0e --- /dev/null +++ b/packages/cli/src/utils/preconditions.ts @@ -0,0 +1,41 @@ +import color from "chalk"; +import semver from "semver"; +import { loadProjectPackageInfo } from "./get-package-info"; +import { log } from "./prompts"; + +const peerDependencies: Record = { + svelte: "5.x", + tailwindcss: "3.x", +}; + +export const checkPreconditions = (cwd: string) => { + const pkg = loadProjectPackageInfo(cwd); + + if (pkg.dependencies) { + for (const [name, version] of Object.entries(pkg.dependencies)) { + const peerDepVersion = peerDependencies[name]; + + if (!peerDepVersion || !version) continue; + + if (!semver.satisfies(version, peerDepVersion)) { + log.warn( + `This version of ${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` + ); + } + } + } + + if (pkg.devDependencies) { + for (const [name, version] of Object.entries(pkg.devDependencies)) { + const peerDepVersion = peerDependencies[name]; + + if (!peerDepVersion || !version) continue; + + if (!semver.satisfies(version, peerDepVersion)) { + log.warn( + `${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` + ); + } + } + } +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2d5226e4..5624a3853 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,10 +80,16 @@ importers: node-fetch-native: specifier: ^1.6.4 version: 1.6.4 + semver: + specifier: ^7.7.1 + version: 7.7.1 devDependencies: '@types/node': specifier: ^18.19.22 version: 18.19.22 + '@types/semver': + specifier: ^7.5.8 + version: 7.5.8 cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -3420,6 +3426,7 @@ packages: lodash.template@4.5.0: resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. lodash.templatesettings@4.2.0: resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} @@ -4391,6 +4398,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} @@ -9937,6 +9949,8 @@ snapshots: semver@7.6.3: {} + semver@7.7.1: {} + set-blocking@2.0.0: {} set-cookie-parser@2.6.0: {} From b73c617054b5fe78d3f621eaed396b0827cb7a7d Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Mon, 17 Feb 2025 09:32:42 -0600 Subject: [PATCH 02/11] refactor duplicated code --- packages/cli/src/utils/preconditions.ts | 27 ++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 164df6a0e..b955d34db 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -11,29 +11,24 @@ const peerDependencies: Record = { export const checkPreconditions = (cwd: string) => { const pkg = loadProjectPackageInfo(cwd); - if (pkg.dependencies) { - for (const [name, version] of Object.entries(pkg.dependencies)) { - const peerDepVersion = peerDependencies[name]; - - if (!peerDepVersion || !version) continue; - - if (!semver.satisfies(version, peerDepVersion)) { - log.warn( - `This version of ${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` - ); - } - } - } + checkDependencies(pkg.dependencies); + checkDependencies(pkg.devDependencies); +}; - if (pkg.devDependencies) { - for (const [name, version] of Object.entries(pkg.devDependencies)) { +/** Checks that all dependencies meet peer dependency requirements and logs a warning if they don't. + * + * @param dependencies + */ +const checkDependencies = (dependencies: Partial> | undefined) => { + if (dependencies) { + for (const [name, version] of Object.entries(dependencies)) { const peerDepVersion = peerDependencies[name]; if (!peerDepVersion || !version) continue; if (!semver.satisfies(version, peerDepVersion)) { log.warn( - `${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` + `This version of ${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` ); } } From e743f1a8dd51d75ac394c4e70622ddf11624960d Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Mon, 17 Feb 2025 09:36:13 -0600 Subject: [PATCH 03/11] update warning message --- packages/cli/src/utils/preconditions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index b955d34db..2f97082d3 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -28,7 +28,7 @@ const checkDependencies = (dependencies: Partial> | undef if (!semver.satisfies(version, peerDepVersion)) { log.warn( - `This version of ${color.bold("shadcn-svelte")} is intended for use with ${name}@${peerDepVersion}. Use at your own risk.` + `This version of ${color.bold("shadcn-svelte")} is intended for use with ${color.bold(`${name}@${peerDepVersion}`)}. Use at your own risk!` ); } } From 84db6bd12c29fa037e4206b51dc40f5f95e9ea03 Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Mon, 17 Feb 2025 09:41:33 -0600 Subject: [PATCH 04/11] Create blue-drinks-rush.md --- .changeset/blue-drinks-rush.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/blue-drinks-rush.md diff --git a/.changeset/blue-drinks-rush.md b/.changeset/blue-drinks-rush.md new file mode 100644 index 000000000..89e16e9c8 --- /dev/null +++ b/.changeset/blue-drinks-rush.md @@ -0,0 +1,5 @@ +--- +"shadcn-svelte": patch +--- + +chore: Add warning to Svelte 3 and Tailwind v4 users that their version is not supported. From 60654258a9c36bd9173fc36e56c550807fe7410c Mon Sep 17 00:00:00 2001 From: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:18:37 -0500 Subject: [PATCH 05/11] tweaks --- packages/cli/src/commands/add.ts | 2 +- packages/cli/src/commands/init.ts | 2 +- packages/cli/src/commands/update.ts | 2 +- packages/cli/src/utils/preconditions.ts | 56 ++++++++++++++---------- packages/cli/src/utils/prompt-helpers.ts | 5 +++ 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/packages/cli/src/commands/add.ts b/packages/cli/src/commands/add.ts index 28fed83d6..88904744f 100644 --- a/packages/cli/src/commands/add.ts +++ b/packages/cli/src/commands/add.ts @@ -65,7 +65,7 @@ export const add = new Command() registry.setRegistry(config.registry); - await checkPreconditions(cwd); + checkPreconditions(cwd); await runAdd(cwd, config, options); diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 74715c01f..b24c49a03 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -81,7 +81,7 @@ export const init = new Command() throw error(`The path ${color.cyan(cwd)} does not exist. Please try again.`); } - await checkPreconditions(cwd); + checkPreconditions(cwd); // Read config. const existingConfig = await cliConfig.getConfig(cwd); diff --git a/packages/cli/src/commands/update.ts b/packages/cli/src/commands/update.ts index c8da94077..4b496fa8f 100644 --- a/packages/cli/src/commands/update.ts +++ b/packages/cli/src/commands/update.ts @@ -61,7 +61,7 @@ export const update = new Command() registry.setRegistry(config.registry); - await checkPreconditions(cwd); + checkPreconditions(cwd); await runUpdate(cwd, config, options); diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 2f97082d3..76161b189 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -2,35 +2,47 @@ import color from "chalk"; import semver from "semver"; import { loadProjectPackageInfo } from "./get-package-info"; import { log } from "./prompts"; +import { getPadding } from "./prompt-helpers.js"; const peerDependencies: Record = { - svelte: "5.x", - tailwindcss: "3.x", + svelte: "^5.0.0", + tailwindcss: "^3.0.0", }; -export const checkPreconditions = (cwd: string) => { +export function checkPreconditions(cwd: string) { const pkg = loadProjectPackageInfo(cwd); - checkDependencies(pkg.dependencies); - checkDependencies(pkg.devDependencies); -}; + const dependencies = { ...pkg.dependencies, ...pkg.devDependencies }; + checkDependencies(dependencies); +} -/** Checks that all dependencies meet peer dependency requirements and logs a warning if they don't. - * - * @param dependencies +/** + * Checks that all dependencies meet peer dependency requirements and logs a warning if they don't. */ -const checkDependencies = (dependencies: Partial> | undefined) => { - if (dependencies) { - for (const [name, version] of Object.entries(dependencies)) { - const peerDepVersion = peerDependencies[name]; - - if (!peerDepVersion || !version) continue; - - if (!semver.satisfies(version, peerDepVersion)) { - log.warn( - `This version of ${color.bold("shadcn-svelte")} is intended for use with ${color.bold(`${name}@${peerDepVersion}`)}. Use at your own risk!` - ); - } +function checkDependencies(dependencies: Partial>) { + const incompatible = []; + + for (const [name, version] of Object.entries(dependencies)) { + const targetVersion = peerDependencies[name]; + const currentVersion = semver.coerce(version); + + if (!targetVersion || !currentVersion) continue; + + if (!semver.satisfies(currentVersion, targetVersion)) { + incompatible.push([ + `${color.bold(name)}@${color.greenBright.bold(targetVersion)}`, + color.yellowBright.bold(currentVersion), + ]); } } -}; + + if (incompatible.length > 0) { + const padding = getPadding(incompatible.map(([target]) => target!)); + const lines = incompatible + .map(([target, current]) => ` need ${target?.padEnd(padding)} >> found ${current}`) + .join("\n"); + log.warn( + `Incompatible dependency versions found:\n${lines}\n\n${color.white.bold("Use at your own risk!")}` + ); + } +} diff --git a/packages/cli/src/utils/prompt-helpers.ts b/packages/cli/src/utils/prompt-helpers.ts index f430e4e68..c4514b9a7 100644 --- a/packages/cli/src/utils/prompt-helpers.ts +++ b/packages/cli/src/utils/prompt-helpers.ts @@ -32,3 +32,8 @@ export function prettifyList(arr: string[], max: number = 9): string { return `${pre}, ${curr}`; }); } + +export function getPadding(lines: string[]) { + const lengths = lines.map((s) => s.length); + return Math.max(...lengths); +} From 2c5cfb70741d8732a85787395e3288bd40d88747 Mon Sep 17 00:00:00 2001 From: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:19:29 -0500 Subject: [PATCH 06/11] changeset --- .changeset/blue-drinks-rush.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/blue-drinks-rush.md b/.changeset/blue-drinks-rush.md index 89e16e9c8..8c4f48a1a 100644 --- a/.changeset/blue-drinks-rush.md +++ b/.changeset/blue-drinks-rush.md @@ -2,4 +2,4 @@ "shadcn-svelte": patch --- -chore: Add warning to Svelte 3 and Tailwind v4 users that their version is not supported. +chore: Add warning for incompatible dependency From cb0fc8ccbd74cfe13670a99cef9f4ac541e42bad Mon Sep 17 00:00:00 2001 From: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:23:19 -0500 Subject: [PATCH 07/11] tweak --- packages/cli/src/utils/preconditions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 76161b189..3abd00db5 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -30,7 +30,7 @@ function checkDependencies(dependencies: Partial>) { if (!semver.satisfies(currentVersion, targetVersion)) { incompatible.push([ - `${color.bold(name)}@${color.greenBright.bold(targetVersion)}`, + `${color.bold(`${name}@`)}${color.greenBright.bold(targetVersion)}`, color.yellowBright.bold(currentVersion), ]); } From b5c2e7ff1359cb0331b268dc519d3e9ab2deae2b Mon Sep 17 00:00:00 2001 From: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:46:13 -0500 Subject: [PATCH 08/11] last bit --- packages/cli/src/utils/preconditions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 3abd00db5..159b51bb7 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -1,12 +1,12 @@ import color from "chalk"; import semver from "semver"; -import { loadProjectPackageInfo } from "./get-package-info"; -import { log } from "./prompts"; +import { loadProjectPackageInfo } from "./get-package-info.js"; +import { log } from "./prompts.js"; import { getPadding } from "./prompt-helpers.js"; const peerDependencies: Record = { - svelte: "^5.0.0", - tailwindcss: "^3.0.0", + svelte: "5.x.x", + tailwindcss: "3.x.x", }; export function checkPreconditions(cwd: string) { From 61dffbbec37df2ff86dda73e3e3e06687a5d0155 Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Wed, 19 Feb 2025 05:38:04 -0600 Subject: [PATCH 09/11] whitespace for my brain --- packages/cli/src/utils/preconditions.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 159b51bb7..898374073 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -13,6 +13,7 @@ export function checkPreconditions(cwd: string) { const pkg = loadProjectPackageInfo(cwd); const dependencies = { ...pkg.dependencies, ...pkg.devDependencies }; + checkDependencies(dependencies); } @@ -38,9 +39,11 @@ function checkDependencies(dependencies: Partial>) { if (incompatible.length > 0) { const padding = getPadding(incompatible.map(([target]) => target!)); + const lines = incompatible .map(([target, current]) => ` need ${target?.padEnd(padding)} >> found ${current}`) .join("\n"); + log.warn( `Incompatible dependency versions found:\n${lines}\n\n${color.white.bold("Use at your own risk!")}` ); From 756033e4e557109e94d8895c16f7bbc64cf0ffc4 Mon Sep 17 00:00:00 2001 From: Aidan Bleser Date: Wed, 19 Feb 2025 05:47:57 -0600 Subject: [PATCH 10/11] format --- packages/cli/src/utils/preconditions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index 898374073..d3e778d6a 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -39,7 +39,7 @@ function checkDependencies(dependencies: Partial>) { if (incompatible.length > 0) { const padding = getPadding(incompatible.map(([target]) => target!)); - + const lines = incompatible .map(([target, current]) => ` need ${target?.padEnd(padding)} >> found ${current}`) .join("\n"); From d8d50b6bdc6c66ae4f0fd920ebcbf9f06d51904a Mon Sep 17 00:00:00 2001 From: AdrianGonz97 <31664583+AdrianGonz97@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:48:58 -0500 Subject: [PATCH 11/11] final changes --- packages/cli/src/utils/preconditions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/utils/preconditions.ts b/packages/cli/src/utils/preconditions.ts index d3e778d6a..f7fc14686 100644 --- a/packages/cli/src/utils/preconditions.ts +++ b/packages/cli/src/utils/preconditions.ts @@ -21,7 +21,7 @@ export function checkPreconditions(cwd: string) { * Checks that all dependencies meet peer dependency requirements and logs a warning if they don't. */ function checkDependencies(dependencies: Partial>) { - const incompatible = []; + const incompatible: [string, string][] = []; for (const [name, version] of Object.entries(dependencies)) { const targetVersion = peerDependencies[name]; @@ -38,14 +38,14 @@ function checkDependencies(dependencies: Partial>) { } if (incompatible.length > 0) { - const padding = getPadding(incompatible.map(([target]) => target!)); + const padding = getPadding(incompatible.map(([target]) => target)); const lines = incompatible - .map(([target, current]) => ` need ${target?.padEnd(padding)} >> found ${current}`) + .map(([target, current]) => ` need ${target.padEnd(padding)} >> found ${current}`) .join("\n"); log.warn( - `Incompatible dependency versions found:\n${lines}\n\n${color.white.bold("Use at your own risk!")}` + `Incompatible dependency versions detected:\n\n${lines}\n\n${color.white.bold("Use at your own risk!")}` ); } }