mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
feat(cli): deno init --lib
(#22499)
Closes #22287 Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com> Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
parent
9776a13e33
commit
ff5163af05
9 changed files with 233 additions and 69 deletions
|
@ -205,6 +205,7 @@ impl FmtFlags {
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct InitFlags {
|
pub struct InitFlags {
|
||||||
pub dir: Option<String>,
|
pub dir: Option<String>,
|
||||||
|
pub lib: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -2052,11 +2053,18 @@ fn init_subcommand() -> Command {
|
||||||
Command::new("init")
|
Command::new("init")
|
||||||
.about("Initialize a new project")
|
.about("Initialize a new project")
|
||||||
.defer(|cmd| {
|
.defer(|cmd| {
|
||||||
cmd.arg(
|
cmd
|
||||||
|
.arg(
|
||||||
Arg::new("dir")
|
Arg::new("dir")
|
||||||
.required(false)
|
.required(false)
|
||||||
.value_hint(ValueHint::DirPath),
|
.value_hint(ValueHint::DirPath),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("lib")
|
||||||
|
.long("lib")
|
||||||
|
.required(false)
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4033,6 +4041,7 @@ fn fmt_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
fn init_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
fn init_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
flags.subcommand = DenoSubcommand::Init(InitFlags {
|
flags.subcommand = DenoSubcommand::Init(InitFlags {
|
||||||
dir: matches.remove_one::<String>("dir"),
|
dir: matches.remove_one::<String>("dir"),
|
||||||
|
lib: matches.get_flag("lib"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9753,7 +9762,10 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Init(InitFlags { dir: None }),
|
subcommand: DenoSubcommand::Init(InitFlags {
|
||||||
|
dir: None,
|
||||||
|
lib: false
|
||||||
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -9764,6 +9776,7 @@ mod tests {
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Init(InitFlags {
|
subcommand: DenoSubcommand::Init(InitFlags {
|
||||||
dir: Some(String::from("foo")),
|
dir: Some(String::from("foo")),
|
||||||
|
lib: false
|
||||||
}),
|
}),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -9773,11 +9786,38 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Init(InitFlags { dir: None }),
|
subcommand: DenoSubcommand::Init(InitFlags {
|
||||||
|
dir: None,
|
||||||
|
lib: false
|
||||||
|
}),
|
||||||
log_level: Some(Level::Error),
|
log_level: Some(Level::Error),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let r = flags_from_vec(svec!["deno", "init", "--lib"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Init(InitFlags {
|
||||||
|
dir: None,
|
||||||
|
lib: true
|
||||||
|
}),
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let r = flags_from_vec(svec!["deno", "init", "foo", "--lib"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Init(InitFlags {
|
||||||
|
dir: Some(String::from("foo")),
|
||||||
|
lib: true
|
||||||
|
}),
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -4,10 +4,145 @@ use crate::args::InitFlags;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::serde_json::json;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn init_project(init_flags: InitFlags) -> Result<(), AnyError> {
|
||||||
|
let cwd =
|
||||||
|
std::env::current_dir().context("Can't read current working directory.")?;
|
||||||
|
let dir = if let Some(dir) = &init_flags.dir {
|
||||||
|
let dir = cwd.join(dir);
|
||||||
|
std::fs::create_dir_all(&dir)?;
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
cwd
|
||||||
|
};
|
||||||
|
|
||||||
|
if init_flags.lib {
|
||||||
|
// Extract the directory name to use as the project name
|
||||||
|
let project_name = dir
|
||||||
|
.file_name()
|
||||||
|
.unwrap_or_else(|| dir.as_os_str())
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
create_file(
|
||||||
|
&dir,
|
||||||
|
"mod.ts",
|
||||||
|
r#"export function add(a: number, b: number): number {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
create_file(
|
||||||
|
&dir,
|
||||||
|
"mod_test.ts",
|
||||||
|
r#"import { assertEquals } from "jsr:@std/assert";
|
||||||
|
import { add } from "./mod.ts";
|
||||||
|
|
||||||
|
Deno.test(function addTest() {
|
||||||
|
assertEquals(add(2, 3), 5);
|
||||||
|
});
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
create_json_file(
|
||||||
|
&dir,
|
||||||
|
"deno.json",
|
||||||
|
&json!({
|
||||||
|
"name": project_name,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"exports": "./mod.ts",
|
||||||
|
"tasks": {
|
||||||
|
"dev": "deno test --watch mod.ts"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
create_file(
|
||||||
|
&dir,
|
||||||
|
"main.ts",
|
||||||
|
r#"export function add(a: number, b: number): number {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Learn more at https://deno.land/manual/examples/module_metadata#concepts
|
||||||
|
if (import.meta.main) {
|
||||||
|
console.log("Add 2 + 3 =", add(2, 3));
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
create_file(
|
||||||
|
&dir,
|
||||||
|
"main_test.ts",
|
||||||
|
r#"import { assertEquals } from "jsr:@std/assert";
|
||||||
|
import { add } from "./main.ts";
|
||||||
|
|
||||||
|
Deno.test(function addTest() {
|
||||||
|
assertEquals(add(2, 3), 5);
|
||||||
|
});
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
create_json_file(
|
||||||
|
&dir,
|
||||||
|
"deno.json",
|
||||||
|
&json!({
|
||||||
|
"tasks": {
|
||||||
|
"dev": "deno run --watch main.ts"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("✅ {}", colors::green("Project initialized"));
|
||||||
|
info!("");
|
||||||
|
info!("{}", colors::gray("Run these commands to get started"));
|
||||||
|
info!("");
|
||||||
|
if let Some(dir) = init_flags.dir {
|
||||||
|
info!(" cd {}", dir);
|
||||||
|
info!("");
|
||||||
|
}
|
||||||
|
if init_flags.lib {
|
||||||
|
info!(" {}", colors::gray("# Run the tests"));
|
||||||
|
info!(" deno test");
|
||||||
|
info!("");
|
||||||
|
info!(
|
||||||
|
" {}",
|
||||||
|
colors::gray("# Run the tests and watch for file changes")
|
||||||
|
);
|
||||||
|
info!(" deno task dev");
|
||||||
|
info!("");
|
||||||
|
info!(" {}", colors::gray("# Publish to JSR (dry run)"));
|
||||||
|
info!(" deno publish --dry-run");
|
||||||
|
} else {
|
||||||
|
info!(" {}", colors::gray("# Run the program"));
|
||||||
|
info!(" deno run main.ts");
|
||||||
|
info!("");
|
||||||
|
info!(
|
||||||
|
" {}",
|
||||||
|
colors::gray("# Run the program and watch for file changes")
|
||||||
|
);
|
||||||
|
info!(" deno task dev");
|
||||||
|
info!("");
|
||||||
|
info!(" {}", colors::gray("# Run the tests"));
|
||||||
|
info!(" deno test");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_json_file(
|
||||||
|
dir: &Path,
|
||||||
|
filename: &str,
|
||||||
|
value: &deno_core::serde_json::Value,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
let mut text = deno_core::serde_json::to_string_pretty(value)?;
|
||||||
|
text.push('\n');
|
||||||
|
create_file(dir, filename, &text)
|
||||||
|
}
|
||||||
|
|
||||||
fn create_file(
|
fn create_file(
|
||||||
dir: &Path,
|
dir: &Path,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
|
@ -30,46 +165,3 @@ fn create_file(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_project(init_flags: InitFlags) -> Result<(), AnyError> {
|
|
||||||
let cwd =
|
|
||||||
std::env::current_dir().context("Can't read current working directory.")?;
|
|
||||||
let dir = if let Some(dir) = &init_flags.dir {
|
|
||||||
let dir = cwd.join(dir);
|
|
||||||
std::fs::create_dir_all(&dir)?;
|
|
||||||
dir
|
|
||||||
} else {
|
|
||||||
cwd
|
|
||||||
};
|
|
||||||
|
|
||||||
let main_ts = include_str!("./templates/main.ts");
|
|
||||||
create_file(&dir, "main.ts", main_ts)?;
|
|
||||||
|
|
||||||
create_file(
|
|
||||||
&dir,
|
|
||||||
"main_test.ts",
|
|
||||||
include_str!("./templates/main_test.ts"),
|
|
||||||
)?;
|
|
||||||
create_file(&dir, "deno.json", include_str!("./templates/deno.json"))?;
|
|
||||||
|
|
||||||
info!("✅ {}", colors::green("Project initialized"));
|
|
||||||
info!("");
|
|
||||||
info!("{}", colors::gray("Run these commands to get started"));
|
|
||||||
info!("");
|
|
||||||
if let Some(dir) = init_flags.dir {
|
|
||||||
info!(" cd {}", dir);
|
|
||||||
info!("");
|
|
||||||
}
|
|
||||||
info!(" {}", colors::gray("# Run the program"));
|
|
||||||
info!(" deno run main.ts");
|
|
||||||
info!("");
|
|
||||||
info!(
|
|
||||||
" {}",
|
|
||||||
colors::gray("# Run the program and watch for file changes")
|
|
||||||
);
|
|
||||||
info!(" deno task dev");
|
|
||||||
info!("");
|
|
||||||
info!(" {}", colors::gray("# Run the tests"));
|
|
||||||
info!(" deno test");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"tasks": {
|
|
||||||
"dev": "deno run --watch main.ts"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
export function add(a: number, b: number): number {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Learn more at https://deno.land/manual/examples/module_metadata#concepts
|
|
||||||
if (import.meta.main) {
|
|
||||||
console.log("Add 2 + 3 =", add(2, 3));
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import { assertEquals } from "jsr:@std/assert";
|
|
||||||
import { add } from "./main.ts";
|
|
||||||
|
|
||||||
Deno.test(function addTest() {
|
|
||||||
assertEquals(add(2, 3), 5);
|
|
||||||
});
|
|
16
tests/specs/init/lib/__test__.jsonc
Normal file
16
tests/specs/init/lib/__test__.jsonc
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"steps": [{
|
||||||
|
"args": "init --lib project",
|
||||||
|
"output": "init.out"
|
||||||
|
}, {
|
||||||
|
"cwd": "project",
|
||||||
|
"args": "test",
|
||||||
|
"output": "test.out"
|
||||||
|
}, {
|
||||||
|
"cwd": "project",
|
||||||
|
"args": "publish --dry-run",
|
||||||
|
"output": "dry_publish.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}]
|
||||||
|
}
|
7
tests/specs/init/lib/dry_publish.out
Normal file
7
tests/specs/init/lib/dry_publish.out
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Check file:///[WILDLINE]/mod.ts
|
||||||
|
Checking for slow types in the public API...
|
||||||
|
Check file:///[WILDLINE]/mod.ts
|
||||||
|
error: Failed preparing 'project'.
|
||||||
|
|
||||||
|
Caused by:
|
||||||
|
Invalid package name, use '@<scope_name>/<package_name> format
|
14
tests/specs/init/lib/init.out
Normal file
14
tests/specs/init/lib/init.out
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
✅ Project initialized
|
||||||
|
|
||||||
|
Run these commands to get started
|
||||||
|
|
||||||
|
cd project
|
||||||
|
|
||||||
|
# Run the tests
|
||||||
|
deno test
|
||||||
|
|
||||||
|
# Run the tests and watch for file changes
|
||||||
|
deno task dev
|
||||||
|
|
||||||
|
# Publish to JSR (dry run)
|
||||||
|
deno publish --dry-run
|
14
tests/specs/init/lib/test.out
Normal file
14
tests/specs/init/lib/test.out
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/meta.json
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/0.220.1_meta.json
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/0.220.1/mod.ts
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/0.220.1/assert_equals.ts
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/0.220.1/assert.ts
|
||||||
|
Download http://127.0.0.1:4250/@std/assert/0.220.1/fail.ts
|
||||||
|
[UNORDERED_END]
|
||||||
|
Check file:///[WILDLINE]/mod_test.ts
|
||||||
|
running 1 test from ./mod_test.ts
|
||||||
|
addTest ... ok ([WILDLINE])
|
||||||
|
|
||||||
|
ok | 1 passed | 0 failed ([WILDLINE])
|
||||||
|
|
Loading…
Reference in a new issue