From 7f5db56ee9e579b9164b848f52aeb2b9d9444beb Mon Sep 17 00:00:00 2001 From: Geoffrey Hendrey Date: Thu, 26 Sep 2024 18:10:12 -0700 Subject: [PATCH] Bun support (#80) * introduce CliCoreBase.ts to remove all Node repl dependencies, allowing future REPL to be built without using Node REPL. Small change to stringify so that Timer objects are recognized in Bun. Add couple Bun detectors in tests to work around Jest specialties that are not availavle in Bun. Add github actions so that all tests run on Bun as well as node. * fix bun:run script * make workaround for bug in pulsar-flex. Issue submitted: https://github.com/ayeo-flex-org/pulsar-flex/issues/90 --- .github/workflows/test.yml | 2 +- .github/workflows/test_bun.yml | 42 +++ package-lock.json | 474 +++------------------------- package.json | 6 +- src/CliCore.ts | 484 +---------------------------- src/CliCoreBase.ts | 445 ++++++++++++++++++++++++++ src/StatedREPL.ts | 24 +- src/index.ts | 1 + src/test/Pulsar.test.js | 117 +++++-- src/test/StatedREPL.test.js | 119 +++---- src/test/TemplateProcessor.test.js | 2 +- src/test/utils/rateLimit.test.js | 94 +++--- src/utils/stringify.ts | 4 +- yarn.lock | 389 ++++++----------------- 14 files changed, 864 insertions(+), 1339 deletions(-) create mode 100644 .github/workflows/test_bun.yml create mode 100644 src/CliCoreBase.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 794a450d..8006381d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Run Jest Tests +name: Run Jest Tests on Node.js on: push: diff --git a/.github/workflows/test_bun.yml b/.github/workflows/test_bun.yml new file mode 100644 index 00000000..393aba6d --- /dev/null +++ b/.github/workflows/test_bun.yml @@ -0,0 +1,42 @@ +name: Run Jest Tests on Bun.js + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test-bun: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Apache Pulsar + uses: reugn/github-action-pulsar@v1 + + - name: Install Bun + run: | + curl https://bun.sh/install | bash + echo "$HOME/.bun/bin" >> $GITHUB_PATH + + - name: Verify Bun Installation + run: bun --version + + - name: Install dependencies with Bun + run: bun install + + - name: Run Bun tests + run: bun run test:bun + + - name: Upload Bun test logs on failure + if: failure() + uses: actions/upload-artifact@v3 + with: + name: bun-test-logs + path: ./bun-test-logs/* + diff --git a/package-lock.json b/package-lock.json index b2a6c298..736ce7e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,27 @@ { "name": "stated-js", - "version": "0.1.28", + "version": "0.1.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "stated-js", - "version": "0.1.28", + "version": "0.1.34", "license": "Apache-2.0", "dependencies": { + "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.14.195", + "@types/lodash-es": "^4.17.12", + "@types/minimist": "^1.2.5", "chalk": "^5.3.0", "flatbuffers": "^23.5.26", "js-yaml": "^4.1.0", "json-colorizer": "^2.2.2", - "jsonata": "^2.0.3", + "jsonata": "2.0.4", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "minimist": "^1.2.8", - "pulsar-client": "^1.12.0", + "pulsar-flex": "^1.1.1", "readline": "^1.3.0", "repl": "^0.1.3", "string-argv": "^0.3.2", @@ -31,9 +35,7 @@ "@babel/core": "^7.22.20", "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/preset-env": "^7.22.20", - "@types/js-yaml": "^4.0.9", - "@types/lodash-es": "^4.17.12", - "@types/minimist": "^1.2.5", + "@jest/globals": "latest", "babel-loader": "^9.1.3", "copy-webpack-plugin": "^11.0.0", "jest": "^29.7.0", @@ -2864,78 +2866,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "license": "BSD-3-Clause", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3127,7 +3057,6 @@ "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { @@ -3141,14 +3070,12 @@ "version": "4.17.0", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", - "dev": true, "license": "MIT" }, "node_modules/@types/lodash-es": { "version": "4.17.12", "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/lodash": "*" @@ -3158,7 +3085,6 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, "license": "MIT" }, "node_modules/@types/node": { @@ -3420,12 +3346,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" - }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -3449,18 +3369,6 @@ "acorn": "^8" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -3529,6 +3437,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3568,26 +3477,6 @@ "node": ">= 8" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3840,21 +3729,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3987,15 +3869,6 @@ "node": ">=10" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -4112,15 +3985,6 @@ "simple-swizzle": "^0.2.2" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -4156,14 +4020,9 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC" - }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -4210,6 +4069,12 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/crc-full": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/crc-full/-/crc-full-1.1.0.tgz", + "integrity": "sha512-7YK4t8C9PiekOSnBotYjU2roaaorUXHyT+Xzb12Zgg4DsfG58AxmPk2/wx7XnC9UXyriqRvl3c+U0zFsZkdVYg==", + "license": "MIT" + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -4304,6 +4169,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -4342,21 +4208,6 @@ "node": ">=0.10.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -4421,6 +4272,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/enabled": { @@ -4704,12 +4556,6 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -4796,40 +4642,11 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -4854,27 +4671,6 @@ "dev": true, "license": "MIT" }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4923,6 +4719,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -4989,6 +4786,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5019,12 +4822,6 @@ "node": ">=8" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -5032,19 +4829,6 @@ "dev": true, "license": "MIT" }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5113,6 +4897,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -5169,6 +4954,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6912,9 +6698,9 @@ } }, "node_modules/jsonata": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.3.tgz", - "integrity": "sha512-Up2H81MUtjqI/dWwWX7p4+bUMfMrQJVMN/jW6clFMTiYP528fBOBNtRu944QhKTs3+IsVWbgMeUTny5fw2VMUA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.4.tgz", + "integrity": "sha512-vfavX4/G/yrYxE+UrmT/oUJ3ph7KqUrb0R7b0LVRcntQwxw+Z5kA1pNUIQzX5hF04Oe1eKxyoIPsmXtc2LgJTQ==", "license": "MIT", "engines": { "node": ">= 8" @@ -7192,6 +6978,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -7213,54 +7000,12 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, "license": "ISC", "engines": { "node": ">=8" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7281,32 +7026,6 @@ "dev": true, "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "license": "MIT" - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7321,21 +7040,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7359,32 +7063,11 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -7510,6 +7193,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7732,19 +7416,17 @@ "node": ">= 6" } }, - "node_modules/pulsar-client": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/pulsar-client/-/pulsar-client-1.12.0.tgz", - "integrity": "sha512-6xzL7ACXW6vf5J6ilsXB0Zvn1SjtLnuSP8AX+M1xtaVrR/F04BCMifOhxywpPWJpW7yaGJR1zYZjfimGxS8wiw==", - "hasInstallScript": true, - "license": "Apache-2.0", + "node_modules/pulsar-flex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pulsar-flex/-/pulsar-flex-1.1.1.tgz", + "integrity": "sha512-R6jNg4E326uItcG/QcNYLSOnZxMvVo4ZzxB2scEZDN3mp2VHKzPr/iiC07sXthrtdAVXlFTUt8+QyujoKc54ZA==", + "license": "MIT", "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "bindings": "^1.5.0", - "node-addon-api": "^4.3.0" + "crc-full": "^1.1.0", + "google-protobuf": "^3.17.3" }, "engines": { - "node": ">=12.3.0" + "node": ">=10.6.0" } }, "node_modules/punycode": { @@ -8183,12 +7865,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -8242,6 +7918,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, "license": "ISC" }, "node_modules/simple-swizzle": { @@ -8365,6 +8042,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -8395,6 +8073,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -8486,29 +8165,6 @@ "node": ">=6" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/terser": { "version": "5.19.4", "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", @@ -8709,12 +8365,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/triple-beam": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", @@ -8953,12 +8603,6 @@ "node": ">=10.13.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/webpack": { "version": "5.88.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", @@ -9149,16 +8793,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -9175,15 +8809,6 @@ "node": ">= 8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -9340,6 +8965,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { diff --git a/package.json b/package.json index f4c780f5..88fb1764 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "build": "tsc && npm run webpack && npm run docs", "webpack": "webpack && webpack --config webpack.config.cjs.js && webpack --config webpack.nodeSingleBin.cjs.js", "test": "npm run clean && npm run build && node --experimental-vm-modules node_modules/jest/bin/jest.js --detectOpenHandles", + "test:bun": "npm run clean && npm run build && bun test", "test-fast": "node --experimental-vm-modules node_modules/jest/bin/jest.js", "stated": "node --experimental-vm-modules dist/stated.js", "docs": "typedoc --out docs src/*" @@ -54,11 +55,11 @@ "flatbuffers": "^23.5.26", "js-yaml": "^4.1.0", "json-colorizer": "^2.2.2", - "jsonata": "^2.0.3", + "jsonata": "2.0.4", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "minimist": "^1.2.8", - "pulsar-client": "^1.12.0", + "pulsar-flex": "^1.1.1", "readline": "^1.3.0", "repl": "^0.1.3", "string-argv": "^0.3.2", @@ -69,6 +70,7 @@ "@babel/core": "^7.22.20", "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/preset-env": "^7.22.20", + "@jest/globals": "latest", "babel-loader": "^9.1.3", "copy-webpack-plugin": "^11.0.0", "jest": "^29.7.0", diff --git a/src/CliCore.ts b/src/CliCore.ts index 3e1b18e9..17079df8 100644 --- a/src/CliCore.ts +++ b/src/CliCore.ts @@ -11,354 +11,22 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -import fs from 'fs'; -import path from 'path'; + import TemplateProcessor from './TemplateProcessor.js'; -import yaml from 'js-yaml'; -import minimist from "minimist"; -import parseArgsStringToArgv from 'string-argv'; -import {Levels, LOG_LEVELS} from "./ConsoleLogger.js"; import * as repl from 'repl'; import {stringifyTemplateJSON} from "./utils/stringify.js"; import jsonata from "jsonata"; -import VizGraph from "./VizGraph.js"; -import { exec } from 'child_process'; -import http from 'http'; -import * as child_process from "child_process"; -import os from "os"; +import {CliCoreBase} from "./CliCoreBase.js"; -export default class CliCore { - private templateProcessor: TemplateProcessor; - private logLevel: keyof typeof LOG_LEVELS; - private currentDirectory:string; - //@ts-ignore - private server: http.Server; //http server to serve SVG images +export default class CliCore extends CliCoreBase{ //@ts-ignore public replServer:repl.REPLServer; - public onInit: () => Promise|void; constructor(templateProcessor: TemplateProcessor) { - this.templateProcessor = templateProcessor; - this.logLevel = "info"; - this.currentDirectory = process.cwd(); - this.onInit = ()=>{}; - } - public async close(){ - if(this.templateProcessor){ - await this.templateProcessor.close(); - } - if(this.server){ - this.server.close(); - } - } - - - static minimistArgs(replCmdInputStr:string) { - const args = parseArgsStringToArgv(replCmdInputStr); - return minimist(args); - - } - static parseInitArgs(replCmdInputStr:string){ - - const parsed = CliCore.minimistArgs(replCmdInputStr); - let {_:bareArgs ,f:filepath, o:oneshot,options="{}", ctx={}} = parsed; - let tags:any = parsed.tags ||""; - if(tags === true){ //weird case of --tags with no arguments - tags = ""; - } - if(tags===""){ - tags=[]; - }else { - tags = tags.split(',').map((s:string) => s.trim()); //tags are provided as JSON array - } - try { - options = JSON.parse(options); - }catch(e:any){ - console.error("failed to parse --options json: " + e.message); - throw e; - } - - filepath = filepath?filepath:bareArgs[0]; - oneshot = oneshot===true?oneshot:bareArgs.length > 0; - const processedArgs = {filepath, tags, oneshot, options, ctx}; - return {...parsed, ...processedArgs}; //spread the processedArgs back into what was parsed - } - - async readFileAndParse(filepath:string, importPath?:string) { - const fileExtension = path.extname(filepath).toLowerCase().replace(/\W/g, ''); - if (fileExtension === 'js' || fileExtension === 'mjs') { - return await import(CliCore.resolveImportPath(filepath, importPath)); - } - - const fileContent = await fs.promises.readFile(filepath, 'utf8'); - - if (fileExtension === 'yaml' || fileExtension === 'yml') { - return yaml.load(fileContent); - } else { - return JSON.parse(fileContent); - } - } - - static isNodeEnvironment() { - return typeof process !== 'undefined' && process.versions != null && process.versions.node != null; - } - - - static resolveImportPath(filepath: any, importPath: any): string { - if (!filepath) throw new Error("filepath is required"); - - // can't do any path resolution in browser - if (!CliCore.isNodeEnvironment()) return filepath; - - if (importPath) { - if (filepath && filepath.startsWith("~")) throw new Error("Cannot use file path starting with '~' with importPath"); - if (filepath && filepath.startsWith("/")) throw new Error("Cannot use file path starting with '/' with importPath"); - if (importPath.startsWith("/")) return path.resolve(path.join(importPath, filepath)) - - if (importPath.startsWith("~")) return path.resolve(path.join(importPath.replace("~", os.homedir()), filepath)); - - //relative path - return path.resolve(path.join(importPath, filepath)); - } - - if (filepath && filepath.includes("~")) return path.normalize(path.resolve(filepath.replace("~", os.homedir()))); - if (filepath && filepath.startsWith("/")) return path.normalize(filepath); - return path.join(process.cwd(), filepath); - } - - //replCmdInoutStr like: -f "defaultSnapshot.json" - - /** - * replCmdInoutStr example: -f "example/restoreSnapshot.json" --tags=["PEACE"] --xf=example/myEnv.json - * @param replCmdInputStr - the command line string that will be parsed into arguments - */ - async restore(replCmdInputStr: string) { - return this.init(replCmdInputStr, true); - - } - - /** - * This Cli core command may be invoked directly from the REPL init command or from restore command - * - * - fromSnapshot=false, replCmdInoutStr example: -f "example/ex23.json" --tags=["PEACE"] --xf=example/myEnv.json - * - fromSnapshot=true, replCmdInoutStr example: -f "example/restoreSnapshot.json" --tags=["PEACE"] --xf=example/myEnv.json - * - * @param replCmdInputStr - * @param fromSnapshot - when set to true, template processor will treat input as a snapshot of a previous - * templateProcessor state - */ - async init(replCmdInputStr:string, fromSnapshot: boolean=false) { - if(this.templateProcessor){ - this.templateProcessor.close(); - } - const parsed:any = CliCore.parseInitArgs(replCmdInputStr); - const {filepath, tags,oneshot, options, xf:contextFilePath, importPath=this.currentDirectory, tail, ctx={}} = parsed; - if(filepath===undefined){ - return undefined; - } - const input = await this.openFile(filepath); - let contextData = contextFilePath ? await this.readFileAndParse(contextFilePath, importPath) : {}; - contextData = {...contextData, ...ctx} //--ctx.foo=bar creates ctx={foo:bar}. The dot argument syntax is built into minimist - options.importPath = importPath; //path is where local imports will be sourced from. We sneak path in with the options - // if we initialize for the first time, we need to create a new instance of TemplateProcessor - if (!this.templateProcessor && !fromSnapshot) { - this.templateProcessor = new TemplateProcessor(input, contextData, options); - } else if (!this.templateProcessor && fromSnapshot) { - this.templateProcessor = TemplateProcessor.constructFromSnapshotObject(input, contextData); - } else { // if we are re-initializing, we need to reset the tagSet and options, if provided - this.templateProcessor.tagSet = new Set(); - this.templateProcessor.options = options; - if (contextData && Object.keys(contextData).length > 0) { - this.templateProcessor.setupContext(contextData); - } - } - if(this.replServer){ - //make variable called 'template' accessible in REPL - this.replServer.context.template = this.templateProcessor; - } - this.templateProcessor.onInitialize.set("CLI",this.onInit); - tags.forEach((a:string) => this.templateProcessor.tagSet.add(a)); - // set options - this.templateProcessor.logger.level = this.logLevel; - this.templateProcessor.logger.debug(`arguments: ${JSON.stringify(parsed)}`); - this.templateProcessor.context["open"] = this.openFile.bind(this); //$open('foo.json') is supported by the CLI adding $open function. It is not part of core TemplateProcessor as that would be security hole - try { - let tailPromise; - if(tail !== undefined){ - tailPromise = this.tail(tail); - } - if (fromSnapshot) { // restore from a snapshot - await this.templateProcessor.initialize(undefined, "/", input); - } else { - await this.templateProcessor.initialize(input); - } - const {__init} = contextData; - __init && __init(this.templateProcessor); //if a function named __init is found in the --xf, said context function is run - if(tail !== undefined){ - return tailPromise; - } - if (oneshot === true) { - return this.templateProcessor.output; - } - return this.templateProcessor.input; - - } catch (error:any) { - return { - name: error.name, - message: error.message - }; - } - - } - - private async openFile(fname:string){ - let _filepath = fname; - if(this.currentDirectory){ - _filepath = path.join(this.currentDirectory, _filepath); - } - return await this.readFileAndParse(_filepath); - } - - - async set(args:string) { - const options:any = args.match(/(?:[^\s"]+|"[^"]*")+/g); - let [path, data] = options; - let jsonPtr = path; - if (path === '-f') { - try { - // Read file - const fileContent = await fs.promises.readFile(data, 'utf8'); - const tmp = JSON.parse(fileContent); - jsonPtr = tmp.path; // Assumes the file contains an object with 'path' and 'data' properties - data = tmp.data; - } catch (err) { - console.error('Error reading file:', err); - throw err; - } - } - - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - try { - data = JSON.parse(data); - } catch (err) { - console.error('Error parsing JSON data:', err); - throw err; - } - - await this.templateProcessor.setData(jsonPtr, data); - return this.templateProcessor.output; - } - - in() { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - return this.templateProcessor.input; - } - - out(replCmdInputStr:string) { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - const parsed = CliCore.minimistArgs(replCmdInputStr === undefined ? "" : replCmdInputStr) - let {_:jsonPointer=""} = parsed; - if(Array.isArray(jsonPointer)){ - jsonPointer = jsonPointer[0]; - if(jsonPointer===undefined){ - jsonPointer = ""; - } - } - return this.templateProcessor.out(jsonPointer); - } - - state() { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - return this.templateProcessor.templateMeta; - } - - from(args:string) { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - const [jsonPtr, option] = args.split(' '); - return option === '--shallow' ? this.templateProcessor.getDependents(jsonPtr) : this.templateProcessor.from(jsonPtr); - } - - to(args:string) { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - const [jsonPtr, option] = args.split(' '); - return option === '--shallow' ? this.templateProcessor.getDependencies(jsonPtr) : this.templateProcessor.to(jsonPtr); + super(templateProcessor); } - async plan() { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - return await this.templateProcessor.getEvaluationPlan(); - } - - log(level:Levels) { - this.logLevel = level; - if(this.templateProcessor){ - this.templateProcessor.logger.level = level; - } - return {"log level":level}; - } - - note(){ - return "============================================================="; - } - - async debug(replCmdInputStr:string) { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - const parsed = CliCore.minimistArgs(replCmdInputStr) - return this.templateProcessor.debugger.processCommands(parsed); - } - - async errors() { - if (!this.templateProcessor) { - throw new Error('Initialize the template first.'); - } - return this.templateProcessor.errorReport; - } - - private extractArgsInfo(args:string) { - // Define the regex patterns - const jsonPointerNumberPattern = /^(?\/[^\s]*)(?:\s+(?\d+))?$/; - const untilJsonataPattern = /^(?\/[^\s]*)\s+until\s+(?[^\n]+)$/; - - // Try to match the args string against both patterns - const matchNumberFormat = args.match(jsonPointerNumberPattern); - const matchUntilJsonataFormat = args.match(untilJsonataPattern); - - // Check which format was matched - if (matchNumberFormat) { - // Extracted information for format - const { jsonPointer, number } = matchNumberFormat.groups || {}; - if (jsonPointer) { - return { format: "Number", jsonPointer, number: parseInt(number, 10) }; - } - } else if (matchUntilJsonataFormat) { - // Extracted information for format - const { jsonPointer, jsonataExpression } = matchUntilJsonataFormat.groups || {}; - if (jsonPointer) { - return { format: "UntilJsonata", jsonPointer, jsonataExpression }; - } - } - - throw new Error(`invalid --tail args: ${args}`); - } - - public async tail(args: string): Promise { console.log("Started tailing... Press Ctrl+C to stop.") @@ -445,149 +113,5 @@ export default class CliCore { }; //the last result tailed to the screen is what this command returns } - - - public async open(directory: string = this.currentDirectory) { - if(directory === ""){ - directory = this.currentDirectory; - } - - let files: string[]|undefined = undefined; - try { - // Read all files from the directory - files = await fs.promises.readdir(directory); - } catch (error) { - console.log(`Error reading directory ${directory}: ${error}`); - console.log('Changed directory with .cd or .open an/existing/directory'); - this.replServer.displayPrompt(); - return {error: `Error reading directory ${directory}: ${error}`}; - } - // Filter out only .json and .yaml files - const templateFiles: string[] = files.filter(file => file.endsWith('.json') || file.endsWith('.yaml')); - - // Display the list of files to the user - templateFiles.forEach((file, index) => { - console.log(`${index + 1}: ${file}`); - }); - - // Create an instance of AbortController - const ac = new AbortController(); - const {signal} = ac; // Get the AbortSignal from the controller - - // Ask the user to choose a file - this.replServer.question('Enter the number of the file to open (or type "abort" to cancel): ', {signal}, async (answer) => { - // Check if the operation was aborted - if (signal.aborted) { - console.log('File open operation was aborted.'); - this.replServer.displayPrompt(); - return; - } - - const fileIndex = parseInt(answer, 10) - 1; // Convert to zero-based index - if (fileIndex >= 0 && fileIndex < templateFiles.length) { - // User has entered a valid file number; initialize with this file - const filepath = templateFiles[fileIndex]; - try { - const result = await this.init(`-f "${filepath}"`); // Adjust this call as per your init method's expected format - console.log(stringifyTemplateJSON(result)); - console.log("...try '.out' or 'template.output' to see evaluated template") - } catch (error) { - console.log('Error loading file:', error); - } - } else { - console.log('Invalid file number.'); - } - this.replServer.displayPrompt(); - }); - - // Allow the user to type "abort" to cancel the file open operation - this.replServer.once('SIGINT', () => { - ac.abort(); - }); - - return "open... (type 'abort' to cancel)"; - } - - - public cd(newDirectory: string) { - // Resolve the new path against the current directory to support relative paths - const resolvedNewDirectory = path.resolve(this.currentDirectory, newDirectory); - - // Check if the resolved new directory path is valid - if (fs.existsSync(resolvedNewDirectory) && fs.lstatSync(resolvedNewDirectory).isDirectory()) { - this.currentDirectory = resolvedNewDirectory; - return `Current directory changed to: ${this.currentDirectory}`; - } else { - return `Invalid directory: ${newDirectory}`; - } - } - - public svg(replCmdInputStr:string):string { - const {port=3000} = CliCore.minimistArgs(replCmdInputStr); - - const startServer = () => { - this.server = http.createServer((req, res) => { - // Check for a specific URL path or request method if needed - - // Execute 'dot' to convert the DOT code to SVG - const dotProcess:child_process.ChildProcess = exec(`dot -Tsvg`, (error, stdout, stderr) => { - if (error) { - console.error(`Error converting DOT to SVG: ${error.message}`); - res.writeHead(500, { 'Content-Type': 'text/plain' }); - res.end('Internal Server Error'); - return; - } - - if (stderr) { - console.error(`dot stderr: ${stderr}`); - } - - // Set the response headers for SVG content - res.writeHead(200, { - 'Content-Type': 'image/svg+xml', - }); - - // Send the SVG data as the HTTP response - res.end(stdout); - }); - if(this.templateProcessor && dotProcess) { - const dot = VizGraph.dot(this.templateProcessor); - // Pipe the DOT code string to the 'dot' process - dotProcess.stdin?.write(dot); - dotProcess.stdin?.end(); - } - }); - - this.server.on('error', (error:any) => { - if (error.code === 'EADDRINUSE') { - console.error(`Port ${port} is already in use.`); - } else { - console.error(`Server error: ${error.message}`); - } - }); - - this.server.listen(port, () => { - console.log(`Server is running on port ${port}`); - }); - }; - - if (this.server) { - // Server is already running, return its URL - return `http://localhost:${port}`; - } else { - // Start the server and return its URL - startServer(); - return `http://localhost:${port}`; - } - } - - /** - * this method is just here as a stub to allow tests to pass. Color is in reality handled only by StatedRepl, - * it is not something that is possible to 'see' from the CLI since CLI returns pure JSON which has no concept - * of terminal colors. - */ - color(){ - ""; - } } diff --git a/src/CliCoreBase.ts b/src/CliCoreBase.ts new file mode 100644 index 00000000..c8c46177 --- /dev/null +++ b/src/CliCoreBase.ts @@ -0,0 +1,445 @@ +// Copyright 2023 Cisco Systems, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import fs from 'fs'; +import path from 'path'; +import TemplateProcessor from './TemplateProcessor.js'; +import yaml from 'js-yaml'; +import minimist from "minimist"; +import parseArgsStringToArgv from 'string-argv'; +import {Levels, LOG_LEVELS} from "./ConsoleLogger.js"; +import VizGraph from "./VizGraph.js"; +import { exec } from 'child_process'; +import http from 'http'; +import * as child_process from "child_process"; +import os from "os"; + +/** + * Base class for building CLIs. By itself can be used for a CLI that does not support the tail command. Tail command + * uses Node repl class that is not implemented in other JS runtimes such as Bun. CliCoreBase should run in Bun. + */ +export class CliCoreBase { + protected templateProcessor: TemplateProcessor; + private logLevel: keyof typeof LOG_LEVELS; + protected currentDirectory:string; + //@ts-ignore + private server: http.Server; //http server to serve SVG images + public onInit: () => Promise|void; + + constructor(templateProcessor: TemplateProcessor) { + this.templateProcessor = templateProcessor; + this.logLevel = "info"; + this.currentDirectory = process.cwd(); + this.onInit = ()=>{}; + } + public async close(){ + if(this.templateProcessor){ + await this.templateProcessor.close(); + } + if(this.server){ + this.server.close(); + } + } + + + static minimistArgs(replCmdInputStr:string) { + const args = parseArgsStringToArgv(replCmdInputStr); + return minimist(args); + + } + static parseInitArgs(replCmdInputStr:string){ + + const parsed = CliCoreBase.minimistArgs(replCmdInputStr); + let {_:bareArgs ,f:filepath, o:oneshot,options="{}", ctx={}} = parsed; + let tags:any = parsed.tags ||""; + if(tags === true){ //weird case of --tags with no arguments + tags = ""; + } + if(tags===""){ + tags=[]; + }else { + tags = tags.split(',').map((s:string) => s.trim()); //tags are provided as JSON array + } + try { + options = JSON.parse(options); + }catch(e:any){ + console.error("failed to parse --options json: " + e.message); + throw e; + } + + filepath = filepath?filepath:bareArgs[0]; + oneshot = oneshot===true?oneshot:bareArgs.length > 0; + const processedArgs = {filepath, tags, oneshot, options, ctx}; + return {...parsed, ...processedArgs}; //spread the processedArgs back into what was parsed + } + + async readFileAndParse(filepath:string, importPath?:string) { + const fileExtension = path.extname(filepath).toLowerCase().replace(/\W/g, ''); + if (fileExtension === 'js' || fileExtension === 'mjs') { + return await import(CliCoreBase.resolveImportPath(filepath, importPath)); + } + + const fileContent = await fs.promises.readFile(filepath, 'utf8'); + + if (fileExtension === 'yaml' || fileExtension === 'yml') { + return yaml.load(fileContent); + } else { + return JSON.parse(fileContent); + } + } + + static isNodeEnvironment() { + return typeof process !== 'undefined' && process.versions != null && process.versions.node != null; + } + + + static resolveImportPath(filepath: any, importPath: any): string { + if (!filepath) throw new Error("filepath is required"); + + // can't do any path resolution in browser + if (!CliCoreBase.isNodeEnvironment()) return filepath; + + if (importPath) { + if (filepath && filepath.startsWith("~")) throw new Error("Cannot use file path starting with '~' with importPath"); + if (filepath && filepath.startsWith("/")) throw new Error("Cannot use file path starting with '/' with importPath"); + if (importPath.startsWith("/")) return path.resolve(path.join(importPath, filepath)) + + if (importPath.startsWith("~")) return path.resolve(path.join(importPath.replace("~", os.homedir()), filepath)); + + //relative path + return path.resolve(path.join(importPath, filepath)); + } + + if (filepath && filepath.includes("~")) return path.normalize(path.resolve(filepath.replace("~", os.homedir()))); + if (filepath && filepath.startsWith("/")) return path.normalize(filepath); + return path.join(process.cwd(), filepath); + } + + //replCmdInoutStr like: -f "defaultSnapshot.json" + + /** + * replCmdInoutStr example: -f "example/restoreSnapshot.json" --tags=["PEACE"] --xf=example/myEnv.json + * @param replCmdInputStr - the command line string that will be parsed into arguments + */ + async restore(replCmdInputStr: string) { + return this.init(replCmdInputStr, true); + + } + + /** + * This Cli core command may be invoked directly from the REPL init command or from restore command + * + * - fromSnapshot=false, replCmdInoutStr example: -f "example/ex23.json" --tags=["PEACE"] --xf=example/myEnv.json + * - fromSnapshot=true, replCmdInoutStr example: -f "example/restoreSnapshot.json" --tags=["PEACE"] --xf=example/myEnv.json + * + * @param replCmdInputStr + * @param fromSnapshot - when set to true, template processor will treat input as a snapshot of a previous + * templateProcessor state + */ + async init(replCmdInputStr:string, fromSnapshot: boolean=false) { + if(this.templateProcessor){ + this.templateProcessor.close(); + } + const parsed:any = CliCoreBase.parseInitArgs(replCmdInputStr); + const {filepath, tags,oneshot, options, xf:contextFilePath, importPath=this.currentDirectory, tail, ctx={}} = parsed; + if(filepath===undefined){ + return undefined; + } + const input = await this.openFile(filepath); + let contextData = contextFilePath ? await this.readFileAndParse(contextFilePath, importPath) : {}; + contextData = {...contextData, ...ctx} //--ctx.foo=bar creates ctx={foo:bar}. The dot argument syntax is built into minimist + options.importPath = importPath; //path is where local imports will be sourced from. We sneak path in with the options + // if we initialize for the first time, we need to create a new instance of TemplateProcessor + if (!this.templateProcessor && !fromSnapshot) { + this.templateProcessor = new TemplateProcessor(input, contextData, options); + } else if (!this.templateProcessor && fromSnapshot) { + this.templateProcessor = TemplateProcessor.constructFromSnapshotObject(input, contextData); + } else { // if we are re-initializing, we need to reset the tagSet and options, if provided + this.templateProcessor.tagSet = new Set(); + this.templateProcessor.options = options; + if (contextData && Object.keys(contextData).length > 0) { + this.templateProcessor.setupContext(contextData); + } + } + this.templateProcessor.onInitialize.set("CLI",this.onInit); + tags.forEach((a:string) => this.templateProcessor.tagSet.add(a)); + // set options + this.templateProcessor.logger.level = this.logLevel; + this.templateProcessor.logger.debug(`arguments: ${JSON.stringify(parsed)}`); + this.templateProcessor.context["open"] = this.openFile.bind(this); //$open('foo.json') is supported by the CLI adding $open function. It is not part of core TemplateProcessor as that would be security hole + try { + let tailPromise; + if(tail !== undefined){ + tailPromise = this.tail(tail); + } + if (fromSnapshot) { // restore from a snapshot + await this.templateProcessor.initialize(undefined, "/", input); + } else { + await this.templateProcessor.initialize(input); + } + const {__init} = contextData; + __init && __init(this.templateProcessor); //if a function named __init is found in the --xf, said context function is run + if(tail !== undefined){ + return tailPromise; + } + if (oneshot === true) { + return this.templateProcessor.output; + } + return this.templateProcessor.input; + + } catch (error:any) { + return { + name: error.name, + message: error.message + }; + } + + } + + private async openFile(fname:string){ + let _filepath = fname; + if(this.currentDirectory){ + _filepath = path.join(this.currentDirectory, _filepath); + } + return await this.readFileAndParse(_filepath); + } + + + async set(args:string) { + const options:any = args.match(/(?:[^\s"]+|"[^"]*")+/g); + let [path, data] = options; + let jsonPtr = path; + if (path === '-f') { + try { + // Read file + const fileContent = await fs.promises.readFile(data, 'utf8'); + const tmp = JSON.parse(fileContent); + jsonPtr = tmp.path; // Assumes the file contains an object with 'path' and 'data' properties + data = tmp.data; + } catch (err) { + console.error('Error reading file:', err); + throw err; + } + } + + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + try { + data = JSON.parse(data); + } catch (err) { + console.error('Error parsing JSON data:', err); + throw err; + } + + await this.templateProcessor.setData(jsonPtr, data); + return this.templateProcessor.output; + } + + in() { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + return this.templateProcessor.input; + } + + out(replCmdInputStr:string) { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + const parsed = CliCoreBase.minimistArgs(replCmdInputStr === undefined ? "" : replCmdInputStr) + let {_:jsonPointer=""} = parsed; + if(Array.isArray(jsonPointer)){ + jsonPointer = jsonPointer[0]; + if(jsonPointer===undefined){ + jsonPointer = ""; + } + } + return this.templateProcessor.out(jsonPointer); + } + + state() { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + return this.templateProcessor.templateMeta; + } + + from(args:string) { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + const [jsonPtr, option] = args.split(' '); + return option === '--shallow' ? this.templateProcessor.getDependents(jsonPtr) : this.templateProcessor.from(jsonPtr); + } + + to(args:string) { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + const [jsonPtr, option] = args.split(' '); + return option === '--shallow' ? this.templateProcessor.getDependencies(jsonPtr) : this.templateProcessor.to(jsonPtr); + } + + async plan() { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + return await this.templateProcessor.getEvaluationPlan(); + } + + log(level:Levels) { + this.logLevel = level; + if(this.templateProcessor){ + this.templateProcessor.logger.level = level; + } + return {"log level":level}; + } + + note(){ + return "============================================================="; + } + + async debug(replCmdInputStr:string) { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + const parsed = CliCoreBase.minimistArgs(replCmdInputStr) + return this.templateProcessor.debugger.processCommands(parsed); + } + + async errors() { + if (!this.templateProcessor) { + throw new Error('Initialize the template first.'); + } + return this.templateProcessor.errorReport; + } + + protected extractArgsInfo(args:string) { + // Define the regex patterns + const jsonPointerNumberPattern = /^(?\/[^\s]*)(?:\s+(?\d+))?$/; + const untilJsonataPattern = /^(?\/[^\s]*)\s+until\s+(?[^\n]+)$/; + + // Try to match the args string against both patterns + const matchNumberFormat = args.match(jsonPointerNumberPattern); + const matchUntilJsonataFormat = args.match(untilJsonataPattern); + + // Check which format was matched + if (matchNumberFormat) { + // Extracted information for format + const { jsonPointer, number } = matchNumberFormat.groups || {}; + if (jsonPointer) { + return { format: "Number", jsonPointer, number: parseInt(number, 10) }; + } + } else if (matchUntilJsonataFormat) { + // Extracted information for format + const { jsonPointer, jsonataExpression } = matchUntilJsonataFormat.groups || {}; + if (jsonPointer) { + return { format: "UntilJsonata", jsonPointer, jsonataExpression }; + } + } + + throw new Error(`invalid --tail args: ${args}`); + } + + + public cd(newDirectory: string) { + // Resolve the new path against the current directory to support relative paths + const resolvedNewDirectory = path.resolve(this.currentDirectory, newDirectory); + + // Check if the resolved new directory path is valid + if (fs.existsSync(resolvedNewDirectory) && fs.lstatSync(resolvedNewDirectory).isDirectory()) { + this.currentDirectory = resolvedNewDirectory; + return `Current directory changed to: ${this.currentDirectory}`; + } else { + return `Invalid directory: ${newDirectory}`; + } + } + + public svg(replCmdInputStr:string):string { + const {port=3000} = CliCoreBase.minimistArgs(replCmdInputStr); + + const startServer = () => { + this.server = http.createServer((req, res) => { + // Check for a specific URL path or request method if needed + + // Execute 'dot' to convert the DOT code to SVG + const dotProcess:child_process.ChildProcess = exec(`dot -Tsvg`, (error, stdout, stderr) => { + if (error) { + console.error(`Error converting DOT to SVG: ${error.message}`); + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end('Internal Server Error'); + return; + } + + if (stderr) { + console.error(`dot stderr: ${stderr}`); + } + + // Set the response headers for SVG content + res.writeHead(200, { + 'Content-Type': 'image/svg+xml', + }); + + // Send the SVG data as the HTTP response + res.end(stdout); + }); + if(this.templateProcessor && dotProcess) { + const dot = VizGraph.dot(this.templateProcessor); + // Pipe the DOT code string to the 'dot' process + dotProcess.stdin?.write(dot); + dotProcess.stdin?.end(); + } + }); + + this.server.on('error', (error:any) => { + if (error.code === 'EADDRINUSE') { + console.error(`Port ${port} is already in use.`); + } else { + console.error(`Server error: ${error.message}`); + } + }); + + this.server.listen(port, () => { + console.log(`Server is running on port ${port}`); + }); + }; + + if (this.server) { + // Server is already running, return its URL + return `http://localhost:${port}`; + } else { + // Start the server and return its URL + startServer(); + return `http://localhost:${port}`; + } + } + + /** + * this method is just here as a stub to allow tests to pass. Color is in reality handled only by StatedRepl, + * it is not something that is possible to 'see' from the CLI since CLI returns pure JSON which has no concept + * of terminal colors. + */ + color(){ + return; + } + + getTemplateProcessor() { + return this.templateProcessor; + } + + public async tail(args: string): Promise { + throw new Error('tail command is not implemented in CliCoreBase'); + } +} + diff --git a/src/StatedREPL.ts b/src/StatedREPL.ts index 70243a6c..e3d764fd 100755 --- a/src/StatedREPL.ts +++ b/src/StatedREPL.ts @@ -22,7 +22,7 @@ import TemplateProcessor from "./TemplateProcessor.js"; export default class StatedREPL { private readonly cliCore: CliCore; //@ts-ignore - r: repl.REPLServer; + replServer: repl.REPLServer; private isColorized:boolean=false; constructor(templateProcessor: TemplateProcessor) { this.cliCore = new CliCore(templateProcessor); @@ -67,31 +67,33 @@ export default class StatedREPL { return; //do not start REPL. We produced oneshot output, now bail } //crank up the interactive REPL - this.r = repl.start({ + this.replServer = repl.start({ prompt: '> ', useColors:true, useGlobal:true }); - this.cliCore.replServer = this.r; + //make variable called 'template' accessible in REPL + this.replServer.context.template = this.cliCore.getTemplateProcessor(); + this.cliCore.replServer = this.replServer; this.registerCommands(); } close(){ this.cliCore.close(); - this.r.close(); + this.replServer.close(); } registerCommands() { StatedREPL.CLICORE_COMMANDS.map(c=>{ const [cmdName, helpMsg] = c; - this.r.defineCommand(cmdName, { + this.replServer.defineCommand(cmdName, { help: helpMsg, action: async (args) => { await this.cli(cmdName, args); }, }); }); - this.r.defineCommand("color", { + this.replServer.defineCommand("color", { help: "[on|off] colorize JSON", action: async (args) => { if(args.trim()==="on"){ @@ -99,25 +101,25 @@ export default class StatedREPL { }else if(args.trim()==="off"){ this.isColorized = false; } - this.r.displayPrompt(); + this.replServer.displayPrompt(); }, }); //these other commands are REPL-only commands and are not part of the CLiCore that does //template processing - this.r.defineCommand('help', { + this.replServer.defineCommand('help', { help: 'Display available commands and their descriptions', action: () => { try { console.log('Available commands:'); - Object.entries(this.r.commands).forEach(([name, command]) => { + Object.entries(this.replServer.commands).forEach(([name, command]) => { //@ts-ignore console.log(` .${name} - ${command.help}`); }); } catch (e) { console.error(e); } - this.r.displayPrompt(); + this.replServer.displayPrompt(); }, }); } @@ -137,7 +139,7 @@ export default class StatedREPL { } catch (e:any) { console.error(stringify(e.message)); } - this.r.displayPrompt(); + this.replServer.displayPrompt(); } static colorize(s:string):string{ diff --git a/src/index.ts b/src/index.ts index c459c20d..79009c01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,4 +5,5 @@ export * from './TemplateProcessor.js'; export * as MetaInfoProducer from './MetaInfoProducer.js'; export {default as JsonPointer} from './JsonPointer.js' export {stringifyTemplateJSON} from './utils/stringify.js' +export {CliCoreBase} from './CliCoreBase.js'; diff --git a/src/test/Pulsar.test.js b/src/test/Pulsar.test.js index 3c523734..a3411b8f 100644 --- a/src/test/Pulsar.test.js +++ b/src/test/Pulsar.test.js @@ -1,47 +1,106 @@ -// pulsar.test.js -import Pulsar from 'pulsar-client'; +import pulsar from 'pulsar-flex'; +import {jest, describe, beforeAll, afterAll, test, expect} from "@jest/globals"; -describe('Pulsar Standalone Mode', () => { - let client; +describe('pulsar-flex Integration Test', () => { + //jest.useFakeTimers() let producer; let consumer; + const topic = "persistent://public/default/yyy"; + const subscription = "test-subscription-xxx"; + + const messagesToSend = [ + { properties: { pulsar: "flex" }, payload: 'Ayeo' } + ]; + + let receivedMessages = []; + + // Increase Jest's default timeout since Pulsar operations might take longer + jest.setTimeout(1000000000); // 20 seconds + beforeAll(async () => { - // Create a Pulsar client connected to the local standalone broker - client = new Pulsar.Client({ - serviceUrl: 'pulsar://localhost:6650', + // Initialize Producer + producer = new pulsar.Producer({ + topic: topic, + discoveryServers: ['localhost:6650'], + // If your Pulsar setup requires JWT, ensure it's set in the environment variables + jwt: process.env.JWT_TOKEN, + producerAccessMode: pulsar.Producer.ACCESS_MODES.SHARED, + logLevel: pulsar.logLevel.TRACE + // Optionally, provide a logCreator function for custom logging + }); + + // Initialize Consumer + consumer = new pulsar.Consumer({ + topic: topic, + subscription: subscription, + discoveryServers: ['localhost:6650'], + jwt: process.env.JWT_TOKEN, + subType: pulsar.Consumer.SUB_TYPES.EXCLUSIVE, + consumerName: 'Test Consumer xxx', + receiveQueueSize: 1, + logLevel: pulsar.logLevel.TRACE, + // Optionally, provide a logCreator function for custom logging }); - // Create a producer on a test topic - producer = await client.createProducer({ - topic: 'persistent://public/default/test-topic', + // Create Producer + await producer.create(); + + + // Optional: Listen to Consumer state changes + consumer.onStateChange(({ previousState, newState }) => { + //console.log(`Consumer state changed from ${previousState} to ${newState}.`); }); - // Create a consumer to verify message delivery - consumer = await client.subscribe({ - topic: 'persistent://public/default/test-topic', - subscription: 'test-subscription', - subscriptionType: 'Exclusive', + // Subscribe Consumer + await consumer.subscribe(); + + // Run Consumer + await consumer.run({ + onMessage: async ({ ack, message, properties, redeliveryCount }) => { + await ack(); // Acknowledge the message + receivedMessages.push({ + message: message, // Contains the payload + properties: properties, // Message properties + redeliveryCount: redeliveryCount, // Number of times the message was redelivered + }); + }, + autoAck: false, // Manual acknowledgment }); }); - afterAll(async () => { - // Clean up: close the producer, consumer, and client + test('should produce and consume messages successfully', async () => { + // Send a batch of messages + await producer.sendMessage({ properties: { pulsar: "flex" }, payload: 'Ayeo' }); await producer.close(); - await consumer.close(); - await client.close(); - }); + // Wait for messages to be received + const maxWaitTime = 10000; // 10 seconds + const pollInterval = 100; // 100ms + let waited = 0; + + while (receivedMessages.length < 1 && waited < maxWaitTime) { + await new Promise(resolve => setTimeout(resolve, pollInterval)); + waited += pollInterval; + } - test('should produce and consume a message', async () => { - // Send a test message - const message = Buffer.from('Hello, Pulsar!'); - await producer.send({ data: message }); + // Assertions + expect(receivedMessages.length).toBe(messagesToSend.length); - // Receive the message - const msg = await consumer.receive(); - expect(msg.getData().toString()).toBe('Hello, Pulsar!'); + receivedMessages.forEach((received, index) => { + expect(received.message.toString()).toBe(messagesToSend[index].payload); + expect(received.properties).toEqual(messagesToSend[index].properties); + expect(received.redeliveryCount).toBe(0); // Assuming no redeliveries + }); - // Acknowledge the message - consumer.acknowledge(msg); + try { + await consumer.unsubscribe(); + } catch (error) { + console.error('Error during cleanup:', error); + } + /** uncomment these lines, and you will find that the test completes normally with no open handles + * detected. + */ + producer._client.getCnx().close(); + await new Promise(resolve => setTimeout(resolve, 11000)); }); }); diff --git a/src/test/StatedREPL.test.js b/src/test/StatedREPL.test.js index fa86b0ee..5491d0b2 100644 --- a/src/test/StatedREPL.test.js +++ b/src/test/StatedREPL.test.js @@ -33,34 +33,69 @@ test("test stringify custom print function", async () => { }`); }); -/** Test that the onInit function is called when the .init command is called */ -test("test onInit", async () => { - const repl1 = new StatedREPL(); - await repl1.initialize(); - - const repl2 = new StatedREPL(); - await repl2.initialize(); - - try { - let beenCalled1 = false; - repl1.cliCore.onInit = () => { - beenCalled1 = true; +if(typeof Bun === "undefined") { //run on node, not bun + /** Test that the onInit function is called when the .init command is called */ + test("test onInitxx", async () => { + const repl1 = new StatedREPL(); + await repl1.initialize(); + + const repl2 = new StatedREPL(); + await repl2.initialize(); + + try { + let beenCalled1 = false; + repl1.cliCore.onInit = () => { + beenCalled1 = true; + } + let beenCalled2 = false; + repl2.cliCore.onInit = () => { + beenCalled2 = true; + } + await repl1.cliCore.init('-f "example/ex01.yaml"'); + expect(beenCalled1).toBe(true); + expect(beenCalled2).toBe(false); + + await repl2.cliCore.init('-f "example/ex01.yaml"'); + expect(beenCalled2).toBe(true); + } finally { + await repl1.close(); + await repl2.close(); } - let beenCalled2 = false; - repl2.cliCore.onInit = () => { - beenCalled2 = true; + }); + // Validates restore command + test("Extend CliCore with restore command", async () => { + + // ensure jest argv does not interfere with the test + const originalCmdLineArgsStr = process.argv; + process.argv = ["node", "dist/stated.js"]; // this is an argv when running stated.js repl. + + // extend CliCore with restore command + const repl = new StatedREPL(); + + try { + await repl.initialize(); + + // we call restore on the repl, which will expect it to be defined in CliCore. + await repl.cli('restore', '-f example/restoreSnapshot.json'); + + console.log(stringify(repl.cliCore.templateProcessor.output)); + expect(repl.cliCore.templateProcessor.output).toBeDefined(); + expect(repl.cliCore.templateProcessor.output.count).toBeGreaterThanOrEqual(3); // should be 3 or more right after restoring from the snapshot + expect(repl.cliCore.templateProcessor.output.count).toBeLessThan(10); // ... but less than 10 + + + while (repl.cliCore.templateProcessor.output.count < 10) { // validates that templateProcessor picks up where it was left in the snapshot. + console.log("waiting for output.count to reach 10") + await new Promise(resolve => setTimeout(resolve, 50)); + } + expect(repl.cliCore.templateProcessor.output.count).toBe(10); + } finally { + process.argv = originalCmdLineArgsStr; + if (repl !== undefined) await repl.close(); } - await repl1.cliCore.init('-f "example/ex01.yaml"'); - expect(beenCalled1).toBe(true); - expect(beenCalled2).toBe(false); - - await repl2.cliCore.init('-f "example/ex01.yaml"'); - expect(beenCalled2).toBe(true); - }finally { - await repl1.close(); - await repl2.close(); - } -}); + }); + +} // This test validates a bug when running an init command in StatedREPL overwrites context of provided TemplateProcessor test("TemplateProcessor keeps context on init", async () => { @@ -78,35 +113,3 @@ test("TemplateProcessor keeps context on init", async () => { ); }); -// Validates restore command -test("Extend CliCore with restore command", async () => { - - // ensure jest argv does not interfere with the test - const originalCmdLineArgsStr = process.argv; - process.argv = ["node", "dist/stated.js"]; // this is an argv when running stated.js repl. - - // extend CliCore with restore command - const repl = new StatedREPL(); - - try { - await repl.initialize(); - - // we call restore on the repl, which will expect it to be defined in CliCore. - await repl.cli('restore', '-f example/restoreSnapshot.json'); - - console.log(stringify(repl.cliCore.templateProcessor.output)); - expect(repl.cliCore.templateProcessor.output).toBeDefined(); - expect(repl.cliCore.templateProcessor.output.count).toBeGreaterThanOrEqual(3); // should be 3 or more right after restoring from the snapshot - expect(repl.cliCore.templateProcessor.output.count).toBeLessThan(10); // ... but less than 10 - - - while (repl.cliCore.templateProcessor.output.count < 10) { // validates that templateProcessor picks up where it was left in the snapshot. - console.log("waiting for output.count to reach 10") - await new Promise(resolve => setTimeout(resolve, 50)); - } - expect(repl.cliCore.templateProcessor.output.count).toBe(10); - } finally { - process.argv = originalCmdLineArgsStr; - if (repl !== undefined) await repl.close(); - } -}); \ No newline at end of file diff --git a/src/test/TemplateProcessor.test.js b/src/test/TemplateProcessor.test.js index b7ce3525..6e666e8c 100644 --- a/src/test/TemplateProcessor.test.js +++ b/src/test/TemplateProcessor.test.js @@ -22,7 +22,7 @@ import {dirname} from 'path'; import DependencyFinder from "../../dist/src/DependencyFinder.js"; import jsonata from "jsonata"; import { default as jp } from "../../dist/src/JsonPointer.js"; -import {expect} from "@jest/globals"; +//import {expect} from "@jest/globals"; import StatedREPL from "../../dist/src/StatedREPL.js"; test("test 1", async () => { diff --git a/src/test/utils/rateLimit.test.js b/src/test/utils/rateLimit.test.js index 47e30538..3528c109 100644 --- a/src/test/utils/rateLimit.test.js +++ b/src/test/utils/rateLimit.test.js @@ -13,54 +13,64 @@ // limitations under the License. import { rateLimit } from "../../../dist/src/utils/rateLimit.js"; -import {expect, jest} from '@jest/globals' +import { jest, expect, describe, beforeEach, afterEach, test} from '@jest/globals'; -describe('rateLimit function', () => { - jest.useFakeTimers(); - /** - * Below test validates the following scenario - * rateLimitedFunction('First call'); // called at 0ms and Executed immediately - * rateLimitedFunction('Second call'); // called at 500ms, deferred till execution at 1000ms - * rateLimitedFunction('Third call'); // called at 700ms, deferred till execution at 1000ms, and replaces the Second call - * // at 1000ms 'Third call' gets executed. - * rateLimitedFunction('Forth call'); // called at 1100ms and gets executed in 2000ms - **/ - it('should rate limit function calls as specified', () => { - const mockFunction = jest.fn(); - const maxWait = 1000; - const rateLimitedFunction = rateLimit(mockFunction, maxWait); +if(typeof Bun === 'undefined'){ //advanceTimersByTime is not available in Bun + describe('rateLimit function', () => { + beforeEach(() => { + // Enable fake timers before each test + jest.useFakeTimers('modern'); + }); - // First call - executed immediately - rateLimitedFunction('First call'); - expect(mockFunction).toHaveBeenCalledTimes(1); - expect(mockFunction).toHaveBeenCalledWith('First call'); + afterEach(() => { + // Restore real timers after each test + jest.useRealTimers(); + }); - // Second call - deferred - jest.advanceTimersByTime(500); - rateLimitedFunction('Second call'); - expect(mockFunction).toHaveBeenCalledTimes(1); + /** + * Below test validates the following scenario + * rateLimitedFunction('First call'); // called at 0ms and Executed immediately + * rateLimitedFunction('Second call'); // called at 500ms, deferred till execution at 1000ms + * rateLimitedFunction('Third call'); // called at 700ms, deferred till execution at 1000ms, and replaces the Second call + * // at 1000ms 'Third call' gets executed. + * rateLimitedFunction('Forth call'); // called at 1100ms and gets executed in 2000ms + **/ + test('should rate limit function calls as specified', () => { + const mockFunction = jest.fn(); + const maxWait = 1000; + const rateLimitedFunction = rateLimit(mockFunction, maxWait); - // Third call - replaces second, also deferred - jest.advanceTimersByTime(200); - rateLimitedFunction('Third call'); - expect(mockFunction).toHaveBeenCalledTimes(1); + // First call - executed immediately + rateLimitedFunction('First call'); + expect(mockFunction).toHaveBeenCalledTimes(1); + expect(mockFunction).toHaveBeenCalledWith('First call'); - // Executing the deferred 'Third call' - jest.advanceTimersByTime(350); - expect(mockFunction).toHaveBeenCalledTimes(2); - expect(mockFunction).toHaveBeenCalledWith('Third call'); + // Second call - deferred + jest.advanceTimersByTime(500); + rateLimitedFunction('Second call'); + expect(mockFunction).toHaveBeenCalledTimes(1); - // Fourth call - at 1100ms from start gets defferred till 2000ms - jest.advanceTimersByTime(100); - rateLimitedFunction('Forth call'); - jest.advanceTimersByTime(900); - expect(mockFunction).toHaveBeenCalledTimes(3); - expect(mockFunction).toHaveBeenCalledWith('Forth call'); + // Third call - replaces second, also deferred + jest.advanceTimersByTime(200); + rateLimitedFunction('Third call'); + expect(mockFunction).toHaveBeenCalledTimes(1); - // no more calls expected - jest.advanceTimersByTime(1000); - expect(mockFunction).toHaveBeenCalledTimes(3); - }); -}); + // Executing the deferred 'Third call' + jest.advanceTimersByTime(350); + expect(mockFunction).toHaveBeenCalledTimes(2); + expect(mockFunction).toHaveBeenCalledWith('Third call'); + + // Fourth call - at 1100ms from start gets defferred till 2000ms + jest.advanceTimersByTime(100); + rateLimitedFunction('Forth call'); + jest.advanceTimersByTime(900); + expect(mockFunction).toHaveBeenCalledTimes(3); + expect(mockFunction).toHaveBeenCalledWith('Forth call'); + // no more calls expected + jest.advanceTimersByTime(1000); + expect(mockFunction).toHaveBeenCalledTimes(3); + }); + }); +} diff --git a/src/utils/stringify.ts b/src/utils/stringify.ts index 3da53839..515f0d9e 100644 --- a/src/utils/stringify.ts +++ b/src/utils/stringify.ts @@ -31,10 +31,12 @@ export const circularReplacer = (key: any, value: any) => { return "--compiled expression--"; } if (null !== value) { + const tag = Object.prototype.toString.call(value); const { _idleTimeout, _onTimeout } = value; - if (_idleTimeout !== undefined && _onTimeout !== undefined) { + if (tag === '[object Timeout]'|| (_idleTimeout !== undefined && _onTimeout !== undefined)) { //Node.js return "--interval/timeout--"; } + if (value instanceof Set) { return Array.from(value); } diff --git a/yarn.lock b/yarn.lock index 4bcaff8f..e51a77a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,7 +23,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz" integrity sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.22.20": +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.22.20", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0": version "7.22.20" resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz" integrity sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA== @@ -1098,7 +1098,7 @@ jest-mock "^29.7.0" jest-util "^29.7.0" -"@jest/globals@^29.7.0": +"@jest/globals@^29.7.0", "@jest/globals@latest": version "29.7.0" resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== @@ -1234,16 +1234,16 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.15" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz" @@ -1252,21 +1252,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@mapbox/node-pre-gyp@^1.0.11": - version "1.0.11" - resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz" - integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== - dependencies: - detect-libc "^2.0.0" - https-proxy-agent "^5.0.0" - make-dir "^3.1.0" - node-fetch "^2.6.7" - nopt "^5.0.0" - npmlog "^5.0.1" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.11" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -1275,7 +1260,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -1409,19 +1394,14 @@ dependencies: "@types/lodash" "*" -"@types/lodash@*": +"@types/lodash@*", "@types/lodash@^4.14.195": version "4.17.0" resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz" integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== -"@types/lodash@^4.14.195": - version "4.17.9" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.9.tgz#0dc4902c229f6b8e2ac5456522104d7b1a230290" - integrity sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w== - "@types/minimist@^1.2.5": version "1.2.5" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + resolved "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz" integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/node@*": @@ -1451,7 +1431,7 @@ dependencies: "@types/yargs-parser" "*" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": +"@webassemblyjs/ast@^1.11.5", "@webassemblyjs/ast@1.11.6": version "1.11.6" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz" integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== @@ -1552,7 +1532,7 @@ "@webassemblyjs/wasm-gen" "1.11.6" "@webassemblyjs/wasm-parser" "1.11.6" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": +"@webassemblyjs/wasm-parser@^1.11.5", "@webassemblyjs/wasm-parser@1.11.6": version "1.11.6" resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz" integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== @@ -1597,28 +1577,16 @@ resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - acorn-import-assertions@^1.9.0: version "1.9.0" resolved "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== -acorn@^8.7.1, acorn@^8.8.2: +acorn@^8, acorn@^8.7.1, acorn@^8.8.2: version "8.10.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== -agent-base@6: - version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" @@ -1638,7 +1606,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.5: +ajv@^6.12.5, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1648,7 +1616,7 @@ ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.9.0: +ajv@^8.0.0, ajv@^8.8.2, ajv@^8.9.0: version "8.12.0" resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -1687,7 +1655,14 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1712,19 +1687,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -"aproba@^1.0.3 || ^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - -are-we-there-yet@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" - integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" @@ -1839,13 +1801,6 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -1868,7 +1823,7 @@ braces@^3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.9: +browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.9, "browserslist@>= 4.21.0": version "4.21.10" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz" integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== @@ -1910,7 +1865,16 @@ caniuse-lite@^1.0.30001517: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001535.tgz" integrity sha512-48jLyUkiWFfhm/afF7cQPqPjaUmSraEhK4j+FCTJpgnGGEZHqyLe3hmWH7lIooZdSzXL0ReMvHz0vKDoTBsrwg== -chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1937,11 +1901,6 @@ char-regex@^1.0.2: resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" @@ -1999,7 +1958,7 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3, color-name@^1.0.0: +color-name@^1.0.0, color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== @@ -2017,11 +1976,6 @@ color-string@^1.6.0: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.2: - version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - color@^3.1.3: version "3.2.1" resolved "https://registry.npmjs.org/color/-/color-3.2.1.tgz" @@ -2063,11 +2017,6 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -console-control-strings@^1.0.0, console-control-strings@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== - convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" @@ -2097,6 +2046,11 @@ core-js-compat@^3.31.0: dependencies: browserslist "^4.21.10" +crc-full@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/crc-full/-/crc-full-1.1.0.tgz" + integrity sha512-7YK4t8C9PiekOSnBotYjU2roaaorUXHyT+Xzb12Zgg4DsfG58AxmPk2/wx7XnC9UXyriqRvl3c+U0zFsZkdVYg== + create-jest@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" @@ -2119,7 +2073,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -debug@4, debug@^4.1.0, debug@^4.1.1: +debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2136,16 +2090,6 @@ deepmerge@^4.2.2: resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== - -detect-libc@^2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz" - integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" @@ -2349,11 +2293,6 @@ fecha@^4.2.0: resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" @@ -2403,13 +2342,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" @@ -2417,7 +2349,7 @@ fs.realpath@^1.0.0: fsevents@^2.3.2: version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: @@ -2425,21 +2357,6 @@ function-bind@^1.1.1: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" @@ -2518,6 +2435,11 @@ globby@^13.1.1: merge2 "^1.4.1" slash "^4.0.0" +google-protobuf@^3.17.3: + version "3.21.4" + resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz" + integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ== + graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" @@ -2533,11 +2455,6 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== - has@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" @@ -2550,14 +2467,6 @@ html-escaper@^2.0.0: resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" @@ -2589,7 +2498,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3: +inherits@^2.0.3, inherits@2: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2931,7 +2840,7 @@ jest-resolve-dependencies@^29.7.0: jest-regex-util "^29.6.3" jest-snapshot "^29.7.0" -jest-resolve@^29.7.0: +jest-resolve@*, jest-resolve@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== @@ -3152,10 +3061,10 @@ json5@^2.2.3: resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonata@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/jsonata/-/jsonata-2.0.3.tgz" - integrity sha512-Up2H81MUtjqI/dWwWX7p4+bUMfMrQJVMN/jW6clFMTiYP528fBOBNtRu944QhKTs3+IsVWbgMeUTny5fw2VMUA== +jsonata@2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/jsonata/-/jsonata-2.0.4.tgz" + integrity sha512-vfavX4/G/yrYxE+UrmT/oUJ3ph7KqUrb0R7b0LVRcntQwxw+Z5kA1pNUIQzX5hF04Oe1eKxyoIPsmXtc2LgJTQ== jsonc-parser@^3.2.0: version "3.2.1" @@ -3262,13 +3171,6 @@ lunr@^2.3.9: resolved "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz" integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== -make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - make-dir@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" @@ -3349,14 +3251,7 @@ minimist@^1.2.8: resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^5.0.0, "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "5.0.0" resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== @@ -3366,20 +3261,7 @@ minipass@^7.0.4: resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz" integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA== -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.1.2, ms@^2.1.1: +ms@^2.1.1, ms@2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -3394,18 +3276,6 @@ neo-async@^2.6.2: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-addon-api@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz" - integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== - -node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" @@ -3416,13 +3286,6 @@ node-releases@^2.0.13: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== -nopt@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" - integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== - dependencies: - abbrev "1" - normalize-path@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" @@ -3435,21 +3298,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - once@^1.3.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" @@ -3610,14 +3458,13 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -pulsar-client@^1.12.0: - version "1.12.0" - resolved "https://registry.npmjs.org/pulsar-client/-/pulsar-client-1.12.0.tgz" - integrity sha512-6xzL7ACXW6vf5J6ilsXB0Zvn1SjtLnuSP8AX+M1xtaVrR/F04BCMifOhxywpPWJpW7yaGJR1zYZjfimGxS8wiw== +pulsar-flex@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/pulsar-flex/-/pulsar-flex-1.1.1.tgz" + integrity sha512-R6jNg4E326uItcG/QcNYLSOnZxMvVo4ZzxB2scEZDN3mp2VHKzPr/iiC07sXthrtdAVXlFTUt8+QyujoKc54ZA== dependencies: - "@mapbox/node-pre-gyp" "^1.0.11" - bindings "^1.5.0" - node-addon-api "^4.3.0" + crc-full "^1.1.0" + google-protobuf "^3.17.3" punycode@^2.1.0: version "2.3.0" @@ -3756,13 +3603,6 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@^5.0.7: version "5.0.7" resolved "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz" @@ -3787,7 +3627,16 @@ safe-stable-stringify@^2.3.1: resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.1.1: + version "3.3.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -3806,17 +3655,19 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5: - version "7.6.3" - resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.5.3: + version "7.5.4" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" -semver@^7.5.3, semver@^7.5.4: +semver@^7.5.4: version "7.5.4" resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -3830,11 +3681,6 @@ serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: dependencies: randombytes "^2.1.0" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" @@ -3864,7 +3710,7 @@ shiki@^0.14.7: vscode-oniguruma "^1.7.0" vscode-textmate "^8.0.0" -signal-exit@^3.0.0, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -3896,14 +3742,6 @@ slash@^4.0.0: resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -3912,6 +3750,14 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" @@ -3934,6 +3780,13 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + string-argv@^0.3.2: version "0.3.2" resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" @@ -3956,7 +3809,7 @@ string-length@^4.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3974,13 +3827,6 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -4048,18 +3894,6 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.1.11: - version "6.2.1" - resolved "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz" - integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - terser-webpack-plugin@^5.3.7: version "5.3.9" resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz" @@ -4112,11 +3946,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - triple-beam@^1.3.0: version "1.4.1" resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz" @@ -4142,7 +3971,7 @@ typedoc@^0.25.7: minimatch "^9.0.3" shiki "^0.14.7" -typescript@^5.3.3: +typescript@^5.3.3, "typescript@4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x": version "5.3.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== @@ -4224,12 +4053,7 @@ watchpack@^2.4.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -webpack-cli@^5.1.4: +webpack-cli@^5.1.4, webpack-cli@5.x.x: version "5.1.4" resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz" integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== @@ -4266,7 +4090,7 @@ webpack-sources@^3.2.3: resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.88.2: +webpack@^5.1.0, webpack@^5.88.2, webpack@>=5, webpack@5.x.x: version "5.88.2" resolved "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz" integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== @@ -4296,14 +4120,6 @@ webpack@^5.88.2: watchpack "^2.4.0" webpack-sources "^3.2.3" -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" @@ -4311,13 +4127,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.2: - version "1.1.5" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - wildcard@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz"