Skip to content

Commit f93c9b5

Browse files
committed
feat: multiple import maps
1 parent 4a1f63b commit f93c9b5

File tree

22 files changed

+668
-605
lines changed

22 files changed

+668
-605
lines changed

cli/args/flags.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ pub struct Flags {
731731
/// Flags that aren't exposed in the CLI, but are used internally.
732732
pub internal: InternalFlags,
733733
pub ignore: Vec<String>,
734-
pub import_map_path: Option<String>,
734+
pub import_map_paths: Vec<String>,
735735
pub env_file: Option<Vec<String>>,
736736
pub inspect_brk: Option<SocketAddr>,
737737
pub inspect_wait: Option<SocketAddr>,
@@ -4388,6 +4388,7 @@ fn import_map_arg() -> Arg {
43884388
<p(245)>Docs: https://docs.deno.com/runtime/manual/basics/import_maps</>",
43894389
))
43904390
.value_hint(ValueHint::FilePath)
4391+
.action(ArgAction::Append)
43914392
.help_heading(DEPENDENCY_MANAGEMENT_HEADING)
43924393
}
43934394

@@ -6325,7 +6326,10 @@ fn inspect_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
63256326
}
63266327

63276328
fn import_map_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
6328-
flags.import_map_path = matches.remove_one::<String>("import-map");
6329+
flags.import_map_paths = matches
6330+
.remove_many::<String>("import-map")
6331+
.unwrap_or_default()
6332+
.collect();
63296333
}
63306334

63316335
fn env_file_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
@@ -8375,7 +8379,7 @@ mod tests {
83758379
print: false,
83768380
code: "42".to_string(),
83778381
}),
8378-
import_map_path: Some("import_map.json".to_string()),
8382+
import_map_paths: vec!["import_map.json".to_string()],
83798383
no_remote: true,
83808384
config_flag: ConfigFlag::Path("tsconfig.json".to_owned()),
83818385
type_check_mode: TypeCheckMode::None,
@@ -8470,7 +8474,7 @@ mod tests {
84708474
is_default_command: false,
84718475
json: false,
84728476
}),
8473-
import_map_path: Some("import_map.json".to_string()),
8477+
import_map_paths: vec!["import_map.json".to_string()],
84748478
no_remote: true,
84758479
config_flag: ConfigFlag::Path("tsconfig.json".to_owned()),
84768480
type_check_mode: TypeCheckMode::None,
@@ -9058,7 +9062,7 @@ mod tests {
90589062
subcommand: DenoSubcommand::Run(RunFlags::new_default(
90599063
"script.ts".to_string(),
90609064
)),
9061-
import_map_path: Some("import_map.json".to_owned()),
9065+
import_map_paths: vec!["import_map.json".to_owned()],
90629066
code_cache_enabled: true,
90639067
..Flags::default()
90649068
}
@@ -9080,7 +9084,7 @@ mod tests {
90809084
file: Some("script.ts".to_string()),
90819085
json: false,
90829086
}),
9083-
import_map_path: Some("import_map.json".to_owned()),
9087+
import_map_paths: vec!["import_map.json".to_owned()],
90849088
..Flags::default()
90859089
}
90869090
);
@@ -9100,7 +9104,7 @@ mod tests {
91009104
subcommand: DenoSubcommand::Cache(CacheFlags {
91019105
files: svec!["script.ts"],
91029106
}),
9103-
import_map_path: Some("import_map.json".to_owned()),
9107+
import_map_paths: vec!["import_map.json".to_owned()],
91049108
..Flags::default()
91059109
}
91069110
);
@@ -9125,7 +9129,7 @@ mod tests {
91259129
lint: false,
91269130
filter: None,
91279131
}),
9128-
import_map_path: Some("import_map.json".to_owned()),
9132+
import_map_paths: vec!["import_map.json".to_owned()],
91299133
..Flags::default()
91309134
}
91319135
);
@@ -9360,7 +9364,7 @@ mod tests {
93609364
force: true,
93619365
}
93629366
),),
9363-
import_map_path: Some("import_map.json".to_string()),
9367+
import_map_paths: vec!["import_map.json".to_string()],
93649368
no_remote: true,
93659369
config_flag: ConfigFlag::Path("tsconfig.json".to_owned()),
93669370
type_check_mode: TypeCheckMode::None,
@@ -11081,7 +11085,7 @@ mod tests {
1108111085
exclude: vec!["exclude.txt".to_string()],
1108211086
eszip: false
1108311087
}),
11084-
import_map_path: Some("import_map.json".to_string()),
11088+
import_map_paths: vec!["import_map.json".to_string()],
1108511089
no_remote: true,
1108611090
code_cache_enabled: false,
1108711091
config_flag: ConfigFlag::Path("tsconfig.json".to_owned()),

cli/args/mod.rs

Lines changed: 27 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,11 @@ impl CliOptions {
576576
///
577577
/// This will NOT include the config file if it
578578
/// happens to be an import map.
579-
pub fn resolve_specified_import_map_specifier(
579+
pub fn resolve_specified_import_map_specifiers(
580580
&self,
581-
) -> Result<Option<ModuleSpecifier>, ImportMapSpecifierResolveError> {
582-
resolve_import_map_specifier(
583-
self.flags.import_map_path.as_deref(),
584-
self.workspace().root_deno_json().map(|c| c.as_ref()),
581+
) -> Result<Vec<ModuleSpecifier>, ImportMapSpecifierResolveError> {
582+
resolve_import_map_specifiers(
583+
self.flags.import_map_paths.iter().map(String::as_ref),
585584
&self.initial_cwd,
586585
)
587586
}
@@ -1322,9 +1321,12 @@ impl CliOptions {
13221321
);
13231322
}
13241323

1325-
if let Ok(Some(import_map_path)) = self
1326-
.resolve_specified_import_map_specifier()
1327-
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
1324+
for import_map_path in self
1325+
.resolve_specified_import_map_specifiers()
1326+
.ok()
1327+
.into_iter()
1328+
.flatten()
1329+
.flat_map(|ms| ms.to_file_path().ok())
13281330
{
13291331
full_paths.push(import_map_path);
13301332
}
@@ -1417,28 +1419,19 @@ pub struct ImportMapSpecifierResolveError {
14171419
source: deno_path_util::ResolveUrlOrPathError,
14181420
}
14191421

1420-
fn resolve_import_map_specifier(
1421-
maybe_import_map_path: Option<&str>,
1422-
maybe_config_file: Option<&ConfigFile>,
1422+
// TODO: Shouldn't it also include deno.json in result?
1423+
fn resolve_import_map_specifiers<'i>(
1424+
maybe_import_map_paths: impl Iterator<Item = &'i str>,
14231425
current_dir: &Path,
1424-
) -> Result<Option<Url>, ImportMapSpecifierResolveError> {
1425-
if let Some(import_map_path) = maybe_import_map_path {
1426-
if let Some(config_file) = &maybe_config_file
1427-
&& config_file.json.import_map.is_some()
1428-
{
1429-
log::warn!(
1430-
"{} the configuration file \"{}\" contains an entry for \"importMap\" that is being ignored.",
1431-
colors::yellow("Warning"),
1432-
config_file.specifier,
1433-
);
1434-
}
1435-
let specifier =
1436-
deno_path_util::resolve_url_or_path(import_map_path, current_dir)
1437-
.map_err(|source| ImportMapSpecifierResolveError { source })?;
1438-
Ok(Some(specifier))
1439-
} else {
1440-
Ok(None)
1441-
}
1426+
) -> Result<Vec<Url>, ImportMapSpecifierResolveError> {
1427+
maybe_import_map_paths
1428+
.map(|import_map_path| {
1429+
let specifier =
1430+
deno_path_util::resolve_url_or_path(import_map_path, current_dir)
1431+
.map_err(|source| ImportMapSpecifierResolveError { source })?;
1432+
Ok(specifier)
1433+
})
1434+
.collect()
14421435
}
14431436

14441437
/// Resolves the no_prompt value based on the cli flags and environment.
@@ -1717,40 +1710,27 @@ mod test {
17171710

17181711
#[test]
17191712
fn resolve_import_map_flags_take_precedence() {
1720-
let config_text = r#"{
1721-
"importMap": "import_map.json"
1722-
}"#;
17231713
let cwd = &std::env::current_dir().unwrap();
1724-
let config_specifier = Url::parse("file:///deno/deno.jsonc").unwrap();
1725-
let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
1726-
let actual = resolve_import_map_specifier(
1727-
Some("import-map.json"),
1728-
Some(&config_file),
1729-
cwd,
1730-
);
1714+
let actual = resolve_import_map_specifiers(&["import-map.json"], cwd);
17311715
let import_map_path = cwd.join("import-map.json");
17321716
let expected_specifier =
17331717
deno_path_util::url_from_file_path(&import_map_path).unwrap();
17341718
assert!(actual.is_ok());
17351719
let actual = actual.unwrap();
1736-
assert_eq!(actual, Some(expected_specifier));
1720+
assert_eq!(actual, vec![expected_specifier]);
17371721
}
17381722

17391723
#[test]
17401724
fn resolve_import_map_none() {
1741-
let config_text = r#"{}"#;
1742-
let config_specifier = Url::parse("file:///deno/deno.jsonc").unwrap();
1743-
let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
1744-
let actual =
1745-
resolve_import_map_specifier(None, Some(&config_file), Path::new("/"));
1725+
let actual = resolve_import_map_specifiers(&[], Path::new("/"));
17461726
assert!(actual.is_ok());
17471727
let actual = actual.unwrap();
1748-
assert_eq!(actual, None);
1728+
assert_eq!(actual, vec![]);
17491729
}
17501730

17511731
#[test]
17521732
fn resolve_import_map_no_config() {
1753-
let actual = resolve_import_map_specifier(None, None, Path::new("/"));
1733+
let actual = resolve_import_map_specifiers(&[], Path::new("/"));
17541734
assert!(actual.is_ok());
17551735
let actual = actual.unwrap();
17561736
assert_eq!(actual, None);

cli/factory.rs

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ struct CliSpecifiedImportMapProvider {
186186
impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
187187
async fn get(
188188
&self,
189-
) -> Result<Option<deno_resolver::workspace::SpecifiedImportMap>, AnyError>
189+
) -> Result<Vec<deno_resolver::workspace::SpecifiedImportMap>, AnyError>
190190
{
191191
async fn resolve_import_map_value_from_specifier(
192192
specifier: &Url,
@@ -204,40 +204,37 @@ impl SpecifiedImportMapProvider for CliSpecifiedImportMapProvider {
204204
}
205205
}
206206

207-
let maybe_import_map_specifier =
208-
self.cli_options.resolve_specified_import_map_specifier()?;
209-
match maybe_import_map_specifier {
210-
Some(specifier) => {
211-
let value = match self.eszip_module_loader_provider.get().await? {
212-
Some(eszip) => eszip.load_import_map_value(&specifier)?,
213-
None => resolve_import_map_value_from_specifier(
214-
&specifier,
215-
&self.file_fetcher,
216-
)
217-
.await
218-
.with_context(|| {
219-
format!("Unable to load '{}' import map", specifier)
220-
})?,
221-
};
222-
Ok(Some(deno_resolver::workspace::SpecifiedImportMap {
223-
base_url: specifier,
224-
value,
225-
}))
226-
}
227-
None => {
228-
if let Some(import_map) =
229-
self.workspace_external_import_map_loader.get_or_load()?
230-
{
231-
let path_url = deno_path_util::url_from_file_path(&import_map.path)?;
232-
Ok(Some(deno_resolver::workspace::SpecifiedImportMap {
233-
base_url: path_url,
234-
value: import_map.value.clone(),
235-
}))
236-
} else {
237-
Ok(None)
238-
}
239-
}
207+
let mut out = Vec::new();
208+
209+
let maybe_import_map_specifiers =
210+
self.cli_options.resolve_specified_import_map_specifiers()?;
211+
212+
for specifier in maybe_import_map_specifiers {
213+
let value = match self.eszip_module_loader_provider.get().await? {
214+
Some(eszip) => eszip.load_import_map_value(&specifier)?,
215+
None => resolve_import_map_value_from_specifier(
216+
&specifier,
217+
&self.file_fetcher,
218+
)
219+
.await
220+
.with_context(|| {
221+
format!("Unable to load '{}' import map", specifier)
222+
})?,
223+
};
224+
out.push(deno_resolver::workspace::SpecifiedImportMap {
225+
base_url: specifier,
226+
value,
227+
})
240228
}
229+
for import_map in self.workspace_external_import_map_loader.get_or_load()? {
230+
let path_url = deno_path_util::url_from_file_path(&import_map.path)?;
231+
out.push(deno_resolver::workspace::SpecifiedImportMap {
232+
base_url: path_url,
233+
value: import_map.value.clone(),
234+
})
235+
}
236+
237+
Ok(out)
241238
}
242239
}
243240

@@ -1192,7 +1189,7 @@ impl CliFactory {
11921189
},
11931190
node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)),
11941191
npm_system_info: self.flags.subcommand.npm_system_info(),
1195-
specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider {
1192+
specified_import_map: Box::new(CliSpecifiedImportMapProvider {
11961193
cli_options: options.clone(),
11971194
eszip_module_loader_provider: self
11981195
.eszip_module_loader_provider()?
@@ -1201,7 +1198,7 @@ impl CliFactory {
12011198
workspace_external_import_map_loader: self
12021199
.workspace_external_import_map_loader()?
12031200
.clone(),
1204-
})),
1201+
}),
12051202
bare_node_builtins: options.unstable_bare_node_builtins(),
12061203
unstable_sloppy_imports: options.unstable_sloppy_imports(),
12071204
on_mapped_resolution_diagnostic: Some(Arc::new(

cli/lib/standalone/binary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub struct SerializedResolverWorkspaceJsrPackage {
6363

6464
#[derive(Deserialize, Serialize)]
6565
pub struct SerializedWorkspaceResolver {
66-
pub import_map: Option<SerializedWorkspaceResolverImportMap>,
66+
pub import_maps: Vec<SerializedWorkspaceResolverImportMap>,
6767
pub jsr_pkgs: Vec<SerializedResolverWorkspaceJsrPackage>,
6868
pub package_jsons: BTreeMap<String, serde_json::Value>,
6969
pub pkg_json_resolution: PackageJsonDepResolution,

0 commit comments

Comments
 (0)