fix(config-schema): allow field pattern to be a regex (#3971)
This commit is contained in:
parent
7ee9f2f188
commit
652045c9de
@ -173,13 +173,13 @@ describe('config', () => {
|
||||
|
||||
it('should throw if collection publish is not a boolean', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge(validConfig, { collections: [{ publish: 'false' }] }));
|
||||
validateConfig(merge({}, validConfig, { collections: [{ publish: 'false' }] }));
|
||||
}).toThrowError("'collections[0].publish' should be boolean");
|
||||
});
|
||||
|
||||
it('should not throw if collection publish is a boolean', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge(validConfig, { collections: [{ publish: false }] }));
|
||||
validateConfig(merge({}, validConfig, { collections: [{ publish: false }] }));
|
||||
}).not.toThrowError();
|
||||
});
|
||||
|
||||
@ -201,10 +201,48 @@ describe('config', () => {
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw if collection names are not unique', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
collections: [validConfig.collections[0], validConfig.collections[0]],
|
||||
}),
|
||||
);
|
||||
}).toThrowError("'collections' collections names must be unique");
|
||||
});
|
||||
|
||||
it('should throw if collection file names are not unique', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
collections: [
|
||||
{},
|
||||
{
|
||||
files: [
|
||||
{
|
||||
name: 'a',
|
||||
label: 'a',
|
||||
file: 'a.md',
|
||||
fields: [{ name: 'title', label: 'title', widget: 'string' }],
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'b',
|
||||
file: 'b.md',
|
||||
fields: [{ name: 'title', label: 'title', widget: 'string' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
}).toThrowError("'collections[1].files' files names must be unique");
|
||||
});
|
||||
|
||||
it('should throw if collection fields names are not unique', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge(validConfig, {
|
||||
merge({}, validConfig, {
|
||||
collections: [
|
||||
{
|
||||
fields: [
|
||||
@ -221,7 +259,7 @@ describe('config', () => {
|
||||
it('should not throw if collection fields are unique across nesting levels', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge(validConfig, {
|
||||
merge({}, validConfig, {
|
||||
collections: [
|
||||
{
|
||||
fields: [
|
||||
@ -257,7 +295,7 @@ describe('config', () => {
|
||||
it('should throw if nested relation displayFields and searchFields are not arrays', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge(validConfig, {
|
||||
merge({}, validConfig, {
|
||||
collections: [
|
||||
{
|
||||
fields: [
|
||||
@ -288,7 +326,7 @@ describe('config', () => {
|
||||
it('should not throw if nested relation displayFields and searchFields are arrays', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge(validConfig, {
|
||||
merge({}, validConfig, {
|
||||
collections: [
|
||||
{
|
||||
fields: [
|
||||
@ -358,5 +396,45 @@ describe('config', () => {
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw if collection field pattern is not an array', () => {
|
||||
expect(() => {
|
||||
validateConfig(merge({}, validConfig, { collections: [{ fields: [{ pattern: '' }] }] }));
|
||||
}).toThrowError("'collections[0].fields[0].pattern' should be array");
|
||||
});
|
||||
|
||||
it('should throw if collection field pattern is not an array of [string|regex, string]', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, { collections: [{ fields: [{ pattern: [1, ''] }] }] }),
|
||||
);
|
||||
}).toThrowError(
|
||||
"'collections[0].fields[0].pattern[0]' should be string\n'collections[0].fields[0].pattern[0]' should be a regular expression",
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, { collections: [{ fields: [{ pattern: ['', 1] }] }] }),
|
||||
);
|
||||
}).toThrowError("'collections[0].fields[0].pattern[1]' should be string");
|
||||
});
|
||||
|
||||
it('should allow collection field pattern to be an array of [string|regex, string]', () => {
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
collections: [{ fields: [{ pattern: ['pattern', 'error'] }] }],
|
||||
}),
|
||||
);
|
||||
}).not.toThrow();
|
||||
|
||||
expect(() => {
|
||||
validateConfig(
|
||||
merge({}, validConfig, {
|
||||
collections: [{ fields: [{ pattern: [/pattern/, 'error'] }] }],
|
||||
}),
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import AJV from 'ajv';
|
||||
import { select, uniqueItemProperties } from 'ajv-keywords/keywords';
|
||||
import { select, uniqueItemProperties, instanceof as instanceOf } from 'ajv-keywords/keywords';
|
||||
import ajvErrors from 'ajv-errors';
|
||||
import { formatExtensions, frontmatterFormats, extensionFormatters } from 'Formats/formats';
|
||||
import { getWidgets } from 'Lib/registry';
|
||||
@ -21,7 +21,11 @@ const fieldsConfig = () => ({
|
||||
widget: { type: 'string' },
|
||||
required: { type: 'boolean' },
|
||||
hint: { type: 'string' },
|
||||
pattern: { type: 'array', minItems: 2, items: { type: 'string' } },
|
||||
pattern: {
|
||||
type: 'array',
|
||||
minItems: 2,
|
||||
items: [{ oneOf: [{ type: 'string' }, { instanceof: 'RegExp' }] }, { type: 'string' }],
|
||||
},
|
||||
field: { $ref: 'field' },
|
||||
fields: { $ref: 'fields' },
|
||||
types: { $ref: 'fields' },
|
||||
@ -274,25 +278,40 @@ export function validateConfig(config) {
|
||||
const ajv = new AJV({ allErrors: true, jsonPointers: true, $data: true });
|
||||
uniqueItemProperties(ajv);
|
||||
select(ajv);
|
||||
instanceOf(ajv);
|
||||
ajvErrors(ajv);
|
||||
|
||||
const valid = ajv.validate(getConfigSchema(), config);
|
||||
if (!valid) {
|
||||
const errors = ajv.errors.map(e => {
|
||||
// TODO: remove after https://github.com/ajv-validator/ajv-keywords/pull/123 is merged
|
||||
if (e.keyword === 'uniqueItemProperties') {
|
||||
const path = e.dataPath || '';
|
||||
let newError = e;
|
||||
if (path.endsWith('/fields')) {
|
||||
newError = { ...e, message: 'fields names must be unique' };
|
||||
} else if (path.endsWith('/files')) {
|
||||
newError = { ...e, message: 'files names must be unique' };
|
||||
} else if (path.endsWith('/collections')) {
|
||||
newError = { ...e, message: 'collections names must be unique' };
|
||||
switch (e.keyword) {
|
||||
// TODO: remove after https://github.com/ajv-validator/ajv-keywords/pull/123 is merged
|
||||
case 'uniqueItemProperties': {
|
||||
const path = e.dataPath || '';
|
||||
let newError = e;
|
||||
if (path.endsWith('/fields')) {
|
||||
newError = { ...e, message: 'fields names must be unique' };
|
||||
} else if (path.endsWith('/files')) {
|
||||
newError = { ...e, message: 'files names must be unique' };
|
||||
} else if (path.endsWith('/collections')) {
|
||||
newError = { ...e, message: 'collections names must be unique' };
|
||||
}
|
||||
return newError;
|
||||
}
|
||||
return newError;
|
||||
case 'instanceof': {
|
||||
const path = e.dataPath || '';
|
||||
let newError = e;
|
||||
if (/fields\/\d+\/pattern\/\d+/.test(path)) {
|
||||
newError = {
|
||||
...e,
|
||||
message: 'should be a regular expression',
|
||||
};
|
||||
}
|
||||
return newError;
|
||||
}
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
return e;
|
||||
});
|
||||
console.error('Config Errors', errors);
|
||||
throw new ConfigError(errors);
|
||||
|
Loading…
x
Reference in New Issue
Block a user