@amazon/vinyl-validation 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,30 +1,34 @@
1
- # Validation
1
+ # @amazon/vinyl-validation
2
+
3
+ [![Website](https://img.shields.io/badge/website-amazonmusic.github.io%2Fvinyl-blue)](https://amazonmusic.github.io/vinyl)
4
+ [![npm](https://img.shields.io/npm/v/@amazon/vinyl-validation.svg)](https://www.npmjs.com/package/@amazon/vinyl-validation)
5
+ [![size](https://img.shields.io/bundlejs/size/@amazon/vinyl-validation.svg?label=size)](https://bundlejs.com/?q=@amazon/vinyl-validation)
2
6
 
3
7
  A TypeScript-first validation library for runtime type checking and schema
4
- validation.
8
+ validation. Composable validators for primitives, objects, arrays, sets,
9
+ records, tuples, functions, and unions, with strong inference of the result
10
+ type.
5
11
 
6
- ## Installation
12
+ ## Install
7
13
 
8
- ```bash
14
+ ```shell
9
15
  npm install @amazon/vinyl-validation
10
16
  ```
11
17
 
12
18
  ## Basic Usage
13
19
 
14
20
  ```typescript
15
- import { string, number, object, array } from '@amazon/vinyl-validation'
21
+ import { string, number } from '@amazon/vinyl-validation'
16
22
 
17
- // Create validators
18
23
  const nameValidator = string().notEmpty()
19
24
  const ageValidator = number().gte(0)
20
25
 
21
- // Validate values
22
- console.log(nameValidator.isValid('John')) // true
23
- console.log(ageValidator.isValid(-5)) // false
26
+ nameValidator.isValid('John') // true
27
+ ageValidator.isValid(-5) // false
24
28
 
25
29
  // Get validation errors
26
30
  const errors = nameValidator.validate('')
27
- console.log(errors) // [{ message: 'Expected: not empty, but was: "". At: ', path: [] }]
31
+ // [{ message: 'Expected: not empty, but was: "". At: ', path: [] }]
28
32
  ```
29
33
 
30
34
  ## Core Validators
@@ -60,10 +64,8 @@ const nullishValidator = nullish() // null or undefined
60
64
  ```typescript
61
65
  import { isOneOf, instanceOf } from '@amazon/vinyl-validation'
62
66
 
63
- // Literal values
64
67
  const statusValidator = isOneOf('active', 'inactive', 'pending')
65
68
 
66
- // Instance checking
67
69
  const dateValidator = instanceOf(Date)
68
70
  const errorValidator = instanceOf(Error)
69
71
  ```
@@ -74,13 +76,12 @@ const errorValidator = instanceOf(Error)
74
76
  import { string } from '@amazon/vinyl-validation'
75
77
 
76
78
  const validator = string()
77
- .notEmpty() // not empty string
78
- .minLength(3) // at least 3 characters
79
- .maxLength(50) // at most 50 characters
80
- .noWhitespace() // no whitespace characters
81
- .matches(/^[a-z]+$/) // matches regex pattern
79
+ .notEmpty()
80
+ .minLength(3)
81
+ .maxLength(50)
82
+ .noWhitespace()
83
+ .matches(/^[a-z]+$/)
82
84
 
83
- // Usage
84
85
  validator.isValid('hello') // true
85
86
  validator.isValid('') // false (empty)
86
87
  validator.isValid('ab') // false (too short)
@@ -91,16 +92,8 @@ validator.isValid('ab') // false (too short)
91
92
  ```typescript
92
93
  import { number } from '@amazon/vinyl-validation'
93
94
 
94
- const validator = number()
95
- .gte(0) // greater than or equal to 0
96
- .gt(0) // greater than 0
97
- .lte(100) // less than or equal to 100
98
- .lt(100) // less than 100
99
- .within(1, 99) // between 1 and 99 (inclusive)
100
- .safeInteger() // safe integer
101
- .finite() // finite number
95
+ const validator = number().gte(0).lte(100).within(1, 99).safeInteger().finite()
102
96
 
103
- // Usage
104
97
  validator.isValid(50) // true
105
98
  validator.isValid(-1) // false (less than 0)
106
99
  validator.isValid(Infinity) // false (not finite)
@@ -109,7 +102,13 @@ validator.isValid(Infinity) // false (not finite)
109
102
  ## Object Validation
110
103
 
111
104
  ```typescript
112
- import { object, string, number } from '@amazon/vinyl-validation'
105
+ import {
106
+ object,
107
+ string,
108
+ number,
109
+ isOneOf,
110
+ array,
111
+ } from '@amazon/vinyl-validation'
113
112
 
114
113
  const userValidator = object({
115
114
  name: string().notEmpty(),
@@ -117,9 +116,8 @@ const userValidator = object({
117
116
  email: string().matches(/^[^\s@]+@[^\s@]+\.[^\s@]+$/),
118
117
  })
119
118
 
120
- // Usage
121
119
  const user = { name: 'John', age: 30, email: 'john@example.com' }
122
- console.log(userValidator.isValid(user)) // true
120
+ userValidator.isValid(user) // true
123
121
 
124
122
  // Extend existing schemas
125
123
  const adminValidator = userValidator.extend({
@@ -131,22 +129,19 @@ const adminValidator = userValidator.extend({
131
129
  ## Array Validation
132
130
 
133
131
  ```typescript
134
- import { array, string, number, tuple } from '@amazon/vinyl-validation'
132
+ import { array, string, number, tuple, boolean } from '@amazon/vinyl-validation'
135
133
 
136
- // Array of strings
137
134
  const stringArrayValidator = array(string())
138
135
 
139
- // Array of numbers with constraints
140
136
  const numberArrayValidator = array(number().gte(0))
141
- .minLength(1) // at least 1 element
142
- .maxLength(10) // at most 10 elements
143
- .notEmpty() // not empty array
137
+ .minLength(1)
138
+ .maxLength(10)
139
+ .notEmpty()
144
140
 
145
- // Tuple validation (fixed-length array with specific types)
141
+ // Tuples (fixed-length, positional)
146
142
  const coordinateValidator = tuple(number(), number()) // [x, y]
147
143
  const personValidator = tuple(string(), number(), boolean()) // [name, age, active]
148
144
 
149
- // Usage
150
145
  stringArrayValidator.isValid(['a', 'b', 'c']) // true
151
146
  coordinateValidator.isValid([10, 20]) // true
152
147
  coordinateValidator.isValid([10, 20, 30]) // false (wrong length)
@@ -157,16 +152,13 @@ coordinateValidator.isValid([10, 20, 30]) // false (wrong length)
157
152
  ```typescript
158
153
  import { record, recordValues, string, number } from '@amazon/vinyl-validation'
159
154
 
160
- // Record with string keys and number values
161
155
  const scoresValidator = recordValues(number().gte(0))
162
156
 
163
- // Record with specific key and value types
164
157
  const configValidator = record(
165
- string().matches(/^[A-Z_]+$/), // keys must be uppercase with underscores
166
- string().notEmpty() // values must be non-empty strings
158
+ string().matches(/^[A-Z_]+$/),
159
+ string().notEmpty()
167
160
  )
168
161
 
169
- // Usage
170
162
  scoresValidator.isValid({ alice: 95, bob: 87 }) // true
171
163
  configValidator.isValid({ API_KEY: 'secret', DB_URL: 'localhost' }) // true
172
164
  ```
@@ -178,7 +170,6 @@ import { set, string } from '@amazon/vinyl-validation'
178
170
 
179
171
  const tagValidator = set(string().notEmpty())
180
172
 
181
- // Usage
182
173
  tagValidator.isValid(new Set(['tag1', 'tag2'])) // true
183
174
  tagValidator.isValid(new Set(['tag1', ''])) // false (empty string)
184
175
  ```
@@ -188,12 +179,8 @@ tagValidator.isValid(new Set(['tag1', ''])) // false (empty string)
188
179
  ```typescript
189
180
  import { func } from '@amazon/vinyl-validation'
190
181
 
191
- const functionValidator = func()
192
- .withArity(2) // exactly 2 parameters
193
- .withMinArity(1) // at least 1 parameter
194
- .withMaxArity(3) // at most 3 parameters
182
+ const functionValidator = func().withArity(2).withMinArity(1).withMaxArity(3)
195
183
 
196
- // Usage
197
184
  functionValidator.isValid((a, b) => a + b) // true
198
185
  functionValidator.isValid(() => 'hello') // false (wrong arity)
199
186
  ```
@@ -201,18 +188,12 @@ functionValidator.isValid(() => 'hello') // false (wrong arity)
201
188
  ## Optional and Nullable Values
202
189
 
203
190
  ```typescript
204
- import { string, number } from '@amazon/vinyl-validation'
205
-
206
- // Optional (allows undefined)
207
- const optionalName = string().optional()
208
-
209
- // Nullable (allows null)
210
- const nullableName = string().nullable()
191
+ import { string } from '@amazon/vinyl-validation'
211
192
 
212
- // Maybe (allows null or undefined)
213
- const maybeName = string().maybe()
193
+ const optionalName = string().optional() // allows undefined
194
+ const nullableName = string().nullable() // allows null
195
+ const maybeName = string().maybe() // allows null or undefined
214
196
 
215
- // Usage
216
197
  optionalName.isValid(undefined) // true
217
198
  nullableName.isValid(null) // true
218
199
  maybeName.isValid(null) // true
@@ -224,9 +205,9 @@ maybeName.isValid(undefined) // true
224
205
  ### OR Logic
225
206
 
226
207
  ```typescript
227
- import { or, string, number } from '@amazon/vinyl-validation'
208
+ import { orValidators, string, number } from '@amazon/vinyl-validation'
228
209
 
229
- const stringOrNumber = or(string(), number())
210
+ const stringOrNumber = orValidators(string(), number())
230
211
 
231
212
  stringOrNumber.isValid('hello') // true
232
213
  stringOrNumber.isValid(42) // true
@@ -236,9 +217,9 @@ stringOrNumber.isValid(true) // false
236
217
  ### AND Logic
237
218
 
238
219
  ```typescript
239
- import { and, string } from '@amazon/vinyl-validation'
220
+ import { andValidators, string } from '@amazon/vinyl-validation'
240
221
 
241
- const shortUppercaseString = and(
222
+ const shortUppercaseString = andValidators(
242
223
  string().maxLength(10),
243
224
  string().matches(/^[A-Z]+$/)
244
225
  )
@@ -258,14 +239,6 @@ const evenNumberValidator = custom<number>(
258
239
  (input): input is number => typeof input === 'number' && input % 2 === 0
259
240
  )
260
241
 
261
- // With custom stringify function
262
- const positiveValidator = custom<number>(
263
- 'positive number',
264
- (input): input is number => typeof input === 'number' && input > 0,
265
- (input) => `number: ${input}`
266
- )
267
-
268
- // Usage
269
242
  evenNumberValidator.isValid(4) // true
270
243
  evenNumberValidator.isValid(3) // false
271
244
  ```
@@ -282,12 +255,6 @@ const validator = object({
282
255
 
283
256
  // Collect all errors (default: stop at first error)
284
257
  const errors = validator.validate({ name: '', email: 'invalid' }, { all: true })
285
-
286
- console.log(errors)
287
- // [
288
- // { message: 'Expected: not empty, but was: "". At: name', path: ['name'] },
289
- // { message: 'Expected: matches /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/, but was: "invalid". At: email', path: ['email'] }
290
- // ]
291
258
  ```
292
259
 
293
260
  ## Error Handling
@@ -302,43 +269,35 @@ try {
302
269
  validator.assert('') // throws ValidationError if invalid
303
270
  } catch (error) {
304
271
  if (error instanceof ValidationError) {
305
- console.log(error.message) // validation error details
272
+ console.log(error.message)
306
273
  }
307
274
  }
308
-
309
- // Or use validate() for non-throwing validation
310
- const errors = validator.validate('')
311
- if (errors.length > 0) {
312
- console.log('Validation failed:', errors)
313
- }
314
275
  ```
315
276
 
316
277
  ## TypeScript Integration
317
278
 
318
- The idiomatic usage is to start with an interface and create a schema for it:
319
-
320
279
  ```typescript
321
280
  import { object, string, number, array } from '@amazon/vinyl-validation'
322
281
 
323
- // Define your interface first
324
282
  interface User {
325
283
  name: string
326
284
  age?: number
327
285
  tags: string[]
328
286
  }
329
287
 
330
- // Create a validator that matches the interface
331
288
  const userValidator = object<User>({
332
289
  name: string(),
333
290
  age: number().optional(),
334
291
  tags: array(string()),
335
292
  })
336
293
 
337
- // Type-safe validation
338
294
  function processUser(data: unknown) {
339
295
  if (userValidator.isValid(data)) {
340
- // data is now typed as User
341
- console.log(data.name) // TypeScript knows this is a string
296
+ console.log(data.name) // typed as string
342
297
  }
343
298
  }
344
299
  ```
300
+
301
+ ## License
302
+
303
+ Apache-2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amazon/vinyl-validation",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Basic input shape validation",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,14 +70,14 @@
70
70
  "watch:release": "tsx buildSrc/build.ts --watch --release"
71
71
  },
72
72
  "devDependencies": {
73
- "@amazon/vinyl-build-utils": "^1.1.0",
74
- "@amazon/vinyl-jasmine-wrapper": "^1.1.0"
73
+ "@amazon/vinyl-build-utils": "^1.1.1",
74
+ "@amazon/vinyl-jasmine-wrapper": "^1.1.1"
75
75
  },
76
76
  "dependencies": {
77
- "@amazon/vinyl-util": "^1.1.0"
77
+ "@amazon/vinyl-util": "^1.1.1"
78
78
  },
79
79
  "browserslist": [
80
80
  "defaults, chrome 52, firefox 54, edge 15, safari 8"
81
81
  ],
82
- "gitHead": "ea13070fb52c1903723f08f31c356465d2f3279e"
82
+ "gitHead": "e5a3429d802564132b16808a5b8a8e15a023a548"
83
83
  }