@@ -28,6 +28,10 @@ use std::path::PathBuf;
28
28
use std:: rc:: Rc ;
29
29
use tokio:: task:: LocalSet ;
30
30
31
+ // WARNING: Do not depend on this env var in user code. It's not stable API.
32
+ const USE_PKG_JSON_HIDDEN_ENV_VAR_NAME : & str =
33
+ "DENO_INTERNAL_TASK_USE_PKG_JSON" ;
34
+
31
35
pub async fn execute_script (
32
36
flags : Flags ,
33
37
task_flags : TaskFlags ,
@@ -55,13 +59,20 @@ pub async fn execute_script(
55
59
let npm_resolver = factory. npm_resolver ( ) . await ?;
56
60
let node_resolver = factory. node_resolver ( ) . await ?;
57
61
let env_vars = real_env_vars ( ) ;
62
+ let force_use_pkg_json = std:: env:: var_os ( USE_PKG_JSON_HIDDEN_ENV_VAR_NAME )
63
+ . map ( |v| {
64
+ // always remove so sub processes don't inherit this env var
65
+ std:: env:: remove_var ( USE_PKG_JSON_HIDDEN_ENV_VAR_NAME ) ;
66
+ v == "1"
67
+ } )
68
+ . unwrap_or ( false ) ;
58
69
59
70
if let Some (
60
71
deno_config:: Task :: Definition ( script)
61
72
| deno_config:: Task :: Commented {
62
73
definition : script, ..
63
74
} ,
64
- ) = tasks_config. get ( task_name)
75
+ ) = tasks_config. get ( task_name) . filter ( |_| !force_use_pkg_json )
65
76
{
66
77
let config_file_url = cli_options. maybe_config_file_specifier ( ) . unwrap ( ) ;
67
78
let config_file_path = if config_file_url. scheme ( ) == "file" {
@@ -77,16 +88,18 @@ pub async fn execute_script(
77
88
78
89
let custom_commands =
79
90
resolve_custom_commands ( npm_resolver. as_ref ( ) , node_resolver) ?;
80
- run_task (
91
+ run_task ( RunTaskOptions {
81
92
task_name,
82
93
script,
83
- & cwd,
84
- cli_options. initial_cwd ( ) ,
94
+ cwd : & cwd,
95
+ init_cwd : cli_options. initial_cwd ( ) ,
85
96
env_vars,
86
- cli_options. argv ( ) ,
97
+ argv : cli_options. argv ( ) ,
87
98
custom_commands,
88
- npm_resolver. root_node_modules_path ( ) . map ( |p| p. as_path ( ) ) ,
89
- )
99
+ root_node_modules_dir : npm_resolver
100
+ . root_node_modules_path ( )
101
+ . map ( |p| p. as_path ( ) ) ,
102
+ } )
90
103
. await
91
104
} else if package_json_scripts. contains_key ( task_name) {
92
105
let package_json_deps_provider = factory. package_json_deps_provider ( ) ;
@@ -134,18 +147,20 @@ pub async fn execute_script(
134
147
] ;
135
148
let custom_commands =
136
149
resolve_custom_commands ( npm_resolver. as_ref ( ) , node_resolver) ?;
137
- for task_name in task_names {
138
- if let Some ( script) = package_json_scripts. get ( & task_name) {
139
- let exit_code = run_task (
140
- & task_name,
150
+ for task_name in & task_names {
151
+ if let Some ( script) = package_json_scripts. get ( task_name) {
152
+ let exit_code = run_task ( RunTaskOptions {
153
+ task_name,
141
154
script,
142
- & cwd,
143
- cli_options. initial_cwd ( ) ,
144
- env_vars. clone ( ) ,
145
- cli_options. argv ( ) ,
146
- custom_commands. clone ( ) ,
147
- npm_resolver. root_node_modules_path ( ) . map ( |p| p. as_path ( ) ) ,
148
- )
155
+ cwd : & cwd,
156
+ init_cwd : cli_options. initial_cwd ( ) ,
157
+ env_vars : env_vars. clone ( ) ,
158
+ argv : cli_options. argv ( ) ,
159
+ custom_commands : custom_commands. clone ( ) ,
160
+ root_node_modules_dir : npm_resolver
161
+ . root_node_modules_path ( )
162
+ . map ( |p| p. as_path ( ) ) ,
163
+ } )
149
164
. await ?;
150
165
if exit_code > 0 {
151
166
return Ok ( exit_code) ;
@@ -167,25 +182,31 @@ pub async fn execute_script(
167
182
}
168
183
}
169
184
170
- #[ allow( clippy:: too_many_arguments) ]
171
- async fn run_task (
172
- task_name : & str ,
173
- script : & str ,
174
- cwd : & Path ,
175
- init_cwd : & Path ,
185
+ struct RunTaskOptions < ' a > {
186
+ task_name : & ' a str ,
187
+ script : & ' a str ,
188
+ cwd : & ' a Path ,
189
+ init_cwd : & ' a Path ,
176
190
env_vars : HashMap < String , String > ,
177
- argv : & [ String ] ,
191
+ argv : & ' a [ String ] ,
178
192
custom_commands : HashMap < String , Rc < dyn ShellCommand > > ,
179
- root_node_modules_dir : Option < & Path > ,
180
- ) -> Result < i32 , AnyError > {
181
- let script = get_script_with_args ( script, argv) ;
182
- output_task ( task_name, & script) ;
193
+ root_node_modules_dir : Option < & ' a Path > ,
194
+ }
195
+
196
+ async fn run_task ( opts : RunTaskOptions < ' _ > ) -> Result < i32 , AnyError > {
197
+ let script = get_script_with_args ( opts. script , opts. argv ) ;
198
+ output_task ( opts. task_name , & script) ;
183
199
let seq_list = deno_task_shell:: parser:: parse ( & script)
184
- . with_context ( || format ! ( "Error parsing script '{}'." , task_name) ) ?;
185
- let env_vars = prepare_env_vars ( env_vars, init_cwd, root_node_modules_dir) ;
200
+ . with_context ( || format ! ( "Error parsing script '{}'." , opts. task_name) ) ?;
201
+ let env_vars =
202
+ prepare_env_vars ( opts. env_vars , opts. init_cwd , opts. root_node_modules_dir ) ;
186
203
let local = LocalSet :: new ( ) ;
187
- let future =
188
- deno_task_shell:: execute ( seq_list, env_vars, cwd, custom_commands) ;
204
+ let future = deno_task_shell:: execute (
205
+ seq_list,
206
+ env_vars,
207
+ opts. cwd ,
208
+ opts. custom_commands ,
209
+ ) ;
189
210
Ok ( local. run_until ( future) . await )
190
211
}
191
212
@@ -315,6 +336,48 @@ fn print_available_tasks(
315
336
Ok ( ( ) )
316
337
}
317
338
339
+ struct NpmCommand ;
340
+
341
+ impl ShellCommand for NpmCommand {
342
+ fn execute (
343
+ & self ,
344
+ mut context : ShellCommandContext ,
345
+ ) -> LocalBoxFuture < ' static , ExecuteResult > {
346
+ if context. args . first ( ) . map ( |s| s. as_str ( ) ) == Some ( "run" )
347
+ && !context. args . iter ( ) . any ( |s| s == "--" )
348
+ {
349
+ if let Some ( task_name) = context. args . get ( 1 ) {
350
+ // run with deno task instead
351
+ let mut args = vec ! [ "task" . to_string( ) , task_name. to_string( ) ] ;
352
+ args. extend ( context. args . iter ( ) . skip ( 2 ) . cloned ( ) ) ;
353
+ let mut state = context. state ;
354
+ state. apply_env_var ( USE_PKG_JSON_HIDDEN_ENV_VAR_NAME , "1" ) ;
355
+ return ExecutableCommand :: new (
356
+ "deno" . to_string ( ) ,
357
+ std:: env:: current_exe ( ) . unwrap ( ) ,
358
+ )
359
+ . execute ( ShellCommandContext {
360
+ args,
361
+ state,
362
+ ..context
363
+ } ) ;
364
+ }
365
+ }
366
+
367
+ // fallback to running the real npm command
368
+ let npm_path = match context. resolve_command_path ( "npm" ) {
369
+ Ok ( path) => path,
370
+ Err ( err) => {
371
+ let _ = context. stderr . write_line ( & format ! ( "{}" , err) ) ;
372
+ return Box :: pin ( futures:: future:: ready (
373
+ ExecuteResult :: from_exit_code ( err. exit_code ( ) ) ,
374
+ ) ) ;
375
+ }
376
+ } ;
377
+ ExecutableCommand :: new ( "npm" . to_string ( ) , npm_path) . execute ( context)
378
+ }
379
+ }
380
+
318
381
struct NpxCommand ;
319
382
320
383
impl ShellCommand for NpxCommand {
@@ -413,15 +476,17 @@ fn resolve_custom_commands(
413
476
npm_resolver : & dyn CliNpmResolver ,
414
477
node_resolver : & NodeResolver ,
415
478
) -> Result < HashMap < String , Rc < dyn ShellCommand > > , AnyError > {
416
- match npm_resolver. as_inner ( ) {
479
+ let mut commands = match npm_resolver. as_inner ( ) {
417
480
InnerCliNpmResolverRef :: Byonm ( npm_resolver) => {
418
481
let node_modules_dir = npm_resolver. root_node_modules_path ( ) . unwrap ( ) ;
419
- Ok ( resolve_npm_commands_from_bin_dir ( node_modules_dir) )
482
+ resolve_npm_commands_from_bin_dir ( node_modules_dir)
420
483
}
421
484
InnerCliNpmResolverRef :: Managed ( npm_resolver) => {
422
- resolve_managed_npm_commands ( npm_resolver, node_resolver)
485
+ resolve_managed_npm_commands ( npm_resolver, node_resolver) ?
423
486
}
424
- }
487
+ } ;
488
+ commands. insert ( "npm" . to_string ( ) , Rc :: new ( NpmCommand ) ) ;
489
+ Ok ( commands)
425
490
}
426
491
427
492
fn resolve_npm_commands_from_bin_dir (
0 commit comments