@safeaccess/inline 0.1.1
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 +16 -0
- package/.gitkeep +0 -0
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +454 -0
- package/benchmarks/get.bench.ts +26 -0
- package/benchmarks/parse.bench.ts +41 -0
- package/dist/accessors/abstract-accessor.d.ts +213 -0
- package/dist/accessors/abstract-accessor.js +294 -0
- package/dist/accessors/formats/any-accessor.d.ts +35 -0
- package/dist/accessors/formats/any-accessor.js +44 -0
- package/dist/accessors/formats/array-accessor.d.ts +26 -0
- package/dist/accessors/formats/array-accessor.js +39 -0
- package/dist/accessors/formats/env-accessor.d.ts +27 -0
- package/dist/accessors/formats/env-accessor.js +64 -0
- package/dist/accessors/formats/ini-accessor.d.ts +41 -0
- package/dist/accessors/formats/ini-accessor.js +109 -0
- package/dist/accessors/formats/json-accessor.d.ts +26 -0
- package/dist/accessors/formats/json-accessor.js +56 -0
- package/dist/accessors/formats/ndjson-accessor.d.ts +28 -0
- package/dist/accessors/formats/ndjson-accessor.js +71 -0
- package/dist/accessors/formats/object-accessor.d.ts +48 -0
- package/dist/accessors/formats/object-accessor.js +90 -0
- package/dist/accessors/formats/xml-accessor.d.ts +27 -0
- package/dist/accessors/formats/xml-accessor.js +52 -0
- package/dist/accessors/formats/yaml-accessor.d.ts +29 -0
- package/dist/accessors/formats/yaml-accessor.js +46 -0
- package/dist/contracts/accessors-interface.d.ts +11 -0
- package/dist/contracts/accessors-interface.js +1 -0
- package/dist/contracts/factory-accessors-interface.d.ts +16 -0
- package/dist/contracts/factory-accessors-interface.js +1 -0
- package/dist/contracts/parse-integration-interface.d.ts +31 -0
- package/dist/contracts/parse-integration-interface.js +1 -0
- package/dist/contracts/path-cache-interface.d.ts +40 -0
- package/dist/contracts/path-cache-interface.js +1 -0
- package/dist/contracts/readable-accessors-interface.d.ts +79 -0
- package/dist/contracts/readable-accessors-interface.js +1 -0
- package/dist/contracts/security-guard-interface.d.ts +40 -0
- package/dist/contracts/security-guard-interface.js +1 -0
- package/dist/contracts/security-parser-interface.d.ts +67 -0
- package/dist/contracts/security-parser-interface.js +1 -0
- package/dist/contracts/writable-accessors-interface.d.ts +65 -0
- package/dist/contracts/writable-accessors-interface.js +1 -0
- package/dist/core/dot-notation-parser.d.ts +204 -0
- package/dist/core/dot-notation-parser.js +343 -0
- package/dist/exceptions/accessor-exception.d.ts +13 -0
- package/dist/exceptions/accessor-exception.js +16 -0
- package/dist/exceptions/invalid-format-exception.d.ts +14 -0
- package/dist/exceptions/invalid-format-exception.js +17 -0
- package/dist/exceptions/parser-exception.d.ts +14 -0
- package/dist/exceptions/parser-exception.js +17 -0
- package/dist/exceptions/path-not-found-exception.d.ts +14 -0
- package/dist/exceptions/path-not-found-exception.js +17 -0
- package/dist/exceptions/readonly-violation-exception.d.ts +15 -0
- package/dist/exceptions/readonly-violation-exception.js +18 -0
- package/dist/exceptions/security-exception.d.ts +18 -0
- package/dist/exceptions/security-exception.js +21 -0
- package/dist/exceptions/unsupported-type-exception.d.ts +14 -0
- package/dist/exceptions/unsupported-type-exception.js +17 -0
- package/dist/exceptions/yaml-parse-exception.d.ts +17 -0
- package/dist/exceptions/yaml-parse-exception.js +20 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +30 -0
- package/dist/inline.d.ts +402 -0
- package/dist/inline.js +512 -0
- package/dist/parser/xml-parser.d.ts +46 -0
- package/dist/parser/xml-parser.js +288 -0
- package/dist/parser/yaml-parser.d.ts +94 -0
- package/dist/parser/yaml-parser.js +286 -0
- package/dist/security/forbidden-keys.d.ts +34 -0
- package/dist/security/forbidden-keys.js +80 -0
- package/dist/security/security-guard.d.ts +94 -0
- package/dist/security/security-guard.js +172 -0
- package/dist/security/security-parser.d.ts +130 -0
- package/dist/security/security-parser.js +192 -0
- package/dist/type-format.d.ts +28 -0
- package/dist/type-format.js +29 -0
- package/eslint.config.js +1 -0
- package/package.json +39 -0
- package/src/accessors/abstract-accessor.ts +353 -0
- package/src/accessors/formats/any-accessor.ts +51 -0
- package/src/accessors/formats/array-accessor.ts +45 -0
- package/src/accessors/formats/env-accessor.ts +79 -0
- package/src/accessors/formats/ini-accessor.ts +124 -0
- package/src/accessors/formats/json-accessor.ts +66 -0
- package/src/accessors/formats/ndjson-accessor.ts +82 -0
- package/src/accessors/formats/object-accessor.ts +100 -0
- package/src/accessors/formats/xml-accessor.ts +58 -0
- package/src/accessors/formats/yaml-accessor.ts +52 -0
- package/src/contracts/accessors-interface.ts +12 -0
- package/src/contracts/factory-accessors-interface.ts +16 -0
- package/src/contracts/parse-integration-interface.ts +32 -0
- package/src/contracts/path-cache-interface.ts +43 -0
- package/src/contracts/readable-accessors-interface.ts +88 -0
- package/src/contracts/security-guard-interface.ts +43 -0
- package/src/contracts/security-parser-interface.ts +74 -0
- package/src/contracts/writable-accessors-interface.ts +70 -0
- package/src/core/dot-notation-parser.ts +419 -0
- package/src/exceptions/accessor-exception.ts +16 -0
- package/src/exceptions/invalid-format-exception.ts +18 -0
- package/src/exceptions/parser-exception.ts +18 -0
- package/src/exceptions/path-not-found-exception.ts +18 -0
- package/src/exceptions/readonly-violation-exception.ts +19 -0
- package/src/exceptions/security-exception.ts +22 -0
- package/src/exceptions/unsupported-type-exception.ts +18 -0
- package/src/exceptions/yaml-parse-exception.ts +21 -0
- package/src/index.ts +46 -0
- package/src/inline.ts +570 -0
- package/src/parser/xml-parser.ts +334 -0
- package/src/parser/yaml-parser.ts +368 -0
- package/src/security/forbidden-keys.ts +81 -0
- package/src/security/security-guard.ts +195 -0
- package/src/security/security-parser.ts +233 -0
- package/src/type-format.ts +28 -0
- package/stryker.config.json +24 -0
- package/tests/accessors/accessors.test.ts +1017 -0
- package/tests/accessors/json-accessor.test.ts +171 -0
- package/tests/core/dot-notation-parser.test.ts +587 -0
- package/tests/exceptions/parser-exception.test.ts +31 -0
- package/tests/inline.test.ts +445 -0
- package/tests/mocks/fake-parse-integration.ts +24 -0
- package/tests/mocks/fake-path-cache.ts +31 -0
- package/tests/parity.test.ts +164 -0
- package/tests/parser/xml-parser.test.ts +618 -0
- package/tests/parser/yaml-parser.test.ts +463 -0
- package/tests/security/security-guard.test.ts +646 -0
- package/tests/security/security-parser.test.ts +391 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +19 -0
package/dist/inline.js
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { TypeFormat } from './type-format.js';
|
|
2
|
+
import { DotNotationParser } from './core/dot-notation-parser.js';
|
|
3
|
+
import { SecurityGuard } from './security/security-guard.js';
|
|
4
|
+
import { SecurityParser } from './security/security-parser.js';
|
|
5
|
+
import { AbstractAccessor } from './accessors/abstract-accessor.js';
|
|
6
|
+
import { ArrayAccessor } from './accessors/formats/array-accessor.js';
|
|
7
|
+
import { ObjectAccessor } from './accessors/formats/object-accessor.js';
|
|
8
|
+
import { JsonAccessor } from './accessors/formats/json-accessor.js';
|
|
9
|
+
import { XmlAccessor } from './accessors/formats/xml-accessor.js';
|
|
10
|
+
import { YamlAccessor } from './accessors/formats/yaml-accessor.js';
|
|
11
|
+
import { IniAccessor } from './accessors/formats/ini-accessor.js';
|
|
12
|
+
import { EnvAccessor } from './accessors/formats/env-accessor.js';
|
|
13
|
+
import { NdjsonAccessor } from './accessors/formats/ndjson-accessor.js';
|
|
14
|
+
import { AnyAccessor } from './accessors/formats/any-accessor.js';
|
|
15
|
+
import { UnsupportedTypeException } from './exceptions/unsupported-type-exception.js';
|
|
16
|
+
import { InvalidFormatException } from './exceptions/invalid-format-exception.js';
|
|
17
|
+
/**
|
|
18
|
+
* Facade for creating typed data accessors fluently.
|
|
19
|
+
*
|
|
20
|
+
* All static factory methods return a strongly-typed accessor instance.
|
|
21
|
+
* Use the builder methods (`withSecurityGuard`, `withSecurityParser`) to
|
|
22
|
+
* customize the security configuration before creating an accessor.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const accessor = Inline.fromJson('{"name":"Alice"}');
|
|
26
|
+
* accessor.get('name'); // 'Alice'
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const accessor = Inline.from(TypeFormat.Yaml, 'name: Alice');
|
|
30
|
+
* accessor.get('name'); // 'Alice'
|
|
31
|
+
*/
|
|
32
|
+
export class Inline {
|
|
33
|
+
guard;
|
|
34
|
+
secParser;
|
|
35
|
+
pathCache;
|
|
36
|
+
integration;
|
|
37
|
+
strictMode;
|
|
38
|
+
constructor(guard, secParser, pathCache = null, integration = null, strictMode = null) {
|
|
39
|
+
this.guard = guard;
|
|
40
|
+
this.secParser = secParser;
|
|
41
|
+
this.pathCache = pathCache;
|
|
42
|
+
this.integration = integration;
|
|
43
|
+
this.strictMode = strictMode;
|
|
44
|
+
}
|
|
45
|
+
static defaultInstance() {
|
|
46
|
+
return new Inline(new SecurityGuard(), new SecurityParser());
|
|
47
|
+
}
|
|
48
|
+
makeParser() {
|
|
49
|
+
return new DotNotationParser(this.guard, this.secParser, this.pathCache ?? undefined);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Apply configured strict mode to a new accessor before hydration.
|
|
53
|
+
*
|
|
54
|
+
* @param accessor - Unhydrated accessor instance.
|
|
55
|
+
* @returns Same accessor with strict mode applied if configured.
|
|
56
|
+
*/
|
|
57
|
+
prepare(accessor) {
|
|
58
|
+
if (this.strictMode !== null) {
|
|
59
|
+
return accessor.strict(this.strictMode);
|
|
60
|
+
}
|
|
61
|
+
return accessor;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Return a new Inline instance with a custom SecurityGuard, preserving other settings.
|
|
65
|
+
*
|
|
66
|
+
* @param guard - Custom security guard implementation.
|
|
67
|
+
* @returns New Inline builder instance.
|
|
68
|
+
*/
|
|
69
|
+
withSecurityGuard(guard) {
|
|
70
|
+
return new Inline(guard, this.secParser, this.pathCache, this.integration, this.strictMode);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Return a new Inline instance with a custom SecurityParser, preserving other settings.
|
|
74
|
+
*
|
|
75
|
+
* @param parser - Custom security parser implementation.
|
|
76
|
+
* @returns New Inline builder instance.
|
|
77
|
+
*/
|
|
78
|
+
withSecurityParser(parser) {
|
|
79
|
+
return new Inline(this.guard, parser, this.pathCache, this.integration, this.strictMode);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Return a new Inline instance with a custom path cache, preserving other settings.
|
|
83
|
+
*
|
|
84
|
+
* @param cache - Custom path cache implementation.
|
|
85
|
+
* @returns New Inline builder instance.
|
|
86
|
+
*/
|
|
87
|
+
withPathCache(cache) {
|
|
88
|
+
return new Inline(this.guard, this.secParser, cache, this.integration, this.strictMode);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Return a new Inline instance with a custom parser integration, preserving other settings.
|
|
92
|
+
*
|
|
93
|
+
* @param integration - Custom format integration implementation.
|
|
94
|
+
* @returns New Inline builder instance.
|
|
95
|
+
*/
|
|
96
|
+
withParserIntegration(integration) {
|
|
97
|
+
return new Inline(this.guard, this.secParser, this.pathCache, integration, this.strictMode);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Return a new Inline instance with the given strict mode, preserving other settings.
|
|
101
|
+
*
|
|
102
|
+
* @param strict - Whether to enable strict security validation.
|
|
103
|
+
* @returns New Inline builder instance.
|
|
104
|
+
*
|
|
105
|
+
* @security Passing `false` disables all SecurityGuard and SecurityParser
|
|
106
|
+
* validation. Only use with fully trusted, application-controlled input.
|
|
107
|
+
*/
|
|
108
|
+
withStrictMode(strict) {
|
|
109
|
+
return new Inline(this.guard, this.secParser, this.pathCache, this.integration, strict);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Return a new Inline instance with a custom SecurityGuard.
|
|
113
|
+
*
|
|
114
|
+
* @param guard - Custom security guard implementation.
|
|
115
|
+
* @returns New Inline builder instance.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* Inline.withSecurityGuard(new SecurityGuard(10, ['extraKey'])).fromJson('{}');
|
|
119
|
+
*/
|
|
120
|
+
static withSecurityGuard(guard) {
|
|
121
|
+
return new Inline(guard, new SecurityParser());
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Return a new Inline instance with a custom SecurityParser.
|
|
125
|
+
*
|
|
126
|
+
* @param parser - Custom security parser implementation.
|
|
127
|
+
* @returns New Inline builder instance.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* Inline.withSecurityParser(new SecurityParser({ maxDepth: 10 })).fromJson('{}');
|
|
131
|
+
*/
|
|
132
|
+
static withSecurityParser(parser) {
|
|
133
|
+
return new Inline(new SecurityGuard(), parser);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Return a new Inline instance with a custom path cache.
|
|
137
|
+
*
|
|
138
|
+
* @param cache - Custom path cache implementation.
|
|
139
|
+
* @returns New Inline builder instance.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* const cache: PathCacheInterface = { get: () => null, set: () => {}, has: () => false, clear: () => {} };
|
|
143
|
+
* Inline.withPathCache(cache).fromJson('{"key":"value"}');
|
|
144
|
+
*/
|
|
145
|
+
static withPathCache(cache) {
|
|
146
|
+
return new Inline(new SecurityGuard(), new SecurityParser(), cache);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Return a new Inline instance with a custom parser integration for `fromAny()`.
|
|
150
|
+
*
|
|
151
|
+
* @param integration - Custom format integration implementation.
|
|
152
|
+
* @returns New Inline builder instance.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* Inline.withParserIntegration(new MyCsvIntegration()).fromAny(csvString);
|
|
156
|
+
*/
|
|
157
|
+
static withParserIntegration(integration) {
|
|
158
|
+
return new Inline(new SecurityGuard(), new SecurityParser(), null, integration);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Return a new Inline instance with the given strict mode.
|
|
162
|
+
*
|
|
163
|
+
* @param strict - Whether to enable strict security validation.
|
|
164
|
+
* @returns New Inline builder instance.
|
|
165
|
+
*
|
|
166
|
+
* @security Passing `false` disables all SecurityGuard and SecurityParser
|
|
167
|
+
* validation. Only use with fully trusted, application-controlled input.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* Inline.withStrictMode(false).fromJson(hugePayload).get('key');
|
|
171
|
+
*/
|
|
172
|
+
static withStrictMode(strict) {
|
|
173
|
+
return new Inline(new SecurityGuard(), new SecurityParser(), null, null, strict);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Create an ArrayAccessor from a plain object or array.
|
|
177
|
+
*
|
|
178
|
+
* @param data - Plain object or array input.
|
|
179
|
+
* @returns Populated ArrayAccessor instance.
|
|
180
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* inline.fromArray({ name: 'Alice' }).get('name'); // 'Alice'
|
|
184
|
+
*/
|
|
185
|
+
fromArray(data) {
|
|
186
|
+
return this.prepare(new ArrayAccessor(this.makeParser())).from(data);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Create an ObjectAccessor from a JavaScript object.
|
|
190
|
+
*
|
|
191
|
+
* @param data - Object input (plain object, class instance, etc.).
|
|
192
|
+
* @returns Populated ObjectAccessor instance.
|
|
193
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* inline.fromObject({ user: { name: 'Alice' } }).get('user.name');
|
|
197
|
+
*/
|
|
198
|
+
fromObject(data) {
|
|
199
|
+
return this.prepare(new ObjectAccessor(this.makeParser())).from(data);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Create a JsonAccessor from a JSON string.
|
|
203
|
+
*
|
|
204
|
+
* @param data - Raw JSON string.
|
|
205
|
+
* @returns Populated JsonAccessor instance.
|
|
206
|
+
* @throws {InvalidFormatException} When the JSON is malformed.
|
|
207
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* inline.fromJson('{"key":"value"}').get('key'); // 'value'
|
|
211
|
+
*/
|
|
212
|
+
fromJson(data) {
|
|
213
|
+
return this.prepare(new JsonAccessor(this.makeParser())).from(data);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Create an XmlAccessor from an XML string.
|
|
217
|
+
*
|
|
218
|
+
* @param data - Raw XML string.
|
|
219
|
+
* @returns Populated XmlAccessor instance.
|
|
220
|
+
* @throws {InvalidFormatException} When the XML is malformed.
|
|
221
|
+
* @throws {SecurityException} When DOCTYPE is detected.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* inline.fromXml('<root><key>value</key></root>').get('key');
|
|
225
|
+
*/
|
|
226
|
+
fromXml(data) {
|
|
227
|
+
return this.prepare(new XmlAccessor(this.makeParser())).from(data);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Create a YamlAccessor from a YAML string.
|
|
231
|
+
*
|
|
232
|
+
* @param data - Raw YAML string.
|
|
233
|
+
* @returns Populated YamlAccessor instance.
|
|
234
|
+
* @throws {YamlParseException} When the YAML is malformed or contains unsafe constructs.
|
|
235
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* inline.fromYaml('name: Alice').get('name'); // 'Alice'
|
|
239
|
+
*/
|
|
240
|
+
fromYaml(data) {
|
|
241
|
+
return this.prepare(new YamlAccessor(this.makeParser())).from(data);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Create an IniAccessor from an INI string.
|
|
245
|
+
*
|
|
246
|
+
* @param data - Raw INI string.
|
|
247
|
+
* @returns Populated IniAccessor instance.
|
|
248
|
+
* @throws {InvalidFormatException} When the input is not a string.
|
|
249
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* inline.fromIni('[section]\nkey=value').get('section.key'); // 'value'
|
|
253
|
+
*/
|
|
254
|
+
fromIni(data) {
|
|
255
|
+
return this.prepare(new IniAccessor(this.makeParser())).from(data);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Create an EnvAccessor from a dotenv-formatted string.
|
|
259
|
+
*
|
|
260
|
+
* @param data - Raw dotenv string.
|
|
261
|
+
* @returns Populated EnvAccessor instance.
|
|
262
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* inline.fromEnv('APP_NAME=MyApp').get('APP_NAME'); // 'MyApp'
|
|
266
|
+
*/
|
|
267
|
+
fromEnv(data) {
|
|
268
|
+
return this.prepare(new EnvAccessor(this.makeParser())).from(data);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Create an NdjsonAccessor from a newline-delimited JSON string.
|
|
272
|
+
*
|
|
273
|
+
* @param data - Raw NDJSON string.
|
|
274
|
+
* @returns Populated NdjsonAccessor instance.
|
|
275
|
+
* @throws {InvalidFormatException} When any JSON line is malformed.
|
|
276
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* inline.fromNdjson('{"id":1}\n{"id":2}').get('0.id'); // 1
|
|
280
|
+
*/
|
|
281
|
+
fromNdjson(data) {
|
|
282
|
+
return this.prepare(new NdjsonAccessor(this.makeParser())).from(data);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Create an AnyAccessor from raw data using a custom integration.
|
|
286
|
+
*
|
|
287
|
+
* Uses the integration provided via `withParserIntegration()` by default,
|
|
288
|
+
* or the one passed as the second argument for a one-off override.
|
|
289
|
+
*
|
|
290
|
+
* @param data - Raw input data in any format supported by the integration.
|
|
291
|
+
* @param integration - Override integration for this call (optional).
|
|
292
|
+
* @returns Populated AnyAccessor instance.
|
|
293
|
+
* @throws {InvalidFormatException} When no integration is available or it rejects the format.
|
|
294
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* Inline.withParserIntegration(new CsvIntegration()).fromAny(csvString);
|
|
298
|
+
*/
|
|
299
|
+
fromAny(data, integration) {
|
|
300
|
+
const resolved = integration ?? this.integration;
|
|
301
|
+
if (resolved === null) {
|
|
302
|
+
throw new InvalidFormatException('AnyAccessor requires a ParseIntegrationInterface — use Inline.withParserIntegration(integration).fromAny(data).');
|
|
303
|
+
}
|
|
304
|
+
return this.prepare(new AnyAccessor(this.makeParser(), resolved)).from(data);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Create a typed accessor by its constructor.
|
|
308
|
+
*
|
|
309
|
+
* @param AccessorConstructor - The accessor class to instantiate.
|
|
310
|
+
* @param data - Raw data to hydrate the accessor with.
|
|
311
|
+
* @returns Populated accessor instance.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* Inline.make(JsonAccessor, '{"key":"value"}').get('key'); // 'value'
|
|
315
|
+
*/
|
|
316
|
+
make(AccessorConstructor, data) {
|
|
317
|
+
const accessor = new AccessorConstructor(this.makeParser());
|
|
318
|
+
if (this.strictMode !== null && accessor instanceof AbstractAccessor) {
|
|
319
|
+
return accessor.strict(this.strictMode).from(data);
|
|
320
|
+
}
|
|
321
|
+
return accessor.from(data);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Create an accessor for the given TypeFormat and raw data.
|
|
325
|
+
*
|
|
326
|
+
* @param typeFormat - The format to parse as.
|
|
327
|
+
* @param data - Raw input data.
|
|
328
|
+
* @returns Populated accessor instance.
|
|
329
|
+
* @throws {InvalidFormatException} When the data is malformed for the target format.
|
|
330
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
331
|
+
* @throws {UnsupportedTypeException} When the TypeFormat is not supported.
|
|
332
|
+
*/
|
|
333
|
+
from(typeFormat, data) {
|
|
334
|
+
switch (typeFormat) {
|
|
335
|
+
case TypeFormat.Array:
|
|
336
|
+
return this.fromArray(data);
|
|
337
|
+
case TypeFormat.Object:
|
|
338
|
+
return this.fromObject(data);
|
|
339
|
+
case TypeFormat.Json:
|
|
340
|
+
return this.fromJson(data);
|
|
341
|
+
case TypeFormat.Xml:
|
|
342
|
+
return this.fromXml(data);
|
|
343
|
+
case TypeFormat.Yaml:
|
|
344
|
+
return this.fromYaml(data);
|
|
345
|
+
case TypeFormat.Ini:
|
|
346
|
+
return this.fromIni(data);
|
|
347
|
+
case TypeFormat.Env:
|
|
348
|
+
return this.fromEnv(data);
|
|
349
|
+
case TypeFormat.Ndjson:
|
|
350
|
+
return this.fromNdjson(data);
|
|
351
|
+
case TypeFormat.Any:
|
|
352
|
+
return this.fromAny(data);
|
|
353
|
+
default: {
|
|
354
|
+
const exhaustive = typeFormat;
|
|
355
|
+
throw new UnsupportedTypeException(`TypeFormat '${String(exhaustive)}' is not supported.`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Create an ArrayAccessor from a plain object or array.
|
|
361
|
+
*
|
|
362
|
+
* @param data - Plain object or array input.
|
|
363
|
+
* @returns Populated ArrayAccessor instance.
|
|
364
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* Inline.fromArray({ name: 'Alice' }).get('name'); // 'Alice'
|
|
368
|
+
*/
|
|
369
|
+
static fromArray(data) {
|
|
370
|
+
return Inline.defaultInstance().fromArray(data);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Create an ObjectAccessor from a JavaScript object.
|
|
374
|
+
*
|
|
375
|
+
* @param data - Object input (plain object, class instance, etc.).
|
|
376
|
+
* @returns Populated ObjectAccessor instance.
|
|
377
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* Inline.fromObject({ user: { name: 'Alice' } }).get('user.name');
|
|
381
|
+
*/
|
|
382
|
+
static fromObject(data) {
|
|
383
|
+
return Inline.defaultInstance().fromObject(data);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Create a JsonAccessor from a JSON string.
|
|
387
|
+
*
|
|
388
|
+
* @param data - Raw JSON string.
|
|
389
|
+
* @returns Populated JsonAccessor instance.
|
|
390
|
+
* @throws {InvalidFormatException} When the JSON is malformed.
|
|
391
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* Inline.fromJson('{"key":"value"}').get('key'); // 'value'
|
|
395
|
+
*/
|
|
396
|
+
static fromJson(data) {
|
|
397
|
+
return Inline.defaultInstance().fromJson(data);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Create an XmlAccessor from an XML string.
|
|
401
|
+
*
|
|
402
|
+
* @param data - Raw XML string.
|
|
403
|
+
* @returns Populated XmlAccessor instance.
|
|
404
|
+
* @throws {InvalidFormatException} When the XML is malformed.
|
|
405
|
+
* @throws {SecurityException} When DOCTYPE is detected.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* Inline.fromXml('<root><key>value</key></root>').get('key');
|
|
409
|
+
*/
|
|
410
|
+
static fromXml(data) {
|
|
411
|
+
return Inline.defaultInstance().fromXml(data);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Create a YamlAccessor from a YAML string.
|
|
415
|
+
*
|
|
416
|
+
* @param data - Raw YAML string.
|
|
417
|
+
* @returns Populated YamlAccessor instance.
|
|
418
|
+
* @throws {YamlParseException} When the YAML is malformed or contains unsafe constructs.
|
|
419
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* Inline.fromYaml('name: Alice\nage: 30').get('name'); // 'Alice'
|
|
423
|
+
*/
|
|
424
|
+
static fromYaml(data) {
|
|
425
|
+
return Inline.defaultInstance().fromYaml(data);
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Create an IniAccessor from an INI string.
|
|
429
|
+
*
|
|
430
|
+
* @param data - Raw INI string.
|
|
431
|
+
* @returns Populated IniAccessor instance.
|
|
432
|
+
* @throws {InvalidFormatException} When the input is not a string.
|
|
433
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* Inline.fromIni('[section]\nkey=value').get('section.key'); // 'value'
|
|
437
|
+
*/
|
|
438
|
+
static fromIni(data) {
|
|
439
|
+
return Inline.defaultInstance().fromIni(data);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Create an EnvAccessor from a dotenv-formatted string.
|
|
443
|
+
*
|
|
444
|
+
* @param data - Raw dotenv string.
|
|
445
|
+
* @returns Populated EnvAccessor instance.
|
|
446
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* Inline.fromEnv('APP_NAME=MyApp\nDEBUG=true').get('APP_NAME'); // 'MyApp'
|
|
450
|
+
*/
|
|
451
|
+
static fromEnv(data) {
|
|
452
|
+
return Inline.defaultInstance().fromEnv(data);
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Create an NdjsonAccessor from a newline-delimited JSON string.
|
|
456
|
+
*
|
|
457
|
+
* @param data - Raw NDJSON string.
|
|
458
|
+
* @returns Populated NdjsonAccessor instance.
|
|
459
|
+
* @throws {InvalidFormatException} When any JSON line is malformed.
|
|
460
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* Inline.fromNdjson('{"id":1}\n{"id":2}').get('0.id'); // 1
|
|
464
|
+
*/
|
|
465
|
+
static fromNdjson(data) {
|
|
466
|
+
return Inline.defaultInstance().fromNdjson(data);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Create an accessor for the given TypeFormat and raw data.
|
|
470
|
+
*
|
|
471
|
+
* @param typeFormat - The format to parse as.
|
|
472
|
+
* @param data - Raw input data.
|
|
473
|
+
* @returns Populated accessor instance.
|
|
474
|
+
* @throws {InvalidFormatException} When the data is malformed for the target format.
|
|
475
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
476
|
+
* @throws {UnsupportedTypeException} When the TypeFormat is not supported.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* Inline.from(TypeFormat.Json, '{"key":"value"}').get('key'); // 'value'
|
|
480
|
+
*/
|
|
481
|
+
static from(typeFormat, data) {
|
|
482
|
+
return Inline.defaultInstance().from(typeFormat, data);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Create an AnyAccessor from raw data using a custom integration.
|
|
486
|
+
*
|
|
487
|
+
* @param data - Raw input data.
|
|
488
|
+
* @param integration - Integration that detects and parses the format (optional if set via `withParserIntegration`).
|
|
489
|
+
* @returns Populated AnyAccessor instance.
|
|
490
|
+
* @throws {InvalidFormatException} When no integration is available or it rejects the format.
|
|
491
|
+
* @throws {SecurityException} When security constraints are violated.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* Inline.fromAny(csvString, new CsvIntegration()).get('0.name');
|
|
495
|
+
*/
|
|
496
|
+
static fromAny(data, integration) {
|
|
497
|
+
return Inline.defaultInstance().fromAny(data, integration);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Create a typed accessor by its constructor.
|
|
501
|
+
*
|
|
502
|
+
* @param AccessorConstructor - The accessor class to instantiate.
|
|
503
|
+
* @param data - Raw data to hydrate the accessor with.
|
|
504
|
+
* @returns Populated accessor instance.
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* Inline.make(JsonAccessor, '{"key":"value"}').get('key'); // 'value'
|
|
508
|
+
*/
|
|
509
|
+
static make(AccessorConstructor, data) {
|
|
510
|
+
return Inline.defaultInstance().make(AccessorConstructor, data);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal XML-to-object parser for XmlAccessor.
|
|
3
|
+
*
|
|
4
|
+
* Provides both a browser path (DOMParser) and a minimal manual parser
|
|
5
|
+
* for Node.js environments. Does not depend on external XML libraries.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare class XmlParser {
|
|
10
|
+
private readonly maxDepth;
|
|
11
|
+
private readonly maxElements;
|
|
12
|
+
/**
|
|
13
|
+
* @param maxDepth - Maximum structural depth allowed.
|
|
14
|
+
* @param maxElements - Maximum number of opening-tag occurrences allowed in the
|
|
15
|
+
* Node.js manual-parser path before parsing is aborted. Acts as a complexity
|
|
16
|
+
* bound and defence-in-depth against document-bombing. Defaults to 10 000
|
|
17
|
+
* (matches `SecurityParser.maxKeys`). Non-positive, non-finite, or `NaN` values
|
|
18
|
+
* are clamped to 10 000 to prevent accidental guard disablement.
|
|
19
|
+
*/
|
|
20
|
+
constructor(maxDepth: number, maxElements?: number);
|
|
21
|
+
/**
|
|
22
|
+
* Parse an XML body into a plain object using the best available parser.
|
|
23
|
+
*
|
|
24
|
+
* @param xml - Raw XML content (must not contain DOCTYPE).
|
|
25
|
+
* @returns Parsed data structure.
|
|
26
|
+
* @throws {InvalidFormatException} When XML is malformed.
|
|
27
|
+
* @throws {SecurityException} When structural depth exceeds limit.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* new XmlParser(10).parse('<root><key>value</key></root>'); // { key: 'value' }
|
|
31
|
+
*/
|
|
32
|
+
parse(xml: string): Record<string, unknown>;
|
|
33
|
+
private parseBrowserXml;
|
|
34
|
+
private elementToRecord;
|
|
35
|
+
private parseXmlManual;
|
|
36
|
+
/**
|
|
37
|
+
* Extract root element inner content using an indexOf-based O(n) scan.
|
|
38
|
+
*
|
|
39
|
+
* Replaces the previous backreference regex to guarantee O(n) time regardless
|
|
40
|
+
* of document structure. The closing-tag match is verified by scanning
|
|
41
|
+
* backwards from the final `>` character of the trimmed document.
|
|
42
|
+
*/
|
|
43
|
+
private extractRootContent;
|
|
44
|
+
private parseXmlChildren;
|
|
45
|
+
private addChild;
|
|
46
|
+
}
|