@interstellar-tools/temporal 0.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/README.md +18 -0
- package/dist/__tests__/convert-temporal-unit.spec.d.ts +2 -0
- package/dist/__tests__/convert-temporal-unit.spec.d.ts.map +1 -0
- package/dist/__tests__/convert-temporal-unit.spec.js +93 -0
- package/dist/__tests__/convert-temporal-unit.spec.js.map +1 -0
- package/dist/__tests__/normalize-temporal-units.spec.d.ts +2 -0
- package/dist/__tests__/normalize-temporal-units.spec.d.ts.map +1 -0
- package/dist/__tests__/normalize-temporal-units.spec.js +86 -0
- package/dist/__tests__/normalize-temporal-units.spec.js.map +1 -0
- package/dist/convert-temporal-unit.d.ts +67 -0
- package/dist/convert-temporal-unit.d.ts.map +1 -0
- package/dist/convert-temporal-unit.js +96 -0
- package/dist/convert-temporal-unit.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize-temporal-unit.d.ts +116 -0
- package/dist/normalize-temporal-unit.d.ts.map +1 -0
- package/dist/normalize-temporal-unit.js +123 -0
- package/dist/normalize-temporal-unit.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @interstellar-tools/temporal
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
- [Node.js](https://nodejs.org/) version 22.9.0 or higher
|
|
6
|
+
- npm version 11.5.1 or higher
|
|
7
|
+
|
|
8
|
+
::: code-group
|
|
9
|
+
|
|
10
|
+
```shell [npm]
|
|
11
|
+
npm i --save @interstellar-tools/temporal
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```shell [yarn]
|
|
15
|
+
yarn add @interstellar-tools/temporal
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
:::
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-temporal-unit.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/convert-temporal-unit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test, { describe } from 'node:test';
|
|
3
|
+
import { convertTemporalUnit } from '../convert-temporal-unit';
|
|
4
|
+
import { JULIAN_YEAR_SECONDS, SECONDS_PER_DAY } from '@interstellar-tools/constants';
|
|
5
|
+
// Helpers
|
|
6
|
+
const EPS_ABS = 1e-9;
|
|
7
|
+
const EPS_REL = 1e-12;
|
|
8
|
+
const approxEqual = (a, b, msg) => {
|
|
9
|
+
const diff = Math.abs(a - b);
|
|
10
|
+
const scale = Math.max(1, Math.abs(a), Math.abs(b));
|
|
11
|
+
assert.ok(diff <= Math.max(EPS_ABS, EPS_REL * scale), msg ?? `expected ~${b}, got ${a}`);
|
|
12
|
+
};
|
|
13
|
+
const conv = (value, unit, target) => {
|
|
14
|
+
return convertTemporalUnit({ value, unit }, target);
|
|
15
|
+
};
|
|
16
|
+
const CANONICAL = [
|
|
17
|
+
's',
|
|
18
|
+
'ms',
|
|
19
|
+
'μs',
|
|
20
|
+
'ns',
|
|
21
|
+
'ps',
|
|
22
|
+
'fs',
|
|
23
|
+
'as',
|
|
24
|
+
'zs',
|
|
25
|
+
'ys',
|
|
26
|
+
'min',
|
|
27
|
+
'h',
|
|
28
|
+
'd',
|
|
29
|
+
'yr',
|
|
30
|
+
'kyr',
|
|
31
|
+
'Myr',
|
|
32
|
+
'Gyr'
|
|
33
|
+
];
|
|
34
|
+
const roundTo3 = (v) => Math.round(v * 1000) / 1000;
|
|
35
|
+
describe('convert-temporal-unit', () => {
|
|
36
|
+
test('identity: all canonical units map to themselves', () => {
|
|
37
|
+
for (const u of CANONICAL) {
|
|
38
|
+
const out = conv(123.456, u, u);
|
|
39
|
+
assert.equal(out.unit, u);
|
|
40
|
+
assert.equal(roundTo3(out.value), 123.456);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
test('SI submultiples: seconds ↔ ms/μs/ns', () => {
|
|
44
|
+
assert.equal(conv(2, 's', 'ms').value, 2000);
|
|
45
|
+
assert.equal(conv(2, 's', 'μs').value, 2000000);
|
|
46
|
+
approxEqual(conv(2, 's', 'ns').value, 2000000000);
|
|
47
|
+
approxEqual(conv(500, 'ms', 's').value, 0.5);
|
|
48
|
+
approxEqual(conv(250000, 'μs', 's').value, 0.25);
|
|
49
|
+
});
|
|
50
|
+
test('minutes/hours/days basics', () => {
|
|
51
|
+
assert.equal(conv(90, 'min', 'h').value, 1.5);
|
|
52
|
+
assert.equal(conv(2, 'h', 'min').value, 120);
|
|
53
|
+
assert.equal(conv(1, 'd', 'h').value, 24);
|
|
54
|
+
assert.equal(conv(0.5, 'd', 's').value, SECONDS_PER_DAY / 2);
|
|
55
|
+
});
|
|
56
|
+
test('Julian year family: yr ↔ d, kyr/Myr/Gyr scaling', () => {
|
|
57
|
+
// 1 yr = 365.25 d
|
|
58
|
+
approxEqual(conv(1, 'yr', 'd').value, 365.25);
|
|
59
|
+
approxEqual(conv(365.25, 'd', 'yr').value, 1);
|
|
60
|
+
// Scaling
|
|
61
|
+
assert.equal(conv(3, 'Myr', 'kyr').value, 3000);
|
|
62
|
+
assert.equal(conv(2, 'Gyr', 'yr').value, 2000000000);
|
|
63
|
+
// Seconds linkage
|
|
64
|
+
approxEqual(conv(1, 'Myr', 's').value, JULIAN_YEAR_SECONDS * 1e6);
|
|
65
|
+
approxEqual(conv(1e3, 'yr', 's').value, JULIAN_YEAR_SECONDS * 1e3);
|
|
66
|
+
});
|
|
67
|
+
test('extremes: yoctoseconds ↔ seconds round-trip', () => {
|
|
68
|
+
const s = conv(1, 'ys', 's').value;
|
|
69
|
+
approxEqual(s, 1e-24);
|
|
70
|
+
const back = conv(s, 's', 'ys').value;
|
|
71
|
+
approxEqual(back, 1);
|
|
72
|
+
});
|
|
73
|
+
test('round-trip property across units', () => {
|
|
74
|
+
const pairs = [
|
|
75
|
+
['h', 's', 2.75],
|
|
76
|
+
['d', 'min', 0.125],
|
|
77
|
+
['yr', 'd', 3.5],
|
|
78
|
+
['kyr', 'yr', 1.234],
|
|
79
|
+
['Myr', 'kyr', 0.00042],
|
|
80
|
+
['Gyr', 'yr', 0.009]
|
|
81
|
+
];
|
|
82
|
+
for (const [from, mid, val] of pairs) {
|
|
83
|
+
const midVal = conv(val, from, mid).value;
|
|
84
|
+
const back = conv(midVal, mid, from).value;
|
|
85
|
+
approxEqual(back, val, `round-trip failed for ${from}↔${mid}`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
test('unit labels in output are canonical', () => {
|
|
89
|
+
const out = conv(42, 'h', 'min');
|
|
90
|
+
assert.equal(out.unit, 'min');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=convert-temporal-unit.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-temporal-unit.spec.js","sourceRoot":"","sources":["../../src/__tests__/convert-temporal-unit.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-temporal-units.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/normalize-temporal-units.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test, { describe } from 'node:test';
|
|
3
|
+
import { normalizeTemporalUnit } from '../normalize-temporal-unit';
|
|
4
|
+
const canonical = [
|
|
5
|
+
's',
|
|
6
|
+
'ms',
|
|
7
|
+
'μs',
|
|
8
|
+
'ns',
|
|
9
|
+
'ps',
|
|
10
|
+
'fs',
|
|
11
|
+
'as',
|
|
12
|
+
'zs',
|
|
13
|
+
'ys',
|
|
14
|
+
'min',
|
|
15
|
+
'h',
|
|
16
|
+
'd',
|
|
17
|
+
'yr',
|
|
18
|
+
'kyr',
|
|
19
|
+
'Myr',
|
|
20
|
+
'Gyr'
|
|
21
|
+
];
|
|
22
|
+
const aliasPairs = [
|
|
23
|
+
// seconds & submultiples
|
|
24
|
+
['second', 's'],
|
|
25
|
+
['seconds', 's'],
|
|
26
|
+
['millisecond', 'ms'],
|
|
27
|
+
['milliseconds', 'ms'],
|
|
28
|
+
['microsecond', 'μs'],
|
|
29
|
+
['microseconds', 'μs'],
|
|
30
|
+
['us', 'μs'],
|
|
31
|
+
// clock units
|
|
32
|
+
['minute', 'min'],
|
|
33
|
+
['minutes', 'min'],
|
|
34
|
+
['hour', 'h'],
|
|
35
|
+
['hours', 'h'],
|
|
36
|
+
['day', 'd'],
|
|
37
|
+
['days', 'd'],
|
|
38
|
+
// years & multiples (Julian-year-based)
|
|
39
|
+
['year', 'yr'],
|
|
40
|
+
['years', 'yr'],
|
|
41
|
+
['yr', 'yr'],
|
|
42
|
+
['yrs', 'yr'],
|
|
43
|
+
['kiloyear', 'kyr'],
|
|
44
|
+
['kiloyears', 'kyr'],
|
|
45
|
+
['kyr', 'kyr'],
|
|
46
|
+
// million years (geology/astro spellings)
|
|
47
|
+
['megayear', 'Myr'],
|
|
48
|
+
['megayears', 'Myr'],
|
|
49
|
+
['megaannum', 'Myr'],
|
|
50
|
+
['megaannums', 'Myr'],
|
|
51
|
+
['Myr', 'Myr'],
|
|
52
|
+
['Ma', 'Myr'],
|
|
53
|
+
// billion years
|
|
54
|
+
['gigayear', 'Gyr'],
|
|
55
|
+
['gigayears', 'Gyr'],
|
|
56
|
+
['gigaannum', 'Gyr'],
|
|
57
|
+
['gigaannums', 'Gyr'],
|
|
58
|
+
['Gyr', 'Gyr'],
|
|
59
|
+
['Ga', 'Gyr']
|
|
60
|
+
];
|
|
61
|
+
describe('normalizeTemporalUnit', () => {
|
|
62
|
+
test('canonical units map to themselves', () => {
|
|
63
|
+
for (const u of canonical) {
|
|
64
|
+
assert.equal(normalizeTemporalUnit(u), u, `expected '${u}' → '${u}'`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
test('aliases map to canonical symbols', () => {
|
|
68
|
+
for (const [input, expected] of aliasPairs) {
|
|
69
|
+
assert.equal(normalizeTemporalUnit(input), expected, `expected '${input}' → '${expected}'`);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
test('trims surrounding whitespace', () => {
|
|
73
|
+
assert.equal(normalizeTemporalUnit(' seconds '), 's');
|
|
74
|
+
assert.equal(normalizeTemporalUnit('\tus\n'), 'μs');
|
|
75
|
+
});
|
|
76
|
+
test('case-sensitive matching', () => {
|
|
77
|
+
assert.throws(() => normalizeTemporalUnit('Seconds'), /Unsupported unit: Seconds/, 'capitalized alias should be rejected');
|
|
78
|
+
assert.throws(() => normalizeTemporalUnit('US'), /Unsupported unit: US/, 'uppercase "US" should not be treated as microseconds');
|
|
79
|
+
});
|
|
80
|
+
test('rejects unknown or empty inputs', () => {
|
|
81
|
+
assert.throws(() => normalizeTemporalUnit(''), /Unsupported unit:/);
|
|
82
|
+
assert.throws(() => normalizeTemporalUnit(' '), /Unsupported unit:\s+/);
|
|
83
|
+
assert.throws(() => normalizeTemporalUnit('lightyear'), /Unsupported unit:/);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=normalize-temporal-units.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-temporal-units.spec.js","sourceRoot":"","sources":["../../src/__tests__/normalize-temporal-units.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { TemporalInterface, TemporalUnitType } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Seconds-per-unit lookup for all canonical {@link TemporalUnitType} symbols.
|
|
4
|
+
*
|
|
5
|
+
* ### Conventions
|
|
6
|
+
* - **Base**: conversions are performed via **seconds**.
|
|
7
|
+
* - **SI day**: `d = 86 400 s` (from {@link SECONDS_PER_DAY}).
|
|
8
|
+
* - **Julian year**: `yr = 365.25 d = 31 557 600 s`
|
|
9
|
+
* (from {@link JULIAN_YEAR_SECONDS}); `kyr/Myr/Gyr` are powers of 10 thereof.
|
|
10
|
+
* - Units are **canonical** and **case-sensitive** (e.g., `'μs'` uses the Unicode micro sign).
|
|
11
|
+
*
|
|
12
|
+
* $$
|
|
13
|
+
* \text{seconds}(u) \;=\; \text{value}\times \mathrm{SECONDS\_PER}[u]
|
|
14
|
+
* $$
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // seconds per hour:
|
|
19
|
+
* SECONDS_PER.h; // 3600
|
|
20
|
+
*
|
|
21
|
+
* // seconds in a Julian year:
|
|
22
|
+
* SECONDS_PER.yr; // 31_557_600
|
|
23
|
+
* ```
|
|
24
|
+
* @hidden
|
|
25
|
+
*/
|
|
26
|
+
export declare const SECONDS_PER: Record<TemporalUnitType, number>;
|
|
27
|
+
/**
|
|
28
|
+
* Convert a temporal **duration** between any two canonical {@link TemporalUnitType} units.
|
|
29
|
+
*
|
|
30
|
+
* - Uses {@link SECONDS_PER} with **seconds** as the intermediate unit.
|
|
31
|
+
* - Interprets `d` as the **SI day** and `yr/kyr/Myr/Gyr` via the **Julian year** convention.
|
|
32
|
+
* - The `time.unit` is expected to be **canonical**; if you accept aliases upstream,
|
|
33
|
+
* normalize them before calling (e.g., with `normalizeTemporalUnit`).
|
|
34
|
+
* - The `targetUnit` is normalized to a canonical symbol (idempotent for canonical input).
|
|
35
|
+
*
|
|
36
|
+
* $$
|
|
37
|
+
* \text{value}_{\text{target}}
|
|
38
|
+
* \;=\;
|
|
39
|
+
* \frac{\text{value}_{\text{in}} \cdot \mathrm{SECONDS\_PER}[u_{\text{in}}]}
|
|
40
|
+
* {\mathrm{SECONDS\_PER}[u_{\text{out}}]}
|
|
41
|
+
* $$
|
|
42
|
+
*
|
|
43
|
+
* @param time Input duration `{ value, unit }` in canonical units.
|
|
44
|
+
* @param targetUnit Desired canonical output unit (will be normalized).
|
|
45
|
+
* @returns A new `{ value, unit }` where `unit` is the canonical target symbol.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* convertTemporalUnit({ value: 2, unit: 'h' }, 'min');
|
|
50
|
+
* // → { value: 120, unit: 'min' }
|
|
51
|
+
*
|
|
52
|
+
* convertTemporalUnit({ value: 1, unit: 'd' }, 's');
|
|
53
|
+
* // → { value: 86_400, unit: 's' }
|
|
54
|
+
*
|
|
55
|
+
* convertTemporalUnit({ value: 3, unit: 'Myr' }, 'kyr');
|
|
56
|
+
* // → { value: 3000, unit: 'kyr' }
|
|
57
|
+
*
|
|
58
|
+
* convertTemporalUnit({ value: 1, unit: 'yr' }, 'd');
|
|
59
|
+
* // → { value: 365.25, unit: 'd' }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @see SECONDS_PER_DAY
|
|
63
|
+
* @see JULIAN_YEAR_SECONDS
|
|
64
|
+
* @see normalizeTemporalUnit
|
|
65
|
+
*/
|
|
66
|
+
export declare const convertTemporalUnit: (time: TemporalInterface, targetUnit: TemporalUnitType) => TemporalInterface;
|
|
67
|
+
//# sourceMappingURL=convert-temporal-unit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-temporal-unit.d.ts","sourceRoot":"","sources":["../src/convert-temporal-unit.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAIhF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAsBxD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,iBAAiB,EACvB,YAAY,gBAAgB,KAC3B,iBASF,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { JULIAN_YEAR_SECONDS, SECONDS_PER_DAY } from '@interstellar-tools/constants';
|
|
2
|
+
import { normalizeTemporalUnit } from './normalize-temporal-unit';
|
|
3
|
+
/**
|
|
4
|
+
* Seconds-per-unit lookup for all canonical {@link TemporalUnitType} symbols.
|
|
5
|
+
*
|
|
6
|
+
* ### Conventions
|
|
7
|
+
* - **Base**: conversions are performed via **seconds**.
|
|
8
|
+
* - **SI day**: `d = 86 400 s` (from {@link SECONDS_PER_DAY}).
|
|
9
|
+
* - **Julian year**: `yr = 365.25 d = 31 557 600 s`
|
|
10
|
+
* (from {@link JULIAN_YEAR_SECONDS}); `kyr/Myr/Gyr` are powers of 10 thereof.
|
|
11
|
+
* - Units are **canonical** and **case-sensitive** (e.g., `'μs'` uses the Unicode micro sign).
|
|
12
|
+
*
|
|
13
|
+
* $$
|
|
14
|
+
* \text{seconds}(u) \;=\; \text{value}\times \mathrm{SECONDS\_PER}[u]
|
|
15
|
+
* $$
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // seconds per hour:
|
|
20
|
+
* SECONDS_PER.h; // 3600
|
|
21
|
+
*
|
|
22
|
+
* // seconds in a Julian year:
|
|
23
|
+
* SECONDS_PER.yr; // 31_557_600
|
|
24
|
+
* ```
|
|
25
|
+
* @hidden
|
|
26
|
+
*/
|
|
27
|
+
export const SECONDS_PER = {
|
|
28
|
+
// SI base & submultiples
|
|
29
|
+
s: 1,
|
|
30
|
+
ms: 1e-3,
|
|
31
|
+
μs: 1e-6,
|
|
32
|
+
ns: 1e-9,
|
|
33
|
+
ps: 1e-12,
|
|
34
|
+
fs: 1e-15,
|
|
35
|
+
as: 1e-18,
|
|
36
|
+
zs: 1e-21,
|
|
37
|
+
ys: 1e-24,
|
|
38
|
+
// convenient larger units
|
|
39
|
+
min: 60,
|
|
40
|
+
h: 60 * 60,
|
|
41
|
+
d: SECONDS_PER_DAY,
|
|
42
|
+
// year family (Julian-year-based)
|
|
43
|
+
yr: JULIAN_YEAR_SECONDS,
|
|
44
|
+
kyr: JULIAN_YEAR_SECONDS * 1e3,
|
|
45
|
+
Myr: JULIAN_YEAR_SECONDS * 1e6,
|
|
46
|
+
Gyr: JULIAN_YEAR_SECONDS * 1e9
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Convert a temporal **duration** between any two canonical {@link TemporalUnitType} units.
|
|
50
|
+
*
|
|
51
|
+
* - Uses {@link SECONDS_PER} with **seconds** as the intermediate unit.
|
|
52
|
+
* - Interprets `d` as the **SI day** and `yr/kyr/Myr/Gyr` via the **Julian year** convention.
|
|
53
|
+
* - The `time.unit` is expected to be **canonical**; if you accept aliases upstream,
|
|
54
|
+
* normalize them before calling (e.g., with `normalizeTemporalUnit`).
|
|
55
|
+
* - The `targetUnit` is normalized to a canonical symbol (idempotent for canonical input).
|
|
56
|
+
*
|
|
57
|
+
* $$
|
|
58
|
+
* \text{value}_{\text{target}}
|
|
59
|
+
* \;=\;
|
|
60
|
+
* \frac{\text{value}_{\text{in}} \cdot \mathrm{SECONDS\_PER}[u_{\text{in}}]}
|
|
61
|
+
* {\mathrm{SECONDS\_PER}[u_{\text{out}}]}
|
|
62
|
+
* $$
|
|
63
|
+
*
|
|
64
|
+
* @param time Input duration `{ value, unit }` in canonical units.
|
|
65
|
+
* @param targetUnit Desired canonical output unit (will be normalized).
|
|
66
|
+
* @returns A new `{ value, unit }` where `unit` is the canonical target symbol.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* convertTemporalUnit({ value: 2, unit: 'h' }, 'min');
|
|
71
|
+
* // → { value: 120, unit: 'min' }
|
|
72
|
+
*
|
|
73
|
+
* convertTemporalUnit({ value: 1, unit: 'd' }, 's');
|
|
74
|
+
* // → { value: 86_400, unit: 's' }
|
|
75
|
+
*
|
|
76
|
+
* convertTemporalUnit({ value: 3, unit: 'Myr' }, 'kyr');
|
|
77
|
+
* // → { value: 3000, unit: 'kyr' }
|
|
78
|
+
*
|
|
79
|
+
* convertTemporalUnit({ value: 1, unit: 'yr' }, 'd');
|
|
80
|
+
* // → { value: 365.25, unit: 'd' }
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @see SECONDS_PER_DAY
|
|
84
|
+
* @see JULIAN_YEAR_SECONDS
|
|
85
|
+
* @see normalizeTemporalUnit
|
|
86
|
+
*/
|
|
87
|
+
export const convertTemporalUnit = (time, targetUnit) => {
|
|
88
|
+
const normalizedTargetUnit = normalizeTemporalUnit(targetUnit);
|
|
89
|
+
const { value, unit } = time;
|
|
90
|
+
// Convert input to seconds
|
|
91
|
+
const inSeconds = value * SECONDS_PER[unit];
|
|
92
|
+
// Convert seconds to target
|
|
93
|
+
const convertedValue = inSeconds / SECONDS_PER[normalizedTargetUnit];
|
|
94
|
+
return { value: convertedValue, unit: normalizedTargetUnit };
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=convert-temporal-unit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-temporal-unit.js","sourceRoot":"","sources":["../src/convert-temporal-unit.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,eAAe,EAChB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,yBAAyB;IACzB,CAAC,EAAE,CAAC;IACJ,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;IACT,EAAE,EAAE,KAAK;IAET,0BAA0B;IAC1B,GAAG,EAAE,EAAE;IACP,CAAC,EAAE,EAAE,GAAG,EAAE;IACV,CAAC,EAAE,eAAe;IAElB,kCAAkC;IAClC,EAAE,EAAE,mBAAmB;IACvB,GAAG,EAAE,mBAAmB,GAAG,GAAG;IAC9B,GAAG,EAAE,mBAAmB,GAAG,GAAG;IAC9B,GAAG,EAAE,mBAAmB,GAAG,GAAG;CAC/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,IAAuB,EACvB,UAA4B,EACT,EAAE;IACrB,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC/D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAC7B,2BAA2B;IAC3B,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5C,4BAA4B;IAC5B,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,CAAC,oBAAoB,CAAC,CAAC;IAErE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;AAC/D,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AAExC,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AAExC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { TemporalUnitType } from '@interstellar-tools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Lookup table that **normalizes user-facing time unit aliases** (and the canonical
|
|
4
|
+
* symbols themselves) to a single, canonical {@link TemporalUnitType}.
|
|
5
|
+
*
|
|
6
|
+
* ## Purpose
|
|
7
|
+
* - Centralizes all **string → symbol** normalization (e.g., `"seconds"` → `"s"`, `"us"` → `"μs"`).
|
|
8
|
+
* - Ensures downstream math uses only **canonical units** (`s`, `ms`, `μs`, `min`, `h`, `d`, `yr`, `kyr`, `Myr`, `Gyr`).
|
|
9
|
+
*
|
|
10
|
+
* ## Conventions & semantics
|
|
11
|
+
* - **Durations only** (no timestamp/"ago" meaning). Geology-style tokens (`Ma`, `Ga`, `megaannum`, `gigaannum`)
|
|
12
|
+
* are treated as **durations** and normalized to `Myr`/`Gyr`.
|
|
13
|
+
* - **Day** is [SI](https://en.wikipedia.org/wiki/International_System_of_Units) day: exactly **86 400 s**.
|
|
14
|
+
* - **Year family** (`yr`, `kyr`, `Myr`, `Gyr`) is the **Julian year** convention: **365.25 d = 31 557 600 s**.
|
|
15
|
+
* - **Case-sensitive** and exact matching. The ASCII alias `"us"` is accepted and normalized to the Unicode `μs`.
|
|
16
|
+
*
|
|
17
|
+
* ## Usage pattern
|
|
18
|
+
* - Accept `TemporalUnitAliasType | TemporalUnitType` at your boundaries.
|
|
19
|
+
* - Normalize with this map.
|
|
20
|
+
* - Store/compute exclusively with canonical {@link TemporalUnitType}.
|
|
21
|
+
*
|
|
22
|
+
* ::: tip
|
|
23
|
+
*
|
|
24
|
+
* If you require runtime immutability, wrap with `Object.freeze(NORMALIZE_UNIT)`.
|
|
25
|
+
*
|
|
26
|
+
* :::
|
|
27
|
+
*
|
|
28
|
+
* @see https://www.bipm.org/en/publications/si-brochure ([SI](https://en.wikipedia.org/wiki/International_System_of_Units) Brochure — second & day)
|
|
29
|
+
* @see https://en.wikipedia.org/wiki/Julian_year_(astronomy) (Julian year for yr/kyr/Myr/Gyr)
|
|
30
|
+
*/
|
|
31
|
+
export declare const NORMALIZE_UNIT: {
|
|
32
|
+
readonly s: "s";
|
|
33
|
+
readonly ms: "ms";
|
|
34
|
+
readonly μs: "μs";
|
|
35
|
+
readonly ns: "ns";
|
|
36
|
+
readonly ps: "ps";
|
|
37
|
+
readonly fs: "fs";
|
|
38
|
+
readonly as: "as";
|
|
39
|
+
readonly zs: "zs";
|
|
40
|
+
readonly ys: "ys";
|
|
41
|
+
readonly min: "min";
|
|
42
|
+
readonly h: "h";
|
|
43
|
+
readonly d: "d";
|
|
44
|
+
readonly yr: "yr";
|
|
45
|
+
readonly kyr: "kyr";
|
|
46
|
+
readonly Myr: "Myr";
|
|
47
|
+
readonly Gyr: "Gyr";
|
|
48
|
+
readonly second: "s";
|
|
49
|
+
readonly seconds: "s";
|
|
50
|
+
readonly millisecond: "ms";
|
|
51
|
+
readonly milliseconds: "ms";
|
|
52
|
+
readonly microsecond: "μs";
|
|
53
|
+
readonly microseconds: "μs";
|
|
54
|
+
readonly us: "μs";
|
|
55
|
+
readonly minute: "min";
|
|
56
|
+
readonly minutes: "min";
|
|
57
|
+
readonly hour: "h";
|
|
58
|
+
readonly hours: "h";
|
|
59
|
+
readonly day: "d";
|
|
60
|
+
readonly days: "d";
|
|
61
|
+
readonly year: "yr";
|
|
62
|
+
readonly years: "yr";
|
|
63
|
+
readonly yrs: "yr";
|
|
64
|
+
readonly kiloyear: "kyr";
|
|
65
|
+
readonly kiloyears: "kyr";
|
|
66
|
+
readonly megayear: "Myr";
|
|
67
|
+
readonly megayears: "Myr";
|
|
68
|
+
readonly megaannum: "Myr";
|
|
69
|
+
readonly megaannums: "Myr";
|
|
70
|
+
readonly Ma: "Myr";
|
|
71
|
+
readonly gigayear: "Gyr";
|
|
72
|
+
readonly gigayears: "Gyr";
|
|
73
|
+
readonly gigaannum: "Gyr";
|
|
74
|
+
readonly gigaannums: "Gyr";
|
|
75
|
+
readonly Ga: "Gyr";
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Normalize a user-provided **temporal unit string** into a canonical {@link TemporalUnitType}.
|
|
79
|
+
*
|
|
80
|
+
* - Trims surrounding whitespace.
|
|
81
|
+
* - Accepts both **canonical symbols** (e.g., `"s"`, `"ms"`, `"μs"`, `"min"`, `"h"`, `"d"`, `"yr"`, `"kyr"`, `"Myr"`, `"Gyr"`)
|
|
82
|
+
* and **aliases** (e.g., `"seconds"`, `"milliseconds"`, `"us"`, `"hours"`, `"years"`, `"Ma"`, `"Ga"`),
|
|
83
|
+
* using {@link NORMALIZE_UNIT} as the single source of truth.
|
|
84
|
+
* - Returns a **canonical** unit suitable for arithmetic, storage, and serialization.
|
|
85
|
+
*
|
|
86
|
+
* ### Conventions
|
|
87
|
+
* - **Durations only** (no timestamp or "ago" semantics). Geology-style tokens like `"Ma"`/`"Ga"` are
|
|
88
|
+
* interpreted as durations and normalized to `"Myr"`/`"Gyr"`.
|
|
89
|
+
* - **Case-sensitive** exact match against {@link NORMALIZE_UNIT}. For example, `"Seconds"` (capital S)
|
|
90
|
+
* will fail; use `"seconds"` instead, or pre-normalize casing upstream if desired.
|
|
91
|
+
* - The ASCII alias `"us"` is accepted and normalized to the Unicode microsecond symbol `"μs"`.
|
|
92
|
+
*
|
|
93
|
+
* @param u - The input unit string. Leading/trailing whitespace is ignored; content is **case-sensitive**.
|
|
94
|
+
* @returns The canonical {@link TemporalUnitType} (e.g., `"s"`, `"ms"`, `"μs"`, `"min"`, `"h"`, `"d"`, `"yr"`, `"kyr"`, `"Myr"`, `"Gyr"`).
|
|
95
|
+
*
|
|
96
|
+
* @throws {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError | RangeError} If `u` does not match any known key in {@link NORMALIZE_UNIT}.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* // Canonical conversion using the normalized unit:
|
|
101
|
+
* const unit = normalizeTemporalUnit(' seconds '); // → 's'
|
|
102
|
+
* const valueInSeconds = 2 * (unit === 's' ? 1 : NaN); // 2
|
|
103
|
+
*
|
|
104
|
+
* normalizeTemporalUnit('us'); // → 'μs'
|
|
105
|
+
* normalizeTemporalUnit('Myr'); // → 'Myr' (already canonical)
|
|
106
|
+
* normalizeTemporalUnit('Ma'); // → 'Myr' (geology-style alias)
|
|
107
|
+
* normalizeTemporalUnit('Ga'); // → 'Gyr'
|
|
108
|
+
* // normalizeTemporalUnit('Seconds'); // throws (case-sensitive)
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @see {@link NORMALIZE_UNIT} for the complete alias→canonical mapping.
|
|
112
|
+
* @see https://www.bipm.org/en/publications/si-brochure (SI Brochure — second/day)
|
|
113
|
+
* @see https://en.wikipedia.org/wiki/Julian_year_(astronomy) (Julian year for yr/kyr/Myr/Gyr)
|
|
114
|
+
*/
|
|
115
|
+
export declare const normalizeTemporalUnit: (u: string) => TemporalUnitType;
|
|
116
|
+
//# sourceMappingURL=normalize-temporal-unit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-temporal-unit.d.ts","sourceRoot":"","sources":["../src/normalize-temporal-unit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,qBAAqB,GAAI,GAAG,MAAM,KAAG,gBAOjD,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lookup table that **normalizes user-facing time unit aliases** (and the canonical
|
|
3
|
+
* symbols themselves) to a single, canonical {@link TemporalUnitType}.
|
|
4
|
+
*
|
|
5
|
+
* ## Purpose
|
|
6
|
+
* - Centralizes all **string → symbol** normalization (e.g., `"seconds"` → `"s"`, `"us"` → `"μs"`).
|
|
7
|
+
* - Ensures downstream math uses only **canonical units** (`s`, `ms`, `μs`, `min`, `h`, `d`, `yr`, `kyr`, `Myr`, `Gyr`).
|
|
8
|
+
*
|
|
9
|
+
* ## Conventions & semantics
|
|
10
|
+
* - **Durations only** (no timestamp/"ago" meaning). Geology-style tokens (`Ma`, `Ga`, `megaannum`, `gigaannum`)
|
|
11
|
+
* are treated as **durations** and normalized to `Myr`/`Gyr`.
|
|
12
|
+
* - **Day** is [SI](https://en.wikipedia.org/wiki/International_System_of_Units) day: exactly **86 400 s**.
|
|
13
|
+
* - **Year family** (`yr`, `kyr`, `Myr`, `Gyr`) is the **Julian year** convention: **365.25 d = 31 557 600 s**.
|
|
14
|
+
* - **Case-sensitive** and exact matching. The ASCII alias `"us"` is accepted and normalized to the Unicode `μs`.
|
|
15
|
+
*
|
|
16
|
+
* ## Usage pattern
|
|
17
|
+
* - Accept `TemporalUnitAliasType | TemporalUnitType` at your boundaries.
|
|
18
|
+
* - Normalize with this map.
|
|
19
|
+
* - Store/compute exclusively with canonical {@link TemporalUnitType}.
|
|
20
|
+
*
|
|
21
|
+
* ::: tip
|
|
22
|
+
*
|
|
23
|
+
* If you require runtime immutability, wrap with `Object.freeze(NORMALIZE_UNIT)`.
|
|
24
|
+
*
|
|
25
|
+
* :::
|
|
26
|
+
*
|
|
27
|
+
* @see https://www.bipm.org/en/publications/si-brochure ([SI](https://en.wikipedia.org/wiki/International_System_of_Units) Brochure — second & day)
|
|
28
|
+
* @see https://en.wikipedia.org/wiki/Julian_year_(astronomy) (Julian year for yr/kyr/Myr/Gyr)
|
|
29
|
+
*/
|
|
30
|
+
export const NORMALIZE_UNIT = {
|
|
31
|
+
// canonical already map to themselves:
|
|
32
|
+
s: 's',
|
|
33
|
+
ms: 'ms',
|
|
34
|
+
μs: 'μs',
|
|
35
|
+
ns: 'ns',
|
|
36
|
+
ps: 'ps',
|
|
37
|
+
fs: 'fs',
|
|
38
|
+
as: 'as',
|
|
39
|
+
zs: 'zs',
|
|
40
|
+
ys: 'ys',
|
|
41
|
+
min: 'min',
|
|
42
|
+
h: 'h',
|
|
43
|
+
d: 'd',
|
|
44
|
+
yr: 'yr',
|
|
45
|
+
kyr: 'kyr',
|
|
46
|
+
Myr: 'Myr',
|
|
47
|
+
Gyr: 'Gyr',
|
|
48
|
+
// aliases → canonical
|
|
49
|
+
second: 's',
|
|
50
|
+
seconds: 's',
|
|
51
|
+
millisecond: 'ms',
|
|
52
|
+
milliseconds: 'ms',
|
|
53
|
+
microsecond: 'μs',
|
|
54
|
+
microseconds: 'μs',
|
|
55
|
+
us: 'μs',
|
|
56
|
+
minute: 'min',
|
|
57
|
+
minutes: 'min',
|
|
58
|
+
hour: 'h',
|
|
59
|
+
hours: 'h',
|
|
60
|
+
day: 'd',
|
|
61
|
+
days: 'd',
|
|
62
|
+
year: 'yr',
|
|
63
|
+
years: 'yr',
|
|
64
|
+
yrs: 'yr',
|
|
65
|
+
kiloyear: 'kyr',
|
|
66
|
+
kiloyears: 'kyr',
|
|
67
|
+
megayear: 'Myr',
|
|
68
|
+
megayears: 'Myr',
|
|
69
|
+
megaannum: 'Myr',
|
|
70
|
+
megaannums: 'Myr',
|
|
71
|
+
Ma: 'Myr',
|
|
72
|
+
gigayear: 'Gyr',
|
|
73
|
+
gigayears: 'Gyr',
|
|
74
|
+
gigaannum: 'Gyr',
|
|
75
|
+
gigaannums: 'Gyr',
|
|
76
|
+
Ga: 'Gyr'
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Normalize a user-provided **temporal unit string** into a canonical {@link TemporalUnitType}.
|
|
80
|
+
*
|
|
81
|
+
* - Trims surrounding whitespace.
|
|
82
|
+
* - Accepts both **canonical symbols** (e.g., `"s"`, `"ms"`, `"μs"`, `"min"`, `"h"`, `"d"`, `"yr"`, `"kyr"`, `"Myr"`, `"Gyr"`)
|
|
83
|
+
* and **aliases** (e.g., `"seconds"`, `"milliseconds"`, `"us"`, `"hours"`, `"years"`, `"Ma"`, `"Ga"`),
|
|
84
|
+
* using {@link NORMALIZE_UNIT} as the single source of truth.
|
|
85
|
+
* - Returns a **canonical** unit suitable for arithmetic, storage, and serialization.
|
|
86
|
+
*
|
|
87
|
+
* ### Conventions
|
|
88
|
+
* - **Durations only** (no timestamp or "ago" semantics). Geology-style tokens like `"Ma"`/`"Ga"` are
|
|
89
|
+
* interpreted as durations and normalized to `"Myr"`/`"Gyr"`.
|
|
90
|
+
* - **Case-sensitive** exact match against {@link NORMALIZE_UNIT}. For example, `"Seconds"` (capital S)
|
|
91
|
+
* will fail; use `"seconds"` instead, or pre-normalize casing upstream if desired.
|
|
92
|
+
* - The ASCII alias `"us"` is accepted and normalized to the Unicode microsecond symbol `"μs"`.
|
|
93
|
+
*
|
|
94
|
+
* @param u - The input unit string. Leading/trailing whitespace is ignored; content is **case-sensitive**.
|
|
95
|
+
* @returns The canonical {@link TemporalUnitType} (e.g., `"s"`, `"ms"`, `"μs"`, `"min"`, `"h"`, `"d"`, `"yr"`, `"kyr"`, `"Myr"`, `"Gyr"`).
|
|
96
|
+
*
|
|
97
|
+
* @throws {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError | RangeError} If `u` does not match any known key in {@link NORMALIZE_UNIT}.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* // Canonical conversion using the normalized unit:
|
|
102
|
+
* const unit = normalizeTemporalUnit(' seconds '); // → 's'
|
|
103
|
+
* const valueInSeconds = 2 * (unit === 's' ? 1 : NaN); // 2
|
|
104
|
+
*
|
|
105
|
+
* normalizeTemporalUnit('us'); // → 'μs'
|
|
106
|
+
* normalizeTemporalUnit('Myr'); // → 'Myr' (already canonical)
|
|
107
|
+
* normalizeTemporalUnit('Ma'); // → 'Myr' (geology-style alias)
|
|
108
|
+
* normalizeTemporalUnit('Ga'); // → 'Gyr'
|
|
109
|
+
* // normalizeTemporalUnit('Seconds'); // throws (case-sensitive)
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @see {@link NORMALIZE_UNIT} for the complete alias→canonical mapping.
|
|
113
|
+
* @see https://www.bipm.org/en/publications/si-brochure (SI Brochure — second/day)
|
|
114
|
+
* @see https://en.wikipedia.org/wiki/Julian_year_(astronomy) (Julian year for yr/kyr/Myr/Gyr)
|
|
115
|
+
*/
|
|
116
|
+
export const normalizeTemporalUnit = (u) => {
|
|
117
|
+
const k = u.trim();
|
|
118
|
+
const v = NORMALIZE_UNIT[k];
|
|
119
|
+
if (!v)
|
|
120
|
+
throw new Error(`Unsupported unit: ${u}`);
|
|
121
|
+
return v;
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=normalize-temporal-unit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-temporal-unit.js","sourceRoot":"","sources":["../src/normalize-temporal-unit.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,uCAAuC;IACvC,CAAC,EAAE,GAAG;IACN,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,CAAC,EAAE,GAAG;IACN,CAAC,EAAE,GAAG;IACN,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IAEV,sBAAsB;IACtB,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,EAAE,EAAE,IAAI;IACR,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IAET,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,KAAK;IAChB,UAAU,EAAE,KAAK;IACjB,EAAE,EAAE,KAAK;IACT,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,KAAK;IAChB,UAAU,EAAE,KAAK;IACjB,EAAE,EAAE,KAAK;CAIV,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAS,EAAoB,EAAE;IACnE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnB,MAAM,CAAC,GAAG,cAAc,CAAC,CAAgC,CAAC,CAAC;IAE3D,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAElD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@interstellar-tools/temporal",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "temporal",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"temporal"
|
|
7
|
+
],
|
|
8
|
+
"homepage": "https://phun-ky.net/projects/interstellar-tools",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/phun-ky/interstellar-tools/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/phun-ky/interstellar-tools.git"
|
|
15
|
+
},
|
|
16
|
+
"funding": "https://github.com/phun-ky/interstellar-tools?sponsor=1",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Alexander Vassbotn Røyne-Helgesen <alexander@phun-ky.net>",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"scripts": {
|
|
33
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
34
|
+
"release": "release-it",
|
|
35
|
+
"test": "tsx --test **/__tests__/**/*.spec.ts",
|
|
36
|
+
"pretest:ci": "rm -rf coverage && mkdir -p coverage",
|
|
37
|
+
"test:ci": "glob -c \"node --import tsx --test --no-warnings --experimental-test-coverage --test-reporter=cobertura --test-reporter-destination=coverage/cobertura-coverage.xml --test-reporter=spec --test-reporter-destination=stdout\" \"**/__tests__/**/*.spec.ts\""
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@interstellar-tools/types": "^0.1.0",
|
|
41
|
+
"@interstellar-tools/constants": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^24.0.3",
|
|
45
|
+
"eslint": "^9.27.0",
|
|
46
|
+
"eslint-config-phun-ky": "^1.0.3",
|
|
47
|
+
"prettier": "^3.5.3",
|
|
48
|
+
"typescript": "^5.8.3"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=22.9.0",
|
|
52
|
+
"npm": ">=11.5.1"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|