@jmespath-community/jmespath 1.1.5 → 1.3.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.
Files changed (64) hide show
  1. package/README.md +175 -68
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.mjs +2181 -0
  4. package/dist/cli.mjs.map +1 -0
  5. package/dist/index.cjs +2118 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +412 -0
  8. package/dist/index.d.ts +412 -0
  9. package/dist/index.esm.js +2099 -0
  10. package/dist/index.esm.js.map +1 -0
  11. package/dist/index.esm.min.js +2 -0
  12. package/dist/index.esm.min.js.map +1 -0
  13. package/dist/index.mjs +2089 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/dist/index.umd.js +2133 -0
  16. package/dist/index.umd.js.map +1 -0
  17. package/dist/index.umd.min.js +2 -0
  18. package/dist/index.umd.min.js.map +1 -0
  19. package/package.json +30 -5
  20. package/dist/jmespath.esm.js +0 -2351
  21. package/dist/jmespath.esm.min.js +0 -2
  22. package/dist/jmespath.esm.min.js.map +0 -1
  23. package/dist/jmespath.umd.js +0 -2380
  24. package/dist/jmespath.umd.min.js +0 -2
  25. package/dist/jmespath.umd.min.js.map +0 -1
  26. package/dist/lib/AST.type.js +0 -3
  27. package/dist/lib/AST.type.js.map +0 -1
  28. package/dist/lib/JSON.type.js +0 -3
  29. package/dist/lib/JSON.type.js.map +0 -1
  30. package/dist/lib/Lexer.js +0 -326
  31. package/dist/lib/Lexer.js.map +0 -1
  32. package/dist/lib/Lexer.type.js +0 -45
  33. package/dist/lib/Lexer.type.js.map +0 -1
  34. package/dist/lib/Parser.js +0 -459
  35. package/dist/lib/Parser.js.map +0 -1
  36. package/dist/lib/Parser.type.js +0 -3
  37. package/dist/lib/Parser.type.js.map +0 -1
  38. package/dist/lib/Runtime.js +0 -924
  39. package/dist/lib/Runtime.js.map +0 -1
  40. package/dist/lib/Scope.js +0 -29
  41. package/dist/lib/Scope.js.map +0 -1
  42. package/dist/lib/TreeInterpreter.js +0 -312
  43. package/dist/lib/TreeInterpreter.js.map +0 -1
  44. package/dist/lib/index.js +0 -67
  45. package/dist/lib/index.js.map +0 -1
  46. package/dist/lib/utils/index.js +0 -144
  47. package/dist/lib/utils/index.js.map +0 -1
  48. package/dist/lib/utils/strings.js +0 -92
  49. package/dist/lib/utils/strings.js.map +0 -1
  50. package/dist/lib/utils/text.js +0 -44
  51. package/dist/lib/utils/text.js.map +0 -1
  52. package/dist/types/AST.type.d.ts +0 -98
  53. package/dist/types/JSON.type.d.ts +0 -10
  54. package/dist/types/Lexer.d.ts +0 -19
  55. package/dist/types/Lexer.type.d.ts +0 -50
  56. package/dist/types/Parser.d.ts +0 -33
  57. package/dist/types/Parser.type.d.ts +0 -4
  58. package/dist/types/Runtime.d.ts +0 -87
  59. package/dist/types/Scope.d.ts +0 -8
  60. package/dist/types/TreeInterpreter.d.ts +0 -22
  61. package/dist/types/index.d.ts +0 -45
  62. package/dist/types/utils/index.d.ts +0 -16
  63. package/dist/types/utils/strings.d.ts +0 -11
  64. package/dist/types/utils/text.d.ts +0 -11
package/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  # @jmespath-community/jmespath
4
4
 
5
-
6
5
  @jmespath-community/jmespath is a **TypeScript** implementation of the [JMESPath](https://jmespath.site/) spec.
7
6
 
8
7
  JMESPath is a query language for JSON. It will take a JSON document
@@ -20,12 +19,9 @@ npm install @jmespath-community/jmespath
20
19
  ### `search(data: JSONValue, expression: string): JSONValue`
21
20
 
22
21
  ```javascript
23
- import { search } from '@jmespath-community/jmespath';
22
+ import { search } from "@jmespath-community/jmespath";
24
23
 
25
- search(
26
- {foo: {bar: {baz: [0, 1, 2, 3, 4]}}},
27
- "foo.bar.baz[2]"
28
- );
24
+ search({ foo: { bar: { baz: [0, 1, 2, 3, 4] } } }, "foo.bar.baz[2]");
29
25
 
30
26
  // OUTPUTS: 2
31
27
  ```
@@ -35,50 +31,42 @@ In the example we gave the `search` function input data of
35
31
  expression `foo.bar.baz[2]`, and the `search` function evaluated
36
32
  the expression against the input data to produce the result `2`.
37
33
 
38
- The JMESPath language can do *a lot* more than select an element
39
- from a list. Here are a few more examples:
34
+ The JMESPath language can do _a lot_ more than select an element
35
+ from a list. Here are a few more examples:
40
36
 
41
37
  ```javascript
42
- import { search } from '@jmespath-community/jmespath';
38
+ import { search } from "@jmespath-community/jmespath";
43
39
 
44
40
  /* --- EXAMPLE 1 --- */
45
41
 
46
42
  let JSON_DOCUMENT = {
47
43
  foo: {
48
44
  bar: {
49
- baz: [0, 1, 2, 3, 4]
50
- }
51
- }
45
+ baz: [0, 1, 2, 3, 4],
46
+ },
47
+ },
52
48
  };
53
49
 
54
50
  search(JSON_DOCUMENT, "foo.bar");
55
51
  // OUTPUTS: { baz: [ 0, 1, 2, 3, 4 ] }
56
52
 
57
-
58
53
  /* --- EXAMPLE 2 --- */
59
54
 
60
55
  JSON_DOCUMENT = {
61
- "foo": [
62
- {"first": "a", "last": "b"},
63
- {"first": "c", "last": "d"}
64
- ]
56
+ foo: [
57
+ { first: "a", last: "b" },
58
+ { first: "c", last: "d" },
59
+ ],
65
60
  };
66
61
 
67
- search(JSON_DOCUMENT, "foo[*].first")
62
+ search(JSON_DOCUMENT, "foo[*].first");
68
63
  // OUTPUTS: [ 'a', 'c' ]
69
64
 
70
-
71
65
  /* --- EXAMPLE 3 --- */
72
66
 
73
67
  JSON_DOCUMENT = {
74
- "foo": [
75
- {"age": 20},
76
- {"age": 25},
77
- {"age": 30},
78
- {"age": 35},
79
- {"age": 40}
80
- ]
81
- }
68
+ foo: [{ age: 20 }, { age: 25 }, { age: 30 }, { age: 35 }, { age: 40 }],
69
+ };
82
70
 
83
71
  search(JSON_DOCUMENT, "foo[?age > `30`]");
84
72
  // OUTPUTS: [ { age: 35 }, { age: 40 } ]
@@ -86,91 +74,210 @@ search(JSON_DOCUMENT, "foo[?age > `30`]");
86
74
 
87
75
  ### `compile(expression: string): ExpressionNodeTree`
88
76
 
89
- You can precompile all your expressions ready for use later on. the `compile`
77
+ You can precompile all your expressions ready for use later on. The `compile`
90
78
  function takes a JMESPath expression and returns an abstract syntax tree that
91
79
  can be used by the TreeInterpreter function
92
80
 
93
81
  ```javascript
94
- import { compile, TreeInterpreter } from '@jmespath-community/jmespath';
82
+ import { compile, TreeInterpreter } from "@jmespath-community/jmespath";
95
83
 
96
- const ast = compile('foo.bar');
84
+ const ast = compile("foo.bar");
97
85
 
98
- TreeInterpreter.search(ast, {foo: {bar: 'BAZ'}})
86
+ TreeInterpreter.search(ast, { foo: { bar: "BAZ" } });
99
87
  // RETURNS: "BAZ"
100
-
101
88
  ```
102
89
 
103
90
  ---
91
+
104
92
  ## EXTENSIONS TO ORIGINAL SPEC
105
93
 
106
- 1. ### Register you own custom functions
94
+ 1. ### Register your own custom functions
95
+
96
+ #### Enhanced Function Registry API
97
+
98
+ The library provides both backward-compatible and enhanced APIs for registering custom functions with improved developer experience, type safety, and flexible override behavior.
99
+
100
+ ##### Basic Usage (Backward Compatible)
101
+
102
+ ```javascript
103
+ import { search, registerFunction, TYPE_NUMBER } from "@jmespath-community/jmespath";
104
+
105
+ search({ foo: 60, bar: 10 }, "divide(foo, bar)");
106
+ // THROWS ERROR: Error: Unknown function: divide()
107
107
 
108
- #### `registerFunction(functionName: string, customFunction: RuntimeFunction, signature: InputSignature[]): void`
108
+ registerFunction(
109
+ "divide", // FUNCTION NAME
110
+ (resolvedArgs) => {
111
+ // CUSTOM FUNCTION
112
+ const [dividend, divisor] = resolvedArgs;
113
+ return dividend / divisor;
114
+ },
115
+ [{ types: [TYPE_NUMBER] }, { types: [TYPE_NUMBER] }], //SIGNATURE
116
+ );
109
117
 
110
- Extend the list of built in JMESpath expressions with your own functions.
118
+ search({ foo: 60, bar: 10 }, "divide(foo, bar)");
119
+ // OUTPUTS: 6
120
+ ```
111
121
 
112
- ```javascript
113
- import {search, registerFunction, TYPE_NUMBER} from '@jmespath-community/jmespath'
122
+ ##### Enhanced Registry API with Type Safety
114
123
 
124
+ ```typescript
125
+ import { register, search, TYPE_NUMBER } from "@jmespath-community/jmespath";
115
126
 
116
- search({ foo: 60, bar: 10 }, 'divide(foo, bar)')
117
- // THROWS ERROR: Error: Unknown function: divide()
127
+ // TypeScript prevents registering built-in functions at compile time
128
+ // register('sum', myFunc, signature); // TypeScript error!
118
129
 
119
- registerFunction(
120
- 'divide', // FUNCTION NAME
121
- (resolvedArgs) => { // CUSTOM FUNCTION
122
- const [dividend, divisor] = resolvedArgs;
123
- return dividend / divisor;
124
- },
125
- [{ types: [TYPE_NUMBER] }, { types: [TYPE_NUMBER] }] //SIGNATURE
126
- );
130
+ // Enhanced registration with better error handling
131
+ const result = register('multiply', ([a, b]) => a * b, [
132
+ { types: [TYPE_NUMBER] },
133
+ { types: [TYPE_NUMBER] }
134
+ ]);
127
135
 
128
- search({ foo: 60,bar: 10 }, 'divide(foo, bar)');
129
- // OUTPUTS: 6
136
+ if (result.success) {
137
+ console.log(result.message); // "Function multiply() registered successfully"
138
+ } else {
139
+ console.error(result.message); // Detailed error information
140
+ }
141
+ ```
130
142
 
131
- ```
143
+ ##### Override Existing Functions
132
144
 
133
- Optional arguments are supported by setting `{..., optional: true}` in argument signatures
145
+ ```javascript
146
+ import { registerFunction, register } from "@jmespath-community/jmespath";
134
147
 
148
+ // Option 1: Using registerFunction with options
149
+ registerFunction('myFunc', () => 'first', []);
150
+ registerFunction('myFunc', () => 'second', [], { override: true, warn: true });
151
+ // Console: "Warning: Overriding existing function: myFunc()"
135
152
 
136
- ```javascript
153
+ // Option 2: Using enhanced register API
154
+ const result = register('myFunc', () => 'third', [], { override: true });
155
+ console.log(result.message); // "Function myFunc() overridden successfully"
156
+ ```
137
157
 
138
- registerFunction(
139
- 'divide',
140
- (resolvedArgs) => {
141
- const [dividend, divisor] = resolvedArgs;
142
- return dividend / divisor ?? 1; //OPTIONAL DIVISOR THAT DEFAULTS TO 1
143
- },
144
- [{ types: [TYPE_NUMBER] }, { types: [TYPE_NUMBER], optional: true }] //SIGNATURE
145
- );
158
+ ##### Registry Management
146
159
 
147
- search({ foo: 60, bar: 10 }, 'divide(foo)');
148
- // OUTPUTS: 60
160
+ ```javascript
161
+ import {
162
+ isRegistered,
163
+ getRegisteredFunctions,
164
+ getCustomFunctions,
165
+ unregisterFunction,
166
+ clearCustomFunctions
167
+ } from "@jmespath-community/jmespath";
149
168
 
150
- ```
169
+ // Check if function exists
170
+ console.log(isRegistered('sum')); // true (built-in)
171
+ console.log(isRegistered('myFunc')); // true (if registered)
172
+
173
+ // Get all registered functions
174
+ const allFunctions = getRegisteredFunctions();
175
+ console.log(allFunctions); // ['abs', 'avg', 'ceil', ..., 'myFunc']
176
+
177
+ // Get only custom functions
178
+ const customFunctions = getCustomFunctions();
179
+ console.log(customFunctions); // ['myFunc', 'divide', ...]
180
+
181
+ // Unregister custom function (built-ins cannot be unregistered)
182
+ const removed = unregisterFunction('myFunc');
183
+ console.log(removed); // true if successful
184
+
185
+ // Clear all custom functions
186
+ clearCustomFunctions();
187
+ console.log(getCustomFunctions()); // []
188
+ ```
189
+
190
+ ##### Optional Arguments
191
+
192
+ Optional arguments are supported by setting `{..., optional: true}` in argument signatures
193
+
194
+ ```javascript
195
+ registerFunction(
196
+ "divide",
197
+ (resolvedArgs) => {
198
+ const [dividend, divisor] = resolvedArgs;
199
+ return dividend / (divisor ?? 1); //OPTIONAL DIVISOR THAT DEFAULTS TO 1
200
+ },
201
+ [{ types: [TYPE_NUMBER] }, { types: [TYPE_NUMBER], optional: true }], //SIGNATURE
202
+ );
203
+
204
+ search({ foo: 60, bar: 10 }, "divide(foo)");
205
+ // OUTPUTS: 60
206
+ ```
151
207
 
152
208
  2. ### Root value access with `$` symbol
153
209
 
154
210
  ```javascript
155
-
156
- search({foo: {bar: 999}, baz: [1, 2, 3]}, '$.baz[*].[@, $.foo.bar]')
211
+ search({ foo: { bar: 999 }, baz: [1, 2, 3] }, "$.baz[*].[@, $.foo.bar]");
157
212
 
158
213
  // OUTPUTS:
159
214
  // [ [ 1, 999 ], [ 2, 999 ], [ 3, 999 ] ]
160
215
  ```
161
216
 
162
-
163
217
  ## More Resources
164
218
 
165
219
  The example above only show a small amount of what
166
220
  a JMESPath expression can do. If you want to take a
167
- tour of the language, the *best* place to go is the
221
+ tour of the language, the _best_ place to go is the
168
222
  [JMESPath Tutorial](http://jmespath.site/main#tutorial).
169
223
 
170
224
  One of the best things about JMESPath is that it is
171
225
  implemented in many different programming languages including
172
- python, ruby, php, lua, etc. To see a complete list of libraries,
226
+ python, ruby, php, lua, etc. To see a complete list of libraries,
173
227
  check out the [JMESPath libraries page](http://jmespath.site/main#libraries).
174
228
 
175
229
  And finally, the full JMESPath specification can be found
176
230
  on the [JMESPath site](https://jmespath.site/main/#specification).
231
+
232
+ ## Experimental Features
233
+
234
+ ### Ternary Operations (`? :`)
235
+
236
+ **Supported Version:** 1.1.6
237
+
238
+ Experimental support for [ternary operations](https://github.com/jmespath-community/jmespath.spec/discussions/179) has been added, allowing for conditional logic within your JMESPath expressions. The syntax is `condition ? value_if_true : value_if_false`.
239
+
240
+ - **Condition:** The expression before the `?`. JMESPath determines truthiness based on the evaluated value:
241
+ - `true` is truthy.
242
+ - Any non-empty object, array, or string is truthy.
243
+ - Any non-zero number is truthy.
244
+ - `false`, `null`, empty objects `{}`, empty arrays `[]`, and empty strings `''` are falsy.
245
+ - **Value if true:** The expression between the `?` and `:`. This is evaluated and returned if the condition is truthy.
246
+ - **Value if false:** The expression after the `:`. This is evaluated and returned if the condition is falsy.
247
+
248
+ **Examples:**
249
+
250
+ Basic usage:
251
+
252
+ ```javascript
253
+ search({ is_active: true, user: "Alice" }, "is_active ? user : 'Guest'");
254
+ // OUTPUTS: "Alice"
255
+
256
+ search({ is_active: false, user: "Bob" }, "is_active ? user : 'Guest'");
257
+ // OUTPUTS: "Guest"
258
+ ```
259
+
260
+ Truthiness with different types:
261
+
262
+ ```javascript
263
+ search({ data: [1, 2] }, "data ? 'has_data' : 'no_data'");
264
+ // OUTPUTS: "has_data"
265
+
266
+ search({ data: [] }, "data ? 'has_data' : 'no_data'");
267
+ // OUTPUTS: "no_data"
268
+
269
+ search({ count: 5 }, "count ? 'count_present' : 'no_count'");
270
+ // OUTPUTS: "count_present"
271
+
272
+ search({ count: 0 }, "count ? 'count_present' : 'no_count'");
273
+ // OUTPUTS: "no_count"
274
+ ```
275
+
276
+ Nested Ternaries:
277
+
278
+ ```javascript
279
+ search({ a: true, b: false, val1: 10, val2: 20, val3: 30 }, "a ? (b ? val1 : val2) : val3");
280
+ // OUTPUTS: 20
281
+ ```
282
+
283
+ This feature is currently experimental and its syntax or behavior might change in future releases.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }