@sinclair/typebox 0.26.7 → 0.27.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/compiler/compiler.js +13 -6
- package/errors/errors.d.ts +2 -2
- package/errors/errors.js +21 -10
- package/package.json +2 -2
- package/readme.md +178 -108
- package/typebox.d.ts +115 -39
- package/typebox.js +399 -51
- package/value/cast.d.ts +4 -4
- package/value/cast.js +14 -9
- package/value/check.d.ts +2 -2
- package/value/check.js +17 -9
- package/value/convert.d.ts +2 -2
- package/value/convert.js +14 -9
- package/value/create.d.ts +6 -2
- package/value/create.js +35 -16
package/typebox.js
CHANGED
|
@@ -27,13 +27,22 @@ THE SOFTWARE.
|
|
|
27
27
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.Type = exports.StandardType = exports.ExtendedTypeBuilder = exports.StandardTypeBuilder = exports.TypeBuilder = exports.KeyResolver = exports.ObjectMap = exports.TypeClone = exports.TypeExtends = exports.TypeExtendsResult = exports.ExtendsUndefined = exports.TypeGuard = exports.TypeGuardUnknownTypeError = exports.FormatRegistry = exports.TypeRegistry = exports.Kind = exports.Hint = exports.Modifier = void 0;
|
|
30
|
+
exports.Type = exports.StandardType = exports.ExtendedTypeBuilder = exports.StandardTypeBuilder = exports.TypeBuilder = exports.TemplateLiteralGenerator = exports.TemplateLiteralFinite = exports.TemplateLiteralParser = exports.TemplateLiteralParserError = exports.TemplateLiteralResolver = exports.TemplateLiteralPattern = exports.KeyResolver = exports.ObjectMap = exports.TypeClone = exports.TypeExtends = exports.TypeExtendsResult = exports.ExtendsUndefined = exports.TypeGuard = exports.TypeGuardUnknownTypeError = exports.FormatRegistry = exports.TypeRegistry = exports.PatternStringExact = exports.PatternNumberExact = exports.PatternBooleanExact = exports.PatternString = exports.PatternNumber = exports.PatternBoolean = exports.Kind = exports.Hint = exports.Modifier = void 0;
|
|
31
31
|
// --------------------------------------------------------------------------
|
|
32
|
-
//
|
|
32
|
+
// Symbols
|
|
33
33
|
// --------------------------------------------------------------------------
|
|
34
34
|
exports.Modifier = Symbol.for('TypeBox.Modifier');
|
|
35
35
|
exports.Hint = Symbol.for('TypeBox.Hint');
|
|
36
36
|
exports.Kind = Symbol.for('TypeBox.Kind');
|
|
37
|
+
// --------------------------------------------------------------------------
|
|
38
|
+
// Patterns
|
|
39
|
+
// --------------------------------------------------------------------------
|
|
40
|
+
exports.PatternBoolean = '(true|false)';
|
|
41
|
+
exports.PatternNumber = '(0|[1-9][0-9]*)';
|
|
42
|
+
exports.PatternString = '.*';
|
|
43
|
+
exports.PatternBooleanExact = `^${exports.PatternBoolean}$`;
|
|
44
|
+
exports.PatternNumberExact = `^${exports.PatternNumber}$`;
|
|
45
|
+
exports.PatternStringExact = `^${exports.PatternString}$`;
|
|
37
46
|
/** A registry for user defined types */
|
|
38
47
|
var TypeRegistry;
|
|
39
48
|
(function (TypeRegistry) {
|
|
@@ -183,7 +192,7 @@ var TypeGuard;
|
|
|
183
192
|
IsOptionalBoolean(schema.uniqueItems));
|
|
184
193
|
}
|
|
185
194
|
TypeGuard.TArray = TArray;
|
|
186
|
-
/** Returns true if the given schema is
|
|
195
|
+
/** Returns true if the given schema is TBigInt */
|
|
187
196
|
function TBigInt(schema) {
|
|
188
197
|
// prettier-ignore
|
|
189
198
|
return (TKind(schema) &&
|
|
@@ -404,15 +413,6 @@ var TypeGuard;
|
|
|
404
413
|
return true;
|
|
405
414
|
}
|
|
406
415
|
TypeGuard.TRecord = TRecord;
|
|
407
|
-
/** Returns true if the given schema is TSelf */
|
|
408
|
-
function TSelf(schema) {
|
|
409
|
-
// prettier-ignore
|
|
410
|
-
return (TKind(schema) &&
|
|
411
|
-
schema[exports.Kind] === 'Self' &&
|
|
412
|
-
IsOptionalString(schema.$id) &&
|
|
413
|
-
IsString(schema.$ref));
|
|
414
|
-
}
|
|
415
|
-
TypeGuard.TSelf = TSelf;
|
|
416
416
|
/** Returns true if the given schema is TRef */
|
|
417
417
|
function TRef(schema) {
|
|
418
418
|
// prettier-ignore
|
|
@@ -444,6 +444,26 @@ var TypeGuard;
|
|
|
444
444
|
IsOptionalString(schema.$id));
|
|
445
445
|
}
|
|
446
446
|
TypeGuard.TSymbol = TSymbol;
|
|
447
|
+
/** Returns true if the given schema is TTemplateLiteral */
|
|
448
|
+
function TTemplateLiteral(schema) {
|
|
449
|
+
// prettier-ignore
|
|
450
|
+
return (TKind(schema) &&
|
|
451
|
+
schema[exports.Kind] === 'TemplateLiteral' &&
|
|
452
|
+
schema.type === 'string' &&
|
|
453
|
+
IsString(schema.pattern) &&
|
|
454
|
+
schema.pattern[0] === '^' &&
|
|
455
|
+
schema.pattern[schema.pattern.length - 1] === '$');
|
|
456
|
+
}
|
|
457
|
+
TypeGuard.TTemplateLiteral = TTemplateLiteral;
|
|
458
|
+
/** Returns true if the given schema is TThis */
|
|
459
|
+
function TThis(schema) {
|
|
460
|
+
// prettier-ignore
|
|
461
|
+
return (TKind(schema) &&
|
|
462
|
+
schema[exports.Kind] === 'This' &&
|
|
463
|
+
IsOptionalString(schema.$id) &&
|
|
464
|
+
IsString(schema.$ref));
|
|
465
|
+
}
|
|
466
|
+
TypeGuard.TThis = TThis;
|
|
447
467
|
/** Returns true if the given schema is TTuple */
|
|
448
468
|
function TTuple(schema) {
|
|
449
469
|
// prettier-ignore
|
|
@@ -513,6 +533,13 @@ var TypeGuard;
|
|
|
513
533
|
IsOptionalString(schema.$id));
|
|
514
534
|
}
|
|
515
535
|
TypeGuard.TUnknown = TUnknown;
|
|
536
|
+
/** Returns true if the given schema is a raw TUnsafe */
|
|
537
|
+
function TUnsafe(schema) {
|
|
538
|
+
// prettier-ignore
|
|
539
|
+
return (TKind(schema) &&
|
|
540
|
+
schema[exports.Kind] === 'Unsafe');
|
|
541
|
+
}
|
|
542
|
+
TypeGuard.TUnsafe = TUnsafe;
|
|
516
543
|
/** Returns true if the given schema is TVoid */
|
|
517
544
|
function TVoid(schema) {
|
|
518
545
|
// prettier-ignore
|
|
@@ -558,15 +585,17 @@ var TypeGuard;
|
|
|
558
585
|
TObject(schema) ||
|
|
559
586
|
TPromise(schema) ||
|
|
560
587
|
TRecord(schema) ||
|
|
561
|
-
TSelf(schema) ||
|
|
562
588
|
TRef(schema) ||
|
|
563
589
|
TString(schema) ||
|
|
564
590
|
TSymbol(schema) ||
|
|
591
|
+
TTemplateLiteral(schema) ||
|
|
592
|
+
TThis(schema) ||
|
|
565
593
|
TTuple(schema) ||
|
|
566
594
|
TUndefined(schema) ||
|
|
567
595
|
TUnion(schema) ||
|
|
568
596
|
TUint8Array(schema) ||
|
|
569
597
|
TUnknown(schema) ||
|
|
598
|
+
TUnsafe(schema) ||
|
|
570
599
|
TVoid(schema) ||
|
|
571
600
|
(TKind(schema) && TypeRegistry.Has(schema[exports.Kind]))));
|
|
572
601
|
}
|
|
@@ -1030,17 +1059,17 @@ var TypeExtends;
|
|
|
1030
1059
|
// Record
|
|
1031
1060
|
// --------------------------------------------------------------------------
|
|
1032
1061
|
function RecordKey(schema) {
|
|
1033
|
-
if (
|
|
1062
|
+
if (exports.PatternNumberExact in schema.patternProperties)
|
|
1034
1063
|
return exports.Type.Number();
|
|
1035
|
-
if (
|
|
1064
|
+
if (exports.PatternStringExact in schema.patternProperties)
|
|
1036
1065
|
return exports.Type.String();
|
|
1037
1066
|
throw Error('TypeExtends: Cannot get record key');
|
|
1038
1067
|
}
|
|
1039
1068
|
function RecordValue(schema) {
|
|
1040
|
-
if (
|
|
1041
|
-
return schema.patternProperties[
|
|
1042
|
-
if (
|
|
1043
|
-
return schema.patternProperties[
|
|
1069
|
+
if (exports.PatternNumberExact in schema.patternProperties)
|
|
1070
|
+
return schema.patternProperties[exports.PatternNumberExact];
|
|
1071
|
+
if (exports.PatternStringExact in schema.patternProperties)
|
|
1072
|
+
return schema.patternProperties[exports.PatternStringExact];
|
|
1044
1073
|
throw Error('TypeExtends: Cannot get record value');
|
|
1045
1074
|
}
|
|
1046
1075
|
function RecordRight(left, right) {
|
|
@@ -1261,6 +1290,12 @@ var TypeExtends;
|
|
|
1261
1290
|
return TypeGuard.TVoid(right) ? TypeExtendsResult.True : TypeExtendsResult.False;
|
|
1262
1291
|
}
|
|
1263
1292
|
function Visit(left, right) {
|
|
1293
|
+
// template union remap
|
|
1294
|
+
if (TypeGuard.TTemplateLiteral(left))
|
|
1295
|
+
return Visit(TemplateLiteralResolver.Resolve(left), right);
|
|
1296
|
+
if (TypeGuard.TTemplateLiteral(right))
|
|
1297
|
+
return Visit(left, TemplateLiteralResolver.Resolve(right));
|
|
1298
|
+
// standard extends
|
|
1264
1299
|
if (TypeGuard.TAny(left))
|
|
1265
1300
|
return Any(left, right);
|
|
1266
1301
|
if (TypeGuard.TArray(left))
|
|
@@ -1287,14 +1322,14 @@ var TypeExtends;
|
|
|
1287
1322
|
return Null(left, right);
|
|
1288
1323
|
if (TypeGuard.TNumber(left))
|
|
1289
1324
|
return Number(left, right);
|
|
1325
|
+
if (TypeGuard.TObject(left))
|
|
1326
|
+
return Object(left, right);
|
|
1290
1327
|
if (TypeGuard.TRecord(left))
|
|
1291
1328
|
return Record(left, right);
|
|
1292
1329
|
if (TypeGuard.TString(left))
|
|
1293
1330
|
return String(left, right);
|
|
1294
1331
|
if (TypeGuard.TSymbol(left))
|
|
1295
1332
|
return Symbol(left, right);
|
|
1296
|
-
if (TypeGuard.TObject(left))
|
|
1297
|
-
return Object(left, right);
|
|
1298
1333
|
if (TypeGuard.TTuple(left))
|
|
1299
1334
|
return Tuple(left, right);
|
|
1300
1335
|
if (TypeGuard.TPromise(left))
|
|
@@ -1414,6 +1449,278 @@ var KeyResolver;
|
|
|
1414
1449
|
KeyResolver.Resolve = Resolve;
|
|
1415
1450
|
})(KeyResolver = exports.KeyResolver || (exports.KeyResolver = {}));
|
|
1416
1451
|
// --------------------------------------------------------------------------
|
|
1452
|
+
// TemplateLiteralPattern
|
|
1453
|
+
// --------------------------------------------------------------------------
|
|
1454
|
+
var TemplateLiteralPattern;
|
|
1455
|
+
(function (TemplateLiteralPattern) {
|
|
1456
|
+
function Escape(value) {
|
|
1457
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1458
|
+
}
|
|
1459
|
+
function Visit(schema, acc) {
|
|
1460
|
+
if (TypeGuard.TTemplateLiteral(schema)) {
|
|
1461
|
+
const pattern = schema.pattern.slice(1, schema.pattern.length - 1);
|
|
1462
|
+
return pattern;
|
|
1463
|
+
}
|
|
1464
|
+
else if (TypeGuard.TUnion(schema)) {
|
|
1465
|
+
const tokens = schema.anyOf.map((schema) => Visit(schema, acc)).join('|');
|
|
1466
|
+
return `(${tokens})`;
|
|
1467
|
+
}
|
|
1468
|
+
else if (TypeGuard.TNumber(schema)) {
|
|
1469
|
+
return `${acc}${exports.PatternNumber}`;
|
|
1470
|
+
}
|
|
1471
|
+
else if (TypeGuard.TInteger(schema)) {
|
|
1472
|
+
return `${acc}${exports.PatternNumber}`;
|
|
1473
|
+
}
|
|
1474
|
+
else if (TypeGuard.TBigInt(schema)) {
|
|
1475
|
+
return `${acc}${exports.PatternNumber}`;
|
|
1476
|
+
}
|
|
1477
|
+
else if (TypeGuard.TString(schema)) {
|
|
1478
|
+
return `${acc}${exports.PatternString}`;
|
|
1479
|
+
}
|
|
1480
|
+
else if (TypeGuard.TLiteral(schema)) {
|
|
1481
|
+
return `${acc}${Escape(schema.const.toString())}`;
|
|
1482
|
+
}
|
|
1483
|
+
else if (TypeGuard.TBoolean(schema)) {
|
|
1484
|
+
return `${acc}${exports.PatternBoolean}`;
|
|
1485
|
+
}
|
|
1486
|
+
else if (TypeGuard.TNever(schema)) {
|
|
1487
|
+
throw Error('TemplateLiteralPattern: TemplateLiteral cannot operate on types of TNever');
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
throw Error(`TemplateLiteralPattern: Unexpected Kind '${schema[exports.Kind]}'`);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
function Create(kinds) {
|
|
1494
|
+
return `^${kinds.map((schema) => Visit(schema, '')).join('')}\$`;
|
|
1495
|
+
}
|
|
1496
|
+
TemplateLiteralPattern.Create = Create;
|
|
1497
|
+
})(TemplateLiteralPattern = exports.TemplateLiteralPattern || (exports.TemplateLiteralPattern = {}));
|
|
1498
|
+
// --------------------------------------------------------------------------------------
|
|
1499
|
+
// TemplateLiteralResolver
|
|
1500
|
+
// --------------------------------------------------------------------------------------
|
|
1501
|
+
var TemplateLiteralResolver;
|
|
1502
|
+
(function (TemplateLiteralResolver) {
|
|
1503
|
+
function Resolve(template) {
|
|
1504
|
+
const expression = TemplateLiteralParser.ParseExact(template.pattern);
|
|
1505
|
+
if (!TemplateLiteralFinite.Check(expression))
|
|
1506
|
+
return exports.Type.String();
|
|
1507
|
+
const literals = [...TemplateLiteralGenerator.Generate(expression)].map((value) => exports.Type.Literal(value));
|
|
1508
|
+
return exports.Type.Union(literals);
|
|
1509
|
+
}
|
|
1510
|
+
TemplateLiteralResolver.Resolve = Resolve;
|
|
1511
|
+
})(TemplateLiteralResolver = exports.TemplateLiteralResolver || (exports.TemplateLiteralResolver = {}));
|
|
1512
|
+
// --------------------------------------------------------------------------------------
|
|
1513
|
+
// TemplateLiteralParser
|
|
1514
|
+
// --------------------------------------------------------------------------------------
|
|
1515
|
+
class TemplateLiteralParserError extends Error {
|
|
1516
|
+
constructor(message) {
|
|
1517
|
+
super(message);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
exports.TemplateLiteralParserError = TemplateLiteralParserError;
|
|
1521
|
+
var TemplateLiteralParser;
|
|
1522
|
+
(function (TemplateLiteralParser) {
|
|
1523
|
+
function Unescape(value) {
|
|
1524
|
+
return value.replace(/\\/g, '');
|
|
1525
|
+
}
|
|
1526
|
+
function IsNonEscaped(pattern, index, char) {
|
|
1527
|
+
return pattern[index] === char && pattern.charCodeAt(index - 1) !== 92;
|
|
1528
|
+
}
|
|
1529
|
+
function IsOpenParen(pattern, index) {
|
|
1530
|
+
return IsNonEscaped(pattern, index, '(');
|
|
1531
|
+
}
|
|
1532
|
+
function IsCloseParen(pattern, index) {
|
|
1533
|
+
return IsNonEscaped(pattern, index, ')');
|
|
1534
|
+
}
|
|
1535
|
+
function IsSeparator(pattern, index) {
|
|
1536
|
+
return IsNonEscaped(pattern, index, '|');
|
|
1537
|
+
}
|
|
1538
|
+
function IsGroup(pattern) {
|
|
1539
|
+
if (!(IsOpenParen(pattern, 0) && IsCloseParen(pattern, pattern.length - 1)))
|
|
1540
|
+
return false;
|
|
1541
|
+
let count = 0;
|
|
1542
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
1543
|
+
if (IsOpenParen(pattern, index))
|
|
1544
|
+
count += 1;
|
|
1545
|
+
if (IsCloseParen(pattern, index))
|
|
1546
|
+
count -= 1;
|
|
1547
|
+
if (count === 0 && index !== pattern.length - 1)
|
|
1548
|
+
return false;
|
|
1549
|
+
}
|
|
1550
|
+
return true;
|
|
1551
|
+
}
|
|
1552
|
+
function InGroup(pattern) {
|
|
1553
|
+
return pattern.slice(1, pattern.length - 1);
|
|
1554
|
+
}
|
|
1555
|
+
function IsPrecedenceOr(pattern) {
|
|
1556
|
+
let count = 0;
|
|
1557
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
1558
|
+
if (IsOpenParen(pattern, index))
|
|
1559
|
+
count += 1;
|
|
1560
|
+
if (IsCloseParen(pattern, index))
|
|
1561
|
+
count -= 1;
|
|
1562
|
+
if (IsSeparator(pattern, index) && count === 0)
|
|
1563
|
+
return true;
|
|
1564
|
+
}
|
|
1565
|
+
return false;
|
|
1566
|
+
}
|
|
1567
|
+
function IsPrecedenceAnd(pattern) {
|
|
1568
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
1569
|
+
if (IsOpenParen(pattern, index))
|
|
1570
|
+
return true;
|
|
1571
|
+
}
|
|
1572
|
+
return false;
|
|
1573
|
+
}
|
|
1574
|
+
function Or(pattern) {
|
|
1575
|
+
let [count, start] = [0, 0];
|
|
1576
|
+
const expressions = [];
|
|
1577
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
1578
|
+
if (IsOpenParen(pattern, index))
|
|
1579
|
+
count += 1;
|
|
1580
|
+
if (IsCloseParen(pattern, index))
|
|
1581
|
+
count -= 1;
|
|
1582
|
+
if (IsSeparator(pattern, index) && count === 0) {
|
|
1583
|
+
const range = pattern.slice(start, index);
|
|
1584
|
+
if (range.length > 0)
|
|
1585
|
+
expressions.push(Parse(range));
|
|
1586
|
+
start = index + 1;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
const range = pattern.slice(start);
|
|
1590
|
+
if (range.length > 0)
|
|
1591
|
+
expressions.push(Parse(range));
|
|
1592
|
+
if (expressions.length === 0)
|
|
1593
|
+
return { type: 'const', const: '' };
|
|
1594
|
+
if (expressions.length === 1)
|
|
1595
|
+
return expressions[0];
|
|
1596
|
+
return { type: 'or', expr: expressions };
|
|
1597
|
+
}
|
|
1598
|
+
function And(pattern) {
|
|
1599
|
+
function Group(value, index) {
|
|
1600
|
+
if (!IsOpenParen(value, index))
|
|
1601
|
+
throw new TemplateLiteralParserError(`TemplateLiteralParser: Index must point to open parens`);
|
|
1602
|
+
let count = 0;
|
|
1603
|
+
for (let scan = index; scan < value.length; scan++) {
|
|
1604
|
+
if (IsOpenParen(value, scan))
|
|
1605
|
+
count += 1;
|
|
1606
|
+
if (IsCloseParen(value, scan))
|
|
1607
|
+
count -= 1;
|
|
1608
|
+
if (count === 0)
|
|
1609
|
+
return [index, scan];
|
|
1610
|
+
}
|
|
1611
|
+
throw new TemplateLiteralParserError(`TemplateLiteralParser: Unclosed group parens in expression`);
|
|
1612
|
+
}
|
|
1613
|
+
function Range(pattern, index) {
|
|
1614
|
+
for (let scan = index; scan < pattern.length; scan++) {
|
|
1615
|
+
if (IsOpenParen(pattern, scan))
|
|
1616
|
+
return [index, scan];
|
|
1617
|
+
}
|
|
1618
|
+
return [index, pattern.length];
|
|
1619
|
+
}
|
|
1620
|
+
const expressions = [];
|
|
1621
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
1622
|
+
if (IsOpenParen(pattern, index)) {
|
|
1623
|
+
const [start, end] = Group(pattern, index);
|
|
1624
|
+
const range = pattern.slice(start, end + 1);
|
|
1625
|
+
expressions.push(Parse(range));
|
|
1626
|
+
index = end;
|
|
1627
|
+
}
|
|
1628
|
+
else {
|
|
1629
|
+
const [start, end] = Range(pattern, index);
|
|
1630
|
+
const range = pattern.slice(start, end);
|
|
1631
|
+
if (range.length > 0)
|
|
1632
|
+
expressions.push(Parse(range));
|
|
1633
|
+
index = end - 1;
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
if (expressions.length === 0)
|
|
1637
|
+
return { type: 'const', const: '' };
|
|
1638
|
+
if (expressions.length === 1)
|
|
1639
|
+
return expressions[0];
|
|
1640
|
+
return { type: 'and', expr: expressions };
|
|
1641
|
+
}
|
|
1642
|
+
/** Parses a pattern and returns an expression tree */
|
|
1643
|
+
function Parse(pattern) {
|
|
1644
|
+
if (IsGroup(pattern))
|
|
1645
|
+
return Parse(InGroup(pattern));
|
|
1646
|
+
if (IsPrecedenceOr(pattern))
|
|
1647
|
+
return Or(pattern);
|
|
1648
|
+
if (IsPrecedenceAnd(pattern))
|
|
1649
|
+
return And(pattern);
|
|
1650
|
+
return { type: 'const', const: Unescape(pattern) };
|
|
1651
|
+
}
|
|
1652
|
+
TemplateLiteralParser.Parse = Parse;
|
|
1653
|
+
/** Parses a pattern and strips forward and trailing ^ and $ */
|
|
1654
|
+
function ParseExact(pattern) {
|
|
1655
|
+
return Parse(pattern.slice(1, pattern.length - 1));
|
|
1656
|
+
}
|
|
1657
|
+
TemplateLiteralParser.ParseExact = ParseExact;
|
|
1658
|
+
})(TemplateLiteralParser = exports.TemplateLiteralParser || (exports.TemplateLiteralParser = {}));
|
|
1659
|
+
// --------------------------------------------------------------------------------------
|
|
1660
|
+
// TemplateLiteralFinite
|
|
1661
|
+
// --------------------------------------------------------------------------------------
|
|
1662
|
+
var TemplateLiteralFinite;
|
|
1663
|
+
(function (TemplateLiteralFinite) {
|
|
1664
|
+
function IsNumber(expression) {
|
|
1665
|
+
return expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === '0' && expression.expr[1].type === 'const' && expression.expr[1].const === '[1-9][0-9]*';
|
|
1666
|
+
}
|
|
1667
|
+
function IsBoolean(expression) {
|
|
1668
|
+
return expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === 'true' && expression.expr[1].type === 'const' && expression.expr[1].const === 'false';
|
|
1669
|
+
}
|
|
1670
|
+
function IsString(expression) {
|
|
1671
|
+
return expression.type === 'const' && expression.const === '.*';
|
|
1672
|
+
}
|
|
1673
|
+
function Check(expression) {
|
|
1674
|
+
if (IsBoolean(expression))
|
|
1675
|
+
return true;
|
|
1676
|
+
if (IsNumber(expression) || IsString(expression))
|
|
1677
|
+
return false;
|
|
1678
|
+
if (expression.type === 'and')
|
|
1679
|
+
return expression.expr.every((expr) => Check(expr));
|
|
1680
|
+
if (expression.type === 'or')
|
|
1681
|
+
return expression.expr.every((expr) => Check(expr));
|
|
1682
|
+
if (expression.type === 'const')
|
|
1683
|
+
return true;
|
|
1684
|
+
throw Error(`TemplateLiteralFinite: Unknown expression type`);
|
|
1685
|
+
}
|
|
1686
|
+
TemplateLiteralFinite.Check = Check;
|
|
1687
|
+
})(TemplateLiteralFinite = exports.TemplateLiteralFinite || (exports.TemplateLiteralFinite = {}));
|
|
1688
|
+
// --------------------------------------------------------------------------------------
|
|
1689
|
+
// TemplateLiteralGenerator
|
|
1690
|
+
// --------------------------------------------------------------------------------------
|
|
1691
|
+
var TemplateLiteralGenerator;
|
|
1692
|
+
(function (TemplateLiteralGenerator) {
|
|
1693
|
+
function* Reduce(buffer) {
|
|
1694
|
+
if (buffer.length === 1)
|
|
1695
|
+
return yield* buffer[0];
|
|
1696
|
+
for (const left of buffer[0]) {
|
|
1697
|
+
for (const right of Reduce(buffer.slice(1))) {
|
|
1698
|
+
yield `${left}${right}`;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
function* And(expression) {
|
|
1703
|
+
return yield* Reduce(expression.expr.map((expr) => [...Generate(expr)]));
|
|
1704
|
+
}
|
|
1705
|
+
function* Or(expression) {
|
|
1706
|
+
for (const expr of expression.expr)
|
|
1707
|
+
yield* Generate(expr);
|
|
1708
|
+
}
|
|
1709
|
+
function* Const(expression) {
|
|
1710
|
+
return yield expression.const;
|
|
1711
|
+
}
|
|
1712
|
+
function* Generate(expression) {
|
|
1713
|
+
if (expression.type === 'and')
|
|
1714
|
+
return yield* And(expression);
|
|
1715
|
+
if (expression.type === 'or')
|
|
1716
|
+
return yield* Or(expression);
|
|
1717
|
+
if (expression.type === 'const')
|
|
1718
|
+
return yield* Const(expression);
|
|
1719
|
+
throw Error('TemplateLiteralGenerator: Unknown expression');
|
|
1720
|
+
}
|
|
1721
|
+
TemplateLiteralGenerator.Generate = Generate;
|
|
1722
|
+
})(TemplateLiteralGenerator = exports.TemplateLiteralGenerator || (exports.TemplateLiteralGenerator = {}));
|
|
1723
|
+
// --------------------------------------------------------------------------
|
|
1417
1724
|
// TypeOrdinal: Used for auto $id generation
|
|
1418
1725
|
// --------------------------------------------------------------------------
|
|
1419
1726
|
let TypeOrdinal = 0;
|
|
@@ -1528,6 +1835,10 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1528
1835
|
}
|
|
1529
1836
|
/** `[Standard]` Excludes from the left type any type that is not assignable to the right */
|
|
1530
1837
|
Exclude(left, right, options = {}) {
|
|
1838
|
+
if (TypeGuard.TTemplateLiteral(left))
|
|
1839
|
+
return this.Exclude(TemplateLiteralResolver.Resolve(left), right, options);
|
|
1840
|
+
if (TypeGuard.TTemplateLiteral(right))
|
|
1841
|
+
return this.Exclude(left, TemplateLiteralResolver.Resolve(right), options);
|
|
1531
1842
|
if (TypeGuard.TUnion(left)) {
|
|
1532
1843
|
const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) === TypeExtendsResult.False);
|
|
1533
1844
|
return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
|
|
@@ -1538,6 +1849,10 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1538
1849
|
}
|
|
1539
1850
|
/** `[Standard]` Extracts from the left type any type that is assignable to the right */
|
|
1540
1851
|
Extract(left, right, options = {}) {
|
|
1852
|
+
if (TypeGuard.TTemplateLiteral(left))
|
|
1853
|
+
return this.Extract(TemplateLiteralResolver.Resolve(left), right, options);
|
|
1854
|
+
if (TypeGuard.TTemplateLiteral(right))
|
|
1855
|
+
return this.Extract(left, TemplateLiteralResolver.Resolve(right), options);
|
|
1541
1856
|
if (TypeGuard.TUnion(left)) {
|
|
1542
1857
|
const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) !== TypeExtendsResult.False);
|
|
1543
1858
|
return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
|
|
@@ -1567,10 +1882,21 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1567
1882
|
}
|
|
1568
1883
|
/** `[Standard]` Creates a KeyOf type */
|
|
1569
1884
|
KeyOf(schema, options = {}) {
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1885
|
+
if (TypeGuard.TRecord(schema)) {
|
|
1886
|
+
const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0];
|
|
1887
|
+
if (pattern === exports.PatternNumberExact)
|
|
1888
|
+
return this.Number(options);
|
|
1889
|
+
if (pattern === exports.PatternStringExact)
|
|
1890
|
+
return this.String(options);
|
|
1891
|
+
throw Error('StandardTypeBuilder: Unable to resolve key type from Record key pattern');
|
|
1892
|
+
}
|
|
1893
|
+
else {
|
|
1894
|
+
const resolved = KeyResolver.Resolve(schema);
|
|
1895
|
+
if (resolved.length === 0)
|
|
1896
|
+
return this.Never(options);
|
|
1897
|
+
const literals = resolved.map((key) => this.Literal(key));
|
|
1898
|
+
return this.Union(literals, options);
|
|
1899
|
+
}
|
|
1574
1900
|
}
|
|
1575
1901
|
/** `[Standard]` Creates a Literal type */
|
|
1576
1902
|
Literal(value, options = {}) {
|
|
@@ -1672,15 +1998,16 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1672
1998
|
return this.Create(schema);
|
|
1673
1999
|
}, options);
|
|
1674
2000
|
}
|
|
2001
|
+
/** `[Standard]` Creates a Record type */
|
|
1675
2002
|
Record(key, schema, options = {}) {
|
|
1676
|
-
if (TypeGuard.
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2003
|
+
if (TypeGuard.TTemplateLiteral(key)) {
|
|
2004
|
+
const expression = TemplateLiteralParser.ParseExact(key.pattern);
|
|
2005
|
+
// prettier-ignore
|
|
2006
|
+
return TemplateLiteralFinite.Check(expression)
|
|
2007
|
+
? (this.Object([...TemplateLiteralGenerator.Generate(expression)].reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(schema, {}) }), {}), options))
|
|
2008
|
+
: this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
|
|
1682
2009
|
}
|
|
1683
|
-
if (TypeGuard.
|
|
2010
|
+
else if (TypeGuard.TUnionLiteral(key)) {
|
|
1684
2011
|
if (key.anyOf.every((schema) => TypeGuard.TLiteral(schema) && (typeof schema.const === 'string' || typeof schema.const === 'number'))) {
|
|
1685
2012
|
const properties = key.anyOf.reduce((acc, literal) => ({ ...acc, [literal.const]: TypeClone.Clone(schema, {}) }), {});
|
|
1686
2013
|
return this.Object(properties, { ...options, [exports.Hint]: 'Record' });
|
|
@@ -1688,22 +2015,32 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1688
2015
|
else
|
|
1689
2016
|
throw Error('TypeBuilder: Record key can only be derived from union literal of number or string');
|
|
1690
2017
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
2018
|
+
else if (TypeGuard.TLiteral(key)) {
|
|
2019
|
+
if (typeof key.const === 'string' || typeof key.const === 'number') {
|
|
2020
|
+
return this.Object({ [key.const]: TypeClone.Clone(schema, {}) }, options);
|
|
2021
|
+
}
|
|
2022
|
+
else
|
|
2023
|
+
throw Error('TypeBuilder: Record key can only be derived from literals of number or string');
|
|
2024
|
+
}
|
|
2025
|
+
else if (TypeGuard.TInteger(key) || TypeGuard.TNumber(key)) {
|
|
2026
|
+
const pattern = exports.PatternNumberExact;
|
|
2027
|
+
return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
|
|
2028
|
+
}
|
|
2029
|
+
else if (TypeGuard.TString(key)) {
|
|
2030
|
+
const pattern = key.pattern === undefined ? exports.PatternStringExact : key.pattern;
|
|
2031
|
+
return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema, {}) }, additionalProperties: false });
|
|
2032
|
+
}
|
|
2033
|
+
else {
|
|
2034
|
+
throw Error(`StandardTypeBuilder: Invalid Record Key`);
|
|
2035
|
+
}
|
|
1699
2036
|
}
|
|
1700
2037
|
/** `[Standard]` Creates a Recursive type */
|
|
1701
2038
|
Recursive(callback, options = {}) {
|
|
1702
2039
|
if (options.$id === undefined)
|
|
1703
2040
|
options.$id = `T${TypeOrdinal++}`;
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
return this.Create({ ...options, ...
|
|
2041
|
+
const thisType = callback({ [exports.Kind]: 'This', $ref: `${options.$id}` });
|
|
2042
|
+
thisType.$id = options.$id;
|
|
2043
|
+
return this.Create({ ...options, ...thisType });
|
|
1707
2044
|
}
|
|
1708
2045
|
/** `[Standard]` Creates a Ref type. The referenced type must contain a $id */
|
|
1709
2046
|
Ref(schema, options = {}) {
|
|
@@ -1741,6 +2078,11 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1741
2078
|
String(options = {}) {
|
|
1742
2079
|
return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
|
|
1743
2080
|
}
|
|
2081
|
+
/** `[Standard]` Creates a template literal type */
|
|
2082
|
+
TemplateLiteral(kinds, options = {}) {
|
|
2083
|
+
const pattern = TemplateLiteralPattern.Create(kinds);
|
|
2084
|
+
return this.Create({ ...options, [exports.Kind]: 'TemplateLiteral', type: 'string', pattern });
|
|
2085
|
+
}
|
|
1744
2086
|
/** `[Standard]` Creates a Tuple type */
|
|
1745
2087
|
Tuple(items, options = {}) {
|
|
1746
2088
|
const [additionalItems, minItems, maxItems] = [false, items.length, items.length];
|
|
@@ -1751,13 +2093,19 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1751
2093
|
{ ...options, [exports.Kind]: 'Tuple', type: 'array', minItems, maxItems });
|
|
1752
2094
|
return this.Create(schema);
|
|
1753
2095
|
}
|
|
1754
|
-
Union(
|
|
1755
|
-
if (
|
|
1756
|
-
return
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
2096
|
+
Union(union, options = {}) {
|
|
2097
|
+
if (TypeGuard.TTemplateLiteral(union)) {
|
|
2098
|
+
return TemplateLiteralResolver.Resolve(union);
|
|
2099
|
+
}
|
|
2100
|
+
else {
|
|
2101
|
+
const anyOf = union;
|
|
2102
|
+
if (anyOf.length === 0)
|
|
2103
|
+
return this.Never(options);
|
|
2104
|
+
if (anyOf.length === 1)
|
|
2105
|
+
return this.Create(TypeClone.Clone(anyOf[0], options));
|
|
2106
|
+
const clonedAnyOf = anyOf.map((schema) => TypeClone.Clone(schema, {}));
|
|
2107
|
+
return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: clonedAnyOf });
|
|
2108
|
+
}
|
|
1761
2109
|
}
|
|
1762
2110
|
/** `[Standard]` Creates an Unknown type */
|
|
1763
2111
|
Unknown(options = {}) {
|
|
@@ -1770,7 +2118,7 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1770
2118
|
}
|
|
1771
2119
|
exports.StandardTypeBuilder = StandardTypeBuilder;
|
|
1772
2120
|
// --------------------------------------------------------------------------
|
|
1773
|
-
//
|
|
2121
|
+
// ExtendedTypeBuilder
|
|
1774
2122
|
// --------------------------------------------------------------------------
|
|
1775
2123
|
class ExtendedTypeBuilder extends StandardTypeBuilder {
|
|
1776
2124
|
/** `[Extended]` Creates a BigInt type */
|
package/value/cast.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Types from '../typebox';
|
|
2
2
|
export declare class ValueCastReferenceTypeError extends Error {
|
|
3
|
-
readonly schema: Types.TRef | Types.
|
|
4
|
-
constructor(schema: Types.TRef | Types.
|
|
3
|
+
readonly schema: Types.TRef | Types.TThis;
|
|
4
|
+
constructor(schema: Types.TRef | Types.TThis);
|
|
5
5
|
}
|
|
6
6
|
export declare class ValueCastArrayUniqueItemsTypeError extends Error {
|
|
7
7
|
readonly schema: Types.TSchema;
|
|
@@ -21,8 +21,8 @@ export declare class ValueCastUnknownTypeError extends Error {
|
|
|
21
21
|
constructor(schema: Types.TSchema);
|
|
22
22
|
}
|
|
23
23
|
export declare class ValueCastDereferenceError extends Error {
|
|
24
|
-
readonly schema: Types.TRef | Types.
|
|
25
|
-
constructor(schema: Types.TRef | Types.
|
|
24
|
+
readonly schema: Types.TRef | Types.TThis;
|
|
25
|
+
constructor(schema: Types.TRef | Types.TThis);
|
|
26
26
|
}
|
|
27
27
|
export declare namespace ValueCast {
|
|
28
28
|
function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): any;
|
package/value/cast.js
CHANGED
|
@@ -255,19 +255,22 @@ var ValueCast;
|
|
|
255
255
|
const target = references[index];
|
|
256
256
|
return Visit(target, references, value);
|
|
257
257
|
}
|
|
258
|
-
function Self(schema, references, value) {
|
|
259
|
-
const index = references.findIndex((foreign) => foreign.$id === schema.$ref);
|
|
260
|
-
if (index === -1)
|
|
261
|
-
throw new ValueCastDereferenceError(schema);
|
|
262
|
-
const target = references[index];
|
|
263
|
-
return Visit(target, references, value);
|
|
264
|
-
}
|
|
265
258
|
function String(schema, references, value) {
|
|
266
259
|
return check_1.ValueCheck.Check(schema, references, value) ? value : create_1.ValueCreate.Create(schema, references);
|
|
267
260
|
}
|
|
268
261
|
function Symbol(schema, references, value) {
|
|
269
262
|
return check_1.ValueCheck.Check(schema, references, value) ? clone_1.ValueClone.Clone(value) : create_1.ValueCreate.Create(schema, references);
|
|
270
263
|
}
|
|
264
|
+
function TemplateLiteral(schema, references, value) {
|
|
265
|
+
return check_1.ValueCheck.Check(schema, references, value) ? clone_1.ValueClone.Clone(value) : create_1.ValueCreate.Create(schema, references);
|
|
266
|
+
}
|
|
267
|
+
function This(schema, references, value) {
|
|
268
|
+
const index = references.findIndex((foreign) => foreign.$id === schema.$ref);
|
|
269
|
+
if (index === -1)
|
|
270
|
+
throw new ValueCastDereferenceError(schema);
|
|
271
|
+
const target = references[index];
|
|
272
|
+
return Visit(target, references, value);
|
|
273
|
+
}
|
|
271
274
|
function Tuple(schema, references, value) {
|
|
272
275
|
if (check_1.ValueCheck.Check(schema, references, value))
|
|
273
276
|
return clone_1.ValueClone.Clone(value);
|
|
@@ -335,12 +338,14 @@ var ValueCast;
|
|
|
335
338
|
return Record(schema_, references_, value);
|
|
336
339
|
case 'Ref':
|
|
337
340
|
return Ref(schema_, references_, value);
|
|
338
|
-
case 'Self':
|
|
339
|
-
return Self(schema_, references_, value);
|
|
340
341
|
case 'String':
|
|
341
342
|
return String(schema_, references_, value);
|
|
342
343
|
case 'Symbol':
|
|
343
344
|
return Symbol(schema_, references_, value);
|
|
345
|
+
case 'TemplateLiteral':
|
|
346
|
+
return TemplateLiteral(schema_, references_, value);
|
|
347
|
+
case 'This':
|
|
348
|
+
return This(schema_, references_, value);
|
|
344
349
|
case 'Tuple':
|
|
345
350
|
return Tuple(schema_, references_, value);
|
|
346
351
|
case 'Undefined':
|