JavaScript resolver validation utilities for AWS AppSync
npm install @sot1986/appsync-precognitionLean validation library for AppSync JS runtime, implementing Precognition protocol for real-time form validation.
- Installation
- Basic Usage
- Simple Validation
- Precognitive Validation (Real-time)
- Validation Rules
- Basic Rules
- Type Rules
- String Validation
- Date/Time Validation
- Numeric Validation
- Size Constraints
- Pattern Matching
- Date Comparisons
- Nested Object Validation
- Array Validation
- Custom Error Messages
- Custom Attribute Names
- Validation Options
- Precognitive Validation Features
- Client Integration
- Internationalization
- Error Handling
- Advanced Usage
- Assert Validated Data
- Check Localization
``bash`
npm install appsync-precognition
`javascript
import { validate } from 'appsync-precognition'
export function request(ctx) {
const validatedArgs = validate({
name: 'Marco',
age: 15,
email: 'marco@email.it',
}, {
name: ['required', ['min', 3]],
age: ['required', ['min', 18]],
email: ['required', 'email'],
phone: ['sometimes', 'phone']
})
return {
operation: 'PutItem',
key: util.dynamodb.toMapValues({ id: util.autoId() }),
attributeValues: util.dynamodb.toMapValues(validatedArgs)
}
}
`ValidationError
This validation will throw an Error of type .
`typescript`
util.error(
'age min value is 18',
'ValidationError',
null,
{
path: 'age',
value: 15
}
)
`javascript
import { precognitiveValidation } from 'appsync-precognition'
export function request(ctx) {
const validatedArgs = precognitiveValidation(ctx, {
name: ['required', ['min', 3]],
age: ['required', ['min', 18]],
email: ['required', 'email'],
phone: ['nullable', 'phone']
})
return {
operation: 'PutItem',
key: util.dynamodb.toMapValues({ id: util.autoId() }),
attributeValues: util.dynamodb.toMapValues(validatedArgs)
}
}
`{ data: null, errors: undefined }
1. Module checks for precognition headers and/or keys.
2. Validates the request payload accordingly
3. In case of success and precognitive requests, it will immediately return with
- Field must have a value
- nullable - Field can be null but validates if present
- sometimes - Field is optional but validates if present$3
- string - Must be a string
- number - Must be a number
- boolean - Must be a boolean
- array - Must be an array
- object - Must be an object$3
- email - Valid email format
- phone - Valid phone number (+123...)
- url - Valid URL format
- uuid - Valid UUID format
- ulid - Valid ULID format$3
- date - Valid date (YYYY-MM-DD)
- time - Valid time (HH:MM:SS)
- datetime - Valid ISO datetime$3
- integer - Valid integer
- numeric - Valid number format$3
- ['min', number] - Minimum value/length
- ['max', number] - Maximum value/length
- ['between', min, max] - Between values (inclusive)
- ['bigger', number] - Strictly greater than
- ['lower', number] - Strictly less than
- ['within', min, max] - Strictly between values$3
- ['regex', pattern] - Match regex pattern
- ['in', ...values] - Value must be in list
- ['notIn', ...values] - Value must not be in list$3
- ['before', date] - Before specified date
- ['after', date] - After specified date
- ['beforeOrEqual', date] - Before or equal to date
- ['afterOrEqual', date] - After or equal to dateNested Object Validation
`javascript
const validatedArgs = validate(ctx.args, {
'user.name': ['required', ['min', 3]],
'user.email': ['required', 'email'],
'address.street': ['required'],
'address.zipCode': ['required', ['between', 5, 10]]
})
`Array Validation
To simplify error rules definition, the shortcut
* is supported.`javascript
const validatedArgs = validate(ctx.args, {
'hobbies': ['required', 'array', ['min', 1]],
'hobbies.*': ['required', 'string', ['max', 50]], // Validates each array item
'tags': ['sometimes', 'array'],
'tags.*.value': ['string']
})
`Custom Error Messages
`javascript
const validatedArgs = validate(ctx.args, {
email: [{ rule: 'email', msg: 'Please enter a valid email address' }],
age: [{ rule: ['min', 18], msg: 'You must be at least 18 years old' }]
})
`Custom Attribute Names
Attribute names can be customized by adding a third parameter to the validate function.`javascript
const validatedArgs = validate(ctx.args, {
'email': ['required', 'email'],
'phone': ['required', 'phone'],
'hobbies.*': ['required', ['min', 2]] // each hobbies should have at least 2 chars
}, {
attributes: {
':email': 'Email Address',
':phone': 'Phone Number',
':hobbies.*': 'Hobby' // 'Hobby must have at least 2 characters'
}
})
`Validation Options
`javascript
const validatedArgs = validate(ctx.args, rules, {
trim: true, // Trim string values (default: true)
allowEmptyString: false, // Allow empty strings (default: false)
errors: {
required: ':attr is mandatory',
email: ':attr must be a valid email'
},
attributes: {
':email': 'Email Address'
}
})
`Precognitive Validation Features
The
precognitiveValidation function automatically handles:
- Full validation when precognition header is not present
- Selective validation when precognition-validate-only header specifies fields
- Early return for precognitive requests with proper headers
- Response headers for client-side precognition handling$3
Your frontend should send these headers for precognitive validation:
`json
{
"Precognition": "true",
"Precognition-Validate-Only": "email,name"
}
`In addition, these headers must be enabled in the CORS policy of AppSync.
Internationalization
`javascript
import { localize } from 'appsync-precognition/i18n'export function request(ctx) {
// Set up localization based on Accept-Language header
localize(ctx, {
errors: {
en: { required: ':attr is required' },
es: { required: ':attr es requerido' },
it: { required: 'il campo :attr è obbligatorio' }
},
attributes: {
en: { ':name': 'Name', ':email': 'Email' },
es: { ':name': 'Nombre', ':email': 'Correo' },
it: { ':name': 'Nome', ':email': 'Email' }
}
}) // locale details will be added in stash object
const validatedArgs = precognitiveValidation(ctx, {
name: ['required'],
email: ['required', 'email']
})
return { / your operation / }
}
`
If needed, it can be useful to split the localization and validation in separate resolvers of the same pipeline.Error Handling
Validation errors are thrown as AppSync errors with detailed information:
`javascript
// When validation fails, the error contains:
// - message: Human-readable error message
// - errorType: 'ValidationError'
// - errorInfo: { path: 'field.name', value: invalidValue }
`Advanced Usage
$3
`javascript
import { assertValidated } from 'appsync-precognition'export function request(ctx) {
precognitiveValidation(ctx, rules)
return { / operation / }
}
export function response(ctx) {
assertValidated(ctx) // Ensures validation was performed
return ctx.stash.__validated
}
`$3
`javascript
import { assertLocalized, isLocalized } from 'appsync-precognition'export function request(ctx) {
if (isLocalized(ctx, 'es')) {
// Handle Spanish localization
}
assertLocalized(ctx) // Throws if not localized
}
``