2024-01-01 14:58:21 -05:00
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2022-02-16 13:14:19 -05:00
use std ::path ::Path ;
use std ::path ::PathBuf ;
2022-06-29 20:41:48 -04:00
use std ::sync ::Arc ;
2022-02-16 13:14:19 -05:00
2022-06-14 10:05:37 -04:00
use deno_ast ::ModuleSpecifier ;
2023-05-19 18:39:27 -04:00
use deno_ast ::TextChange ;
2022-02-16 13:14:19 -05:00
use deno_core ::anyhow ::bail ;
use deno_core ::anyhow ::Context ;
use deno_core ::error ::AnyError ;
2023-07-14 18:10:42 -04:00
use deno_core ::futures ::FutureExt ;
2022-02-16 13:14:19 -05:00
use deno_core ::resolve_url_or_path ;
2023-06-06 17:07:46 -04:00
use deno_graph ::GraphKind ;
2024-07-09 21:18:10 -04:00
use deno_runtime ::colors ;
2022-06-14 10:05:37 -04:00
use log ::warn ;
2022-02-16 13:14:19 -05:00
2022-06-29 20:41:48 -04:00
use crate ::args ::CliOptions ;
2023-05-19 18:39:27 -04:00
use crate ::args ::ConfigFile ;
2022-06-29 20:41:48 -04:00
use crate ::args ::Flags ;
2022-06-27 16:54:09 -04:00
use crate ::args ::FmtOptionsConfig ;
use crate ::args ::VendorFlags ;
2023-05-01 14:35:23 -04:00
use crate ::factory ::CliFactory ;
2022-06-14 10:05:37 -04:00
use crate ::tools ::fmt ::format_json ;
2022-11-28 17:28:54 -05:00
use crate ::util ::fs ::canonicalize_path ;
use crate ::util ::fs ::resolve_from_cwd ;
use crate ::util ::path ::relative_specifier ;
2024-04-17 10:19:55 -04:00
use deno_runtime ::fs_util ::specifier_to_file_path ;
2022-02-16 13:14:19 -05:00
mod analyze ;
mod build ;
mod import_map ;
mod mappings ;
mod specifiers ;
#[ cfg(test) ]
mod test ;
2022-06-29 20:41:48 -04:00
pub async fn vendor (
flags : Flags ,
vendor_flags : VendorFlags ,
) -> Result < ( ) , AnyError > {
2024-07-09 21:18:10 -04:00
log ::info! (
" {} " ,
colors ::yellow ( " ⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0. \n Add ` \" vendor \" : true` to your `deno.json` or use the `--vendor` flag instead. " ) ,
) ;
2022-06-29 20:41:48 -04:00
let mut cli_options = CliOptions ::from_flags ( flags ) ? ;
let raw_output_dir = match & vendor_flags . output_path {
2024-03-14 19:53:46 -04:00
Some ( output_path ) = > PathBuf ::from ( output_path ) . to_owned ( ) ,
2022-02-16 13:14:19 -05:00
None = > PathBuf ::from ( " vendor/ " ) ,
} ;
2022-11-28 17:28:54 -05:00
let output_dir = resolve_from_cwd ( & raw_output_dir ) ? ;
2022-06-29 20:41:48 -04:00
validate_output_dir ( & output_dir , & vendor_flags ) ? ;
validate_options ( & mut cli_options , & output_dir ) ? ;
2023-05-01 14:35:23 -04:00
let factory = CliFactory ::from_cli_options ( Arc ::new ( cli_options ) ) ;
let cli_options = factory . cli_options ( ) ;
2024-07-03 20:54:33 -04:00
if cli_options . workspace . config_folders ( ) . len ( ) > 1 {
bail! ( " deno vendor is not supported in a workspace. Set ` \" vendor \" : true` in the workspace deno.json file instead " ) ;
}
2023-07-14 18:10:42 -04:00
let entry_points =
resolve_entry_points ( & vendor_flags , cli_options . initial_cwd ( ) ) ? ;
2024-07-03 20:54:33 -04:00
let jsx_import_source =
cli_options . workspace . to_maybe_jsx_import_source_config ( ) ? ;
2024-02-20 16:29:57 -05:00
let module_graph_creator = factory . module_graph_creator ( ) . await ? . clone ( ) ;
2024-07-03 20:54:33 -04:00
let workspace_resolver = factory . workspace_resolver ( ) . await ? ;
let root_folder = cli_options . workspace . root_folder ( ) . 1 ;
let maybe_config_file = root_folder . deno_json . as_ref ( ) ;
2023-07-14 18:10:42 -04:00
let output = build ::build ( build ::BuildInput {
entry_points ,
build_graph : move | entry_points | {
async move {
2024-02-20 16:29:57 -05:00
module_graph_creator
2023-07-14 18:10:42 -04:00
. create_graph ( GraphKind ::All , entry_points )
. await
}
. boxed_local ( )
} ,
2023-10-25 18:13:22 -04:00
parsed_source_cache : factory . parsed_source_cache ( ) ,
2023-07-14 18:10:42 -04:00
output_dir : & output_dir ,
2024-07-03 20:54:33 -04:00
maybe_original_import_map : workspace_resolver . maybe_import_map ( ) ,
2023-07-14 18:10:42 -04:00
maybe_jsx_import_source : jsx_import_source . as_ref ( ) ,
resolver : factory . resolver ( ) . await ? . as_graph_resolver ( ) ,
environment : & build ::RealVendorEnvironment ,
} )
2023-04-17 15:36:23 -04:00
. await ? ;
2023-07-14 18:10:42 -04:00
let vendored_count = output . vendored_count ;
let graph = output . graph ;
2023-05-19 18:39:27 -04:00
let npm_package_count = graph . npm_packages . len ( ) ;
let try_add_node_modules_dir = npm_package_count > 0
& & cli_options . node_modules_dir_enablement ( ) . unwrap_or ( true ) ;
2022-02-16 13:14:19 -05:00
2022-12-09 10:54:24 -05:00
log ::info! (
2022-06-14 10:05:37 -04:00
concat! ( " Vendored {} {} into {} directory. " , ) ,
2022-02-16 13:14:19 -05:00
vendored_count ,
if vendored_count = = 1 {
" module "
} else {
" modules "
} ,
raw_output_dir . display ( ) ,
) ;
2023-05-19 18:39:27 -04:00
let try_add_import_map = vendored_count > 0 ;
let modified_result = maybe_update_config_file (
& output_dir ,
2024-07-03 20:54:33 -04:00
maybe_config_file ,
2023-05-19 18:39:27 -04:00
try_add_import_map ,
try_add_node_modules_dir ,
) ;
// cache the node_modules folder when it's been added to the config file
if modified_result . added_node_modules_dir {
2024-04-05 10:34:51 -04:00
let node_modules_path =
cli_options . node_modules_dir_path ( ) . cloned ( ) . or_else ( | | {
2024-07-03 20:54:33 -04:00
maybe_config_file
. as_ref ( )
. map ( | d | & d . specifier )
2024-04-05 10:34:51 -04:00
. filter ( | c | c . scheme ( ) = = " file " )
. and_then ( | c | c . to_file_path ( ) . ok ( ) )
. map ( | config_path | config_path . parent ( ) . unwrap ( ) . join ( " node_modules " ) )
} ) ;
2023-05-19 18:39:27 -04:00
if let Some ( node_modules_path ) = node_modules_path {
2023-10-02 17:53:55 -04:00
let cli_options =
cli_options . with_node_modules_dir_path ( node_modules_path ) ;
let factory = CliFactory ::from_cli_options ( Arc ::new ( cli_options ) ) ;
if let Some ( managed ) = factory . npm_resolver ( ) . await ? . as_managed ( ) {
managed . cache_packages ( ) . await ? ;
}
2023-05-19 18:39:27 -04:00
}
log ::info! (
concat! (
" Vendored {} npm {} into node_modules directory. Set `nodeModulesDir: false` " ,
" in the Deno configuration file to disable vendoring npm packages in the future. " ,
) ,
npm_package_count ,
if npm_package_count = = 1 {
" package "
} else {
" packages "
} ,
) ;
}
2022-06-14 10:05:37 -04:00
if vendored_count > 0 {
let import_map_path = raw_output_dir . join ( " import_map.json " ) ;
2023-05-19 18:39:27 -04:00
if modified_result . updated_import_map {
2022-12-09 10:54:24 -05:00
log ::info! (
2022-06-14 10:05:37 -04:00
concat! (
" \n Updated your local Deno configuration file with a reference to the " ,
" new vendored import map at {}. Invoking Deno subcommands will now " ,
" automatically resolve using the vendored modules. You may override " ,
" this by providing the `--import-map <other-import-map>` flag or by " ,
" manually editing your Deno configuration file. " ,
) ,
import_map_path . display ( ) ,
) ;
} else {
2022-12-09 10:54:24 -05:00
log ::info! (
2022-06-14 10:05:37 -04:00
concat! (
" \n To use vendored modules, specify the `--import-map {}` flag when " ,
r # "invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` "# ,
" entry to a deno.json file. " ,
) ,
import_map_path . display ( ) ,
) ;
}
}
2022-02-16 13:14:19 -05:00
Ok ( ( ) )
}
fn validate_output_dir (
output_dir : & Path ,
flags : & VendorFlags ,
) -> Result < ( ) , AnyError > {
if ! flags . force & & ! is_dir_empty ( output_dir ) ? {
bail! ( concat! (
" Output directory was not empty. Please specify an empty directory or use " ,
" --force to ignore this error and potentially overwrite its contents. " ,
) ) ;
}
2022-06-29 20:41:48 -04:00
Ok ( ( ) )
}
2022-02-16 13:14:19 -05:00
2022-06-29 20:41:48 -04:00
fn validate_options (
options : & mut CliOptions ,
output_dir : & Path ,
) -> Result < ( ) , AnyError > {
2024-02-24 00:21:09 -05:00
let import_map_specifier = options
. resolve_specified_import_map_specifier ( ) ?
. or_else ( | | {
2024-07-03 20:54:33 -04:00
let config_file = options . workspace . root_folder ( ) . 1. deno_json . as_ref ( ) ? ;
2024-02-24 00:21:09 -05:00
config_file
. to_import_map_specifier ( )
. ok ( )
. flatten ( )
. or_else ( | | {
if config_file . is_an_import_map ( ) {
Some ( config_file . specifier . clone ( ) )
} else {
None
}
} )
} ) ;
2022-02-16 13:14:19 -05:00
// check the import map
2024-02-24 00:21:09 -05:00
if let Some ( import_map_path ) = import_map_specifier
2022-06-29 20:41:48 -04:00
. and_then ( | p | specifier_to_file_path ( & p ) . ok ( ) )
2022-11-28 17:28:54 -05:00
. and_then ( | p | canonicalize_path ( & p ) . ok ( ) )
2022-02-16 13:14:19 -05:00
{
// make the output directory in order to canonicalize it for the check below
2022-11-17 20:59:10 -05:00
std ::fs ::create_dir_all ( output_dir ) ? ;
2022-11-28 17:28:54 -05:00
let output_dir = canonicalize_path ( output_dir ) . with_context ( | | {
format! ( " Failed to canonicalize: {} " , output_dir . display ( ) )
} ) ? ;
2022-02-16 13:14:19 -05:00
2022-12-17 17:20:15 -05:00
if import_map_path . starts_with ( output_dir ) {
2022-06-14 10:05:37 -04:00
// canonicalize to make the test for this pass on the CI
2022-11-28 17:28:54 -05:00
let cwd = canonicalize_path ( & std ::env ::current_dir ( ) ? ) ? ;
2022-06-14 10:05:37 -04:00
// We don't allow using the output directory to help generate the
// new state because this may lead to cryptic error messages.
2022-06-29 20:41:48 -04:00
log ::warn! (
2022-06-14 10:05:37 -04:00
concat! (
2022-06-29 20:41:48 -04:00
" Ignoring import map. Specifying an import map file ({}) in the " ,
" deno vendor output directory is not supported. If you wish to use " ,
" an import map while vendoring, please specify one located outside " ,
" this directory. "
2022-06-14 10:05:37 -04:00
) ,
import_map_path
. strip_prefix ( & cwd )
. unwrap_or ( & import_map_path )
. display ( )
. to_string ( ) ,
2022-02-16 13:14:19 -05:00
) ;
2022-06-29 20:41:48 -04:00
// don't use an import map in the config
options . set_import_map_specifier ( None ) ;
2022-02-16 13:14:19 -05:00
}
}
Ok ( ( ) )
}
2023-05-19 18:39:27 -04:00
fn maybe_update_config_file (
output_dir : & Path ,
2024-07-03 20:54:33 -04:00
maybe_config_file : Option < & Arc < ConfigFile > > ,
2023-05-19 18:39:27 -04:00
try_add_import_map : bool ,
try_add_node_modules_dir : bool ,
) -> ModifiedResult {
2022-06-14 10:05:37 -04:00
assert! ( output_dir . is_absolute ( ) ) ;
2024-07-03 20:54:33 -04:00
let config_file = match maybe_config_file {
2023-05-19 18:39:27 -04:00
Some ( config_file ) = > config_file ,
None = > return ModifiedResult ::default ( ) ,
2022-06-14 10:05:37 -04:00
} ;
2023-05-19 18:39:27 -04:00
if config_file . specifier . scheme ( ) ! = " file " {
return ModifiedResult ::default ( ) ;
}
2023-01-07 15:22:09 -05:00
2024-01-18 15:57:30 -05:00
let fmt_config_options = config_file
2023-05-19 18:39:27 -04:00
. to_fmt_config ( )
. ok ( )
2024-01-18 15:57:30 -05:00
. map ( | config | config . options )
2022-06-14 10:05:37 -04:00
. unwrap_or_default ( ) ;
let result = update_config_file (
2023-05-19 18:39:27 -04:00
config_file ,
2024-01-18 15:57:30 -05:00
& fmt_config_options ,
2023-05-19 18:39:27 -04:00
if try_add_import_map {
Some (
ModuleSpecifier ::from_file_path ( output_dir . join ( " import_map.json " ) )
. unwrap ( ) ,
)
} else {
None
} ,
try_add_node_modules_dir ,
2022-06-14 10:05:37 -04:00
) ;
match result {
2023-05-19 18:39:27 -04:00
Ok ( modified_result ) = > modified_result ,
2022-06-14 10:05:37 -04:00
Err ( err ) = > {
warn! ( " Error updating config file. {:#} " , err ) ;
2023-05-19 18:39:27 -04:00
ModifiedResult ::default ( )
2022-06-14 10:05:37 -04:00
}
}
}
fn update_config_file (
2023-05-19 18:39:27 -04:00
config_file : & ConfigFile ,
2022-06-14 10:05:37 -04:00
fmt_options : & FmtOptionsConfig ,
2023-05-19 18:39:27 -04:00
import_map_specifier : Option < ModuleSpecifier > ,
try_add_node_modules_dir : bool ,
) -> Result < ModifiedResult , AnyError > {
let config_path = specifier_to_file_path ( & config_file . specifier ) ? ;
2022-06-14 10:05:37 -04:00
let config_text = std ::fs ::read_to_string ( & config_path ) ? ;
2023-05-19 18:39:27 -04:00
let import_map_specifier =
import_map_specifier . and_then ( | import_map_specifier | {
relative_specifier ( & config_file . specifier , & import_map_specifier )
} ) ;
let modified_result = update_config_text (
& config_text ,
fmt_options ,
import_map_specifier . as_deref ( ) ,
try_add_node_modules_dir ,
) ? ;
if let Some ( new_text ) = & modified_result . new_text {
2022-06-14 10:05:37 -04:00
std ::fs ::write ( config_path , new_text ) ? ;
}
2023-05-19 18:39:27 -04:00
Ok ( modified_result )
}
2022-06-14 10:05:37 -04:00
2023-05-19 18:39:27 -04:00
#[ derive(Default) ]
struct ModifiedResult {
updated_import_map : bool ,
added_node_modules_dir : bool ,
new_text : Option < String > ,
2022-06-14 10:05:37 -04:00
}
fn update_config_text (
text : & str ,
fmt_options : & FmtOptionsConfig ,
2023-05-19 18:39:27 -04:00
import_map_specifier : Option < & str > ,
try_add_node_modules_dir : bool ,
) -> Result < ModifiedResult , AnyError > {
2022-06-14 10:05:37 -04:00
use jsonc_parser ::ast ::ObjectProp ;
use jsonc_parser ::ast ::Value ;
2024-04-18 15:48:15 -04:00
let text = if text . trim ( ) . is_empty ( ) { " {} \n " } else { text } ;
2022-07-26 21:24:56 -04:00
let ast =
2023-05-19 18:39:27 -04:00
jsonc_parser ::parse_to_ast ( text , & Default ::default ( ) , & Default ::default ( ) ) ? ;
2022-06-14 10:05:37 -04:00
let obj = match ast . value {
Some ( Value ::Object ( obj ) ) = > obj ,
2023-05-19 18:39:27 -04:00
_ = > bail! ( " Failed updating config file due to no object. " ) ,
2022-06-14 10:05:37 -04:00
} ;
2023-05-19 18:39:27 -04:00
let mut modified_result = ModifiedResult ::default ( ) ;
let mut text_changes = Vec ::new ( ) ;
let mut should_format = false ;
if try_add_node_modules_dir {
// Only modify the nodeModulesDir property if it's not set
// as this allows people to opt-out of this when vendoring
// by specifying `nodeModulesDir: false`
if obj . get ( " nodeModulesDir " ) . is_none ( ) {
2022-06-14 10:05:37 -04:00
let insert_position = obj . range . end - 1 ;
2023-05-19 18:39:27 -04:00
text_changes . push ( TextChange {
range : insert_position .. insert_position ,
new_text : r #" " nodeModulesDir " : true " #. to_string ( ) ,
} ) ;
should_format = true ;
modified_result . added_node_modules_dir = true ;
2022-06-14 10:05:37 -04:00
}
}
2023-05-19 18:39:27 -04:00
if let Some ( import_map_specifier ) = import_map_specifier {
let import_map_specifier = import_map_specifier . replace ( '\"' , " \\ \" " ) ;
match obj . get ( " importMap " ) {
Some ( ObjectProp {
value : Value ::StringLit ( lit ) ,
..
} ) = > {
text_changes . push ( TextChange {
range : lit . range . start .. lit . range . end ,
new_text : format ! ( " \" {} \" " , import_map_specifier ) ,
} ) ;
modified_result . updated_import_map = true ;
}
None = > {
// insert it crudely at a position that won't cause any issues
// with comments and format after to make it look nice
let insert_position = obj . range . end - 1 ;
text_changes . push ( TextChange {
range : insert_position .. insert_position ,
new_text : format ! ( r # ""importMap": "{}""# , import_map_specifier ) ,
} ) ;
should_format = true ;
modified_result . updated_import_map = true ;
}
// shouldn't happen
Some ( _ ) = > {
bail! ( " Failed updating importMap in config file due to invalid type. " )
}
}
}
if text_changes . is_empty ( ) {
return Ok ( modified_result ) ;
}
let new_text = deno_ast ::apply_text_changes ( text , text_changes ) ;
modified_result . new_text = if should_format {
2023-10-24 09:37:02 -04:00
format_json ( & PathBuf ::from ( " deno.json " ) , & new_text , fmt_options )
2023-05-19 18:39:27 -04:00
. ok ( )
. map ( | formatted_text | formatted_text . unwrap_or ( new_text ) )
} else {
Some ( new_text )
} ;
Ok ( modified_result )
2022-06-14 10:05:37 -04:00
}
2022-02-16 13:14:19 -05:00
fn is_dir_empty ( dir_path : & Path ) -> Result < bool , AnyError > {
2022-11-17 20:59:10 -05:00
match std ::fs ::read_dir ( dir_path ) {
2022-02-16 13:14:19 -05:00
Ok ( mut dir ) = > Ok ( dir . next ( ) . is_none ( ) ) ,
Err ( err ) if err . kind ( ) = = std ::io ::ErrorKind ::NotFound = > Ok ( true ) ,
Err ( err ) = > {
bail! ( " Error reading directory {}: {} " , dir_path . display ( ) , err )
}
}
}
2023-07-14 18:10:42 -04:00
fn resolve_entry_points (
2022-02-16 13:14:19 -05:00
flags : & VendorFlags ,
2023-04-17 15:36:23 -04:00
initial_cwd : & Path ,
2023-07-14 18:10:42 -04:00
) -> Result < Vec < ModuleSpecifier > , AnyError > {
flags
2022-02-16 13:14:19 -05:00
. specifiers
. iter ( )
2023-07-14 18:10:42 -04:00
. map ( | p | resolve_url_or_path ( p , initial_cwd ) . map_err ( | e | e . into ( ) ) )
. collect ::< Result < Vec < _ > , _ > > ( )
2022-06-14 10:05:37 -04:00
}
2022-02-16 13:14:19 -05:00
2022-06-14 10:05:37 -04:00
#[ cfg(test) ]
mod internal_test {
use super ::* ;
use pretty_assertions ::assert_eq ;
2022-02-16 13:14:19 -05:00
2022-06-14 10:05:37 -04:00
#[ test ]
fn update_config_text_no_existing_props_add_prop ( ) {
2023-05-19 18:39:27 -04:00
let result = update_config_text (
" { \n } " ,
& Default ::default ( ) ,
Some ( " ./vendor/import_map.json " ) ,
false ,
)
. unwrap ( ) ;
assert! ( result . updated_import_map ) ;
assert! ( ! result . added_node_modules_dir ) ;
assert_eq! (
result . new_text . unwrap ( ) ,
r #" {
" importMap " : " ./vendor/import_map.json "
}
" #
) ;
let result = update_config_text (
2022-06-14 10:05:37 -04:00
" { \n } " ,
& Default ::default ( ) ,
2023-05-19 18:39:27 -04:00
Some ( " ./vendor/import_map.json " ) ,
true ,
2022-06-14 10:05:37 -04:00
)
. unwrap ( ) ;
2023-05-19 18:39:27 -04:00
assert! ( result . updated_import_map ) ;
assert! ( result . added_node_modules_dir ) ;
2022-06-14 10:05:37 -04:00
assert_eq! (
2023-05-19 18:39:27 -04:00
result . new_text . unwrap ( ) ,
2022-06-14 10:05:37 -04:00
r #" {
2023-05-19 18:39:27 -04:00
" nodeModulesDir " : true ,
2022-06-14 10:05:37 -04:00
" importMap " : " ./vendor/import_map.json "
}
2023-05-19 18:39:27 -04:00
" #
) ;
let result =
update_config_text ( " { \n } " , & Default ::default ( ) , None , true ) . unwrap ( ) ;
assert! ( ! result . updated_import_map ) ;
assert! ( result . added_node_modules_dir ) ;
assert_eq! (
result . new_text . unwrap ( ) ,
r #" {
" nodeModulesDir " : true
}
2022-06-14 10:05:37 -04:00
" #
) ;
}
#[ test ]
fn update_config_text_existing_props_add_prop ( ) {
2023-05-19 18:39:27 -04:00
let result = update_config_text (
2022-06-14 10:05:37 -04:00
r #" {
" tasks " : {
" task1 " : " other "
}
}
" #,
& Default ::default ( ) ,
2023-05-19 18:39:27 -04:00
Some ( " ./vendor/import_map.json " ) ,
false ,
)
. unwrap ( ) ;
assert_eq! (
result . new_text . unwrap ( ) ,
r #" {
" tasks " : {
" task1 " : " other "
} ,
" importMap " : " ./vendor/import_map.json "
}
" #
) ;
// trailing comma
let result = update_config_text (
r #" {
" tasks " : {
" task1 " : " other "
} ,
}
" #,
& Default ::default ( ) ,
Some ( " ./vendor/import_map.json " ) ,
false ,
2022-06-14 10:05:37 -04:00
)
. unwrap ( ) ;
assert_eq! (
2023-05-19 18:39:27 -04:00
result . new_text . unwrap ( ) ,
2022-06-14 10:05:37 -04:00
r #" {
" tasks " : {
" task1 " : " other "
} ,
" importMap " : " ./vendor/import_map.json "
}
" #
) ;
}
#[ test ]
fn update_config_text_update_prop ( ) {
2023-05-19 18:39:27 -04:00
let result = update_config_text (
2022-06-14 10:05:37 -04:00
r #" {
" importMap " : " ./local.json "
}
" #,
& Default ::default ( ) ,
2023-05-19 18:39:27 -04:00
Some ( " ./vendor/import_map.json " ) ,
false ,
2022-06-14 10:05:37 -04:00
)
. unwrap ( ) ;
assert_eq! (
2023-05-19 18:39:27 -04:00
result . new_text . unwrap ( ) ,
2022-06-14 10:05:37 -04:00
r #" {
" importMap " : " ./vendor/import_map.json "
}
" #
) ;
}
2023-05-19 18:39:27 -04:00
#[ test ]
fn no_update_node_modules_dir ( ) {
// will not update if this is already set (even if it's false)
let result = update_config_text (
r #" {
" nodeModulesDir " : false
}
" #,
& Default ::default ( ) ,
None ,
true ,
)
. unwrap ( ) ;
assert! ( ! result . added_node_modules_dir ) ;
assert! ( ! result . updated_import_map ) ;
assert_eq! ( result . new_text , None ) ;
let result = update_config_text (
r #" {
" nodeModulesDir " : true
}
" #,
& Default ::default ( ) ,
None ,
true ,
)
. unwrap ( ) ;
assert! ( ! result . added_node_modules_dir ) ;
assert! ( ! result . updated_import_map ) ;
assert_eq! ( result . new_text , None ) ;
}
2022-02-16 13:14:19 -05:00
}