unacy 0.1.0 → 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/dist/__tests__/formatters.test.d.ts.map +1 -0
- package/dist/__tests__/formatters.test.js +244 -0
- package/dist/__tests__/formatters.test.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +35 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/formatters.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { describe, it, expect, expectTypeOf } from 'vitest';
|
|
2
|
+
import { ParseError } from '../errors';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
describe('Formatter Type', () => {
|
|
5
|
+
it('formatter converts tagged value to string', () => {
|
|
6
|
+
const formatISO = (date) => date.toISOString();
|
|
7
|
+
const now = new Date('2026-01-06T12:00:00.000Z');
|
|
8
|
+
const str = formatISO(now);
|
|
9
|
+
expect(typeof str).toBe('string');
|
|
10
|
+
expect(str).toBe('2026-01-06T12:00:00.000Z');
|
|
11
|
+
});
|
|
12
|
+
it('formatter maintains format identity through transformation', () => {
|
|
13
|
+
const formatHex = (color) => color.toUpperCase();
|
|
14
|
+
const color = '#ff5733';
|
|
15
|
+
const formatted = formatHex(color);
|
|
16
|
+
expect(formatted).toBe('#FF5733');
|
|
17
|
+
expectTypeOf(formatted).toEqualTypeOf();
|
|
18
|
+
});
|
|
19
|
+
it('formatter works with different base types', () => {
|
|
20
|
+
const formatTimestamp = (ts) => String(ts);
|
|
21
|
+
const timestamp = Date.now();
|
|
22
|
+
const str = formatTimestamp(timestamp);
|
|
23
|
+
expect(typeof str).toBe('string');
|
|
24
|
+
expect(str).toMatch(/^\d+$/);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('Parser Type', () => {
|
|
28
|
+
it('parser converts string to tagged value with Zod validation', () => {
|
|
29
|
+
const parseISO = (input) => {
|
|
30
|
+
const schema = z.string().datetime();
|
|
31
|
+
const validated = schema.parse(input);
|
|
32
|
+
return new Date(validated);
|
|
33
|
+
};
|
|
34
|
+
const str = '2026-01-06T12:00:00.000Z';
|
|
35
|
+
const date = parseISO(str);
|
|
36
|
+
expectTypeOf(date).toEqualTypeOf();
|
|
37
|
+
expect(date).toBeInstanceOf(Date);
|
|
38
|
+
expect(date.toISOString()).toBe(str);
|
|
39
|
+
});
|
|
40
|
+
it('invalid string input throws ParseError with context', () => {
|
|
41
|
+
const parseHex = (input) => {
|
|
42
|
+
const schema = z.string().regex(/^#[0-9A-Fa-f]{6}$/);
|
|
43
|
+
try {
|
|
44
|
+
return schema.parse(input);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new ParseError('HexColor', input, 'Expected #RRGGBB format');
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
expect(() => {
|
|
51
|
+
parseHex('not-a-color');
|
|
52
|
+
}).toThrow(ParseError);
|
|
53
|
+
try {
|
|
54
|
+
parseHex('invalid');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
expect(err).toBeInstanceOf(ParseError);
|
|
58
|
+
if (err instanceof ParseError) {
|
|
59
|
+
expect(err.format).toBe('HexColor');
|
|
60
|
+
expect(err.input).toBe('invalid');
|
|
61
|
+
expect(err.reason).toBe('Expected #RRGGBB format');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
it('parser rejects input before tagging (no invalid tagged values)', () => {
|
|
66
|
+
const parsePositive = (input) => {
|
|
67
|
+
const schema = z
|
|
68
|
+
.string()
|
|
69
|
+
.transform((s) => parseFloat(s))
|
|
70
|
+
.refine((n) => n > 0);
|
|
71
|
+
try {
|
|
72
|
+
return schema.parse(input);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
throw new ParseError('Positive', input, 'Must be a positive number');
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
expect(() => {
|
|
79
|
+
parsePositive('-5');
|
|
80
|
+
}).toThrow(ParseError);
|
|
81
|
+
expect(() => {
|
|
82
|
+
parsePositive('not-a-number');
|
|
83
|
+
}).toThrow(ParseError);
|
|
84
|
+
// Valid input should work
|
|
85
|
+
const result = parsePositive('10');
|
|
86
|
+
expect(result).toBe(10);
|
|
87
|
+
});
|
|
88
|
+
it('handles empty input', () => {
|
|
89
|
+
const parseNonEmpty = (input) => {
|
|
90
|
+
if (input === '') {
|
|
91
|
+
throw new ParseError('NonEmpty', input, 'Cannot be empty');
|
|
92
|
+
}
|
|
93
|
+
return input;
|
|
94
|
+
};
|
|
95
|
+
expect(() => {
|
|
96
|
+
parseNonEmpty('');
|
|
97
|
+
}).toThrow(ParseError);
|
|
98
|
+
try {
|
|
99
|
+
parseNonEmpty('');
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (err instanceof ParseError) {
|
|
103
|
+
expect(err.message).toContain('""');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
it('compile-time: wrong format type to parser causes error', () => {
|
|
108
|
+
const parseISO = (input) => {
|
|
109
|
+
return new Date(input);
|
|
110
|
+
};
|
|
111
|
+
const str = '2026-01-06T12:00:00.000Z';
|
|
112
|
+
const date = parseISO(str);
|
|
113
|
+
// @ts-expect-error - Cannot assign ISO8601 to HexColor
|
|
114
|
+
const color = date;
|
|
115
|
+
expect(color).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('FormatterParser Type', () => {
|
|
119
|
+
it('round-trip (format then parse) produces equivalent value', () => {
|
|
120
|
+
const iso8601 = {
|
|
121
|
+
format: (date) => date.toISOString(),
|
|
122
|
+
parse: (input) => {
|
|
123
|
+
const schema = z.string().datetime();
|
|
124
|
+
const validated = schema.parse(input);
|
|
125
|
+
return new Date(validated);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const original = new Date('2026-01-06T12:00:00.000Z');
|
|
129
|
+
const formatted = iso8601.format(original);
|
|
130
|
+
const parsed = iso8601.parse(formatted);
|
|
131
|
+
expect(parsed.getTime()).toBe(original.getTime());
|
|
132
|
+
});
|
|
133
|
+
it('integration test: full formatter/parser pair for ISO8601 dates', () => {
|
|
134
|
+
const iso8601 = {
|
|
135
|
+
format: (date) => date.toISOString(),
|
|
136
|
+
parse: (input) => {
|
|
137
|
+
const schema = z.string().datetime();
|
|
138
|
+
try {
|
|
139
|
+
const validated = schema.parse(input);
|
|
140
|
+
return new Date(validated);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
throw new ParseError('ISO8601', input, 'Invalid ISO8601 date format');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
// Test formatting
|
|
148
|
+
const date = new Date('2026-01-06T12:34:56.789Z');
|
|
149
|
+
const str = iso8601.format(date);
|
|
150
|
+
expect(str).toBe('2026-01-06T12:34:56.789Z');
|
|
151
|
+
// Test parsing
|
|
152
|
+
const parsed = iso8601.parse('2026-12-31T23:59:59.999Z');
|
|
153
|
+
expect(parsed).toBeInstanceOf(Date);
|
|
154
|
+
expect(parsed.toISOString()).toBe('2026-12-31T23:59:59.999Z');
|
|
155
|
+
// Test round-trip
|
|
156
|
+
const roundTrip = iso8601.parse(iso8601.format(date));
|
|
157
|
+
expect(roundTrip.getTime()).toBe(date.getTime());
|
|
158
|
+
// Test error handling
|
|
159
|
+
expect(() => {
|
|
160
|
+
iso8601.parse('invalid-date');
|
|
161
|
+
}).toThrow(ParseError);
|
|
162
|
+
});
|
|
163
|
+
it('works with different format types', () => {
|
|
164
|
+
const hexColor = {
|
|
165
|
+
format: (color) => color.toLowerCase(),
|
|
166
|
+
parse: (input) => {
|
|
167
|
+
const schema = z.string().regex(/^#[0-9a-fA-F]{6}$/);
|
|
168
|
+
try {
|
|
169
|
+
return schema.parse(input);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
throw new ParseError('HexColor', input, 'Expected #RRGGBB format');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const color = '#FF5733';
|
|
177
|
+
const formatted = hexColor.format(color);
|
|
178
|
+
expect(formatted).toBe('#ff5733');
|
|
179
|
+
const parsed = hexColor.parse('#00FF00');
|
|
180
|
+
expectTypeOf(parsed).toEqualTypeOf();
|
|
181
|
+
expect(parsed).toBe('#00FF00');
|
|
182
|
+
// Round-trip with case normalization
|
|
183
|
+
const original = '#ABCDEF';
|
|
184
|
+
const roundTrip = hexColor.parse(hexColor.format(original));
|
|
185
|
+
expect(roundTrip.toLowerCase()).toBe(original.toLowerCase());
|
|
186
|
+
});
|
|
187
|
+
it('timestamp formatter/parser preserves value', () => {
|
|
188
|
+
const unixTimestamp = {
|
|
189
|
+
format: (ts) => String(ts),
|
|
190
|
+
parse: (input) => {
|
|
191
|
+
const schema = z
|
|
192
|
+
.string()
|
|
193
|
+
.regex(/^\d+$/)
|
|
194
|
+
.transform((s) => parseInt(s, 10));
|
|
195
|
+
try {
|
|
196
|
+
return schema.parse(input);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
throw new ParseError('UnixTimestamp', input, 'Expected Unix timestamp');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const timestamp = Date.now();
|
|
204
|
+
const str = unixTimestamp.format(timestamp);
|
|
205
|
+
const parsed = unixTimestamp.parse(str);
|
|
206
|
+
expect(parsed).toBe(timestamp);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
describe('Formatter/Parser Examples', () => {
|
|
210
|
+
it('YYYY-MM-DD format with validation', () => {
|
|
211
|
+
const yyyymmdd = {
|
|
212
|
+
format: (dateStr) => dateStr,
|
|
213
|
+
parse: (input) => {
|
|
214
|
+
const schema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
215
|
+
try {
|
|
216
|
+
const validated = schema.parse(input);
|
|
217
|
+
// Additional validation: check if it's a valid date
|
|
218
|
+
const parts = validated.split('-');
|
|
219
|
+
const year = parseInt(parts[0], 10);
|
|
220
|
+
const month = parseInt(parts[1], 10);
|
|
221
|
+
const day = parseInt(parts[2], 10);
|
|
222
|
+
const date = new Date(year, month - 1, day);
|
|
223
|
+
if (date.getFullYear() !== year ||
|
|
224
|
+
date.getMonth() !== month - 1 ||
|
|
225
|
+
date.getDate() !== day) {
|
|
226
|
+
throw new Error('Invalid date');
|
|
227
|
+
}
|
|
228
|
+
return validated;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
throw new ParseError('YYYY-MM-DD', input, 'Invalid date format');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
// Valid dates
|
|
236
|
+
expect(yyyymmdd.parse('2026-01-06')).toBe('2026-01-06');
|
|
237
|
+
expect(yyyymmdd.parse('2026-12-31')).toBe('2026-12-31');
|
|
238
|
+
// Invalid dates
|
|
239
|
+
expect(() => yyyymmdd.parse('2026-13-01')).toThrow(ParseError); // Invalid month
|
|
240
|
+
expect(() => yyyymmdd.parse('2026-02-30')).toThrow(ParseError); // Invalid day
|
|
241
|
+
expect(() => yyyymmdd.parse('not-a-date')).toThrow(ParseError);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=formatters.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.test.js","sourceRoot":"","sources":["../../src/__tests__/formatters.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrD,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAGtE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGvE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAG3C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EACxD,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,MAAM,EAAE,CAAC,GACR,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAU1B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validation helpers for parsers
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import { ParseError } from '../errors';
|
|
6
|
+
/**
|
|
7
|
+
* Create a parser with Zod schema validation.
|
|
8
|
+
*
|
|
9
|
+
* @template F - Format identifier
|
|
10
|
+
* @template T - Base type
|
|
11
|
+
* @param schema - Zod schema for validation
|
|
12
|
+
* @param format - Format identifier string
|
|
13
|
+
* @returns Parser function that validates and tags values
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const parseHex = createParserWithSchema(
|
|
18
|
+
* z.string().regex(/^#[0-9A-Fa-f]{6}$/),
|
|
19
|
+
* 'HexColor'
|
|
20
|
+
* );
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function createParserWithSchema(schema, format) {
|
|
24
|
+
return (input) => {
|
|
25
|
+
try {
|
|
26
|
+
const validated = schema.parse(input);
|
|
27
|
+
return validated;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
31
|
+
throw new ParseError(format, input, message);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAoB,EACpB,MAAS;IAET,OAAO,CAAC,KAAa,EAAoB,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtC,OAAO,SAA6B,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unacy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Type-safe unit and format conversion library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -20,21 +20,21 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"type-fest": "^5.3.1"
|
|
24
|
-
"zod": "^3.24.1"
|
|
23
|
+
"type-fest": "^5.3.1"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
26
|
"@types/node": "^25.0.3",
|
|
28
|
-
"typescript": "
|
|
29
|
-
"vitest": "^4.0.16"
|
|
27
|
+
"@typescript/native-preview": "7.0.0-dev.20260106.1",
|
|
28
|
+
"vitest": "^4.0.16",
|
|
29
|
+
"zod": "^4.3.5"
|
|
30
30
|
},
|
|
31
31
|
"engines": {
|
|
32
32
|
"node": ">=20.0.0"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"build": "
|
|
35
|
+
"build": "tsgo",
|
|
36
36
|
"clean": "rm -rf dist",
|
|
37
|
-
"type-check": "
|
|
37
|
+
"type-check": "tsgo --noEmit",
|
|
38
38
|
"test": "vitest run",
|
|
39
39
|
"test:watch": "vitest"
|
|
40
40
|
}
|