-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathindex.js
151 lines (131 loc) · 4.45 KB
/
index.js
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import path from 'path'
import Joi from 'joi'
import chalk from 'chalk'
import moduleSchemaFn from './properties/module'
import entrySchema from './properties/entry'
import contextSchema from './properties/context'
import devtoolSchema from './properties/devtool'
import externalsSchema from './properties/externals'
import nodeSchema from './properties/node'
import pluginsSchema from './properties/plugins'
import resolveSchemaFn from './properties/resolve'
import outputSchema from './properties/output'
import watchOptionsSchema from './properties/watchOptions'
import devServerSchema from './properties/devServer'
import performanceSchema from './properties/performance'
import { looksLikeAbsolutePath } from './types'
import _merge from 'lodash/merge'
import sh from 'shelljs'
import semver from 'semver'
sh.config.silent = true
const defaultSchemaOptions = {
rules: {
'no-root-files-node-modules-nameclash': true,
'loader-enforce-include-or-exclude': false,
'loader-prefer-include': false,
},
}
function makeSchema(schemaOptions, schemaExtension) {
const resolveSchema = resolveSchemaFn(schemaOptions)
const moduleSchema = moduleSchemaFn(schemaOptions)
const schema = Joi.object({
amd: Joi.object(),
bail: Joi.boolean(),
cache: Joi.boolean(),
context: contextSchema,
debug: Joi.boolean(),
devServer: devServerSchema,
devtool: devtoolSchema,
entry: entrySchema,
externals: externalsSchema,
loader: Joi.any(), // ?
module: moduleSchema,
node: nodeSchema,
output: outputSchema,
plugins: pluginsSchema,
profile: Joi.boolean(),
progress: Joi.boolean(),
recordsInputPath: looksLikeAbsolutePath,
recordsOutputPath: looksLikeAbsolutePath,
recordsPath: looksLikeAbsolutePath,
resolve: resolveSchema,
resolveLoader: resolveSchema.concat(Joi.object({
moduleTemplates: Joi.array().items(Joi.string()),
})),
watch: Joi.boolean(),
watchOptions: watchOptionsSchema,
performance: performanceSchema,
stats: Joi.any(), // TODO
target: Joi.any(), // TODO
// Plugins
postcss: Joi.any(),
eslint: Joi.any(),
tslint: Joi.any(),
metadata: Joi.any(),
})
return schemaExtension ? schema.concat(schemaExtension) : schema
}
function throwForWebpack2() {
const cwd = process.cwd()
let satisifies = true
try {
const webpackPackagePath = path.join(cwd, 'node_modules', 'webpack', 'package.json')
const { version } = require(webpackPackagePath)
satisifies = semver.satisfies(version, '^1.x')
} catch (error) {
// ignore...
}
if (!satisifies) {
throw new Error(
'It looks like you\'re using version 2 or greater of webpack. ' +
'The official release of 2 of webpack was released with built-in validation. ' +
'So webpack-validator does not support that version. ' +
'Please uninstall webpack-validator and remove it from your project!'
)
}
}
function validate(config, options = {}) {
const {
// Don't return the config object and throw on error, but just return the validation result
returnValidation, // bool
schema: overrideSchema, // Don't take internal schema, but override with this one
schemaExtension, // Internal schema will be `Joi.concat`-ted with this schema if supplied
rules,
} = options
throwForWebpack2()
const schemaOptions = _merge(defaultSchemaOptions, { rules })
const schema = overrideSchema || makeSchema(schemaOptions, schemaExtension)
const validationResult = Joi.validate(config, schema, { abortEarly: false })
validationResult.schemaOptions = schemaOptions // Mainly for having sth to assert on right now
if (returnValidation) return validationResult
if (validationResult.error) {
console.error(validationResult.error.annotate())
process.exit(1)
}
return config
}
module.exports = validate
// Easier consumability for require (default use case for non-transpiled webpack configs)
function validateRoot(config, options = {}) {
const {
quiet,
} = options
let validationResult,
multiValidationResults
if (Array.isArray(config)) {
multiValidationResults = []
config.forEach((cfg) => {
multiValidationResults.push(
validate(cfg, options)
)
})
} else {
validationResult = validate(config, options)
}
if (!quiet) {
console.info(chalk.green('[webpack-validator] Config is valid.'))
}
return validationResult || multiValidationResults
}
module.exports.validateRoot = validateRoot
module.exports.Joi = Joi