Skip to content

Commit

Permalink
Feat: ftd.app_mounts variable in js output
Browse files Browse the repository at this point in the history
This variable is used to support the optional second parameter (app) in
`ftd.app-path` function.

The `ftd.app-path` function now takes a second optional arg. This arg is
used to construct app paths for any app that is mounted using
`fastn.app` in FASTN.ftd.
  • Loading branch information
siddhantk232 committed Jan 31, 2025
1 parent 87a5e6a commit 4088c59
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 30 deletions.
46 changes: 46 additions & 0 deletions fastn-builtins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,52 @@ pub fn default_bag() -> indexmap::IndexMap<String, fastn_resolved::Definition> {
external_implementation: true
})
),
(
"ftd#app-path-ex".to_string(),
fastn_resolved::Definition::Function(fastn_resolved::Function {
name: "ftd#app-path-ex".to_string(),
return_kind: fastn_resolved::KindData {
kind: fastn_resolved::Kind::string(),
caption: false,
body: false,
},
arguments: vec![
fastn_resolved::Argument {
name: "path".to_string(),
kind: fastn_resolved::KindData {
kind: fastn_resolved::Kind::string(),
caption: false,
body: false,
},
mutable: false,
value: None,
access_modifier: Default::default(),
line_number: 0,
},
fastn_resolved::Argument {
name: "app".to_string(),
kind: fastn_resolved::KindData {
kind: fastn_resolved::Kind::string(),
caption: false,
body: false,
},
mutable: false,
value: None,
access_modifier: Default::default(),
line_number: 0,
},
],
expression: vec![
fastn_resolved::FunctionExpression {
expression: "ftd.app_path_ex(path, app)".to_string(),
line_number: 0,
}
],
js: None,
line_number: 0,
external_implementation: true
})
),
(
"ftd#set-bool".to_string(),
fastn_resolved::Definition::Function(fastn_resolved::Function {
Expand Down
9 changes: 5 additions & 4 deletions fastn-core/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ fn cached_parse(
}

pub fn package_dependent_builtins(
pkg: &fastn_core::Package,
config: &fastn_core::Config,
req_path: &str,
) -> ftd::interpreter::HostBuiltins {
[
fastn_core::host_builtins::app_path(pkg, req_path),
fastn_core::host_builtins::main_package(pkg),
fastn_core::host_builtins::app_path(config, req_path),
fastn_core::host_builtins::main_package(config),
fastn_core::host_builtins::app_mounts(config),
]
}

Expand All @@ -47,7 +48,7 @@ pub async fn interpret_helper(
) -> ftd::interpreter::Result<ftd::interpreter::Document> {
let doc = cached_parse(name, source, line_number)?;

let builtin_overrides = package_dependent_builtins(&lib.config.package, lib.request.path());
let builtin_overrides = package_dependent_builtins(&lib.config, lib.request.path());
let mut s = ftd::interpreter::interpret_with_line_number(name, doc, Some(builtin_overrides))?;
lib.module_package_map.insert(
name.trim_matches('/').to_string(),
Expand Down
84 changes: 66 additions & 18 deletions fastn-core/src/host_builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@
///
/// Visiting `/app/` in browser should render /app/test/
#[inline]
pub fn app_path(pkg: &fastn_core::Package, req_path: &str) -> (String, fastn_resolved::Definition) {
let prefix = pkg
pub fn app_path(
config: &fastn_core::Config,
req_path: &str,
) -> (String, fastn_resolved::Definition) {
let app_system_name = config
.package
.apps
.iter()
.find(|a| req_path.starts_with(&a.mount_point))
.map(|a| a.mount_point.clone())
.and_then(|a| a.package.system.clone())
.unwrap_or_default();
let prefix = prefix.trim_end_matches('/');

let name = "ftd#app-path".to_string();
let def = fastn_resolved::Definition::Function(fastn_resolved::Function {
Expand All @@ -39,20 +42,36 @@ pub fn app_path(pkg: &fastn_core::Package, req_path: &str) -> (String, fastn_res
caption: false,
body: false,
},
arguments: vec![fastn_resolved::Argument {
name: "path".to_string(),
kind: fastn_resolved::KindData {
kind: fastn_resolved::Kind::string(),
caption: false,
body: false,
arguments: vec![
fastn_resolved::Argument {
name: "path".to_string(),
kind: fastn_resolved::KindData {
kind: fastn_resolved::Kind::string(),
caption: false,
body: false,
},
mutable: false,
value: None,
access_modifier: Default::default(),
line_number: 0,
},
mutable: false,
value: None,
access_modifier: Default::default(),
line_number: 0,
}],
fastn_resolved::Argument {
name: "app".to_string(),
kind: fastn_resolved::KindData::new(fastn_resolved::Kind::string()),
mutable: false,
value: Some(fastn_resolved::PropertyValue::Value {
value: fastn_resolved::Value::String {
text: app_system_name,
},
is_mutable: false,
line_number: 0,
}),
access_modifier: Default::default(),
line_number: 0,
},
],
expression: vec![fastn_resolved::FunctionExpression {
expression: format!("\"{}\" + path", prefix),
expression: "ftd.app_path_ex(path, app)".to_string(),
line_number: 0,
}],
js: None,
Expand All @@ -67,14 +86,14 @@ pub fn app_path(pkg: &fastn_core::Package, req_path: &str) -> (String, fastn_res
///
/// Useful to determine if the package is run standalone or as a dependency:
#[inline]
pub fn main_package(pkg: &fastn_core::Package) -> (String, fastn_resolved::Definition) {
pub fn main_package(config: &fastn_core::Config) -> (String, fastn_resolved::Definition) {
let name = "ftd#main-package".to_string();
let def = fastn_resolved::Definition::Variable(fastn_resolved::Variable {
name: name.clone(),
kind: fastn_resolved::Kind::string().into_kind_data(),
value: fastn_resolved::PropertyValue::Value {
value: fastn_resolved::Value::String {
text: pkg.name.clone(),
text: config.package.name.clone(),
},
is_mutable: false,
line_number: 0,
Expand All @@ -85,6 +104,35 @@ pub fn main_package(pkg: &fastn_core::Package) -> (String, fastn_resolved::Defin
line_number: 0,
});

(name, def)
}

/// Ftd string variable that holds the `fastn.app` mounts
///
/// Used by `ftd.app-path` to determine the mountpoint of the app
#[inline]
pub fn app_mounts(config: &fastn_core::Config) -> (String, fastn_resolved::Definition) {
let name = "ftd#app-mounts".to_string();
let variants = config
.app_mounts()
.unwrap_or_default()
.into_iter()
.map(|(k, v)| {
fastn_resolved::OrTypeVariant::Constant(fastn_resolved::Field::new(
&k,
fastn_resolved::Kind::string().into_kind_data().caption(),
false,
Some(fastn_resolved::Value::new_string(&v).into_property_value(false, 0)),
0,
))
})
.collect();

let def = fastn_resolved::Definition::OrType(fastn_resolved::OrType {
name: name.clone(),
line_number: 0,
variants,
});

(name, def)
}
17 changes: 17 additions & 0 deletions fastn-js/js/ftd.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ const ftd = (function () {
);
};

exports.app_path_ex = (path, app) => {
if (path instanceof fastn.mutableClass)
path = fastn_utils.getStaticValue(path);
if (app instanceof fastn.mutableClass)
app = fastn_utils.getStaticValue(app);

app = app.replaceAll("-", "_");

let prefix = ftd.app_mounts.get(app)?.get() || "";

if (prefix.length > 0 && prefix.charAt(prefix.length - 1) === '/') {
prefix = prefix.substring(0, prefix.length - 1);
}

return prefix + path;
};

// Todo: Implement this (Remove highlighter)
exports.clean_code = (args) => args.a;

Expand Down
2 changes: 1 addition & 1 deletion ftd/src/interpreter/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ftd::interpreter::{ComponentExt, VariableExt};


/// Array with the size of how many builtins are provided by the host
pub type HostBuiltins = [(String, fastn_resolved::Definition); 2];
pub type HostBuiltins = [(String, fastn_resolved::Definition); 3];

/// The `InterpreterState` struct is a representation of the state of an interpreter. It contains
/// information about the interpreter's current state and its progress through the code being
Expand Down
17 changes: 10 additions & 7 deletions ftd/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub fn default_bag_into_js_ast() -> Vec<fastn_js::Ast> {
ftd_asts
}

const IGNORE_GLOBAL: [&str; 2] = ["ftd#main-package", "ftd#app-mounts"];

#[derive(Debug)]
pub struct JSAstData {
/// This contains asts of things (other than `ftd`) and instructions/tree
Expand Down Expand Up @@ -109,17 +111,13 @@ pub fn document_into_js_ast(document: ftd::interpreter::Document) -> JSAstData {
if let ftd::interpreter::Thing::Component(c) = thing {
document_asts.push(c.to_ast(&doc, &mut has_rive_components));
} else if let ftd::interpreter::Thing::Variable(v) = thing {
let prefix = if v.name == "ftd#main-package" {
let prefix = if IGNORE_GLOBAL.contains(&v.name.as_str()) {
None
} else {
Some(fastn_js::GLOBAL_VARIABLE_MAP.to_string())
};

document_asts.push(v.to_ast(
&doc,
prefix,
&mut has_rive_components,
));
document_asts.push(v.to_ast(&doc, prefix, &mut has_rive_components));
} else if let ftd::interpreter::Thing::WebComponent(web_component) = thing {
document_asts.push(web_component.to_ast(&doc));
} else if let ftd::interpreter::Thing::Function(f) = thing {
Expand Down Expand Up @@ -151,13 +149,18 @@ pub fn document_into_js_ast(document: ftd::interpreter::Document) -> JSAstData {
));
}
}
let prefix = if IGNORE_GLOBAL.contains(&ot.name.as_str()) {
None
} else {
Some(fastn_js::GLOBAL_VARIABLE_MAP.to_string())
};
document_asts.push(fastn_js::Ast::OrType(fastn_js::OrType {
name: ot.name.clone(),
variant: fastn_js::SetPropertyValue::Value(fastn_js::Value::Record {
fields,
other_references: vec![],
}),
prefix: Some(fastn_js::GLOBAL_VARIABLE_MAP.to_string()),
prefix,
}));
}
}
Expand Down

0 comments on commit 4088c59

Please sign in to comment.