@nmtjs/contract 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/event.js +4 -4
- package/dist/schemas/event.js.map +1 -1
- package/dist/schemas/procedure.js +4 -5
- package/dist/schemas/procedure.js.map +1 -1
- package/dist/schemas/service.js +1 -6
- package/dist/schemas/service.js.map +1 -1
- package/dist/schemas/subscription.js +13 -14
- package/dist/schemas/subscription.js.map +1 -1
- package/dist/types/blob.js +13 -0
- package/dist/types/blob.js.map +1 -0
- package/dist/utils.js.map +1 -1
- package/package.json +8 -18
- package/src/index.ts +31 -0
- package/src/schemas/event.ts +7 -11
- package/src/schemas/procedure.ts +21 -23
- package/src/schemas/service.ts +41 -31
- package/src/schemas/subscription.ts +27 -49
- package/src/types/blob.ts +25 -0
- package/src/utils.ts +5 -6
- package/dist/compiler.js +0 -50
- package/dist/compiler.js.map +0 -1
- package/dist/contract.js +0 -24
- package/dist/contract.js.map +0 -1
- package/dist/formats.js +0 -127
- package/dist/formats.js.map +0 -1
- package/dist/guards/blob.js +0 -3
- package/dist/guards/blob.js.map +0 -1
- package/dist/guards/event.js +0 -3
- package/dist/guards/event.js.map +0 -1
- package/dist/guards/native-enum.js +0 -3
- package/dist/guards/native-enum.js.map +0 -1
- package/dist/guards/nullable.js +0 -2
- package/dist/guards/nullable.js.map +0 -1
- package/dist/guards/procedure.js +0 -3
- package/dist/guards/procedure.js.map +0 -1
- package/dist/guards/service.js +0 -3
- package/dist/guards/service.js.map +0 -1
- package/dist/guards/subscription.js +0 -3
- package/dist/guards/subscription.js.map +0 -1
- package/dist/guards/union-enum.js +0 -3
- package/dist/guards/union-enum.js.map +0 -1
- package/dist/guards.js +0 -20
- package/dist/guards.js.map +0 -1
- package/dist/schemas/blob.js +0 -26
- package/dist/schemas/blob.js.map +0 -1
- package/dist/schemas/native-enum.js +0 -14
- package/dist/schemas/native-enum.js.map +0 -1
- package/dist/schemas/nullable.js +0 -5
- package/dist/schemas/nullable.js.map +0 -1
- package/dist/schemas/union-enum.js +0 -13
- package/dist/schemas/union-enum.js.map +0 -1
- package/src/compiler.ts +0 -63
- package/src/contract.ts +0 -62
- package/src/formats.ts +0 -181
- package/src/guards/blob.ts +0 -5
- package/src/guards/event.ts +0 -6
- package/src/guards/native-enum.ts +0 -7
- package/src/guards/nullable.ts +0 -14
- package/src/guards/procedure.ts +0 -6
- package/src/guards/service.ts +0 -6
- package/src/guards/subscription.ts +0 -10
- package/src/guards/union-enum.ts +0 -7
- package/src/guards.ts +0 -21
- package/src/schemas/blob.ts +0 -58
- package/src/schemas/native-enum.ts +0 -29
- package/src/schemas/nullable.ts +0 -6
- package/src/schemas/union-enum.ts +0 -43
package/src/compiler.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type TypeCheck,
|
|
3
|
-
TypeCompiler,
|
|
4
|
-
type ValueErrorIterator,
|
|
5
|
-
} from '@sinclair/typebox/compiler'
|
|
6
|
-
import type { TSchema } from '@sinclair/typebox/type'
|
|
7
|
-
import { Value } from '@sinclair/typebox/value'
|
|
8
|
-
|
|
9
|
-
export type Compiled = {
|
|
10
|
-
check: (val: unknown) => boolean
|
|
11
|
-
errors: (val: unknown) => ValueErrorIterator
|
|
12
|
-
decode: (
|
|
13
|
-
val: unknown,
|
|
14
|
-
) => { success: true; value: unknown } | { success: false; error: any }
|
|
15
|
-
encode: (
|
|
16
|
-
val: unknown,
|
|
17
|
-
) => { success: true; value: unknown } | { success: false; error: any }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const compileSchema = (
|
|
21
|
-
schema: TSchema,
|
|
22
|
-
): TypeCheck<TSchema> & {
|
|
23
|
-
Prepare: (value: any) => unknown
|
|
24
|
-
} => {
|
|
25
|
-
const compiled = TypeCompiler.Compile(schema)
|
|
26
|
-
const Prepare = (value: any) => {
|
|
27
|
-
for (const fn of [Value.Clean, Value.Default]) {
|
|
28
|
-
value = fn(schema, value)
|
|
29
|
-
}
|
|
30
|
-
return value
|
|
31
|
-
}
|
|
32
|
-
return Object.assign(compiled, { Prepare })
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const compile = (schema: TSchema): Compiled => {
|
|
36
|
-
const compiled = compileSchema(schema)
|
|
37
|
-
|
|
38
|
-
// TODO: custom error handling/shaping
|
|
39
|
-
return {
|
|
40
|
-
check: compiled.Check.bind(compiled),
|
|
41
|
-
errors: compiled.Errors.bind(compiled),
|
|
42
|
-
decode: (val) => {
|
|
43
|
-
try {
|
|
44
|
-
return {
|
|
45
|
-
success: true as const,
|
|
46
|
-
value: compiled.Decode(compiled.Prepare(val)),
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
return { success: false as const, error }
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
encode: (val) => {
|
|
53
|
-
try {
|
|
54
|
-
return {
|
|
55
|
-
success: true as const,
|
|
56
|
-
value: compiled.Encode(compiled.Prepare(val)),
|
|
57
|
-
}
|
|
58
|
-
} catch (error) {
|
|
59
|
-
return { success: false as const, error }
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/contract.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
JsonTypeBuilder,
|
|
3
|
-
Kind,
|
|
4
|
-
type StaticDecode,
|
|
5
|
-
type StaticEncode,
|
|
6
|
-
type TSchema,
|
|
7
|
-
} from '@sinclair/typebox/type'
|
|
8
|
-
import { register } from './formats.ts' // register ajv formats
|
|
9
|
-
|
|
10
|
-
import { BlobType, type TBlob } from './schemas/blob.ts'
|
|
11
|
-
import { EventContract, type TEventContract } from './schemas/event.ts'
|
|
12
|
-
import { NativeEnum, type TNativeEnum } from './schemas/native-enum.ts'
|
|
13
|
-
import { Nullable } from './schemas/nullable.ts'
|
|
14
|
-
import {
|
|
15
|
-
ProcedureContract,
|
|
16
|
-
type TBaseProcedureContract,
|
|
17
|
-
type TProcedureContract,
|
|
18
|
-
} from './schemas/procedure.ts'
|
|
19
|
-
import { ServiceContract, type TServiceContract } from './schemas/service.ts'
|
|
20
|
-
import {
|
|
21
|
-
SubscriptionContract,
|
|
22
|
-
type TSubscriptionContract,
|
|
23
|
-
} from './schemas/subscription.ts'
|
|
24
|
-
import { type TUnionEnum, UnionEnum } from './schemas/union-enum.ts'
|
|
25
|
-
|
|
26
|
-
register()
|
|
27
|
-
|
|
28
|
-
const Contract = Object.freeze({
|
|
29
|
-
Procedure: ProcedureContract,
|
|
30
|
-
Event: EventContract,
|
|
31
|
-
Subscription: SubscriptionContract,
|
|
32
|
-
Service: ServiceContract,
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const Type = Object.freeze(
|
|
36
|
-
Object.assign(new JsonTypeBuilder(), {
|
|
37
|
-
UnionEnum,
|
|
38
|
-
NativeEnum,
|
|
39
|
-
Nullable,
|
|
40
|
-
Blob: BlobType,
|
|
41
|
-
}),
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
type Encoded<T extends TSchema> = StaticEncode<T>
|
|
45
|
-
type Decoded<T extends TSchema> = StaticDecode<T>
|
|
46
|
-
|
|
47
|
-
export {
|
|
48
|
-
Contract,
|
|
49
|
-
Kind,
|
|
50
|
-
Type,
|
|
51
|
-
type Decoded,
|
|
52
|
-
type Encoded,
|
|
53
|
-
type TBlob,
|
|
54
|
-
type TEventContract,
|
|
55
|
-
type TProcedureContract,
|
|
56
|
-
type TBaseProcedureContract,
|
|
57
|
-
type TSchema,
|
|
58
|
-
type TServiceContract,
|
|
59
|
-
type TSubscriptionContract,
|
|
60
|
-
type TUnionEnum,
|
|
61
|
-
type TNativeEnum,
|
|
62
|
-
}
|
package/src/formats.ts
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { FormatRegistry } from '@sinclair/typebox/type'
|
|
2
|
-
|
|
3
|
-
// TODO: review all of this
|
|
4
|
-
|
|
5
|
-
export const register = () => {
|
|
6
|
-
for (const [name, format] of Object.entries(fullFormats)) {
|
|
7
|
-
if (format === true) {
|
|
8
|
-
FormatRegistry.Set(name, () => true)
|
|
9
|
-
continue
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
if (typeof format === 'function') {
|
|
13
|
-
FormatRegistry.Set(name, format)
|
|
14
|
-
continue
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
FormatRegistry.Set(name, (value) => format.test(value))
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const fullFormats: Record<
|
|
22
|
-
string,
|
|
23
|
-
RegExp | ((v: any) => boolean) | true
|
|
24
|
-
> = {
|
|
25
|
-
// date: http://tools.ietf.org/html/rfc3339#section-5.6
|
|
26
|
-
date,
|
|
27
|
-
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
|
|
28
|
-
time: getTime(true),
|
|
29
|
-
'date-time': getDateTime(true),
|
|
30
|
-
'iso-time': getTime(),
|
|
31
|
-
'iso-date-time': getDateTime(),
|
|
32
|
-
// duration: https://tools.ietf.org/html/rfc3339#appendix-A
|
|
33
|
-
duration:
|
|
34
|
-
/^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,
|
|
35
|
-
uri,
|
|
36
|
-
'uri-reference':
|
|
37
|
-
/^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,
|
|
38
|
-
// uri-template: https://tools.ietf.org/html/rfc6570
|
|
39
|
-
'uri-template':
|
|
40
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex:
|
|
41
|
-
/^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,
|
|
42
|
-
// For the source: https://gist.github.com/dperini/729294
|
|
43
|
-
// For test cases: https://mathiasbynens.be/demo/url-regex
|
|
44
|
-
url: /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu,
|
|
45
|
-
email:
|
|
46
|
-
/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
|
|
47
|
-
hostname:
|
|
48
|
-
/^(?=.{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,
|
|
49
|
-
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
|
|
50
|
-
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)$/,
|
|
51
|
-
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,
|
|
52
|
-
regex,
|
|
53
|
-
// uuid: http://tools.ietf.org/html/rfc4122
|
|
54
|
-
uuid: /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,
|
|
55
|
-
// JSON-pointer: https://tools.ietf.org/html/rfc6901
|
|
56
|
-
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
|
|
57
|
-
'json-pointer': /^(?:\/(?:[^~/]|~0|~1)*)*$/,
|
|
58
|
-
'json-pointer-uri-fragment':
|
|
59
|
-
/^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,
|
|
60
|
-
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
|
|
61
|
-
'relative-json-pointer': /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/,
|
|
62
|
-
// the following formats are used by the openapi specification: https://spec.openapis.org/oas/v3.0.0#data-types
|
|
63
|
-
// byte: https://github.com/miguelmota/is-base64
|
|
64
|
-
byte,
|
|
65
|
-
// signed 32 bit integer
|
|
66
|
-
int32: validateInt32,
|
|
67
|
-
// signed 64 bit integer
|
|
68
|
-
int64: validateInt64,
|
|
69
|
-
// C-type float
|
|
70
|
-
float: validateNumber,
|
|
71
|
-
// C-type double
|
|
72
|
-
double: validateNumber,
|
|
73
|
-
// hint to the UI to hide input strings
|
|
74
|
-
password: true,
|
|
75
|
-
// unchecked string payload
|
|
76
|
-
binary: true,
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function isLeapYear(year: number): boolean {
|
|
80
|
-
// https://tools.ietf.org/html/rfc3339#appendix-C
|
|
81
|
-
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/
|
|
85
|
-
const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
86
|
-
|
|
87
|
-
function date(str: string): boolean {
|
|
88
|
-
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
|
|
89
|
-
const matches: string[] | null = DATE.exec(str)
|
|
90
|
-
if (!matches) return false
|
|
91
|
-
const year: number = +matches[1]
|
|
92
|
-
const month: number = +matches[2]
|
|
93
|
-
const day: number = +matches[3]
|
|
94
|
-
return (
|
|
95
|
-
month >= 1 &&
|
|
96
|
-
month <= 12 &&
|
|
97
|
-
day >= 1 &&
|
|
98
|
-
day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month])
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i
|
|
103
|
-
|
|
104
|
-
function getTime(strictTimeZone?: boolean): (str: string) => boolean {
|
|
105
|
-
return function time(str: string): boolean {
|
|
106
|
-
const matches: string[] | null = TIME.exec(str)
|
|
107
|
-
if (!matches) return false
|
|
108
|
-
const hr: number = +matches[1]
|
|
109
|
-
const min: number = +matches[2]
|
|
110
|
-
const sec: number = +matches[3]
|
|
111
|
-
const tz: string | undefined = matches[4]
|
|
112
|
-
const tzSign: number = matches[5] === '-' ? -1 : 1
|
|
113
|
-
const tzH: number = +(matches[6] || 0)
|
|
114
|
-
const tzM: number = +(matches[7] || 0)
|
|
115
|
-
if (tzH > 23 || tzM > 59 || (strictTimeZone && !tz)) return false
|
|
116
|
-
if (hr <= 23 && min <= 59 && sec < 60) return true
|
|
117
|
-
// leap second
|
|
118
|
-
const utcMin = min - tzM * tzSign
|
|
119
|
-
const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0)
|
|
120
|
-
return (
|
|
121
|
-
(utcHr === 23 || utcHr === -1) &&
|
|
122
|
-
(utcMin === 59 || utcMin === -1) &&
|
|
123
|
-
sec < 61
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const DATE_TIME_SEPARATOR = /t|\s/i
|
|
129
|
-
function getDateTime(strictTimeZone?: boolean): (str: string) => boolean {
|
|
130
|
-
const time = getTime(strictTimeZone)
|
|
131
|
-
|
|
132
|
-
return function date_time(str: string): boolean {
|
|
133
|
-
// http://tools.ietf.org/html/rfc3339#section-5.6
|
|
134
|
-
const dateTime: string[] = str.split(DATE_TIME_SEPARATOR)
|
|
135
|
-
return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1])
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const NOT_URI_FRAGMENT = /\/|:/
|
|
140
|
-
const URI =
|
|
141
|
-
/^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i
|
|
142
|
-
|
|
143
|
-
function uri(str: string): boolean {
|
|
144
|
-
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
|
|
145
|
-
return NOT_URI_FRAGMENT.test(str) && URI.test(str)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const BYTE =
|
|
149
|
-
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm
|
|
150
|
-
|
|
151
|
-
function byte(str: string): boolean {
|
|
152
|
-
BYTE.lastIndex = 0
|
|
153
|
-
return BYTE.test(str)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const MIN_INT32 = -(2 ** 31)
|
|
157
|
-
const MAX_INT32 = 2 ** 31 - 1
|
|
158
|
-
|
|
159
|
-
function validateInt32(value: number): boolean {
|
|
160
|
-
return Number.isInteger(value) && value <= MAX_INT32 && value >= MIN_INT32
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function validateInt64(value: number): boolean {
|
|
164
|
-
// JSON and javascript max Int is 2**53, so any int that passes isInteger is valid for Int64
|
|
165
|
-
return Number.isInteger(value)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function validateNumber(): boolean {
|
|
169
|
-
return true
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const Z_ANCHOR = /[^\\]\\Z/
|
|
173
|
-
function regex(str: string): boolean {
|
|
174
|
-
if (Z_ANCHOR.test(str)) return false
|
|
175
|
-
try {
|
|
176
|
-
new RegExp(str)
|
|
177
|
-
return true
|
|
178
|
-
} catch (e) {
|
|
179
|
-
return false
|
|
180
|
-
}
|
|
181
|
-
}
|
package/src/guards/blob.ts
DELETED
package/src/guards/event.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { KindGuard, type TSchema } from '@sinclair/typebox'
|
|
2
|
-
import { NativeEnumKind, type TNativeEnum } from '../schemas/native-enum.ts'
|
|
3
|
-
|
|
4
|
-
export const IsNativeEnum = (
|
|
5
|
-
schema: TSchema,
|
|
6
|
-
): schema is TNativeEnum<Record<string, string>> =>
|
|
7
|
-
KindGuard.IsKindOf(schema, NativeEnumKind)
|
package/src/guards/nullable.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
KindGuard,
|
|
3
|
-
type TNull,
|
|
4
|
-
type TSchema,
|
|
5
|
-
type TUnion,
|
|
6
|
-
} from '@sinclair/typebox'
|
|
7
|
-
|
|
8
|
-
export const IsNullable = (
|
|
9
|
-
schema: TSchema,
|
|
10
|
-
): schema is TUnion<[TSchema, TNull]> =>
|
|
11
|
-
KindGuard.IsUnion(schema) &&
|
|
12
|
-
schema.anyOf.length === 2 &&
|
|
13
|
-
KindGuard.IsNull(schema.anyOf[1]) &&
|
|
14
|
-
KindGuard.IsSchema(schema.anyOf[0])
|
package/src/guards/procedure.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { KindGuard, type TSchema } from '@sinclair/typebox'
|
|
2
|
-
|
|
3
|
-
import { ProcedureKind, type TProcedureContract } from '../schemas/procedure.ts'
|
|
4
|
-
|
|
5
|
-
export const IsProcedure = (schema: TSchema): schema is TProcedureContract =>
|
|
6
|
-
KindGuard.IsKindOf(schema, ProcedureKind)
|
package/src/guards/service.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { KindGuard, type TSchema } from '@sinclair/typebox'
|
|
2
|
-
import {
|
|
3
|
-
SubscriptionKind,
|
|
4
|
-
type TSubscriptionContract,
|
|
5
|
-
} from '../schemas/subscription.ts'
|
|
6
|
-
|
|
7
|
-
export const IsSubscription = (
|
|
8
|
-
schema: TSchema,
|
|
9
|
-
): schema is TSubscriptionContract =>
|
|
10
|
-
KindGuard.IsKindOf(schema, SubscriptionKind)
|
package/src/guards/union-enum.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { KindGuard, type TSchema } from '@sinclair/typebox'
|
|
2
|
-
import { type TUnionEnum, UnionEnumKind } from '../schemas/union-enum.ts'
|
|
3
|
-
|
|
4
|
-
export const IsUnionEnum = (
|
|
5
|
-
schema: TSchema,
|
|
6
|
-
): schema is TUnionEnum<(string | number)[]> =>
|
|
7
|
-
KindGuard.IsKindOf(schema, UnionEnumKind)
|
package/src/guards.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { KindGuard } from '@sinclair/typebox'
|
|
2
|
-
import { IsBlob } from './guards/blob.ts'
|
|
3
|
-
import { IsEvent } from './guards/event.ts'
|
|
4
|
-
import { IsNativeEnum } from './guards/native-enum.ts'
|
|
5
|
-
import { IsNullable } from './guards/nullable.ts'
|
|
6
|
-
import { IsProcedure } from './guards/procedure.ts'
|
|
7
|
-
import { IsService } from './guards/service.ts'
|
|
8
|
-
import { IsSubscription } from './guards/subscription.ts'
|
|
9
|
-
import { IsUnionEnum } from './guards/union-enum.ts'
|
|
10
|
-
|
|
11
|
-
export const ContractGuard = {
|
|
12
|
-
...KindGuard,
|
|
13
|
-
IsEvent,
|
|
14
|
-
IsSubscription,
|
|
15
|
-
IsProcedure,
|
|
16
|
-
IsService,
|
|
17
|
-
IsBlob,
|
|
18
|
-
IsNullable,
|
|
19
|
-
IsUnionEnum,
|
|
20
|
-
IsNativeEnum,
|
|
21
|
-
}
|
package/src/schemas/blob.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { ApiBlob, type ApiBlobInterface } from '@nmtjs/common'
|
|
2
|
-
import {
|
|
3
|
-
Kind,
|
|
4
|
-
type TSchema,
|
|
5
|
-
Type,
|
|
6
|
-
TypeBoxError,
|
|
7
|
-
TypeRegistry,
|
|
8
|
-
} from '@sinclair/typebox/type'
|
|
9
|
-
import { type ContractSchemaOptions, createSchema } from '../utils.ts'
|
|
10
|
-
|
|
11
|
-
export const BlobKind = 'ApiBlob'
|
|
12
|
-
|
|
13
|
-
export type BlobOptions = {
|
|
14
|
-
maxSize?: number
|
|
15
|
-
contentType?: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface TBlob extends TSchema {
|
|
19
|
-
[Kind]: typeof BlobKind
|
|
20
|
-
type: 'neemata:blob'
|
|
21
|
-
static: ApiBlobInterface
|
|
22
|
-
maxSize?: BlobOptions['maxSize']
|
|
23
|
-
contentType?: BlobOptions['contentType']
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const BlobType = (
|
|
27
|
-
options: BlobOptions = {},
|
|
28
|
-
schemaOptions: ContractSchemaOptions = {} as ContractSchemaOptions,
|
|
29
|
-
) => {
|
|
30
|
-
if (!TypeRegistry.Has(BlobKind)) {
|
|
31
|
-
TypeRegistry.Set(BlobKind, (schema: TBlob, value) => {
|
|
32
|
-
return 'metadata' in (value as any)
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return Type.Transform(
|
|
37
|
-
createSchema<TBlob>({
|
|
38
|
-
...schemaOptions,
|
|
39
|
-
[Kind]: BlobKind,
|
|
40
|
-
type: 'neemata:blob',
|
|
41
|
-
...options,
|
|
42
|
-
}),
|
|
43
|
-
)
|
|
44
|
-
.Decode((value) => {
|
|
45
|
-
if ('metadata' in value) {
|
|
46
|
-
if (options.maxSize) {
|
|
47
|
-
const size = (value as ApiBlobInterface).metadata.size
|
|
48
|
-
if (size === -1 || size > options.maxSize) {
|
|
49
|
-
throw new TypeBoxError(
|
|
50
|
-
'Blob size unknown or exceeds maximum allowed size',
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return value
|
|
56
|
-
})
|
|
57
|
-
.Encode((value) => value) as unknown as TBlob
|
|
58
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Kind,
|
|
3
|
-
type SchemaOptions,
|
|
4
|
-
type TSchema,
|
|
5
|
-
TypeRegistry,
|
|
6
|
-
} from '@sinclair/typebox/type'
|
|
7
|
-
|
|
8
|
-
export const NativeEnumKind = 'NativeEnum'
|
|
9
|
-
export interface TNativeEnum<T extends Record<string, string>> extends TSchema {
|
|
10
|
-
[Kind]: typeof NativeEnumKind
|
|
11
|
-
static: T[keyof T][]
|
|
12
|
-
enum: T[keyof T][]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function NativeEnum<T extends Record<string, string>>(
|
|
16
|
-
value: T,
|
|
17
|
-
options: SchemaOptions = {},
|
|
18
|
-
) {
|
|
19
|
-
const values = Object.values(value)
|
|
20
|
-
|
|
21
|
-
function NativeEnumCheck(schema: TNativeEnum<T>, value: unknown) {
|
|
22
|
-
return typeof value === 'string' && schema.enum.includes(value as any)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!TypeRegistry.Has(NativeEnumKind))
|
|
26
|
-
TypeRegistry.Set(NativeEnumKind, NativeEnumCheck)
|
|
27
|
-
|
|
28
|
-
return { ...options, [Kind]: NativeEnumKind, enum: values } as TNativeEnum<T>
|
|
29
|
-
}
|
package/src/schemas/nullable.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Kind,
|
|
3
|
-
type SchemaOptions,
|
|
4
|
-
type TSchema,
|
|
5
|
-
TypeRegistry,
|
|
6
|
-
} from '@sinclair/typebox/type'
|
|
7
|
-
|
|
8
|
-
export const UnionEnumKind = 'UnionEnum'
|
|
9
|
-
|
|
10
|
-
// Ref: https://github.com/sinclairzx81/typebox/blob/master/example/prototypes/union-enum.ts
|
|
11
|
-
|
|
12
|
-
// -------------------------------------------------------------------------------------
|
|
13
|
-
// TUnionEnum
|
|
14
|
-
// -------------------------------------------------------------------------------------
|
|
15
|
-
export interface TUnionEnum<T extends (string | number)[]> extends TSchema {
|
|
16
|
-
[Kind]: typeof UnionEnumKind
|
|
17
|
-
static: T[number]
|
|
18
|
-
enum: T
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// -------------------------------------------------------------------------------------
|
|
22
|
-
// UnionEnum
|
|
23
|
-
// -------------------------------------------------------------------------------------
|
|
24
|
-
/** `[Experimental]` Creates a Union type with a `enum` schema representation */
|
|
25
|
-
export function UnionEnum<T extends (string | number)[]>(
|
|
26
|
-
values: [...T],
|
|
27
|
-
options: SchemaOptions = {},
|
|
28
|
-
) {
|
|
29
|
-
function UnionEnumCheck(
|
|
30
|
-
schema: TUnionEnum<(string | number)[]>,
|
|
31
|
-
value: unknown,
|
|
32
|
-
) {
|
|
33
|
-
return (
|
|
34
|
-
(typeof value === 'string' || typeof value === 'number') &&
|
|
35
|
-
schema.enum.includes(value)
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!TypeRegistry.Has(UnionEnumKind))
|
|
40
|
-
TypeRegistry.Set(UnionEnumKind, UnionEnumCheck)
|
|
41
|
-
|
|
42
|
-
return { ...options, [Kind]: UnionEnumKind, enum: values } as TUnionEnum<T>
|
|
43
|
-
}
|