Skip to content

Commit

Permalink
feat(cli): improve DX by saving configuration in a local config file (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
QuiiBz authored Feb 19, 2023
1 parent f1271d4 commit 73856f5
Show file tree
Hide file tree
Showing 13 changed files with 548 additions and 474 deletions.
10 changes: 10 additions & 0 deletions .changeset/nice-cars-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@lagon/cli': minor
'@lagon/docs': minor
---

Improve functions configuration by saving parameters into a local config file.

When using `lagon dev`, `lagon build` or `lagon deploy`, you don't need anymore to specify the function's entrypoint and the public directory. These configuration are saved into a local `.lagon/config.json` file.

Note that `lagon dev` still allows to specify an entrypoint and public directory as before using arguments and options, making it easy to test locally.
33 changes: 13 additions & 20 deletions crates/cli/src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,35 @@ use std::{fs, path::PathBuf};

use anyhow::{anyhow, Result};

use crate::utils::{
bundle_function, debug, print_progress, success, validate_code_file, validate_public_dir,
};
use crate::utils::{bundle_function, debug, get_root, print_progress, success, FunctionConfig};

pub fn build(file: PathBuf, client: Option<PathBuf>, public_dir: Option<PathBuf>) -> Result<()> {
validate_code_file(&file)?;

let client = match client {
Some(client) => {
validate_code_file(&client)?;
Some(client)
}
None => None,
};

let public_dir = validate_public_dir(public_dir)?;
let (index, assets) = bundle_function(&file, &client, &public_dir)?;
pub fn build(
client: Option<PathBuf>,
public_dir: Option<PathBuf>,
directory: Option<PathBuf>,
) -> Result<()> {
let root = get_root(directory);
let function_config = FunctionConfig::load(&root, client, public_dir)?;
let (index, assets) = bundle_function(&function_config, &root)?;

let end_progress = print_progress("Writting index.js...");

fs::create_dir_all(".lagon")?;
fs::write(".lagon/index.js", index)?;
fs::create_dir_all(root.join(".lagon"))?;
fs::write(root.join(".lagon").join("index.js"), index)?;

end_progress();

for (path, content) in assets {
let message = format!("Writting {path}...");
let end_progress = print_progress(&message);

let dir = PathBuf::from(".lagon").join("public").join(
let dir = root.join(".lagon").join("public").join(
PathBuf::from(&path)
.parent()
.ok_or_else(|| anyhow!("Could not find parent of {}", path))?,
);
fs::create_dir_all(dir)?;
fs::write(format!(".lagon/public/{path}"), content)?;
fs::write(root.join(".lagon").join("public").join(path), content)?;

end_progress();
}
Expand Down
179 changes: 75 additions & 104 deletions crates/cli/src/commands/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use dialoguer::{Confirm, Input, Select};
use serde::{Deserialize, Serialize};

use crate::utils::{
create_deployment, debug, get_function_config, info, print_progress, validate_code_file,
validate_public_dir, write_function_config, Config, DeploymentConfig, TrpcClient,
create_deployment, debug, get_root, info, print_progress, Config, FunctionConfig, TrpcClient,
};

#[derive(Deserialize, Debug)]
Expand Down Expand Up @@ -54,124 +53,96 @@ impl Display for Function {
pub type FunctionsResponse = Vec<Function>;

pub async fn deploy(
file: PathBuf,
client: Option<PathBuf>,
public_dir: Option<PathBuf>,
prod: bool,
directory: Option<PathBuf>,
) -> Result<()> {
let config = Config::new()?;

if config.token.is_none() {
return Err(anyhow!(
"You are not logged in. Please login with `lagon login`",
"You are not logged in. Please log in with `lagon login`",
));
}

validate_code_file(&file)?;

let client = match client {
Some(client) => {
validate_code_file(&client)?;
Some(client)
}
None => None,
};

let public_dir = validate_public_dir(public_dir)?;
match get_function_config(&file)? {
None => {
println!("{}", debug("No deployment config found..."));
println!();

let trpc_client = TrpcClient::new(&config);
let response = trpc_client
.query::<(), OrganizationsResponse>("organizationsList", None)
.await?;
let organizations = response.result.data;

let index = Select::new().items(&organizations).default(0).interact()?;
let organization = &organizations[index];

match Confirm::new()
.with_prompt(info("Link to an existing Function?"))
.interact()?
{
true => {
let response = trpc_client
.query::<(), FunctionsResponse>("functionsList", None)
.await?;
let functions = response.result.data;

let index = Select::new().items(&functions).default(0).interact()?;
let function = &functions[index];

write_function_config(
&file,
DeploymentConfig {
function_id: function.id.clone(),
organization_id: organization.id.clone(),
let root = get_root(directory);
let mut function_config = FunctionConfig::load(&root, client, public_dir)?;

if function_config.function_id.is_empty() {
println!("{}", debug("No deployment config found..."));
println!();

let trpc_client = TrpcClient::new(&config);
let response = trpc_client
.query::<(), OrganizationsResponse>("organizationsList", None)
.await?;
let organizations = response.result.data;

let index = Select::new()
.items(&organizations)
.default(0)
.with_prompt(info("Select an Organization to deploy to"))
.interact()?;
let organization = &organizations[index];

match Confirm::new()
.with_prompt(info("Link to an existing Function?"))
.interact()?
{
true => {
let response = trpc_client
.query::<(), FunctionsResponse>("functionsList", None)
.await?;
let functions = response.result.data;

let index = Select::new()
.items(&functions)
.default(0)
.with_prompt(info("Select a Function to link from"))
.interact()?;
let function = &functions[index];

function_config.function_id = function.id.clone();
function_config.organization_id = organization.id.clone();
function_config.write(&root)?;

create_deployment(&config, &function_config, prod, &root).await?;
}
false => {
let name = Input::<String>::new()
.with_prompt(info("What is the name of this new Function?"))
.interact_text()?;

println!();
let message = format!("Creating Function {name}...");
let end_progress = print_progress(&message);

let response = trpc_client
.mutation::<CreateFunctionRequest, CreateFunctionResponse>(
"functionCreate",
CreateFunctionRequest {
name,
domains: Vec::new(),
env: Vec::new(),
cron: None,
},
)?;

create_deployment(
function.id.clone(),
&file,
&client,
&public_dir,
&config,
prod,
)
.await?;
}
false => {
let name = Input::<String>::new()
.with_prompt(info("What is the name of this new Function?"))
.interact_text()?;

println!();
let message = format!("Creating Function {name}...");
let end_progress = print_progress(&message);

let response = trpc_client
.mutation::<CreateFunctionRequest, CreateFunctionResponse>(
"functionCreate",
CreateFunctionRequest {
name,
domains: Vec::new(),
env: Vec::new(),
cron: None,
},
)
.await?;
let function = response.result.data;

end_progress();

write_function_config(
&file,
DeploymentConfig {
function_id: function.id.clone(),
organization_id: organization.id.clone(),
},
)?;
let function = response.result.data;

create_deployment(function.id, &file, &client, &public_dir, &config, prod)
.await?;
}
};
end_progress();

Ok(())
}
Some(function_config) => {
create_deployment(
function_config.function_id,
&file,
&client,
&public_dir,
&config,
prod,
)
.await
function_config.function_id = function.id.clone();
function_config.organization_id = organization.id.clone();
function_config.write(&root)?;

create_deployment(&config, &function_config, prod, &root).await?;
}
}
} else {
create_deployment(&config, &function_config, prod, &root).await?;
}

Ok(())
}
Loading

4 comments on commit 73856f5

@vercel
Copy link

@vercel vercel bot commented on 73856f5 Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

storybook – ./packages/ui

storybook-lagon.vercel.app
ui.lagon.app
storybook-swart-eight.vercel.app
storybook-git-main-lagon.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 73856f5 Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

dashboard – ./packages/dashboard

dashboard-git-main-lagon.vercel.app
dashboard-lagon.vercel.app
dash.lagon.app

@vercel
Copy link

@vercel vercel bot commented on 73856f5 Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./packages/docs

docs-lagon.vercel.app
docs.lagon.app
docs-git-main-lagon.vercel.app
lagon-docs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 73856f5 Feb 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

www – ./www

www-lagon.vercel.app
www-git-main-lagon.vercel.app
lagon.dev
lagon.app

Please sign in to comment.