Skip to content

Commit

Permalink
splitting shared parse and build apis in result and spec modules to b…
Browse files Browse the repository at this point in the history
…uild and parse modules
  • Loading branch information
Adam McKee committed Jan 9, 2025
1 parent f97de22 commit e2736f3
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 99 deletions.
40 changes: 34 additions & 6 deletions fn_build/src/spec.rs → fn_build/src/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::checksum::Checksum;
use crate::runtime::Runtime;
use crate::{FnDependencies, FnHandler, FnParseError, FnParseSpec, FnSource};
use serde::Deserialize;
use std::collections::HashMap;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;

Expand All @@ -9,12 +13,6 @@ pub enum BuildMode {
Release,
}

pub struct FnParseSpec {
pub entrypoint: PathBuf,
pub project_dir: Arc<PathBuf>,
pub runtime: Runtime,
}

/// Output config for the build.
#[derive(Clone, Deserialize)]
pub struct FnOutputConfig {
Expand Down Expand Up @@ -69,3 +67,33 @@ impl FnBuildSpec {
}
}
}

#[derive(Clone, Deserialize)]
pub struct FnBuildOutput {
pub archive_file: Option<PathBuf>,
/// PathBuf to the build's output directory partitioned by the build's BuildMode.
pub build_dir: PathBuf,
}

#[derive(Clone, Deserialize)]
pub struct FnBuildManifest {
/// Checksums of the original sources of the function's build.
pub checksums: HashMap<PathBuf, Checksum>,
pub dependencies: FnDependencies,
pub entrypoint: PathBuf,
pub handler: FnHandler,
pub output: FnBuildOutput,
pub sources: Vec<FnSource>,
}

#[derive(thiserror::Error, Debug)]
pub enum FnBuildError {
#[error("{0}")]
IoError(#[from] io::Error),
#[error("error parsing function: {0}")]
ParseError(#[from] FnParseError),
#[error("build task error: {0}")]
KnownError(#[from] anyhow::Error),
}

pub type FnBuildResult<T> = Result<T, FnBuildError>;
2 changes: 1 addition & 1 deletion fn_build/src/build_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async fn build_fn_errors_for_missing_handler() {
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"entrypoint routes/data/lambda.js does not have a handler fn someWackyFunctionName"
"error parsing function: entrypoint routes/data/lambda.js does not have a handler fn someWackyFunctionName"
);
}

Expand Down
8 changes: 4 additions & 4 deletions fn_build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod archive;
mod build;
mod checksum;
mod parse;
mod paths;
mod result;
mod routing;
pub mod runtime;
mod spec;
mod swc;

#[cfg(test)]
Expand All @@ -25,9 +25,9 @@ mod testing;
#[cfg(test)]
mod routing_test;

pub use crate::result::*;
pub use crate::build::*;
pub use crate::parse::*;
pub use crate::routing::*;
pub use crate::spec::*;

/// Builds a lambda function.
pub async fn build_fn(build_spec: FnBuildSpec) -> FnBuildResult<FnBuildManifest> {
Expand Down
152 changes: 64 additions & 88 deletions fn_build/src/result.rs → fn_build/src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
use crate::checksum::Checksum;
use crate::runtime::Runtime;
use crate::{FnRouting, HttpMethod};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum ModuleImport {
PackageDependency {
package: String,
subpath: Option<String>,
},
/// A source file import specified by relative path from the project's root.
RelativeSource(PathBuf),
/// An unresolvable import specifier.
Unknown(String),
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct FnSource {
pub imports: Vec<ModuleImport>,
pub path: PathBuf,
pub struct FnParseSpec {
pub entrypoint: PathBuf,
pub project_dir: Arc<PathBuf>,
pub runtime: Runtime,
}

#[derive(Clone, Deserialize, Serialize)]
Expand All @@ -40,75 +27,6 @@ pub struct FnHandler {
pub routing: FnRouting,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct FnEntrypoint {
pub handlers: Vec<FnHandler>,
pub path: PathBuf,
}

#[derive(Clone, Deserialize, Serialize)]
pub struct FnParseManifest {
pub dependencies: FnDependencies,
pub entrypoint: FnEntrypoint,
pub sources: Vec<FnSource>,
}

#[derive(thiserror::Error, Debug)]
pub enum FnParseError {
#[error("entrypoint file type is unsupported")]
InvalidFileType,
#[error("{0}")]
IoError(#[from] io::Error),
#[error("syntax error")]
SyntaxError,
}

pub type FnParseResult<T> = Result<T, FnParseError>;

#[derive(Clone, Deserialize)]
pub struct FnBuildOutput {
pub archive_file: Option<PathBuf>,
/// PathBuf to the build's output directory partitioned by the build's BuildMode.
pub build_dir: PathBuf,
}

#[derive(Clone, Deserialize)]
pub struct FnBuildManifest {
/// Checksums of the original sources of the function's build.
pub checksums: HashMap<PathBuf, Checksum>,
pub dependencies: FnDependencies,
pub entrypoint: PathBuf,
pub handler: FnHandler,
pub output: FnBuildOutput,
pub sources: Vec<FnSource>,
}

#[derive(thiserror::Error, Debug)]
pub enum FnBuildError {
#[error("{0}")]
IoError(#[from] io::Error),
#[error("error parsing function: {0}")]
ParseError(#[from] FnParseError),
#[error("entrypoint {0} does not have a handler fn {1}")]
MissingHandler(PathBuf, String),
#[error("build task error: {0}")]
KnownError(#[from] anyhow::Error),
}

pub type FnBuildResult<T> = Result<T, FnBuildError>;

impl FnEntrypoint {
pub fn to_fn_identifier(&self, handler_fn_name: &str) -> FnBuildResult<String> {
self.handlers
.iter()
.find(|h| h.fn_name == handler_fn_name)
.map(FnHandler::to_fn_identifier)
.ok_or_else(|| {
FnBuildError::MissingHandler(self.path.clone(), handler_fn_name.to_string())
})
}
}

impl FnHandler {
pub fn from_handler_fn(path: &Path, fn_name: String) -> Self {
let routing = FnRouting::from_handler_fn(path, fn_name.as_str());
Expand All @@ -135,8 +53,66 @@ impl FnHandler {
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct FnEntrypoint {
pub handlers: Vec<FnHandler>,
pub path: PathBuf,
}

impl FnEntrypoint {
pub fn to_fn_identifier(&self, handler_fn_name: &str) -> FnParseResult<String> {
self.handlers
.iter()
.find(|h| h.fn_name == handler_fn_name)
.map(FnHandler::to_fn_identifier)
.ok_or_else(|| {
FnParseError::MissingHandler(self.path.clone(), handler_fn_name.to_string())
})
}
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum ModuleImport {
PackageDependency {
package: String,
subpath: Option<String>,
},
/// A source file import specified by relative path from the project's root.
RelativeSource(PathBuf),
/// An unresolvable import specifier.
Unknown(String),
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct FnSource {
pub imports: Vec<ModuleImport>,
pub path: PathBuf,
}

#[derive(Clone, Deserialize, Serialize)]
pub struct FnParseManifest {
pub dependencies: FnDependencies,
pub entrypoint: FnEntrypoint,
pub sources: Vec<FnSource>,
}

impl FnParseManifest {
pub fn source_paths(&self) -> Vec<PathBuf> {
self.sources.iter().map(|s| s.path.clone()).collect()
}
}

#[derive(thiserror::Error, Debug)]
pub enum FnParseError {
#[error("entrypoint file type is unsupported")]
InvalidFileType,
#[error("{0}")]
IoError(#[from] io::Error),
#[error("entrypoint {0} does not have a handler fn {1}")]
MissingHandler(PathBuf, String),
#[error("syntax error")]
SyntaxError,
}

pub type FnParseResult<T> = Result<T, FnParseError>;

0 comments on commit e2736f3

Please sign in to comment.