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', () => {
|
it('should throw if collection publish is not a boolean', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(merge(validConfig, { collections: [{ publish: 'false' }] }));
|
validateConfig(merge({}, validConfig, { collections: [{ publish: 'false' }] }));
|
||||||
}).toThrowError("'collections[0].publish' should be boolean");
|
}).toThrowError("'collections[0].publish' should be boolean");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not throw if collection publish is a boolean', () => {
|
it('should not throw if collection publish is a boolean', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(merge(validConfig, { collections: [{ publish: false }] }));
|
validateConfig(merge({}, validConfig, { collections: [{ publish: false }] }));
|
||||||
}).not.toThrowError();
|
}).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -201,10 +201,48 @@ describe('config', () => {
|
|||||||
}).not.toThrow();
|
}).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', () => {
|
it('should throw if collection fields names are not unique', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(
|
validateConfig(
|
||||||
merge(validConfig, {
|
merge({}, validConfig, {
|
||||||
collections: [
|
collections: [
|
||||||
{
|
{
|
||||||
fields: [
|
fields: [
|
||||||
@ -221,7 +259,7 @@ describe('config', () => {
|
|||||||
it('should not throw if collection fields are unique across nesting levels', () => {
|
it('should not throw if collection fields are unique across nesting levels', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(
|
validateConfig(
|
||||||
merge(validConfig, {
|
merge({}, validConfig, {
|
||||||
collections: [
|
collections: [
|
||||||
{
|
{
|
||||||
fields: [
|
fields: [
|
||||||
@ -257,7 +295,7 @@ describe('config', () => {
|
|||||||
it('should throw if nested relation displayFields and searchFields are not arrays', () => {
|
it('should throw if nested relation displayFields and searchFields are not arrays', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(
|
validateConfig(
|
||||||
merge(validConfig, {
|
merge({}, validConfig, {
|
||||||
collections: [
|
collections: [
|
||||||
{
|
{
|
||||||
fields: [
|
fields: [
|
||||||
@ -288,7 +326,7 @@ describe('config', () => {
|
|||||||
it('should not throw if nested relation displayFields and searchFields are arrays', () => {
|
it('should not throw if nested relation displayFields and searchFields are arrays', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
validateConfig(
|
validateConfig(
|
||||||
merge(validConfig, {
|
merge({}, validConfig, {
|
||||||
collections: [
|
collections: [
|
||||||
{
|
{
|
||||||
fields: [
|
fields: [
|
||||||
@ -358,5 +396,45 @@ describe('config', () => {
|
|||||||
);
|
);
|
||||||
}).not.toThrow();
|
}).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 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 ajvErrors from 'ajv-errors';
|
||||||
import { formatExtensions, frontmatterFormats, extensionFormatters } from 'Formats/formats';
|
import { formatExtensions, frontmatterFormats, extensionFormatters } from 'Formats/formats';
|
||||||
import { getWidgets } from 'Lib/registry';
|
import { getWidgets } from 'Lib/registry';
|
||||||
@ -21,7 +21,11 @@ const fieldsConfig = () => ({
|
|||||||
widget: { type: 'string' },
|
widget: { type: 'string' },
|
||||||
required: { type: 'boolean' },
|
required: { type: 'boolean' },
|
||||||
hint: { type: 'string' },
|
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' },
|
field: { $ref: 'field' },
|
||||||
fields: { $ref: 'fields' },
|
fields: { $ref: 'fields' },
|
||||||
types: { $ref: 'fields' },
|
types: { $ref: 'fields' },
|
||||||
@ -274,25 +278,40 @@ export function validateConfig(config) {
|
|||||||
const ajv = new AJV({ allErrors: true, jsonPointers: true, $data: true });
|
const ajv = new AJV({ allErrors: true, jsonPointers: true, $data: true });
|
||||||
uniqueItemProperties(ajv);
|
uniqueItemProperties(ajv);
|
||||||
select(ajv);
|
select(ajv);
|
||||||
|
instanceOf(ajv);
|
||||||
ajvErrors(ajv);
|
ajvErrors(ajv);
|
||||||
|
|
||||||
const valid = ajv.validate(getConfigSchema(), config);
|
const valid = ajv.validate(getConfigSchema(), config);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
const errors = ajv.errors.map(e => {
|
const errors = ajv.errors.map(e => {
|
||||||
// TODO: remove after https://github.com/ajv-validator/ajv-keywords/pull/123 is merged
|
switch (e.keyword) {
|
||||||
if (e.keyword === 'uniqueItemProperties') {
|
// TODO: remove after https://github.com/ajv-validator/ajv-keywords/pull/123 is merged
|
||||||
const path = e.dataPath || '';
|
case 'uniqueItemProperties': {
|
||||||
let newError = e;
|
const path = e.dataPath || '';
|
||||||
if (path.endsWith('/fields')) {
|
let newError = e;
|
||||||
newError = { ...e, message: 'fields names must be unique' };
|
if (path.endsWith('/fields')) {
|
||||||
} else if (path.endsWith('/files')) {
|
newError = { ...e, message: 'fields names must be unique' };
|
||||||
newError = { ...e, message: 'files names must be unique' };
|
} else if (path.endsWith('/files')) {
|
||||||
} else if (path.endsWith('/collections')) {
|
newError = { ...e, message: 'files names must be unique' };
|
||||||
newError = { ...e, message: 'collections 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);
|
console.error('Config Errors', errors);
|
||||||
throw new ConfigError(errors);
|
throw new ConfigError(errors);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user