-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
/
validationUtils.ts
108 lines (93 loc) · 2.79 KB
/
validationUtils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import logger from '@docusaurus/logger';
import Yaml from 'js-yaml';
import {PluginIdSchema} from './validationSchemas';
import type {ValidationOptions} from 'joi';
import type Joi from './Joi';
/** Print warnings returned from Joi validation. */
export function printWarning(warning?: Joi.ValidationError): void {
if (warning) {
const warningMessages = warning.details
.map(({message}) => message)
.join('\n');
logger.warn(warningMessages);
}
}
/**
* The callback that should be used to validate plugin options. Handles plugin
* IDs on a generic level: no matter what the schema declares, this callback
* would require a string ID or default to "default".
*/
export function normalizePluginOptions<T extends {id?: string}>(
schema: Joi.ObjectSchema<T>,
// This allows us to automatically normalize undefined to { id: "default" }
options: Partial<T> = {},
): T {
// All plugins can be provided an "id" option (multi-instance support)
// we add schema validation automatically
const finalSchema = schema.append({
id: PluginIdSchema,
});
const {error, warning, value} = finalSchema.validate(options, {
convert: false,
});
printWarning(warning);
if (error) {
throw error;
}
return value;
}
/**
* The callback that should be used to validate theme config. No matter what the
* schema declares, this callback would allow unknown attributes.
*/
export function normalizeThemeConfig<T>(
schema: Joi.ObjectSchema<T>,
themeConfig: Partial<T>,
): T {
// A theme should only validate its "slice" of the full themeConfig,
// not the whole object, so we allow unknown attributes
// otherwise one theme would fail validating the data of another theme
const finalSchema = schema.unknown();
const {error, warning, value} = finalSchema.validate(themeConfig, {
convert: false,
});
printWarning(warning);
if (error) {
throw error;
}
return value;
}
/**
* Validate front matter with better error message
*/
export function validateFrontMatter<T>(
frontMatter: unknown,
schema: Joi.ObjectSchema<T>,
options?: ValidationOptions,
): T {
const {value, error, warning} = schema.validate(frontMatter, {
convert: true,
allowUnknown: true,
abortEarly: false,
...options,
});
printWarning(warning);
if (error) {
const errorDetails = error.details;
const invalidFields = errorDetails.map(({path}) => path).join(', ');
logger.error`The following front matter:
---
${Yaml.dump(frontMatter)}---
contains invalid values for field(s): code=${invalidFields}.
${errorDetails.map(({message}) => message)}
`;
throw error;
}
return value;
}