#neon #frame #macro #apps #error

neon-frame

简化编写 Neon 应用的宏

2 个版本

0.1.1 2022年10月2日
0.1.0 2022年4月9日

#15 in #neon

Download history 23/week @ 2024-03-28 12/week @ 2024-04-04 31/week @ 2024-04-18 23/week @ 2024-04-25 4/week @ 2024-06-06

262 每月下载量

Apache-2.0

3KB
56

Neon Frame

"Crates",link="https://crates.io/crates/neon-frame" "Crates",link="https://crates.io/crates/neon-frame-macro" "npm (scoped)",link="https://npmjs.net.cn/package/@emeraldpay/neon-frame" "License"

一个高度定制的框架,用于构建基于 Neon 的 Rust 库以供 Node 使用。 Neon Frame 为 Rust 库提供一个标准的接口,以便响应 JavaScript。它负责处理错误并将响应转换回 JS。

Neon Frame 通过统一处理和转换结果和错误的方式简化了处理器的逻辑。现在您只需编写一个返回 Result<T, E> 的常规方法,它就会自动转换为 Node 并返回。

您可以选择使用通道,在这种情况下,Neon Frame 的 JavaScript 端会包装这些调用以获得一个普通的 Promise<T>

安装

.Cargo.toml [来源,toml]

[dependencies]
neon-frame = "0.1"
neon-frame-macro = "0.1"

.package.json [来源,json]

"dependencies": {
    "@emeraldpay/neon-frame": "^0.1.1"
}

.JS 导入 [来源,typescript]

import {neonFrameCall} from "@emeraldpay/neon-frame";

关于其用法的简要介绍

Rust 端

.现在您可以使用 #[neon_frame_fn] 宏标记一个函数:[来源,rust]

#[macro_use]
extern crate neon_frame_macro;

#[neon_frame_fn]
pub fn function_hello_world(_cx: &mut FunctionContext) -> Result<String, Errors> {
    Ok("Hello World".to_string())
}

该宏会自动将 Rust 类型转换为 Node 类型。除了 String 之外,它可以是任何 Serializable 结构。内部它只是将其包装成一个 JSON,这可以在 Node 端轻松处理。

JavaScript 端

[来源,typescript]

import {neonFrameDirectCall} from "@emeraldpay/neon-frame";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const addon = require('path/to/index.node');

export function helloWorld(): string {
    return neonFrameDirectCall<string>(addon, "function_hello_world", []);
}

如果您想在单独的线程中处理某些内容怎么办?例如,在 JavaScript 中异步地作为 Promise 获取它?

Rust 端使用通道

.使用 #[neon_frame_fn) 宏,它为您提供了一个回调函数:[来源,rust]

#[neon_frame_fn(channel)]
pub fn function_default_channel<H>(_cx: &mut FunctionContext, handler: H) -> Result<(), Errors>
    where
        H: FnOnce(Result<String, Errors>) + Send + 'static {

    std::thread::spawn(move || {
        let result = "Hello World".to_string();
        handler(Ok(result));
    });

    Ok(())
}

JavaScript 端使用 Promise

[来源,typescript]

import {neonFrameHandlerCall} from "@emeraldpay/neon-frame";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const addon = require('path/to/index.node');

export function default_channel(): Promise<string> {
    return neonFrameHandlerCall<string>(addon, "function_default_channel", []);
}

示例

/integration-tests 目录中,您可以找到交互测试,这些测试也可以作为实现示例。

如何工作及细节

作为响应,它使用类似于 JSON 的格式:[来源,json]

{
  "succeeded": true,
  "result": {
    "foo": "bar"
  }
}

其中 {"foo": "bar"} 表示实际结果。

如果方法失败,则返回类似的内容。

[source, json]

{
  "succeeded": false,
  "error": {
    "code": 100,
    "message": "Invalid input value for #0"
  }
}

作为一个 TypeScript 类型,它是

[来源,typescript]

type Status<T> = {
    succeeded: boolean,
    result: T | undefined,
    error: {
        code: number,
        message: string
    } | undefined
}

要使用 Neon Frame,只需在方法上添加注解 #[neon_frame_fn]

[source, rust]

#[neon_frame_fn]
pub fn hello_world(cx: &mut FunctionContext) -> Result<String, MyError> {
    Ok("Hello World".to_string())
}

注意:该方法预期使用 cx: &mut FunctionContext 而不是 mut cx: FunctionContext

此外,您需要编写一个从 MyError(usize, String) 的转换器。即实现以下 trait:impl From<MyError> for (usize, String)

[source, rust]

impl From<MyError> for (usize, String) {
    fn from(err: MyError) -> Self {
        todo!()
    }
}

除了标准的同步调用外,库还为 Channel 处理程序提供了相同的简化。在这种情况下,您使用 #[neon_frame_fn(channel)] 宏,并为处理响应的 FnOnce 函数提供额外的参数

[source, rust]

// function called from JS as:
//
// hello_world((x) => { ... });
//
#[neon_frame_fn(channel)]
pub fn hello_world<H>(cx: &mut FunctionContext, handler: H) -> Result<(), MyError>
    where
        H: FnOnce(Result<String, MyError>) + Send + 'static {

    std::thread::spawn(move || {
        handler(Ok("Hello World".to_string()));
    });
    Ok(())
}

默认情况下,它使用第一个 JS 参数作为处理函数。但如果您需要在不同的位置使用它,可以将其指定为参数,例如 #[neon_frame_fn(channel=2)]

[source, rust]

// function called from JS as:
//
// hello_world("hi", "there", (x) => { ... });
//
// i.e. with handler at the 3rd position, which is 2 starting from zero
//
#[neon_frame_fn(channel=2)]
pub fn hello_world<H>(cx: &mut FunctionContext, handler: H) -> Result<(), MyError>
    where
        H: FnOnce(Result<String, MyError>) + Send + 'static {

    todo!()
}

许可

版权所有 2022 EmeraldPay, Inc

根据 Apache License,版本 2.0(“许可”)许可;除非遵守许可,否则您不得使用此文件。您可以在以下位置获取许可副本:

https://apache.ac.cn/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则在许可下分发的软件按“原样”基础分发,不提供任何明示或暗示的保证或条件。有关许可的具体语言,请参阅许可。

依赖项

~0.6–1.4MB
~32K SLoC