@safeaccess/inline 0.1.1 → 0.1.3
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 +23 -5
- package/LICENSE +1 -1
- package/README.md +79 -21
- package/dist/accessors/abstract-accessor.d.ts +24 -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 +26 -56
- package/dist/inline.js +43 -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 +4 -1
- package/dist/security/security-guard.js +7 -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 +25 -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 +46 -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 +10 -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 +379 -0
- package/tests/parser/xml-parser.test.ts +17 -330
- 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 +8 -479
- 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
package/.gitattributes
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Distribution archive ignore
|
|
1
|
+
# Distribution archive ignore - files excluded from npm/archive downloads
|
|
2
2
|
# Note: npm uses the `files` field in package.json for publish filtering.
|
|
3
3
|
# These export-ignore rules apply to git archive and the split repo.
|
|
4
4
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,17 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the `@safeaccess/inline` JavaScript/TypeScript package are documented in this file.
|
|
4
4
|
|
|
5
|
-
## [0.1.
|
|
5
|
+
## [0.1.3](https://github.com/felipesauer/safeaccess-inline/compare/js-v0.1.2...js-v0.1.3) (2026-04-09)
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
###
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **js:** expose readonly extraForbiddenKeys on SecurityGuard for PHP parity ([2b428f6](https://github.com/felipesauer/safeaccess-inline/commit/2b428f6a1fef3607cb968ff18b52d8281158cc92))
|
|
11
|
+
* **php:** correct array<string,mixed> type annotations and NdjsonAccessor integer key coercion ([7849f89](https://github.com/felipesauer/safeaccess-inline/commit/7849f89365bd5970738105ed3be9d2b58a15cd93))
|
|
12
|
+
|
|
13
|
+
## [0.1.2](https://github.com/felipesauer/safeaccess-inline/compare/js-v0.1.1...js-v0.1.2) (2026-04-08)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
9
16
|
|
|
10
|
-
|
|
17
|
+
- **js:** fix logo image URL in README ([16f4fc5](https://github.com/felipesauer/safeaccess-inline/commit/16f4fc5d69fa7ce86e3017bbbfc9f393925a5c37))
|
|
18
|
+
|
|
19
|
+
### Internal Changes
|
|
20
|
+
|
|
21
|
+
- **js:** expose `readonly extraForbiddenKeys` on `SecurityGuard` for parity with PHP (`public readonly array $extraForbiddenKeys`)
|
|
22
|
+
- **js:** extract `ValidatableParserInterface` from `DotNotationParser` — `AbstractAccessor` now types its parser dependency against this contract instead of the concrete class
|
|
23
|
+
- **js:** `SecurityGuard.sanitize()` handles nested arrays via a dedicated `sanitizeArray()` private method, matching the PHP `sanitizeRecursive` pattern
|
|
24
|
+
|
|
25
|
+
## [0.1.1](https://github.com/felipesauer/safeaccess-inline/compare/js-v0.1.0...js-v0.1.1) (2026-04-07)
|
|
26
|
+
|
|
27
|
+
### Features
|
|
11
28
|
|
|
29
|
+
- **js:** bootstrap release tracking for rebranded package ([5fc07d7](https://github.com/felipesauer/safeaccess-inline/commit/5fc07d7126870d72145bbfc80609370c9d1509c7))
|
|
12
30
|
|
|
13
31
|
### Bug Fixes
|
|
14
32
|
|
|
15
|
-
|
|
33
|
+
- **js:** add repository field for npm provenance validation ([b34cdef](https://github.com/felipesauer/safeaccess-inline/commit/b34cdeff01e7e7566921f04b11f33fbd391aa8d2))
|
|
16
34
|
|
|
17
35
|
## 0.1.0 (2026-04-07)
|
|
18
36
|
|
|
@@ -20,7 +38,7 @@ All notable changes to the `@safeaccess/inline` JavaScript/TypeScript package ar
|
|
|
20
38
|
|
|
21
39
|
- **ci:** achieve 100% branch coverage on Vitest 4.x and fix docs-ci workflow ([#14](https://github.com/felipesauer/safeaccess-inline/issues/14)) ([11daf5a](https://github.com/felipesauer/safeaccess-inline/commit/11daf5aaa1ff1b901c8297921533485f1584a330))
|
|
22
40
|
|
|
23
|
-
## [0.1.0]
|
|
41
|
+
## [0.1.0] - 2026-04-06
|
|
24
42
|
|
|
25
43
|
### Features
|
|
26
44
|
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="https://raw.githubusercontent.com/felipesauer/safeaccess-inline/main/.github/assets/logo.svg" width="80" alt="safeaccess-inline logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">Safe Access Inline
|
|
5
|
+
<h1 align="center">Safe Access Inline - TypeScript</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/@safeaccess/inline"><img src="https://img.shields.io/npm/v/@safeaccess/inline?label=npm" alt="npm"></a>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
Safe nested data access with dot notation for JavaScript and TypeScript. Navigate deeply nested objects, JSON, YAML, XML, INI, ENV, and NDJSON structures
|
|
14
|
+
Safe nested data access with dot notation for JavaScript and TypeScript. Navigate deeply nested arrays, objects, JSON, YAML, XML, INI, ENV, and NDJSON structures - with built-in security validation, immutable writes, and a fluent builder API.
|
|
15
15
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
@@ -33,7 +33,7 @@ accessor.get('user.email', 'N/A'); // 'N/A' (default when missing)
|
|
|
33
33
|
accessor.has('user.age'); // true
|
|
34
34
|
accessor.getOrFail('user.name'); // 'Alice' (throws if missing)
|
|
35
35
|
|
|
36
|
-
// Immutable writes
|
|
36
|
+
// Immutable writes - original is never modified
|
|
37
37
|
const updated = accessor.set('user.email', 'alice@example.com');
|
|
38
38
|
updated.get('user.email'); // 'alice@example.com'
|
|
39
39
|
accessor.has('user.email'); // false (original unchanged)
|
|
@@ -41,12 +41,14 @@ accessor.has('user.email'); // false (original unchanged)
|
|
|
41
41
|
|
|
42
42
|
## Dot Notation Syntax
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
### Basic Syntax
|
|
45
45
|
|
|
46
|
-
| Syntax
|
|
47
|
-
|
|
|
48
|
-
| `key.key`
|
|
49
|
-
| `key.0.key`
|
|
46
|
+
| Syntax | Example | Description |
|
|
47
|
+
| ----------------- | ------------------ | ------------------------------- |
|
|
48
|
+
| `key.key` | `user.name` | Nested key access |
|
|
49
|
+
| `key.0.key` | `users.0.name` | Numeric key (array index) |
|
|
50
|
+
| `key\.with\.dots` | `config\.db\.host` | Escaped dots in key names |
|
|
51
|
+
| `$` or `$.path` | `$.user.name` | Optional root prefix (stripped) |
|
|
50
52
|
|
|
51
53
|
```typescript
|
|
52
54
|
const data = Inline.fromJson('{"users": [{"name": "Alice"}, {"name": "Bob"}]}');
|
|
@@ -54,7 +56,46 @@ data.get('users.0.name'); // 'Alice'
|
|
|
54
56
|
data.get('users.1.name'); // 'Bob'
|
|
55
57
|
```
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
### Advanced PathQuery
|
|
60
|
+
|
|
61
|
+
| Syntax | Example | Description |
|
|
62
|
+
| --------------- | ------------------- | ----------------------------------------- |
|
|
63
|
+
| `[0]` | `users[0]` | Bracket index access |
|
|
64
|
+
| `*` or `[*]` | `users.*` | Wildcard - expand all children |
|
|
65
|
+
| `..key` | `..name` | Recursive descent - find key at any depth |
|
|
66
|
+
| `..['a','b']` | `..['name','age']` | Multi-key recursive descent |
|
|
67
|
+
| `[0,1,2]` | `users[0,1,2]` | Multi-index selection |
|
|
68
|
+
| `['a','b']` | `['name','age']` | Multi-key selection |
|
|
69
|
+
| `[0:5]` | `items[0:5]` | Slice - indices 0 through 4 |
|
|
70
|
+
| `[::2]` | `items[::2]` | Slice with step |
|
|
71
|
+
| `[::-1]` | `items[::-1]` | Reverse slice |
|
|
72
|
+
| `[?expr]` | `users[?age>18]` | Filter predicate expression |
|
|
73
|
+
| `.{fields}` | `.{name, age}` | Projection - select fields |
|
|
74
|
+
| `.{alias: src}` | `.{fullName: name}` | Aliased projection |
|
|
75
|
+
|
|
76
|
+
### Filter Expressions
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const data = Inline.fromJson(`[
|
|
80
|
+
{"name": "Alice", "age": 25, "role": "admin"},
|
|
81
|
+
{"name": "Bob", "age": 17, "role": "user"},
|
|
82
|
+
{"name": "Carol", "age": 30, "role": "admin"}
|
|
83
|
+
]`);
|
|
84
|
+
|
|
85
|
+
// Comparison: ==, !=, >, <, >=, <=
|
|
86
|
+
data.get('[?age>18]'); // Alice and Carol
|
|
87
|
+
|
|
88
|
+
// Logical: && and ||
|
|
89
|
+
data.get('[?age>18 && role=="admin"]'); // Alice and Carol
|
|
90
|
+
|
|
91
|
+
// Built-in functions: starts_with, contains, values
|
|
92
|
+
data.get('[?starts_with(@.name, "A")]'); // Alice
|
|
93
|
+
data.get('[?contains(@.name, "ob")]'); // Bob
|
|
94
|
+
|
|
95
|
+
// Arithmetic in predicates: +, -, *, /
|
|
96
|
+
const orders = Inline.fromJson('[{"price": 10, "qty": 5}, {"price": 3, "qty": 2}]');
|
|
97
|
+
orders.get('[?@.price * @.qty > 20]'); // first order only
|
|
98
|
+
```
|
|
58
99
|
|
|
59
100
|
## Supported Formats
|
|
60
101
|
|
|
@@ -110,7 +151,7 @@ accessor.get('database.host'); // 'localhost'
|
|
|
110
151
|
<summary><strong>ENV (dotenv)</strong></summary>
|
|
111
152
|
|
|
112
153
|
```typescript
|
|
113
|
-
const accessor = Inline.fromEnv('APP_NAME=MyApp\nDB_HOST=localhost');
|
|
154
|
+
const accessor = Inline.fromEnv('APP_NAME=MyApp\nAPP_DEBUG=true\nDB_HOST=localhost');
|
|
114
155
|
accessor.get('DB_HOST'); // 'localhost'
|
|
115
156
|
```
|
|
116
157
|
|
|
@@ -140,6 +181,20 @@ objAccessor.get('name'); // 'Alice'
|
|
|
140
181
|
|
|
141
182
|
</details>
|
|
142
183
|
|
|
184
|
+
<details>
|
|
185
|
+
<summary><strong>Any (custom format via integration)</strong></summary>
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { Inline } from '@safeaccess/inline';
|
|
189
|
+
import type { ParseIntegrationInterface } from '@safeaccess/inline';
|
|
190
|
+
|
|
191
|
+
// Requires implementing ParseIntegrationInterface
|
|
192
|
+
const accessor = Inline.withParserIntegration(new MyCsvIntegration()).fromAny(csvString);
|
|
193
|
+
accessor.get('0.column_name');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
</details>
|
|
197
|
+
|
|
143
198
|
<details>
|
|
144
199
|
<summary><strong>Dynamic (by TypeFormat enum)</strong></summary>
|
|
145
200
|
|
|
@@ -173,13 +228,11 @@ accessor.getMany({
|
|
|
173
228
|
}); // { 'a.b': 1, 'a.x': 'fallback' }
|
|
174
229
|
accessor.getRaw(); // original JSON string
|
|
175
230
|
|
|
176
|
-
// Write (immutable
|
|
177
|
-
const updated = accessor.set('a.d', 3);
|
|
178
|
-
|
|
179
|
-
const merged = cleaned.merge('a', { e: 4 });
|
|
180
|
-
const full = merged.mergeAll({ f: 5 });
|
|
231
|
+
// Write (immutable - every write returns a new instance)
|
|
232
|
+
const updated = accessor.set('a.d', 3).remove('a.c').merge('a', { e: 4 }).mergeAll({ f: 5 });
|
|
233
|
+
updated.all(); // { a: { b: 1, d: 3, e: 4 }, f: 5 }
|
|
181
234
|
|
|
182
|
-
// Readonly mode
|
|
235
|
+
// Readonly mode - block all writes
|
|
183
236
|
const readonly = accessor.readonly();
|
|
184
237
|
readonly.get('a.b'); // 1 (reads work)
|
|
185
238
|
readonly.set('a.b', 99); // throws ReadonlyViolationException
|
|
@@ -204,7 +257,7 @@ const accessor = Inline.withSecurityGuard(new SecurityGuard(512, ['secret']))
|
|
|
204
257
|
| ------------------------------------ | ------------------------------------------------ |
|
|
205
258
|
| `withSecurityGuard(guard)` | Custom forbidden-key rules and depth limits |
|
|
206
259
|
| `withSecurityParser(parser)` | Custom payload size and structural limits |
|
|
207
|
-
| `withPathCache(cache)` |
|
|
260
|
+
| `withPathCache(cache)` | Path segment cache for repeated lookups |
|
|
208
261
|
| `withParserIntegration(integration)` | Custom format parser for `fromAny()` |
|
|
209
262
|
| `withStrictMode(false)` | Disable security validation (trusted input only) |
|
|
210
263
|
|
|
@@ -243,7 +296,7 @@ const accessor = Inline.withSecurityGuard(guard).fromJson(data);
|
|
|
243
296
|
|
|
244
297
|
| Format | Protection |
|
|
245
298
|
| ------ | ------------------------------------------------ |
|
|
246
|
-
| XML | Rejects `<!DOCTYPE`
|
|
299
|
+
| XML | Rejects `<!DOCTYPE` - prevents XXE attacks |
|
|
247
300
|
| YAML | Blocks unsafe tags, anchors, aliases, merge keys |
|
|
248
301
|
| All | Forbidden key validation on every parsed key |
|
|
249
302
|
|
|
@@ -291,7 +344,7 @@ try {
|
|
|
291
344
|
|
|
292
345
|
| Exception | Extends | When |
|
|
293
346
|
| ---------------------------- | ------------------------ | ----------------------------------------- |
|
|
294
|
-
| `AccessorException` | `Error` | Root
|
|
347
|
+
| `AccessorException` | `Error` | Root - catch-all |
|
|
295
348
|
| `SecurityException` | `AccessorException` | Forbidden key, payload, structural limits |
|
|
296
349
|
| `InvalidFormatException` | `AccessorException` | Malformed JSON, XML, INI, NDJSON |
|
|
297
350
|
| `YamlParseException` | `InvalidFormatException` | Unsafe or malformed YAML |
|
|
@@ -315,6 +368,7 @@ const accessor = Inline.withStrictMode(false).fromJson(trustedPayload);
|
|
|
315
368
|
|
|
316
369
|
```typescript
|
|
317
370
|
// Implement PathCacheInterface for repeated lookups
|
|
371
|
+
const cacheMap = new Map();
|
|
318
372
|
const cache: PathCacheInterface = {
|
|
319
373
|
get: (path) => cacheMap.get(path) ?? null,
|
|
320
374
|
set: (path, segments) => {
|
|
@@ -349,7 +403,7 @@ const accessor = Inline.withParserIntegration(csvIntegration).fromAny(csvString)
|
|
|
349
403
|
|
|
350
404
|
## API Reference
|
|
351
405
|
|
|
352
|
-
###
|
|
406
|
+
### `Inline` Facade
|
|
353
407
|
|
|
354
408
|
#### Static Factory Methods
|
|
355
409
|
|
|
@@ -400,6 +454,10 @@ const accessor = Inline.withParserIntegration(csvIntegration).fromAny(csvString)
|
|
|
400
454
|
| `readonly(flag?)` | Block all writes |
|
|
401
455
|
| `strict(flag?)` | Toggle security validation |
|
|
402
456
|
|
|
457
|
+
#### TypeFormat Enum
|
|
458
|
+
|
|
459
|
+
`Array` · `Object` · `Json` · `Xml` · `Yaml` · `Ini` · `Env` · `Ndjson` · `Any`
|
|
460
|
+
|
|
403
461
|
## Exports
|
|
404
462
|
|
|
405
463
|
The package uses **named exports only** (no default exports). All public types are available from the main entry point:
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import type { AccessorsInterface } from '../contracts/accessors-interface.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { ValidatableParserInterface } from '../contracts/validatable-parser-interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base accessor providing read, write, and lifecycle operations.
|
|
5
|
+
*
|
|
6
|
+
* Implements all AccessorsInterface methods with immutable copy
|
|
7
|
+
* semantics for writes, optional readonly enforcement, and strict mode
|
|
8
|
+
* for security validation on data ingestion.
|
|
9
|
+
*
|
|
10
|
+
* Subclasses must implement `parse()` to convert raw input into
|
|
11
|
+
* a normalized plain object.
|
|
12
|
+
*
|
|
13
|
+
* @api
|
|
14
|
+
*/
|
|
3
15
|
export declare abstract class AbstractAccessor implements AccessorsInterface {
|
|
4
|
-
protected readonly parser:
|
|
16
|
+
protected readonly parser: ValidatableParserInterface;
|
|
5
17
|
/** @internal Mutable state grouped to allow O(1) shallow clone in mutations. */
|
|
6
18
|
private _state;
|
|
7
19
|
/**
|
|
8
20
|
* @param parser - Dot-notation parser for path operations.
|
|
9
21
|
*/
|
|
10
|
-
constructor(parser:
|
|
22
|
+
constructor(parser: ValidatableParserInterface);
|
|
11
23
|
/**
|
|
12
24
|
* Convert raw input data into a normalized plain object.
|
|
13
25
|
*
|
|
@@ -33,6 +45,8 @@ export declare abstract class AbstractAccessor implements AccessorsInterface {
|
|
|
33
45
|
*
|
|
34
46
|
* @param data - Raw input in the format expected by the accessor.
|
|
35
47
|
* @returns Populated accessor instance.
|
|
48
|
+
* @throws {InvalidFormatException} When the raw input cannot be parsed.
|
|
49
|
+
* @throws {SecurityException} When payload exceeds size limit, data contains forbidden keys, or violates structural limits.
|
|
36
50
|
*/
|
|
37
51
|
abstract from(data: unknown): this;
|
|
38
52
|
/**
|
|
@@ -59,7 +73,7 @@ export declare abstract class AbstractAccessor implements AccessorsInterface {
|
|
|
59
73
|
* Only use with fully trusted, application-controlled input.
|
|
60
74
|
*
|
|
61
75
|
* @example
|
|
62
|
-
* // Trust the input
|
|
76
|
+
* // Trust the input - skip all security checks
|
|
63
77
|
* const accessor = new JsonAccessor(parser).strict(false).from(trustedPayload);
|
|
64
78
|
*/
|
|
65
79
|
strict(strict?: boolean): this;
|
|
@@ -159,19 +173,19 @@ export declare abstract class AbstractAccessor implements AccessorsInterface {
|
|
|
159
173
|
*/
|
|
160
174
|
all(): Record<string, unknown>;
|
|
161
175
|
/**
|
|
162
|
-
* Count elements at a path, or the root if undefined.
|
|
176
|
+
* Count elements at a path, or the root if null/undefined.
|
|
163
177
|
*
|
|
164
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
178
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
165
179
|
* @returns Number of elements.
|
|
166
180
|
*/
|
|
167
|
-
count(path?: string): number;
|
|
181
|
+
count(path?: string | null): number;
|
|
168
182
|
/**
|
|
169
|
-
* Retrieve array keys at a path, or root keys if undefined.
|
|
183
|
+
* Retrieve array keys at a path, or root keys if null/undefined.
|
|
170
184
|
*
|
|
171
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
185
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
172
186
|
* @returns List of keys.
|
|
173
187
|
*/
|
|
174
|
-
keys(path?: string): string[];
|
|
188
|
+
keys(path?: string | null): string[];
|
|
175
189
|
/**
|
|
176
190
|
* Deep-merge an object into the value at a dot-notation path.
|
|
177
191
|
*
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { PathNotFoundException } from '../exceptions/path-not-found-exception.js';
|
|
2
2
|
import { ReadonlyViolationException } from '../exceptions/readonly-violation-exception.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base accessor providing read, write, and lifecycle operations.
|
|
5
|
+
*
|
|
6
|
+
* Implements all AccessorsInterface methods with immutable copy
|
|
7
|
+
* semantics for writes, optional readonly enforcement, and strict mode
|
|
8
|
+
* for security validation on data ingestion.
|
|
9
|
+
*
|
|
10
|
+
* Subclasses must implement `parse()` to convert raw input into
|
|
11
|
+
* a normalized plain object.
|
|
12
|
+
*
|
|
13
|
+
* @api
|
|
14
|
+
*/
|
|
3
15
|
export class AbstractAccessor {
|
|
4
16
|
parser;
|
|
5
17
|
/** @internal Mutable state grouped to allow O(1) shallow clone in mutations. */
|
|
@@ -68,7 +80,7 @@ export class AbstractAccessor {
|
|
|
68
80
|
* Only use with fully trusted, application-controlled input.
|
|
69
81
|
*
|
|
70
82
|
* @example
|
|
71
|
-
* // Trust the input
|
|
83
|
+
* // Trust the input - skip all security checks
|
|
72
84
|
* const accessor = new JsonAccessor(parser).strict(false).from(trustedPayload);
|
|
73
85
|
*/
|
|
74
86
|
strict(strict = true) {
|
|
@@ -133,7 +145,8 @@ export class AbstractAccessor {
|
|
|
133
145
|
* @returns True if the path resolves to a value.
|
|
134
146
|
*/
|
|
135
147
|
hasAt(segments) {
|
|
136
|
-
|
|
148
|
+
const sentinel = Object.create(null);
|
|
149
|
+
return this.parser.getAt(this._state.data, segments, sentinel) !== sentinel;
|
|
137
150
|
}
|
|
138
151
|
/**
|
|
139
152
|
* Set a value at a dot-notation path.
|
|
@@ -207,26 +220,26 @@ export class AbstractAccessor {
|
|
|
207
220
|
return this._state.data;
|
|
208
221
|
}
|
|
209
222
|
/**
|
|
210
|
-
* Count elements at a path, or the root if undefined.
|
|
223
|
+
* Count elements at a path, or the root if null/undefined.
|
|
211
224
|
*
|
|
212
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
225
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
213
226
|
* @returns Number of elements.
|
|
214
227
|
*/
|
|
215
228
|
count(path) {
|
|
216
|
-
const target = path
|
|
229
|
+
const target = path != null ? this.get(path, {}) : this._state.data;
|
|
217
230
|
if (typeof target === 'object' && target !== null) {
|
|
218
231
|
return Object.keys(target).length;
|
|
219
232
|
}
|
|
220
233
|
return 0;
|
|
221
234
|
}
|
|
222
235
|
/**
|
|
223
|
-
* Retrieve array keys at a path, or root keys if undefined.
|
|
236
|
+
* Retrieve array keys at a path, or root keys if null/undefined.
|
|
224
237
|
*
|
|
225
|
-
* @param path - Dot-notation path, or undefined for root.
|
|
238
|
+
* @param path - Dot-notation path, or null/undefined for root.
|
|
226
239
|
* @returns List of keys.
|
|
227
240
|
*/
|
|
228
241
|
keys(path) {
|
|
229
|
-
const target = path
|
|
242
|
+
const target = path != null ? this.get(path, {}) : this._state.data;
|
|
230
243
|
/* Stryker disable next-line ConditionalExpression -- equivalent: get() always returns an object-type value here; typeof check is a type guard only */
|
|
231
244
|
if (typeof target === 'object' && target !== null) {
|
|
232
245
|
return Object.keys(target);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AbstractAccessor } from './abstract-accessor.js';
|
|
2
|
+
import type { ParseIntegrationInterface } from '../contracts/parse-integration-interface.js';
|
|
3
|
+
import type { ValidatableParserInterface } from '../contracts/validatable-parser-interface.js';
|
|
4
|
+
/**
|
|
5
|
+
* Base accessor with custom format integration support.
|
|
6
|
+
*
|
|
7
|
+
* Extends {@link AbstractAccessor} to inject a {@link ParseIntegrationInterface}
|
|
8
|
+
* for user-defined format detection and parsing. Used exclusively by
|
|
9
|
+
* {@link AnyAccessor} to handle arbitrary input formats.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class AbstractIntegrationAccessor extends AbstractAccessor {
|
|
14
|
+
protected readonly integration: ParseIntegrationInterface;
|
|
15
|
+
/**
|
|
16
|
+
* Create an accessor with parser and custom integration dependencies.
|
|
17
|
+
*
|
|
18
|
+
* @param parser - Dot-notation parser.
|
|
19
|
+
* @param integration - Custom format parser.
|
|
20
|
+
*/
|
|
21
|
+
constructor(parser: ValidatableParserInterface, integration: ParseIntegrationInterface);
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AbstractAccessor } from './abstract-accessor.js';
|
|
2
|
+
/**
|
|
3
|
+
* Base accessor with custom format integration support.
|
|
4
|
+
*
|
|
5
|
+
* Extends {@link AbstractAccessor} to inject a {@link ParseIntegrationInterface}
|
|
6
|
+
* for user-defined format detection and parsing. Used exclusively by
|
|
7
|
+
* {@link AnyAccessor} to handle arbitrary input formats.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export class AbstractIntegrationAccessor extends AbstractAccessor {
|
|
12
|
+
integration;
|
|
13
|
+
/**
|
|
14
|
+
* Create an accessor with parser and custom integration dependencies.
|
|
15
|
+
*
|
|
16
|
+
* @param parser - Dot-notation parser.
|
|
17
|
+
* @param integration - Custom format parser.
|
|
18
|
+
*/
|
|
19
|
+
constructor(parser, integration) {
|
|
20
|
+
super(parser);
|
|
21
|
+
this.integration = integration;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbstractIntegrationAccessor } from '../abstract-integration-accessor.js';
|
|
2
2
|
import type { ParseIntegrationInterface } from '../../contracts/parse-integration-interface.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ValidatableParserInterface } from '../../contracts/validatable-parser-interface.js';
|
|
4
4
|
/**
|
|
5
5
|
* Accessor for arbitrary formats via a custom {@link ParseIntegrationInterface}.
|
|
6
6
|
*
|
|
7
7
|
* Delegates format detection and parsing to a user-provided integration.
|
|
8
8
|
* Validates string payloads against security constraints before parsing.
|
|
9
9
|
*
|
|
10
|
+
* @api
|
|
11
|
+
*
|
|
10
12
|
* @example
|
|
11
13
|
* const integration = new MyCsvIntegration();
|
|
12
14
|
* const accessor = Inline.withParserIntegration(integration).fromAny(csvString);
|
|
13
15
|
* accessor.get('0.name'); // first row, name column
|
|
14
16
|
*/
|
|
15
|
-
export declare class AnyAccessor extends
|
|
16
|
-
private readonly integration;
|
|
17
|
+
export declare class AnyAccessor extends AbstractIntegrationAccessor {
|
|
17
18
|
/**
|
|
18
19
|
* @param parser - Dot-notation parser with security configuration.
|
|
19
20
|
* @param integration - Custom format parser for detecting and parsing input.
|
|
20
21
|
*/
|
|
21
|
-
constructor(parser:
|
|
22
|
+
constructor(parser: ValidatableParserInterface, integration: ParseIntegrationInterface);
|
|
22
23
|
/**
|
|
23
24
|
* Hydrate from raw data via the custom integration.
|
|
24
25
|
*
|
|
@@ -26,10 +27,11 @@ export declare class AnyAccessor extends AbstractAccessor {
|
|
|
26
27
|
* @returns Populated accessor instance.
|
|
27
28
|
* @throws {InvalidFormatException} When the integration rejects the format.
|
|
28
29
|
* @throws {SecurityException} When string input violates payload-size limits.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const accessor = new AnyAccessor(parser, integration).from(rawData);
|
|
29
33
|
*/
|
|
30
34
|
from(data: unknown): this;
|
|
31
|
-
/**
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
35
|
+
/** {@inheritDoc} */
|
|
34
36
|
protected parse(raw: unknown): Record<string, unknown>;
|
|
35
37
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbstractIntegrationAccessor } from '../abstract-integration-accessor.js';
|
|
2
2
|
import { InvalidFormatException } from '../../exceptions/invalid-format-exception.js';
|
|
3
3
|
/**
|
|
4
4
|
* Accessor for arbitrary formats via a custom {@link ParseIntegrationInterface}.
|
|
@@ -6,20 +6,20 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
6
6
|
* Delegates format detection and parsing to a user-provided integration.
|
|
7
7
|
* Validates string payloads against security constraints before parsing.
|
|
8
8
|
*
|
|
9
|
+
* @api
|
|
10
|
+
*
|
|
9
11
|
* @example
|
|
10
12
|
* const integration = new MyCsvIntegration();
|
|
11
13
|
* const accessor = Inline.withParserIntegration(integration).fromAny(csvString);
|
|
12
14
|
* accessor.get('0.name'); // first row, name column
|
|
13
15
|
*/
|
|
14
|
-
export class AnyAccessor extends
|
|
15
|
-
integration;
|
|
16
|
+
export class AnyAccessor extends AbstractIntegrationAccessor {
|
|
16
17
|
/**
|
|
17
18
|
* @param parser - Dot-notation parser with security configuration.
|
|
18
19
|
* @param integration - Custom format parser for detecting and parsing input.
|
|
19
20
|
*/
|
|
20
21
|
constructor(parser, integration) {
|
|
21
|
-
super(parser);
|
|
22
|
-
this.integration = integration;
|
|
22
|
+
super(parser, integration);
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Hydrate from raw data via the custom integration.
|
|
@@ -28,6 +28,9 @@ export class AnyAccessor extends AbstractAccessor {
|
|
|
28
28
|
* @returns Populated accessor instance.
|
|
29
29
|
* @throws {InvalidFormatException} When the integration rejects the format.
|
|
30
30
|
* @throws {SecurityException} When string input violates payload-size limits.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const accessor = new AnyAccessor(parser, integration).from(rawData);
|
|
31
34
|
*/
|
|
32
35
|
from(data) {
|
|
33
36
|
if (!this.integration.assertFormat(data)) {
|
|
@@ -35,9 +38,7 @@ export class AnyAccessor extends AbstractAccessor {
|
|
|
35
38
|
}
|
|
36
39
|
return this.ingest(data);
|
|
37
40
|
}
|
|
38
|
-
/**
|
|
39
|
-
* @internal
|
|
40
|
-
*/
|
|
41
|
+
/** {@inheritDoc} */
|
|
41
42
|
parse(raw) {
|
|
42
43
|
return this.integration.parse(raw);
|
|
43
44
|
}
|
|
@@ -4,6 +4,8 @@ import { AbstractAccessor } from '../abstract-accessor.js';
|
|
|
4
4
|
*
|
|
5
5
|
* Accepts a plain object or array directly. No string parsing is involved.
|
|
6
6
|
*
|
|
7
|
+
* @api
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* const accessor = new ArrayAccessor(parser).from({ key: 'value' });
|
|
9
11
|
* accessor.get('key'); // 'value'
|
|
@@ -5,6 +5,8 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
5
5
|
*
|
|
6
6
|
* Accepts a plain object or array directly. No string parsing is involved.
|
|
7
7
|
*
|
|
8
|
+
* @api
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* const accessor = new ArrayAccessor(parser).from({ key: 'value' });
|
|
10
12
|
* accessor.get('key'); // 'value'
|
|
@@ -5,6 +5,8 @@ import { AbstractAccessor } from '../abstract-accessor.js';
|
|
|
5
5
|
* Parses KEY=VALUE lines, skipping comments (#) and blank lines.
|
|
6
6
|
* Strips surrounding single and double quotes from values.
|
|
7
7
|
*
|
|
8
|
+
* @api
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* const accessor = new EnvAccessor(parser).from('DB_HOST=localhost\nDEBUG=true');
|
|
10
12
|
* accessor.get('DB_HOST'); // 'localhost'
|
|
@@ -6,6 +6,8 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
6
6
|
* Parses KEY=VALUE lines, skipping comments (#) and blank lines.
|
|
7
7
|
* Strips surrounding single and double quotes from values.
|
|
8
8
|
*
|
|
9
|
+
* @api
|
|
10
|
+
*
|
|
9
11
|
* @example
|
|
10
12
|
* const accessor = new EnvAccessor(parser).from('DB_HOST=localhost\nDEBUG=true');
|
|
11
13
|
* accessor.get('DB_HOST'); // 'localhost'
|
|
@@ -5,6 +5,8 @@ import { AbstractAccessor } from '../abstract-accessor.js';
|
|
|
5
5
|
* Parses sections (e.g. `[section]`) as nested keys.
|
|
6
6
|
* Type inference: numeric strings become numbers, `true`/`false` become booleans.
|
|
7
7
|
*
|
|
8
|
+
* @api
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* const accessor = new IniAccessor(parser).from('[db]\nhost=localhost\nport=5432');
|
|
10
12
|
* accessor.get('db.host'); // 'localhost'
|
|
@@ -6,6 +6,8 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
6
6
|
* Parses sections (e.g. `[section]`) as nested keys.
|
|
7
7
|
* Type inference: numeric strings become numbers, `true`/`false` become booleans.
|
|
8
8
|
*
|
|
9
|
+
* @api
|
|
10
|
+
*
|
|
9
11
|
* @example
|
|
10
12
|
* const accessor = new IniAccessor(parser).from('[db]\nhost=localhost\nport=5432');
|
|
11
13
|
* accessor.get('db.host'); // 'localhost'
|
|
@@ -4,6 +4,8 @@ import { AbstractAccessor } from '../abstract-accessor.js';
|
|
|
4
4
|
*
|
|
5
5
|
* Decodes JSON via `JSON.parse()`. Validates payload size before parsing.
|
|
6
6
|
*
|
|
7
|
+
* @api
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* const accessor = new JsonAccessor(parser).from('{"key":"value"}');
|
|
9
11
|
* accessor.get('key'); // 'value'
|
|
@@ -5,6 +5,8 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
5
5
|
*
|
|
6
6
|
* Decodes JSON via `JSON.parse()`. Validates payload size before parsing.
|
|
7
7
|
*
|
|
8
|
+
* @api
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* const accessor = new JsonAccessor(parser).from('{"key":"value"}');
|
|
10
12
|
* accessor.get('key'); // 'value'
|
|
@@ -5,6 +5,8 @@ import { AbstractAccessor } from '../abstract-accessor.js';
|
|
|
5
5
|
* Parses each non-empty line as a standalone JSON object,
|
|
6
6
|
* producing an indexed record of parsed entries.
|
|
7
7
|
*
|
|
8
|
+
* @api
|
|
9
|
+
*
|
|
8
10
|
* @example
|
|
9
11
|
* const ndjson = '{"id":1}\n{"id":2}';
|
|
10
12
|
* const accessor = new NdjsonAccessor(parser).from(ndjson);
|
|
@@ -6,6 +6,8 @@ import { InvalidFormatException } from '../../exceptions/invalid-format-exceptio
|
|
|
6
6
|
* Parses each non-empty line as a standalone JSON object,
|
|
7
7
|
* producing an indexed record of parsed entries.
|
|
8
8
|
*
|
|
9
|
+
* @api
|
|
10
|
+
*
|
|
9
11
|
* @example
|
|
10
12
|
* const ndjson = '{"id":1}\n{"id":2}';
|
|
11
13
|
* const accessor = new NdjsonAccessor(parser).from(ndjson);
|