2024-01-01 14:58:21 -05:00
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2022-06-27 16:54:09 -04:00
2024-03-05 15:45:44 -05:00
pub mod deno_json ;
2022-11-25 17:00:28 -05:00
mod flags ;
2023-08-03 07:19:19 -04:00
mod flags_net ;
2023-01-25 15:13:40 -05:00
mod import_map ;
mod lockfile ;
2024-07-03 20:54:33 -04:00
mod package_json ;
2022-06-27 16:54:09 -04:00
2024-04-11 19:00:17 -04:00
use deno_ast ::SourceMapOption ;
2024-08-30 17:58:24 -04:00
use deno_config ::deno_json ::NodeModulesDirMode ;
2024-07-03 20:54:33 -04:00
use deno_config ::workspace ::CreateResolverOptions ;
2024-08-30 17:58:24 -04:00
use deno_config ::workspace ::FolderConfigs ;
2024-07-03 20:54:33 -04:00
use deno_config ::workspace ::PackageJsonDepResolution ;
2024-07-05 17:53:09 -04:00
use deno_config ::workspace ::VendorEnablement ;
2024-07-03 20:54:33 -04:00
use deno_config ::workspace ::Workspace ;
2024-07-19 15:56:07 -04:00
use deno_config ::workspace ::WorkspaceDirectory ;
use deno_config ::workspace ::WorkspaceDirectoryEmptyOptions ;
2024-07-03 20:54:33 -04:00
use deno_config ::workspace ::WorkspaceDiscoverOptions ;
use deno_config ::workspace ::WorkspaceDiscoverStart ;
2024-07-19 15:56:07 -04:00
use deno_config ::workspace ::WorkspaceLintConfig ;
2024-07-03 20:54:33 -04:00
use deno_config ::workspace ::WorkspaceResolver ;
2023-03-22 10:15:53 -04:00
use deno_core ::resolve_url_or_path ;
2024-05-16 03:09:35 -04:00
use deno_graph ::GraphKind ;
2024-05-23 17:26:23 -04:00
use deno_npm ::npm_rc ::NpmRc ;
use deno_npm ::npm_rc ::ResolvedNpmRc ;
2023-04-13 10:47:45 -04:00
use deno_npm ::resolution ::ValidSerializedNpmResolutionSnapshot ;
2023-05-17 17:38:50 -04:00
use deno_npm ::NpmSystemInfo ;
2024-09-28 07:55:01 -04:00
use deno_path_util ::normalize_path ;
2023-04-06 18:46:44 -04:00
use deno_semver ::npm ::NpmPackageReqReference ;
2024-07-03 20:54:33 -04:00
use import_map ::resolve_import_map_value_from_specifier ;
2023-02-20 13:14:06 -05:00
2024-07-19 15:56:07 -04:00
pub use deno_config ::deno_json ::BenchConfig ;
pub use deno_config ::deno_json ::ConfigFile ;
pub use deno_config ::deno_json ::FmtOptionsConfig ;
pub use deno_config ::deno_json ::JsxImportSourceConfig ;
pub use deno_config ::deno_json ::LintRulesConfig ;
pub use deno_config ::deno_json ::ProseWrap ;
pub use deno_config ::deno_json ::TsConfig ;
pub use deno_config ::deno_json ::TsConfigForEmit ;
pub use deno_config ::deno_json ::TsConfigType ;
pub use deno_config ::deno_json ::TsTypeLib ;
2024-01-15 19:15:39 -05:00
pub use deno_config ::glob ::FilePatterns ;
2024-09-04 11:39:30 -04:00
pub use deno_json ::check_warn_tsconfig ;
2022-06-27 16:54:09 -04:00
pub use flags ::* ;
2024-06-28 20:18:21 -04:00
pub use lockfile ::CliLockfile ;
2024-10-02 16:17:39 -04:00
pub use lockfile ::CliLockfileReadFromPathOptions ;
2024-09-04 10:00:44 -04:00
pub use package_json ::NpmInstallDepsProvider ;
2022-06-28 16:45:55 -04:00
use deno_ast ::ModuleSpecifier ;
use deno_core ::anyhow ::bail ;
use deno_core ::anyhow ::Context ;
use deno_core ::error ::AnyError ;
2023-02-20 13:14:06 -05:00
use deno_core ::serde_json ;
2022-06-28 16:45:55 -04:00
use deno_core ::url ::Url ;
2024-06-06 23:37:53 -04:00
use deno_runtime ::deno_permissions ::PermissionsOptions ;
2023-10-31 07:55:46 -04:00
use deno_runtime ::deno_tls ::deno_native_certs ::load_native_certs ;
2023-01-07 15:22:09 -05:00
use deno_runtime ::deno_tls ::rustls ;
2022-06-28 16:45:55 -04:00
use deno_runtime ::deno_tls ::rustls ::RootCertStore ;
2023-01-07 15:22:09 -05:00
use deno_runtime ::deno_tls ::rustls_pemfile ;
use deno_runtime ::deno_tls ::webpki_roots ;
2022-06-28 16:45:55 -04:00
use deno_runtime ::inspector_server ::InspectorServer ;
2024-02-07 11:25:14 -05:00
use deno_terminal ::colors ;
2023-11-01 11:21:13 -04:00
use dotenvy ::from_filename ;
2023-02-20 13:14:06 -05:00
use once_cell ::sync ::Lazy ;
2023-10-02 17:53:55 -04:00
use serde ::Deserialize ;
use serde ::Serialize ;
2024-08-30 17:58:24 -04:00
use std ::borrow ::Cow ;
2023-03-22 10:15:53 -04:00
use std ::collections ::HashMap ;
2022-06-28 16:45:55 -04:00
use std ::env ;
2022-11-28 17:28:54 -05:00
use std ::io ::BufReader ;
2023-01-17 19:18:24 -05:00
use std ::io ::Cursor ;
2024-09-27 15:35:37 -04:00
use std ::io ::Read ;
use std ::io ::Seek ;
2022-06-28 16:45:55 -04:00
use std ::net ::SocketAddr ;
2023-01-07 15:22:09 -05:00
use std ::num ::NonZeroUsize ;
2023-02-20 13:14:06 -05:00
use std ::path ::Path ;
2022-06-28 16:45:55 -04:00
use std ::path ::PathBuf ;
2022-11-02 11:32:30 -04:00
use std ::sync ::Arc ;
2023-05-01 16:42:05 -04:00
use thiserror ::Error ;
2022-06-28 16:45:55 -04:00
2024-06-26 18:17:00 -04:00
use crate ::cache ;
2024-08-15 23:48:48 -04:00
use crate ::cache ::DenoDirProvider ;
2023-01-25 15:13:40 -05:00
use crate ::file_fetcher ::FileFetcher ;
2022-11-28 17:28:54 -05:00
use crate ::util ::fs ::canonicalize_path_maybe_not_exists ;
2022-06-28 16:45:55 -04:00
use crate ::version ;
2024-07-19 15:56:07 -04:00
use deno_config ::deno_json ::FmtConfig ;
use deno_config ::deno_json ::LintConfig ;
use deno_config ::deno_json ::TestConfig ;
2023-08-24 05:21:34 -04:00
2024-03-06 08:24:15 -05:00
pub fn npm_registry_url ( ) -> & 'static Url {
2023-10-25 14:39:00 -04:00
static NPM_REGISTRY_DEFAULT_URL : Lazy < Url > = Lazy ::new ( | | {
let env_var_name = " NPM_CONFIG_REGISTRY " ;
if let Ok ( registry_url ) = std ::env ::var ( env_var_name ) {
// ensure there is a trailing slash for the directory
let registry_url = format! ( " {} / " , registry_url . trim_end_matches ( '/' ) ) ;
match Url ::parse ( & registry_url ) {
Ok ( url ) = > {
return url ;
}
Err ( err ) = > {
log ::debug! (
" Invalid {} environment variable: {:#} " ,
env_var_name ,
err ,
) ;
}
2023-10-02 17:53:55 -04:00
}
}
2023-10-25 14:39:00 -04:00
Url ::parse ( " https://registry.npmjs.org " ) . unwrap ( )
} ) ;
2023-10-02 17:53:55 -04:00
& NPM_REGISTRY_DEFAULT_URL
}
2024-03-07 08:59:57 -05:00
pub static DENO_DISABLE_PEDANTIC_NODE_WARNINGS : Lazy < bool > = Lazy ::new ( | | {
std ::env ::var ( " DENO_DISABLE_PEDANTIC_NODE_WARNINGS " )
. ok ( )
. is_some ( )
} ) ;
2024-02-14 13:30:44 -05:00
pub fn jsr_url ( ) -> & 'static Url {
static JSR_URL : Lazy < Url > = Lazy ::new ( | | {
let env_var_name = " JSR_URL " ;
2023-12-12 09:45:20 -05:00
if let Ok ( registry_url ) = std ::env ::var ( env_var_name ) {
// ensure there is a trailing slash for the directory
let registry_url = format! ( " {} / " , registry_url . trim_end_matches ( '/' ) ) ;
match Url ::parse ( & registry_url ) {
Ok ( url ) = > {
return url ;
}
Err ( err ) = > {
log ::debug! (
" Invalid {} environment variable: {:#} " ,
env_var_name ,
err ,
) ;
}
}
}
2023-12-15 08:14:28 -05:00
Url ::parse ( " https://jsr.io/ " ) . unwrap ( )
2023-12-12 09:45:20 -05:00
} ) ;
2024-02-14 13:30:44 -05:00
& JSR_URL
2023-12-12 09:45:20 -05:00
}
2024-02-14 13:30:44 -05:00
pub fn jsr_api_url ( ) -> & 'static Url {
static JSR_API_URL : Lazy < Url > = Lazy ::new ( | | {
let mut jsr_api_url = jsr_url ( ) . clone ( ) ;
jsr_api_url . set_path ( " api/ " ) ;
jsr_api_url
2023-12-12 09:45:20 -05:00
} ) ;
2024-02-14 13:30:44 -05:00
& JSR_API_URL
2023-12-12 09:45:20 -05:00
}
2024-04-11 19:00:17 -04:00
pub fn ts_config_to_transpile_and_emit_options (
2024-07-19 15:56:07 -04:00
config : deno_config ::deno_json ::TsConfig ,
2024-04-23 11:50:50 -04:00
) -> Result < ( deno_ast ::TranspileOptions , deno_ast ::EmitOptions ) , AnyError > {
2024-07-19 15:56:07 -04:00
let options : deno_config ::deno_json ::EmitConfigOptions =
2024-04-23 11:50:50 -04:00
serde_json ::from_value ( config . 0 )
. context ( " Failed to parse compilerOptions " ) ? ;
2023-08-24 05:21:34 -04:00
let imports_not_used_as_values =
match options . imports_not_used_as_values . as_str ( ) {
" preserve " = > deno_ast ::ImportsNotUsedAsValues ::Preserve ,
" error " = > deno_ast ::ImportsNotUsedAsValues ::Error ,
_ = > deno_ast ::ImportsNotUsedAsValues ::Remove ,
} ;
2023-11-01 16:30:23 -04:00
let ( transform_jsx , jsx_automatic , jsx_development , precompile_jsx ) =
2023-08-24 05:21:34 -04:00
match options . jsx . as_str ( ) {
2023-11-01 16:30:23 -04:00
" react " = > ( true , false , false , false ) ,
" react-jsx " = > ( true , true , false , false ) ,
" react-jsxdev " = > ( true , true , true , false ) ,
" precompile " = > ( false , false , false , true ) ,
_ = > ( false , false , false , false ) ,
2023-08-24 05:21:34 -04:00
} ;
2024-04-11 19:00:17 -04:00
let source_map = if options . inline_source_map {
SourceMapOption ::Inline
} else if options . source_map {
SourceMapOption ::Separate
} else {
SourceMapOption ::None
} ;
2024-04-23 11:50:50 -04:00
Ok ( (
2024-04-11 19:00:17 -04:00
deno_ast ::TranspileOptions {
use_ts_decorators : options . experimental_decorators ,
use_decorators_proposal : ! options . experimental_decorators ,
emit_metadata : options . emit_decorator_metadata ,
imports_not_used_as_values ,
jsx_automatic ,
jsx_development ,
jsx_factory : options . jsx_factory ,
jsx_fragment_factory : options . jsx_fragment_factory ,
jsx_import_source : options . jsx_import_source ,
precompile_jsx ,
2024-04-22 11:07:36 -04:00
precompile_jsx_skip_elements : options . jsx_precompile_skip_elements ,
2024-07-10 09:51:55 -04:00
precompile_jsx_dynamic_props : None ,
2024-04-11 19:00:17 -04:00
transform_jsx ,
var_decl_imports : false ,
} ,
deno_ast ::EmitOptions {
inline_sources : options . inline_sources ,
2024-06-05 11:04:16 -04:00
remove_comments : false ,
2024-04-11 19:00:17 -04:00
source_map ,
2024-07-31 18:31:03 -04:00
source_map_base : None ,
2024-04-30 14:12:35 -04:00
source_map_file : None ,
2024-04-11 19:00:17 -04:00
} ,
2024-04-23 11:50:50 -04:00
) )
2023-08-24 05:21:34 -04:00
}
2023-01-07 15:22:09 -05:00
2022-11-28 17:28:54 -05:00
/// Indicates how cached source files should be handled.
#[ derive(Debug, Clone, Eq, PartialEq) ]
pub enum CacheSetting {
/// Only the cached files should be used. Any files not in the cache will
/// error. This is the equivalent of `--cached-only` in the CLI.
Only ,
/// No cached source files should be used, and all files should be reloaded.
/// This is the equivalent of `--reload` in the CLI.
ReloadAll ,
/// Only some cached resources should be used. This is the equivalent of
2024-04-10 17:26:35 -04:00
/// `--reload=jsr:@std/http/file-server` or
/// `--reload=jsr:@std/http/file-server,jsr:@std/assert/assert-equals`.
2022-11-28 17:28:54 -05:00
ReloadSome ( Vec < String > ) ,
/// The usability of a cached value is determined by analyzing the cached
/// headers and other metadata associated with a cached response, reloading
/// any cached "non-fresh" cached responses.
RespectHeaders ,
/// The cached source files should be used for local modules. This is the
/// default behavior of the CLI.
Use ,
}
impl CacheSetting {
pub fn should_use_for_npm_package ( & self , package_name : & str ) -> bool {
match self {
CacheSetting ::ReloadAll = > false ,
CacheSetting ::ReloadSome ( list ) = > {
if list . iter ( ) . any ( | i | i = = " npm: " ) {
return false ;
}
2023-01-27 10:43:16 -05:00
let specifier = format! ( " npm: {package_name} " ) ;
2022-11-28 17:28:54 -05:00
if list . contains ( & specifier ) {
return false ;
}
true
}
_ = > true ,
}
}
}
2024-07-03 20:54:33 -04:00
pub struct WorkspaceBenchOptions {
2023-01-07 15:22:09 -05:00
pub filter : Option < String > ,
2023-02-12 12:40:45 -05:00
pub json : bool ,
2023-03-26 10:55:58 -04:00
pub no_run : bool ,
2023-01-07 15:22:09 -05:00
}
2024-07-03 20:54:33 -04:00
impl WorkspaceBenchOptions {
pub fn resolve ( bench_flags : & BenchFlags ) -> Self {
Self {
filter : bench_flags . filter . clone ( ) ,
json : bench_flags . json ,
no_run : bench_flags . no_run ,
}
}
}
#[ derive(Clone, Debug, Eq, PartialEq) ]
pub struct BenchOptions {
pub files : FilePatterns ,
}
2023-01-07 15:22:09 -05:00
impl BenchOptions {
2024-07-08 10:12:10 -04:00
pub fn resolve ( bench_config : BenchConfig , _bench_flags : & BenchFlags ) -> Self {
// this is the same, but keeping the same pattern as everywhere else for the future
Self {
files : bench_config . files ,
}
2023-01-07 15:22:09 -05:00
}
}
2024-08-02 09:52:48 -04:00
#[ derive(Clone, Debug, Default, PartialEq, Eq, Hash) ]
pub struct UnstableFmtOptions {
2024-08-14 16:58:48 -04:00
pub component : bool ,
2024-08-02 09:52:48 -04:00
}
2024-01-18 15:57:30 -05:00
#[ derive(Clone, Debug) ]
2023-01-07 15:22:09 -05:00
pub struct FmtOptions {
pub options : FmtOptionsConfig ,
2024-08-02 09:52:48 -04:00
pub unstable : UnstableFmtOptions ,
2024-01-08 12:18:42 -05:00
pub files : FilePatterns ,
2023-01-07 15:22:09 -05:00
}
2024-03-26 11:52:20 -04:00
impl Default for FmtOptions {
fn default ( ) -> Self {
Self ::new_with_base ( PathBuf ::from ( " / " ) )
}
}
2023-01-07 15:22:09 -05:00
impl FmtOptions {
2024-01-18 15:57:30 -05:00
pub fn new_with_base ( base : PathBuf ) -> Self {
Self {
options : FmtOptionsConfig ::default ( ) ,
2024-08-02 09:52:48 -04:00
unstable : Default ::default ( ) ,
2024-01-18 15:57:30 -05:00
files : FilePatterns ::new_with_base ( base ) ,
}
}
2024-08-02 09:52:48 -04:00
pub fn resolve (
fmt_config : FmtConfig ,
unstable : UnstableFmtOptions ,
fmt_flags : & FmtFlags ,
) -> Self {
2024-07-08 10:12:10 -04:00
Self {
2024-07-03 20:54:33 -04:00
options : resolve_fmt_options ( fmt_flags , fmt_config . options ) ,
2024-08-02 09:52:48 -04:00
unstable : UnstableFmtOptions {
2024-08-14 16:58:48 -04:00
component : unstable . component | | fmt_flags . unstable_component ,
2024-08-02 09:52:48 -04:00
} ,
2024-07-08 10:12:10 -04:00
files : fmt_config . files ,
}
2023-01-07 15:22:09 -05:00
}
}
fn resolve_fmt_options (
2024-07-03 20:54:33 -04:00
fmt_flags : & FmtFlags ,
mut options : FmtOptionsConfig ,
2023-01-07 15:22:09 -05:00
) -> FmtOptionsConfig {
2024-07-03 20:54:33 -04:00
if let Some ( use_tabs ) = fmt_flags . use_tabs {
options . use_tabs = Some ( use_tabs ) ;
}
2023-01-07 15:22:09 -05:00
2024-07-03 20:54:33 -04:00
if let Some ( line_width ) = fmt_flags . line_width {
options . line_width = Some ( line_width . get ( ) ) ;
}
2023-01-07 15:22:09 -05:00
2024-07-03 20:54:33 -04:00
if let Some ( indent_width ) = fmt_flags . indent_width {
options . indent_width = Some ( indent_width . get ( ) ) ;
}
2023-01-07 15:22:09 -05:00
2024-07-03 20:54:33 -04:00
if let Some ( single_quote ) = fmt_flags . single_quote {
options . single_quote = Some ( single_quote ) ;
}
2023-01-07 15:22:09 -05:00
2024-07-03 20:54:33 -04:00
if let Some ( prose_wrap ) = & fmt_flags . prose_wrap {
options . prose_wrap = Some ( match prose_wrap . as_str ( ) {
" always " = > ProseWrap ::Always ,
" never " = > ProseWrap ::Never ,
" preserve " = > ProseWrap ::Preserve ,
// validators in `flags.rs` makes other values unreachable
_ = > unreachable! ( ) ,
} ) ;
}
2023-01-24 15:07:00 -05:00
2024-07-03 20:54:33 -04:00
if let Some ( no_semis ) = & fmt_flags . no_semicolons {
options . semi_colons = Some ( ! no_semis ) ;
2023-01-07 15:22:09 -05:00
}
options
}
2024-07-03 20:54:33 -04:00
#[ derive(Clone, Debug) ]
pub struct WorkspaceTestOptions {
2023-01-07 15:22:09 -05:00
pub doc : bool ,
pub no_run : bool ,
pub fail_fast : Option < NonZeroUsize > ,
2024-09-02 18:06:27 -04:00
pub permit_no_files : bool ,
2023-01-07 15:22:09 -05:00
pub filter : Option < String > ,
pub shuffle : Option < u64 > ,
pub concurrent_jobs : NonZeroUsize ,
2024-02-28 11:12:43 -05:00
pub trace_leaks : bool ,
2023-08-02 12:38:10 -04:00
pub reporter : TestReporterConfig ,
2023-08-02 22:05:34 -04:00
pub junit_path : Option < String > ,
2024-08-19 21:27:36 -04:00
pub hide_stacktraces : bool ,
2023-01-07 15:22:09 -05:00
}
2024-07-03 20:54:33 -04:00
impl WorkspaceTestOptions {
pub fn resolve ( test_flags : & TestFlags ) -> Self {
Self {
2024-09-02 18:06:27 -04:00
permit_no_files : test_flags . permit_no_files ,
2023-01-07 15:22:09 -05:00
concurrent_jobs : test_flags
. concurrent_jobs
. unwrap_or_else ( | | NonZeroUsize ::new ( 1 ) . unwrap ( ) ) ,
doc : test_flags . doc ,
fail_fast : test_flags . fail_fast ,
2024-07-03 20:54:33 -04:00
filter : test_flags . filter . clone ( ) ,
2023-01-07 15:22:09 -05:00
no_run : test_flags . no_run ,
shuffle : test_flags . shuffle ,
2024-02-28 11:12:43 -05:00
trace_leaks : test_flags . trace_leaks ,
2023-08-02 12:38:10 -04:00
reporter : test_flags . reporter ,
2024-07-03 20:54:33 -04:00
junit_path : test_flags . junit_path . clone ( ) ,
2024-08-19 21:27:36 -04:00
hide_stacktraces : test_flags . hide_stacktraces ,
2024-07-03 20:54:33 -04:00
}
}
}
#[ derive(Debug, Clone) ]
pub struct TestOptions {
pub files : FilePatterns ,
}
impl TestOptions {
2024-07-08 10:12:10 -04:00
pub fn resolve ( test_config : TestConfig , _test_flags : & TestFlags ) -> Self {
// this is the same, but keeping the same pattern as everywhere else for the future
Self {
files : test_config . files ,
}
2023-01-07 15:22:09 -05:00
}
}
2024-07-03 20:54:33 -04:00
#[ derive(Clone, Copy, Default, Debug) ]
2023-01-07 15:22:09 -05:00
pub enum LintReporterKind {
2023-03-09 14:18:00 -05:00
#[ default ]
2023-01-07 15:22:09 -05:00
Pretty ,
Json ,
Compact ,
}
2024-07-03 20:54:33 -04:00
#[ derive(Clone, Debug) ]
pub struct WorkspaceLintOptions {
pub reporter_kind : LintReporterKind ,
}
impl WorkspaceLintOptions {
pub fn resolve (
lint_config : & WorkspaceLintConfig ,
lint_flags : & LintFlags ,
) -> Result < Self , AnyError > {
let mut maybe_reporter_kind = if lint_flags . json {
Some ( LintReporterKind ::Json )
} else if lint_flags . compact {
Some ( LintReporterKind ::Compact )
} else {
None
} ;
if maybe_reporter_kind . is_none ( ) {
// Flag not set, so try to get lint reporter from the config file.
maybe_reporter_kind = match lint_config . report . as_deref ( ) {
Some ( " json " ) = > Some ( LintReporterKind ::Json ) ,
Some ( " compact " ) = > Some ( LintReporterKind ::Compact ) ,
Some ( " pretty " ) = > Some ( LintReporterKind ::Pretty ) ,
Some ( _ ) = > {
bail! ( " Invalid lint report type in config file " )
}
None = > None ,
}
}
Ok ( Self {
reporter_kind : maybe_reporter_kind . unwrap_or_default ( ) ,
} )
}
}
2024-01-18 15:57:30 -05:00
#[ derive(Clone, Debug) ]
2023-01-07 15:22:09 -05:00
pub struct LintOptions {
pub rules : LintRulesConfig ,
2024-01-08 12:18:42 -05:00
pub files : FilePatterns ,
2024-03-21 17:18:59 -04:00
pub fix : bool ,
2023-01-07 15:22:09 -05:00
}
2024-03-26 11:52:20 -04:00
impl Default for LintOptions {
fn default ( ) -> Self {
Self ::new_with_base ( PathBuf ::from ( " / " ) )
}
}
2023-01-07 15:22:09 -05:00
impl LintOptions {
2024-01-18 15:57:30 -05:00
pub fn new_with_base ( base : PathBuf ) -> Self {
Self {
rules : Default ::default ( ) ,
files : FilePatterns ::new_with_base ( base ) ,
2024-03-21 17:18:59 -04:00
fix : false ,
2024-01-18 15:57:30 -05:00
}
}
2024-07-08 10:12:10 -04:00
pub fn resolve ( lint_config : LintConfig , lint_flags : & LintFlags ) -> Self {
Self {
files : lint_config . files ,
2023-01-07 15:22:09 -05:00
rules : resolve_lint_rules_options (
2024-07-08 10:12:10 -04:00
lint_config . options . rules ,
lint_flags . maybe_rules_tags . clone ( ) ,
lint_flags . maybe_rules_include . clone ( ) ,
lint_flags . maybe_rules_exclude . clone ( ) ,
2023-01-07 15:22:09 -05:00
) ,
2024-07-03 20:54:33 -04:00
fix : lint_flags . fix ,
2024-07-08 10:12:10 -04:00
}
2023-01-07 15:22:09 -05:00
}
}
fn resolve_lint_rules_options (
2024-07-03 20:54:33 -04:00
config_rules : LintRulesConfig ,
2023-01-07 15:22:09 -05:00
mut maybe_rules_tags : Option < Vec < String > > ,
mut maybe_rules_include : Option < Vec < String > > ,
mut maybe_rules_exclude : Option < Vec < String > > ,
) -> LintRulesConfig {
2024-07-03 20:54:33 -04:00
// Try to get configured rules. CLI flags take precedence
// over config file, i.e. if there's `rules.include` in config file
// and `--rules-include` CLI flag, only the flag value is taken into account.
if maybe_rules_include . is_none ( ) {
maybe_rules_include = config_rules . include ;
}
if maybe_rules_exclude . is_none ( ) {
maybe_rules_exclude = config_rules . exclude ;
}
if maybe_rules_tags . is_none ( ) {
maybe_rules_tags = config_rules . tags ;
2023-01-07 15:22:09 -05:00
}
2024-07-03 20:54:33 -04:00
2023-01-07 15:22:09 -05:00
LintRulesConfig {
exclude : maybe_rules_exclude ,
include : maybe_rules_include ,
tags : maybe_rules_tags ,
}
}
2024-07-18 18:16:35 -04:00
pub fn discover_npmrc_from_workspace (
workspace : & Workspace ,
) -> Result < ( Arc < ResolvedNpmRc > , Option < PathBuf > ) , AnyError > {
2024-07-19 15:56:07 -04:00
let root_folder = workspace . root_folder_configs ( ) ;
2024-07-18 18:16:35 -04:00
discover_npmrc (
root_folder . pkg_json . as_ref ( ) . map ( | p | p . path . clone ( ) ) ,
root_folder . deno_json . as_ref ( ) . and_then ( | cf | {
if cf . specifier . scheme ( ) = = " file " {
Some ( cf . specifier . to_file_path ( ) . unwrap ( ) )
} else {
None
}
} ) ,
)
}
2024-05-23 17:26:23 -04:00
/// Discover `.npmrc` file - currently we only support it next to `package.json`
/// or next to `deno.json`.
///
/// In the future we will need to support it in user directory or global directory
/// as per https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#files.
2024-07-27 09:04:28 -04:00
fn discover_npmrc (
2024-05-23 17:26:23 -04:00
maybe_package_json_path : Option < PathBuf > ,
maybe_deno_json_path : Option < PathBuf > ,
2024-05-29 23:16:15 -04:00
) -> Result < ( Arc < ResolvedNpmRc > , Option < PathBuf > ) , AnyError > {
2024-05-23 17:26:23 -04:00
const NPMRC_NAME : & str = " .npmrc " ;
fn get_env_var ( var_name : & str ) -> Option < String > {
std ::env ::var ( var_name ) . ok ( )
}
2024-07-27 09:04:28 -04:00
#[ derive(Debug, Error) ]
#[ error( " Error loading .npmrc at {}. " , path.display()) ]
struct NpmRcLoadError {
path : PathBuf ,
#[ source ]
source : std ::io ::Error ,
}
2024-05-23 17:26:23 -04:00
fn try_to_read_npmrc (
dir : & Path ,
2024-07-27 09:04:28 -04:00
) -> Result < Option < ( String , PathBuf ) > , NpmRcLoadError > {
2024-05-23 17:26:23 -04:00
let path = dir . join ( NPMRC_NAME ) ;
let maybe_source = match std ::fs ::read_to_string ( & path ) {
Ok ( source ) = > Some ( source ) ,
Err ( err ) if err . kind ( ) = = std ::io ::ErrorKind ::NotFound = > None ,
2024-07-27 09:04:28 -04:00
Err ( err ) = > return Err ( NpmRcLoadError { path , source : err } ) ,
2024-05-23 17:26:23 -04:00
} ;
Ok ( maybe_source . map ( | source | ( source , path ) ) )
}
fn try_to_parse_npmrc (
source : String ,
path : & Path ,
) -> Result < Arc < ResolvedNpmRc > , AnyError > {
let npmrc = NpmRc ::parse ( & source , & get_env_var ) . with_context ( | | {
format! ( " Failed to parse .npmrc at {} " , path . display ( ) )
} ) ? ;
let resolved = npmrc
. as_resolved ( npm_registry_url ( ) )
. context ( " Failed to resolve .npmrc options " ) ? ;
Ok ( Arc ::new ( resolved ) )
}
2024-06-26 18:17:00 -04:00
// 1. Try `.npmrc` next to `package.json`
2024-05-23 17:26:23 -04:00
if let Some ( package_json_path ) = maybe_package_json_path {
if let Some ( package_json_dir ) = package_json_path . parent ( ) {
if let Some ( ( source , path ) ) = try_to_read_npmrc ( package_json_dir ) ? {
2024-05-29 23:16:15 -04:00
return try_to_parse_npmrc ( source , & path ) . map ( | r | ( r , Some ( path ) ) ) ;
2024-05-23 17:26:23 -04:00
}
}
}
2024-06-26 18:17:00 -04:00
// 2. Try `.npmrc` next to `deno.json(c)`
2024-05-23 17:26:23 -04:00
if let Some ( deno_json_path ) = maybe_deno_json_path {
if let Some ( deno_json_dir ) = deno_json_path . parent ( ) {
if let Some ( ( source , path ) ) = try_to_read_npmrc ( deno_json_dir ) ? {
2024-05-29 23:16:15 -04:00
return try_to_parse_npmrc ( source , & path ) . map ( | r | ( r , Some ( path ) ) ) ;
2024-05-23 17:26:23 -04:00
}
}
}
2024-06-26 18:17:00 -04:00
// TODO(bartlomieju): update to read both files - one in the project root and one and
// home dir and then merge them.
// 3. Try `.npmrc` in the user's home directory
if let Some ( home_dir ) = cache ::home_dir ( ) {
2024-07-27 09:04:28 -04:00
match try_to_read_npmrc ( & home_dir ) {
Ok ( Some ( ( source , path ) ) ) = > {
return try_to_parse_npmrc ( source , & path ) . map ( | r | ( r , Some ( path ) ) ) ;
}
Ok ( None ) = > { }
Err ( err ) if err . source . kind ( ) = = std ::io ::ErrorKind ::PermissionDenied = > {
log ::debug! (
" Skipping .npmrc in home directory due to permission denied error. {:#} " ,
err
) ;
}
Err ( err ) = > {
return Err ( err . into ( ) ) ;
}
2024-06-26 18:17:00 -04:00
}
}
2024-05-23 17:26:23 -04:00
log ::debug! ( " No .npmrc file found " ) ;
2024-05-29 23:16:15 -04:00
Ok ( ( create_default_npmrc ( ) , None ) )
2024-05-23 17:26:23 -04:00
}
pub fn create_default_npmrc ( ) -> Arc < ResolvedNpmRc > {
Arc ::new ( ResolvedNpmRc {
default_config : deno_npm ::npm_rc ::RegistryConfigWithUrl {
registry_url : npm_registry_url ( ) . clone ( ) ,
config : Default ::default ( ) ,
} ,
scopes : Default ::default ( ) ,
2024-06-05 17:24:52 -04:00
registry_configs : Default ::default ( ) ,
2024-05-23 17:26:23 -04:00
} )
}
2023-05-01 16:42:05 -04:00
#[ derive(Error, Debug, Clone) ]
pub enum RootCertStoreLoadError {
#[ error(
" Unknown certificate store \" {0} \" specified (allowed: \" system,mozilla \" ) "
) ]
UnknownStore ( String ) ,
#[ error( " Unable to add pem file to certificate store: {0} " ) ]
FailedAddPemFile ( String ) ,
#[ error( " Failed opening CA file: {0} " ) ]
CaFileOpenError ( String ) ,
}
2022-11-28 17:28:54 -05:00
/// Create and populate a root cert store based on the passed options and
/// environment.
pub fn get_root_cert_store (
maybe_root_path : Option < PathBuf > ,
maybe_ca_stores : Option < Vec < String > > ,
2023-01-17 19:18:24 -05:00
maybe_ca_data : Option < CaData > ,
2023-05-01 16:42:05 -04:00
) -> Result < RootCertStore , RootCertStoreLoadError > {
2022-11-28 17:28:54 -05:00
let mut root_cert_store = RootCertStore ::empty ( ) ;
let ca_stores : Vec < String > = maybe_ca_stores
. or_else ( | | {
let env_ca_store = env ::var ( " DENO_TLS_CA_STORE " ) . ok ( ) ? ;
Some (
env_ca_store
. split ( ',' )
. map ( | s | s . trim ( ) . to_string ( ) )
. filter ( | s | ! s . is_empty ( ) )
. collect ( ) ,
)
} )
. unwrap_or_else ( | | vec! [ " mozilla " . to_string ( ) ] ) ;
for store in ca_stores . iter ( ) {
match store . as_str ( ) {
" mozilla " = > {
2024-07-01 20:09:47 -04:00
root_cert_store . extend ( webpki_roots ::TLS_SERVER_ROOTS . to_vec ( ) ) ;
2022-11-28 17:28:54 -05:00
}
" system " = > {
let roots = load_native_certs ( ) . expect ( " could not load platform certs " ) ;
for root in roots {
2024-08-13 12:12:45 -04:00
if let Err ( err ) = root_cert_store
. add ( rustls ::pki_types ::CertificateDer ::from ( root . 0. clone ( ) ) )
{
log ::error! (
" {} " ,
colors ::yellow ( & format! (
" Unable to add system certificate to certificate store: {:?} " ,
err
) )
) ;
let hex_encoded_root = faster_hex ::hex_string ( & root . 0 ) ;
log ::error! ( " {} " , colors ::gray ( & hex_encoded_root ) ) ;
}
2022-11-28 17:28:54 -05:00
}
}
_ = > {
2023-05-01 16:42:05 -04:00
return Err ( RootCertStoreLoadError ::UnknownStore ( store . clone ( ) ) ) ;
2022-11-28 17:28:54 -05:00
}
}
}
2023-01-17 19:18:24 -05:00
let ca_data =
maybe_ca_data . or_else ( | | env ::var ( " DENO_CERT " ) . ok ( ) . map ( CaData ::File ) ) ;
if let Some ( ca_data ) = ca_data {
let result = match ca_data {
CaData ::File ( ca_file ) = > {
let ca_file = if let Some ( root ) = & maybe_root_path {
root . join ( & ca_file )
} else {
PathBuf ::from ( ca_file )
} ;
2023-05-01 16:42:05 -04:00
let certfile = std ::fs ::File ::open ( ca_file ) . map_err ( | err | {
RootCertStoreLoadError ::CaFileOpenError ( err . to_string ( ) )
} ) ? ;
2023-01-17 19:18:24 -05:00
let mut reader = BufReader ::new ( certfile ) ;
2024-07-01 20:09:47 -04:00
rustls_pemfile ::certs ( & mut reader ) . collect ::< Result < Vec < _ > , _ > > ( )
2023-01-17 19:18:24 -05:00
}
CaData ::Bytes ( data ) = > {
let mut reader = BufReader ::new ( Cursor ::new ( data ) ) ;
2024-07-01 20:09:47 -04:00
rustls_pemfile ::certs ( & mut reader ) . collect ::< Result < Vec < _ > , _ > > ( )
2023-01-17 19:18:24 -05:00
}
2022-11-28 17:28:54 -05:00
} ;
2023-01-17 19:18:24 -05:00
match result {
2022-11-28 17:28:54 -05:00
Ok ( certs ) = > {
2024-07-01 20:09:47 -04:00
root_cert_store . add_parsable_certificates ( certs ) ;
2022-11-28 17:28:54 -05:00
}
Err ( e ) = > {
2023-05-01 16:42:05 -04:00
return Err ( RootCertStoreLoadError ::FailedAddPemFile ( e . to_string ( ) ) ) ;
2022-11-28 17:28:54 -05:00
}
}
}
Ok ( root_cert_store )
}
2023-10-02 17:53:55 -04:00
/// State provided to the process via an environment variable.
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub struct NpmProcessState {
2023-10-25 14:39:00 -04:00
pub kind : NpmProcessStateKind ,
2023-10-02 17:53:55 -04:00
pub local_node_modules_path : Option < String > ,
}
2023-10-25 14:39:00 -04:00
#[ derive(Clone, Debug, Serialize, Deserialize) ]
pub enum NpmProcessStateKind {
Snapshot ( deno_npm ::resolution ::SerializedNpmResolutionSnapshot ) ,
Byonm ,
}
2023-02-20 13:14:06 -05:00
static NPM_PROCESS_STATE : Lazy < Option < NpmProcessState > > = Lazy ::new ( | | {
2024-09-27 15:35:37 -04:00
use deno_runtime ::ops ::process ::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME ;
let fd = std ::env ::var ( NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME ) . ok ( ) ? ;
std ::env ::remove_var ( NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME ) ;
let fd = fd . parse ::< usize > ( ) . ok ( ) ? ;
let mut file = {
use deno_runtime ::deno_io ::FromRawIoHandle ;
unsafe { std ::fs ::File ::from_raw_io_handle ( fd as _ ) }
} ;
let mut buf = Vec ::new ( ) ;
// seek to beginning. after the file is written the position will be inherited by this subprocess,
// and also this file might have been read before
file . seek ( std ::io ::SeekFrom ::Start ( 0 ) ) . unwrap ( ) ;
file
. read_to_end ( & mut buf )
. inspect_err ( | e | {
log ::error! ( " failed to read npm process state from fd {fd}: {e} " ) ;
} )
. ok ( ) ? ;
let state : NpmProcessState = serde_json ::from_slice ( & buf )
. inspect_err ( | e | {
log ::error! (
" failed to deserialize npm process state: {e} {} " ,
String ::from_utf8_lossy ( & buf )
)
} )
. ok ( ) ? ;
2023-02-20 13:14:06 -05:00
Some ( state )
} ) ;
2022-06-29 20:41:48 -04:00
/// Overrides for the options below that when set will
/// use these values over the values derived from the
/// CLI flags or config file.
2023-10-02 17:53:55 -04:00
#[ derive(Default, Clone) ]
2022-06-29 20:41:48 -04:00
struct CliOptionOverrides {
import_map_specifier : Option < Option < ModuleSpecifier > > ,
}
2023-05-10 20:06:59 -04:00
/// Holds the resolved options of many sources used by subcommands
2022-06-28 16:45:55 -04:00
/// and provides some helper function for creating common objects.
2022-06-29 11:51:11 -04:00
pub struct CliOptions {
// the source of the options is a detail the rest of the
2022-06-28 16:45:55 -04:00
// application need not concern itself with, so keep these private
2024-07-23 19:00:48 -04:00
flags : Arc < Flags > ,
2023-03-13 21:12:09 -04:00
initial_cwd : PathBuf ,
2024-09-25 21:50:54 -04:00
main_module_cell : std ::sync ::OnceLock < Result < ModuleSpecifier , AnyError > > ,
2023-02-22 20:16:16 -05:00
maybe_node_modules_folder : Option < PathBuf > ,
2024-05-23 17:26:23 -04:00
npmrc : Arc < ResolvedNpmRc > ,
2024-06-28 20:18:21 -04:00
maybe_lockfile : Option < Arc < CliLockfile > > ,
2022-06-29 20:41:48 -04:00
overrides : CliOptionOverrides ,
2024-07-19 15:56:07 -04:00
pub start_dir : Arc < WorkspaceDirectory > ,
2024-08-15 23:48:48 -04:00
pub deno_dir_provider : Arc < DenoDirProvider > ,
2022-06-28 16:45:55 -04:00
}
2022-06-29 11:51:11 -04:00
impl CliOptions {
2022-11-02 11:32:30 -04:00
pub fn new (
2024-07-23 19:00:48 -04:00
flags : Arc < Flags > ,
2023-02-22 20:16:16 -05:00
initial_cwd : PathBuf ,
2024-06-28 20:18:21 -04:00
maybe_lockfile : Option < Arc < CliLockfile > > ,
2024-05-23 17:26:23 -04:00
npmrc : Arc < ResolvedNpmRc > ,
2024-07-19 15:56:07 -04:00
start_dir : Arc < WorkspaceDirectory > ,
2024-02-28 22:54:16 -05:00
force_global_cache : bool ,
2023-02-22 20:16:16 -05:00
) -> Result < Self , AnyError > {
2022-06-28 16:45:55 -04:00
if let Some ( insecure_allowlist ) =
flags . unsafely_ignore_certificate_errors . as_ref ( )
{
let domains = if insecure_allowlist . is_empty ( ) {
" for all hostnames " . to_string ( )
} else {
format! ( " for: {} " , insecure_allowlist . join ( " , " ) )
} ;
let msg =
2024-05-08 22:45:06 -04:00
format! ( " DANGER: TLS certificate validation is disabled {} " , domains ) ;
#[ allow(clippy::print_stderr) ]
{
// use eprintln instead of log::warn so this always gets shown
eprintln! ( " {} " , colors ::yellow ( msg ) ) ;
}
2022-06-28 16:45:55 -04:00
}
2024-02-28 22:54:16 -05:00
let maybe_lockfile = maybe_lockfile . filter ( | _ | ! force_global_cache ) ;
2024-08-15 23:48:48 -04:00
let deno_dir_provider =
2024-10-02 16:17:39 -04:00
Arc ::new ( DenoDirProvider ::new ( flags . internal . cache_path . clone ( ) ) ) ;
2023-08-01 20:49:09 -04:00
let maybe_node_modules_folder = resolve_node_modules_folder (
2023-02-22 20:16:16 -05:00
& initial_cwd ,
& flags ,
2024-08-29 18:57:43 -04:00
& start_dir . workspace ,
2024-08-15 23:48:48 -04:00
& deno_dir_provider ,
2023-02-22 20:16:16 -05:00
)
. with_context ( | | " Resolving node_modules folder. " ) ? ;
2023-11-16 20:28:38 -05:00
2024-07-09 17:33:41 -04:00
load_env_variables_from_env_file ( flags . env_file . as_ref ( ) ) ;
2023-11-01 11:21:13 -04:00
2023-02-22 20:16:16 -05:00
Ok ( Self {
flags ,
2023-03-13 21:12:09 -04:00
initial_cwd ,
2022-11-02 11:32:30 -04:00
maybe_lockfile ,
2024-05-23 17:26:23 -04:00
npmrc ,
2023-02-22 20:16:16 -05:00
maybe_node_modules_folder ,
2022-06-29 20:41:48 -04:00
overrides : Default ::default ( ) ,
2024-09-25 21:50:54 -04:00
main_module_cell : std ::sync ::OnceLock ::new ( ) ,
2024-07-19 15:56:07 -04:00
start_dir ,
2024-08-15 23:48:48 -04:00
deno_dir_provider ,
2023-02-22 20:16:16 -05:00
} )
2022-07-01 11:50:16 -04:00
}
2024-07-23 19:00:48 -04:00
pub fn from_flags ( flags : Arc < Flags > ) -> Result < Self , AnyError > {
2023-02-22 20:16:16 -05:00
let initial_cwd =
std ::env ::current_dir ( ) . with_context ( | | " Failed getting cwd. " ) ? ;
2024-07-05 17:53:09 -04:00
let maybe_vendor_override = flags . vendor . map ( | v | match v {
true = > VendorEnablement ::Enable { cwd : & initial_cwd } ,
false = > VendorEnablement ::Disable ,
} ) ;
2024-07-03 20:54:33 -04:00
let resolve_workspace_discover_options = | | {
let additional_config_file_names : & 'static [ & 'static str ] =
if matches! ( flags . subcommand , DenoSubcommand ::Publish ( .. ) ) {
& [ " jsr.json " , " jsr.jsonc " ]
} else {
& [ ]
} ;
2024-07-19 15:56:07 -04:00
let config_parse_options = deno_config ::deno_json ::ConfigParseOptions {
2024-07-03 20:54:33 -04:00
include_task_comments : matches ! (
flags . subcommand ,
DenoSubcommand ::Task ( .. )
) ,
2024-02-27 03:27:21 -05:00
} ;
2024-07-19 15:56:07 -04:00
let discover_pkg_json = flags . config_flag ! = ConfigFlag ::Disabled
2024-07-03 20:54:33 -04:00
& & ! flags . no_npm
& & ! has_flag_env_var ( " DENO_NO_PACKAGE_JSON " ) ;
if ! discover_pkg_json {
log ::debug! ( " package.json auto-discovery is disabled " ) ;
}
WorkspaceDiscoverOptions {
2024-07-23 17:34:46 -04:00
fs : Default ::default ( ) , // use real fs
2024-07-18 18:16:35 -04:00
deno_json_cache : None ,
2024-07-25 19:08:14 -04:00
pkg_json_cache : Some ( & node_resolver ::PackageJsonThreadLocalCache ) ,
2024-07-19 15:56:07 -04:00
workspace_cache : None ,
2024-07-03 20:54:33 -04:00
config_parse_options ,
additional_config_file_names ,
discover_pkg_json ,
2024-07-05 17:53:09 -04:00
maybe_vendor_override ,
2024-07-03 20:54:33 -04:00
}
2024-03-27 17:14:27 -04:00
} ;
2024-07-19 15:56:07 -04:00
let resolve_empty_options = | | WorkspaceDirectoryEmptyOptions {
2024-07-05 17:53:09 -04:00
root_dir : Arc ::new (
ModuleSpecifier ::from_directory_path ( & initial_cwd ) . unwrap ( ) ,
) ,
use_vendor_dir : maybe_vendor_override
. unwrap_or ( VendorEnablement ::Disable ) ,
} ;
2023-02-20 13:14:06 -05:00
2024-07-19 15:56:07 -04:00
let start_dir = match & flags . config_flag {
ConfigFlag ::Discover = > {
2024-07-08 10:12:10 -04:00
if let Some ( start_paths ) = flags . config_path_args ( & initial_cwd ) {
2024-07-19 15:56:07 -04:00
WorkspaceDirectory ::discover (
2024-07-08 10:12:10 -04:00
WorkspaceDiscoverStart ::Paths ( & start_paths ) ,
2024-07-03 20:54:33 -04:00
& resolve_workspace_discover_options ( ) ,
) ?
} else {
2024-07-19 15:56:07 -04:00
WorkspaceDirectory ::empty ( resolve_empty_options ( ) )
2024-07-03 20:54:33 -04:00
}
2023-02-20 13:14:06 -05:00
}
2024-07-19 15:56:07 -04:00
ConfigFlag ::Path ( path ) = > {
2024-07-03 20:54:33 -04:00
let config_path = normalize_path ( initial_cwd . join ( path ) ) ;
2024-07-19 15:56:07 -04:00
WorkspaceDirectory ::discover (
2024-07-03 20:54:33 -04:00
WorkspaceDiscoverStart ::ConfigFile ( & config_path ) ,
& resolve_workspace_discover_options ( ) ,
) ?
}
2024-07-19 15:56:07 -04:00
ConfigFlag ::Disabled = > {
WorkspaceDirectory ::empty ( resolve_empty_options ( ) )
2024-07-05 17:53:09 -04:00
}
2024-07-03 20:54:33 -04:00
} ;
2024-07-19 15:56:07 -04:00
for diagnostic in start_dir . workspace . diagnostics ( ) {
2024-07-12 12:48:53 -04:00
log ::warn! ( " {} {} " , colors ::yellow ( " Warning " ) , diagnostic ) ;
2023-02-20 13:14:06 -05:00
}
2024-07-03 20:54:33 -04:00
2024-07-19 15:56:07 -04:00
let ( npmrc , _ ) = discover_npmrc_from_workspace ( & start_dir . workspace ) ? ;
2023-02-24 13:51:21 -05:00
2024-07-19 15:56:07 -04:00
let maybe_lock_file = CliLockfile ::discover ( & flags , & start_dir . workspace ) ? ;
2024-07-03 20:54:33 -04:00
log ::debug! ( " Finished config loading. " ) ;
2023-02-22 20:16:16 -05:00
Self ::new (
2023-02-20 13:14:06 -05:00
flags ,
2023-02-22 20:16:16 -05:00
initial_cwd ,
2024-06-28 20:18:21 -04:00
maybe_lock_file . map ( Arc ::new ) ,
2024-05-23 17:26:23 -04:00
npmrc ,
2024-07-19 15:56:07 -04:00
Arc ::new ( start_dir ) ,
2024-02-28 22:54:16 -05:00
false ,
2023-02-22 20:16:16 -05:00
)
2022-06-28 16:45:55 -04:00
}
2024-07-23 19:00:48 -04:00
/// This method is purposefully verbose to disourage its use. Do not use it
/// except in the factory structs. Instead, prefer specific methods on `CliOptions`
/// that can take all sources of information into account (ex. config files or env vars).
pub fn into_self_and_flags (
self : Arc < CliOptions > ,
) -> ( Arc < CliOptions > , Arc < Flags > ) {
let flags = self . flags . clone ( ) ;
( self , flags )
}
2023-03-13 21:12:09 -04:00
#[ inline(always) ]
pub fn initial_cwd ( & self ) -> & Path {
& self . initial_cwd
}
2024-07-19 15:56:07 -04:00
#[ inline(always) ]
pub fn workspace ( & self ) -> & Arc < Workspace > {
& self . start_dir . workspace
}
2024-05-16 03:09:35 -04:00
pub fn graph_kind ( & self ) -> GraphKind {
match self . sub_command ( ) {
DenoSubcommand ::Cache ( _ ) = > GraphKind ::All ,
DenoSubcommand ::Check ( _ ) = > GraphKind ::TypesOnly ,
_ = > self . type_check_mode ( ) . as_graph_kind ( ) ,
}
}
2022-06-28 16:45:55 -04:00
pub fn ts_type_lib_window ( & self ) -> TsTypeLib {
2024-01-21 17:47:46 -05:00
TsTypeLib ::DenoWindow
2022-06-28 16:45:55 -04:00
}
pub fn ts_type_lib_worker ( & self ) -> TsTypeLib {
2024-01-21 17:47:46 -05:00
TsTypeLib ::DenoWorker
2022-06-28 16:45:55 -04:00
}
pub fn cache_setting ( & self ) -> CacheSetting {
if self . flags . cached_only {
CacheSetting ::Only
} else if ! self . flags . cache_blocklist . is_empty ( ) {
CacheSetting ::ReloadSome ( self . flags . cache_blocklist . clone ( ) )
} else if self . flags . reload {
CacheSetting ::ReloadAll
} else {
CacheSetting ::Use
}
}
2023-05-17 17:38:50 -04:00
pub fn npm_system_info ( & self ) -> NpmSystemInfo {
match self . sub_command ( ) {
DenoSubcommand ::Compile ( CompileFlags {
target : Some ( target ) ,
..
} ) = > {
// the values of NpmSystemInfo align with the possible values for the
// `arch` and `platform` fields of Node.js' `process` global:
// https://nodejs.org/api/process.html
match target . as_str ( ) {
" aarch64-apple-darwin " = > NpmSystemInfo {
os : " darwin " . to_string ( ) ,
cpu : " arm64 " . to_string ( ) ,
} ,
2024-02-23 13:18:39 -05:00
" aarch64-unknown-linux-gnu " = > NpmSystemInfo {
os : " linux " . to_string ( ) ,
cpu : " arm64 " . to_string ( ) ,
} ,
2023-05-17 17:38:50 -04:00
" x86_64-apple-darwin " = > NpmSystemInfo {
os : " darwin " . to_string ( ) ,
cpu : " x64 " . to_string ( ) ,
} ,
" x86_64-unknown-linux-gnu " = > NpmSystemInfo {
os : " linux " . to_string ( ) ,
cpu : " x64 " . to_string ( ) ,
} ,
" x86_64-pc-windows-msvc " = > NpmSystemInfo {
os : " win32 " . to_string ( ) ,
cpu : " x64 " . to_string ( ) ,
} ,
value = > {
2024-02-23 16:34:24 -05:00
log ::warn! (
concat! (
" Not implemented npm system info for target '{}'. Using current " ,
" system default. This may impact architecture specific dependencies. "
) ,
value ,
) ;
2023-05-17 17:38:50 -04:00
NpmSystemInfo ::default ( )
}
}
}
_ = > NpmSystemInfo ::default ( ) ,
}
}
2024-02-24 00:21:09 -05:00
/// Resolve the specifier for a specified import map.
///
/// This will NOT include the config file if it
/// happens to be an import map.
pub fn resolve_specified_import_map_specifier (
2022-06-28 16:45:55 -04:00
& self ,
) -> Result < Option < ModuleSpecifier > , AnyError > {
2022-06-29 20:41:48 -04:00
match self . overrides . import_map_specifier . clone ( ) {
2024-04-29 14:32:27 -04:00
Some ( maybe_url ) = > Ok ( maybe_url ) ,
2022-06-29 20:41:48 -04:00
None = > resolve_import_map_specifier (
self . flags . import_map_path . as_deref ( ) ,
2024-07-19 15:56:07 -04:00
self . workspace ( ) . root_deno_json ( ) . map ( | c | c . as_ref ( ) ) ,
2023-03-13 21:12:09 -04:00
& self . initial_cwd ,
2022-06-29 20:41:48 -04:00
) ,
}
}
2024-07-03 20:54:33 -04:00
pub async fn create_workspace_resolver (
2023-01-25 15:13:40 -05:00
& self ,
file_fetcher : & FileFetcher ,
2024-07-04 20:41:01 -04:00
pkg_json_dep_resolution : PackageJsonDepResolution ,
2024-07-03 20:54:33 -04:00
) -> Result < WorkspaceResolver , AnyError > {
let overrode_no_import_map = self
2024-02-24 00:21:09 -05:00
. overrides
. import_map_specifier
. as_ref ( )
. map ( | s | s . is_none ( ) )
2024-07-03 20:54:33 -04:00
= = Some ( true ) ;
let cli_arg_specified_import_map = if overrode_no_import_map {
// use a fake empty import map
Some ( deno_config ::workspace ::SpecifiedImportMap {
2024-07-19 15:56:07 -04:00
base_url : self . workspace ( ) . root_dir ( ) . join ( " import_map.json " ) . unwrap ( ) ,
2024-07-03 20:54:33 -04:00
value : serde_json ::Value ::Object ( Default ::default ( ) ) ,
} )
} else {
let maybe_import_map_specifier =
self . resolve_specified_import_map_specifier ( ) ? ;
match maybe_import_map_specifier {
Some ( specifier ) = > {
let value =
resolve_import_map_value_from_specifier ( & specifier , file_fetcher )
. await
. with_context ( | | {
format! ( " Unable to load ' {} ' import map " , specifier )
} ) ? ;
Some ( deno_config ::workspace ::SpecifiedImportMap {
base_url : specifier ,
value ,
} )
}
None = > None ,
}
} ;
2024-09-23 14:46:50 -04:00
Ok ( self . workspace ( ) . create_resolver (
CreateResolverOptions {
pkg_json_dep_resolution ,
specified_import_map : cli_arg_specified_import_map ,
} ,
| path | Ok ( std ::fs ::read_to_string ( path ) ? ) ,
) ? )
2023-01-25 15:13:40 -05:00
}
2023-12-19 07:37:22 -05:00
pub fn node_ipc_fd ( & self ) -> Option < i64 > {
2024-07-30 19:13:24 -04:00
let maybe_node_channel_fd = std ::env ::var ( " NODE_CHANNEL_FD " ) . ok ( ) ;
2023-12-13 05:14:16 -05:00
if let Some ( node_channel_fd ) = maybe_node_channel_fd {
// Remove so that child processes don't inherit this environment variable.
2024-07-30 19:13:24 -04:00
std ::env ::remove_var ( " NODE_CHANNEL_FD " ) ;
2023-12-19 07:37:22 -05:00
node_channel_fd . parse ::< i64 > ( ) . ok ( )
2023-12-13 05:14:16 -05:00
} else {
None
}
}
2024-05-17 01:38:50 -04:00
pub fn serve_port ( & self ) -> Option < u16 > {
2024-04-24 15:45:49 -04:00
if let DenoSubcommand ::Serve ( flags ) = self . sub_command ( ) {
Some ( flags . port )
} else {
None
}
}
pub fn serve_host ( & self ) -> Option < String > {
if let DenoSubcommand ::Serve ( flags ) = self . sub_command ( ) {
Some ( flags . host . clone ( ) )
} else {
None
}
}
2024-07-09 17:33:41 -04:00
pub fn env_file_name ( & self ) -> Option < & String > {
self . flags . env_file . as_ref ( )
}
2024-09-25 21:50:54 -04:00
pub fn resolve_main_module ( & self ) -> Result < & ModuleSpecifier , AnyError > {
self
. main_module_cell
. get_or_init ( | | {
let main_module = match & self . flags . subcommand {
DenoSubcommand ::Compile ( compile_flags ) = > {
resolve_url_or_path ( & compile_flags . source_file , self . initial_cwd ( ) ) ?
}
DenoSubcommand ::Eval ( _ ) = > {
resolve_url_or_path ( " ./$deno$eval.ts " , self . initial_cwd ( ) ) ?
}
DenoSubcommand ::Repl ( _ ) = > {
resolve_url_or_path ( " ./$deno$repl.ts " , self . initial_cwd ( ) ) ?
}
DenoSubcommand ::Run ( run_flags ) = > {
if run_flags . is_stdin ( ) {
resolve_url_or_path ( " ./$deno$stdin.ts " , self . initial_cwd ( ) ) ?
} else {
resolve_url_or_path ( & run_flags . script , self . initial_cwd ( ) ) ?
}
}
DenoSubcommand ::Serve ( run_flags ) = > {
resolve_url_or_path ( & run_flags . script , self . initial_cwd ( ) ) ?
}
_ = > {
bail! ( " No main module. " )
}
} ;
2024-07-03 20:54:33 -04:00
2024-09-25 21:50:54 -04:00
Ok ( main_module )
} )
. as_ref ( )
. map_err ( | err | deno_core ::anyhow ::anyhow! ( " {} " , err ) )
2023-03-22 10:15:53 -04:00
}
pub fn resolve_file_header_overrides (
& self ,
) -> HashMap < ModuleSpecifier , HashMap < String , String > > {
let maybe_main_specifier = self . resolve_main_module ( ) . ok ( ) ;
// TODO(Cre3per): This mapping moved to deno_ast with https://github.com/denoland/deno_ast/issues/133 and should be available in deno_ast >= 0.25.0 via `MediaType::from_path(...).as_media_type()`
let maybe_content_type =
self . flags . ext . as_ref ( ) . and_then ( | el | match el . as_str ( ) {
" ts " = > Some ( " text/typescript " ) ,
" tsx " = > Some ( " text/tsx " ) ,
" js " = > Some ( " text/javascript " ) ,
" jsx " = > Some ( " text/jsx " ) ,
_ = > None ,
} ) ;
if let ( Some ( main_specifier ) , Some ( content_type ) ) =
( maybe_main_specifier , maybe_content_type )
{
HashMap ::from ( [ (
2024-09-25 21:50:54 -04:00
main_specifier . clone ( ) ,
2023-03-22 10:15:53 -04:00
HashMap ::from ( [ ( " content-type " . to_string ( ) , content_type . to_string ( ) ) ] ) ,
) ] )
} else {
HashMap ::default ( )
}
}
2023-10-02 17:53:55 -04:00
pub fn resolve_npm_resolution_snapshot (
2023-03-12 23:32:59 -04:00
& self ,
2023-04-13 10:47:45 -04:00
) -> Result < Option < ValidSerializedNpmResolutionSnapshot > , AnyError > {
2023-10-25 14:39:00 -04:00
if let Some ( NpmProcessStateKind ::Snapshot ( snapshot ) ) =
NPM_PROCESS_STATE . as_ref ( ) . map ( | s | & s . kind )
{
2023-02-20 13:14:06 -05:00
// TODO(bartlomieju): remove this clone
2023-10-25 14:39:00 -04:00
Ok ( Some ( snapshot . clone ( ) . into_valid ( ) ? ) )
2023-10-02 17:53:55 -04:00
} else {
Ok ( None )
2023-02-20 13:14:06 -05:00
}
}
// If the main module should be treated as being in an npm package.
// This is triggered via a secret environment variable which is used
// for functionality like child_process.fork. Users should NOT depend
// on this functionality.
pub fn is_npm_main ( & self ) -> bool {
2023-02-22 20:16:16 -05:00
NPM_PROCESS_STATE . is_some ( )
2023-02-20 13:14:06 -05:00
}
2023-02-22 20:16:16 -05:00
pub fn has_node_modules_dir ( & self ) -> bool {
2024-04-05 10:34:51 -04:00
self . maybe_node_modules_folder . is_some ( )
2023-02-22 20:16:16 -05:00
}
2023-02-20 13:14:06 -05:00
2024-04-05 10:34:51 -04:00
pub fn node_modules_dir_path ( & self ) -> Option < & PathBuf > {
self . maybe_node_modules_folder . as_ref ( )
2022-12-16 17:41:51 -05:00
}
2024-08-30 17:58:24 -04:00
pub fn node_modules_dir (
& self ,
) -> Result < Option < NodeModulesDirMode > , AnyError > {
if let Some ( flag ) = self . flags . node_modules_dir {
return Ok ( Some ( flag ) ) ;
2024-08-29 18:57:43 -04:00
}
2024-09-04 11:39:30 -04:00
self . workspace ( ) . node_modules_dir ( ) . map_err ( Into ::into )
2023-05-19 18:39:27 -04:00
}
2023-08-06 21:56:56 -04:00
pub fn vendor_dir_path ( & self ) -> Option < & PathBuf > {
2024-07-19 15:56:07 -04:00
self . workspace ( ) . vendor_dir_path ( )
2023-08-01 20:49:09 -04:00
}
2022-06-28 16:45:55 -04:00
pub fn resolve_ts_config_for_emit (
& self ,
config_type : TsConfigType ,
2022-11-25 18:29:48 -05:00
) -> Result < TsConfigForEmit , AnyError > {
2024-09-02 11:27:37 -04:00
self . workspace ( ) . resolve_ts_config_for_emit ( config_type )
2022-06-28 16:45:55 -04:00
}
2024-04-11 19:17:10 -04:00
pub fn resolve_inspector_server (
& self ,
) -> Result < Option < InspectorServer > , AnyError > {
2022-12-12 09:33:30 -05:00
let maybe_inspect_host = self
. flags
. inspect
. or ( self . flags . inspect_brk )
. or ( self . flags . inspect_wait ) ;
2024-04-11 19:17:10 -04:00
let Some ( host ) = maybe_inspect_host else {
return Ok ( None ) ;
} ;
2024-08-15 17:47:16 -04:00
Ok ( Some ( InspectorServer ::new (
host ,
version ::DENO_VERSION_INFO . user_agent ,
) ? ) )
2022-06-28 16:45:55 -04:00
}
2024-07-23 19:00:48 -04:00
pub fn maybe_lockfile ( & self ) -> Option < & Arc < CliLockfile > > {
self . maybe_lockfile . as_ref ( )
2022-06-28 16:45:55 -04:00
}
2024-07-09 17:07:16 -04:00
pub fn to_compiler_option_types (
2023-08-24 05:21:34 -04:00
& self ,
) -> Result < Vec < deno_graph ::ReferrerImports > , AnyError > {
2024-07-10 14:46:09 -04:00
self
2024-07-19 15:56:07 -04:00
. workspace ( )
2024-07-10 14:46:09 -04:00
. to_compiler_option_types ( )
. map ( | maybe_imports | {
maybe_imports
. into_iter ( )
. map ( | ( referrer , imports ) | deno_graph ::ReferrerImports {
referrer ,
imports ,
} )
. collect ( )
} )
2023-02-20 13:14:06 -05:00
}
2024-05-23 17:26:23 -04:00
pub fn npmrc ( & self ) -> & Arc < ResolvedNpmRc > {
& self . npmrc
}
2024-07-03 20:54:33 -04:00
pub fn resolve_fmt_options_for_members (
& self ,
fmt_flags : & FmtFlags ,
2024-07-19 15:56:07 -04:00
) -> Result < Vec < ( WorkspaceDirectory , FmtOptions ) > , AnyError > {
2024-07-03 20:54:33 -04:00
let cli_arg_patterns =
fmt_flags . files . as_file_patterns ( self . initial_cwd ( ) ) ? ;
2024-07-08 10:12:10 -04:00
let member_configs = self
2024-07-19 15:56:07 -04:00
. workspace ( )
2024-07-08 10:12:10 -04:00
. resolve_fmt_config_for_members ( & cli_arg_patterns ) ? ;
2024-08-02 09:52:48 -04:00
let unstable = self . resolve_config_unstable_fmt_options ( ) ;
2024-07-08 10:12:10 -04:00
let mut result = Vec ::with_capacity ( member_configs . len ( ) ) ;
for ( ctx , config ) in member_configs {
2024-08-02 09:52:48 -04:00
let options = FmtOptions ::resolve ( config , unstable . clone ( ) , fmt_flags ) ;
2024-07-08 10:12:10 -04:00
result . push ( ( ctx , options ) ) ;
2023-02-20 13:14:06 -05:00
}
2024-07-03 20:54:33 -04:00
Ok ( result )
2023-02-20 13:14:06 -05:00
}
2024-08-02 09:52:48 -04:00
pub fn resolve_config_unstable_fmt_options ( & self ) -> UnstableFmtOptions {
2024-08-09 12:52:23 -04:00
let workspace = self . workspace ( ) ;
2024-08-02 09:52:48 -04:00
UnstableFmtOptions {
2024-08-14 16:58:48 -04:00
component : workspace . has_unstable ( " fmt-component " ) ,
2024-08-02 09:52:48 -04:00
}
}
2024-07-03 20:54:33 -04:00
pub fn resolve_workspace_lint_options (
& self ,
lint_flags : & LintFlags ,
) -> Result < WorkspaceLintOptions , AnyError > {
2024-07-19 15:56:07 -04:00
let lint_config = self . workspace ( ) . to_lint_config ( ) ? ;
2024-07-03 20:54:33 -04:00
WorkspaceLintOptions ::resolve ( & lint_config , lint_flags )
}
pub fn resolve_lint_options_for_members (
& self ,
lint_flags : & LintFlags ,
2024-07-19 15:56:07 -04:00
) -> Result < Vec < ( WorkspaceDirectory , LintOptions ) > , AnyError > {
2024-07-03 20:54:33 -04:00
let cli_arg_patterns =
lint_flags . files . as_file_patterns ( self . initial_cwd ( ) ) ? ;
2024-07-08 10:12:10 -04:00
let member_configs = self
2024-07-19 15:56:07 -04:00
. workspace ( )
2024-07-08 10:12:10 -04:00
. resolve_lint_config_for_members ( & cli_arg_patterns ) ? ;
let mut result = Vec ::with_capacity ( member_configs . len ( ) ) ;
for ( ctx , config ) in member_configs {
let options = LintOptions ::resolve ( config , lint_flags ) ;
result . push ( ( ctx , options ) ) ;
2024-07-03 20:54:33 -04:00
}
Ok ( result )
2022-06-28 16:45:55 -04:00
}
2024-07-08 10:12:10 -04:00
pub fn resolve_deno_lint_config (
2024-05-29 20:09:16 -04:00
& self ,
) -> Result < deno_lint ::linter ::LintConfig , AnyError > {
let ts_config_result =
self . resolve_ts_config_for_emit ( TsConfigType ::Emit ) ? ;
let ( transpile_options , _ ) =
crate ::args ::ts_config_to_transpile_and_emit_options (
ts_config_result . ts_config ,
) ? ;
Ok ( deno_lint ::linter ::LintConfig {
2024-09-27 10:14:17 -04:00
default_jsx_factory : ( ! transpile_options . jsx_automatic )
2024-05-29 20:09:16 -04:00
. then ( | | transpile_options . jsx_factory . clone ( ) ) ,
2024-09-27 10:14:17 -04:00
default_jsx_fragment_factory : ( ! transpile_options . jsx_automatic )
2024-05-29 20:09:16 -04:00
. then ( | | transpile_options . jsx_fragment_factory . clone ( ) ) ,
} )
}
2024-07-03 20:54:33 -04:00
pub fn resolve_workspace_test_options (
& self ,
test_flags : & TestFlags ,
) -> WorkspaceTestOptions {
WorkspaceTestOptions ::resolve ( test_flags )
}
pub fn resolve_test_options_for_members (
& self ,
test_flags : & TestFlags ,
2024-07-19 15:56:07 -04:00
) -> Result < Vec < ( WorkspaceDirectory , TestOptions ) > , AnyError > {
2024-07-03 20:54:33 -04:00
let cli_arg_patterns =
test_flags . files . as_file_patterns ( self . initial_cwd ( ) ) ? ;
2024-07-19 15:56:07 -04:00
let workspace_dir_configs = self
. workspace ( )
2024-07-08 10:12:10 -04:00
. resolve_test_config_for_members ( & cli_arg_patterns ) ? ;
2024-07-19 15:56:07 -04:00
let mut result = Vec ::with_capacity ( workspace_dir_configs . len ( ) ) ;
for ( member_dir , config ) in workspace_dir_configs {
2024-07-08 10:12:10 -04:00
let options = TestOptions ::resolve ( config , test_flags ) ;
2024-07-19 15:56:07 -04:00
result . push ( ( member_dir , options ) ) ;
2024-07-03 20:54:33 -04:00
}
Ok ( result )
}
pub fn resolve_workspace_bench_options (
& self ,
bench_flags : & BenchFlags ,
) -> WorkspaceBenchOptions {
WorkspaceBenchOptions ::resolve ( bench_flags )
2024-01-03 20:43:17 -05:00
}
2024-07-03 20:54:33 -04:00
pub fn resolve_bench_options_for_members (
& self ,
bench_flags : & BenchFlags ,
2024-07-19 15:56:07 -04:00
) -> Result < Vec < ( WorkspaceDirectory , BenchOptions ) > , AnyError > {
2024-07-03 20:54:33 -04:00
let cli_arg_patterns =
bench_flags . files . as_file_patterns ( self . initial_cwd ( ) ) ? ;
2024-07-19 15:56:07 -04:00
let workspace_dir_configs = self
. workspace ( )
2024-07-08 10:12:10 -04:00
. resolve_bench_config_for_members ( & cli_arg_patterns ) ? ;
2024-07-19 15:56:07 -04:00
let mut result = Vec ::with_capacity ( workspace_dir_configs . len ( ) ) ;
for ( member_dir , config ) in workspace_dir_configs {
2024-07-08 10:12:10 -04:00
let options = BenchOptions ::resolve ( config , bench_flags ) ;
2024-07-19 15:56:07 -04:00
result . push ( ( member_dir , options ) ) ;
2024-07-03 20:54:33 -04:00
}
Ok ( result )
2022-12-09 20:30:47 -05:00
}
2022-06-28 16:45:55 -04:00
/// Vector of user script CLI arguments.
pub fn argv ( & self ) -> & Vec < String > {
& self . flags . argv
}
2023-01-17 19:18:24 -05:00
pub fn ca_data ( & self ) -> & Option < CaData > {
& self . flags . ca_data
2022-12-08 11:50:09 -05:00
}
pub fn ca_stores ( & self ) -> & Option < Vec < String > > {
& self . flags . ca_stores
}
2022-06-28 16:45:55 -04:00
pub fn check_js ( & self ) -> bool {
2024-07-19 15:56:07 -04:00
self . workspace ( ) . check_js ( )
2022-06-28 16:45:55 -04:00
}
2022-08-12 15:21:17 -04:00
pub fn coverage_dir ( & self ) -> Option < String > {
2023-06-15 13:09:37 -04:00
match & self . flags . subcommand {
DenoSubcommand ::Test ( test ) = > test
2022-08-12 15:21:17 -04:00
. coverage_dir
. as_ref ( )
. map ( ToOwned ::to_owned )
2023-06-15 13:09:37 -04:00
. or_else ( | | env ::var ( " DENO_UNSTABLE_COVERAGE_DIR " ) . ok ( ) ) ,
_ = > None ,
2022-08-12 15:21:17 -04:00
}
2022-06-28 16:45:55 -04:00
}
2023-11-05 16:27:36 -05:00
pub fn enable_op_summary_metrics ( & self ) -> bool {
self . flags . enable_op_summary_metrics
| | matches! (
self . flags . subcommand ,
2023-12-17 05:11:07 -05:00
DenoSubcommand ::Test ( _ )
| DenoSubcommand ::Repl ( _ )
| DenoSubcommand ::Jupyter ( _ )
2023-11-05 16:27:36 -05:00
)
}
2022-06-28 16:45:55 -04:00
pub fn enable_testing_features ( & self ) -> bool {
self . flags . enable_testing_features
}
2023-03-22 10:15:53 -04:00
pub fn ext_flag ( & self ) -> & Option < String > {
& self . flags . ext
}
2023-10-30 20:25:58 -04:00
pub fn has_hmr ( & self ) -> bool {
if let DenoSubcommand ::Run ( RunFlags {
watch : Some ( WatchFlagsWithPaths { hmr , .. } ) ,
..
} ) = & self . flags . subcommand
{
* hmr
} else {
false
}
}
2022-07-19 11:58:18 -04:00
/// If the --inspect or --inspect-brk flags are used.
pub fn is_inspecting ( & self ) -> bool {
2022-12-12 09:33:30 -05:00
self . flags . inspect . is_some ( )
| | self . flags . inspect_brk . is_some ( )
| | self . flags . inspect_wait . is_some ( )
2022-07-19 11:58:18 -04:00
}
2022-06-28 16:45:55 -04:00
pub fn inspect_brk ( & self ) -> Option < SocketAddr > {
self . flags . inspect_brk
}
2022-12-12 09:33:30 -05:00
pub fn inspect_wait ( & self ) -> Option < SocketAddr > {
self . flags . inspect_wait
}
2022-06-28 16:45:55 -04:00
pub fn log_level ( & self ) -> Option < log ::Level > {
self . flags . log_level
}
2022-11-30 17:25:20 -05:00
pub fn is_quiet ( & self ) -> bool {
self
. log_level ( )
. map ( | l | l = = log ::Level ::Error )
. unwrap_or ( false )
}
2022-12-08 11:50:09 -05:00
pub fn location_flag ( & self ) -> & Option < Url > {
& self . flags . location
2022-06-28 16:45:55 -04:00
}
pub fn no_remote ( & self ) -> bool {
self . flags . no_remote
}
2022-09-07 09:33:51 -04:00
pub fn no_npm ( & self ) -> bool {
self . flags . no_npm
}
2024-05-06 19:21:58 -04:00
pub fn permission_flags ( & self ) -> & PermissionFlags {
& self . flags . permissions
}
2024-09-16 16:39:37 -04:00
pub fn permissions_options ( & self ) -> PermissionsOptions {
2024-09-25 21:50:54 -04:00
fn files_to_urls ( files : & [ String ] ) -> Vec < Cow < '_ , Url > > {
files
. iter ( )
. filter_map ( | f | Url ::parse ( f ) . ok ( ) . map ( Cow ::Owned ) )
. collect ( )
}
// get a list of urls to imply for --allow-import
let cli_arg_urls = self
. resolve_main_module ( )
. ok ( )
. map ( | url | vec! [ Cow ::Borrowed ( url ) ] )
. or_else ( | | match & self . flags . subcommand {
DenoSubcommand ::Cache ( cache_flags ) = > {
Some ( files_to_urls ( & cache_flags . files ) )
}
DenoSubcommand ::Check ( check_flags ) = > {
Some ( files_to_urls ( & check_flags . files ) )
}
DenoSubcommand ::Install ( InstallFlags {
kind : InstallKind ::Global ( flags ) ,
} ) = > Url ::parse ( & flags . module_url )
. ok ( )
. map ( | url | vec! [ Cow ::Owned ( url ) ] ) ,
_ = > None ,
} )
. unwrap_or_default ( ) ;
self . flags . permissions . to_options ( & cli_arg_urls )
2022-06-28 16:45:55 -04:00
}
pub fn reload_flag ( & self ) -> bool {
self . flags . reload
}
pub fn seed ( & self ) -> Option < u64 > {
self . flags . seed
}
pub fn sub_command ( & self ) -> & DenoSubcommand {
& self . flags . subcommand
}
2023-11-10 12:41:24 -05:00
pub fn strace_ops ( & self ) -> & Option < Vec < String > > {
& self . flags . strace_ops
}
2023-12-06 16:36:06 -05:00
pub fn take_binary_npm_command_name ( & self ) -> Option < String > {
match self . sub_command ( ) {
DenoSubcommand ::Run ( flags ) = > {
const NPM_CMD_NAME_ENV_VAR_NAME : & str = " DENO_INTERNAL_NPM_CMD_NAME " ;
match std ::env ::var ( NPM_CMD_NAME_ENV_VAR_NAME ) {
Ok ( var ) = > {
// remove the env var so that child sub processes won't pick this up
std ::env ::remove_var ( NPM_CMD_NAME_ENV_VAR_NAME ) ;
Some ( var )
}
Err ( _ ) = > NpmPackageReqReference ::from_str ( & flags . script )
. ok ( )
. map ( | req_ref | npm_pkg_req_ref_to_binary_command ( & req_ref ) ) ,
}
}
_ = > None ,
}
}
2022-06-28 16:45:55 -04:00
pub fn type_check_mode ( & self ) -> TypeCheckMode {
self . flags . type_check_mode
}
2022-12-08 11:50:09 -05:00
pub fn unsafely_ignore_certificate_errors ( & self ) -> & Option < Vec < String > > {
& self . flags . unsafely_ignore_certificate_errors
2022-06-28 16:45:55 -04:00
}
2023-11-01 19:04:54 -04:00
pub fn unstable_bare_node_builtins ( & self ) -> bool {
2024-01-22 12:37:28 -05:00
self . flags . unstable_config . bare_node_builtins
2024-07-19 15:56:07 -04:00
| | self . workspace ( ) . has_unstable ( " bare-node-builtins " )
2023-10-20 00:02:08 -04:00
}
2024-10-14 20:48:39 -04:00
pub fn unstable_detect_cjs ( & self ) -> bool {
self . flags . unstable_config . detect_cjs
| | self . workspace ( ) . has_unstable ( " detect-cjs " )
}
2024-08-29 18:57:43 -04:00
fn byonm_enabled ( & self ) -> bool {
// check if enabled via unstable
2024-08-30 17:58:24 -04:00
self . node_modules_dir ( ) . ok ( ) . flatten ( ) = = Some ( NodeModulesDirMode ::Manual )
2024-08-29 18:57:43 -04:00
| | NPM_PROCESS_STATE
. as_ref ( )
. map ( | s | matches! ( s . kind , NpmProcessStateKind ::Byonm ) )
. unwrap_or ( false )
}
2024-04-02 18:43:03 -04:00
pub fn use_byonm ( & self ) -> bool {
2024-08-30 17:58:24 -04:00
if self . node_modules_dir ( ) . ok ( ) . flatten ( ) . is_none ( )
2024-08-28 20:21:59 -04:00
& & self . maybe_node_modules_folder . is_some ( )
2024-07-03 20:54:33 -04:00
& & self
2024-07-19 15:56:07 -04:00
. workspace ( )
2024-07-03 20:54:33 -04:00
. config_folders ( )
. values ( )
. any ( | f | f . pkg_json . is_some ( ) )
2024-04-05 10:34:51 -04:00
{
return true ;
}
2024-04-02 18:43:03 -04:00
2024-08-29 18:57:43 -04:00
self . byonm_enabled ( )
2023-12-06 19:03:18 -05:00
}
pub fn unstable_sloppy_imports ( & self ) -> bool {
2024-01-22 12:37:28 -05:00
self . flags . unstable_config . sloppy_imports
2024-07-19 15:56:07 -04:00
| | self . workspace ( ) . has_unstable ( " sloppy-imports " )
2023-10-25 14:39:00 -04:00
}
2023-11-01 18:15:08 -04:00
pub fn unstable_features ( & self ) -> Vec < String > {
2024-07-19 15:56:07 -04:00
let mut from_config_file = self . workspace ( ) . unstable_features ( ) . to_vec ( ) ;
2023-11-01 18:15:08 -04:00
2024-07-02 19:15:10 -04:00
self
. flags
. unstable_config
. features
. iter ( )
. for_each ( | feature | {
if ! from_config_file . contains ( feature ) {
from_config_file . push ( feature . to_string ( ) ) ;
}
} ) ;
2024-05-27 19:43:07 -04:00
2024-07-08 21:50:47 -04:00
if ! from_config_file . is_empty ( ) {
2024-10-14 20:48:39 -04:00
let all_valid_unstable_flags : Vec < & str > = crate ::UNSTABLE_GRANULAR_FLAGS
. iter ( )
. map ( | granular_flag | granular_flag . name )
. chain ( [
" sloppy-imports " ,
" byonm " ,
" bare-node-builtins " ,
" fmt-component " ,
" detect-cjs " ,
] )
. collect ( ) ;
2024-07-08 21:50:47 -04:00
// check and warn if the unstable flag of config file isn't supported, by
// iterating through the vector holding the unstable flags
for unstable_value_from_config_file in & from_config_file {
if ! all_valid_unstable_flags
. contains ( & unstable_value_from_config_file . as_str ( ) )
{
log ::warn! (
" {} '{}' isn't a valid unstable feature " ,
colors ::yellow ( " Warning " ) ,
unstable_value_from_config_file
) ;
}
}
}
2023-11-01 18:15:08 -04:00
from_config_file
}
2022-12-08 11:50:09 -05:00
pub fn v8_flags ( & self ) -> & Vec < String > {
& self . flags . v8_flags
}
2024-04-17 10:19:55 -04:00
pub fn code_cache_enabled ( & self ) -> bool {
self . flags . code_cache_enabled
}
2023-06-15 13:09:37 -04:00
pub fn watch_paths ( & self ) -> Vec < PathBuf > {
2024-03-14 19:53:46 -04:00
let mut full_paths = Vec ::new ( ) ;
if let DenoSubcommand ::Run ( RunFlags {
2023-06-15 13:09:37 -04:00
watch : Some ( WatchFlagsWithPaths { paths , .. } ) ,
..
} ) = & self . flags . subcommand
{
2024-03-14 19:53:46 -04:00
full_paths . extend ( paths . iter ( ) . map ( | path | self . initial_cwd . join ( path ) ) ) ;
}
2023-06-15 13:09:37 -04:00
if let Ok ( Some ( import_map_path ) ) = self
2024-02-24 00:21:09 -05:00
. resolve_specified_import_map_specifier ( )
2023-06-15 13:09:37 -04:00
. map ( | ms | ms . and_then ( | ref s | s . to_file_path ( ) . ok ( ) ) )
{
2024-03-14 19:53:46 -04:00
full_paths . push ( import_map_path ) ;
2023-06-15 13:09:37 -04:00
}
2024-07-03 20:54:33 -04:00
2024-07-19 15:56:07 -04:00
for ( _ , folder ) in self . workspace ( ) . config_folders ( ) {
2024-07-03 20:54:33 -04:00
if let Some ( deno_json ) = & folder . deno_json {
if deno_json . specifier . scheme ( ) = = " file " {
if let Ok ( path ) = deno_json . specifier . to_file_path ( ) {
full_paths . push ( path ) ;
}
2023-06-14 18:29:19 -04:00
}
}
2024-07-03 20:54:33 -04:00
if let Some ( pkg_json ) = & folder . pkg_json {
full_paths . push ( pkg_json . path . clone ( ) ) ;
}
2023-06-14 18:29:19 -04:00
}
2024-03-14 19:53:46 -04:00
full_paths
2022-06-28 16:45:55 -04:00
}
2024-07-09 23:06:08 -04:00
pub fn lifecycle_scripts_config ( & self ) -> LifecycleScriptsConfig {
LifecycleScriptsConfig {
allowed : self . flags . allow_scripts . clone ( ) ,
2024-09-24 15:23:57 -04:00
initial_cwd : self . initial_cwd . clone ( ) ,
root_dir : self . workspace ( ) . root_dir_path ( ) ,
2024-09-26 13:13:33 -04:00
explicit_install : matches ! (
self . sub_command ( ) ,
DenoSubcommand ::Install ( _ )
| DenoSubcommand ::Cache ( _ )
| DenoSubcommand ::Add ( _ )
) ,
2024-07-09 23:06:08 -04:00
}
}
2022-06-28 16:45:55 -04:00
}
2023-02-22 20:16:16 -05:00
/// Resolves the path to use for a local node_modules folder.
2023-08-01 20:49:09 -04:00
fn resolve_node_modules_folder (
2023-02-22 20:16:16 -05:00
cwd : & Path ,
flags : & Flags ,
2024-08-29 18:57:43 -04:00
workspace : & Workspace ,
2024-08-15 23:48:48 -04:00
deno_dir_provider : & Arc < DenoDirProvider > ,
2023-02-22 20:16:16 -05:00
) -> Result < Option < PathBuf > , AnyError > {
2024-08-30 17:58:24 -04:00
fn resolve_from_root ( root_folder : & FolderConfigs , cwd : & Path ) -> PathBuf {
root_folder
. deno_json
. as_ref ( )
. map ( | c | Cow ::Owned ( c . dir_path ( ) ) )
. or_else ( | | {
root_folder
. pkg_json
. as_ref ( )
. map ( | c | Cow ::Borrowed ( c . dir_path ( ) ) )
} )
. unwrap_or ( Cow ::Borrowed ( cwd ) )
. join ( " node_modules " )
}
let root_folder = workspace . root_folder_configs ( ) ;
let use_node_modules_dir = if let Some ( mode ) = flags . node_modules_dir {
Some ( mode . uses_node_modules_dir ( ) )
2024-08-29 18:57:43 -04:00
} else {
2024-08-30 17:58:24 -04:00
workspace
2024-09-04 11:39:30 -04:00
. node_modules_dir ( ) ?
2024-08-30 17:58:24 -04:00
. map ( | m | m . uses_node_modules_dir ( ) )
2024-08-29 18:57:43 -04:00
. or ( flags . vendor )
2024-08-30 17:58:24 -04:00
. or_else ( | | root_folder . deno_json . as_ref ( ) . and_then ( | c | c . json . vendor ) )
2024-08-29 18:57:43 -04:00
} ;
2023-05-18 18:10:44 -04:00
let path = if use_node_modules_dir = = Some ( false ) {
2023-02-22 20:16:16 -05:00
return Ok ( None ) ;
} else if let Some ( state ) = & * NPM_PROCESS_STATE {
return Ok ( state . local_node_modules_path . as_ref ( ) . map ( PathBuf ::from ) ) ;
2024-09-03 05:18:37 -04:00
} else if root_folder . pkg_json . is_some ( ) {
2024-08-30 17:58:24 -04:00
let node_modules_dir = resolve_from_root ( root_folder , cwd ) ;
2024-08-15 23:48:48 -04:00
if let Ok ( deno_dir ) = deno_dir_provider . get_or_create ( ) {
// `deno_dir.root` can be symlink in macOS
if let Ok ( root ) = canonicalize_path_maybe_not_exists ( & deno_dir . root ) {
2024-08-30 17:58:24 -04:00
if node_modules_dir . starts_with ( root ) {
2024-08-15 23:48:48 -04:00
// if the package.json is in deno_dir, then do not use node_modules
// next to it as local node_modules dir
return Ok ( None ) ;
}
}
}
2024-08-30 17:58:24 -04:00
node_modules_dir
2023-05-18 18:10:44 -04:00
} else if use_node_modules_dir . is_none ( ) {
2023-02-22 20:16:16 -05:00
return Ok ( None ) ;
} else {
2024-08-30 17:58:24 -04:00
resolve_from_root ( root_folder , cwd )
2023-02-22 20:16:16 -05:00
} ;
Ok ( Some ( canonicalize_path_maybe_not_exists ( & path ) ? ) )
}
2022-06-28 16:45:55 -04:00
fn resolve_import_map_specifier (
maybe_import_map_path : Option < & str > ,
maybe_config_file : Option < & ConfigFile > ,
2023-03-13 21:12:09 -04:00
current_dir : & Path ,
2022-06-28 16:45:55 -04:00
) -> Result < Option < ModuleSpecifier > , AnyError > {
if let Some ( import_map_path ) = maybe_import_map_path {
if let Some ( config_file ) = & maybe_config_file {
2024-02-24 00:21:09 -05:00
if config_file . json . import_map . is_some ( ) {
2022-07-01 11:50:16 -04:00
log ::warn! ( " {} the configuration file \" {} \" contains an entry for \" importMap \" that is being ignored. " , colors ::yellow ( " Warning " ) , config_file . specifier ) ;
2022-06-28 16:45:55 -04:00
}
}
2023-03-13 21:12:09 -04:00
let specifier =
deno_core ::resolve_url_or_path ( import_map_path , current_dir )
2023-03-21 14:13:32 -04:00
. with_context ( | | {
format! ( " Bad URL ( \" {import_map_path} \" ) for import map. " )
} ) ? ;
2024-02-24 00:21:09 -05:00
Ok ( Some ( specifier ) )
} else {
Ok ( None )
2022-06-28 16:45:55 -04:00
}
}
2023-04-27 10:05:20 -04:00
pub struct StorageKeyResolver ( Option < Option < String > > ) ;
impl StorageKeyResolver {
pub fn from_options ( options : & CliOptions ) -> Self {
Self ( if let Some ( location ) = & options . flags . location {
// if a location is set, then the ascii serialization of the location is
// used, unless the origin is opaque, and then no storage origin is set, as
// we can't expect the origin to be reproducible
let storage_origin = location . origin ( ) ;
if storage_origin . is_tuple ( ) {
Some ( Some ( storage_origin . ascii_serialization ( ) ) )
} else {
Some ( None )
}
} else {
// otherwise we will use the path to the config file or None to
// fall back to using the main module's path
options
2024-07-19 15:56:07 -04:00
. start_dir
2024-07-03 20:54:33 -04:00
. maybe_deno_json ( )
2023-04-27 10:05:20 -04:00
. map ( | config_file | Some ( config_file . specifier . to_string ( ) ) )
} )
}
2023-05-01 08:59:38 -04:00
/// Creates a storage key resolver that will always resolve to being empty.
pub fn empty ( ) -> Self {
Self ( Some ( None ) )
}
2023-04-27 10:05:20 -04:00
/// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key (
& self ,
main_module : & ModuleSpecifier ,
) -> Option < String > {
// use the stored value or fall back to using the path of the main module.
if let Some ( maybe_value ) = & self . 0 {
maybe_value . clone ( )
} else {
Some ( main_module . to_string ( ) )
}
}
}
2022-12-08 11:50:09 -05:00
/// Resolves the no_prompt value based on the cli flags and environment.
2024-05-06 19:21:58 -04:00
pub fn resolve_no_prompt ( flags : & PermissionFlags ) -> bool {
2023-02-24 14:23:07 -05:00
flags . no_prompt | | has_flag_env_var ( " DENO_NO_PROMPT " )
}
2023-05-22 21:28:36 -04:00
pub fn has_flag_env_var ( name : & str ) -> bool {
2023-02-24 14:23:07 -05:00
let value = env ::var ( name ) ;
matches! ( value . as_ref ( ) . map ( | s | s . as_str ( ) ) , Ok ( " 1 " ) )
2022-12-08 11:50:09 -05:00
}
2023-05-10 20:06:59 -04:00
pub fn npm_pkg_req_ref_to_binary_command (
req_ref : & NpmPackageReqReference ,
) -> String {
2023-08-21 05:53:52 -04:00
let binary_name = req_ref . sub_path ( ) . unwrap_or ( req_ref . req ( ) . name . as_str ( ) ) ;
2023-05-10 20:06:59 -04:00
binary_name . to_string ( )
}
2024-07-03 20:54:33 -04:00
pub fn config_to_deno_graph_workspace_member (
config : & ConfigFile ,
) -> Result < deno_graph ::WorkspaceMember , AnyError > {
2024-08-30 17:12:13 -04:00
let name = match & config . json . name {
Some ( name ) = > name . clone ( ) ,
None = > bail! ( " Missing 'name' field in config file. " ) ,
} ;
let version = match & config . json . version {
Some ( name ) = > Some ( deno_semver ::Version ::parse_standard ( name ) ? ) ,
2024-08-30 18:05:44 -04:00
None = > None ,
2024-07-03 20:54:33 -04:00
} ;
Ok ( deno_graph ::WorkspaceMember {
base : config . specifier . join ( " ./ " ) . unwrap ( ) ,
2024-08-30 17:12:13 -04:00
name ,
version ,
2024-07-03 20:54:33 -04:00
exports : config . to_exports_config ( ) ? . into_map ( ) ,
} )
}
2024-07-09 17:33:41 -04:00
fn load_env_variables_from_env_file ( filename : Option < & String > ) {
let Some ( env_file_name ) = filename else {
return ;
} ;
match from_filename ( env_file_name ) {
Ok ( _ ) = > ( ) ,
Err ( error ) = > {
match error {
dotenvy ::Error ::LineParse ( line , index ) = > log ::info! ( " {} Parsing failed within the specified environment file: {} at index: {} of the value: {} " , colors ::yellow ( " Warning " ) , env_file_name , index , line ) ,
2024-08-08 09:50:57 -04:00
dotenvy ::Error ::Io ( _ ) = > log ::info! ( " {} The `--env-file` flag was used, but the environment file specified '{}' was not found. " , colors ::yellow ( " Warning " ) , env_file_name ) ,
2024-07-09 17:33:41 -04:00
dotenvy ::Error ::EnvVar ( _ ) = > log ::info! ( " {} One or more of the environment variables isn't present or not unicode within the specified environment file: {} " , colors ::yellow ( " Warning " ) , env_file_name ) ,
_ = > log ::info! ( " {} Unknown failure occurred with the specified environment file: {} " , colors ::yellow ( " Warning " ) , env_file_name ) ,
}
}
}
}
2022-06-28 16:45:55 -04:00
#[ cfg(test) ]
mod test {
2023-05-22 21:39:59 -04:00
use pretty_assertions ::assert_eq ;
2022-06-28 16:45:55 -04:00
2024-07-08 10:12:10 -04:00
use super ::* ;
2022-06-28 16:45:55 -04:00
#[ test ]
fn resolve_import_map_flags_take_precedence ( ) {
let config_text = r #" {
" importMap " : " import_map.json "
} " #;
2023-03-14 07:37:15 -04:00
let cwd = & std ::env ::current_dir ( ) . unwrap ( ) ;
2022-06-28 16:45:55 -04:00
let config_specifier =
ModuleSpecifier ::parse ( " file:///deno/deno.jsonc " ) . unwrap ( ) ;
2024-03-27 17:14:27 -04:00
let config_file = ConfigFile ::new (
config_text ,
config_specifier ,
2024-07-19 15:56:07 -04:00
& deno_config ::deno_json ::ConfigParseOptions ::default ( ) ,
2024-03-27 17:14:27 -04:00
)
. unwrap ( ) ;
2023-03-13 21:12:09 -04:00
let actual = resolve_import_map_specifier (
Some ( " import-map.json " ) ,
Some ( & config_file ) ,
cwd ,
) ;
let import_map_path = cwd . join ( " import-map.json " ) ;
2022-06-28 16:45:55 -04:00
let expected_specifier =
2022-12-17 17:20:15 -05:00
ModuleSpecifier ::from_file_path ( import_map_path ) . unwrap ( ) ;
2022-06-28 16:45:55 -04:00
assert! ( actual . is_ok ( ) ) ;
let actual = actual . unwrap ( ) ;
assert_eq! ( actual , Some ( expected_specifier ) ) ;
}
#[ test ]
fn resolve_import_map_none ( ) {
let config_text = r # "{}"# ;
let config_specifier =
ModuleSpecifier ::parse ( " file:///deno/deno.jsonc " ) . unwrap ( ) ;
2024-03-27 17:14:27 -04:00
let config_file = ConfigFile ::new (
config_text ,
config_specifier ,
2024-07-19 15:56:07 -04:00
& deno_config ::deno_json ::ConfigParseOptions ::default ( ) ,
2024-03-27 17:14:27 -04:00
)
. unwrap ( ) ;
2023-03-13 21:12:09 -04:00
let actual = resolve_import_map_specifier (
None ,
Some ( & config_file ) ,
& PathBuf ::from ( " / " ) ,
) ;
2022-06-28 16:45:55 -04:00
assert! ( actual . is_ok ( ) ) ;
let actual = actual . unwrap ( ) ;
assert_eq! ( actual , None ) ;
}
#[ test ]
fn resolve_import_map_no_config ( ) {
2023-03-13 21:12:09 -04:00
let actual = resolve_import_map_specifier ( None , None , & PathBuf ::from ( " / " ) ) ;
2022-06-28 16:45:55 -04:00
assert! ( actual . is_ok ( ) ) ;
let actual = actual . unwrap ( ) ;
assert_eq! ( actual , None ) ;
}
2023-04-27 10:05:20 -04:00
#[ test ]
fn storage_key_resolver_test ( ) {
let resolver = StorageKeyResolver ( None ) ;
let specifier = ModuleSpecifier ::parse ( " file:///a.ts " ) . unwrap ( ) ;
assert_eq! (
resolver . resolve_storage_key ( & specifier ) ,
Some ( specifier . to_string ( ) )
) ;
let resolver = StorageKeyResolver ( Some ( None ) ) ;
assert_eq! ( resolver . resolve_storage_key ( & specifier ) , None ) ;
let resolver = StorageKeyResolver ( Some ( Some ( " value " . to_string ( ) ) ) ) ;
assert_eq! (
resolver . resolve_storage_key ( & specifier ) ,
Some ( " value " . to_string ( ) )
) ;
2023-05-01 08:59:38 -04:00
// test empty
let resolver = StorageKeyResolver ::empty ( ) ;
assert_eq! ( resolver . resolve_storage_key ( & specifier ) , None ) ;
2023-04-27 10:05:20 -04:00
}
2023-05-22 21:39:59 -04:00
2023-12-12 09:45:20 -05:00
#[ test ]
2024-02-14 13:30:44 -05:00
fn jsr_urls ( ) {
let reg_url = jsr_url ( ) ;
2023-12-12 09:45:20 -05:00
assert! ( reg_url . as_str ( ) . ends_with ( '/' ) ) ;
2024-02-14 13:30:44 -05:00
let reg_api_url = jsr_api_url ( ) ;
2023-12-12 09:45:20 -05:00
assert! ( reg_api_url . as_str ( ) . ends_with ( '/' ) ) ;
}
2022-06-28 16:45:55 -04:00
}