unacy 0.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/LICENSE +21 -0
- package/README.md +232 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +115 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-present Pradeep Mouli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# @unacy/core
|
|
2
|
+
|
|
3
|
+
Type-safe unit and format conversion library with automatic multi-hop composition.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 **Type-safe conversions** - Compile-time checks prevent mixing incompatible units
|
|
8
|
+
- 🔄 **Auto-composition** - Automatically chains converters (A→B→C for A→C)
|
|
9
|
+
- 🚀 **Zero runtime overhead** - Phantom types have no performance cost
|
|
10
|
+
- 🎯 **Shortest path** - BFS finds optimal conversion routes
|
|
11
|
+
- 🛡️ **Cycle detection** - Prevents infinite conversion loops
|
|
12
|
+
- 📦 **Tree-shakeable** - Only bundle converters you use
|
|
13
|
+
- ✨ **Fluent API** - Clean, readable conversion syntax
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @unacy/core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createRegistry, type WithUnits } from '@unacy/core';
|
|
25
|
+
|
|
26
|
+
// Define your unit types
|
|
27
|
+
type Celsius = WithUnits<number, 'Celsius'>;
|
|
28
|
+
type Fahrenheit = WithUnits<number, 'Fahrenheit'>;
|
|
29
|
+
|
|
30
|
+
// Create a registry
|
|
31
|
+
const tempRegistry = createRegistry()
|
|
32
|
+
.register('Celsius', 'Fahrenheit', (c) => ((c * 9/5) + 32) as Fahrenheit);
|
|
33
|
+
|
|
34
|
+
// Convert with type safety - two ways:
|
|
35
|
+
const temp: Celsius = 25 as Celsius;
|
|
36
|
+
|
|
37
|
+
// Method 1: unit accessor API
|
|
38
|
+
const fahrenheit2 = tempRegistry.Celsius.to.Fahrenheit(temp as Celsius) satisfies Fahrenheit;
|
|
39
|
+
|
|
40
|
+
console.log(fahrenheit2); // 77
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage Examples
|
|
44
|
+
|
|
45
|
+
### Basic Unit Conversions
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Same registry as above
|
|
49
|
+
const distance: Meters = 10 as Meters;
|
|
50
|
+
|
|
51
|
+
// Access units directly via property syntax
|
|
52
|
+
const feet = distanceRegistry.meters.to.feet(distance);
|
|
53
|
+
console.log(feet); // 32.8084
|
|
54
|
+
|
|
55
|
+
// Works in both directions
|
|
56
|
+
const meters = distanceRegistry.feet.to.meters(32.8084 as Feet) satisfies Meters;
|
|
57
|
+
console.log(meters); // 10
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Bidirectional Converters
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { createRegistry, type WithUnits } from '@unacy/core';
|
|
64
|
+
|
|
65
|
+
type Meters = WithUnits<number, 'meters'>;
|
|
66
|
+
type Kilometers = WithUnits<number, 'kilometers'>;
|
|
67
|
+
|
|
68
|
+
const registry = createRegistry<'meters' | 'kilometers'>()
|
|
69
|
+
.registerBidirectional('meters', 'kilometers', {
|
|
70
|
+
to: (m) => (m / 1000) as Kilometers,
|
|
71
|
+
from: (km) => (km * 1000) as Meters
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Both directions work automatically
|
|
75
|
+
const km = registry.convert(5000 as Meters, 'meters').to('kilometers'); // 5
|
|
76
|
+
const m = registry.convert(5 as Kilometers, 'kilometers').to('meters'); // 5000
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Multi-Hop Auto-Composition
|
|
80
|
+
|
|
81
|
+
The registry automatically composes converters via shortest path:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
type Meters = WithUnits<number, 'meters'>;
|
|
85
|
+
type Kilometers = WithUnits<number, 'kilometers'>;
|
|
86
|
+
type Miles = WithUnits<number, 'miles'>;
|
|
87
|
+
|
|
88
|
+
const registry = createRegistry<'meters' | 'kilometers' | 'miles'>()
|
|
89
|
+
.registerBidirectional('meters', 'kilometers', {
|
|
90
|
+
to: (m) => (m / 1000) as Kilometers,
|
|
91
|
+
from: (km) => (km * 1000) as Meters
|
|
92
|
+
})
|
|
93
|
+
.registerBidirectional('kilometers', 'miles', {
|
|
94
|
+
to: (km) => (km * 0.621371) as Miles,
|
|
95
|
+
from: (mi) => (mi / 0.621371) as Kilometers
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// No direct meters→miles converter registered!
|
|
99
|
+
// Registry auto-composes: meters → kilometers → miles
|
|
100
|
+
const meters: Meters = 5000 as Meters;
|
|
101
|
+
const miles = registry.convert(meters, 'meters').to('miles');
|
|
102
|
+
console.log(miles); // 3.106855
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Format-Tagged Values
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { type WithFormat, type FormatterParser, ParseError } from '@unacy/core';
|
|
109
|
+
import { z } from 'zod';
|
|
110
|
+
|
|
111
|
+
type ISO8601 = WithFormat<Date, 'ISO8601'>;
|
|
112
|
+
|
|
113
|
+
const iso8601: FormatterParser<ISO8601> = {
|
|
114
|
+
format: (date) => date.toISOString(),
|
|
115
|
+
parse: (input) => {
|
|
116
|
+
const schema = z.string().datetime();
|
|
117
|
+
try {
|
|
118
|
+
return new Date(schema.parse(input)) as ISO8601;
|
|
119
|
+
} catch {
|
|
120
|
+
throw new ParseError('ISO8601', input, 'Invalid date format');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Format
|
|
126
|
+
const now: ISO8601 = new Date() as ISO8601;
|
|
127
|
+
const str = iso8601.format(now); // "2026-01-06T12:00:00.000Z"
|
|
128
|
+
|
|
129
|
+
// Parse
|
|
130
|
+
const date = iso8601.parse('2026-01-06T12:00:00.000Z');
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## API Reference
|
|
134
|
+
|
|
135
|
+
### Types
|
|
136
|
+
|
|
137
|
+
#### `WithUnits<T, U>`
|
|
138
|
+
Brand a value with a unit identifier for compile-time safety.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
type Celsius = WithUnits<number, 'Celsius'>;
|
|
142
|
+
const temp: Celsius = 25 as Celsius;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### `WithFormat<T, F>`
|
|
146
|
+
Brand a value with a format identifier for serialization safety.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
type ISO8601 = WithFormat<Date, 'ISO8601'>;
|
|
150
|
+
const date: ISO8601 = new Date() as ISO8601;
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### `Converter<TInput, TOutput>`
|
|
154
|
+
Unidirectional converter function.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const c2f: Converter<Celsius, Fahrenheit> = (c) =>
|
|
158
|
+
((c * 9/5) + 32) as Fahrenheit;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `BidirectionalConverter<TInput, TOutput>`
|
|
162
|
+
Pair of converters for two-way transformations.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const meterKm: BidirectionalConverter<Meters, Kilometers> = {
|
|
166
|
+
to: (m) => (m / 1000) as Kilometers,
|
|
167
|
+
from: (km) => (km * 1000) as Meters
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Registry
|
|
172
|
+
|
|
173
|
+
#### `createRegistry<Units>()`
|
|
174
|
+
Create a new converter registry.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const registry = createRegistry<'A' | 'B' | 'C'>();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### `register(from, to, converter)`
|
|
181
|
+
Register a unidirectional converter.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
registry.register('Celsius', 'Fahrenheit', celsiusToFahrenheit);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### `registerBidirectional(from, to, converter)`
|
|
188
|
+
Register both directions at once.
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
registry.registerBidirectional('meters', 'kilometers', meterKm);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### `convert(value, fromUnit).to(toUnit)`
|
|
195
|
+
Fluent API for type-safe conversions.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const result = registry.convert(value, 'Celsius').to('Fahrenheit');
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Errors
|
|
202
|
+
|
|
203
|
+
- `UnacyError` - Base error class
|
|
204
|
+
- `CycleError` - Cycle detected in conversion graph
|
|
205
|
+
- `MaxDepthError` - Exceeded maximum conversion depth (5 hops)
|
|
206
|
+
- `ConversionError` - No conversion path found
|
|
207
|
+
- `ParseError` - Invalid input during parsing
|
|
208
|
+
|
|
209
|
+
## Best Practices
|
|
210
|
+
|
|
211
|
+
1. **Define unit types at module boundaries** for consistency
|
|
212
|
+
2. **Use bidirectional converters** when both directions are needed
|
|
213
|
+
3. **Document precision loss** in converters
|
|
214
|
+
4. **Cache registries** for performance
|
|
215
|
+
5. **Validate with Zod** in parsers
|
|
216
|
+
|
|
217
|
+
## Performance
|
|
218
|
+
|
|
219
|
+
- Direct conversions: O(1) lookup
|
|
220
|
+
- Multi-hop conversions: O(V+E) BFS with caching
|
|
221
|
+
- Type checking: <1s for typical graphs (<100 units)
|
|
222
|
+
- Zero runtime overhead for type brands
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
|
227
|
+
|
|
228
|
+
## Links
|
|
229
|
+
|
|
230
|
+
- [Specification](../../specs/001-unacy-core/spec.md)
|
|
231
|
+
- [Quickstart Guide](../../specs/001-unacy-core/quickstart.md)
|
|
232
|
+
- [API Contracts](../../specs/001-unacy-core/contracts/api.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, it, expect, expectTypeOf } from 'vitest';
|
|
2
|
+
describe('WithUnits Type Safety', () => {
|
|
3
|
+
it('allows assignment with explicit cast', () => {
|
|
4
|
+
const temp = 25;
|
|
5
|
+
expect(temp).toBe(25);
|
|
6
|
+
});
|
|
7
|
+
it('preserves numeric operations at runtime', () => {
|
|
8
|
+
const temp1 = 10;
|
|
9
|
+
const temp2 = 20;
|
|
10
|
+
// Runtime operations work normally
|
|
11
|
+
expect(temp1 + temp2).toBe(30);
|
|
12
|
+
});
|
|
13
|
+
it('compile-time: prevents assignment without cast', () => {
|
|
14
|
+
// @ts-expect-error - Cannot assign plain number to branded type
|
|
15
|
+
const temp = 25;
|
|
16
|
+
expect(temp).toBe(25); // Runtime still works, but type error at compile time
|
|
17
|
+
});
|
|
18
|
+
it('compile-time: prevents mixing different unit types', () => {
|
|
19
|
+
const temp = 25;
|
|
20
|
+
// @ts-expect-error - Cannot assign Celsius to Fahrenheit
|
|
21
|
+
const fahrenheit = temp;
|
|
22
|
+
expect(fahrenheit).toBe(temp); // Runtime value is same, but type mismatch
|
|
23
|
+
});
|
|
24
|
+
it('compile-time: different units are not compatible', () => {
|
|
25
|
+
const distance = 100;
|
|
26
|
+
// @ts-expect-error - Cannot assign Meters to Celsius
|
|
27
|
+
const temp = distance;
|
|
28
|
+
expect(temp).toBe(distance);
|
|
29
|
+
});
|
|
30
|
+
it('type inference: maintains branded type through variables', () => {
|
|
31
|
+
const temp1 = 25;
|
|
32
|
+
const temp2 = temp1; // Type should be inferred as Celsius
|
|
33
|
+
expectTypeOf(temp2).toEqualTypeOf();
|
|
34
|
+
});
|
|
35
|
+
it('type inference: array of branded types', () => {
|
|
36
|
+
const temps = [10, 20, 30].map((n) => n);
|
|
37
|
+
expectTypeOf(temps).toEqualTypeOf();
|
|
38
|
+
expect(temps).toHaveLength(3);
|
|
39
|
+
});
|
|
40
|
+
it('supports different base types', () => {
|
|
41
|
+
const distance = 1000n;
|
|
42
|
+
const money = '100.50';
|
|
43
|
+
expectTypeOf(distance).toEqualTypeOf();
|
|
44
|
+
expectTypeOf(money).toEqualTypeOf();
|
|
45
|
+
expect(distance).toBe(1000n);
|
|
46
|
+
expect(money).toBe('100.50');
|
|
47
|
+
});
|
|
48
|
+
it('supports string literal as unit identifier', () => {
|
|
49
|
+
const value = 42;
|
|
50
|
+
expectTypeOf(value).toEqualTypeOf();
|
|
51
|
+
expect(value).toBe(42);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('WithFormat Type Safety', () => {
|
|
55
|
+
it('allows assignment with explicit cast', () => {
|
|
56
|
+
const date = new Date();
|
|
57
|
+
expect(date).toBeInstanceOf(Date);
|
|
58
|
+
});
|
|
59
|
+
it('compile-time: prevents assignment without cast', () => {
|
|
60
|
+
const now = new Date();
|
|
61
|
+
// @ts-expect-error - Cannot assign Date to branded ISO8601
|
|
62
|
+
const date = now;
|
|
63
|
+
expect(date).toBe(now);
|
|
64
|
+
});
|
|
65
|
+
it('compile-time: prevents mixing different format types', () => {
|
|
66
|
+
const timestamp = Date.now();
|
|
67
|
+
// @ts-expect-error - Cannot assign UnixTimestamp to HexColor
|
|
68
|
+
const color = timestamp;
|
|
69
|
+
expect(color).toBe(timestamp);
|
|
70
|
+
});
|
|
71
|
+
it('compile-time: different formats of same base type are incompatible', () => {
|
|
72
|
+
const date = new Date();
|
|
73
|
+
// Both are Dates, and branded types are assignable to base types
|
|
74
|
+
const plainDate = date;
|
|
75
|
+
expect(plainDate).toBe(date);
|
|
76
|
+
});
|
|
77
|
+
it('type inference: maintains branded type', () => {
|
|
78
|
+
const color1 = '#FF5733';
|
|
79
|
+
const color2 = color1;
|
|
80
|
+
expectTypeOf(color2).toEqualTypeOf();
|
|
81
|
+
});
|
|
82
|
+
it('supports different base types with same format name', () => {
|
|
83
|
+
const str = 'test';
|
|
84
|
+
const num = 123;
|
|
85
|
+
expectTypeOf(str).toEqualTypeOf();
|
|
86
|
+
expectTypeOf(num).toEqualTypeOf();
|
|
87
|
+
// These should be different types
|
|
88
|
+
expectTypeOf(str).not.toEqualTypeOf();
|
|
89
|
+
});
|
|
90
|
+
it('type inference: array of formatted values', () => {
|
|
91
|
+
const colors = ['#FF0000', '#00FF00', '#0000FF'].map((c) => c);
|
|
92
|
+
expectTypeOf(colors).toEqualTypeOf();
|
|
93
|
+
expect(colors).toHaveLength(3);
|
|
94
|
+
});
|
|
95
|
+
it('supports complex format identifiers', () => {
|
|
96
|
+
const value = '2026-01-06T12:00:00.000+00:00';
|
|
97
|
+
expectTypeOf(value).toEqualTypeOf();
|
|
98
|
+
expect(value).toContain('T');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('WithUnits and WithFormat Interaction', () => {
|
|
102
|
+
it('units and formats are independent type brands', () => {
|
|
103
|
+
const temp = 25;
|
|
104
|
+
const date = new Date();
|
|
105
|
+
expectTypeOf(temp).toEqualTypeOf();
|
|
106
|
+
expectTypeOf(date).toEqualTypeOf();
|
|
107
|
+
// Different brand systems
|
|
108
|
+
expectTypeOf(temp).not.toEqualTypeOf();
|
|
109
|
+
});
|
|
110
|
+
it('can apply both brands (theoretical, but should type-check)', () => {
|
|
111
|
+
const value = 25;
|
|
112
|
+
expectTypeOf(value).toEqualTypeOf();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "unacy",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Type-safe unit and format conversion library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": false,
|
|
7
|
+
"author": "Pradeep Mouli",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"type-fest": "^5.3.1",
|
|
24
|
+
"zod": "^3.24.1"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^25.0.3",
|
|
28
|
+
"typescript": "^5.9.3",
|
|
29
|
+
"vitest": "^4.0.16"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20.0.0"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc",
|
|
36
|
+
"clean": "rm -rf dist",
|
|
37
|
+
"type-check": "tsc --noEmit",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest"
|
|
40
|
+
}
|
|
41
|
+
}
|