@sinclair/typebox 0.26.8 → 0.27.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/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 +205 -109
- package/typebox.d.ts +113 -39
- package/typebox.js +391 -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/value/index.d.ts +1 -0
- package/value/mutate.d.ts +13 -0
- package/value/mutate.js +121 -0
- package/value/value.d.ts +3 -0
- package/value/value.js +6 -0
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
|
|
@@ -565,10 +585,11 @@ var TypeGuard;
|
|
|
565
585
|
TObject(schema) ||
|
|
566
586
|
TPromise(schema) ||
|
|
567
587
|
TRecord(schema) ||
|
|
568
|
-
TSelf(schema) ||
|
|
569
588
|
TRef(schema) ||
|
|
570
589
|
TString(schema) ||
|
|
571
590
|
TSymbol(schema) ||
|
|
591
|
+
TTemplateLiteral(schema) ||
|
|
592
|
+
TThis(schema) ||
|
|
572
593
|
TTuple(schema) ||
|
|
573
594
|
TUndefined(schema) ||
|
|
574
595
|
TUnion(schema) ||
|
|
@@ -1038,17 +1059,17 @@ var TypeExtends;
|
|
|
1038
1059
|
// Record
|
|
1039
1060
|
// --------------------------------------------------------------------------
|
|
1040
1061
|
function RecordKey(schema) {
|
|
1041
|
-
if (
|
|
1062
|
+
if (exports.PatternNumberExact in schema.patternProperties)
|
|
1042
1063
|
return exports.Type.Number();
|
|
1043
|
-
if (
|
|
1064
|
+
if (exports.PatternStringExact in schema.patternProperties)
|
|
1044
1065
|
return exports.Type.String();
|
|
1045
1066
|
throw Error('TypeExtends: Cannot get record key');
|
|
1046
1067
|
}
|
|
1047
1068
|
function RecordValue(schema) {
|
|
1048
|
-
if (
|
|
1049
|
-
return schema.patternProperties[
|
|
1050
|
-
if (
|
|
1051
|
-
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];
|
|
1052
1073
|
throw Error('TypeExtends: Cannot get record value');
|
|
1053
1074
|
}
|
|
1054
1075
|
function RecordRight(left, right) {
|
|
@@ -1269,6 +1290,12 @@ var TypeExtends;
|
|
|
1269
1290
|
return TypeGuard.TVoid(right) ? TypeExtendsResult.True : TypeExtendsResult.False;
|
|
1270
1291
|
}
|
|
1271
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
|
|
1272
1299
|
if (TypeGuard.TAny(left))
|
|
1273
1300
|
return Any(left, right);
|
|
1274
1301
|
if (TypeGuard.TArray(left))
|
|
@@ -1295,14 +1322,14 @@ var TypeExtends;
|
|
|
1295
1322
|
return Null(left, right);
|
|
1296
1323
|
if (TypeGuard.TNumber(left))
|
|
1297
1324
|
return Number(left, right);
|
|
1325
|
+
if (TypeGuard.TObject(left))
|
|
1326
|
+
return Object(left, right);
|
|
1298
1327
|
if (TypeGuard.TRecord(left))
|
|
1299
1328
|
return Record(left, right);
|
|
1300
1329
|
if (TypeGuard.TString(left))
|
|
1301
1330
|
return String(left, right);
|
|
1302
1331
|
if (TypeGuard.TSymbol(left))
|
|
1303
1332
|
return Symbol(left, right);
|
|
1304
|
-
if (TypeGuard.TObject(left))
|
|
1305
|
-
return Object(left, right);
|
|
1306
1333
|
if (TypeGuard.TTuple(left))
|
|
1307
1334
|
return Tuple(left, right);
|
|
1308
1335
|
if (TypeGuard.TPromise(left))
|
|
@@ -1422,6 +1449,278 @@ var KeyResolver;
|
|
|
1422
1449
|
KeyResolver.Resolve = Resolve;
|
|
1423
1450
|
})(KeyResolver = exports.KeyResolver || (exports.KeyResolver = {}));
|
|
1424
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
|
+
// --------------------------------------------------------------------------
|
|
1425
1724
|
// TypeOrdinal: Used for auto $id generation
|
|
1426
1725
|
// --------------------------------------------------------------------------
|
|
1427
1726
|
let TypeOrdinal = 0;
|
|
@@ -1536,6 +1835,10 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1536
1835
|
}
|
|
1537
1836
|
/** `[Standard]` Excludes from the left type any type that is not assignable to the right */
|
|
1538
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);
|
|
1539
1842
|
if (TypeGuard.TUnion(left)) {
|
|
1540
1843
|
const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) === TypeExtendsResult.False);
|
|
1541
1844
|
return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
|
|
@@ -1546,6 +1849,10 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1546
1849
|
}
|
|
1547
1850
|
/** `[Standard]` Extracts from the left type any type that is assignable to the right */
|
|
1548
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);
|
|
1549
1856
|
if (TypeGuard.TUnion(left)) {
|
|
1550
1857
|
const narrowed = left.anyOf.filter((inner) => TypeExtends.Extends(inner, right) !== TypeExtendsResult.False);
|
|
1551
1858
|
return (narrowed.length === 1 ? TypeClone.Clone(narrowed[0], options) : this.Union(narrowed, options));
|
|
@@ -1575,10 +1882,21 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1575
1882
|
}
|
|
1576
1883
|
/** `[Standard]` Creates a KeyOf type */
|
|
1577
1884
|
KeyOf(schema, options = {}) {
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
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
|
+
}
|
|
1582
1900
|
}
|
|
1583
1901
|
/** `[Standard]` Creates a Literal type */
|
|
1584
1902
|
Literal(value, options = {}) {
|
|
@@ -1680,15 +1998,16 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1680
1998
|
return this.Create(schema);
|
|
1681
1999
|
}, options);
|
|
1682
2000
|
}
|
|
2001
|
+
/** `[Standard]` Creates a Record type */
|
|
1683
2002
|
Record(key, schema, options = {}) {
|
|
1684
|
-
if (TypeGuard.
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
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 });
|
|
1690
2009
|
}
|
|
1691
|
-
if (TypeGuard.
|
|
2010
|
+
else if (TypeGuard.TUnionLiteral(key)) {
|
|
1692
2011
|
if (key.anyOf.every((schema) => TypeGuard.TLiteral(schema) && (typeof schema.const === 'string' || typeof schema.const === 'number'))) {
|
|
1693
2012
|
const properties = key.anyOf.reduce((acc, literal) => ({ ...acc, [literal.const]: TypeClone.Clone(schema, {}) }), {});
|
|
1694
2013
|
return this.Object(properties, { ...options, [exports.Hint]: 'Record' });
|
|
@@ -1696,22 +2015,32 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1696
2015
|
else
|
|
1697
2016
|
throw Error('TypeBuilder: Record key can only be derived from union literal of number or string');
|
|
1698
2017
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
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
|
+
}
|
|
1707
2036
|
}
|
|
1708
2037
|
/** `[Standard]` Creates a Recursive type */
|
|
1709
2038
|
Recursive(callback, options = {}) {
|
|
1710
2039
|
if (options.$id === undefined)
|
|
1711
2040
|
options.$id = `T${TypeOrdinal++}`;
|
|
1712
|
-
const
|
|
1713
|
-
|
|
1714
|
-
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 });
|
|
1715
2044
|
}
|
|
1716
2045
|
/** `[Standard]` Creates a Ref type. The referenced type must contain a $id */
|
|
1717
2046
|
Ref(schema, options = {}) {
|
|
@@ -1749,6 +2078,11 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1749
2078
|
String(options = {}) {
|
|
1750
2079
|
return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
|
|
1751
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
|
+
}
|
|
1752
2086
|
/** `[Standard]` Creates a Tuple type */
|
|
1753
2087
|
Tuple(items, options = {}) {
|
|
1754
2088
|
const [additionalItems, minItems, maxItems] = [false, items.length, items.length];
|
|
@@ -1759,13 +2093,19 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1759
2093
|
{ ...options, [exports.Kind]: 'Tuple', type: 'array', minItems, maxItems });
|
|
1760
2094
|
return this.Create(schema);
|
|
1761
2095
|
}
|
|
1762
|
-
Union(
|
|
1763
|
-
if (
|
|
1764
|
-
return
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
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
|
+
}
|
|
1769
2109
|
}
|
|
1770
2110
|
/** `[Standard]` Creates an Unknown type */
|
|
1771
2111
|
Unknown(options = {}) {
|
|
@@ -1778,7 +2118,7 @@ class StandardTypeBuilder extends TypeBuilder {
|
|
|
1778
2118
|
}
|
|
1779
2119
|
exports.StandardTypeBuilder = StandardTypeBuilder;
|
|
1780
2120
|
// --------------------------------------------------------------------------
|
|
1781
|
-
//
|
|
2121
|
+
// ExtendedTypeBuilder
|
|
1782
2122
|
// --------------------------------------------------------------------------
|
|
1783
2123
|
class ExtendedTypeBuilder extends StandardTypeBuilder {
|
|
1784
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':
|
package/value/check.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export declare class ValueCheckUnknownTypeError extends Error {
|
|
|
4
4
|
constructor(schema: Types.TSchema);
|
|
5
5
|
}
|
|
6
6
|
export declare class ValueCheckDereferenceError extends Error {
|
|
7
|
-
readonly schema: Types.TRef | Types.
|
|
8
|
-
constructor(schema: Types.TRef | Types.
|
|
7
|
+
readonly schema: Types.TRef | Types.TThis;
|
|
8
|
+
constructor(schema: Types.TRef | Types.TThis);
|
|
9
9
|
}
|
|
10
10
|
export declare namespace ValueCheck {
|
|
11
11
|
function Check<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: any): boolean;
|