@accelint/geo 0.5.1 → 0.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 (112) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +233 -1
  3. package/catalog-info.yaml +1 -1
  4. package/dist/cartesian.d.ts +2 -0
  5. package/dist/cartesian.js +2 -0
  6. package/dist/cartesian.js.map +1 -1
  7. package/dist/coordinates/coordinate.d.ts +41 -7
  8. package/dist/coordinates/coordinate.js +102 -12
  9. package/dist/coordinates/coordinate.js.map +1 -1
  10. package/dist/coordinates/latlon/decimal-degrees/formatter.d.ts +20 -0
  11. package/dist/coordinates/latlon/decimal-degrees/formatter.js +38 -0
  12. package/dist/coordinates/latlon/decimal-degrees/formatter.js.map +1 -1
  13. package/dist/coordinates/latlon/decimal-degrees/parser.d.ts +68 -2
  14. package/dist/coordinates/latlon/decimal-degrees/parser.js +66 -5
  15. package/dist/coordinates/latlon/decimal-degrees/parser.js.map +1 -1
  16. package/dist/coordinates/latlon/decimal-degrees/system.d.ts +32 -0
  17. package/dist/coordinates/latlon/decimal-degrees/system.js +31 -0
  18. package/dist/coordinates/latlon/decimal-degrees/system.js.map +1 -1
  19. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.d.ts +20 -0
  20. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js +37 -0
  21. package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js.map +1 -1
  22. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.d.ts +72 -2
  23. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js +66 -3
  24. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js.map +1 -1
  25. package/dist/coordinates/latlon/degrees-decimal-minutes/system.d.ts +32 -0
  26. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js +31 -0
  27. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js.map +1 -1
  28. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.d.ts +20 -0
  29. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js +37 -0
  30. package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js.map +1 -1
  31. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.d.ts +74 -2
  32. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js +66 -3
  33. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js.map +1 -1
  34. package/dist/coordinates/latlon/degrees-minutes-seconds/system.d.ts +32 -0
  35. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js +31 -0
  36. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js.map +1 -1
  37. package/dist/coordinates/latlon/internal/coordinate-system.d.ts +22 -0
  38. package/dist/coordinates/latlon/internal/create-cache.d.ts +17 -1
  39. package/dist/coordinates/latlon/internal/create-cache.js +19 -3
  40. package/dist/coordinates/latlon/internal/create-cache.js.map +1 -1
  41. package/dist/coordinates/latlon/internal/exhaustive-errors.d.ts +15 -0
  42. package/dist/coordinates/latlon/internal/exhaustive-errors.js +28 -0
  43. package/dist/coordinates/latlon/internal/exhaustive-errors.js.map +1 -1
  44. package/dist/coordinates/latlon/internal/format.d.ts +20 -0
  45. package/dist/coordinates/latlon/internal/format.js +20 -0
  46. package/dist/coordinates/latlon/internal/format.js.map +1 -1
  47. package/dist/coordinates/latlon/internal/in-range.d.ts +23 -0
  48. package/dist/coordinates/latlon/internal/in-range.js +24 -0
  49. package/dist/coordinates/latlon/internal/in-range.js.map +1 -1
  50. package/dist/coordinates/latlon/internal/index.d.ts +16 -1
  51. package/dist/coordinates/latlon/internal/index.js +25 -1
  52. package/dist/coordinates/latlon/internal/index.js.map +1 -1
  53. package/dist/coordinates/latlon/internal/lexer.d.ts +2 -0
  54. package/dist/coordinates/latlon/internal/lexer.js +26 -0
  55. package/dist/coordinates/latlon/internal/lexer.js.map +1 -1
  56. package/dist/coordinates/latlon/internal/normalize.d.ts +67 -0
  57. package/dist/coordinates/latlon/internal/normalize.js +87 -0
  58. package/dist/coordinates/latlon/internal/normalize.js.map +1 -0
  59. package/dist/coordinates/latlon/internal/ordinal.d.ts +25 -0
  60. package/dist/coordinates/latlon/internal/ordinal.js +25 -0
  61. package/dist/coordinates/latlon/internal/ordinal.js.map +1 -1
  62. package/dist/coordinates/latlon/internal/parse-format.d.ts +22 -0
  63. package/dist/coordinates/latlon/internal/parse-format.js +43 -1
  64. package/dist/coordinates/latlon/internal/parse-format.js.map +1 -1
  65. package/dist/coordinates/latlon/internal/parse.d.ts +2 -0
  66. package/dist/coordinates/latlon/internal/parse.js +4 -1
  67. package/dist/coordinates/latlon/internal/parse.js.map +1 -1
  68. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.d.ts +17 -0
  69. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js +16 -0
  70. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js.map +1 -1
  71. package/dist/coordinates/latlon/internal/pipes/check-numbers.d.ts +25 -0
  72. package/dist/coordinates/latlon/internal/pipes/check-numbers.js +33 -0
  73. package/dist/coordinates/latlon/internal/pipes/check-numbers.js.map +1 -1
  74. package/dist/coordinates/latlon/internal/pipes/fix-bearings.d.ts +17 -0
  75. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js +31 -0
  76. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js.map +1 -1
  77. package/dist/coordinates/latlon/internal/pipes/fix-dividers.d.ts +17 -0
  78. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js +29 -0
  79. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js.map +1 -1
  80. package/dist/coordinates/latlon/internal/pipes/genome.d.ts +16 -0
  81. package/dist/coordinates/latlon/internal/pipes/genome.js +41 -0
  82. package/dist/coordinates/latlon/internal/pipes/genome.js.map +1 -1
  83. package/dist/coordinates/latlon/internal/pipes/index.d.ts +32 -2
  84. package/dist/coordinates/latlon/internal/pipes/index.js +57 -4
  85. package/dist/coordinates/latlon/internal/pipes/index.js.map +1 -1
  86. package/dist/coordinates/latlon/internal/pipes/simpler.d.ts +16 -3
  87. package/dist/coordinates/latlon/internal/pipes/simpler.js +15 -3
  88. package/dist/coordinates/latlon/internal/pipes/simpler.js.map +1 -1
  89. package/dist/coordinates/latlon/internal/validate.d.ts +75 -0
  90. package/dist/coordinates/latlon/internal/validate.js +105 -0
  91. package/dist/coordinates/latlon/internal/validate.js.map +1 -0
  92. package/dist/coordinates/latlon/internal/violation.d.ts +18 -0
  93. package/dist/coordinates/latlon/internal/violation.js +18 -0
  94. package/dist/coordinates/latlon/internal/violation.js.map +1 -1
  95. package/dist/coordinates/mgrs/parser.d.ts +24 -0
  96. package/dist/coordinates/mgrs/parser.js +56 -0
  97. package/dist/coordinates/mgrs/parser.js.map +1 -1
  98. package/dist/coordinates/mgrs/system.d.ts +31 -0
  99. package/dist/coordinates/mgrs/system.js +30 -0
  100. package/dist/coordinates/mgrs/system.js.map +1 -1
  101. package/dist/coordinates/utm/parser.d.ts +24 -0
  102. package/dist/coordinates/utm/parser.js +56 -0
  103. package/dist/coordinates/utm/parser.js.map +1 -1
  104. package/dist/coordinates/utm/system.d.ts +21 -0
  105. package/dist/coordinates/utm/system.js +20 -0
  106. package/dist/coordinates/utm/system.js.map +1 -1
  107. package/dist/index.d.ts +3 -1
  108. package/dist/index.js +3 -1
  109. package/dist/patterning.d.ts +12 -2
  110. package/dist/patterning.js +12 -2
  111. package/dist/patterning.js.map +1 -1
  112. package/package.json +3 -1
@@ -19,6 +19,16 @@ const GENOME_PATTERN = /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$
19
19
  * Get the position (index) of where to insert a divider into the token list;
20
20
  * basically, the count of numeric components (left-of-divider position) plus
21
21
  * 1 if there is a bearing identifier (left-of-divider).
22
+ *
23
+ * @param _full - Full regex match string (unused).
24
+ * @param args - Regex capture groups: [bearing1, number1, bearing2, number2].
25
+ * @returns String representation of the divider index position.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');
30
+ * // '3' (bearing + 2 numeric components)
31
+ * ```
22
32
  */
23
33
  function dividerIndexer(_full, ...args) {
24
34
  const [bearing1 = "", number1, bearing2 = "", number2] = args;
@@ -34,6 +44,22 @@ function dividerIndexer(_full, ...args) {
34
44
  * - S = seconds (number with seconds character following)
35
45
  * - N = number (no identifying character following)
36
46
  * - X = for unmatched token types
47
+ *
48
+ * @param acc - Accumulated genome sequence string.
49
+ * @param t - Current token to classify.
50
+ * @returns Updated genome sequence with new character appended.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * genomeSequencer('', '45°');
55
+ * // 'D'
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * genomeSequencer('D', 'N');
61
+ * // 'DB'
62
+ * ```
37
63
  */
38
64
  function genomeSequencer(acc, t) {
39
65
  if (t.includes(SYMBOLS.DEGREES)) return `${acc}D`;
@@ -46,6 +72,21 @@ function genomeSequencer(acc, t) {
46
72
  /**
47
73
  * Use the "genome" sequence of the token list to find the index for inserting
48
74
  * a missing divider token.
75
+ *
76
+ * @param tokens - Array of coordinate tokens to analyze.
77
+ * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);
82
+ * // 3 (insert divider after latitude components)
83
+ * ```
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * getGenomeIndex(['45', '30', '15']);
88
+ * // 0 (pattern doesn't match genome sequence)
89
+ * ```
49
90
  */
50
91
  function getGenomeIndex(tokens) {
51
92
  const seq = tokens.reduce(genomeSequencer, "");
@@ -1 +1 @@
1
- {"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ;;;;;;AAOF,SAAS,eAAe,OAAe,GAAG,MAAgB;CACxD,MAAM,CAAC,WAAW,IAAI,SAAS,WAAW,IAAI,WAAW;AAGzD,KAAI,EAAE,SAAS,UAAU,SAAS,QAChC,QAAO;AAGT,QAAO,GAAG,QAAQ,UAAU,SAAS,UAAU,SAAS;;;;;;;;;;;;AAa1D,SAAS,gBAAgB,KAAa,GAAW;AAC/C,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,gBAAgB,KAAK,KAAK,EAAE,CAC9B,QAAO,GAAG,IAAI;AAGhB,KAAI,KAAK,KAAK,EAAE,CACd,QAAO,GAAG,IAAI;AAGhB,QAAO,GAAG,IAAI;;;;;;AAOhB,SAAgB,eAAe,QAAgB;CAC7C,MAAM,MAAM,OAAO,OAAO,iBAAiB,GAAG;AAE9C,QAAO,eAAe,KAAK,IAAI,GAC3B,OAAO,SAAS,IAAI,QAAQ,gBAAgB,eAAe,EAAE,GAAG,GAChE"}
1
+ {"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n *\n * @param _full - Full regex match string (unused).\n * @param args - Regex capture groups: [bearing1, number1, bearing2, number2].\n * @returns String representation of the divider index position.\n *\n * @example\n * ```typescript\n * dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');\n * // '3' (bearing + 2 numeric components)\n * ```\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n *\n * @param acc - Accumulated genome sequence string.\n * @param t - Current token to classify.\n * @returns Updated genome sequence with new character appended.\n *\n * @example\n * ```typescript\n * genomeSequencer('', '45°');\n * // 'D'\n * ```\n *\n * @example\n * ```typescript\n * genomeSequencer('D', 'N');\n * // 'DB'\n * ```\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n *\n * @param tokens - Array of coordinate tokens to analyze.\n * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);\n * // 3 (insert divider after latitude components)\n * ```\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45', '30', '15']);\n * // 0 (pattern doesn't match genome sequence)\n * ```\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ;;;;;;;;;;;;;;;;AAiBF,SAAS,eAAe,OAAe,GAAG,MAAgB;CACxD,MAAM,CAAC,WAAW,IAAI,SAAS,WAAW,IAAI,WAAW;AAGzD,KAAI,EAAE,SAAS,UAAU,SAAS,QAChC,QAAO;AAGT,QAAO,GAAG,QAAQ,UAAU,SAAS,UAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B1D,SAAS,gBAAgB,KAAa,GAAW;AAC/C,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,gBAAgB,KAAK,KAAK,EAAE,CAC9B,QAAO,GAAG,IAAI;AAGhB,KAAI,KAAK,KAAK,EAAE,CACd,QAAO,GAAG,IAAI;AAGhB,QAAO,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;AAsBhB,SAAgB,eAAe,QAAgB;CAC7C,MAAM,MAAM,OAAO,OAAO,iBAAiB,GAAG;AAE9C,QAAO,eAAe,KAAK,IAAI,GAC3B,OAAO,SAAS,IAAI,QAAQ,gBAAgB,eAAe,EAAE,GAAG,GAChE"}
@@ -20,7 +20,21 @@ type PipeResult = ReturnType<Pipe>;
20
20
  * Consistently create a PipesResult array to return. Use this instead of
21
21
  * casting to PipesResult everywhere.
22
22
  *
23
- * @param e true = has error, false = no error
23
+ * @param t - Array of coordinate tokens.
24
+ * @param e - Error status: true = has error, false = no error, or error message string.
25
+ * @returns Pipe result tuple with tokens (empty if error) and error status.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * pipesResult(['45', 'N', '/', '122', 'W'], false);
30
+ * // [['45', 'N', '/', '122', 'W'], false]
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * pipesResult(['45'], 'Too few numbers.');
36
+ * // [[], 'Too few numbers.']
37
+ * ```
24
38
  *
25
39
  * @remarks
26
40
  * pure function
@@ -30,7 +44,23 @@ declare const pipesResult: (t: Tokens, e: boolean | string) => PipeResult;
30
44
  * Run the tokens through a preset pipeline of violations checks exiting the
31
45
  * process as early as possible when violations are found because violations
32
46
  * will make further violations checks less accurate and could return inaccurate
33
- * violations that could be misleading or hide the most important violation
47
+ * violations that could be misleading or hide the most important violation.
48
+ *
49
+ * @param tokens - Array of parsed coordinate tokens to validate and normalize.
50
+ * @param format - Optional coordinate format (LATLON or LONLAT) for inference.
51
+ * @returns Tuple of [processed tokens, array of error messages].
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
56
+ * // [['45', 'N', '/', '122', 'W'], []]
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * pipesRunner(['45'], 'LATLON');
62
+ * // [[], ['Too few numbers.']]
63
+ * ```
34
64
  */
35
65
  declare function pipesRunner(tokens: Tokens, format?: Format): [Tokens, string[]];
36
66
  //#endregion
@@ -18,19 +18,56 @@ import { fixBearings } from "./fix-bearings.js";
18
18
  import { fixDivider } from "./fix-dividers.js";
19
19
 
20
20
  //#region src/coordinates/latlon/internal/pipes/index.ts
21
- /** Make a RegExp global. */
21
+ /**
22
+ * Make a RegExp global.
23
+ *
24
+ * @param k - Key of the SYMBOL_PATTERNS object.
25
+ * @returns New global RegExp based on the pattern.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * makeGlobal('NSEW');
30
+ * // /[NSEW]/g
31
+ * ```
32
+ */
22
33
  const makeGlobal = (k) => new RegExp(SYMBOL_PATTERNS[k], "g");
23
34
  /**
24
35
  * Consistently create a PipesResult array to return. Use this instead of
25
36
  * casting to PipesResult everywhere.
26
37
  *
27
- * @param e true = has error, false = no error
38
+ * @param t - Array of coordinate tokens.
39
+ * @param e - Error status: true = has error, false = no error, or error message string.
40
+ * @returns Pipe result tuple with tokens (empty if error) and error status.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * pipesResult(['45', 'N', '/', '122', 'W'], false);
45
+ * // [['45', 'N', '/', '122', 'W'], false]
46
+ * ```
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * pipesResult(['45'], 'Too few numbers.');
51
+ * // [[], 'Too few numbers.']
52
+ * ```
28
53
  *
29
54
  * @remarks
30
55
  * pure function
31
56
  */
32
57
  const pipesResult = (t, e) => [e ? [] : t, e];
33
- /** Check if there are more than 2 of something. */
58
+ /**
59
+ * Check if there are more than 2 of something.
60
+ *
61
+ * @param p - Regular expression pattern to match.
62
+ * @returns Function that takes tokens and returns pipe result with error if >2 matches found.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const checkBearings = tooMany(/[NSEW]/g);
67
+ * checkBearings(['N', 'S', 'E', 'W']);
68
+ * // Returns error=true (more than 2 bearings)
69
+ * ```
70
+ */
34
71
  const tooMany = (p) => (t) => pipesResult(t, (t.join("").match(p) ?? []).length > 2);
35
72
  const pipes = [
36
73
  ["Too many bearings.", tooMany(makeGlobal("NSEW"))],
@@ -47,7 +84,23 @@ const pipes = [
47
84
  * Run the tokens through a preset pipeline of violations checks exiting the
48
85
  * process as early as possible when violations are found because violations
49
86
  * will make further violations checks less accurate and could return inaccurate
50
- * violations that could be misleading or hide the most important violation
87
+ * violations that could be misleading or hide the most important violation.
88
+ *
89
+ * @param tokens - Array of parsed coordinate tokens to validate and normalize.
90
+ * @param format - Optional coordinate format (LATLON or LONLAT) for inference.
91
+ * @returns Tuple of [processed tokens, array of error messages].
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
96
+ * // [['45', 'N', '/', '122', 'W'], []]
97
+ * ```
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * pipesRunner(['45'], 'LATLON');
102
+ * // [[], ['Too few numbers.']]
103
+ * ```
51
104
  */
52
105
  function pipesRunner(tokens, format) {
53
106
  let copy = tokens.slice(0);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n/** Make a RegExp global. */\nconst makeGlobal = (k: keyof typeof SYMBOL_PATTERNS) =>\n new RegExp(SYMBOL_PATTERNS[k], 'g');\n\n/**\n * Consistently create a PipesResult array to return. Use this instead of\n * casting to PipesResult everywhere.\n *\n * @param e true = has error, false = no error\n *\n * @remarks\n * pure function\n */\nexport const pipesResult = (t: Tokens, e: boolean | string): PipeResult => [\n // if there are errors do NOT return the tokens\n e ? [] : t,\n e,\n];\n\n/** Check if there are more than 2 of something. */\nconst tooMany = (p: RegExp) => (t: Tokens) =>\n pipesResult(t, (t.join('').match(p) ?? []).length > 2);\n\nconst pipes: [string, Pipe][] = [\n // Unrecoverable violations\n ['Too many bearings.', tooMany(makeGlobal('NSEW'))],\n ['Too many numeric signs.', tooMany(/[-+]/g)],\n ['Too many degrees indicators.', tooMany(makeGlobal('DEGREES'))],\n ['Too many minutes indicators.', tooMany(makeGlobal('MINUTES'))],\n ['Too many seconds indicators.', tooMany(makeGlobal('SECONDS'))],\n ['Number values checks.', checkNumberValues],\n ['Ambiguous grouping of numbers with no divider.', checkAmbiguousGrouping],\n\n // fix values and formatting to be consistent\n ['Unable to identify latitude from longitude.', fixDivider],\n ['Unable to identify bearings.', fixBearings],\n];\n\n/**\n * Run the tokens through a preset pipeline of violations checks exiting the\n * process as early as possible when violations are found because violations\n * will make further violations checks less accurate and could return inaccurate\n * violations that could be misleading or hide the most important violation\n */\nexport function pipesRunner(\n tokens: Tokens,\n format?: Format,\n): [Tokens, string[]] {\n let copy = tokens.slice(0);\n let error: PipeResult[1] = false;\n const errors = [] as string[];\n\n for (const [message, op] of pipes) {\n [copy, error] = op(copy, format);\n\n if (error) {\n // accumulate the \"errors\" because if tokens are returned\n // the errors are only warnings and are recoverable\n errors.push(error === true ? message : error);\n\n if (!copy.length) {\n return [copy, [error === true ? message : error]];\n }\n }\n }\n\n return [copy, errors];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,cAAc,MAClB,IAAI,OAAO,gBAAgB,IAAI,IAAI;;;;;;;;;;AAWrC,MAAa,eAAe,GAAW,MAAoC,CAEzE,IAAI,EAAE,GAAG,GACT,EACD;;AAGD,MAAM,WAAW,OAAe,MAC9B,YAAY,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE;AAExD,MAAMA,QAA0B;CAE9B,CAAC,sBAAsB,QAAQ,WAAW,OAAO,CAAC,CAAC;CACnD,CAAC,2BAA2B,QAAQ,QAAQ,CAAC;CAC7C,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,yBAAyB,kBAAkB;CAC5C,CAAC,kDAAkD,uBAAuB;CAG1E,CAAC,+CAA+C,WAAW;CAC3D,CAAC,gCAAgC,YAAY;CAC9C;;;;;;;AAQD,SAAgB,YACd,QACA,QACoB;CACpB,IAAI,OAAO,OAAO,MAAM,EAAE;CAC1B,IAAIC,QAAuB;CAC3B,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,CAAC,SAAS,OAAO,OAAO;AACjC,GAAC,MAAM,SAAS,GAAG,MAAM,OAAO;AAEhC,MAAI,OAAO;AAGT,UAAO,KAAK,UAAU,OAAO,UAAU,MAAM;AAE7C,OAAI,CAAC,KAAK,OACR,QAAO,CAAC,MAAM,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC;;;AAKvD,QAAO,CAAC,MAAM,OAAO"}
1
+ {"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n/**\n * Make a RegExp global.\n *\n * @param k - Key of the SYMBOL_PATTERNS object.\n * @returns New global RegExp based on the pattern.\n *\n * @example\n * ```typescript\n * makeGlobal('NSEW');\n * // /[NSEW]/g\n * ```\n */\nconst makeGlobal = (k: keyof typeof SYMBOL_PATTERNS) =>\n new RegExp(SYMBOL_PATTERNS[k], 'g');\n\n/**\n * Consistently create a PipesResult array to return. Use this instead of\n * casting to PipesResult everywhere.\n *\n * @param t - Array of coordinate tokens.\n * @param e - Error status: true = has error, false = no error, or error message string.\n * @returns Pipe result tuple with tokens (empty if error) and error status.\n *\n * @example\n * ```typescript\n * pipesResult(['45', 'N', '/', '122', 'W'], false);\n * // [['45', 'N', '/', '122', 'W'], false]\n * ```\n *\n * @example\n * ```typescript\n * pipesResult(['45'], 'Too few numbers.');\n * // [[], 'Too few numbers.']\n * ```\n *\n * @remarks\n * pure function\n */\nexport const pipesResult = (t: Tokens, e: boolean | string): PipeResult => [\n // if there are errors do NOT return the tokens\n e ? [] : t,\n e,\n];\n\n/**\n * Check if there are more than 2 of something.\n *\n * @param p - Regular expression pattern to match.\n * @returns Function that takes tokens and returns pipe result with error if >2 matches found.\n *\n * @example\n * ```typescript\n * const checkBearings = tooMany(/[NSEW]/g);\n * checkBearings(['N', 'S', 'E', 'W']);\n * // Returns error=true (more than 2 bearings)\n * ```\n */\nconst tooMany = (p: RegExp) => (t: Tokens) =>\n pipesResult(t, (t.join('').match(p) ?? []).length > 2);\n\nconst pipes: [string, Pipe][] = [\n // Unrecoverable violations\n ['Too many bearings.', tooMany(makeGlobal('NSEW'))],\n ['Too many numeric signs.', tooMany(/[-+]/g)],\n ['Too many degrees indicators.', tooMany(makeGlobal('DEGREES'))],\n ['Too many minutes indicators.', tooMany(makeGlobal('MINUTES'))],\n ['Too many seconds indicators.', tooMany(makeGlobal('SECONDS'))],\n ['Number values checks.', checkNumberValues],\n ['Ambiguous grouping of numbers with no divider.', checkAmbiguousGrouping],\n\n // fix values and formatting to be consistent\n ['Unable to identify latitude from longitude.', fixDivider],\n ['Unable to identify bearings.', fixBearings],\n];\n\n/**\n * Run the tokens through a preset pipeline of violations checks exiting the\n * process as early as possible when violations are found because violations\n * will make further violations checks less accurate and could return inaccurate\n * violations that could be misleading or hide the most important violation.\n *\n * @param tokens - Array of parsed coordinate tokens to validate and normalize.\n * @param format - Optional coordinate format (LATLON or LONLAT) for inference.\n * @returns Tuple of [processed tokens, array of error messages].\n *\n * @example\n * ```typescript\n * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');\n * // [['45', 'N', '/', '122', 'W'], []]\n * ```\n *\n * @example\n * ```typescript\n * pipesRunner(['45'], 'LATLON');\n * // [[], ['Too few numbers.']]\n * ```\n */\nexport function pipesRunner(\n tokens: Tokens,\n format?: Format,\n): [Tokens, string[]] {\n let copy = tokens.slice(0);\n let error: PipeResult[1] = false;\n const errors = [] as string[];\n\n for (const [message, op] of pipes) {\n [copy, error] = op(copy, format);\n\n if (error) {\n // accumulate the \"errors\" because if tokens are returned\n // the errors are only warnings and are recoverable\n errors.push(error === true ? message : error);\n\n if (!copy.length) {\n return [copy, [error === true ? message : error]];\n }\n }\n }\n\n return [copy, errors];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAM,cAAc,MAClB,IAAI,OAAO,gBAAgB,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;AAyBrC,MAAa,eAAe,GAAW,MAAoC,CAEzE,IAAI,EAAE,GAAG,GACT,EACD;;;;;;;;;;;;;;AAeD,MAAM,WAAW,OAAe,MAC9B,YAAY,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE;AAExD,MAAMA,QAA0B;CAE9B,CAAC,sBAAsB,QAAQ,WAAW,OAAO,CAAC,CAAC;CACnD,CAAC,2BAA2B,QAAQ,QAAQ,CAAC;CAC7C,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,yBAAyB,kBAAkB;CAC5C,CAAC,kDAAkD,uBAAuB;CAG1E,CAAC,+CAA+C,WAAW;CAC3D,CAAC,gCAAgC,YAAY;CAC9C;;;;;;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,YACd,QACA,QACoB;CACpB,IAAI,OAAO,OAAO,MAAM,EAAE;CAC1B,IAAIC,QAAuB;CAC3B,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,CAAC,SAAS,OAAO,OAAO;AACjC,GAAC,MAAM,SAAS,GAAG,MAAM,OAAO;AAEhC,MAAI,OAAO;AAGT,UAAO,KAAK,UAAU,OAAO,UAAU,MAAM;AAE7C,OAAI,CAAC,KAAK,OACR,QAAO,CAAC,MAAM,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC;;;AAKvD,QAAO,CAAC,MAAM,OAAO"}
@@ -13,15 +13,28 @@
13
13
  import { Tokens } from "../lexer.js";
14
14
 
15
15
  //#region src/coordinates/latlon/internal/pipes/simpler.d.ts
16
+
16
17
  /**
17
18
  * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to
18
19
  * allow for simpler pattern matching.
19
20
  *
20
- * @remarks
21
- * pure function
21
+ * @param tokens - Array of coordinate tokens to simplify.
22
+ * @returns Simplified pattern string where 'N' = number and 'B' = bearing.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * simpler(['45', '30', 'N', '/', '122', '15', 'W']);
27
+ * // 'NNBNNNB'
28
+ * ```
22
29
  *
23
30
  * @example
24
- * simplify(tokens); // 'NNNBNNNB' or similar
31
+ * ```typescript
32
+ * simpler(['45', 'N']);
33
+ * // 'NB'
34
+ * ```
35
+ *
36
+ * @remarks
37
+ * pure function
25
38
  */
26
39
  declare const simpler: (tokens: Tokens) => string;
27
40
  //#endregion
@@ -16,11 +16,23 @@
16
16
  * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to
17
17
  * allow for simpler pattern matching.
18
18
  *
19
- * @remarks
20
- * pure function
19
+ * @param tokens - Array of coordinate tokens to simplify.
20
+ * @returns Simplified pattern string where 'N' = number and 'B' = bearing.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * simpler(['45', '30', 'N', '/', '122', '15', 'W']);
25
+ * // 'NNBNNNB'
26
+ * ```
21
27
  *
22
28
  * @example
23
- * simplify(tokens); // 'NNNBNNNB' or similar
29
+ * ```typescript
30
+ * simpler(['45', 'N']);
31
+ * // 'NB'
32
+ * ```
33
+ *
34
+ * @remarks
35
+ * pure function
24
36
  */
25
37
  const simpler = (tokens) => tokens.map((t) => /\d/.test(t) ? "N" : "B").join("");
26
38
 
@@ -1 +1 @@
1
- {"version":3,"file":"simpler.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/simpler.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Tokens } from '../lexer';\n\n/**\n * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to\n * allow for simpler pattern matching.\n *\n * @remarks\n * pure function\n *\n * @example\n * simplify(tokens); // 'NNNBNNNB' or similar\n */\nexport const simpler = (tokens: Tokens) =>\n tokens.map((t) => (/\\d/.test(t) ? 'N' : 'B')).join('');\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAa,WAAW,WACtB,OAAO,KAAK,MAAO,KAAK,KAAK,EAAE,GAAG,MAAM,IAAK,CAAC,KAAK,GAAG"}
1
+ {"version":3,"file":"simpler.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/simpler.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Tokens } from '../lexer';\n\n/**\n * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to\n * allow for simpler pattern matching.\n *\n * @param tokens - Array of coordinate tokens to simplify.\n * @returns Simplified pattern string where 'N' = number and 'B' = bearing.\n *\n * @example\n * ```typescript\n * simpler(['45', '30', 'N', '/', '122', '15', 'W']);\n * // 'NNBNNNB'\n * ```\n *\n * @example\n * ```typescript\n * simpler(['45', 'N']);\n * // 'NB'\n * ```\n *\n * @remarks\n * pure function\n */\nexport const simpler = (tokens: Tokens) =>\n tokens.map((t) => (/\\d/.test(t) ? 'N' : 'B')).join('');\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,WAAW,WACtB,OAAO,KAAK,MAAO,KAAK,KAAK,EAAE,GAAG,MAAM,IAAK,CAAC,KAAK,GAAG"}
@@ -0,0 +1,75 @@
1
+ //#region src/coordinates/latlon/internal/validate.d.ts
2
+ /**
3
+ * Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).
4
+ *
5
+ * @param value - The numeric value to check
6
+ * @returns True if the value is a finite number, false otherwise
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * isFiniteNumber(42); // true
11
+ * isFiniteNumber(NaN); // false
12
+ * isFiniteNumber(Infinity); // false
13
+ * ```
14
+ */
15
+ declare function isFiniteNumber(value: number): boolean;
16
+ /**
17
+ * Validates that a value is within a signed range (-limit to +limit).
18
+ *
19
+ * @param label - The label for error messages (used as-is for range errors,
20
+ * lowercased for "Invalid" errors)
21
+ * @param value - The numeric value to validate
22
+ * @param limit - The absolute limit (validates -limit to +limit)
23
+ * @returns Error message string if validation fails, undefined if valid
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * validateSignedRange('Latitude', 45, 90);
28
+ * // => undefined
29
+ * ```
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * validateSignedRange('Latitude', 95, 90);
34
+ * // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * validateSignedRange('Longitude', NaN, 180);
40
+ * // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'
41
+ * ```
42
+ */
43
+ declare function validateSignedRange(label: string, value: number, limit: number): string | undefined;
44
+ /**
45
+ * Validates numeric latitude and longitude coordinate values.
46
+ *
47
+ * @param lat - The latitude value to validate (must be -90 to 90)
48
+ * @param lon - The longitude value to validate (must be -180 to 180)
49
+ * @returns Array of error message strings, empty if all validations pass
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * validateNumericCoordinate(45.5, -122.6);
54
+ * // => []
55
+ * ```
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * validateNumericCoordinate(91, -122.6);
60
+ * // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * validateNumericCoordinate(NaN, 200);
66
+ * // => [
67
+ * // '[ERROR] Invalid latitude value (NaN); expected a finite number.',
68
+ * // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'
69
+ * // ]
70
+ * ```
71
+ */
72
+ declare function validateNumericCoordinate(lat: number, lon: number): string[];
73
+ //#endregion
74
+ export { isFiniteNumber, validateNumericCoordinate, validateSignedRange };
75
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+
14
+ import { violation } from "./violation.js";
15
+
16
+ //#region src/coordinates/latlon/internal/validate.ts
17
+ const LAT_LIMIT = 90;
18
+ const LON_LIMIT = 180;
19
+ /**
20
+ * Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).
21
+ *
22
+ * @param value - The numeric value to check
23
+ * @returns True if the value is a finite number, false otherwise
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * isFiniteNumber(42); // true
28
+ * isFiniteNumber(NaN); // false
29
+ * isFiniteNumber(Infinity); // false
30
+ * ```
31
+ */
32
+ function isFiniteNumber(value) {
33
+ return typeof value === "number" && Number.isFinite(value);
34
+ }
35
+ /**
36
+ * Validates that a value is within a signed range (-limit to +limit).
37
+ *
38
+ * @param label - The label for error messages (used as-is for range errors,
39
+ * lowercased for "Invalid" errors)
40
+ * @param value - The numeric value to validate
41
+ * @param limit - The absolute limit (validates -limit to +limit)
42
+ * @returns Error message string if validation fails, undefined if valid
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * validateSignedRange('Latitude', 45, 90);
47
+ * // => undefined
48
+ * ```
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * validateSignedRange('Latitude', 95, 90);
53
+ * // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * validateSignedRange('Longitude', NaN, 180);
59
+ * // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'
60
+ * ```
61
+ */
62
+ function validateSignedRange(label, value, limit) {
63
+ if (!isFiniteNumber(value)) return violation(`Invalid ${label.toLowerCase()} value (${value}); expected a finite number.`);
64
+ if (value < -limit || value > limit) return violation(`${label} value (${value}) is outside valid range (-${limit} to ${limit}).`);
65
+ }
66
+ /**
67
+ * Validates numeric latitude and longitude coordinate values.
68
+ *
69
+ * @param lat - The latitude value to validate (must be -90 to 90)
70
+ * @param lon - The longitude value to validate (must be -180 to 180)
71
+ * @returns Array of error message strings, empty if all validations pass
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * validateNumericCoordinate(45.5, -122.6);
76
+ * // => []
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * validateNumericCoordinate(91, -122.6);
82
+ * // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']
83
+ * ```
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * validateNumericCoordinate(NaN, 200);
88
+ * // => [
89
+ * // '[ERROR] Invalid latitude value (NaN); expected a finite number.',
90
+ * // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'
91
+ * // ]
92
+ * ```
93
+ */
94
+ function validateNumericCoordinate(lat, lon) {
95
+ const errors = [];
96
+ const latError = validateSignedRange("Latitude", lat, LAT_LIMIT);
97
+ if (latError) errors.push(latError);
98
+ const lonError = validateSignedRange("Longitude", lon, LON_LIMIT);
99
+ if (lonError) errors.push(lonError);
100
+ return errors;
101
+ }
102
+
103
+ //#endregion
104
+ export { isFiniteNumber, validateNumericCoordinate, validateSignedRange };
105
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","names":["errors: string[]"],"sources":["../../../../src/coordinates/latlon/internal/validate.ts"],"sourcesContent":["/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { violation } from './violation';\n\nconst LAT_LIMIT = 90;\nconst LON_LIMIT = 180;\n\n/**\n * Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).\n *\n * @param value - The numeric value to check\n * @returns True if the value is a finite number, false otherwise\n *\n * @example\n * ```typescript\n * isFiniteNumber(42); // true\n * isFiniteNumber(NaN); // false\n * isFiniteNumber(Infinity); // false\n * ```\n */\nexport function isFiniteNumber(value: number): boolean {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\n/**\n * Validates that a value is within a signed range (-limit to +limit).\n *\n * @param label - The label for error messages (used as-is for range errors,\n * lowercased for \"Invalid\" errors)\n * @param value - The numeric value to validate\n * @param limit - The absolute limit (validates -limit to +limit)\n * @returns Error message string if validation fails, undefined if valid\n *\n * @example\n * ```typescript\n * validateSignedRange('Latitude', 45, 90);\n * // => undefined\n * ```\n *\n * @example\n * ```typescript\n * validateSignedRange('Latitude', 95, 90);\n * // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'\n * ```\n *\n * @example\n * ```typescript\n * validateSignedRange('Longitude', NaN, 180);\n * // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'\n * ```\n */\nexport function validateSignedRange(\n label: string,\n value: number,\n limit: number,\n): string | undefined {\n if (!isFiniteNumber(value)) {\n return violation(\n `Invalid ${label.toLowerCase()} value (${value}); expected a finite number.`,\n );\n }\n\n if (value < -limit || value > limit) {\n return violation(\n `${label} value (${value}) is outside valid range (-${limit} to ${limit}).`,\n );\n }\n}\n\n/**\n * Validates numeric latitude and longitude coordinate values.\n *\n * @param lat - The latitude value to validate (must be -90 to 90)\n * @param lon - The longitude value to validate (must be -180 to 180)\n * @returns Array of error message strings, empty if all validations pass\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(45.5, -122.6);\n * // => []\n * ```\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(91, -122.6);\n * // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']\n * ```\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(NaN, 200);\n * // => [\n * // '[ERROR] Invalid latitude value (NaN); expected a finite number.',\n * // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'\n * // ]\n * ```\n */\nexport function validateNumericCoordinate(lat: number, lon: number): string[] {\n const errors: string[] = [];\n\n const latError = validateSignedRange('Latitude', lat, LAT_LIMIT);\n if (latError) {\n errors.push(latError);\n }\n\n const lonError = validateSignedRange('Longitude', lon, LON_LIMIT);\n if (lonError) {\n errors.push(lonError);\n }\n\n return errors;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,MAAM,YAAY;AAClB,MAAM,YAAY;;;;;;;;;;;;;;AAelB,SAAgB,eAAe,OAAwB;AACrD,QAAO,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B5D,SAAgB,oBACd,OACA,OACA,OACoB;AACpB,KAAI,CAAC,eAAe,MAAM,CACxB,QAAO,UACL,WAAW,MAAM,aAAa,CAAC,UAAU,MAAM,8BAChD;AAGH,KAAI,QAAQ,CAAC,SAAS,QAAQ,MAC5B,QAAO,UACL,GAAG,MAAM,UAAU,MAAM,6BAA6B,MAAM,MAAM,MAAM,IACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCL,SAAgB,0BAA0B,KAAa,KAAuB;CAC5E,MAAMA,SAAmB,EAAE;CAE3B,MAAM,WAAW,oBAAoB,YAAY,KAAK,UAAU;AAChE,KAAI,SACF,QAAO,KAAK,SAAS;CAGvB,MAAM,WAAW,oBAAoB,aAAa,KAAK,UAAU;AACjE,KAAI,SACF,QAAO,KAAK,SAAS;AAGvB,QAAO"}
@@ -1,4 +1,22 @@
1
1
  //#region src/coordinates/latlon/internal/violation.d.ts
2
+ /**
3
+ * Formats an error message with a standard [ERROR] prefix.
4
+ *
5
+ * @param s - The error message string to format.
6
+ * @returns Formatted error string with [ERROR] prefix.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * violation('Invalid coordinate value.');
11
+ * // '[ERROR] Invalid coordinate value.'
12
+ * ```
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * violation('Degrees value (91) exceeds max value (90).');
17
+ * // '[ERROR] Degrees value (91) exceeds max value (90).'
18
+ * ```
19
+ */
2
20
  declare const violation: (s: string) => string;
3
21
  //#endregion
4
22
  export { violation };
@@ -12,6 +12,24 @@
12
12
 
13
13
 
14
14
  //#region src/coordinates/latlon/internal/violation.ts
15
+ /**
16
+ * Formats an error message with a standard [ERROR] prefix.
17
+ *
18
+ * @param s - The error message string to format.
19
+ * @returns Formatted error string with [ERROR] prefix.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * violation('Invalid coordinate value.');
24
+ * // '[ERROR] Invalid coordinate value.'
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * violation('Degrees value (91) exceeds max value (90).');
30
+ * // '[ERROR] Degrees value (91) exceeds max value (90).'
31
+ * ```
32
+ */
15
33
  const violation = (s) => `[ERROR] ${s}`;
16
34
 
17
35
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"violation.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/violation.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport const violation = (s: string) => `[ERROR] ${s}`;\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,aAAa,MAAc,WAAW"}
1
+ {"version":3,"file":"violation.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/violation.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Formats an error message with a standard [ERROR] prefix.\n *\n * @param s - The error message string to format.\n * @returns Formatted error string with [ERROR] prefix.\n *\n * @example\n * ```typescript\n * violation('Invalid coordinate value.');\n * // '[ERROR] Invalid coordinate value.'\n * ```\n *\n * @example\n * ```typescript\n * violation('Degrees value (91) exceeds max value (90).');\n * // '[ERROR] Degrees value (91) exceeds max value (90).'\n * ```\n */\nexport const violation = (s: string) => `[ERROR] ${s}`;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,aAAa,MAAc,WAAW"}
@@ -13,6 +13,30 @@
13
13
  import { ParseResults } from "../latlon/internal/parse.js";
14
14
 
15
15
  //#region src/coordinates/mgrs/parser.d.ts
16
+
17
+ /**
18
+ * Parses a Military Grid Reference System (MGRS) coordinate string into latitude/longitude values.
19
+ *
20
+ * Converts MGRS coordinates to UTM, then to latitude/longitude decimal degrees. Returns
21
+ * detailed error messages for invalid MGRS formats including zone numbers, band letters,
22
+ * square identification, and numerical locations.
23
+ *
24
+ * @param _format - Format parameter (unused, MGRS has fixed format).
25
+ * @param input - The MGRS coordinate string to parse (e.g., '31U BF 12345 67890').
26
+ * @returns Parse results with coordinate values or detailed error messages.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * parseMGRS(null, '31U BF 12345 67890');
31
+ * // [[['48.123456', 'N'], ['11.234567', 'E']], []]
32
+ * ```
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * parseMGRS(null, 'invalid');
37
+ * // [[], ['Invalid UTM zone number found...']]
38
+ * ```
39
+ */
16
40
  declare function parseMGRS(_format: any, input: string): ParseResults;
17
41
  //#endregion
18
42
  export { parseMGRS };