1pub mod core;
2pub mod transform;
3
4#[cfg(test)]
5mod tests;
6
7use crate::{
8 Config, Engine, Result, Vars, data,
9 scheduler::{Context, Runtime},
10 store::DbCollectionIden,
11};
12use dashmap::DashMap;
13use serde::{Deserialize, Serialize};
14use std::{fmt::Debug, sync::Arc};
15use tracing::debug;
16
17#[cfg(test)]
18pub use core::RunningMode;
19
20#[derive(Debug, Clone)]
21pub struct Package {
22 packages: Arc<DashMap<String, ActPackageRegister>>,
23}
24
25#[async_trait::async_trait]
26
27pub trait ActPackage: Send + Sync {
28 fn new(config: &Config) -> Result<Self>
30 where
31 Self: Sized;
32 fn definition() -> ActPackageDefinition
34 where
35 Self: Sized;
36 async fn execute(&self, _ctx: &Context, _params: &serde_json::Value) -> Result<Option<Vars>> {
38 Ok(None)
39 }
40 async fn start(
42 &self,
43 _rt: &Arc<Runtime>,
44 _params: &serde_json::Value,
45 _options: &Vars,
46 ) -> Result<Option<Vars>> {
47 Ok(None)
48 }
49}
50
51#[derive(
52 Serialize,
53 Deserialize,
54 Debug,
55 Clone,
56 Copy,
57 Default,
58 PartialEq,
59 strum::AsRefStr,
60 strum::EnumString,
61)]
62#[serde(rename_all = "snake_case")]
63#[strum(serialize_all = "snake_case")]
64pub enum ActRunAs {
65 Func,
67 #[default]
69 Irq,
70 Msg,
72}
73
74#[derive(
75 Serialize,
76 Deserialize,
77 Debug,
78 Clone,
79 Copy,
80 Default,
81 PartialEq,
82 strum::AsRefStr,
83 strum::EnumString,
84)]
85#[serde(rename_all = "snake_case")]
86#[strum(serialize_all = "snake_case")]
87pub enum ActPackageCatalog {
88 Core,
90
91 Event,
93
94 Output,
96
97 Transform,
99
100 Form,
102
103 Ai,
105
106 #[default]
109 App,
110}
111
112#[derive(Debug, Clone, Deserialize, Serialize)]
113pub struct ActPackageDefinition {
114 pub id: &'static str,
116
117 pub name: &'static str,
119
120 pub desc: &'static str,
122
123 pub icon: &'static str,
125
126 pub doc: &'static str,
128
129 pub version: &'static str,
131
132 pub schema: serde_json::Value,
134
135 #[serde(default)]
137 pub options: Option<serde_json::Value>,
138
139 pub run_as: ActRunAs,
142
143 pub resources: Vec<ActResource>,
147
148 pub catalog: ActPackageCatalog,
150}
151
152#[derive(Debug, Clone, Deserialize, Serialize)]
153pub struct ActResource {
154 pub name: String,
155 pub desc: String,
156 pub value: serde_json::Value,
157}
158
159#[derive(Debug, Clone)]
160pub struct ActPackageRegister {
161 pub meta: fn() -> ActPackageDefinition,
162 pub create: fn(config: &Config) -> Result<Arc<dyn ActPackage>>,
163}
164
165impl ActPackageRegister {
166 pub(crate) const fn new<T>() -> Self
167 where
168 T: ActPackage + 'static,
169 {
170 Self {
171 meta: T::definition,
172 create: (|config: &Config| {
173 let ret = T::new(config)?;
182 Ok(Arc::new(ret) as Arc<dyn ActPackage>)
183 }),
184 }
185 }
186}
187
188impl Default for Package {
189 fn default() -> Self {
190 Self::new()
191 }
192}
193
194impl Package {
195 pub fn new() -> Self {
196 Self {
197 packages: Arc::new(DashMap::new()),
198 }
199 }
200
201 pub fn register(&self, id: &str, register: &ActPackageRegister) {
202 self.packages.insert(id.to_string(), register.clone());
203 }
204
205 pub fn get(&self, id: &str) -> Option<ActPackageRegister> {
206 self.packages.get(id).map(|v| v.clone())
207 }
208}
209
210impl ActPackageDefinition {
211 pub fn into_data(&self) -> Result<data::Package> {
212 let pack = self.clone();
213 Ok(data::Package {
214 id: pack.id.to_string(),
215 name: pack.name.to_string(),
216 desc: pack.desc.to_string(),
217 icon: pack.icon.to_string(),
218 doc: pack.doc.to_string(),
219 version: pack.version.to_string(),
220 schema: pack.schema.to_string(),
221 options: pack.options.map(|v| v.to_string()),
222 run_as: pack.run_as,
223 resources: serde_json::to_string(&pack.resources)
224 .expect("cannot convert ActPackageMeta.resources to json"),
225 catalog: pack.catalog,
226 create_time: 0,
227 update_time: 0,
228 timestamp: 0,
229 built_in: false,
230 v: data::Package::version(),
231 })
232 }
233}
234
235inventory::collect!(ActPackageRegister);
236
237pub async fn init(engine: &Engine) -> Result<()> {
238 for register in inventory::iter::<ActPackageRegister> {
239 let meta = (register.meta)();
240 debug!("package: {}", meta.name);
241
242 let mut pack = meta.into_data()?;
243 pack.built_in = true;
244 engine.executor().pack().publish(&pack).await?;
245 engine.runtime().package().register(meta.id, register);
246 }
247 Ok(())
248}