use std::path::Path;
use super::config_parser;
use super::{PathRule, Plugin, PluginResult};
const ENABLERS: &[&str] = &["@adonisjs/core"];
const ENTRY_PATTERNS: &[&str] = &[
"server.{ts,js}",
"ace",
"ace.{ts,js}",
"bin/**/*.{ts,js}",
"start/**/*.{ts,js}",
"providers/**/*.{ts,js}",
"commands/**/*.{ts,js}",
"config/**/*.{ts,js}",
"contracts/**/*.ts",
"database/migrations/**/*.{ts,js}",
"database/seeders/**/*.{ts,js}",
"database/factories/**/*.{ts,js}",
"app/Controllers/Http/**/*.ts",
"app/Controllers/Ws/**/*.ts",
"app/Models/**/*.ts",
"app/Middleware/**/*.ts",
"app/Validators/**/*.ts",
"app/Exceptions/**/*.ts",
"app/Mailers/**/*.ts",
"app/Listeners/**/*.ts",
"app/Services/**/*.ts",
"app/Repositories/**/*.ts",
"app/Strategies/**/*.ts",
"app/Helpers/**/*.{ts,js}",
"app/controllers/**/*.ts",
"app/models/**/*.ts",
"app/middleware/**/*.ts",
"app/validators/**/*.ts",
"app/exceptions/**/*.ts",
"app/mails/**/*.ts",
"app/listeners/**/*.ts",
"app/services/**/*.ts",
"app/repositories/**/*.ts",
"app/helpers/**/*.ts",
];
const CONFIG_PATTERNS: &[&str] = &[
".adonisrc.json",
"adonisrc.ts",
"adonisrc.js",
];
const ALWAYS_USED: &[&str] = &[
".adonisrc.json",
"adonisrc.ts",
"adonisrc.js",
"ace-manifest.json",
"tsconfig.json",
"env.ts",
"japaFile.ts",
];
const VIRTUAL_MODULE_PREFIXES: &[&str] = &["@ioc:"];
const TOOLING_DEPENDENCIES: &[&str] = &[
"@adonisjs/core",
"@adonisjs/application",
"@adonisjs/ace",
"@adonisjs/assembler",
"@adonisjs/repl",
"@adonisjs/fold",
"@adonisjs/config",
"@adonisjs/env",
"@adonisjs/encryption",
"@adonisjs/hash",
"@adonisjs/events",
"@adonisjs/logger",
"@adonisjs/http-server",
"@adonisjs/bodyparser",
"@adonisjs/static",
"@adonisjs/health",
"@adonisjs/lucid",
"@adonisjs/auth",
"@adonisjs/session",
"@adonisjs/shield",
"@adonisjs/view",
"@adonisjs/i18n",
"@adonisjs/mail",
"@adonisjs/redis",
"@adonisjs/bouncer",
"@adonisjs/limiter",
"@adonisjs/drive",
"@adonisjs/validator",
"@adonisjs/http-transformers",
"@vinejs/vine",
"adonis-preset-ts",
"adonis5-sentry",
"@boringnode/encryption",
"argon2",
"bcrypt",
"edge.js",
"pino-pretty",
"youch",
"phc-bcrypt",
"reflect-metadata",
];
const V5_PATH_ARRAY_KEYS: &[&str] = &["preloads", "providers", "commands", "aceProviders"];
fn local_path_to_entry_patterns(raw: &str) -> Vec<String> {
let stripped = raw.strip_prefix("./").unwrap_or(raw);
let no_ext = stripped
.strip_suffix(".ts")
.or_else(|| stripped.strip_suffix(".js"))
.unwrap_or(stripped)
.trim_end_matches('/');
if no_ext.is_empty() {
return Vec::new();
}
vec![
format!("{no_ext}.{{ts,js}}"),
format!("{no_ext}/**/*.{{ts,js}}"),
]
}
fn is_local_rc_path(spec: &str) -> bool {
spec.starts_with("./") || spec.starts_with("../") || spec.starts_with('/')
}
fn rc_path_entries(source: &str, config_path: &Path, key: &str) -> Vec<String> {
let mut entries = config_parser::extract_config_string_array(source, config_path, &[key]);
entries.extend(config_parser::extract_config_array_object_strings(
source,
config_path,
&[key],
"file",
));
entries
}
fn resolve_v5_adonisrc(config_path: &Path, source: &str) -> PluginResult {
let mut result = PluginResult::default();
for key in V5_PATH_ARRAY_KEYS {
for entry in rc_path_entries(source, config_path, key) {
if is_local_rc_path(&entry) {
for glob in local_path_to_entry_patterns(&entry) {
result.entry_patterns.push(PathRule::new(glob));
}
} else {
let pkg = crate::resolve::extract_package_name(&entry);
if !pkg.is_empty() {
result.referenced_dependencies.push(pkg);
}
}
}
}
for (find, replacement) in
config_parser::extract_config_aliases(source, config_path, &["aliases"])
{
let prefix = if find.ends_with('/') {
find
} else {
format!("{find}/")
};
let stripped = replacement.trim_start_matches("./").trim_end_matches('/');
let target = if stripped.is_empty() {
String::from("./")
} else {
format!("{stripped}/")
};
result.path_aliases.push((prefix, target));
}
for pattern in config_parser::extract_config_array_object_strings(
source,
config_path,
&["metaFiles"],
"pattern",
) {
result.always_used_files.push(pattern);
}
for raw in config_parser::extract_config_string_array(source, config_path, &["types"]) {
let normalized = raw.trim_start_matches("./").to_string();
if !normalized.is_empty() {
result.always_used_files.push(normalized);
}
}
result
}
const V6_LAZY_IMPORT_ARRAY_KEYS: &[&str] = &["commands", "providers", "preloads"];
const V6_LAZY_IMPORT_NESTED_ARRAY_PATHS: &[&[&str]] = &[
&["hooks", "onBuildStarting"],
&["hooks", "onBuildCompleted"],
&["hooks", "onDevServerStarted"],
&["hooks", "onSourceFileChanged"],
];
fn resolve_v6_adonisrc(config_path: &Path, source: &str, root: &Path) -> PluginResult {
let mut result = PluginResult::default();
for key in V6_LAZY_IMPORT_ARRAY_KEYS {
for spec in config_parser::extract_lazy_imports_in_array(source, config_path, &[key]) {
classify_v6_specifier(&spec, &mut result);
}
}
for path in V6_LAZY_IMPORT_NESTED_ARRAY_PATHS {
for spec in config_parser::extract_lazy_imports_in_array(source, config_path, path) {
classify_v6_specifier(&spec, &mut result);
}
}
let directory_keys =
config_parser::extract_config_object_keys(source, config_path, &["directories"]);
for key in &directory_keys {
let Some(dir_path) =
config_parser::extract_config_string(source, config_path, &["directories", key])
else {
continue;
};
let trimmed = dir_path.trim_start_matches("./").trim_end_matches('/');
if !trimmed.is_empty() {
result
.entry_patterns
.push(PathRule::new(format!("{trimmed}/**/*.{{ts,js}}")));
}
}
for pattern in config_parser::extract_config_array_object_strings(
source,
config_path,
&["metaFiles"],
"pattern",
) {
result.always_used_files.push(pattern);
}
if let Some(pairs) = read_subpath_imports(root) {
for (find, replacement) in pairs {
if let Some(alias) = subpath_import_to_path_alias(&find, &replacement) {
result.path_aliases.push(alias);
}
}
}
result
}
fn classify_v6_specifier(spec: &str, result: &mut PluginResult) {
if spec.starts_with('#') {
return;
}
if is_local_rc_path(spec) {
for glob in local_path_to_entry_patterns(spec) {
result.entry_patterns.push(PathRule::new(glob));
}
return;
}
let pkg = crate::resolve::extract_package_name(spec);
if !pkg.is_empty() {
result.referenced_dependencies.push(pkg);
}
}
fn subpath_import_to_path_alias(key: &str, value: &str) -> Option<(String, String)> {
let prefix = key.strip_suffix("/*")?;
if prefix.is_empty() {
return None;
}
let target = value
.trim_start_matches("./")
.strip_suffix("/*.js")
.or_else(|| value.trim_start_matches("./").strip_suffix("/*.ts"))
.or_else(|| value.trim_start_matches("./").strip_suffix("/*"))?;
if target.is_empty() {
return None;
}
Some((format!("{prefix}/"), format!("{target}/")))
}
fn read_subpath_imports(root: &Path) -> Option<Vec<(String, String)>> {
let pkg_path = root.join("package.json");
let content = std::fs::read_to_string(&pkg_path).ok()?;
let value: serde_json::Value = serde_json::from_str(&content).ok()?;
let imports = value.get("imports")?.as_object()?;
let mut pairs = Vec::with_capacity(imports.len());
for (k, v) in imports {
if let Some(s) = v.as_str() {
pairs.push((k.clone(), s.to_string()));
}
}
Some(pairs)
}
define_plugin! {
struct AdonisPlugin => "adonis",
enablers: ENABLERS,
entry_patterns: ENTRY_PATTERNS,
config_patterns: CONFIG_PATTERNS,
always_used: ALWAYS_USED,
tooling_dependencies: TOOLING_DEPENDENCIES,
virtual_module_prefixes: VIRTUAL_MODULE_PREFIXES,
resolve_config(config_path, source, root) {
let filename = config_path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("");
match filename {
".adonisrc.json" => resolve_v5_adonisrc(config_path, source),
"adonisrc.ts" | "adonisrc.js" => resolve_v6_adonisrc(config_path, source, root),
_ => PluginResult::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn has_entry_pattern(result: &PluginResult, pattern: &str) -> bool {
result
.entry_patterns
.iter()
.any(|rule| rule.pattern == pattern)
}
fn rc_path() -> &'static Path {
Path::new(".adonisrc.json")
}
#[test]
fn local_path_emits_file_and_dir_globs() {
assert_eq!(
local_path_to_entry_patterns("./start/routes"),
vec![
"start/routes.{ts,js}".to_string(),
"start/routes/**/*.{ts,js}".to_string(),
]
);
}
#[test]
fn local_path_strips_existing_extension() {
assert_eq!(
local_path_to_entry_patterns("./providers/AppProvider.ts"),
vec![
"providers/AppProvider.{ts,js}".to_string(),
"providers/AppProvider/**/*.{ts,js}".to_string(),
]
);
}
#[test]
fn local_path_handles_directory_form() {
assert_eq!(
local_path_to_entry_patterns("./commands"),
vec![
"commands.{ts,js}".to_string(),
"commands/**/*.{ts,js}".to_string(),
]
);
}
#[test]
fn local_path_rejects_empty_after_stripping() {
assert!(local_path_to_entry_patterns("./").is_empty());
assert!(local_path_to_entry_patterns("").is_empty());
}
#[test]
fn is_local_rc_path_detects_relative_and_absolute() {
assert!(is_local_rc_path("./start/routes"));
assert!(is_local_rc_path("../shared/config"));
assert!(is_local_rc_path("/abs/path"));
assert!(!is_local_rc_path("@adonisjs/core"));
assert!(!is_local_rc_path("adonis5-sentry"));
}
#[test]
fn resolve_v5_extracts_preloads_providers_commands() {
let source = r#"{
"typescript": true,
"preloads": ["./start/routes", "./start/kernel"],
"providers": [
"./providers/AppProvider",
"@adonisjs/core",
"@adonisjs/lucid"
],
"commands": [
"./commands",
"@adonisjs/core/build/commands/index.js"
]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(has_entry_pattern(&result, "start/routes.{ts,js}"));
assert!(has_entry_pattern(&result, "start/kernel.{ts,js}"));
assert!(has_entry_pattern(&result, "providers/AppProvider.{ts,js}"));
assert!(has_entry_pattern(&result, "commands.{ts,js}"));
assert!(has_entry_pattern(&result, "commands/**/*.{ts,js}"));
assert!(
result
.referenced_dependencies
.contains(&"@adonisjs/core".to_string())
);
assert!(
result
.referenced_dependencies
.contains(&"@adonisjs/lucid".to_string())
);
}
#[test]
fn resolve_v5_extracts_object_form_entries() {
let source = r#"{
"preloads": [
{ "file": "./start/socket", "environment": ["web"] },
"./start/events"
]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(has_entry_pattern(&result, "start/socket.{ts,js}"));
assert!(has_entry_pattern(&result, "start/events.{ts,js}"));
}
#[test]
fn resolve_v5_extracts_ace_providers() {
let source = r#"{
"aceProviders": [
"@adonisjs/repl",
"./providers/AceProvider"
]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(has_entry_pattern(&result, "providers/AceProvider.{ts,js}"));
assert!(
result
.referenced_dependencies
.contains(&"@adonisjs/repl".to_string())
);
}
#[test]
fn resolve_v5_extracts_path_aliases() {
let source = r#"{
"aliases": {
"App": "app",
"Config": "config",
"Database": "database",
"Contracts": "contracts"
}
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(
result
.path_aliases
.contains(&("App/".to_string(), "app/".to_string()))
);
assert!(
result
.path_aliases
.contains(&("Config/".to_string(), "config/".to_string()))
);
assert!(
result
.path_aliases
.contains(&("Database/".to_string(), "database/".to_string()))
);
assert!(
result
.path_aliases
.contains(&("Contracts/".to_string(), "contracts/".to_string()))
);
}
#[test]
fn resolve_v5_path_aliases_strip_dot_slash() {
let source = r#"{
"aliases": {
"App": "./app"
}
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(
result
.path_aliases
.contains(&("App/".to_string(), "app/".to_string()))
);
}
#[test]
fn resolve_v5_extracts_meta_files_patterns() {
let source = r#"{
"metaFiles": [
{ "pattern": "resources/views/**/*.edge", "reloadServer": false },
{ "pattern": "newrelic.js", "reloadServer": false }
]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(
result
.always_used_files
.contains(&"resources/views/**/*.edge".to_string())
);
assert!(
result
.always_used_files
.contains(&"newrelic.js".to_string())
);
}
#[test]
fn resolve_v5_extracts_types_declarations() {
let source = r#"{
"types": ["./contracts/logger.ts", "./contracts/env.ts"]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
assert!(
result
.always_used_files
.contains(&"contracts/logger.ts".to_string())
);
assert!(
result
.always_used_files
.contains(&"contracts/env.ts".to_string())
);
}
#[test]
fn resolve_v5_ignores_non_adonisrc_filenames() {
let plugin = AdonisPlugin;
let result = plugin.resolve_config(
Path::new("some-other.json"),
r#"{ "preloads": ["./should-not-be-extracted"] }"#,
Path::new("/project"),
);
assert!(result.entry_patterns.is_empty());
assert!(result.referenced_dependencies.is_empty());
assert!(result.path_aliases.is_empty());
}
#[test]
fn resolve_v5_full_customer_api_shape() {
let source = r#"{
"typescript": true,
"commands": [
"./commands",
"@adonisjs/core/build/commands/index.js",
"@adonisjs/repl/build/commands",
"@adonisjs/lucid/build/commands",
"@adonisjs/mail/build/commands"
],
"exceptionHandlerNamespace": "App/Exceptions/Handler",
"aliases": {
"App": "app",
"Config": "config",
"Database": "database",
"Contracts": "contracts"
},
"preloads": [
"./start/routes",
"./start/events",
"./start/kernel",
"./start/validator"
],
"providers": [
"./providers/AppProvider",
"./providers/LoggerProvider",
"@adonisjs/core",
"@adonisjs/lucid",
"@adonisjs/auth",
"@adonisjs/mail",
"adonis5-sentry",
"@adonisjs/view"
],
"aceProviders": ["@adonisjs/repl"],
"metaFiles": [
{ "pattern": "resources/views/**/*.edge", "reloadServer": false },
{ "pattern": "newrelic.js", "reloadServer": false }
],
"types": ["./contracts/logger.ts"]
}"#;
let result = resolve_v5_adonisrc(rc_path(), source);
for preload in [
"start/routes.{ts,js}",
"start/events.{ts,js}",
"start/kernel.{ts,js}",
"start/validator.{ts,js}",
] {
assert!(
has_entry_pattern(&result, preload),
"missing preload entry: {preload}"
);
}
assert!(has_entry_pattern(&result, "providers/AppProvider.{ts,js}"));
assert!(has_entry_pattern(
&result,
"providers/LoggerProvider.{ts,js}"
));
for ext in [
"@adonisjs/core",
"@adonisjs/lucid",
"@adonisjs/auth",
"@adonisjs/mail",
"@adonisjs/view",
"@adonisjs/repl",
"adonis5-sentry",
] {
assert!(
result.referenced_dependencies.contains(&ext.to_string()),
"missing referenced dependency: {ext}"
);
}
assert_eq!(result.path_aliases.len(), 4);
assert!(
result
.always_used_files
.contains(&"resources/views/**/*.edge".to_string())
);
assert!(
result
.always_used_files
.contains(&"newrelic.js".to_string())
);
assert!(
result
.always_used_files
.contains(&"contracts/logger.ts".to_string())
);
}
#[test]
fn is_enabled_detects_adonis_core_dependency() {
let plugin = AdonisPlugin;
assert!(plugin.is_enabled_with_deps(
&["@adonisjs/core".to_string(), "luxon".to_string()],
Path::new("/project"),
));
assert!(!plugin.is_enabled_with_deps(
&["express".to_string(), "luxon".to_string()],
Path::new("/project"),
));
}
#[test]
fn subpath_import_to_path_alias_typical_form() {
assert_eq!(
subpath_import_to_path_alias("#controllers/*", "./app/controllers/*.js"),
Some(("#controllers/".to_string(), "app/controllers/".to_string()))
);
}
#[test]
fn subpath_import_to_path_alias_ts_extension_form() {
assert_eq!(
subpath_import_to_path_alias("#models/*", "./app/models/*.ts"),
Some(("#models/".to_string(), "app/models/".to_string()))
);
}
#[test]
fn subpath_import_to_path_alias_no_extension() {
assert_eq!(
subpath_import_to_path_alias("#start/*", "./start/*"),
Some(("#start/".to_string(), "start/".to_string()))
);
}
#[test]
fn subpath_import_to_path_alias_rejects_bare_keys() {
assert_eq!(
subpath_import_to_path_alias("#start/routes", "./start/routes.js"),
None
);
}
fn rc_ts_path() -> &'static Path {
Path::new("adonisrc.ts")
}
#[test]
fn resolve_v6_classifies_lazy_imports_into_correct_buckets() {
let source = r"
import { defineConfig } from '@adonisjs/core/app'
export default defineConfig({
commands: [
() => import('@adonisjs/core/commands'),
() => import('@adonisjs/lucid/commands'),
],
providers: [
() => import('@adonisjs/core/providers/app_provider'),
{
file: () => import('@adonisjs/core/providers/repl_provider'),
environment: ['repl', 'test'],
},
() => import('./providers/app_provider'),
],
preloads: [
() => import('#start/routes'),
() => import('#start/kernel'),
],
})
";
let result = resolve_v6_adonisrc(rc_ts_path(), source, Path::new("/non-existent-root"));
for ext in ["@adonisjs/core", "@adonisjs/lucid"] {
assert!(
result.referenced_dependencies.contains(&ext.to_string()),
"missing referenced dep: {ext}"
);
}
assert!(has_entry_pattern(&result, "providers/app_provider.{ts,js}"));
assert!(
!has_entry_pattern(&result, "start/routes.{ts,js}"),
"subpath spec should not become an entry pattern directly"
);
}
#[test]
fn resolve_v6_extracts_directory_overrides() {
let source = r"
export default defineConfig({
directories: {
resolvers: 'app/graphql/resolvers',
schemas: './app/graphql/schemas',
},
})
";
let result = resolve_v6_adonisrc(rc_ts_path(), source, Path::new("/non-existent-root"));
assert!(has_entry_pattern(
&result,
"app/graphql/resolvers/**/*.{ts,js}"
));
assert!(has_entry_pattern(
&result,
"app/graphql/schemas/**/*.{ts,js}"
));
}
#[test]
fn resolve_v6_classifies_hook_lazy_imports() {
let source = r"
import { defineConfig } from '@adonisjs/core/app'
export default defineConfig({
hooks: {
onBuildStarting: [
() => import('@adonisjs/vite/build_hook'),
() => import('./hooks/on_build_starting'),
],
onBuildCompleted: [
() => import('my-package/hooks/on_build_completed'),
],
onDevServerStarted: [
() => import('./hooks/on_dev_started'),
],
onSourceFileChanged: [
() => import('@scope/dev-tools/hooks/on_change'),
],
},
})
";
let result = resolve_v6_adonisrc(rc_ts_path(), source, Path::new("/non-existent-root"));
for pkg in ["@adonisjs/vite", "my-package", "@scope/dev-tools"] {
assert!(
result.referenced_dependencies.contains(&pkg.to_string()),
"missing referenced hook dep: {pkg}"
);
}
assert!(has_entry_pattern(
&result,
"hooks/on_build_starting.{ts,js}"
));
assert!(has_entry_pattern(&result, "hooks/on_dev_started.{ts,js}"));
}
#[test]
fn resolve_v6_extracts_meta_files() {
let source = r"
export default defineConfig({
metaFiles: [
{ pattern: 'public/**', reloadServer: false },
{ pattern: 'resources/views/**/*.edge', reloadServer: false },
],
})
";
let result = resolve_v6_adonisrc(rc_ts_path(), source, Path::new("/non-existent-root"));
assert!(result.always_used_files.contains(&"public/**".to_string()));
assert!(
result
.always_used_files
.contains(&"resources/views/**/*.edge".to_string())
);
}
#[test]
fn resolve_v6_reads_subpath_imports_from_package_json() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
std::fs::write(
root.join("package.json"),
r##"{
"name": "test-v6-app",
"type": "module",
"imports": {
"#controllers/*": "./app/controllers/*.js",
"#models/*": "./app/models/*.js",
"#start/*": "./start/*.js",
"#config/*": "./config/*.js",
"#graphql/*": "./app/graphql/*.js"
}
}"##,
)
.expect("write package.json");
let rc_source = r"
export default defineConfig({
preloads: [() => import('#start/routes')],
})
";
let rc_path = root.join("adonisrc.ts");
std::fs::write(&rc_path, rc_source).expect("write adonisrc.ts");
let result = resolve_v6_adonisrc(&rc_path, rc_source, root);
for (find, repl) in [
("#controllers/", "app/controllers/"),
("#models/", "app/models/"),
("#start/", "start/"),
("#config/", "config/"),
("#graphql/", "app/graphql/"),
] {
assert!(
result
.path_aliases
.contains(&(find.to_string(), repl.to_string())),
"missing alias: {find} -> {repl}"
);
}
}
#[test]
fn resolve_v6_handles_missing_package_json_gracefully() {
let source = r"
export default defineConfig({
providers: [() => import('@adonisjs/core/providers/app_provider')],
})
";
let result = resolve_v6_adonisrc(rc_ts_path(), source, Path::new("/non-existent-root"));
assert!(result.path_aliases.is_empty());
assert!(
result
.referenced_dependencies
.contains(&"@adonisjs/core".to_string())
);
}
#[test]
fn resolve_v6_full_friends_of_adonis_playground_shape() {
let source = r"
import { indexEntities } from '@adonisjs/core'
import { defineConfig } from '@adonisjs/core/app'
import { indexResolvers } from '@foadonis/graphql'
export default defineConfig({
commands: [
() => import('@adonisjs/core/commands'),
() => import('@adonisjs/lucid/commands'),
() => import('@adonisjs/bouncer/commands'),
() => import('@foadonis/graphql/commands'),
],
providers: [
() => import('@adonisjs/core/providers/app_provider'),
() => import('@adonisjs/core/providers/hash_provider'),
{
file: () => import('@adonisjs/core/providers/repl_provider'),
environment: ['repl', 'test'],
},
() => import('@foadonis/graphql/graphql_provider'),
() => import('@adonisjs/lucid/database_provider'),
],
preloads: [
() => import('#start/routes'),
() => import('#start/kernel'),
() => import('#start/graphql'),
],
directories: {
resolvers: 'app/graphql/resolvers',
},
})
";
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path();
std::fs::write(
root.join("package.json"),
r##"{
"name": "playground-graphql",
"type": "module",
"imports": {
"#controllers/*": "./app/controllers/*.js",
"#models/*": "./app/models/*.js",
"#middleware/*": "./app/middleware/*.js",
"#start/*": "./start/*.js",
"#config/*": "./config/*.js",
"#graphql/*": "./app/graphql/*.js"
}
}"##,
)
.expect("write package.json");
let result = resolve_v6_adonisrc(&root.join("adonisrc.ts"), source, root);
for pkg in [
"@adonisjs/core",
"@adonisjs/lucid",
"@adonisjs/bouncer",
"@foadonis/graphql",
] {
assert!(
result.referenced_dependencies.contains(&pkg.to_string()),
"missing referenced dep: {pkg}"
);
}
assert!(has_entry_pattern(
&result,
"app/graphql/resolvers/**/*.{ts,js}"
));
assert!(
result
.path_aliases
.contains(&("#graphql/".to_string(), "app/graphql/".to_string()))
);
assert!(
result
.path_aliases
.contains(&("#start/".to_string(), "start/".to_string()))
);
}
}