@port-labs/jq-node-bindings 0.0.15-dev2 → 0.0.15-dev3

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/lib/jq.js CHANGED
@@ -15,7 +15,6 @@ class JqExecCompileError extends JqExecError {
15
15
  }
16
16
 
17
17
  const exec = (object, filter, {enableEnv = false, throwOnError = false} = {}) => {
18
- console.log("exec",object,filter)
19
18
  try {
20
19
  const data = nativeJq.execSync(JSON.stringify(object), formatFilter(filter, {enableEnv}))
21
20
 
@@ -29,7 +28,6 @@ const exec = (object, filter, {enableEnv = false, throwOnError = false} = {}) =>
29
28
  }
30
29
 
31
30
  const execAsync = async (object, filter, {enableEnv = false, throwOnError = false} = {}) => {
32
- console.log(object,filter)
33
31
  try {
34
32
  const data = await nativeJq.execAsync(JSON.stringify(object), formatFilter(filter, {enableEnv}))
35
33
  return data?.value;
@@ -119,7 +119,6 @@ const renderRecursivelyAsync = async(inputJson, template, execOptions = {}) => {
119
119
  `Evaluated object key should be undefined, null or string. Original key: ${key}, evaluated to: ${JSON.stringify(evaluatedKey)}`,
120
120
  );
121
121
  }
122
- console.log("evaluatedKey",evaluatedKey,value)
123
122
  return evaluatedKey ? [[evaluatedKey, await renderRecursivelyAsync(inputJson, value, execOptions)]] : [];
124
123
  });
125
124
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@port-labs/jq-node-bindings",
3
- "version": "v0.0.15-dev2",
3
+ "version": "v0.0.15-dev3",
4
4
  "description": "Node.js bindings for JQ",
5
- "jq-node-bindings": "0.0.15-dev2",
5
+ "jq-node-bindings": "0.0.15-dev3",
6
6
  "main": "lib/index.js",
7
7
  "scripts": {
8
8
  "configure": "node-gyp configure",
package/src/binding.cc CHANGED
@@ -9,23 +9,40 @@
9
9
  #include "src/binding.h"
10
10
 
11
11
 
12
- #ifdef DEBUG_MODE
13
- static bool debug_enabled = true;
14
- #else
15
- static bool debug_enabled = false;
16
- #endif
12
+ // #ifdef DEBUG_MODE
13
+ // static bool debug_enabled = true;
14
+ // #else
15
+ // static bool debug_enabled = false;
16
+ // #endif
17
+
18
+ // #define DEBUG_LOG(fmt, ...) \
19
+ // do { if (debug_enabled) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__); } while (0)
17
20
 
18
- #define DEBUG_LOG(fmt, ...) \
19
- do { if (debug_enabled) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__); } while (0)
21
+ // #define ASYNC_DEBUG_LOG(work, fmt, ...) \
22
+ // do { if (debug_enabled) printf("[DEBUG][ASYNC][%p] " fmt "\n", (jv*)work, ##__VA_ARGS__); } while (0)
20
23
 
21
- #define ASYNC_DEBUG_LOG(work, fmt, ...) \
22
- do { if (debug_enabled) printf("[DEBUG][ASYNC][%p] " fmt "\n", (jv*)work, ##__VA_ARGS__); } while (0)
24
+ // #define CACHE_DEBUG_LOG(cache, fmt, ...) \
25
+ // do { if (debug_enabled) printf("[DEBUG][CACHE][%p] " fmt "\n", (void*)cache, ##__VA_ARGS__); } while (0)
23
26
 
24
- #define CACHE_DEBUG_LOG(cache, fmt, ...) \
25
- do { if (debug_enabled) printf("[DEBUG][CACHE][%p] " fmt "\n", (void*)cache, ##__VA_ARGS__); } while (0)
27
+ // #define WRAPPER_DEBUG_LOG(wrapper, fmt, ...) \
28
+ // do { if (debug_enabled) printf("[DEBUG][WRAPPER:%p] " fmt "\n", (void*)wrapper, ##__VA_ARGS__); } while (0)
29
+ #ifdef ENABLE_DEBUG // We'll use ENABLE_DEBUG as our flag name
30
+ #define DEBUG_ENABLED 1
31
+ #else
32
+ #define DEBUG_ENABLED 0
33
+ #endif
26
34
 
27
- #define WRAPPER_DEBUG_LOG(wrapper, fmt, ...) \
28
- do { if (debug_enabled) printf("[DEBUG][WRAPPER:%p] " fmt "\n", (void*)wrapper, ##__VA_ARGS__); } while (0)
35
+ #ifdef ENABLE_DEBUG
36
+ #define DEBUG_LOG(fmt, ...) fprintf(stderr, "[DEBUG] " fmt "\n", ##__VA_ARGS__)
37
+ #define ASYNC_DEBUG_LOG(work, fmt, ...) fprintf(stderr, "[DEBUG][ASYNC][%p] " fmt "\n", (void*)work, ##__VA_ARGS__)
38
+ #define CACHE_DEBUG_LOG(cache, fmt, ...) fprintf(stderr, "[DEBUG][CACHE][%p] " fmt "\n", (void*)cache, ##__VA_ARGS__)
39
+ #define WRAPPER_DEBUG_LOG(wrapper, fmt, ...) fprintf(stderr, "[DEBUG][WRAPPER][%p] " fmt "\n", (void*)wrapper, ##__VA_ARGS__)
40
+ #else
41
+ #define DEBUG_LOG(fmt, ...) ((void)0)
42
+ #define ASYNC_DEBUG_LOG(work, fmt, ...) ((void)0)
43
+ #define CACHE_DEBUG_LOG(cache, fmt, ...) ((void)0)
44
+ #define WRAPPER_DEBUG_LOG(wrapper, fmt, ...) ((void)0)
45
+ #endif
29
46
 
30
47
  static size_t global_cache_size = 100;
31
48
 
@@ -81,7 +98,6 @@ struct JqFilterWrapper {
81
98
  public:
82
99
  std::string filter_name;
83
100
  std::list<JqFilterWrapper*>::iterator cache_pos;
84
-
85
101
  /* init mutex and set filter_name */
86
102
  explicit JqFilterWrapper(jq_state* jq_, std::string filter_name_) :
87
103
  filter_name(filter_name_),
@@ -124,7 +140,7 @@ private:
124
140
  pthread_mutex_t cache_mutex;
125
141
  std::list<JqFilterWrapper*> item_list;
126
142
  std::unordered_map<KEY_T, JqFilterWrapper*> item_map;
127
- std::unordered_map<JqFilterWrapper*, bool> is_item_in_use;
143
+ std::unordered_map<JqFilterWrapper*, size_t> item_refcnt;
128
144
 
129
145
  size_t cache_size;
130
146
 
@@ -139,8 +155,8 @@ private:
139
155
  auto last_it = item_list.end();
140
156
  last_it--;
141
157
  JqFilterWrapper* wrapper = *last_it;
142
- CACHE_DEBUG_LOG((void*)wrapper, "Examining wrapper: name='%s', is_in_use=%zu", wrapper->filter_name.c_str(), is_item_in_use[wrapper]);
143
- if(is_item_in_use[wrapper]){
158
+ CACHE_DEBUG_LOG((void*)wrapper, "Examining wrapper: name='%s', refcnt=%zu", wrapper->filter_name.c_str(), item_refcnt[wrapper]);
159
+ if(item_refcnt[wrapper]>0){
144
160
  CACHE_DEBUG_LOG((void*)wrapper, "Wrapper is busy, skipping");
145
161
  break;
146
162
  }
@@ -152,7 +168,7 @@ private:
152
168
  CACHE_DEBUG_LOG((void*)wrapper, "Removing wrapper from cache");
153
169
  item_map.erase(wrapper->filter_name);
154
170
  };
155
- is_item_in_use.erase(wrapper);
171
+ item_refcnt.erase(wrapper);
156
172
  item_list.pop_back();
157
173
  CACHE_DEBUG_LOG((void*)wrapper, "Deleting wrapper");
158
174
  delete wrapper;
@@ -171,20 +187,20 @@ public:
171
187
  //clear cache
172
188
  pthread_mutex_destroy(&cache_mutex);
173
189
  }
174
- void set_item_in_use_true(JqFilterWrapper* val){
190
+ void inc_refcnt(JqFilterWrapper* val){
175
191
  CACHE_DEBUG_LOG((void*)val, "Incrementing refcnt for wrapper:%p", (void*)val);
176
- is_item_in_use[val] = true;
192
+ item_refcnt[val]++;
177
193
  }
178
- void set_item_in_use_false(JqFilterWrapper* val){
194
+ void dec_refcnt(JqFilterWrapper* val){
179
195
  pthread_mutex_lock(&cache_mutex);
180
196
  CACHE_DEBUG_LOG((void*)val, "Decrementing refcnt for wrapper:%p", (void*)val);
181
- is_item_in_use[val] = false;
197
+ item_refcnt[val]--;
182
198
  pthread_mutex_unlock(&cache_mutex);
183
199
  }
184
200
  void put(const KEY_T &key, JqFilterWrapper* val) {
185
201
  CACHE_DEBUG_LOG((void*)val, "Putting key='%s' wrapper:%p", key.c_str(), (void*)val);
186
202
  pthread_mutex_lock(&cache_mutex);
187
- set_item_in_use_true(val);
203
+ inc_refcnt(val);
188
204
  CACHE_DEBUG_LOG((void*)val, "Got cache lock for put operation");
189
205
 
190
206
  auto it = item_map.find(key);
@@ -217,9 +233,9 @@ public:
217
233
  item_list.erase(wrapper->cache_pos);
218
234
  item_list.push_front(wrapper);
219
235
  wrapper->cache_pos = item_list.begin();
220
- set_item_in_use_true(wrapper);
221
- CACHE_DEBUG_LOG((void*)wrapper, "Cache hit for jq wrapper,pointer=%p,name=%s",
222
- (void*)wrapper, wrapper->filter_name.c_str());
236
+ inc_refcnt(wrapper);
237
+ CACHE_DEBUG_LOG((void*)wrapper, "Cache hit for jq wrapper,pointer=%p,name=%s,refcnt=%zu",
238
+ (void*)wrapper, wrapper->filter_name.c_str(),item_refcnt[wrapper]);
223
239
  pthread_mutex_unlock(&cache_mutex);
224
240
  CACHE_DEBUG_LOG((void*)wrapper, "Released cache lock after get");
225
241
  return wrapper;
@@ -412,13 +428,13 @@ napi_value ExecSync(napi_env env, napi_callback_info info) {
412
428
  napi_throw_error(env, nullptr, err_msg_conversion.c_str());
413
429
  jv_free(result);
414
430
  wrapper->unlock();
415
- cache.set_item_in_use_false(wrapper);
431
+ cache.dec_refcnt(wrapper);
416
432
  return nullptr;
417
433
  }
418
434
 
419
435
  jv_free(result);
420
436
  wrapper->unlock();
421
- cache.set_item_in_use_false(wrapper);
437
+ cache.dec_refcnt(wrapper);
422
438
  return ret;
423
439
  }
424
440
 
@@ -430,7 +446,8 @@ struct AsyncWork {
430
446
  napi_deferred deferred;
431
447
  napi_async_work async_work;
432
448
  /* output */
433
- jv result;
449
+ bool is_undefined;
450
+ std::string result;
434
451
  std::string error;
435
452
  bool success;
436
453
  };
@@ -466,8 +483,8 @@ void ExecuteAsync(napi_env env, void* data) {
466
483
  work->error = "Invalid JSON input";
467
484
  work->success = false;
468
485
  jv_free(input);
486
+ cache.dec_refcnt(wrapper);
469
487
  wrapper->unlock();
470
- cache.set_item_in_use_false(wrapper);
471
488
 
472
489
  return;
473
490
  }
@@ -476,14 +493,43 @@ void ExecuteAsync(napi_env env, void* data) {
476
493
  ASYNC_DEBUG_LOG(work, "jq execution started");
477
494
 
478
495
  jv result=jq_next(wrapper->get_jq());
479
- work->result = result;
480
- work->success = true;
496
+ if(jv_get_kind(result) == JV_KIND_INVALID){
497
+ jv msg = jv_invalid_get_msg(jv_copy(result));
498
+
499
+ if (jv_get_kind(msg) == JV_KIND_STRING) {
500
+ work->error = std::string("jq: error: ") + jv_string_value(msg);
501
+ jv_free(msg);
502
+ work->success=false;
503
+ }else{
504
+ work->is_undefined = true;
505
+ work->success=true;
506
+ }
507
+ }else{
508
+ jv dump = jv_dump_string(result, JV_PRINT_INVALID);
509
+ if(jv_is_valid(dump)){
510
+ work->result = jv_string_value(dump);
511
+ work->success = true;
512
+ }else{
513
+ ASYNC_DEBUG_LOG(work, "failed to get result");
514
+ work->error = "failed to get result";
515
+ work->success = false;
516
+ }
517
+ jv_free(dump);
518
+ }
481
519
  wrapper->unlock();
520
+ cache.dec_refcnt(wrapper);
482
521
 
483
- cache.set_item_in_use_false(wrapper);
484
- ASYNC_DEBUG_LOG(work, "jq execution finished - got result, %p", work->result);
522
+ ASYNC_DEBUG_LOG(work, "jq execution finished - got result, %s", work->result.c_str());
485
523
  }
486
524
 
525
+ void reject_with_error_message(napi_env env, napi_deferred deferred, std::string error_message){
526
+ napi_value error;
527
+ napi_create_string_utf8(env, error_message.c_str(), NAPI_AUTO_LENGTH, &error);
528
+ napi_value error_obj;
529
+ napi_create_object(env, &error_obj);
530
+ napi_set_named_property(env, error_obj, "message", error);
531
+ napi_reject_deferred(env, deferred, error_obj);
532
+ }
487
533
 
488
534
  void CompleteAsync(napi_env env, napi_status status, void* data) {
489
535
  AsyncWork* work = static_cast<AsyncWork*>(data);
@@ -491,69 +537,50 @@ void CompleteAsync(napi_env env, napi_status status, void* data) {
491
537
 
492
538
  auto cleanup = [&]() {
493
539
  if (!cleanup_done) {
494
- DEBUG_LOG("Freeing result, %p,refcnt %zu", work->result, jv_get_refcnt(work->result));
495
- jv_free(work->result);
496
540
  napi_delete_async_work(env, work->async_work);
497
541
  ASYNC_DEBUG_LOG(work, "Deleting AsyncWork");
498
542
  delete work;
499
543
  cleanup_done = true;
500
544
  }
501
545
  };
502
- if(status != napi_ok){
503
- napi_throw_type_error(env, nullptr, "Got error from async work");
504
- napi_reject_deferred(env, work->deferred, nullptr);
546
+
547
+ if(status != napi_ok || !work->success){
548
+ std::string error_message = work->error;
549
+ if(error_message == ""){
550
+ error_message = "Got error from async work";
551
+ }
552
+ reject_with_error_message(env, work->deferred, error_message);
505
553
  cleanup();
506
554
  return;
507
555
  }
508
556
  napi_handle_scope scope;
509
- status = napi_open_handle_scope(env, &scope);
557
+ status = napi_open_handle_scope(env, &scope);
510
558
  if (status != napi_ok) {
511
- napi_throw_type_error(env, nullptr, "Failed to create handle scope");
512
- napi_reject_deferred(env, work->deferred, nullptr);
559
+ reject_with_error_message(env, work->deferred, "Failed to create handle scope");
513
560
  cleanup();
514
561
  return;
515
562
  }
516
563
 
517
- if (work->success) {
518
564
  napi_value ret;
519
565
 
520
566
  status=napi_create_object(env, &ret);
521
- if(status != napi_ok){
522
- napi_throw_error(env, nullptr, "Failed to create object");
523
- napi_close_handle_scope(env, scope);
524
- napi_resolve_deferred(env, work->deferred, ret);
525
- cleanup();
526
- return;
567
+
568
+ jv result_jv;
569
+ if(work->is_undefined){
570
+ result_jv = jv_invalid();
571
+ }else{
572
+ result_jv= jv_parse(work->result.c_str());
527
573
  }
528
- DEBUG_LOG("[COMPLETE ASYNC][%p] result %p", work, work->result);
529
574
  std::string err_msg_conversion;
530
- bool success = jv_object_to_napi("value", env, work->result, ret,err_msg_conversion);
531
- if(!success){
532
- napi_value error;
533
- napi_create_string_utf8(env, err_msg_conversion.c_str(), NAPI_AUTO_LENGTH, &error);
534
-
535
- napi_value error_obj;
536
- napi_create_object(env, &error_obj);
537
- napi_set_named_property(env, error_obj, "message", error);
538
- // napi_create_error(env, nullptr, error, &error_obj);
539
- napi_reject_deferred(env, work->deferred, error_obj);
575
+ bool success = jv_object_to_napi("value", env, result_jv, ret,err_msg_conversion);
576
+ jv_free(result_jv);
540
577
 
541
- jv_free(work->result);
578
+ if(!success){
579
+ reject_with_error_message(env, work->deferred, err_msg_conversion);
542
580
  napi_close_handle_scope(env, scope);
543
581
  return;
544
582
  }
545
583
  napi_resolve_deferred(env, work->deferred, ret);
546
- } else {
547
- napi_value error;
548
- napi_create_string_utf8(env, work->error.c_str(), NAPI_AUTO_LENGTH, &error);
549
-
550
- napi_value error_obj;
551
- napi_create_object(env, &error_obj);
552
- napi_set_named_property(env, error_obj, "message", error);
553
-
554
- // napi_create_error(env, nullptr, error, &error_obj);
555
- napi_reject_deferred(env, work->deferred, error_obj);
556
- }
557
584
  cleanup();
558
585
  napi_close_handle_scope(env, scope);
559
586
  }
@@ -598,26 +625,26 @@ napi_value ExecAsync(napi_env env, napi_callback_info info) {
598
625
  return promise;
599
626
  }
600
627
 
601
- napi_value SetDebugMode(napi_env env, napi_callback_info info) {
602
- size_t argc = 1;
603
- napi_value args[1];
604
- bool enable;
628
+ // napi_value SetDebugMode(napi_env env, napi_callback_info info) {
629
+ // size_t argc = 1;
630
+ // napi_value args[1];
631
+ // bool enable;
605
632
 
606
- napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
633
+ // napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
607
634
 
608
- if (argc < 1) {
609
- napi_throw_type_error(env, nullptr, "Wrong number of arguments");
610
- return nullptr;
611
- }
635
+ // if (argc < 1) {
636
+ // napi_throw_type_error(env, nullptr, "Wrong number of arguments");
637
+ // return nullptr;
638
+ // }
612
639
 
613
- napi_get_value_bool(env, args[0], &enable);
614
- debug_enabled = enable;
615
- DEBUG_LOG("Debug mode %s", enable ? "enabled" : "disabled");
640
+ // napi_get_value_bool(env, args[0], &enable);
641
+ // debug_enabled = enable;
642
+ // DEBUG_LOG("Debug mode %s", enable ? "enabled" : "disabled");
616
643
 
617
- napi_value result;
618
- napi_get_boolean(env, debug_enabled, &result);
619
- return result;
620
- }
644
+ // napi_value result;
645
+ // napi_get_boolean(env, debug_enabled, &result);
646
+ // return result;
647
+ // }
621
648
 
622
649
  // napi_value GetCacheStats(napi_env env, napi_callback_info info) {
623
650
  // napi_value result;
@@ -663,16 +690,16 @@ napi_value SetCacheSize(napi_env env, napi_callback_info info) {
663
690
  }
664
691
 
665
692
  napi_value Init(napi_env env, napi_value exports) {
666
- napi_value exec_sync, exec_async, debug_fn, cache_size_fn,cache_stats_fn;
693
+ napi_value exec_sync, exec_async, cache_size_fn,cache_stats_fn;
667
694
 
668
695
  napi_create_function(env, "execSync", NAPI_AUTO_LENGTH, ExecSync, nullptr, &exec_sync);
669
696
  napi_create_function(env, "execAsync", NAPI_AUTO_LENGTH, ExecAsync, nullptr, &exec_async);
670
- napi_create_function(env, "setDebugMode", NAPI_AUTO_LENGTH, SetDebugMode, nullptr, &debug_fn);
697
+ // napi_create_function(env, "setDebugMode", NAPI_AUTO_LENGTH, SetDebugMode, nullptr, &debug_fn);
671
698
  napi_create_function(env, "setCacheSize", NAPI_AUTO_LENGTH, SetCacheSize, nullptr, &cache_size_fn);
672
699
  // napi_create_function(env, "getCacheStats", NAPI_AUTO_LENGTH, GetCacheStats, nullptr, &cache_stats_fn);
673
700
  napi_set_named_property(env, exports, "execSync", exec_sync);
674
701
  napi_set_named_property(env, exports, "execAsync", exec_async);
675
- napi_set_named_property(env, exports, "setDebugMode", debug_fn);
702
+ // napi_set_named_property(env, exports, "setDebugMode", debug_fn);
676
703
  napi_set_named_property(env, exports, "setCacheSize", cache_size_fn);
677
704
  // napi_set_named_property(env, exports, "getCacheStats", cache_stats_fn);
678
705
  return exports;
@@ -44,7 +44,6 @@ describe('template', () => {
44
44
  const json = "foo";
45
45
  const input = '{{.foo}}';
46
46
  const result = jq.renderRecursively(json, input);
47
- console.log('!!!!!',result);
48
47
  expect(result).toBe(null);
49
48
  });
50
49
  it('should excape \'\' to ""', () => {