titanpl-sdk 0.2.0 → 0.2.1

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/index.d.ts CHANGED
@@ -5,6 +5,10 @@ declare global {
5
5
  * Titan Runtime Global Object
6
6
  */
7
7
  const t: Titan.Runtime;
8
+ /**
9
+ * Titan Runtime Global Object
10
+ */
11
+ const Titan: Titan.Runtime;
8
12
  }
9
13
 
10
14
  export namespace Titan {
@@ -18,7 +22,7 @@ export namespace Titan {
18
22
  * Read file content
19
23
  */
20
24
  read(path: string): string;
21
-
25
+
22
26
  /**
23
27
  * Fetch API wrapper
24
28
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "titanpl-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Development SDK for Titan Planet. Provides TypeScript type definitions for the global 't' runtime object and a 'lite' test-harness runtime for building and verifying extensions.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -535,7 +535,13 @@ fn js_from_value<'a>(
535
535
  val: serde_json::Value,
536
536
  ) -> v8::Local<'a, v8::Value> {
537
537
  match ret_type {
538
- ReturnType::String => v8::String::new(scope, val.as_str().unwrap_or("")).unwrap().into(),
538
+ ReturnType::String => {
539
+ let s = match val.as_str() {
540
+ Some(x) => x,
541
+ None => "",
542
+ };
543
+ v8::String::new(scope, s).unwrap().into()
544
+ },
539
545
  ReturnType::F64 => v8::Number::new(scope, val.as_f64().unwrap_or(0.0)).into(),
540
546
  ReturnType::Bool => v8::Boolean::new(scope, val.as_bool().unwrap_or(false)).into(),
541
547
  ReturnType::Json => {
@@ -566,10 +572,32 @@ fn js_from_value<'a>(
566
572
  macro_rules! dispatch_ret {
567
573
  ($ptr:expr, $ret:expr, ($($arg_ty:ty),*), ($($arg:expr),*)) => {
568
574
  match $ret {
569
- ReturnType::String => { let f: extern "C" fn($($arg_ty),*) -> String; f = std::mem::transmute($ptr); serde_json::Value::String(f($($arg),*)) },
575
+ ReturnType::String => {
576
+ let f: extern "C" fn($($arg_ty),*) -> *mut std::os::raw::c_char;
577
+ f = std::mem::transmute($ptr);
578
+ let ptr = f($($arg),*);
579
+ if ptr.is_null() {
580
+ serde_json::Value::String(String::new())
581
+ } else {
582
+ let s = unsafe { std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned() };
583
+ // We leak the pointer here because we don't have a shared allocator/free function.
584
+ // This prevents the double-free/heap corruption crash.
585
+ serde_json::Value::String(s)
586
+ }
587
+ },
570
588
  ReturnType::F64 => { let f: extern "C" fn($($arg_ty),*) -> f64; f = std::mem::transmute($ptr); serde_json::json!(f($($arg),*)) },
571
589
  ReturnType::Bool => { let f: extern "C" fn($($arg_ty),*) -> bool; f = std::mem::transmute($ptr); serde_json::json!(f($($arg),*)) },
572
- ReturnType::Json => { let f: extern "C" fn($($arg_ty),*) -> serde_json::Value; f = std::mem::transmute($ptr); f($($arg),*) },
590
+ ReturnType::Json => {
591
+ let f: extern "C" fn($($arg_ty),*) -> *mut std::os::raw::c_char;
592
+ f = std::mem::transmute($ptr);
593
+ let ptr = f($($arg),*);
594
+ if ptr.is_null() {
595
+ serde_json::Value::Null
596
+ } else {
597
+ let s = unsafe { std::ffi::CStr::from_ptr(ptr).to_string_lossy().into_owned() };
598
+ serde_json::from_str(&s).unwrap_or(serde_json::Value::Null)
599
+ }
600
+ },
573
601
  ReturnType::Buffer => { let f: extern "C" fn($($arg_ty),*) -> Vec<u8>; f = std::mem::transmute($ptr);
574
602
  let v = f($($arg),*);
575
603
  serde_json::Value::Array(v.into_iter().map(serde_json::Value::from).collect())
@@ -619,10 +647,18 @@ fn native_invoke_extension(scope: &mut v8::HandleScope, args: v8::FunctionCallba
619
647
  1 => {
620
648
  let v0 = vals.remove(0);
621
649
  match sig.params[0] {
622
- ParamType::String => { let a0 = v0.as_str().unwrap_or("").to_string(); dispatch_ret!(ptr, sig.ret, (String), (a0)) },
650
+ ParamType::String => {
651
+ let s = v0.as_str().unwrap_or("").to_string();
652
+ let c = std::ffi::CString::new(s).unwrap();
653
+ dispatch_ret!(ptr, sig.ret, (*const std::os::raw::c_char), (c.as_ptr()))
654
+ },
623
655
  ParamType::F64 => { let a0 = v0.as_f64().unwrap_or(0.0); dispatch_ret!(ptr, sig.ret, (f64), (a0)) },
624
656
  ParamType::Bool => { let a0 = v0.as_bool().unwrap_or(false); dispatch_ret!(ptr, sig.ret, (bool), (a0)) },
625
- ParamType::Json => { let a0 = v0; dispatch_ret!(ptr, sig.ret, (serde_json::Value), (a0)) },
657
+ ParamType::Json => {
658
+ let s = v0.to_string();
659
+ let c = std::ffi::CString::new(s).unwrap();
660
+ dispatch_ret!(ptr, sig.ret, (*const std::os::raw::c_char), (c.as_ptr()))
661
+ },
626
662
  ParamType::Buffer => {
627
663
  // Extract vec u8
628
664
  let a0: Vec<u8> = if let Some(arr) = v0.as_array() {
@@ -637,14 +673,17 @@ fn native_invoke_extension(scope: &mut v8::HandleScope, args: v8::FunctionCallba
637
673
  let v1 = vals.remove(0);
638
674
  match (sig.params[0].clone(), sig.params[1].clone()) { // Clone to satisfy borrow checker if needed
639
675
  (ParamType::String, ParamType::String) => {
640
- let a0 = v0.as_str().unwrap_or("").to_string();
641
- let a1 = v1.as_str().unwrap_or("").to_string();
642
- dispatch_ret!(ptr, sig.ret, (String, String), (a0, a1))
676
+ let s0 = v0.as_str().unwrap_or("").to_string();
677
+ let c0 = std::ffi::CString::new(s0).unwrap();
678
+ let s1 = v1.as_str().unwrap_or("").to_string();
679
+ let c1 = std::ffi::CString::new(s1).unwrap();
680
+ dispatch_ret!(ptr, sig.ret, (*const std::os::raw::c_char, *const std::os::raw::c_char), (c0.as_ptr(), c1.as_ptr()))
643
681
  },
644
682
  (ParamType::String, ParamType::F64) => {
645
- let a0 = v0.as_str().unwrap_or("").to_string();
683
+ let s0 = v0.as_str().unwrap_or("").to_string();
684
+ let c0 = std::ffi::CString::new(s0).unwrap();
646
685
  let a1 = v1.as_f64().unwrap_or(0.0);
647
- dispatch_ret!(ptr, sig.ret, (String, f64), (a0, a1))
686
+ dispatch_ret!(ptr, sig.ret, (*const std::os::raw::c_char, f64), (c0.as_ptr(), a1))
648
687
  },
649
688
  // Add more combinations as needed.
650
689
  _ => { println!("Unsupported 2-arg signature"); serde_json::Value::Null }
@@ -803,4 +842,4 @@ pub fn inject_extensions(scope: &mut v8::HandleScope, global: v8::Local<v8::Obje
803
842
 
804
843
  let t_key = v8_str(scope, "t");
805
844
  global.set(scope, t_key.into(), t_obj.into());
806
- }
845
+ }
@@ -1,3 +0,0 @@
1
- node_modules
2
- npm-debug.log
3
- .git
@@ -1,53 +0,0 @@
1
- # ================================================================
2
- # STAGE 1 — Build Titan (JS → Rust)
3
- # ================================================================
4
- FROM rust:1.91.1 AS builder
5
-
6
- # Install Node for Titan CLI + bundler
7
- RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
8
- && apt-get install -y nodejs
9
-
10
- # Install Titan CLI (latest)
11
- RUN npm install -g @ezetgalaxy/titan@latest
12
-
13
- WORKDIR /app
14
-
15
- # Copy project files
16
- COPY . .
17
-
18
- # Install JS dependencies (needed for Titan DSL + bundler)
19
- RUN npm install
20
-
21
- # Build Titan metadata + bundle JS actions
22
- RUN titan build
23
-
24
- # Build Rust binary
25
- RUN cd server && cargo build --release
26
-
27
-
28
-
29
- # ================================================================
30
- # STAGE 2 — Runtime Image (Lightweight)
31
- # ================================================================
32
- FROM debian:stable-slim
33
-
34
- WORKDIR /app
35
-
36
- # Copy Rust binary from builder stage
37
- COPY --from=builder /app/server/target/release/server ./titan-server
38
-
39
- # Copy Titan routing metadata
40
- COPY --from=builder /app/server/routes.json ./routes.json
41
- COPY --from=builder /app/server/action_map.json ./action_map.json
42
-
43
- # Copy Titan JS bundles
44
- RUN mkdir -p /app/actions
45
- COPY --from=builder /app/server/actions /app/actions
46
-
47
- COPY --from=builder /app/db /app/assets
48
-
49
- # Expose Titan port
50
- EXPOSE 3000
51
-
52
- # Start Titan
53
- CMD ["./titan-server"]