yini-parser 1.4.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +187 -35
  3. package/dist/YINI.d.ts +29 -18
  4. package/dist/YINI.js +104 -3
  5. package/dist/core/astBuilder.d.ts +94 -18
  6. package/dist/core/astBuilder.js +439 -376
  7. package/dist/core/errorDataHandler.d.ts +6 -1
  8. package/dist/core/errorDataHandler.js +30 -43
  9. package/dist/core/internalTypes.d.ts +10 -1
  10. package/dist/core/objectBuilder.d.ts +8 -4
  11. package/dist/core/objectBuilder.js +47 -62
  12. package/dist/core/options/defaultParserOptions.d.ts +3 -2
  13. package/dist/core/options/defaultParserOptions.js +11 -2
  14. package/dist/core/options/optionsFunctions.js +6 -4
  15. package/dist/core/parsingRules/modeFromRulesMatcher.d.ts +1 -1
  16. package/dist/core/parsingRules/modeFromRulesMatcher.js +22 -13
  17. package/dist/core/pipeline/pipeline.js +35 -10
  18. package/dist/core/runtime.js +28 -19
  19. package/dist/grammar/generated/YiniLexer.d.ts +40 -53
  20. package/dist/grammar/generated/YiniLexer.js +357 -356
  21. package/dist/grammar/generated/YiniParser.d.ts +174 -118
  22. package/dist/grammar/generated/YiniParser.js +1185 -929
  23. package/dist/grammar/generated/YiniParserVisitor.d.ts +82 -19
  24. package/dist/grammar/generated/YiniParserVisitor.js +1 -1
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +4 -3
  27. package/dist/parsers/extractHeaderParts.d.ts +12 -19
  28. package/dist/parsers/extractHeaderParts.js +57 -46
  29. package/dist/parsers/parseNumber.d.ts +24 -6
  30. package/dist/parsers/parseNumber.js +114 -49
  31. package/dist/parsers/parseSectionHeader.d.ts +11 -3
  32. package/dist/parsers/parseSectionHeader.js +55 -43
  33. package/dist/parsers/parseString.js +39 -20
  34. package/dist/parsers/validateShebangPlacement.d.ts +3 -0
  35. package/dist/parsers/validateShebangPlacement.js +52 -0
  36. package/dist/types/index.d.ts +20 -3
  37. package/dist/utils/print.d.ts +1 -0
  38. package/dist/utils/print.js +5 -1
  39. package/dist/utils/string.d.ts +1 -0
  40. package/dist/utils/string.js +17 -1
  41. package/dist/utils/system.d.ts +1 -0
  42. package/dist/utils/system.js +6 -1
  43. package/dist/utils/yiniHelpers.d.ts +44 -2
  44. package/dist/utils/yiniHelpers.js +134 -46
  45. package/examples/compare-formats.md +1 -1
  46. package/examples/nested.yini +1 -1
  47. package/package.json +11 -3
  48. package/dist/YINI.js.map +0 -1
  49. package/dist/config/env.js.map +0 -1
  50. package/dist/core/astBuilder.js.map +0 -1
  51. package/dist/core/errorDataHandler.js.map +0 -1
  52. package/dist/core/internalTypes.js.map +0 -1
  53. package/dist/core/objectBuilder.js.map +0 -1
  54. package/dist/core/options/defaultParserOptions.js.map +0 -1
  55. package/dist/core/options/failLevel.js.map +0 -1
  56. package/dist/core/options/optionsFunctions.js.map +0 -1
  57. package/dist/core/parsingRules/modeFromRulesMatcher.js.map +0 -1
  58. package/dist/core/parsingRules/rulesConstAndGuards.js.map +0 -1
  59. package/dist/core/pipeline/errorListeners.js.map +0 -1
  60. package/dist/core/pipeline/pipeline.js.map +0 -1
  61. package/dist/core/resultMetadataBuilder.js.map +0 -1
  62. package/dist/core/runtime.js.map +0 -1
  63. package/dist/dev/main.d.ts +0 -1
  64. package/dist/dev/main.js +0 -168
  65. package/dist/dev/main.js.map +0 -1
  66. package/dist/dev/quick-test-samples/defect-inputs.d.ts +0 -37
  67. package/dist/dev/quick-test-samples/defect-inputs.js +0 -106
  68. package/dist/dev/quick-test-samples/defect-inputs.js.map +0 -1
  69. package/dist/dev/quick-test-samples/valid-inputs.d.ts +0 -21
  70. package/dist/dev/quick-test-samples/valid-inputs.js +0 -422
  71. package/dist/dev/quick-test-samples/valid-inputs.js.map +0 -1
  72. package/dist/grammar/generated/YiniLexer.js.map +0 -1
  73. package/dist/grammar/generated/YiniParser.js.map +0 -1
  74. package/dist/grammar/generated/YiniParserVisitor.js.map +0 -1
  75. package/dist/index.js.map +0 -1
  76. package/dist/parsers/extractHeaderParts.js.map +0 -1
  77. package/dist/parsers/extractSignificantYiniLine.js.map +0 -1
  78. package/dist/parsers/parseBoolean.js.map +0 -1
  79. package/dist/parsers/parseNull.js.map +0 -1
  80. package/dist/parsers/parseNumber.js.map +0 -1
  81. package/dist/parsers/parseSectionHeader.js.map +0 -1
  82. package/dist/parsers/parseString.js.map +0 -1
  83. package/dist/types/index.js.map +0 -1
  84. package/dist/utils/number.js.map +0 -1
  85. package/dist/utils/object.js.map +0 -1
  86. package/dist/utils/pathAndFileName.js.map +0 -1
  87. package/dist/utils/print.js.map +0 -1
  88. package/dist/utils/string.js.map +0 -1
  89. package/dist/utils/system.js.map +0 -1
  90. package/dist/utils/yiniHelpers.js.map +0 -1
@@ -8,6 +8,7 @@ export declare class ErrorDataHandler {
8
8
  private readonly subjectType;
9
9
  private readonly fileName;
10
10
  private readonly persistThreshold;
11
+ private readonly isDiagnosticOutputEnabled;
11
12
  private readonly isQuiet;
12
13
  private readonly isSilent;
13
14
  private readonly isThrowOnError;
@@ -30,7 +31,8 @@ export declare class ErrorDataHandler {
30
31
  - Level 1 = abort on errors only
31
32
  - Level 2 = abort even on warnings
32
33
  */
33
- constructor(subjectType: TSubjectType, fileName?: string | undefined, bailSensitivityLevel?: TBailSensitivityLevel, isQuiet?: boolean, // Reduce output (show only errors, does not effect warnings and etc. in meta data).
34
+ constructor(subjectType: TSubjectType, fileName?: string | undefined, bailSensitivityLevel?: TBailSensitivityLevel, isDiagnosticOutputEnabled?: boolean, // Opt in to writing diagnostics to stderr.
35
+ isQuiet?: boolean, // When diagnostic output is enabled, show errors only.
34
36
  isSilent?: boolean, // Suppress all output (even errors, exit code only).
35
37
  isThrowOnError?: boolean);
36
38
  private makeIssue;
@@ -50,6 +52,9 @@ export declare class ErrorDataHandler {
50
52
  */
51
53
  pushOrBail(locInput: IErrorLocationInput | undefined, type: TIssueType, msgWhat: string, msgWhy?: string, msgHint?: string): void;
52
54
  private formatSignificantMessageLine;
55
+ private shouldEmitDiagnostics;
56
+ private shouldEmitNonErrors;
57
+ private emitDiagnosticToStderr;
53
58
  private emitFatalError;
54
59
  private emitInternalError;
55
60
  private emitSyntaxError;
@@ -42,7 +42,8 @@ class ErrorDataHandler {
42
42
  - Level 1 = abort on errors only
43
43
  - Level 2 = abort even on warnings
44
44
  */
45
- constructor(subjectType, fileName = undefined, bailSensitivityLevel = '1-Abort-on-Errors', isQuiet = false, // Reduce output (show only errors, does not effect warnings and etc. in meta data).
45
+ constructor(subjectType, fileName = undefined, bailSensitivityLevel = '1-Abort-on-Errors', isDiagnosticOutputEnabled = false, // Opt in to writing diagnostics to stderr.
46
+ isQuiet = false, // When diagnostic output is enabled, show errors only.
46
47
  isSilent = false, // Suppress all output (even errors, exit code only).
47
48
  isThrowOnError = false) {
48
49
  this.errors = [];
@@ -58,6 +59,7 @@ class ErrorDataHandler {
58
59
  this.subjectType = subjectType;
59
60
  this.fileName = fileName;
60
61
  this.persistThreshold = bailSensitivityLevel;
62
+ this.isDiagnosticOutputEnabled = isDiagnosticOutputEnabled;
61
63
  this.isQuiet = isQuiet;
62
64
  this.isSilent = isSilent;
63
65
  this.isThrowOnError = isThrowOnError;
@@ -118,8 +120,8 @@ class ErrorDataHandler {
118
120
  lineNum: lineNum || 0, // 1-based, if n/a use 0.
119
121
  colNum: colNum || 0, // 1-based, if n/a use 0.
120
122
  };
121
- if (!this.isSilent) {
122
- console.log(); // Print an empty line before outputting message.
123
+ if (this.shouldEmitDiagnostics()) {
124
+ console.error(); // Print an empty line before outputting message.
123
125
  }
124
126
  switch (type) {
125
127
  case 'Internal-Error':
@@ -229,68 +231,53 @@ class ErrorDataHandler {
229
231
  }
230
232
  }
231
233
  }
232
- /*
233
- * - error/warning → console.error / console.warn
234
- * - notice/info → console.log / console.info
235
- */
234
+ shouldEmitDiagnostics() {
235
+ return this.isDiagnosticOutputEnabled && !this.isSilent;
236
+ }
237
+ shouldEmitNonErrors() {
238
+ return this.shouldEmitDiagnostics() && !this.isQuiet;
239
+ }
240
+ emitDiagnosticToStderr(write, messageHeader, msgWhat = '', msgWhy = '', msgHint = '') {
241
+ write(messageHeader);
242
+ msgWhat && write(msgWhat);
243
+ msgWhy && write(msgWhy);
244
+ msgHint && write(msgHint);
245
+ write();
246
+ }
236
247
  emitFatalError(loc, msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') {
237
248
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[0]);
238
- if (!this.isSilent) {
239
- console.error(messageHeader); // Print the issue title.
240
- msgWhat && console.log(msgWhat);
241
- msgWhy && console.log(msgWhy);
242
- msgHint && console.log(msgHint);
243
- console.log(); // Emit an empty line before outputting message.
249
+ if (this.shouldEmitDiagnostics()) {
250
+ this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
244
251
  }
245
252
  }
246
253
  emitInternalError(loc, msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') {
247
254
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[1]);
248
- if (!this.isSilent) {
249
- console.error(messageHeader); // Print the issue title.
250
- msgWhat && console.log(msgWhat);
251
- msgWhy && console.log(msgWhy);
252
- msgHint && console.log(msgHint);
253
- console.log(); // Emit an empty line before outputting message.
255
+ if (this.shouldEmitDiagnostics()) {
256
+ this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
254
257
  }
255
258
  }
256
259
  emitSyntaxError(loc, msgWhat, msgWhy = '', msgHint = '') {
257
260
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[2]);
258
- if (!this.isSilent) {
259
- console.error(messageHeader); // Print the issue title.
260
- msgWhat && console.log(msgWhat);
261
- msgWhy && console.log(msgWhy);
262
- msgHint && console.log(msgHint);
263
- console.log(); // Emit an empty line before outputting message.
261
+ if (this.shouldEmitDiagnostics()) {
262
+ this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
264
263
  }
265
264
  }
266
265
  emitSyntaxWarning(loc, msgWhat, msgWhy = '', msgHint = '') {
267
266
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[3]);
268
- if (!this.isQuiet && !this.isSilent) {
269
- console.warn(messageHeader); // Print the issue title.
270
- msgWhat && console.log(msgWhat);
271
- msgWhy && console.log(msgWhy);
272
- msgHint && console.log(msgHint);
273
- console.log(); // Emit an empty line before outputting message.
267
+ if (this.shouldEmitNonErrors()) {
268
+ this.emitDiagnosticToStderr(console.warn.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
274
269
  }
275
270
  }
276
271
  emitNotice(loc, msgWhat, msgWhy = '', msgHint = '') {
277
272
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[4]);
278
- if (!this.isQuiet && !this.isSilent) {
279
- console.log(messageHeader); // Print the issue title.
280
- msgWhat && console.log(msgWhat);
281
- msgWhy && console.log(msgWhy);
282
- msgHint && console.log(msgHint);
283
- console.log(); // Emit an empty line before outputting message.
273
+ if (this.shouldEmitNonErrors()) {
274
+ this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
284
275
  }
285
276
  }
286
277
  emitInfo(loc, msgWhat, msgWhy = '', msgHint = '') {
287
278
  const messageHeader = this.formatSignificantMessageLine(loc, issueTitle[5]);
288
- if (!this.isQuiet && !this.isSilent) {
289
- console.info(messageHeader); // Print the issue title.
290
- msgWhat && console.log(msgWhat);
291
- msgWhy && console.log(msgWhy);
292
- msgHint && console.log(msgHint);
293
- console.log(); // Emit an empty line before outputting message.
279
+ if (this.shouldEmitNonErrors()) {
280
+ this.emitDiagnosticToStderr(console.error.bind(console), messageHeader, msgWhat, msgWhy, msgHint);
294
281
  }
295
282
  }
296
283
  getNumOfAllMessages() {
@@ -70,7 +70,7 @@ export type TObjectValue = {
70
70
  entries: Readonly<Record<string, TValueLiteral>>;
71
71
  tag: string | undefined;
72
72
  };
73
- type TStringKind = 'raw' | 'classic' | 'hyper' | 'triple-raw' | 'triple-classic';
73
+ type TStringKind = 'raw' | 'classic' | 'triple-raw' | 'triple-classic';
74
74
  export interface IParsedStringInput {
75
75
  strKind: TStringKind;
76
76
  value: string;
@@ -82,6 +82,13 @@ export interface IErrorLocationInput {
82
82
  endColumn?: number;
83
83
  }
84
84
  export type TIssueType = 'Fatal-Error' | 'Internal-Error' | 'Syntax-Error' | 'Syntax-Warning' | 'Notice' | 'Info';
85
+ export interface IPreflightIssue {
86
+ locInput: IErrorLocationInput | undefined;
87
+ type: TIssueType;
88
+ msgWhat: string;
89
+ msgWhy?: string;
90
+ msgHint?: string;
91
+ }
85
92
  interface IMetaBaseInfo {
86
93
  sourceType: TSourceType;
87
94
  fileName: string | undefined;
@@ -96,6 +103,7 @@ export interface IRuntimeInfo extends IMetaBaseInfo {
96
103
  timeIoMs: number | null;
97
104
  preferredBailSensitivity: null | PreferredFailLevel;
98
105
  sha256: string | null;
106
+ preflightIssues: IPreflightIssue[];
99
107
  }
100
108
  export interface IParseCoreOptions {
101
109
  rules: IParseRuleOptions;
@@ -104,6 +112,7 @@ export interface IParseCoreOptions {
104
112
  isWithDiagnostics: boolean;
105
113
  isWithTiming: boolean;
106
114
  isKeepUndefinedInMeta: boolean;
115
+ isDiagnosticOutputEnabled: boolean;
107
116
  isQuiet: boolean;
108
117
  isSilent: boolean;
109
118
  isThrowOnError: boolean;
@@ -1,11 +1,15 @@
1
1
  import { ErrorDataHandler } from './errorDataHandler';
2
2
  import { IYiniAST } from './internalTypes';
3
3
  /**
4
- * Construct the final JavaScript Object.
5
- * Transforms the AST to the plain JS object.
4
+ * Construct the final JavaScript object.
5
+ * Transforms the AST into a plain JS object.
6
6
  *
7
- * - Keys are used exactly as-is.
8
- * - Order of properties matches the AST traversal order.
7
+ * Behavior:
8
+ * - Explicit top-level sections are mounted directly on the result.
9
+ * - In lenient mode, orphan top-level members are also mounted directly
10
+ * on the result.
11
+ * - Any collision between an orphan member name and a top-level section
12
+ * name results in an error.
9
13
  *
10
14
  * @note All `tag` fields MUST be ignored.
11
15
  */
@@ -1,63 +1,71 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.astToObject = void 0;
4
+ // src/core/objectBuilder.ts
4
5
  const env_1 = require("../config/env");
5
6
  const print_1 = require("../utils/print");
6
7
  /**
7
- * Construct the final JavaScript Object.
8
- * Transforms the AST to the plain JS object.
8
+ * Construct the final JavaScript object.
9
+ * Transforms the AST into a plain JS object.
9
10
  *
10
- * - Keys are used exactly as-is.
11
- * - Order of properties matches the AST traversal order.
11
+ * Behavior:
12
+ * - Explicit top-level sections are mounted directly on the result.
13
+ * - In lenient mode, orphan top-level members are also mounted directly
14
+ * on the result.
15
+ * - Any collision between an orphan member name and a top-level section
16
+ * name results in an error.
12
17
  *
13
18
  * @note All `tag` fields MUST be ignored.
14
19
  */
20
+ // src/core/objectBuilder.ts
15
21
  const astToObject = (ast, errorHandler) => {
16
22
  (0, print_1.debugPrint)('-> constructFinalObject(..)');
17
- // return sectionChildrenToObject(ast.root)
18
23
  const out = {};
24
+ // 1) In lenient mode, mount orphan root members directly onto result.
25
+ if (!ast.isStrict) {
26
+ for (const [key, val] of ast.root.members) {
27
+ define(out, key, literalToJS(val));
28
+ }
29
+ }
30
+ // 2) Mount explicit top-level sections directly onto result.
19
31
  for (const child of ast.root.children) {
20
- define(out, child.sectionName, sectionToObject(child));
32
+ if (Object.prototype.hasOwnProperty.call(out, child.sectionName)) {
33
+ errorHandler.pushOrBail(undefined, 'Syntax-Error', `Name collision between orphan member and section '${child.sectionName}'`, `The name '${child.sectionName}' is already used by a top-level member outside any explicit section and cannot also be used as a top-level section name.`, `Rename either the orphan member or the section to avoid the collision.`);
34
+ continue;
35
+ }
36
+ // define(out, child.sectionName, sectionToObject(child))
37
+ define(out, child.sectionName, sectionToObject(child, errorHandler));
21
38
  }
22
39
  return out;
23
40
  };
24
41
  exports.astToObject = astToObject;
25
- /** Convert only the children of a section into an object keyed by sectionName. */
26
- // function sectionChildrenToObject(
27
- // section: YiniSection,
28
- // ): Record<string, unknown> {
29
- // const out: Record<string, unknown> = {}
30
- // for (const child of section.children) {
31
- // out[child.sectionName] = sectionToObject(child)
32
- // }
33
- // return out
34
- // }
35
- /** Convert a section (its members + nested sections) to a plain object. */
36
- // function sectionToObject(node: YiniSection): Record<string, unknown> {
42
+ /**
43
+ * Convert a section (members + nested sections) to a plain object,
44
+ * preserving insertion order.
45
+ */
46
+ // const sectionToObject = (node: IYiniSection): Record<string, unknown> => {
37
47
  // const obj: Record<string, unknown> = {}
38
- // // Members properties
39
- // for (const [key, val] of node.members.entries()) {
40
- // obj[key] = literalToJS(val)
48
+ // // 1) Members (Map preserves insertion order).
49
+ // for (const [key, val] of node.members) {
50
+ // define(obj, key, literalToJS(val))
41
51
  // }
42
- // // Nested sections nested objects keyed by sectionName
52
+ // // 2) Nested sections (array order preserved).
43
53
  // for (const child of node.children) {
44
- // obj[child.sectionName] = sectionToObject(child)
54
+ // define(obj, child.sectionName, sectionToObject(child))
45
55
  // }
46
56
  // return obj
47
57
  // }
48
- /**
49
- * Convert a section (members + nested sections) to a plain
50
- * object, preserving order.
51
- */
52
- const sectionToObject = (node) => {
58
+ const sectionToObject = (node, errorHandler) => {
53
59
  const obj = {};
54
- // 1) Members (Map preserves insertion order).
55
60
  for (const [key, val] of node.members) {
56
61
  define(obj, key, literalToJS(val));
57
62
  }
58
- // 2) Nested sections (array order preserved).
59
63
  for (const child of node.children) {
60
- define(obj, child.sectionName, sectionToObject(child));
64
+ if (Object.prototype.hasOwnProperty.call(obj, child.sectionName)) {
65
+ errorHandler.pushOrBail(undefined, 'Syntax-Error', `Name collision between member and subsection '${child.sectionName}'`, `The name '${child.sectionName}' is already used by a member in section '${node.sectionName}' and cannot also be used as a subsection name.`, 'Rename either the member or the subsection.');
66
+ continue;
67
+ }
68
+ define(obj, child.sectionName, sectionToObject(child, errorHandler));
61
69
  }
62
70
  return obj;
63
71
  };
@@ -72,12 +80,6 @@ const sectionToObject = (node) => {
72
80
  const literalToJS = (v) => {
73
81
  const IS_LOCAL_DEBUG = false;
74
82
  (0, print_1.debugPrint)('In literalToJS(..)');
75
- // if (!v) {
76
- // // NOTE: Only in lenient-mode, if parsing a
77
- // // member (key = value), but the value is invalid
78
- // // key will get undefined
79
- // return undefined
80
- // }
81
83
  switch (v.type) {
82
84
  case 'String':
83
85
  case 'Number':
@@ -96,37 +98,20 @@ const literalToJS = (v) => {
96
98
  }
97
99
  const out = v.elems.map((elem) => {
98
100
  const ret = literalToJS(elem);
99
- if (IS_LOCAL_DEBUG) {
100
- if ((0, env_1.isDebug)()) {
101
- console.log(`elem:`);
102
- (0, print_1.printObject)(elem);
103
- }
101
+ if (IS_LOCAL_DEBUG && (0, env_1.isDebug)()) {
102
+ console.log('elem:');
103
+ (0, print_1.printObject)(elem);
104
104
  }
105
105
  return ret;
106
106
  });
107
- if (IS_LOCAL_DEBUG) {
108
- if ((0, env_1.isDebug)()) {
109
- console.log('Returning:');
110
- (0, print_1.printObject)(out);
111
- }
107
+ if (IS_LOCAL_DEBUG && (0, env_1.isDebug)()) {
108
+ console.log('Returning:');
109
+ (0, print_1.printObject)(out);
112
110
  }
113
111
  return out;
114
112
  }
115
113
  case 'Object': {
116
114
  const out = {};
117
- // for (const key of Object.keys(v.entries)) {
118
- // const entry = v.entries[key]
119
- // if (isScalar(entry)) {
120
- // // Scalar entries in object-literals: value
121
- // // out[key] = { type: entry.type, value: entry.value }
122
- // out[key] = entry.value
123
- // } else if (entry.type === 'List') {
124
- // out[key] = entry.elems.map(literalToJS)
125
- // } else {
126
- // out[key] = literalToJS(entry) // nested object-literal
127
- // }
128
- // }
129
- // Object.keys preserves property insertion order for plain objects
130
115
  for (const k of Object.keys(v.entries)) {
131
116
  define(out, k, literalToJS(v.entries[k]));
132
117
  }
@@ -135,8 +120,8 @@ const literalToJS = (v) => {
135
120
  }
136
121
  };
137
122
  /**
138
- * Helper function, defines a property to preserve explicit insertion
139
- * order and enumerability.
123
+ * Helper function that defines a property while preserving explicit
124
+ * insertion order and enumerability.
140
125
  */
141
126
  const define = (obj, key, value) => {
142
127
  Object.defineProperty(obj, key, {
@@ -7,11 +7,12 @@ export declare const getDefaultUserOptions: (mode: TParserMode) => {
7
7
  onDuplicateKey: import("../../types").OnDuplicateKey;
8
8
  requireDocTerminator: import("../../types").DocumentTerminatorRule;
9
9
  treatEmptyValueAsNull: import("../../types").EmptyValueRule;
10
+ logDiagnostics: boolean;
10
11
  quiet: boolean;
11
12
  silent: boolean;
12
13
  throwOnError: boolean;
13
- strictMode: boolean;
14
14
  failLevel: import("../../types").PreferredFailLevel;
15
15
  includeMetadata: boolean;
16
+ strictMode: boolean;
16
17
  };
17
- export type TNormalizedUserOptions = Required<Pick<ParseOptions, 'strictMode' | 'failLevel' | 'includeMetadata' | 'includeDiagnostics' | 'includeTiming' | 'preserveUndefinedInMeta' | 'onDuplicateKey' | 'requireDocTerminator' | 'treatEmptyValueAsNull' | 'quiet' | 'silent' | 'throwOnError'>>;
18
+ export type TNormalizedUserOptions = Required<Pick<ParseOptions, 'strictMode' | 'failLevel' | 'includeMetadata' | 'includeDiagnostics' | 'includeTiming' | 'preserveUndefinedInMeta' | 'onDuplicateKey' | 'requireDocTerminator' | 'treatEmptyValueAsNull' | 'logDiagnostics' | 'quiet' | 'silent' | 'throwOnError'>>;
@@ -14,11 +14,16 @@ const BASE_DEFAULTS = {
14
14
  onDuplicateKey: 'error',
15
15
  requireDocTerminator: 'optional',
16
16
  treatEmptyValueAsNull: 'allow-with-warning',
17
- quiet: false, // Suppress warnings in console (does not affect warnings in meta data).
17
+ logDiagnostics: false,
18
+ quiet: false, // When logDiagnostics is true, suppress warnings in stderr output.
18
19
  silent: false,
19
20
  //@todo: Change default throwOnError to false
20
21
  throwOnError: true, // Will throw on first parse error encountered.
21
22
  };
23
+ /**
24
+ * @note If editing any of these, the values in src/core/parsingRules/modeFromRulesMatcher.ts
25
+ * must match too.
26
+ */
22
27
  const DEFAULT_LENIENT_OPTS = {
23
28
  ...BASE_DEFAULTS,
24
29
  strictMode: false,
@@ -28,13 +33,17 @@ const DEFAULT_LENIENT_OPTS = {
28
33
  requireDocTerminator: 'optional',
29
34
  treatEmptyValueAsNull: 'allow',
30
35
  };
36
+ /**
37
+ * @note If editing any of these, the values in src/core/parsingRules/modeFromRulesMatcher.ts
38
+ * must match too.
39
+ */
31
40
  const DEFAULT_STRICT_OPTS = {
32
41
  ...BASE_DEFAULTS,
33
42
  strictMode: true,
34
43
  failLevel: 'errors',
35
44
  // Below are options for pure rules:
36
45
  onDuplicateKey: 'error',
37
- requireDocTerminator: 'optional',
46
+ requireDocTerminator: 'required',
38
47
  treatEmptyValueAsNull: 'disallow',
39
48
  };
40
49
  //# sourceMappingURL=defaultParserOptions.js.map
@@ -15,13 +15,16 @@ const toCoreOptions = (userOpts, bailLevel) => {
15
15
  treatEmptyValueAsNull: userOpts.treatEmptyValueAsNull,
16
16
  },
17
17
  bailSensitivity: level,
18
- isIncludeMeta: userOpts.includeMetadata,
18
+ isIncludeMeta: userOpts.includeMetadata ||
19
+ userOpts.includeDiagnostics ||
20
+ userOpts.includeTiming,
19
21
  // isWithDiagnostics: isDev() || isDebug() || userOpts.includeDiagnostics,
20
22
  isWithDiagnostics: userOpts.includeDiagnostics,
21
23
  // isWithTiming: isDev() || isDebug() || userOpts.includeTiming,
22
24
  isWithTiming: userOpts.includeTiming,
23
25
  // isKeepUndefinedInMeta: isDebug() || userOpts.preserveUndefinedInMeta,
24
26
  isKeepUndefinedInMeta: userOpts.preserveUndefinedInMeta,
27
+ isDiagnosticOutputEnabled: userOpts.logDiagnostics,
25
28
  isQuiet: userOpts.quiet, // Suppress warnings, etc.
26
29
  isSilent: userOpts.silent,
27
30
  isThrowOnError: userOpts.throwOnError,
@@ -32,8 +35,6 @@ exports.toCoreOptions = toCoreOptions;
32
35
  const isOptionsObjectForm = (v) => {
33
36
  return (v != null &&
34
37
  typeof v === 'object' &&
35
- // Note: If one wants, this can be relax to "typeof v === 'object'"
36
- // but this keeps accidental booleans/strings out.
37
38
  ('strictMode' in v ||
38
39
  'failLevel' in v ||
39
40
  'includeMetadata' in v ||
@@ -43,9 +44,10 @@ const isOptionsObjectForm = (v) => {
43
44
  'onDuplicateKey' in v ||
44
45
  'requireDocTerminator' in v ||
45
46
  'treatEmptyValueAsNull' in v ||
47
+ 'logDiagnostics' in v ||
46
48
  'quiet' in v ||
47
49
  'silent' in v ||
48
- 'isThrowOnError' in v));
50
+ 'throwOnError' in v));
49
51
  };
50
52
  exports.isOptionsObjectForm = isOptionsObjectForm;
51
53
  const inferModeFromArgs = (arg2) => {
@@ -1,4 +1,4 @@
1
- import { ParseOptions } from 'querystring';
1
+ import { ParseOptions } from '../../types';
2
2
  import { IParseCoreOptions, TExactMode } from '../internalTypes';
3
3
  export declare const matchModeFromParseOptions: (parserOptions: ParseOptions) => TExactMode;
4
4
  /**
@@ -1,14 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.matchModeFromCoreOptions = exports.matchModeFromParseOptions = void 0;
4
+ // src/core/parsingRules/modeFromRulesMatcher.ts
5
+ // import { ParseOptions } from 'querystring'
4
6
  const env_1 = require("../../config/env");
5
7
  const print_1 = require("../../utils/print");
6
8
  const errorDataHandler_1 = require("../errorDataHandler");
7
9
  const optionsFunctions_1 = require("../options/optionsFunctions");
10
+ /*
11
+ * Strict-mode defaults are:
12
+ * - onDuplicateKey: 'error' → 2
13
+ * - requireDocTerminator: 'required' → 2
14
+ * - treatEmptyValueAsNull: 'disallow' → 2
15
+ */
8
16
  const MODE_PROFILES = {
9
17
  lenient: [0, 0, 0],
10
18
  // moderate: [1, 0, 1],
11
- strict: [2, 0, 2],
19
+ strict: [2, 2, 2],
12
20
  //'pedantic'
13
21
  //'paranoid'
14
22
  };
@@ -22,7 +30,7 @@ const matchModeFromCoreOptions = (coreOptions) => {
22
30
  (0, print_1.debugPrint)('-> matchModeFromRules(..):');
23
31
  if (!coreOptions?.rules) {
24
32
  // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold.
25
- new errorDataHandler_1.ErrorDataHandler('None/Ignore').pushOrBail(undefined, 'Fatal-Error', `The passed input object is missing rules object.`, 'Option might be of wrong type, it must be core options.');
33
+ new errorDataHandler_1.ErrorDataHandler('None/Ignore').pushOrBail(undefined, 'Fatal-Error', `The passed input object is missing rules object.`, 'The passed option object may be of the wrong type; expected core options.');
26
34
  }
27
35
  // debugPrint(
28
36
  // 'coreOptions.rules.?onDuplicateKey = ' +
@@ -60,11 +68,12 @@ const inferTParserModeExact = (rules) => {
60
68
  // debugPrint('rules.onDuplicateKey = ' + rules.onDuplicateKey)
61
69
  // debugPrint('rules.requireDocTerminator = ' + rules.requireDocTerminator)
62
70
  // debugPrint('rules.treatEmptyValueAsNull = ' + rules.treatEmptyValueAsNull)
63
- // Note, **each rule** is scored on a strictness scale (0 = lenient, 1 = medium, 2 = strict).
71
+ // Each rule is scored on a strictness scale:
72
+ // 0 = lenient / permissive, 1 = warning-level / intermediate, 2 = strict / enforcing.
64
73
  const vector = [
65
- scoreDupl(rules.onDuplicateKey),
66
- scoreTerm(rules.requireDocTerminator),
67
- scoreEmpty(rules.treatEmptyValueAsNull),
74
+ scoreDuplicateKey(rules.onDuplicateKey),
75
+ scoreRequireDocTerminator(rules.requireDocTerminator),
76
+ scoreEmptyValue(rules.treatEmptyValueAsNull),
68
77
  ];
69
78
  (0, print_1.debugPrint)('** vector:');
70
79
  // isDebug() && printObject(vector)
@@ -76,29 +85,29 @@ const inferTParserModeExact = (rules) => {
76
85
  }
77
86
  return { mode: 'custom', vector };
78
87
  };
79
- const scoreDupl = (v) => {
88
+ const scoreDuplicateKey = (v) => {
80
89
  switch (v) {
81
90
  case 'keep-first':
82
91
  case 'warn-and-keep-first':
83
- return 0; // Rule in lenient mode.
92
+ return 0; // Lenient / permissive rule level.
84
93
  case 'overwrite':
85
94
  case 'warn-and-overwrite':
86
95
  return 1;
87
96
  case 'error':
88
- return 2; // Rule in strict mode.
97
+ return 2; // Strict / enforcing rule level.
89
98
  }
90
99
  };
91
- const scoreTerm = (v) => {
100
+ const scoreRequireDocTerminator = (v) => {
92
101
  switch (v) {
93
102
  case 'optional':
94
- return 0; // Rule in lenient and strict mode.
103
+ return 0; // Lenient / permissive rule level.
95
104
  case 'warn-if-missing':
96
105
  return 1;
97
106
  case 'required':
98
- return 2;
107
+ return 2; // Strict / enforcing rule level.
99
108
  }
100
109
  };
101
- const scoreEmpty = (v) => {
110
+ const scoreEmptyValue = (v) => {
102
111
  switch (v) {
103
112
  case 'allow':
104
113
  return 0; // Rule in lenient mode.