Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expr #1775

Merged
merged 26 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ members = [
"fastn-lang",
"foo",
"fastn-ds",
"fastn-update",
"fastn-update", "fastn-expr",
# "fastn-wasm",
# "fastn-runtime",
]
Expand Down Expand Up @@ -93,6 +93,7 @@ fastn-package = { path = "fastn-package" }
fastn-runtime = { path = "fastn-runtime" }
fastn-wasm = { path = "fastn-wasm" }
fastn-grammar = { path = "fastn-grammar" }
fastn-expr = { path = "fastn-expr" }
fluent = "0.16"
format_num = "0.1"
ftd = { path = "ftd" }
Expand Down
1 change: 1 addition & 0 deletions fastn-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ uuid.workspace = true
validator.workspace = true
zxcvbn.workspace = true
zip.workspace = true
fastn-expr.workspace = true

[dev-dependencies]
fbt-lib.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions fastn-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ pub enum Error {
#[error("FTDP1Error: {}", _0)]
FTDP1Error(#[from] ftd::p1::Error),

#[error("FTDInterpolationError: {}", _0)]
FTDInterpolationError(#[from] fastn_expr::interpolator::InterpolationError),

#[error("FTDAstError: {}", _0)]
FTDAstError(#[from] ftd::ast::Error),

Expand Down
70 changes: 55 additions & 15 deletions fastn-core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1091,21 +1091,12 @@ pub(crate) async fn interpolate_env_vars(

let key = captures.get(1).unwrap().as_str().trim();

let value = match key {
key if key.starts_with("env.") => {
let env_key = key.trim_start_matches("env.");
ds.env(env_key).await.map_err(|e| {
fastn_core::error::Error::generic(format!(
"Failed to interpolate environment variable '{}' in endpoint.: {e}",
env_key
))
})?
}
_ => {
return Err(fastn_core::error::Error::generic(format!(
"Failed to interpolate unknown variable '{}' in endpoint.",
key
)))
let value = match get_interpolated_value(ds, key).await {
Ok(value) => value,
Err(e) => {
return fastn_core::generic_error(format!(
"Failed to interpolate value in endpoint: {e}"
));
}
};

Expand All @@ -1117,3 +1108,52 @@ pub(crate) async fn interpolate_env_vars(
result.push_str(&endpoint[last_end..]);
Ok(result)
}

async fn get_interpolated_value(
ds: &fastn_ds::DocumentStore,
input: &str,
) -> fastn_core::Result<String> {
let value = match fastn_expr::interpolator::get_var_name_and_default(input)? {
(Some(var_name), default_value) => match var_name {
key if key.starts_with("env.") => {
let env_key = key.trim_start_matches("env.");

get_env_value_or_default(ds, env_key, default_value).await?
}
_ => {
return Err(fastn_core::error::Error::generic(format!(
"unknown variable '{}'.",
input,
)))
}
},
(None, Some(default_value)) => default_value,
_ => {
return Err(fastn_core::error::Error::generic(
"unsupported interpolation syntax used.".to_string(),
))
}
};

Ok(value)
}

async fn get_env_value_or_default(
ds: &fastn_ds::DocumentStore,
env_key: &str,
default_value: Option<String>,
) -> fastn_core::Result<String> {
match ds.env(env_key).await {
Ok(value) => Ok(value),
Err(e) => {
if let Some(default_value) = default_value {
Ok(default_value)
} else {
Err(fastn_core::error::Error::generic(format!(
"could not find environment variable '{}': {e}",
env_key
)))
}
}
}
}
2 changes: 1 addition & 1 deletion fastn-core/tests/19-offline-build/output/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion fastn-core/tests/21-http-endpoint/cmd.p1
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ output: .build
Updated package dependency.
Processing fastn-stack.github.io/http-endpoint-test/manifest.json ... done in <omitted>
Processing fastn-stack.github.io/http-endpoint-test/FASTN/ ... done in <omitted>
Processing fastn-stack.github.io/http-endpoint-test/ ... done in <omitted>
Processing fastn-stack.github.io/http-endpoint-test/ ... calling `http` processor with url: http://reqres.in/api/users/2
done in <omitted>
1 change: 1 addition & 0 deletions fastn-core/tests/21-http-endpoint/input/FASTN.ftd
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
-- fastn.url-mappings:

/api/* -> http+proxy://${env.REQRES}/api/*
/api/v2/* -> http+proxy://${env.EXAMPLE or "example.com"}/api/v2/*
7 changes: 6 additions & 1 deletion fastn-core/tests/21-http-endpoint/input/index.ftd
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ $processor$: pr.http
url: /api/users/2



-- display-user: $u



-- component display-user:
user u:
caption user u:

-- ftd.row:
spacing.fixed.rem: 1
Expand Down
1 change: 1 addition & 0 deletions fastn-core/tests/21-http-endpoint/output/FASTN.ftd
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
-- fastn.url-mappings:

/api/* -> http+proxy://${env.REQRES}/api/*
/api/v2/* -> http+proxy://${env.EXAMPLE or "example.com"}/api/v2/*
7 changes: 6 additions & 1 deletion fastn-core/tests/21-http-endpoint/output/index.ftd
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ $processor$: pr.http
url: /api/users/2



-- display-user: $u



-- component display-user:
user u:
caption user u:

-- ftd.row:
spacing.fixed.rem: 1
Expand Down
49 changes: 48 additions & 1 deletion fastn-core/tests/21-http-endpoint/output/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions fastn-core/tests/21-http-endpoint/output/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
"files": {
"FASTN.ftd": {
"name": "FASTN.ftd",
"checksum": "1A051A65F8DEDF8464FC2B0BC057E78D565655893F0435EE5E145EB23A667C7C",
"size": 145
"checksum": "ABE2D16D99185C27D6D576949BDC5B0E5DD95C64731873126B1033A9C0E8B4DB",
"size": 212
},
"index.ftd": {
"name": "index.ftd",
"checksum": "6010AAF5DE489BB2FDA2A46ADC560309F2C5E4A5D16E5CCC2787D6B4C60D8AE5",
"size": 424
"checksum": "C0F81A62DC5A838C286CDFE72FFD50467C99312D3A1367AFC14105941AB12BC9",
"size": 456
}
},
"zip_url": "https://codeload.github.com/fastn-stack/http-endpoint-test/zip/refs/heads/main",
"checksum": "6B712EBA21408F2619EC7EBB3B90BAE0879A4AA451F08BD9FA54F2D34159BBE0"
"checksum": "D365DD22B14D7FFB1C3D6E27AF6FD658351AB6B3F4A2ABA2E55BC63DC61898FC"
}
14 changes: 14 additions & 0 deletions fastn-expr/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "fastn-expr"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
description.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
thiserror.workspace = true
47 changes: 47 additions & 0 deletions fastn-expr/src/interpolator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#[derive(thiserror::Error, Debug)]
pub enum InterpolationError {
#[error("Failed to parse interpolation: {0}")]
FailedToParse(#[from] fastn_expr::parser::ParseError),
#[error("Failed to interpolate: {0}")]
CantInterpolate(String),
}

pub fn get_var_name_and_default(
key: &str,
) -> Result<(Option<String>, Option<String>), InterpolationError> {
let result = fastn_expr::parser::parse(key)?;

match result {
fastn_expr::parser::ExprNode::Binary(
boxed_lhs,
fastn_expr::tokenizer::Operator::Or,
boxed_rhs,
) => {
let (var_name, default_value) = match (*boxed_lhs, *boxed_rhs) {
(
fastn_expr::parser::ExprNode::Identifier(var_name),
fastn_expr::parser::ExprNode::StringLiteral(default_value),
) => (Some(var_name.clone()), Some(default_value)),
(
fastn_expr::parser::ExprNode::Identifier(var_name),
fastn_expr::parser::ExprNode::Integer(default_value),
) => (Some(var_name.clone()), Some(default_value.to_string())),
(
fastn_expr::parser::ExprNode::Identifier(var_name),
fastn_expr::parser::ExprNode::Decimal(default_value),
) => (Some(var_name.clone()), Some(default_value.to_string())),
_ => {
return Err(InterpolationError::CantInterpolate(
"Invalid expression".to_string(),
))
}
};

Ok((var_name, default_value))
}
fastn_expr::parser::ExprNode::Identifier(var_name) => Ok((Some(var_name), None)),
fastn_expr::parser::ExprNode::StringLiteral(value) => Ok((None, Some(value))),
fastn_expr::parser::ExprNode::Integer(value) => Ok((None, Some(value.to_string()))),
fastn_expr::parser::ExprNode::Decimal(value) => Ok((None, Some(value.to_string()))),
}
}
5 changes: 5 additions & 0 deletions fastn-expr/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub extern crate self as fastn_expr;

pub mod interpolator;
pub(crate) mod parser;
pub(crate) mod tokenizer;
Loading
Loading