cmpstr 3.2.1 → 3.3.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 (155) hide show
  1. package/README.md +24 -18
  2. package/dist/CmpStr.esm.js +1904 -1211
  3. package/dist/CmpStr.esm.min.js +2 -3
  4. package/dist/CmpStr.umd.js +1924 -1236
  5. package/dist/CmpStr.umd.min.js +2 -3
  6. package/dist/cjs/CmpStr.cjs +134 -64
  7. package/dist/cjs/CmpStrAsync.cjs +60 -37
  8. package/dist/cjs/index.cjs +1 -2
  9. package/dist/cjs/metric/Cosine.cjs +1 -2
  10. package/dist/cjs/metric/DamerauLevenshtein.cjs +1 -2
  11. package/dist/cjs/metric/DiceSorensen.cjs +1 -2
  12. package/dist/cjs/metric/Hamming.cjs +5 -4
  13. package/dist/cjs/metric/Jaccard.cjs +1 -2
  14. package/dist/cjs/metric/JaroWinkler.cjs +1 -2
  15. package/dist/cjs/metric/LCS.cjs +1 -2
  16. package/dist/cjs/metric/Levenshtein.cjs +1 -2
  17. package/dist/cjs/metric/Metric.cjs +90 -53
  18. package/dist/cjs/metric/NeedlemanWunsch.cjs +1 -2
  19. package/dist/cjs/metric/QGram.cjs +1 -2
  20. package/dist/cjs/metric/SmithWaterman.cjs +1 -2
  21. package/dist/cjs/phonetic/Caverphone.cjs +1 -2
  22. package/dist/cjs/phonetic/Cologne.cjs +1 -2
  23. package/dist/cjs/phonetic/Metaphone.cjs +1 -2
  24. package/dist/cjs/phonetic/Phonetic.cjs +80 -48
  25. package/dist/cjs/phonetic/Soundex.cjs +1 -2
  26. package/dist/cjs/root.cjs +6 -3
  27. package/dist/cjs/utils/DeepMerge.cjs +109 -99
  28. package/dist/cjs/utils/DiffChecker.cjs +1 -2
  29. package/dist/cjs/utils/Errors.cjs +106 -0
  30. package/dist/cjs/utils/Filter.cjs +97 -37
  31. package/dist/cjs/utils/HashTable.cjs +44 -30
  32. package/dist/cjs/utils/Normalizer.cjs +84 -35
  33. package/dist/cjs/utils/OptionsValidator.cjs +211 -0
  34. package/dist/cjs/utils/Pool.cjs +57 -19
  35. package/dist/cjs/utils/Profiler.cjs +41 -28
  36. package/dist/cjs/utils/Registry.cjs +48 -24
  37. package/dist/cjs/utils/StructuredData.cjs +95 -57
  38. package/dist/cjs/utils/TextAnalyzer.cjs +1 -2
  39. package/dist/esm/CmpStr.mjs +133 -61
  40. package/dist/esm/CmpStrAsync.mjs +56 -33
  41. package/dist/esm/index.mjs +1 -2
  42. package/dist/esm/metric/Cosine.mjs +1 -2
  43. package/dist/esm/metric/DamerauLevenshtein.mjs +1 -2
  44. package/dist/esm/metric/DiceSorensen.mjs +1 -2
  45. package/dist/esm/metric/Hamming.mjs +5 -4
  46. package/dist/esm/metric/Jaccard.mjs +1 -2
  47. package/dist/esm/metric/JaroWinkler.mjs +1 -2
  48. package/dist/esm/metric/LCS.mjs +1 -2
  49. package/dist/esm/metric/Levenshtein.mjs +1 -2
  50. package/dist/esm/metric/Metric.mjs +92 -53
  51. package/dist/esm/metric/NeedlemanWunsch.mjs +1 -2
  52. package/dist/esm/metric/QGram.mjs +1 -2
  53. package/dist/esm/metric/SmithWaterman.mjs +1 -2
  54. package/dist/esm/phonetic/Caverphone.mjs +1 -2
  55. package/dist/esm/phonetic/Cologne.mjs +1 -2
  56. package/dist/esm/phonetic/Metaphone.mjs +1 -2
  57. package/dist/esm/phonetic/Phonetic.mjs +83 -48
  58. package/dist/esm/phonetic/Soundex.mjs +1 -2
  59. package/dist/esm/root.mjs +5 -4
  60. package/dist/esm/utils/DeepMerge.mjs +109 -95
  61. package/dist/esm/utils/DiffChecker.mjs +1 -2
  62. package/dist/esm/utils/Errors.mjs +106 -0
  63. package/dist/esm/utils/Filter.mjs +97 -37
  64. package/dist/esm/utils/HashTable.mjs +44 -30
  65. package/dist/esm/utils/Normalizer.mjs +84 -35
  66. package/dist/esm/utils/OptionsValidator.mjs +210 -0
  67. package/dist/esm/utils/Pool.mjs +53 -19
  68. package/dist/esm/utils/Profiler.mjs +41 -28
  69. package/dist/esm/utils/Registry.mjs +48 -24
  70. package/dist/esm/utils/StructuredData.mjs +95 -57
  71. package/dist/esm/utils/TextAnalyzer.mjs +1 -2
  72. package/dist/types/CmpStr.d.ts +25 -14
  73. package/dist/types/CmpStrAsync.d.ts +4 -0
  74. package/dist/types/index.d.ts +3 -2
  75. package/dist/types/metric/Metric.d.ts +15 -14
  76. package/dist/types/phonetic/Phonetic.d.ts +7 -4
  77. package/dist/types/root.d.ts +4 -2
  78. package/dist/types/utils/DeepMerge.d.ts +80 -58
  79. package/dist/types/utils/Errors.d.ts +154 -0
  80. package/dist/types/utils/Filter.d.ts +8 -1
  81. package/dist/types/utils/HashTable.d.ts +12 -11
  82. package/dist/types/utils/Normalizer.d.ts +5 -1
  83. package/dist/types/utils/OptionsValidator.d.ts +193 -0
  84. package/dist/types/utils/Pool.d.ts +2 -0
  85. package/dist/types/utils/Profiler.d.ts +9 -28
  86. package/dist/types/utils/Registry.d.ts +3 -3
  87. package/dist/types/utils/StructuredData.d.ts +6 -1
  88. package/dist/types/utils/Types.d.ts +39 -1
  89. package/package.json +20 -11
  90. package/dist/CmpStr.esm.js.map +0 -1
  91. package/dist/CmpStr.esm.min.js.map +0 -1
  92. package/dist/CmpStr.umd.js.map +0 -1
  93. package/dist/CmpStr.umd.min.js.map +0 -1
  94. package/dist/cjs/CmpStr.cjs.map +0 -1
  95. package/dist/cjs/CmpStrAsync.cjs.map +0 -1
  96. package/dist/cjs/index.cjs.map +0 -1
  97. package/dist/cjs/metric/Cosine.cjs.map +0 -1
  98. package/dist/cjs/metric/DamerauLevenshtein.cjs.map +0 -1
  99. package/dist/cjs/metric/DiceSorensen.cjs.map +0 -1
  100. package/dist/cjs/metric/Hamming.cjs.map +0 -1
  101. package/dist/cjs/metric/Jaccard.cjs.map +0 -1
  102. package/dist/cjs/metric/JaroWinkler.cjs.map +0 -1
  103. package/dist/cjs/metric/LCS.cjs.map +0 -1
  104. package/dist/cjs/metric/Levenshtein.cjs.map +0 -1
  105. package/dist/cjs/metric/Metric.cjs.map +0 -1
  106. package/dist/cjs/metric/NeedlemanWunsch.cjs.map +0 -1
  107. package/dist/cjs/metric/QGram.cjs.map +0 -1
  108. package/dist/cjs/metric/SmithWaterman.cjs.map +0 -1
  109. package/dist/cjs/phonetic/Caverphone.cjs.map +0 -1
  110. package/dist/cjs/phonetic/Cologne.cjs.map +0 -1
  111. package/dist/cjs/phonetic/Metaphone.cjs.map +0 -1
  112. package/dist/cjs/phonetic/Phonetic.cjs.map +0 -1
  113. package/dist/cjs/phonetic/Soundex.cjs.map +0 -1
  114. package/dist/cjs/root.cjs.map +0 -1
  115. package/dist/cjs/utils/DeepMerge.cjs.map +0 -1
  116. package/dist/cjs/utils/DiffChecker.cjs.map +0 -1
  117. package/dist/cjs/utils/Filter.cjs.map +0 -1
  118. package/dist/cjs/utils/HashTable.cjs.map +0 -1
  119. package/dist/cjs/utils/Normalizer.cjs.map +0 -1
  120. package/dist/cjs/utils/Pool.cjs.map +0 -1
  121. package/dist/cjs/utils/Profiler.cjs.map +0 -1
  122. package/dist/cjs/utils/Registry.cjs.map +0 -1
  123. package/dist/cjs/utils/StructuredData.cjs.map +0 -1
  124. package/dist/cjs/utils/TextAnalyzer.cjs.map +0 -1
  125. package/dist/esm/CmpStr.mjs.map +0 -1
  126. package/dist/esm/CmpStrAsync.mjs.map +0 -1
  127. package/dist/esm/index.mjs.map +0 -1
  128. package/dist/esm/metric/Cosine.mjs.map +0 -1
  129. package/dist/esm/metric/DamerauLevenshtein.mjs.map +0 -1
  130. package/dist/esm/metric/DiceSorensen.mjs.map +0 -1
  131. package/dist/esm/metric/Hamming.mjs.map +0 -1
  132. package/dist/esm/metric/Jaccard.mjs.map +0 -1
  133. package/dist/esm/metric/JaroWinkler.mjs.map +0 -1
  134. package/dist/esm/metric/LCS.mjs.map +0 -1
  135. package/dist/esm/metric/Levenshtein.mjs.map +0 -1
  136. package/dist/esm/metric/Metric.mjs.map +0 -1
  137. package/dist/esm/metric/NeedlemanWunsch.mjs.map +0 -1
  138. package/dist/esm/metric/QGram.mjs.map +0 -1
  139. package/dist/esm/metric/SmithWaterman.mjs.map +0 -1
  140. package/dist/esm/phonetic/Caverphone.mjs.map +0 -1
  141. package/dist/esm/phonetic/Cologne.mjs.map +0 -1
  142. package/dist/esm/phonetic/Metaphone.mjs.map +0 -1
  143. package/dist/esm/phonetic/Phonetic.mjs.map +0 -1
  144. package/dist/esm/phonetic/Soundex.mjs.map +0 -1
  145. package/dist/esm/root.mjs.map +0 -1
  146. package/dist/esm/utils/DeepMerge.mjs.map +0 -1
  147. package/dist/esm/utils/DiffChecker.mjs.map +0 -1
  148. package/dist/esm/utils/Filter.mjs.map +0 -1
  149. package/dist/esm/utils/HashTable.mjs.map +0 -1
  150. package/dist/esm/utils/Normalizer.mjs.map +0 -1
  151. package/dist/esm/utils/Pool.mjs.map +0 -1
  152. package/dist/esm/utils/Profiler.mjs.map +0 -1
  153. package/dist/esm/utils/Registry.mjs.map +0 -1
  154. package/dist/esm/utils/StructuredData.mjs.map +0 -1
  155. package/dist/esm/utils/TextAnalyzer.mjs.map +0 -1
@@ -1,8 +1,7 @@
1
1
  /**
2
- * CmpStr v3.2.1 build-3439ccb-260130
2
+ * CmpStr v3.3.0 build-3699f85-260318
3
3
  * This is a lightweight, fast and well performing library for calculating string similarity.
4
4
  * (c) 2023-2026 Paul Köhler @komed3 / MIT License
5
5
  * Visit https://github.com/komed3/cmpstr and https://npmjs.org/package/cmpstr
6
6
  */
7
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CmpStr={})}(this,function(t){"use strict";const e=/\[(\d+)]/g,r=new Map;function s(t){let s=r.get(t);if(s)return s;const n=t.replace(e,".$1").split(".").map(t=>{const e=Number(t);return Number.isInteger(e)&&String(e)===t?e:t});return r.set(t,n),n}function n(t,e,r){let n=t;for(const t of s(e)){if(null==n||!(t in n))return r;n=n[t]}return n}function i(t,e,r){if(""===e)return r;const n=s(e);if(void 0!==t&&("object"!=typeof t||null===t))throw Error(`Cannot set property <${n[0]}> of <${JSON.stringify(t)}>`);const i=t??("number"==typeof n[0]?[]:Object.create(null));let a=i;for(let t=0;t<n.length-1;t++){const e=n[t];let r=a[e];if(null!=r&&"object"!=typeof r)throw Error(`Cannot set property <${n[t+1]}> of <${JSON.stringify(r)}>`);null==r&&(r=a[e]="number"==typeof n[t+1]?[]:Object.create(null)),a=r}return a[n[n.length-1]]=r,i}function a(t=Object.create(null),e=Object.create(null),r=!1){const s=t??Object.create(null);return Object.keys(e).forEach(t=>{const n=e[t];if((r||void 0!==n)&&"__proto__"!==t&&"constructor"!==t)if(null===n||"object"!=typeof n||Array.isArray(n))s[t]=n;else{const e=s[t];s[t]=a(null===e||"object"!=typeof e||Array.isArray(e)?Object.create(null):e,n,r)}}),s}function o(t,e,r=!1){const n=s(e),i=(t,e=0)=>{const s=n[e];if(!t||"object"!=typeof t)return!1;if(e===n.length-1)return delete t[s];if(!i(t[s],e+1))return!1;if(!r){const e=t[s];"object"==typeof e&&(Array.isArray(e)&&e.every(t=>null==t)||!Array.isArray(e)&&0===Object.keys(e).length)&&delete t[s]}return!0};return i(t),t}var c=Object.freeze({__proto__:null,get:n,has:function(t,e){let r=t;for(const t of s(e)){if(null==r||!(t in r))return!1;r=r[t]}return!0},merge:a,rmv:o,set:i});class l{a;b;options;entries=[];grouped=[];diffRun=!1;constructor(t,e,r={}){this.a=t,this.b=e,this.options={mode:"word",caseInsensitive:!1,contextLines:1,groupedLines:!0,expandLines:!1,showChangeMagnitude:!0,maxMagnitudeSymbols:5,lineBreak:"\n",...r},this.computeDiff()}text2lines(){const t=this.a.trim().split(/\r?\n/),e=this.b.trim().split(/\r?\n/);return{linesA:t,linesB:e,maxLen:Math.max(t.length,e.length)}}tokenize(t){switch(this.options.mode){case"line":return[t];case"word":return t.split(/\s+/)}}concat(t){return t.join("word"===this.options.mode?" ":"")}computeDiff(){if(this.diffRun)return;const{linesA:t,linesB:e,maxLen:r}=this.text2lines();for(let s=0;s<r;s++)this.lineDiff(t[s]||"",e[s]||"",s);this.findGroups(),this.diffRun=!0}lineDiff(t,e,r){const{mode:s,caseInsensitive:n}=this.options,i=Math.max(t.length,e.length);let a=t,o=e;n&&(a=t.toLowerCase(),o=e.toLowerCase());let c=[],l=0,h=0;switch(s){case"line":a!==o&&(c.push({posA:0,posB:0,del:t,ins:e,size:e.length-t.length}),l=t.length,h=e.length);break;case"word":c=this.preciseDiff(t,a,e,o);for(const t of c)l+=t.del.length,h+=t.ins.length}c.length&&this.entries.push({line:r,diffs:c,delSize:l,insSize:h,baseLen:i,totalSize:h-l,magnitude:this.magnitude(l,h,i)})}preciseDiff(t,e,r,s){const n=t=>t.reduce((e,r,s)=>(e.push(s?e[s-1]+t[s-1].length+1:0),e),[]),i=this.tokenize(t),a=this.tokenize(r),o=this.tokenize(e),c=this.tokenize(s),l=o.length,h=c.length,p=n(i),u=n(a),d=[];let g=0,m=0;for(;g<l&&m<h;)if(o[g]===c[m]){let t=1;for(;g+t<l&&m+t<h&&o[g+t]===c[m+t];)t++;d.push({ai:g,bi:m,len:t}),g+=t,m+=t}else{let t=!1;for(let e=1;e<=3&&!t;e++)g+e<l&&o[g+e]===c[m]?(d.push({ai:g+e,bi:m,len:1}),g+=e+1,m+=1,t=!0):m+e<h&&o[g]===c[m+e]&&(d.push({ai:g,bi:m+e,len:1}),g+=1,m+=e+1,t=!0);t||(g++,m++)}const f=[];let y=0,w=0;for(const t of d){if(y<t.ai||w<t.bi){const e=i.slice(y,t.ai),r=a.slice(w,t.bi);f.push({posA:p[y]??0,posB:u[w]??0,del:this.concat(e),ins:this.concat(r),size:r.join("").length-e.join("").length})}y=t.ai+t.len,w=t.bi+t.len}if(y<l||w<h){const t=i.slice(y),e=a.slice(w);f.push({posA:p[y]??0,posB:u[w]??0,del:this.concat(t),ins:this.concat(e),size:e.join("").length-t.join("").length})}return f.filter(t=>t.del.length>0||t.ins.length>0)}findGroups(){const{contextLines:t}=this.options,e=(t,e,r)=>{const[s,n,i,a]=["delSize","insSize","totalSize","baseLen"].map(e=>t.reduce((t,r)=>t+r[e],0));this.grouped.push({start:e,end:r,delSize:s,insSize:n,totalSize:i,line:t[0].line,entries:t,magnitude:this.magnitude(s,n,a)})};let r=[],s=0,n=0;for(const i of this.entries){const a=Math.max(0,i.line-t),o=i.line+t;!r.length||a<=n+1?(r.length||(s=a),n=Math.max(n,o),r.push(i)):(e(r,s,n),r=[i],s=a,n=o)}r.length&&e(r,s,n)}magnitude(t,e,r){const{maxMagnitudeSymbols:s}=this.options,n=t+e;if(0===n||0===r)return"";const i=Math.min(s,Math.max(Math.round(n/r*s),1)),a=Math.round(e/n*i),o=i-a;return"+".repeat(a)+"-".repeat(o)}output(t){const{mode:e,contextLines:r,groupedLines:s,expandLines:n,showChangeMagnitude:i,lineBreak:a}=this.options,{linesA:o,linesB:c,maxLen:l}=this.text2lines(),h=Math.max(4,l.toString().length),p=(e,r)=>t?`[${r}m${e}`:e,u=e=>t?`${e}`:`-[${e}]`,d=e=>t?`${e}`:`+[${e}]`,g=(t,e,r,s)=>{s&&m(s);for(let s=t;s<=e;s++)f(s,r??s);w.push("")},m=t=>{var e;w.push(`${" ".repeat(h)} ${e=`@@ -${t.line+1},${t.delSize} +${t.line+1},${t.insSize} @@`,p(e,"36")} ${i?(t=>p(t,"33"))(t.magnitude):""}`)},f=(t,e)=>{if(o[t]||c[t]){const s=this.entries.find(e=>e.line===t),n=(t+1).toString().padStart(h," ");s&&e===t?(w.push(`${n} ${r=`- ${y(o[t],s.diffs,"del")}`,p(r,"31")}`),w.push(`${" ".repeat(h)} ${(t=>p(t,"32"))(`+ ${y(c[t],s.diffs,"ins")}`)}`)):w.push(`${n} ${(t=>p(t,"90"))(o[t])}`)}var r},y=(t,r,s)=>{if(!r.length||"line"===e)return t;let n="",i=0;for(const e of r){const r="del"===s?e.posA:e.posB,a="del"===s?e.del:e.ins;a&&(r>i&&(n+=t.slice(i,r)),n+="del"===s?u(a):d(a),i=r+a.length)}return n+t.slice(i)};let w=[""];switch(!0){case n:g(0,l);break;case s:for(const t of this.grouped)g(t.start,t.end,void 0,t);break;default:for(const t of this.entries)g(t.line-r,t.line+r,t.line,t)}return w.join(a)}getStructuredDiff=()=>this.entries;getGroupedDiff=()=>this.grouped;getASCIIDiff=()=>this.output(!1);getCLIDiff=()=>this.output(!0)}class h{static filters=new Map;static pipeline=new Map;static getPipeline(t){const e=h.pipeline.get(t);if(e)return e;const r=h.filters.get(t);if(!r)return t=>t;const s=Array.from(r.values()).filter(t=>t.active).sort((t,e)=>t.priority-e.priority).map(t=>t.fn),n=t=>s.reduce((t,e)=>e(t),t);return h.pipeline.set(t,n),n}static has(t,e){return!!h.filters.get(t)?.has(e)}static add(t,e,r,s={}){const{priority:n=10,active:i=!0,overrideable:a=!0}=s,o=h.filters.get(t)??new Map,c=o.get(e);return!(c&&!c.overrideable||(o.set(e,{id:e,fn:r,priority:n,active:i,overrideable:a}),h.filters.set(t,o),h.pipeline.delete(t),0))}static remove(t,e){h.pipeline.delete(t);const r=h.filters.get(t);return!!r&&r.delete(e)}static pause(t,e){h.pipeline.delete(t);const r=h.filters.get(t)?.get(e);return!(!r||(r.active=!1,0))}static resume(t,e){h.pipeline.delete(t);const r=h.filters.get(t)?.get(e);return!(!r||(r.active=!0,0))}static list(t,e=!1){const r=h.filters.get(t);if(!r)return[];const s=[];for(const t of r.values())e&&!t.active||s.push(t.id);return s}static apply(t,e){const r=h.getPipeline(t);return Array.isArray(e)?e.map(r):r(e)}static async applyAsync(t,e){const r=h.getPipeline(t);return Array.isArray(e)?Promise.all(e.map(r)):Promise.resolve(r(e))}static clear(t){h.pipeline.clear(),t?h.filters.delete(t):h.filters.clear()}static clearPipeline(){h.pipeline.clear()}}class p{static FNV_PRIME=16777619;static HASH_OFFSET=2166136261;static fastFNV1a(t){const e=t.length;let r=this.HASH_OFFSET;const s=Math.floor(e/4);for(let e=0;e<s;e++){const s=4*e;r^=t.charCodeAt(s)|t.charCodeAt(s+1)<<8|t.charCodeAt(s+2)<<16|t.charCodeAt(s+3)<<24,r=Math.imul(r,this.FNV_PRIME)}const n=e%4;if(n>0){const e=4*s;for(let s=0;s<n;s++)r^=t.charCodeAt(e+s),r=Math.imul(r,this.FNV_PRIME)}return r^=r>>>16,r*=2246822507,r^=r>>>13,r*=3266489909,r^=r>>>16,r>>>0}}class u{LRU;static MAX_LEN=2048;static TABLE_SIZE=1e4;table=new Map;constructor(t=!0){this.LRU=t}key(t,e,r=!1){for(const t of e)if(t.length>u.MAX_LEN)return!1;const s=e.map(t=>p.fastFNV1a(t));return[t,...r?s.sort():s].join("-")}has=t=>this.table.has(t);get=t=>this.table.get(t);set(t,e,r=!0){if(!r&&this.table.has(t))return!1;for(;!this.table.has(t)&&this.table.size>=u.TABLE_SIZE;){if(!this.LRU)return!1;this.table.delete(this.table.keys().next().value)}return this.table.set(t,e),!0}delete=t=>this.table.delete(t);clear=()=>this.table.clear();size=()=>this.table.size}class d{static pipeline=new Map;static cache=new u;static REGEX={whitespace:/\s+/g,doubleChars:/(.)\1+/g,specialChars:/[^\p{L}\p{N}\s]/gu,nonLetters:/[^\p{L}]/gu,nonNumbers:/\p{N}/gu};static canonicalFlags(t){return Array.from(new Set(t)).sort().join("")}static getPipeline(t){if(d.pipeline.has(t))return d.pipeline.get(t);const{REGEX:e}=d,r=[["d",t=>t.normalize("NFD")],["i",t=>t.toLowerCase()],["k",t=>t.replace(e.nonLetters,"")],["n",t=>t.replace(e.nonNumbers,"")],["r",t=>t.replace(e.doubleChars,"$1")],["s",t=>t.replace(e.specialChars,"")],["t",t=>t.trim()],["u",t=>t.normalize("NFC")],["w",t=>t.replace(e.whitespace," ")],["x",t=>t.normalize("NFKC")]].filter(([e])=>t.includes(e)).map(([,t])=>t),s=t=>r.reduce((t,e)=>e(t),t);return d.pipeline.set(t,s),s}static normalize(t,e){if(!e||"string"!=typeof e||!t)return t;if(e=this.canonicalFlags(e),Array.isArray(t))return t.map(t=>d.normalize(t,e));const r=d.cache.key(e,[t]);if(r&&d.cache.has(r))return d.cache.get(r);const s=d.getPipeline(e)(t);return r&&d.cache.set(r,s),s}static async normalizeAsync(t,e){return await(Array.isArray(t)?Promise.all(t.map(t=>d.normalize(t,e))):Promise.resolve(d.normalize(t,e)))}static clear(){d.pipeline.clear(),d.cache.clear()}}class g{active;static ENV;static instance;nowFn;memFn;store=new Set;totalTime=0;totalMem=0;static detectEnv(){"undefined"!=typeof process?g.ENV="nodejs":"undefined"!=typeof performance?g.ENV="browser":g.ENV="unknown"}static getInstance(t){return g.ENV||g.detectEnv(),g.instance||=new g(t)}constructor(t=!1){switch(this.active=t,g.ENV){case"nodejs":this.nowFn=()=>Number(process.hrtime.bigint())/1e6,this.memFn=()=>process.memoryUsage().heapUsed;break;case"browser":this.nowFn=()=>performance.now(),this.memFn=()=>performance.memory?.usedJSHeapSize??0;break;default:this.nowFn=()=>Date.now(),this.memFn=()=>0}}now=()=>this.nowFn();mem=()=>this.memFn();profile(t,e){const r=this.now(),s=this.mem(),n=t(),i=this.now()-r,a=this.mem()-s;return this.store.add({time:i,mem:a,res:n,meta:e}),this.totalTime+=i,this.totalMem+=a,n}enable=()=>{this.active=!0};disable=()=>{this.active=!1};clear(){this.store.clear(),this.totalTime=0,this.totalMem=0}run(t,e={}){return this.active?this.profile(t,e):t()}async runAsync(t,e={}){return this.active?this.profile(async()=>await t(),e):await t()}getAll=()=>[...this.store];getLast=()=>this.getAll().pop();getTotal=()=>({time:this.totalTime,mem:this.totalMem});services=Object.freeze({enable:this.enable.bind(this),disable:this.disable.bind(this),clear:this.clear.bind(this),report:this.getAll.bind(this),last:this.getLast.bind(this),total:this.getTotal.bind(this)})}const m=Object.create(null),f=Object.create(null);function y(t,e){if(t in m||t in f)throw new Error(`Registry <${t}> already exists / overwriting is forbidden`);const r=Object.create(null),s=Object.freeze({add(s,n,i=!1){if(!(n.prototype instanceof e))throw new TypeError(`Class must extend <${t}>`);if(!i&&s in r)throw new Error(`Entry <${s}> already exists / use <update=true> to overwrite`);r[s]=n},remove(t){delete r[t]},has:t=>t in r,list:()=>Object.keys(r),get(e){if(!(e in r))throw new Error(`Class <${e}> not registered for <${t}>`);return r[e]}});return m[t]=s,f[t]=(e,...r)=>function(t,e,...r){e=function(t,e){if(!(t in m))throw new ReferenceError(`Registry <${t}> does not exist`);return"string"==typeof e?m[t]?.get(e):e}(t,e);try{return new e(...r)}catch(t){throw new Error(`Cannot instantiate class <${e.name??e}>`,{cause:t})}}(t,e,...r),s}class w{maxSize;buffers=[];pointer=0;constructor(t){this.maxSize=t}acquire(t,e){const r=this.buffers.length;for(let s=0;s<r;s++){const n=this.pointer+s&r-1,i=this.buffers[n];if(i.size>=t&&(e||i.size===t))return this.pointer=n+1&r-1,i}return null}release(t){this.buffers.length<this.maxSize?this.buffers.push(t):(this.buffers[this.pointer]=t,this.pointer=(this.pointer+1)%this.maxSize)}clear(){this.buffers=[],this.pointer=0}}class b{static CONFIG={int32:{type:"int32",maxSize:64,maxItemSize:2048,allowOversize:!0},"number[]":{type:"number[]",maxSize:16,maxItemSize:1024,allowOversize:!1},"string[]":{type:"string[]",maxSize:2,maxItemSize:1024,allowOversize:!1},set:{type:"set",maxSize:8,maxItemSize:0,allowOversize:!1},map:{type:"map",maxSize:8,maxItemSize:0,allowOversize:!1}};static POOLS={int32:new w(64),"number[]":new w(16),"string[]":new w(2),set:new w(8),map:new w(8)};static allocate(t,e){switch(t){case"int32":return new Int32Array(e);case"number[]":return new Float64Array(e);case"string[]":return new Array(e);case"set":return new Set;case"map":return new Map}}static acquire(t,e){const r=this.CONFIG[t];if(e>r.maxItemSize)return this.allocate(t,e);const s=this.POOLS[t].acquire(e,r.allowOversize);return s?"int32"===t?s.buffer.subarray(0,e):s.buffer:this.allocate(t,e)}static acquireMany(t,e){return e.map(e=>this.acquire(t,e))}static release(t,e,r){r<=this.CONFIG[t].maxItemSize&&this.POOLS[t].release({buffer:e,size:r})}}class A{data;key;static create(t,e){return new A(t,e)}constructor(t,e){this.data=t,this.key=e}extractFrom(t,e){const r=b.acquire("string[]",t.length);for(let s=0;s<t.length;s++){const n=t[s][e];r[s]="string"==typeof n?n:String(n??"")}return r}extract=()=>this.extractFrom(this.data,this.key);isMetricResult(t){return"object"==typeof t&&null!==t&&"a"in t&&"b"in t&&"res"in t}isCmpStrResult(t){return"object"==typeof t&&null!==t&&"source"in t&&"target"in t&&"match"in t}normalizeResults(t){if(!Array.isArray(t)||0===t.length)return[];const e=t[0];let r=[];if(this.isMetricResult(e))r=t;else{if(!this.isCmpStrResult(e))throw new TypeError("Unsupported result format for StructuredData normalization.");r=t.map(t=>({metric:"unknown",a:t.source,b:t.target,res:t.match,raw:t.raw}))}return r.map((t,e)=>({...t,__idx:e}))}rebuild(t,e,r,s,n){const i=new Map;for(let t=0;t<r.length;t++){const e=r[t];i.has(e)||i.set(e,[]),i.get(e).push(t)}const a=new Array(t.length),o=new Map;let c=0;for(let l=0;l<t.length;l++){const h=t[l];if(s&&0===h.res)continue;const p=h.b||"",u=i.get(p);let d;if(u&&u.length>0){const t=o.get(p)??0;o.set(p,t+1),d=u[t%u.length]}else d=h.__idx??l;if(d<0||d>=e.length)continue;const g=e[d],m=r[d]||p;a[c++]=n?g:{obj:g,key:this.key,result:{source:h.a,target:m,match:h.res},...h.raw?{raw:h.raw}:null}}return a.length=c,a}sort(t,e){if(!e||t.length<=1)return t;const r="asc"===e;return t.sort((t,e)=>r?t.res-e.res:e.res-t.res)}finalizeLookup(t,e,r){return this.rebuild(this.sort(this.normalizeResults(t),r?.sort),this.data,e,r?.removeZero,r?.objectsOnly)}performLookup(t,e,r){return this.finalizeLookup(t(),e,r)}async performLookupAsync(t,e,r){return this.finalizeLookup(await t(),e,r)}lookup(t,e,r){const s=this.extract();try{return this.performLookup(()=>t(e,s,r),s,r)}finally{b.release("string[]",s,s.length)}}async lookupAsync(t,e,r){const s=this.extract();try{return await this.performLookupAsync(()=>t(e,s,r),s,r)}finally{b.release("string[]",s,s.length)}}lookupPairs(t,e,r,s){const n=this.extract(),i=this.extractFrom(e,r);try{return this.performLookup(()=>t(n,i,s),n,s)}finally{b.release("string[]",n,n.length),b.release("string[]",i,i.length)}}async lookupPairsAsync(t,e,r,s){const n=this.extract(),i=this.extractFrom(e,r);try{return await this.performLookupAsync(()=>t(n,i,s),n,s)}finally{b.release("string[]",n,n.length),b.release("string[]",i,i.length)}}}class x{static REGEX={number:/\d/,sentence:/(?<=[.!?])\s+/,word:/\p{L}+/gu,nonWord:/[^\p{L}]/gu,vowelGroup:/[aeiouy]+/g,letter:/\p{L}/gu,ucLetter:/\p{Lu}/gu};text;words=[];sentences=[];charFrequency=new Map;wordHistogram=new Map;syllableCache=new Map;syllableStats;constructor(t){this.text=t.trim(),this.tokenize(),this.computeFrequencies()}tokenize(){let t;const e=this.text.toLowerCase();for(;null!==(t=x.REGEX.word.exec(e));)this.words.push(t[0]);this.sentences=this.text.split(x.REGEX.sentence).filter(Boolean)}computeFrequencies(){for(const t of this.text)this.charFrequency.set(t,(this.charFrequency.get(t)??0)+1);for(const t of this.words)this.wordHistogram.set(t,(this.wordHistogram.get(t)??0)+1)}estimateSyllables(t){const e=t.normalize("NFC").toLowerCase().replace(x.REGEX.nonWord,"");if(this.syllableCache.has(e))return this.syllableCache.get(e);const r=e.match(x.REGEX.vowelGroup),s=r?r.length:1;return this.syllableCache.set(e,s),s}computeSyllableStats(){return this.syllableStats||=(()=>{const t=this.words.map(t=>this.estimateSyllables(t)).sort((t,e)=>t-e),e=t.reduce((t,e)=>t+e,0),r=t.filter(t=>1===t).length,s=t.length?t.length%2==0?(t[t.length/2-1]+t[t.length/2])/2:t[Math.floor(t.length/2)]:0;return{total:e,mono:r,perWord:t,avg:t.length?e/t.length:0,median:s}})()}getLength=()=>this.text.length;getWordCount=()=>this.words.length;getSentenceCount=()=>this.sentences.length;getAvgWordLength(){return this.words.length?this.words.join("").length/this.words.length:0}getAvgSentenceLength(){return this.sentences.length?this.words.length/this.sentences.length:0}getWordHistogram(){return Object.fromEntries(this.wordHistogram)}getMostCommonWords(t=5){return[...this.wordHistogram.entries()].sort((t,e)=>e[1]-t[1]).slice(0,t).map(t=>t[0])}getHapaxLegomena(){return[...this.wordHistogram.entries()].filter(([,t])=>1===t).map(t=>t[0])}hasNumbers=()=>x.REGEX.number.test(this.text);getUpperCaseRatio(){const t=this.text.match(x.REGEX.letter)||[],e=this.text.match(x.REGEX.ucLetter)?.length||0;return t.length?e/t.length:0}getCharFrequency(){return Object.fromEntries(this.charFrequency)}getUnicodeCodepoints(){const t={};for(const[e,r]of this.charFrequency){const s=e.charCodeAt(0).toString(16).padStart(4,"0").toUpperCase();t[s]=(t[s]||0)+r}return t}getLongWordRatio(t=7){let e=0;for(const r of this.words)r.length>=t&&e++;return this.words.length?e/this.words.length:0}getShortWordRatio(t=3){let e=0;for(const r of this.words)r.length<=t&&e++;return this.words.length?e/this.words.length:0}getSyllablesCount(){return this.computeSyllableStats().total}getMonosyllabicWordCount(){return this.computeSyllableStats().mono}getMinSyllablesWordCount(t){return this.computeSyllableStats().perWord.filter(e=>e>=t).length}getMaxSyllablesWordCount(t){return this.computeSyllableStats().perWord.filter(e=>e<=t).length}getAvgSyllablesPerWord(){return this.computeSyllableStats().avg}getMedianSyllablesPerWord(){return this.computeSyllableStats().median}getHonoresR(){try{return 100*Math.log(this.words.length)/(1-this.getHapaxLegomena().length/(this.wordHistogram.size??1))}catch{return 0}}getReadingTime(t=200){return this.words.length/(t??1)}getReadabilityScore(t="flesch"){const e=this.words.length||1,r=e/(this.sentences.length||1),s=(this.getSyllablesCount()||1)/e;switch(t){case"flesch":return 206.835-1.015*r-84.6*s;case"fleschde":return 180-r-58.5*s;case"kincaid":return.39*r+11.8*s-15.59}}getLIXScore(){const t=this.words.length||1;return t/(this.sentences.length||1)+this.getLongWordRatio()*t/t*100}getWSTFScore(){const t=this.words.length||1,e=this.getMinSyllablesWordCount(3)/t*100,r=this.getAvgSentenceLength(),s=100*this.getLongWordRatio();return[.1935*e+.1672*r+.1297*s-this.getMonosyllabicWordCount()/t*100*.0327-.875,.2007*e+.1682*r+.1373*s-2.779,.2963*e+.1905*r-1.1144,.2744*e+.2656*r-1.693]}}const S=g.getInstance();class v{static cache=new u;metric;a;b;origA=[];origB=[];options;optKey;symmetric;results;static clear=()=>this.cache.clear();static swap=(t,e,r,s)=>r>s?[e,t,s,r]:[t,e,r,s];static clamp=t=>Math.max(0,Math.min(1,t));constructor(t,e,r,s={},n=!1){if(this.metric=t,this.a=Array.isArray(e)?e:[e],this.b=Array.isArray(r)?r:[r],0===this.a.length||0===this.b.length)throw new Error("Inputs <a> and <b> must not be empty");this.options=s,this.optKey=p.fastFNV1a(JSON.stringify(s,Object.keys(s).sort())).toString(),this.symmetric=n}preCompute(t,e,r,s){return t===e?{res:1}:0==r||0==s||r<2&&s<2?{res:0}:void 0}compute(t,e,r,s,n){throw new Error("Method compute() must be overridden in a subclass")}runSingle(t,e){let r=String(this.a[t]),s=r,n=String(this.b[e]),i=n,a=s.length,o=i.length,c=this.preCompute(s,i,a,o);return c||(c=S.run(()=>{this.symmetric&&([s,i,a,o]=v.swap(s,i,a,o));const t=v.cache.key(this.metric,[s,i],this.symmetric)+this.optKey;return v.cache.get(t||"")??(()=>{const e=this.compute(s,i,a,o,Math.max(a,o));return t&&v.cache.set(t,e),e})()})),{metric:this.metric,a:this.origA[t]??r,b:this.origB[e]??n,...c}}async runSingleAsync(t,e){return Promise.resolve(this.runSingle(t,e))}runBatch(){const t=[];for(let e=0;e<this.a.length;e++)for(let r=0;r<this.b.length;r++)t.push(this.runSingle(e,r));this.results=t}async runBatchAsync(){const t=[];for(let e=0;e<this.a.length;e++)for(let r=0;r<this.b.length;r++)t.push(await this.runSingleAsync(e,r));this.results=t}runPairwise(){const t=[];for(let e=0;e<this.a.length;e++)t.push(this.runSingle(e,e));this.results=t}async runPairwiseAsync(){const t=[];for(let e=0;e<this.a.length;e++)t.push(await this.runSingleAsync(e,e));this.results=t}setOriginal(t,e){return t&&(this.origA=Array.isArray(t)?t:[t]),e&&(this.origB=Array.isArray(e)?e:[e]),this}isBatch=()=>this.a.length>1||this.b.length>1;isSingle=()=>!this.isBatch();isPairwise(t=!1){return!(!this.isBatch()||this.a.length!==this.b.length)||!t&&(()=>{throw new Error("Mode <pairwise> requires arrays of equal length")})()}isSymmetrical=()=>this.symmetric;whichMode=t=>t??this.options?.mode??"default";clear=()=>this.results=void 0;run(t,e=!0){switch(e&&this.clear(),this.whichMode(t)){case"default":if(this.isSingle()){this.results=this.runSingle(0,0);break}case"batch":this.runBatch();break;case"single":this.results=this.runSingle(0,0);break;case"pairwise":this.isPairwise()&&this.runPairwise();break;default:throw new Error(`Unsupported mode <${t}>`)}}async runAsync(t,e=!0){switch(e&&this.clear(),this.whichMode(t)){case"default":if(this.isSingle()){this.results=await this.runSingleAsync(0,0);break}case"batch":await this.runBatchAsync();break;case"single":this.results=await this.runSingleAsync(0,0);break;case"pairwise":this.isPairwise()&&await this.runPairwiseAsync();break;default:throw new Error(`Unsupported async mode <${t}>`)}}getMetricName=()=>this.metric;getResults(){if(void 0===this.results)throw new Error("run() must be called before getResult()");return this.results}}const z=y("metric",v);z.add("cosine",class extends v{constructor(t,e,r={}){super("cosine",t,e,r,!0)}_termFreq(t,e){const r=t.split(e),s=b.acquire("map",r.length);for(const t of r)s.set(t,(s.get(t)||0)+1);return s}compute(t,e){const{delimiter:r=" "}=this.options,s=this._termFreq(t,r),n=this._termFreq(e,r);try{let t=0,e=0,r=0;for(const[r,i]of s)t+=i*(n.get(r)||0),e+=i*i;for(const t of n.values())r+=t*t;return e=Math.sqrt(e),r=Math.sqrt(r),{res:e&&r?v.clamp(t/(e*r)):0,raw:{dotProduct:t,magnitudeA:e,magnitudeB:r}}}finally{b.release("map",s,s.size),b.release("map",n,n.size)}}}),z.add("damerau",class extends v{constructor(t,e,r={}){super("damerau",t,e,r,!0)}compute(t,e,r,s,n){const i=r+1,[a,o,c]=b.acquireMany("int32",[i,i,i]);try{for(let t=0;t<=r;t++)o[t]=t;for(let n=1;n<=s;n++){c[0]=n;const s=e.charCodeAt(n-1);for(let i=1;i<=r;i++){const r=t.charCodeAt(i-1),l=r===s?0:1;let h=Math.min(c[i-1]+1,o[i]+1,o[i-1]+l);i>1&&n>1&&r===e.charCodeAt(n-2)&&s===t.charCodeAt(i-2)&&(h=Math.min(h,a[i-2]+l)),c[i]=h}a.set(o),o.set(c)}const i=o[r];return{res:0===n?1:v.clamp(1-i/n),raw:{dist:i,maxLen:n}}}finally{b.release("int32",a,i),b.release("int32",o,i),b.release("int32",c,i)}}}),z.add("dice",class extends v{constructor(t,e,r={}){super("dice",t,e,r,!0)}_bigrams(t){const e=t.length-1,r=b.acquire("set",e);for(let s=0;s<e;s++)r.add(t.substring(s,s+2));return r}compute(t,e){const r=this._bigrams(t),s=this._bigrams(e),n=r.size,i=s.size;try{let t=0;for(const e of r)s.has(e)&&t++;const e=n+i;return{res:0===e?1:v.clamp(2*t/e),raw:{intersection:t,size:e}}}finally{b.release("set",r,n),b.release("set",s,i)}}}),z.add("hamming",class extends v{constructor(t,e,r={}){super("hamming",t,e,r,!0)}compute(t,e,r,s,n){if(r!==s){if(void 0===this.options.pad)throw new Error(`Strings must be of equal length for Hamming Distance, a=${r} and b=${s} given, use option.pad for automatic adjustment`);r<n&&(t=t.padEnd(n,this.options.pad)),s<n&&(e=e.padEnd(n,this.options.pad)),r=s=n}let i=0;for(let s=0;s<r;s++)t[s]!==e[s]&&i++;return{res:0===r?1:v.clamp(1-i/r),raw:{dist:i}}}}),z.add("jaccard",class extends v{constructor(t,e,r={}){super("jaccard",t,e,r,!0)}compute(t,e,r,s){const[n,i]=b.acquireMany("set",[r,s]);try{for(const e of t)n.add(e);for(const t of e)i.add(t);let r=0;for(const t of n)i.has(t)&&r++;const s=n.size+i.size-r;return{res:0===s?1:v.clamp(r/s),raw:{intersection:r,union:s}}}finally{b.release("set",n,r),b.release("set",i,s)}}}),z.add("jaroWinkler",class extends v{constructor(t,e,r={}){super("jaroWinkler",t,e,r,!0)}compute(t,e,r,s){const[n,i]=b.acquireMany("int32",[r,s]);try{for(let t=0;t<r;t++)n[t]=0;for(let t=0;t<s;t++)i[t]=0;const a=Math.max(0,Math.floor(s/2)-1);let o=0;for(let c=0;c<r;c++){const r=Math.max(0,c-a),l=Math.min(c+a+1,s);for(let s=r;s<l;s++)if(!i[s]&&t[c]===e[s]){n[c]=1,i[s]=1,o++;break}}let c=0,l=0,h=0,p=0;if(o>0){let a=0;for(let s=0;s<r;s++)if(n[s]){for(;!i[a];)a++;t[s]!==e[a]&&c++,a++}c/=2,l=(o/r+o/s+(o-c)/o)/3;for(let n=0;n<Math.min(4,r,s)&&t[n]===e[n];n++)h++;p=l+.1*h*(1-l)}return{res:v.clamp(p),raw:{matchWindow:a,matches:o,transpos:c,jaro:l,prefix:h}}}finally{b.release("int32",n,r),b.release("int32",i,s)}}}),z.add("lcs",class extends v{constructor(t,e,r={}){super("lcs",t,e,r,!0)}compute(t,e,r,s,n){const i=r+1,[a,o]=b.acquireMany("int32",[i,i]);try{for(let t=0;t<=r;t++)a[t]=0;for(let n=1;n<=s;n++){o[0]=0;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++)t.charCodeAt(e-1)===s?o[e]=a[e-1]+1:o[e]=Math.max(a[e],o[e-1]);a.set(o)}const i=a[r];return{res:0===n?1:v.clamp(i/n),raw:{lcs:i,maxLen:n}}}finally{b.release("int32",a,i),b.release("int32",o,i)}}}),z.add("levenshtein",class extends v{constructor(t,e,r={}){super("levenshtein",t,e,r,!0)}compute(t,e,r,s,n){const i=r+1,[a,o]=b.acquireMany("int32",[i,i]);try{for(let t=0;t<=r;t++)a[t]=t;for(let n=1;n<=s;n++){o[0]=n;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?0:1;o[e]=Math.min(o[e-1]+1,a[e]+1,a[e-1]+r)}a.set(o)}const i=a[r];return{res:0===n?1:v.clamp(1-i/n),raw:{dist:i,maxLen:n}}}finally{b.release("int32",a,i),b.release("int32",o,i)}}}),z.add("needlemanWunsch",class extends v{constructor(t,e,r={}){super("needlemanWunsch",t,e,r,!0)}compute(t,e,r,s,n){const{match:i=1,mismatch:a=-1,gap:o=-1}=this.options,c=r+1,[l,h]=b.acquireMany("int32",[c,c]);try{l[0]=0;for(let t=1;t<=r;t++)l[t]=l[t-1]+o;for(let n=1;n<=s;n++){h[0]=l[0]+o;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?i:a;h[e]=Math.max(l[e-1]+r,l[e]+o,h[e-1]+o)}l.set(h)}const c=l[r],p=n*i;return{res:0===p?0:v.clamp(c/p),raw:{score:c,denum:p}}}finally{b.release("int32",l,c),b.release("int32",h,c)}}}),z.add("qGram",class extends v{constructor(t,e,r={}){super("qGram",t,e,r,!0)}_qGrams(t,e){const r=Math.max(0,t.length-e+1),s=b.acquire("set",r);for(let n=0;n<r;n++)s.add(t.slice(n,n+e));return s}compute(t,e){const{q:r=2}=this.options,s=this._qGrams(t,r),n=this._qGrams(e,r),i=s.size,a=n.size;try{let t=0;for(const e of s)n.has(e)&&t++;const e=Math.max(i,a);return{res:0===e?1:v.clamp(t/e),raw:{intersection:t,size:e}}}finally{b.release("set",s,i),b.release("set",n,a)}}}),z.add("smithWaterman",class extends v{constructor(t,e,r={}){super("smithWaterman",t,e,r,!0)}compute(t,e,r,s){const{match:n=2,mismatch:i=-1,gap:a=-2}=this.options,o=r+1,[c,l]=b.acquireMany("int32",[o,o]);let h=0;try{for(let t=0;t<=r;t++)c[t]=0;for(let o=1;o<=s;o++){l[0]=0;const s=e.charCodeAt(o-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?n:i;l[e]=Math.max(0,c[e-1]+r,c[e]+a,l[e-1]+a),l[e]>h&&(h=l[e])}c.set(l)}const o=Math.min(r*n,s*n);return{res:0===o?0:v.clamp(h/o),raw:{score:h,denum:o}}}finally{b.release("int32",c,o),b.release("int32",l,o)}}});const k=g.getInstance();class M{static cache=new u;static default;algo;options;optKey;map;static clear=()=>this.cache.clear();constructor(t,e={}){const r=this.constructor.default??{},s=e.map??r.map;if(!s)throw new Error("No mapping specified for phonetic algorithm");const n=E.get(t,s);if(void 0===n)throw new Error(`Requested mapping <${s}> is not declared`);this.options=a(a(r,n.options??{}),e),this.optKey=p.fastFNV1a(JSON.stringify(this.options,Object.keys(this.options).sort())).toString(),this.algo=t,this.map=n}applyPattern(t){const{patterns:e=[]}=this.map;if(!e||!e.length)return t;for(const{pattern:r,replace:s,all:n=!1}of e)t=t[n?"replaceAll":"replace"](r,s);return t}applyRules(t,e,r,s){const{ruleset:n=[]}=this.map;if(!n||!n.length)return;const i=r[e-1]||"",a=r[e-2]||"",o=r[e+1]||"",c=r[e+2]||"";for(const l of n)if((!l.char||l.char===t)&&("start"!==l.position||0===e)&&("middle"!==l.position||0!==e&&e!==s-1)&&("end"!==l.position||e===s)&&(!l.prev||l.prev.includes(i))&&(!l.prevNot||!l.prevNot.includes(i))&&(!l.prev2||l.prev2.includes(a))&&(!l.prev2Not||!l.prev2Not.includes(a))&&(!l.next||l.next.includes(o))&&(!l.nextNot||!l.nextNot.includes(o))&&(!l.next2||l.next2.includes(c))&&(!l.next2Not||!l.next2Not.includes(c))&&(!l.leading||l.leading.includes(r.slice(0,l.leading.length).join("")))&&(!l.trailing||l.trailing.includes(r.slice(-l.trailing.length).join("")))&&(!l.match||l.match.every((t,s)=>r[e+s]===t)))return l.code}encode(t){const{map:e={},ignore:r=[]}=this.map;t=this.applyPattern(t);const s=this.word2Chars(t),n=s.length;let i="",a=null;for(let t=0;t<n;t++){const o=s[t];if(r.includes(o))continue;const c=this.mapChar(o,t,s,n,a,e);if(void 0!==c&&(i+=c,a=c,this.exitEarly(i,t)))break}return this.adjustCode(i,s)}mapChar(t,e,r,s,n,i){const{dedupe:a=!0,fallback:o}=this.options,c=this.applyRules(t,e,r,s)??i[t]??o;return a&&c===n?void 0:c}equalLen(t){const{length:e=-1,pad:r="0"}=this.options;return-1===e?t:(t+r.repeat(e)).slice(0,e)}word2Chars=t=>t.toLowerCase().split("");exitEarly(t,e){const{length:r=-1}=this.options;return r>0&&t.length>=r}adjustCode(t,e){return t}loop(t){const e=[];for(const r of t){const t=M.cache.key(this.algo,[r])+this.optKey,s=M.cache.get(t||"")??(()=>{const e=this.encode(r);return t&&M.cache.set(t,e),e})();s&&s.length&&e.push(this.equalLen(s))}return e}async loopAsync(t){const e=[];for(const r of t){const t=M.cache.key(this.algo,[r])+this.optKey,s=await Promise.resolve(M.cache.get(t||"")??(()=>{const e=this.encode(r);return t&&M.cache.set(t,e),e})());s&&s.length&&e.push(this.equalLen(s))}return e}getAlgoName=()=>this.algo;getIndex(t){const{delimiter:e=" "}=this.options;return k.run(()=>this.loop(t.split(e).filter(Boolean)).filter(Boolean))}async getIndexAsync(t){const{delimiter:e=" "}=this.options;return(await k.runAsync(async()=>await this.loopAsync(t.split(e).filter(Boolean)))).filter(Boolean)}}const C=y("phonetic",M),E=(()=>{const t=Object.create(null),e=e=>t[e]||=Object.create(null);return Object.freeze({add(t,r,s,n=!1){const i=e(t);if(!n&&r in i)throw new Error(`Entry <${r}> already exists / use <update=true> to overwrite`);i[r]=s},remove(t,r){delete e(t)[r]},has:(t,r)=>r in e(t),get:(t,r)=>e(t)[r],list:t=>Object.keys(e(t))})})();class O extends M{static REGEX={uppercase:/[^A-Z]/gi};static default={map:"en2",delimiter:" ",length:-1,pad:"",dedupe:!1};constructor(t={}){super("caverphone",t)}encode(t){return t=t.replace(O.REGEX.uppercase,"").toLowerCase(),super.encode(t)}mapChar=t=>t;adjustCode=t=>t.toUpperCase()}C.add("caverphone",O),E.add("caverphone","en1",{options:{length:6,pad:"1"},map:{},patterns:[{pattern:/^(c|r|t|en)ough/,replace:"$1ou2f"},{pattern:/^gn/,replace:"2n"},{pattern:/mb$/,replace:"m2"},{pattern:/cq/g,replace:"2q"},{pattern:/c(e|i|y)/g,replace:"s$1"},{pattern:/tch/g,replace:"2ch"},{pattern:/[cqx]/g,replace:"k"},{pattern:/v/g,replace:"f"},{pattern:/dg/g,replace:"2g"},{pattern:/ti(a|o)/g,replace:"si$1"},{pattern:/d/g,replace:"t"},{pattern:/ph/g,replace:"fh"},{pattern:/b/g,replace:"p"},{pattern:/sh/g,replace:"s2"},{pattern:/z/g,replace:"s"},{pattern:/^[aeiou]/,replace:"A"},{pattern:/[aeiou]/g,replace:"3"},{pattern:/3gh3/g,replace:"3kh3"},{pattern:/gh/g,replace:"22"},{pattern:/g/g,replace:"k"},{pattern:/s+/g,replace:"S"},{pattern:/t+/g,replace:"T"},{pattern:/p+/g,replace:"P"},{pattern:/k+/g,replace:"K"},{pattern:/f+/g,replace:"F"},{pattern:/m+/g,replace:"M"},{pattern:/n+/g,replace:"N"},{pattern:/j/g,replace:"y"},{pattern:/l3/g,replace:"L3"},{pattern:/r3/g,replace:"R3"},{pattern:/w3/g,replace:"W3"},{pattern:/y3/g,replace:"Y3"},{pattern:/ly/g,replace:"Ly"},{pattern:/ry/g,replace:"Ry"},{pattern:/wy/g,replace:"Wy"},{pattern:/wh3/g,replace:"Wh3"},{pattern:/why/g,replace:"Why"},{pattern:/^h/,replace:"A"},{pattern:/[hlrwy23]/g,replace:""}]}),E.add("caverphone","en2",{options:{length:10,pad:"1"},map:{},patterns:[{pattern:/e$/,replace:""},{pattern:/^(c|r|t|en|tr)ough/,replace:"$1ou2f"},{pattern:/^gn/,replace:"2n"},{pattern:/mb$/,replace:"m2"},{pattern:/cq/g,replace:"2q"},{pattern:/c(e|i|y)/g,replace:"s$1"},{pattern:/tch/g,replace:"2ch"},{pattern:/[cqx]/g,replace:"k"},{pattern:/v/g,replace:"f"},{pattern:/dg/g,replace:"2g"},{pattern:/ti(a|o)/g,replace:"si$1"},{pattern:/d/g,replace:"t"},{pattern:/ph/g,replace:"fh"},{pattern:/b/g,replace:"p"},{pattern:/sh/g,replace:"s2"},{pattern:/z/g,replace:"s"},{pattern:/^[aeiou]/,replace:"A"},{pattern:/[aeiou]/g,replace:"3"},{pattern:/j/g,replace:"y"},{pattern:/^y3/,replace:"Y3"},{pattern:/^y/,replace:"A"},{pattern:/y/g,replace:"3"},{pattern:/3gh3/g,replace:"3kh3"},{pattern:/gh/g,replace:"22"},{pattern:/g/g,replace:"k"},{pattern:/s+/g,replace:"S"},{pattern:/t+/g,replace:"T"},{pattern:/p+/g,replace:"P"},{pattern:/k+/g,replace:"K"},{pattern:/f+/g,replace:"F"},{pattern:/m+/g,replace:"M"},{pattern:/n+/g,replace:"N"},{pattern:/l3/g,replace:"L3"},{pattern:/r3/g,replace:"R3"},{pattern:/w3/g,replace:"W3"},{pattern:/wh3/g,replace:"Wh3"},{pattern:/[lrw]$/,replace:"3"},{pattern:/^h/,replace:"A"},{pattern:/3$/,replace:"A"},{pattern:/[hlrw23]/g,replace:""}]}),C.add("cologne",class extends M{static default={map:"default",delimiter:" ",length:-1,dedupe:!0};constructor(t={}){super("cologne",t)}adjustCode(t){return t.slice(0,1)+t.slice(1).replaceAll("0","")}}),E.add("cologne","default",{map:{a:"0","ä":"0",e:"0",i:"0",j:"0",o:"0","ö":"0",u:"0","ü":"0",y:"0",b:"1",p:"1",d:"2",t:"2",f:"3",v:"3",w:"3",g:"4",k:"4",q:"4",l:"5",m:"6",n:"6",r:"7",c:"8",s:"8","ß":"8",z:"8",x:"48"},ignore:["h"],ruleset:[{char:"p",next:["h"],code:"3"},{char:"c",position:"start",next:["a","h","k","l","o","q","r","u","x"],code:"4"},{char:"c",next:["a","h","k","o","q","u","x"],prevNot:["s","z"],code:"4"},{char:"d",next:["c","s","z"],code:"8"},{char:"t",next:["c","s","z"],code:"8"},{char:"x",prev:["c","k","q"],code:"8"}]});class j extends M{static REGEX={adjacent:/([A-BD-Z])\1+/gi,vowel:/[AEIOU]/g};static default={map:"en90",delimiter:" ",length:-1,pad:"",dedupe:!1};constructor(t={}){super("metaphone",t)}encode(t){return t=t.replace(j.REGEX.adjacent,(t,e)=>"C"===e?t:e),super.encode(t)}adjustCode(t){return t.slice(0,1)+t.slice(1).replace(j.REGEX.vowel,"")}}C.add("metaphone",j),E.add("metaphone","en90",{map:{a:"A",b:"B",c:"K",d:"T",e:"E",f:"F",g:"K",h:"H",i:"I",j:"J",k:"K",l:"L",m:"M",n:"N",o:"O",p:"P",q:"K",r:"R",s:"S",t:"T",u:"U",v:"F",w:"W",x:"KS",y:"Y",z:"S"},ruleset:[{char:"a",position:"start",next:["e"],code:""},{char:"g",position:"start",next:["n"],code:""},{char:"k",position:"start",next:["n"],code:""},{char:"p",position:"start",next:["n"],code:""},{char:"w",position:"start",next:["r"],code:""},{char:"b",position:"end",prev:["m"],code:""},{char:"c",next:["h"],prevNot:["s"],code:"X"},{char:"c",next:["i"],next2:["a"],code:"X"},{char:"c",next:["e","i","y"],code:"S"},{char:"d",next:["g"],next2:["e","i","y"],code:"J"},{char:"g",next:["h"],next2Not:["","a","e","i","o","u"],code:""},{char:"g",trailing:"n",code:""},{char:"g",trailing:"ned",code:""},{char:"g",next:["e","i","y"],prevNot:["g"],code:"J"},{char:"h",prev:["a","e","i","o","u"],nextNot:["a","e","i","o","u"],code:""},{char:"h",prev:["c","g","p","s","t"],code:""},{char:"k",prev:["c"],code:""},{char:"p",next:["h"],code:"F"},{char:"s",next:["h"],code:"X"},{char:"s",next:["i"],next2:["a","o"],code:"X"},{char:"t",next:["i"],next2:["a","o"],code:"X"},{char:"t",next:["h"],code:"0"},{char:"t",next:["c"],next2:["h"],code:""},{char:"w",nextNot:["a","e","i","o","u"],code:""},{char:"h",leading:"w",code:""},{char:"x",position:"start",code:"S"},{char:"y",nextNot:["a","e","i","o","u"],code:""}]}),C.add("soundex",class extends M{static default={map:"en",delimiter:" ",length:4,pad:"0",dedupe:!0};constructor(t={}){super("soundex",t)}adjustCode(t,e){return e[0].toUpperCase()+t.slice(1).replaceAll("0","")}}),E.add("soundex","en",{map:{a:"0",e:"0",h:"0",i:"0",o:"0",u:"0",w:"0",y:"0",b:"1",f:"1",p:"1",v:"1",c:"2",g:"2",j:"2",k:"2",q:"2",s:"2",x:"2",z:"2",d:"3",t:"3",l:"4",m:"5",n:"5",r:"6"}}),E.add("soundex","de",{map:{a:"0","ä":"0",e:"0",h:"0",i:"0",j:"0",o:"0","ö":"0",u:"0","ü":"0",y:"0",b:"1",f:"1",p:"1",v:"1",w:"1",c:"2",g:"2",k:"2",q:"2",s:"2","ß":"2",x:"2",z:"2",d:"3",t:"3",l:"4",m:"5",n:"5",r:"6"},ruleset:[{char:"c",next:["h"],code:"7"}]});const L=g.getInstance();class N{static filter={has:h.has,add:h.add,remove:h.remove,pause:h.pause,resume:h.resume,list:h.list,clear:h.clear};static metric={add:z.add,remove:z.remove,has:z.has,list:z.list};static phonetic={add:C.add,remove:C.remove,has:C.has,list:C.list,map:{add:E.add,remove:E.remove,has:E.has,list:E.list}};static profiler=L.services;static clearCache={normalizer:d.clear,filter:h.clearPipeline,metric:v.clear,phonetic:M.clear};static analyze=t=>new x(t);static diff=(t,e,r)=>new l(t,e,r);static create(t){return new N(t)}options=Object.create(null);constructor(t){t&&("string"==typeof t?this.setSerializedOptions(t):this.setOptions(t))}assert(t,e){switch(t){case"metric":if(!N.metric.has(e))throw new Error("CmpStr <metric> must be set, call .setMetric(), use CmpStr.metric.list() for available metrics");break;case"phonetic":if(!N.phonetic.has(e))throw new Error("CmpStr <phonetic> must be set, call .setPhonetic(), use CmpStr.phonetic.list() for available phonetic algorithms");break;default:throw new Error(`Cmpstr condition <${t}> unknown`)}}assertMany(...t){for(const[e,r]of t)this.assert(e,r)}resolveOptions(t){return a({...this.options??Object.create(null)},t)}normalize(t,e){return d.normalize(t,e??this.options.flags??"")}filter(t,e){return h.apply(e,t)}prepare(t,e){const{flags:r,processors:s}=e??this.options;return r?.length&&(t=this.normalize(t,r)),t=this.filter(t,"input"),s?.phonetic&&(t=this.index(t,s.phonetic)),t}postProcess(t,e){return e?.removeZero&&Array.isArray(t)&&(t=t.filter(t=>t.res>0)),t}index(t,{algo:e,opt:r}){this.assert("phonetic",e);const s=f.phonetic(e,r),n=r?.delimiter??" ";return Array.isArray(t)?t.map(t=>s.getIndex(t).join(n)):s.getIndex(t).join(n)}structured(t,e){return A.create(t,e)}compute(t,e,r,s,n,i){const a=this.resolveOptions(r);this.assert("metric",a.metric);const o=i?t:this.prepare(t,a),c=i?e:this.prepare(e,a);if(a.safeEmpty&&(Array.isArray(o)&&0===o.length||Array.isArray(c)&&0===c.length||""===o||""===c))return[];const l=f.metric(a.metric,o,c,a.opt);"prep"!==a.output&&l.setOriginal(t,e),l.run(s);const h=this.postProcess(l.getResults(),a);return this.output(h,n??a.raw)}output(t,e){return e??this.options.raw?t:Array.isArray(t)?t.map(t=>({source:t.a,target:t.b,match:t.res})):{source:t.a,target:t.b,match:t.res}}clone=()=>Object.assign(Object.create(Object.getPrototypeOf(this)),this);reset(){for(const t in this.options)delete this.options[t];return this}setOptions(t){return this.options=t,this}mergeOptions(t){return a(this.options,t),this}setSerializedOptions(t){return this.options=JSON.parse(t),this}setOption(t,e){return i(this.options,t,e),this}rmvOption(t){return o(this.options,t),this}setRaw=t=>this.setOption("raw",t);setMetric=t=>this.setOption("metric",t);setFlags=t=>this.setOption("flags",t);rmvFlags=()=>this.rmvOption("flags");setProcessors=t=>this.setOption("processors",t);rmvProcessors=()=>this.rmvOption("processors");getOptions=()=>this.options;getSerializedOptions=()=>JSON.stringify(this.options);getOption=t=>n(this.options,t);test(t,e,r){return this.compute(t,e,r,"single")}compare(t,e,r){return this.compute(t,e,r,"single",!0).res}batchTest(t,e,r){return this.compute(t,e,r,"batch")}batchSorted(t,e,r="desc",s){return this.output(this.compute(t,e,s,"batch",!0).sort((t,e)=>"asc"===r?t.res-e.res:e.res-t.res),s?.raw??this.options.raw)}pairs(t,e,r){return this.compute(t,e,r,"pairwise")}match(t,e,r,s){return this.output(this.compute(t,e,s,"batch",!0).filter(t=>t.res>=r).sort((t,e)=>e.res-t.res),s?.raw??this.options.raw)}closest(t,e,r=1,s){return this.batchSorted(t,e,"desc",s).slice(0,r)}furthest(t,e,r=1,s){return this.batchSorted(t,e,"asc",s).slice(0,r)}search(t,e,r,s){const n=this.resolveOptions({flags:r,processors:s}),i=this.prepare(t,n),a=this.prepare(e,n);return e.filter((t,e)=>a[e].includes(i))}matrix(t,e){return(t=this.prepare(t,this.resolveOptions(e))).map(e=>this.compute(e,t,void 0,"batch",!0,!0).map(t=>t.res??0))}phoneticIndex(t,e,r){const{algo:s,opt:n}=this.options.processors?.phonetic??{};return this.index(t,{algo:e??s,opt:r??n})}structuredLookup(t,e,r,s){return this.structured(e,r).lookup((t,e,r)=>this.batchTest(t,e,r),t,s)}structuredMatch(t,e,r,s,n){return this.structured(e,r).lookup((t,e,r)=>this.match(t,e,s,r),t,{...n,sort:"desc"})}structuredClosest(t,e,r,s=1,n){return this.structured(e,r).lookup((t,e,r)=>this.closest(t,e,s,r),t,{...n,sort:"desc"})}structuredFurthest(t,e,r,s=1,n){return this.structured(e,r).lookup((t,e,r)=>this.furthest(t,e,s,r),t,{...n,sort:"asc"})}structuredPairs(t,e,r,s,n){return this.structured(t,e).lookupPairs((t,e,r)=>this.pairs(t,e,r),r,s,n)}}class F extends N{static create(t){return new F(t)}constructor(t){super(t)}async normalizeAsync(t,e){return d.normalizeAsync(t,e??this.options.flags??"")}async filterAsync(t,e){return h.applyAsync(e,t)}async prepareAsync(t,e){const{flags:r,processors:s}=e??this.options;return r?.length&&(t=await this.normalizeAsync(t,r)),t=await this.filterAsync(t,"input"),s?.phonetic&&(t=await this.indexAsync(t,s.phonetic)),t}async indexAsync(t,{algo:e,opt:r}){this.assert("phonetic",e);const s=f.phonetic(e,r),n=r?.delimiter??" ";return Array.isArray(t)?Promise.all(t.map(t=>s.getIndexAsync(t).then(t=>t.join(n)))):s.getIndexAsync(t).then(t=>t.join(n))}async computeAsync(t,e,r,s,n,i){const a=this.resolveOptions(r);this.assert("metric",a.metric);const o=i?t:await this.prepareAsync(t,a),c=i?e:await this.prepareAsync(e,a);if(a.safeEmpty&&(Array.isArray(o)&&0===o.length||Array.isArray(c)&&0===c.length||""===o||""===c))return[];const l=f.metric(a.metric,o,c,a.opt);"prep"!==a.output&&l.setOriginal(t,e),await l.runAsync(s);const h=this.postProcess(l.getResults(),a);return this.output(h,n??a.raw)}async testAsync(t,e,r){return this.computeAsync(t,e,r,"single")}async compareAsync(t,e,r){return(await this.computeAsync(t,e,r,"single",!0)).res}async batchTestAsync(t,e,r){return this.computeAsync(t,e,r,"batch")}async batchSortedAsync(t,e,r="desc",s){const n=await this.computeAsync(t,e,s,"batch",!0);return this.output(n.sort((t,e)=>"asc"===r?t.res-e.res:e.res-t.res),s?.raw??this.options.raw)}async pairsAsync(t,e,r){return this.computeAsync(t,e,r,"pairwise")}async matchAsync(t,e,r,s){const n=await this.computeAsync(t,e,s,"batch",!0);return this.output(n.filter(t=>t.res>=r).sort((t,e)=>e.res-t.res),s?.raw??this.options.raw)}async closestAsync(t,e,r=1,s){return(await this.batchSortedAsync(t,e,"desc",s)).slice(0,r)}async furthestAsync(t,e,r=1,s){return(await this.batchSortedAsync(t,e,"asc",s)).slice(0,r)}async searchAsync(t,e,r,s){const n=this.resolveOptions({flags:r,processors:s}),i=await this.prepareAsync(t,n),a=await this.prepareAsync(e,n);return e.filter((t,e)=>a[e].includes(i))}async matrixAsync(t,e){return t=await this.prepareAsync(t,this.resolveOptions(e)),Promise.all(t.map(async e=>await this.computeAsync(e,t,void 0,"batch",!0,!0).then(t=>t.map(t=>t.res??0))))}async phoneticIndexAsync(t,e,r){const{algo:s,opt:n}=this.options.processors?.phonetic??{};return this.indexAsync(t,{algo:e??s,opt:r??n})}async structuredLookupAsync(t,e,r,s){return await this.structured(e,r).lookupAsync((t,e,r)=>this.batchTestAsync(t,e,r),t,s)}async structuredMatchAsync(t,e,r,s,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.matchAsync(t,e,s,r),t,{...n,sort:"desc"})}async structuredClosestAsync(t,e,r,s=1,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.closestAsync(t,e,s,r),t,{...n,sort:"desc"})}async structuredFurthestAsync(t,e,r,s=1,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.furthestAsync(t,e,s,r),t,{...n,sort:"asc"})}async structuredPairsAsync(t,e,r,s,n){return await this.structured(t,e).lookupPairsAsync((t,e,r)=>this.pairsAsync(t,e,r),r,s,n)}}t.CmpStr=N,t.CmpStrAsync=F,t.DeepMerge=c,t.DiffChecker=l,t.Filter=h,t.HashTable=u,t.Hasher=p,t.Metric=v,t.MetricRegistry=z,t.Normalizer=d,t.Phonetic=M,t.PhoneticMappingRegistry=E,t.PhoneticRegistry=C,t.Pool=b,t.Profiler=g,t.StructuredData=A,t.TextAnalyzer=x});
8
- //# sourceMappingURL=CmpStr.umd.min.js.map
7
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).CmpStr={})}(this,function(t){"use strict";class e extends Error{code;meta;when=(new Date).toISOString();constructor(t,e,r,s){super(e,void 0!==s?{cause:s}:void 0),this.name=this.constructor.name,this.code=t,this.meta=r,"function"==typeof Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}format(t=!1){const e=[`${this.name} [${this.code}]`,this.message];if(this.meta)for(const t in this.meta){e.push(JSON.stringify(this.meta));break}return e.join(" - ")+(t&&this.stack?`\nStack Trace:\n${this.stack}`:"")}toString(){return this.format(!1)}toJSON(t=!1){return{name:this.name,code:this.code,message:this.message,meta:this.meta,when:this.when,cause:this.cause instanceof Error?{name:this.cause.name,message:this.cause.message,stack:t&&this.cause.stack}:this.cause}}}class r extends e{constructor(t,e,r){super("E_VALIDATION",t,e,r)}}class s extends e{constructor(t,e,r){super("E_NOT_FOUND",t,e,r)}}class n extends e{constructor(t,e,r){super("E_USAGE",t,e,r)}}class a extends e{constructor(t,e,r){super("E_INTERNAL",t,e,r)}}class i{static assert(t,e,r){if(!t)throw new n(e,r)}static rethrow(t,r,s){if(t instanceof e)throw t;throw new a(r,s,t)}static format(t){return t instanceof e?t.toString():t instanceof Error?`${t.name}: ${t.message}`:String(t)}static wrap(t,r,s){try{return t()}catch(t){if(t instanceof e)throw t;throw new a(r,s,t)}}static async wrapAsync(t,r,s){try{return await t()}catch(t){if(t instanceof e)throw t;throw new a(r,s,t)}}}var o=Object.freeze({__proto__:null,CmpStrError:e,CmpStrInternalError:a,CmpStrNotFoundError:s,CmpStrUsageError:n,CmpStrValidationError:r,ErrorUtil:i});class c{static BRACKET_PATTERN=/\[(\d+)]/g;static PATH_CACHE=new Map;static walk(t,e){let r=t;for(let t=0;t<e.length;t++){const s=e[t];if(null==r||!(s in r))return{exists:!1};r=r[s]}return{exists:!0,value:r}}static parse(t){const e=c.PATH_CACHE.get(t);if(e)return e;const r=t.replace(c.BRACKET_PATTERN,".$1").split(".").map(t=>{const e=Number(t);return Number.isInteger(e)&&String(e)===t?e:t});return c.PATH_CACHE.size>2e3&&c.PATH_CACHE.clear(),c.PATH_CACHE.set(t,r),r}static has(t,e){return c.walk(t,c.parse(e)).exists}static get(t,e,r){const s=c.walk(t,c.parse(e));return s.exists?s.value:r}static set(t,e,r){if(""===e)return r;const s=c.parse(e);i.assert(void 0===t||"object"==typeof t&&null!==t,`Cannot set property <${s[0]}> of <${JSON.stringify(t)}>`,{path:s[0],target:t});const n=t??("number"==typeof s[0]?[]:Object.create(null));let a=n;for(let t=0;t<s.length-1;t++){const e=s[t];let r=a[e];i.assert(null==r||"object"==typeof r,`Cannot set property <${s[t+1]}> of <${JSON.stringify(r)}>`,{path:s.slice(0,t+2),value:r}),null==r&&(r=a[e]="number"==typeof s[t+1]?[]:Object.create(null)),a=r}return a[s[s.length-1]]=r,n}static rmv(t,e,r=!1){const s=c.parse(e),n=(t,e=0)=>{const a=s[e];if(!t||"object"!=typeof t)return!1;if(e===s.length-1)return delete t[a];if(!n(t[a],e+1))return!1;if(!r){const e=t[a];let r=!0;if("object"==typeof e)if(Array.isArray(e)){for(let t=0;t<e.length;t++)if(null!=e[t]){r=!1;break}}else r=!1;r&&delete t[a]}return!0};return n(t),t}static merge(t=Object.create(null),e=Object.create(null),r=!1){const s=t??Object.create(null);for(const t in e){const n=e[t];if((r||void 0!==n)&&"__proto__"!==t&&"constructor"!==t)if(null===n||"object"!=typeof n||Array.isArray(n))s[t]=n;else{const e=s[t];s[t]=c.merge(null===e||"object"!=typeof e||Array.isArray(e)?Object.create(null):e,n,r)}}return s}}class l{a;b;options;entries=[];grouped=[];diffRun=!1;constructor(t,e,r={}){this.a=t,this.b=e,this.options={mode:"word",caseInsensitive:!1,contextLines:1,groupedLines:!0,expandLines:!1,showChangeMagnitude:!0,maxMagnitudeSymbols:5,lineBreak:"\n",...r},this.computeDiff()}text2lines(){const t=this.a.trim().split(/\r?\n/),e=this.b.trim().split(/\r?\n/);return{linesA:t,linesB:e,maxLen:Math.max(t.length,e.length)}}tokenize(t){switch(this.options.mode){case"line":return[t];case"word":return t.split(/\s+/)}}concat(t){return t.join("word"===this.options.mode?" ":"")}computeDiff(){if(this.diffRun)return;const{linesA:t,linesB:e,maxLen:r}=this.text2lines();for(let s=0;s<r;s++)this.lineDiff(t[s]||"",e[s]||"",s);this.findGroups(),this.diffRun=!0}lineDiff(t,e,r){const{mode:s,caseInsensitive:n}=this.options,a=Math.max(t.length,e.length);let i=t,o=e;n&&(i=t.toLowerCase(),o=e.toLowerCase());let c=[],l=0,h=0;switch(s){case"line":i!==o&&(c.push({posA:0,posB:0,del:t,ins:e,size:e.length-t.length}),l=t.length,h=e.length);break;case"word":c=this.preciseDiff(t,i,e,o);for(const t of c)l+=t.del.length,h+=t.ins.length}c.length&&this.entries.push({line:r,diffs:c,delSize:l,insSize:h,baseLen:a,totalSize:h-l,magnitude:this.magnitude(l,h,a)})}preciseDiff(t,e,r,s){const n=t=>t.reduce((e,r,s)=>(e.push(s?e[s-1]+t[s-1].length+1:0),e),[]),a=this.tokenize(t),i=this.tokenize(r),o=this.tokenize(e),c=this.tokenize(s),l=o.length,h=c.length,p=n(a),u=n(i),d=[];let g=0,m=0;for(;g<l&&m<h;)if(o[g]===c[m]){let t=1;for(;g+t<l&&m+t<h&&o[g+t]===c[m+t];)t++;d.push({ai:g,bi:m,len:t}),g+=t,m+=t}else{let t=!1;for(let e=1;e<=3&&!t;e++)g+e<l&&o[g+e]===c[m]?(d.push({ai:g+e,bi:m,len:1}),g+=e+1,m+=1,t=!0):m+e<h&&o[g]===c[m+e]&&(d.push({ai:g,bi:m+e,len:1}),g+=1,m+=e+1,t=!0);t||(g++,m++)}const f=[];let y=0,w=0;for(const t of d){if(y<t.ai||w<t.bi){const e=a.slice(y,t.ai),r=i.slice(w,t.bi);f.push({posA:p[y]??0,posB:u[w]??0,del:this.concat(e),ins:this.concat(r),size:r.join("").length-e.join("").length})}y=t.ai+t.len,w=t.bi+t.len}if(y<l||w<h){const t=a.slice(y),e=i.slice(w);f.push({posA:p[y]??0,posB:u[w]??0,del:this.concat(t),ins:this.concat(e),size:e.join("").length-t.join("").length})}return f.filter(t=>t.del.length>0||t.ins.length>0)}findGroups(){const{contextLines:t}=this.options,e=(t,e,r)=>{const[s,n,a,i]=["delSize","insSize","totalSize","baseLen"].map(e=>t.reduce((t,r)=>t+r[e],0));this.grouped.push({start:e,end:r,delSize:s,insSize:n,totalSize:a,line:t[0].line,entries:t,magnitude:this.magnitude(s,n,i)})};let r=[],s=0,n=0;for(const a of this.entries){const i=Math.max(0,a.line-t),o=a.line+t;!r.length||i<=n+1?(r.length||(s=i),n=Math.max(n,o),r.push(a)):(e(r,s,n),r=[a],s=i,n=o)}r.length&&e(r,s,n)}magnitude(t,e,r){const{maxMagnitudeSymbols:s}=this.options,n=t+e;if(0===n||0===r)return"";const a=Math.min(s,Math.max(Math.round(n/r*s),1)),i=Math.round(e/n*a),o=a-i;return"+".repeat(i)+"-".repeat(o)}output(t){const{mode:e,contextLines:r,groupedLines:s,expandLines:n,showChangeMagnitude:a,lineBreak:i}=this.options,{linesA:o,linesB:c,maxLen:l}=this.text2lines(),h=Math.max(4,l.toString().length),p=(e,r)=>t?`[${r}m${e}`:e,u=e=>t?`${e}`:`-[${e}]`,d=e=>t?`${e}`:`+[${e}]`,g=(t,e,r,s)=>{s&&m(s);for(let s=t;s<=e;s++)f(s,r??s);w.push("")},m=t=>{var e;w.push(`${" ".repeat(h)} ${e=`@@ -${t.line+1},${t.delSize} +${t.line+1},${t.insSize} @@`,p(e,"36")} ${a?(t=>p(t,"33"))(t.magnitude):""}`)},f=(t,e)=>{if(o[t]||c[t]){const s=this.entries.find(e=>e.line===t),n=(t+1).toString().padStart(h," ");s&&e===t?(w.push(`${n} ${r=`- ${y(o[t],s.diffs,"del")}`,p(r,"31")}`),w.push(`${" ".repeat(h)} ${(t=>p(t,"32"))(`+ ${y(c[t],s.diffs,"ins")}`)}`)):w.push(`${n} ${(t=>p(t,"90"))(o[t])}`)}var r},y=(t,r,s)=>{if(!r.length||"line"===e)return t;let n="",a=0;for(const e of r){const r="del"===s?e.posA:e.posB,i="del"===s?e.del:e.ins;i&&(r>a&&(n+=t.slice(a,r)),n+="del"===s?u(i):d(i),a=r+i.length)}return n+t.slice(a)};let w=[""];switch(!0){case n:g(0,l);break;case s:for(const t of this.grouped)g(t.start,t.end,void 0,t);break;default:for(const t of this.entries)g(t.line-r,t.line+r,t.line,t)}return w.join(i)}getStructuredDiff=()=>this.entries;getGroupedDiff=()=>this.grouped;getASCIIDiff=()=>this.output(!1);getCLIDiff=()=>this.output(!0)}class h{static IDENTITY=t=>t;static filters=new Map;static pipeline=new Map;static getPipeline(t,e=!1){return i.wrap(()=>{if(!e){const e=h.pipeline.get(t);if(e)return e}const r=h.filters.get(t);if(!r)return h.pipeline.set(t,h.IDENTITY),h.IDENTITY;const s=[];for(const t of r.values())t.active&&s.push(t);s.sort((t,e)=>t.priority-e.priority);const n=0===s.length?h.IDENTITY:t=>{let e=t;for(let t=0;t<s.length;t++)e=s[t].fn(e);return e};return h.pipeline.set(t,n),n},`Error compiling filter pipeline for hook <${t}>`,{hook:t})}static has(t,e){return!!h.filters.get(t)?.has(e)}static add(t,e,r,s={}){return i.wrap(()=>{const{priority:n=10,active:a=!0,overrideable:i=!0}=s,o=h.filters.get(t)??new Map,c=o.get(e);return!(c&&!c.overrideable||(c&&c.fn===r&&c.priority===n&&c.active===a||(o.set(e,{id:e,fn:r,priority:n,active:a,overrideable:i}),h.filters.set(t,o),h.getPipeline(t,!0)),0))},`Error adding filter <${e}> to hook <${t}>`,{hook:t,id:e,opt:s})}static remove(t,e){const r=h.filters.get(t);return!(!r||!r.delete(e)||(h.getPipeline(t,!0),0))}static pause(t,e){const r=h.filters.get(t);if(!r)return!1;const s=r.get(e);return!(!s||!s.active||(s.active=!1,h.getPipeline(t,!0),0))}static resume(t,e){const r=h.filters.get(t);if(!r)return!1;const s=r.get(e);return!(!s||s.active||(s.active=!0,h.getPipeline(t,!0),0))}static list(t,e=!1){const r=h.filters.get(t);if(!r)return[];const s=[];for(const t of r.values())e&&!t.active||s.push(t.id);return s}static apply(t,e){return i.wrap(()=>{const r=h.getPipeline(t);if("string"==typeof e)return r(e);const s=e,n=new Array(s.length);for(let t=0;t<s.length;t++)n[t]=r(s[t]);return n},`Error applying filters for hook <${t}>`,{hook:t,input:e})}static async applyAsync(t,e){return i.wrapAsync(async()=>{const r=h.getPipeline(t);if("string"==typeof e)return Promise.resolve(r(e));const s=e,n=new Array(s.length);for(let t=0;t<s.length;t++)n[t]=Promise.resolve(r(s[t]));return Promise.all(n)},`Error applying filters for hook <${t}>`,{hook:t,input:e})}static clear(t){h.clearPipeline(),t?h.filters.delete(t):h.filters.clear()}static clearPipeline(){h.pipeline.clear()}}class p{static FNV_PRIME=16777619;static HASH_OFFSET=2166136261;static fastFNV1a(t){const e=t.length,r=-4&e;let s=this.HASH_OFFSET,n=0;for(;n<r;n+=4)s^=t.charCodeAt(n)|t.charCodeAt(n+1)<<8|t.charCodeAt(n+2)<<16|t.charCodeAt(n+3)<<24,s=Math.imul(s,this.FNV_PRIME);for(;n<e;n++)s^=t.charCodeAt(n),s=Math.imul(s,this.FNV_PRIME);return s^=s>>>16,s*=2246822507,s^=s>>>13,s*=3266489909,s^=s>>>16,s>>>0}}class u{FIFO;maxSize;static MAX_LEN=2048;table=new Map;constructor(t=!0,e=1e4){this.FIFO=t,this.maxSize=e}key(t,e,r=!1){const s=e.length,n=new Array(s);for(let t=0;t<s;t++){const r=e[t];if(r.length>u.MAX_LEN)return!1;n[t]=p.fastFNV1a(r)}r&&n.sort((t,e)=>t-e);let a=t;for(let t=0;t<n.length;t++)a+="-"+n[t];return a}has(t){return this.table.has(t)}get(t){return this.table.get(t)}set(t,e,r=!0){if(!r&&this.table.has(t))return!1;if(!this.table.has(t)&&this.table.size>=this.maxSize){if(!this.FIFO)return!1;this.table.delete(this.table.keys().next().value)}return this.table.set(t,e),!0}delete(t){return this.table.delete(t)}clear(){this.table.clear()}size(){return this.table.size}}class d{static pipeline=new Map;static cache=new u;static REGEX={whitespace:/\s+/g,doubleChars:/(.)\1+/g,specialChars:/[^\p{L}\p{N}\s]/gu,nonLetters:/[^\p{L}]/gu,nonNumbers:/\p{N}/gu};static canonicalFlags(t){return Array.from(new Set(t)).sort().join("")}static getPipeline(t){return i.wrap(()=>{const e=d.pipeline.get(t);if(e)return e;const{REGEX:r}=d,s=[];for(let e=0;e<t.length;e++)switch(t[e]){case"d":s.push(t=>t.normalize("NFD"));break;case"i":s.push(t=>t.toLowerCase());break;case"k":s.push(t=>t.replace(r.nonLetters,""));break;case"n":s.push(t=>t.replace(r.nonNumbers,""));break;case"r":s.push(t=>t.replace(r.doubleChars,"$1"));break;case"s":s.push(t=>t.replace(r.specialChars,""));break;case"t":s.push(t=>t.trim());break;case"u":s.push(t=>t.normalize("NFC"));break;case"w":s.push(t=>t.replace(r.whitespace," "));break;case"x":s.push(t=>t.normalize("NFKC"))}const n=t=>{let e=t;for(let t=0;t<s.length;t++)e=s[t](e);return e};return d.pipeline.set(t,n),n},`Failed to create normalization pipeline for flags: ${t}`,{flags:t})}static normalize(t,e,r){return i.wrap(()=>{if(!e||"string"!=typeof e||!t)return t;e=r??this.canonicalFlags(e);const s=d.getPipeline(e),n=t=>{const r=d.cache.key(e,[t]);if(r&&d.cache.has(r))return d.cache.get(r);const n=s(t);return r&&d.cache.set(r,n),n};return Array.isArray(t)?t.map(n):n(t)},`Failed to normalize input with flags: ${e}`,{input:t,flags:e})}static async normalizeAsync(t,e){return await i.wrapAsync(async()=>e&&"string"==typeof e&&t?await(Array.isArray(t)?Promise.all(t.map(t=>d.normalize(t,e))):Promise.resolve(d.normalize(t,e))):t,`Failed to asynchronously normalize input with flags: ${e}`,{input:t,flags:e})}static clear(){d.pipeline.clear(),d.cache.clear()}}class g{maxSize;buffers=[];pointer=0;constructor(t){this.maxSize=t}acquire(t,e){return i.wrap(()=>{const r=this.buffers,s=r.length;for(let n=0;n<s;n++){const a=(this.pointer+n)%s,i=r[a],o=i.size;if(o>=t&&(e||o===t))return this.pointer=(a+1)%s,i}return null},`Failed to acquire buffer of size >= ${t} from pool`,{minSize:t,allowOversize:e})}release(t){i.wrap(()=>{const e=this.buffers;e.length<this.maxSize?e.push(t):(e[this.pointer]=t,this.pointer=(this.pointer+1)%this.maxSize)},"Failed to release buffer back to pool",{item:t})}clear(){this.buffers=[],this.pointer=0}}class m{static CONFIG={int32:{type:"int32",maxSize:64,maxItemSize:2048,allowOversize:!0},"arr[]":{type:"arr[]",maxSize:4,maxItemSize:1024,allowOversize:!1},"number[]":{type:"number[]",maxSize:16,maxItemSize:1024,allowOversize:!1},"string[]":{type:"string[]",maxSize:2,maxItemSize:1024,allowOversize:!1},set:{type:"set",maxSize:8,maxItemSize:0,allowOversize:!1},map:{type:"map",maxSize:8,maxItemSize:0,allowOversize:!1}};static POOLS={int32:new g(64),"arr[]":new g(4),"number[]":new g(16),"string[]":new g(2),set:new g(8),map:new g(8)};static allocate(t,e){switch(t){case"int32":return new Int32Array(e);case"arr[]":case"string[]":return new Array(e);case"number[]":return new Float64Array(e);case"set":return new Set;case"map":return new Map}}static acquire(t,e){const r=this.CONFIG[t];if(!r)throw new n(`Unsupported pool type <${t}>`,{type:t});if(e>r.maxItemSize)return this.allocate(t,e);const s=this.POOLS[t].acquire(e,r.allowOversize);return s?"int32"===t?s.buffer.subarray(0,e):s.buffer:this.allocate(t,e)}static acquireMany(t,e){const r=new Array(e.length);for(let s=0;s<e.length;s++)r[s]=this.acquire(t,e[s]);return r}static release(t,e,r){const s=this.CONFIG[t];if(!s)throw new n(`Unsupported pool type <${t}>`,{type:t});r<=s.maxItemSize&&this.POOLS[t].release({buffer:e,size:r})}}class f{active;static ENV;static instance;nowFn;memFn;store=[];last;totalTime=0;totalMem=0;static detectEnv(){"undefined"!=typeof process&&process.versions?.node?f.ENV="nodejs":"undefined"!=typeof performance?f.ENV="browser":f.ENV="unknown"}static getInstance(t){return f.ENV||f.detectEnv(),f.instance||=new f(t)}constructor(t=!1){switch(this.active=t,f.ENV){case"nodejs":this.nowFn=()=>1e-6*Number(process.hrtime.bigint()),this.memFn=()=>process.memoryUsage().heapUsed;break;case"browser":this.nowFn=()=>performance.now(),this.memFn=()=>performance.memory?.usedJSHeapSize??0;break;default:this.nowFn=()=>Date.now(),this.memFn=()=>0}}storeRes(t){this.store.push(this.last=t),this.totalTime+=t.time,this.totalMem+=t.mem}enable(){this.active=!0}disable(){this.active=!1}clear(){this.store.length=0,this.last=void 0,this.totalTime=0,this.totalMem=0}run(t,e={}){if(!this.active)return t();const r=this.nowFn(),s=this.memFn(),n=t(),a=this.nowFn()-r,i=this.memFn()-s;return this.storeRes({time:a,mem:i,res:n,meta:e}),n}async runAsync(t,e={}){if(!this.active)return t();const r=this.nowFn(),s=this.memFn(),n=await t(),a=this.nowFn()-r,i=this.memFn()-s;return this.storeRes({time:a,mem:i,res:n,meta:e}),n}getAll(){return[...this.store]}getLast(){return this.last}getTotal(){return{time:this.totalTime,mem:this.totalMem}}services=Object.freeze({enable:this.enable.bind(this),disable:this.disable.bind(this),clear:this.clear.bind(this),report:this.getAll.bind(this),last:this.getLast.bind(this),total:this.getTotal.bind(this)})}const y=Object.create(null),w=Object.create(null);function b(t,e){i.assert(!(t in y||t in w),`Registry <${t}> already exists / overwriting is forbidden`,{registry:t});const r=Object.create(null),n=Object.freeze({add(s,n,a=!1){i.assert("string"==typeof s&&s.length>0,"Class name must be a non-empty string",{registry:t,name:s}),i.assert("function"==typeof n,"Class must be a constructor function",{registry:t,class:n}),i.assert(n.prototype instanceof e,`Class must extend <${t}>`,{registry:t,class:n}),i.assert(a||!(s in r),`Class <${s}> already exists / use <update=true> to overwrite`,{registry:t,name:s}),r[s]=n},remove(t){delete r[t]},has:t=>t in r,list:()=>Object.keys(r),get:e=>(i.assert("string"==typeof e&&e.length>0,"Class name must be a non-empty string",{registry:t,name:e}),i.assert(e in r,`Class <${e}> not registered for <${t}>`,{registry:t,name:e}),r[e])});return y[t]=n,w[t]=(e,...r)=>function(t,e,...r){const n=function(t,e){if(!(t in y))throw new s(`Registry <${t}> does not exist`,{registry:t});return"string"==typeof e?y[t].get(e):e}(t,e);return i.wrap(()=>new n(...r),`Failed to create instance of class <${n.name??e}> from registry <${t}>`,{registry:t,class:e,args:r})}(t,e,...r),n}const A=f.getInstance();class v{static cache=new u;metric;a;b;origA=[];origB=[];options;optKey;symmetric;results;static clear(){this.cache.clear()}static swap(t,e,r,s){return r>s?[e,t,s,r]:[t,e,r,s]}static clamp(t){return Math.max(0,Math.min(1,t))}constructor(t,e,r,s={},n=!1){this.metric=t,this.a=Array.isArray(e)?e:[e],this.b=Array.isArray(r)?r:[r],i.assert(this.a.length>0&&this.b.length>0,"Inputs <a> and <b> must not be empty",{a:this.a,b:this.b}),this.options=s,this.optKey=p.fastFNV1a(JSON.stringify(s,Object.keys(s).sort())).toString(),this.symmetric=n}preCompute(t,e,r,s){return t===e?{res:1}:0==r||0==s||r<2&&s<2?{res:0}:void 0}compute(t,e,r,s,n){throw new a("Method compute() must be overridden in a subclass")}runSingle(t,e){return i.wrap(()=>{let r=String(this.a[t]),s=r,n=String(this.b[e]),a=n,i=s.length,o=a.length,c=this.preCompute(s,a,i,o);return c||(c=A.run(()=>{this.symmetric&&([s,a,i,o]=v.swap(s,a,i,o));let t=v.cache.key(this.metric,[s,a],this.symmetric);return t&&(t+=this.optKey),v.cache.get(t||"")??(()=>{const e=i>o?i:o,r=this.compute(s,a,i,o,e);return t&&v.cache.set(t,r),r})()})),{metric:this.metric,a:this.origA.length>t?this.origA[t]:r,b:this.origB.length>e?this.origB[e]:n,...c}},`Failed to compute metric for inputs at indices a[${t}] and b[${e}]`,{i:t,j:e})}async runSingleAsync(t,e){return Promise.resolve(this.runSingle(t,e))}runBatch(){const t=[];for(let e=0;e<this.a.length;e++)for(let r=0;r<this.b.length;r++)t.push(this.runSingle(e,r));this.results=t}async runBatchAsync(){const t=[];for(let e=0;e<this.a.length;e++)for(let r=0;r<this.b.length;r++)t.push(this.runSingleAsync(e,r));this.results=await Promise.all(t)}runPairwise(){const t=[];for(let e=0;e<this.a.length;e++)t.push(this.runSingle(e,e));this.results=t}async runPairwiseAsync(){const t=[];for(let e=0;e<this.a.length;e++)t.push(this.runSingleAsync(e,e));this.results=await Promise.all(t)}setOriginal(t,e){return t&&(this.origA=Array.isArray(t)?t:[t]),e&&(this.origB=Array.isArray(e)?e:[e]),this}isBatch(){return this.a.length>1||this.b.length>1}isSingle(){return!this.isBatch()}isPairwise(t=!1){return!(!this.isBatch()||this.a.length!==this.b.length)||!t&&(()=>{throw new n("Mode <pairwise> requires arrays of equal length",{a:this.a,b:this.b})})()}isSymmetrical(){return this.symmetric}whichMode(t){return t??this.options.mode??"default"}clear(){this.results=void 0}run(t,e=!0){switch(e&&this.clear(),this.whichMode(t)){case"default":if(this.isSingle()){this.results=this.runSingle(0,0);break}case"batch":this.runBatch();break;case"single":this.results=this.runSingle(0,0);break;case"pairwise":this.isPairwise()&&this.runPairwise();break;default:throw new a(`Unsupported mode <${t}>`)}}async runAsync(t,e=!0){switch(e&&this.clear(),this.whichMode(t)){case"default":if(this.isSingle()){this.results=await this.runSingleAsync(0,0);break}case"batch":await this.runBatchAsync();break;case"single":this.results=await this.runSingleAsync(0,0);break;case"pairwise":this.isPairwise()&&await this.runPairwiseAsync();break;default:throw new a(`Unsupported async mode <${t}>`)}}getMetricName(){return this.metric}getResults(){return i.assert(void 0!==this.results,"run() must be called before getResults()"),this.results}}const S=b("metric",v);S.add("cosine",class extends v{constructor(t,e,r={}){super("cosine",t,e,r,!0)}_termFreq(t,e){const r=t.split(e),s=m.acquire("map",r.length);for(const t of r)s.set(t,(s.get(t)||0)+1);return s}compute(t,e){const{delimiter:r=" "}=this.options,s=this._termFreq(t,r),n=this._termFreq(e,r);try{let t=0,e=0,r=0;for(const[r,a]of s)t+=a*(n.get(r)||0),e+=a*a;for(const t of n.values())r+=t*t;return e=Math.sqrt(e),r=Math.sqrt(r),{res:e&&r?v.clamp(t/(e*r)):0,raw:{dotProduct:t,magnitudeA:e,magnitudeB:r}}}finally{m.release("map",s,s.size),m.release("map",n,n.size)}}}),S.add("damerau",class extends v{constructor(t,e,r={}){super("damerau",t,e,r,!0)}compute(t,e,r,s,n){const a=r+1,[i,o,c]=m.acquireMany("int32",[a,a,a]);try{for(let t=0;t<=r;t++)o[t]=t;for(let n=1;n<=s;n++){c[0]=n;const s=e.charCodeAt(n-1);for(let a=1;a<=r;a++){const r=t.charCodeAt(a-1),l=r===s?0:1;let h=Math.min(c[a-1]+1,o[a]+1,o[a-1]+l);a>1&&n>1&&r===e.charCodeAt(n-2)&&s===t.charCodeAt(a-2)&&(h=Math.min(h,i[a-2]+l)),c[a]=h}i.set(o),o.set(c)}const a=o[r];return{res:0===n?1:v.clamp(1-a/n),raw:{dist:a,maxLen:n}}}finally{m.release("int32",i,a),m.release("int32",o,a),m.release("int32",c,a)}}}),S.add("dice",class extends v{constructor(t,e,r={}){super("dice",t,e,r,!0)}_bigrams(t){const e=t.length-1,r=m.acquire("set",e);for(let s=0;s<e;s++)r.add(t.substring(s,s+2));return r}compute(t,e){const r=this._bigrams(t),s=this._bigrams(e),n=r.size,a=s.size;try{let t=0;for(const e of r)s.has(e)&&t++;const e=n+a;return{res:0===e?1:v.clamp(2*t/e),raw:{intersection:t,size:e}}}finally{m.release("set",r,n),m.release("set",s,a)}}}),S.add("hamming",class extends v{constructor(t,e,r={}){super("hamming",t,e,r,!0)}compute(t,e,r,s,a){if(r!==s){if(void 0===this.options.pad)throw new n(`Strings must be of equal length for Hamming Distance, a=${r} and b=${s} given, use option.pad for automatic adjustment`,{a:r,b:s});r<a&&(t=t.padEnd(a,this.options.pad)),s<a&&(e=e.padEnd(a,this.options.pad)),r=s=a}let i=0;for(let s=0;s<r;s++)t[s]!==e[s]&&i++;return{res:0===r?1:v.clamp(1-i/r),raw:{dist:i}}}}),S.add("jaccard",class extends v{constructor(t,e,r={}){super("jaccard",t,e,r,!0)}compute(t,e,r,s){const[n,a]=m.acquireMany("set",[r,s]);try{for(const e of t)n.add(e);for(const t of e)a.add(t);let r=0;for(const t of n)a.has(t)&&r++;const s=n.size+a.size-r;return{res:0===s?1:v.clamp(r/s),raw:{intersection:r,union:s}}}finally{m.release("set",n,r),m.release("set",a,s)}}}),S.add("jaroWinkler",class extends v{constructor(t,e,r={}){super("jaroWinkler",t,e,r,!0)}compute(t,e,r,s){const[n,a]=m.acquireMany("int32",[r,s]);try{for(let t=0;t<r;t++)n[t]=0;for(let t=0;t<s;t++)a[t]=0;const i=Math.max(0,Math.floor(s/2)-1);let o=0;for(let c=0;c<r;c++){const r=Math.max(0,c-i),l=Math.min(c+i+1,s);for(let s=r;s<l;s++)if(!a[s]&&t[c]===e[s]){n[c]=1,a[s]=1,o++;break}}let c=0,l=0,h=0,p=0;if(o>0){let i=0;for(let s=0;s<r;s++)if(n[s]){for(;!a[i];)i++;t[s]!==e[i]&&c++,i++}c/=2,l=(o/r+o/s+(o-c)/o)/3;for(let n=0;n<Math.min(4,r,s)&&t[n]===e[n];n++)h++;p=l+.1*h*(1-l)}return{res:v.clamp(p),raw:{matchWindow:i,matches:o,transpos:c,jaro:l,prefix:h}}}finally{m.release("int32",n,r),m.release("int32",a,s)}}}),S.add("lcs",class extends v{constructor(t,e,r={}){super("lcs",t,e,r,!0)}compute(t,e,r,s,n){const a=r+1,[i,o]=m.acquireMany("int32",[a,a]);try{for(let t=0;t<=r;t++)i[t]=0;for(let n=1;n<=s;n++){o[0]=0;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++)t.charCodeAt(e-1)===s?o[e]=i[e-1]+1:o[e]=Math.max(i[e],o[e-1]);i.set(o)}const a=i[r];return{res:0===n?1:v.clamp(a/n),raw:{lcs:a,maxLen:n}}}finally{m.release("int32",i,a),m.release("int32",o,a)}}}),S.add("levenshtein",class extends v{constructor(t,e,r={}){super("levenshtein",t,e,r,!0)}compute(t,e,r,s,n){const a=r+1,[i,o]=m.acquireMany("int32",[a,a]);try{for(let t=0;t<=r;t++)i[t]=t;for(let n=1;n<=s;n++){o[0]=n;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?0:1;o[e]=Math.min(o[e-1]+1,i[e]+1,i[e-1]+r)}i.set(o)}const a=i[r];return{res:0===n?1:v.clamp(1-a/n),raw:{dist:a,maxLen:n}}}finally{m.release("int32",i,a),m.release("int32",o,a)}}}),S.add("needlemanWunsch",class extends v{constructor(t,e,r={}){super("needlemanWunsch",t,e,r,!0)}compute(t,e,r,s,n){const{match:a=1,mismatch:i=-1,gap:o=-1}=this.options,c=r+1,[l,h]=m.acquireMany("int32",[c,c]);try{l[0]=0;for(let t=1;t<=r;t++)l[t]=l[t-1]+o;for(let n=1;n<=s;n++){h[0]=l[0]+o;const s=e.charCodeAt(n-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?a:i;h[e]=Math.max(l[e-1]+r,l[e]+o,h[e-1]+o)}l.set(h)}const c=l[r],p=n*a;return{res:0===p?0:v.clamp(c/p),raw:{score:c,denum:p}}}finally{m.release("int32",l,c),m.release("int32",h,c)}}}),S.add("qGram",class extends v{constructor(t,e,r={}){super("qGram",t,e,r,!0)}_qGrams(t,e){const r=Math.max(0,t.length-e+1),s=m.acquire("set",r);for(let n=0;n<r;n++)s.add(t.slice(n,n+e));return s}compute(t,e){const{q:r=2}=this.options,s=this._qGrams(t,r),n=this._qGrams(e,r),a=s.size,i=n.size;try{let t=0;for(const e of s)n.has(e)&&t++;const e=Math.max(a,i);return{res:0===e?1:v.clamp(t/e),raw:{intersection:t,size:e}}}finally{m.release("set",s,a),m.release("set",n,i)}}}),S.add("smithWaterman",class extends v{constructor(t,e,r={}){super("smithWaterman",t,e,r,!0)}compute(t,e,r,s){const{match:n=2,mismatch:a=-1,gap:i=-2}=this.options,o=r+1,[c,l]=m.acquireMany("int32",[o,o]);let h=0;try{for(let t=0;t<=r;t++)c[t]=0;for(let o=1;o<=s;o++){l[0]=0;const s=e.charCodeAt(o-1);for(let e=1;e<=r;e++){const r=t.charCodeAt(e-1)===s?n:a;l[e]=Math.max(0,c[e-1]+r,c[e]+i,l[e-1]+i),l[e]>h&&(h=l[e])}c.set(l)}const o=Math.min(r*n,s*n);return{res:0===o?0:v.clamp(h/o),raw:{score:h,denum:o}}}finally{m.release("int32",c,o),m.release("int32",l,o)}}});const x=f.getInstance();class O{static cache=new u;static default;algo;options;optKey;map;ignoreSet;static clear(){this.cache.clear()}constructor(t,e={}){const r=this.constructor.default??{},n=e.map??r.map;if(!n)throw new s("No mapping specified for phonetic algorithm",{algo:t});const a=C.get(t,n);if(void 0===a)throw new s(`Requested mapping <${n}> is not declared`,{algo:t,mapId:n});this.options=c.merge(c.merge(r,a.options??{}),e),this.optKey=p.fastFNV1a(JSON.stringify(this.options,Object.keys(this.options).sort())).toString(),this.algo=t,this.map=a,this.ignoreSet=new Set(a.ignore??[])}applyPattern(t){const{patterns:e=[]}=this.map;if(!e.length)return t;for(const{pattern:r,replace:s,all:n=!1}of e)t=n?t.replaceAll(r,s):t.replace(r,s);return t}applyRules(t,e,r,s){const{ruleset:n=[]}=this.map;if(!n.length)return;const a=r[e-1]||"",i=r[e-2]||"",o=r[e+1]||"",c=r[e+2]||"",l=r.join("");for(const h of n)if((!h.char||h.char===t)&&("start"!==h.position||0===e)&&("middle"!==h.position||0!==e&&e!==s-1)&&("end"!==h.position||e===s-1)&&(!h.prev||h.prev.includes(a))&&(!h.prevNot||!h.prevNot.includes(a))&&(!h.prev2||h.prev2.includes(i))&&(!h.prev2Not||!h.prev2Not.includes(i))&&(!h.next||h.next.includes(o))&&(!h.nextNot||!h.nextNot.includes(o))&&(!h.next2||h.next2.includes(c))&&(!h.next2Not||!h.next2Not.includes(c))&&(!h.leading||h.leading.includes(l.slice(0,h.leading.length)))&&(!h.trailing||h.trailing.includes(l.slice(-h.trailing.length)))&&(!h.match||h.match.every((t,s)=>r[e+s]===t)))return h.code}encode(t){const{map:e={}}=this.map;t=this.applyPattern(t);const r=this.word2Chars(t),s=r.length;let n="",a=null;for(let t=0;t<s;t++){const i=r[t];if(this.ignoreSet.has(i))continue;const o=this.mapChar(i,t,r,s,a,e);if(void 0!==o&&(n+=o,a=o,this.exitEarly(n,t)))break}return this.adjustCode(n,r)}mapChar(t,e,r,s,n,a){const{dedupe:i=!0,fallback:o}=this.options,c=this.applyRules(t,e,r,s)??a[t]??o;return i&&c===n?void 0:c}equalLen(t){const{length:e=-1,pad:r="0"}=this.options;return-1===e?t:(t+r.repeat(e)).slice(0,e)}word2Chars(t){return Array.from(t.toLowerCase())}exitEarly(t,e){const{length:r=-1}=this.options;return r>0&&t.length>=r}adjustCode(t,e){return t}loop(t){return i.wrap(()=>{const e=[];for(const r of t){let t=O.cache.key(this.algo,[r]);t&&(t+=this.optKey);const s=O.cache.get(t||"")??(()=>{const e=this.encode(r);return t&&O.cache.set(t,e),e})();s&&s.length&&e.push(this.equalLen(s))}return e},"Failed to generate phonetic index",{algo:this.algo,words:t})}async loopAsync(t){return i.wrapAsync(async()=>{const e=[];for(const r of t){const t=O.cache.key(this.algo,[r])+this.optKey,s=await Promise.resolve(O.cache.get(t||"")??(()=>{const e=this.encode(r);return t&&O.cache.set(t,e),e})());s&&s.length&&e.push(this.equalLen(s))}return e},"Failed to generate phonetic index asynchronously",{algo:this.algo,words:t})}getAlgoName(){return this.algo}getIndex(t){const{delimiter:e=" "}=this.options;return x.run(()=>this.loop(t.split(e).filter(Boolean)).filter(Boolean))}async getIndexAsync(t){const{delimiter:e=" "}=this.options;return(await x.runAsync(async()=>await this.loopAsync(t.split(e).filter(Boolean)))).filter(Boolean)}}const k=b("phonetic",O),C=(()=>{const t=Object.create(null),e=e=>t[e]||=Object.create(null);return Object.freeze({add(t,r,s,n=!1){const a=e(t);i.assert(!(!r||r in a)||n,`Entry <${r}> already exists / use <update=true> to overwrite`,{algo:t,id:r}),a[r]=s},remove(t,r){delete e(t)[r]},has:(t,r)=>r in e(t),get:(t,r)=>e(t)[r],list:t=>Object.keys(e(t))})})();class E extends O{static REGEX={uppercase:/[^A-Z]/gi};static default={map:"en2",delimiter:" ",length:-1,pad:"",dedupe:!1};constructor(t={}){super("caverphone",t)}encode(t){return t=t.replace(E.REGEX.uppercase,"").toLowerCase(),super.encode(t)}mapChar=t=>t;adjustCode=t=>t.toUpperCase()}k.add("caverphone",E),C.add("caverphone","en1",{options:{length:6,pad:"1"},map:{},patterns:[{pattern:/^(c|r|t|en)ough/,replace:"$1ou2f"},{pattern:/^gn/,replace:"2n"},{pattern:/mb$/,replace:"m2"},{pattern:/cq/g,replace:"2q"},{pattern:/c(e|i|y)/g,replace:"s$1"},{pattern:/tch/g,replace:"2ch"},{pattern:/[cqx]/g,replace:"k"},{pattern:/v/g,replace:"f"},{pattern:/dg/g,replace:"2g"},{pattern:/ti(a|o)/g,replace:"si$1"},{pattern:/d/g,replace:"t"},{pattern:/ph/g,replace:"fh"},{pattern:/b/g,replace:"p"},{pattern:/sh/g,replace:"s2"},{pattern:/z/g,replace:"s"},{pattern:/^[aeiou]/,replace:"A"},{pattern:/[aeiou]/g,replace:"3"},{pattern:/3gh3/g,replace:"3kh3"},{pattern:/gh/g,replace:"22"},{pattern:/g/g,replace:"k"},{pattern:/s+/g,replace:"S"},{pattern:/t+/g,replace:"T"},{pattern:/p+/g,replace:"P"},{pattern:/k+/g,replace:"K"},{pattern:/f+/g,replace:"F"},{pattern:/m+/g,replace:"M"},{pattern:/n+/g,replace:"N"},{pattern:/j/g,replace:"y"},{pattern:/l3/g,replace:"L3"},{pattern:/r3/g,replace:"R3"},{pattern:/w3/g,replace:"W3"},{pattern:/y3/g,replace:"Y3"},{pattern:/ly/g,replace:"Ly"},{pattern:/ry/g,replace:"Ry"},{pattern:/wy/g,replace:"Wy"},{pattern:/wh3/g,replace:"Wh3"},{pattern:/why/g,replace:"Why"},{pattern:/^h/,replace:"A"},{pattern:/[hlrwy23]/g,replace:""}]}),C.add("caverphone","en2",{options:{length:10,pad:"1"},map:{},patterns:[{pattern:/e$/,replace:""},{pattern:/^(c|r|t|en|tr)ough/,replace:"$1ou2f"},{pattern:/^gn/,replace:"2n"},{pattern:/mb$/,replace:"m2"},{pattern:/cq/g,replace:"2q"},{pattern:/c(e|i|y)/g,replace:"s$1"},{pattern:/tch/g,replace:"2ch"},{pattern:/[cqx]/g,replace:"k"},{pattern:/v/g,replace:"f"},{pattern:/dg/g,replace:"2g"},{pattern:/ti(a|o)/g,replace:"si$1"},{pattern:/d/g,replace:"t"},{pattern:/ph/g,replace:"fh"},{pattern:/b/g,replace:"p"},{pattern:/sh/g,replace:"s2"},{pattern:/z/g,replace:"s"},{pattern:/^[aeiou]/,replace:"A"},{pattern:/[aeiou]/g,replace:"3"},{pattern:/j/g,replace:"y"},{pattern:/^y3/,replace:"Y3"},{pattern:/^y/,replace:"A"},{pattern:/y/g,replace:"3"},{pattern:/3gh3/g,replace:"3kh3"},{pattern:/gh/g,replace:"22"},{pattern:/g/g,replace:"k"},{pattern:/s+/g,replace:"S"},{pattern:/t+/g,replace:"T"},{pattern:/p+/g,replace:"P"},{pattern:/k+/g,replace:"K"},{pattern:/f+/g,replace:"F"},{pattern:/m+/g,replace:"M"},{pattern:/n+/g,replace:"N"},{pattern:/l3/g,replace:"L3"},{pattern:/r3/g,replace:"R3"},{pattern:/w3/g,replace:"W3"},{pattern:/wh3/g,replace:"Wh3"},{pattern:/[lrw]$/,replace:"3"},{pattern:/^h/,replace:"A"},{pattern:/3$/,replace:"A"},{pattern:/[hlrw23]/g,replace:""}]}),k.add("cologne",class extends O{static default={map:"default",delimiter:" ",length:-1,dedupe:!0};constructor(t={}){super("cologne",t)}adjustCode(t){return t.slice(0,1)+t.slice(1).replaceAll("0","")}}),C.add("cologne","default",{map:{a:"0","ä":"0",e:"0",i:"0",j:"0",o:"0","ö":"0",u:"0","ü":"0",y:"0",b:"1",p:"1",d:"2",t:"2",f:"3",v:"3",w:"3",g:"4",k:"4",q:"4",l:"5",m:"6",n:"6",r:"7",c:"8",s:"8","ß":"8",z:"8",x:"48"},ignore:["h"],ruleset:[{char:"p",next:["h"],code:"3"},{char:"c",position:"start",next:["a","h","k","l","o","q","r","u","x"],code:"4"},{char:"c",next:["a","h","k","o","q","u","x"],prevNot:["s","z"],code:"4"},{char:"d",next:["c","s","z"],code:"8"},{char:"t",next:["c","s","z"],code:"8"},{char:"x",prev:["c","k","q"],code:"8"}]});class z extends O{static REGEX={adjacent:/([A-BD-Z])\1+/gi,vowel:/[AEIOU]/g};static default={map:"en90",delimiter:" ",length:-1,pad:"",dedupe:!1};constructor(t={}){super("metaphone",t)}encode(t){return t=t.replace(z.REGEX.adjacent,(t,e)=>"C"===e?t:e),super.encode(t)}adjustCode(t){return t.slice(0,1)+t.slice(1).replace(z.REGEX.vowel,"")}}k.add("metaphone",z),C.add("metaphone","en90",{map:{a:"A",b:"B",c:"K",d:"T",e:"E",f:"F",g:"K",h:"H",i:"I",j:"J",k:"K",l:"L",m:"M",n:"N",o:"O",p:"P",q:"K",r:"R",s:"S",t:"T",u:"U",v:"F",w:"W",x:"KS",y:"Y",z:"S"},ruleset:[{char:"a",position:"start",next:["e"],code:""},{char:"g",position:"start",next:["n"],code:""},{char:"k",position:"start",next:["n"],code:""},{char:"p",position:"start",next:["n"],code:""},{char:"w",position:"start",next:["r"],code:""},{char:"b",position:"end",prev:["m"],code:""},{char:"c",next:["h"],prevNot:["s"],code:"X"},{char:"c",next:["i"],next2:["a"],code:"X"},{char:"c",next:["e","i","y"],code:"S"},{char:"d",next:["g"],next2:["e","i","y"],code:"J"},{char:"g",next:["h"],next2Not:["","a","e","i","o","u"],code:""},{char:"g",trailing:"n",code:""},{char:"g",trailing:"ned",code:""},{char:"g",next:["e","i","y"],prevNot:["g"],code:"J"},{char:"h",prev:["a","e","i","o","u"],nextNot:["a","e","i","o","u"],code:""},{char:"h",prev:["c","g","p","s","t"],code:""},{char:"k",prev:["c"],code:""},{char:"p",next:["h"],code:"F"},{char:"s",next:["h"],code:"X"},{char:"s",next:["i"],next2:["a","o"],code:"X"},{char:"t",next:["i"],next2:["a","o"],code:"X"},{char:"t",next:["h"],code:"0"},{char:"t",next:["c"],next2:["h"],code:""},{char:"w",nextNot:["a","e","i","o","u"],code:""},{char:"h",leading:"w",code:""},{char:"x",position:"start",code:"S"},{char:"y",nextNot:["a","e","i","o","u"],code:""}]}),k.add("soundex",class extends O{static default={map:"en",delimiter:" ",length:4,pad:"0",dedupe:!0};constructor(t={}){super("soundex",t)}adjustCode(t,e){return e[0].toUpperCase()+t.slice(1).replaceAll("0","")}}),C.add("soundex","en",{map:{a:"0",e:"0",h:"0",i:"0",o:"0",u:"0",w:"0",y:"0",b:"1",f:"1",p:"1",v:"1",c:"2",g:"2",j:"2",k:"2",q:"2",s:"2",x:"2",z:"2",d:"3",t:"3",l:"4",m:"5",n:"5",r:"6"}}),C.add("soundex","de",{map:{a:"0","ä":"0",e:"0",h:"0",i:"0",j:"0",o:"0","ö":"0",u:"0","ü":"0",y:"0",b:"1",f:"1",p:"1",v:"1",w:"1",c:"2",g:"2",k:"2",q:"2",s:"2","ß":"2",x:"2",z:"2",d:"3",t:"3",l:"4",m:"5",n:"5",r:"6"},ruleset:[{char:"c",next:["h"],code:"7"}]});class M{static ALLOWED_FLAGS=new Set(["d","u","x","w","t","r","s","k","n","i"]);static ALLOWED_OUTPUT=new Set(["orig","prep"]);static ALLOWED_MODES=new Set(["default","batch","single","pairwise"]);static ALLOWED_SORT=new Set(["asc","desc"]);static PROCESSORS={phonetic:t=>{t&&(M.validatePhoneticName(t.algo),M.validatePhoneticOptions(t.opt))}};static METRIC_OPT_MAP={mode:t=>M.validateMode(t),delimiter:t=>M.validateString(t,"opt.delimiter"),pad:t=>M.validateString(t,"opt.pad"),q:t=>M.validateNumber(t,"opt.q"),match:t=>M.validateNumber(t,"opt.match"),mismatch:t=>M.validateNumber(t,"opt.mismatch"),gap:t=>M.validateNumber(t,"opt.gap")};static PHONETIC_OPT_MAP={map:t=>M.validateString(t,"processors.phonetic.opt.map"),delimiter:t=>M.validateString(t,"processors.phonetic.opt.delimiter"),length:t=>M.validateNumber(t,"processors.phonetic.opt.length"),pad:t=>M.validateString(t,"processors.phonetic.opt.pad"),dedupe:t=>M.validateBoolean(t,"processors.phonetic.opt.dedupe"),fallback:t=>M.validateString(t,"processors.phonetic.opt.fallback")};static CMPSTR_OPT_MAP={raw:t=>M.validateBoolean(t,"raw"),removeZero:t=>M.validateBoolean(t,"removeZero"),safeEmpty:t=>M.validateBoolean(t,"safeEmpty"),flags:t=>M.validateFlags(t),metric:t=>M.validateMetricName(t),output:t=>M.validateOutput(t),opt:t=>M.validateMetricOptions(t),processors:t=>M.validateProcessors(t),sort:t=>M.validateSort(t,"sort"),objectsOnly:t=>M.validateBoolean(t,"objectsOnly")};static set2string(t){return Array.from(t).join(" | ")}static validateType(t,e,s){if(void 0!==t&&(typeof t!==s||"number"===s&&Number.isNaN(t)))throw new r(`Invalid option <${e}>: expected ${s}`,{name:e,value:t})}static validateEnum(t,e,s){if(void 0!==t&&("string"!=typeof t||!s.has(t)))throw new r(`Invalid option <${e}>: expected ${M.set2string(s)}`,{name:e,value:t})}static validateMap(t,e){if(t)for(const s in t){const n=e[s];if(!n)throw new r(`Invalid option <${s}>`,{option:s,value:e[s]});n(t[s])}}static validateRegistryName(t,e,s,n,a){if(void 0!==t){if("string"!=typeof t||0===t.length)throw new r(`Invalid option <${e}>: expected non-empty string`,{name:e,value:t});if(!n(t))throw new r(`${s} <${t}> is not registered`,{name:e,value:t,available:a()})}}static validateBoolean(t,e){M.validateType(t,e,"boolean")}static validateNumber(t,e){M.validateType(t,e,"number")}static validateString(t,e){M.validateType(t,e,"string")}static validateFlags(t){if(void 0!==t){if("string"!=typeof t)throw new r("Invalid option <flags>: expected string",{flags:t});for(let e=0;e<t.length;e++){const s=t[e];if(!M.ALLOWED_FLAGS.has(s))throw new r(`Invalid normalization flag <${s}> in <flags>: expected ${M.set2string(M.ALLOWED_FLAGS)}`,{flags:t,invalid:s})}}}static validateOutput(t){M.validateEnum(t,"output",M.ALLOWED_OUTPUT)}static validateMode(t){M.validateEnum(t,"mode",M.ALLOWED_MODES)}static validateSort(t,e){void 0!==t&&"boolean"!=typeof t&&M.validateEnum(t,e,M.ALLOWED_SORT)}static validateMetricName(t){M.validateRegistryName(t,"metric","Comparison metric",S.has,S.list)}static validatePhoneticName(t){M.validateRegistryName(t,"phonetic","Phonetic algorithm",k.has,k.list)}static validateMetricOptions(t){M.validateMap(t,M.METRIC_OPT_MAP)}static validatePhoneticOptions(t){M.validateMap(t,M.PHONETIC_OPT_MAP)}static validateProcessors(t){if(t)for(const e in t){const s=M.PROCESSORS[e];if(!s)throw new r(`Invalid processor type <${e}> in <processors>: expected ${Object.keys(M.PROCESSORS).join(" | ")}`,{processors:t,invalid:e});s(t[e])}}static validateOptions(t){M.validateMap(t,M.CMPSTR_OPT_MAP)}}class P{data;key;static SORT_ASC=(t,e)=>t.res-e.res;static SORT_DESC=(t,e)=>e.res-t.res;static create(t,e){return new P(t,e)}constructor(t,e){this.data=t,this.key=e}extractFrom(t,e){const r=t.length,s=new Array(r);for(let n=0;n<r;n++){const r=t[n][e];s[n]=null!=r?String(r):""}return s}extract(){return this.extractFrom(this.data,this.key)}isMetricResult(t){return"object"==typeof t&&null!==t&&"a"in t&&"b"in t&&"res"in t}isCmpStrResult(t){return"object"==typeof t&&null!==t&&"source"in t&&"target"in t&&"match"in t}normalizeResults(t){if(!Array.isArray(t)||0===t.length)return[];const e=t[0];let s=new Array(t.length);if(this.isMetricResult(e)){const e=t;for(let t=0;t<e.length;t++)s[t]={...e[t],__idx:t}}else{if(!this.isCmpStrResult(e))throw new r("Unsupported result format for StructuredData normalization.");{const e=t;for(let t=0;t<e.length;t++){const r=e[t];s[t]={metric:"unknown",a:r.source,b:r.target,res:r.match,raw:r.raw,__idx:t}}}}return s}rebuild(t,e,r,s,n){const a=r.length,i=t.length,o=m.acquire("map",a),c=m.acquire("map",i),l=new Array(i);o.clear(),c.clear();try{for(let t=0;t<a;t++){const e=r[t];let s=o.get(e);s||(s=[],o.set(e,s)),s.push(t)}let h=0;for(let a=0;a<i;a++){const i=t[a];if(s&&0===i.res)continue;const p=i.b||"",u=o.get(p);let d;if(u&&u.length>0){const t=c.get(p)??0;c.set(p,t+1),d=u[t%u.length]}else d=i.__idx??a;if(d<0||d>=e.length)continue;const g=e[d],m=r[d]||p;l[h++]=n?g:{obj:g,key:this.key,result:{source:i.a,target:m,match:i.res},...i.raw?{raw:i.raw}:null}}return l.length=h,l}finally{m.release("map",o,a),m.release("map",c,i)}}sort(t,e){return!e||t.length<=1?t:t.sort("asc"===e?P.SORT_ASC:P.SORT_DESC)}finalizeLookup(t,e,r){return this.rebuild(this.sort(this.normalizeResults(t),r?.sort),this.data,e,r?.removeZero,r?.objectsOnly)}performLookup(t,e,r){return i.wrap(()=>this.finalizeLookup(t(),e,r),"StructuredData lookup failed",{key:this.key})}async performLookupAsync(t,e,r){return await i.wrapAsync(async()=>this.finalizeLookup(await t(),e,r),"StructuredData async lookup failed",{key:this.key})}lookup(t,e,r){const s=this.extract();try{return this.performLookup(()=>t(e,s,r),s,r)}finally{m.release("string[]",s,s.length)}}async lookupAsync(t,e,r){const s=this.extract();try{return await this.performLookupAsync(()=>t(e,s,r),s,r)}finally{m.release("string[]",s,s.length)}}lookupPairs(t,e,r,s){const n=this.extract(),a=this.extractFrom(e,r);try{return this.performLookup(()=>t(n,a,s),n,s)}finally{m.release("string[]",n,n.length),m.release("string[]",a,a.length)}}async lookupPairsAsync(t,e,r,s){const n=this.extract(),a=this.extractFrom(e,r);try{return await this.performLookupAsync(()=>t(n,a,s),n,s)}finally{m.release("string[]",n,n.length),m.release("string[]",a,a.length)}}}class N{static REGEX={number:/\d/,sentence:/(?<=[.!?])\s+/,word:/\p{L}+/gu,nonWord:/[^\p{L}]/gu,vowelGroup:/[aeiouy]+/g,letter:/\p{L}/gu,ucLetter:/\p{Lu}/gu};text;words=[];sentences=[];charFrequency=new Map;wordHistogram=new Map;syllableCache=new Map;syllableStats;constructor(t){this.text=t.trim(),this.tokenize(),this.computeFrequencies()}tokenize(){let t;const e=this.text.toLowerCase();for(;null!==(t=N.REGEX.word.exec(e));)this.words.push(t[0]);this.sentences=this.text.split(N.REGEX.sentence).filter(Boolean)}computeFrequencies(){for(const t of this.text)this.charFrequency.set(t,(this.charFrequency.get(t)??0)+1);for(const t of this.words)this.wordHistogram.set(t,(this.wordHistogram.get(t)??0)+1)}estimateSyllables(t){const e=t.normalize("NFC").toLowerCase().replace(N.REGEX.nonWord,"");if(this.syllableCache.has(e))return this.syllableCache.get(e);const r=e.match(N.REGEX.vowelGroup),s=r?r.length:1;return this.syllableCache.set(e,s),s}computeSyllableStats(){return this.syllableStats||=(()=>{const t=this.words.map(t=>this.estimateSyllables(t)).sort((t,e)=>t-e),e=t.reduce((t,e)=>t+e,0),r=t.filter(t=>1===t).length,s=t.length?t.length%2==0?(t[t.length/2-1]+t[t.length/2])/2:t[Math.floor(t.length/2)]:0;return{total:e,mono:r,perWord:t,avg:t.length?e/t.length:0,median:s}})()}getLength=()=>this.text.length;getWordCount=()=>this.words.length;getSentenceCount=()=>this.sentences.length;getAvgWordLength(){return this.words.length?this.words.join("").length/this.words.length:0}getAvgSentenceLength(){return this.sentences.length?this.words.length/this.sentences.length:0}getWordHistogram(){return Object.fromEntries(this.wordHistogram)}getMostCommonWords(t=5){return[...this.wordHistogram.entries()].sort((t,e)=>e[1]-t[1]).slice(0,t).map(t=>t[0])}getHapaxLegomena(){return[...this.wordHistogram.entries()].filter(([,t])=>1===t).map(t=>t[0])}hasNumbers=()=>N.REGEX.number.test(this.text);getUpperCaseRatio(){const t=this.text.match(N.REGEX.letter)||[],e=this.text.match(N.REGEX.ucLetter)?.length||0;return t.length?e/t.length:0}getCharFrequency(){return Object.fromEntries(this.charFrequency)}getUnicodeCodepoints(){const t={};for(const[e,r]of this.charFrequency){const s=e.charCodeAt(0).toString(16).padStart(4,"0").toUpperCase();t[s]=(t[s]||0)+r}return t}getLongWordRatio(t=7){let e=0;for(const r of this.words)r.length>=t&&e++;return this.words.length?e/this.words.length:0}getShortWordRatio(t=3){let e=0;for(const r of this.words)r.length<=t&&e++;return this.words.length?e/this.words.length:0}getSyllablesCount(){return this.computeSyllableStats().total}getMonosyllabicWordCount(){return this.computeSyllableStats().mono}getMinSyllablesWordCount(t){return this.computeSyllableStats().perWord.filter(e=>e>=t).length}getMaxSyllablesWordCount(t){return this.computeSyllableStats().perWord.filter(e=>e<=t).length}getAvgSyllablesPerWord(){return this.computeSyllableStats().avg}getMedianSyllablesPerWord(){return this.computeSyllableStats().median}getHonoresR(){try{return 100*Math.log(this.words.length)/(1-this.getHapaxLegomena().length/(this.wordHistogram.size??1))}catch{return 0}}getReadingTime(t=200){return this.words.length/(t??1)}getReadabilityScore(t="flesch"){const e=this.words.length||1,r=e/(this.sentences.length||1),s=(this.getSyllablesCount()||1)/e;switch(t){case"flesch":return 206.835-1.015*r-84.6*s;case"fleschde":return 180-r-58.5*s;case"kincaid":return.39*r+11.8*s-15.59}}getLIXScore(){const t=this.words.length||1;return t/(this.sentences.length||1)+this.getLongWordRatio()*t/t*100}getWSTFScore(){const t=this.words.length||1,e=this.getMinSyllablesWordCount(3)/t*100,r=this.getAvgSentenceLength(),s=100*this.getLongWordRatio();return[.1935*e+.1672*r+.1297*s-this.getMonosyllabicWordCount()/t*100*.0327-.875,.2007*e+.1682*r+.1373*s-2.779,.2963*e+.1905*r-1.1144,.2744*e+.2656*r-1.693]}}const L=f.getInstance();class F{static filter={has:h.has,add:h.add,remove:h.remove,pause:h.pause,resume:h.resume,list:h.list,clear:h.clear};static metric={add:S.add,remove:S.remove,has:S.has,list:S.list};static phonetic={add:k.add,remove:k.remove,has:k.has,list:k.list,map:{add:C.add,remove:C.remove,has:C.has,list:C.list}};static profiler=L.services;static clearCache={normalizer:d.clear,filter:h.clearPipeline,metric:v.clear,phonetic:O.clear};static analyze=t=>new N(t);static diff=(t,e,r)=>new l(t,e,r);static create(t){return new F(t)}options=Object.create(null);constructor(t){t&&("string"==typeof t?this.setSerializedOptions(t):this.setOptions(t))}assert(t,e){switch(t){default:throw new a(`Cmpstr condition <${t}> unknown`);case"metric":M.validateMetricName(e);break;case"phonetic":M.validatePhoneticName(e)}}assertMany(...t){for(const[e,r]of t)this.assert(e,r)}resolveOptions(t){const e=c.merge({...this.options??Object.create(null)},t);return M.validateOptions(e),e}normalize(t,e){return d.normalize(t,e??this.options.flags??"")}filter(t,e){return h.apply(e,t)}prepare(t,e){const{flags:r,processors:s}=e??this.options;return r?.length&&(t=this.normalize(t,r)),t=this.filter(t,"input"),s?.phonetic&&(t=this.index(t,s.phonetic)),t}postProcess(t,e){return Array.isArray(t)&&e?.removeZero&&(t=t.filter(t=>t.res>0)),t}index(t,{algo:e,opt:r}){this.assert("phonetic",e);const s=w.phonetic(e,r),n=r?.delimiter??" ";return Array.isArray(t)?t.map(t=>s.getIndex(t).join(n)):s.getIndex(t).join(n)}structured(t,e){return P.create(t,e)}compute(t,e,r,s,n,a){const o=this.resolveOptions(r);return this.assert("metric",o.metric),i.wrap(()=>{const r=a?t:this.prepare(t,o),i=a?e:this.prepare(e,o);if(o.safeEmpty&&(Array.isArray(r)&&0===r.length||Array.isArray(i)&&0===i.length||""===r||""===i))return[];const c=w.metric(o.metric,r,i,o.opt);"prep"!==o.output&&c.setOriginal(t,e),c.run(s);const l=this.postProcess(c.getResults(),o);return this.output(l,n??o.raw)},`Failed to compute metric <${o.metric}> for the given inputs`,{a:t,b:e,options:r})}output(t,e){return i.wrap(()=>e??this.options.raw?t:Array.isArray(t)?t.map(t=>({source:t.a,target:t.b,match:t.res})):{source:t.a,target:t.b,match:t.res},"Failed to resolve output format for the metric result",{result:t,raw:e})}clone(){const t=Object.assign(Object.create(Object.getPrototypeOf(this)),this);return t.options=c.merge(Object.create(null),this.options),t}reset(){return this.options=Object.create(null),this}setOptions(t){return M.validateOptions(t),this.options=t,this}mergeOptions(t){return c.merge(this.options,t),M.validateOptions(this.options),this}setSerializedOptions(t){try{const e=JSON.parse(t);return M.validateOptions(e),this.options=e,this}catch(e){if(e instanceof SyntaxError)throw new r("Failed to parse serialized options, invalid JSON string",{opt:t,error:e instanceof Error?e.message:String(e)});throw e}}setOption(t,e){return c.set(this.options,t,e),M.validateOptions(this.options),this}rmvOption(t){return c.rmv(this.options,t),this}setRaw(t){return this.setOption("raw",t)}setMetric(t){return this.setOption("metric",t)}setFlags(t){return this.setOption("flags",t)}rmvFlags(){return this.rmvOption("flags")}setProcessors(t){return this.setOption("processors",t)}rmvProcessors(){return this.rmvOption("processors")}getOptions(){return this.options}getSerializedOptions(){return JSON.stringify(this.options)}getOption(t){return c.get(this.options,t)}test(t,e,r){return this.compute(t,e,r,"single")}compare(t,e,r){return this.compute(t,e,r,"single",!0).res}batchTest(t,e,r){return this.compute(t,e,r,"batch")}batchSorted(t,e,r="desc",s){return this.output(this.compute(t,e,s,"batch",!0).sort((t,e)=>"asc"===r?t.res-e.res:e.res-t.res),s?.raw??this.options.raw)}pairs(t,e,r){return this.compute(t,e,r,"pairwise")}match(t,e,r,s){return this.output(this.compute(t,e,s,"batch",!0).filter(t=>t.res>=r).sort((t,e)=>e.res-t.res),s?.raw??this.options.raw)}closest(t,e,r=1,s){return this.batchSorted(t,e,"desc",s).slice(0,r)}furthest(t,e,r=1,s){return this.batchSorted(t,e,"asc",s).slice(0,r)}search(t,e,r,s){const n=this.resolveOptions({flags:r,processors:s}),a=this.prepare(t,n),i=this.prepare(e,n),o=[];for(let t=0,r=i.length;t<r;t++)i[t].includes(a)&&o.push(e[t]);return o}matrix(t,e){const r=this.resolveOptions(e),s=this.prepare(t,r),n=s.length,a=Array.from({length:n},()=>new Array(n).fill(0));for(let t=0;t<n;t++)for(let e=t;e<n;e++)if(t===e)a[t][e]=1;else{const n=this.compute(s[t],s[e],r,"single",!0,!0).res;a[t][e]=n,a[e][t]=n}return a}phoneticIndex(t,e,r){const{algo:s,opt:n}=this.options.processors?.phonetic??{};return this.index(t,{algo:e??s,opt:r??n})}structuredLookup(t,e,r,s){return this.structured(e,r).lookup((t,e,r)=>this.batchTest(t,e,r),t,s)}structuredMatch(t,e,r,s,n){return this.structured(e,r).lookup((t,e,r)=>this.match(t,e,s,r),t,{...n,sort:"desc"})}structuredClosest(t,e,r,s=1,n){return this.structured(e,r).lookup((t,e,r)=>this.closest(t,e,s,r),t,{...n,sort:"desc"})}structuredFurthest(t,e,r,s=1,n){return this.structured(e,r).lookup((t,e,r)=>this.furthest(t,e,s,r),t,{...n,sort:"asc"})}structuredPairs(t,e,r,s,n){return this.structured(t,e).lookupPairs((t,e,r)=>this.pairs(t,e,r),r,s,n)}}class $ extends F{static create(t){return new $(t)}constructor(t){super(t)}async normalizeAsync(t,e){return d.normalizeAsync(t,e??this.options.flags??"")}async filterAsync(t,e){return h.applyAsync(e,t)}async prepareAsync(t,e){const{flags:r,processors:s}=e??this.options;return r?.length&&(t=await this.normalizeAsync(t,r)),t=await this.filterAsync(t,"input"),s?.phonetic&&(t=await this.indexAsync(t,s.phonetic)),t}async indexAsync(t,{algo:e,opt:r}){this.assert("phonetic",e);const s=w.phonetic(e,r),n=r?.delimiter??" ";return Array.isArray(t)?Promise.all(t.map(t=>s.getIndexAsync(t).then(t=>t.join(n)))):s.getIndexAsync(t).then(t=>t.join(n))}async computeAsync(t,e,r,s,n,a){const o=this.resolveOptions(r);return this.assert("metric",o.metric),i.wrapAsync(async()=>{const r=a?t:await this.prepareAsync(t,o),i=a?e:await this.prepareAsync(e,o);if(o.safeEmpty&&(Array.isArray(r)&&0===r.length||Array.isArray(i)&&0===i.length||""===r||""===i))return[];const c=w.metric(o.metric,r,i,o.opt);"prep"!==o.output&&c.setOriginal(t,e),await c.runAsync(s);const l=this.postProcess(c.getResults(),o);return this.output(l,n??o.raw)},`Failed to compute metric <${r?.metric??this.options.metric}> for the given inputs`,{a:t,b:e,opt:r})}async testAsync(t,e,r){return this.computeAsync(t,e,r,"single")}async compareAsync(t,e,r){return(await this.computeAsync(t,e,r,"single",!0)).res}async batchTestAsync(t,e,r){return this.computeAsync(t,e,r,"batch")}async batchSortedAsync(t,e,r="desc",s){const n=await this.computeAsync(t,e,s,"batch",!0);return this.output(n.sort((t,e)=>"asc"===r?t.res-e.res:e.res-t.res),s?.raw??this.options.raw)}async pairsAsync(t,e,r){return this.computeAsync(t,e,r,"pairwise")}async matchAsync(t,e,r,s){const n=await this.computeAsync(t,e,s,"batch",!0);return this.output(n.filter(t=>t.res>=r).sort((t,e)=>e.res-t.res),s?.raw??this.options.raw)}async closestAsync(t,e,r=1,s){return(await this.batchSortedAsync(t,e,"desc",s)).slice(0,r)}async furthestAsync(t,e,r=1,s){return(await this.batchSortedAsync(t,e,"asc",s)).slice(0,r)}async searchAsync(t,e,r,s){const n=this.resolveOptions({flags:r,processors:s}),a=await this.prepareAsync(t,n),i=await this.prepareAsync(e,n),o=[];for(let t=0;t<i.length;t++)i[t].includes(a)&&o.push(e[t]);return o}async matrixAsync(t,e){const r=this.resolveOptions(e),s=await this.prepareAsync(t,r),n=s.length,a=Array.from({length:n},()=>new Array(n).fill(0));for(let t=0;t<n;t++)await Promise.all(Array.from({length:n-t},(e,r)=>t+r).map(async e=>{if(t===e)a[t][e]=1;else{const n=(await this.computeAsync(s[t],s[e],r,"single",!0,!0)).res;a[t][e]=n,a[e][t]=n}}));return a}async phoneticIndexAsync(t,e,r){const{algo:s,opt:n}=this.options.processors?.phonetic??{};return this.indexAsync(t,{algo:e??s,opt:r??n})}async structuredLookupAsync(t,e,r,s){return await this.structured(e,r).lookupAsync((t,e,r)=>this.batchTestAsync(t,e,r),t,s)}async structuredMatchAsync(t,e,r,s,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.matchAsync(t,e,s,r),t,{...n,sort:"desc"})}async structuredClosestAsync(t,e,r,s=1,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.closestAsync(t,e,s,r),t,{...n,sort:"desc"})}async structuredFurthestAsync(t,e,r,s=1,n){return await this.structured(e,r).lookupAsync((t,e,r)=>this.furthestAsync(t,e,s,r),t,{...n,sort:"asc"})}async structuredPairsAsync(t,e,r,s,n){return await this.structured(t,e).lookupPairsAsync((t,e,r)=>this.pairsAsync(t,e,r),r,s,n)}}t.CmpStr=F,t.CmpStrAsync=$,t.CmpStrError=o,t.DeepMerge=c,t.DiffChecker=l,t.Filter=h,t.HashTable=u,t.Hasher=p,t.Metric=v,t.MetricRegistry=S,t.Normalizer=d,t.OptionsValidator=M,t.Phonetic=O,t.PhoneticMappingRegistry=C,t.PhoneticRegistry=k,t.Pool=m,t.Profiler=f,t.StructuredData=P,t.TextAnalyzer=N});
@@ -1,10 +1,12 @@
1
- // CmpStr v3.2.1 build-3439ccb-260130 by Paul Köhler @komed3 / MIT License
1
+ // CmpStr v3.3.0 build-3699f85-260318 by Paul Köhler @komed3 / MIT License
2
2
  'use strict';
3
3
 
4
4
  var DeepMerge = require('./utils/DeepMerge.cjs');
5
5
  var DiffChecker = require('./utils/DiffChecker.cjs');
6
+ var Errors = require('./utils/Errors.cjs');
6
7
  var Filter = require('./utils/Filter.cjs');
7
8
  var Normalizer = require('./utils/Normalizer.cjs');
9
+ var OptionsValidator = require('./utils/OptionsValidator.cjs');
8
10
  var Profiler = require('./utils/Profiler.cjs');
9
11
  var Registry = require('./utils/Registry.cjs');
10
12
  var StructuredData = require('./utils/StructuredData.cjs');
@@ -77,29 +79,28 @@ class CmpStr {
77
79
  }
78
80
  assert(cond, test) {
79
81
  switch (cond) {
82
+ default:
83
+ throw new Errors.CmpStrInternalError(
84
+ `Cmpstr condition <${cond}> unknown`
85
+ );
80
86
  case 'metric':
81
- if (!CmpStr.metric.has(test))
82
- throw new Error(
83
- `CmpStr <metric> must be set, call .setMetric(), ` +
84
- `use CmpStr.metric.list() for available metrics`
85
- );
87
+ OptionsValidator.OptionsValidator.validateMetricName(test);
86
88
  break;
87
89
  case 'phonetic':
88
- if (!CmpStr.phonetic.has(test))
89
- throw new Error(
90
- `CmpStr <phonetic> must be set, call .setPhonetic(), ` +
91
- `use CmpStr.phonetic.list() for available phonetic algorithms`
92
- );
90
+ OptionsValidator.OptionsValidator.validatePhoneticName(test);
93
91
  break;
94
- default:
95
- throw new Error(`Cmpstr condition <${cond}> unknown`);
96
92
  }
97
93
  }
98
94
  assertMany(...cond) {
99
95
  for (const [c, test] of cond) this.assert(c, test);
100
96
  }
101
97
  resolveOptions(opt) {
102
- return DeepMerge.merge({ ...(this.options ?? Object.create(null)) }, opt);
98
+ const merged = DeepMerge.DeepMerge.merge(
99
+ { ...(this.options ?? Object.create(null)) },
100
+ opt
101
+ );
102
+ OptionsValidator.OptionsValidator.validateOptions(merged);
103
+ return merged;
103
104
  }
104
105
  normalize(input, flags) {
105
106
  return Normalizer.Normalizer.normalize(
@@ -118,7 +119,7 @@ class CmpStr {
118
119
  return input;
119
120
  }
120
121
  postProcess(result, opt) {
121
- if (opt?.removeZero && Array.isArray(result))
122
+ if (Array.isArray(result) && opt?.removeZero)
122
123
  result = result.filter((r) => r.res > 0);
123
124
  return result;
124
125
  }
@@ -136,69 +137,119 @@ class CmpStr {
136
137
  compute(a, b, opt, mode, raw, skip) {
137
138
  const resolved = this.resolveOptions(opt);
138
139
  this.assert('metric', resolved.metric);
139
- const A = skip ? a : this.prepare(a, resolved);
140
- const B = skip ? b : this.prepare(b, resolved);
141
- if (
142
- resolved.safeEmpty &&
143
- ((Array.isArray(A) && A.length === 0) ||
144
- (Array.isArray(B) && B.length === 0) ||
145
- A === '' ||
146
- B === '')
147
- ) {
148
- return [];
149
- }
150
- const metric = Registry.factory['metric'](
151
- resolved.metric,
152
- A,
153
- B,
154
- resolved.opt
140
+ return Errors.ErrorUtil.wrap(
141
+ () => {
142
+ const A = skip ? a : this.prepare(a, resolved);
143
+ const B = skip ? b : this.prepare(b, resolved);
144
+ if (
145
+ resolved.safeEmpty &&
146
+ ((Array.isArray(A) && A.length === 0) ||
147
+ (Array.isArray(B) && B.length === 0) ||
148
+ A === '' ||
149
+ B === '')
150
+ ) {
151
+ return [];
152
+ }
153
+ const metric = Registry.factory['metric'](
154
+ resolved.metric,
155
+ A,
156
+ B,
157
+ resolved.opt
158
+ );
159
+ if (resolved.output !== 'prep') metric.setOriginal(a, b);
160
+ metric.run(mode);
161
+ const result = this.postProcess(metric.getResults(), resolved);
162
+ return this.output(result, raw ?? resolved.raw);
163
+ },
164
+ `Failed to compute metric <${resolved.metric}> for the given inputs`,
165
+ { a, b, options: opt }
155
166
  );
156
- if (resolved.output !== 'prep') metric.setOriginal(a, b);
157
- metric.run(mode);
158
- const result = this.postProcess(metric.getResults(), resolved);
159
- return this.output(result, raw ?? resolved.raw);
160
167
  }
161
168
  output(result, raw) {
162
- return (raw ?? this.options.raw)
163
- ? result
164
- : Array.isArray(result)
165
- ? result.map((r) => ({ source: r.a, target: r.b, match: r.res }))
166
- : { source: result.a, target: result.b, match: result.res };
169
+ return Errors.ErrorUtil.wrap(
170
+ () =>
171
+ (raw ?? this.options.raw)
172
+ ? result
173
+ : Array.isArray(result)
174
+ ? result.map((r) => ({ source: r.a, target: r.b, match: r.res }))
175
+ : { source: result.a, target: result.b, match: result.res },
176
+ `Failed to resolve output format for the metric result`,
177
+ { result, raw }
178
+ );
179
+ }
180
+ clone() {
181
+ const inst = Object.assign(
182
+ Object.create(Object.getPrototypeOf(this)),
183
+ this
184
+ );
185
+ inst.options = DeepMerge.DeepMerge.merge(Object.create(null), this.options);
186
+ return inst;
167
187
  }
168
- clone = () => Object.assign(Object.create(Object.getPrototypeOf(this)), this);
169
188
  reset() {
170
- for (const k in this.options) delete this.options[k];
189
+ this.options = Object.create(null);
171
190
  return this;
172
191
  }
173
192
  setOptions(opt) {
193
+ OptionsValidator.OptionsValidator.validateOptions(opt);
174
194
  this.options = opt;
175
195
  return this;
176
196
  }
177
197
  mergeOptions(opt) {
178
- DeepMerge.merge(this.options, opt);
198
+ DeepMerge.DeepMerge.merge(this.options, opt);
199
+ OptionsValidator.OptionsValidator.validateOptions(this.options);
179
200
  return this;
180
201
  }
181
202
  setSerializedOptions(opt) {
182
- this.options = JSON.parse(opt);
183
- return this;
203
+ try {
204
+ const parsed = JSON.parse(opt);
205
+ OptionsValidator.OptionsValidator.validateOptions(parsed);
206
+ this.options = parsed;
207
+ return this;
208
+ } catch (err) {
209
+ if (err instanceof SyntaxError)
210
+ throw new Errors.CmpStrValidationError(
211
+ `Failed to parse serialized options, invalid JSON string`,
212
+ { opt, error: err instanceof Error ? err.message : String(err) }
213
+ );
214
+ throw err;
215
+ }
184
216
  }
185
217
  setOption(path, value) {
186
- DeepMerge.set(this.options, path, value);
218
+ DeepMerge.DeepMerge.set(this.options, path, value);
219
+ OptionsValidator.OptionsValidator.validateOptions(this.options);
187
220
  return this;
188
221
  }
189
222
  rmvOption(path) {
190
- DeepMerge.rmv(this.options, path);
223
+ DeepMerge.DeepMerge.rmv(this.options, path);
191
224
  return this;
192
225
  }
193
- setRaw = (enable) => this.setOption('raw', enable);
194
- setMetric = (name) => this.setOption('metric', name);
195
- setFlags = (flags) => this.setOption('flags', flags);
196
- rmvFlags = () => this.rmvOption('flags');
197
- setProcessors = (opt) => this.setOption('processors', opt);
198
- rmvProcessors = () => this.rmvOption('processors');
199
- getOptions = () => this.options;
200
- getSerializedOptions = () => JSON.stringify(this.options);
201
- getOption = (path) => DeepMerge.get(this.options, path);
226
+ setRaw(enable) {
227
+ return this.setOption('raw', enable);
228
+ }
229
+ setMetric(name) {
230
+ return this.setOption('metric', name);
231
+ }
232
+ setFlags(flags) {
233
+ return this.setOption('flags', flags);
234
+ }
235
+ rmvFlags() {
236
+ return this.rmvOption('flags');
237
+ }
238
+ setProcessors(opt) {
239
+ return this.setOption('processors', opt);
240
+ }
241
+ rmvProcessors() {
242
+ return this.rmvOption('processors');
243
+ }
244
+ getOptions() {
245
+ return this.options;
246
+ }
247
+ getSerializedOptions() {
248
+ return JSON.stringify(this.options);
249
+ }
250
+ getOption(path) {
251
+ return DeepMerge.DeepMerge.get(this.options, path);
252
+ }
202
253
  test(a, b, opt) {
203
254
  return this.compute(a, b, opt, 'single');
204
255
  }
@@ -237,15 +288,35 @@ class CmpStr {
237
288
  const resolved = this.resolveOptions({ flags, processors });
238
289
  const test = this.prepare(needle, resolved);
239
290
  const hstk = this.prepare(haystack, resolved);
240
- return haystack.filter((_, i) => hstk[i].includes(test));
291
+ const out = [];
292
+ for (let i = 0, len = hstk.length; i < len; i++) {
293
+ if (hstk[i].includes(test)) out.push(haystack[i]);
294
+ }
295
+ return out;
241
296
  }
242
297
  matrix(input, opt) {
243
- input = this.prepare(input, this.resolveOptions(opt));
244
- return input.map((a) =>
245
- this.compute(a, input, undefined, 'batch', true, true).map(
246
- (b) => b.res ?? 0
247
- )
248
- );
298
+ const resolved = this.resolveOptions(opt);
299
+ const arr = this.prepare(input, resolved);
300
+ const n = arr.length;
301
+ const out = Array.from({ length: n }, () => new Array(n).fill(0));
302
+ for (let i = 0; i < n; i++)
303
+ for (let j = i; j < n; j++) {
304
+ if (i === j) {
305
+ out[i][j] = 1;
306
+ } else {
307
+ const score = this.compute(
308
+ arr[i],
309
+ arr[j],
310
+ resolved,
311
+ 'single',
312
+ true,
313
+ true
314
+ ).res;
315
+ out[i][j] = score;
316
+ out[j][i] = score;
317
+ }
318
+ }
319
+ return out;
249
320
  }
250
321
  phoneticIndex(input, algo, opt) {
251
322
  const { algo: a, opt: o } = this.options.processors?.phonetic ?? {};
@@ -290,4 +361,3 @@ class CmpStr {
290
361
  }
291
362
 
292
363
  exports.CmpStr = CmpStr;
293
- //# sourceMappingURL=CmpStr.cjs.map