@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.
Files changed (179) hide show
  1. package/.gitattributes +1 -1
  2. package/CHANGELOG.md +10 -5
  3. package/LICENSE +1 -1
  4. package/README.md +56 -14
  5. package/dist/accessors/abstract-accessor.d.ts +22 -10
  6. package/dist/accessors/abstract-accessor.js +21 -8
  7. package/dist/accessors/abstract-integration-accessor.d.ts +22 -0
  8. package/dist/accessors/abstract-integration-accessor.js +23 -0
  9. package/dist/accessors/formats/any-accessor.d.ts +10 -8
  10. package/dist/accessors/formats/any-accessor.js +9 -8
  11. package/dist/accessors/formats/array-accessor.d.ts +2 -0
  12. package/dist/accessors/formats/array-accessor.js +2 -0
  13. package/dist/accessors/formats/env-accessor.d.ts +2 -0
  14. package/dist/accessors/formats/env-accessor.js +2 -0
  15. package/dist/accessors/formats/ini-accessor.d.ts +2 -0
  16. package/dist/accessors/formats/ini-accessor.js +2 -0
  17. package/dist/accessors/formats/json-accessor.d.ts +2 -0
  18. package/dist/accessors/formats/json-accessor.js +2 -0
  19. package/dist/accessors/formats/ndjson-accessor.d.ts +2 -0
  20. package/dist/accessors/formats/ndjson-accessor.js +2 -0
  21. package/dist/accessors/formats/object-accessor.d.ts +2 -0
  22. package/dist/accessors/formats/object-accessor.js +2 -0
  23. package/dist/accessors/formats/xml-accessor.d.ts +2 -0
  24. package/dist/accessors/formats/xml-accessor.js +2 -0
  25. package/dist/accessors/formats/yaml-accessor.d.ts +3 -1
  26. package/dist/accessors/formats/yaml-accessor.js +4 -2
  27. package/dist/cache/simple-path-cache.d.ts +51 -0
  28. package/dist/cache/simple-path-cache.js +72 -0
  29. package/dist/contracts/accessors-interface.d.ts +2 -0
  30. package/dist/contracts/factory-accessors-interface.d.ts +2 -0
  31. package/dist/contracts/filter-evaluator-interface.d.ts +28 -0
  32. package/dist/contracts/filter-evaluator-interface.js +1 -0
  33. package/dist/contracts/parse-integration-interface.d.ts +2 -0
  34. package/dist/contracts/parser-interface.d.ts +92 -0
  35. package/dist/contracts/parser-interface.js +1 -0
  36. package/dist/contracts/path-cache-interface.d.ts +7 -6
  37. package/dist/contracts/readable-accessors-interface.d.ts +11 -6
  38. package/dist/contracts/security-guard-interface.d.ts +2 -0
  39. package/dist/contracts/security-parser-interface.d.ts +2 -0
  40. package/dist/contracts/validatable-parser-interface.d.ts +59 -0
  41. package/dist/contracts/validatable-parser-interface.js +1 -0
  42. package/dist/contracts/writable-accessors-interface.d.ts +5 -0
  43. package/dist/core/accessor-factory.d.ts +124 -0
  44. package/dist/core/accessor-factory.js +157 -0
  45. package/dist/core/dot-notation-parser.d.ts +34 -5
  46. package/dist/core/dot-notation-parser.js +51 -10
  47. package/dist/core/inline-builder-accessor.d.ts +82 -0
  48. package/dist/core/inline-builder-accessor.js +107 -0
  49. package/dist/exceptions/accessor-exception.d.ts +9 -0
  50. package/dist/exceptions/accessor-exception.js +9 -0
  51. package/dist/exceptions/invalid-format-exception.d.ts +5 -0
  52. package/dist/exceptions/invalid-format-exception.js +5 -0
  53. package/dist/exceptions/parser-exception.d.ts +4 -0
  54. package/dist/exceptions/parser-exception.js +4 -0
  55. package/dist/exceptions/path-not-found-exception.d.ts +4 -0
  56. package/dist/exceptions/path-not-found-exception.js +4 -0
  57. package/dist/exceptions/readonly-violation-exception.d.ts +4 -0
  58. package/dist/exceptions/readonly-violation-exception.js +4 -0
  59. package/dist/exceptions/security-exception.d.ts +6 -0
  60. package/dist/exceptions/security-exception.js +6 -0
  61. package/dist/exceptions/unsupported-type-exception.d.ts +4 -0
  62. package/dist/exceptions/unsupported-type-exception.js +4 -0
  63. package/dist/exceptions/yaml-parse-exception.d.ts +4 -0
  64. package/dist/exceptions/yaml-parse-exception.js +4 -0
  65. package/dist/index.js +2 -1
  66. package/dist/inline.d.ts +22 -56
  67. package/dist/inline.js +39 -111
  68. package/dist/parser/xml-parser.js +23 -10
  69. package/dist/parser/yaml-parser.d.ts +54 -7
  70. package/dist/parser/yaml-parser.js +268 -51
  71. package/dist/path-query/segment-filter-parser.d.ts +142 -0
  72. package/dist/path-query/segment-filter-parser.js +384 -0
  73. package/dist/path-query/segment-parser.d.ts +98 -0
  74. package/dist/path-query/segment-parser.js +283 -0
  75. package/dist/path-query/segment-path-resolver.d.ts +149 -0
  76. package/dist/path-query/segment-path-resolver.js +351 -0
  77. package/dist/path-query/segment-type.d.ts +85 -0
  78. package/dist/path-query/segment-type.js +35 -0
  79. package/dist/security/forbidden-keys.d.ts +2 -2
  80. package/dist/security/forbidden-keys.js +5 -5
  81. package/dist/security/security-guard.d.ts +3 -1
  82. package/dist/security/security-guard.js +5 -2
  83. package/dist/security/security-parser.d.ts +10 -1
  84. package/dist/security/security-parser.js +10 -1
  85. package/dist/type-format.d.ts +2 -0
  86. package/dist/type-format.js +2 -0
  87. package/package.json +11 -3
  88. package/src/accessors/abstract-accessor.ts +23 -19
  89. package/src/accessors/abstract-integration-accessor.ts +27 -0
  90. package/src/accessors/formats/any-accessor.ts +11 -11
  91. package/src/accessors/formats/array-accessor.ts +2 -0
  92. package/src/accessors/formats/env-accessor.ts +2 -0
  93. package/src/accessors/formats/ini-accessor.ts +2 -0
  94. package/src/accessors/formats/json-accessor.ts +2 -0
  95. package/src/accessors/formats/ndjson-accessor.ts +2 -0
  96. package/src/accessors/formats/object-accessor.ts +2 -0
  97. package/src/accessors/formats/xml-accessor.ts +2 -0
  98. package/src/accessors/formats/yaml-accessor.ts +4 -2
  99. package/src/cache/simple-path-cache.ts +77 -0
  100. package/src/contracts/accessors-interface.ts +2 -0
  101. package/src/contracts/factory-accessors-interface.ts +2 -0
  102. package/src/contracts/filter-evaluator-interface.ts +30 -0
  103. package/src/contracts/parse-integration-interface.ts +2 -0
  104. package/src/contracts/parser-interface.ts +114 -0
  105. package/src/contracts/path-cache-interface.ts +8 -6
  106. package/src/contracts/readable-accessors-interface.ts +11 -6
  107. package/src/contracts/security-guard-interface.ts +2 -0
  108. package/src/contracts/security-parser-interface.ts +2 -0
  109. package/src/contracts/validatable-parser-interface.ts +64 -0
  110. package/src/contracts/writable-accessors-interface.ts +5 -0
  111. package/src/core/accessor-factory.ts +173 -0
  112. package/src/core/dot-notation-parser.ts +74 -11
  113. package/src/core/inline-builder-accessor.ts +163 -0
  114. package/src/exceptions/accessor-exception.ts +9 -0
  115. package/src/exceptions/invalid-format-exception.ts +5 -0
  116. package/src/exceptions/parser-exception.ts +4 -0
  117. package/src/exceptions/path-not-found-exception.ts +4 -0
  118. package/src/exceptions/readonly-violation-exception.ts +4 -0
  119. package/src/exceptions/security-exception.ts +6 -0
  120. package/src/exceptions/unsupported-type-exception.ts +4 -0
  121. package/src/exceptions/yaml-parse-exception.ts +4 -0
  122. package/src/index.ts +3 -1
  123. package/src/inline.ts +42 -120
  124. package/src/parser/xml-parser.ts +31 -10
  125. package/src/parser/yaml-parser.ts +310 -45
  126. package/src/path-query/segment-filter-parser.ts +444 -0
  127. package/src/path-query/segment-parser.ts +321 -0
  128. package/src/path-query/segment-path-resolver.ts +521 -0
  129. package/src/path-query/segment-type.ts +82 -0
  130. package/src/security/forbidden-keys.ts +5 -5
  131. package/src/security/security-guard.ts +7 -2
  132. package/src/security/security-parser.ts +18 -3
  133. package/src/type-format.ts +2 -0
  134. package/stryker.config.json +8 -10
  135. package/tests/accessors/abstract-accessor.test.ts +217 -0
  136. package/tests/accessors/abstract-integration-accessor.test.ts +37 -0
  137. package/tests/accessors/formats/any-accessor.test.ts +57 -0
  138. package/tests/accessors/formats/array-accessor.test.ts +42 -0
  139. package/tests/accessors/formats/env-accessor.test.ts +103 -0
  140. package/tests/accessors/formats/ini-accessor.test.ts +186 -0
  141. package/tests/accessors/{json-accessor.test.ts → formats/json-accessor.test.ts} +6 -6
  142. package/tests/accessors/formats/ndjson-accessor.test.ts +49 -0
  143. package/tests/accessors/formats/object-accessor.test.ts +172 -0
  144. package/tests/accessors/formats/xml-accessor.test.ts +162 -0
  145. package/tests/accessors/formats/yaml-accessor.test.ts +36 -0
  146. package/tests/cache/simple-path-cache.test.ts +168 -0
  147. package/tests/core/accessor-factory.test.ts +157 -0
  148. package/tests/core/dot-notation-parser-edge-cases.test.ts +415 -0
  149. package/tests/core/dot-notation-parser.test.ts +0 -288
  150. package/tests/core/inline-builder-accessor.test.ts +114 -0
  151. package/tests/exceptions/accessor-exception.test.ts +28 -0
  152. package/tests/exceptions/invalid-format-exception.test.ts +31 -0
  153. package/tests/exceptions/path-not-found-exception.test.ts +33 -0
  154. package/tests/exceptions/readonly-violation-exception.test.ts +35 -0
  155. package/tests/exceptions/security-exception.test.ts +33 -0
  156. package/tests/exceptions/unsupported-type-exception.test.ts +33 -0
  157. package/tests/exceptions/yaml-parse-exception.test.ts +38 -0
  158. package/tests/mocks/fake-path-cache.ts +4 -3
  159. package/tests/parity-from.test.ts +118 -0
  160. package/tests/parity.test.ts +227 -10
  161. package/tests/parser/xml-parser-mutations.test.ts +579 -0
  162. package/tests/parser/xml-parser-scanner.test.ts +332 -0
  163. package/tests/parser/xml-parser.test.ts +10 -334
  164. package/tests/parser/yaml-parser-mutations.test.ts +750 -0
  165. package/tests/parser/yaml-parser.test.ts +844 -18
  166. package/tests/path-query/segment-filter-parser-mutations.test.ts +735 -0
  167. package/tests/path-query/segment-filter-parser.test.ts +1091 -0
  168. package/tests/path-query/segment-parser-mutations.test.ts +539 -0
  169. package/tests/path-query/segment-parser.test.ts +606 -0
  170. package/tests/path-query/segment-path-resolver-mutations.test.ts +626 -0
  171. package/tests/path-query/segment-path-resolver.test.ts +1009 -0
  172. package/tests/security/security-guard-advanced.test.ts +413 -0
  173. package/tests/security/security-guard-forbidden-keys.test.ts +87 -0
  174. package/tests/security/security-guard.test.ts +3 -484
  175. package/tests/security/security-parser.test.ts +18 -14
  176. package/vitest.config.ts +3 -3
  177. package/benchmarks/get.bench.ts +0 -26
  178. package/benchmarks/parse.bench.ts +0 -41
  179. package/tests/accessors/accessors.test.ts +0 -1017
package/src/index.ts CHANGED
@@ -19,7 +19,9 @@ export { NdjsonAccessor } from './accessors/formats/ndjson-accessor.js';
19
19
  export { AnyAccessor } from './accessors/formats/any-accessor.js';
20
20
 
21
21
  // Core
22
- // NOTE: DotNotationParser is intentionally not exported it is an internal component.
22
+ // NOTE: DotNotationParser is intentionally not exported - it is an internal component.
23
+
24
+ // Cache - SimplePathCache is @internal; consumers must use PathCacheInterface
23
25
 
24
26
  // Security
25
27
  export { SecurityGuard } from './security/security-guard.js';
package/src/inline.ts CHANGED
@@ -1,12 +1,10 @@
1
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
2
  import type { SecurityGuardInterface } from './contracts/security-guard-interface.js';
6
3
  import type { SecurityParserInterface } from './contracts/security-parser-interface.js';
7
4
  import type { AccessorsInterface } from './contracts/accessors-interface.js';
8
5
  import type { ParseIntegrationInterface } from './contracts/parse-integration-interface.js';
9
6
  import type { PathCacheInterface } from './contracts/path-cache-interface.js';
7
+ import type { ValidatableParserInterface } from './contracts/validatable-parser-interface.js';
10
8
  import { AbstractAccessor } from './accessors/abstract-accessor.js';
11
9
  import { ArrayAccessor } from './accessors/formats/array-accessor.js';
12
10
  import { ObjectAccessor } from './accessors/formats/object-accessor.js';
@@ -18,7 +16,7 @@ import { EnvAccessor } from './accessors/formats/env-accessor.js';
18
16
  import { NdjsonAccessor } from './accessors/formats/ndjson-accessor.js';
19
17
  import { AnyAccessor } from './accessors/formats/any-accessor.js';
20
18
  import { UnsupportedTypeException } from './exceptions/unsupported-type-exception.js';
21
- import { InvalidFormatException } from './exceptions/invalid-format-exception.js';
19
+ import { InlineBuilderAccessor } from './core/inline-builder-accessor.js';
22
20
 
23
21
  /**
24
22
  * Facade for creating typed data accessors fluently.
@@ -27,6 +25,8 @@ import { InvalidFormatException } from './exceptions/invalid-format-exception.js
27
25
  * Use the builder methods (`withSecurityGuard`, `withSecurityParser`) to
28
26
  * customize the security configuration before creating an accessor.
29
27
  *
28
+ * @api
29
+ *
30
30
  * @example
31
31
  * const accessor = Inline.fromJson('{"name":"Alice"}');
32
32
  * accessor.get('name'); // 'Alice'
@@ -35,100 +35,12 @@ import { InvalidFormatException } from './exceptions/invalid-format-exception.js
35
35
  * const accessor = Inline.from(TypeFormat.Yaml, 'name: Alice');
36
36
  * accessor.get('name'); // 'Alice'
37
37
  */
38
- export class Inline {
39
- private readonly guard: SecurityGuardInterface;
40
- private readonly secParser: SecurityParserInterface;
41
- private readonly pathCache: PathCacheInterface | null;
42
- private readonly integration: ParseIntegrationInterface | null;
43
- private readonly strictMode: boolean | null;
44
-
45
- private constructor(
46
- guard: SecurityGuardInterface,
47
- secParser: SecurityParserInterface,
48
- pathCache: PathCacheInterface | null = null,
49
- integration: ParseIntegrationInterface | null = null,
50
- strictMode: boolean | null = null,
51
- ) {
52
- this.guard = guard;
53
- this.secParser = secParser;
54
- this.pathCache = pathCache;
55
- this.integration = integration;
56
- this.strictMode = strictMode;
57
- }
58
-
38
+ export class Inline extends InlineBuilderAccessor {
59
39
  private static defaultInstance(): Inline {
60
- return new Inline(new SecurityGuard(), new SecurityParser());
40
+ return new Inline();
61
41
  }
62
42
 
63
- private makeParser(): DotNotationParser {
64
- return new DotNotationParser(this.guard, this.secParser, this.pathCache ?? undefined);
65
- }
66
-
67
- /**
68
- * Apply configured strict mode to a new accessor before hydration.
69
- *
70
- * @param accessor - Unhydrated accessor instance.
71
- * @returns Same accessor with strict mode applied if configured.
72
- */
73
- private prepare<T extends AbstractAccessor>(accessor: T): T {
74
- if (this.strictMode !== null) {
75
- return accessor.strict(this.strictMode) as T;
76
- }
77
- return accessor;
78
- }
79
-
80
- /**
81
- * Return a new Inline instance with a custom SecurityGuard, preserving other settings.
82
- *
83
- * @param guard - Custom security guard implementation.
84
- * @returns New Inline builder instance.
85
- */
86
- withSecurityGuard(guard: SecurityGuardInterface): Inline {
87
- return new Inline(guard, this.secParser, this.pathCache, this.integration, this.strictMode);
88
- }
89
-
90
- /**
91
- * Return a new Inline instance with a custom SecurityParser, preserving other settings.
92
- *
93
- * @param parser - Custom security parser implementation.
94
- * @returns New Inline builder instance.
95
- */
96
- withSecurityParser(parser: SecurityParserInterface): Inline {
97
- return new Inline(this.guard, parser, this.pathCache, this.integration, this.strictMode);
98
- }
99
-
100
- /**
101
- * Return a new Inline instance with a custom path cache, preserving other settings.
102
- *
103
- * @param cache - Custom path cache implementation.
104
- * @returns New Inline builder instance.
105
- */
106
- withPathCache(cache: PathCacheInterface): Inline {
107
- return new Inline(this.guard, this.secParser, cache, this.integration, this.strictMode);
108
- }
109
-
110
- /**
111
- * Return a new Inline instance with a custom parser integration, preserving other settings.
112
- *
113
- * @param integration - Custom format integration implementation.
114
- * @returns New Inline builder instance.
115
- */
116
- withParserIntegration(integration: ParseIntegrationInterface): Inline {
117
- return new Inline(this.guard, this.secParser, this.pathCache, integration, this.strictMode);
118
- }
119
-
120
- /**
121
- * Return a new Inline instance with the given strict mode, preserving other settings.
122
- *
123
- * @param strict - Whether to enable strict security validation.
124
- * @returns New Inline builder instance.
125
- *
126
- * @security Passing `false` disables all SecurityGuard and SecurityParser
127
- * validation. Only use with fully trusted, application-controlled input.
128
- */
129
- withStrictMode(strict: boolean): Inline {
130
- return new Inline(this.guard, this.secParser, this.pathCache, this.integration, strict);
131
- }
43
+ // ── Instance factory methods ──────────────────────────────────────
132
44
 
133
45
  /**
134
46
  * Return a new Inline instance with a custom SecurityGuard.
@@ -140,7 +52,7 @@ export class Inline {
140
52
  * Inline.withSecurityGuard(new SecurityGuard(10, ['extraKey'])).fromJson('{}');
141
53
  */
142
54
  static withSecurityGuard(guard: SecurityGuardInterface): Inline {
143
- return new Inline(guard, new SecurityParser());
55
+ return new Inline(guard);
144
56
  }
145
57
 
146
58
  /**
@@ -153,7 +65,7 @@ export class Inline {
153
65
  * Inline.withSecurityParser(new SecurityParser({ maxDepth: 10 })).fromJson('{}');
154
66
  */
155
67
  static withSecurityParser(parser: SecurityParserInterface): Inline {
156
- return new Inline(new SecurityGuard(), parser);
68
+ return new Inline(undefined, parser);
157
69
  }
158
70
 
159
71
  /**
@@ -167,7 +79,7 @@ export class Inline {
167
79
  * Inline.withPathCache(cache).fromJson('{"key":"value"}');
168
80
  */
169
81
  static withPathCache(cache: PathCacheInterface): Inline {
170
- return new Inline(new SecurityGuard(), new SecurityParser(), cache);
82
+ return new Inline(undefined, undefined, cache);
171
83
  }
172
84
 
173
85
  /**
@@ -180,7 +92,7 @@ export class Inline {
180
92
  * Inline.withParserIntegration(new MyCsvIntegration()).fromAny(csvString);
181
93
  */
182
94
  static withParserIntegration(integration: ParseIntegrationInterface): Inline {
183
- return new Inline(new SecurityGuard(), new SecurityParser(), null, integration);
95
+ return new Inline(undefined, undefined, null, integration);
184
96
  }
185
97
 
186
98
  /**
@@ -196,7 +108,7 @@ export class Inline {
196
108
  * Inline.withStrictMode(false).fromJson(hugePayload).get('key');
197
109
  */
198
110
  static withStrictMode(strict: boolean): Inline {
199
- return new Inline(new SecurityGuard(), new SecurityParser(), null, null, strict);
111
+ return new Inline(undefined, undefined, null, null, strict);
200
112
  }
201
113
 
202
114
  /**
@@ -210,7 +122,7 @@ export class Inline {
210
122
  * inline.fromArray({ name: 'Alice' }).get('name'); // 'Alice'
211
123
  */
212
124
  fromArray(data: Record<string, unknown> | unknown[]): ArrayAccessor {
213
- return this.prepare(new ArrayAccessor(this.makeParser())).from(data);
125
+ return this.builder().array(data);
214
126
  }
215
127
 
216
128
  /**
@@ -224,7 +136,7 @@ export class Inline {
224
136
  * inline.fromObject({ user: { name: 'Alice' } }).get('user.name');
225
137
  */
226
138
  fromObject(data: object): ObjectAccessor {
227
- return this.prepare(new ObjectAccessor(this.makeParser())).from(data);
139
+ return this.builder().object(data);
228
140
  }
229
141
 
230
142
  /**
@@ -239,12 +151,15 @@ export class Inline {
239
151
  * inline.fromJson('{"key":"value"}').get('key'); // 'value'
240
152
  */
241
153
  fromJson(data: string): JsonAccessor {
242
- return this.prepare(new JsonAccessor(this.makeParser())).from(data);
154
+ return this.builder().json(data);
243
155
  }
244
156
 
245
157
  /**
246
158
  * Create an XmlAccessor from an XML string.
247
159
  *
160
+ * Note: The PHP equivalent also accepts `\SimpleXMLElement`; JS only
161
+ * accepts raw XML strings (no pre-parsed equivalent exists in JS).
162
+ *
248
163
  * @param data - Raw XML string.
249
164
  * @returns Populated XmlAccessor instance.
250
165
  * @throws {InvalidFormatException} When the XML is malformed.
@@ -254,7 +169,7 @@ export class Inline {
254
169
  * inline.fromXml('<root><key>value</key></root>').get('key');
255
170
  */
256
171
  fromXml(data: string): XmlAccessor {
257
- return this.prepare(new XmlAccessor(this.makeParser())).from(data);
172
+ return this.builder().xml(data);
258
173
  }
259
174
 
260
175
  /**
@@ -269,7 +184,7 @@ export class Inline {
269
184
  * inline.fromYaml('name: Alice').get('name'); // 'Alice'
270
185
  */
271
186
  fromYaml(data: string): YamlAccessor {
272
- return this.prepare(new YamlAccessor(this.makeParser())).from(data);
187
+ return this.builder().yaml(data);
273
188
  }
274
189
 
275
190
  /**
@@ -284,7 +199,7 @@ export class Inline {
284
199
  * inline.fromIni('[section]\nkey=value').get('section.key'); // 'value'
285
200
  */
286
201
  fromIni(data: string): IniAccessor {
287
- return this.prepare(new IniAccessor(this.makeParser())).from(data);
202
+ return this.builder().ini(data);
288
203
  }
289
204
 
290
205
  /**
@@ -298,7 +213,7 @@ export class Inline {
298
213
  * inline.fromEnv('APP_NAME=MyApp').get('APP_NAME'); // 'MyApp'
299
214
  */
300
215
  fromEnv(data: string): EnvAccessor {
301
- return this.prepare(new EnvAccessor(this.makeParser())).from(data);
216
+ return this.builder().env(data);
302
217
  }
303
218
 
304
219
  /**
@@ -313,7 +228,7 @@ export class Inline {
313
228
  * inline.fromNdjson('{"id":1}\n{"id":2}').get('0.id'); // 1
314
229
  */
315
230
  fromNdjson(data: string): NdjsonAccessor {
316
- return this.prepare(new NdjsonAccessor(this.makeParser())).from(data);
231
+ return this.builder().ndjson(data);
317
232
  }
318
233
 
319
234
  /**
@@ -332,18 +247,15 @@ export class Inline {
332
247
  * Inline.withParserIntegration(new CsvIntegration()).fromAny(csvString);
333
248
  */
334
249
  fromAny(data: unknown, integration?: ParseIntegrationInterface): AnyAccessor {
335
- const resolved = integration ?? this.integration;
336
- if (resolved === null) {
337
- throw new InvalidFormatException(
338
- 'AnyAccessor requires a ParseIntegrationInterface — use Inline.withParserIntegration(integration).fromAny(data).',
339
- );
340
- }
341
- return this.prepare(new AnyAccessor(this.makeParser(), resolved)).from(data);
250
+ return this.builder().any(data, integration);
342
251
  }
343
252
 
344
253
  /**
345
254
  * Create a typed accessor by its constructor.
346
255
  *
256
+ * Note: The PHP equivalent accepts a class-string (FQCN) instead of a
257
+ * constructor reference, e.g. `Inline::make(JsonAccessor::class, $data)`.
258
+ *
347
259
  * @param AccessorConstructor - The accessor class to instantiate.
348
260
  * @param data - Raw data to hydrate the accessor with.
349
261
  * @returns Populated accessor instance.
@@ -352,12 +264,13 @@ export class Inline {
352
264
  * Inline.make(JsonAccessor, '{"key":"value"}').get('key'); // 'value'
353
265
  */
354
266
  make<T extends AccessorsInterface>(
355
- AccessorConstructor: new (parser: DotNotationParser) => T,
267
+ AccessorConstructor: new (parser: ValidatableParserInterface) => T,
356
268
  data: unknown,
357
269
  ): T {
358
- const accessor = new AccessorConstructor(this.makeParser());
359
- if (this.strictMode !== null && accessor instanceof AbstractAccessor) {
360
- return (accessor.strict(this.strictMode) as T).from(data);
270
+ const factory = this.builder();
271
+ const accessor = new AccessorConstructor(factory.getParser());
272
+ if (this._strictMode !== null && accessor instanceof AbstractAccessor) {
273
+ return (accessor.strict(this._strictMode) as T).from(data);
361
274
  }
362
275
  return accessor.from(data);
363
276
  }
@@ -371,6 +284,9 @@ export class Inline {
371
284
  * @throws {InvalidFormatException} When the data is malformed for the target format.
372
285
  * @throws {SecurityException} When security constraints are violated.
373
286
  * @throws {UnsupportedTypeException} When the TypeFormat is not supported.
287
+ *
288
+ * @example
289
+ * Inline.from(TypeFormat.Json, '{"key":"value"}').get('key'); // 'value'
374
290
  */
375
291
  from(typeFormat: TypeFormat, data: unknown): AccessorsInterface {
376
292
  switch (typeFormat) {
@@ -447,6 +363,9 @@ export class Inline {
447
363
  /**
448
364
  * Create an XmlAccessor from an XML string.
449
365
  *
366
+ * Note: The PHP equivalent also accepts `\SimpleXMLElement`; JS only
367
+ * accepts raw XML strings (no pre-parsed equivalent exists in JS).
368
+ *
450
369
  * @param data - Raw XML string.
451
370
  * @returns Populated XmlAccessor instance.
452
371
  * @throws {InvalidFormatException} When the XML is malformed.
@@ -554,6 +473,9 @@ export class Inline {
554
473
  /**
555
474
  * Create a typed accessor by its constructor.
556
475
  *
476
+ * Note: The PHP equivalent accepts a class-string (FQCN) instead of a
477
+ * constructor reference, e.g. `Inline::make(JsonAccessor::class, $data)`.
478
+ *
557
479
  * @param AccessorConstructor - The accessor class to instantiate.
558
480
  * @param data - Raw data to hydrate the accessor with.
559
481
  * @returns Populated accessor instance.
@@ -562,7 +484,7 @@ export class Inline {
562
484
  * Inline.make(JsonAccessor, '{"key":"value"}').get('key'); // 'value'
563
485
  */
564
486
  static make<T extends AccessorsInterface>(
565
- AccessorConstructor: new (parser: DotNotationParser) => T,
487
+ AccessorConstructor: new (parser: ValidatableParserInterface) => T,
566
488
  data: unknown,
567
489
  ): T {
568
490
  return Inline.defaultInstance().make(AccessorConstructor, data);
@@ -23,9 +23,7 @@ export class XmlParser {
23
23
  */
24
24
  constructor(maxDepth: number, maxElements: number = 10_000) {
25
25
  this.maxDepth = maxDepth;
26
- this.maxElements = Number.isFinite(maxElements) && maxElements >= 1
27
- ? maxElements
28
- : 10_000;
26
+ this.maxElements = Number.isFinite(maxElements) && maxElements >= 1 ? maxElements : 10_000;
29
27
  }
30
28
 
31
29
  /**
@@ -114,7 +112,7 @@ export class XmlParser {
114
112
  const stripped = xml.replace(/<\?xml[^?]*\?>/i, '').trim();
115
113
 
116
114
  // Bound parser complexity before the linear inner-content scan: count opening
117
- // tags as a document-complexity proxy. This is a defence-in-depth limit
115
+ // tags as a document-complexity proxy. This is a defence-in-depth limit -
118
116
  // the linear scanner below is already O(n), but bounding element count also
119
117
  // caps the total number of recursive parseXmlChildren calls.
120
118
  // Browser environments (DOMParser) are unaffected.
@@ -168,9 +166,12 @@ export class XmlParser {
168
166
  }
169
167
 
170
168
  // Walk backward from the final '>' to locate the closing tag for this root element.
171
- // This is O(tagNameLen) the tag name is typically short and always bounded.
169
+ // This is O(tagNameLen) - the tag name is typically short and always bounded.
172
170
  let pos = doc.length - 2;
173
- while (pos >= 0 && (doc[pos] === ' ' || doc[pos] === '\t' || doc[pos] === '\n' || doc[pos] === '\r')) {
171
+ while (
172
+ pos >= 0 &&
173
+ (doc[pos] === ' ' || doc[pos] === '\t' || doc[pos] === '\n' || doc[pos] === '\r')
174
+ ) {
174
175
  pos--;
175
176
  }
176
177
 
@@ -258,7 +259,14 @@ export class XmlParser {
258
259
 
259
260
  if (content.startsWith(closeTag, nextLt)) {
260
261
  const c = content[nextLt + closeTag.length];
261
- if (c === '>' || c === ' ' || c === '\t' || c === '\n' || c === '\r' || c === undefined) {
262
+ if (
263
+ c === '>' ||
264
+ c === ' ' ||
265
+ c === '\t' ||
266
+ c === '\n' ||
267
+ c === '\r' ||
268
+ c === undefined
269
+ ) {
262
270
  nestDepth--;
263
271
  if (nestDepth === 0) {
264
272
  innerEnd = nextLt;
@@ -273,9 +281,22 @@ export class XmlParser {
273
281
 
274
282
  if (content.startsWith(openPrefix, nextLt)) {
275
283
  const c = content[nextLt + openPrefix.length];
276
- if (c === '>' || c === ' ' || c === '\t' || c === '\n' || c === '\r' || c === '/') {
284
+ if (
285
+ c === '>' ||
286
+ c === ' ' ||
287
+ c === '\t' ||
288
+ c === '\n' ||
289
+ c === '\r' ||
290
+ c === '/'
291
+ ) {
277
292
  const ogt = content.indexOf('>', nextLt + openPrefix.length);
278
- if (ogt !== -1 && !content.slice(nextLt + openPrefix.length, ogt).trimEnd().endsWith('/')) {
293
+ if (
294
+ ogt !== -1 &&
295
+ !content
296
+ .slice(nextLt + openPrefix.length, ogt)
297
+ .trimEnd()
298
+ .endsWith('/')
299
+ ) {
279
300
  nestDepth++;
280
301
  }
281
302
  }
@@ -285,7 +306,7 @@ export class XmlParser {
285
306
  }
286
307
 
287
308
  if (innerEnd === -1) {
288
- // Unclosed or malformed tag skip past the opening tag
309
+ // Unclosed or malformed tag - skip past the opening tag
289
310
  i = gt + 1;
290
311
  continue;
291
312
  }