Skip to content
4 changes: 2 additions & 2 deletions packages/adders/eslint/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const adder = defineAdderConfig({
name: 'eslint-config-prettier',
version: '^9.1.0',
dev: true,
condition: ({ prettier }) => prettier
condition: ({ dependencyVersion }) => Boolean(dependencyVersion('prettier'))
}
],
files: [
Expand Down Expand Up @@ -141,7 +141,7 @@ export const adder = defineAdderConfig({
{
name: () => 'eslint.config.js',
contentType: 'script',
condition: ({ prettier }) => prettier,
condition: ({ dependencyVersion }) => Boolean(dependencyVersion('prettier')),
content: addEslintConfigPrettier
}
]
Expand Down
17 changes: 9 additions & 8 deletions packages/adders/prettier/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const adder = defineAdderConfig({
name: 'eslint-config-prettier',
version: '^9.1.0',
dev: true,
condition: ({ dependencies }) => hasEslint(dependencies)
condition: ({ dependencyVersion }) => hasEslint(dependencyVersion)
}
],
files: [
Expand Down Expand Up @@ -69,13 +69,13 @@ export const adder = defineAdderConfig({
{
name: () => 'package.json',
contentType: 'json',
content: ({ data, dependencies }) => {
content: ({ data, dependencyVersion }) => {
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
const CHECK_CMD = 'prettier --check .';
scripts['format'] ??= 'prettier --write .';

if (hasEslint(dependencies)) {
if (hasEslint(dependencyVersion)) {
scripts['lint'] ??= `${CHECK_CMD} && eslint .`;
if (!scripts['lint'].includes(CHECK_CMD)) scripts['lint'] += ` && ${CHECK_CMD}`;
} else {
Expand All @@ -86,17 +86,17 @@ export const adder = defineAdderConfig({
{
name: () => 'eslint.config.js',
contentType: 'script',
condition: ({ dependencies: deps }) => {
condition: ({ dependencyVersion }) => {
// We only want this to execute when it's `false`, not falsy

if (deps['eslint']?.startsWith(SUPPORTED_ESLINT_VERSION) === false) {
if (dependencyVersion('eslint')?.startsWith(SUPPORTED_ESLINT_VERSION) === false) {
log.warn(
`An older major version of ${colors.yellow(
'eslint'
)} was detected. Skipping ${colors.yellow('eslint-config-prettier')} installation.`
);
}
return hasEslint(deps);
return hasEslint(dependencyVersion);
},
content: addEslintConfigPrettier
}
Expand All @@ -105,6 +105,7 @@ export const adder = defineAdderConfig({

const SUPPORTED_ESLINT_VERSION = '9';

function hasEslint(deps: Record<string, string>): boolean {
return !!deps['eslint'] && deps['eslint'].startsWith(SUPPORTED_ESLINT_VERSION);
function hasEslint(dependencyVersion: (pkg: string) => string | undefined): boolean {
const version = dependencyVersion('eslint');
return !!version && version.startsWith(SUPPORTED_ESLINT_VERSION);
}
4 changes: 2 additions & 2 deletions packages/adders/tailwindcss/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const adder = defineAdderConfig({
name: 'prettier-plugin-tailwindcss',
version: '^0.6.5',
dev: true,
condition: ({ prettier }) => prettier
condition: ({ dependencyVersion }) => Boolean(dependencyVersion('prettier'))
}
],
files: [
Expand Down Expand Up @@ -134,7 +134,7 @@ export const adder = defineAdderConfig({

if (!plugins.includes(PLUGIN_NAME)) plugins.push(PLUGIN_NAME);
},
condition: ({ prettier }) => prettier
condition: ({ dependencyVersion }) => Boolean(dependencyVersion('prettier'))
}
]
});
8 changes: 6 additions & 2 deletions packages/cli/commands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ export async function runAddCommand(options: Options, adders: string[]): Promise
let installed = false;
installed = dependent.config.packages.every(
// we'll skip the conditions since we don't have any options to supply it
(p) => p.condition !== undefined || !!workspace.dependencies[p.name]
(p) => p.condition !== undefined || !!workspace.dependencyVersion(p.name)
);

if (installed) continue;
Expand Down Expand Up @@ -463,7 +463,11 @@ export async function runAddCommand(options: Options, adders: string[]): Promise

// format modified/created files with prettier (if available)
const workspace = createWorkspace(options.cwd);
if (filesToFormat.length > 0 && depsStatus === 'installed' && workspace.prettier) {
if (
filesToFormat.length > 0 &&
depsStatus === 'installed' &&
!!workspace.dependencyVersion('prettier')
) {
const { start, stop } = p.spinner();
start('Formatting modified files');
try {
Expand Down
35 changes: 22 additions & 13 deletions packages/core/files/workspace.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import * as find from 'empathic/find';
import * as resolve from 'empathic/resolve';
import { AGENTS, detectSync, type AgentName } from 'package-manager-detector';
import { type AstTypes, parseScript } from '@svelte-cli/ast-tooling';
import { TESTING } from '../env.ts';
Expand All @@ -13,8 +12,13 @@ import process from 'node:process';
export type Workspace<Args extends OptionDefinition> = {
options: OptionValues<Args>;
cwd: string;
dependencies: Record<string, string>;
prettier: boolean;
/**
* Returns the dependency version declared in the package.json.
* This may differ from the installed version.
* @param pkg the package to check for
* @returns the dependency version with any leading characters such as ^ or ~ removed
*/
dependencyVersion: (pkg: string) => string | undefined;
typescript: boolean;
kit: { libDirectory: string; routesDirectory: string } | undefined;
packageManager: AgentName;
Expand All @@ -24,7 +28,7 @@ export function createEmptyWorkspace<Args extends OptionDefinition>() {
return {
options: {},
cwd: '',
prettier: false,
dependencyVersion: (_pkg) => undefined,
typescript: false,
kit: undefined
} as Workspace<Args>;
Expand All @@ -45,17 +49,22 @@ export function createWorkspace<Args extends OptionDefinition>(cwd: string): Wor
}

const { data: packageJson } = getPackageJson(workspace);

workspace.dependencies = { ...packageJson.devDependencies, ...packageJson.dependencies };
const dependencies = { ...packageJson.devDependencies, ...packageJson.dependencies };

workspace.dependencyVersion = (pkg) => {
// TODO: support monorepos
// it would be nice to keep this working before the user has done an install
// we could go up checking all the package.json until we find a pnpm-workspace.yaml, etc.
const found = dependencies[pkg];
if (!found) {
return found;
}
// removes the version ranges (e.g. `^` is removed from: `^9.0.0`)
return found.replaceAll(/[^\d|.]/g, '');
};
workspace.typescript = usesTypescript;
workspace.prettier = Boolean(resolve.from(cwd, 'prettier', true));
workspace.packageManager = detectPackageManager(cwd);
if ('@sveltejs/kit' in workspace.dependencies) workspace.kit = parseKitOptions(workspace);
for (const [key, value] of Object.entries(workspace.dependencies)) {
// removes the version ranges (e.g. `^` is removed from: `^9.0.0`)
workspace.dependencies[key] = value.replaceAll(/[^\d|.]/g, '');
}

if ('@sveltejs/kit' in dependencies) workspace.kit = parseKitOptions(workspace);
return workspace;
}

Expand Down
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.