typebox 1.1.9 → 1.1.11

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.
@@ -1,2 +1,5 @@
1
- /** Returns true if the value is an Email */
1
+ /**
2
+ * Returns true if the value is an Email
3
+ * @specification Json Schema 2020-12
4
+ */
2
5
  export declare function IsEmail(value: string): boolean;
@@ -1,5 +1,29 @@
1
- const Email = /^(?!.*\.\.)[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i;
2
- /** Returns true if the value is an Email */
1
+ import { IsIPv4Internal } from './ipv4.mjs';
2
+ /**
3
+ * Returns true if the value is an Email
4
+ * @specification Json Schema 2020-12
5
+ */
3
6
  export function IsEmail(value) {
4
- return Email.test(value);
7
+ const dot = value.indexOf('.');
8
+ const at = value.indexOf('@');
9
+ const quoted = value[0] === '"' && value[at - 1] === '"';
10
+ const ipLiteral = value[at + 1] === '[' && value[value.length - 1] === ']';
11
+ const ipv6 = ipLiteral && value.indexOf(':', at) !== -1;
12
+ const ipv4 = ipLiteral && !ipv6 && IsIPv4Internal(value, at + 2, value.length - 1);
13
+ return (at > 0 && at < value.length - 1) &&
14
+ !(
15
+ // .test@example.com
16
+ (!quoted && dot === 0) ||
17
+ // te..st@example.com
18
+ (!quoted && dot !== -1 && value.indexOf('.', dot + 1) === dot + 1) ||
19
+ // test.@example.com
20
+ (dot !== -1 && value.indexOf('@', dot) === dot + 1) ||
21
+ // joe bloggs@example.com
22
+ (!quoted && value.indexOf(' ') !== -1) ||
23
+ // user1@oceania.org, user2@oceania.org
24
+ (value.indexOf(',') !== -1) ||
25
+ // joe.bloggs@[127.0.0.300]
26
+ (ipLiteral && !ipv4 && !ipv6) ||
27
+ // joe.bloggs@invalid=domain.com
28
+ (value.indexOf('=', at) !== -1));
5
29
  }
@@ -1,22 +1,22 @@
1
1
  export * from './_registry.mjs';
2
- export * from './date-time.mjs';
3
- export * from './date.mjs';
4
- export * from './duration.mjs';
5
- export * from './email.mjs';
6
- export * from './hostname.mjs';
7
- export * from './idn-email.mjs';
8
- export * from './idn-hostname.mjs';
9
- export * from './ipv4.mjs';
10
- export * from './ipv6.mjs';
11
- export * from './iri-reference.mjs';
12
- export * from './iri.mjs';
13
- export * from './json-pointer-uri-fragment.mjs';
14
- export * from './json-pointer.mjs';
15
- export * from './regex.mjs';
16
- export * from './relative-json-pointer.mjs';
17
- export * from './time.mjs';
18
- export * from './uri-reference.mjs';
19
- export * from './uri-template.mjs';
20
- export * from './uri.mjs';
21
- export * from './url.mjs';
22
- export * from './uuid.mjs';
2
+ export { IsDateTime } from './date-time.mjs';
3
+ export { IsDate } from './date.mjs';
4
+ export { IsDuration } from './duration.mjs';
5
+ export { IsEmail } from './email.mjs';
6
+ export { IsHostname } from './hostname.mjs';
7
+ export { IsIdnEmail } from './idn-email.mjs';
8
+ export { IsIdnHostname } from './idn-hostname.mjs';
9
+ export { IsIPv4 } from './ipv4.mjs';
10
+ export { IsIPv6 } from './ipv6.mjs';
11
+ export { IsIriReference } from './iri-reference.mjs';
12
+ export { IsIri } from './iri.mjs';
13
+ export { IsJsonPointerUriFragment } from './json-pointer-uri-fragment.mjs';
14
+ export { IsJsonPointer } from './json-pointer.mjs';
15
+ export { IsRegex } from './regex.mjs';
16
+ export { IsRelativeJsonPointer } from './relative-json-pointer.mjs';
17
+ export { IsTime } from './time.mjs';
18
+ export { IsUriReference } from './uri-reference.mjs';
19
+ export { IsUriTemplate } from './uri-template.mjs';
20
+ export { IsUri } from './uri.mjs';
21
+ export { IsUrl } from './url.mjs';
22
+ export { IsUuid } from './uuid.mjs';
@@ -1,22 +1,22 @@
1
1
  export * from './_registry.mjs';
2
- export * from './date-time.mjs';
3
- export * from './date.mjs';
4
- export * from './duration.mjs';
5
- export * from './email.mjs';
6
- export * from './hostname.mjs';
7
- export * from './idn-email.mjs';
8
- export * from './idn-hostname.mjs';
9
- export * from './ipv4.mjs';
10
- export * from './ipv6.mjs';
11
- export * from './iri-reference.mjs';
12
- export * from './iri.mjs';
13
- export * from './json-pointer-uri-fragment.mjs';
14
- export * from './json-pointer.mjs';
15
- export * from './regex.mjs';
16
- export * from './relative-json-pointer.mjs';
17
- export * from './time.mjs';
18
- export * from './uri-reference.mjs';
19
- export * from './uri-template.mjs';
20
- export * from './uri.mjs';
21
- export * from './url.mjs';
22
- export * from './uuid.mjs';
2
+ export { IsDateTime } from './date-time.mjs';
3
+ export { IsDate } from './date.mjs';
4
+ export { IsDuration } from './duration.mjs';
5
+ export { IsEmail } from './email.mjs';
6
+ export { IsHostname } from './hostname.mjs';
7
+ export { IsIdnEmail } from './idn-email.mjs';
8
+ export { IsIdnHostname } from './idn-hostname.mjs';
9
+ export { IsIPv4 } from './ipv4.mjs';
10
+ export { IsIPv6 } from './ipv6.mjs';
11
+ export { IsIriReference } from './iri-reference.mjs';
12
+ export { IsIri } from './iri.mjs';
13
+ export { IsJsonPointerUriFragment } from './json-pointer-uri-fragment.mjs';
14
+ export { IsJsonPointer } from './json-pointer.mjs';
15
+ export { IsRegex } from './regex.mjs';
16
+ export { IsRelativeJsonPointer } from './relative-json-pointer.mjs';
17
+ export { IsTime } from './time.mjs';
18
+ export { IsUriReference } from './uri-reference.mjs';
19
+ export { IsUriTemplate } from './uri-template.mjs';
20
+ export { IsUri } from './uri.mjs';
21
+ export { IsUrl } from './url.mjs';
22
+ export { IsUuid } from './uuid.mjs';
@@ -1,2 +1,5 @@
1
- /** Returns true if the value is a Hostname */
1
+ /**
2
+ * Returns true if the value matches RFC 1123 hostname syntax.
3
+ * @specification https://tools.ietf.org/html/rfc1123
4
+ */
2
5
  export declare function IsHostname(value: string): boolean;
@@ -1,5 +1,34 @@
1
- const Hostname = /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i;
2
- /** Returns true if the value is a Hostname */
1
+ /**
2
+ * Returns true if the value matches RFC 1123 hostname syntax.
3
+ * @specification https://tools.ietf.org/html/rfc1123
4
+ */
3
5
  export function IsHostname(value) {
4
- return Hostname.test(value);
6
+ if (value.length > 253 || value.length === 0)
7
+ return false;
8
+ let start = 0;
9
+ let prev = 0;
10
+ for (let i = 0; i < value.length; i++) {
11
+ const ch = value.charCodeAt(i);
12
+ if (ch === 46) { // '.'
13
+ // trailing dot is valid e.g. "example.com." but not "."
14
+ if (i === value.length - 1 && start < i)
15
+ break;
16
+ const len = i - start;
17
+ if (len === 0 || len > 63 || value.charCodeAt(start) === 45 || prev === 45)
18
+ return false;
19
+ start = i + 1;
20
+ }
21
+ else if (!((ch >= 97 && ch <= 122) || // a-z
22
+ (ch >= 65 && ch <= 90) || // A-Z
23
+ (ch >= 48 && ch <= 57) || // 0-9
24
+ ch === 45 // '-'
25
+ )) {
26
+ return false;
27
+ }
28
+ prev = ch;
29
+ }
30
+ const length = value.length - start;
31
+ const first = value.charCodeAt(start);
32
+ const last = value.charCodeAt(value.length - 1);
33
+ return length > 0 && length <= 63 && first !== 45 && last !== 45;
5
34
  }
@@ -1,2 +1,5 @@
1
- /** Returns true if the value is a Idn Email */
1
+ /**
2
+ * Returns true if the value is an IdnEmail
3
+ * @specification Json Schema 2020-12
4
+ */
2
5
  export declare function IsIdnEmail(value: string): boolean;
@@ -1,5 +1,8 @@
1
- const IdnEmail = /^(?!.*\.\.)[\p{L}\p{N}!#$%&'*+/=?^_`{|}~-]+(?:\.[\p{L}\p{N}!#$%&'*+/=?^_`{|}~-]+)*@[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,61}[\p{L}\p{N}])?(?:\.[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,61}[\p{L}\p{N}])?)*$/iu;
2
- /** Returns true if the value is a Idn Email */
1
+ import { IsEmail } from './email.mjs';
2
+ /**
3
+ * Returns true if the value is an IdnEmail
4
+ * @specification Json Schema 2020-12
5
+ */
3
6
  export function IsIdnEmail(value) {
4
- return IdnEmail.test(value);
7
+ return IsEmail(value);
5
8
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Returns true if the value is a Hostname
3
- * @specification
2
+ * Returns true if the value is an IDN Hostname
3
+ * @specification Json Schema 2020-12
4
4
  */
5
5
  export declare function IsIdnHostname(value: string): boolean;
@@ -1,124 +1,115 @@
1
- function IsValidAdjacentForKatakanaMiddleDot(char) {
2
- const codePoint = char.codePointAt(0);
3
- // deno-coverage-ignore - internal condition never reached
4
- if (codePoint === undefined)
5
- return false;
6
- return ((codePoint >= 0x3040 && codePoint <= 0x309F) || // Hiragana
7
- (codePoint >= 0x30A0 && codePoint <= 0x30FF && codePoint !== 0x30FB) || // Katakana (excluding U+30FB)
8
- (codePoint >= 0x4E00 && codePoint <= 0x9FFF) // Han (CJK Unified Ideographs)
1
+ function IsValidAdjacentForKatakanaMiddleDot(cp) {
2
+ return ((cp >= 0x3040 && cp <= 0x309F) || // Hiragana
3
+ (cp >= 0x30A0 && cp <= 0x30FF && cp !== 0x30FB) || // Katakana (excluding U+30FB)
4
+ (cp >= 0x4E00 && cp <= 0x9FFF) // Han (CJK Unified Ideographs)
9
5
  );
10
6
  }
11
7
  /**
12
- * Returns true if the value is a Hostname
13
- * @specification
8
+ * Returns true if the value is an IDN Hostname
9
+ * @specification Json Schema 2020-12
14
10
  */
15
11
  export function IsIdnHostname(value) {
16
- if (value.length === 0)
17
- return false;
18
- if (value.includes(' '))
12
+ if (value.length === 0 || value.includes(' '))
19
13
  return false;
20
- // Allowed label separators per RFC3490: U+002E, U+3002, U+FF0E, U+FF61.
21
- const separators = /[\u002E\u3002\uFF0E\uFF61]/g;
22
- // Normalize (NFC) and replace allowed separators with a dot.
23
- const normalized = value.normalize('NFC').replace(separators, '.');
14
+ // Normalize (NFC) and replace allowed separators with a dot
15
+ // Allowed label separators per RFC3490: U+002E, U+3002, U+FF0E, U+FF61
16
+ const normalized = value.normalize('NFC').replace(/[\u002E\u3002\uFF0E\uFF61]/g, '.');
24
17
  if (normalized.length > 253)
25
18
  return false;
26
- // Split into labels; disallow empty labels.
27
19
  const labels = normalized.split('.');
28
- if (labels.some((label) => label.length === 0))
29
- return false;
30
20
  for (const label of labels) {
31
- // Each label must be 63 characters.
32
- if (label.length > 63)
21
+ if (label.length === 0 || label.length > 63)
33
22
  return false;
34
- // Labels must not begin or end with a hyphen.
35
- if (label.startsWith('-') || label.endsWith('-'))
23
+ // Labels must not begin or end with a hyphen
24
+ if (label.charCodeAt(0) === 45 || label.charCodeAt(label.length - 1) === 45)
36
25
  return false;
37
- // A-label (punycode) checks.
38
- if (/^xn--/i.test(label)) {
26
+ // A-label (punycode) checks
27
+ if ((label.charCodeAt(0) === 120 || label.charCodeAt(0) === 88) && // 'x' or 'X'
28
+ (label.charCodeAt(1) === 110 || label.charCodeAt(1) === 78) && // 'n' or 'N'
29
+ label.charCodeAt(2) === 45 && // '-'
30
+ label.charCodeAt(3) === 45 // '-'
31
+ ) {
39
32
  const punycodePart = label.slice(4);
40
- if (punycodePart.length < 2)
41
- return false;
42
- if (punycodePart.includes('---'))
33
+ if (punycodePart.length < 2 || punycodePart.includes('---'))
43
34
  return false;
44
35
  continue;
45
36
  }
46
- // U-label: Reject if any disallowed code points occur.
47
- // Disallowed: U+302E, U+302F, U+3031, U+3032, U+3033, U+3034, U+3035, U+303B, U+0640, U+07FA.
48
- if (/[\u302E\u302F\u3031\u3032\u3033\u3034\u3035\u303B\u0640\u07FA]/.test(label)) {
49
- return false;
50
- }
51
- // Disallow labels starting with certain combining marks.
52
- const firstChar = label.charAt(0);
53
- if (/[\u0903\u0300\u0488]/.test(firstChar))
54
- return false;
55
- // Check each character within the label.
37
+ // U-label checks
38
+ let hasArabicIndic = false;
39
+ let hasExtendedArabicIndic = false;
56
40
  for (let i = 0; i < label.length; i++) {
57
- const char = label.charAt(i);
58
- // --- MIDDLE DOT (U+00B7) ---
59
- // Must be flanked on both sides by "l" or "L".
60
- if (char === '\u00B7') {
41
+ // deno-coverage-ignore
42
+ const cp = label.codePointAt(i) ?? 0;
43
+ // Disallowed code points
44
+ if (cp === 0x302E || cp === 0x302F ||
45
+ cp === 0x3031 || cp === 0x3032 || cp === 0x3033 || cp === 0x3034 || cp === 0x3035 ||
46
+ cp === 0x303B || cp === 0x0640 || cp === 0x07FA)
47
+ return false;
48
+ // Disallow labels starting with certain combining marks
49
+ if (i === 0 && (cp === 0x0903 || cp === 0x0300 || cp === 0x0488))
50
+ return false;
51
+ // MIDDLE DOT (U+00B7) must be flanked by 'l' or 'L'
52
+ if (cp === 0x00B7) {
61
53
  if (i === 0 || i === label.length - 1)
62
54
  return false;
63
- const prev = label.charAt(i - 1);
64
- const next = label.charAt(i + 1);
65
- if (!/^[lL]$/.test(prev) || !/^[lL]$/.test(next))
55
+ // deno-coverage-ignore
56
+ const prev = label.codePointAt(i - 1) ?? 0;
57
+ // deno-coverage-ignore
58
+ const next = label.codePointAt(i + 1) ?? 0;
59
+ if ((prev !== 108 && prev !== 76) || (next !== 108 && next !== 76))
66
60
  return false;
67
61
  }
68
- // --- KATAKANA MIDDLE DOT (U+30FB) ---
69
- if (char === '\u30FB') {
70
- // If label is a single character, it's invalid.
62
+ // KATAKANA MIDDLE DOT (U+30FB) | U+30FB is below U+FFFF so stride is always 1
63
+ if (cp === 0x30FB) {
71
64
  if (label.length === 1)
72
65
  return false;
73
66
  if (i === 0) {
74
- // At beginning: check following character.
75
- const next = label.charAt(i + 1);
67
+ // deno-coverage-ignore
68
+ const next = label.codePointAt(i + 1) ?? 0;
76
69
  if (!IsValidAdjacentForKatakanaMiddleDot(next))
77
70
  return false;
78
71
  }
79
72
  else {
80
- // In the middle: check both adjacent characters.
81
- const prev = label.charAt(i - 1);
82
- const next = label.charAt(i + 1);
83
- if (!IsValidAdjacentForKatakanaMiddleDot(prev) || !IsValidAdjacentForKatakanaMiddleDot(next)) {
73
+ // deno-coverage-ignore
74
+ const prev = label.codePointAt(i - 1) ?? 0;
75
+ // deno-coverage-ignore
76
+ const next = label.codePointAt(i + 1) ?? 0;
77
+ if (!IsValidAdjacentForKatakanaMiddleDot(prev) || !IsValidAdjacentForKatakanaMiddleDot(next))
84
78
  return false;
85
- }
86
79
  }
87
80
  }
88
- // --- Greek Keraia (U+0375) ---
89
- if (char === '\u0375') {
81
+ // Greek KERAIA (U+0375) | U+0375 is below U+FFFF so stride is always 1
82
+ if (cp === 0x0375) {
90
83
  if (i === label.length - 1)
91
84
  return false;
92
- const next = label.charAt(i + 1);
93
- if (!/[\u0370-\u03FF]/.test(next))
85
+ // deno-coverage-ignore
86
+ const next = label.codePointAt(i + 1) ?? 0;
87
+ if (next < 0x0370 || next > 0x03FF)
94
88
  return false;
95
89
  }
96
- // --- Hebrew GERESH (U+05F3) and GERSHAYIM (U+05F4) ---
97
- if (char === '\u05F3' || char === '\u05F4') {
90
+ // Hebrew GERESH (U+05F3) and GERSHAYIM (U+05F4)
91
+ if (cp === 0x05F3 || cp === 0x05F4) {
98
92
  if (i === 0)
99
93
  return false;
100
- const prev = label.charAt(i - 1);
101
- if (!/[\u05D0-\u05EA]/.test(prev))
94
+ // deno-coverage-ignore
95
+ const prev = label.codePointAt(i - 1) ?? 0;
96
+ if (prev < 0x05D0 || prev > 0x05EA)
102
97
  return false;
103
98
  }
104
- // --- ZERO WIDTH JOINER (U+200D) ---
105
- if (char === '\u200D') {
99
+ // ZERO WIDTH JOINER (U+200D)
100
+ if (cp === 0x200D) {
106
101
  if (i === 0)
107
102
  return false;
108
- const prev = label.charAt(i - 1);
109
- if (prev !== '\u094D')
103
+ // deno-coverage-ignore
104
+ const prev = label.codePointAt(i - 1) ?? 0;
105
+ if (prev !== 0x094D)
110
106
  return false;
111
107
  }
112
- // ZERO WIDTH NON-JOINER (U+200C) is allowed.
113
- }
114
- // --- Arabic-Indic digits vs. Extended Arabic-Indic digits ---
115
- let hasArabicIndic = false;
116
- let hasExtendedArabicIndic = false;
117
- for (let i = 0; i < label.length; i++) {
118
- const char = label.charAt(i);
119
- if (/[\u0660-\u0669]/.test(char))
108
+ // Arabic-Indic digits
109
+ if (cp >= 0x0660 && cp <= 0x0669)
120
110
  hasArabicIndic = true;
121
- if (/[\u06F0-\u06F9]/.test(char))
111
+ // Extended Arabic-Indic digits
112
+ if (cp >= 0x06F0 && cp <= 0x06F9)
122
113
  hasExtendedArabicIndic = true;
123
114
  }
124
115
  if (hasArabicIndic && hasExtendedArabicIndic)
@@ -1,6 +1,6 @@
1
+ export declare function IsIPv4Internal(value: string, start: number, end: number): boolean;
1
2
  /**
2
3
  * Returns true if the value is a IPV4 address
3
- * @source ajv-formats
4
4
  * @specification http://tools.ietf.org/html/rfc2673#section-3.2
5
5
  */
6
6
  export declare function IsIPv4(value: string): boolean;
@@ -1,9 +1,38 @@
1
- const IPv4 = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;
1
+ // ------------------------------------------------------------------
2
+ // Ranged Fast Path
3
+ // ------------------------------------------------------------------
4
+ /* Returns true if the value is a IPV4 address from index range offsets */
5
+ export function IsIPv4Internal(value, start, end) {
6
+ let dots = 0;
7
+ let num = 0;
8
+ let digits = 0;
9
+ let leading = 0;
10
+ for (let i = start; i < end; i++) {
11
+ const ch = value.charCodeAt(i);
12
+ if (ch === 46) { // '.'
13
+ if (digits === 0 || num > 255 || (leading === 48 && digits > 1))
14
+ return false;
15
+ dots++;
16
+ num = 0;
17
+ digits = 0;
18
+ leading = 0;
19
+ }
20
+ else if (ch >= 48 && ch <= 57) { // '0'-'9'
21
+ if (digits === 0)
22
+ leading = ch;
23
+ num = num * 10 + (ch - 48);
24
+ digits++;
25
+ }
26
+ else {
27
+ return false;
28
+ }
29
+ }
30
+ return dots === 3 && digits > 0 && num <= 255 && !(leading === 48 && digits > 1);
31
+ }
2
32
  /**
3
33
  * Returns true if the value is a IPV4 address
4
- * @source ajv-formats
5
34
  * @specification http://tools.ietf.org/html/rfc2673#section-3.2
6
35
  */
7
36
  export function IsIPv4(value) {
8
- return IPv4.test(value);
37
+ return IsIPv4Internal(value, 0, value.length);
9
38
  }
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Returns true if the value is a IPV6 address
3
- * @source ajv-formats
2
+ * Returns true if the value is an IPv6 address
4
3
  * @specification http://tools.ietf.org/html/rfc2373#section-2.2
5
4
  */
6
5
  export declare function IsIPv6(value: string): boolean;
@@ -1,9 +1,67 @@
1
- const IPv6 = /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i;
1
+ import { IsIPv4Internal } from './ipv4.mjs';
2
+ function InRange(ch) {
3
+ return (ch >= 48 && ch <= 57) || // 0-9
4
+ (ch >= 65 && ch <= 70) || // A-F
5
+ (ch >= 97 && ch <= 102); // a-f
6
+ }
2
7
  /**
3
- * Returns true if the value is a IPV6 address
4
- * @source ajv-formats
8
+ * Returns true if the value is an IPv6 address
5
9
  * @specification http://tools.ietf.org/html/rfc2373#section-2.2
6
10
  */
7
11
  export function IsIPv6(value) {
8
- return IPv6.test(value);
12
+ const length = value.length;
13
+ if (length === 0)
14
+ return false;
15
+ let groups = 0;
16
+ let compressed = false;
17
+ let i = 0;
18
+ // handle leading '::'
19
+ if (value.charCodeAt(0) === 58 && value.charCodeAt(1) === 58) {
20
+ if (length === 2)
21
+ return true; // '::' is valid
22
+ compressed = true;
23
+ i = 2;
24
+ }
25
+ while (i < length) {
26
+ // read hex digits
27
+ let digits = 0;
28
+ const start = i;
29
+ while (i < length && InRange(value.charCodeAt(i))) {
30
+ i++;
31
+ digits++;
32
+ }
33
+ if (digits === 0)
34
+ return false;
35
+ const next = value.charCodeAt(i);
36
+ // check for embedded IPv4 at the end
37
+ if (next === 46) { // '.'
38
+ if (!IsIPv4Internal(value, start, length))
39
+ return false;
40
+ groups += 2;
41
+ i = length;
42
+ break;
43
+ }
44
+ if (digits > 4)
45
+ return false;
46
+ groups++;
47
+ if (i === length)
48
+ break;
49
+ // expect ':' separator
50
+ if (next !== 58)
51
+ return false;
52
+ i++;
53
+ // check for '::' compression
54
+ if (value.charCodeAt(i) === 58) {
55
+ if (compressed)
56
+ return false; // only one '::' allowed
57
+ // check for ':::'
58
+ if (value.charCodeAt(i + 1) === 58)
59
+ return false;
60
+ compressed = true;
61
+ i++;
62
+ if (i === length)
63
+ break; // trailing '::'
64
+ }
65
+ }
66
+ return compressed ? groups <= 7 : groups === 8;
9
67
  }
@@ -1,6 +1,5 @@
1
1
  /**
2
- * Returns true if the value is a uri
3
- * @specification
4
- * @source ajv-formats
2
+ * Returns true if the value matches RFC 3986 URI syntax.
3
+ * @specification https://tools.ietf.org/html/rfc3986
5
4
  */
6
5
  export declare function IsUri(value: string): boolean;
@@ -1,9 +1,135 @@
1
- const Uri = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i;
1
+ function IsAlpha(ch) {
2
+ return (ch >= 97 && ch <= 122) || (ch >= 65 && ch <= 90); // a-z, A-Z
3
+ }
4
+ function IsAlphaNumeric(ch) {
5
+ return IsAlpha(ch) || (ch >= 48 && ch <= 57); // a-z, A-Z, 0-9
6
+ }
7
+ function IsHex(ch) {
8
+ return (ch >= 48 && ch <= 57) || // 0-9
9
+ (ch >= 65 && ch <= 70) || // A-F
10
+ (ch >= 97 && ch <= 102); // a-f
11
+ }
12
+ function IsSchemeChar(ch) {
13
+ return IsAlphaNumeric(ch) ||
14
+ ch === 43 || ch === 45 || ch === 46; // '+', '-', '.'
15
+ }
16
+ function IsUnreserved(ch) {
17
+ return IsAlphaNumeric(ch) ||
18
+ ch === 45 || ch === 46 || // '-', '.'
19
+ ch === 95 || ch === 126; // '_', '~'
20
+ }
21
+ function IsSubDelim(ch) {
22
+ return ch === 33 || ch === 36 || ch === 38 || ch === 39 ||
23
+ ch === 40 || ch === 41 || ch === 42 || ch === 43 ||
24
+ ch === 44 || ch === 59 || ch === 61; // ! $ & ' ( ) * + , ; =
25
+ }
26
+ function IsPchar(ch) {
27
+ return IsUnreserved(ch) || IsSubDelim(ch) || ch === 58 || ch === 64; // ':', '@'
28
+ }
2
29
  /**
3
- * Returns true if the value is a uri
4
- * @specification
5
- * @source ajv-formats
30
+ * Returns true if the value matches RFC 3986 URI syntax.
31
+ * @specification https://tools.ietf.org/html/rfc3986
6
32
  */
7
33
  export function IsUri(value) {
8
- return Uri.test(value);
34
+ const length = value.length;
35
+ if (length === 0)
36
+ return false;
37
+ // Scheme: must start with a letter
38
+ if (!IsAlpha(value.charCodeAt(0)))
39
+ return false;
40
+ // Scheme: continues until ':'
41
+ let i = 1;
42
+ while (i < length) {
43
+ const ch = value.charCodeAt(i);
44
+ if (ch === 58)
45
+ break; // ':'
46
+ if (!IsSchemeChar(ch))
47
+ return false;
48
+ i++;
49
+ }
50
+ // Ensure scheme is terminated by ':'
51
+ if (value.charCodeAt(i) !== 58)
52
+ return false;
53
+ i++;
54
+ // Authority: optional '//'
55
+ if (value.charCodeAt(i) === 47 && value.charCodeAt(i + 1) === 47) {
56
+ i += 2;
57
+ // Userinfo: check for '@' before path/query/fragment delimiters
58
+ const authorityStart = i;
59
+ let atPos = -1;
60
+ for (let j = i; j < length; j++) {
61
+ const ch = value.charCodeAt(j);
62
+ if (ch === 64) {
63
+ atPos = j;
64
+ break;
65
+ } // '@'
66
+ if (ch === 47 || ch === 63 || ch === 35)
67
+ break; // '/', '?', '#'
68
+ }
69
+ if (atPos !== -1) {
70
+ // Userinfo: validate allowed chars and percent-encoding
71
+ for (let j = authorityStart; j < atPos; j++) {
72
+ const ch = value.charCodeAt(j);
73
+ if (ch === 91 || ch === 93)
74
+ return false; // No '[' or ']' in userinfo
75
+ if (ch === 37) { // '%' percent-encoding
76
+ if (j + 2 >= atPos || !IsHex(value.charCodeAt(j + 1)) || !IsHex(value.charCodeAt(j + 2)))
77
+ return false;
78
+ j += 2;
79
+ }
80
+ else if (!IsUnreserved(ch) && !IsSubDelim(ch) && ch !== 58)
81
+ return false;
82
+ }
83
+ i = atPos + 1;
84
+ }
85
+ // Host: IP-literal [addr] or reg-name
86
+ if (value.charCodeAt(i) === 91) { // '['
87
+ i++;
88
+ while (i < length && value.charCodeAt(i) !== 93)
89
+ i++;
90
+ if (value.charCodeAt(i) !== 93)
91
+ return false; // ']'
92
+ i++;
93
+ }
94
+ else {
95
+ // Host: validate ASCII; skip validation for non-ASCII (Unicode hosts)
96
+ while (i < length) {
97
+ const ch = value.charCodeAt(i);
98
+ if (ch === 47 || ch === 63 || ch === 35 || ch === 58)
99
+ break;
100
+ if (ch < 128 && !IsUnreserved(ch) && !IsSubDelim(ch))
101
+ return false;
102
+ i++;
103
+ }
104
+ }
105
+ // Port: optional digits after ':'
106
+ if (value.charCodeAt(i) === 58) { // ':'
107
+ i++;
108
+ while (i < length) {
109
+ const ch = value.charCodeAt(i);
110
+ if (ch === 47 || ch === 63 || ch === 35)
111
+ break;
112
+ if (ch < 48 || ch > 57)
113
+ return false; // 0-9
114
+ i++;
115
+ }
116
+ }
117
+ }
118
+ // Path, Query, and Fragment
119
+ while (i < length) {
120
+ const ch = value.charCodeAt(i);
121
+ if (ch === 37) { // '%' percent-encoding
122
+ if (i + 2 >= length || !IsHex(value.charCodeAt(i + 1)) || !IsHex(value.charCodeAt(i + 2)))
123
+ return false;
124
+ i += 2;
125
+ }
126
+ else if (ch > 127) {
127
+ return false; // URI is ASCII-only
128
+ }
129
+ else if (!(IsPchar(ch) || ch === 47 || ch === 63 || ch === 35)) {
130
+ return false; // '/', '?', '#'
131
+ }
132
+ i++;
133
+ }
134
+ return true;
9
135
  }
@@ -3,10 +3,10 @@ import { type TIdentifier } from '../types/identifier.mjs';
3
3
  import { type TDeferred } from '../types/deferred.mjs';
4
4
  import { type TInstantiate } from '../engine/instantiate.mjs';
5
5
  /** Creates a deferred Mapped action. */
6
- export type TMappedDeferred<Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema> = (TDeferred<'Mapped', [Identifier, Key, As, Property]>);
6
+ export type TMappedDeferred<Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema> = (TDeferred<'Mapped', [Identifier, Type, As, Property]>);
7
7
  /** Creates a deferred Mapped action. */
8
- export declare function MappedDeferred<Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema>(identifier: Identifier, key: Key, as: As, property: Property, options?: TSchemaOptions): TMappedDeferred<Identifier, Key, As, Property>;
8
+ export declare function MappedDeferred<Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema>(identifier: Identifier, type: Type, as: As, property: Property, options?: TSchemaOptions): TMappedDeferred<Identifier, Type, As, Property>;
9
9
  /** Applies a Mapped action using the given types. */
10
- export type TMapped<Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema> = (TInstantiate<{}, TMappedDeferred<Identifier, Key, As, Property>>);
10
+ export type TMapped<Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema> = (TInstantiate<{}, TMappedDeferred<Identifier, Type, As, Property>>);
11
11
  /** Applies a Mapped action using the given types. */
12
- export declare function Mapped<Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema>(identifier: Identifier, key: Key, as: As, property: Property, options?: TSchemaOptions): TMapped<Identifier, Key, As, Property>;
12
+ export declare function Mapped<Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema>(identifier: Identifier, type: Type, as: As, property: Property, options?: TSchemaOptions): TMapped<Identifier, Type, As, Property>;
@@ -2,10 +2,10 @@
2
2
  import { Deferred } from '../types/deferred.mjs';
3
3
  import { Instantiate } from '../engine/instantiate.mjs';
4
4
  /** Creates a deferred Mapped action. */
5
- export function MappedDeferred(identifier, key, as, property, options = {}) {
6
- return Deferred('Mapped', [identifier, key, as, property], options);
5
+ export function MappedDeferred(identifier, type, as, property, options = {}) {
6
+ return Deferred('Mapped', [identifier, type, as, property], options);
7
7
  }
8
8
  /** Applies a Mapped action using the given types. */
9
- export function Mapped(identifier, key, as, property, options = {}) {
10
- return Instantiate({}, MappedDeferred(identifier, key, as, property, options));
9
+ export function Mapped(identifier, type, as, property, options = {}) {
10
+ return Instantiate({}, MappedDeferred(identifier, type, as, property, options));
11
11
  }
@@ -3,13 +3,13 @@ import { type TUnion } from '../../types/union.mjs';
3
3
  import { type TDeferred } from '../../types/deferred.mjs';
4
4
  import { type TRef } from '../../types/ref.mjs';
5
5
  import { type TParameter } from '../../types/parameter.mjs';
6
- type TCollectDistributionNames<Expression extends TSchema, Result extends string[] = []> = (Expression extends TDeferred<'Conditional', [infer Left extends TSchema, infer _Right extends TSchema, infer True extends TSchema, infer False extends TSchema]> ? Left extends TRef<infer Name extends string> ? TCollectDistributionNames<True, TCollectDistributionNames<False, [...Result, Name]>> : TCollectDistributionNames<True, TCollectDistributionNames<False, Result>> : Result);
6
+ type TCollectDistributionNames<Expression extends TSchema, Result extends string[] = []> = (Expression extends TDeferred<'Conditional', [infer Left extends TSchema, infer _Right extends TSchema, infer True extends TSchema, infer False extends TSchema]> ? Left extends TRef<infer Name extends string> ? TCollectDistributionNames<True, TCollectDistributionNames<False, [...Result, Name]>> : TCollectDistributionNames<True, TCollectDistributionNames<False, Result>> : Expression extends TDeferred<'Mapped', [infer _Identifier extends TSchema, infer Type extends TSchema, infer _As extends TSchema, infer _Property extends TSchema]> ? (Type extends TDeferred<'KeyOf', [infer Ref extends TRef]> ? [...Result, Ref['$ref']] : Result) : Result);
7
7
  type TBuildDistributionArray<Parameters extends TParameter[], Names extends string[], Result extends boolean[] = []> = (Parameters extends [infer Left extends TParameter, ...infer Right extends TParameter[]] ? Left['name'] extends Names[number] ? TBuildDistributionArray<Right, Names, [...Result, true]> : TBuildDistributionArray<Right, Names, [...Result, false]> : Result);
8
8
  type TZipDistributionArray<Arguments extends TSchema[], DistributionArray extends boolean[], Result extends [boolean, TSchema][] = []> = (Arguments extends [infer ArgumentLeft extends TSchema, ...infer ArgumentRight extends TSchema[]] ? DistributionArray extends [infer BooleanLeft extends boolean, ...infer BooleanRight extends boolean[]] ? TZipDistributionArray<ArgumentRight, BooleanRight, [...Result, [BooleanLeft, ArgumentLeft]]> : Result : Result);
9
9
  type TExpand<Type extends TSchema> = (Type extends TUnion<infer Types extends TSchema[]> ? [...Types] : [Type]);
10
10
  type TAppend<Current extends TSchema[][], Type extends TSchema, Result extends TSchema[][] = []> = (Current extends [infer Left extends TSchema[], ...infer Right extends TSchema[][]] ? TAppend<Right, Type, [...Result, [...Left, Type]]> : Result);
11
11
  type TCross<Current extends TSchema[][], Variants extends TSchema[], Result extends TSchema[][] = []> = (Variants extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TCross<Current, Right, [...Result, ...TAppend<Current, Left>]> : Result);
12
12
  type TDistribute<ZippedArguments extends [boolean, TSchema][], Result extends TSchema[][] = [[]]> = (ZippedArguments extends [infer Left extends [boolean, TSchema], ...infer Right extends [boolean, TSchema][]] ? Left[0] extends true ? TDistribute<Right, TCross<Result, TExpand<Left[1]>>> : TDistribute<Right, TCross<Result, [Left[1]]>> : Result);
13
- export type TDistributeArguments<Parameters extends TParameter[], Arguments extends TSchema[], Expression extends TSchema, DistributionNames extends string[] = TCollectDistributionNames<Expression>, DistributionArray extends boolean[] = TBuildDistributionArray<Parameters, DistributionNames>, ZippedArguments extends [boolean, TSchema][] = TZipDistributionArray<Arguments, DistributionArray>, Result extends TSchema[][] = Expression extends TDeferred<'Conditional', TSchema[]> ? TDistribute<ZippedArguments> : [Arguments]> = Result;
13
+ export type TDistributeArguments<Parameters extends TParameter[], Arguments extends TSchema[], Expression extends TSchema, DistributionNames extends string[] = TCollectDistributionNames<Expression>, DistributionArray extends boolean[] = TBuildDistributionArray<Parameters, DistributionNames>, ZippedArguments extends [boolean, TSchema][] = TZipDistributionArray<Arguments, DistributionArray>, Result extends TSchema[][] = (Expression extends TDeferred<'Conditional', TSchema[]> ? TDistribute<ZippedArguments> : Expression extends TDeferred<'Mapped', TSchema[]> ? TDistribute<ZippedArguments> : [Arguments])> = Result;
14
14
  export declare function DistributeArguments<Parameters extends TParameter[], Arguments extends TSchema[], Expression extends TSchema>(parameters: [...Parameters], arguments_: [...Arguments], expression: Expression): TDistributeArguments<Parameters, Arguments, Expression>;
15
15
  export {};
@@ -4,11 +4,16 @@ import { IsUnion } from '../../types/union.mjs';
4
4
  import { IsDeferred } from '../../types/deferred.mjs';
5
5
  import { IsRef } from '../../types/ref.mjs';
6
6
  function CollectDistributionNames(expression, result = []) {
7
- return (IsDeferred(expression) && Guard.IsEqual(expression.action, 'Conditional')
7
+ return (
8
+ // Conditional
9
+ IsDeferred(expression) && Guard.IsEqual(expression.action, 'Conditional')
8
10
  ? IsRef(expression.parameters[0])
9
11
  ? CollectDistributionNames(expression.parameters[2], CollectDistributionNames(expression.parameters[3], [...result, expression.parameters[0].$ref]))
10
12
  : CollectDistributionNames(expression.parameters[2], CollectDistributionNames(expression.parameters[3], result))
11
- : result);
13
+ // Mapped
14
+ : IsDeferred(expression) && Guard.IsEqual(expression.action, 'Mapped')
15
+ ? (IsDeferred(expression.parameters[1]) && Guard.IsEqual(expression.parameters[1].action, 'KeyOf') && IsRef(expression.parameters[1].parameters[0]) ? [...result, expression.parameters[1].parameters[0]['$ref']] :
16
+ result) : result);
12
17
  }
13
18
  function BuildDistributionArray(parameters, names) {
14
19
  return parameters.reduce((result, left) => [...result, names.includes(left.name)], []);
@@ -48,5 +53,7 @@ export function DistributeArguments(parameters, arguments_, expression) {
48
53
  const zippedArguments = ZipDistributionArray(arguments_, distributionArray);
49
54
  return (IsDeferred(expression) && Guard.IsEqual(expression.action, 'Conditional')
50
55
  ? Distribute(zippedArguments)
51
- : [arguments_]);
56
+ : IsDeferred(expression) && Guard.IsEqual(expression.action, 'Mapped')
57
+ ? Distribute(zippedArguments)
58
+ : [arguments_]);
52
59
  }
@@ -31,7 +31,7 @@ function CallDistributed(context, state, target, parameters, expression, distrib
31
31
  function CallImmediate(context, state, target, parameters, expression, arguments_) {
32
32
  const distributedArguments = DistributeArguments(parameters, arguments_, expression);
33
33
  const returnTypes = CallDistributed(context, state, target, parameters, expression, distributedArguments);
34
- const result = returnTypes.length === 1 ? returnTypes[0] : EvaluateUnion(returnTypes);
34
+ const result = Guard.IsEqual(returnTypes.length, 1) ? returnTypes[0] : EvaluateUnion(returnTypes);
35
35
  return result;
36
36
  }
37
37
  export function CallInstantiate(context, state, target, arguments_) {
@@ -4,25 +4,22 @@ import { type TLiteral } from '../../types/literal.mjs';
4
4
  import { type TObject } from '../../types/object.mjs';
5
5
  import { type TProperties } from '../../types/properties.mjs';
6
6
  import { type TIdentifier } from '../../types/identifier.mjs';
7
- import { type TMappedKeys } from './mapped-keys.mjs';
8
7
  import { type TTemplateLiteral } from '../../types/template-literal.mjs';
9
8
  import { type TMappedDeferred } from '../../action/mapped.mjs';
10
9
  import { type TTemplateLiteralDecode } from '../template-literal/decode.mjs';
11
10
  import { type TState, type TInstantiateType, type TCanInstantiate } from '../instantiate.mjs';
12
- type TInstantiateKeyAs<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, ContextWithKey extends TProperties = Memory.TAssign<Context, {
13
- [_ in Identifier['name']]: Key;
14
- }>, InstantiatedKeyAs extends TSchema = TInstantiateType<ContextWithKey, State, As>, Result extends TSchema = InstantiatedKeyAs extends TTemplateLiteral<infer Pattern extends string> ? TTemplateLiteralDecode<Pattern> : InstantiatedKeyAs> = Result;
15
- type TInstantiateProperty<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, Property extends TSchema, ContextWithKey extends TProperties = Memory.TAssign<Context, {
16
- [_ in Identifier['name']]: Key;
17
- }>, InstantiatedProperty extends TSchema = TInstantiateType<ContextWithKey, State, Property>> = InstantiatedProperty;
18
- type TMappedProperty<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema, InstantiatedProperty extends TSchema = TInstantiateProperty<Context, State, Identifier, Key, Property>, InstantiatedKeyAs extends TSchema = TInstantiateKeyAs<Context, State, Identifier, Key, As>, Result extends TProperties = (InstantiatedKeyAs extends TLiteral<string | number> ? {
19
- [_ in InstantiatedKeyAs['const']]: InstantiatedProperty;
20
- } : {})> = Result;
21
- type TMappedProperties<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Keys extends TSchema[], As extends TSchema, Type extends TSchema, Result extends TProperties = {}> = (Keys extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TMappedProperties<Context, State, Identifier, Right, As, Type, Result & TMappedProperty<Context, State, Identifier, Left, As, Type>> : Result);
22
- type TMappedAction<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema, Keys extends TSchema[] = TMappedKeys<Key>, Mapped extends TProperties = TMappedProperties<Context, State, Identifier, Keys, As, Property>, Result extends TSchema = TObject<{
23
- [Key in keyof Mapped]: Mapped[Key];
24
- }>> = Result;
25
- type TMappedImmediate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema, InstantiatedKey extends TSchema = TInstantiateType<Context, State, Key>> = TMappedAction<Context, State, Identifier, InstantiatedKey, As, Property>;
26
- export type TMappedInstantiate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema> = TCanInstantiate<Context, [Key]> extends true ? TMappedImmediate<Context, State, Identifier, Key, As, Property> : TMappedDeferred<Identifier, Key, As, Property>;
27
- export declare function MappedInstantiate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Key extends TSchema, As extends TSchema, Property extends TSchema>(context: Context, state: State, identifier: Identifier, key: Key, as: As, property: Property, options: TSchemaOptions): TMappedInstantiate<Context, State, Identifier, Key, As, Property>;
11
+ import { type TMappedVariants } from './mapped-variants.mjs';
12
+ import { type TEvaluateIntersect } from '../evaluate/index.mjs';
13
+ type TCanonicalAs<InstantiatedAs extends TSchema, Result extends TSchema = InstantiatedAs extends TTemplateLiteral<infer Pattern extends string> ? TTemplateLiteralDecode<Pattern> : InstantiatedAs> = Result;
14
+ type TMappedVariant<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Variant extends TSchema, As extends TSchema, Property extends TSchema, VariantContext extends TProperties = Memory.TAssign<Context, {
15
+ [_ in Identifier['name']]: Variant;
16
+ }>, InstantiatedAs extends TSchema = TInstantiateType<VariantContext, State, As>, CanonicalAs extends TSchema = TCanonicalAs<InstantiatedAs>, InstantiatedProperty extends TSchema = TInstantiateType<VariantContext, State, Property>, Result extends TProperties = CanonicalAs extends TLiteral<string | number> ? {
17
+ [_ in CanonicalAs['const']]: InstantiatedProperty;
18
+ } : {}> = Result;
19
+ type TMappedProperties<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Variants extends TSchema[], As extends TSchema, Property extends TSchema, Result extends TProperties[] = []> = (Variants extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TMappedProperties<Context, State, Identifier, Right, As, Property, [...Result, TMappedVariant<Context, State, Identifier, Left, As, Property>]> : Result);
20
+ type TReduceProperties<Properties extends TProperties[], Result extends TSchema[] = []> = (Properties extends [infer Left extends TProperties, ...infer Right extends TProperties[]] ? TReduceProperties<Right, [...Result, TObject<Left>]> : Result);
21
+ type TMappedAction<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema, Variants extends TSchema[] = TMappedVariants<Type>, MappedProperties extends TProperties[] = TMappedProperties<Context, State, Identifier, Variants, As, Property>, MappedObjects extends TSchema[] = TReduceProperties<MappedProperties>, Result extends TSchema = TEvaluateIntersect<MappedObjects>> = Result;
22
+ type TMappedImmediate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema, InstantiatedType extends TSchema = TInstantiateType<Context, State, Type>> = TMappedAction<Context, State, Identifier, InstantiatedType, As, Property>;
23
+ export type TMappedInstantiate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema> = TCanInstantiate<Context, [Type]> extends true ? TMappedImmediate<Context, State, Identifier, Type, As, Property> : TMappedDeferred<Identifier, Type, As, Property>;
24
+ export declare function MappedInstantiate<Context extends TProperties, State extends TState, Identifier extends TIdentifier, Type extends TSchema, As extends TSchema, Property extends TSchema>(context: Context, state: State, identifier: Identifier, type: Type, as: As, property: Property, options: TSchemaOptions): TMappedInstantiate<Context, State, Identifier, Type, As, Property>;
28
25
  export {};
@@ -2,46 +2,48 @@
2
2
  import { Memory } from '../../../system/memory/index.mjs';
3
3
  import { IsLiteralNumber, IsLiteralString } from '../../types/literal.mjs';
4
4
  import { Object } from '../../types/object.mjs';
5
- import { MappedKeys } from './mapped-keys.mjs';
6
5
  import { IsTemplateLiteral } from '../../types/template-literal.mjs';
7
6
  import { MappedDeferred } from '../../action/mapped.mjs';
8
7
  import { TemplateLiteralDecode } from '../template-literal/decode.mjs';
9
8
  import { InstantiateType, CanInstantiate } from '../instantiate.mjs';
10
- function InstantiateKeyAs(context, state, identifier, key, as) {
11
- const contextWithKey = Memory.Assign(context, { [identifier['name']]: key });
12
- const instantiatedKeyAs = InstantiateType(contextWithKey, state, as);
13
- const result = IsTemplateLiteral(instantiatedKeyAs) ? TemplateLiteralDecode(instantiatedKeyAs.pattern) : instantiatedKeyAs;
9
+ import { MappedVariants } from './mapped-variants.mjs';
10
+ import { EvaluateIntersect } from '../evaluate/index.mjs';
11
+ function CanonicalAs(instantiatedAs) {
12
+ const result = IsTemplateLiteral(instantiatedAs) ? TemplateLiteralDecode(instantiatedAs.pattern) : instantiatedAs;
14
13
  return result;
15
14
  }
16
- function InstantiateProperty(context, state, identifier, key, property) {
17
- const contextWithKey = Memory.Assign(context, { [identifier['name']]: key });
18
- const instantiatedProperty = InstantiateType(contextWithKey, state, property);
19
- return instantiatedProperty;
20
- }
21
- function MappedProperty(context, state, identifier, key, as, property) {
22
- const instantiatedProperty = InstantiateProperty(context, state, identifier, key, property);
23
- const instantiatedKeyAs = InstantiateKeyAs(context, state, identifier, key, as);
24
- return (IsLiteralString(instantiatedKeyAs) || IsLiteralNumber(instantiatedKeyAs)
25
- ? { [instantiatedKeyAs.const]: instantiatedProperty }
15
+ function MappedVariant(context, state, identifier, variant, as, property) {
16
+ const variantContext = Memory.Assign(context, { [identifier['name']]: variant });
17
+ const instantiatedAs = InstantiateType(variantContext, state, as);
18
+ const canonicalAs = CanonicalAs(instantiatedAs);
19
+ const instantiatedProperty = InstantiateType(variantContext, state, property);
20
+ return (IsLiteralNumber(canonicalAs) || IsLiteralString(canonicalAs)
21
+ ? { [canonicalAs.const]: instantiatedProperty }
26
22
  : {});
27
23
  }
28
- function MappedProperties(context, state, identifier, keys, as, type) {
29
- return keys.reduce((result, left) => {
30
- return { ...result, ...MappedProperty(context, state, identifier, left, as, type) };
31
- }, {});
24
+ function MappedProperties(context, state, identifier, variants, as, property) {
25
+ return variants.reduce((result, left) => {
26
+ return [...result, MappedVariant(context, state, identifier, left, as, property)];
27
+ }, []);
28
+ }
29
+ function MappedObjects(properties) {
30
+ return properties.reduce((result, left) => {
31
+ return [...result, Object(left)];
32
+ }, []);
32
33
  }
33
- function MappedAction(context, state, identifier, key, as, type) {
34
- const keys = MappedKeys(key);
35
- const mapped = MappedProperties(context, state, identifier, keys, as, type);
36
- const result = Object(mapped);
34
+ function MappedAction(context, state, identifier, type, as, property) {
35
+ const variants = MappedVariants(type);
36
+ const mappedProperties = MappedProperties(context, state, identifier, variants, as, property);
37
+ const mappedObjects = MappedObjects(mappedProperties);
38
+ const result = EvaluateIntersect(mappedObjects);
37
39
  return result;
38
40
  }
39
- function MappedImmediate(context, state, identifier, key, as, property, options) {
40
- const instantiatedKey = InstantiateType(context, state, key);
41
- return Memory.Update(MappedAction(context, state, identifier, instantiatedKey, as, property), {}, options);
41
+ function MappedImmediate(context, state, identifier, type, as, property, options) {
42
+ const instantiatedType = InstantiateType(context, state, type);
43
+ return Memory.Update(MappedAction(context, state, identifier, instantiatedType, as, property), {}, options);
42
44
  }
43
- export function MappedInstantiate(context, state, identifier, key, as, property, options) {
44
- return (CanInstantiate(context, [key])
45
- ? MappedImmediate(context, state, identifier, key, as, property, options)
46
- : MappedDeferred(identifier, key, as, property, options));
45
+ export function MappedInstantiate(context, state, identifier, type, as, property, options) {
46
+ return (CanInstantiate(context, [type])
47
+ ? MappedImmediate(context, state, identifier, type, as, property, options)
48
+ : MappedDeferred(identifier, type, as, property, options));
47
49
  }
@@ -5,10 +5,11 @@ import { type TTemplateLiteral } from '../../types/template-literal.mjs';
5
5
  import { type TUnion } from '../../types/union.mjs';
6
6
  import { type TEnumValuesToVariants } from '../enum/index.mjs';
7
7
  import { type TTemplateLiteralDecode } from '../template-literal/decode.mjs';
8
- type TFromTemplateLiteral<Pattern extends string, Decoded extends TSchema = TTemplateLiteralDecode<Pattern>, Result extends TSchema = TFromType<Decoded>> = Result;
8
+ type TFromTemplateLiteral<Pattern extends string, Decoded extends TSchema = TTemplateLiteralDecode<Pattern>, Result extends TSchema[] = TFromType<Decoded>> = Result;
9
9
  type TFromUnion<Types extends TSchema[], Result extends TSchema[] = []> = (Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromUnion<Right, [...Result, ...TFromType<Left>]> : Result);
10
10
  type TFromType<Type extends TSchema, Result extends TSchema[] = (Type extends TEnum<infer Values extends TEnumValue[]> ? TFromUnion<TEnumValuesToVariants<Values>> : Type extends TLiteral<string | number> ? [Type] : Type extends TTemplateLiteral<infer Pattern extends string> ? TFromTemplateLiteral<Pattern> : Type extends TUnion<infer Types extends TSchema[]> ? TFromUnion<Types> : [
11
+ Type
11
12
  ])> = Result;
12
- export type TMappedKeys<Type extends TSchema, Result extends TSchema[] = TFromType<Type>> = Result;
13
- export declare function MappedKeys<Type extends TSchema>(type: Type): TMappedKeys<Type>;
13
+ export type TMappedVariants<Type extends TSchema, Result extends TSchema[] = TFromType<Type>> = Result;
14
+ export declare function MappedVariants<Type extends TSchema>(type: Type): TMappedVariants<Type>;
14
15
  export {};
@@ -20,10 +20,10 @@ function FromType(type) {
20
20
  IsLiteralString(type) || IsLiteralNumber(type) ? [type] :
21
21
  IsTemplateLiteral(type) ? FromTemplateLiteral(type.pattern) :
22
22
  IsUnion(type) ? FromUnion(type.anyOf) :
23
- []);
23
+ [type]);
24
24
  return result;
25
25
  }
26
- export function MappedKeys(type) {
26
+ export function MappedVariants(type) {
27
27
  const result = FromType(type);
28
28
  return result;
29
29
  }
@@ -274,7 +274,7 @@ export type TMappedOptionalMapping<Input extends [unknown, unknown] | [unknown]
274
274
  export declare function MappedOptionalMapping(input: [unknown, unknown] | [unknown] | []): unknown;
275
275
  export type TMappedAsMapping<Input extends [unknown, unknown] | []> = (Input extends ['as', infer Type extends T.TSchema] ? [Type] : []);
276
276
  export declare function MappedAsMapping(input: [unknown, unknown] | []): unknown;
277
- export type TMappedMapping<Input extends [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]> = (Input extends ['{', infer Readonly extends TModifierOperation, '[', infer Key extends string, 'in', infer Union extends T.TSchema, infer As extends T.TSchema[], ']', infer Optional extends TModifierOperation, ':', infer Type extends T.TSchema, null, '}'] ? (As extends [infer As extends T.TSchema] ? C.TMappedDeferred<T.TIdentifier<Key>, Union, As, TApplyReadonly<Readonly, TApplyOptional<Optional, Type>>> : C.TMappedDeferred<T.TIdentifier<Key>, Union, T.TRef<Key>, TApplyReadonly<Readonly, TApplyOptional<Optional, Type>>>) : never);
277
+ export type TMappedMapping<Input extends [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]> = (Input extends ['{', infer Readonly extends TModifierOperation, '[', infer Key extends string, 'in', infer Type extends T.TSchema, infer As extends T.TSchema[], ']', infer Optional extends TModifierOperation, ':', infer Property extends T.TSchema, null, '}'] ? (As extends [infer As extends T.TSchema] ? C.TMappedDeferred<T.TIdentifier<Key>, Type, As, TApplyReadonly<Readonly, TApplyOptional<Optional, Property>>> : C.TMappedDeferred<T.TIdentifier<Key>, Type, T.TRef<Key>, TApplyReadonly<Readonly, TApplyOptional<Optional, Property>>>) : never);
278
278
  export declare function MappedMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]): unknown;
279
279
  export type TReferenceMapping<Input extends string, Result extends T.TSchema = T.TRef<Input>> = Result;
280
280
  export declare function ReferenceMapping(input: string): unknown;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typebox",
3
3
  "description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
4
- "version": "1.1.9",
4
+ "version": "1.1.11",
5
5
  "keywords": [
6
6
  "typescript",
7
7
  "jsonschema"