@corva/convert-units 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +13 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -77,6 +77,7 @@ var loadDefinitions = () => {
|
|
|
77
77
|
"formationDensity",
|
|
78
78
|
"concentration",
|
|
79
79
|
"gasConcentration",
|
|
80
|
+
"proportion",
|
|
80
81
|
"force",
|
|
81
82
|
"gravity",
|
|
82
83
|
"gasVolume",
|
|
@@ -136,13 +137,22 @@ var getUnit = (abbr, measure) => {
|
|
|
136
137
|
if (!entry) throwUnsupportedCompatibilityError(abbr, measure);
|
|
137
138
|
return entry;
|
|
138
139
|
}
|
|
140
|
+
const direct = unitIndex.get(abbr);
|
|
141
|
+
if (direct) return direct;
|
|
139
142
|
const canonical = aliasMap.get(abbr);
|
|
140
143
|
return canonical !== void 0 ? unitIndex.get(canonical) : void 0;
|
|
141
144
|
};
|
|
142
145
|
var getUnitForPair = (abbrOne, abbrTwo) => {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
for (const entries of measureIndex.values()) {
|
|
147
|
+
let one;
|
|
148
|
+
let two;
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
if (entry.abbr === abbrOne) one = entry;
|
|
151
|
+
else if (entry.abbr === abbrTwo) two = entry;
|
|
152
|
+
if (one && two) return [one, two];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
146
156
|
};
|
|
147
157
|
var toPlainUnit = ({ abbr, measure, system, unit }) => ({
|
|
148
158
|
abbr,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/loader.ts","../src/errors.ts","../src/core.ts"],"sourcesContent":["export type {\n UnitDefinition,\n MeasureDefinition,\n SystemAnchor,\n ResolvedUnit,\n ConversionResult,\n PlainUnit,\n BucketMapping,\n UnitNames,\n} from './types';\n\nexport {\n convert,\n getMeasures,\n describe,\n getUnit,\n getUnitForPair,\n listUnits,\n listUnitsWithAliases,\n possibilities,\n toBest,\n bucketMapping,\n getUnitKeyByAlias,\n} from './core';\n\nexport { convert as default } from './core';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MeasureDefinition, BucketMapping } from './types';\n\nconst UNIT_BUCKET_MAPPING_FILE = 'unitBucketMapping.json';\nconst DEFS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'definitions');\n\nconst loadDefinitions = (): Record<string, MeasureDefinition> => {\n const result: Record<string, MeasureDefinition> = {};\n const files = fs.readdirSync(DEFS_DIR).filter((f) => f.endsWith('.json') && f !== UNIT_BUCKET_MAPPING_FILE);\n\n for (const file of files) {\n const name = path.basename(file, '.json');\n const raw = JSON.parse(fs.readFileSync(path.join(DEFS_DIR, file), 'utf-8'));\n\n if (raw._anchors) {\n for (const key of Object.keys(raw._anchors)) {\n const anchor = raw._anchors[key];\n if (typeof anchor.transform === 'string') {\n anchor.transform = new Function('val', `return ${anchor.transform}`) as (val: number) => number;\n }\n }\n }\n\n result[name] = raw;\n }\n\n if (result.density) result.formationDensity = result.density;\n\n // Restore the same lookup priority as the original library.\n //\n // Measures listed here are moved to the END of the insertion order so that\n // \"first occurrence wins\" in buildIndexes() resolves shared unit keys correctly:\n //\n // density / formationDensity — share kPa/m and psi/ft with pressureGradient;\n // pressureGradient anchors must win\n // concentration — shares ppm with partsPer; partsPer must win\n // gasConcentration — shares ppm with partsPer; partsPer must win\n // force / gravity — share g with mass; mass (gram) must win\n // gasVolume — shares gal/bbl/m3 with volume; liquid anchors must win\n // spontaneousPotential — shares mV with voltage; voltage must win\n const DEPRIORITIZED = [\n 'density',\n 'formationDensity',\n 'concentration',\n 'gasConcentration',\n 'force',\n 'gravity',\n 'gasVolume',\n 'spontaneousPotential',\n ];\n const deprioritized: Record<string, MeasureDefinition> = {};\n for (const key of DEPRIORITIZED) {\n if (result[key]) {\n deprioritized[key] = result[key];\n delete result[key];\n }\n }\n return { ...result, ...deprioritized };\n};\n\nexport const measures: Record<string, MeasureDefinition> = loadDefinitions();\n\nexport const bucketMapping: BucketMapping = JSON.parse(\n fs.readFileSync(path.join(DEFS_DIR, UNIT_BUCKET_MAPPING_FILE), 'utf-8'),\n);\n","export const throwUnsupportedUnitError = (what: string, validUnits: string[]): never => {\n throw new Error(`Unsupported unit ${what}, use one of: ${validUnits.join(', ')}`);\n};\n\nexport const throwUnsupportedCompatibilityError = (abbr: string, measure: string): never => {\n throw new Error(`Unsupported compatibility for unit ${abbr} and measure ${measure}`);\n};\n\nexport const throwIncompatibleMeasuresError = (destMeasure: string, originMeasure: string): never => {\n throw new Error(`Cannot convert incompatible measures of ${destMeasure} and ${originMeasure}`);\n};\n","import { measures, bucketMapping } from './loader';\nimport {\n throwUnsupportedCompatibilityError,\n throwUnsupportedUnitError,\n throwIncompatibleMeasuresError,\n} from './errors';\nimport type { UnitDefinition, ResolvedUnit, PlainUnit, ConversionResult } from './types';\n\nconst unitIndex = new Map<string, ResolvedUnit>();\nconst measureIndex = new Map<string, ResolvedUnit[]>();\nconst aliasMap = new Map<string, string>();\n\nconst _buildIndexes = (): ResolvedUnit[] => {\n const all: ResolvedUnit[] = [];\n\n for (const [measure, systems] of Object.entries(measures)) {\n for (const [system, units] of Object.entries(systems)) {\n if (system === '_anchors') continue;\n for (const [abbr, unit] of Object.entries(units as Record<string, UnitDefinition>)) {\n const entry: ResolvedUnit = { abbr, unit, system, measure };\n all.push(entry);\n\n // First occurrence wins (preserves density over formationDensity for global lookups).\n if (!unitIndex.has(abbr)) unitIndex.set(abbr, entry);\n\n if (!measureIndex.has(measure)) measureIndex.set(measure, []);\n measureIndex.get(measure)!.push(entry);\n\n aliasMap.set(abbr, abbr);\n for (const alias of unit.aliases ?? []) aliasMap.set(alias, abbr);\n }\n }\n }\n\n return all;\n};\n\nconst allUnits = _buildIndexes();\n\n// Lookup helpers\nconst getUnit = (abbr: string, measure?: string): ResolvedUnit | undefined => {\n if (measure) {\n const entry = measureIndex.get(measure)?.find((e) => e.abbr === abbr || e.unit.aliases?.includes(abbr));\n if (!entry) throwUnsupportedCompatibilityError(abbr, measure);\n return entry;\n }\n const canonical = aliasMap.get(abbr);\n return canonical !== undefined ? unitIndex.get(canonical) : undefined;\n};\n\nconst getUnitForPair = (abbrOne: string, abbrTwo: string): [ResolvedUnit, ResolvedUnit] | null => {\n const one = unitIndex.get(abbrOne);\n const two = unitIndex.get(abbrTwo);\n return one && two && one.measure === two.measure ? [one, two] : null;\n};\n\nconst toPlainUnit = ({ abbr, measure, system, unit }: ResolvedUnit): PlainUnit => ({\n abbr,\n measure,\n system,\n singular: unit.name.singular,\n plural: unit.name.plural,\n display: unit.name.display,\n});\n\nconst _toPlainUnitWithAlias = (entry: ResolvedUnit): PlainUnit => ({\n ...toPlainUnit(entry),\n aliases: entry.unit.aliases,\n});\n\nconst listUnits = (measure?: string, withAliases = false): PlainUnit[] => {\n const decorator = withAliases ? _toPlainUnitWithAlias : toPlainUnit;\n const entries = measure ? (measureIndex.get(measure) ?? []) : allUnits;\n return entries.map(decorator);\n};\n\nconst getPossibilities = (measure?: string, origin?: ResolvedUnit): string[] => {\n const m = measure ?? origin?.measure;\n if (!m) return [...unitIndex.keys()];\n return (measureIndex.get(m) ?? []).map((e) => e.abbr);\n};\n\nconst convert = (value: number, from: string, to: string, measure?: string): number => {\n const origin = getUnit(from, measure) ?? throwUnsupportedUnitError(from, getPossibilities());\n const dest = getUnit(to, measure) ?? throwUnsupportedUnitError(to, getPossibilities());\n\n if (origin.abbr === dest.abbr) return value;\n\n let src = origin;\n let tgt = dest;\n\n if (dest.measure !== origin.measure) {\n if (measure) throwIncompatibleMeasuresError(dest.measure, origin.measure);\n [tgt, src] =\n getUnitForPair(dest.abbr, origin.abbr) ?? throwIncompatibleMeasuresError(dest.measure, origin.measure);\n }\n\n let result = value * src.unit.to_anchor;\n if (src.unit.anchor_shift) result -= src.unit.anchor_shift;\n\n if (src.system !== tgt.system) {\n const anchor = measures[src.measure]._anchors[src.system];\n result = typeof anchor.transform === 'function' ? anchor.transform(result) : result * anchor.ratio!;\n }\n\n if (tgt.unit.anchor_shift) result += tgt.unit.anchor_shift;\n return result / tgt.unit.to_anchor;\n};\n\nconst toBest = (\n value: number,\n from: string,\n measure?: string,\n exclude: string[] = [],\n): ConversionResult | undefined => {\n const origin = getUnit(from, measure);\n if (!origin) return undefined;\n\n let best: ConversionResult | undefined;\n\n for (const abbr of getPossibilities(origin.measure)) {\n if (exclude.includes(abbr)) continue;\n const entry = measureIndex.get(origin.measure)?.find((e) => e.abbr === abbr);\n if (!entry || entry.system !== origin.system) continue;\n\n const result = convert(value, from, abbr, origin.measure);\n const { singular, plural, display } = toPlainUnit(entry);\n if (!best || (result >= 1 && result < best.val)) {\n best = { val: result, unit: abbr, singular, plural, display };\n }\n }\n\n return best;\n};\n\nconst getMeasures = (): string[] => Object.keys(measures);\n\nconst describe = (abbr: string): PlainUnit =>\n toPlainUnit(getUnit(abbr) ?? throwUnsupportedUnitError(abbr, getPossibilities()));\n\nconst listUnitsWithAliases = (measure?: string): PlainUnit[] => listUnits(measure, true);\n\nconst possibilities = (measure?: string): string[] => getPossibilities(measure);\n\nconst getUnitKeyByAlias = (alias: string): string | undefined => aliasMap.get(alias);\n\nexport {\n measures,\n bucketMapping,\n aliasMap,\n getUnit,\n getUnitForPair,\n toPlainUnit,\n listUnits,\n listUnitsWithAliases,\n getMeasures,\n describe,\n possibilities,\n getUnitKeyByAlias,\n getPossibilities,\n convert,\n toBest,\n};\n"],"mappings":"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","names":["path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/loader.ts","../src/errors.ts","../src/core.ts"],"sourcesContent":["export type {\n UnitDefinition,\n MeasureDefinition,\n SystemAnchor,\n ResolvedUnit,\n ConversionResult,\n PlainUnit,\n BucketMapping,\n UnitNames,\n} from './types';\n\nexport {\n convert,\n getMeasures,\n describe,\n getUnit,\n getUnitForPair,\n listUnits,\n listUnitsWithAliases,\n possibilities,\n toBest,\n bucketMapping,\n getUnitKeyByAlias,\n} from './core';\n\nexport { convert as default } from './core';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MeasureDefinition, BucketMapping } from './types';\n\nconst UNIT_BUCKET_MAPPING_FILE = 'unitBucketMapping.json';\nconst DEFS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'definitions');\n\nconst loadDefinitions = (): Record<string, MeasureDefinition> => {\n const result: Record<string, MeasureDefinition> = {};\n const files = fs.readdirSync(DEFS_DIR).filter((f) => f.endsWith('.json') && f !== UNIT_BUCKET_MAPPING_FILE);\n\n for (const file of files) {\n const name = path.basename(file, '.json');\n const raw = JSON.parse(fs.readFileSync(path.join(DEFS_DIR, file), 'utf-8'));\n\n if (raw._anchors) {\n for (const key of Object.keys(raw._anchors)) {\n const anchor = raw._anchors[key];\n if (typeof anchor.transform === 'string') {\n anchor.transform = new Function('val', `return ${anchor.transform}`) as (val: number) => number;\n }\n }\n }\n\n result[name] = raw;\n }\n\n if (result.density) result.formationDensity = result.density;\n\n // Restore the same lookup priority as the original library.\n //\n // Measures listed here are moved to the END of the insertion order so that\n // \"first occurrence wins\" in buildIndexes() resolves shared unit keys correctly:\n //\n // density / formationDensity — share kPa/m and psi/ft with pressureGradient;\n // pressureGradient anchors must win\n // concentration — shares ppm with partsPer; partsPer must win\n // gasConcentration — shares ppm with partsPer; partsPer must win.\n // Kept BEFORE proportion so that % resolves to\n // gasConcentration, matching the original library order.\n // proportion — shares % with gasConcentration; gasConcentration must win\n // force / gravity — share g with mass; mass (gram) must win\n // gasVolume — shares gal/bbl/m3 with volume; liquid anchors must win\n // spontaneousPotential — shares mV with voltage; voltage must win\n const DEPRIORITIZED = [\n 'density',\n 'formationDensity',\n 'concentration',\n 'gasConcentration',\n 'proportion',\n 'force',\n 'gravity',\n 'gasVolume',\n 'spontaneousPotential',\n ];\n const deprioritized: Record<string, MeasureDefinition> = {};\n for (const key of DEPRIORITIZED) {\n if (result[key]) {\n deprioritized[key] = result[key];\n delete result[key];\n }\n }\n return { ...result, ...deprioritized };\n};\n\nexport const measures: Record<string, MeasureDefinition> = loadDefinitions();\n\nexport const bucketMapping: BucketMapping = JSON.parse(\n fs.readFileSync(path.join(DEFS_DIR, UNIT_BUCKET_MAPPING_FILE), 'utf-8'),\n);\n","export const throwUnsupportedUnitError = (what: string, validUnits: string[]): never => {\n throw new Error(`Unsupported unit ${what}, use one of: ${validUnits.join(', ')}`);\n};\n\nexport const throwUnsupportedCompatibilityError = (abbr: string, measure: string): never => {\n throw new Error(`Unsupported compatibility for unit ${abbr} and measure ${measure}`);\n};\n\nexport const throwIncompatibleMeasuresError = (destMeasure: string, originMeasure: string): never => {\n throw new Error(`Cannot convert incompatible measures of ${destMeasure} and ${originMeasure}`);\n};\n","import { measures, bucketMapping } from './loader';\nimport {\n throwUnsupportedCompatibilityError,\n throwUnsupportedUnitError,\n throwIncompatibleMeasuresError,\n} from './errors';\nimport type { UnitDefinition, ResolvedUnit, PlainUnit, ConversionResult } from './types';\n\nconst unitIndex = new Map<string, ResolvedUnit>();\nconst measureIndex = new Map<string, ResolvedUnit[]>();\nconst aliasMap = new Map<string, string>();\n\nconst _buildIndexes = (): ResolvedUnit[] => {\n const all: ResolvedUnit[] = [];\n\n for (const [measure, systems] of Object.entries(measures)) {\n for (const [system, units] of Object.entries(systems)) {\n if (system === '_anchors') continue;\n for (const [abbr, unit] of Object.entries(units as Record<string, UnitDefinition>)) {\n const entry: ResolvedUnit = { abbr, unit, system, measure };\n all.push(entry);\n\n // First occurrence wins (preserves density over formationDensity for global lookups).\n if (!unitIndex.has(abbr)) unitIndex.set(abbr, entry);\n\n if (!measureIndex.has(measure)) measureIndex.set(measure, []);\n measureIndex.get(measure)!.push(entry);\n\n aliasMap.set(abbr, abbr);\n for (const alias of unit.aliases ?? []) aliasMap.set(alias, abbr);\n }\n }\n }\n\n return all;\n};\n\nconst allUnits = _buildIndexes();\n\n// Lookup helpers\nconst getUnit = (abbr: string, measure?: string): ResolvedUnit | undefined => {\n if (measure) {\n const entry = measureIndex.get(measure)?.find((e) => e.abbr === abbr || e.unit.aliases?.includes(abbr));\n if (!entry) throwUnsupportedCompatibilityError(abbr, measure);\n return entry;\n }\n // Exact canonical key match wins before alias resolution, so e.g. '1/s'\n // stays angularVelocity (unit key) rather than strokesRate ('strokes/sec' alias).\n const direct = unitIndex.get(abbr);\n if (direct) return direct;\n const canonical = aliasMap.get(abbr);\n return canonical !== undefined ? unitIndex.get(canonical) : undefined;\n};\n\n// Searches every measure (in priority order) for one containing BOTH unit keys.\n// This allows conversions between units whose global lookups resolve to different\n// measures, as long as some single measure defines both (e.g. % and Fraction in\n// proportion, or bbl and Mscf in gasVolume).\nconst getUnitForPair = (abbrOne: string, abbrTwo: string): [ResolvedUnit, ResolvedUnit] | null => {\n for (const entries of measureIndex.values()) {\n let one: ResolvedUnit | undefined;\n let two: ResolvedUnit | undefined;\n for (const entry of entries) {\n if (entry.abbr === abbrOne) one = entry;\n else if (entry.abbr === abbrTwo) two = entry;\n if (one && two) return [one, two];\n }\n }\n return null;\n};\n\nconst toPlainUnit = ({ abbr, measure, system, unit }: ResolvedUnit): PlainUnit => ({\n abbr,\n measure,\n system,\n singular: unit.name.singular,\n plural: unit.name.plural,\n display: unit.name.display,\n});\n\nconst _toPlainUnitWithAlias = (entry: ResolvedUnit): PlainUnit => ({\n ...toPlainUnit(entry),\n aliases: entry.unit.aliases,\n});\n\nconst listUnits = (measure?: string, withAliases = false): PlainUnit[] => {\n const decorator = withAliases ? _toPlainUnitWithAlias : toPlainUnit;\n const entries = measure ? (measureIndex.get(measure) ?? []) : allUnits;\n return entries.map(decorator);\n};\n\nconst getPossibilities = (measure?: string, origin?: ResolvedUnit): string[] => {\n const m = measure ?? origin?.measure;\n if (!m) return [...unitIndex.keys()];\n return (measureIndex.get(m) ?? []).map((e) => e.abbr);\n};\n\nconst convert = (value: number, from: string, to: string, measure?: string): number => {\n const origin = getUnit(from, measure) ?? throwUnsupportedUnitError(from, getPossibilities());\n const dest = getUnit(to, measure) ?? throwUnsupportedUnitError(to, getPossibilities());\n\n if (origin.abbr === dest.abbr) return value;\n\n let src = origin;\n let tgt = dest;\n\n if (dest.measure !== origin.measure) {\n if (measure) throwIncompatibleMeasuresError(dest.measure, origin.measure);\n [tgt, src] =\n getUnitForPair(dest.abbr, origin.abbr) ?? throwIncompatibleMeasuresError(dest.measure, origin.measure);\n }\n\n let result = value * src.unit.to_anchor;\n if (src.unit.anchor_shift) result -= src.unit.anchor_shift;\n\n if (src.system !== tgt.system) {\n const anchor = measures[src.measure]._anchors[src.system];\n result = typeof anchor.transform === 'function' ? anchor.transform(result) : result * anchor.ratio!;\n }\n\n if (tgt.unit.anchor_shift) result += tgt.unit.anchor_shift;\n return result / tgt.unit.to_anchor;\n};\n\nconst toBest = (\n value: number,\n from: string,\n measure?: string,\n exclude: string[] = [],\n): ConversionResult | undefined => {\n const origin = getUnit(from, measure);\n if (!origin) return undefined;\n\n let best: ConversionResult | undefined;\n\n for (const abbr of getPossibilities(origin.measure)) {\n if (exclude.includes(abbr)) continue;\n const entry = measureIndex.get(origin.measure)?.find((e) => e.abbr === abbr);\n if (!entry || entry.system !== origin.system) continue;\n\n const result = convert(value, from, abbr, origin.measure);\n const { singular, plural, display } = toPlainUnit(entry);\n if (!best || (result >= 1 && result < best.val)) {\n best = { val: result, unit: abbr, singular, plural, display };\n }\n }\n\n return best;\n};\n\nconst getMeasures = (): string[] => Object.keys(measures);\n\nconst describe = (abbr: string): PlainUnit =>\n toPlainUnit(getUnit(abbr) ?? throwUnsupportedUnitError(abbr, getPossibilities()));\n\nconst listUnitsWithAliases = (measure?: string): PlainUnit[] => listUnits(measure, true);\n\nconst possibilities = (measure?: string): string[] => getPossibilities(measure);\n\nconst getUnitKeyByAlias = (alias: string): string | undefined => aliasMap.get(alias);\n\nexport {\n measures,\n bucketMapping,\n aliasMap,\n getUnit,\n getUnitForPair,\n toPlainUnit,\n listUnits,\n listUnitsWithAliases,\n getMeasures,\n describe,\n possibilities,\n getUnitKeyByAlias,\n getPossibilities,\n convert,\n toBest,\n};\n"],"mappings":"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","names":["path","fs"]}
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var loadDefinitions = () => {
|
|
|
26
26
|
"formationDensity",
|
|
27
27
|
"concentration",
|
|
28
28
|
"gasConcentration",
|
|
29
|
+
"proportion",
|
|
29
30
|
"force",
|
|
30
31
|
"gravity",
|
|
31
32
|
"gasVolume",
|
|
@@ -85,13 +86,22 @@ var getUnit = (abbr, measure) => {
|
|
|
85
86
|
if (!entry) throwUnsupportedCompatibilityError(abbr, measure);
|
|
86
87
|
return entry;
|
|
87
88
|
}
|
|
89
|
+
const direct = unitIndex.get(abbr);
|
|
90
|
+
if (direct) return direct;
|
|
88
91
|
const canonical = aliasMap.get(abbr);
|
|
89
92
|
return canonical !== void 0 ? unitIndex.get(canonical) : void 0;
|
|
90
93
|
};
|
|
91
94
|
var getUnitForPair = (abbrOne, abbrTwo) => {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
for (const entries of measureIndex.values()) {
|
|
96
|
+
let one;
|
|
97
|
+
let two;
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
if (entry.abbr === abbrOne) one = entry;
|
|
100
|
+
else if (entry.abbr === abbrTwo) two = entry;
|
|
101
|
+
if (one && two) return [one, two];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
95
105
|
};
|
|
96
106
|
var toPlainUnit = ({ abbr, measure, system, unit }) => ({
|
|
97
107
|
abbr,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader.ts","../src/errors.ts","../src/core.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MeasureDefinition, BucketMapping } from './types';\n\nconst UNIT_BUCKET_MAPPING_FILE = 'unitBucketMapping.json';\nconst DEFS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'definitions');\n\nconst loadDefinitions = (): Record<string, MeasureDefinition> => {\n const result: Record<string, MeasureDefinition> = {};\n const files = fs.readdirSync(DEFS_DIR).filter((f) => f.endsWith('.json') && f !== UNIT_BUCKET_MAPPING_FILE);\n\n for (const file of files) {\n const name = path.basename(file, '.json');\n const raw = JSON.parse(fs.readFileSync(path.join(DEFS_DIR, file), 'utf-8'));\n\n if (raw._anchors) {\n for (const key of Object.keys(raw._anchors)) {\n const anchor = raw._anchors[key];\n if (typeof anchor.transform === 'string') {\n anchor.transform = new Function('val', `return ${anchor.transform}`) as (val: number) => number;\n }\n }\n }\n\n result[name] = raw;\n }\n\n if (result.density) result.formationDensity = result.density;\n\n // Restore the same lookup priority as the original library.\n //\n // Measures listed here are moved to the END of the insertion order so that\n // \"first occurrence wins\" in buildIndexes() resolves shared unit keys correctly:\n //\n // density / formationDensity — share kPa/m and psi/ft with pressureGradient;\n // pressureGradient anchors must win\n // concentration — shares ppm with partsPer; partsPer must win\n // gasConcentration — shares ppm with partsPer; partsPer must win\n // force / gravity — share g with mass; mass (gram) must win\n // gasVolume — shares gal/bbl/m3 with volume; liquid anchors must win\n // spontaneousPotential — shares mV with voltage; voltage must win\n const DEPRIORITIZED = [\n 'density',\n 'formationDensity',\n 'concentration',\n 'gasConcentration',\n 'force',\n 'gravity',\n 'gasVolume',\n 'spontaneousPotential',\n ];\n const deprioritized: Record<string, MeasureDefinition> = {};\n for (const key of DEPRIORITIZED) {\n if (result[key]) {\n deprioritized[key] = result[key];\n delete result[key];\n }\n }\n return { ...result, ...deprioritized };\n};\n\nexport const measures: Record<string, MeasureDefinition> = loadDefinitions();\n\nexport const bucketMapping: BucketMapping = JSON.parse(\n fs.readFileSync(path.join(DEFS_DIR, UNIT_BUCKET_MAPPING_FILE), 'utf-8'),\n);\n","export const throwUnsupportedUnitError = (what: string, validUnits: string[]): never => {\n throw new Error(`Unsupported unit ${what}, use one of: ${validUnits.join(', ')}`);\n};\n\nexport const throwUnsupportedCompatibilityError = (abbr: string, measure: string): never => {\n throw new Error(`Unsupported compatibility for unit ${abbr} and measure ${measure}`);\n};\n\nexport const throwIncompatibleMeasuresError = (destMeasure: string, originMeasure: string): never => {\n throw new Error(`Cannot convert incompatible measures of ${destMeasure} and ${originMeasure}`);\n};\n","import { measures, bucketMapping } from './loader';\nimport {\n throwUnsupportedCompatibilityError,\n throwUnsupportedUnitError,\n throwIncompatibleMeasuresError,\n} from './errors';\nimport type { UnitDefinition, ResolvedUnit, PlainUnit, ConversionResult } from './types';\n\nconst unitIndex = new Map<string, ResolvedUnit>();\nconst measureIndex = new Map<string, ResolvedUnit[]>();\nconst aliasMap = new Map<string, string>();\n\nconst _buildIndexes = (): ResolvedUnit[] => {\n const all: ResolvedUnit[] = [];\n\n for (const [measure, systems] of Object.entries(measures)) {\n for (const [system, units] of Object.entries(systems)) {\n if (system === '_anchors') continue;\n for (const [abbr, unit] of Object.entries(units as Record<string, UnitDefinition>)) {\n const entry: ResolvedUnit = { abbr, unit, system, measure };\n all.push(entry);\n\n // First occurrence wins (preserves density over formationDensity for global lookups).\n if (!unitIndex.has(abbr)) unitIndex.set(abbr, entry);\n\n if (!measureIndex.has(measure)) measureIndex.set(measure, []);\n measureIndex.get(measure)!.push(entry);\n\n aliasMap.set(abbr, abbr);\n for (const alias of unit.aliases ?? []) aliasMap.set(alias, abbr);\n }\n }\n }\n\n return all;\n};\n\nconst allUnits = _buildIndexes();\n\n// Lookup helpers\nconst getUnit = (abbr: string, measure?: string): ResolvedUnit | undefined => {\n if (measure) {\n const entry = measureIndex.get(measure)?.find((e) => e.abbr === abbr || e.unit.aliases?.includes(abbr));\n if (!entry) throwUnsupportedCompatibilityError(abbr, measure);\n return entry;\n }\n const canonical = aliasMap.get(abbr);\n return canonical !== undefined ? unitIndex.get(canonical) : undefined;\n};\n\nconst getUnitForPair = (abbrOne: string, abbrTwo: string): [ResolvedUnit, ResolvedUnit] | null => {\n const one = unitIndex.get(abbrOne);\n const two = unitIndex.get(abbrTwo);\n return one && two && one.measure === two.measure ? [one, two] : null;\n};\n\nconst toPlainUnit = ({ abbr, measure, system, unit }: ResolvedUnit): PlainUnit => ({\n abbr,\n measure,\n system,\n singular: unit.name.singular,\n plural: unit.name.plural,\n display: unit.name.display,\n});\n\nconst _toPlainUnitWithAlias = (entry: ResolvedUnit): PlainUnit => ({\n ...toPlainUnit(entry),\n aliases: entry.unit.aliases,\n});\n\nconst listUnits = (measure?: string, withAliases = false): PlainUnit[] => {\n const decorator = withAliases ? _toPlainUnitWithAlias : toPlainUnit;\n const entries = measure ? (measureIndex.get(measure) ?? []) : allUnits;\n return entries.map(decorator);\n};\n\nconst getPossibilities = (measure?: string, origin?: ResolvedUnit): string[] => {\n const m = measure ?? origin?.measure;\n if (!m) return [...unitIndex.keys()];\n return (measureIndex.get(m) ?? []).map((e) => e.abbr);\n};\n\nconst convert = (value: number, from: string, to: string, measure?: string): number => {\n const origin = getUnit(from, measure) ?? throwUnsupportedUnitError(from, getPossibilities());\n const dest = getUnit(to, measure) ?? throwUnsupportedUnitError(to, getPossibilities());\n\n if (origin.abbr === dest.abbr) return value;\n\n let src = origin;\n let tgt = dest;\n\n if (dest.measure !== origin.measure) {\n if (measure) throwIncompatibleMeasuresError(dest.measure, origin.measure);\n [tgt, src] =\n getUnitForPair(dest.abbr, origin.abbr) ?? throwIncompatibleMeasuresError(dest.measure, origin.measure);\n }\n\n let result = value * src.unit.to_anchor;\n if (src.unit.anchor_shift) result -= src.unit.anchor_shift;\n\n if (src.system !== tgt.system) {\n const anchor = measures[src.measure]._anchors[src.system];\n result = typeof anchor.transform === 'function' ? anchor.transform(result) : result * anchor.ratio!;\n }\n\n if (tgt.unit.anchor_shift) result += tgt.unit.anchor_shift;\n return result / tgt.unit.to_anchor;\n};\n\nconst toBest = (\n value: number,\n from: string,\n measure?: string,\n exclude: string[] = [],\n): ConversionResult | undefined => {\n const origin = getUnit(from, measure);\n if (!origin) return undefined;\n\n let best: ConversionResult | undefined;\n\n for (const abbr of getPossibilities(origin.measure)) {\n if (exclude.includes(abbr)) continue;\n const entry = measureIndex.get(origin.measure)?.find((e) => e.abbr === abbr);\n if (!entry || entry.system !== origin.system) continue;\n\n const result = convert(value, from, abbr, origin.measure);\n const { singular, plural, display } = toPlainUnit(entry);\n if (!best || (result >= 1 && result < best.val)) {\n best = { val: result, unit: abbr, singular, plural, display };\n }\n }\n\n return best;\n};\n\nconst getMeasures = (): string[] => Object.keys(measures);\n\nconst describe = (abbr: string): PlainUnit =>\n toPlainUnit(getUnit(abbr) ?? throwUnsupportedUnitError(abbr, getPossibilities()));\n\nconst listUnitsWithAliases = (measure?: string): PlainUnit[] => listUnits(measure, true);\n\nconst possibilities = (measure?: string): string[] => getPossibilities(measure);\n\nconst getUnitKeyByAlias = (alias: string): string | undefined => aliasMap.get(alias);\n\nexport {\n measures,\n bucketMapping,\n aliasMap,\n getUnit,\n getUnitForPair,\n toPlainUnit,\n listUnits,\n listUnitsWithAliases,\n getMeasures,\n describe,\n possibilities,\n getUnitKeyByAlias,\n getPossibilities,\n convert,\n toBest,\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts","../src/errors.ts","../src/core.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MeasureDefinition, BucketMapping } from './types';\n\nconst UNIT_BUCKET_MAPPING_FILE = 'unitBucketMapping.json';\nconst DEFS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'definitions');\n\nconst loadDefinitions = (): Record<string, MeasureDefinition> => {\n const result: Record<string, MeasureDefinition> = {};\n const files = fs.readdirSync(DEFS_DIR).filter((f) => f.endsWith('.json') && f !== UNIT_BUCKET_MAPPING_FILE);\n\n for (const file of files) {\n const name = path.basename(file, '.json');\n const raw = JSON.parse(fs.readFileSync(path.join(DEFS_DIR, file), 'utf-8'));\n\n if (raw._anchors) {\n for (const key of Object.keys(raw._anchors)) {\n const anchor = raw._anchors[key];\n if (typeof anchor.transform === 'string') {\n anchor.transform = new Function('val', `return ${anchor.transform}`) as (val: number) => number;\n }\n }\n }\n\n result[name] = raw;\n }\n\n if (result.density) result.formationDensity = result.density;\n\n // Restore the same lookup priority as the original library.\n //\n // Measures listed here are moved to the END of the insertion order so that\n // \"first occurrence wins\" in buildIndexes() resolves shared unit keys correctly:\n //\n // density / formationDensity — share kPa/m and psi/ft with pressureGradient;\n // pressureGradient anchors must win\n // concentration — shares ppm with partsPer; partsPer must win\n // gasConcentration — shares ppm with partsPer; partsPer must win.\n // Kept BEFORE proportion so that % resolves to\n // gasConcentration, matching the original library order.\n // proportion — shares % with gasConcentration; gasConcentration must win\n // force / gravity — share g with mass; mass (gram) must win\n // gasVolume — shares gal/bbl/m3 with volume; liquid anchors must win\n // spontaneousPotential — shares mV with voltage; voltage must win\n const DEPRIORITIZED = [\n 'density',\n 'formationDensity',\n 'concentration',\n 'gasConcentration',\n 'proportion',\n 'force',\n 'gravity',\n 'gasVolume',\n 'spontaneousPotential',\n ];\n const deprioritized: Record<string, MeasureDefinition> = {};\n for (const key of DEPRIORITIZED) {\n if (result[key]) {\n deprioritized[key] = result[key];\n delete result[key];\n }\n }\n return { ...result, ...deprioritized };\n};\n\nexport const measures: Record<string, MeasureDefinition> = loadDefinitions();\n\nexport const bucketMapping: BucketMapping = JSON.parse(\n fs.readFileSync(path.join(DEFS_DIR, UNIT_BUCKET_MAPPING_FILE), 'utf-8'),\n);\n","export const throwUnsupportedUnitError = (what: string, validUnits: string[]): never => {\n throw new Error(`Unsupported unit ${what}, use one of: ${validUnits.join(', ')}`);\n};\n\nexport const throwUnsupportedCompatibilityError = (abbr: string, measure: string): never => {\n throw new Error(`Unsupported compatibility for unit ${abbr} and measure ${measure}`);\n};\n\nexport const throwIncompatibleMeasuresError = (destMeasure: string, originMeasure: string): never => {\n throw new Error(`Cannot convert incompatible measures of ${destMeasure} and ${originMeasure}`);\n};\n","import { measures, bucketMapping } from './loader';\nimport {\n throwUnsupportedCompatibilityError,\n throwUnsupportedUnitError,\n throwIncompatibleMeasuresError,\n} from './errors';\nimport type { UnitDefinition, ResolvedUnit, PlainUnit, ConversionResult } from './types';\n\nconst unitIndex = new Map<string, ResolvedUnit>();\nconst measureIndex = new Map<string, ResolvedUnit[]>();\nconst aliasMap = new Map<string, string>();\n\nconst _buildIndexes = (): ResolvedUnit[] => {\n const all: ResolvedUnit[] = [];\n\n for (const [measure, systems] of Object.entries(measures)) {\n for (const [system, units] of Object.entries(systems)) {\n if (system === '_anchors') continue;\n for (const [abbr, unit] of Object.entries(units as Record<string, UnitDefinition>)) {\n const entry: ResolvedUnit = { abbr, unit, system, measure };\n all.push(entry);\n\n // First occurrence wins (preserves density over formationDensity for global lookups).\n if (!unitIndex.has(abbr)) unitIndex.set(abbr, entry);\n\n if (!measureIndex.has(measure)) measureIndex.set(measure, []);\n measureIndex.get(measure)!.push(entry);\n\n aliasMap.set(abbr, abbr);\n for (const alias of unit.aliases ?? []) aliasMap.set(alias, abbr);\n }\n }\n }\n\n return all;\n};\n\nconst allUnits = _buildIndexes();\n\n// Lookup helpers\nconst getUnit = (abbr: string, measure?: string): ResolvedUnit | undefined => {\n if (measure) {\n const entry = measureIndex.get(measure)?.find((e) => e.abbr === abbr || e.unit.aliases?.includes(abbr));\n if (!entry) throwUnsupportedCompatibilityError(abbr, measure);\n return entry;\n }\n // Exact canonical key match wins before alias resolution, so e.g. '1/s'\n // stays angularVelocity (unit key) rather than strokesRate ('strokes/sec' alias).\n const direct = unitIndex.get(abbr);\n if (direct) return direct;\n const canonical = aliasMap.get(abbr);\n return canonical !== undefined ? unitIndex.get(canonical) : undefined;\n};\n\n// Searches every measure (in priority order) for one containing BOTH unit keys.\n// This allows conversions between units whose global lookups resolve to different\n// measures, as long as some single measure defines both (e.g. % and Fraction in\n// proportion, or bbl and Mscf in gasVolume).\nconst getUnitForPair = (abbrOne: string, abbrTwo: string): [ResolvedUnit, ResolvedUnit] | null => {\n for (const entries of measureIndex.values()) {\n let one: ResolvedUnit | undefined;\n let two: ResolvedUnit | undefined;\n for (const entry of entries) {\n if (entry.abbr === abbrOne) one = entry;\n else if (entry.abbr === abbrTwo) two = entry;\n if (one && two) return [one, two];\n }\n }\n return null;\n};\n\nconst toPlainUnit = ({ abbr, measure, system, unit }: ResolvedUnit): PlainUnit => ({\n abbr,\n measure,\n system,\n singular: unit.name.singular,\n plural: unit.name.plural,\n display: unit.name.display,\n});\n\nconst _toPlainUnitWithAlias = (entry: ResolvedUnit): PlainUnit => ({\n ...toPlainUnit(entry),\n aliases: entry.unit.aliases,\n});\n\nconst listUnits = (measure?: string, withAliases = false): PlainUnit[] => {\n const decorator = withAliases ? _toPlainUnitWithAlias : toPlainUnit;\n const entries = measure ? (measureIndex.get(measure) ?? []) : allUnits;\n return entries.map(decorator);\n};\n\nconst getPossibilities = (measure?: string, origin?: ResolvedUnit): string[] => {\n const m = measure ?? origin?.measure;\n if (!m) return [...unitIndex.keys()];\n return (measureIndex.get(m) ?? []).map((e) => e.abbr);\n};\n\nconst convert = (value: number, from: string, to: string, measure?: string): number => {\n const origin = getUnit(from, measure) ?? throwUnsupportedUnitError(from, getPossibilities());\n const dest = getUnit(to, measure) ?? throwUnsupportedUnitError(to, getPossibilities());\n\n if (origin.abbr === dest.abbr) return value;\n\n let src = origin;\n let tgt = dest;\n\n if (dest.measure !== origin.measure) {\n if (measure) throwIncompatibleMeasuresError(dest.measure, origin.measure);\n [tgt, src] =\n getUnitForPair(dest.abbr, origin.abbr) ?? throwIncompatibleMeasuresError(dest.measure, origin.measure);\n }\n\n let result = value * src.unit.to_anchor;\n if (src.unit.anchor_shift) result -= src.unit.anchor_shift;\n\n if (src.system !== tgt.system) {\n const anchor = measures[src.measure]._anchors[src.system];\n result = typeof anchor.transform === 'function' ? anchor.transform(result) : result * anchor.ratio!;\n }\n\n if (tgt.unit.anchor_shift) result += tgt.unit.anchor_shift;\n return result / tgt.unit.to_anchor;\n};\n\nconst toBest = (\n value: number,\n from: string,\n measure?: string,\n exclude: string[] = [],\n): ConversionResult | undefined => {\n const origin = getUnit(from, measure);\n if (!origin) return undefined;\n\n let best: ConversionResult | undefined;\n\n for (const abbr of getPossibilities(origin.measure)) {\n if (exclude.includes(abbr)) continue;\n const entry = measureIndex.get(origin.measure)?.find((e) => e.abbr === abbr);\n if (!entry || entry.system !== origin.system) continue;\n\n const result = convert(value, from, abbr, origin.measure);\n const { singular, plural, display } = toPlainUnit(entry);\n if (!best || (result >= 1 && result < best.val)) {\n best = { val: result, unit: abbr, singular, plural, display };\n }\n }\n\n return best;\n};\n\nconst getMeasures = (): string[] => Object.keys(measures);\n\nconst describe = (abbr: string): PlainUnit =>\n toPlainUnit(getUnit(abbr) ?? throwUnsupportedUnitError(abbr, getPossibilities()));\n\nconst listUnitsWithAliases = (measure?: string): PlainUnit[] => listUnits(measure, true);\n\nconst possibilities = (measure?: string): string[] => getPossibilities(measure);\n\nconst getUnitKeyByAlias = (alias: string): string | undefined => aliasMap.get(alias);\n\nexport {\n measures,\n bucketMapping,\n aliasMap,\n getUnit,\n getUnitForPair,\n toPlainUnit,\n listUnits,\n listUnitsWithAliases,\n getMeasures,\n describe,\n possibilities,\n getUnitKeyByAlias,\n getPossibilities,\n convert,\n toBest,\n};\n"],"mappings":"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","names":[]}
|