mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 00:28:33 +00:00
feat: improve native
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -44,6 +44,7 @@ dependencies = [
|
|||||||
"docx-parser",
|
"docx-parser",
|
||||||
"infer",
|
"infer",
|
||||||
"nanoid",
|
"nanoid",
|
||||||
|
"napi",
|
||||||
"path-ext",
|
"path-ext",
|
||||||
"pdf-extract",
|
"pdf-extract",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
@@ -126,6 +127,7 @@ dependencies = [
|
|||||||
"affine_nbstore",
|
"affine_nbstore",
|
||||||
"affine_sqlite_v1",
|
"affine_sqlite_v1",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"mimalloc",
|
||||||
"napi",
|
"napi",
|
||||||
"napi-build",
|
"napi-build",
|
||||||
"napi-derive",
|
"napi-derive",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ crate-type = ["cdylib"]
|
|||||||
affine_common = { workspace = true, features = [
|
affine_common = { workspace = true, features = [
|
||||||
"doc-loader",
|
"doc-loader",
|
||||||
"hashcash",
|
"hashcash",
|
||||||
|
"napi",
|
||||||
"ydoc-loader",
|
"ydoc-loader",
|
||||||
] }
|
] }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use affine_common::doc_parser::{self, BlockInfo, CrawlResult, MarkdownResult, PageDocContent, WorkspaceDocContent};
|
use affine_common::{
|
||||||
|
doc_parser::{self, BlockInfo, CrawlResult, MarkdownResult, PageDocContent, WorkspaceDocContent},
|
||||||
|
napi_utils::map_napi_err,
|
||||||
|
};
|
||||||
use napi::bindgen_prelude::*;
|
use napi::bindgen_prelude::*;
|
||||||
use napi_derive::napi;
|
use napi_derive::napi;
|
||||||
|
|
||||||
@@ -95,22 +98,25 @@ impl From<CrawlResult> for NativeCrawlResult {
|
|||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn parse_doc_from_binary(doc_bin: Buffer, doc_id: String) -> Result<NativeCrawlResult> {
|
pub fn parse_doc_from_binary(doc_bin: Buffer, doc_id: String) -> Result<NativeCrawlResult> {
|
||||||
let result = doc_parser::parse_doc_from_binary(doc_bin.into(), doc_id)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::parse_doc_from_binary(doc_bin.into(), doc_id),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(result.into())
|
Ok(result.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn parse_page_doc(doc_bin: Buffer, max_summary_length: Option<i32>) -> Result<Option<NativePageDocContent>> {
|
pub fn parse_page_doc(doc_bin: Buffer, max_summary_length: Option<i32>) -> Result<Option<NativePageDocContent>> {
|
||||||
let result = doc_parser::parse_page_doc(doc_bin.into(), max_summary_length.map(|v| v as isize))
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::parse_page_doc(doc_bin.into(), max_summary_length.map(|v| v as isize)),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(result.map(Into::into))
|
Ok(result.map(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn parse_workspace_doc(doc_bin: Buffer) -> Result<Option<NativeWorkspaceDocContent>> {
|
pub fn parse_workspace_doc(doc_bin: Buffer) -> Result<Option<NativeWorkspaceDocContent>> {
|
||||||
let result =
|
let result = map_napi_err(doc_parser::parse_workspace_doc(doc_bin.into()), Status::GenericFailure)?;
|
||||||
doc_parser::parse_workspace_doc(doc_bin.into()).map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
|
||||||
Ok(result.map(Into::into))
|
Ok(result.map(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +127,19 @@ pub fn parse_doc_to_markdown(
|
|||||||
ai_editable: Option<bool>,
|
ai_editable: Option<bool>,
|
||||||
doc_url_prefix: Option<String>,
|
doc_url_prefix: Option<String>,
|
||||||
) -> Result<NativeMarkdownResult> {
|
) -> Result<NativeMarkdownResult> {
|
||||||
let result = doc_parser::parse_doc_to_markdown(doc_bin.into(), doc_id, ai_editable.unwrap_or(false), doc_url_prefix)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::parse_doc_to_markdown(doc_bin.into(), doc_id, ai_editable.unwrap_or(false), doc_url_prefix),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(result.into())
|
Ok(result.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn read_all_doc_ids_from_root_doc(doc_bin: Buffer, include_trash: Option<bool>) -> Result<Vec<String>> {
|
pub fn read_all_doc_ids_from_root_doc(doc_bin: Buffer, include_trash: Option<bool>) -> Result<Vec<String>> {
|
||||||
let result = doc_parser::get_doc_ids_from_binary(doc_bin.into(), include_trash.unwrap_or(false))
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::get_doc_ids_from_binary(doc_bin.into(), include_trash.unwrap_or(false)),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +154,10 @@ pub fn read_all_doc_ids_from_root_doc(doc_bin: Buffer, include_trash: Option<boo
|
|||||||
/// A Buffer containing the y-octo document update binary
|
/// A Buffer containing the y-octo document update binary
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn create_doc_with_markdown(title: String, markdown: String, doc_id: String) -> Result<Buffer> {
|
pub fn create_doc_with_markdown(title: String, markdown: String, doc_id: String) -> Result<Buffer> {
|
||||||
let result = doc_parser::build_full_doc(&title, &markdown, &doc_id)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::build_full_doc(&title, &markdown, &doc_id),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,8 +173,10 @@ pub fn create_doc_with_markdown(title: String, markdown: String, doc_id: String)
|
|||||||
/// A Buffer containing only the delta (changes) as a y-octo update binary
|
/// A Buffer containing only the delta (changes) as a y-octo update binary
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn update_doc_with_markdown(existing_binary: Buffer, new_markdown: String, doc_id: String) -> Result<Buffer> {
|
pub fn update_doc_with_markdown(existing_binary: Buffer, new_markdown: String, doc_id: String) -> Result<Buffer> {
|
||||||
let result = doc_parser::update_doc(&existing_binary, &new_markdown, &doc_id)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::update_doc(&existing_binary, &new_markdown, &doc_id),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,8 +191,10 @@ pub fn update_doc_with_markdown(existing_binary: Buffer, new_markdown: String, d
|
|||||||
/// A Buffer containing only the delta (changes) as a y-octo update binary
|
/// A Buffer containing only the delta (changes) as a y-octo update binary
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn update_doc_title(existing_binary: Buffer, title: String, doc_id: String) -> Result<Buffer> {
|
pub fn update_doc_title(existing_binary: Buffer, title: String, doc_id: String) -> Result<Buffer> {
|
||||||
let result = doc_parser::update_doc_title(&existing_binary, &doc_id, &title)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::update_doc_title(&existing_binary, &doc_id, &title),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,14 +218,16 @@ pub fn update_doc_properties(
|
|||||||
created_by: Option<String>,
|
created_by: Option<String>,
|
||||||
updated_by: Option<String>,
|
updated_by: Option<String>,
|
||||||
) -> Result<Buffer> {
|
) -> Result<Buffer> {
|
||||||
let result = doc_parser::update_doc_properties(
|
let result = map_napi_err(
|
||||||
&existing_binary,
|
doc_parser::update_doc_properties(
|
||||||
&properties_doc_id,
|
&existing_binary,
|
||||||
&target_doc_id,
|
&properties_doc_id,
|
||||||
created_by.as_deref(),
|
&target_doc_id,
|
||||||
updated_by.as_deref(),
|
created_by.as_deref(),
|
||||||
)
|
updated_by.as_deref(),
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,8 +243,10 @@ pub fn update_doc_properties(
|
|||||||
/// A Buffer containing the y-octo update binary to apply to the root doc
|
/// A Buffer containing the y-octo update binary to apply to the root doc
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn add_doc_to_root_doc(root_doc_bin: Buffer, doc_id: String, title: Option<String>) -> Result<Buffer> {
|
pub fn add_doc_to_root_doc(root_doc_bin: Buffer, doc_id: String, title: Option<String>) -> Result<Buffer> {
|
||||||
let result = doc_parser::add_doc_to_root_doc(root_doc_bin.into(), &doc_id, title.as_deref())
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::add_doc_to_root_doc(root_doc_bin.into(), &doc_id, title.as_deref()),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +261,9 @@ pub fn add_doc_to_root_doc(root_doc_bin: Buffer, doc_id: String, title: Option<S
|
|||||||
/// A Buffer containing the y-octo update binary to apply to the root doc
|
/// A Buffer containing the y-octo update binary to apply to the root doc
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn update_root_doc_meta_title(root_doc_bin: Buffer, doc_id: String, title: String) -> Result<Buffer> {
|
pub fn update_root_doc_meta_title(root_doc_bin: Buffer, doc_id: String, title: String) -> Result<Buffer> {
|
||||||
let result = doc_parser::update_root_doc_meta_title(&root_doc_bin, &doc_id, &title)
|
let result = map_napi_err(
|
||||||
.map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?;
|
doc_parser::update_root_doc_meta_title(&root_doc_bin, &doc_id, &title),
|
||||||
|
Status::GenericFailure,
|
||||||
|
)?;
|
||||||
Ok(Buffer::from(result))
|
Ok(Buffer::from(result))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use affine_common::doc_loader::Doc;
|
use affine_common::{doc_loader::Doc, napi_utils::map_napi_err};
|
||||||
use napi::{
|
use napi::{
|
||||||
Env, Result, Task,
|
Env, Result, Status, Task,
|
||||||
anyhow::anyhow,
|
|
||||||
bindgen_prelude::{AsyncTask, Buffer},
|
bindgen_prelude::{AsyncTask, Buffer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,7 +53,7 @@ impl Task for AsyncParseDocResponse {
|
|||||||
type JsValue = ParsedDoc;
|
type JsValue = ParsedDoc;
|
||||||
|
|
||||||
fn compute(&mut self) -> Result<Self::Output> {
|
fn compute(&mut self) -> Result<Self::Output> {
|
||||||
let doc = Doc::new(&self.file_path, &self.doc).map_err(|e| anyhow!(e))?;
|
let doc = map_napi_err(Doc::new(&self.file_path, &self.doc), Status::GenericFailure)?;
|
||||||
Ok(Document { inner: doc })
|
Ok(Document { inner: doc })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,8 @@ pub mod hashcash;
|
|||||||
pub mod html_sanitize;
|
pub mod html_sanitize;
|
||||||
pub mod tiktoken;
|
pub mod tiktoken;
|
||||||
|
|
||||||
use std::fmt::{Debug, Display};
|
use affine_common::napi_utils::map_napi_err;
|
||||||
|
use napi::{Result, Status, bindgen_prelude::*};
|
||||||
use napi::{Error, Result, Status, bindgen_prelude::*};
|
|
||||||
use y_octo::Doc;
|
use y_octo::Doc;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "arm"))]
|
#[cfg(not(target_arch = "arm"))]
|
||||||
@@ -21,35 +20,16 @@ static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate napi_derive;
|
extern crate napi_derive;
|
||||||
|
|
||||||
fn map_err_inner<T, E: Display + Debug>(v: std::result::Result<T, E>, status: Status) -> Result<T> {
|
|
||||||
match v {
|
|
||||||
Ok(val) => Ok(val),
|
|
||||||
Err(e) => {
|
|
||||||
dbg!(&e);
|
|
||||||
Err(Error::new(status, e.to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! map_err {
|
|
||||||
($val: expr) => {
|
|
||||||
map_err_inner($val, Status::GenericFailure)
|
|
||||||
};
|
|
||||||
($val: expr, $stauts: ident) => {
|
|
||||||
map_err_inner($val, $stauts)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merge updates in form like `Y.applyUpdate(doc, update)` way and return the
|
/// Merge updates in form like `Y.applyUpdate(doc, update)` way and return the
|
||||||
/// result binary.
|
/// result binary.
|
||||||
#[napi(catch_unwind)]
|
#[napi(catch_unwind)]
|
||||||
pub fn merge_updates_in_apply_way(updates: Vec<Buffer>) -> Result<Buffer> {
|
pub fn merge_updates_in_apply_way(updates: Vec<Buffer>) -> Result<Buffer> {
|
||||||
let mut doc = Doc::default();
|
let mut doc = Doc::default();
|
||||||
for update in updates {
|
for update in updates {
|
||||||
map_err!(doc.apply_update_from_binary_v1(update.as_ref()))?;
|
map_napi_err(doc.apply_update_from_binary_v1(update.as_ref()), Status::GenericFailure)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let buf = map_err!(doc.encode_update_v1())?;
|
let buf = map_napi_err(doc.encode_update_v1(), Status::GenericFailure)?;
|
||||||
|
|
||||||
Ok(buf.into())
|
Ok(buf.into())
|
||||||
}
|
}
|
||||||
@@ -59,3 +39,17 @@ pub const AFFINE_PRO_PUBLIC_KEY: Option<&'static str> = std::option_env!("AFFINE
|
|||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
pub const AFFINE_PRO_LICENSE_AES_KEY: Option<&'static str> = std::option_env!("AFFINE_PRO_LICENSE_AES_KEY");
|
pub const AFFINE_PRO_LICENSE_AES_KEY: Option<&'static str> = std::option_env!("AFFINE_PRO_LICENSE_AES_KEY");
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn merge_updates_reports_generic_failure() {
|
||||||
|
let err = match merge_updates_in_apply_way(vec![Buffer::from(vec![0])]) {
|
||||||
|
Ok(_) => panic!("expected error"),
|
||||||
|
Err(err) => err,
|
||||||
|
};
|
||||||
|
assert_eq!(err.status, Status::GenericFailure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ doc-loader = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
hashcash = ["chrono", "sha3", "rand"]
|
hashcash = ["chrono", "sha3", "rand"]
|
||||||
|
napi = ["dep:napi"]
|
||||||
tree-sitter = [
|
tree-sitter = [
|
||||||
"cc",
|
"cc",
|
||||||
"dep:tree-sitter",
|
"dep:tree-sitter",
|
||||||
@@ -53,6 +54,7 @@ chrono = { workspace = true, optional = true }
|
|||||||
docx-parser = { workspace = true, optional = true }
|
docx-parser = { workspace = true, optional = true }
|
||||||
infer = { workspace = true, optional = true }
|
infer = { workspace = true, optional = true }
|
||||||
nanoid = { workspace = true, optional = true }
|
nanoid = { workspace = true, optional = true }
|
||||||
|
napi = { workspace = true, optional = true }
|
||||||
path-ext = { workspace = true, optional = true }
|
path-ext = { workspace = true, optional = true }
|
||||||
pdf-extract = { workspace = true, optional = true }
|
pdf-extract = { workspace = true, optional = true }
|
||||||
pulldown-cmark = { workspace = true, optional = true }
|
pulldown-cmark = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -4,3 +4,5 @@ pub mod doc_loader;
|
|||||||
pub mod doc_parser;
|
pub mod doc_parser;
|
||||||
#[cfg(feature = "hashcash")]
|
#[cfg(feature = "hashcash")]
|
||||||
pub mod hashcash;
|
pub mod hashcash;
|
||||||
|
#[cfg(feature = "napi")]
|
||||||
|
pub mod napi_utils;
|
||||||
|
|||||||
22
packages/common/native/src/napi_utils.rs
Normal file
22
packages/common/native/src/napi_utils.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
use napi::{Error, Result, Status};
|
||||||
|
|
||||||
|
pub fn to_napi_error<E: Display + Debug>(err: E, status: Status) -> Error {
|
||||||
|
Error::new(status, err.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_napi_err<T, E: Display + Debug>(value: std::result::Result<T, E>, status: Status) -> Result<T> {
|
||||||
|
value.map_err(|err| to_napi_error(err, status))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn map_napi_err_keeps_message() {
|
||||||
|
let err = map_napi_err::<(), _>(Err("boom"), Status::GenericFailure).unwrap_err();
|
||||||
|
assert!(err.to_string().contains("boom"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user