Update to v13 and add queue and completely change code

This commit is contained in:
a 2021-12-06 16:34:00 +01:00
parent dcef23d0ed
commit 55a38726a3
6706 changed files with 424137 additions and 61608 deletions

5
node_modules/jsonpath-plus/.babelrc.json generated vendored Normal file
View file

@ -0,0 +1,5 @@
{
"presets": [
["@babel/preset-env"]
]
}

16
node_modules/jsonpath-plus/.editorconfig generated vendored Normal file
View 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
View file

@ -0,0 +1,6 @@
node_modules
dist
docs/ts
coverage
ignore
!*.js

105
node_modules/jsonpath-plus/.eslintrc.js generated vendored Normal file
View 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
View 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
View 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
View file

@ -0,0 +1,396 @@
[![npm](https://img.shields.io/npm/v/jsonpath-plus.svg)](https://www.npmjs.com/package/jsonpath-plus)
[![Dependencies](https://img.shields.io/david/s3u/JSONPath.svg)](https://david-dm.org/s3u/JSONPath)
[![devDependencies](https://img.shields.io/david/dev/s3u/JSONPath.svg)](https://david-dm.org/s3u/JSONPath?type=dev)
[![testing badge](https://raw.githubusercontent.com/s3u/JSONPath/master/badges/tests-badge.svg?sanitize=true)](badges/tests-badge.svg)
[![coverage badge](https://raw.githubusercontent.com/s3u/JSONPath/master/badges/coverage-badge.svg?sanitize=true)](badges/coverage-badge.svg)
[![Known Vulnerabilities](https://snyk.io/test/github/s3u/JSONPath/badge.svg)](https://snyk.io/test/github/s3u/JSONPath)
[![Total Alerts](https://img.shields.io/lgtm/alerts/g/s3u/JSONPath.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/s3u/JSONPath/alerts)
[![Code Quality: Javascript](https://img.shields.io/lgtm/grade/javascript/g/s3u/JSONPath.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/s3u/JSONPath/context:javascript)
<!--[![License](https://img.shields.io/npm/l/JSONPath.svg)](LICENSE-MIT.txt)-->
[![Licenses badge](https://raw.githubusercontent.com/s3u/JSONPath/master/badges/licenses-badge.svg?sanitize=true)](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 [![Node.js CI status](https://github.com/git://github.com/s3u/JSONPath.git/workflows/Node.js%20CI/badge.svg)](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
View 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
View 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="{&quot;books&quot;: []}"></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
View 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
View 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

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

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

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

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
View 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
View 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
View file

@ -0,0 +1,4 @@
{
"bundledRootPackages": [],
"filesByLicense": {}
}

151
node_modules/jsonpath-plus/package.json generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["es2015"]
},
"exclude": ["node_modules"]
}