summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormuddlebee <anweshknayak@gmail.com>2024-07-10 06:43:34 +0530
committerGitHub <noreply@github.com>2024-07-09 21:13:34 -0400
commitff5163af05d95409cbb3d1a13f49a43fefd4849a (patch)
tree1b441f411224a0f45177beb77ba7822505cc8166
parent9776a13e33bc371a67f0d44925e2bf04dca159f1 (diff)
feat(cli): `deno init --lib` (#22499)
Closes #22287 Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com> Co-authored-by: David Sherret <dsherret@gmail.com>
-rw-r--r--cli/args/flags.rs54
-rw-r--r--cli/tools/init/mod.rs176
-rw-r--r--cli/tools/init/templates/deno.json5
-rw-r--r--cli/tools/init/templates/main.ts8
-rw-r--r--cli/tools/init/templates/main_test.ts6
-rw-r--r--tests/specs/init/lib/__test__.jsonc16
-rw-r--r--tests/specs/init/lib/dry_publish.out7
-rw-r--r--tests/specs/init/lib/init.out14
-rw-r--r--tests/specs/init/lib/test.out14
9 files changed, 232 insertions, 68 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 89f53d593..d2321f32e 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -205,6 +205,7 @@ impl FmtFlags {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InitFlags {
pub dir: Option<String>,
+ pub lib: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -2052,11 +2053,18 @@ fn init_subcommand() -> Command {
Command::new("init")
.about("Initialize a new project")
.defer(|cmd| {
- cmd.arg(
- Arg::new("dir")
- .required(false)
- .value_hint(ValueHint::DirPath),
- )
+ cmd
+ .arg(
+ Arg::new("dir")
+ .required(false)
+ .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) {
flags.subcommand = DenoSubcommand::Init(InitFlags {
dir: matches.remove_one::<String>("dir"),
+ lib: matches.get_flag("lib"),
});
}
@@ -9753,7 +9762,10 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Init(InitFlags { dir: None }),
+ subcommand: DenoSubcommand::Init(InitFlags {
+ dir: None,
+ lib: false
+ }),
..Flags::default()
}
);
@@ -9764,6 +9776,7 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Init(InitFlags {
dir: Some(String::from("foo")),
+ lib: false
}),
..Flags::default()
}
@@ -9773,11 +9786,38 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Init(InitFlags { dir: None }),
+ subcommand: DenoSubcommand::Init(InitFlags {
+ dir: None,
+ lib: false
+ }),
log_level: Some(Level::Error),
..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]
diff --git a/cli/tools/init/mod.rs b/cli/tools/init/mod.rs
index fb2e6e7af..23b14e17c 100644
--- a/cli/tools/init/mod.rs
+++ b/cli/tools/init/mod.rs
@@ -4,33 +4,11 @@ use crate::args::InitFlags;
use crate::colors;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
+use deno_core::serde_json::json;
use log::info;
use std::io::Write;
use std::path::Path;
-fn create_file(
- dir: &Path,
- filename: &str,
- content: &str,
-) -> Result<(), AnyError> {
- let path = dir.join(filename);
- if path.exists() {
- info!(
- "ℹ️ {}",
- colors::gray(format!("Skipped creating {filename} as it already exists"))
- );
- Ok(())
- } else {
- let mut file = std::fs::OpenOptions::new()
- .write(true)
- .create_new(true)
- .open(path)
- .with_context(|| format!("Failed to create {filename} file"))?;
- file.write_all(content.as_bytes())?;
- Ok(())
- }
-}
-
pub fn init_project(init_flags: InitFlags) -> Result<(), AnyError> {
let cwd =
std::env::current_dir().context("Can't read current working directory.")?;
@@ -42,15 +20,82 @@ pub fn init_project(init_flags: InitFlags) -> Result<(), AnyError> {
cwd
};
- let main_ts = include_str!("./templates/main.ts");
- create_file(&dir, "main.ts", main_ts)?;
+ 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";
- create_file(
- &dir,
- "main_test.ts",
- include_str!("./templates/main_test.ts"),
- )?;
- create_file(&dir, "deno.json", include_str!("./templates/deno.json"))?;
+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!("");
@@ -60,16 +105,63 @@ pub fn init_project(init_flags: InitFlags) -> Result<(), AnyError> {
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");
+ 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(
+ dir: &Path,
+ filename: &str,
+ content: &str,
+) -> Result<(), AnyError> {
+ let path = dir.join(filename);
+ if path.exists() {
+ info!(
+ "ℹ️ {}",
+ colors::gray(format!("Skipped creating {filename} as it already exists"))
+ );
+ Ok(())
+ } else {
+ let mut file = std::fs::OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(path)
+ .with_context(|| format!("Failed to create {filename} file"))?;
+ file.write_all(content.as_bytes())?;
+ Ok(())
+ }
+}
diff --git a/cli/tools/init/templates/deno.json b/cli/tools/init/templates/deno.json
deleted file mode 100644
index 3c5130f1d..000000000
--- a/cli/tools/init/templates/deno.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "tasks": {
- "dev": "deno run --watch main.ts"
- }
-}
diff --git a/cli/tools/init/templates/main.ts b/cli/tools/init/templates/main.ts
deleted file mode 100644
index be043e97c..000000000
--- a/cli/tools/init/templates/main.ts
+++ /dev/null
@@ -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));
-}
diff --git a/cli/tools/init/templates/main_test.ts b/cli/tools/init/templates/main_test.ts
deleted file mode 100644
index 26af2582b..000000000
--- a/cli/tools/init/templates/main_test.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { assertEquals } from "jsr:@std/assert";
-import { add } from "./main.ts";
-
-Deno.test(function addTest() {
- assertEquals(add(2, 3), 5);
-});
diff --git a/tests/specs/init/lib/__test__.jsonc b/tests/specs/init/lib/__test__.jsonc
new file mode 100644
index 000000000..076930ae6
--- /dev/null
+++ b/tests/specs/init/lib/__test__.jsonc
@@ -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
+ }]
+}
diff --git a/tests/specs/init/lib/dry_publish.out b/tests/specs/init/lib/dry_publish.out
new file mode 100644
index 000000000..31f91c38d
--- /dev/null
+++ b/tests/specs/init/lib/dry_publish.out
@@ -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
diff --git a/tests/specs/init/lib/init.out b/tests/specs/init/lib/init.out
new file mode 100644
index 000000000..0f1a83f30
--- /dev/null
+++ b/tests/specs/init/lib/init.out
@@ -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
diff --git a/tests/specs/init/lib/test.out b/tests/specs/init/lib/test.out
new file mode 100644
index 000000000..0b225a52b
--- /dev/null
+++ b/tests/specs/init/lib/test.out
@@ -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])
+