measurable 2.0.0 → 3.1.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.
- package/CHANGELOG.md +84 -0
- package/README.md +129 -27
- package/dist/dimensions/angle.js +12 -5
- package/dist/dimensions/area.js +37 -16
- package/dist/dimensions/data.js +11 -8
- package/dist/dimensions/energy.js +18 -11
- package/dist/dimensions/force.js +5 -5
- package/dist/dimensions/frequency.js +2 -2
- package/dist/dimensions/illuminance.js +7 -4
- package/dist/dimensions/length.js +6 -6
- package/dist/dimensions/luminance.js +5 -8
- package/dist/dimensions/luminousIntensity.js +7 -7
- package/dist/dimensions/mass.js +12 -8
- package/dist/dimensions/power.js +4 -4
- package/dist/dimensions/pressure.js +12 -9
- package/dist/dimensions/temperature.js +3 -3
- package/dist/dimensions/time.js +18 -6
- package/dist/dimensions/volume.js +56 -23
- package/dist/errors/AmbiguousUnitError.js +1 -2
- package/dist/errors/ArgumentError.d.ts +7 -0
- package/dist/errors/ArgumentError.js +11 -0
- package/dist/errors/DimensionMismatchError.d.ts +13 -0
- package/dist/errors/DimensionMismatchError.js +16 -0
- package/dist/errors/DuplicateUnitError.d.ts +5 -0
- package/dist/errors/DuplicateUnitError.js +10 -0
- package/dist/errors/ParseError.d.ts +4 -0
- package/dist/errors/ParseError.js +10 -0
- package/dist/errors/UnsupportedDimensionError.d.ts +10 -0
- package/dist/errors/UnsupportedDimensionError.js +14 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/dist/lib/Dimension.d.ts +14 -5
- package/dist/lib/Dimension.js +22 -19
- package/dist/lib/MeasurementSystem.js +4 -15
- package/dist/lib/Quantity.d.ts +81 -3
- package/dist/lib/Quantity.js +82 -4
- package/dist/lib/Rational.d.ts +1 -1
- package/dist/lib/Rational.js +6 -5
- package/dist/lib/Unit.d.ts +18 -11
- package/dist/lib/Unit.js +7 -3
- package/dist/utils/definePrefixed.d.ts +8 -15
- package/dist/utils/definePrefixed.js +21 -10
- package/package.json +8 -3
package/dist/dimensions/mass.js
CHANGED
|
@@ -9,16 +9,20 @@ const definePrefixed_1 = require("../utils/definePrefixed");
|
|
|
9
9
|
* choice of base is internal and does not affect any conversion.)
|
|
10
10
|
*/
|
|
11
11
|
exports.mass = new Dimension_1.Dimension("mass");
|
|
12
|
-
exports.gram = exports.mass.base("gram",
|
|
12
|
+
exports.gram = exports.mass.base("gram", { symbol: "g", plural: "grams" });
|
|
13
13
|
// Customary units, expressed in grams.
|
|
14
|
-
exports.pound = exports.mass.unit("pound", 453.59237,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
exports.pound = exports.mass.unit("pound", 453.59237, {
|
|
15
|
+
symbol: "lb",
|
|
16
|
+
plural: "pounds",
|
|
17
|
+
aliases: ["lbs"],
|
|
18
|
+
});
|
|
19
|
+
exports.ounce = exports.mass.unit("ounce", 28.349523125, { symbol: "oz", plural: "ounces" });
|
|
20
|
+
exports.stone = exports.mass.unit("stone", 6350.29318, { symbol: "st", plural: "stones" });
|
|
21
|
+
exports.tonne = exports.mass.unit("tonne", 1000000, { symbol: "t", plural: "tonnes" });
|
|
18
22
|
// Short (US) and long (Imperial) tons share the "ton" alias but differ in size;
|
|
19
23
|
// the metric tonne above is a separate unit again. Parsing disambiguates these.
|
|
20
|
-
exports.shortTon = exports.mass.unit("shortTon", 907184.74,
|
|
21
|
-
exports.longTon = exports.mass.unit("longTon", 1016046.9088,
|
|
24
|
+
exports.shortTon = exports.mass.unit("shortTon", 907184.74, { plural: "tons", aliases: ["ton"] });
|
|
25
|
+
exports.longTon = exports.mass.unit("longTon", 1016046.9088, { plural: "tons", aliases: ["ton"] });
|
|
22
26
|
/** Every SI-prefixed gram — including the kilogram — keyed by name. */
|
|
23
|
-
exports.metricMass = (0, definePrefixed_1.definePrefixed)(exports.mass,
|
|
27
|
+
exports.metricMass = (0, definePrefixed_1.definePrefixed)(exports.mass, exports.gram);
|
|
24
28
|
exports.kilogram = exports.metricMass.kilogram, exports.megagram = exports.metricMass.megagram, exports.hectogram = exports.metricMass.hectogram, exports.decagram = exports.metricMass.decagram, exports.decigram = exports.metricMass.decigram, exports.centigram = exports.metricMass.centigram, exports.milligram = exports.metricMass.milligram, exports.microgram = exports.metricMass.microgram, exports.nanogram = exports.metricMass.nanogram;
|
package/dist/dimensions/power.js
CHANGED
|
@@ -5,9 +5,9 @@ const Dimension_1 = require("../lib/Dimension");
|
|
|
5
5
|
const definePrefixed_1 = require("../utils/definePrefixed");
|
|
6
6
|
/** Power. Base unit: watt. */
|
|
7
7
|
exports.power = new Dimension_1.Dimension("power");
|
|
8
|
-
exports.watt = exports.power.base("watt",
|
|
9
|
-
exports.horsepower = exports.power.unit("horsepower", 745.699872,
|
|
10
|
-
exports.metricHorsepower = exports.power.unit("metricHorsepower", 735.49875,
|
|
8
|
+
exports.watt = exports.power.base("watt", { symbol: "W", plural: "watts" });
|
|
9
|
+
exports.horsepower = exports.power.unit("horsepower", 745.699872, { symbol: "hp" });
|
|
10
|
+
exports.metricHorsepower = exports.power.unit("metricHorsepower", 735.49875, { symbol: "PS" });
|
|
11
11
|
/** Every SI-prefixed watt (kilowatt, megawatt, gigawatt, milliwatt, …), keyed by name. */
|
|
12
|
-
exports.metricPower = (0, definePrefixed_1.definePrefixed)(exports.power,
|
|
12
|
+
exports.metricPower = (0, definePrefixed_1.definePrefixed)(exports.power, exports.watt);
|
|
13
13
|
exports.kilowatt = exports.metricPower.kilowatt, exports.megawatt = exports.metricPower.megawatt, exports.gigawatt = exports.metricPower.gigawatt, exports.terawatt = exports.metricPower.terawatt, exports.milliwatt = exports.metricPower.milliwatt;
|
|
@@ -5,14 +5,17 @@ const Dimension_1 = require("../lib/Dimension");
|
|
|
5
5
|
const definePrefixed_1 = require("../utils/definePrefixed");
|
|
6
6
|
/** Pressure. Base unit: pascal. */
|
|
7
7
|
exports.pressure = new Dimension_1.Dimension("pressure");
|
|
8
|
-
exports.pascal = exports.pressure.base("pascal",
|
|
9
|
-
exports.bar = exports.pressure.unit("bar", 1e5,
|
|
10
|
-
exports.millibar = exports.pressure.unit("millibar", 1e2,
|
|
11
|
-
exports.atmosphere = exports.pressure.unit("atmosphere", 101325,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
exports.
|
|
8
|
+
exports.pascal = exports.pressure.base("pascal", { symbol: "Pa", plural: "pascals" });
|
|
9
|
+
exports.bar = exports.pressure.unit("bar", 1e5, { symbol: "bar", plural: "bars" });
|
|
10
|
+
exports.millibar = exports.pressure.unit("millibar", 1e2, { symbol: "mbar", plural: "millibars" });
|
|
11
|
+
exports.atmosphere = exports.pressure.unit("atmosphere", 101325, {
|
|
12
|
+
symbol: "atm",
|
|
13
|
+
plural: "atmospheres",
|
|
14
|
+
});
|
|
15
|
+
exports.torr = exports.pressure.unit("torr", 101325 / 760, { symbol: "Torr", plural: "torrs" });
|
|
16
|
+
exports.psi = exports.pressure.unit("psi", 6894.757293168, { aliases: ["lbf/in²", "lbf/in2"] });
|
|
17
|
+
exports.inchOfMercury = exports.pressure.unit("inchOfMercury", 3386.389, { symbol: "inHg" });
|
|
18
|
+
exports.inchOfWater = exports.pressure.unit("inchOfWater", 249.0889, { symbol: "inAq" });
|
|
16
19
|
/** Every SI-prefixed pascal (kilopascal, hectopascal, megapascal, …), keyed by name. */
|
|
17
|
-
exports.metricPressure = (0, definePrefixed_1.definePrefixed)(exports.pressure,
|
|
20
|
+
exports.metricPressure = (0, definePrefixed_1.definePrefixed)(exports.pressure, exports.pascal);
|
|
18
21
|
exports.kilopascal = exports.metricPressure.kilopascal, exports.hectopascal = exports.metricPressure.hectopascal, exports.megapascal = exports.metricPressure.megapascal, exports.gigapascal = exports.metricPressure.gigapascal;
|
|
@@ -13,6 +13,6 @@ exports.temperature = new Dimension_1.Dimension("temperature");
|
|
|
13
13
|
// rational arithmetic so conversions round-trip without drift.
|
|
14
14
|
const fahrenheitScale = new Rational_1.Rational(5, 9);
|
|
15
15
|
const fahrenheitOffset = Rational_1.Rational.from(273.15).minus(new Rational_1.Rational(32).times(fahrenheitScale));
|
|
16
|
-
exports.kelvin = exports.temperature.base("kelvin",
|
|
17
|
-
exports.celsius = exports.temperature.affine("celsius", { scale: 1, offset: 273.15 },
|
|
18
|
-
exports.fahrenheit = exports.temperature.affine("fahrenheit", { scale: fahrenheitScale, offset: fahrenheitOffset },
|
|
16
|
+
exports.kelvin = exports.temperature.base("kelvin", { symbol: "K" });
|
|
17
|
+
exports.celsius = exports.temperature.affine("celsius", { scale: 1, offset: 273.15 }, { symbol: "°C", aliases: ["C"] });
|
|
18
|
+
exports.fahrenheit = exports.temperature.affine("fahrenheit", { scale: fahrenheitScale, offset: fahrenheitOffset }, { symbol: "°F", aliases: ["F"] });
|
package/dist/dimensions/time.js
CHANGED
|
@@ -5,14 +5,26 @@ const Dimension_1 = require("../lib/Dimension");
|
|
|
5
5
|
const definePrefixed_1 = require("../utils/definePrefixed");
|
|
6
6
|
/** Time / duration. Base unit: second. */
|
|
7
7
|
exports.time = new Dimension_1.Dimension("time");
|
|
8
|
-
exports.second = exports.time.base("second",
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
exports.second = exports.time.base("second", {
|
|
9
|
+
symbol: "s",
|
|
10
|
+
plural: "seconds",
|
|
11
|
+
aliases: ["sec", "secs"],
|
|
12
|
+
});
|
|
13
|
+
exports.minute = exports.time.unit("minute", 60, {
|
|
14
|
+
symbol: "min",
|
|
15
|
+
plural: "minutes",
|
|
16
|
+
aliases: ["mins"],
|
|
17
|
+
});
|
|
18
|
+
exports.hour = exports.time.unit("hour", 3600, {
|
|
19
|
+
symbol: "h",
|
|
20
|
+
plural: "hours",
|
|
21
|
+
aliases: ["hr", "hrs"],
|
|
22
|
+
});
|
|
23
|
+
exports.day = exports.time.unit("day", 86400, { symbol: "d", plural: "days" });
|
|
24
|
+
exports.week = exports.time.unit("week", 604800, { symbol: "wk", plural: "weeks" });
|
|
13
25
|
/**
|
|
14
26
|
* SI-submultiple seconds (millisecond, microsecond, nanosecond, …). Only
|
|
15
27
|
* fractions are generated; larger spans use minute/hour/day/week above.
|
|
16
28
|
*/
|
|
17
|
-
exports.metricTime = (0, definePrefixed_1.definePrefixed)(exports.time,
|
|
29
|
+
exports.metricTime = (0, definePrefixed_1.definePrefixed)(exports.time, exports.second, definePrefixed_1.SI_SUBMULTIPLE_PREFIXES);
|
|
18
30
|
exports.millisecond = exports.metricTime.millisecond, exports.microsecond = exports.metricTime.microsecond, exports.nanosecond = exports.metricTime.nanosecond, exports.picosecond = exports.metricTime.picosecond;
|
|
@@ -5,33 +5,66 @@ const Dimension_1 = require("../lib/Dimension");
|
|
|
5
5
|
const definePrefixed_1 = require("../utils/definePrefixed");
|
|
6
6
|
/** Volume / capacity. Base unit: liter. */
|
|
7
7
|
exports.volume = new Dimension_1.Dimension("volume");
|
|
8
|
-
exports.liter = exports.volume.base("liter",
|
|
8
|
+
exports.liter = exports.volume.base("liter", { symbol: "L", plural: "liters" });
|
|
9
9
|
// US and Imperial liquid measures share names ("gallon", "pint", …) but differ
|
|
10
10
|
// in size, so each is a distinct unit carrying the shared aliases; parsing
|
|
11
11
|
// disambiguates via a preferred measurement system. Imperial has 160 fluid
|
|
12
12
|
// ounces per gallon, US customary has 128.
|
|
13
|
-
exports.usGallon = exports.volume.unit("usGallon", 3.785411784,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
exports.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
exports.usGallon = exports.volume.unit("usGallon", 3.785411784, {
|
|
14
|
+
symbol: "gal",
|
|
15
|
+
plural: "gallons",
|
|
16
|
+
aliases: ["gallon"],
|
|
17
|
+
});
|
|
18
|
+
exports.usQuart = exports.volume.unit("usQuart", 0.946352946, {
|
|
19
|
+
symbol: "qt",
|
|
20
|
+
plural: "quarts",
|
|
21
|
+
aliases: ["quart"],
|
|
22
|
+
});
|
|
23
|
+
exports.usPint = exports.volume.unit("usPint", 0.473176473, {
|
|
24
|
+
symbol: "pt",
|
|
25
|
+
plural: "pints",
|
|
26
|
+
aliases: ["pint"],
|
|
27
|
+
});
|
|
28
|
+
exports.usGill = exports.volume.unit("usGill", 0.11829411825, { plural: "gills", aliases: ["gill"] });
|
|
29
|
+
exports.usFluidOunce = exports.volume.unit("usFluidOunce", 0.0295735295625, {
|
|
30
|
+
symbol: "floz",
|
|
31
|
+
plural: "fluidOunces",
|
|
32
|
+
aliases: ["fluidOunce"],
|
|
33
|
+
});
|
|
34
|
+
exports.imperialGallon = exports.volume.unit("imperialGallon", 4.54609, {
|
|
35
|
+
symbol: "gal",
|
|
36
|
+
plural: "gallons",
|
|
37
|
+
aliases: ["gallon"],
|
|
38
|
+
});
|
|
39
|
+
exports.imperialQuart = exports.volume.unit("imperialQuart", 1.1365225, {
|
|
40
|
+
symbol: "qt",
|
|
41
|
+
plural: "quarts",
|
|
42
|
+
aliases: ["quart"],
|
|
43
|
+
});
|
|
44
|
+
exports.imperialPint = exports.volume.unit("imperialPint", 0.56826125, {
|
|
45
|
+
symbol: "pt",
|
|
46
|
+
plural: "pints",
|
|
47
|
+
aliases: ["pint"],
|
|
48
|
+
});
|
|
49
|
+
exports.imperialGill = exports.volume.unit("imperialGill", 0.1420653125, {
|
|
50
|
+
plural: "gills",
|
|
51
|
+
aliases: ["gill"],
|
|
52
|
+
});
|
|
53
|
+
exports.imperialFluidOunce = exports.volume.unit("imperialFluidOunce", 0.0284130625, {
|
|
54
|
+
symbol: "floz",
|
|
55
|
+
plural: "fluidOunces",
|
|
56
|
+
aliases: ["fluidOunce"],
|
|
57
|
+
});
|
|
31
58
|
// US-only cooking measures (no competing imperial unit, so left unprefixed).
|
|
32
|
-
exports.cup = exports.volume.unit("cup", 0.2365882365,
|
|
33
|
-
exports.tablespoon = exports.volume.unit("tablespoon", 0.01478676478125,
|
|
34
|
-
|
|
59
|
+
exports.cup = exports.volume.unit("cup", 0.2365882365, { plural: "cups" });
|
|
60
|
+
exports.tablespoon = exports.volume.unit("tablespoon", 0.01478676478125, {
|
|
61
|
+
symbol: "tbsp",
|
|
62
|
+
plural: "tablespoons",
|
|
63
|
+
});
|
|
64
|
+
exports.teaspoon = exports.volume.unit("teaspoon", 0.00492892159375, {
|
|
65
|
+
symbol: "tsp",
|
|
66
|
+
plural: "teaspoons",
|
|
67
|
+
});
|
|
35
68
|
/** Every SI-prefixed liter (milliliter, centiliter, kiloliter, …), keyed by name. */
|
|
36
|
-
exports.metricVolume = (0, definePrefixed_1.definePrefixed)(exports.volume,
|
|
69
|
+
exports.metricVolume = (0, definePrefixed_1.definePrefixed)(exports.volume, exports.liter);
|
|
37
70
|
exports.kiloliter = exports.metricVolume.kiloliter, exports.hectoliter = exports.metricVolume.hectoliter, exports.decaliter = exports.metricVolume.decaliter, exports.deciliter = exports.metricVolume.deciliter, exports.centiliter = exports.metricVolume.centiliter, exports.milliliter = exports.metricVolume.milliliter;
|
|
@@ -4,8 +4,7 @@ exports.AmbiguousUnitError = void 0;
|
|
|
4
4
|
class AmbiguousUnitError extends Error {
|
|
5
5
|
constructor(token, candidates) {
|
|
6
6
|
const names = candidates.map((unit) => unit.name).join(", ");
|
|
7
|
-
super(`Ambiguous unit "${token}": matches ${names}.
|
|
8
|
-
`Pass a preferred measurement system to disambiguate.`);
|
|
7
|
+
super(`Ambiguous unit "${token}": matches ${names}. Pass a preferred measurement system to disambiguate.`);
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
10
|
exports.AmbiguousUnitError = AmbiguousUnitError;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when a caller passes an invalid argument — an empty required list, a
|
|
3
|
+
* value outside an allowed range, a wrong numeric type, and so on. Signals a
|
|
4
|
+
* mistake in the calling code rather than a recoverable runtime condition.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ArgumentError extends Error {
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ArgumentError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when a caller passes an invalid argument — an empty required list, a
|
|
6
|
+
* value outside an allowed range, a wrong numeric type, and so on. Signals a
|
|
7
|
+
* mistake in the calling code rather than a recoverable runtime condition.
|
|
8
|
+
*/
|
|
9
|
+
class ArgumentError extends Error {
|
|
10
|
+
}
|
|
11
|
+
exports.ArgumentError = ArgumentError;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Unit } from "../lib/Unit";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when an operation is attempted on two units from different dimensions —
|
|
4
|
+
* converting, comparing, or combining them (e.g. `meter` and `liter`). Such
|
|
5
|
+
* units are dimensionally incompatible, so the operation has no meaning.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DimensionMismatchError extends Error {
|
|
8
|
+
constructor(from: Unit, to: Unit);
|
|
9
|
+
}
|
|
10
|
+
/** @deprecated Renamed to {@link DimensionMismatchError}. */
|
|
11
|
+
export declare const InvalidConversionError: typeof DimensionMismatchError;
|
|
12
|
+
/** @deprecated Renamed to {@link DimensionMismatchError}. */
|
|
13
|
+
export type InvalidConversionError = DimensionMismatchError;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvalidConversionError = exports.DimensionMismatchError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when an operation is attempted on two units from different dimensions —
|
|
6
|
+
* converting, comparing, or combining them (e.g. `meter` and `liter`). Such
|
|
7
|
+
* units are dimensionally incompatible, so the operation has no meaning.
|
|
8
|
+
*/
|
|
9
|
+
class DimensionMismatchError extends Error {
|
|
10
|
+
constructor(from, to) {
|
|
11
|
+
super(`Invalid conversion: ${from.name} to ${to.name}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.DimensionMismatchError = DimensionMismatchError;
|
|
15
|
+
/** @deprecated Renamed to {@link DimensionMismatchError}. */
|
|
16
|
+
exports.InvalidConversionError = DimensionMismatchError;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DuplicateUnitError = void 0;
|
|
4
|
+
/** Thrown when defining a unit whose name already exists in its dimension. */
|
|
5
|
+
class DuplicateUnitError extends Error {
|
|
6
|
+
constructor(name, dimension) {
|
|
7
|
+
super(`Duplicate unit name "${name}" in dimension "${dimension.name}"`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.DuplicateUnitError = DuplicateUnitError;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParseError = void 0;
|
|
4
|
+
/** Thrown when a string can't be parsed into a quantity (no magnitude/unit found). */
|
|
5
|
+
class ParseError extends Error {
|
|
6
|
+
constructor(input) {
|
|
7
|
+
super(`Could not parse a quantity from "${input}"`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ParseError = ParseError;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Dimension } from "../lib/Dimension";
|
|
2
|
+
import type { MeasurementSystem } from "../lib/MeasurementSystem";
|
|
3
|
+
/**
|
|
4
|
+
* Thrown when a measurement system is asked to express a quantity in a dimension
|
|
5
|
+
* for which it has no units (e.g. an imperial-only system and a metric-only
|
|
6
|
+
* dimension).
|
|
7
|
+
*/
|
|
8
|
+
export declare class UnsupportedDimensionError extends Error {
|
|
9
|
+
constructor(system: MeasurementSystem, dimension: Dimension);
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsupportedDimensionError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when a measurement system is asked to express a quantity in a dimension
|
|
6
|
+
* for which it has no units (e.g. an imperial-only system and a metric-only
|
|
7
|
+
* dimension).
|
|
8
|
+
*/
|
|
9
|
+
class UnsupportedDimensionError extends Error {
|
|
10
|
+
constructor(system, dimension) {
|
|
11
|
+
super(`Measurement system "${system.name}" has no "${dimension.name}" units to express in`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.UnsupportedDimensionError = UnsupportedDimensionError;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export * from "./errors/AmbiguousUnitError";
|
|
2
|
-
export * from "./errors/
|
|
2
|
+
export * from "./errors/ArgumentError";
|
|
3
|
+
export * from "./errors/DimensionMismatchError";
|
|
4
|
+
export * from "./errors/DuplicateUnitError";
|
|
5
|
+
export * from "./errors/ParseError";
|
|
3
6
|
export * from "./errors/UnknownUnitError";
|
|
7
|
+
export * from "./errors/UnsupportedDimensionError";
|
|
4
8
|
export * from "./lib/Dimension";
|
|
5
9
|
export * from "./lib/MeasurementSystem";
|
|
6
10
|
export * from "./lib/Quantity";
|
package/dist/index.js
CHANGED
|
@@ -15,8 +15,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./errors/AmbiguousUnitError"), exports);
|
|
18
|
-
__exportStar(require("./errors/
|
|
18
|
+
__exportStar(require("./errors/ArgumentError"), exports);
|
|
19
|
+
__exportStar(require("./errors/DimensionMismatchError"), exports);
|
|
20
|
+
__exportStar(require("./errors/DuplicateUnitError"), exports);
|
|
21
|
+
__exportStar(require("./errors/ParseError"), exports);
|
|
19
22
|
__exportStar(require("./errors/UnknownUnitError"), exports);
|
|
23
|
+
__exportStar(require("./errors/UnsupportedDimensionError"), exports);
|
|
20
24
|
__exportStar(require("./lib/Dimension"), exports);
|
|
21
25
|
__exportStar(require("./lib/MeasurementSystem"), exports);
|
|
22
26
|
__exportStar(require("./lib/Quantity"), exports);
|
package/dist/lib/Dimension.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Rational } from "
|
|
1
|
+
import { Rational } from "./Rational";
|
|
2
2
|
import { Unit } from "./Unit";
|
|
3
3
|
/** A linear unit with an additive offset (e.g. temperature scales). */
|
|
4
4
|
export interface AffineSpec {
|
|
@@ -16,6 +16,15 @@ export interface CustomSpec {
|
|
|
16
16
|
toBase: (value: number) => number;
|
|
17
17
|
fromBase: (value: number) => number;
|
|
18
18
|
}
|
|
19
|
+
/** Optional descriptors for a unit: its symbol, plural, and extra parse aliases. */
|
|
20
|
+
export interface UnitDef {
|
|
21
|
+
/** Canonical symbol, e.g. `"g"`, `"km"`, `"°C"`. Also registered for parsing. */
|
|
22
|
+
symbol?: string;
|
|
23
|
+
/** Plural name, e.g. `"grams"`. Also registered for parsing. */
|
|
24
|
+
plural?: string;
|
|
25
|
+
/** Additional names this unit parses from (beyond name, symbol, and plural). */
|
|
26
|
+
aliases?: string[];
|
|
27
|
+
}
|
|
19
28
|
/**
|
|
20
29
|
* A dimension is a single *kind* of measurable quantity (length, volume, mass,
|
|
21
30
|
* temperature, …). It owns one canonical **base unit** that every other unit in
|
|
@@ -48,15 +57,15 @@ export declare class Dimension {
|
|
|
48
57
|
baseUnit?: Unit;
|
|
49
58
|
constructor(name: string);
|
|
50
59
|
/** Define the canonical base unit (identity transform). */
|
|
51
|
-
base(name: string,
|
|
60
|
+
base(name: string, def?: UnitDef): Unit;
|
|
52
61
|
/**
|
|
53
62
|
* Define a linear unit. `scale` is how many base units make up one of this
|
|
54
63
|
* unit (e.g. a kilometer is `1000` meters). Pass a {@link Rational} for a
|
|
55
64
|
* scale a decimal cannot represent exactly.
|
|
56
65
|
*/
|
|
57
|
-
unit(name: string, scale: number | Rational,
|
|
66
|
+
unit(name: string, scale: number | Rational, def?: UnitDef): Unit;
|
|
58
67
|
/** Define an affine unit (scale plus additive offset, e.g. °C against K). */
|
|
59
|
-
affine(name: string, { scale, offset }: AffineSpec,
|
|
68
|
+
affine(name: string, { scale, offset }: AffineSpec, def?: UnitDef): Unit;
|
|
60
69
|
/**
|
|
61
70
|
* Define a non-linear unit from an arbitrary, hand-written inverse transform
|
|
62
71
|
* pair. Reserve this for units that genuinely cannot be expressed as `value *
|
|
@@ -64,7 +73,7 @@ export declare class Dimension {
|
|
|
64
73
|
* affine units should use {@link unit} / {@link affine} so conversions stay
|
|
65
74
|
* exact.
|
|
66
75
|
*/
|
|
67
|
-
custom(name: string, { toBase, fromBase }: CustomSpec,
|
|
76
|
+
custom(name: string, { toBase, fromBase }: CustomSpec, def?: UnitDef): Unit;
|
|
68
77
|
/** Convert a `number` value between two units of this dimension. */
|
|
69
78
|
convert(value: number, from: Unit, to: Unit): number;
|
|
70
79
|
/**
|
package/dist/lib/Dimension.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Dimension = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const DimensionMismatchError_1 = require("../errors/DimensionMismatchError");
|
|
5
|
+
const DuplicateUnitError_1 = require("../errors/DuplicateUnitError");
|
|
6
|
+
const Rational_1 = require("./Rational");
|
|
6
7
|
const Unit_1 = require("./Unit");
|
|
7
8
|
/** The rational `0`. */
|
|
8
9
|
const zero = new Rational_1.Rational(0n);
|
|
@@ -39,8 +40,8 @@ class Dimension {
|
|
|
39
40
|
this.index = new Map();
|
|
40
41
|
}
|
|
41
42
|
/** Define the canonical base unit (identity transform). */
|
|
42
|
-
base(name,
|
|
43
|
-
const unit = this.defineLinear(name, { scale: one, offset: zero },
|
|
43
|
+
base(name, def = {}) {
|
|
44
|
+
const unit = this.defineLinear(name, { scale: one, offset: zero }, def);
|
|
44
45
|
this.baseUnit = unit;
|
|
45
46
|
return unit;
|
|
46
47
|
}
|
|
@@ -49,12 +50,12 @@ class Dimension {
|
|
|
49
50
|
* unit (e.g. a kilometer is `1000` meters). Pass a {@link Rational} for a
|
|
50
51
|
* scale a decimal cannot represent exactly.
|
|
51
52
|
*/
|
|
52
|
-
unit(name, scale,
|
|
53
|
-
return this.defineLinear(name, { scale: Rational_1.Rational.from(scale), offset: zero },
|
|
53
|
+
unit(name, scale, def = {}) {
|
|
54
|
+
return this.defineLinear(name, { scale: Rational_1.Rational.from(scale), offset: zero }, def);
|
|
54
55
|
}
|
|
55
56
|
/** Define an affine unit (scale plus additive offset, e.g. °C against K). */
|
|
56
|
-
affine(name, { scale, offset },
|
|
57
|
-
return this.defineLinear(name, { scale: Rational_1.Rational.from(scale), offset: Rational_1.Rational.from(offset) },
|
|
57
|
+
affine(name, { scale, offset }, def = {}) {
|
|
58
|
+
return this.defineLinear(name, { scale: Rational_1.Rational.from(scale), offset: Rational_1.Rational.from(offset) }, def);
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
60
61
|
* Define a non-linear unit from an arbitrary, hand-written inverse transform
|
|
@@ -63,8 +64,8 @@ class Dimension {
|
|
|
63
64
|
* affine units should use {@link unit} / {@link affine} so conversions stay
|
|
64
65
|
* exact.
|
|
65
66
|
*/
|
|
66
|
-
custom(name, { toBase, fromBase },
|
|
67
|
-
return this.define(name,
|
|
67
|
+
custom(name, { toBase, fromBase }, def = {}) {
|
|
68
|
+
return this.define(name, def, { toBase, fromBase });
|
|
68
69
|
}
|
|
69
70
|
/** Convert a `number` value between two units of this dimension. */
|
|
70
71
|
convert(value, from, to) {
|
|
@@ -79,7 +80,7 @@ class Dimension {
|
|
|
79
80
|
*/
|
|
80
81
|
convertRational(value, from, to) {
|
|
81
82
|
if (!this.units.has(from) || !this.units.has(to)) {
|
|
82
|
-
throw new
|
|
83
|
+
throw new DimensionMismatchError_1.DimensionMismatchError(from, to);
|
|
83
84
|
}
|
|
84
85
|
if (from === to) {
|
|
85
86
|
return value;
|
|
@@ -99,20 +100,22 @@ class Dimension {
|
|
|
99
100
|
return this.units.has(unit);
|
|
100
101
|
}
|
|
101
102
|
/** Define a linear / affine unit from its exact rational transform. */
|
|
102
|
-
defineLinear(name, linear,
|
|
103
|
-
return this.define(name,
|
|
103
|
+
defineLinear(name, linear, def) {
|
|
104
|
+
return this.define(name, def, { linear });
|
|
104
105
|
}
|
|
105
|
-
define(name, aliases, transform) {
|
|
106
|
+
define(name, { symbol, plural, aliases = [] }, transform) {
|
|
106
107
|
for (const existing of this.units) {
|
|
107
108
|
if (existing.name === name) {
|
|
108
|
-
throw new
|
|
109
|
+
throw new DuplicateUnitError_1.DuplicateUnitError(name, this);
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
|
-
const unit = new Unit_1.Unit({ name, dimension: this, ...transform });
|
|
112
|
+
const unit = new Unit_1.Unit({ name, dimension: this, symbol, plural, ...transform });
|
|
112
113
|
this.units.add(unit);
|
|
113
|
-
this
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
// Register every label this unit can be parsed from, de-duplicated so a unit
|
|
115
|
+
// never appears twice among a token's candidates (e.g. if symbol === name).
|
|
116
|
+
const tokens = new Set([name, symbol, plural, ...aliases].filter((t) => !!t));
|
|
117
|
+
for (const token of tokens) {
|
|
118
|
+
this.register(token, unit);
|
|
116
119
|
}
|
|
117
120
|
return unit;
|
|
118
121
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MeasurementSystem = void 0;
|
|
4
|
-
const
|
|
4
|
+
const UnsupportedDimensionError_1 = require("../errors/UnsupportedDimensionError");
|
|
5
5
|
/**
|
|
6
6
|
* A measurement system (metric, imperial, US customary, …) is a cross-dimension
|
|
7
7
|
* collection of units that share a real-world standard.
|
|
@@ -37,22 +37,11 @@ class MeasurementSystem {
|
|
|
37
37
|
* to the smallest unit when even that rounds below 1).
|
|
38
38
|
*/
|
|
39
39
|
express(quantity) {
|
|
40
|
-
const candidates = this.in(quantity.unit.dimension)
|
|
40
|
+
const candidates = this.in(quantity.unit.dimension);
|
|
41
41
|
if (candidates.length === 0) {
|
|
42
|
-
throw new
|
|
43
|
-
`"${quantity.unit.dimension.name}" units to express in`);
|
|
42
|
+
throw new UnsupportedDimensionError_1.UnsupportedDimensionError(this, quantity.unit.dimension);
|
|
44
43
|
}
|
|
45
|
-
|
|
46
|
-
let chosen = candidates[0];
|
|
47
|
-
for (const unit of candidates) {
|
|
48
|
-
if (Math.abs(unit.fromBase(base)) >= 1) {
|
|
49
|
-
chosen = unit;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return quantity.to(chosen);
|
|
44
|
+
return quantity.best(...candidates);
|
|
56
45
|
}
|
|
57
46
|
}
|
|
58
47
|
exports.MeasurementSystem = MeasurementSystem;
|