Skip to content

Commit 4450aef

Browse files
authored
feat: add @microsoft/fast-build npm package with WASM CLI (#7358)
## Summary Wraps the `microsoft-fast-build` Rust crate as a WebAssembly module and exposes it as a new npm package `@microsoft/fast-build` with a `fast build` CLI. ## Changes ### `crates/microsoft-fast-build` - Added `crate-type = ["cdylib", "rlib"]` to `Cargo.toml` to support WASM compilation - Added `wasm-bindgen` as a **conditional WASM-only dependency** — native targets remain zero-dependency - Added `src/wasm.rs` exposing two `#[wasm_bindgen]` functions: - `render(entry, state)` — render a template with JSON state - `render_with_templates(entry, templates_json, state)` — render with custom element templates passed as a JSON map ### `packages/fast-build` (new) - `package.json` — `@microsoft/fast-build`, **no runtime npm dependencies**; includes a `build` script to regenerate the WASM via `wasm-pack` - `bin/fast.js` — CLI supporting `fast build` with: - `--templates="<glob>"` — glob pattern(s) for custom element HTML templates; warns if not provided or no files match - `--output="output.html"` — output file (default: `output.html`) - `--entry="index.html"` — entry HTML template (default: `index.html`) - `--state="state.json"` — state JSON file (default: `state.json`) - `wasm/` — pre-built WASM module and JS bindings (generated by `wasm-pack --target nodejs`) ## Notes - All file I/O and glob resolution is done in plain Node.js with no external dependencies - The existing Rust unit test suite continues to pass
1 parent fb1ac76 commit 4450aef

14 files changed

Lines changed: 668 additions & 2 deletions

build/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@microsoft/fast-build",
2+
"name": "@microsoft/fast-build-tools",
33
"description": "Build utilities for FAST monorepo",
44
"version": "0.0.0",
55
"private": true,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "none",
3+
"comment": "Initial addition of npm package for fast CLI",
4+
"packageName": "@microsoft/fast-build",
5+
"email": "7559015+janechu@users.noreply.github.com",
6+
"dependentChangeType": "none"
7+
}

crates/microsoft-fast-build/Cargo.lock

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

crates/microsoft-fast-build/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ categories = ["template-engine", "web-programming"]
1313
[lib]
1414
name = "microsoft_fast_build"
1515
path = "src/lib.rs"
16+
crate-type = ["cdylib", "rlib"]
17+
18+
[target.'cfg(target_arch = "wasm32")'.dependencies]
19+
wasm-bindgen = "0.2"

crates/microsoft-fast-build/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ mod node;
99
mod renderer;
1010
mod error;
1111
mod locator;
12+
#[cfg(target_arch = "wasm32")]
13+
mod wasm;
1214

1315
pub use json::{JsonValue, JsonError};
1416
pub use error::RenderError;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use wasm_bindgen::prelude::*;
2+
use std::collections::HashMap;
3+
use crate::{json, Locator, render_template, render_template_with_locator};
4+
5+
/// Render a FAST HTML template with a JSON state string.
6+
/// Returns the rendered HTML or throws a JavaScript error.
7+
#[wasm_bindgen]
8+
pub fn render(entry: &str, state: &str) -> Result<String, JsValue> {
9+
render_template(entry, state).map_err(|e| JsValue::from_str(&e.to_string()))
10+
}
11+
12+
/// Render a FAST HTML template with custom element templates and a JSON state string.
13+
/// `templates_json` is a JSON object mapping element names to their HTML template strings,
14+
/// e.g. `{"my-button": "<template>...</template>"}`.
15+
/// Returns the rendered HTML or throws a JavaScript error.
16+
#[wasm_bindgen]
17+
pub fn render_with_templates(entry: &str, templates_json: &str, state: &str) -> Result<String, JsValue> {
18+
let templates = parse_templates_map(templates_json)?;
19+
let locator = Locator::from_templates(templates);
20+
render_template_with_locator(entry, state, &locator)
21+
.map_err(|e| JsValue::from_str(&e.to_string()))
22+
}
23+
24+
fn parse_templates_map(templates_json: &str) -> Result<HashMap<String, String>, JsValue> {
25+
let parsed = json::parse(templates_json)
26+
.map_err(|e| JsValue::from_str(&format!("Failed to parse templates JSON: {}", e.message)))?;
27+
match parsed {
28+
json::JsonValue::Object(obj) => {
29+
let mut map = HashMap::new();
30+
for (k, v) in obj {
31+
match v {
32+
json::JsonValue::String(s) => { map.insert(k, s); }
33+
_ => return Err(JsValue::from_str(&format!(
34+
"Template value for '{}' must be a string", k
35+
))),
36+
}
37+
}
38+
Ok(map)
39+
}
40+
_ => Err(JsValue::from_str("Templates must be a JSON object")),
41+
}
42+
}

package-lock.json

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)