@ezetgalaxy/titan 26.13.8 → 26.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezetgalaxy/titan",
3
- "version": "26.13.8",
3
+ "version": "26.14.0",
4
4
  "description": "Titan Planet is a JavaScript-first backend framework that embeds JS actions into a Rust + Axum server and ships as a single native binary. Routes are compiled to static metadata; only actions run in the embedded JS runtime. No Node.js. No event loop in production.",
5
5
  "license": "ISC",
6
6
  "author": "ezetgalaxy",
@@ -325,14 +325,6 @@ export const time: typeof t.time;
325
325
  */
326
326
  export const url: typeof t.url;
327
327
 
328
- /**
329
- * HTTP response builder for controlling status codes, headers, and content types.
330
- *
331
- * Re-exported from the `t` global for module-style imports.
332
- * @see {@link TitanCore.ResponseModule} for full documentation.
333
- */
334
- export const response: typeof t.response;
335
-
336
328
  /**
337
329
  * Runtime validation utilities.
338
330
  *
@@ -1046,15 +1038,6 @@ declare global {
1046
1038
 
1047
1039
  /**
1048
1040
 
1049
-
1050
- /**
1051
- * HTTP response builder utilities.
1052
- * @see https://www.npmjs.com/package/@titanpl/13-titan-core — TitanCore Valid Extension
1053
- */
1054
- response: TitanCore.ResponseModule;
1055
-
1056
-
1057
-
1058
1041
  /**
1059
1042
  * Runtime validation utilities.
1060
1043
  *
@@ -1994,71 +1977,6 @@ declare global {
1994
1977
  SearchParams: any;
1995
1978
  }
1996
1979
 
1997
-
1998
-
1999
- interface ResponseModule {
2000
-
2001
- /**
2002
- * Return a JSON response.
2003
- * Body is automatically JSON.stringify-ed.
2004
- *
2005
- * @example
2006
- * ```js
2007
- * return t.response.json({ ok: true });
2008
- * ```
2009
- */
2010
- json(
2011
- data: any,
2012
- status?: number,
2013
- extraHeaders?: Record<string, string>
2014
- ): TitanResponse;
2015
-
2016
- /**
2017
- * Return a plain-text response.
2018
- * Content-Type: text/plain
2019
- *
2020
- * @example
2021
- * ```js
2022
- * return t.response.text("Hello World");
2023
- * ```
2024
- */
2025
- text(
2026
- content: string,
2027
- status?: number,
2028
- extraHeaders?: Record<string, string>
2029
- ): TitanResponse;
2030
-
2031
- /**
2032
- * Return an HTML response.
2033
- * Content-Type: text/html
2034
- *
2035
- * @example
2036
- * ```js
2037
- * return t.response.html("<h1>Hello</h1>");
2038
- * ```
2039
- */
2040
- html(
2041
- content: string,
2042
- status?: number,
2043
- extraHeaders?: Record<string, string>
2044
- ): TitanResponse;
2045
-
2046
- /**
2047
- * Return a redirect response.
2048
- * Defaults to HTTP 302.
2049
- *
2050
- * @example
2051
- * ```js
2052
- * return t.response.redirect("/login");
2053
- * ```
2054
- */
2055
- redirect(
2056
- url: string,
2057
- status?: number,
2058
- extraHeaders?: Record<string, string>
2059
- ): TitanResponse;
2060
- }
2061
-
2062
1980
  }
2063
1981
  }
2064
1982
 
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "include": [
10
10
  "index.js",
11
- "node_modules/titan-sdk/index.d.ts"
11
+ "node_modules/titan-sdk/index.d.ts",
12
+ "node_modules/**/titan-ext.d.ts"
12
13
  ]
13
14
  }
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "include": [
23
23
  "app/**/*",
24
- "titan/**/*"
24
+ "titan/**/*",
25
+ "node_modules/**/titan-ext.d.ts"
25
26
  ]
26
27
  }
@@ -16,19 +16,15 @@ pub struct Registry {
16
16
  pub _libs: Vec<Library>,
17
17
  pub modules: Vec<ModuleDef>,
18
18
  pub natives: Vec<NativeFnEntry>,
19
- pub v8_natives: Vec<usize>,
20
19
  }
21
20
 
22
-
23
21
  #[derive(Clone)]
24
22
  pub struct ModuleDef {
25
23
  pub name: String,
26
24
  pub js: String,
27
25
  pub native_indices: HashMap<String, usize>,
28
- pub v8_native_indices: HashMap<String, usize>,
29
26
  }
30
27
 
31
-
32
28
  #[derive(Clone, Debug, PartialEq)]
33
29
  pub enum ParamType {
34
30
  String, F64, Bool, Json, Buffer,
@@ -60,18 +56,9 @@ struct TitanConfig {
60
56
  #[derive(serde::Deserialize)]
61
57
  struct TitanNativeConfig {
62
58
  path: String,
63
- #[serde(default)]
64
59
  functions: HashMap<String, TitanNativeFunc>,
65
- #[serde(default)]
66
- v8_functions: HashMap<String, TitanV8Func>,
67
60
  }
68
61
 
69
- #[derive(serde::Deserialize)]
70
- struct TitanV8Func {
71
- symbol: String,
72
- }
73
-
74
-
75
62
  #[derive(serde::Deserialize)]
76
63
  struct TitanNativeFunc {
77
64
  symbol: String,
@@ -108,8 +95,6 @@ pub fn load_project_extensions(root: PathBuf) {
108
95
  let mut modules = Vec::new();
109
96
  let mut libs = Vec::new();
110
97
  let mut all_natives = Vec::new();
111
- let mut all_v8_natives = Vec::new();
112
-
113
98
 
114
99
  let mut node_modules = root.join("node_modules");
115
100
  if !node_modules.exists() {
@@ -120,8 +105,7 @@ pub fn load_project_extensions(root: PathBuf) {
120
105
  }
121
106
 
122
107
  // Generic scanner helper
123
- let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>, all_v8_natives: &mut Vec<usize>| {
124
-
108
+ let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>| {
125
109
  if !path.exists() { return; }
126
110
  for entry in WalkDir::new(&path).follow_links(true).min_depth(1).max_depth(4) {
127
111
  let entry = match entry { Ok(e) => e, Err(_) => continue };
@@ -133,9 +117,7 @@ pub fn load_project_extensions(root: PathBuf) {
133
117
  Err(_) => continue,
134
118
  };
135
119
  let mut mod_natives_map = HashMap::new();
136
- let mut mod_v8_natives_map = HashMap::new();
137
120
  if let Some(native_conf) = config.native {
138
-
139
121
  let lib_path = dir.join(&native_conf.path);
140
122
  unsafe {
141
123
  // Try loading library
@@ -144,28 +126,17 @@ pub fn load_project_extensions(root: PathBuf) {
144
126
  // But usually absolute path from `dir` works.
145
127
  match lib_load {
146
128
  Ok(lib) => {
147
- for (fn_name, fn_conf) in &native_conf.functions {
129
+ for (fn_name, fn_conf) in native_conf.functions {
148
130
  let params = fn_conf.parameters.iter().map(|p| parse_type(&p.to_lowercase())).collect();
149
131
  let ret = parse_return(&fn_conf.result.to_lowercase());
150
132
  if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
151
133
  let idx = all_natives.len();
152
134
  all_natives.push(NativeFnEntry { symbol_ptr: *symbol as usize, sig: Signature { params, ret } });
153
- mod_natives_map.insert(fn_name.clone(), idx);
135
+ mod_natives_map.insert(fn_name, idx);
154
136
  } else {
155
137
  println!("{} {} {} -> {}", blue("[Titan]"), red("Symbol not found:"), fn_conf.symbol, config.name);
156
138
  }
157
139
  }
158
-
159
- for (fn_name, fn_conf) in &native_conf.v8_functions {
160
- if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
161
- let idx = all_v8_natives.len();
162
- all_v8_natives.push(*symbol as usize);
163
- mod_v8_natives_map.insert(fn_name.clone(), idx);
164
- } else {
165
- println!("{} {} {} -> {}", blue("[Titan]"), red("V8 Symbol not found:"), fn_conf.symbol, config.name);
166
- }
167
- }
168
-
169
140
  libs.push(lib);
170
141
  },
171
142
  Err(e) => {
@@ -175,13 +146,7 @@ pub fn load_project_extensions(root: PathBuf) {
175
146
  }
176
147
  }
177
148
  let js_path = dir.join(&config.main);
178
- modules.push(ModuleDef {
179
- name: config.name.clone(),
180
- js: fs::read_to_string(js_path).unwrap_or_default(),
181
- native_indices: mod_natives_map,
182
- v8_native_indices: mod_v8_natives_map
183
- });
184
-
149
+ modules.push(ModuleDef { name: config.name.clone(), js: fs::read_to_string(js_path).unwrap_or_default(), native_indices: mod_natives_map });
185
150
  println!("{} {} {}", blue("[Titan]"), green("Extension loaded:"), config.name);
186
151
  }
187
152
  }
@@ -189,18 +154,16 @@ pub fn load_project_extensions(root: PathBuf) {
189
154
 
190
155
  // Scan node_modules
191
156
  if node_modules.exists() {
192
- scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
157
+ scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives);
193
158
  }
194
159
 
195
-
196
160
  // Scan .ext (Production / Docker)
197
161
  let ext_dir = root.join(".ext");
198
162
  if ext_dir.exists() {
199
- scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
163
+ scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives);
200
164
  }
201
165
 
202
- *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives, v8_natives: all_v8_natives });
203
-
166
+ *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives });
204
167
  }
205
168
 
206
169
  pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local<v8::Object>, t_obj: v8::Local<v8::Object>) {
@@ -208,10 +171,9 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
208
171
  let invoke_key = v8_str(scope, "__titan_invoke_native");
209
172
  global.set(scope, invoke_key.into(), invoke_fn.into());
210
173
 
211
- let (modules, v8_native_ptrs) = if let Ok(guard) = REGISTRY.lock() {
212
- (guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default(), guard.as_ref().map(|r| r.v8_natives.clone()).unwrap_or_default())
213
- } else { (vec![], vec![]) };
214
-
174
+ let modules = if let Ok(guard) = REGISTRY.lock() {
175
+ guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default()
176
+ } else { vec![] };
215
177
 
216
178
  for module in modules {
217
179
  let mod_obj = v8::Object::new(scope);
@@ -225,24 +187,6 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
225
187
  }
226
188
  }
227
189
  }
228
-
229
- for (fn_name, &idx) in &module.v8_native_indices {
230
- if let Some(&ptr) = v8_native_ptrs.get(idx) {
231
- if ptr != 0 {
232
- unsafe {
233
- let ext = v8::External::new(scope, ptr as *mut std::ffi::c_void);
234
- let templ = v8::FunctionTemplate::builder(native_invoke_v8_proxy)
235
- .data(ext.into())
236
- .build(scope);
237
-
238
- if let Some(func) = templ.get_function(scope) {
239
- let key = v8_str(scope, fn_name);
240
- mod_obj.set(scope, key.into(), func.into());
241
- }
242
- }
243
- }
244
- }
245
- }
246
190
  let mod_key = v8_str(scope, &module.name);
247
191
  t_obj.set(scope, mod_key.into(), mod_obj.into());
248
192
 
@@ -330,20 +274,6 @@ fn native_invoke_extension(scope: &mut v8::HandleScope, args: v8::FunctionCallba
330
274
  }
331
275
  }
332
276
 
333
- fn native_invoke_v8_proxy(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, retval: v8::ReturnValue) {
334
- let val = args.data();
335
- if let Ok(ext) = v8::Local::<v8::External>::try_from(val) {
336
- let ptr = ext.value() as *mut std::ffi::c_void;
337
- if !ptr.is_null() {
338
- unsafe {
339
- type TitanV8Handler = extern "C" fn(&mut v8::HandleScope, v8::FunctionCallbackArguments, v8::ReturnValue);
340
- let handler: TitanV8Handler = std::mem::transmute(ptr);
341
- handler(scope, args, retval);
342
- }
343
- }
344
- }
345
- }
346
-
347
277
  fn arg_from_v8(scope: &mut v8::HandleScope, val: v8::Local<v8::Value>, ty: &ParamType) -> serde_json::Value {
348
278
  match ty {
349
279
  ParamType::String => serde_json::Value::String(val.to_rust_string_lossy(scope)),
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "include": [
23
23
  "app/**/*",
24
- "titan/**/*"
24
+ "titan/**/*",
25
+ "node_modules/**/titan-ext.d.ts"
25
26
  ]
26
27
  }
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "include": [
24
24
  "app/**/*",
25
- "titan/**/*"
25
+ "titan/**/*",
26
+ "node_modules/**/titan-ext.d.ts"
26
27
  ]
27
28
  }
@@ -16,19 +16,15 @@ pub struct Registry {
16
16
  pub _libs: Vec<Library>,
17
17
  pub modules: Vec<ModuleDef>,
18
18
  pub natives: Vec<NativeFnEntry>,
19
- pub v8_natives: Vec<usize>,
20
19
  }
21
20
 
22
-
23
21
  #[derive(Clone)]
24
22
  pub struct ModuleDef {
25
23
  pub name: String,
26
24
  pub js: String,
27
25
  pub native_indices: HashMap<String, usize>,
28
- pub v8_native_indices: HashMap<String, usize>,
29
26
  }
30
27
 
31
-
32
28
  #[derive(Clone, Debug, PartialEq)]
33
29
  pub enum ParamType {
34
30
  String, F64, Bool, Json, Buffer,
@@ -60,18 +56,9 @@ struct TitanConfig {
60
56
  #[derive(serde::Deserialize)]
61
57
  struct TitanNativeConfig {
62
58
  path: String,
63
- #[serde(default)]
64
59
  functions: HashMap<String, TitanNativeFunc>,
65
- #[serde(default)]
66
- v8_functions: HashMap<String, TitanV8Func>,
67
60
  }
68
61
 
69
- #[derive(serde::Deserialize)]
70
- struct TitanV8Func {
71
- symbol: String,
72
- }
73
-
74
-
75
62
  #[derive(serde::Deserialize)]
76
63
  struct TitanNativeFunc {
77
64
  symbol: String,
@@ -108,8 +95,6 @@ pub fn load_project_extensions(root: PathBuf) {
108
95
  let mut modules = Vec::new();
109
96
  let mut libs = Vec::new();
110
97
  let mut all_natives = Vec::new();
111
- let mut all_v8_natives = Vec::new();
112
-
113
98
 
114
99
  let mut node_modules = root.join("node_modules");
115
100
  if !node_modules.exists() {
@@ -120,8 +105,7 @@ pub fn load_project_extensions(root: PathBuf) {
120
105
  }
121
106
 
122
107
  // Generic scanner helper
123
- let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>, all_v8_natives: &mut Vec<usize>| {
124
-
108
+ let scan_dir = |path: PathBuf, modules: &mut Vec<ModuleDef>, libs: &mut Vec<Library>, all_natives: &mut Vec<NativeFnEntry>| {
125
109
  if !path.exists() { return; }
126
110
  for entry in WalkDir::new(&path).follow_links(true).min_depth(1).max_depth(4) {
127
111
  let entry = match entry { Ok(e) => e, Err(_) => continue };
@@ -133,9 +117,7 @@ pub fn load_project_extensions(root: PathBuf) {
133
117
  Err(_) => continue,
134
118
  };
135
119
  let mut mod_natives_map = HashMap::new();
136
- let mut mod_v8_natives_map = HashMap::new();
137
120
  if let Some(native_conf) = config.native {
138
-
139
121
  let lib_path = dir.join(&native_conf.path);
140
122
  unsafe {
141
123
  // Try loading library
@@ -144,28 +126,17 @@ pub fn load_project_extensions(root: PathBuf) {
144
126
  // But usually absolute path from `dir` works.
145
127
  match lib_load {
146
128
  Ok(lib) => {
147
- for (fn_name, fn_conf) in &native_conf.functions {
129
+ for (fn_name, fn_conf) in native_conf.functions {
148
130
  let params = fn_conf.parameters.iter().map(|p| parse_type(&p.to_lowercase())).collect();
149
131
  let ret = parse_return(&fn_conf.result.to_lowercase());
150
132
  if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
151
133
  let idx = all_natives.len();
152
134
  all_natives.push(NativeFnEntry { symbol_ptr: *symbol as usize, sig: Signature { params, ret } });
153
- mod_natives_map.insert(fn_name.clone(), idx);
135
+ mod_natives_map.insert(fn_name, idx);
154
136
  } else {
155
137
  println!("{} {} {} -> {}", blue("[Titan]"), red("Symbol not found:"), fn_conf.symbol, config.name);
156
138
  }
157
139
  }
158
-
159
- for (fn_name, fn_conf) in &native_conf.v8_functions {
160
- if let Ok(symbol) = lib.get::<*const ()>(fn_conf.symbol.as_bytes()) {
161
- let idx = all_v8_natives.len();
162
- all_v8_natives.push(*symbol as usize);
163
- mod_v8_natives_map.insert(fn_name.clone(), idx);
164
- } else {
165
- println!("{} {} {} -> {}", blue("[Titan]"), red("V8 Symbol not found:"), fn_conf.symbol, config.name);
166
- }
167
- }
168
-
169
140
  libs.push(lib);
170
141
  },
171
142
  Err(e) => {
@@ -175,13 +146,7 @@ pub fn load_project_extensions(root: PathBuf) {
175
146
  }
176
147
  }
177
148
  let js_path = dir.join(&config.main);
178
- modules.push(ModuleDef {
179
- name: config.name.clone(),
180
- js: fs::read_to_string(js_path).unwrap_or_default(),
181
- native_indices: mod_natives_map,
182
- v8_native_indices: mod_v8_natives_map
183
- });
184
-
149
+ modules.push(ModuleDef { name: config.name.clone(), js: fs::read_to_string(js_path).unwrap_or_default(), native_indices: mod_natives_map });
185
150
  println!("{} {} {}", blue("[Titan]"), green("Extension loaded:"), config.name);
186
151
  }
187
152
  }
@@ -189,18 +154,16 @@ pub fn load_project_extensions(root: PathBuf) {
189
154
 
190
155
  // Scan node_modules
191
156
  if node_modules.exists() {
192
- scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
157
+ scan_dir(node_modules, &mut modules, &mut libs, &mut all_natives);
193
158
  }
194
159
 
195
-
196
160
  // Scan .ext (Production / Docker)
197
161
  let ext_dir = root.join(".ext");
198
162
  if ext_dir.exists() {
199
- scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives, &mut all_v8_natives);
163
+ scan_dir(ext_dir, &mut modules, &mut libs, &mut all_natives);
200
164
  }
201
165
 
202
- *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives, v8_natives: all_v8_natives });
203
-
166
+ *REGISTRY.lock().unwrap() = Some(Registry { _libs: libs, modules, natives: all_natives });
204
167
  }
205
168
 
206
169
  pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local<v8::Object>, t_obj: v8::Local<v8::Object>) {
@@ -208,10 +171,9 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
208
171
  let invoke_key = v8_str(scope, "__titan_invoke_native");
209
172
  global.set(scope, invoke_key.into(), invoke_fn.into());
210
173
 
211
- let (modules, v8_native_ptrs) = if let Ok(guard) = REGISTRY.lock() {
212
- (guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default(), guard.as_ref().map(|r| r.v8_natives.clone()).unwrap_or_default())
213
- } else { (vec![], vec![]) };
214
-
174
+ let modules = if let Ok(guard) = REGISTRY.lock() {
175
+ guard.as_ref().map(|r| r.modules.clone()).unwrap_or_default()
176
+ } else { vec![] };
215
177
 
216
178
  for module in modules {
217
179
  let mod_obj = v8::Object::new(scope);
@@ -225,24 +187,6 @@ pub fn inject_external_extensions(scope: &mut v8::HandleScope, global: v8::Local
225
187
  }
226
188
  }
227
189
  }
228
-
229
- for (fn_name, &idx) in &module.v8_native_indices {
230
- if let Some(&ptr) = v8_native_ptrs.get(idx) {
231
- if ptr != 0 {
232
- unsafe {
233
- let ext = v8::External::new(scope, ptr as *mut std::ffi::c_void);
234
- let templ = v8::FunctionTemplate::builder(native_invoke_v8_proxy)
235
- .data(ext.into())
236
- .build(scope);
237
-
238
- if let Some(func) = templ.get_function(scope) {
239
- let key = v8_str(scope, fn_name);
240
- mod_obj.set(scope, key.into(), func.into());
241
- }
242
- }
243
- }
244
- }
245
- }
246
190
  let mod_key = v8_str(scope, &module.name);
247
191
  t_obj.set(scope, mod_key.into(), mod_obj.into());
248
192
 
@@ -330,20 +274,6 @@ fn native_invoke_extension(scope: &mut v8::HandleScope, args: v8::FunctionCallba
330
274
  }
331
275
  }
332
276
 
333
- fn native_invoke_v8_proxy(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, retval: v8::ReturnValue) {
334
- let val = args.data();
335
- if let Ok(ext) = v8::Local::<v8::External>::try_from(val) {
336
- let ptr = ext.value() as *mut std::ffi::c_void;
337
- if !ptr.is_null() {
338
- unsafe {
339
- type TitanV8Handler = extern "C" fn(&mut v8::HandleScope, v8::FunctionCallbackArguments, v8::ReturnValue);
340
- let handler: TitanV8Handler = std::mem::transmute(ptr);
341
- handler(scope, args, retval);
342
- }
343
- }
344
- }
345
- }
346
-
347
277
  fn arg_from_v8(scope: &mut v8::HandleScope, val: v8::Local<v8::Value>, ty: &ParamType) -> serde_json::Value {
348
278
  match ty {
349
279
  ParamType::String => serde_json::Value::String(val.to_rust_string_lossy(scope)),
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "include": [
24
24
  "app/**/*",
25
- "titan/**/*"
25
+ "titan/**/*",
26
+ "node_modules/**/titan-ext.d.ts"
26
27
  ]
27
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "titanpl-sdk",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
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",