1mod areas;
4mod code;
5mod config;
6mod constraints;
7mod contract_traits;
8mod cross_owner;
9mod declarations;
10mod effects;
11mod entitlements;
12mod error;
13mod flags;
14mod gateways;
15mod gating;
16mod handlers;
17mod identity;
18mod islands;
19mod load;
20mod mails;
21mod manifest;
22mod menu;
23mod messages;
24mod metadata;
25pub mod naming;
26mod package_events;
27mod package_routes;
28pub mod permissions;
29mod posts;
30mod provisions;
31mod references;
32mod routes;
33mod shipped;
34mod sign_in;
35mod sources;
36pub mod syntax;
37mod targets;
38mod telemetry;
39#[cfg(feature = "testing")]
40pub mod testing;
41pub mod usage;
42
43use std::path::PathBuf;
44
45use usage::{Mentions, PublicItem};
46
47pub use code::{
48 Aggregate, Code, EnumDeclaration, EnumVariant, FieldDeclaration, Function, InputDeclaration,
49 KeyLiteral, RawSql, ReadModel, ScreenRender, TypeMethod, TypeName,
50};
51pub use config::{ConfigKey, DATABASE_URL, KeyKind, ModuleConfig, config_type_name};
52pub use contract_traits::{ContractMethod, ContractTrait};
53pub use cross_owner::CrossOwnerCheck;
54pub use declarations::{ModuleDeclaration, module_declaration};
55pub use effects::{Call, Effects, MethodCall, Queued, Raised};
56pub use entitlements::{EntitlementDeclaration, Entitlements};
57pub use error::ModelError;
58pub use flags::{FeatureCode, FeatureDeclaration, FeatureGate};
59pub use gateways::{Gateway, GatewayAdapter};
60pub use islands::{Island, IslandBundle, PropsDeclaration, is_island_name, island_bundles};
61pub use load::{
62 dependency_crate, files_with_extension, load, rust_files, subdirectories, workspace_crates,
63};
64pub use manifest::{MANIFEST_CONSTANT, Manifest, Tier, manifest_file};
65pub use messages::interval_seconds;
66pub use metadata::{framework_features, workspace_root};
67pub use naming::{KnownArea, WiringSide};
68pub use package_routes::{ListedRoute, PackageRoutes, RouteMount, RoutedPackage, ServedRoute};
69pub use routes::check_route_path;
70pub use shipped::{MountedScreen, ScreenRoute, ShippedScreen};
71pub use sign_in::SignInPaths;
72pub use telemetry::{ProductEvent, TelemetryCode};
73
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct App {
76 pub root: PathBuf,
77 pub app: Crate,
78 pub modules: Vec<Module>,
79 pub identity: Option<Identity>,
80 pub package_events: Vec<EventDeclaration>,
82 pub packages: Vec<RoutedPackage>,
84 pub split: Split,
85 pub structure_ceilings: bool,
87}
88
89#[derive(Clone, Debug, Default, PartialEq, Eq)]
91pub struct Split {
92 pub serves: Vec<String>,
94 pub remote: Vec<RemoteModule>,
95}
96
97#[derive(Clone, Debug, PartialEq, Eq)]
99pub struct RemoteModule {
100 pub name: String,
101 pub contract: Crate,
102 pub defined_areas: Vec<AreaDefinition>,
103 pub exports: Vec<String>,
104 pub events: Vec<String>,
105 pub traits: Vec<ContractTrait>,
106}
107
108#[derive(Clone, Debug, Default, PartialEq, Eq)]
109pub struct Identity {
110 pub directory: PathBuf,
111 pub screens: Vec<String>,
112 pub routes: Vec<ListedRoute>,
113 pub mounts: Vec<RouteMount>,
114 pub shipped: Vec<ShippedScreen>,
115}
116
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub struct Crate {
119 pub package: String,
120 pub crate_name: String,
121 pub path: PathBuf,
122 pub dependencies: Vec<Dependency>,
123 pub sources: Vec<Source>,
124 pub tests_and_examples: Vec<Source>,
125}
126
127#[derive(Clone, Debug, PartialEq, Eq)]
128pub struct Dependency {
129 pub package: String,
130 pub crate_name: String,
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
134pub struct Source {
135 pub file: PathBuf,
136 pub paths: Vec<PathReference>,
137 pub macros: Vec<MacroCall>,
138 pub mentions: Mentions,
139 pub public_items: Vec<PublicItem>,
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
143pub struct PathReference {
144 pub segments: Vec<String>,
145 pub line: usize,
146}
147
148#[derive(Clone, Debug, PartialEq, Eq)]
149pub struct MacroCall {
150 pub path: Vec<String>,
151 pub first_string: Option<String>,
152 pub line: usize,
153}
154
155impl MacroCall {
156 #[must_use]
157 pub fn name(&self) -> &str {
158 self.path.last().map_or("", String::as_str)
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Eq)]
163pub struct Module {
164 pub krate: Crate,
165 pub manifest: Option<Manifest>,
166 pub config: Option<ModuleConfig>,
167 pub contract: Option<Crate>,
168 pub defined_areas: Vec<AreaDefinition>,
169 pub contract_declares_gen: bool,
170 pub contract_exports: Vec<String>,
171 pub contract_traits: Vec<ContractTrait>,
172 pub migrations: Vec<PathBuf>,
173 pub sqlite_migrations: Vec<PathBuf>,
175 pub areas: Vec<AreaContribution>,
176 pub listeners: Vec<Listener>,
177 pub schedules: Vec<Schedule>,
178 pub events: Vec<String>,
179 pub module_events: Vec<EventDeclaration>,
180 pub jobs: Vec<Job>,
181 pub tasks: Vec<Task>,
182 pub implementations: Vec<Provision>,
183 pub extensions: Vec<Provision>,
184 pub gateways: Vec<Gateway>,
185 pub islands: Vec<Island>,
186 pub components: Vec<PathBuf>,
188 pub languages: Vec<PathBuf>,
190 pub mails: Vec<MailTemplate>,
191 pub plans: Option<PathBuf>,
193 pub private_items: Vec<PrivateItem>,
194 pub code: Code,
195}
196
197#[derive(Clone, Debug, PartialEq, Eq)]
199pub struct PrivateItem {
200 pub path: Vec<String>,
201 pub file: PathBuf,
202 pub line: usize,
203 pub crate_visible: bool,
205}
206
207#[derive(Clone, Debug, PartialEq, Eq)]
210pub struct MailTemplate {
211 pub key: String,
212 pub file: PathBuf,
213}
214
215#[derive(Clone, Debug, PartialEq, Eq)]
216pub struct AreaDefinition {
217 pub name: String,
218 pub type_path: Vec<String>,
219 pub prefix: Option<String>,
220 pub client: AreaClient,
221 pub principal: Vec<String>,
222 pub implements_member_area: bool,
223 pub opens_sign_up: bool,
225 pub file: PathBuf,
226 pub line: usize,
227}
228
229#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
232pub enum AreaClient {
233 #[default]
234 Html,
235 Svelte,
236 React,
237}
238
239#[derive(Clone, Debug, PartialEq, Eq)]
240pub struct Job {
241 pub file: PathBuf,
242 pub line: usize,
243 pub function: Vec<String>,
244}
245
246#[derive(Clone, Debug, PartialEq, Eq)]
248pub struct Task {
249 pub file: PathBuf,
250 pub line: usize,
251 pub function: Vec<String>,
252}
253
254#[derive(Clone, Debug, PartialEq, Eq)]
255pub struct Provision {
256 pub contract: Vec<String>,
257 pub ty: Vec<String>,
258 pub unit: bool,
260 pub file: PathBuf,
261 pub line: usize,
262}
263
264#[derive(Clone, Debug, PartialEq, Eq)]
265pub struct EventDeclaration {
266 pub name: String,
267 pub file: PathBuf,
268 pub line: usize,
269}
270
271#[derive(Clone, Debug, PartialEq, Eq)]
272pub struct Listener {
273 pub file: PathBuf,
274 pub line: usize,
275 pub function: Vec<String>,
276 pub event: Vec<String>,
277}
278
279#[derive(Clone, Debug, PartialEq, Eq)]
280pub struct Schedule {
281 pub file: PathBuf,
282 pub line: usize,
283 pub function: Vec<String>,
284 pub cadence: Cadence,
285 pub each: Option<Vec<String>>,
286}
287
288#[derive(Clone, Debug, PartialEq, Eq)]
291pub enum Cadence {
292 Interval(String),
294 WallClock(WallClock),
295}
296
297#[derive(Clone, Debug, PartialEq, Eq)]
298pub struct WallClock {
299 pub daily_at: String,
300 pub weekly_on: Option<String>,
301 pub zone: String,
302}
303
304impl std::fmt::Display for Cadence {
305 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
306 match self {
307 Self::Interval(interval) => write!(formatter, "every {interval}"),
308 Self::WallClock(WallClock {
309 daily_at,
310 weekly_on: None,
311 zone,
312 }) => write!(formatter, "daily at {daily_at} {zone}"),
313 Self::WallClock(WallClock {
314 daily_at,
315 weekly_on: Some(weekday),
316 zone,
317 }) => write!(formatter, "weekly on {weekday} at {daily_at} {zone}"),
318 }
319 }
320}
321
322#[derive(Clone, Debug, PartialEq, Eq)]
323pub struct AreaContribution {
324 pub area: String,
325 pub routes_file: PathBuf,
326 pub declared: bool,
328 pub routes: Vec<Route>,
329 pub screens: Vec<PathBuf>,
330 pub overrides: Vec<ScreenOverride>,
331 pub menu: Option<MenuFile>,
332}
333
334#[derive(Clone, Debug, PartialEq, Eq)]
335pub struct MenuFile {
336 pub file: PathBuf,
337 pub declared: bool,
338 pub entries: Vec<MenuEntry>,
339}
340
341#[derive(Clone, Debug, PartialEq, Eq)]
342pub struct MenuEntry {
343 pub label: String,
344 pub feature: Option<String>,
345 pub line: usize,
346}
347
348#[derive(Clone, Debug, PartialEq, Eq)]
349pub struct ScreenOverride {
350 pub module: String,
351 pub file: PathBuf,
352}
353
354#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
355pub enum Method {
356 Get,
357 Post,
358 Put,
359 Patch,
360 Delete,
361}
362
363impl Method {
364 const ALL: [Self; 5] = [Self::Get, Self::Post, Self::Put, Self::Patch, Self::Delete];
365
366 #[must_use]
367 pub fn name(self) -> &'static str {
368 match self {
369 Self::Get => "GET",
370 Self::Post => "POST",
371 Self::Put => "PUT",
372 Self::Patch => "PATCH",
373 Self::Delete => "DELETE",
374 }
375 }
376
377 #[must_use]
378 pub fn from_routes_method(name: &str) -> Option<Self> {
379 Self::ALL
380 .into_iter()
381 .find(|method| method.name().to_ascii_lowercase() == name)
382 }
383}
384
385#[derive(Clone, Debug, PartialEq, Eq)]
386pub struct Route {
387 pub method: Method,
388 pub path: String,
389 pub handler: Vec<String>,
390 pub screen: Option<String>,
391 pub island: Option<String>,
392 pub then: Option<Then>,
393 pub modifiers: Vec<Modifier>,
394 pub webhook: Option<String>,
395 pub line: usize,
396}
397
398#[derive(Clone, Debug, PartialEq, Eq)]
399pub enum Modifier {
400 Throttle(String),
401 Signed,
402 Idempotent,
403 BodyLimit(String),
404 Feature(String),
405 Entitled(String),
407 Live(String),
409 Cached(String),
411 Queued,
413 Document(String),
415 FileLimit(String),
417}
418
419#[derive(Clone, Debug, PartialEq, Eq)]
420pub enum Then {
421 Screen {
422 screen: String,
423 fragment: String,
424 },
425 Redirect(String),
426 Follow,
428 RedirectOrFollow(String),
430}