crudjt 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +15 -0
- package/.github/workflows/build.yml +42 -0
- package/CHANGELOG.md +12 -0
- package/Cache.js +82 -0
- package/Cargo.lock +176 -0
- package/Cargo.toml +16 -0
- package/LICENSE.txt +21 -0
- package/README.md +215 -0
- package/cargo.log +30 -0
- package/crudjt-1.0.0-beta.0.tgz +0 -0
- package/errors/internal_error.js +12 -0
- package/errors/invalid_state.js +12 -0
- package/errors.js +13 -0
- package/index.js +440 -0
- package/index.node +0 -0
- package/logos/buy_me_a_coffee_orange.svg +1 -0
- package/logos/crud_jt_logo.png +0 -0
- package/logos/crud_jt_logo_black.png +0 -0
- package/logos/crud_jt_logo_favicon_black.png +0 -0
- package/logos/crud_jt_logo_favicon_black_160.png +0 -0
- package/logos/crud_jt_logo_favicon_white.png +0 -0
- package/logos/crud_jt_logo_favicon_white_160.png +0 -0
- package/logos/crudjt_favicon_160x160_dark_on_white.svg +18 -0
- package/logos/crudjt_favicon_160x160_white.png +0 -0
- package/logos/crudjt_favicon_160x160_white_on_dark.svg +18 -0
- package/logos/crudjt_favicon_white_on_dark.png +0 -0
- package/logos/crudjt_logo_dark.png +0 -0
- package/logos/crudjt_logo_dark_on_white.svg +19 -0
- package/logos/crudjt_logo_white_on_dark.svg +26 -0
- package/native/linux/store_jt_arm64.so +0 -0
- package/native/linux/store_jt_x86_64.so +0 -0
- package/native/macos/store_jt_arm64.dylib +0 -0
- package/native/macos/store_jt_x86_64.dylib +0 -0
- package/native/windows/store_jt_arm64.dll +0 -0
- package/native/windows/store_jt_x86_64.dll +0 -0
- package/package/.github/workflows/build.yml +43 -0
- package/package/Cache.js +78 -0
- package/package/Cargo.lock +217 -0
- package/package/Cargo.toml +16 -0
- package/package/README.md +90 -0
- package/package/Validation.js +26 -0
- package/package/cargo.log +24 -0
- package/package/index.js +197 -0
- package/package/index.node +0 -0
- package/package/native/linux/store_jt_arm64.so +0 -0
- package/package/native/linux/store_jt_x86_64.so +0 -0
- package/package/native/macos/store_jt_arm64.dylib +0 -0
- package/package/native/macos/store_jt_x86_64.dylib +0 -0
- package/package/native/windows/store_jt_arm64.dll +0 -0
- package/package/native/windows/store_jt_x86_64.dll +0 -0
- package/package/package.json +26 -0
- package/package/src/lib.rs +190 -0
- package/package/test-neon-package/package-lock.json +942 -0
- package/package/test-neon-package/package.json +15 -0
- package/package/test-neon-package/test.js +178 -0
- package/package/test.js +202 -0
- package/package.json +41 -0
- package/src/lib.rs +288 -0
- package/test-neon-package/package-lock.json +1135 -0
- package/test-neon-package/package.json +15 -0
- package/test-neon-package/test.js +198 -0
- package/token_service.proto +47 -0
- package/token_service_client.js +33 -0
- package/validation.js +72 -0
package/src/lib.rs
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
use std::ffi::CString;
|
|
2
|
+
use core::ffi::CStr;
|
|
3
|
+
use std::os::raw::{c_char, c_int};
|
|
4
|
+
use neon::prelude::*;
|
|
5
|
+
use neon::types::buffer::TypedArray;
|
|
6
|
+
use std::ptr;
|
|
7
|
+
use libloading::{Library, Symbol};
|
|
8
|
+
use std::sync::{Mutex, Once};
|
|
9
|
+
use lazy_static::lazy_static;
|
|
10
|
+
use std::sync::Arc;
|
|
11
|
+
|
|
12
|
+
use std::path::{Path, PathBuf};
|
|
13
|
+
|
|
14
|
+
fn get_library_path() -> Result<PathBuf, String> {
|
|
15
|
+
let project_root = Path::new(env!("CARGO_MANIFEST_DIR"));
|
|
16
|
+
|
|
17
|
+
let library_subpath = {
|
|
18
|
+
#[cfg(target_os = "linux")]
|
|
19
|
+
{
|
|
20
|
+
if cfg!(target_arch = "x86_64") {
|
|
21
|
+
"native/linux/store_jt_x86_64.so"
|
|
22
|
+
} else if cfg!(target_arch = "aarch64") {
|
|
23
|
+
"native/linux/store_jt_arm64.so"
|
|
24
|
+
} else {
|
|
25
|
+
return Err("Unsupported architecture for Linux".to_string());
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[cfg(target_os = "macos")]
|
|
30
|
+
{
|
|
31
|
+
if cfg!(target_arch = "x86_64") {
|
|
32
|
+
"native/macos/store_jt_x86_64.dylib"
|
|
33
|
+
} else if cfg!(target_arch = "aarch64") {
|
|
34
|
+
"native/macos/store_jt_arm64.dylib"
|
|
35
|
+
} else {
|
|
36
|
+
return Err("Unsupported architecture for macOS".to_string());
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#[cfg(target_os = "windows")]
|
|
41
|
+
{
|
|
42
|
+
if cfg!(target_arch = "x86_64") {
|
|
43
|
+
"native/windows/store_jt_x86_64.dll"
|
|
44
|
+
} else if cfg!(target_arch = "aarch64") {
|
|
45
|
+
"native/windows/store_jt_arm64.dll"
|
|
46
|
+
} else {
|
|
47
|
+
return Err("Unsupported architecture for Windows".to_string());
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
|
|
52
|
+
{
|
|
53
|
+
return Err("Unsupported OS".to_string());
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
Ok(project_root.join(library_subpath))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
lazy_static! {
|
|
61
|
+
pub static ref LIB: Result<Library, String> = unsafe {
|
|
62
|
+
get_library_path().and_then(|path| {
|
|
63
|
+
Library::new(path)
|
|
64
|
+
.map_err(|e| format!("Failed to load library: {}", e))
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fn _start_store_jt(encrypted_key: *const c_char, store_jt_path: *const c_char) -> Result<*const c_char, Box<dyn std::error::Error>> {
|
|
70
|
+
let lib = match &*LIB {
|
|
71
|
+
Ok(lib) => lib,
|
|
72
|
+
Err(e) => return Err(e.clone().into())
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
unsafe {
|
|
76
|
+
let func: libloading::Symbol<unsafe extern fn(*const c_char, *const c_char) -> *const c_char> = lib.get(b"start_store_jt")?;
|
|
77
|
+
Ok(func(encrypted_key, store_jt_path))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fn _create(data: *const u8, len: usize, ttl: i64, silence_read: i32) -> Result<*const c_char, Box<dyn std::error::Error>> {
|
|
82
|
+
let lib = match &*LIB {
|
|
83
|
+
Ok(lib) => lib,
|
|
84
|
+
Err(e) => return Err(e.clone().into())
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
unsafe {
|
|
88
|
+
let func: libloading::Symbol<unsafe extern fn(*const u8, usize, i64, i32) -> *const c_char> = lib.get(b"__create")?;
|
|
89
|
+
Ok(func(data, len, ttl, silence_read))
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fn _read(token: *const c_char) -> Result<*const c_char, Box<dyn std::error::Error>> {
|
|
94
|
+
let lib = match &*LIB {
|
|
95
|
+
Ok(lib) => lib,
|
|
96
|
+
Err(e) => return Err(e.clone().into())
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
unsafe {
|
|
100
|
+
let func: libloading::Symbol<unsafe extern fn(*const c_char) -> *const c_char> = lib.get(b"__read")?;
|
|
101
|
+
let result = func(token);
|
|
102
|
+
|
|
103
|
+
if result.is_null() {
|
|
104
|
+
return Ok(ptr::null());
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Ok(func(token))
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fn _update(token: *const c_char, data: *const u8, len: usize, ttl: i64, silence_read: i32) -> Result<*const c_int, Box<dyn std::error::Error>> {
|
|
112
|
+
let lib = match &*LIB {
|
|
113
|
+
Ok(lib) => lib,
|
|
114
|
+
Err(e) => return Err(e.clone().into())
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
unsafe {
|
|
118
|
+
let func: libloading::Symbol<unsafe extern fn(*const c_char, *const u8, usize, i64, i32) -> *const c_int> = lib.get(b"__update")?;
|
|
119
|
+
Ok(func(token, data, len, ttl, silence_read))
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fn _delete(token: *const c_char) -> Result<*const c_int, Box<dyn std::error::Error>> {
|
|
124
|
+
let lib = match &*LIB {
|
|
125
|
+
Ok(lib) => lib,
|
|
126
|
+
Err(e) => return Err(e.clone().into())
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
unsafe {
|
|
130
|
+
let func: libloading::Symbol<unsafe extern fn(*const c_char) -> *const c_int> = lib.get(b"__delete")?;
|
|
131
|
+
Ok(func(token))
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
136
|
+
fn call_start_store_jt(mut cx: FunctionContext) -> JsResult<JsString> {
|
|
137
|
+
let encrypted_key = cx.argument::<JsString>(0)?.value(&mut cx);
|
|
138
|
+
let c_encrypted_key = match CString::new(encrypted_key) {
|
|
139
|
+
Ok(c) => c,
|
|
140
|
+
Err(e) => return cx.throw_error(format!("Failed to create CString for key: {}", e)),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let c_path_to_db_opt: Option<CString> = match cx.argument_opt(1) {
|
|
144
|
+
Some(arg) => {
|
|
145
|
+
if let Ok(js_str) = arg.downcast::<JsString, _>(&mut cx) {
|
|
146
|
+
match CString::new(js_str.value(&mut cx)) {
|
|
147
|
+
Ok(c) => Some(c),
|
|
148
|
+
Err(e) => return cx.throw_error(format!("Failed to create CString for path_to_db: {}", e)),
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
None
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
None => None,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
let c_path_to_db = c_path_to_db_opt
|
|
158
|
+
.as_ref()
|
|
159
|
+
.map_or(std::ptr::null(), |c| c.as_ptr());
|
|
160
|
+
|
|
161
|
+
let result_ptr = match _start_store_jt(c_encrypted_key.as_ptr(), c_path_to_db) {
|
|
162
|
+
Ok(ptr) => ptr,
|
|
163
|
+
Err(e) => return cx.throw_error(format!("_start_store_jt failed: {}", e)),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
if result_ptr.is_null() {
|
|
167
|
+
return cx.throw_error("_start_store_jt returned null");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let result_str = unsafe { CStr::from_ptr(result_ptr).to_string_lossy().into_owned() };
|
|
171
|
+
|
|
172
|
+
Ok(cx.string(result_str))
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fn call_create(mut cx: FunctionContext) -> JsResult<JsString> {
|
|
176
|
+
let js_buffer = cx.argument::<JsBuffer>(0)?;
|
|
177
|
+
let data_size = cx.argument::<JsNumber>(1)?;
|
|
178
|
+
let data_usize = data_size.value(&mut cx) as usize;
|
|
179
|
+
|
|
180
|
+
let ttl = cx.argument::<JsNumber>(2)?;
|
|
181
|
+
let silence_read = cx.argument::<JsNumber>(3)?;
|
|
182
|
+
|
|
183
|
+
let ttl_int = ttl.value(&mut cx) as i64;
|
|
184
|
+
let silence_read_int = silence_read.value(&mut cx) as i32;
|
|
185
|
+
|
|
186
|
+
let data = js_buffer.as_slice(&cx);
|
|
187
|
+
let data_ptr: *const u8 = data.as_ptr();
|
|
188
|
+
|
|
189
|
+
let result_ptr = match _create(data_ptr, data_usize, ttl_int, silence_read_int) {
|
|
190
|
+
Ok(ptr) => ptr,
|
|
191
|
+
Err(e) => {
|
|
192
|
+
return cx.throw_error(format!("native call_create failed: {}", e));
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
unsafe {
|
|
197
|
+
let result_str = CStr::from_ptr(result_ptr).to_string_lossy().into_owned();
|
|
198
|
+
|
|
199
|
+
Ok(cx.string(result_str))
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
fn call_read(mut cx: FunctionContext) -> JsResult<JsValue> {
|
|
204
|
+
let token = cx.argument::<JsString>(0)?.value(&mut cx);
|
|
205
|
+
|
|
206
|
+
let c_token = match CString::new(token) {
|
|
207
|
+
Ok(c) => c,
|
|
208
|
+
Err(e) => return cx.throw_error(format!("Failed to create CString: {}", e)),
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
unsafe {
|
|
212
|
+
let result = match _read(c_token.as_ptr()) {
|
|
213
|
+
Ok(ptr) => ptr,
|
|
214
|
+
Err(e) => {
|
|
215
|
+
return cx.throw_error(format!("native call_read failed: {}", e));
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
if result.is_null() {
|
|
220
|
+
return Ok(cx.null().upcast());
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let result_str = CStr::from_ptr(result).to_string_lossy().into_owned();
|
|
224
|
+
Ok(cx.string(result_str).upcast())
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
fn call_update(mut cx: FunctionContext) -> JsResult<JsBoolean> {
|
|
229
|
+
let token = cx.argument::<JsString>(0)?.value(&mut cx);
|
|
230
|
+
|
|
231
|
+
let c_token = match CString::new(token) {
|
|
232
|
+
Ok(c) => c,
|
|
233
|
+
Err(e) => return cx.throw_error(format!("Failed to create CString: {}", e)),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
let js_buffer = cx.argument::<JsBuffer>(1)?;
|
|
237
|
+
let data_size = cx.argument::<JsNumber>(2)?;
|
|
238
|
+
let data_usize = data_size.value(&mut cx) as usize;
|
|
239
|
+
|
|
240
|
+
let ttl = cx.argument::<JsNumber>(3)?;
|
|
241
|
+
let silence_read = cx.argument::<JsNumber>(4)?;
|
|
242
|
+
|
|
243
|
+
let ttl_int = ttl.value(&mut cx) as i64;
|
|
244
|
+
let silence_read_int = silence_read.value(&mut cx) as i32;
|
|
245
|
+
|
|
246
|
+
let data = js_buffer.as_slice(&cx);
|
|
247
|
+
let data_ptr: *const u8 = data.as_ptr();
|
|
248
|
+
|
|
249
|
+
let output: *const c_int = match _update(c_token.as_ptr(), data_ptr, data_usize, ttl_int, silence_read_int) {
|
|
250
|
+
Ok(ptr) => ptr,
|
|
251
|
+
Err(e) => {
|
|
252
|
+
return cx.throw_error(format!("native call_update failed: {}", e));
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
let bool: bool = output as usize == 1;
|
|
256
|
+
|
|
257
|
+
Ok(cx.boolean(bool))
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
fn call_delete(mut cx: FunctionContext) -> JsResult<JsBoolean> {
|
|
261
|
+
let token = cx.argument::<JsString>(0)?.value(&mut cx);
|
|
262
|
+
let c_token = match CString::new(token) {
|
|
263
|
+
Ok(c) => c,
|
|
264
|
+
Err(e) => return cx.throw_error(format!("Failed to create CString: {}", e)),
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
let output: *const c_int = match _delete(c_token.as_ptr()) {
|
|
268
|
+
Ok(ptr) => ptr,
|
|
269
|
+
Err(e) => {
|
|
270
|
+
return cx.throw_error(format!("native call_delete failed: {}", e));
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
let bool: bool = output as usize == 1;
|
|
274
|
+
|
|
275
|
+
Ok(cx.boolean(bool))
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
#[neon::main]
|
|
279
|
+
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
|
280
|
+
cx.export_function("start_store_jt", call_start_store_jt)?;
|
|
281
|
+
|
|
282
|
+
cx.export_function("create", call_create)?;
|
|
283
|
+
cx.export_function("read", call_read)?;
|
|
284
|
+
cx.export_function("update", call_update)?;
|
|
285
|
+
cx.export_function("delete", call_delete)?;
|
|
286
|
+
|
|
287
|
+
Ok(())
|
|
288
|
+
}
|