Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
authors = ["Patrick Thach <thachp@gmail.com>"]
edition = "2021"
name = "eventdbxjs"
version = "1.4.3"
version = "1.4.4"

[lib]
crate-type = ["cdylib", "rlib"]
Expand Down
2 changes: 2 additions & 0 deletions eventdbx.wasi-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ const {
export default __napiModule.exports
export const DbxClient = __napiModule.exports.DbxClient
export const createClient = __napiModule.exports.createClient
export const PayloadMode = __napiModule.exports.PayloadMode
export const Priority = __napiModule.exports.Priority
2 changes: 2 additions & 0 deletions eventdbx.wasi.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,5 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule
module.exports = __napiModule.exports
module.exports.DbxClient = __napiModule.exports.DbxClient
module.exports.createClient = __napiModule.exports.createClient
module.exports.PayloadMode = __napiModule.exports.PayloadMode
module.exports.Priority = __napiModule.exports.Priority
52 changes: 45 additions & 7 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export declare class DbxClient {
}

export interface AppendOptions {
payload?: any
metadata?: any
payload?: JsonValue
metadata?: JsonValue
note?: string
token?: string
publishTargets?: Array<PublishTargetOptions>
Expand All @@ -60,8 +60,8 @@ export interface ClientOptions {

export interface CreateAggregateOptions {
token?: string
payload?: any
metadata?: any
payload?: JsonValue
metadata?: JsonValue
note?: string
publishTargets?: Array<PublishTargetOptions>
}
Expand All @@ -77,6 +77,29 @@ export interface GetSnapshotOptions {
token?: string
}

export type JsonPatch =
JsonPatchAddReplaceTest | JsonPatchRemove | JsonPatchMoveCopy

export interface JsonPatchAddReplaceTest {
op: 'add' | 'replace' | 'test'
path: string
value: JsonValue
}

export interface JsonPatchMoveCopy {
op: 'move' | 'copy'
from: string
path: string
}

export interface JsonPatchRemove {
op: 'remove'
path: string
}

export type JsonValue =
any

export interface ListSnapshotsOptions {
aggregateType?: string
aggregateId?: string
Expand All @@ -100,16 +123,31 @@ export interface PageResult {
}

export interface PatchOptions {
metadata?: any
metadata?: JsonValue
note?: string
token?: string
publishTargets?: Array<PublishTargetOptions>
}

export declare const enum PayloadMode {
All = 'all',
EventOnly = 'event-only',
StateOnly = 'state-only',
SchemaOnly = 'schema-only',
EventAndSchema = 'event-and-schema',
ExtensionsOnly = 'extensions-only'
}

export declare const enum Priority {
High = 'high',
Normal = 'normal',
Low = 'low'
}

export interface PublishTargetOptions {
plugin: string
mode?: string
priority?: string
mode?: PayloadMode
priority?: Priority
}

export interface RetryOptions {
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,3 +574,5 @@ if (!nativeBinding) {
module.exports = nativeBinding
module.exports.DbxClient = nativeBinding.DbxClient
module.exports.createClient = nativeBinding.createClient
module.exports.PayloadMode = nativeBinding.PayloadMode
module.exports.Priority = nativeBinding.Priority
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eventdbxjs",
"version": "1.4.3",
"version": "1.4.4",
"description": "EventDBX client for Node.js",
"main": "index.js",
"types": "index.d.ts",
Expand Down
186 changes: 140 additions & 46 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,89 @@ use crate::plugin_api::{
use napi::bindgen_prelude::*;
use napi_derive::napi;
use serde::Deserialize;
use serde_json::{json, Map as JsonMap, Value as JsonValue};
use serde_json::{json, Map as JsonMap};
use tokio::sync::Mutex;
use tokio::time::sleep;

#[napi(js_name = "JsonValue")]
pub type JsonValue = serde_json::Value;

#[napi(object)]
pub struct JsonPatchAddReplaceTest {
#[napi(ts_type = "'add' | 'replace' | 'test'")]
pub op: String,
pub path: String,
#[napi(ts_type = "JsonValue")]
pub value: JsonValue,
}

#[napi(object)]
pub struct JsonPatchRemove {
#[napi(ts_type = "'remove'")]
pub op: String,
pub path: String,
}

#[napi(object)]
pub struct JsonPatchMoveCopy {
#[napi(ts_type = "'move' | 'copy'")]
pub op: String,
pub from: String,
pub path: String,
}

#[napi(js_name = "JsonPatch")]
pub type JsonPatch = Either3<JsonPatchAddReplaceTest, JsonPatchRemove, JsonPatchMoveCopy>;

#[napi(string_enum)]
pub enum PayloadMode {
#[napi(value = "all")]
All,
#[napi(value = "event-only")]
EventOnly,
#[napi(value = "state-only")]
StateOnly,
#[napi(value = "schema-only")]
SchemaOnly,
#[napi(value = "event-and-schema")]
EventAndSchema,
#[napi(value = "extensions-only")]
ExtensionsOnly,
}

impl PayloadMode {
fn as_str(&self) -> &'static str {
match self {
Self::All => "all",
Self::EventOnly => "event-only",
Self::StateOnly => "state-only",
Self::SchemaOnly => "schema-only",
Self::EventAndSchema => "event-and-schema",
Self::ExtensionsOnly => "extensions-only",
}
}
}

#[napi(string_enum)]
pub enum Priority {
#[napi(value = "high")]
High,
#[napi(value = "normal")]
Normal,
#[napi(value = "low")]
Low,
}

impl Priority {
fn as_str(&self) -> &'static str {
match self {
Self::High => "high",
Self::Normal => "normal",
Self::Low => "low",
}
}
}

#[derive(Clone, Debug)]
struct ClientConfig {
ip: String,
Expand Down Expand Up @@ -219,15 +298,19 @@ pub struct PageResult {
#[napi(object)]
pub struct PublishTargetOptions {
pub plugin: String,
#[napi(ts_type = "PayloadMode")]
pub mode: Option<String>,
#[napi(ts_type = "Priority")]
pub priority: Option<String>,
}

#[derive(Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[napi(object)]
pub struct AppendOptions {
#[napi(ts_type = "JsonValue")]
pub payload: Option<serde_json::Value>,
#[napi(ts_type = "JsonValue")]
pub metadata: Option<serde_json::Value>,
pub note: Option<String>,
pub token: Option<String>,
Expand All @@ -236,6 +319,7 @@ pub struct AppendOptions {

#[napi(object)]
pub struct PatchOptions {
#[napi(ts_type = "JsonValue")]
pub metadata: Option<serde_json::Value>,
pub note: Option<String>,
pub token: Option<String>,
Expand All @@ -247,7 +331,9 @@ pub struct PatchOptions {
#[napi(object)]
pub struct CreateAggregateOptions {
pub token: Option<String>,
#[napi(ts_type = "JsonValue")]
pub payload: Option<serde_json::Value>,
#[napi(ts_type = "JsonValue")]
pub metadata: Option<serde_json::Value>,
pub note: Option<String>,
pub publish_targets: Option<Vec<PublishTargetOptions>>,
Expand Down Expand Up @@ -1099,6 +1185,57 @@ pub fn create_client(options: Option<ClientOptions>) -> DbxClient {
DbxClient::new(options)
}

fn normalize_payload_mode(value: Option<String>) -> napi::Result<Option<String>> {
match value {
Some(value) => {
let normalized = value.trim().to_ascii_lowercase();
if normalized.is_empty() {
return Ok(None);
}
let matched = match normalized.as_str() {
"all" => Some(PayloadMode::All),
"event-only" => Some(PayloadMode::EventOnly),
"state-only" => Some(PayloadMode::StateOnly),
"schema-only" => Some(PayloadMode::SchemaOnly),
"event-and-schema" => Some(PayloadMode::EventAndSchema),
"extensions-only" => Some(PayloadMode::ExtensionsOnly),
_ => {
return Err(napi_err(
Status::InvalidArg,
"publish target mode must be one of: all, event-only, state-only, schema-only, event-and-schema, extensions-only",
))
}
};
Ok(matched.map(|mode| mode.as_str().to_owned()))
}
None => Ok(None),
}
}

fn normalize_priority(value: Option<String>) -> napi::Result<Option<String>> {
match value {
Some(value) => {
let normalized = value.trim().to_ascii_lowercase();
if normalized.is_empty() {
return Ok(None);
}
let matched = match normalized.as_str() {
"high" => Some(Priority::High),
"normal" => Some(Priority::Normal),
"low" => Some(Priority::Low),
_ => {
return Err(napi_err(
Status::InvalidArg,
"publish target priority must be one of: high, normal, low",
))
}
};
Ok(matched.map(|priority| priority.as_str().to_owned()))
}
None => Ok(None),
}
}

fn map_publish_targets(
publish_targets: Option<Vec<PublishTargetOptions>>,
) -> napi::Result<Option<Vec<PublishTargetSpec>>> {
Expand All @@ -1114,51 +1251,8 @@ fn map_publish_targets(
"publish target plugin is required",
));
}
let mode = match target.mode {
Some(value) => {
let trimmed = value.trim();
if trimmed.is_empty() {
None
} else {
let normalized = trimmed.to_ascii_lowercase();
match normalized.as_str() {
"all"
| "event-only"
| "state-only"
| "schema-only"
| "event-and-schema"
| "extensions-only" => Some(normalized),
_ => {
return Err(napi_err(
Status::InvalidArg,
"publish target mode must be one of: all, event-only, state-only, schema-only, event-and-schema, extensions-only",
))
}
}
}
}
None => None,
};
let priority = match target.priority {
Some(value) => {
let trimmed = value.trim();
if trimmed.is_empty() {
None
} else {
let normalized = trimmed.to_ascii_lowercase();
match normalized.as_str() {
"high" | "normal" | "low" => Some(normalized),
_ => {
return Err(napi_err(
Status::InvalidArg,
"publish target priority must be one of: high, normal, low",
))
}
}
}
}
None => None,
};
let mode = normalize_payload_mode(target.mode)?;
let priority = normalize_priority(target.priority)?;
Ok(PublishTargetSpec {
plugin,
mode,
Expand Down
Loading