Skip to content
Draft
6 changes: 6 additions & 0 deletions .changeset/early-kiwis-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"sv": patch
---

fix(sv): templates set `engineStrict` in `pnpm-workspace.yaml` when package manager is `pnpm`

4 changes: 2 additions & 2 deletions packages/sv-utils/src/tests/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('transforms', () => {
expect(result).toContain('name: new');
});

it('abort: returns fals if transform is cacelled', () => {
it('abort: returns false if transform is cancelled', () => {
const input = 'name: old\n';
expect(transforms.yaml(() => false)(input)).toBe(false);
});
Expand All @@ -180,7 +180,7 @@ describe('transforms', () => {
expect(result).toContain('name = "new"');
});

it('abort: returns fals if transform is cacelled', () => {
it('abort: returns false if transform is cancelled', () => {
const input = 'name = "old"\n';
expect(transforms.toml(() => false)(input)).toBe(false);
});
Expand Down
2 changes: 2 additions & 0 deletions packages/sv/src/cli/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { formatFiles } from '../core/formatFiles.ts';
import {
AGENT_NAMES,
addAllowBuildsIfPnpm,
addEngineStrict,
detectPackageManager,
installDependencies,
installOption,
Expand Down Expand Up @@ -416,6 +417,7 @@ export async function createProject(cwd: ProjectPath, options: Options) {

const addOnNextSteps = getNextSteps(addOnSuccessfulAddons, workspace, answers, addonSetupResults);

addEngineStrict({ cwd: projectPath, packageManager });
addAllowBuildsIfPnpm({ cwd: projectPath, packageManager, packages: ['esbuild'] });

let depsInstalled = false;
Expand Down
82 changes: 81 additions & 1 deletion packages/sv/src/core/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
color,
detect,
pnpm,
resolveCommand
resolveCommand,
transforms,
type TransformFn
} from '@sveltejs/sv-utils';
import { Option } from 'commander';
import * as find from 'empathic/find';
Expand Down Expand Up @@ -146,3 +148,81 @@ export function addAllowBuildsIfPnpm(options: {
const newContent = pnpm.allowBuilds({ cwd, packages })(content);
if (newContent && newContent !== content) fs.writeFileSync(filePath, newContent, 'utf-8');
}

/**
* add engine strict configuration according to selected package manager
*/
export function addEngineStrict(options: {
cwd: string;
packageManager: AgentName | null | undefined;
}) {
switch (options.packageManager) {
case 'pnpm':
addEngineStrictForPnpm(options);
break;
default:
addEngineStrictForNpm(options);
break;
}
}

/**
* adds `engineStrict` to `pnpm-workspace.yaml` if not set.
* creates the file if it does not exist.
*/
export function addEngineStrictForPnpm(options: {
cwd: string;
packageManager: AgentName | null | undefined;
}): void {
const { cwd, packageManager } = options;
if (packageManager !== 'pnpm') return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the config from .npmrc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, .npmrc files are present in templates and only contain engine-strict=true.

Maybe we can remove the .npmrc completely when the package manager is pnpm ? @see https://pnpm.io/blog/releases/11.0#npmrc-is-authregistry-only

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fine. Something along the lines of: remove prop, if file is empty, delete file. In case we add other props in the future.


const found = find.up('pnpm-workspace.yaml', { cwd });
const filePath = found ?? path.join(cwd, 'pnpm-workspace.yaml');
const content = found ? fs.readFileSync(found, 'utf-8') : '';

function writeEngineStrict(): TransformFn {
return transforms.yaml(({ data }) => {
const existing = data.get('engineStrict');
if (existing !== undefined) {
return false;
}
data.set('engineStrict', true);
});
}

const newContent = writeEngineStrict()(content);

if (newContent && newContent !== content) fs.writeFileSync(filePath, newContent, 'utf-8');
}

/**
* adds `engine-strict` to `.npmrc` if not set.
* creates the file if it does not exist.
*/
export function addEngineStrictForNpm(options: {
cwd: string;
packageManager: AgentName | null | undefined;
}): void {
const { cwd, packageManager } = options;
if (packageManager === 'pnpm') return;

const found = find.up('.npmrc', { cwd });
const filePath = found ?? path.join(cwd, '.npmrc');
const content = found ? fs.readFileSync(found, 'utf-8') : '';

function writeEngineStrict(): TransformFn {
return transforms.text(({ content, text }) => {
const existing = content.includes('engine-strict');
if (existing) {
return false;
}
console.log('adding engine-strict=true');
return text.upsert(content, 'engine-strict', { value: 'true' });
});
}

const newContent = writeEngineStrict()(content);

if (newContent && newContent !== content) fs.writeFileSync(filePath, newContent, 'utf-8');
}
1 change: 0 additions & 1 deletion packages/sv/src/create/templates/library/.npmrc

This file was deleted.

1 change: 0 additions & 1 deletion packages/sv/src/create/templates/minimal/.npmrc

This file was deleted.

Loading