-
Notifications
You must be signed in to change notification settings - Fork 8
/
strings.ts
155 lines (129 loc) · 4.53 KB
/
strings.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import * as t from "io-ts";
import * as validator from "validator";
import { tag, Tagged } from "./types";
export interface INonEmptyStringTag {
readonly kind: "INonEmptyStringTag";
}
/**
* A non-empty string
*/
export const NonEmptyString = tag<INonEmptyStringTag>()(
t.refinement(t.string, s => s.length > 0, "non empty string")
);
export type NonEmptyString = t.TypeOf<typeof NonEmptyString>;
export interface IWithinRangeStringTag<L extends number, H extends number> {
readonly lower: L;
readonly higher: H;
readonly kind: "IWithinRangeStringTag";
}
/**
* A string guaranteed to have a length within the range [L,H)
*/
export const WithinRangeString = <
L extends number,
H extends number,
T extends IWithinRangeStringTag<L, H>
>(
l: L,
h: H
): Tagged<T, string> =>
tag<T>()(
t.refinement(
t.string,
s => s.length >= l && s.length < h,
`string of length >= ${l} and < ${h}`
)
);
export type WithinRangeString<L extends number, H extends number> = string &
IWithinRangeStringTag<L, H>;
export interface IPatternStringTag<P extends string> {
readonly pattern: P;
readonly kind: "IPatternStringTag";
}
/**
* A string that matches a pattern.
*/
export const PatternString = <P extends string, T extends IPatternStringTag<P>>(
p: P
): Tagged<T, string> =>
tag<T>()(
t.refinement(
t.string,
s => s.match(p) !== null,
`string that matches the pattern "${p}"`
)
);
export type PatternString<P extends string> = string & IPatternStringTag<P>;
export interface IEmailStringTag {
readonly kind: "IEmailStringTag";
}
/**
* A string that represents a valid email address.
*/
export const EmailString = tag<IEmailStringTag>()(
t.refinement(
t.string,
s =>
validator.isEmail(s, {
allow_display_name: false,
allow_utf8_local_part: false,
require_tld: true
}),
"string that represents an email address"
)
);
export type EmailString = t.TypeOf<typeof EmailString>;
export interface IIPStringTag {
readonly kind: "IIPStringTag";
}
/**
* A string that represents an IP (v4 or v6).
*/
export const IPString = tag<IIPStringTag>()(
t.refinement(t.string, validator.isIP, "string that represents an IP address")
);
export type IPString = t.TypeOf<typeof IPString>;
const v4 =
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}\\/(3[0-2]|[12]?[0-9])";
const v6seg = "[0-9a-fA-F]{1,4}";
const v6 = `
(
(?:${v6seg}:){7}(?:${v6seg}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8
(?:${v6seg}:){6}(?:${v4}|:${v6seg}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4
(?:${v6seg}:){5}(?::${v4}|(:${v6seg}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4
(?:${v6seg}:){4}(?:(:${v6seg}){0,1}:${v4}|(:${v6seg}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4
(?:${v6seg}:){3}(?:(:${v6seg}){0,2}:${v4}|(:${v6seg}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4
(?:${v6seg}:){2}(?:(:${v6seg}){0,3}:${v4}|(:${v6seg}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4
(?:${v6seg}:){1}(?:(:${v6seg}){0,4}:${v4}|(:${v6seg}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4
(?::((?::${v6seg}){0,5}:${v4}|(?::${v6seg}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4
)(%[0-9a-zA-Z]{1,})? // %eth0 %1
\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])
`
.replace(/\s*\/\/.*$/gm, "")
.replace(/\n/g, "")
.trim();
/**
* A string that represents a valid CIDR.
*/
export const CIDR = PatternString(`(?:^${v4}$)|(?:^${v6}$)`);
export type CIDR = t.TypeOf<typeof CIDR>;
/**
* A valid Fiscal Number (for persons)
*/
export const FiscalCode = PatternString(
"^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]$"
);
export type FiscalCode = t.TypeOf<typeof FiscalCode>;
/**
* A sandbox Fiscal Code (used for development)
* Note that this pattern doesn't generate valid fiscal codes
*/
export const SandboxFiscalCode = PatternString(
"^[A-Z]{6}[0-9]{2}A[0-9]{2}Y[0-9]{3}X$"
);
export type SandboxFiscalCode = t.TypeOf<typeof SandboxFiscalCode>;
/**
* A valid Fiscal Number (for organizations)
*/
export const OrganizationFiscalCode = PatternString("^[0-9]{11}$");
export type OrganizationFiscalCode = t.TypeOf<typeof OrganizationFiscalCode>;