@swaggerexpert/jsonpath 1.2.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,8 +34,9 @@ The development of this library contributed to the identification and formal sub
34
34
  - [Installation](#installation)
35
35
  - [Usage](#usage)
36
36
  - [Parsing](#parsing)
37
- - [Concrete Syntax Tree (CST)](#concrete-syntax-tree-cst)
38
- - [Interpreting Parse result as XML](#interpreting-parse-result-as-xml)
37
+ - [Translators](#translators)
38
+ - [CST](#cst-translator)
39
+ - [XML](#xml-translator)
39
40
  - [Statistics](#statistics)
40
41
  - [Tracing](#tracing)
41
42
  - [Errors](#errors)
@@ -72,228 +73,72 @@ const parseResult = parse('$.store.book[0].title');
72
73
  or
73
74
 
74
75
  ```js
75
- import { parse, JSONPathQueryCST } from '@swaggerexpert/jsonpath';
76
+ import { parse, CSTTranslator } from '@swaggerexpert/jsonpath';
76
77
 
77
- const parseResult = parse('$.store.book[0].title', { ast: new JSONPathQueryCST() });
78
+ const parseResult = parse('$.store.book[0].title', { translator: new CSTTranslator() });
78
79
  ```
79
80
 
80
81
  **parseResult** variable has the following shape:
81
82
 
82
83
  ```
83
84
  {
84
- result: {
85
- success: true,
86
- state: 101,
87
- stateName: 'MATCH',
88
- length: 21,
89
- matched: 21,
90
- maxMatched: 21,
91
- maxTreeDepth: 21,
92
- nodeHits: 298
93
- },
94
- ast: <JSONPathQueryCST>,
95
- computed: {
96
- stack: [],
97
- root: {
98
- type: 'jsonpath-query',
99
- text: '$.store.book[0].title',
100
- start: 0,
101
- length: 21,
102
- children: [
103
- {
104
- type: 'root-identifier',
105
- text: '$',
106
- start: 0,
107
- length: 1,
108
- children: []
109
- },
110
- {
111
- type: 'segments',
112
- text: '.store.book[0].title',
113
- start: 1,
114
- length: 20,
115
- children: [
116
- {
117
- type: 'segment',
118
- text: '.store',
119
- start: 1,
120
- length: 6,
121
- children: [
122
- {
123
- type: 'child-segment',
124
- text: '.store',
125
- start: 1,
126
- length: 6,
127
- children: [
128
- {
129
- type: 'text',
130
- text: '.',
131
- start: 1,
132
- length: 1,
133
- children: []
134
- },
135
- {
136
- type: 'member-name-shorthand',
137
- text: 'store',
138
- start: 2,
139
- length: 5,
140
- children: []
141
- }
142
- ]
143
- }
144
- ]
145
- },
146
- {
147
- type: 'segment',
148
- text: '.book',
149
- start: 7,
150
- length: 5,
151
- children: [
152
- {
153
- type: 'child-segment',
154
- text: '.book',
155
- start: 7,
156
- length: 5,
157
- children: [
158
- {
159
- type: 'text',
160
- text: '.',
161
- start: 7,
162
- length: 1,
163
- children: []
164
- },
165
- {
166
- type: 'member-name-shorthand',
167
- text: 'book',
168
- start: 8,
169
- length: 4,
170
- children: []
171
- }
172
- ]
173
- }
174
- ]
175
- },
176
- {
177
- type: 'segment',
178
- text: '[0]',
179
- start: 12,
180
- length: 3,
181
- children: [
182
- {
183
- type: 'child-segment',
184
- text: '[0]',
185
- start: 12,
186
- length: 3,
187
- children: [
188
- {
189
- type: 'bracketed-selection',
190
- text: '[0]',
191
- start: 12,
192
- length: 3,
193
- children: [
194
- {
195
- type: 'text',
196
- text: '[',
197
- start: 12,
198
- length: 1,
199
- children: []
200
- },
201
- {
202
- type: 'selector',
203
- text: '0',
204
- start: 13,
205
- length: 1,
206
- children: [
207
- {
208
- type: 'index-selector',
209
- text: '0',
210
- start: 13,
211
- length: 1,
212
- children: []
213
- }
214
- ]
215
- },
216
- {
217
- type: 'text',
218
- text: ']',
219
- start: 14,
220
- length: 1,
221
- children: []
222
- }
223
- ]
224
- }
225
- ]
226
- }
227
- ]
228
- },
229
- {
230
- type: 'segment',
231
- text: '.title',
232
- start: 15,
233
- length: 6,
234
- children: [
235
- {
236
- type: 'child-segment',
237
- text: '.title',
238
- start: 15,
239
- length: 6,
240
- children: [
241
- {
242
- type: 'text',
243
- text: '.',
244
- start: 15,
245
- length: 1,
246
- children: []
247
- },
248
- {
249
- type: 'member-name-shorthand',
250
- text: 'title',
251
- start: 16,
252
- length: 5,
253
- children: []
254
- }
255
- ]
256
- }
257
- ]
258
- }
259
- ]
260
- }
261
- ]
262
- }
263
- }
85
+ result: <ParseResult['result]>,
86
+ tree: <ParseResult['tree']>,
87
+ stats: <ParseResult['stats']>,
88
+ trace: <ParseResult['trace']>,
264
89
  }
265
90
  ```
266
91
 
267
- ###### Concrete Syntax Tree (CST)
92
+ [TypeScript typings](https://github.com/swaggerexpert/jsonpath/blob/main/types/index.d.ts) are available for all fields attached to parse result object returned by the `parse` function.
268
93
 
269
- [Concrete Syntax Tree](https://en.wikipedia.org/wiki/Parse_tree) (Parse tree) is available on parse result via `computed` field.
270
- Instance of `JSONPathQueryCST` needs to be assigned to `ast` option in `parse` function (default behavior).
94
+ ##### Translators
95
+
96
+ `@swaggerexpert/jsonpath` provides several translators to convert the parse result into different tree representations.
97
+
98
+ ###### CST translator
99
+
100
+ [Concrete Syntax Tree](https://en.wikipedia.org/wiki/Parse_tree) (Parse tree) representation is available on parse result
101
+ by default or when instance of `CSTTranslator` is provided via a `translator` option to the `parse` function.
271
102
  CST is suitable to be consumed by other tools like IDEs, editors, etc...
272
103
 
273
104
  ```js
274
105
  import { parse } from '@swaggerexpert/jsonpath';
275
106
 
276
- const { computed: CST } = parse('$.store.book[0].title');
107
+ const { tree: CST } = parse('$.store.book[0].title');
277
108
  ```
278
109
 
279
110
  or
280
111
 
281
112
  ```js
282
- import { parse, JSONPathQueryCST } from '@swaggerexpert/jsonpath';
113
+ import { parse, CSTTranslator } from '@swaggerexpert/jsonpath';
114
+
115
+ const { tree: CST } = parse('$.store.book[0].title', { translator: new CSTTranslator() });
116
+ ```
283
117
 
284
- const { computed: CST } = parse('$.store.book[0].title', { ast: new JSONPathQueryCST() });
118
+ CST tree has the following shape:
119
+
120
+ ```ts
121
+ interface CSTTree {
122
+ readonly root: CSTNode;
123
+ }
124
+ interface CSTNode {
125
+ readonly type: string,
126
+ readonly text: string,
127
+ readonly start: number,
128
+ readonly length: number,
129
+ readonly children: CSTNode[],
130
+ }
285
131
  ```
286
132
 
287
- ###### Interpreting Parse result as XML
133
+ ###### XML translator
288
134
 
289
135
  ```js
290
- import { parse } from '@swaggerexpert/jsonpath';
136
+ import { parse, XMLTranslator } from '@swaggerexpert/jsonpath';
291
137
 
292
- const parseResult = parse('$.store.book[0].title');
293
- const xml = parseResult.ast.toXml();
138
+ const { tree: XML } = parse('$.store.book[0].title', { translator: new XMLTranslator() });
294
139
  ```
295
140
 
296
- ###### Statistics
141
+ ##### Statistics
297
142
 
298
143
  `parse` function returns additional statistical information about the parsing process.
299
144
  Collection of the statistics can be enabled by setting `stats` option to `true`.
@@ -307,7 +152,7 @@ stats.displayStats(); // returns operator stats
307
152
  stats.displayHits(); // returns rules grouped by hit count
308
153
  ```
309
154
 
310
- ###### Tracing
155
+ ##### Tracing
311
156
 
312
157
  `parse` function returns additional tracing information about the parsing process.
313
158
  Tracing can be enabled by setting `trace` option to `true`. Tracing is essential
package/cjs/index.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.translateEvaluator = exports.parse = exports.JSONPathQueryCST = exports.Grammar = void 0;
4
+ exports.parse = exports.XMLTranslator = exports.Grammar = exports.CSTTranslator = void 0;
5
5
  var _grammar = _interopRequireDefault(require("./grammar.cjs"));
6
6
  exports.Grammar = _grammar.default;
7
7
  var _index = _interopRequireDefault(require("./parse/index.cjs"));
8
8
  exports.parse = _index.default;
9
- var _JSONPathQueryCST = _interopRequireDefault(require("./parse/ast/JSONPathQueryCST.cjs"));
10
- exports.JSONPathQueryCST = _JSONPathQueryCST.default;
11
- var _translate = _interopRequireDefault(require("./parse/evaluators/translate.cjs"));
12
- exports.translateEvaluator = _translate.default;
9
+ var _CSTTranslator = _interopRequireDefault(require("./parse/translators/CSTTranslator.cjs"));
10
+ exports.CSTTranslator = _CSTTranslator.default;
11
+ var _XMLTranslator = _interopRequireDefault(require("./parse/translators/XMLTranslator.cjs"));
12
+ exports.XMLTranslator = _XMLTranslator.default;
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -10,10 +10,6 @@ const cst = ruleName => {
10
10
  if (!(typeof data === 'object' && data !== null && !Array.isArray(data))) {
11
11
  throw new _JSONPathParseError.default("parser's user data must be an object");
12
12
  }
13
- if (!data.stack) {
14
- data.stack = [];
15
- data.root = null;
16
- }
17
13
 
18
14
  // drop the empty nodes
19
15
  if (phraseLength === 0) return;
@@ -4,35 +4,30 @@ exports.__esModule = true;
4
4
  exports.default = void 0;
5
5
  var _apgLite = require("../apg-lite.cjs");
6
6
  var _grammar = _interopRequireDefault(require("../grammar.cjs"));
7
- var _translate = _interopRequireDefault(require("./evaluators/translate.cjs"));
8
- var _JSONPathQueryCST = _interopRequireDefault(require("./ast/JSONPathQueryCST.cjs"));
7
+ var _CSTTranslator = _interopRequireDefault(require("./translators/CSTTranslator.cjs"));
9
8
  var _JSONPathParseError = _interopRequireDefault(require("../errors/JSONPathParseError.cjs"));
10
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
10
  const grammar = new _grammar.default();
12
11
  const parse = (jsonPath, {
13
- ast = new _JSONPathQueryCST.default(),
12
+ translator = new _CSTTranslator.default(),
14
13
  stats = false,
15
- trace = false,
16
- evaluator = _translate.default
14
+ trace = false
17
15
  } = {}) => {
18
16
  if (typeof jsonPath !== 'string') {
19
17
  throw new TypeError('JSONPath must be a string');
20
18
  }
21
19
  try {
20
+ var _parser$ast;
22
21
  const parser = new _apgLite.Parser();
23
- parser.ast = ast;
22
+ if (translator) parser.ast = translator;
24
23
  if (stats) parser.stats = new _apgLite.Stats();
25
24
  if (trace) parser.trace = new _apgLite.Trace();
26
25
  const result = parser.parse(grammar, 'jsonpath-query', jsonPath);
27
- const computed = evaluator(ast, {
28
- result
29
- });
30
26
  return {
31
27
  result,
32
- ast,
28
+ tree: (_parser$ast = parser.ast) == null ? void 0 : _parser$ast.getTree(),
33
29
  stats: parser.stats,
34
- trace: parser.trace,
35
- computed
30
+ trace: parser.trace
36
31
  };
37
32
  } catch (error) {
38
33
  throw new _JSONPathParseError.default('Unexpected error during JSONPath parsing', {
@@ -5,7 +5,7 @@ exports.default = void 0;
5
5
  var _apgLite = require("../../apg-lite.cjs");
6
6
  var _cst = _interopRequireDefault(require("../callbacks/cst.cjs"));
7
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
- class JSONPathQueryCST extends _apgLite.Ast {
8
+ class CSTTranslator extends _apgLite.Ast {
9
9
  constructor() {
10
10
  super();
11
11
 
@@ -97,5 +97,14 @@ class JSONPathQueryCST extends _apgLite.Ast {
97
97
  this.callbacks['left-paren'] = (0, _cst.default)('text');
98
98
  this.callbacks['right-paren'] = (0, _cst.default)('text');
99
99
  }
100
+ getTree() {
101
+ const data = {
102
+ stack: [],
103
+ root: null
104
+ };
105
+ this.translate(data);
106
+ delete data.stack;
107
+ return data;
108
+ }
100
109
  }
101
- var _default = exports.default = JSONPathQueryCST;
110
+ var _default = exports.default = CSTTranslator;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _CSTTranslator = _interopRequireDefault(require("./CSTTranslator.cjs"));
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ class XMLTranslator extends _CSTTranslator.default {
8
+ getTree() {
9
+ return this.toXml();
10
+ }
11
+ }
12
+ var _default = exports.default = XMLTranslator;
package/es/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default as Grammar } from "./grammar.mjs";
2
2
  export { default as parse } from "./parse/index.mjs";
3
- export { default as JSONPathQueryCST } from "./parse/ast/JSONPathQueryCST.mjs";
4
- export { default as translateEvaluator } from "./parse/evaluators/translate.mjs";
3
+ export { default as CSTTranslator } from "./parse/translators/CSTTranslator.mjs";
4
+ export { default as XMLTranslator } from "./parse/translators/XMLTranslator.mjs";
@@ -5,10 +5,6 @@ const cst = ruleName => {
5
5
  if (!(typeof data === 'object' && data !== null && !Array.isArray(data))) {
6
6
  throw new JSONPathParseError("parser's user data must be an object");
7
7
  }
8
- if (!data.stack) {
9
- data.stack = [];
10
- data.root = null;
11
- }
12
8
 
13
9
  // drop the empty nodes
14
10
  if (phraseLength === 0) return;
@@ -1,33 +1,28 @@
1
1
  import { Parser, Stats, Trace } from 'apg-lite';
2
2
  import Grammar from "../grammar.mjs";
3
- import translateEvaluator from "./evaluators/translate.mjs";
4
- import JSONPathQueryCST from "./ast/JSONPathQueryCST.mjs";
3
+ import CSTTranslator from "./translators/CSTTranslator.mjs";
5
4
  import JSONPathParseError from "../errors/JSONPathParseError.mjs";
6
5
  const grammar = new Grammar();
7
6
  const parse = (jsonPath, {
8
- ast = new JSONPathQueryCST(),
7
+ translator = new CSTTranslator(),
9
8
  stats = false,
10
- trace = false,
11
- evaluator = translateEvaluator
9
+ trace = false
12
10
  } = {}) => {
13
11
  if (typeof jsonPath !== 'string') {
14
12
  throw new TypeError('JSONPath must be a string');
15
13
  }
16
14
  try {
15
+ var _parser$ast;
17
16
  const parser = new Parser();
18
- parser.ast = ast;
17
+ if (translator) parser.ast = translator;
19
18
  if (stats) parser.stats = new Stats();
20
19
  if (trace) parser.trace = new Trace();
21
20
  const result = parser.parse(grammar, 'jsonpath-query', jsonPath);
22
- const computed = evaluator(ast, {
23
- result
24
- });
25
21
  return {
26
22
  result,
27
- ast,
23
+ tree: (_parser$ast = parser.ast) === null || _parser$ast === void 0 ? void 0 : _parser$ast.getTree(),
28
24
  stats: parser.stats,
29
- trace: parser.trace,
30
- computed
25
+ trace: parser.trace
31
26
  };
32
27
  } catch (error) {
33
28
  throw new JSONPathParseError('Unexpected error during JSONPath parsing', {
@@ -1,6 +1,6 @@
1
1
  import { Ast as AST } from 'apg-lite';
2
2
  import cstCallback from "../callbacks/cst.mjs";
3
- class JSONPathQueryCST extends AST {
3
+ class CSTTranslator extends AST {
4
4
  constructor() {
5
5
  super();
6
6
 
@@ -92,5 +92,14 @@ class JSONPathQueryCST extends AST {
92
92
  this.callbacks['left-paren'] = cstCallback('text');
93
93
  this.callbacks['right-paren'] = cstCallback('text');
94
94
  }
95
+ getTree() {
96
+ const data = {
97
+ stack: [],
98
+ root: null
99
+ };
100
+ this.translate(data);
101
+ delete data.stack;
102
+ return data;
103
+ }
95
104
  }
96
- export default JSONPathQueryCST;
105
+ export default CSTTranslator;
@@ -0,0 +1,7 @@
1
+ import CSTTranslator from "./CSTTranslator.mjs";
2
+ class XMLTranslator extends CSTTranslator {
3
+ getTree() {
4
+ return this.toXml();
5
+ }
6
+ }
7
+ export default XMLTranslator;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.2.1",
6
+ "version": "2.0.0",
7
7
  "description": "RCF 9535 implementation of JSONPath",
8
8
  "main": "./cjs/index.cjs",
9
9
  "types": "./types/index.d.ts",
package/types/index.d.ts CHANGED
@@ -4,22 +4,33 @@
4
4
  export function parse(jsonpath: string, options?: ParseOptions): ParseResult;
5
5
 
6
6
  export interface ParseOptions {
7
- readonly ast?: AST;
7
+ readonly translator?: Translator | null;
8
8
  readonly stats?: boolean;
9
9
  readonly trace?: boolean;
10
10
  }
11
11
 
12
- export interface AST {
13
- readonly translate: (parts: Record<string, CSTNode>) => Record<string, CSTNode>;
14
- readonly toXml: () => string;
12
+ export interface Translator<TTree = unknown> {
13
+ getTree(): TTree;
14
+ }
15
+ export declare class CSTTranslator implements Translator<CSTTree> {
16
+ getTree(): CSTTree;
17
+ }
18
+ export declare class XMLTranslator implements Translator<XMLTree> {
19
+ getTree(): XMLTree;
15
20
  }
16
21
 
17
- export interface ParseResult {
22
+ export interface ParseResult<TTree = unknown> {
18
23
  readonly result: {
19
24
  readonly success: boolean;
25
+ readonly state: number;
26
+ readonly stateName: string;
27
+ readonly length: number;
28
+ readonly matched: number;
29
+ readonly maxMatched: number;
30
+ readonly maxTreeDepth: number
31
+ readonly nodeHits: number;
20
32
  };
21
- readonly ast: AST;
22
- readonly computed: Record<string, CSTNode>;
33
+ readonly tree: TTree;
23
34
  readonly stats?: Stats;
24
35
  readonly trace?: Trace;
25
36
  }
@@ -32,6 +43,12 @@ export interface CSTNode {
32
43
  readonly children: CSTNode[],
33
44
  }
34
45
 
46
+ export interface CSTTree {
47
+ readonly root: CSTNode;
48
+ }
49
+
50
+ export type XMLTree = string;
51
+
35
52
  export interface Stats {
36
53
  displayStats(): string;
37
54
  displayHits(): string;
@@ -1,13 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.default = void 0;
5
- const translateEvaluator = (ast, {
6
- result
7
- }) => {
8
- if (!result.success) return null;
9
- const parts = {};
10
- ast.translate(parts);
11
- return parts;
12
- };
13
- var _default = exports.default = translateEvaluator;
@@ -1,9 +0,0 @@
1
- const translateEvaluator = (ast, {
2
- result
3
- }) => {
4
- if (!result.success) return null;
5
- const parts = {};
6
- ast.translate(parts);
7
- return parts;
8
- };
9
- export default translateEvaluator;