@safeaccess/inline 0.1.1 → 0.1.2
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/.gitattributes +1 -1
- package/CHANGELOG.md +10 -5
- package/LICENSE +1 -1
- package/README.md +56 -14
- package/dist/accessors/abstract-accessor.d.ts +22 -10
- package/dist/accessors/abstract-accessor.js +21 -8
- package/dist/accessors/abstract-integration-accessor.d.ts +22 -0
- package/dist/accessors/abstract-integration-accessor.js +23 -0
- package/dist/accessors/formats/any-accessor.d.ts +10 -8
- package/dist/accessors/formats/any-accessor.js +9 -8
- package/dist/accessors/formats/array-accessor.d.ts +2 -0
- package/dist/accessors/formats/array-accessor.js +2 -0
- package/dist/accessors/formats/env-accessor.d.ts +2 -0
- package/dist/accessors/formats/env-accessor.js +2 -0
- package/dist/accessors/formats/ini-accessor.d.ts +2 -0
- package/dist/accessors/formats/ini-accessor.js +2 -0
- package/dist/accessors/formats/json-accessor.d.ts +2 -0
- package/dist/accessors/formats/json-accessor.js +2 -0
- package/dist/accessors/formats/ndjson-accessor.d.ts +2 -0
- package/dist/accessors/formats/ndjson-accessor.js +2 -0
- package/dist/accessors/formats/object-accessor.d.ts +2 -0
- package/dist/accessors/formats/object-accessor.js +2 -0
- package/dist/accessors/formats/xml-accessor.d.ts +2 -0
- package/dist/accessors/formats/xml-accessor.js +2 -0
- package/dist/accessors/formats/yaml-accessor.d.ts +3 -1
- package/dist/accessors/formats/yaml-accessor.js +4 -2
- package/dist/cache/simple-path-cache.d.ts +51 -0
- package/dist/cache/simple-path-cache.js +72 -0
- package/dist/contracts/accessors-interface.d.ts +2 -0
- package/dist/contracts/factory-accessors-interface.d.ts +2 -0
- package/dist/contracts/filter-evaluator-interface.d.ts +28 -0
- package/dist/contracts/filter-evaluator-interface.js +1 -0
- package/dist/contracts/parse-integration-interface.d.ts +2 -0
- package/dist/contracts/parser-interface.d.ts +92 -0
- package/dist/contracts/parser-interface.js +1 -0
- package/dist/contracts/path-cache-interface.d.ts +7 -6
- package/dist/contracts/readable-accessors-interface.d.ts +11 -6
- package/dist/contracts/security-guard-interface.d.ts +2 -0
- package/dist/contracts/security-parser-interface.d.ts +2 -0
- package/dist/contracts/validatable-parser-interface.d.ts +59 -0
- package/dist/contracts/validatable-parser-interface.js +1 -0
- package/dist/contracts/writable-accessors-interface.d.ts +5 -0
- package/dist/core/accessor-factory.d.ts +124 -0
- package/dist/core/accessor-factory.js +157 -0
- package/dist/core/dot-notation-parser.d.ts +34 -5
- package/dist/core/dot-notation-parser.js +51 -10
- package/dist/core/inline-builder-accessor.d.ts +82 -0
- package/dist/core/inline-builder-accessor.js +107 -0
- package/dist/exceptions/accessor-exception.d.ts +9 -0
- package/dist/exceptions/accessor-exception.js +9 -0
- package/dist/exceptions/invalid-format-exception.d.ts +5 -0
- package/dist/exceptions/invalid-format-exception.js +5 -0
- package/dist/exceptions/parser-exception.d.ts +4 -0
- package/dist/exceptions/parser-exception.js +4 -0
- package/dist/exceptions/path-not-found-exception.d.ts +4 -0
- package/dist/exceptions/path-not-found-exception.js +4 -0
- package/dist/exceptions/readonly-violation-exception.d.ts +4 -0
- package/dist/exceptions/readonly-violation-exception.js +4 -0
- package/dist/exceptions/security-exception.d.ts +6 -0
- package/dist/exceptions/security-exception.js +6 -0
- package/dist/exceptions/unsupported-type-exception.d.ts +4 -0
- package/dist/exceptions/unsupported-type-exception.js +4 -0
- package/dist/exceptions/yaml-parse-exception.d.ts +4 -0
- package/dist/exceptions/yaml-parse-exception.js +4 -0
- package/dist/index.js +2 -1
- package/dist/inline.d.ts +22 -56
- package/dist/inline.js +39 -111
- package/dist/parser/xml-parser.js +23 -10
- package/dist/parser/yaml-parser.d.ts +54 -7
- package/dist/parser/yaml-parser.js +268 -51
- package/dist/path-query/segment-filter-parser.d.ts +142 -0
- package/dist/path-query/segment-filter-parser.js +384 -0
- package/dist/path-query/segment-parser.d.ts +98 -0
- package/dist/path-query/segment-parser.js +283 -0
- package/dist/path-query/segment-path-resolver.d.ts +149 -0
- package/dist/path-query/segment-path-resolver.js +351 -0
- package/dist/path-query/segment-type.d.ts +85 -0
- package/dist/path-query/segment-type.js +35 -0
- package/dist/security/forbidden-keys.d.ts +2 -2
- package/dist/security/forbidden-keys.js +5 -5
- package/dist/security/security-guard.d.ts +3 -1
- package/dist/security/security-guard.js +5 -2
- package/dist/security/security-parser.d.ts +10 -1
- package/dist/security/security-parser.js +10 -1
- package/dist/type-format.d.ts +2 -0
- package/dist/type-format.js +2 -0
- package/package.json +11 -3
- package/src/accessors/abstract-accessor.ts +23 -19
- package/src/accessors/abstract-integration-accessor.ts +27 -0
- package/src/accessors/formats/any-accessor.ts +11 -11
- package/src/accessors/formats/array-accessor.ts +2 -0
- package/src/accessors/formats/env-accessor.ts +2 -0
- package/src/accessors/formats/ini-accessor.ts +2 -0
- package/src/accessors/formats/json-accessor.ts +2 -0
- package/src/accessors/formats/ndjson-accessor.ts +2 -0
- package/src/accessors/formats/object-accessor.ts +2 -0
- package/src/accessors/formats/xml-accessor.ts +2 -0
- package/src/accessors/formats/yaml-accessor.ts +4 -2
- package/src/cache/simple-path-cache.ts +77 -0
- package/src/contracts/accessors-interface.ts +2 -0
- package/src/contracts/factory-accessors-interface.ts +2 -0
- package/src/contracts/filter-evaluator-interface.ts +30 -0
- package/src/contracts/parse-integration-interface.ts +2 -0
- package/src/contracts/parser-interface.ts +114 -0
- package/src/contracts/path-cache-interface.ts +8 -6
- package/src/contracts/readable-accessors-interface.ts +11 -6
- package/src/contracts/security-guard-interface.ts +2 -0
- package/src/contracts/security-parser-interface.ts +2 -0
- package/src/contracts/validatable-parser-interface.ts +64 -0
- package/src/contracts/writable-accessors-interface.ts +5 -0
- package/src/core/accessor-factory.ts +173 -0
- package/src/core/dot-notation-parser.ts +74 -11
- package/src/core/inline-builder-accessor.ts +163 -0
- package/src/exceptions/accessor-exception.ts +9 -0
- package/src/exceptions/invalid-format-exception.ts +5 -0
- package/src/exceptions/parser-exception.ts +4 -0
- package/src/exceptions/path-not-found-exception.ts +4 -0
- package/src/exceptions/readonly-violation-exception.ts +4 -0
- package/src/exceptions/security-exception.ts +6 -0
- package/src/exceptions/unsupported-type-exception.ts +4 -0
- package/src/exceptions/yaml-parse-exception.ts +4 -0
- package/src/index.ts +3 -1
- package/src/inline.ts +42 -120
- package/src/parser/xml-parser.ts +31 -10
- package/src/parser/yaml-parser.ts +310 -45
- package/src/path-query/segment-filter-parser.ts +444 -0
- package/src/path-query/segment-parser.ts +321 -0
- package/src/path-query/segment-path-resolver.ts +521 -0
- package/src/path-query/segment-type.ts +82 -0
- package/src/security/forbidden-keys.ts +5 -5
- package/src/security/security-guard.ts +7 -2
- package/src/security/security-parser.ts +18 -3
- package/src/type-format.ts +2 -0
- package/stryker.config.json +8 -10
- package/tests/accessors/abstract-accessor.test.ts +217 -0
- package/tests/accessors/abstract-integration-accessor.test.ts +37 -0
- package/tests/accessors/formats/any-accessor.test.ts +57 -0
- package/tests/accessors/formats/array-accessor.test.ts +42 -0
- package/tests/accessors/formats/env-accessor.test.ts +103 -0
- package/tests/accessors/formats/ini-accessor.test.ts +186 -0
- package/tests/accessors/{json-accessor.test.ts → formats/json-accessor.test.ts} +6 -6
- package/tests/accessors/formats/ndjson-accessor.test.ts +49 -0
- package/tests/accessors/formats/object-accessor.test.ts +172 -0
- package/tests/accessors/formats/xml-accessor.test.ts +162 -0
- package/tests/accessors/formats/yaml-accessor.test.ts +36 -0
- package/tests/cache/simple-path-cache.test.ts +168 -0
- package/tests/core/accessor-factory.test.ts +157 -0
- package/tests/core/dot-notation-parser-edge-cases.test.ts +415 -0
- package/tests/core/dot-notation-parser.test.ts +0 -288
- package/tests/core/inline-builder-accessor.test.ts +114 -0
- package/tests/exceptions/accessor-exception.test.ts +28 -0
- package/tests/exceptions/invalid-format-exception.test.ts +31 -0
- package/tests/exceptions/path-not-found-exception.test.ts +33 -0
- package/tests/exceptions/readonly-violation-exception.test.ts +35 -0
- package/tests/exceptions/security-exception.test.ts +33 -0
- package/tests/exceptions/unsupported-type-exception.test.ts +33 -0
- package/tests/exceptions/yaml-parse-exception.test.ts +38 -0
- package/tests/mocks/fake-path-cache.ts +4 -3
- package/tests/parity-from.test.ts +118 -0
- package/tests/parity.test.ts +227 -10
- package/tests/parser/xml-parser-mutations.test.ts +579 -0
- package/tests/parser/xml-parser-scanner.test.ts +332 -0
- package/tests/parser/xml-parser.test.ts +10 -334
- package/tests/parser/yaml-parser-mutations.test.ts +750 -0
- package/tests/parser/yaml-parser.test.ts +844 -18
- package/tests/path-query/segment-filter-parser-mutations.test.ts +735 -0
- package/tests/path-query/segment-filter-parser.test.ts +1091 -0
- package/tests/path-query/segment-parser-mutations.test.ts +539 -0
- package/tests/path-query/segment-parser.test.ts +606 -0
- package/tests/path-query/segment-path-resolver-mutations.test.ts +626 -0
- package/tests/path-query/segment-path-resolver.test.ts +1009 -0
- package/tests/security/security-guard-advanced.test.ts +413 -0
- package/tests/security/security-guard-forbidden-keys.test.ts +87 -0
- package/tests/security/security-guard.test.ts +3 -484
- package/tests/security/security-parser.test.ts +18 -14
- package/vitest.config.ts +3 -3
- package/benchmarks/get.bench.ts +0 -26
- package/benchmarks/parse.bench.ts +0 -41
- package/tests/accessors/accessors.test.ts +0 -1017
|
@@ -8,6 +8,8 @@ import { YamlParser } from '../../parser/yaml-parser.js';
|
|
|
8
8
|
* depending on external YAML libraries. Tags, anchors, aliases, and
|
|
9
9
|
* merge keys are blocked as unsafe constructs.
|
|
10
10
|
*
|
|
11
|
+
* @api
|
|
12
|
+
*
|
|
11
13
|
* @example
|
|
12
14
|
* const accessor = new YamlAccessor(parser).from('key: value\nnested:\n a: 1');
|
|
13
15
|
* accessor.get('nested.a'); // 1
|
|
@@ -23,7 +25,7 @@ export class YamlAccessor extends AbstractAccessor {
|
|
|
23
25
|
* @throws {SecurityException} When payload size exceeds limit.
|
|
24
26
|
*
|
|
25
27
|
* @example
|
|
26
|
-
* accessor.from('name: Alice\nage: 30');
|
|
28
|
+
* accessor.from('name: Alice\nage: 30'); // { name: 'Alice', age: 30 }
|
|
27
29
|
*/
|
|
28
30
|
from(data) {
|
|
29
31
|
if (typeof data !== 'string') {
|
|
@@ -41,6 +43,6 @@ export class YamlAccessor extends AbstractAccessor {
|
|
|
41
43
|
return {};
|
|
42
44
|
}
|
|
43
45
|
/* c8 ignore stop */
|
|
44
|
-
return new YamlParser().parse(raw);
|
|
46
|
+
return new YamlParser(this.parser.getMaxDepth()).parse(raw);
|
|
45
47
|
}
|
|
46
48
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { PathCacheInterface } from '../contracts/path-cache-interface.js';
|
|
2
|
+
import type { Segment } from '../path-query/segment-type.js';
|
|
3
|
+
/**
|
|
4
|
+
* LRU cache for parsed dot-notation path segments.
|
|
5
|
+
*
|
|
6
|
+
* Stores up to {@link maxSize} entries, evicting the least-recently-used
|
|
7
|
+
* entry when the capacity is reached. Recently accessed entries are
|
|
8
|
+
* promoted to the end of the internal map on read.
|
|
9
|
+
*
|
|
10
|
+
* @internal Consumers should type-hint against {@link PathCacheInterface};
|
|
11
|
+
* this concrete class is an implementation detail subject to change.
|
|
12
|
+
*
|
|
13
|
+
* @see PathCacheInterface
|
|
14
|
+
*/
|
|
15
|
+
export declare class SimplePathCache implements PathCacheInterface {
|
|
16
|
+
private readonly maxSize;
|
|
17
|
+
private readonly cache;
|
|
18
|
+
/**
|
|
19
|
+
* Create a cache with the given maximum capacity.
|
|
20
|
+
*
|
|
21
|
+
* @param maxSize - Maximum number of cached path entries.
|
|
22
|
+
*/
|
|
23
|
+
constructor(maxSize?: number);
|
|
24
|
+
/**
|
|
25
|
+
* Retrieve cached segments and promote to most-recently-used.
|
|
26
|
+
*
|
|
27
|
+
* @param path - Dot-notation path string.
|
|
28
|
+
* @returns Cached segments, or null on miss.
|
|
29
|
+
*/
|
|
30
|
+
get(path: string): Segment[] | null;
|
|
31
|
+
/**
|
|
32
|
+
* Store segments, evicting the oldest entry if capacity is reached.
|
|
33
|
+
*
|
|
34
|
+
* @param path - Dot-notation path string.
|
|
35
|
+
* @param segments - Parsed segment array to cache.
|
|
36
|
+
*/
|
|
37
|
+
set(path: string, segments: Segment[]): void;
|
|
38
|
+
/**
|
|
39
|
+
* Check whether a path exists in the cache.
|
|
40
|
+
*
|
|
41
|
+
* @param path - Dot-notation path string.
|
|
42
|
+
* @returns True if cached.
|
|
43
|
+
*/
|
|
44
|
+
has(path: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Clear all cached entries.
|
|
47
|
+
*
|
|
48
|
+
* @returns Same instance for fluent chaining.
|
|
49
|
+
*/
|
|
50
|
+
clear(): this;
|
|
51
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LRU cache for parsed dot-notation path segments.
|
|
3
|
+
*
|
|
4
|
+
* Stores up to {@link maxSize} entries, evicting the least-recently-used
|
|
5
|
+
* entry when the capacity is reached. Recently accessed entries are
|
|
6
|
+
* promoted to the end of the internal map on read.
|
|
7
|
+
*
|
|
8
|
+
* @internal Consumers should type-hint against {@link PathCacheInterface};
|
|
9
|
+
* this concrete class is an implementation detail subject to change.
|
|
10
|
+
*
|
|
11
|
+
* @see PathCacheInterface
|
|
12
|
+
*/
|
|
13
|
+
export class SimplePathCache {
|
|
14
|
+
maxSize;
|
|
15
|
+
cache = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Create a cache with the given maximum capacity.
|
|
18
|
+
*
|
|
19
|
+
* @param maxSize - Maximum number of cached path entries.
|
|
20
|
+
*/
|
|
21
|
+
constructor(maxSize = 1000) {
|
|
22
|
+
this.maxSize = maxSize;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Retrieve cached segments and promote to most-recently-used.
|
|
26
|
+
*
|
|
27
|
+
* @param path - Dot-notation path string.
|
|
28
|
+
* @returns Cached segments, or null on miss.
|
|
29
|
+
*/
|
|
30
|
+
get(path) {
|
|
31
|
+
if (this.cache.has(path)) {
|
|
32
|
+
const value = this.cache.get(path);
|
|
33
|
+
this.cache.delete(path);
|
|
34
|
+
this.cache.set(path, value);
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Store segments, evicting the oldest entry if capacity is reached.
|
|
41
|
+
*
|
|
42
|
+
* @param path - Dot-notation path string.
|
|
43
|
+
* @param segments - Parsed segment array to cache.
|
|
44
|
+
*/
|
|
45
|
+
set(path, segments) {
|
|
46
|
+
if (this.cache.size >= this.maxSize) {
|
|
47
|
+
const firstKey = this.cache.keys().next().value;
|
|
48
|
+
if (firstKey !== undefined) {
|
|
49
|
+
this.cache.delete(firstKey);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
this.cache.set(path, segments);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check whether a path exists in the cache.
|
|
56
|
+
*
|
|
57
|
+
* @param path - Dot-notation path string.
|
|
58
|
+
* @returns True if cached.
|
|
59
|
+
*/
|
|
60
|
+
has(path) {
|
|
61
|
+
return this.cache.has(path);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clear all cached entries.
|
|
65
|
+
*
|
|
66
|
+
* @returns Same instance for fluent chaining.
|
|
67
|
+
*/
|
|
68
|
+
clear() {
|
|
69
|
+
this.cache.clear();
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -6,6 +6,8 @@ import type { FactoryAccessorsInterface } from './factory-accessors-interface.js
|
|
|
6
6
|
*
|
|
7
7
|
* Marker interface that aggregates all accessor responsibilities into
|
|
8
8
|
* a single type, used as the base contract for AbstractAccessor.
|
|
9
|
+
*
|
|
10
|
+
* @api
|
|
9
11
|
*/
|
|
10
12
|
export interface AccessorsInterface extends ReadableAccessorsInterface, WritableAccessorsInterface, FactoryAccessorsInterface {
|
|
11
13
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FilterExpression } from '../path-query/segment-type.js';
|
|
2
|
+
/**
|
|
3
|
+
* Contract for parsing and evaluating filter predicate expressions.
|
|
4
|
+
*
|
|
5
|
+
* Handles the `[?expression]` segment syntax, converting string predicates
|
|
6
|
+
* into structured condition arrays and evaluating them against data items.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export interface FilterEvaluatorInterface {
|
|
11
|
+
/**
|
|
12
|
+
* Parse a filter expression string into a structured condition array.
|
|
13
|
+
*
|
|
14
|
+
* @param expression - Raw filter expression (e.g. "age>18 && active==true").
|
|
15
|
+
* @returns Parsed conditions and logical operators.
|
|
16
|
+
*
|
|
17
|
+
* @throws {InvalidFormatException} When the expression syntax is invalid.
|
|
18
|
+
*/
|
|
19
|
+
parse(expression: string): FilterExpression;
|
|
20
|
+
/**
|
|
21
|
+
* Evaluate a parsed expression against a single data item.
|
|
22
|
+
*
|
|
23
|
+
* @param item - Data item to test.
|
|
24
|
+
* @param expr - Parsed expression from {@link parse}.
|
|
25
|
+
* @returns True if the item satisfies the expression.
|
|
26
|
+
*/
|
|
27
|
+
evaluate(item: Record<string, unknown>, expr: FilterExpression): boolean;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Enables the {@link AnyAccessor} to accept arbitrary input by delegating
|
|
5
5
|
* format validation and parsing to a user-provided implementation.
|
|
6
6
|
*
|
|
7
|
+
* @api
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* class CsvIntegration implements ParseIntegrationInterface {
|
|
9
11
|
* assertFormat(raw: unknown): boolean { return typeof raw === 'string' && raw.includes(','); }
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core contract for dot-notation path operations on object data.
|
|
3
|
+
*
|
|
4
|
+
* Defines the fundamental CRUD operations for reading, writing, and
|
|
5
|
+
* removing values from nested objects using dot-notation path strings
|
|
6
|
+
* or pre-parsed segment arrays.
|
|
7
|
+
*
|
|
8
|
+
* @internal Not part of the public API - consumers should not implement
|
|
9
|
+
* or type-hint against this interface directly.
|
|
10
|
+
*/
|
|
11
|
+
export interface ParserInterface {
|
|
12
|
+
/**
|
|
13
|
+
* Retrieve a value at the given dot-notation path.
|
|
14
|
+
*
|
|
15
|
+
* @param data - Source data object.
|
|
16
|
+
* @param path - Dot-notation path (e.g. "user.address.city").
|
|
17
|
+
* @param defaultValue - Fallback value when the path does not exist.
|
|
18
|
+
* @returns Resolved value or the default.
|
|
19
|
+
*/
|
|
20
|
+
get(data: Record<string, unknown>, path: string, defaultValue?: unknown): unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Check whether a dot-notation path exists in the data.
|
|
23
|
+
*
|
|
24
|
+
* @param data - Source data object.
|
|
25
|
+
* @param path - Dot-notation path to check.
|
|
26
|
+
* @returns True if the path resolves to an existing value.
|
|
27
|
+
*/
|
|
28
|
+
has(data: Record<string, unknown>, path: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Set a value at the given dot-notation path.
|
|
31
|
+
*
|
|
32
|
+
* @param data - Source data object.
|
|
33
|
+
* @param path - Dot-notation path for the target key.
|
|
34
|
+
* @param value - Value to assign.
|
|
35
|
+
* @returns New object with the value set.
|
|
36
|
+
*
|
|
37
|
+
* @throws {SecurityException} When the path contains forbidden keys.
|
|
38
|
+
*/
|
|
39
|
+
set(data: Record<string, unknown>, path: string, value: unknown): Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Remove a value at the given dot-notation path.
|
|
42
|
+
*
|
|
43
|
+
* @param data - Source data object.
|
|
44
|
+
* @param path - Dot-notation path to remove.
|
|
45
|
+
* @returns New object with the key removed.
|
|
46
|
+
*
|
|
47
|
+
* @throws {SecurityException} When the path contains forbidden keys.
|
|
48
|
+
*/
|
|
49
|
+
remove(data: Record<string, unknown>, path: string): Record<string, unknown>;
|
|
50
|
+
/**
|
|
51
|
+
* Deep-merge an object into the value at the given path.
|
|
52
|
+
*
|
|
53
|
+
* @param data - Source data object.
|
|
54
|
+
* @param path - Dot-notation path to the merge target.
|
|
55
|
+
* @param value - Object to merge into the existing value.
|
|
56
|
+
* @returns New object with merged data.
|
|
57
|
+
*
|
|
58
|
+
* @throws {SecurityException} When merge depth exceeds the configured maximum.
|
|
59
|
+
* @throws {SecurityException} When keys contain forbidden values.
|
|
60
|
+
*/
|
|
61
|
+
merge(data: Record<string, unknown>, path: string, value: Record<string, unknown>): Record<string, unknown>;
|
|
62
|
+
/**
|
|
63
|
+
* Retrieve a value using pre-parsed key segments.
|
|
64
|
+
*
|
|
65
|
+
* @param data - Source data object.
|
|
66
|
+
* @param segments - Ordered list of keys to traverse.
|
|
67
|
+
* @param defaultValue - Fallback value when the path does not exist.
|
|
68
|
+
* @returns Resolved value or the default.
|
|
69
|
+
*/
|
|
70
|
+
getAt(data: Record<string, unknown>, segments: Array<string | number>, defaultValue?: unknown): unknown;
|
|
71
|
+
/**
|
|
72
|
+
* Set a value using pre-parsed key segments.
|
|
73
|
+
*
|
|
74
|
+
* @param data - Source data object.
|
|
75
|
+
* @param segments - Ordered list of keys to the target.
|
|
76
|
+
* @param value - Value to assign.
|
|
77
|
+
* @returns New object with the value set.
|
|
78
|
+
*
|
|
79
|
+
* @throws {SecurityException} When segments contain forbidden keys.
|
|
80
|
+
*/
|
|
81
|
+
setAt(data: Record<string, unknown>, segments: Array<string | number>, value: unknown): Record<string, unknown>;
|
|
82
|
+
/**
|
|
83
|
+
* Remove a value using pre-parsed key segments.
|
|
84
|
+
*
|
|
85
|
+
* @param data - Source data object.
|
|
86
|
+
* @param segments - Ordered list of keys to the target.
|
|
87
|
+
* @returns New object with the key removed.
|
|
88
|
+
*
|
|
89
|
+
* @throws {SecurityException} When segments contain forbidden keys.
|
|
90
|
+
*/
|
|
91
|
+
removeAt(data: Record<string, unknown>, segments: Array<string | number>): Record<string, unknown>;
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import type { Segment } from '../path-query/segment-type.js';
|
|
1
2
|
/**
|
|
2
3
|
* Contract for a path-segment cache.
|
|
3
4
|
*
|
|
4
5
|
* Provides O(1) lookup for previously parsed dot-notation path strings,
|
|
5
6
|
* avoiding repeated segment parsing on hot paths.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Segments are structured typed arrays with {@link SegmentType} metadata,
|
|
9
|
+
* matching the PHP implementation.
|
|
10
|
+
*
|
|
11
|
+
* @api
|
|
11
12
|
*/
|
|
12
13
|
export interface PathCacheInterface {
|
|
13
14
|
/**
|
|
@@ -16,14 +17,14 @@ export interface PathCacheInterface {
|
|
|
16
17
|
* @param path - Dot-notation path string.
|
|
17
18
|
* @returns Cached segment array, or null if not cached.
|
|
18
19
|
*/
|
|
19
|
-
get(path: string):
|
|
20
|
+
get(path: string): Segment[] | null;
|
|
20
21
|
/**
|
|
21
22
|
* Store parsed segments for a path string.
|
|
22
23
|
*
|
|
23
24
|
* @param path - Dot-notation path string.
|
|
24
25
|
* @param segments - Parsed segment array to cache.
|
|
25
26
|
*/
|
|
26
|
-
set(path: string, segments:
|
|
27
|
+
set(path: string, segments: Segment[]): void;
|
|
27
28
|
/**
|
|
28
29
|
* Check whether a path exists in the cache.
|
|
29
30
|
*
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Defines methods for retrieving, checking existence, counting,
|
|
5
5
|
* and inspecting keys within the accessor's internal data store.
|
|
6
|
+
*
|
|
7
|
+
* @api
|
|
8
|
+
*
|
|
9
|
+
* @see AbstractAccessor Base implementation.
|
|
10
|
+
* @see AccessorsInterface Composite interface extending this contract.
|
|
6
11
|
*/
|
|
7
12
|
export interface ReadableAccessorsInterface {
|
|
8
13
|
/**
|
|
@@ -63,17 +68,17 @@ export interface ReadableAccessorsInterface {
|
|
|
63
68
|
*/
|
|
64
69
|
all(): Record<string, unknown>;
|
|
65
70
|
/**
|
|
66
|
-
* Count elements at a path, or the root if undefined.
|
|
71
|
+
* Count elements at a path, or the root if null/undefined.
|
|
67
72
|
*
|
|
68
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
73
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
69
74
|
* @returns Number of elements.
|
|
70
75
|
*/
|
|
71
|
-
count(path?: string): number;
|
|
76
|
+
count(path?: string | null): number;
|
|
72
77
|
/**
|
|
73
|
-
* Retrieve array keys at a path, or root keys if undefined.
|
|
78
|
+
* Retrieve array keys at a path, or root keys if null/undefined.
|
|
74
79
|
*
|
|
75
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
80
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
76
81
|
* @returns List of keys.
|
|
77
82
|
*/
|
|
78
|
-
keys(path?: string): string[];
|
|
83
|
+
keys(path?: string | null): string[];
|
|
79
84
|
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Prevents injection attacks by rejecting prototype pollution vectors,
|
|
5
5
|
* legacy prototype manipulation methods, stream wrapper / protocol URI schemes,
|
|
6
6
|
* and Node.js globals during data access and mutation operations.
|
|
7
|
+
*
|
|
8
|
+
* @api
|
|
7
9
|
*/
|
|
8
10
|
export interface SecurityGuardInterface {
|
|
9
11
|
/**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ParserInterface } from './parser-interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extended parser contract adding security validation capabilities.
|
|
4
|
+
*
|
|
5
|
+
* Adds structural validation and payload size assertion on top of
|
|
6
|
+
* the base {@link ParserInterface} CRUD operations.
|
|
7
|
+
*
|
|
8
|
+
* @internal Not part of the public API - used only by AbstractAccessor internally.
|
|
9
|
+
*/
|
|
10
|
+
export interface ValidatableParserInterface extends ParserInterface {
|
|
11
|
+
/**
|
|
12
|
+
* Retrieve a value at the given path, throwing when not found.
|
|
13
|
+
*
|
|
14
|
+
* @param data - Source data object.
|
|
15
|
+
* @param path - Dot-notation path.
|
|
16
|
+
* @returns Resolved value.
|
|
17
|
+
*
|
|
18
|
+
* @throws {PathNotFoundException} When the path does not exist.
|
|
19
|
+
*/
|
|
20
|
+
getStrict(data: Record<string, unknown>, path: string): unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Validate data structure against security constraints.
|
|
23
|
+
*
|
|
24
|
+
* Assert key safety, maximum keys, and structural depth
|
|
25
|
+
* using configured security guards and parser options.
|
|
26
|
+
*
|
|
27
|
+
* @param data - Data to validate.
|
|
28
|
+
*
|
|
29
|
+
* @throws {SecurityException} When any constraint is violated.
|
|
30
|
+
*/
|
|
31
|
+
validate(data: Record<string, unknown>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Assert that a raw string payload does not exceed size limits.
|
|
34
|
+
*
|
|
35
|
+
* @param input - Raw input string to check.
|
|
36
|
+
*
|
|
37
|
+
* @throws {SecurityException} When the payload exceeds the configured maximum.
|
|
38
|
+
*/
|
|
39
|
+
assertPayload(input: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Return the configured maximum structural nesting depth.
|
|
42
|
+
*
|
|
43
|
+
* Used by accessors that perform their own recursive traversal
|
|
44
|
+
* (e.g. ObjectAccessor) before the post-parse validation step runs.
|
|
45
|
+
*
|
|
46
|
+
* @returns Maximum allowed structural depth.
|
|
47
|
+
*/
|
|
48
|
+
getMaxDepth(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Return the configured maximum total key count.
|
|
51
|
+
*
|
|
52
|
+
* Used by format parsers that enforce a document element-count limit before
|
|
53
|
+
* structural traversal runs. Accessor implementations that wrap XML parsers
|
|
54
|
+
* can pass this value as an upper bound to prevent document-bombing attacks.
|
|
55
|
+
*
|
|
56
|
+
* @returns Maximum allowed key count.
|
|
57
|
+
*/
|
|
58
|
+
getMaxKeys(): number;
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* All mutations return a new instance with the modification applied,
|
|
5
5
|
* preserving the original accessor instance.
|
|
6
|
+
*
|
|
7
|
+
* @api
|
|
8
|
+
*
|
|
9
|
+
* @see AccessorsInterface Composite interface extending this contract.
|
|
10
|
+
* @see AbstractAccessor Base implementation enforcing readonly guards.
|
|
6
11
|
*/
|
|
7
12
|
export interface WritableAccessorsInterface {
|
|
8
13
|
/**
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { ValidatableParserInterface } from '../contracts/validatable-parser-interface.js';
|
|
2
|
+
import type { ParseIntegrationInterface } from '../contracts/parse-integration-interface.js';
|
|
3
|
+
import { ArrayAccessor } from '../accessors/formats/array-accessor.js';
|
|
4
|
+
import { ObjectAccessor } from '../accessors/formats/object-accessor.js';
|
|
5
|
+
import { JsonAccessor } from '../accessors/formats/json-accessor.js';
|
|
6
|
+
import { XmlAccessor } from '../accessors/formats/xml-accessor.js';
|
|
7
|
+
import { YamlAccessor } from '../accessors/formats/yaml-accessor.js';
|
|
8
|
+
import { IniAccessor } from '../accessors/formats/ini-accessor.js';
|
|
9
|
+
import { EnvAccessor } from '../accessors/formats/env-accessor.js';
|
|
10
|
+
import { NdjsonAccessor } from '../accessors/formats/ndjson-accessor.js';
|
|
11
|
+
import { AnyAccessor } from '../accessors/formats/any-accessor.js';
|
|
12
|
+
/**
|
|
13
|
+
* Factory for creating typed format-specific accessors.
|
|
14
|
+
*
|
|
15
|
+
* Encapsulates the wiring between a parser and accessor construction,
|
|
16
|
+
* providing one method per supported format. Used internally by
|
|
17
|
+
* {@link Inline} to create accessors.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare class AccessorFactory {
|
|
22
|
+
private readonly parser;
|
|
23
|
+
private readonly defaultIntegration;
|
|
24
|
+
private readonly strictMode;
|
|
25
|
+
/**
|
|
26
|
+
* Initialize the factory with a parser, optional integration, and optional strict mode.
|
|
27
|
+
*
|
|
28
|
+
* @param parser - Parser for dot-notation resolution.
|
|
29
|
+
* @param defaultIntegration - Default integration for AnyAccessor.
|
|
30
|
+
* @param strictMode - Override strict mode for created accessors.
|
|
31
|
+
*/
|
|
32
|
+
constructor(parser: ValidatableParserInterface, defaultIntegration?: ParseIntegrationInterface | null, strictMode?: boolean | null);
|
|
33
|
+
/**
|
|
34
|
+
* Return the underlying parser used by this factory.
|
|
35
|
+
*
|
|
36
|
+
* @returns The parser instance.
|
|
37
|
+
*/
|
|
38
|
+
getParser(): ValidatableParserInterface;
|
|
39
|
+
/**
|
|
40
|
+
* Apply configured strict mode to a new accessor before hydration.
|
|
41
|
+
*
|
|
42
|
+
* @param accessor - Unhydrated accessor instance.
|
|
43
|
+
* @returns Same accessor with strict mode applied if configured.
|
|
44
|
+
*/
|
|
45
|
+
private applyOptions;
|
|
46
|
+
/**
|
|
47
|
+
* Create an ArrayAccessor from raw array data.
|
|
48
|
+
*
|
|
49
|
+
* @param data - Source array or object.
|
|
50
|
+
* @returns Populated ArrayAccessor.
|
|
51
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
52
|
+
*/
|
|
53
|
+
array(data: Record<string, unknown> | unknown[]): ArrayAccessor;
|
|
54
|
+
/**
|
|
55
|
+
* Create an ObjectAccessor from a source object.
|
|
56
|
+
*
|
|
57
|
+
* @param data - Source object.
|
|
58
|
+
* @returns Populated ObjectAccessor.
|
|
59
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
60
|
+
*/
|
|
61
|
+
object(data: object): ObjectAccessor;
|
|
62
|
+
/**
|
|
63
|
+
* Create a JsonAccessor from a JSON string.
|
|
64
|
+
*
|
|
65
|
+
* @param data - Raw JSON string.
|
|
66
|
+
* @returns Populated JsonAccessor.
|
|
67
|
+
* @throws {InvalidFormatException} When the JSON is malformed.
|
|
68
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
69
|
+
*/
|
|
70
|
+
json(data: string): JsonAccessor;
|
|
71
|
+
/**
|
|
72
|
+
* Create an XmlAccessor from an XML string.
|
|
73
|
+
*
|
|
74
|
+
* @param data - Raw XML string.
|
|
75
|
+
* @returns Populated XmlAccessor.
|
|
76
|
+
* @throws {InvalidFormatException} When the XML is malformed.
|
|
77
|
+
* @throws {SecurityException} When DOCTYPE is detected.
|
|
78
|
+
*/
|
|
79
|
+
xml(data: string): XmlAccessor;
|
|
80
|
+
/**
|
|
81
|
+
* Create a YamlAccessor from a YAML string.
|
|
82
|
+
*
|
|
83
|
+
* @param data - Raw YAML string.
|
|
84
|
+
* @returns Populated YamlAccessor.
|
|
85
|
+
* @throws {YamlParseException} When the YAML is malformed.
|
|
86
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
87
|
+
*/
|
|
88
|
+
yaml(data: string): YamlAccessor;
|
|
89
|
+
/**
|
|
90
|
+
* Create an IniAccessor from an INI string.
|
|
91
|
+
*
|
|
92
|
+
* @param data - Raw INI string.
|
|
93
|
+
* @returns Populated IniAccessor.
|
|
94
|
+
* @throws {InvalidFormatException} When the INI is malformed.
|
|
95
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
96
|
+
*/
|
|
97
|
+
ini(data: string): IniAccessor;
|
|
98
|
+
/**
|
|
99
|
+
* Create an EnvAccessor from a dotenv-formatted string.
|
|
100
|
+
*
|
|
101
|
+
* @param data - Raw dotenv string.
|
|
102
|
+
* @returns Populated EnvAccessor.
|
|
103
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
104
|
+
*/
|
|
105
|
+
env(data: string): EnvAccessor;
|
|
106
|
+
/**
|
|
107
|
+
* Create an NdjsonAccessor from a newline-delimited JSON string.
|
|
108
|
+
*
|
|
109
|
+
* @param data - Raw NDJSON string.
|
|
110
|
+
* @returns Populated NdjsonAccessor.
|
|
111
|
+
* @throws {InvalidFormatException} When any JSON line is malformed.
|
|
112
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
113
|
+
*/
|
|
114
|
+
ndjson(data: string): NdjsonAccessor;
|
|
115
|
+
/**
|
|
116
|
+
* Create an AnyAccessor with automatic format detection.
|
|
117
|
+
*
|
|
118
|
+
* @param data - Raw data in any supported format.
|
|
119
|
+
* @param integration - Override integration (falls back to default).
|
|
120
|
+
* @returns Populated AnyAccessor.
|
|
121
|
+
* @throws {InvalidFormatException} When no integration is available.
|
|
122
|
+
*/
|
|
123
|
+
any(data: unknown, integration?: ParseIntegrationInterface | null): AnyAccessor;
|
|
124
|
+
}
|