Update to v13 and add queue and completely change code
This commit is contained in:
parent
dcef23d0ed
commit
55a38726a3
6706 changed files with 424137 additions and 61608 deletions
5
node_modules/jsonpath-plus/.babelrc.json
generated
vendored
Normal file
5
node_modules/jsonpath-plus/.babelrc.json
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"presets": [
|
||||
["@babel/preset-env"]
|
||||
]
|
||||
}
|
16
node_modules/jsonpath-plus/.editorconfig
generated
vendored
Normal file
16
node_modules/jsonpath-plus/.editorconfig
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
; EditorConfig file: https://EditorConfig.org
|
||||
; Install the "EditorConfig" plugin into your editor to use
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
; indent_style = tab
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{json,yml}]
|
||||
indent_size = 2
|
6
node_modules/jsonpath-plus/.eslintignore
generated
vendored
Normal file
6
node_modules/jsonpath-plus/.eslintignore
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
node_modules
|
||||
dist
|
||||
docs/ts
|
||||
coverage
|
||||
ignore
|
||||
!*.js
|
105
node_modules/jsonpath-plus/.eslintrc.js
generated
vendored
Normal file
105
node_modules/jsonpath-plus/.eslintrc.js
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: ['ash-nazg/sauron-node-overrides'],
|
||||
settings: {
|
||||
polyfills: [
|
||||
'Array.isArray',
|
||||
'console',
|
||||
'Date.now',
|
||||
'document.head',
|
||||
'document.querySelector',
|
||||
'JSON',
|
||||
'Number.isFinite',
|
||||
'Number.parseInt',
|
||||
'Object.keys',
|
||||
'Object.values',
|
||||
'XMLHttpRequest'
|
||||
]
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['src/jsonpath-node.js', 'test-helpers/node-env.js'],
|
||||
env: {
|
||||
mocha: true
|
||||
},
|
||||
// ESLint doesn't seem to remember this
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module'
|
||||
},
|
||||
rules: {
|
||||
'node/no-unsupported-features/es-syntax': ['error', {
|
||||
ignores: [
|
||||
'regexpNamedCaptureGroups', 'modules', 'dynamicImport'
|
||||
]
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.md/*.js', '*.md/*.html'],
|
||||
rules: {
|
||||
'import/unambiguous': 0,
|
||||
'import/no-commonjs': 0,
|
||||
'import/no-unresolved': ['error', {
|
||||
ignore: ['jsonpath-plus']
|
||||
}],
|
||||
'no-multiple-empty-lines': ['error', {
|
||||
max: 1, maxEOF: 2, maxBOF: 2
|
||||
}],
|
||||
'no-undef': 0,
|
||||
'no-unused-vars': ['error', {
|
||||
varsIgnorePattern: 'json|result'
|
||||
}],
|
||||
'import/no-extraneous-dependencies': 0,
|
||||
'node/no-extraneous-import': ['error', {
|
||||
allowModules: ['jsonpath-plus']
|
||||
}],
|
||||
'node/no-missing-require': ['error', {
|
||||
allowModules: ['jsonpath-plus']
|
||||
}],
|
||||
// Unfortunately, with the new processor approach, the filename
|
||||
// is now README.md so our paths must be `../`. However, even
|
||||
// with that, eslint-plugin-node is not friendly to such
|
||||
// imports, so we disable
|
||||
'node/no-missing-import': 'off',
|
||||
'node/no-unpublished-import': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['test/**'],
|
||||
extends: [
|
||||
'plugin:chai-expect/recommended',
|
||||
'plugin:chai-friendly/recommended'
|
||||
],
|
||||
globals: {
|
||||
assert: 'readonly',
|
||||
expect: 'readonly',
|
||||
jsonpath: 'readonly'
|
||||
},
|
||||
env: {mocha: true},
|
||||
rules: {
|
||||
quotes: 0,
|
||||
'quote-props': 0,
|
||||
'import/unambiguous': 0,
|
||||
// Todo: Reenable
|
||||
'max-len': 0
|
||||
}
|
||||
}
|
||||
],
|
||||
rules: {
|
||||
indent: ['error', 4, {outerIIFEBody: 0}],
|
||||
'promise/prefer-await-to-callbacks': 0,
|
||||
'require-jsdoc': 0,
|
||||
|
||||
// Disable for now
|
||||
'eslint-comments/require-description': 0,
|
||||
// Reenable as have time and confirming no longer needing:
|
||||
// https://github.com/babel/babel/issues/8951#issuecomment-508045524 is no
|
||||
'prefer-named-capture-group': 0,
|
||||
|
||||
// Reenable when no longer having problems
|
||||
'unicorn/no-unsafe-regex': 0,
|
||||
'unicorn/consistent-destructuring': 0
|
||||
}
|
||||
};
|
327
node_modules/jsonpath-plus/CHANGES.md
generated
vendored
Normal file
327
node_modules/jsonpath-plus/CHANGES.md
generated
vendored
Normal file
|
@ -0,0 +1,327 @@
|
|||
# CHANGES for jsonpath-plus
|
||||
|
||||
## 5.0.7 (2021-04-12)
|
||||
|
||||
- Fix: Add `packge.json` to `exports` (@sebastiendavid)
|
||||
|
||||
## 5.0.6 (2021-04-09)
|
||||
|
||||
- Fix: Remove `static` modifiers (@sdolski)
|
||||
- Linting: As per latest ash-nazg
|
||||
- npm: Update devDeps.
|
||||
|
||||
## 5.0.5 (2021-04-09)
|
||||
|
||||
- Fix: Avoid cache corruption when the returned structure is modified.
|
||||
Fixes #102. (@tejodorus)
|
||||
|
||||
## 5.0.4 (2021-03-02)
|
||||
|
||||
- Fix: allow falsey at values in filter (now may require checking for
|
||||
presence of `@` in some cases); fixes #136
|
||||
- Docs: Add old missing release info (reconciling with GitHub releases)
|
||||
- Docs: Update README to reflect 1.2.0 was not a released version (subsume
|
||||
release details into 2.0.0)
|
||||
- Linting: As per latest ash-nazg
|
||||
- npm: Update devDeps.
|
||||
|
||||
## 5.0.3 (2021-02-06)
|
||||
|
||||
- Fix: Add package exports for browser and umd (#145) (@gjvoosten)
|
||||
- Update: Build as per refactoring
|
||||
- Docs: Update as per typedoc update
|
||||
- Docs: Update license badges per latest
|
||||
- Linting: As per latest ash-nazg
|
||||
- CI: Update from Travis -> GitHub Actions
|
||||
- npm: Switch from `eslint-plugin-sonarjs` to `eslint-plugin-radar`
|
||||
- npm: Switch to pnpm
|
||||
- npm: Update devDeps.
|
||||
|
||||
## 5.0.2 (2021-01-15)
|
||||
|
||||
- Fix: Proper Node CommonJS export; fixes #144
|
||||
|
||||
## 5.0.1 (2021-01-15)
|
||||
|
||||
- Fix: Proper Node CommonJS export; fixes #143
|
||||
- Docs: Properly indicate new browser paths
|
||||
|
||||
## 5.0.0 (2021-01-14)
|
||||
|
||||
- Breaking change: Add `type: 'commonjs'` and `exports: {import, require}`
|
||||
(with `node-import-test` npm script to demo)
|
||||
- Breaking change: Change paths for browser (now is
|
||||
`dist/index-browser-umd.js` or `dist/index-browser-es.js`)
|
||||
(for Node, `main` and `module` point to new Node-specific dist)
|
||||
- Breaking enhancement: Add `browser` for browser bundling;
|
||||
allowing static analysis environments, doesn't have however
|
||||
conditional code to require `vm`); for ESM browser bundling,
|
||||
now must check `browser` in Rollup Node resolver plugin;
|
||||
see README
|
||||
- Build: Update per latest devDeps.
|
||||
- Docs: Add Regex (`.match`) example on value (@jeffreypriebe)
|
||||
- Docs: Add Regex (`.match`) example on property
|
||||
- Docs: Fix XPath example (@humbertoc-silva)
|
||||
- Docs: Link to XPath 2.0 tester
|
||||
- Docs: Update badges per latest updates
|
||||
- Linting: quote props
|
||||
- Linting: As per latest ash-nazg
|
||||
- Testing: Fix browser tests
|
||||
- Testing: Add test case for setting values in callbacks (issue #126)
|
||||
- Testing: Add more at-sign tests
|
||||
- Testing: Bump timeout
|
||||
- Travis: Check Node 14
|
||||
- Travis: add default `dist` field to avoid extra config reporting
|
||||
- npm: Update from deprecated `rollup-plugin-babel` to `@rollup/plugin-babel`
|
||||
(and make `babelHelpers` explicit)
|
||||
- npm: Reorder scripts by test execution order
|
||||
- npm: Update devDeps
|
||||
|
||||
## 4.0.0 (2020-04-09)
|
||||
|
||||
- Breaking change/fix: Disallow `resultType` from being lower-cased
|
||||
(broke `parentProperty`)
|
||||
- Breaking change: Expect Node >= 10
|
||||
- Build: As per latest rollup
|
||||
- Linting: Check hidden files; update as per latest ash-nazg
|
||||
- Docs: Update coverage badge
|
||||
- npm: Update devDeps
|
||||
|
||||
## 3.0.0 (2020-01-13)
|
||||
|
||||
- Breaking change: Expect Node >= 8
|
||||
- Fix: Require `json` as "own" property
|
||||
- Fix: wrap: false returning inconsistent data types (@CacheControl)
|
||||
- Fix: Ensure throwing with a bad result type
|
||||
- Fix: Allow empty string keys
|
||||
- Fix: Avoid erring when value before parent selector is falsey
|
||||
- Fix: If `resultType` is "all", if path resolves internally to a
|
||||
non-array (string), ensure it is converted to an array before
|
||||
converting to pointer for `pointer`
|
||||
- Enhancement: Allow path as array in non-object signature
|
||||
- Docs: Add locally-generated badges for testing, coverage, etc.
|
||||
- Linting (ESLint): As per latest ash-nazg
|
||||
- Linting (ESLint): Remove redundant "use strict" with switch to ESM
|
||||
- Maintenance: 2 sp. for package.json
|
||||
- Testing: Add nyc for coverage
|
||||
- Testing: Test against source (using `esm`)
|
||||
- Testing: Improve coverage (more type operator tests)
|
||||
- Testing: Check vm
|
||||
- npm: Add `test-cov` script
|
||||
- npm: Update devDeps
|
||||
|
||||
## 2.0.0 (2019-11-23)
|
||||
|
||||
- Breaking change: Throw `TypeError` instead of `Error` for missing
|
||||
`otherTypeCallback` when using `@other`
|
||||
- Breaking change: Throw `TypeError` instead of `Error` for missing `path`
|
||||
- Enhancement: Throw `TypeError` for missing `json` (fixes #110)
|
||||
- Enhancement: Use more efficient `new Function` over `eval`;
|
||||
also allows use of cyclic context objects
|
||||
- Enhancement: Add `@root` filter selector
|
||||
- Maintenance: Add `.editorconfig`
|
||||
- Docs: Document options in jsdoc; add return values to callbacks;
|
||||
fix constructor doc sig.
|
||||
- Testing: Add test for missing `path` or `json`
|
||||
- Testing: Remove unneeded closures
|
||||
- npm: Update devDeps and `package-lock.json`
|
||||
|
||||
## 1.1.0 (September 26, 2019)
|
||||
|
||||
- Enhancement: Add explicit 'any' to `evaluate()` declaration (for use
|
||||
with `noImplicitAny` TypeScript option)
|
||||
- Build: Update minified build files
|
||||
- Travis: Update to check Node 6, 10, 12
|
||||
- npm: Ignore `.idea`/`.remarkrc` files
|
||||
- npm: Update devDeps (Babel, linting, Rollup, TypeScript related)
|
||||
- npm: Avoid eslint script within test script
|
||||
- npm: Ignore typescript docs
|
||||
|
||||
## 1.0.0 (August 7, 2019)
|
||||
|
||||
- Add TypeScript declaration
|
||||
|
||||
## 0.20.2 (July 9, 2019)
|
||||
|
||||
- `supportsNodeVM` check that works in GOJA, node and ReactNative. (@legander)
|
||||
|
||||
## 0.20.1 (June 12, 2019)
|
||||
|
||||
- npm: Avoid adding `core-js-bundle` as peerDep. (fixes #95)
|
||||
|
||||
## 0.20.0 (June 4, 2019)
|
||||
|
||||
- Build: Add `browserslist` for Babel builds
|
||||
- Linting: Conform to ESLint updates (jsdoc)
|
||||
- Testing: Switch from end-of-lifed nodeunit to Mocha
|
||||
- Testing: Add performance test to browser, but bump duration
|
||||
- npm: Update devDeps; add core-js-bundle to peerDependencies
|
||||
- npm: Ignore some unneeded files
|
||||
- Bump Node version in Travis to avoid erring with object rest
|
||||
in eslint-plugin-node routine
|
||||
|
||||
## 0.19.0 (May 16, 2019)
|
||||
|
||||
- Docs (README): Indicate features, including performance (removing old note)
|
||||
- Docs (README): Add headings for setup and fix headings levels
|
||||
- Docs (README): Indicate parent selector was not present in original spec
|
||||
(not just not documented)
|
||||
- Docs (README): Fix escaping
|
||||
- Linting: Switch to Unix line breaks and other changes per ash-nazg, including linting Markdown JS
|
||||
- Linting: Use recommended `.json` extension
|
||||
- Linting: Switch to ash-nazg
|
||||
- Linting: Add lgtm.yml file for lgtm.com
|
||||
- npm: Update devDeps, and update per security audit
|
||||
|
||||
## 0.18.1 (May 14, 2019)
|
||||
|
||||
- Fix: Expose `pointer` on `resultType: "all"`
|
||||
|
||||
## 0.18.0 (October 20, 2018)
|
||||
|
||||
- Security enhancement: Use global eval instead of regular eval
|
||||
- Fix: Handle React-Native environment's lack of support for
|
||||
Node vm (@simon-scherzinger); closes #87
|
||||
- Refactoring: Use arrow functions, for-of, declare block scope vars
|
||||
closer to block
|
||||
- Docs: Clarify current `wrap` behavior
|
||||
- npm: Add Rollup to test scripts
|
||||
|
||||
## 0.17.0 (October 19, 2018)
|
||||
|
||||
- Breaking change: With Node use, must now use
|
||||
`require('jsonpath-plus').JSONPath`.
|
||||
- Breaking change: Stop including polyfills for array and string `includes`
|
||||
(can get with `@babel/polyfill` or own)
|
||||
- Breaking change: Remove deprecated `JSONPath.eval`
|
||||
- License: Remove old and unneeded license portion from within source file
|
||||
(already have external file)
|
||||
- Fix: Support object shorthand functions on sandbox objects
|
||||
(`toString()` had not been working properly with them)
|
||||
- Enhancement: Add Rollup/Babel/Terser and `module` in `package.json`
|
||||
- Refactoring: Use ES6 features such as object shorthand
|
||||
- Linting: prefer const and no var
|
||||
- Testing: Replace custom server code with `node-static` and add `opn-cli`;
|
||||
mostly switch to ESM
|
||||
- npm: Update devDeps; add `package-lock.json`; remove non-functioning remark
|
||||
|
||||
## 0.16.0 (January 14, 2017)
|
||||
|
||||
- Breaking change: Give preference to treating special chars in a property
|
||||
as special (override with backtick operator)
|
||||
- Breaking feature: Add custom \` operator to allow unambiguous literal
|
||||
sequences (if an initial backtick is needed, an additional one must
|
||||
now be added)
|
||||
- Fix: `toPathArray` caching bug
|
||||
- Improvements: Performance optimizations
|
||||
- Dev testing: Rename test file
|
||||
|
||||
## 0.15.0 (Mar 15, 2016)
|
||||
|
||||
- Fix: Fixing support for sandbox in the case of functions
|
||||
- Feature: Use `this` if present for global export
|
||||
- Docs: Clarify function signature
|
||||
- Docs: Update testing section
|
||||
- Dev testing: Add in missing test for browser testing
|
||||
- Dev testing: Add remark linting to testing process (#70)
|
||||
- Dev testing: Lint JS test support files
|
||||
- Dev testing: Split out tests into `eslint`, `remark`, `lint`, `nodeunit`
|
||||
- Dev testing: Remove need for nodeunit build step
|
||||
- Dev testing: Simplify nodeunit usage and make available
|
||||
as `npm run browser-test`
|
||||
|
||||
## 0.14.0 (Jan 10, 2016)
|
||||
|
||||
- Feature: Add `@scalar()` type operator (in JavaScript mode, will also
|
||||
include)
|
||||
|
||||
## 0.13.1 (Jan 5, 2016)
|
||||
|
||||
- Fix: Avoid double-encoding path in results
|
||||
|
||||
## 0.13.0 (Dec 13, 2015)
|
||||
|
||||
- Breaking change (from version 0.11): Silently strip `~` and `^` operators
|
||||
and type operators such as `@string()` in `JSONPath.toPathString()` calls.
|
||||
- Breaking change: Remove `Array.isArray` polyfill as no longer
|
||||
supporting IE <= 8
|
||||
- Feature: Allow omission of options first argument to `JSONPath`
|
||||
- Feature: Add `JSONPath.toPointer()` and "pointer" `resultType` option.
|
||||
- Fix: Correctly support `callback` and `otherTypeCallback` as numbered
|
||||
arguments to `JSONPath`.
|
||||
- Fix: Enhance Node checking to avoid issue reported with angular-mock
|
||||
- Fix: Allow for `@` or other special characters in at-sign-prefixed
|
||||
property names (by use of `[?(@['...'])]` or `[(@['...'])]`).
|
||||
|
||||
## 0.12.0 (Dec 12, 2015 10:39pm)
|
||||
|
||||
- Breaking change: Problems with upper-case letters in npm is causing
|
||||
us to rename the package, so have renamed package to "jsonpath-plus"
|
||||
(there are already package with lower-case "jsonpath" or "json-path").
|
||||
The new name also reflects that there have been changes to the
|
||||
original spec.
|
||||
|
||||
## 0.11.2 (Dec 12, 2015 10:36pm)
|
||||
|
||||
- Docs: Actually add the warning in the README that problems in npm
|
||||
with upper-case letters is causing us to rename to "jsonpath-plus"
|
||||
(next version will actually apply the change).
|
||||
|
||||
## 0.11.1 (Dec 12, 2015 10:11pm)
|
||||
|
||||
- Docs: Give warning in README that problems in npm with upper-case letters
|
||||
is causing us to rename to "jsonpath-plus" (next version will actually
|
||||
apply the change).
|
||||
|
||||
## 0.11.0 (Dec 12, 2015)
|
||||
|
||||
- Breaking change: For unwrapped results, return `undefined` instead
|
||||
of `false` upon failure to find path (to allow distinguishing of
|
||||
`undefined`--a non-allowed JSON value--from the valid JSON values,
|
||||
`null` or `false`) and return the exact value upon falsy single
|
||||
results (in order to allow return of `null`)
|
||||
- Deprecated: Use of `jsonPath.eval()`; use new class-based API instead
|
||||
- Feature: AMD export
|
||||
- Feature: By using `self` instead of `window` export, allow JSONPath
|
||||
to be trivially imported into web workers, without breaking
|
||||
compatibility in normal scenarios. See [MDN on self](https://developer.mozilla.org/en-US/docs/Web/API/Window/self)
|
||||
- Feature: Offer new class-based API and object-based arguments (with
|
||||
option to run new queries via `evaluate()` method without resupplying config)
|
||||
- Feature: Allow new `preventEval=true` and `autostart=false` option
|
||||
- Feature: Allow new callback option to allow a callback function to execute as
|
||||
each final result node is obtained
|
||||
- Feature: Allow type operators: JavaScript types (`@boolean()`, `@number()`,
|
||||
`@string()`), other fundamental JavaScript types (`@null()`, `@object()`,
|
||||
`@array()`), the JSONSchema-added type, `@integer()`, and the following
|
||||
non-JSON types that can nevertheless be used with JSONPath when querying
|
||||
non-JSON JavaScript objects (`@undefined()`, `@function()`, `@nonFinite()`).
|
||||
Finally, `@other()` is made available in conjunction with a new callback
|
||||
option, `otherTypeCallback`, can be used to allow user-defined type
|
||||
detection (at least until JSON Schema awareness may be provided).
|
||||
- Feature: Support "parent" and "parentProperty" for resultType along with
|
||||
"all" (which also includes "path" and "value" together)
|
||||
- Feature: Support custom `@parent`, `@parentProperty`, `@property` (in
|
||||
addition to custom property `@path`) inside evaluations
|
||||
- Feature: Support a custom operator (`~`) to allow grabbing of property names
|
||||
- Feature: Support `$` for retrieval of root, and document this as well as
|
||||
`$..` behavior
|
||||
- Feature: Expose cache on `JSONPath.cache` for those who wish to preserve and
|
||||
reuse it
|
||||
- Feature: Expose class methods `toPathString` for converting a path as array
|
||||
into a (normalized) path as string and `toPathArray` for the reverse (though
|
||||
accepting unnormalized strings as well as normalized)
|
||||
- Fix: Allow `^` as property name
|
||||
- Fix: Support `.` within properties
|
||||
- Fix: `@path` in index/property evaluations
|
||||
|
||||
## 0.10.0 (Oct 23, 2013)
|
||||
|
||||
- Feature: Support for parent selection via `^`
|
||||
- Feature: Access current path via `@path` in test statements
|
||||
- Feature: Allowing for multi-statement evals
|
||||
- Improvements: Performance
|
||||
|
||||
## 0.9.0 (Mar 28, 2012)
|
||||
|
||||
- Feature: Support a sandbox arg to eval
|
||||
- Improvements: Use `vm.runInNewContext` in place of eval
|
22
node_modules/jsonpath-plus/LICENSE-MIT.txt
generated
vendored
Normal file
22
node_modules/jsonpath-plus/LICENSE-MIT.txt
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2019 Stefan Goessner, Subbu Allamaraju, Mike Brevoort,
|
||||
Robert Krahn, Brett Zamir, Richard Schneider
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
396
node_modules/jsonpath-plus/README.md
generated
vendored
Normal file
396
node_modules/jsonpath-plus/README.md
generated
vendored
Normal file
|
@ -0,0 +1,396 @@
|
|||
[](https://www.npmjs.com/package/jsonpath-plus)
|
||||
[](https://david-dm.org/s3u/JSONPath)
|
||||
[](https://david-dm.org/s3u/JSONPath?type=dev)
|
||||
|
||||
[](badges/tests-badge.svg)
|
||||
[](badges/coverage-badge.svg)
|
||||
|
||||
[](https://snyk.io/test/github/s3u/JSONPath)
|
||||
[](https://lgtm.com/projects/g/s3u/JSONPath/alerts)
|
||||
[](https://lgtm.com/projects/g/s3u/JSONPath/context:javascript)
|
||||
|
||||
<!--[](LICENSE-MIT.txt)-->
|
||||
[](badges/licenses-badge.svg)
|
||||
|
||||
<small>(see also [licenses for dev. deps.](https://raw.githubusercontent.com/s3u/JSONPath/master/badges/licenses-badge-dev.svg?sanitize=true))</small>
|
||||
|
||||
# JSONPath Plus [](https://github.com/git://github.com/s3u/JSONPath.git/actions)
|
||||
|
||||
Analyse, transform, and selectively extract data from JSON
|
||||
documents (and JavaScript objects).
|
||||
|
||||
`jsonpath-plus` expands on the original specification to add some
|
||||
additional operators and makes explicit some behaviors the original
|
||||
did not spell out.
|
||||
|
||||
Try the [browser demo](https://jsonpath-plus.github.io/JSONPath/demo/) or
|
||||
[Runkit (Node)](https://npm.runkit.com/jsonpath-plus).
|
||||
|
||||
## Features
|
||||
|
||||
* **Compliant** with the original jsonpath spec
|
||||
* Convenient **additions or elaborations** not provided in the original spec:
|
||||
* `^` for grabbing the **parent** of a matching item
|
||||
* `~` for grabbing **property names** of matching items (as array)
|
||||
* **Type selectors** for obtaining:
|
||||
* Basic JSON types: `@null()`, `@boolean()`, `@number()`, `@string()`, `@array()`, `@object()`
|
||||
* `@integer()`
|
||||
* The compound type `@scalar()` (which also accepts `undefined` and
|
||||
non-finite numbers when querying JavaScript objects as well as all of the basic non-object/non-function types)
|
||||
* `@other()` usable in conjunction with a user-defined `otherTypeCallback`
|
||||
* Non-JSON types that can nevertheless be used when querying
|
||||
non-JSON JavaScript objects (`@undefined()`, `@function()`, `@nonFinite()`)
|
||||
* `@path`/`@parent`/`@property`/`@parentProperty`/`@root` **shorthand selectors** within filters
|
||||
* **Escaping**
|
||||
* `` ` `` for escaping remaining sequence
|
||||
* `@['...']`/`?@['...']` syntax for escaping special characters within
|
||||
property names in filters
|
||||
* Documents `$..` (**getting all parent components**)
|
||||
* **ESM** and **UMD** export formats
|
||||
* In addition to queried values, **can return various meta-information**
|
||||
including paths or pointers to the value, as well as the parent
|
||||
object and parent property name (to allow for modification).
|
||||
* **Utilities for converting** between paths, arrays, and pointers
|
||||
* Option to **prevent evaluations** permitted in the original spec or supply
|
||||
a **sandbox** for evaluated values.
|
||||
* Option for **callback to handle results** as they are obtained.
|
||||
|
||||
## Benchmarking
|
||||
|
||||
`jsonpath-plus` is consistently performant with both large and small datasets compared to other json querying libraries per [json-querying-performance-testing](https://github.com/andykais/json-querying-performance-testing). You can verify these findings by [running the project yourself](https://github.com/andykais/json-querying-performance-testing#how-to-run) and adding more perf cases.
|
||||
|
||||
## Install
|
||||
|
||||
```shell
|
||||
npm install jsonpath-plus
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
### Node.js
|
||||
|
||||
```js
|
||||
const {JSONPath} = require('jsonpath-plus');
|
||||
|
||||
const result = JSONPath({path: '...', json});
|
||||
```
|
||||
|
||||
### Browser
|
||||
|
||||
For browser usage you can directly include `dist/index-browser-umd.js`; no Browserify
|
||||
magic is necessary:
|
||||
|
||||
```html
|
||||
<!-- Polyfill recommended by Babel for items not covered for older
|
||||
browsers in dist -->
|
||||
<script src="node_modules/core-js-bundle/minified.js"></script>
|
||||
|
||||
<script src="node_modules/jsonpath-plus/dist/index-browser-umd.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
const result = JSONPath.JSONPath({path: '...', json: {}});
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
### ESM (Modern browsers)
|
||||
|
||||
You may also use ES6 Module imports (for modern browsers):
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
|
||||
import {
|
||||
JSONPath
|
||||
} from './node_modules/jsonpath-plus/dist/index-browser-esm.js';
|
||||
|
||||
const result = JSONPath({path: '...', json: {}});
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
### ESM (Bundlers)
|
||||
|
||||
Or if you are bundling your JavaScript (e.g., with Rollup), just use,
|
||||
noting that [`mainFields`](https://github.com/rollup/plugins/tree/master/packages/node-resolve#mainfields)
|
||||
should include `browser` for browser builds (for Node, the default, which
|
||||
checks `module`, should be fine):
|
||||
|
||||
```js
|
||||
import {JSONPath} from 'jsonpath-plus';
|
||||
|
||||
const result = JSONPath({path: '...', json});
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The full signature available is:
|
||||
|
||||
```
|
||||
const result = JSONPath([options,] path, json, callback, otherTypeCallback);
|
||||
```
|
||||
|
||||
The arguments `path`, `json`, `callback`, and `otherTypeCallback`
|
||||
can alternatively be expressed (along with any other of the
|
||||
available properties) on `options`.
|
||||
|
||||
Note that `result` will contain all items found (optionally
|
||||
wrapped into an array) whereas `callback` can be used if you
|
||||
wish to perform some operation as each item is discovered, with
|
||||
the callback function being executed 0 to N times depending
|
||||
on the number of independent items to be found in the result.
|
||||
See the docs below for more on `JSONPath`'s available arguments.
|
||||
|
||||
See also the [API docs](https://jsonpath-plus.github.io/JSONPath/docs/ts/).
|
||||
|
||||
### Properties
|
||||
|
||||
The properties that can be supplied on the options object or
|
||||
evaluate method (as the first argument) include:
|
||||
|
||||
- ***path*** (**required**) - The JSONPath expression as a (normalized
|
||||
or unnormalized) string or array
|
||||
- ***json*** (**required**) - The JSON object to evaluate (whether of
|
||||
null, boolean, number, string, object, or array type).
|
||||
- ***autostart*** (**default: true**) - If this is supplied as `false`,
|
||||
one may call the `evaluate` method manually.
|
||||
- ***flatten*** (**default: false**) - Whether the returned array of results
|
||||
will be flattened to a single dimension array.
|
||||
- ***resultType*** (**default: "value"**) - Can be case-insensitive form of
|
||||
"value", "path", "pointer", "parent", or "parentProperty" to determine
|
||||
respectively whether to return results as the values of the found items,
|
||||
as their absolute paths, as [JSON Pointers](https://tools.ietf.org/html/rfc6901)
|
||||
to the absolute paths, as their parent objects, or as their parent's
|
||||
property name. If set to "all", all of these types will be returned on
|
||||
an object with the type as key name.
|
||||
- ***sandbox*** (**default: {}**) - Key-value map of variables to be
|
||||
available to code evaluations such as filtering expressions. (Note
|
||||
that the current path and value will also be available to those
|
||||
expressions; see the Syntax section for details.)
|
||||
- ***wrap*** (**default: true**) - Whether or not to wrap the results
|
||||
in an array. If `wrap` is set to `false`, and no results are found,
|
||||
`undefined` will be returned (as opposed to an empty array when
|
||||
`wrap` is set to true). If `wrap` is set to `false` and a single
|
||||
non-array result is found, that result will be the only item returned
|
||||
(not within an array). An array will still be returned if multiple
|
||||
results are found, however. To avoid ambiguities (in the case where
|
||||
it is necessary to distinguish between a result which is a failure
|
||||
and one which is an empty array), it is recommended to switch the
|
||||
default to `false`.
|
||||
- ***preventEval*** (**default: false**) - Although JavaScript evaluation
|
||||
expressions are allowed by default, for security reasons (if one is
|
||||
operating on untrusted user input, for example), one may wish to
|
||||
set this option to `true` to throw exceptions when these expressions
|
||||
are attempted.
|
||||
- ***parent*** (**default: null**) - In the event that a query could be
|
||||
made to return the root node, this allows the parent of that root node
|
||||
to be returned within results.
|
||||
- ***parentProperty*** (**default: null**) - In the event that a query
|
||||
could be made to return the root node, this allows the `parentProperty`
|
||||
of that root node to be returned within results.
|
||||
- ***callback*** (**default: (none)**) - If supplied, a callback will be
|
||||
called immediately upon retrieval of an end point value. The three arguments
|
||||
supplied will be the value of the payload (according to `resultType`),
|
||||
the type of the payload (whether it is a normal "value" or a "property"
|
||||
name), and a full payload object (with all `resultType`s).
|
||||
- ***otherTypeCallback*** (**default: \<A function that throws an error**
|
||||
**when @other() is encountered\>**) - In the current absence of JSON
|
||||
Schema support, one can determine types beyond the built-in types by
|
||||
adding the operator `@other()` at the end of one's query. If such a
|
||||
path is encountered, the `otherTypeCallback` will be invoked with the
|
||||
value of the item, its path, its parent, and its parent's property name,
|
||||
and it should return a boolean indicating whether the supplied value
|
||||
belongs to the "other" type or not (or it may handle transformations and
|
||||
return false).
|
||||
|
||||
### Instance methods
|
||||
|
||||
- ***evaluate(path, json, callback, otherTypeCallback)*** OR
|
||||
***evaluate({path: \<path\>, json: \<json object\>, callback:***
|
||||
***\<callback function\>, otherTypeCallback:***
|
||||
***\<otherTypeCallback function\>})*** - This method is only
|
||||
necessary if the `autostart` property is set to `false`. It
|
||||
can be used for repeated evaluations using the same configuration.
|
||||
Besides the listed properties, the latter method pattern can
|
||||
accept any of the other allowed instance properties (except
|
||||
for `autostart` which would have no relevance here).
|
||||
|
||||
### Class properties and methods
|
||||
|
||||
- ***JSONPath.cache*** - Exposes the cache object for those who wish
|
||||
to preserve and reuse it for optimization purposes.
|
||||
- ***JSONPath.toPathArray(pathAsString)*** - Accepts a normalized or
|
||||
unnormalized path as string and converts to an array: for
|
||||
example, `['$', 'aProperty', 'anotherProperty']`.
|
||||
- ***JSONPath.toPathString(pathAsArray)*** - Accepts a path array and
|
||||
converts to a normalized path string. The string will be in a form
|
||||
like: `$['aProperty']['anotherProperty][0]`. The JSONPath terminal
|
||||
constructions `~` and `^` and type operators like `@string()` are
|
||||
silently stripped.
|
||||
- ***JSONPath.toPointer(pathAsArray)*** - Accepts a path array and
|
||||
converts to a [JSON Pointer](https://tools.ietf.org/html/rfc6901).
|
||||
The string will be in a form like: `/aProperty/anotherProperty/0`
|
||||
(with any `~` and `/` internal characters escaped as per the JSON
|
||||
Pointer spec). The JSONPath terminal constructions `~` and `^` and
|
||||
type operators like `@string()` are silently stripped.
|
||||
|
||||
## Syntax through examples
|
||||
|
||||
Given the following JSON, taken from <http://goessner.net/articles/JsonPath/>:
|
||||
|
||||
```json
|
||||
{
|
||||
"store": {
|
||||
"book": [
|
||||
{
|
||||
"category": "reference",
|
||||
"author": "Nigel Rees",
|
||||
"title": "Sayings of the Century",
|
||||
"price": 8.95
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Herman Melville",
|
||||
"title": "Moby Dick",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "J. R. R. Tolkien",
|
||||
"title": "The Lord of the Rings",
|
||||
"isbn": "0-395-19395-8",
|
||||
"price": 22.99
|
||||
}
|
||||
],
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
and the following XML representation:
|
||||
|
||||
```xml
|
||||
<store>
|
||||
<book>
|
||||
<category>reference</category>
|
||||
<author>Nigel Rees</author>
|
||||
<title>Sayings of the Century</title>
|
||||
<price>8.95</price>
|
||||
</book>
|
||||
<book>
|
||||
<category>fiction</category>
|
||||
<author>Evelyn Waugh</author>
|
||||
<title>Sword of Honour</title>
|
||||
<price>12.99</price>
|
||||
</book>
|
||||
<book>
|
||||
<category>fiction</category>
|
||||
<author>Herman Melville</author>
|
||||
<title>Moby Dick</title>
|
||||
<isbn>0-553-21311-3</isbn>
|
||||
<price>8.99</price>
|
||||
</book>
|
||||
<book>
|
||||
<category>fiction</category>
|
||||
<author>J. R. R. Tolkien</author>
|
||||
<title>The Lord of the Rings</title>
|
||||
<isbn>0-395-19395-8</isbn>
|
||||
<price>22.99</price>
|
||||
</book>
|
||||
<bicycle>
|
||||
<color>red</color>
|
||||
<price>19.95</price>
|
||||
</bicycle>
|
||||
</store>
|
||||
```
|
||||
|
||||
Please note that the XPath examples below do not distinguish between
|
||||
retrieving elements and their text content (except where useful for
|
||||
comparisons or to prevent ambiguity). Note: to test the XPath examples
|
||||
(including 2.0 ones), [this demo](http://videlibri.sourceforge.net/cgi-bin/xidelcgi)
|
||||
may be helpful (set to `xml` or `xml-strict`).
|
||||
|
||||
| XPath | JSONPath | Result | Notes |
|
||||
| ----------------- | ---------------------- | ------------------------------------- | ----- |
|
||||
/store/book/author | $.store.book\[*].author | The authors of all books in the store | Can also be represented without the `$.` as `store.book[*].author` (though this is not present in the original spec); note that some character literals (`$` and `@`) require escaping, however
|
||||
//author | $..author | All authors |
|
||||
/store/* | $.store.* | All things in store, which are its books (a book array) and a red bicycle (a bicycle object).|
|
||||
/store//price | $.store..price | The price of everything in the store. |
|
||||
//book\[3] | $..book\[2] | The third book (book object) |
|
||||
//book\[last()] | $..book\[(@.length-1)]<br>$..book\[-1:] | The last book in order.| To access a property with a special character, utilize `[(@['...'])]` for the filter (this particular feature is not present in the original spec)
|
||||
//book\[position()<3]| $..book\[0,1]<br>$..book\[:2]| The first two books |
|
||||
//book/*\[self::category\|self::author] or //book/(category,author) in XPath 2.0 | $..book\[0]\[category,author]| The categories and authors of all books |
|
||||
//book\[isbn] | $..book\[?(@.isbn)] | Filter all books with an ISBN number | To access a property with a special character, utilize `[?@['...']]` for the filter (this particular feature is not present in the original spec)
|
||||
//book\[price<10] | $..book\[?(@.price<10)] | Filter all books cheaper than 10 |
|
||||
| //\*\[name() = 'price' and . != 8.95] | $..\*\[?(@property === 'price' && @ !== 8.95)] | Obtain all property values of objects whose property is price and which does not equal 8.95 | With the bare `@` allowing filtering objects by property value (not necessarily within arrays), you can add `^` after the expression to get at the object possessing the filtered properties
|
||||
/ | $ | The root of the JSON object (i.e., the whole object itself) | To get a literal `$` (by itself or anywhere in the path), you must use the backtick escape
|
||||
//\*/\*\|//\*/\*/text() | $..* | All Elements (and text) beneath root in an XML document. All members of a JSON structure beneath the root. |
|
||||
//* | $.. | All Elements in an XML document. All parent components of a JSON structure including root. | This behavior was not directly specified in the original spec
|
||||
//*\[price>19]/.. | $..\[?(@.price>19)]^ | Parent of those specific items with a price greater than 19 (i.e., the store value as the parent of the bicycle and the book array as parent of an individual book) | Parent (caret) not present in the original spec
|
||||
/store/*/name() (in XPath 2.0) | $.store.*~ | The property names of the store sub-object ("book" and "bicycle"). Useful with wildcard properties. | Property name (tilde) is not present in the original spec
|
||||
/store/book\[not(. is /store/book\[1\])\] (in XPath 2.0) | $.store.book\[?(@path !== "$\[\'store\']\[\'book\']\[0]")] | All books besides that at the path pointing to the first | @path not present in the original spec
|
||||
//book\[parent::\*/bicycle/color = "red"]/category | $..book\[?(@parent.bicycle && @parent.bicycle.color === "red")].category | Grabs all categories of books where the parent object of the book has a bicycle child whose color is red (i.e., all the books) | @parent is not present in the original spec
|
||||
//book/*\[name() != 'category'] | $..book.*\[?(@property !== "category")] | Grabs all children of "book" except for "category" ones | @property is not present in the original spec
|
||||
//book\[position() != 1] | $..book\[?(@property !== 0)] | Grabs all books whose property (which, being that we are reaching inside an array, is the numeric index) is not 0 | @property is not present in the original spec
|
||||
/store/\*/\*\[name(parent::*) != 'book'] | $.store.*\[?(@parentProperty !== "book")] | Grabs the grandchildren of store whose parent property is not book (i.e., bicycle's children, "color" and "price") | @parentProperty is not present in the original spec
|
||||
//book\[count(preceding-sibling::\*) != 0]/\*/text() | $..book.*\[?(@parentProperty !== 0)] | Get the property values of all book instances whereby the parent property of these values (i.e., the array index holding the book item parent object) is not 0 | @parentProperty is not present in the original spec
|
||||
//book\[price = /store/book\[3]/price] | $..book\[?(@.price === @root.store.book\[2].price)] | Filter all books whose price equals the price of the third book | @root is not present in the original spec
|
||||
//book/../\*\[. instance of element(\*, xs:decimal)\] (in XPath 2.0) | $..book..\*@number() | Get the numeric values within the book array | @number(), the other basic types (@boolean(), @string()), other low-level derived types (@null(), @object(), @array()), the JSONSchema-added type, @integer(), the compound type @scalar() (which also accepts `undefined` and non-finite numbers for JavaScript objects as well as all of the basic non-object/non-function types), the type, @other(), to be used in conjunction with a user-defined callback (see `otherTypeCallback`) and the following non-JSON types that can nevertheless be used with JSONPath when querying non-JSON JavaScript objects (@undefined(), @function(), @nonFinite()) are not present in the original spec
|
||||
//book/*[name() = 'category' and matches(., 'tion$')] (XPath 2.0) | $..book.*\[?(@property === "category" && @.match(/TION$/i))] | All categories of books which match the regex (end in 'TION' case insensitive) | @property is not present in the original spec.
|
||||
//book/*[matches(name(), 'bn$')]/parent::* (XPath 2.0) | $..book.*\[?(@property.match(/bn$/i))]^ | All books which have a property matching the regex (end in 'TION' case insensitive) | @property is not present in the original spec. Note: Uses the parent selector \^ at the end of the expression to return to the parent object; without the parent selector, it matches the two `isbn` key values.
|
||||
| | `` ` `` (e.g., `` `$`` to match a property literally named `$`) | Escapes the entire sequence following (to be treated as a literal) | `` ` `` is not present in the original spec; to get a literal backtick, use an additional backtick to escape
|
||||
|
||||
Any additional variables supplied as properties on the optional "sandbox"
|
||||
object option are also available to (parenthetical-based)
|
||||
evaluations.
|
||||
|
||||
## Potential sources of confusion for XPath users
|
||||
|
||||
1. In JSONPath, a filter expression, in addition to its `@` being a
|
||||
reference to its children, actually selects the immediate children
|
||||
as well, whereas in XPath, filter conditions do not select the children
|
||||
but delimit which of its parent nodes will be obtained in the result.
|
||||
1. In JSONPath, array indexes are, as in JavaScript, 0-based (they begin
|
||||
from 0), whereas in XPath, they are 1-based.
|
||||
1. In JSONPath, equality tests utilize (as per JavaScript) multiple equal signs
|
||||
whereas in XPath, they use a single equal sign.
|
||||
|
||||
## Ideas
|
||||
|
||||
1. Support OR outside of filters (as in XPath `|`) and grouping.
|
||||
1. Create syntax to work like XPath filters in not selecting children?
|
||||
1. Allow option for parentNode equivalent (maintaining entire chain of
|
||||
parent-and-parentProperty objects up to root)
|
||||
|
||||
## Development
|
||||
|
||||
Running the tests on Node:
|
||||
|
||||
```shell
|
||||
npm test
|
||||
```
|
||||
|
||||
For in-browser tests:
|
||||
|
||||
- Serve the js/html files:
|
||||
|
||||
```shell
|
||||
npm run browser-test
|
||||
```
|
||||
|
||||
- Visit [http://localhost:8082/test/](http://localhost:8082/test/).
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](http://www.opensource.org/licenses/mit-license.php).
|
19
node_modules/jsonpath-plus/demo/index.css
generated
vendored
Normal file
19
node_modules/jsonpath-plus/demo/index.css
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
#jsonpath {
|
||||
width: 90%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
float: left;
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.container textarea {
|
||||
margin: 2%;
|
||||
width: 98%;
|
||||
height: 565px;
|
||||
}
|
||||
|
||||
#demoNode {
|
||||
font-size: small;
|
||||
}
|
32
node_modules/jsonpath-plus/demo/index.html
generated
vendored
Normal file
32
node_modules/jsonpath-plus/demo/index.html
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSONPath Demo</title>
|
||||
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
|
||||
<link rel="stylesheet" href="index.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>JSONPath Demo <i id="demoNode">(To demo on Node instead, see the <a href="https://npm.runkit.com/jsonpath-plus">library on Runkit</a>.)</i>
|
||||
</h2>
|
||||
<form>
|
||||
<div>
|
||||
<label><b>JSONPath:</b>
|
||||
<input id="jsonpath" placeholder="$.books" />
|
||||
</label>
|
||||
</div>
|
||||
<div id="jsonSampleContainer" class="container">
|
||||
<label><b>JSON sample:</b>
|
||||
<textarea id="jsonSample" placeholder="{"books": []}"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
<div id="resultContainer" class="container">
|
||||
<label><b>Results:</b>
|
||||
<textarea id="results"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<script src="../dist/index-browser-umd.js"></script>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
48
node_modules/jsonpath-plus/demo/index.js
generated
vendored
Normal file
48
node_modules/jsonpath-plus/demo/index.js
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* globals JSONPath */
|
||||
/* eslint-disable import/unambiguous */
|
||||
|
||||
// Todo: Extract testing example paths/contents and use for a
|
||||
// pulldown that can populate examples
|
||||
|
||||
// Todo: Make configurable with other JSONPath options
|
||||
|
||||
// Todo: Allow source to be treated as an (evaled) JSON object
|
||||
|
||||
// Todo: Could add JSON/JS syntax highlighting in sample and result,
|
||||
// ideally with a jsonpath-plus parser highlighter as well
|
||||
|
||||
const $ = (s) => document.querySelector(s);
|
||||
|
||||
const updateResults = () => {
|
||||
const jsonSample = $('#jsonSample');
|
||||
const reportValidity = () => {
|
||||
// Doesn't work without a timeout
|
||||
setTimeout(() => {
|
||||
jsonSample.reportValidity();
|
||||
});
|
||||
};
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(jsonSample.value);
|
||||
jsonSample.setCustomValidity('');
|
||||
reportValidity();
|
||||
} catch (err) {
|
||||
jsonSample.setCustomValidity('Error parsing JSON: ' + err.toString());
|
||||
reportValidity();
|
||||
return;
|
||||
}
|
||||
const result = JSONPath.JSONPath({
|
||||
path: $('#jsonpath').value,
|
||||
json
|
||||
});
|
||||
|
||||
$('#results').value = JSON.stringify(result, null, 2);
|
||||
};
|
||||
|
||||
$('#jsonpath').addEventListener('input', () => {
|
||||
updateResults();
|
||||
});
|
||||
|
||||
$('#jsonSample').addEventListener('input', () => {
|
||||
updateResults();
|
||||
});
|
46
node_modules/jsonpath-plus/demo/node-import-test.mjs
generated
vendored
Normal file
46
node_modules/jsonpath-plus/demo/node-import-test.mjs
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
import {JSONPath} from '../dist/index-node-esm.mjs';
|
||||
|
||||
/* eslint-disable quotes, quote-props */
|
||||
const json = {
|
||||
"store": {
|
||||
"book": [{
|
||||
"category": "reference",
|
||||
"author": "Nigel Rees",
|
||||
"title": "Sayings of the Century",
|
||||
"price": 8.95
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Herman Melville",
|
||||
"title": "Moby Dick",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "J. R. R. Tolkien",
|
||||
"title": "The Lord of the Rings",
|
||||
"isbn": "0-395-19395-8",
|
||||
"price": 22.99
|
||||
}],
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95
|
||||
}
|
||||
}
|
||||
};
|
||||
/* eslint-enable quotes, quote-props */
|
||||
|
||||
const result = JSONPath({
|
||||
json,
|
||||
path: '$.store.book[*].author'
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('result', result);
|
1056
node_modules/jsonpath-plus/dist/index-browser-esm.js
generated
vendored
Normal file
1056
node_modules/jsonpath-plus/dist/index-browser-esm.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
node_modules/jsonpath-plus/dist/index-browser-esm.min.js
generated
vendored
Normal file
2
node_modules/jsonpath-plus/dist/index-browser-esm.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/jsonpath-plus/dist/index-browser-esm.min.js.map
generated
vendored
Normal file
1
node_modules/jsonpath-plus/dist/index-browser-esm.min.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1066
node_modules/jsonpath-plus/dist/index-browser-umd.js
generated
vendored
Normal file
1066
node_modules/jsonpath-plus/dist/index-browser-umd.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
node_modules/jsonpath-plus/dist/index-browser-umd.min.js
generated
vendored
Normal file
2
node_modules/jsonpath-plus/dist/index-browser-umd.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/jsonpath-plus/dist/index-browser-umd.min.js.map
generated
vendored
Normal file
1
node_modules/jsonpath-plus/dist/index-browser-umd.min.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
735
node_modules/jsonpath-plus/dist/index-node-cjs.js
generated
vendored
Normal file
735
node_modules/jsonpath-plus/dist/index-node-cjs.js
generated
vendored
Normal file
|
@ -0,0 +1,735 @@
|
|||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var vm = require('vm');
|
||||
|
||||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
||||
|
||||
var vm__default = /*#__PURE__*/_interopDefaultLegacy(vm);
|
||||
|
||||
const {
|
||||
hasOwnProperty: hasOwnProp
|
||||
} = Object.prototype;
|
||||
/**
|
||||
* @typedef {null|boolean|number|string|PlainObject|GenericArray} JSONObject
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copies array and then pushes item into it.
|
||||
* @param {GenericArray} arr Array to copy and into which to push
|
||||
* @param {any} item Array item to add (to end)
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
|
||||
function push(arr, item) {
|
||||
arr = arr.slice();
|
||||
arr.push(item);
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Copies array and then unshifts item into it.
|
||||
* @param {any} item Array item to add (to beginning)
|
||||
* @param {GenericArray} arr Array to copy and into which to unshift
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
|
||||
|
||||
function unshift(item, arr) {
|
||||
arr = arr.slice();
|
||||
arr.unshift(item);
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Caught when JSONPath is used without `new` but rethrown if with `new`
|
||||
* @extends Error
|
||||
*/
|
||||
|
||||
|
||||
class NewError extends Error {
|
||||
/**
|
||||
* @param {any} value The evaluated scalar value
|
||||
*/
|
||||
constructor(value) {
|
||||
super('JSONPath should not be called with "new" (it prevents return ' + 'of (unwrapped) scalar values)');
|
||||
this.avoidNew = true;
|
||||
this.value = value;
|
||||
this.name = 'NewError';
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @typedef {PlainObject} ReturnObject
|
||||
* @property {string} path
|
||||
* @property {JSONObject} value
|
||||
* @property {PlainObject|GenericArray} parent
|
||||
* @property {string} parentProperty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback JSONPathCallback
|
||||
* @param {string|PlainObject} preferredOutput
|
||||
* @param {"value"|"property"} type
|
||||
* @param {ReturnObject} fullRetObj
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback OtherTypeCallback
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
|
||||
/**
|
||||
* @typedef {PlainObject} JSONPathOptions
|
||||
* @property {JSON} json
|
||||
* @property {string|string[]} path
|
||||
* @property {"value"|"path"|"pointer"|"parent"|"parentProperty"|"all"} [resultType="value"]
|
||||
* @property {boolean} [flatten=false]
|
||||
* @property {boolean} [wrap=true]
|
||||
* @property {PlainObject} [sandbox={}]
|
||||
* @property {boolean} [preventEval=false]
|
||||
* @property {PlainObject|GenericArray|null} [parent=null]
|
||||
* @property {string|null} [parentProperty=null]
|
||||
* @property {JSONPathCallback} [callback]
|
||||
* @property {OtherTypeCallback} [otherTypeCallback] Defaults to
|
||||
* function which throws on encountering `@other`
|
||||
* @property {boolean} [autostart=true]
|
||||
*/
|
||||
|
||||
/* eslint-enable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
|
||||
/**
|
||||
* @param {string|JSONPathOptions} opts If a string, will be treated as `expr`
|
||||
* @param {string} [expr] JSON path to evaluate
|
||||
* @param {JSON} [obj] JSON object to evaluate against
|
||||
* @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload
|
||||
* per `resultType`, 2) `"value"|"property"`, 3) Full returned object with
|
||||
* all payloads
|
||||
* @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
|
||||
* of one's query, this will be invoked with the value of the item, its
|
||||
* path, its parent, and its parent's property name, and it should return
|
||||
* a boolean indicating whether the supplied value belongs to the "other"
|
||||
* type or not (or it may handle transformations and return `false`).
|
||||
* @returns {JSONPath}
|
||||
* @class
|
||||
*/
|
||||
|
||||
|
||||
function JSONPath(opts, expr, obj, callback, otherTypeCallback) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (!(this instanceof JSONPath)) {
|
||||
try {
|
||||
return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
|
||||
} catch (e) {
|
||||
if (!e.avoidNew) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opts === 'string') {
|
||||
otherTypeCallback = callback;
|
||||
callback = obj;
|
||||
obj = expr;
|
||||
expr = opts;
|
||||
opts = null;
|
||||
}
|
||||
|
||||
const optObj = opts && typeof opts === 'object';
|
||||
opts = opts || {};
|
||||
this.json = opts.json || obj;
|
||||
this.path = opts.path || expr;
|
||||
this.resultType = opts.resultType || 'value';
|
||||
this.flatten = opts.flatten || false;
|
||||
this.wrap = hasOwnProp.call(opts, 'wrap') ? opts.wrap : true;
|
||||
this.sandbox = opts.sandbox || {};
|
||||
this.preventEval = opts.preventEval || false;
|
||||
this.parent = opts.parent || null;
|
||||
this.parentProperty = opts.parentProperty || null;
|
||||
this.callback = opts.callback || callback || null;
|
||||
|
||||
this.otherTypeCallback = opts.otherTypeCallback || otherTypeCallback || function () {
|
||||
throw new TypeError('You must supply an otherTypeCallback callback option ' + 'with the @other() operator.');
|
||||
};
|
||||
|
||||
if (opts.autostart !== false) {
|
||||
const args = {
|
||||
path: optObj ? opts.path : expr
|
||||
};
|
||||
|
||||
if (!optObj) {
|
||||
args.json = obj;
|
||||
} else if ('json' in opts) {
|
||||
args.json = opts.json;
|
||||
}
|
||||
|
||||
const ret = this.evaluate(args);
|
||||
|
||||
if (!ret || typeof ret !== 'object') {
|
||||
throw new NewError(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // PUBLIC METHODS
|
||||
|
||||
|
||||
JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback) {
|
||||
let currParent = this.parent,
|
||||
currParentProperty = this.parentProperty;
|
||||
let {
|
||||
flatten,
|
||||
wrap
|
||||
} = this;
|
||||
this.currResultType = this.resultType;
|
||||
this.currPreventEval = this.preventEval;
|
||||
this.currSandbox = this.sandbox;
|
||||
callback = callback || this.callback;
|
||||
this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
|
||||
json = json || this.json;
|
||||
expr = expr || this.path;
|
||||
|
||||
if (expr && typeof expr === 'object' && !Array.isArray(expr)) {
|
||||
if (!expr.path && expr.path !== '') {
|
||||
throw new TypeError('You must supply a "path" property when providing an object ' + 'argument to JSONPath.evaluate().');
|
||||
}
|
||||
|
||||
if (!hasOwnProp.call(expr, 'json')) {
|
||||
throw new TypeError('You must supply a "json" property when providing an object ' + 'argument to JSONPath.evaluate().');
|
||||
}
|
||||
|
||||
({
|
||||
json
|
||||
} = expr);
|
||||
flatten = hasOwnProp.call(expr, 'flatten') ? expr.flatten : flatten;
|
||||
this.currResultType = hasOwnProp.call(expr, 'resultType') ? expr.resultType : this.currResultType;
|
||||
this.currSandbox = hasOwnProp.call(expr, 'sandbox') ? expr.sandbox : this.currSandbox;
|
||||
wrap = hasOwnProp.call(expr, 'wrap') ? expr.wrap : wrap;
|
||||
this.currPreventEval = hasOwnProp.call(expr, 'preventEval') ? expr.preventEval : this.currPreventEval;
|
||||
callback = hasOwnProp.call(expr, 'callback') ? expr.callback : callback;
|
||||
this.currOtherTypeCallback = hasOwnProp.call(expr, 'otherTypeCallback') ? expr.otherTypeCallback : this.currOtherTypeCallback;
|
||||
currParent = hasOwnProp.call(expr, 'parent') ? expr.parent : currParent;
|
||||
currParentProperty = hasOwnProp.call(expr, 'parentProperty') ? expr.parentProperty : currParentProperty;
|
||||
expr = expr.path;
|
||||
}
|
||||
|
||||
currParent = currParent || null;
|
||||
currParentProperty = currParentProperty || null;
|
||||
|
||||
if (Array.isArray(expr)) {
|
||||
expr = JSONPath.toPathString(expr);
|
||||
}
|
||||
|
||||
if (!expr && expr !== '' || !json) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const exprList = JSONPath.toPathArray(expr);
|
||||
|
||||
if (exprList[0] === '$' && exprList.length > 1) {
|
||||
exprList.shift();
|
||||
}
|
||||
|
||||
this._hasParentSelector = null;
|
||||
|
||||
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
|
||||
return ea && !ea.isParentSelector;
|
||||
});
|
||||
|
||||
if (!result.length) {
|
||||
return wrap ? [] : undefined;
|
||||
}
|
||||
|
||||
if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
|
||||
return this._getPreferredOutput(result[0]);
|
||||
}
|
||||
|
||||
return result.reduce((rslt, ea) => {
|
||||
const valOrPath = this._getPreferredOutput(ea);
|
||||
|
||||
if (flatten && Array.isArray(valOrPath)) {
|
||||
rslt = rslt.concat(valOrPath);
|
||||
} else {
|
||||
rslt.push(valOrPath);
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}, []);
|
||||
}; // PRIVATE METHODS
|
||||
|
||||
|
||||
JSONPath.prototype._getPreferredOutput = function (ea) {
|
||||
const resultType = this.currResultType;
|
||||
|
||||
switch (resultType) {
|
||||
case 'all':
|
||||
{
|
||||
const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
|
||||
ea.pointer = JSONPath.toPointer(path);
|
||||
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
|
||||
return ea;
|
||||
}
|
||||
|
||||
case 'value':
|
||||
case 'parent':
|
||||
case 'parentProperty':
|
||||
return ea[resultType];
|
||||
|
||||
case 'path':
|
||||
return JSONPath.toPathString(ea[resultType]);
|
||||
|
||||
case 'pointer':
|
||||
return JSONPath.toPointer(ea.path);
|
||||
|
||||
default:
|
||||
throw new TypeError('Unknown result type');
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
|
||||
if (callback) {
|
||||
const preferredOutput = this._getPreferredOutput(fullRetObj);
|
||||
|
||||
fullRetObj.path = typeof fullRetObj.path === 'string' ? fullRetObj.path : JSONPath.toPathString(fullRetObj.path); // eslint-disable-next-line node/callback-return
|
||||
|
||||
callback(preferredOutput, type, fullRetObj);
|
||||
}
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param {string} expr
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @param {JSONPathCallback} callback
|
||||
* @param {boolean} hasArrExpr
|
||||
* @param {boolean} literalPriority
|
||||
* @returns {ReturnObject|ReturnObject[]}
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) {
|
||||
// No expr to follow? return path and value as the result of
|
||||
// this trace branch
|
||||
let retObj;
|
||||
|
||||
if (!expr.length) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName,
|
||||
hasArrExpr
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
|
||||
return retObj;
|
||||
}
|
||||
|
||||
const loc = expr[0],
|
||||
x = expr.slice(1); // We need to gather the return value of recursive trace calls in order to
|
||||
// do the parent sel computation.
|
||||
|
||||
const ret = [];
|
||||
/**
|
||||
*
|
||||
* @param {ReturnObject|ReturnObject[]} elems
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
function addRet(elems) {
|
||||
if (Array.isArray(elems)) {
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test:
|
||||
// `ret.push(...elems);`
|
||||
elems.forEach(t => {
|
||||
ret.push(t);
|
||||
});
|
||||
} else {
|
||||
ret.push(elems);
|
||||
}
|
||||
}
|
||||
|
||||
if ((typeof loc !== 'string' || literalPriority) && val && hasOwnProp.call(val, loc)) {
|
||||
// simple case--directly follow property
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
|
||||
} else if (loc === '*') {
|
||||
// all child properties
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb, true, true));
|
||||
});
|
||||
} else if (loc === '..') {
|
||||
// all descendent parent properties
|
||||
// Check remaining expression with val's immediate children
|
||||
addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
// We don't join m and x here because we only want parents,
|
||||
// not scalar values
|
||||
if (typeof v[m] === 'object') {
|
||||
// Keep going with recursive descent on val's
|
||||
// object children
|
||||
addRet(this._trace(unshift(l, _x), v[m], push(p, m), v, m, cb, true));
|
||||
}
|
||||
}); // The parent sel computation is handled in the frame above using the
|
||||
// ancestor object of val
|
||||
|
||||
} else if (loc === '^') {
|
||||
// This is not a final endpoint, so we do not invoke the callback here
|
||||
this._hasParentSelector = true;
|
||||
return {
|
||||
path: path.slice(0, -1),
|
||||
expr: x,
|
||||
isParentSelector: true
|
||||
};
|
||||
} else if (loc === '~') {
|
||||
// property name
|
||||
retObj = {
|
||||
path: push(path, loc),
|
||||
value: parentPropName,
|
||||
parent,
|
||||
parentProperty: null
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'property');
|
||||
|
||||
return retObj;
|
||||
} else if (loc === '$') {
|
||||
// root only
|
||||
addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
|
||||
} else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
|
||||
// [start:end:step] Python slice syntax
|
||||
addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
|
||||
} else if (loc.indexOf('?(') === 0) {
|
||||
// [?(expr)] (filtering)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
|
||||
}
|
||||
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
if (this._eval(l.replace(/^\?\((.*?)\)$/u, '$1'), v[m], m, p, par, pr)) {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb, true));
|
||||
}
|
||||
});
|
||||
} else if (loc[0] === '(') {
|
||||
// [(expr)] (dynamic property/index)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [(expr)] prevented in JSONPath expression.');
|
||||
} // As this will resolve to a property name (but we don't know it
|
||||
// yet), property and parent information is relative to the
|
||||
// parent of the property to which this expression will resolve
|
||||
|
||||
|
||||
addRet(this._trace(unshift(this._eval(loc, val, path[path.length - 1], path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
} else if (loc[0] === '@') {
|
||||
// value type: @boolean(), etc.
|
||||
let addType = false;
|
||||
const valueType = loc.slice(1, -2);
|
||||
|
||||
switch (valueType) {
|
||||
case 'scalar':
|
||||
if (!val || !['object', 'function'].includes(typeof val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
case 'string':
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
if (Number.isFinite(val) && !(val % 1)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
if (Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'nonFinite':
|
||||
if (typeof val === 'number' && !Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (val && typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
if (Array.isArray(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'other':
|
||||
addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
|
||||
break;
|
||||
|
||||
case 'null':
|
||||
if (val === null) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* istanbul ignore next */
|
||||
|
||||
default:
|
||||
throw new TypeError('Unknown value type ' + valueType);
|
||||
}
|
||||
|
||||
if (addType) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
|
||||
return retObj;
|
||||
} // `-escaped property
|
||||
|
||||
} else if (loc[0] === '`' && val && hasOwnProp.call(val, loc.slice(1))) {
|
||||
const locProp = loc.slice(1);
|
||||
addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
|
||||
} else if (loc.includes(',')) {
|
||||
// [name1,name2,...]
|
||||
const parts = loc.split(',');
|
||||
|
||||
for (const part of parts) {
|
||||
addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
|
||||
} // simple case--directly follow property
|
||||
|
||||
} else if (!literalPriority && val && hasOwnProp.call(val, loc)) {
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
|
||||
} // We check the resulting values for parent selections. For parent
|
||||
// selections we discard the value object and continue the trace with the
|
||||
// current val object
|
||||
|
||||
|
||||
if (this._hasParentSelector) {
|
||||
for (let t = 0; t < ret.length; t++) {
|
||||
const rett = ret[t];
|
||||
|
||||
if (rett && rett.isParentSelector) {
|
||||
const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
|
||||
|
||||
if (Array.isArray(tmp)) {
|
||||
ret[t] = tmp[0];
|
||||
const tl = tmp.length;
|
||||
|
||||
for (let tt = 1; tt < tl; tt++) {
|
||||
t++;
|
||||
ret.splice(t, 0, tmp[tt]);
|
||||
}
|
||||
} else {
|
||||
ret[t] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._walk = function (loc, expr, val, path, parent, parentPropName, callback, f) {
|
||||
if (Array.isArray(val)) {
|
||||
const n = val.length;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
f(i, loc, expr, val, path, parent, parentPropName, callback);
|
||||
}
|
||||
} else if (val && typeof val === 'object') {
|
||||
Object.keys(val).forEach(m => {
|
||||
f(m, loc, expr, val, path, parent, parentPropName, callback);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
|
||||
if (!Array.isArray(val)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const len = val.length,
|
||||
parts = loc.split(':'),
|
||||
step = parts[2] && Number.parseInt(parts[2]) || 1;
|
||||
let start = parts[0] && Number.parseInt(parts[0]) || 0,
|
||||
end = parts[1] && Number.parseInt(parts[1]) || len;
|
||||
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
|
||||
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
|
||||
const ret = [];
|
||||
|
||||
for (let i = start; i < end; i += step) {
|
||||
const tmp = this._trace(unshift(i, expr), val, path, parent, parentPropName, callback, true); // Should only be possible to be an array here since first part of
|
||||
// ``unshift(i, expr)` passed in above would not be empty, nor `~`,
|
||||
// nor begin with `@` (as could return objects)
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test: `ret.push(...tmp);`
|
||||
|
||||
|
||||
tmp.forEach(t => {
|
||||
ret.push(t);
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropName) {
|
||||
if (code.includes('@parentProperty')) {
|
||||
this.currSandbox._$_parentProperty = parentPropName;
|
||||
code = code.replace(/@parentProperty/gu, '_$_parentProperty');
|
||||
}
|
||||
|
||||
if (code.includes('@parent')) {
|
||||
this.currSandbox._$_parent = parent;
|
||||
code = code.replace(/@parent/gu, '_$_parent');
|
||||
}
|
||||
|
||||
if (code.includes('@property')) {
|
||||
this.currSandbox._$_property = _vname;
|
||||
code = code.replace(/@property/gu, '_$_property');
|
||||
}
|
||||
|
||||
if (code.includes('@path')) {
|
||||
this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
|
||||
code = code.replace(/@path/gu, '_$_path');
|
||||
}
|
||||
|
||||
if (code.includes('@root')) {
|
||||
this.currSandbox._$_root = this.json;
|
||||
code = code.replace(/@root/gu, '_$_root');
|
||||
}
|
||||
|
||||
if (/@([.\s)[])/u.test(code)) {
|
||||
this.currSandbox._$_v = _v;
|
||||
code = code.replace(/@([.\s)[])/gu, '_$_v$1');
|
||||
}
|
||||
|
||||
try {
|
||||
return this.vm.runInNewContext(code, this.currSandbox);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
throw new Error('jsonPath: ' + e.message + ': ' + code);
|
||||
}
|
||||
}; // PUBLIC CLASS PROPERTIES AND METHODS
|
||||
// Could store the cache object itself
|
||||
|
||||
|
||||
JSONPath.cache = {};
|
||||
/**
|
||||
* @param {string[]} pathArr Array to convert
|
||||
* @returns {string} The path string
|
||||
*/
|
||||
|
||||
JSONPath.toPathString = function (pathArr) {
|
||||
const x = pathArr,
|
||||
n = x.length;
|
||||
let p = '$';
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
/**
|
||||
* @param {string} pointer JSON Path
|
||||
* @returns {string} JSON Pointer
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.toPointer = function (pointer) {
|
||||
const x = pointer,
|
||||
n = x.length;
|
||||
let p = '';
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += '/' + x[i].toString().replace(/~/gu, '~0').replace(/\//gu, '~1');
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
/**
|
||||
* @param {string} expr Expression to convert
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.toPathArray = function (expr) {
|
||||
const {
|
||||
cache
|
||||
} = JSONPath;
|
||||
|
||||
if (cache[expr]) {
|
||||
return cache[expr].concat();
|
||||
}
|
||||
|
||||
const subx = [];
|
||||
const normalized = expr // Properties
|
||||
.replace(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;') // Parenthetical evaluations (filtering and otherwise), directly
|
||||
// within brackets or single quotes
|
||||
.replace(/[['](\??\(.*?\))[\]']/gu, function ($0, $1) {
|
||||
return '[#' + (subx.push($1) - 1) + ']';
|
||||
}) // Escape periods and tildes within properties
|
||||
.replace(/\['([^'\]]*)'\]/gu, function ($0, prop) {
|
||||
return "['" + prop.replace(/\./gu, '%@%').replace(/~/gu, '%%@@%%') + "']";
|
||||
}) // Properties operator
|
||||
.replace(/~/gu, ';~;') // Split by property boundaries
|
||||
.replace(/'?\.'?(?![^[]*\])|\['?/gu, ';') // Reinsert periods within properties
|
||||
.replace(/%@%/gu, '.') // Reinsert tildes within properties
|
||||
.replace(/%%@@%%/gu, '~') // Parent
|
||||
.replace(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
|
||||
return ';' + ups.split('').join(';') + ';';
|
||||
}) // Descendents
|
||||
.replace(/;;;|;;/gu, ';..;') // Remove trailing
|
||||
.replace(/;$|'?\]|'$/gu, '');
|
||||
const exprList = normalized.split(';').map(function (exp) {
|
||||
const match = exp.match(/#(\d+)/u);
|
||||
return !match || !match[1] ? exp : subx[match[1]];
|
||||
});
|
||||
cache[expr] = exprList;
|
||||
return cache[expr].concat();
|
||||
};
|
||||
|
||||
JSONPath.prototype.vm = vm__default['default'];
|
||||
|
||||
exports.JSONPath = JSONPath;
|
727
node_modules/jsonpath-plus/dist/index-node-esm.mjs
generated
vendored
Normal file
727
node_modules/jsonpath-plus/dist/index-node-esm.mjs
generated
vendored
Normal file
|
@ -0,0 +1,727 @@
|
|||
import vm from 'vm';
|
||||
|
||||
const {
|
||||
hasOwnProperty: hasOwnProp
|
||||
} = Object.prototype;
|
||||
/**
|
||||
* @typedef {null|boolean|number|string|PlainObject|GenericArray} JSONObject
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copies array and then pushes item into it.
|
||||
* @param {GenericArray} arr Array to copy and into which to push
|
||||
* @param {any} item Array item to add (to end)
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
|
||||
function push(arr, item) {
|
||||
arr = arr.slice();
|
||||
arr.push(item);
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Copies array and then unshifts item into it.
|
||||
* @param {any} item Array item to add (to beginning)
|
||||
* @param {GenericArray} arr Array to copy and into which to unshift
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
|
||||
|
||||
function unshift(item, arr) {
|
||||
arr = arr.slice();
|
||||
arr.unshift(item);
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Caught when JSONPath is used without `new` but rethrown if with `new`
|
||||
* @extends Error
|
||||
*/
|
||||
|
||||
|
||||
class NewError extends Error {
|
||||
/**
|
||||
* @param {any} value The evaluated scalar value
|
||||
*/
|
||||
constructor(value) {
|
||||
super('JSONPath should not be called with "new" (it prevents return ' + 'of (unwrapped) scalar values)');
|
||||
this.avoidNew = true;
|
||||
this.value = value;
|
||||
this.name = 'NewError';
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @typedef {PlainObject} ReturnObject
|
||||
* @property {string} path
|
||||
* @property {JSONObject} value
|
||||
* @property {PlainObject|GenericArray} parent
|
||||
* @property {string} parentProperty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback JSONPathCallback
|
||||
* @param {string|PlainObject} preferredOutput
|
||||
* @param {"value"|"property"} type
|
||||
* @param {ReturnObject} fullRetObj
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback OtherTypeCallback
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
|
||||
/**
|
||||
* @typedef {PlainObject} JSONPathOptions
|
||||
* @property {JSON} json
|
||||
* @property {string|string[]} path
|
||||
* @property {"value"|"path"|"pointer"|"parent"|"parentProperty"|"all"} [resultType="value"]
|
||||
* @property {boolean} [flatten=false]
|
||||
* @property {boolean} [wrap=true]
|
||||
* @property {PlainObject} [sandbox={}]
|
||||
* @property {boolean} [preventEval=false]
|
||||
* @property {PlainObject|GenericArray|null} [parent=null]
|
||||
* @property {string|null} [parentProperty=null]
|
||||
* @property {JSONPathCallback} [callback]
|
||||
* @property {OtherTypeCallback} [otherTypeCallback] Defaults to
|
||||
* function which throws on encountering `@other`
|
||||
* @property {boolean} [autostart=true]
|
||||
*/
|
||||
|
||||
/* eslint-enable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
|
||||
/**
|
||||
* @param {string|JSONPathOptions} opts If a string, will be treated as `expr`
|
||||
* @param {string} [expr] JSON path to evaluate
|
||||
* @param {JSON} [obj] JSON object to evaluate against
|
||||
* @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload
|
||||
* per `resultType`, 2) `"value"|"property"`, 3) Full returned object with
|
||||
* all payloads
|
||||
* @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
|
||||
* of one's query, this will be invoked with the value of the item, its
|
||||
* path, its parent, and its parent's property name, and it should return
|
||||
* a boolean indicating whether the supplied value belongs to the "other"
|
||||
* type or not (or it may handle transformations and return `false`).
|
||||
* @returns {JSONPath}
|
||||
* @class
|
||||
*/
|
||||
|
||||
|
||||
function JSONPath(opts, expr, obj, callback, otherTypeCallback) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (!(this instanceof JSONPath)) {
|
||||
try {
|
||||
return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
|
||||
} catch (e) {
|
||||
if (!e.avoidNew) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opts === 'string') {
|
||||
otherTypeCallback = callback;
|
||||
callback = obj;
|
||||
obj = expr;
|
||||
expr = opts;
|
||||
opts = null;
|
||||
}
|
||||
|
||||
const optObj = opts && typeof opts === 'object';
|
||||
opts = opts || {};
|
||||
this.json = opts.json || obj;
|
||||
this.path = opts.path || expr;
|
||||
this.resultType = opts.resultType || 'value';
|
||||
this.flatten = opts.flatten || false;
|
||||
this.wrap = hasOwnProp.call(opts, 'wrap') ? opts.wrap : true;
|
||||
this.sandbox = opts.sandbox || {};
|
||||
this.preventEval = opts.preventEval || false;
|
||||
this.parent = opts.parent || null;
|
||||
this.parentProperty = opts.parentProperty || null;
|
||||
this.callback = opts.callback || callback || null;
|
||||
|
||||
this.otherTypeCallback = opts.otherTypeCallback || otherTypeCallback || function () {
|
||||
throw new TypeError('You must supply an otherTypeCallback callback option ' + 'with the @other() operator.');
|
||||
};
|
||||
|
||||
if (opts.autostart !== false) {
|
||||
const args = {
|
||||
path: optObj ? opts.path : expr
|
||||
};
|
||||
|
||||
if (!optObj) {
|
||||
args.json = obj;
|
||||
} else if ('json' in opts) {
|
||||
args.json = opts.json;
|
||||
}
|
||||
|
||||
const ret = this.evaluate(args);
|
||||
|
||||
if (!ret || typeof ret !== 'object') {
|
||||
throw new NewError(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // PUBLIC METHODS
|
||||
|
||||
|
||||
JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback) {
|
||||
let currParent = this.parent,
|
||||
currParentProperty = this.parentProperty;
|
||||
let {
|
||||
flatten,
|
||||
wrap
|
||||
} = this;
|
||||
this.currResultType = this.resultType;
|
||||
this.currPreventEval = this.preventEval;
|
||||
this.currSandbox = this.sandbox;
|
||||
callback = callback || this.callback;
|
||||
this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
|
||||
json = json || this.json;
|
||||
expr = expr || this.path;
|
||||
|
||||
if (expr && typeof expr === 'object' && !Array.isArray(expr)) {
|
||||
if (!expr.path && expr.path !== '') {
|
||||
throw new TypeError('You must supply a "path" property when providing an object ' + 'argument to JSONPath.evaluate().');
|
||||
}
|
||||
|
||||
if (!hasOwnProp.call(expr, 'json')) {
|
||||
throw new TypeError('You must supply a "json" property when providing an object ' + 'argument to JSONPath.evaluate().');
|
||||
}
|
||||
|
||||
({
|
||||
json
|
||||
} = expr);
|
||||
flatten = hasOwnProp.call(expr, 'flatten') ? expr.flatten : flatten;
|
||||
this.currResultType = hasOwnProp.call(expr, 'resultType') ? expr.resultType : this.currResultType;
|
||||
this.currSandbox = hasOwnProp.call(expr, 'sandbox') ? expr.sandbox : this.currSandbox;
|
||||
wrap = hasOwnProp.call(expr, 'wrap') ? expr.wrap : wrap;
|
||||
this.currPreventEval = hasOwnProp.call(expr, 'preventEval') ? expr.preventEval : this.currPreventEval;
|
||||
callback = hasOwnProp.call(expr, 'callback') ? expr.callback : callback;
|
||||
this.currOtherTypeCallback = hasOwnProp.call(expr, 'otherTypeCallback') ? expr.otherTypeCallback : this.currOtherTypeCallback;
|
||||
currParent = hasOwnProp.call(expr, 'parent') ? expr.parent : currParent;
|
||||
currParentProperty = hasOwnProp.call(expr, 'parentProperty') ? expr.parentProperty : currParentProperty;
|
||||
expr = expr.path;
|
||||
}
|
||||
|
||||
currParent = currParent || null;
|
||||
currParentProperty = currParentProperty || null;
|
||||
|
||||
if (Array.isArray(expr)) {
|
||||
expr = JSONPath.toPathString(expr);
|
||||
}
|
||||
|
||||
if (!expr && expr !== '' || !json) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const exprList = JSONPath.toPathArray(expr);
|
||||
|
||||
if (exprList[0] === '$' && exprList.length > 1) {
|
||||
exprList.shift();
|
||||
}
|
||||
|
||||
this._hasParentSelector = null;
|
||||
|
||||
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
|
||||
return ea && !ea.isParentSelector;
|
||||
});
|
||||
|
||||
if (!result.length) {
|
||||
return wrap ? [] : undefined;
|
||||
}
|
||||
|
||||
if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
|
||||
return this._getPreferredOutput(result[0]);
|
||||
}
|
||||
|
||||
return result.reduce((rslt, ea) => {
|
||||
const valOrPath = this._getPreferredOutput(ea);
|
||||
|
||||
if (flatten && Array.isArray(valOrPath)) {
|
||||
rslt = rslt.concat(valOrPath);
|
||||
} else {
|
||||
rslt.push(valOrPath);
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}, []);
|
||||
}; // PRIVATE METHODS
|
||||
|
||||
|
||||
JSONPath.prototype._getPreferredOutput = function (ea) {
|
||||
const resultType = this.currResultType;
|
||||
|
||||
switch (resultType) {
|
||||
case 'all':
|
||||
{
|
||||
const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
|
||||
ea.pointer = JSONPath.toPointer(path);
|
||||
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
|
||||
return ea;
|
||||
}
|
||||
|
||||
case 'value':
|
||||
case 'parent':
|
||||
case 'parentProperty':
|
||||
return ea[resultType];
|
||||
|
||||
case 'path':
|
||||
return JSONPath.toPathString(ea[resultType]);
|
||||
|
||||
case 'pointer':
|
||||
return JSONPath.toPointer(ea.path);
|
||||
|
||||
default:
|
||||
throw new TypeError('Unknown result type');
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
|
||||
if (callback) {
|
||||
const preferredOutput = this._getPreferredOutput(fullRetObj);
|
||||
|
||||
fullRetObj.path = typeof fullRetObj.path === 'string' ? fullRetObj.path : JSONPath.toPathString(fullRetObj.path); // eslint-disable-next-line node/callback-return
|
||||
|
||||
callback(preferredOutput, type, fullRetObj);
|
||||
}
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param {string} expr
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @param {JSONPathCallback} callback
|
||||
* @param {boolean} hasArrExpr
|
||||
* @param {boolean} literalPriority
|
||||
* @returns {ReturnObject|ReturnObject[]}
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) {
|
||||
// No expr to follow? return path and value as the result of
|
||||
// this trace branch
|
||||
let retObj;
|
||||
|
||||
if (!expr.length) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName,
|
||||
hasArrExpr
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
|
||||
return retObj;
|
||||
}
|
||||
|
||||
const loc = expr[0],
|
||||
x = expr.slice(1); // We need to gather the return value of recursive trace calls in order to
|
||||
// do the parent sel computation.
|
||||
|
||||
const ret = [];
|
||||
/**
|
||||
*
|
||||
* @param {ReturnObject|ReturnObject[]} elems
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
function addRet(elems) {
|
||||
if (Array.isArray(elems)) {
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test:
|
||||
// `ret.push(...elems);`
|
||||
elems.forEach(t => {
|
||||
ret.push(t);
|
||||
});
|
||||
} else {
|
||||
ret.push(elems);
|
||||
}
|
||||
}
|
||||
|
||||
if ((typeof loc !== 'string' || literalPriority) && val && hasOwnProp.call(val, loc)) {
|
||||
// simple case--directly follow property
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
|
||||
} else if (loc === '*') {
|
||||
// all child properties
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb, true, true));
|
||||
});
|
||||
} else if (loc === '..') {
|
||||
// all descendent parent properties
|
||||
// Check remaining expression with val's immediate children
|
||||
addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
// We don't join m and x here because we only want parents,
|
||||
// not scalar values
|
||||
if (typeof v[m] === 'object') {
|
||||
// Keep going with recursive descent on val's
|
||||
// object children
|
||||
addRet(this._trace(unshift(l, _x), v[m], push(p, m), v, m, cb, true));
|
||||
}
|
||||
}); // The parent sel computation is handled in the frame above using the
|
||||
// ancestor object of val
|
||||
|
||||
} else if (loc === '^') {
|
||||
// This is not a final endpoint, so we do not invoke the callback here
|
||||
this._hasParentSelector = true;
|
||||
return {
|
||||
path: path.slice(0, -1),
|
||||
expr: x,
|
||||
isParentSelector: true
|
||||
};
|
||||
} else if (loc === '~') {
|
||||
// property name
|
||||
retObj = {
|
||||
path: push(path, loc),
|
||||
value: parentPropName,
|
||||
parent,
|
||||
parentProperty: null
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'property');
|
||||
|
||||
return retObj;
|
||||
} else if (loc === '$') {
|
||||
// root only
|
||||
addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
|
||||
} else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
|
||||
// [start:end:step] Python slice syntax
|
||||
addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
|
||||
} else if (loc.indexOf('?(') === 0) {
|
||||
// [?(expr)] (filtering)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
|
||||
}
|
||||
|
||||
this._walk(loc, x, val, path, parent, parentPropName, callback, (m, l, _x, v, p, par, pr, cb) => {
|
||||
if (this._eval(l.replace(/^\?\((.*?)\)$/u, '$1'), v[m], m, p, par, pr)) {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb, true));
|
||||
}
|
||||
});
|
||||
} else if (loc[0] === '(') {
|
||||
// [(expr)] (dynamic property/index)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [(expr)] prevented in JSONPath expression.');
|
||||
} // As this will resolve to a property name (but we don't know it
|
||||
// yet), property and parent information is relative to the
|
||||
// parent of the property to which this expression will resolve
|
||||
|
||||
|
||||
addRet(this._trace(unshift(this._eval(loc, val, path[path.length - 1], path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
} else if (loc[0] === '@') {
|
||||
// value type: @boolean(), etc.
|
||||
let addType = false;
|
||||
const valueType = loc.slice(1, -2);
|
||||
|
||||
switch (valueType) {
|
||||
case 'scalar':
|
||||
if (!val || !['object', 'function'].includes(typeof val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
case 'string':
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
if (Number.isFinite(val) && !(val % 1)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
if (Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'nonFinite':
|
||||
if (typeof val === 'number' && !Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (val && typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
if (Array.isArray(val)) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'other':
|
||||
addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
|
||||
break;
|
||||
|
||||
case 'null':
|
||||
if (val === null) {
|
||||
addType = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* istanbul ignore next */
|
||||
|
||||
default:
|
||||
throw new TypeError('Unknown value type ' + valueType);
|
||||
}
|
||||
|
||||
if (addType) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName
|
||||
};
|
||||
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
|
||||
return retObj;
|
||||
} // `-escaped property
|
||||
|
||||
} else if (loc[0] === '`' && val && hasOwnProp.call(val, loc.slice(1))) {
|
||||
const locProp = loc.slice(1);
|
||||
addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
|
||||
} else if (loc.includes(',')) {
|
||||
// [name1,name2,...]
|
||||
const parts = loc.split(',');
|
||||
|
||||
for (const part of parts) {
|
||||
addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
|
||||
} // simple case--directly follow property
|
||||
|
||||
} else if (!literalPriority && val && hasOwnProp.call(val, loc)) {
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
|
||||
} // We check the resulting values for parent selections. For parent
|
||||
// selections we discard the value object and continue the trace with the
|
||||
// current val object
|
||||
|
||||
|
||||
if (this._hasParentSelector) {
|
||||
for (let t = 0; t < ret.length; t++) {
|
||||
const rett = ret[t];
|
||||
|
||||
if (rett && rett.isParentSelector) {
|
||||
const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
|
||||
|
||||
if (Array.isArray(tmp)) {
|
||||
ret[t] = tmp[0];
|
||||
const tl = tmp.length;
|
||||
|
||||
for (let tt = 1; tt < tl; tt++) {
|
||||
t++;
|
||||
ret.splice(t, 0, tmp[tt]);
|
||||
}
|
||||
} else {
|
||||
ret[t] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._walk = function (loc, expr, val, path, parent, parentPropName, callback, f) {
|
||||
if (Array.isArray(val)) {
|
||||
const n = val.length;
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
f(i, loc, expr, val, path, parent, parentPropName, callback);
|
||||
}
|
||||
} else if (val && typeof val === 'object') {
|
||||
Object.keys(val).forEach(m => {
|
||||
f(m, loc, expr, val, path, parent, parentPropName, callback);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
|
||||
if (!Array.isArray(val)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const len = val.length,
|
||||
parts = loc.split(':'),
|
||||
step = parts[2] && Number.parseInt(parts[2]) || 1;
|
||||
let start = parts[0] && Number.parseInt(parts[0]) || 0,
|
||||
end = parts[1] && Number.parseInt(parts[1]) || len;
|
||||
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
|
||||
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
|
||||
const ret = [];
|
||||
|
||||
for (let i = start; i < end; i += step) {
|
||||
const tmp = this._trace(unshift(i, expr), val, path, parent, parentPropName, callback, true); // Should only be possible to be an array here since first part of
|
||||
// ``unshift(i, expr)` passed in above would not be empty, nor `~`,
|
||||
// nor begin with `@` (as could return objects)
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test: `ret.push(...tmp);`
|
||||
|
||||
|
||||
tmp.forEach(t => {
|
||||
ret.push(t);
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropName) {
|
||||
if (code.includes('@parentProperty')) {
|
||||
this.currSandbox._$_parentProperty = parentPropName;
|
||||
code = code.replace(/@parentProperty/gu, '_$_parentProperty');
|
||||
}
|
||||
|
||||
if (code.includes('@parent')) {
|
||||
this.currSandbox._$_parent = parent;
|
||||
code = code.replace(/@parent/gu, '_$_parent');
|
||||
}
|
||||
|
||||
if (code.includes('@property')) {
|
||||
this.currSandbox._$_property = _vname;
|
||||
code = code.replace(/@property/gu, '_$_property');
|
||||
}
|
||||
|
||||
if (code.includes('@path')) {
|
||||
this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
|
||||
code = code.replace(/@path/gu, '_$_path');
|
||||
}
|
||||
|
||||
if (code.includes('@root')) {
|
||||
this.currSandbox._$_root = this.json;
|
||||
code = code.replace(/@root/gu, '_$_root');
|
||||
}
|
||||
|
||||
if (/@([.\s)[])/u.test(code)) {
|
||||
this.currSandbox._$_v = _v;
|
||||
code = code.replace(/@([.\s)[])/gu, '_$_v$1');
|
||||
}
|
||||
|
||||
try {
|
||||
return this.vm.runInNewContext(code, this.currSandbox);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
throw new Error('jsonPath: ' + e.message + ': ' + code);
|
||||
}
|
||||
}; // PUBLIC CLASS PROPERTIES AND METHODS
|
||||
// Could store the cache object itself
|
||||
|
||||
|
||||
JSONPath.cache = {};
|
||||
/**
|
||||
* @param {string[]} pathArr Array to convert
|
||||
* @returns {string} The path string
|
||||
*/
|
||||
|
||||
JSONPath.toPathString = function (pathArr) {
|
||||
const x = pathArr,
|
||||
n = x.length;
|
||||
let p = '$';
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
/**
|
||||
* @param {string} pointer JSON Path
|
||||
* @returns {string} JSON Pointer
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.toPointer = function (pointer) {
|
||||
const x = pointer,
|
||||
n = x.length;
|
||||
let p = '';
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
|
||||
p += '/' + x[i].toString().replace(/~/gu, '~0').replace(/\//gu, '~1');
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
/**
|
||||
* @param {string} expr Expression to convert
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
|
||||
JSONPath.toPathArray = function (expr) {
|
||||
const {
|
||||
cache
|
||||
} = JSONPath;
|
||||
|
||||
if (cache[expr]) {
|
||||
return cache[expr].concat();
|
||||
}
|
||||
|
||||
const subx = [];
|
||||
const normalized = expr // Properties
|
||||
.replace(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;') // Parenthetical evaluations (filtering and otherwise), directly
|
||||
// within brackets or single quotes
|
||||
.replace(/[['](\??\(.*?\))[\]']/gu, function ($0, $1) {
|
||||
return '[#' + (subx.push($1) - 1) + ']';
|
||||
}) // Escape periods and tildes within properties
|
||||
.replace(/\['([^'\]]*)'\]/gu, function ($0, prop) {
|
||||
return "['" + prop.replace(/\./gu, '%@%').replace(/~/gu, '%%@@%%') + "']";
|
||||
}) // Properties operator
|
||||
.replace(/~/gu, ';~;') // Split by property boundaries
|
||||
.replace(/'?\.'?(?![^[]*\])|\['?/gu, ';') // Reinsert periods within properties
|
||||
.replace(/%@%/gu, '.') // Reinsert tildes within properties
|
||||
.replace(/%%@@%%/gu, '~') // Parent
|
||||
.replace(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
|
||||
return ';' + ups.split('').join(';') + ';';
|
||||
}) // Descendents
|
||||
.replace(/;;;|;;/gu, ';..;') // Remove trailing
|
||||
.replace(/;$|'?\]|'$/gu, '');
|
||||
const exprList = normalized.split(';').map(function (exp) {
|
||||
const match = exp.match(/#(\d+)/u);
|
||||
return !match || !match[1] ? exp : subx[match[1]];
|
||||
});
|
||||
cache[expr] = exprList;
|
||||
return cache[expr].concat();
|
||||
};
|
||||
|
||||
JSONPath.prototype.vm = vm;
|
||||
|
||||
export { JSONPath };
|
4
node_modules/jsonpath-plus/licenseInfo.json
generated
vendored
Normal file
4
node_modules/jsonpath-plus/licenseInfo.json
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"bundledRootPackages": [],
|
||||
"filesByLicense": {}
|
||||
}
|
151
node_modules/jsonpath-plus/package.json
generated
vendored
Normal file
151
node_modules/jsonpath-plus/package.json
generated
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
{
|
||||
"author": "Stefan Goessner",
|
||||
"name": "jsonpath-plus",
|
||||
"version": "5.0.7",
|
||||
"main": "dist/index-node-cjs.js",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"browser": "./dist/index-browser-esm.js",
|
||||
"umd": "./dist/index-browser-umd.js",
|
||||
"import": "./dist/index-node-esm.mjs",
|
||||
"require": "./dist/index-node-cjs.js",
|
||||
"default": "./dist/index-browser-esm.js"
|
||||
}
|
||||
},
|
||||
"module": "dist/index-node-esm.mjs",
|
||||
"browser": "dist/index-browser-esm.js",
|
||||
"types": "./src/jsonpath.d.ts",
|
||||
"description": "A JS implementation of JSONPath with some additional operators",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Prof. Gössner",
|
||||
"email": "stefan.goessner@fh-dortmund.de"
|
||||
},
|
||||
{
|
||||
"name": "Subbu Allamaraju",
|
||||
"email": "subbu@subbu.org"
|
||||
},
|
||||
{
|
||||
"name": "Mike Brevoort",
|
||||
"email": "mike@brevoort.com"
|
||||
},
|
||||
{
|
||||
"name": "Robert Krahn",
|
||||
"email": "robert.krahn@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Brett Zamir",
|
||||
"email": "brettz9@yahoo.com"
|
||||
},
|
||||
{
|
||||
"name": "Richard Schneider",
|
||||
"email": "makaretu@gmail.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/s3u/JSONPath.git"
|
||||
},
|
||||
"bugs": "https://github.com/s3u/JSONPath/issues/",
|
||||
"homepage": "https://github.com/s3u/JSONPath",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"react-native": {
|
||||
"vm": false
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.13.15",
|
||||
"@babel/preset-env": "^7.13.15",
|
||||
"@brettz9/eslint-plugin": "^1.0.3",
|
||||
"@rollup/plugin-babel": "^5.3.0",
|
||||
"chai": "^4.3.4",
|
||||
"core-js-bundle": "^3.10.1",
|
||||
"coveradge": "^0.6.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-config-ash-nazg": "^29.9.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-array-func": "^3.1.7",
|
||||
"eslint-plugin-chai-expect": "^2.2.0",
|
||||
"eslint-plugin-chai-friendly": "^0.6.0",
|
||||
"eslint-plugin-compat": "^3.9.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-html": "^6.1.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^32.3.0",
|
||||
"eslint-plugin-markdown": "^2.0.1",
|
||||
"eslint-plugin-no-unsanitized": "^3.1.4",
|
||||
"eslint-plugin-no-use-extend-native": "^0.5.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-radar": "^0.2.1",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-plugin-unicorn": "^29.0.0",
|
||||
"esm": "^3.2.25",
|
||||
"http-server": "^0.12.3",
|
||||
"license-badger": "^0.18.0",
|
||||
"mocha": "^8.3.2",
|
||||
"mocha-badge-generator": "^0.9.0",
|
||||
"mocha-multi-reporters": "^1.5.1",
|
||||
"nyc": "^15.1.0",
|
||||
"open-cli": "^6.0.1",
|
||||
"remark-cli": "^9.0.0",
|
||||
"remark-lint-code-block-style": "^2.0.1",
|
||||
"remark-lint-ordered-list-marker-value": "^2.0.1",
|
||||
"rollup": "2.45.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typedoc": "^0.20.35",
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"keywords": [
|
||||
"json",
|
||||
"jsonpath"
|
||||
],
|
||||
"browserslist": [
|
||||
"cover 100%"
|
||||
],
|
||||
"nyc": {
|
||||
"reporter": [
|
||||
"text",
|
||||
"html",
|
||||
"json-summary"
|
||||
],
|
||||
"exclude": [
|
||||
".mocharc.js",
|
||||
".eslintrc.js",
|
||||
"rollup.config.js",
|
||||
".idea",
|
||||
"coverage",
|
||||
"dist",
|
||||
"demo",
|
||||
"docs",
|
||||
"ignore",
|
||||
"test",
|
||||
"test-helpers"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"prepublishOnly": "pnpm i && echo 'reenable this when may be working for pnpm: npm run license-badges'",
|
||||
"license-badge": "license-badger --corrections --uncategorizedLicenseTemplate \"\\${license} (\\${name} (\\${version}))\" --filteredTypes=nonempty --textTemplate \"License types\n(project, deps, and bundled devDeps)\" --packageJson --production badges/licenses-badge.svg",
|
||||
"license-badge-dev": "license-badger --corrections --filteredTypes=nonempty --textTemplate \"License types\n(all devDeps)\" --allDevelopment badges/licenses-badge-dev.svg",
|
||||
"license-badges": "npm run license-badge && npm run license-badge-dev",
|
||||
"remark": "remark -q -f .",
|
||||
"build-docs": "typedoc --out docs/ts src --excludeExternals --tsconfig src/tsconfig.json",
|
||||
"open-docs": "open-cli http://localhost:8084/docs/ts/ && npm start",
|
||||
"coverage": "open-cli http://localhost:8084/coverage/ && npm start",
|
||||
"coverage-badge": "coveradge badges/coverage-badge.svg",
|
||||
"node-import-test": "node --experimental-modules demo/node-import-test.mjs",
|
||||
"open": "open-cli http://localhost:8084/demo/ && npm start",
|
||||
"start": "http-server -p 8084",
|
||||
"typescript": "tsc -p src",
|
||||
"mocha": "mocha --require esm --require test-helpers/node-env.js --reporter-options configFile=mocha-multi-reporters.json test",
|
||||
"nyc": "rm -Rf ./coverage && rm -Rf ./node_modules/.cache && nyc --all npm run mocha && npm run coverage-badge",
|
||||
"rollup": "rollup -c",
|
||||
"eslint": "eslint --ext js,md,html .",
|
||||
"test": "npm run eslint && npm run rollup && npm run nyc && npm run typescript",
|
||||
"browser-test": "npm run eslint && npm run rollup && open-cli http://localhost:8084/test/ && npm start"
|
||||
}
|
||||
}
|
78
node_modules/jsonpath-plus/src/jsonpath-browser.js
generated
vendored
Normal file
78
node_modules/jsonpath-plus/src/jsonpath-browser.js
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
import {JSONPath} from './jsonpath.js';
|
||||
|
||||
/**
|
||||
* @callback ConditionCallback
|
||||
* @param {any} item
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copy items out of one array into another.
|
||||
* @param {GenericArray} source Array with items to copy
|
||||
* @param {GenericArray} target Array to which to copy
|
||||
* @param {ConditionCallback} conditionCb Callback passed the current item;
|
||||
* will move item if evaluates to `true`
|
||||
* @returns {void}
|
||||
*/
|
||||
const moveToAnotherArray = function (source, target, conditionCb) {
|
||||
const il = source.length;
|
||||
for (let i = 0; i < il; i++) {
|
||||
const item = source[i];
|
||||
if (conditionCb(item)) {
|
||||
target.push(source.splice(i--, 1)[0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype.vm = {
|
||||
/**
|
||||
* @param {string} expr Expression to evaluate
|
||||
* @param {PlainObject} context Object whose items will be added
|
||||
* to evaluation
|
||||
* @returns {any} Result of evaluated code
|
||||
*/
|
||||
runInNewContext (expr, context) {
|
||||
const keys = Object.keys(context);
|
||||
const funcs = [];
|
||||
moveToAnotherArray(keys, funcs, (key) => {
|
||||
return typeof context[key] === 'function';
|
||||
});
|
||||
const values = keys.map((vr, i) => {
|
||||
return context[vr];
|
||||
});
|
||||
|
||||
const funcString = funcs.reduce((s, func) => {
|
||||
let fString = context[func].toString();
|
||||
if (!(/function/u).test(fString)) {
|
||||
fString = 'function ' + fString;
|
||||
}
|
||||
return 'var ' + func + '=' + fString + ';' + s;
|
||||
}, '');
|
||||
|
||||
expr = funcString + expr;
|
||||
|
||||
// Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function
|
||||
if (!(/(['"])use strict\1/u).test(expr) &&
|
||||
!keys.includes('arguments')
|
||||
) {
|
||||
expr = 'var arguments = undefined;' + expr;
|
||||
}
|
||||
|
||||
// Remove last semi so `return` will be inserted before
|
||||
// the previous one instead, allowing for the return
|
||||
// of a bare ending expression
|
||||
expr = expr.replace(/;\s*$/u, '');
|
||||
|
||||
// Insert `return`
|
||||
const lastStatementEnd = expr.lastIndexOf(';');
|
||||
const code = (lastStatementEnd > -1
|
||||
? expr.slice(0, lastStatementEnd + 1) +
|
||||
' return ' + expr.slice(lastStatementEnd + 1)
|
||||
: ' return ' + expr);
|
||||
|
||||
// eslint-disable-next-line no-new-func
|
||||
return (new Function(...keys, code))(...values);
|
||||
}
|
||||
};
|
||||
|
||||
export {JSONPath};
|
6
node_modules/jsonpath-plus/src/jsonpath-node.js
generated
vendored
Normal file
6
node_modules/jsonpath-plus/src/jsonpath-node.js
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
import vm from 'vm';
|
||||
import {JSONPath} from './jsonpath.js';
|
||||
|
||||
JSONPath.prototype.vm = vm;
|
||||
|
||||
export {JSONPath};
|
196
node_modules/jsonpath-plus/src/jsonpath.d.ts
generated
vendored
Normal file
196
node_modules/jsonpath-plus/src/jsonpath.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* Declaration for https://github.com/s3u/JSONPath
|
||||
*/
|
||||
declare module 'jsonpath-plus' {
|
||||
type JSONPathCallback = (
|
||||
payload: any, payloadType: any, fullPayload: any
|
||||
) => any
|
||||
|
||||
type JSONPathOtherTypeCallback = (...args: any[]) => void
|
||||
|
||||
interface JSONPathOptions {
|
||||
/**
|
||||
* The JSONPath expression as a (normalized or unnormalized) string or
|
||||
* array.
|
||||
*/
|
||||
path: string | any[]
|
||||
/**
|
||||
* The JSON object to evaluate (whether of null, boolean, number,
|
||||
* string, object, or array type).
|
||||
*/
|
||||
json: null | boolean | number | string | object | any[]
|
||||
/**
|
||||
* If this is supplied as false, one may call the evaluate method
|
||||
* manually.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
autostart?: true | boolean
|
||||
/**
|
||||
* Whether the returned array of results will be flattened to a
|
||||
* single dimension array.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
flatten?: false | boolean
|
||||
/**
|
||||
* Can be case-insensitive form of "value", "path", "pointer", "parent",
|
||||
* or "parentProperty" to determine respectively whether to return
|
||||
* results as the values of the found items, as their absolute paths,
|
||||
* as JSON Pointers to the absolute paths, as their parent objects,
|
||||
* or as their parent's property name.
|
||||
*
|
||||
* If set to "all", all of these types will be returned on an object with
|
||||
* the type as key name.
|
||||
*
|
||||
* @default 'value'
|
||||
*/
|
||||
resultType?:
|
||||
'value' | 'path' | 'pointer' | 'parent' | 'parentProperty' | 'all'
|
||||
|
||||
/**
|
||||
* Key-value map of variables to be available to code evaluations such
|
||||
* as filtering expressions.
|
||||
* (Note that the current path and value will also be available to those
|
||||
* expressions; see the Syntax section for details.)
|
||||
*/
|
||||
sandbox?: Map<string, any>
|
||||
/**
|
||||
* Whether or not to wrap the results in an array.
|
||||
*
|
||||
* If wrap is set to false, and no results are found, undefined will be
|
||||
* returned (as opposed to an empty array when wrap is set to true).
|
||||
*
|
||||
* If wrap is set to false and a single non-array result is found, that
|
||||
* result will be the only item returned (not within an array).
|
||||
*
|
||||
* An array will still be returned if multiple results are found, however.
|
||||
* To avoid ambiguities (in the case where it is necessary to distinguish
|
||||
* between a result which is a failure and one which is an empty array),
|
||||
* it is recommended to switch the default to false.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
wrap?: true | boolean
|
||||
/**
|
||||
* Although JavaScript evaluation expressions are allowed by default,
|
||||
* for security reasons (if one is operating on untrusted user input,
|
||||
* for example), one may wish to set this option to true to throw
|
||||
* exceptions when these expressions are attempted.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
preventEval?: false | boolean
|
||||
/**
|
||||
* In the event that a query could be made to return the root node,
|
||||
* this allows the parent of that root node to be returned within results.
|
||||
*
|
||||
* @default null
|
||||
*/
|
||||
parent?: null | any
|
||||
/**
|
||||
* In the event that a query could be made to return the root node,
|
||||
* this allows the parentProperty of that root node to be returned within
|
||||
* results.
|
||||
*
|
||||
* @default null
|
||||
*/
|
||||
parentProperty?: null | any
|
||||
/**
|
||||
* If supplied, a callback will be called immediately upon retrieval of
|
||||
* an end point value.
|
||||
*
|
||||
* The three arguments supplied will be the value of the payload
|
||||
* (according to `resultType`), the type of the payload (whether it is
|
||||
* a normal "value" or a "property" name), and a full payload object
|
||||
* (with all `resultType`s).
|
||||
*
|
||||
* @default undefined
|
||||
*/
|
||||
callback?: undefined | JSONPathCallback
|
||||
/**
|
||||
* In the current absence of JSON Schema support,
|
||||
* one can determine types beyond the built-in types by adding the
|
||||
* perator `@other()` at the end of one's query.
|
||||
*
|
||||
* If such a path is encountered, the `otherTypeCallback` will be invoked
|
||||
* with the value of the item, its path, its parent, and its parent's
|
||||
* property name, and it should return a boolean indicating whether the
|
||||
* supplied value belongs to the "other" type or not (or it may handle
|
||||
* transformations and return false).
|
||||
*
|
||||
* @default undefined
|
||||
* <A function that throws an error when `@other()` is encountered>
|
||||
*/
|
||||
otherTypeCallback?: undefined | JSONPathOtherTypeCallback
|
||||
}
|
||||
|
||||
interface JSONPathOptionsAutoStart extends JSONPathOptions {
|
||||
autostart: false
|
||||
}
|
||||
|
||||
interface JSONPathCallable {
|
||||
<T = any>(options: JSONPathOptionsAutoStart): JSONPathClass
|
||||
<T = any>(options: JSONPathOptions): T
|
||||
|
||||
<T = any>(
|
||||
path: JSONPathOptions['path'],
|
||||
json: JSONPathOptions['json'],
|
||||
callback: JSONPathOptions['callback'],
|
||||
otherTypeCallback: JSONPathOptions['otherTypeCallback']
|
||||
): T
|
||||
}
|
||||
|
||||
class JSONPathClass {
|
||||
/**
|
||||
* Exposes the cache object for those who wish to preserve and reuse
|
||||
* it for optimization purposes.
|
||||
*/
|
||||
cache: any
|
||||
|
||||
/**
|
||||
* Accepts a normalized or unnormalized path as string and
|
||||
* converts to an array: for example,
|
||||
* `['$', 'aProperty', 'anotherProperty']`.
|
||||
*/
|
||||
toPathArray(path: string): string[]
|
||||
|
||||
/**
|
||||
* Accepts a path array and converts to a normalized path string.
|
||||
* The string will be in a form like:
|
||||
* `$['aProperty']['anotherProperty][0]`.
|
||||
* The JSONPath terminal constructions `~` and `^` and type operators
|
||||
* like `@string()` are silently stripped.
|
||||
*/
|
||||
toPathString(path: string[]): string
|
||||
|
||||
/**
|
||||
* Accepts a path array and converts to a JSON Pointer.
|
||||
*
|
||||
* The string will be in a form like: `/aProperty/anotherProperty/0`
|
||||
* (with any `~` and `/` internal characters escaped as per the JSON
|
||||
* Pointer spec).
|
||||
*
|
||||
* The JSONPath terminal constructions `~` and `^` and type operators
|
||||
* like `@string()` are silently stripped.
|
||||
*/
|
||||
toPointer(path: string[]): any
|
||||
|
||||
evaluate(
|
||||
path: JSONPathOptions['path'],
|
||||
json: JSONPathOptions['json'],
|
||||
callback: JSONPathOptions['callback'],
|
||||
otherTypeCallback: JSONPathOptions['otherTypeCallback']
|
||||
): any
|
||||
evaluate(options: {
|
||||
path: JSONPathOptions['path'],
|
||||
json: JSONPathOptions['json'],
|
||||
callback: JSONPathOptions['callback'],
|
||||
otherTypeCallback: JSONPathOptions['otherTypeCallback']
|
||||
}): any
|
||||
}
|
||||
|
||||
type JSONPathType = JSONPathCallable & JSONPathClass
|
||||
|
||||
export const JSONPath: JSONPathType
|
||||
}
|
703
node_modules/jsonpath-plus/src/jsonpath.js
generated
vendored
Normal file
703
node_modules/jsonpath-plus/src/jsonpath.js
generated
vendored
Normal file
|
@ -0,0 +1,703 @@
|
|||
const {hasOwnProperty: hasOwnProp} = Object.prototype;
|
||||
|
||||
/**
|
||||
* @typedef {null|boolean|number|string|PlainObject|GenericArray} JSONObject
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copies array and then pushes item into it.
|
||||
* @param {GenericArray} arr Array to copy and into which to push
|
||||
* @param {any} item Array item to add (to end)
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
function push (arr, item) {
|
||||
arr = arr.slice();
|
||||
arr.push(item);
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Copies array and then unshifts item into it.
|
||||
* @param {any} item Array item to add (to beginning)
|
||||
* @param {GenericArray} arr Array to copy and into which to unshift
|
||||
* @returns {GenericArray} Copy of the original array
|
||||
*/
|
||||
function unshift (item, arr) {
|
||||
arr = arr.slice();
|
||||
arr.unshift(item);
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caught when JSONPath is used without `new` but rethrown if with `new`
|
||||
* @extends Error
|
||||
*/
|
||||
class NewError extends Error {
|
||||
/**
|
||||
* @param {any} value The evaluated scalar value
|
||||
*/
|
||||
constructor (value) {
|
||||
super(
|
||||
'JSONPath should not be called with "new" (it prevents return ' +
|
||||
'of (unwrapped) scalar values)'
|
||||
);
|
||||
this.avoidNew = true;
|
||||
this.value = value;
|
||||
this.name = 'NewError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {PlainObject} ReturnObject
|
||||
* @property {string} path
|
||||
* @property {JSONObject} value
|
||||
* @property {PlainObject|GenericArray} parent
|
||||
* @property {string} parentProperty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback JSONPathCallback
|
||||
* @param {string|PlainObject} preferredOutput
|
||||
* @param {"value"|"property"} type
|
||||
* @param {ReturnObject} fullRetObj
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback OtherTypeCallback
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
/**
|
||||
* @typedef {PlainObject} JSONPathOptions
|
||||
* @property {JSON} json
|
||||
* @property {string|string[]} path
|
||||
* @property {"value"|"path"|"pointer"|"parent"|"parentProperty"|"all"} [resultType="value"]
|
||||
* @property {boolean} [flatten=false]
|
||||
* @property {boolean} [wrap=true]
|
||||
* @property {PlainObject} [sandbox={}]
|
||||
* @property {boolean} [preventEval=false]
|
||||
* @property {PlainObject|GenericArray|null} [parent=null]
|
||||
* @property {string|null} [parentProperty=null]
|
||||
* @property {JSONPathCallback} [callback]
|
||||
* @property {OtherTypeCallback} [otherTypeCallback] Defaults to
|
||||
* function which throws on encountering `@other`
|
||||
* @property {boolean} [autostart=true]
|
||||
*/
|
||||
/* eslint-enable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
|
||||
|
||||
/**
|
||||
* @param {string|JSONPathOptions} opts If a string, will be treated as `expr`
|
||||
* @param {string} [expr] JSON path to evaluate
|
||||
* @param {JSON} [obj] JSON object to evaluate against
|
||||
* @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload
|
||||
* per `resultType`, 2) `"value"|"property"`, 3) Full returned object with
|
||||
* all payloads
|
||||
* @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
|
||||
* of one's query, this will be invoked with the value of the item, its
|
||||
* path, its parent, and its parent's property name, and it should return
|
||||
* a boolean indicating whether the supplied value belongs to the "other"
|
||||
* type or not (or it may handle transformations and return `false`).
|
||||
* @returns {JSONPath}
|
||||
* @class
|
||||
*/
|
||||
function JSONPath (opts, expr, obj, callback, otherTypeCallback) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
if (!(this instanceof JSONPath)) {
|
||||
try {
|
||||
return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
|
||||
} catch (e) {
|
||||
if (!e.avoidNew) {
|
||||
throw e;
|
||||
}
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opts === 'string') {
|
||||
otherTypeCallback = callback;
|
||||
callback = obj;
|
||||
obj = expr;
|
||||
expr = opts;
|
||||
opts = null;
|
||||
}
|
||||
const optObj = opts && typeof opts === 'object';
|
||||
opts = opts || {};
|
||||
this.json = opts.json || obj;
|
||||
this.path = opts.path || expr;
|
||||
this.resultType = opts.resultType || 'value';
|
||||
this.flatten = opts.flatten || false;
|
||||
this.wrap = hasOwnProp.call(opts, 'wrap') ? opts.wrap : true;
|
||||
this.sandbox = opts.sandbox || {};
|
||||
this.preventEval = opts.preventEval || false;
|
||||
this.parent = opts.parent || null;
|
||||
this.parentProperty = opts.parentProperty || null;
|
||||
this.callback = opts.callback || callback || null;
|
||||
this.otherTypeCallback = opts.otherTypeCallback ||
|
||||
otherTypeCallback ||
|
||||
function () {
|
||||
throw new TypeError(
|
||||
'You must supply an otherTypeCallback callback option ' +
|
||||
'with the @other() operator.'
|
||||
);
|
||||
};
|
||||
|
||||
if (opts.autostart !== false) {
|
||||
const args = {
|
||||
path: (optObj ? opts.path : expr)
|
||||
};
|
||||
if (!optObj) {
|
||||
args.json = obj;
|
||||
} else if ('json' in opts) {
|
||||
args.json = opts.json;
|
||||
}
|
||||
const ret = this.evaluate(args);
|
||||
if (!ret || typeof ret !== 'object') {
|
||||
throw new NewError(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// PUBLIC METHODS
|
||||
JSONPath.prototype.evaluate = function (
|
||||
expr, json, callback, otherTypeCallback
|
||||
) {
|
||||
let currParent = this.parent,
|
||||
currParentProperty = this.parentProperty;
|
||||
let {flatten, wrap} = this;
|
||||
|
||||
this.currResultType = this.resultType;
|
||||
this.currPreventEval = this.preventEval;
|
||||
this.currSandbox = this.sandbox;
|
||||
callback = callback || this.callback;
|
||||
this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
|
||||
|
||||
json = json || this.json;
|
||||
expr = expr || this.path;
|
||||
if (expr && typeof expr === 'object' && !Array.isArray(expr)) {
|
||||
if (!expr.path && expr.path !== '') {
|
||||
throw new TypeError(
|
||||
'You must supply a "path" property when providing an object ' +
|
||||
'argument to JSONPath.evaluate().'
|
||||
);
|
||||
}
|
||||
if (!(hasOwnProp.call(expr, 'json'))) {
|
||||
throw new TypeError(
|
||||
'You must supply a "json" property when providing an object ' +
|
||||
'argument to JSONPath.evaluate().'
|
||||
);
|
||||
}
|
||||
({json} = expr);
|
||||
flatten = hasOwnProp.call(expr, 'flatten') ? expr.flatten : flatten;
|
||||
this.currResultType = hasOwnProp.call(expr, 'resultType')
|
||||
? expr.resultType
|
||||
: this.currResultType;
|
||||
this.currSandbox = hasOwnProp.call(expr, 'sandbox')
|
||||
? expr.sandbox
|
||||
: this.currSandbox;
|
||||
wrap = hasOwnProp.call(expr, 'wrap') ? expr.wrap : wrap;
|
||||
this.currPreventEval = hasOwnProp.call(expr, 'preventEval')
|
||||
? expr.preventEval
|
||||
: this.currPreventEval;
|
||||
callback = hasOwnProp.call(expr, 'callback') ? expr.callback : callback;
|
||||
this.currOtherTypeCallback = hasOwnProp.call(expr, 'otherTypeCallback')
|
||||
? expr.otherTypeCallback
|
||||
: this.currOtherTypeCallback;
|
||||
currParent = hasOwnProp.call(expr, 'parent') ? expr.parent : currParent;
|
||||
currParentProperty = hasOwnProp.call(expr, 'parentProperty')
|
||||
? expr.parentProperty
|
||||
: currParentProperty;
|
||||
expr = expr.path;
|
||||
}
|
||||
currParent = currParent || null;
|
||||
currParentProperty = currParentProperty || null;
|
||||
|
||||
if (Array.isArray(expr)) {
|
||||
expr = JSONPath.toPathString(expr);
|
||||
}
|
||||
if ((!expr && expr !== '') || !json) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const exprList = JSONPath.toPathArray(expr);
|
||||
if (exprList[0] === '$' && exprList.length > 1) { exprList.shift(); }
|
||||
this._hasParentSelector = null;
|
||||
const result = this
|
||||
._trace(
|
||||
exprList, json, ['$'], currParent, currParentProperty, callback
|
||||
)
|
||||
.filter(function (ea) { return ea && !ea.isParentSelector; });
|
||||
|
||||
if (!result.length) { return wrap ? [] : undefined; }
|
||||
if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
|
||||
return this._getPreferredOutput(result[0]);
|
||||
}
|
||||
return result.reduce((rslt, ea) => {
|
||||
const valOrPath = this._getPreferredOutput(ea);
|
||||
if (flatten && Array.isArray(valOrPath)) {
|
||||
rslt = rslt.concat(valOrPath);
|
||||
} else {
|
||||
rslt.push(valOrPath);
|
||||
}
|
||||
return rslt;
|
||||
}, []);
|
||||
};
|
||||
|
||||
// PRIVATE METHODS
|
||||
|
||||
JSONPath.prototype._getPreferredOutput = function (ea) {
|
||||
const resultType = this.currResultType;
|
||||
switch (resultType) {
|
||||
case 'all': {
|
||||
const path = Array.isArray(ea.path)
|
||||
? ea.path
|
||||
: JSONPath.toPathArray(ea.path);
|
||||
ea.pointer = JSONPath.toPointer(path);
|
||||
ea.path = typeof ea.path === 'string'
|
||||
? ea.path
|
||||
: JSONPath.toPathString(ea.path);
|
||||
return ea;
|
||||
} case 'value': case 'parent': case 'parentProperty':
|
||||
return ea[resultType];
|
||||
case 'path':
|
||||
return JSONPath.toPathString(ea[resultType]);
|
||||
case 'pointer':
|
||||
return JSONPath.toPointer(ea.path);
|
||||
default:
|
||||
throw new TypeError('Unknown result type');
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
|
||||
if (callback) {
|
||||
const preferredOutput = this._getPreferredOutput(fullRetObj);
|
||||
fullRetObj.path = typeof fullRetObj.path === 'string'
|
||||
? fullRetObj.path
|
||||
: JSONPath.toPathString(fullRetObj.path);
|
||||
// eslint-disable-next-line node/callback-return
|
||||
callback(preferredOutput, type, fullRetObj);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} expr
|
||||
* @param {JSONObject} val
|
||||
* @param {string} path
|
||||
* @param {PlainObject|GenericArray} parent
|
||||
* @param {string} parentPropName
|
||||
* @param {JSONPathCallback} callback
|
||||
* @param {boolean} hasArrExpr
|
||||
* @param {boolean} literalPriority
|
||||
* @returns {ReturnObject|ReturnObject[]}
|
||||
*/
|
||||
JSONPath.prototype._trace = function (
|
||||
expr, val, path, parent, parentPropName, callback, hasArrExpr,
|
||||
literalPriority
|
||||
) {
|
||||
// No expr to follow? return path and value as the result of
|
||||
// this trace branch
|
||||
let retObj;
|
||||
if (!expr.length) {
|
||||
retObj = {
|
||||
path,
|
||||
value: val,
|
||||
parent,
|
||||
parentProperty: parentPropName,
|
||||
hasArrExpr
|
||||
};
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
return retObj;
|
||||
}
|
||||
|
||||
const loc = expr[0], x = expr.slice(1);
|
||||
|
||||
// We need to gather the return value of recursive trace calls in order to
|
||||
// do the parent sel computation.
|
||||
const ret = [];
|
||||
/**
|
||||
*
|
||||
* @param {ReturnObject|ReturnObject[]} elems
|
||||
* @returns {void}
|
||||
*/
|
||||
function addRet (elems) {
|
||||
if (Array.isArray(elems)) {
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test:
|
||||
// `ret.push(...elems);`
|
||||
elems.forEach((t) => {
|
||||
ret.push(t);
|
||||
});
|
||||
} else {
|
||||
ret.push(elems);
|
||||
}
|
||||
}
|
||||
if ((typeof loc !== 'string' || literalPriority) && val &&
|
||||
hasOwnProp.call(val, loc)
|
||||
) { // simple case--directly follow property
|
||||
addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback,
|
||||
hasArrExpr));
|
||||
} else if (loc === '*') { // all child properties
|
||||
this._walk(
|
||||
loc, x, val, path, parent, parentPropName, callback,
|
||||
(m, l, _x, v, p, par, pr, cb) => {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb,
|
||||
true, true));
|
||||
}
|
||||
);
|
||||
} else if (loc === '..') { // all descendent parent properties
|
||||
// Check remaining expression with val's immediate children
|
||||
addRet(
|
||||
this._trace(x, val, path, parent, parentPropName, callback,
|
||||
hasArrExpr)
|
||||
);
|
||||
this._walk(
|
||||
loc, x, val, path, parent, parentPropName, callback,
|
||||
(m, l, _x, v, p, par, pr, cb) => {
|
||||
// We don't join m and x here because we only want parents,
|
||||
// not scalar values
|
||||
if (typeof v[m] === 'object') {
|
||||
// Keep going with recursive descent on val's
|
||||
// object children
|
||||
addRet(this._trace(
|
||||
unshift(l, _x), v[m], push(p, m), v, m, cb, true
|
||||
));
|
||||
}
|
||||
}
|
||||
);
|
||||
// The parent sel computation is handled in the frame above using the
|
||||
// ancestor object of val
|
||||
} else if (loc === '^') {
|
||||
// This is not a final endpoint, so we do not invoke the callback here
|
||||
this._hasParentSelector = true;
|
||||
return {
|
||||
path: path.slice(0, -1),
|
||||
expr: x,
|
||||
isParentSelector: true
|
||||
};
|
||||
} else if (loc === '~') { // property name
|
||||
retObj = {
|
||||
path: push(path, loc),
|
||||
value: parentPropName,
|
||||
parent,
|
||||
parentProperty: null
|
||||
};
|
||||
this._handleCallback(retObj, callback, 'property');
|
||||
return retObj;
|
||||
} else if (loc === '$') { // root only
|
||||
addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
|
||||
} else if ((/^(-?\d*):(-?\d*):?(\d*)$/u).test(loc)) { // [start:end:step] Python slice syntax
|
||||
addRet(
|
||||
this._slice(loc, x, val, path, parent, parentPropName, callback)
|
||||
);
|
||||
} else if (loc.indexOf('?(') === 0) { // [?(expr)] (filtering)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
|
||||
}
|
||||
this._walk(
|
||||
loc, x, val, path, parent, parentPropName, callback,
|
||||
(m, l, _x, v, p, par, pr, cb) => {
|
||||
if (this._eval(l.replace(/^\?\((.*?)\)$/u, '$1'), v[m], m, p, par, pr)) {
|
||||
addRet(this._trace(unshift(m, _x), v, p, par, pr, cb,
|
||||
true));
|
||||
}
|
||||
}
|
||||
);
|
||||
} else if (loc[0] === '(') { // [(expr)] (dynamic property/index)
|
||||
if (this.currPreventEval) {
|
||||
throw new Error('Eval [(expr)] prevented in JSONPath expression.');
|
||||
}
|
||||
// As this will resolve to a property name (but we don't know it
|
||||
// yet), property and parent information is relative to the
|
||||
// parent of the property to which this expression will resolve
|
||||
addRet(this._trace(unshift(
|
||||
this._eval(
|
||||
loc, val, path[path.length - 1],
|
||||
path.slice(0, -1), parent, parentPropName
|
||||
),
|
||||
x
|
||||
), val, path, parent, parentPropName, callback, hasArrExpr));
|
||||
} else if (loc[0] === '@') { // value type: @boolean(), etc.
|
||||
let addType = false;
|
||||
const valueType = loc.slice(1, -2);
|
||||
switch (valueType) {
|
||||
case 'scalar':
|
||||
if (!val || !(['object', 'function'].includes(typeof val))) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'boolean': case 'string': case 'undefined': case 'function':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'integer':
|
||||
if (Number.isFinite(val) && !(val % 1)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'number':
|
||||
if (Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'nonFinite':
|
||||
if (typeof val === 'number' && !Number.isFinite(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'object':
|
||||
// eslint-disable-next-line valid-typeof
|
||||
if (val && typeof val === valueType) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'array':
|
||||
if (Array.isArray(val)) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
case 'other':
|
||||
addType = this.currOtherTypeCallback(
|
||||
val, path, parent, parentPropName
|
||||
);
|
||||
break;
|
||||
case 'null':
|
||||
if (val === null) {
|
||||
addType = true;
|
||||
}
|
||||
break;
|
||||
/* istanbul ignore next */
|
||||
default:
|
||||
throw new TypeError('Unknown value type ' + valueType);
|
||||
}
|
||||
if (addType) {
|
||||
retObj = {path, value: val, parent, parentProperty: parentPropName};
|
||||
this._handleCallback(retObj, callback, 'value');
|
||||
return retObj;
|
||||
}
|
||||
// `-escaped property
|
||||
} else if (loc[0] === '`' && val && hasOwnProp.call(val, loc.slice(1))) {
|
||||
const locProp = loc.slice(1);
|
||||
addRet(this._trace(
|
||||
x, val[locProp], push(path, locProp), val, locProp, callback,
|
||||
hasArrExpr, true
|
||||
));
|
||||
} else if (loc.includes(',')) { // [name1,name2,...]
|
||||
const parts = loc.split(',');
|
||||
for (const part of parts) {
|
||||
addRet(this._trace(
|
||||
unshift(part, x), val, path, parent, parentPropName, callback,
|
||||
true
|
||||
));
|
||||
}
|
||||
// simple case--directly follow property
|
||||
} else if (
|
||||
!literalPriority && val && hasOwnProp.call(val, loc)
|
||||
) {
|
||||
addRet(
|
||||
this._trace(x, val[loc], push(path, loc), val, loc, callback,
|
||||
hasArrExpr, true)
|
||||
);
|
||||
}
|
||||
|
||||
// We check the resulting values for parent selections. For parent
|
||||
// selections we discard the value object and continue the trace with the
|
||||
// current val object
|
||||
if (this._hasParentSelector) {
|
||||
for (let t = 0; t < ret.length; t++) {
|
||||
const rett = ret[t];
|
||||
if (rett && rett.isParentSelector) {
|
||||
const tmp = this._trace(
|
||||
rett.expr, val, rett.path, parent, parentPropName, callback,
|
||||
hasArrExpr
|
||||
);
|
||||
if (Array.isArray(tmp)) {
|
||||
ret[t] = tmp[0];
|
||||
const tl = tmp.length;
|
||||
for (let tt = 1; tt < tl; tt++) {
|
||||
t++;
|
||||
ret.splice(t, 0, tmp[tt]);
|
||||
}
|
||||
} else {
|
||||
ret[t] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._walk = function (
|
||||
loc, expr, val, path, parent, parentPropName, callback, f
|
||||
) {
|
||||
if (Array.isArray(val)) {
|
||||
const n = val.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
f(i, loc, expr, val, path, parent, parentPropName, callback);
|
||||
}
|
||||
} else if (val && typeof val === 'object') {
|
||||
Object.keys(val).forEach((m) => {
|
||||
f(m, loc, expr, val, path, parent, parentPropName, callback);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
JSONPath.prototype._slice = function (
|
||||
loc, expr, val, path, parent, parentPropName, callback
|
||||
) {
|
||||
if (!Array.isArray(val)) { return undefined; }
|
||||
const len = val.length, parts = loc.split(':'),
|
||||
step = (parts[2] && Number.parseInt(parts[2])) || 1;
|
||||
let start = (parts[0] && Number.parseInt(parts[0])) || 0,
|
||||
end = (parts[1] && Number.parseInt(parts[1])) || len;
|
||||
start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);
|
||||
end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);
|
||||
const ret = [];
|
||||
for (let i = start; i < end; i += step) {
|
||||
const tmp = this._trace(
|
||||
unshift(i, expr), val, path, parent, parentPropName, callback, true
|
||||
);
|
||||
// Should only be possible to be an array here since first part of
|
||||
// ``unshift(i, expr)` passed in above would not be empty, nor `~`,
|
||||
// nor begin with `@` (as could return objects)
|
||||
// This was causing excessive stack size in Node (with or
|
||||
// without Babel) against our performance test: `ret.push(...tmp);`
|
||||
tmp.forEach((t) => {
|
||||
ret.push(t);
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
JSONPath.prototype._eval = function (
|
||||
code, _v, _vname, path, parent, parentPropName
|
||||
) {
|
||||
if (code.includes('@parentProperty')) {
|
||||
this.currSandbox._$_parentProperty = parentPropName;
|
||||
code = code.replace(/@parentProperty/gu, '_$_parentProperty');
|
||||
}
|
||||
if (code.includes('@parent')) {
|
||||
this.currSandbox._$_parent = parent;
|
||||
code = code.replace(/@parent/gu, '_$_parent');
|
||||
}
|
||||
if (code.includes('@property')) {
|
||||
this.currSandbox._$_property = _vname;
|
||||
code = code.replace(/@property/gu, '_$_property');
|
||||
}
|
||||
if (code.includes('@path')) {
|
||||
this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
|
||||
code = code.replace(/@path/gu, '_$_path');
|
||||
}
|
||||
if (code.includes('@root')) {
|
||||
this.currSandbox._$_root = this.json;
|
||||
code = code.replace(/@root/gu, '_$_root');
|
||||
}
|
||||
if ((/@([.\s)[])/u).test(code)) {
|
||||
this.currSandbox._$_v = _v;
|
||||
code = code.replace(/@([.\s)[])/gu, '_$_v$1');
|
||||
}
|
||||
try {
|
||||
return this.vm.runInNewContext(code, this.currSandbox);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
throw new Error('jsonPath: ' + e.message + ': ' + code);
|
||||
}
|
||||
};
|
||||
|
||||
// PUBLIC CLASS PROPERTIES AND METHODS
|
||||
|
||||
// Could store the cache object itself
|
||||
JSONPath.cache = {};
|
||||
|
||||
/**
|
||||
* @param {string[]} pathArr Array to convert
|
||||
* @returns {string} The path string
|
||||
*/
|
||||
JSONPath.toPathString = function (pathArr) {
|
||||
const x = pathArr, n = x.length;
|
||||
let p = '$';
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
|
||||
p += (/^[0-9*]+$/u).test(x[i]) ? ('[' + x[i] + ']') : ("['" + x[i] + "']");
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} pointer JSON Path
|
||||
* @returns {string} JSON Pointer
|
||||
*/
|
||||
JSONPath.toPointer = function (pointer) {
|
||||
const x = pointer, n = x.length;
|
||||
let p = '';
|
||||
for (let i = 1; i < n; i++) {
|
||||
if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
|
||||
p += '/' + x[i].toString()
|
||||
.replace(/~/gu, '~0')
|
||||
.replace(/\//gu, '~1');
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} expr Expression to convert
|
||||
* @returns {string[]}
|
||||
*/
|
||||
JSONPath.toPathArray = function (expr) {
|
||||
const {cache} = JSONPath;
|
||||
if (cache[expr]) { return cache[expr].concat(); }
|
||||
const subx = [];
|
||||
const normalized = expr
|
||||
// Properties
|
||||
.replace(
|
||||
/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu,
|
||||
';$&;'
|
||||
)
|
||||
// Parenthetical evaluations (filtering and otherwise), directly
|
||||
// within brackets or single quotes
|
||||
.replace(/[['](\??\(.*?\))[\]']/gu, function ($0, $1) {
|
||||
return '[#' + (subx.push($1) - 1) + ']';
|
||||
})
|
||||
// Escape periods and tildes within properties
|
||||
.replace(/\['([^'\]]*)'\]/gu, function ($0, prop) {
|
||||
return "['" + prop
|
||||
.replace(/\./gu, '%@%')
|
||||
.replace(/~/gu, '%%@@%%') +
|
||||
"']";
|
||||
})
|
||||
// Properties operator
|
||||
.replace(/~/gu, ';~;')
|
||||
// Split by property boundaries
|
||||
.replace(/'?\.'?(?![^[]*\])|\['?/gu, ';')
|
||||
// Reinsert periods within properties
|
||||
.replace(/%@%/gu, '.')
|
||||
// Reinsert tildes within properties
|
||||
.replace(/%%@@%%/gu, '~')
|
||||
// Parent
|
||||
.replace(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
|
||||
return ';' + ups.split('').join(';') + ';';
|
||||
})
|
||||
// Descendents
|
||||
.replace(/;;;|;;/gu, ';..;')
|
||||
// Remove trailing
|
||||
.replace(/;$|'?\]|'$/gu, '');
|
||||
|
||||
const exprList = normalized.split(';').map(function (exp) {
|
||||
const match = exp.match(/#(\d+)/u);
|
||||
return !match || !match[1] ? exp : subx[match[1]];
|
||||
});
|
||||
cache[expr] = exprList;
|
||||
return cache[expr].concat();
|
||||
};
|
||||
|
||||
export {JSONPath};
|
6
node_modules/jsonpath-plus/src/tsconfig.json
generated
vendored
Normal file
6
node_modules/jsonpath-plus/src/tsconfig.json
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015"]
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue