Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d270915
feat: migrate to use explicit subcommands
1egoman Jan 14, 2026
a8fbb3c
feat: add subcommand for creating a native package to wrap a given dlib
1egoman Jan 14, 2026
5858091
fix: rename out_disable_auto_loading_lib => out_lib_disable_auto_load…
1egoman Jan 14, 2026
4f5ffd0
fix: update native package scaffolding output to generate functions r…
1egoman Jan 14, 2026
a8cd92d
feat: add out_lib_path_module for use with generated native modules
1egoman Jan 14, 2026
9fc2b64
feat: add filters matching actual js values to check
1egoman Jan 14, 2026
1f48104
feat: add better support for modules without filters
1egoman Jan 14, 2026
e5f212f
feat: expose last resolution error if requiring module fails
1egoman Jan 14, 2026
1831faf
feat: move LibPath::Module resolution logic into commonjs shim layer
1egoman Jan 15, 2026
af7dd99
feat: add optional dependency generation from lib path modules
1egoman Jan 15, 2026
562f3a9
feat: expose os / cpu package json fields
1egoman Jan 15, 2026
593c11b
feat: add --out-lib-path-module json parsing idea from 1:1 with jacob
1egoman Jan 16, 2026
2e5bc7b
feat: add d.cts types for cjs file
1egoman Jan 16, 2026
3957d04
fix: build d.cts and include link in generated package.json
1egoman Jan 21, 2026
5db775a
feat: migrate to cts for commonjs-shim
1egoman Jan 21, 2026
c524d49
fix: address typos in package setup
1egoman Jan 21, 2026
40e554d
feat: add more robust tests for LibPath::as_switch_tokens_by
1egoman Jan 26, 2026
4877c86
feat: run tests in github actions for each repo push
1egoman Jan 26, 2026
e0ca99a
fix: remove --profile ci from github workflow
1egoman Jan 26, 2026
4cfe818
feat: migrate to GenerateNodeBindingsOptions struct for passing param…
1egoman Jan 26, 2026
73734e5
fix: add missing import
1egoman Jan 26, 2026
2a2e660
fix: add missing options prefix
1egoman Jan 26, 2026
9846499
fix: ensure that break after case end is handled
1egoman Jan 26, 2026
eca6ce6
fix: address import path typos
1egoman Jan 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test
on:
workflow_dispatch:
push:
branches: [main]
pull_request:
branches: [main]
types:
- opened
- reopened
- synchronize
- ready_for_review
jobs:
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Rust Toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Test
run: cargo test
21 changes: 11 additions & 10 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cargo_metadata = "0.19.2" # NOTE: keep this version up to date with the version
clap = { version = "4.5.51", features = ["derive"] }
heck = "0.5.0"
serde = "1.0.228"
serde_json = "1.0.149"
textwrap = "0.16.2"
toml = "0.9.8"
uniffi = "0.30.0"
Expand Down
78 changes: 57 additions & 21 deletions src/bindings/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ use anyhow::{Context, Result};
use askama::Template;
use heck::ToKebabCase;

use crate::bindings::{filters, utils::{DirnameApi, ImportExtension}};
use crate::bindings::{filters, utils::{DirnameApi, ImportExtension, LibPath, LibPathSwitchToken}};

pub struct Bindings {
pub package_json_contents: String,
pub sys_ts_template_contents: String,
pub commonjs_shim_cts_template_contents: String,
pub node_ts_file_contents: String,
pub index_ts_file_contents: String,
}
Expand All @@ -22,11 +23,12 @@ pub struct Bindings {
struct PackageJsonTemplate<'ci> {
ci: &'ci ComponentInterface,
out_node_version: String,
out_lib_path: LibPath,
}

impl<'ci> PackageJsonTemplate<'ci> {
pub fn new(ci: &'ci ComponentInterface, out_node_version: &str) -> Self {
Self { ci, out_node_version: out_node_version.into() }
pub fn new(ci: &'ci ComponentInterface, out_node_version: &str, out_lib_path: LibPath) -> Self {
Self { ci, out_node_version: out_node_version.into(), out_lib_path }
}
}

Expand All @@ -36,22 +38,46 @@ struct SysTemplate<'ci> {
ci: &'ci ComponentInterface,

out_dirname_api: DirnameApi,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
out_verbose_logs: bool,
out_lib_path: LibPath,
commonjs_shim_cjs_main_file_name: String,
}

impl<'ci> SysTemplate<'ci> {
pub fn new(
ci: &'ci ComponentInterface,
out_dirname_api: DirnameApi,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
out_verbose_logs: bool,
out_lib_path: LibPath,
commonjs_shim_cjs_main_file_name: &str,
) -> Self {
Self { ci, out_dirname_api, out_disable_auto_loading_lib, out_verbose_logs }
Self {
ci,
out_dirname_api,
out_lib_disable_auto_loading,
out_verbose_logs,
out_lib_path,
commonjs_shim_cjs_main_file_name: commonjs_shim_cjs_main_file_name.into(),
}
}
}

#[derive(Template)]
#[template(escape = "none", path = "commonjs-shim.cts")]
struct CommonJsShimTemplate {
out_lib_path: LibPath,
}

impl CommonJsShimTemplate {
pub fn new(out_lib_path: LibPath) -> Self {
Self { out_lib_path }
}
}



#[derive(Template)]
#[template(escape = "none", path = "node.ts")]
struct NodeTsTemplate<'ci> {
Expand Down Expand Up @@ -83,43 +109,53 @@ struct IndexTsTemplate {
node_ts_main_file_name: String,
sys_ts_main_file_name: String,
out_import_extension: ImportExtension,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
}

impl IndexTsTemplate {
pub fn new(
node_ts_main_file_name: &str,
sys_ts_main_file_name: &str,
out_import_extension: ImportExtension,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
) -> Self {
Self {
node_ts_main_file_name: node_ts_main_file_name.to_string(),
sys_ts_main_file_name: sys_ts_main_file_name.to_string(),
out_import_extension,
out_disable_auto_loading_lib,
out_lib_disable_auto_loading,
}
}
}

/// Options required to pass to [generate_node_bindings] invocations.
#[derive(Debug)]
pub struct GenerateNodeBindingsOptions<'a> {
pub sys_ts_main_file_name: &'a str,
pub node_ts_main_file_name: &'a str,
pub commonjs_shim_cts_main_file_name: &'a str,
pub out_dirname_api: DirnameApi,
pub out_lib_disable_auto_loading: bool,
pub out_import_extension: ImportExtension,
pub out_node_version: &'a str,
pub out_verbose_logs: bool,
pub out_lib_path: LibPath,
}

pub fn generate_node_bindings(
ci: &ComponentInterface,
sys_ts_main_file_name: &str,
node_ts_main_file_name: &str,
out_dirname_api: DirnameApi,
out_disable_auto_loading_lib: bool,
out_import_extension: ImportExtension,
out_node_version: &str,
out_verbose_logs: bool,
options: GenerateNodeBindingsOptions<'_>,
) -> Result<Bindings> {
let package_json_contents = PackageJsonTemplate::new(ci, out_node_version).render().context("failed to render package.json template")?;
let sys_template_contents = SysTemplate::new(ci, out_dirname_api, out_disable_auto_loading_lib, out_verbose_logs).render().context("failed to render sys.ts template")?;
let node_ts_file_contents = NodeTsTemplate::new(ci, sys_ts_main_file_name, out_import_extension.clone(), out_verbose_logs).render().context("failed to render node.ts template")?;
let index_ts_file_contents = IndexTsTemplate::new(node_ts_main_file_name, sys_ts_main_file_name, out_import_extension, out_disable_auto_loading_lib).render().context("failed to render index.ts template")?;
let package_json_contents = PackageJsonTemplate::new(ci, options.out_node_version, options.out_lib_path.clone()).render().context("failed to render package.json template")?;
let sys_ts_template_contents = SysTemplate::new(ci, options.out_dirname_api, options.out_lib_disable_auto_loading, options.out_verbose_logs, options.out_lib_path.clone(), options.commonjs_shim_cts_main_file_name).render().context("failed to render sys.ts template")?;
let commonjs_shim_cts_template_contents = CommonJsShimTemplate::new(options.out_lib_path.clone()).render().context("failed to render commonjs_shim.cjs template")?;
let node_ts_file_contents = NodeTsTemplate::new(ci, options.sys_ts_main_file_name, options.out_import_extension.clone(), options.out_verbose_logs).render().context("failed to render node.ts template")?;
let index_ts_file_contents = IndexTsTemplate::new(options.node_ts_main_file_name, options.sys_ts_main_file_name, options.out_import_extension, options.out_lib_disable_auto_loading).render().context("failed to render index.ts template")?;

Ok(Bindings {
package_json_contents,
sys_ts_template_contents: sys_template_contents,
sys_ts_template_contents,
commonjs_shim_cts_template_contents,
node_ts_file_contents,
index_ts_file_contents,
})
Expand Down
36 changes: 25 additions & 11 deletions src/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,33 @@ mod generator;
mod filters;
pub mod utils;

use crate::{bindings::generator::{generate_node_bindings, Bindings}, utils::write_with_dirs};
use crate::{bindings::generator::{generate_node_bindings, Bindings, GenerateNodeBindingsOptions}, utils::write_with_dirs};

pub struct NodeBindingGenerator {
out_dirname_api: utils::DirnameApi,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
out_import_extension: utils::ImportExtension,
out_node_version: String,
out_verbose_logs: bool,
out_lib_path: utils::LibPath,
}

impl NodeBindingGenerator {
pub fn new(
out_dirname_api: utils::DirnameApi,
out_disable_auto_loading_lib: bool,
out_lib_disable_auto_loading: bool,
out_import_extension: utils::ImportExtension,
out_node_version: &str,
out_verbose_logs: bool,
out_lib_path: utils::LibPath,
) -> Self {
Self {
out_dirname_api,
out_disable_auto_loading_lib,
out_lib_disable_auto_loading,
out_import_extension,
out_node_version: out_node_version.into(),
out_verbose_logs,
out_lib_path,
}
}
}
Expand Down Expand Up @@ -70,21 +73,27 @@ impl BindingGenerator for NodeBindingGenerator {
for uniffi_bindgen::Component { ci, config: _, .. } in components {
let sys_ts_main_file_name = format!("{}-sys", ci.namespace().to_kebab_case());
let node_ts_main_file_name = format!("{}-node", ci.namespace().to_kebab_case());
let commonjs_shim_cts_main_file_name = format!("{}-commonjs-shim", ci.namespace().to_kebab_case());

let Bindings {
package_json_contents,
sys_ts_template_contents,
commonjs_shim_cts_template_contents,
node_ts_file_contents,
index_ts_file_contents,
} = generate_node_bindings(
&ci,
sys_ts_main_file_name.as_str(),
node_ts_main_file_name.as_str(),
self.out_dirname_api.clone(),
self.out_disable_auto_loading_lib,
self.out_import_extension.clone(),
self.out_node_version.as_str(),
self.out_verbose_logs,
GenerateNodeBindingsOptions {
sys_ts_main_file_name: sys_ts_main_file_name.as_str(),
node_ts_main_file_name: node_ts_main_file_name.as_str(),
commonjs_shim_cts_main_file_name: commonjs_shim_cts_main_file_name.as_str(),
out_dirname_api: self.out_dirname_api.clone(),
out_lib_disable_auto_loading: self.out_lib_disable_auto_loading,
out_import_extension: self.out_import_extension.clone(),
out_node_version: self.out_node_version.as_str(),
out_verbose_logs: self.out_verbose_logs,
out_lib_path: self.out_lib_path.clone(),
}
)?;

let package_json_path = settings.out_dir.join("package.json");
Expand All @@ -96,6 +105,11 @@ impl BindingGenerator for NodeBindingGenerator {
let sys_template_path = settings.out_dir.join(format!("{sys_ts_main_file_name}.ts"));
write_with_dirs(&sys_template_path, sys_ts_template_contents)?;

if !commonjs_shim_cts_template_contents.is_empty() {
let commonjs_shim_template_path = settings.out_dir.join(format!("{commonjs_shim_cts_main_file_name}.cts"));
write_with_dirs(&commonjs_shim_template_path, commonjs_shim_cts_template_contents)?;
}

let index_template_path = settings.out_dir.join("index.ts");
write_with_dirs(&index_template_path, index_ts_file_contents)?;
}
Expand Down
Loading