@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
import path from 'node:path' ;
3
3
import process from 'node:process' ;
4
4
import * as find from 'empathic/find' ;
5
- import { exec } from 'tinyexec' ;
5
+ import { x } from 'tinyexec' ;
6
6
import { Option } from 'commander' ;
7
7
import * as p from '@clack/prompts' ;
8
8
import {
@@ -12,7 +12,8 @@ import {
12
12
detect ,
13
13
type AgentName
14
14
} from 'package-manager-detector' ;
15
- import { parseJson } from '@sveltejs/cli-core/parsers' ;
15
+ import { parseJson , parseYaml } from '@sveltejs/cli-core/parsers' ;
16
+ import { isVersionUnsupportedBelow } from '@sveltejs/cli-core' ;
16
17
17
18
export const AGENT_NAMES = AGENTS . filter ( ( agent ) : agent is AgentName => ! agent . includes ( '@' ) ) ;
18
19
const agentOptions : PackageManagerOptions = AGENT_NAMES . map ( ( pm ) => ( { value : pm , label : pm } ) ) ;
@@ -55,19 +56,16 @@ export async function installDependencies(agent: AgentName, cwd: string): Promis
55
56
56
57
try {
57
58
const { command, args } = constructCommand ( COMMANDS [ agent ] . install , [ ] ) ! ;
58
- const proc = exec ( command , args , {
59
+
60
+ const proc = x ( command , args , {
59
61
nodeOptions : { cwd, stdio : 'pipe' } ,
60
62
throwOnError : true
61
63
} ) ;
62
64
63
- proc . process ?. stdout ?. on ( 'data' , ( data ) => {
64
- task . message ( data . toString ( ) , { raw : true } ) ;
65
- } ) ;
66
- proc . process ?. stderr ?. on ( 'data' , ( data ) => {
67
- task . message ( data . toString ( ) , { raw : true } ) ;
68
- } ) ;
69
-
70
- await proc ;
65
+ for await ( const line of proc ) {
66
+ // line will be from stderr/stdout in the order you'd see it in a term
67
+ task . message ( line , { raw : true } ) ;
68
+ }
71
69
72
70
task . success ( 'Successfully installed dependencies' ) ;
73
71
} catch {
@@ -87,35 +85,69 @@ export function getUserAgent(): AgentName | undefined {
87
85
return AGENTS . includes ( name ) ? name : undefined ;
88
86
}
89
87
90
- export function addPnpmBuildDependencies (
88
+ export async function addPnpmBuildDependencies (
91
89
cwd : string ,
92
90
packageManager : AgentName | null | undefined ,
93
91
allowedPackages : string [ ]
94
92
) {
95
93
// other package managers are currently not affected by this change
96
- if ( ! packageManager || packageManager !== 'pnpm' ) return ;
94
+ if ( ! packageManager || packageManager !== 'pnpm' || allowedPackages . length === 0 ) return ;
95
+
96
+ let confIn : 'package.json' | 'pnpm-workspace.yaml' = 'package.json' ;
97
+ const pnpmVersion = await getPnpmVersion ( ) ;
98
+ if ( pnpmVersion ) {
99
+ confIn = isVersionUnsupportedBelow ( pnpmVersion , '10.5' )
100
+ ? 'package.json'
101
+ : 'pnpm-workspace.yaml' ;
102
+ }
97
103
98
104
// find the workspace root (if present)
99
- const pnpmWorkspacePath = find . up ( 'pnpm-workspace.yaml' , { cwd } ) ;
100
- let packageDirectory ;
101
-
102
- if ( pnpmWorkspacePath ) packageDirectory = path . dirname ( pnpmWorkspacePath ) ;
103
- else packageDirectory = cwd ;
104
-
105
- // load the package.json
106
- const pkgPath = path . join ( packageDirectory , 'package.json' ) ;
107
- const content = fs . readFileSync ( pkgPath , 'utf-8' ) ;
108
- const { data, generateCode } = parseJson ( content ) ;
109
-
110
- // add the packages where we install scripts should be executed
111
- data . pnpm ??= { } ;
112
- data . pnpm . onlyBuiltDependencies ??= [ ] ;
113
- for ( const allowedPackage of allowedPackages ) {
114
- if ( data . pnpm . onlyBuiltDependencies . includes ( allowedPackage ) ) continue ;
115
- data . pnpm . onlyBuiltDependencies . push ( allowedPackage ) ;
105
+ const found = find . up ( 'pnpm-workspace.yaml' , { cwd } ) ;
106
+ const dir = found ? path . dirname ( found ) : cwd ;
107
+
108
+ if ( confIn === 'pnpm-workspace.yaml' ) {
109
+ const content = found ? fs . readFileSync ( found , 'utf-8' ) : '' ;
110
+ const { data, generateCode } = parseYaml ( content ) ;
111
+
112
+ const onlyBuiltDependencies = data . get ( 'onlyBuiltDependencies' ) ;
113
+ const items : Array < { value : string } | string > = onlyBuiltDependencies ?. items ?? [ ] ;
114
+
115
+ for ( const item of allowedPackages ) {
116
+ if ( items . includes ( item ) ) continue ;
117
+ if ( items . some ( ( y ) => typeof y === 'object' && y . value === item ) ) continue ;
118
+ items . push ( item ) ;
119
+ }
120
+ data . set ( 'onlyBuiltDependencies' , new Set ( items ) ) ;
121
+
122
+ const newContent = generateCode ( ) ;
123
+
124
+ const pnpmWorkspacePath = found ?? path . join ( cwd , 'pnpm-workspace.yaml' ) ;
125
+ if ( newContent !== content ) fs . writeFileSync ( pnpmWorkspacePath , newContent ) ;
126
+ } else {
127
+ // else is package.json (fallback)
128
+ const pkgPath = path . join ( dir , 'package.json' ) ;
129
+ const content = fs . readFileSync ( pkgPath , 'utf-8' ) ;
130
+ const { data, generateCode } = parseJson ( content ) ;
131
+
132
+ // add the packages where we install scripts should be executed
133
+ data . pnpm ??= { } ;
134
+ data . pnpm . onlyBuiltDependencies ??= [ ] ;
135
+ for ( const allowedPackage of allowedPackages ) {
136
+ if ( data . pnpm . onlyBuiltDependencies . includes ( allowedPackage ) ) continue ;
137
+ data . pnpm . onlyBuiltDependencies . push ( allowedPackage ) ;
138
+ }
139
+
140
+ // save the updated package.json
141
+ const newContent = generateCode ( ) ;
142
+ if ( newContent !== content ) fs . writeFileSync ( pkgPath , newContent ) ;
116
143
}
144
+ }
117
145
118
- // save the updated package.json
119
- const newContent = generateCode ( ) ;
120
- fs . writeFileSync ( pkgPath , newContent ) ;
146
+ async function getPnpmVersion ( ) : Promise < string | undefined > {
147
+ let v : string | undefined = undefined ;
148
+ try {
149
+ const proc = await x ( 'pnpm' , [ '--version' ] , { throwOnError : true } ) ;
150
+ v = proc . stdout . trim ( ) ;
151
+ } catch { }
152
+ return v ;
121
153
}
0 commit comments