json-p3 2.1.1 → 2.2.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/LICENCE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 James Prior
3
+ Copyright (c) 2025 James Prior
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,10 +1,10 @@
1
1
  /*
2
- * json-p3 version 2.1.1
2
+ * json-p3 version 2.2.0
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
6
6
  *
7
- * Copyright (c) 2024 James Prior
7
+ * Copyright (c) 2025 James Prior
8
8
  *
9
9
  * Permission is hereby granted, free of charge, to any person obtaining a copy
10
10
  * of this software and associated documentation files (the "Software"), to deal
@@ -1230,6 +1230,15 @@ function mapRegexp(pattern) {
1230
1230
  }
1231
1231
  return parts.join("");
1232
1232
  }
1233
+ function fullMatch(pattern) {
1234
+ const parts = [];
1235
+ const explicitCaret = pattern.startsWith("^");
1236
+ const explicitDollar = pattern.endsWith("$");
1237
+ if (!explicitCaret && !explicitDollar) parts.push("^(?:");
1238
+ parts.push(mapRegexp(pattern));
1239
+ if (!explicitCaret && !explicitDollar) parts.push(")$");
1240
+ return parts.join("");
1241
+ }
1233
1242
 
1234
1243
  /*
1235
1244
  * iregexp-check version 0.1.1
@@ -2480,7 +2489,7 @@ class Match {
2480
2489
  return false;
2481
2490
  }
2482
2491
  try {
2483
- const re = new RegExp(this.fullMatch(pattern), "u");
2492
+ const re = new RegExp(fullMatch(pattern), "u");
2484
2493
  if (this.cacheSize > 0) this.#cache.set(pattern, re);
2485
2494
  return re.test(s);
2486
2495
  } catch (error) {
@@ -2488,15 +2497,6 @@ class Match {
2488
2497
  return false;
2489
2498
  }
2490
2499
  }
2491
- fullMatch(pattern) {
2492
- const parts = [];
2493
- const explicitCaret = pattern.startsWith("^");
2494
- const explicitDollar = pattern.endsWith("$");
2495
- if (!explicitCaret && !explicitDollar) parts.push("^(?:");
2496
- parts.push(mapRegexp(pattern));
2497
- if (!explicitCaret && !explicitDollar) parts.push(")$");
2498
- return parts.join("");
2499
- }
2500
2500
  }
2501
2501
 
2502
2502
  class Search {
@@ -3070,6 +3070,11 @@ function lexInsideFilter(l) {
3070
3070
  l.emit(TokenKind.CURRENT);
3071
3071
  return lexSegment;
3072
3072
  case "#":
3073
+ if (l.environment.strict) {
3074
+ l.backup();
3075
+ l.error(`unexpected filter selector token '${ch}'`);
3076
+ return null;
3077
+ }
3073
3078
  l.emit(TokenKind.CURRENT_KEY);
3074
3079
  return lexSegment;
3075
3080
  case ".":
@@ -4609,10 +4614,71 @@ class JSONPathEnvironment {
4609
4614
  }
4610
4615
  }
4611
4616
 
4617
+ /**
4618
+ * A function extension that returns `true` if the first argument is an object
4619
+ * value and it contains a property matching the second argument.
4620
+ */
4621
+ class Has {
4622
+ argTypes = (() => [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType])();
4623
+ returnType = (() => FunctionExpressionType.LogicalType)();
4624
+ #cache;
4625
+ constructor() {
4626
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4627
+ this.options = options;
4628
+ this.cacheSize = options.cacheSize ?? 10;
4629
+ this.throwErrors = options.throwErrors ?? false;
4630
+ this.iRegexpCheck = options.iRegexpCheck ?? true;
4631
+ this.search = options.search ?? true;
4632
+ this.#cache = new LRUCache(this.cacheSize);
4633
+ }
4634
+
4635
+ // eslint-disable-next-line sonarjs/cognitive-complexity
4636
+ call(value, pattern) {
4637
+ if (this.cacheSize > 0) {
4638
+ const re = this.#cache.get(pattern);
4639
+ if (re) {
4640
+ try {
4641
+ if (isObject(value)) {
4642
+ return Object.keys(value).some(k => !!k.match(re));
4643
+ }
4644
+ return false;
4645
+ } catch (error) {
4646
+ if (this.throwErrors) throw error;
4647
+ return false;
4648
+ }
4649
+ }
4650
+ }
4651
+ if (!isString(pattern)) {
4652
+ if (this.throwErrors) {
4653
+ throw new IRegexpError(`match() expected a string pattern, found ${pattern}`);
4654
+ }
4655
+ return false;
4656
+ }
4657
+ if (this.iRegexpCheck && !check$1(pattern)) {
4658
+ if (this.throwErrors) {
4659
+ throw new IRegexpError(`pattern ${pattern} is not a valid I-Regexp pattern`);
4660
+ }
4661
+ return false;
4662
+ }
4663
+ try {
4664
+ const re = this.search ? new RegExp(mapRegexp(pattern), "u") : new RegExp(mapRegexp(fullMatch(pattern)), "u");
4665
+ if (this.cacheSize > 0) this.#cache.set(pattern, re);
4666
+ if (isObject(value)) {
4667
+ return Object.keys(value).some(k => !!k.match(re));
4668
+ }
4669
+ return false;
4670
+ } catch (error) {
4671
+ if (this.throwErrors) throw error;
4672
+ return false;
4673
+ }
4674
+ }
4675
+ }
4676
+
4612
4677
  var index$2 = /*#__PURE__*/Object.freeze({
4613
4678
  __proto__: null,
4614
4679
  Count: Count,
4615
4680
  FunctionExpressionType: FunctionExpressionType,
4681
+ Has: Has,
4616
4682
  Length: Length,
4617
4683
  Match: Match,
4618
4684
  Search: Search,
@@ -5206,7 +5272,7 @@ var index = /*#__PURE__*/Object.freeze({
5206
5272
  apply: apply
5207
5273
  });
5208
5274
 
5209
- const version = "2.1.1";
5275
+ const version = "2.2.0";
5210
5276
 
5211
5277
  exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
5212
5278
  exports.FunctionExpressionType = FunctionExpressionType;
@@ -1,10 +1,10 @@
1
1
  /*
2
- * json-p3 version 2.1.1
2
+ * json-p3 version 2.2.0
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
6
6
  *
7
- * Copyright (c) 2024 James Prior
7
+ * Copyright (c) 2025 James Prior
8
8
  *
9
9
  * Permission is hereby granted, free of charge, to any person obtaining a copy
10
10
  * of this software and associated documentation files (the "Software"), to deal
@@ -1228,6 +1228,15 @@ function mapRegexp(pattern) {
1228
1228
  }
1229
1229
  return parts.join("");
1230
1230
  }
1231
+ function fullMatch(pattern) {
1232
+ const parts = [];
1233
+ const explicitCaret = pattern.startsWith("^");
1234
+ const explicitDollar = pattern.endsWith("$");
1235
+ if (!explicitCaret && !explicitDollar) parts.push("^(?:");
1236
+ parts.push(mapRegexp(pattern));
1237
+ if (!explicitCaret && !explicitDollar) parts.push(")$");
1238
+ return parts.join("");
1239
+ }
1231
1240
 
1232
1241
  /*
1233
1242
  * iregexp-check version 0.1.1
@@ -2478,7 +2487,7 @@ class Match {
2478
2487
  return false;
2479
2488
  }
2480
2489
  try {
2481
- const re = new RegExp(this.fullMatch(pattern), "u");
2490
+ const re = new RegExp(fullMatch(pattern), "u");
2482
2491
  if (this.cacheSize > 0) this.#cache.set(pattern, re);
2483
2492
  return re.test(s);
2484
2493
  } catch (error) {
@@ -2486,15 +2495,6 @@ class Match {
2486
2495
  return false;
2487
2496
  }
2488
2497
  }
2489
- fullMatch(pattern) {
2490
- const parts = [];
2491
- const explicitCaret = pattern.startsWith("^");
2492
- const explicitDollar = pattern.endsWith("$");
2493
- if (!explicitCaret && !explicitDollar) parts.push("^(?:");
2494
- parts.push(mapRegexp(pattern));
2495
- if (!explicitCaret && !explicitDollar) parts.push(")$");
2496
- return parts.join("");
2497
- }
2498
2498
  }
2499
2499
 
2500
2500
  class Search {
@@ -3068,6 +3068,11 @@ function lexInsideFilter(l) {
3068
3068
  l.emit(TokenKind.CURRENT);
3069
3069
  return lexSegment;
3070
3070
  case "#":
3071
+ if (l.environment.strict) {
3072
+ l.backup();
3073
+ l.error(`unexpected filter selector token '${ch}'`);
3074
+ return null;
3075
+ }
3071
3076
  l.emit(TokenKind.CURRENT_KEY);
3072
3077
  return lexSegment;
3073
3078
  case ".":
@@ -4607,10 +4612,71 @@ class JSONPathEnvironment {
4607
4612
  }
4608
4613
  }
4609
4614
 
4615
+ /**
4616
+ * A function extension that returns `true` if the first argument is an object
4617
+ * value and it contains a property matching the second argument.
4618
+ */
4619
+ class Has {
4620
+ argTypes = (() => [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType])();
4621
+ returnType = (() => FunctionExpressionType.LogicalType)();
4622
+ #cache;
4623
+ constructor() {
4624
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4625
+ this.options = options;
4626
+ this.cacheSize = options.cacheSize ?? 10;
4627
+ this.throwErrors = options.throwErrors ?? false;
4628
+ this.iRegexpCheck = options.iRegexpCheck ?? true;
4629
+ this.search = options.search ?? true;
4630
+ this.#cache = new LRUCache(this.cacheSize);
4631
+ }
4632
+
4633
+ // eslint-disable-next-line sonarjs/cognitive-complexity
4634
+ call(value, pattern) {
4635
+ if (this.cacheSize > 0) {
4636
+ const re = this.#cache.get(pattern);
4637
+ if (re) {
4638
+ try {
4639
+ if (isObject(value)) {
4640
+ return Object.keys(value).some(k => !!k.match(re));
4641
+ }
4642
+ return false;
4643
+ } catch (error) {
4644
+ if (this.throwErrors) throw error;
4645
+ return false;
4646
+ }
4647
+ }
4648
+ }
4649
+ if (!isString(pattern)) {
4650
+ if (this.throwErrors) {
4651
+ throw new IRegexpError(`match() expected a string pattern, found ${pattern}`);
4652
+ }
4653
+ return false;
4654
+ }
4655
+ if (this.iRegexpCheck && !check$1(pattern)) {
4656
+ if (this.throwErrors) {
4657
+ throw new IRegexpError(`pattern ${pattern} is not a valid I-Regexp pattern`);
4658
+ }
4659
+ return false;
4660
+ }
4661
+ try {
4662
+ const re = this.search ? new RegExp(mapRegexp(pattern), "u") : new RegExp(mapRegexp(fullMatch(pattern)), "u");
4663
+ if (this.cacheSize > 0) this.#cache.set(pattern, re);
4664
+ if (isObject(value)) {
4665
+ return Object.keys(value).some(k => !!k.match(re));
4666
+ }
4667
+ return false;
4668
+ } catch (error) {
4669
+ if (this.throwErrors) throw error;
4670
+ return false;
4671
+ }
4672
+ }
4673
+ }
4674
+
4610
4675
  var index$2 = /*#__PURE__*/Object.freeze({
4611
4676
  __proto__: null,
4612
4677
  Count: Count,
4613
4678
  FunctionExpressionType: FunctionExpressionType,
4679
+ Has: Has,
4614
4680
  Length: Length,
4615
4681
  Match: Match,
4616
4682
  Search: Search,
@@ -5204,6 +5270,6 @@ var index = /*#__PURE__*/Object.freeze({
5204
5270
  apply: apply
5205
5271
  });
5206
5272
 
5207
- const version = "2.1.1";
5273
+ const version = "2.2.0";
5208
5274
 
5209
5275
  export { DEFAULT_ENVIRONMENT, FunctionExpressionType, JSONPatch, JSONPatchError, JSONPatchTestFailure, JSONPathEnvironment, JSONPathError, JSONPathIndexError, JSONPathLexerError, JSONPathNode, JSONPathNodeList, JSONPathQuery, JSONPathRecursionLimitError, JSONPathSyntaxError, JSONPathTypeError, JSONPointer, Nothing, RelativeJSONPointer, Token, TokenKind, UNDEFINED, apply, compile, index as jsonpatch, index$1 as jsonpath, index$3 as jsonpointer, lazyQuery, query, resolve, version };
@@ -1,10 +1,10 @@
1
1
  /*
2
- * json-p3 version 2.1.1
2
+ * json-p3 version 2.2.0
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
6
6
  *
7
- * Copyright (c) 2024 James Prior
7
+ * Copyright (c) 2025 James Prior
8
8
  *
9
9
  * Permission is hereby granted, free of charge, to any person obtaining a copy
10
10
  * of this software and associated documentation files (the "Software"), to deal
@@ -1231,6 +1231,15 @@ var json_p3 = (function (exports) {
1231
1231
  }
1232
1232
  return parts.join("");
1233
1233
  }
1234
+ function fullMatch(pattern) {
1235
+ const parts = [];
1236
+ const explicitCaret = pattern.startsWith("^");
1237
+ const explicitDollar = pattern.endsWith("$");
1238
+ if (!explicitCaret && !explicitDollar) parts.push("^(?:");
1239
+ parts.push(mapRegexp(pattern));
1240
+ if (!explicitCaret && !explicitDollar) parts.push(")$");
1241
+ return parts.join("");
1242
+ }
1234
1243
 
1235
1244
  /*
1236
1245
  * iregexp-check version 0.1.1
@@ -2481,7 +2490,7 @@ var json_p3 = (function (exports) {
2481
2490
  return false;
2482
2491
  }
2483
2492
  try {
2484
- const re = new RegExp(this.fullMatch(pattern), "u");
2493
+ const re = new RegExp(fullMatch(pattern), "u");
2485
2494
  if (this.cacheSize > 0) this.#cache.set(pattern, re);
2486
2495
  return re.test(s);
2487
2496
  } catch (error) {
@@ -2489,15 +2498,6 @@ var json_p3 = (function (exports) {
2489
2498
  return false;
2490
2499
  }
2491
2500
  }
2492
- fullMatch(pattern) {
2493
- const parts = [];
2494
- const explicitCaret = pattern.startsWith("^");
2495
- const explicitDollar = pattern.endsWith("$");
2496
- if (!explicitCaret && !explicitDollar) parts.push("^(?:");
2497
- parts.push(mapRegexp(pattern));
2498
- if (!explicitCaret && !explicitDollar) parts.push(")$");
2499
- return parts.join("");
2500
- }
2501
2501
  }
2502
2502
 
2503
2503
  class Search {
@@ -3071,6 +3071,11 @@ var json_p3 = (function (exports) {
3071
3071
  l.emit(TokenKind.CURRENT);
3072
3072
  return lexSegment;
3073
3073
  case "#":
3074
+ if (l.environment.strict) {
3075
+ l.backup();
3076
+ l.error(`unexpected filter selector token '${ch}'`);
3077
+ return null;
3078
+ }
3074
3079
  l.emit(TokenKind.CURRENT_KEY);
3075
3080
  return lexSegment;
3076
3081
  case ".":
@@ -4610,10 +4615,71 @@ var json_p3 = (function (exports) {
4610
4615
  }
4611
4616
  }
4612
4617
 
4618
+ /**
4619
+ * A function extension that returns `true` if the first argument is an object
4620
+ * value and it contains a property matching the second argument.
4621
+ */
4622
+ class Has {
4623
+ argTypes = (() => [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType])();
4624
+ returnType = (() => FunctionExpressionType.LogicalType)();
4625
+ #cache;
4626
+ constructor() {
4627
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4628
+ this.options = options;
4629
+ this.cacheSize = options.cacheSize ?? 10;
4630
+ this.throwErrors = options.throwErrors ?? false;
4631
+ this.iRegexpCheck = options.iRegexpCheck ?? true;
4632
+ this.search = options.search ?? true;
4633
+ this.#cache = new LRUCache(this.cacheSize);
4634
+ }
4635
+
4636
+ // eslint-disable-next-line sonarjs/cognitive-complexity
4637
+ call(value, pattern) {
4638
+ if (this.cacheSize > 0) {
4639
+ const re = this.#cache.get(pattern);
4640
+ if (re) {
4641
+ try {
4642
+ if (isObject(value)) {
4643
+ return Object.keys(value).some(k => !!k.match(re));
4644
+ }
4645
+ return false;
4646
+ } catch (error) {
4647
+ if (this.throwErrors) throw error;
4648
+ return false;
4649
+ }
4650
+ }
4651
+ }
4652
+ if (!isString(pattern)) {
4653
+ if (this.throwErrors) {
4654
+ throw new IRegexpError(`match() expected a string pattern, found ${pattern}`);
4655
+ }
4656
+ return false;
4657
+ }
4658
+ if (this.iRegexpCheck && !check$1(pattern)) {
4659
+ if (this.throwErrors) {
4660
+ throw new IRegexpError(`pattern ${pattern} is not a valid I-Regexp pattern`);
4661
+ }
4662
+ return false;
4663
+ }
4664
+ try {
4665
+ const re = this.search ? new RegExp(mapRegexp(pattern), "u") : new RegExp(mapRegexp(fullMatch(pattern)), "u");
4666
+ if (this.cacheSize > 0) this.#cache.set(pattern, re);
4667
+ if (isObject(value)) {
4668
+ return Object.keys(value).some(k => !!k.match(re));
4669
+ }
4670
+ return false;
4671
+ } catch (error) {
4672
+ if (this.throwErrors) throw error;
4673
+ return false;
4674
+ }
4675
+ }
4676
+ }
4677
+
4613
4678
  var index$2 = /*#__PURE__*/Object.freeze({
4614
4679
  __proto__: null,
4615
4680
  Count: Count,
4616
4681
  FunctionExpressionType: FunctionExpressionType,
4682
+ Has: Has,
4617
4683
  Length: Length,
4618
4684
  Match: Match,
4619
4685
  Search: Search,
@@ -5207,7 +5273,7 @@ var json_p3 = (function (exports) {
5207
5273
  apply: apply
5208
5274
  });
5209
5275
 
5210
- const version = "2.1.1";
5276
+ const version = "2.2.0";
5211
5277
 
5212
5278
  exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
5213
5279
  exports.FunctionExpressionType = FunctionExpressionType;