Skip to content

Commit

Permalink
test fixtures for fn builds
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam McKee committed Nov 5, 2024
1 parent cb3fa0f commit c724f3d
Show file tree
Hide file tree
Showing 15 changed files with 369 additions and 14 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ members = [

[workspace.dependencies]
anyhow = "1.0.92"
serde = { version = "1.0.213", features = ["derive"] }
serde_json = "1.0.132"
swc = "4.0.0"
swc_common = { version = "3.0.0", features = ["concurrent"] }
swc_ecma_ast = "3.0.0"
Expand Down Expand Up @@ -37,7 +39,7 @@ crossterm = "0.28.1"
lazy_static = "1.5.0"
notify = { version = "7.0.0", default-features = false, features = ["macos_fsevent"] }
regex = "1.11.1"
serde_json = "1.0.132"
serde_json = { workspace = true }
sha2 = "0.10.8"
swc = { workspace = true }
swc_common = { workspace = true }
Expand Down
2 changes: 2 additions & 0 deletions fn_build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ thiserror = "1.0.67"
tokio = { workspace = true }

[dev-dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
temp-dir = { workspace = true }
3 changes: 3 additions & 0 deletions fn_build/fixtures/swc/nodejs/js/http_route/build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"path": "routes/data/lambda.js"
}
6 changes: 6 additions & 0 deletions fn_build/fixtures/swc/nodejs/js/http_route/expect_debug.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"path": "routes/data/lambda.js",
"result": "Identical"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"path": "routes/data/lambda.js",
"result": {
"Content": "export const DELETE=()=>{console.log(\"delete\")};"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const DELETE = () => {
console.log('delete')
}
38 changes: 32 additions & 6 deletions fn_build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
mod result;
mod spec;
mod swc;

#[cfg(test)]
mod parse_test;

use crate::result::{FnBuildError, FnBuildResult, FnSource};
use crate::swc::parse_js_fn;
use std::path::PathBuf;
#[cfg(test)]
mod testing;

use crate::result::{FnBuild, FnBuildError, FnBuildResult, FnSource};
use crate::spec::{FnBuildSpec, FnParseSpec};
use crate::swc::{build_js_fn, parse_js_fn};

pub async fn build_fn(build_spec: FnBuildSpec) -> FnBuildResult<FnBuild> {
debug_assert!(build_spec.entrypoint.is_relative());
debug_assert!(build_spec.entrypoint.parent().is_some());
debug_assert!(build_spec.output.is_absolute());
debug_assert!(build_spec.output.is_dir());
debug_assert!(build_spec.project_dir.is_absolute());
debug_assert!(build_spec.project_dir.is_dir());
match build_spec.entrypoint.extension() {
None => Err(FnBuildError::InvalidFileType),
Some(extension) => match extension.to_string_lossy().as_ref() {
"js" | "mjs" => build_js_fn(build_spec).await,
"py" => todo!(),
"ts" => todo!(),
&_ => Err(FnBuildError::InvalidFileType),
},
}
}

pub async fn parse_fn(entrypoint: PathBuf) -> FnBuildResult<FnSource> {
match entrypoint.extension() {
pub async fn parse_fn(parse_spec: FnParseSpec) -> FnBuildResult<FnSource> {
debug_assert!(parse_spec.entrypoint.is_relative());
debug_assert!(parse_spec.entrypoint.parent().is_some());
debug_assert!(parse_spec.project_dir.is_absolute());
debug_assert!(parse_spec.project_dir.is_dir());
match parse_spec.entrypoint.extension() {
None => Err(FnBuildError::InvalidFileType),
Some(extension) => match extension.to_string_lossy().as_ref() {
"js" | "mjs" => parse_js_fn(entrypoint).await,
"js" | "mjs" => parse_js_fn(parse_spec).await,
"py" => todo!(),
"ts" => todo!(),
&_ => Err(FnBuildError::InvalidFileType),
Expand Down
34 changes: 33 additions & 1 deletion fn_build/src/parse_test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
use crate::{parse_fn, FnBuildError};
use crate::spec::{BuildMode, FnBuildSpec};
use crate::{build_fn, parse_fn, FnBuildError};
use std::path::PathBuf;
use temp_dir::TempDir;

#[tokio::test]
async fn build_fn_errors_for_invalid_extension() {
let build_dir = TempDir::new().unwrap();
let build_spec = FnBuildSpec {
entrypoint: PathBuf::from("README.md"),
mode: BuildMode::Debug,
output: build_dir.path().to_path_buf(),
project_dir: PathBuf::from("fixtures/swc/nodejs/js/http_route"),
};
match build_fn(build_spec).await {
Err(FnBuildError::InvalidFileType) => {}
_ => panic!(),
};
}

#[tokio::test]
async fn build_fn_errors_without_extension() {
let build_dir = TempDir::new().unwrap();
let build_spec = FnBuildSpec {
entrypoint: PathBuf::from("README.md"),
mode: BuildMode::Debug,
output: build_dir.path().to_path_buf(),
project_dir: PathBuf::from("fixtures/swc/nodejs/js/http_route"),
};
match build_fn(build_spec).await {
Err(FnBuildError::InvalidFileType) => {}
_ => panic!(),
};
}

#[tokio::test]
async fn parse_fn_errors_for_invalid_extension() {
Expand Down
8 changes: 8 additions & 0 deletions fn_build/src/result.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::spec::FnBuildOutput;
use std::path::PathBuf;

#[derive(Clone)]
Expand All @@ -19,6 +20,13 @@ pub struct FnSource {
pub path: PathBuf,
}

pub struct FnBuild {
#[allow(unused)]
pub entrypoint: FnSource,
#[allow(unused)]
pub output: FnBuildOutput,
}

#[derive(thiserror::Error, Debug)]
pub enum FnBuildError {
#[error("entrypoint file type is unsupported")]
Expand Down
26 changes: 26 additions & 0 deletions fn_build/src/spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use std::path::PathBuf;

#[derive(Clone, Eq, Hash, PartialEq)]
pub enum BuildMode {
Debug,
Release,
}

pub type FnBuildOutput = PathBuf;

// pub enum FnBuildOutput {
// Archive(PathBuf),
// Directory(PathBuf),
// }

pub struct FnBuildSpec {
pub entrypoint: PathBuf,
pub mode: BuildMode,
pub output: FnBuildOutput,
pub project_dir: PathBuf,
}

pub struct FnParseSpec {
pub entrypoint: PathBuf,
pub project_dir: PathBuf,
}
17 changes: 15 additions & 2 deletions fn_build/src/swc/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ impl SwcCompiler {
}
}

pub fn minify_js(self, path: &Path) -> CompileResult<String> {
self.source_with_compiler(path, |compiler, handler, source_file| {
compiler
.minify(
source_file,
handler,
&Default::default(),
Default::default(),
)
.map(|transform_output| transform_output.code)
})
}

pub fn parse_es_module(self, path: &Path) -> CompileResult<Module> {
self.source_with_compiler(path, |compiler, handler, source_file| {
compiler
Expand All @@ -71,7 +84,7 @@ impl SwcCompiler {
})
}

pub fn source_with_compiler<F, R>(self, p: &Path, f: F) -> CompileResult<R>
fn source_with_compiler<F, R>(self, p: &Path, f: F) -> CompileResult<R>
where
F: FnOnce(&Compiler, &Handler, Arc<SourceFile>) -> Result<R, anyhow::Error>,
{
Expand All @@ -82,7 +95,7 @@ impl SwcCompiler {
self.with_compiler(|compiler, handler| f(compiler, handler, source_file))
}

pub fn with_compiler<F, R>(self, f: F) -> CompileResult<R>
fn with_compiler<F, R>(self, f: F) -> CompileResult<R>
where
F: FnOnce(&Compiler, &Handler) -> Result<R, anyhow::Error>,
{
Expand Down
40 changes: 36 additions & 4 deletions fn_build/src/swc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
use crate::result::{FnBuildError, FnSource, ModuleImport};
use crate::result::{FnBuild, FnBuildError, FnSource, ModuleImport};
use crate::spec::{BuildMode, FnBuildSpec, FnParseSpec};
use crate::swc::compiler::SwcCompiler;
use crate::swc::visitors::ImportVisitor;
use std::path::PathBuf;
use std::fs;
use swc_ecma_visit::FoldWith;

mod compiler;
mod visitors;

#[cfg(test)]
mod swc_test;

#[cfg(test)]
mod visitors_test;

pub async fn parse_js_fn(path: PathBuf) -> Result<FnSource, FnBuildError> {
pub async fn build_js_fn(build_spec: FnBuildSpec) -> Result<FnBuild, FnBuildError> {
let output_file = build_spec.output.join(&build_spec.entrypoint);
fs::create_dir_all(output_file.parent().unwrap()).expect("mkdir -p");
match build_spec.mode {
BuildMode::Debug => {
fs::copy(
build_spec.project_dir.join(&build_spec.entrypoint),
output_file,
)
.expect("cp");
}
BuildMode::Release => {
let js_path = build_spec.project_dir.join(&build_spec.entrypoint);
let minified_js = SwcCompiler::new().minify_js(&js_path).unwrap();
fs::write(output_file, minified_js).unwrap();
}
}
Ok(FnBuild {
entrypoint: FnSource {
imports: Vec::new(),
path: build_spec.entrypoint,
},
output: build_spec.output,
})
}

pub async fn parse_js_fn(parse_spec: FnParseSpec) -> Result<FnSource, FnBuildError> {
let compiler = SwcCompiler::new();
let module = compiler.parse_es_module(&path).unwrap();
let module = compiler
.parse_es_module(&parse_spec.project_dir.join(&parse_spec.entrypoint))
.unwrap();
let mut visitor = ImportVisitor::new();
module.fold_with(&mut visitor);
let imports = visitor
Expand Down
22 changes: 22 additions & 0 deletions fn_build/src/swc/swc_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::spec::FnBuildSpec;
use crate::swc::build_js_fn;
use crate::testing::{run_fixtures, BuildProcess, BuildProcessResult};
use std::path::PathBuf;
use std::sync::Arc;

struct JavaScriptBuild {}

impl BuildProcess for JavaScriptBuild {
fn build(&self, build_spec: FnBuildSpec) -> BuildProcessResult {
Box::pin(build_js_fn(build_spec))
}
}

#[tokio::test]
pub async fn test_nodejs_js_fixtures() {
run_fixtures(
Arc::new(Box::new(JavaScriptBuild {})),
PathBuf::from("fixtures/swc/nodejs/js"),
)
.await;
}
Loading

0 comments on commit c724f3d

Please sign in to comment.