Fresh Plugin API Macros
Proc macros for generating TypeScript definitions from Rust QuickJS API implementations.
Overview
This crate provides the #[plugin_api_impl] attribute macro that:
- Parses method signatures from a
JsEditorApiimpl block - Generates TypeScript type definitions (
.d.ts) - Automatically writes to
plugins/lib/fresh.d.tsduring compilation
Usage
use ;
Attributes
#[plugin_api_impl]
Apply to the impl block to enable TypeScript generation. Generates:
{IMPL_NAME}_TYPESCRIPT_DEFINITIONS: &str- Full.d.tscontent{IMPL_NAME}_JS_METHODS: &[&str]- List of all JS method names
#[plugin_api(...)]
Apply to individual methods for customization:
| Attribute | Description | Example |
|---|---|---|
skip |
Exclude from TypeScript | #[plugin_api(skip)] |
js_name = "..." |
Custom JS method name | #[plugin_api(js_name = "myMethod")] |
async_promise |
Returns Promise<T> |
#[plugin_api(async_promise)] |
async_thenable |
Returns ProcessHandle<T> (cancellable) |
#[plugin_api(async_thenable)] |
ts_type = "..." |
Custom TypeScript type for parameter | #[plugin_api(ts_type = "BufferInfo")] |
ts_return = "..." |
Custom TypeScript return type | #[plugin_api(ts_return = "string")] |
Type Mapping
| Rust Type | TypeScript Type | Notes |
|---|---|---|
u8, u16, u32, i32, etc. |
number |
All numeric types |
bool |
boolean |
|
String, &str |
string |
|
() |
void |
|
Option<T> |
T | null |
|
Vec<T> |
T[] |
|
rquickjs::Ctx<'js> |
(skipped) | Runtime context |
rquickjs::function::Opt<T> |
T? |
Optional parameter |
rquickjs::function::Rest<T> |
...T[] |
Variadic parameter |
rquickjs::Result<T> |
T |
Unwrapped |
rquickjs::Object<'js> |
Record<string, unknown> |
Use ts_type for specifics |
Async Methods
Async methods must be explicitly marked with #[plugin_api(async_promise)] or
#[plugin_api(async_thenable)]. There is no heuristic-based detection.
async_promise: For operations that complete with a resultasync_thenable: For cancellable operations (e.g., process spawning)
File Output
The macro automatically writes plugins/lib/fresh.d.ts when:
- Building the main crate (not the macro crate)
- The content has changed (avoids unnecessary rebuilds)
Design Principles
- Single Source of Truth: API defined once in Rust, TypeScript generated
- Explicit Over Implicit: No magic naming conventions, use attributes
- Deterministic Output: Same input always produces same output
- Preserve Original Code: Macro passes through impl block unchanged
- Clear Errors: Compile-time errors with helpful messages