Skip to content

Commit 80d4748

Browse files
Merge pull request #292 from code0-tech/#291-development-flow
development flow
2 parents ff641e0 + 23e54eb commit 80d4748

10 files changed

Lines changed: 215 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/taurus-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition.workspace = true
55

66
[dependencies]
77
tucana = { workspace = true }
8+
code0-flow = { workspace = true, features = ["flow_config"] }
89
base64 = { workspace = true }
910
rand = { workspace = true }
1011
log = { workspace = true }

crates/taurus-core/src/export.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ fn write(module: &Module, dir: &Path) -> io::Result<()> {
3232
&module.definition_data_types,
3333
|dt| &dt.identifier,
3434
)?;
35+
write_each(&dir.join("flow_types"), &module.flow_types, |ft| {
36+
&ft.identifier
37+
})?;
38+
write_each(
39+
&dir.join("runtime_flow_types"),
40+
&module.runtime_flow_types,
41+
|ft| &ft.identifier,
42+
)?;
3543
write_each(&dir.join("functions"), &module.function_definitions, |f| {
3644
&f.runtime_name
3745
})?;

crates/taurus-core/src/meta.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,26 @@ pub struct ModuleMeta {
5454
pub author: &'static str,
5555
pub icon: &'static str,
5656
pub version: &'static str,
57+
/// Only built by [`crate::registry::build_modules`] while Taurus is
58+
/// running with `ENVIRONMENT=development` (the default) -- lets a module
59+
/// still under development self-register without shipping to staging or
60+
/// production.
61+
pub dev_only: bool,
62+
}
63+
64+
pub struct FlowTypeMeta {
65+
pub identifier: &'static str,
66+
/// Identifier of the [`ModuleMeta`] this flow type belongs to.
67+
pub module: &'static str,
68+
pub name: Vec<Translation>,
69+
pub description: Vec<Translation>,
70+
pub documentation: Vec<Translation>,
71+
pub display_message: Vec<Translation>,
72+
pub alias: Vec<Translation>,
73+
pub editable: bool,
74+
pub display_icon: Option<&'static str>,
75+
pub linked_data_type_identifiers: Vec<&'static str>,
76+
pub signature: &'static str,
5777
}
5878

5979
pub struct MetaRegistration(pub fn() -> RuntimeFunctionMeta);
@@ -62,5 +82,8 @@ inventory::collect!(MetaRegistration);
6282
pub struct DataTypeRegistration(pub fn() -> DataTypeMeta);
6383
inventory::collect!(DataTypeRegistration);
6484

85+
pub struct FlowTypeRegistration(pub fn() -> FlowTypeMeta);
86+
inventory::collect!(FlowTypeRegistration);
87+
6588
pub struct ModuleRegistration(pub fn() -> ModuleMeta);
6689
inventory::collect!(ModuleRegistration);

crates/taurus-core/src/registry.rs

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,51 @@
44
//! the result anywhere (Aquila, a file, ...) is a transport concern that
55
//! belongs to the caller.
66
7+
use std::collections::HashSet;
8+
9+
use code0_flow::flow_config::env_with_default;
10+
use code0_flow::flow_config::environment::Environment;
11+
712
use crate::meta::{
8-
DataTypeMeta, DataTypeRegistration, MetaRegistration, ModuleMeta, ModuleRegistration,
9-
RuntimeFunctionMeta,
13+
DataTypeMeta, DataTypeRegistration, FlowTypeMeta, FlowTypeRegistration, MetaRegistration,
14+
ModuleMeta, ModuleRegistration, RuntimeFunctionMeta,
1015
};
1116
use tucana::shared::{
12-
DefinitionDataType, FunctionDefinition, Module, ParameterDefinition, RuntimeFunctionDefinition,
13-
RuntimeParameterDefinition,
17+
DefinitionDataType, FlowType, FunctionDefinition, Module, ParameterDefinition,
18+
RuntimeFlowType, RuntimeFunctionDefinition, RuntimeParameterDefinition,
1419
};
1520

16-
/// Builds every registered module, complete with its function and data-type
17-
/// definitions. Panics if a function or data type declares a `module` that
21+
/// Builds every registered module, complete with its function, data-type and
22+
/// flow-type definitions. Skips modules declared `dev_only` unless Taurus is
23+
/// running with `ENVIRONMENT=development` (the default), along with anything
24+
/// that declares one of those modules as its owner.
25+
///
26+
/// Panics if a function, data type, or flow type declares a `module` that
1827
/// has no matching `taurus_macros::module!` registration -- a broken link
1928
/// between a handler and its owning module is a programming error, not a
20-
/// runtime condition to recover from.
29+
/// runtime condition to recover from. This does not apply to modules that
30+
/// were themselves excluded for being `dev_only`.
2131
pub fn build_modules() -> Vec<Module> {
32+
let is_dev = env_with_default("ENVIRONMENT", Environment::Development) == Environment::Development;
33+
34+
let mut excluded: HashSet<&'static str> = HashSet::new();
2235
let mut modules: Vec<Module> = inventory::iter::<ModuleRegistration>()
23-
.map(|reg| module_from_meta((reg.0)()))
36+
.map(|reg| (reg.0)())
37+
.filter_map(|meta| {
38+
if meta.dev_only && !is_dev {
39+
excluded.insert(meta.identifier);
40+
None
41+
} else {
42+
Some(module_from_meta(meta))
43+
}
44+
})
2445
.collect();
2546

2647
for reg in inventory::iter::<MetaRegistration>() {
2748
let meta = (reg.0)();
49+
if excluded.contains(meta.module) {
50+
continue;
51+
}
2852
let module = find_module(&mut modules, meta.module, meta.identifier);
2953
let version = module.version.clone();
3054
module
@@ -37,13 +61,29 @@ pub fn build_modules() -> Vec<Module> {
3761

3862
for reg in inventory::iter::<DataTypeRegistration>() {
3963
let meta = (reg.0)();
64+
if excluded.contains(meta.module) {
65+
continue;
66+
}
4067
let module = find_module(&mut modules, meta.module, meta.identifier);
4168
let version = module.version.clone();
4269
module
4370
.definition_data_types
4471
.push(data_type_definition(&meta, version));
4572
}
4673

74+
for reg in inventory::iter::<FlowTypeRegistration>() {
75+
let meta = (reg.0)();
76+
if excluded.contains(meta.module) {
77+
continue;
78+
}
79+
let module = find_module(&mut modules, meta.module, meta.identifier);
80+
let version = module.version.clone();
81+
module
82+
.runtime_flow_types
83+
.push(runtime_flow_type_definition(&meta, version.clone()));
84+
module.flow_types.push(flow_type_definition(&meta, version));
85+
}
86+
4787
modules
4888
}
4989

@@ -148,6 +188,51 @@ fn function_definition(meta: &RuntimeFunctionMeta, version: String) -> FunctionD
148188
}
149189
}
150190

191+
fn flow_type_definition(meta: &FlowTypeMeta, version: String) -> FlowType {
192+
FlowType {
193+
identifier: meta.identifier.to_string(),
194+
settings: Vec::new(),
195+
editable: meta.editable,
196+
name: meta.name.clone(),
197+
description: meta.description.clone(),
198+
documentation: meta.documentation.clone(),
199+
display_message: meta.display_message.clone(),
200+
alias: meta.alias.clone(),
201+
version,
202+
display_icon: meta.display_icon.unwrap_or_default().to_string(),
203+
definition_source: None,
204+
linked_data_type_identifiers: meta
205+
.linked_data_type_identifiers
206+
.iter()
207+
.map(|s| s.to_string())
208+
.collect(),
209+
signature: meta.signature.to_string(),
210+
runtime_identifier: meta.identifier.to_string(),
211+
}
212+
}
213+
214+
fn runtime_flow_type_definition(meta: &FlowTypeMeta, version: String) -> RuntimeFlowType {
215+
RuntimeFlowType {
216+
identifier: meta.identifier.to_string(),
217+
runtime_settings: Vec::new(),
218+
editable: meta.editable,
219+
name: meta.name.clone(),
220+
description: meta.description.clone(),
221+
documentation: meta.documentation.clone(),
222+
display_message: meta.display_message.clone(),
223+
alias: meta.alias.clone(),
224+
version,
225+
display_icon: meta.display_icon.unwrap_or_default().to_string(),
226+
definition_source: None,
227+
linked_data_type_identifiers: meta
228+
.linked_data_type_identifiers
229+
.iter()
230+
.map(|s| s.to_string())
231+
.collect(),
232+
signature: meta.signature.to_string(),
233+
}
234+
}
235+
151236
fn data_type_definition(meta: &DataTypeMeta, version: String) -> DefinitionDataType {
152237
DefinitionDataType {
153238
identifier: meta.identifier.to_string(),
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Development-only module for exercising flow-type features end-to-end
2+
//! without touching a real domain module. Only registered while Taurus runs
3+
//! with `ENVIRONMENT=development` (the default) -- see `dev_only` on
4+
//! `taurus_macros::module!`.
5+
6+
taurus_macros::module! {
7+
identifier = "taurus-dev",
8+
name(en_US = "Development"),
9+
description(en_US = "Development-only flow types and definitions, not shipped to staging or production."),
10+
documentation = "",
11+
author = "CodeZero",
12+
icon = "tabler:test-pipe",
13+
version = "0.0.1",
14+
dev_only,
15+
}
16+
17+
taurus_macros::flow_type! {
18+
identifier = "MANUAL",
19+
module = "taurus-dev",
20+
signature = "(): void",
21+
name(en_US = "Manual"),
22+
description(en_US = "A flow started manually, with no configurable settings."),
23+
display_message(en_US = "Manual"),
24+
alias(en_US = "manual;trigger;dev;test"),
25+
display_icon = "tabler:test-pipe",
26+
}

crates/taurus-core/src/runtime/functions/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod boolean;
1010
mod color;
1111
mod control;
1212
mod date;
13+
mod dev;
1314
mod file;
1415
mod http;
1516
mod number;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Expands the function-like `taurus_macros::flow_type! { ... }` macro. Flow
2+
//! types carry no handler body, like data types -- just metadata.
3+
4+
use proc_macro2::TokenStream;
5+
use quote::{format_ident, quote};
6+
7+
use crate::parse::{AttrArgs, optional_string, translation_vec};
8+
9+
pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
10+
let args = AttrArgs::parse(input)?;
11+
12+
let identifier = args.required_string("identifier")?;
13+
let module = args.required_string("module")?;
14+
let name = translation_vec(&args.translations("name")?);
15+
let description = translation_vec(&args.translations("description")?);
16+
let documentation = translation_vec(&args.translations("documentation")?);
17+
let display_message = translation_vec(&args.translations("display_message")?);
18+
let alias = translation_vec(&args.translations("alias")?);
19+
let editable = args.flag("editable");
20+
let display_icon = optional_string(args.string("display_icon")?);
21+
let linked: Vec<String> = args.string_array("linked_data_type_identifiers")?;
22+
let signature = args.string("signature")?.unwrap_or_default();
23+
24+
let meta_fn_ident = format_ident!(
25+
"__taurus_flow_type_meta_{}",
26+
identifier
27+
.to_lowercase()
28+
.replace(|c: char| !c.is_ascii_alphanumeric(), "_"),
29+
);
30+
31+
Ok(quote! {
32+
#[doc(hidden)]
33+
fn #meta_fn_ident() -> crate::meta::FlowTypeMeta {
34+
crate::meta::FlowTypeMeta {
35+
identifier: #identifier,
36+
module: #module,
37+
name: #name,
38+
description: #description,
39+
documentation: #documentation,
40+
display_message: #display_message,
41+
alias: #alias,
42+
editable: #editable,
43+
display_icon: #display_icon,
44+
linked_data_type_identifiers: vec![#(#linked),*],
45+
signature: #signature,
46+
}
47+
}
48+
49+
::inventory::submit! {
50+
crate::meta::FlowTypeRegistration(#meta_fn_ident)
51+
}
52+
})
53+
}

crates/taurus-macros/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//! entry it constructs.
1313
1414
mod data_type;
15+
mod flow_type;
1516
mod module;
1617
mod parse;
1718
mod runtime_function;
@@ -53,6 +54,12 @@ pub fn data_type(input: TokenStream) -> TokenStream {
5354
run_fnlike(data_type::expand, input)
5455
}
5556

57+
/// Declares a flow type (was `flow_types/*.json`).
58+
#[proc_macro]
59+
pub fn flow_type(input: TokenStream) -> TokenStream {
60+
run_fnlike(flow_type::expand, input)
61+
}
62+
5663
/// Declares a module (was `module.json`). Exactly one per feature file.
5764
#[proc_macro]
5865
pub fn module(input: TokenStream) -> TokenStream {

crates/taurus-macros/src/module.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
1717
let author = args.required_string("author")?;
1818
let icon = args.required_string("icon")?;
1919
let version = args.required_string("version")?;
20+
let dev_only = args.flag("dev_only");
2021

2122
let meta_fn_ident = format_ident!(
2223
"__taurus_module_meta_{}",
@@ -36,6 +37,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
3637
author: #author,
3738
icon: #icon,
3839
version: #version,
40+
dev_only: #dev_only,
3941
}
4042
}
4143

0 commit comments

Comments
 (0)