Skip to content

Commit ce61f69

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feat_mapping_bare_specifiers
# Conflicts: # deno.jsonc
2 parents 7959e37 + 9c71afe commit ce61f69

12 files changed

Lines changed: 286 additions & 7 deletions

File tree

README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,14 @@ await build({
726726

727727
### deno.json Support
728728

729-
Starting in dnt 0.42, the deno.json is auto-discovered. A config file can be
730-
explicitly specified by the `configFile` key:
729+
Starting in dnt 0.42, the deno.json is auto-discovered by searching upwards from
730+
the entry points. dnt logs the config file it discovered:
731+
732+
```
733+
[dnt] Auto-discovered config file: /home/david/dev/my_project/deno.json
734+
```
735+
736+
A config file can be explicitly specified by the `configFile` key:
731737

732738
```ts
733739
await build({
@@ -736,6 +742,16 @@ await build({
736742
});
737743
```
738744

745+
Or set it to `false` to not use a config file at all, which also disables
746+
discovering a package.json and deno.lock:
747+
748+
```ts
749+
await build({
750+
// ...etc...
751+
configFile: false,
752+
});
753+
```
754+
739755
### Frozen Lock File
740756

741757
The deno.lock file that's beside the deno.json is used to resolve dependencies,

deno.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"lib/pkg/",
4545
"rs-lib/src/polyfills/scripts/",
4646
"tests/bare_mapping_project/npm",
47+
"tests/config_discovery_project/npm",
4748
"tests/declaration_import_project/npm",
4849
"tests/frozen_lockfile_project/npm",
4950
"tests/import_map_project/npm",

mod.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,15 @@ export interface BuildOptions {
183183
mappings?: SpecifierMappings;
184184
/** Package.json output. You may override dependencies and dev dependencies in here. */
185185
package: PackageJson;
186-
/** Path or url to a deno.json. */
187-
configFile?: string;
186+
/** Path or url to a deno.json.
187+
*
188+
* When not specified, a deno.json is auto-discovered by searching upwards
189+
* from the entry points.
190+
*
191+
* Specify `false` to disable the auto-discovery, which also disables
192+
* discovering a package.json and deno.lock.
193+
*/
194+
configFile?: string | false;
188195
/** Path or url to import map.
189196
*
190197
* @remarks Use `configFile` for a deno.json. Like `deno --import-map`, the
@@ -352,6 +359,13 @@ export async function build(options: BuildOptions): Promise<void> {
352359

353360
log("Transforming...");
354361
const transformOutput = await transformEntryPoints();
362+
if (transformOutput.discoveredConfigFile != null) {
363+
log(
364+
`Auto-discovered config file: ${
365+
standardizePath(transformOutput.discoveredConfigFile)
366+
}`,
367+
);
368+
}
355369
for (const warning of transformOutput.warnings) {
356370
warn(warning);
357371
}

rs-lib/src/lib.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ pub struct TransformOutput {
101101
pub main: TransformOutputEnvironment,
102102
pub test: TransformOutputEnvironment,
103103
pub warnings: Vec<String>,
104+
/// Config file that was auto-discovered by searching upwards from the
105+
/// entry points (or the cwd when there are no local entry points).
106+
///
107+
/// This is `None` when no config file was found, when one was explicitly
108+
/// provided, or when auto-discovery is disabled.
109+
pub discovered_config_file: Option<PathBuf>,
104110
}
105111

106112
#[cfg_attr(feature = "serialization", derive(serde::Serialize))]
@@ -265,6 +271,11 @@ pub struct TransformOptions {
265271
/// over what `target` implies.
266272
pub polyfills: PolyfillOverrides,
267273
pub config_file: Option<ModuleSpecifier>,
274+
/// Disables auto-discovering a config file based on the entry points
275+
/// when no config file or import map is provided.
276+
///
277+
/// Note this also disables discovering a package.json and deno.lock.
278+
pub no_config: bool,
268279
pub import_map: Option<ModuleSpecifier>,
269280
/// Errors when the deno lockfile would need to be updated in order to
270281
/// transform (ex. a dependency is not in it).
@@ -333,6 +344,7 @@ pub async fn transform(
333344
};
334345
let config_discovery = match maybe_config_path.as_ref() {
335346
Some(config_path) => ConfigDiscoveryOption::Path(config_path.clone()),
347+
None if options.no_config => ConfigDiscoveryOption::Disabled,
336348
None => {
337349
if paths.is_empty() {
338350
ConfigDiscoveryOption::DiscoverCwd
@@ -341,6 +353,10 @@ pub async fn transform(
341353
}
342354
}
343355
};
356+
let is_auto_discovering = matches!(
357+
config_discovery,
358+
ConfigDiscoveryOption::Discover { .. } | ConfigDiscoveryOption::DiscoverCwd
359+
);
344360

345361
let factory = deno_resolver::factory::WorkspaceFactory::new(
346362
sys,
@@ -364,6 +380,14 @@ pub async fn transform(
364380
no_lock: false,
365381
},
366382
);
383+
let discovered_config_file = if is_auto_discovering {
384+
factory
385+
.workspace_directory()?
386+
.member_or_root_deno_json()
387+
.and_then(|c| deno_path_util::url_to_file_path(&c.specifier).ok())
388+
} else {
389+
None
390+
};
367391
let file_fetcher = PermissionedFileFetcher::new(
368392
NullBlobStore,
369393
Rc::new(factory.http_cache()?.clone()),
@@ -680,6 +704,7 @@ pub async fn transform(
680704
main: main_env_context.environment,
681705
test: test_env_context.environment,
682706
warnings,
707+
discovered_config_file,
683708
})
684709
}
685710

rs-lib/tests/integration/test_builder.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub struct TestBuilder {
2929
target: ScriptTarget,
3030
polyfills: PolyfillOverrides,
3131
config_file: Option<ModuleSpecifier>,
32+
no_config: bool,
3233
import_map: Option<ModuleSpecifier>,
3334
frozen_lockfile: Option<bool>,
3435
}
@@ -50,6 +51,7 @@ impl TestBuilder {
5051
target: ScriptTarget::ES5,
5152
polyfills: Default::default(),
5253
config_file: None,
54+
no_config: false,
5355
import_map: None,
5456
frozen_lockfile: None,
5557
}
@@ -81,11 +83,16 @@ impl TestBuilder {
8183
}
8284

8385
pub fn set_config_file(&mut self, url: impl AsRef<str>) -> &mut Self {
84-
self.import_map =
86+
self.config_file =
8587
Some(ModuleSpecifier::parse(&normalize_urls(url.as_ref())).unwrap());
8688
self
8789
}
8890

91+
pub fn set_no_config(&mut self, value: bool) -> &mut Self {
92+
self.no_config = value;
93+
self
94+
}
95+
8996
pub fn set_import_map(&mut self, url: impl AsRef<str>) -> &mut Self {
9097
self.import_map =
9198
Some(ModuleSpecifier::parse(&normalize_urls(url.as_ref())).unwrap());
@@ -218,6 +225,7 @@ impl TestBuilder {
218225
target: self.target,
219226
polyfills: self.polyfills.clone(),
220227
config_file: self.config_file.clone(),
228+
no_config: self.no_config,
221229
import_map: self.import_map.clone(),
222230
frozen_lockfile: self.frozen_lockfile,
223231
cwd: self.loader.sys.env_current_dir().unwrap(),

rs-lib/tests/integration_test.rs

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use pretty_assertions::assert_eq;
1515
#[macro_use]
1616
mod integration;
1717

18+
use integration::InMemoryLoader;
1819
use integration::TestBuilder;
1920

2021
use crate::integration::assert_identity_transforms;
@@ -1244,7 +1245,7 @@ async fn transform_jsr_specifier_mappings() {
12441245
}
12451246

12461247
#[tokio::test]
1247-
async fn transform_jsr_specifier_mapping_via_import_map() {
1248+
async fn transform_jsr_specifier_mapping_via_config_file() {
12481249
let result = TestBuilder::new()
12491250
.with_loader(|loader| {
12501251
loader
@@ -1259,6 +1260,42 @@ async fn transform_jsr_specifier_mapping_via_import_map() {
12591260
);
12601261
})
12611262
.set_config_file("file:///deno.json")
1263+
// the version requirement comes from the config file
1264+
.add_package_specifier_mapping("jsr:@scope/name", "scope-name", None, None)
1265+
.transform()
1266+
.await
1267+
.unwrap();
1268+
1269+
assert_files!(
1270+
result.main.files,
1271+
&[("mod.ts", "import * as pkg from 'scope-name';")]
1272+
);
1273+
assert_eq!(
1274+
result.main.dependencies,
1275+
&[Dependency {
1276+
name: "scope-name".to_string(),
1277+
version: "^1.0.0".to_string(),
1278+
peer_dependency: false,
1279+
}]
1280+
);
1281+
}
1282+
1283+
#[tokio::test]
1284+
async fn transform_jsr_specifier_mapping_via_import_map() {
1285+
let result = TestBuilder::new()
1286+
.with_loader(|loader| {
1287+
loader
1288+
.add_local_file("/mod.ts", "import * as pkg from '@scope/name';")
1289+
.add_local_file(
1290+
"/import_map.json",
1291+
r#"{
1292+
"imports": {
1293+
"@scope/name": "jsr:@scope/name@^1.0.0"
1294+
}
1295+
}"#,
1296+
);
1297+
})
1298+
.set_import_map("file:///import_map.json")
12621299
// the version requirement comes from the import map
12631300
.add_package_specifier_mapping("jsr:@scope/name", "scope-name", None, None)
12641301
.transform()
@@ -1746,6 +1783,8 @@ async fn transform_import_map() {
17461783
.await
17471784
.unwrap();
17481785

1786+
// the import map is used as the config file, so nothing was auto-discovered
1787+
assert_eq!(result.discovered_config_file, None);
17491788
assert_files!(
17501789
result.main.files,
17511790
&[
@@ -1996,6 +2035,8 @@ async fn transform_config_file() {
19962035
.await
19972036
.unwrap();
19982037

2038+
// it was provided, so it wasn't auto-discovered
2039+
assert_eq!(result.discovered_config_file, None);
19992040
assert_files!(
20002041
result.main.files,
20012042
&[
@@ -2006,6 +2047,58 @@ async fn transform_config_file() {
20062047
);
20072048
}
20082049

2050+
#[tokio::test]
2051+
async fn transform_auto_discovered_config_file() {
2052+
let result = TestBuilder::new()
2053+
.with_loader(|loader| {
2054+
add_config_discovery_files(loader);
2055+
})
2056+
.entry_point("file:///sub_dir/mod.ts")
2057+
.transform()
2058+
.await
2059+
.unwrap();
2060+
2061+
assert_eq!(
2062+
result.discovered_config_file,
2063+
Some(PathBuf::from(if cfg!(windows) {
2064+
"C:\\deno.json"
2065+
} else {
2066+
"/deno.json"
2067+
}))
2068+
);
2069+
assert_files!(
2070+
result.main.files,
2071+
&[
2072+
("sub_dir/mod.ts", "import * as remote from '../other.js';",),
2073+
("other.ts", "export function test() {}",)
2074+
]
2075+
);
2076+
}
2077+
2078+
#[tokio::test]
2079+
async fn transform_no_config() {
2080+
let err_message = TestBuilder::new()
2081+
.with_loader(|loader| {
2082+
add_config_discovery_files(loader);
2083+
})
2084+
.entry_point("file:///sub_dir/mod.ts")
2085+
.set_no_config(true)
2086+
.transform()
2087+
.await
2088+
.err()
2089+
.unwrap();
2090+
2091+
// the config file should not have been discovered, so its
2092+
// import mapping should not have been applied
2093+
assert_eq!(
2094+
err_message.to_string(),
2095+
normalize_urls(
2096+
"Import \"localhost/mod.ts\" not a dependency
2097+
at file:///sub_dir/mod.ts:1:25"
2098+
)
2099+
);
2100+
}
2101+
20092102
#[tokio::test]
20102103
async fn transform_multiple_entry_points() {
20112104
let result = TestBuilder::new()
@@ -3021,3 +3114,22 @@ fn get_shim_file_text(mut text: String) -> String {
30213114
);
30223115
text
30233116
}
3117+
3118+
/// Adds a config file in a parent directory of the `/sub_dir/mod.ts`
3119+
/// entry point so that it's only found by searching upwards from it.
3120+
fn add_config_discovery_files(loader: &mut InMemoryLoader) {
3121+
loader
3122+
.add_local_file(
3123+
"/sub_dir/mod.ts",
3124+
"import * as remote from 'localhost/mod.ts';",
3125+
)
3126+
.add_local_file(
3127+
"/deno.json",
3128+
r#"{
3129+
"imports": {
3130+
"localhost/mod.ts": "./other.ts"
3131+
}
3132+
}"#,
3133+
)
3134+
.add_local_file("/other.ts", "export function test() {}");
3135+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"imports": {
3+
"@dnt/marker": "./marker.ts"
4+
}
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Copyright 2018-2024 the Deno authors. MIT license.
2+
3+
export const marker = "marker";
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2018-2024 the Deno authors. MIT license.
2+
3+
import { marker } from "@dnt/marker";
4+
5+
export function getMarker() {
6+
return marker;
7+
}

0 commit comments

Comments
 (0)