joyent-portal/packages/instance-steps/src/validators.js

120 lines
3.4 KiB
JavaScript
Raw Normal View History

2018-03-01 03:15:16 +02:00
import intercept from 'apr-intercept';
import keys from 'lodash.keys';
import reduce from 'apr-reduce';
import assign from 'lodash.assign';
import yup from 'yup';
/*****************************************************************************/
const validateField = async (field, value) => {
const [err] = await intercept(field.validate(value));
return err ? err.errors.shift() : '';
};
const validateSchema = async (schema, value) => {
const errors = await reduce(
keys(schema),
2018-03-01 16:32:55 +02:00
async (errors, name) => {
const msg = await validateField(schema[name], value[name]);
return msg ? assign(errors, { [name]: msg }) : errors;
2018-03-01 16:32:55 +02:00
},
2018-03-01 03:15:16 +02:00
{}
);
2018-03-01 16:32:55 +02:00
if (keys(errors).length) {
throw errors;
}
2018-03-01 03:15:16 +02:00
};
const syncValidateField = (field, value) => {
try {
field.validateSync(value);
} catch (err) {
return err.errors.shift();
}
};
const syncValidateSchema = (schema, value) => {
return keys(schema).reduce((errors, name) => {
const msg = syncValidateField(schema[name], value[name]);
return msg ? assign(errors, { [name]: msg }) : errors;
}, {});
};
2018-03-01 03:15:16 +02:00
/*****************************************************************************/
const matches = {
nameStart: /^[a-zA-Z]|\d/,
2018-03-06 03:14:33 +02:00
nameBody: /^([a-zA-Z]|\d|_|-)+$/
2018-03-01 03:15:16 +02:00
};
const msgs = {
required: prefix => `${prefix} must be defined.`,
nameStart: prefix => `${prefix} can only start with letters and numbers.`,
nameBody: prefix =>
2018-03-06 03:14:33 +02:00
`${prefix} cannot contain spaces and can only contain letters, numbers, underscores (_), and hyphens (-).`
2018-03-01 03:15:16 +02:00
};
const Schemas = {
instanceName: {
name: yup
.string()
.notRequired()
.matches(matches.nameStart, msgs.nameStart('Instance name'))
.matches(matches.nameBody, msgs.nameBody('Instance Name'))
},
2018-03-01 03:15:16 +02:00
tag: {
name: yup
.string()
.required(msgs.required('Key'))
.matches(matches.nameStart, msgs.nameStart('Key'))
.matches(matches.nameBody, msgs.nameBody('Key')),
value: yup
.string()
.required(msgs.required('Value'))
.matches(matches.nameStart, msgs.nameStart('Value'))
.matches(matches.nameBody, msgs.nameBody('Value'))
},
metadata: {
name: yup
.string()
.required(msgs.required('Key'))
.matches(matches.nameStart, msgs.nameStart('Key'))
.matches(matches.nameBody, msgs.nameBody('Key')),
value: yup.string().required(msgs.required('Value'))
},
2018-03-01 03:15:16 +02:00
cns: {
name: yup
.string()
.required(msgs.required('Service names'))
.matches(matches.nameStart, msgs.nameStart('Service names'))
.matches(matches.nameBody, msgs.nameBody('Service names'))
2018-03-01 03:15:16 +02:00
},
affinityRule: {
name: yup
2018-03-01 03:15:16 +02:00
.string()
.required(msgs.required('Key'))
.matches(matches.nameStart, msgs.nameStart('Key'))
.matches(matches.nameBody, msgs.nameBody('Key')),
value: yup
.string()
.required(msgs.required('Value'))
.matches(matches.nameStart, msgs.nameStart('Value'))
.matches(matches.nameBody, msgs.nameBody('Value'))
}
};
/*****************************************************************************/
export const instanceName = ({ name }) =>
name ? syncValidateSchema(Schemas.instanceName, { name }) : null;
2018-03-01 03:15:16 +02:00
export const addTag = tag => validateSchema(Schemas.tag, tag);
2018-03-01 03:15:16 +02:00
export const addMetadata = metadata =>
validateSchema(Schemas.metadata, metadata);
export const addCnsService = service => validateSchema(Schemas.cns, service);
2018-03-01 03:15:16 +02:00
export const addAffinityRule = aff => validateSchema(Schemas.affinityRule, aff);