justus 0.5.0 → 0.5.2

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/src/extra/arn.ts CHANGED
@@ -1,29 +1,47 @@
1
1
  import { assertValidation } from '../errors'
2
2
  import { AbstractValidator, makeValidatorFactory } from '../types'
3
3
 
4
+ /* ===== TYPES ============================================================= */
5
+
4
6
  /** The type for a validated _string_ ARN (Amazon Resource Name) */
5
- export type ArnString<Service extends string = string> = string & { __arn: never }
6
- & ( string extends Service ? string : { [ k in `__arn_${Service}`] : never })
7
+ export type ArnString<
8
+ Service extends string = string,
9
+ ResourceType extends string = string,
10
+ > = string & { __arn: never }
11
+ & ( string extends Service ? string : { [ k in `__arn_service_${Service}`] : never })
12
+ & ( string extends ResourceType ? string : { [ k in `__arn_resource_${ResourceType}`] : never })
7
13
 
8
14
  /** The type for a _parsed_ ARN (Amazon Resource Name) */
9
- export interface ParsedArn<Service extends string = string> {
15
+ export interface ParsedArn<
16
+ Service extends string = string,
17
+ ResourceType extends string = string,
18
+ > {
10
19
  /** The full */
11
- Arn: ArnString<Service>,
20
+ Arn: ArnString<Service, ResourceType>,
12
21
  Partition: string,
13
22
  Service: Service,
14
23
  Region: string,
15
24
  Account: string,
16
- Resource: [ string, ...string[] ],
25
+ Resource: [ ResourceType, ...string[] ],
17
26
  }
18
27
 
19
- /* ========================================================================== */
28
+ /* ===== INTERNALS ========================================================== */
29
+
30
+ function assertComponent<T extends string>(
31
+ actual: string,
32
+ expected: T | undefined,
33
+ kind: string,
34
+ ): asserts actual is T {
35
+ if (expected === undefined) return
36
+ assertValidation(actual === expected, `ARN ${kind} "${actual}" mismatch (expected "${expected}")`)
37
+ }
20
38
 
21
39
  /** Validate a string and convert it into into an {@link ParsedArn} */
22
- function parse<Service extends string>(
40
+ function parse<Service extends string, ResourceType extends string>(
23
41
  value: unknown,
24
42
  service?: Service,
25
- type?: string,
26
- ): ParsedArn<Service> {
43
+ type?: ResourceType,
44
+ ): ParsedArn<Service, ResourceType> {
27
45
  assertValidation(typeof value == 'string', 'Value is not a "string"')
28
46
 
29
47
  const segments = value.split(':')
@@ -38,37 +56,34 @@ function parse<Service extends string>(
38
56
  assertValidation(!! act, 'Missing account ID in ARN')
39
57
  assertValidation(!! res[0], 'Missing resource ID in ARN')
40
58
 
41
- if (service !== undefined) {
42
- assertValidation(svc === service, `ARN Service "${svc}" mismatch (expected "${service}")`)
43
- }
44
-
45
- const [ resArray, resString ] = res[0].includes('/') ?
59
+ const [ [ resType, ...resArray ], resString ] = res[0].includes('/') ?
46
60
  [ res[0].split('/'), res[0] ] :
47
61
  [ res, res.join(':') ]
48
62
 
49
- assertValidation(!! resArray[0], 'Invalid resource ID in ARN')
63
+ assertValidation(!! resType, 'Invalid resource ID in ARN')
50
64
 
51
- if (type !== undefined) {
52
- assertValidation(resArray[0] === type, `ARN Resource Type "${resArray[0]}" mismatch (expected "${type}")`)
53
- }
65
+ assertComponent(svc, service, 'Service')
66
+ assertComponent(resType, type, 'Resource Type')
54
67
 
55
68
  const arn = `arn:${prt}:${svc}:${rgn}:${act}:${resString}`
56
69
 
57
70
  return {
58
- Arn: arn as ArnString<Service>,
71
+ Arn: arn as ArnString<Service, ResourceType>,
59
72
  Partition: prt,
60
- Service: svc as Service,
73
+ Service: svc, // as Service,
61
74
  Region: rgn || '',
62
75
  Account: act,
63
- Resource: resArray as [ string, ...string[] ],
76
+ Resource: [ resType, ...resArray ], // as [ ResourceType, ...string[] ],
64
77
  }
65
78
  }
66
79
 
67
- /* ========================================================================== */
80
+ /* ===== VALIDATOR CLASSES ================================================== */
68
81
 
69
82
  /** Validator parsing an ARN (Amazon Resource Name) and returning its components */
70
- export class ParsedArnValidator<Service extends string = string>
71
- extends AbstractValidator<ParsedArn<Service>, string> {
83
+ export class ParsedArnValidator<
84
+ Service extends string = string,
85
+ ResourceType extends string = string,
86
+ > extends AbstractValidator<ParsedArn<Service, ResourceType>, string> {
72
87
  /**
73
88
  * Create a new {@link ParsedArnValidator} instance.
74
89
  *
@@ -78,19 +93,21 @@ export class ParsedArnValidator<Service extends string = string>
78
93
  * representing (e.g. `role` in the `iam` service, or
79
94
  * `targetgroup` in the `elasticloadbalancing` service)
80
95
  */
81
- constructor(service?: Service, resourceType?: string)
82
- constructor(private _service?: Service, private _type?: string) {
96
+ constructor(service?: Service, resourceType?: ResourceType)
97
+ constructor(private _service?: Service, private _type?: ResourceType) {
83
98
  super()
84
99
  }
85
100
 
86
- validate(value: unknown): ParsedArn<Service> {
101
+ validate(value: unknown): ParsedArn<Service, ResourceType> {
87
102
  return parse(value, this._service, this._type)
88
103
  }
89
104
  }
90
105
 
91
106
  /** Validator validating an ARN (Amazon Resource Name) _string_ */
92
- export class ArnValidator<Service extends string = string>
93
- extends AbstractValidator<ArnString<Service>, string> {
107
+ export class ArnValidator<
108
+ Service extends string = string,
109
+ ResourceType extends string = string,
110
+ > extends AbstractValidator<ArnString<Service, ResourceType>, string> {
94
111
  /**
95
112
  * Create a new {@link ArnValidator} instance.
96
113
  *
@@ -100,17 +117,17 @@ export class ArnValidator<Service extends string = string>
100
117
  * representing (e.g. `role` in the `iam` service, or
101
118
  * `targetgroup` in the `elasticloadbalancing` service)
102
119
  */
103
- constructor(service?: Service, resourceType?: string)
104
- constructor(private _service?: Service, private _type?: string) {
120
+ constructor(service?: Service, resourceType?: ResourceType)
121
+ constructor(private _service?: Service, private _type?: ResourceType) {
105
122
  super()
106
123
  }
107
124
 
108
- validate(value: unknown): ArnString<Service> {
125
+ validate(value: unknown): ArnString<Service, ResourceType> {
109
126
  return parse(value, this._service, this._type).Arn
110
127
  }
111
128
  }
112
129
 
113
- /* ========================================================================== */
130
+ /* ===== VALIDATOR FACTORIES ================================================ */
114
131
 
115
132
  /**
116
133
  * Create a new {@link ParsedArnValidator} parsing an ARN referring to the
@@ -120,10 +137,12 @@ export class ArnValidator<Service extends string = string>
120
137
  * component of the ARN's resource (e.g. `role` in the `iam` service, or
121
138
  * `targetgroup` in the `elasticloadbalancing` service)
122
139
  */
123
- export function parseArnFactory<Service extends string = string>(
140
+ export function parseArnFactory<
141
+ Service extends string = string,
142
+ ResourceType extends string = string>(
124
143
  service: Service,
125
- resourceType?: string,
126
- ): ParsedArnValidator<Service> {
144
+ resourceType?: ResourceType,
145
+ ): ParsedArnValidator<Service, ResourceType> {
127
146
  return new ParsedArnValidator(service, resourceType)
128
147
  }
129
148
 
@@ -135,14 +154,16 @@ export function parseArnFactory<Service extends string = string>(
135
154
  * component of the ARN's resource (e.g. `role` in the `iam` service, or
136
155
  * `targetgroup` in the `elasticloadbalancing` service)
137
156
  */
138
- export function arnFactory<Service extends string = string>(
157
+ export function arnFactory<
158
+ Service extends string = string,
159
+ ResourceType extends string = string>(
139
160
  service: Service,
140
- resourceType?: string,
141
- ): ArnValidator<Service> {
161
+ resourceType?: ResourceType,
162
+ ): ArnValidator<Service, ResourceType> {
142
163
  return new ArnValidator(service, resourceType)
143
164
  }
144
165
 
145
- /* ========================================================================== */
166
+ /* ===== VALIDATOR CONSTANTS ================================================ */
146
167
 
147
168
  /** Validate a string and parse it into into an {@link ParsedArn} */
148
169
  export const parseArn = makeValidatorFactory(new ParsedArnValidator(), parseArnFactory)
package/src/extra/uuid.ts CHANGED
@@ -4,7 +4,7 @@ export const UUID_EXPR = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a
4
4
 
5
5
  export type UUIDString = string & { __uuid: never }
6
6
 
7
- export class UUIDValidator extends StringValidator<UUIDString> {
7
+ export class UUIDValidator extends StringValidator<UUIDString, string> {
8
8
  constructor() {
9
9
  super({ minLength: 36, maxLength: 36, pattern: UUID_EXPR })
10
10
  }
package/src/types.ts CHANGED
@@ -52,7 +52,17 @@ export const defaultValidationOptions: Readonly<Required<ValidationOptions>> = {
52
52
  export interface Validator<T = any, I = T> extends Iterable<TupleRestParameter<T, I>> {
53
53
  [Symbol.justusValidator]: this
54
54
 
55
- optional?: boolean
55
+ /**
56
+ * A flag indicating whether the type being validated is _optional_ (the input
57
+ * can be `undefined`) or not (default: `false`).
58
+ */
59
+ optional: boolean
60
+ /**
61
+ * The _default_ replaced by this `Validator` when the input is `undefined`.
62
+ *
63
+ * This is used in conjunction with the `optional` flag.
64
+ */
65
+ defaultValue: T | undefined
56
66
 
57
67
  /** Validate a _value_ and optionally convert it to the required `Type` */
58
68
  validate(value: unknown, options?: ValidationOptions | undefined): T
@@ -73,6 +83,7 @@ export function makeValidatorFactory<
73
83
  >(validator: V, factory: F): F & V {
74
84
  return Object.assign(factory, {
75
85
  optional: validator.optional,
86
+ defaultValue: validator.defaultValue,
76
87
  validate: validator.validate.bind(validator),
77
88
  [Symbol.iterator]: validator[Symbol.iterator].bind(validator),
78
89
  [Symbol.justusValidator]: validator,
@@ -87,7 +98,8 @@ export abstract class AbstractValidator<T, I = T>
87
98
  implements Validator<T, I>, Iterable<TupleRestParameter<T, I>> {
88
99
  [Symbol.justusValidator] = this
89
100
 
90
- optional?: boolean = undefined
101
+ optional: boolean = false
102
+ defaultValue: T | undefined = undefined
91
103
 
92
104
  /** Validate a _value_ and optionally convert it to the required `Type` */
93
105
  abstract validate(value: unknown, options?: ValidationOptions | undefined): T
package/src/utilities.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { assertSchema } from './errors'
1
2
  import { registry } from './registry'
2
3
 
3
4
  import type { Schema, Validation, Validator } from './types'
@@ -6,12 +7,10 @@ import type { Schema, Validation, Validator } from './types'
6
7
  * UTILITY FUNCTIONS *
7
8
  * ========================================================================== */
8
9
 
9
- /**
10
- * Return the `Validator` for the given `Validation`.
11
- *
12
- * When `validation` is `undefined` it will return a `Validator<any>`,
13
- */
10
+ /** Return the `Validator` for the given `Validation` */
14
11
  export function getValidator(validation: Validation): Validator {
12
+ assertSchema(validation !== undefined, 'No validator for undefined validation')
13
+
15
14
  // Null is a constant
16
15
  if (validation === null) return new (registry.get('constant'))(null)
17
16