@port-labs/jq-node-bindings 1.0.1 → 1.0.3

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.
Files changed (89) hide show
  1. package/deps/jq/COPYING +1 -9
  2. package/deps/jq/Makefile.am +13 -18
  3. package/deps/jq/NEWS.md +2 -2
  4. package/deps/jq/README.md +3 -18
  5. package/deps/jq/configure.ac +1 -0
  6. package/deps/jq/docs/Pipfile.lock +59 -72
  7. package/deps/jq/docs/README.md +1 -1
  8. package/deps/jq/docs/build_manpage.py +1 -1
  9. package/deps/jq/docs/build_mantests.py +1 -1
  10. package/deps/jq/docs/content/download/default.yml +1 -23
  11. package/deps/jq/docs/content/index.yml +0 -5
  12. package/deps/jq/docs/content/manual/{dev/manual.yml → manual.yml} +36 -162
  13. package/deps/jq/docs/content/manual/v1.3/manual.yml +5 -0
  14. package/deps/jq/docs/content/manual/v1.4/manual.yml +5 -0
  15. package/deps/jq/docs/content/manual/v1.5/manual.yml +8 -3
  16. package/deps/jq/docs/content/manual/v1.6/manual.yml +8 -3
  17. package/deps/jq/docs/content/manual/v1.7/manual.yml +11 -6
  18. package/deps/jq/docs/content/tutorial/default.yml +3 -3
  19. package/deps/jq/docs/manual_schema.yml +3 -0
  20. package/deps/jq/docs/templates/index.html.j2 +6 -6
  21. package/deps/jq/docs/templates/manual.html.j2 +1 -11
  22. package/deps/jq/jq.1.prebuilt +26 -162
  23. package/deps/jq/jq.spec +1 -1
  24. package/deps/jq/src/builtin.c +211 -298
  25. package/deps/jq/src/builtin.jq +7 -13
  26. package/deps/jq/src/bytecode.h +3 -8
  27. package/deps/jq/src/compile.c +2 -2
  28. package/deps/jq/src/decNumber/decBasic.c +1 -1
  29. package/deps/jq/src/decNumber/decCommon.c +1 -1
  30. package/deps/jq/src/decNumber/decNumber.c +4 -4
  31. package/deps/jq/src/execute.c +42 -22
  32. package/deps/jq/src/jq.h +1 -1
  33. package/deps/jq/src/jq_test.c +7 -69
  34. package/deps/jq/src/jv.c +12 -17
  35. package/deps/jq/src/jv.h +0 -3
  36. package/deps/jq/src/jv_aux.c +4 -3
  37. package/deps/jq/src/jv_dtoa.c +1 -1
  38. package/deps/jq/src/jv_parse.c +0 -2
  39. package/deps/jq/src/jv_print.c +27 -21
  40. package/deps/jq/src/jv_unicode.c +0 -18
  41. package/deps/jq/src/jv_unicode.h +0 -2
  42. package/deps/jq/src/lexer.c +262 -283
  43. package/deps/jq/src/lexer.h +2 -3
  44. package/deps/jq/src/lexer.l +1 -7
  45. package/deps/jq/src/libm.h +5 -15
  46. package/deps/jq/src/linker.c +4 -6
  47. package/deps/jq/src/main.c +252 -179
  48. package/deps/jq/src/util.c +35 -41
  49. package/deps/jq/src/util.h +1 -1
  50. package/deps/jq/tests/jq.test +10 -148
  51. package/deps/jq/tests/jq_fuzz_load_file.c +0 -1
  52. package/deps/jq/tests/man.test +8 -26
  53. package/deps/jq/tests/setup +0 -4
  54. package/deps/jq/tests/shtest +39 -150
  55. package/index.d.ts +3 -2
  56. package/lib/jq.js +2 -2
  57. package/lib/templateAsync.js +8 -15
  58. package/package.json +2 -2
  59. package/src/binding.cc +46 -27
  60. package/test/santiy-async.test.js +4 -0
  61. package/deps/jq/sig/v1.7.1/jq-1.7.1.tar.gz.asc +0 -16
  62. package/deps/jq/sig/v1.7.1/jq-1.7.1.zip.asc +0 -16
  63. package/deps/jq/sig/v1.7.1/jq-linux-amd64.asc +0 -16
  64. package/deps/jq/sig/v1.7.1/jq-linux-arm64.asc +0 -16
  65. package/deps/jq/sig/v1.7.1/jq-linux-armel.asc +0 -16
  66. package/deps/jq/sig/v1.7.1/jq-linux-armhf.asc +0 -16
  67. package/deps/jq/sig/v1.7.1/jq-linux-i386.asc +0 -16
  68. package/deps/jq/sig/v1.7.1/jq-linux-mips.asc +0 -16
  69. package/deps/jq/sig/v1.7.1/jq-linux-mips64.asc +0 -16
  70. package/deps/jq/sig/v1.7.1/jq-linux-mips64el.asc +0 -16
  71. package/deps/jq/sig/v1.7.1/jq-linux-mips64r6.asc +0 -16
  72. package/deps/jq/sig/v1.7.1/jq-linux-mips64r6el.asc +0 -16
  73. package/deps/jq/sig/v1.7.1/jq-linux-mipsel.asc +0 -16
  74. package/deps/jq/sig/v1.7.1/jq-linux-mipsr6.asc +0 -16
  75. package/deps/jq/sig/v1.7.1/jq-linux-mipsr6el.asc +0 -16
  76. package/deps/jq/sig/v1.7.1/jq-linux-powerpc.asc +0 -16
  77. package/deps/jq/sig/v1.7.1/jq-linux-ppc64el.asc +0 -16
  78. package/deps/jq/sig/v1.7.1/jq-linux-riscv64.asc +0 -16
  79. package/deps/jq/sig/v1.7.1/jq-linux-s390x.asc +0 -16
  80. package/deps/jq/sig/v1.7.1/jq-linux64.asc +0 -16
  81. package/deps/jq/sig/v1.7.1/jq-macos-amd64.asc +0 -16
  82. package/deps/jq/sig/v1.7.1/jq-macos-arm64.asc +0 -16
  83. package/deps/jq/sig/v1.7.1/jq-osx-amd64.asc +0 -16
  84. package/deps/jq/sig/v1.7.1/jq-win64.exe.asc +0 -16
  85. package/deps/jq/sig/v1.7.1/jq-windows-amd64.exe.asc +0 -16
  86. package/deps/jq/sig/v1.7.1/jq-windows-i386.exe.asc +0 -16
  87. package/deps/jq/sig/v1.7.1/sha256sum.txt +0 -26
  88. package/deps/jq/tests/uri.test +0 -38
  89. package/deps/jq/tests/uritest +0 -5
@@ -14,9 +14,6 @@ JQ="$JQ -b"
14
14
 
15
15
  PATH=$JQBASEDIR:$PATH $JQBASEDIR/tests/jq-f-test.sh > /dev/null
16
16
 
17
- SHELL=/bin/sh
18
- export SHELL
19
-
20
17
  if [ -f "$JQBASEDIR/.libs/libinject_errors.so" ]; then
21
18
  # Do some simple error injection tests to check that we're handling
22
19
  # I/O errors correctly.
@@ -213,28 +210,6 @@ else
213
210
  cmp $d/out $d/expected
214
211
  fi
215
212
 
216
- # Regression tests for #3194
217
- echo 42 > $d/expected
218
- $JQ -nn 42 > $d/out 2>&1
219
- cmp $d/out $d/expected
220
-
221
- $JQ -nL. 42 > $d/out 2>&1
222
- cmp $d/out $d/expected
223
- $JQ -nL . 42 > $d/out 2>&1
224
- cmp $d/out $d/expected
225
-
226
- $JQ -h > $d/expected 2>&1
227
- $JQ -hV > $d/out 2>&1
228
- cmp $d/out $d/expected
229
- $JQ -h -V > $d/out 2>&1
230
- cmp $d/out $d/expected
231
-
232
- $JQ -V > $d/expected 2>&1
233
- $JQ -Vh > $d/out 2>&1
234
- cmp $d/out $d/expected
235
- $JQ -V -h > $d/out 2>&1
236
- cmp $d/out $d/expected
237
-
238
213
  ## Test streaming parser
239
214
 
240
215
  ## If we add an option to stream to the `import ... as $symbol;` directive
@@ -384,17 +359,6 @@ if [ "$(HOME="$mods/home1" $VALGRIND $Q $JQ -nr fg)" != foobar ]; then
384
359
  exit 1
385
360
  fi
386
361
 
387
- if $msys || $mingw; then
388
- HOME_BAK=$HOME
389
- unset HOME
390
- if [ "$(USERPROFILE="$mods/home1" $VALGRIND $Q $JQ -nr foo)" != baz ]; then
391
- echo "Bug #3104 regressed (sourcing %USERPROFILE%/.jq on Windows)" 1>&2
392
- exit 1
393
- fi
394
- export HOME=$HOME_BAK
395
- unset HOME_BAK
396
- fi
397
-
398
362
  if [ $(HOME="$mods/home1" $VALGRIND $Q $JQ --debug-dump-disasm -n fg | grep '^[a-z]' | wc -l) -ne 3 ]; then
399
363
  echo "Binding too many defs into program" 1>&2
400
364
  exit 1
@@ -472,96 +436,41 @@ printf '\033[4;31mnull\033[0m\n' > $d/expect
472
436
  cmp $d/color $d/expect
473
437
 
474
438
  ## Default colors, complex input
475
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color
439
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color
476
440
  {
477
- printf '\033[1;39m[\033[0m'
478
- printf '\033[1;39m{\033[0m'
479
- printf '\033[1;34m"a"\033[0m'
480
- printf '\033[1;39m:\033[0m'
481
- printf '\033[0;39mtrue\033[0m'
482
- printf '\033[1;39m,\033[0m'
483
- printf '\033[1;34m"b"\033[0m'
484
- printf '\033[1;39m:\033[0m'
485
- printf '\033[0;39mfalse\033[0m'
486
- printf '\033[1;39m}\033[0m'
487
- printf '\033[1;39m,\033[0m'
488
- printf '\033[0;32m"abc"\033[0m'
489
- printf '\033[1;39m,\033[0m'
490
- printf '\033[0;39m123\033[0m'
491
- printf '\033[1;39m,\033[0m'
492
- printf '\033[0;90mnull\033[0m'
493
- printf '\033[1;39m]\033[0m\n'
441
+ printf '\033[1;39m[\033[1;39m{'
442
+ printf '\033[0m\033[1;34m"a"\033['
443
+ printf '0m\033[1;39m:\033[0m\033['
444
+ printf '0;39mtrue\033[0m\033[1'
445
+ printf ';39m,\033[0m\033[1;34m'
446
+ printf '"b"\033[0m\033[1;39m:\033'
447
+ printf '[0m\033[0;39mfalse\033'
448
+ printf '[0m\033[1;39m\033[1;39'
449
+ printf 'm}\033[0m\033[1;39m,\033['
450
+ printf '0;39m123\033[0m\033[1;'
451
+ printf '39m,\033[0;90mnull\033'
452
+ printf '[0m\033[1;39m\033[1;39'
453
+ printf 'm]\033[0m\n'
494
454
  } > $d/expect
495
455
  cmp $d/color $d/expect
496
456
 
497
457
  ## Set non-default colors, complex input
498
458
  JQ_COLORS='0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
499
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color
500
- {
501
- printf '\033[1;35m[\033[0m'
502
- printf '\033[1;36m{\033[0m'
503
- printf '\033[1;37m"a"\033[0m'
504
- printf '\033[1;36m:\033[0m'
505
- printf '\033[0;32mtrue\033[0m'
506
- printf '\033[1;36m,\033[0m'
507
- printf '\033[1;37m"b"\033[0m'
508
- printf '\033[1;36m:\033[0m'
509
- printf '\033[0;31mfalse\033[0m'
510
- printf '\033[1;36m}\033[0m'
511
- printf '\033[1;35m,\033[0m'
512
- printf '\033[0;34m"abc"\033[0m'
513
- printf '\033[1;35m,\033[0m'
514
- printf '\033[0;33m123\033[0m'
515
- printf '\033[1;35m,\033[0m'
516
- printf '\033[0;30mnull\033[0m'
517
- printf '\033[1;35m]\033[0m\n'
518
- } > $d/expect
519
- cmp $d/color $d/expect
520
-
521
- ## Default colors, complex input, indented
522
- $JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d/color
523
- {
524
- printf '\033[1;39m[\033[0m\n'
525
- printf ' \033[1;39m{\033[0m\n'
526
- printf ' \033[1;34m"a"\033[0m'
527
- printf '\033[1;39m:\033[0m '
528
- printf '\033[0;39mtrue\033[0m'
529
- printf '\033[1;39m,\033[0m\n'
530
- printf ' \033[1;34m"b"\033[0m'
531
- printf '\033[1;39m:\033[0m '
532
- printf '\033[0;39mfalse\033[0m\n'
533
- printf ' \033[1;39m}\033[0m'
534
- printf '\033[1;39m,\033[0m\n'
535
- printf ' \033[0;32m"abc"\033[0m'
536
- printf '\033[1;39m,\033[0m\n'
537
- printf ' \033[0;39m123\033[0m'
538
- printf '\033[1;39m,\033[0m\n'
539
- printf ' \033[0;90mnull\033[0m\n'
540
- printf '\033[1;39m]\033[0m\n'
541
- } > $d/expect
542
- cmp $d/color $d/expect
543
-
544
- ## Set non-default colors, complex input, indented
545
- JQ_COLORS='0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
546
- $JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d/color
459
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color
547
460
  {
548
- printf '\033[1;35m[\033[0m\n'
549
- printf ' \033[1;36m{\033[0m\n'
550
- printf ' \033[1;37m"a"\033[0m'
551
- printf '\033[1;36m:\033[0m '
552
- printf '\033[0;32mtrue\033[0m'
553
- printf '\033[1;36m,\033[0m\n'
554
- printf ' \033[1;37m"b"\033[0m'
555
- printf '\033[1;36m:\033[0m '
556
- printf '\033[0;31mfalse\033[0m\n'
557
- printf ' \033[1;36m}\033[0m'
558
- printf '\033[1;35m,\033[0m\n'
559
- printf ' \033[0;34m"abc"\033[0m'
560
- printf '\033[1;35m,\033[0m\n'
561
- printf ' \033[0;33m123\033[0m'
562
- printf '\033[1;35m,\033[0m\n'
563
- printf ' \033[0;30mnull\033[0m\n'
564
- printf '\033[1;35m]\033[0m\n'
461
+ printf '\033[1;35m[\033[1;36m{'
462
+ printf '\033[0m\033[1;37m"a"\033['
463
+ printf '0m\033[1;36m:\033[0m\033['
464
+ printf '0;32mtrue\033[0m\033[1'
465
+ printf ';36m,\033[0m\033[1;37m'
466
+ printf '"b"\033[0m\033[1;36m:\033'
467
+ printf '[0m\033[0;31mfalse\033'
468
+ printf '[0m\033[1;36m\033[1;36'
469
+ printf 'm}\033[0m\033[1;35m,\033['
470
+ printf '0;33m123\033[0m\033[1;'
471
+ printf '35m,\033[0;30mnull\033'
472
+ printf '[0m\033[1;35m\033[1;35'
473
+ printf 'm]\033[0m\n'
565
474
  } > $d/expect
566
475
  cmp $d/color $d/expect
567
476
 
@@ -571,25 +480,25 @@ cmp $d/color $d/expect
571
480
  # on stderr.
572
481
  set -vx
573
482
  echo 'Failed to set $JQ_COLORS' > $d/expect_warning
574
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/expect
483
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/expect
575
484
  JQ_COLORS='garbage;30:*;31:,;3^:0;$%:0;34:1;35:1;36' \
576
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
485
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
577
486
  cmp $d/color $d/expect
578
487
  cmp $d/warning $d/expect_warning
579
488
  JQ_COLORS='1234567890123456789;30:0;31:0;32:0;33:0;34:1;35:1;36' \
580
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
489
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
581
490
  cmp $d/color $d/expect
582
491
  cmp $d/warning $d/expect_warning
583
492
  JQ_COLORS='1;31234567890123456789:0;31:0;32:0;33:0;34:1;35:1;36' \
584
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
493
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
585
494
  cmp $d/color $d/expect
586
495
  cmp $d/warning $d/expect_warning
587
496
  JQ_COLORS='1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456:1234567890123456;1234567890123456' \
588
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
497
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
589
498
  cmp $d/color $d/expect
590
499
  cmp $d/warning $d/expect_warning
591
500
  JQ_COLORS="0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:0123456789123:" \
592
- $JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d/color 2>$d/warning
501
+ $JQ -Ccn '[{"a":true,"b":false},123,null]' > $d/color 2>$d/warning
593
502
  cmp $d/color $d/expect
594
503
  cmp $d/warning $d/expect_warning
595
504
 
@@ -611,17 +520,17 @@ if $test_no_color && command -v script >/dev/null 2>&1; then
611
520
  od -tc $d/expect
612
521
  od -tc $d/color
613
522
  cmp $d/color $d/expect
614
- faketty env NO_COLOR= $JQ_NO_B -n . > $d/color
523
+ NO_COLOR= faketty $JQ_NO_B -n . > $d/color
615
524
  printf '\033[0;90mnull\033[0m\r\n' > $d/expect
616
525
  od -tc $d/expect
617
526
  od -tc $d/color
618
527
  cmp $d/color $d/expect
619
- faketty env NO_COLOR=1 $JQ_NO_B -n . > $d/color
528
+ NO_COLOR=1 faketty $JQ_NO_B -n . > $d/color
620
529
  printf 'null\r\n' > $d/expect
621
530
  od -tc $d/expect
622
531
  od -tc $d/color
623
532
  cmp $d/color $d/expect
624
- faketty env NO_COLOR=1 $JQ_NO_B -Cn . > $d/color
533
+ NO_COLOR=1 faketty $JQ_NO_B -Cn . > $d/color
625
534
  printf '\033[0;90mnull\033[0m\r\n' > $d/expect
626
535
  od -tc $d/expect
627
536
  od -tc $d/color
@@ -685,30 +594,10 @@ if ! x=$($JQ -n "1 # foo$cr + 2") || [ "$x" != 1 ]; then
685
594
  exit 1
686
595
  fi
687
596
 
688
- if ! x=$($JQ -cn '[
689
- 1,
690
- # foo \
691
- 2,
692
- # bar \\
693
- 3,
694
- 4, # baz \\\
695
- 5, \
696
- 6,
697
- 7
698
- # comment \
699
- comment \
700
- comment
701
- ]') || [ "$x" != '[1,3,4,7]' ]; then
702
- echo 'multiline comment was not handled correctly'
703
- exit 1
704
- fi
705
-
706
597
  # CVE-2023-50268: No stack overflow comparing a nan with a large payload
707
- if $JQ -ne 'have_decnum'; then
708
- $VALGRIND $Q $JQ '1 != .' <<\EOF >/dev/null
709
- Nan4000
598
+ $VALGRIND $Q $JQ '1 != .' <<\EOF >/dev/null
599
+ Nan4000
710
600
  EOF
711
- fi
712
601
 
713
602
  # Allow passing the inline jq script before -- #2919
714
603
  if ! r=$($JQ --args -rn -- '$ARGS.positional[0]' bar) || [ "$r" != bar ]; then
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare module '@port-labs/jq-node-bindings' {
2
2
  type ExecOptions = { enableEnv?: boolean, throwOnError?: boolean };
3
+ type ExecAsyncOptions = { enableEnv?: boolean, throwOnError?: boolean, timeoutSec?: number };
3
4
 
4
5
  export class JqExecError extends Error {
5
6
  }
@@ -8,8 +9,8 @@ declare module '@port-labs/jq-node-bindings' {
8
9
  }
9
10
 
10
11
  export function exec(json: object, input: string, options?: ExecOptions): object | Array<any> | string | number | boolean | null;
11
- export function execAsync(json: object, input: string, options?: ExecOptions): Promise<object | Array<any> | string | number | boolean | null>;
12
+ export function execAsync(json: object, input: string, options?: ExecAsyncOptions): Promise<object | Array<any> | string | number | boolean | null>;
12
13
 
13
14
  export function renderRecursively(json: object, input: object | Array<any> | string | number | boolean | null, execOptions?: ExecOptions): object | Array<any> | string | number | boolean | null;
14
- export function renderRecursivelyAsync(json: object, input: object | Array<any> | string | number | boolean | null, execOptions?: ExecOptions): Promise<object | Array<any> | string | number | boolean | null>;
15
+ export function renderRecursivelyAsync(json: object, input: object | Array<any> | string | number | boolean | null, execOptions?: ExecAsyncOptions): Promise<object | Array<any> | string | number | boolean | null>;
15
16
  }
package/lib/jq.js CHANGED
@@ -27,9 +27,9 @@ const exec = (object, filter, {enableEnv = false, throwOnError = false} = {}) =>
27
27
  }
28
28
  }
29
29
 
30
- const execAsync = async (object, filter, {enableEnv = false, throwOnError = false} = {}) => {
30
+ const execAsync = async (object, filter, {enableEnv = false, throwOnError = false, timeoutSec} = {}) => {
31
31
  try {
32
- const data = await nativeJq.execAsync(JSON.stringify(object), formatFilter(filter, {enableEnv}))
32
+ const data = await nativeJq.execAsync(JSON.stringify(object), formatFilter(filter, {enableEnv}), timeoutSec)
33
33
  return data?.value;
34
34
  } catch (err) {
35
35
  if (throwOnError) {
@@ -1,5 +1,7 @@
1
1
  const jq = require('./jq');
2
2
 
3
+ const SPREAD_KEYWORD_PATTERN = /^\s*\{\{\s*spreadValue\(\s*\)\s*\}\}\s*$/; // matches {{ <Keyword>() }} with white spaces where you'd expect them
4
+
3
5
  const findInsideDoubleBracesIndices = (input) => {
4
6
  let wrappingQuote = null;
5
7
  let insideDoubleBracesStart = null;
@@ -64,15 +66,12 @@ const renderAsync =async (inputJson, template, execOptions = {}) => {
64
66
  const firstIndex = indices[0];
65
67
  if (indices.length === 1 && template.trim().startsWith('{{') && template.trim().endsWith('}}')) {
66
68
  // If entire string is a template, evaluate and return the result with the original type
67
- return await jq.execAsync(inputJson, template.slice(firstIndex.start, firstIndex.end), execOptions);
69
+ return jq.execAsync(inputJson, template.slice(firstIndex.start, firstIndex.end), execOptions);
68
70
  }
69
71
 
70
72
  let result = template.slice(0, firstIndex.start - '{{'.length); // Initiate result with string until first template start index
71
73
  for (let i = 0; i < indices.length; i++) {
72
74
  const index = indices[i];
73
-
74
- // }
75
- // indices.forEach((index, i) => {
76
75
  const jqResult = await jq.execAsync(inputJson, template.slice(index.start, index.end), execOptions);
77
76
  result +=
78
77
  // Add to the result the stringified evaluated jq of the current template
@@ -82,7 +81,6 @@ const renderAsync =async (inputJson, template, execOptions = {}) => {
82
81
  index.end + '}}'.length,
83
82
  i + 1 === indices.length ? template.length : indices[i + 1].start - '{{'.length,
84
83
  );
85
- // });
86
84
  }
87
85
 
88
86
  return result;
@@ -90,20 +88,15 @@ const renderAsync =async (inputJson, template, execOptions = {}) => {
90
88
 
91
89
  const renderRecursivelyAsync = async(inputJson, template, execOptions = {}) => {
92
90
  if (typeof template === 'string') {
93
- return await renderAsync(inputJson, template, execOptions);
91
+ return renderAsync(inputJson, template, execOptions);
94
92
  }
95
93
  if (Array.isArray(template)) {
96
- return await Promise.all(template.map((value) => renderRecursivelyAsync(inputJson, value, execOptions)));
94
+ return Promise.all(template.map((value) => renderRecursivelyAsync(inputJson, value, execOptions)));
97
95
  }
98
96
  if (typeof template === 'object' && template !== null) {
99
-
100
-
101
-
102
- const t =Object.entries(template).map(async([key, value]) => {
103
- const SPREAD_KEYWORD = "spreadValue";
104
- const keywordMatcher = `^\\{\\{\\s*${SPREAD_KEYWORD}\\(\\s*\\)\\s*\\}\\}$`; // matches {{ <Keyword>() }} with white spaces where you'd expect them
97
+ const t = Object.entries(template).map(async([key, value]) => {
105
98
 
106
- if (key.trim().match(keywordMatcher)) {
99
+ if (SPREAD_KEYWORD_PATTERN.test(key)) {
107
100
  const evaluatedValue = await renderRecursivelyAsync(inputJson, value, execOptions);
108
101
  if (typeof evaluatedValue !== "object") {
109
102
  throw new Error(
@@ -114,7 +107,7 @@ const renderRecursivelyAsync = async(inputJson, template, execOptions = {}) => {
114
107
  }
115
108
 
116
109
  const evaluatedKey = await renderRecursivelyAsync(inputJson, key, execOptions);
117
- if (!['undefined', 'string'].includes(typeof evaluatedKey) && evaluatedKey !== null) {
110
+ if (typeof evaluatedKey !== 'string' && evaluatedKey != null) {
118
111
  throw new Error(
119
112
  `Evaluated object key should be undefined, null or string. Original key: ${key}, evaluated to: ${JSON.stringify(evaluatedKey)}`,
120
113
  );
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@port-labs/jq-node-bindings",
3
- "version": "v1.0.1",
3
+ "version": "v1.0.3",
4
4
  "description": "Node.js bindings for JQ",
5
- "jq-node-bindings": "1.0.1",
5
+ "jq-node-bindings": "1.0.3",
6
6
  "main": "lib/index.js",
7
7
  "scripts": {
8
8
  "configure": "node-gyp configure",
package/src/binding.cc CHANGED
@@ -45,6 +45,7 @@
45
45
  #endif
46
46
 
47
47
  static size_t global_cache_size = 100;
48
+ static unsigned int global_timeout_sec = 5;
48
49
 
49
50
  static size_t get_uv_thread_pool_size() {
50
51
  const char* uv_threads = getenv("UV_THREADPOOL_SIZE");
@@ -61,7 +62,7 @@ static size_t validate_cache_size(size_t requested_size) {
61
62
  size_t min_size = get_uv_thread_pool_size();
62
63
  size_t new_size = std::max(requested_size, min_size);
63
64
  if(requested_size < min_size){
64
- DEBUG_LOG("Requested cache size %zu adjusted to minimum %zu (UV thread pool size)",requested_size,min_size);
65
+ DEBUG_LOG("Requested cache size %zu adjusted to minimum %zu (UV thread pool size)",requested_size,min_size);
65
66
  return min_size;
66
67
  }
67
68
  return new_size;
@@ -69,7 +70,7 @@ static size_t validate_cache_size(size_t requested_size) {
69
70
 
70
71
  /* err_data and throw_err_cb to get jq error message*/
71
72
  struct err_data {
72
- char buf[4096];
73
+ char buf[4096];
73
74
  };
74
75
  void throw_err_cb(void* data, jv msg) {
75
76
  struct err_data *err_data = (struct err_data *)data;
@@ -99,8 +100,8 @@ public:
99
100
  std::string filter_name;
100
101
  std::list<JqFilterWrapper*>::iterator cache_pos;
101
102
  /* init mutex and set filter_name */
102
- explicit JqFilterWrapper(jq_state* jq_, std::string filter_name_) :
103
- filter_name(filter_name_),
103
+ explicit JqFilterWrapper(jq_state* jq_, std::string filter_name_) :
104
+ filter_name(filter_name_),
104
105
  jq(jq_) {
105
106
  DEBUG_LOG("[WRAPPER:%p] Creating wrapper for filter: %s", (void*)this, filter_name_.c_str());
106
107
  pthread_mutex_init(&filter_mutex, nullptr);
@@ -137,7 +138,7 @@ private:
137
138
 
138
139
  template <class KEY_T> class LRUCache {
139
140
  private:
140
- pthread_mutex_t cache_mutex;
141
+ pthread_mutex_t cache_mutex;
141
142
  std::list<JqFilterWrapper*> item_list;
142
143
  std::unordered_map<KEY_T, JqFilterWrapper*> item_map;
143
144
  std::unordered_map<JqFilterWrapper*, size_t> item_refcnt;
@@ -171,8 +172,8 @@ private:
171
172
  item_refcnt.erase(wrapper);
172
173
  item_list.pop_back();
173
174
  CACHE_DEBUG_LOG((void*)wrapper, "Deleting wrapper");
174
- delete wrapper;
175
-
175
+ delete wrapper;
176
+
176
177
  }
177
178
  CACHE_DEBUG_LOG(this, "Cleanup complete. New size=%zu", item_map.size());
178
179
  pthread_mutex_unlock(&cache_mutex);
@@ -217,7 +218,7 @@ public:
217
218
  CACHE_DEBUG_LOG((void*)val, "Released cache lock after put");
218
219
  clean();
219
220
  }
220
-
221
+
221
222
  JqFilterWrapper* get(const KEY_T &key) {
222
223
  pthread_mutex_lock(&cache_mutex);
223
224
  CACHE_DEBUG_LOG(nullptr, "Got cache lock for get operation, key='%s'", key.c_str());
@@ -234,7 +235,7 @@ public:
234
235
  item_list.push_front(wrapper);
235
236
  wrapper->cache_pos = item_list.begin();
236
237
  inc_refcnt(wrapper);
237
- CACHE_DEBUG_LOG((void*)wrapper, "Cache hit for jq wrapper,pointer=%p,name=%s,refcnt=%zu",
238
+ CACHE_DEBUG_LOG((void*)wrapper, "Cache hit for jq wrapper,pointer=%p,name=%s,refcnt=%zu",
238
239
  (void*)wrapper, wrapper->filter_name.c_str(),item_refcnt[wrapper]);
239
240
  pthread_mutex_unlock(&cache_mutex);
240
241
  CACHE_DEBUG_LOG((void*)wrapper, "Released cache lock after get");
@@ -385,7 +386,7 @@ napi_value ExecSync(napi_env env, napi_callback_info info) {
385
386
  }
386
387
 
387
388
  struct err_data err_msg;
388
- JqFilterWrapper* wrapper;
389
+ JqFilterWrapper* wrapper;
389
390
 
390
391
  DEBUG_LOG("[SYNC] ExecSync called with filter='%s'", filter.c_str());
391
392
 
@@ -418,7 +419,7 @@ napi_value ExecSync(napi_env env, napi_callback_info info) {
418
419
  wrapper->lock();
419
420
 
420
421
  jq_start(wrapper->get_jq(), input, 0);
421
- jv result = jq_next(wrapper->get_jq());
422
+ jv result = jq_next(wrapper->get_jq(), global_timeout_sec);
422
423
 
423
424
  napi_value ret;
424
425
  napi_create_object(env, &ret);
@@ -442,6 +443,7 @@ struct AsyncWork {
442
443
  /* input */
443
444
  std::string json;
444
445
  std::string filter;
446
+ unsigned int timeout_sec;
445
447
  /* promise */
446
448
  napi_deferred deferred;
447
449
  napi_async_work async_work;
@@ -457,7 +459,7 @@ void ExecuteAsync(napi_env env, void* data) {
457
459
  ASYNC_DEBUG_LOG(work, "ExecuteAsync started for filter='%s'", work->filter.c_str());
458
460
 
459
461
  struct err_data err_msg;
460
- JqFilterWrapper* wrapper;
462
+ JqFilterWrapper* wrapper;
461
463
 
462
464
  wrapper = cache.get(work->filter);
463
465
  if (wrapper == nullptr) {
@@ -474,7 +476,7 @@ void ExecuteAsync(napi_env env, void* data) {
474
476
  wrapper=new JqFilterWrapper(jq, work->filter);
475
477
  cache.put(work->filter, wrapper );
476
478
  }
477
-
479
+
478
480
  jv input = jv_parse_sized(work->json.c_str(), work->json.size());
479
481
  ASYNC_DEBUG_LOG(work, "JSON input parsed");
480
482
 
@@ -488,11 +490,11 @@ void ExecuteAsync(napi_env env, void* data) {
488
490
 
489
491
  return;
490
492
  }
491
- wrapper->lock();
493
+ wrapper->lock();
492
494
  jq_start(wrapper->get_jq(), input, 0);
493
495
  ASYNC_DEBUG_LOG(work, "jq execution started");
494
496
 
495
- jv result=jq_next(wrapper->get_jq());
497
+ jv result=jq_next(wrapper->get_jq(), work->timeout_sec);
496
498
  if(jv_get_kind(result) == JV_KIND_INVALID){
497
499
  jv msg = jv_invalid_get_msg(jv_copy(result));
498
500
 
@@ -590,8 +592,8 @@ void CompleteAsync(napi_env env, napi_status status, void* data) {
590
592
  napi_value ExecAsync(napi_env env, napi_callback_info info) {
591
593
  napi_handle_scope scope;
592
594
 
593
- size_t argc = 2;
594
- napi_value args[2];
595
+ size_t argc = 3;
596
+ napi_value args[3];
595
597
  napi_value promise;
596
598
 
597
599
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
@@ -612,6 +614,23 @@ napi_value ExecAsync(napi_env env, napi_callback_info info) {
612
614
  napi_throw_error(env, nullptr, "Invalid filter input");
613
615
  return nullptr;
614
616
  }
617
+
618
+ work->timeout_sec = global_timeout_sec;
619
+ if(argc > 2){
620
+ napi_valuetype valuetype;
621
+ napi_status status = napi_typeof(env, args[2], &valuetype);
622
+ if(status != napi_ok){
623
+ napi_throw_error(env, nullptr, "Invalid timeout_sec input");
624
+ return nullptr;
625
+ }
626
+ if(valuetype == napi_number){
627
+ status = napi_get_value_uint32(env, args[2], &work->timeout_sec);
628
+ if (status != napi_ok) {
629
+ napi_throw_error(env, nullptr, "Invalid timeout_sec input");
630
+ return nullptr;
631
+ }
632
+ }
633
+ }
615
634
  work->success = false;
616
635
 
617
636
  napi_create_promise(env, &work->deferred, &promise);
@@ -629,18 +648,18 @@ napi_value ExecAsync(napi_env env, napi_callback_info info) {
629
648
  // size_t argc = 1;
630
649
  // napi_value args[1];
631
650
  // bool enable;
632
-
651
+
633
652
  // napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
634
-
653
+
635
654
  // if (argc < 1) {
636
655
  // napi_throw_type_error(env, nullptr, "Wrong number of arguments");
637
656
  // return nullptr;
638
657
  // }
639
-
658
+
640
659
  // napi_get_value_bool(env, args[0], &enable);
641
660
  // debug_enabled = enable;
642
661
  // DEBUG_LOG("Debug mode %s", enable ? "enabled" : "disabled");
643
-
662
+
644
663
  // napi_value result;
645
664
  // napi_get_boolean(env, debug_enabled, &result);
646
665
  // return result;
@@ -648,8 +667,8 @@ napi_value ExecAsync(napi_env env, napi_callback_info info) {
648
667
 
649
668
  // napi_value GetCacheStats(napi_env env, napi_callback_info info) {
650
669
  // napi_value result;
651
- // napi_create_object(env, &result);
652
- // struct rusage usage;
670
+ // napi_create_object(env, &result);
671
+ // struct rusage usage;
653
672
  // getrusage(RUSAGE_SELF, &usage);
654
673
  // napi_value maxrss;
655
674
  // napi_create_int64(env, usage.ru_maxrss, &maxrss);
@@ -661,14 +680,14 @@ napi_value SetCacheSize(napi_env env, napi_callback_info info) {
661
680
  size_t argc = 1;
662
681
  napi_value args[1];
663
682
  int64_t new_size;
664
-
683
+
665
684
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
666
685
  napi_status status;
667
686
  if (argc < 1) {
668
687
  napi_throw_type_error(env, nullptr, "Wrong number of arguments");
669
688
  return nullptr;
670
689
  }
671
-
690
+
672
691
  status=napi_get_value_int64(env, args[0], &new_size);
673
692
  if(!CheckNapiStatus(env,status,"error loading int64")){
674
693
  return nullptr;
@@ -677,13 +696,13 @@ napi_value SetCacheSize(napi_env env, napi_callback_info info) {
677
696
  napi_throw_error(env, nullptr, "Cache size must be positive");
678
697
  return nullptr;
679
698
  }
680
-
699
+
681
700
  DEBUG_LOG("Changing cache size from %zu to %lld", global_cache_size, new_size);
682
701
  size_t old_size = global_cache_size;
683
702
 
684
703
  global_cache_size = validate_cache_size(static_cast<size_t>(new_size));
685
704
  cache.resize(global_cache_size); // Update cache size
686
-
705
+
687
706
  napi_value result;
688
707
  napi_create_int64(env, global_cache_size, &result);
689
708
  return result;
@@ -167,5 +167,9 @@ describe('jq - async', () => {
167
167
  await expect(jq.execAsync({}, 'null | map(.+1)', {throwOnError: true})).rejects.toThrow("jq: error: Cannot iterate over null (null)");
168
168
  await expect(jq.execAsync({foo: "bar"}, '.foo + 1', {throwOnError: true})).rejects.toThrow("jq: error: string (\"bar\") and number (1) cannot be added");
169
169
  })
170
+
171
+ it('throw after timeout', async () => {
172
+ await expect(jq.execAsync({}, '[range(infinite)]', { timeoutSec: 1, throwOnError: true })).rejects.toThrow('timeout');
173
+ });
170
174
  })
171
175
 
@@ -1,16 +0,0 @@
1
- -----BEGIN PGP SIGNATURE-----
2
-
3
- iQIzBAABCgAdFiEEuNEmQbLVV2S3XP+l4aewjAfp7oYFAmV6CBUACgkQ4aewjAfp
4
- 7oYyWw//fvi2FRb/BEHWj9WirM5aj9x3F2J1V3cLH97B9XeBFFw3slj7OtYxjb3o
5
- dm7GzMN9RKlQiI4MQ8nhrzePKeI6c6igURwylVxHgiRp2jENVxCDoZOydnfpEuPx
6
- lIPAmnGNW4mlYVLQSFRZmTunCSIISbtjO/TPxX2x41nBRdp9AhfUQ/MfR0Ioya4V
7
- UHx82ScB5jKejiZqLpEfbqNAonmpDkdM8OXV/wmCAy6ICXB70IjMPgjTWwl0NZdt
8
- 9Ao4q2nZ44G1qOAsDWxIPqG1f6pjmwDE2k/ugpqOaVrXFKMbzdavReicGclw+sPy
9
- KbZ2k6hcz+GkUC/SulDTc6Opa0lonewPKaynRxhVsTX6wGu1M4tsjBSxF8/WlcWM
10
- aUdwDNv2WDsQSFL5AtHsH/V2aBBh6699yS9gz12wzT3qQXO34Gh7uSg8GCTwFhzV
11
- RQbP0oFLSZCGCtVR8zjJbZAHLu0xp25oZWI66HArbuqqQmCrx83FIMPE8rGvM1+4
12
- BeXuz+5gm8lG9JKxGB8klHRqP007XV5dLcYv01G+ITX0gpI+fNi9XTKDUR9W/LSO
13
- WP5P4LOH0N0nCvSPguaGSk5MdDs7SlD364uWfCkEReNDIxSUqNglk5U5vXzMi1Id
14
- hqC800IquRdKkPNolrJlu6IinSLcwld1EPR8HX596b5C0EQk/eU=
15
- =q9i8
16
- -----END PGP SIGNATURE-----
@@ -1,16 +0,0 @@
1
- -----BEGIN PGP SIGNATURE-----
2
-
3
- iQIzBAABCgAdFiEEuNEmQbLVV2S3XP+l4aewjAfp7oYFAmV6CBYACgkQ4aewjAfp
4
- 7obkuw/6Ahvl1j6xlRfZ3SwyWhQscwOBB1LWbIIVhJDOBVKv/XTe/Gx2x0kxMvZX
5
- jrEENi498I2mqQfie7Qw9ThhD8oWnvZLOsa2H1ijK7vcPjbVvPTuE4gvySWPhbIa
6
- tJid1kOBveJ6QJHptznfZzXhMuOUh3kS2lwyzKpru2Ke2hCkc5/qs45HjcRcsS9j
7
- XJTwr4QfCcPOuCeECdZM9I8s1JwmhUVNjyfcMXraFhl1d9lpb1K2pIUVMpxhp7i2
8
- jSRrw0p4a0IWuGnBLhb22PVjHK+vVFxpHblBSqsEYWBwxjIfClIhLgXpQ2SSwUkF
9
- hPRvqOwLemyz+cU3qz/O164td4v7m6DG4cqjpJd2JJepjZVaXs1Tuj18ENhuAdCu
10
- OIRefytdtrBh27cb125yMGMBa+qMgNsQSmpZIXuys4HLFyJWWPtxnU6zIlcnkM/O
11
- G/QEGMWbAdpVx8dIe2SLXrdNJUv1NXMiRTsmd9dmUkAbAb2lQy7rLLP6b8oJZwV+
12
- dsnB8cvftbLnKIAaLNzhfYieK7wtIZ1wNx5sJ+juz6EmpV2I0KdgbpNS2Qr2j6Dr
13
- /KZkaaDQtEX6RLuwQSU+m6odPYJvYryhGNKRgNJ5RTEpq0//sYeHUHsrzw2gOvQK
14
- R8l4Vj1lVbXKamwZj7c8WOS4gnNtMSvGCtSNTCbQNjMIdECVWHA=
15
- =X878
16
- -----END PGP SIGNATURE-----
@@ -1,16 +0,0 @@
1
- -----BEGIN PGP SIGNATURE-----
2
-
3
- iQIzBAABCgAdFiEEuNEmQbLVV2S3XP+l4aewjAfp7oYFAmV6CBYACgkQ4aewjAfp
4
- 7oZ5QRAArt5MOnrI0UNfLl8GjEWwFMxtSh2gz9ykRxdaIqS+xjmuJOs9hm9j4iZx
5
- Nbs3EJkRBgi8CUZZJm6JxRJKkeIBOFn3NSf5Gel9yQH5VPmAkQZCLpGJGt/SGJwb
6
- uzeOI7u+lW+BSMixc3cxTHJgIpQ/WrKd6FAzlqNL6RN8wH0F9b+UALgLoCzgdtSO
7
- km71GNeyP091uIImFvkfjM0jbbksvAIqOYvQO1ZjKLbMBeDrFih4Bp7OiDDRyt9I
8
- XrzMiv8Tg0bOamOpNYd/TwcgnEBtZhsfzwu83Yv+VPKAj/v1852SCJxbji2nO2H2
9
- JtbSg6FX+EnXWD1o9Pjii+31YW1U4C5TnimGsIwIzYKDjB7IFDDr89svj1pdSmv9
10
- kYidSYLu68vo+/nxEGpmapJr0wOIh8ysapsdE/mFlYa6bHn9ocAMj2Xs0BdYphrp
11
- t7ha0nEKKPxu+c96CTP9kH4eE4zTNTb/PY4y8r8p1QOoGteq9aGOUfLjnJeCX6lC
12
- LmT9Bn/9RkZwKJ7TjlHUQIhht2Tf5d/Mtbu68pODU5ruyWf8ZvTDB0m6Ib1A1qiE
13
- nRsNAil5z683Gr54xahSlRiwv0loITTquPEs6lHky+IdZL6MSHjRa5xPGVZ/TS6O
14
- 1Y4wjE1Yogr7821VBV+aXHdDMzVDrJmYKdOdWQkqplXUODaid6k=
15
- =oOwG
16
- -----END PGP SIGNATURE-----