Skip to content

Commit a647a53

Browse files
jonathanglasmeyerKent C. Dodds
authored andcommitted
feat(lib): output subschema (#12)
1 parent e1701cc commit a647a53

File tree

9 files changed

+158
-15
lines changed

9 files changed

+158
-15
lines changed

src/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import externalsSchema from './properties/externals'
88
import nodeSchema from './properties/node'
99
import pluginsSchema from './properties/plugins'
1010
import resolveSchema from './properties/resolve'
11+
import outputSchema from './properties/output'
1112
import { absolutePath } from './types'
1213

1314
const schema = Joi.object({
@@ -23,7 +24,7 @@ const schema = Joi.object({
2324
loader: Joi.any(), // ?
2425
module: moduleSchema,
2526
node: nodeSchema,
26-
output: Joi.any(),
27+
output: outputSchema,
2728
plugins: pluginsSchema,
2829
profile: Joi.boolean(),
2930
recordsInputPath: absolutePath,
@@ -33,8 +34,8 @@ const schema = Joi.object({
3334
resolveLoader: resolveSchema.concat(Joi.object({
3435
moduleTemplates: Joi.array().items(Joi.string()),
3536
})),
36-
stats: Joi.any(),
37-
target: Joi.any(),
37+
stats: Joi.any(), // TODO
38+
target: Joi.any(), // TODO
3839

3940
// Plugins
4041
postcss: Joi.any(),

src/properties/devtool/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ const DEVTOOL_REGEX = new RegExp(
1717
'(#@|@|#)?' + // maybe one of the pragmas
1818
`(${options.join('|')})` // one of the options
1919
)
20-
console.info('[index.js] DEVTOOL_REGEX: ', DEVTOOL_REGEX)
21-
2220

2321
export default Joi
2422
.string()

src/properties/output/index.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
import Joi from 'joi'
2-
3-
// Not an absolute path (not starting with / and not containing /
4-
const notAPath = Joi.string().regex(/^(?!\/)[^\/]+$/)
2+
import { notAbsolutePath, absolutePath, urlPart } from '../../types'
53

64
export default Joi.object({
7-
filename: notAPath,
8-
chunkFilename: notAPath,
5+
filename: notAbsolutePath,
6+
path: absolutePath,
7+
publicPath: urlPart,
8+
chunkFilename: notAbsolutePath,
9+
sourceMapFilename: notAbsolutePath,
10+
devtoolModuleFilenameTemplate: [notAbsolutePath, Joi.func()],
11+
devtoolFallbackModuleFilenameTemplate: [notAbsolutePath, Joi.func()],
12+
devtoolLineToLine: Joi.any(),
13+
hotUpdateChunkFilename: notAbsolutePath,
14+
hotUpdateMainFilename: notAbsolutePath,
15+
jsonpFunction: Joi.string(),
16+
hotUpdateFunction: Joi.string(),
17+
pathinfo: Joi.bool(),
18+
library: notAbsolutePath,
19+
libraryTarget: Joi.string().valid(['var', 'this', 'commonjs', 'commonjs2', 'amd', 'umd']),
20+
umdNamedDefine: Joi.bool(),
21+
sourcePrefix: Joi.string(),
22+
crossOriginLoading: Joi.alternatives().try([
23+
Joi.bool().valid(false),
24+
Joi.string().valid(['anonymous', 'use-credentials']),
25+
]).options({ language: { boolean: {
26+
base: 'should be `false`, "anonymous" or "use-credentials"' } } }),
927
})
1028

src/properties/output/index.test.js

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,110 @@
11
import schema from './index'
22
import { allValid, allInvalid } from '../../../test/utils'
3+
import { notAbsolutePath, absolutePath, urlPart } from '../../types'
34

45
const validModuleConfigs = [
56
// #0
6-
// 'entry.js',
7+
{ filename: 'foo' },
8+
// #1
9+
{ chunkFilename: 'foo' },
10+
// #2
11+
{ path: 'foo/bar' },
12+
// #3
13+
{ path: '/foo/bar' },
14+
// #4
15+
{ publicPath: '/assets/' },
16+
// #5
17+
{ publicPath: 'http://cdn.example.com/assets/[hash]/' },
18+
// #6
19+
{ devtoolModuleFilenameTemplate: 'webpack:///[resourcePath]?[hash]' },
20+
// #7
21+
{ devtoolModuleFilenameTemplate: () => {} },
22+
// #8
23+
{ hotUpdateChunkFilename: '[id].[hash].hot-update.js' },
24+
// #9
25+
{ hotUpdateMainFilename: '[hash].hot-update.json' },
26+
// #10
27+
{ jsonpFunction: 'webpackJsonp' },
28+
// #11
29+
{ hotUpdateFunction: 'webpackHotUpdate' },
30+
// #12
31+
{ pathinfo: false },
32+
// #13
33+
{ library: 'redux' },
34+
// #14
35+
{ libraryTarget: 'commonjs' },
36+
// #15
37+
{ crossOriginLoading: false },
38+
// #16
39+
{ crossOriginLoading: 'anonymous' },
40+
741
]
842

943
const invalidModuleConfigs = [
1044
// #0
11-
// { input: 1, error: { message: '"value" must be a string' } },
45+
{
46+
input: {
47+
filename: '/foo/bar',
48+
},
49+
error: { message: `"filename" ${notAbsolutePath.message}` },
50+
},
51+
// #1
52+
{
53+
input: {
54+
chunkFilename: '/foo/bar',
55+
},
56+
error: { message: `"chunkFilename" ${notAbsolutePath.message}` },
57+
},
58+
// #2
59+
{
60+
input: {
61+
path: './foo/bar',
62+
},
63+
error: { message: `"path" ${absolutePath.message}` },
64+
},
65+
// #3
66+
{
67+
input: {
68+
publicPath: './foo',
69+
},
70+
error: { message: `"publicPath" ${urlPart.message}` },
71+
},
72+
// #4
73+
{
74+
input: {
75+
publicPath: '/foo',
76+
},
77+
error: { message: `"publicPath" ${urlPart.message}` },
78+
},
79+
// #5
80+
{
81+
input: {
82+
devtoolModuleFilenameTemplate: '/foo',
83+
},
84+
error: { message: `"devtoolModuleFilenameTemplate" ${notAbsolutePath.message}` },
85+
},
86+
// #6
87+
{
88+
input: {
89+
libraryTarget: 'comonjs',
90+
},
91+
error: { message: '"libraryTarget" must be one of [var, this, commonjs, commonjs2, amd, umd]' },
92+
},
93+
// #6
94+
{
95+
input: {
96+
crossOriginLoading: 'annonymous',
97+
},
98+
error: { message: '"crossOriginLoading" should be `false`, "anonymous" or "use-credentials"' },
99+
},
100+
// #7
101+
{
102+
input: {
103+
fileName: 'foo',
104+
},
105+
error: { message: '"fileName" is not allowed' },
106+
},
107+
12108
]
13109

14110
describe('output', () => {

src/types/absolutePath.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import Joi from 'joi'
22

3-
export default Joi
3+
const MESSAGE = 'must be an absolute path'
4+
const absolutePath = Joi
45
.string()
56
.regex(/^(?!\.?\.\/).+$/)
6-
.options({ language: { string: { regex: { base: 'must be an absolute path' } } } })
7+
.options({ language: { string: { regex: { base: MESSAGE } } } })
78

9+
absolutePath.message = MESSAGE
10+
11+
export default absolutePath

src/types/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export { default as absolutePath } from './absolutePath'
2+
export { default as notAbsolutePath } from './notAbsolutePath'
3+
export { default as urlPart } from './urlPart'

src/types/notAbsolutePath.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Joi from 'joi'
2+
3+
const MESSAGE = 'must not start with leading slash. ' +
4+
'You probably want to supply an absolute path here, but shouldn\'t.'
5+
6+
const notAbsolutePath = Joi
7+
.string()
8+
.regex(/^(?!\/).+$/)
9+
.options({ language: { string: { regex: { base: MESSAGE } } } })
10+
11+
notAbsolutePath.message = MESSAGE
12+
export default notAbsolutePath

src/types/urlPart.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Joi from 'joi'
2+
3+
const MESSAGE = 'should end with a slash (example: "/assets/" or "http://cdn.example.com/assets/[hash]/")'
4+
const urlPart = Joi
5+
.string()
6+
.regex(/\/$/)
7+
.options({ language: { string: { regex: { base: MESSAGE } } } })
8+
9+
urlPart.message = MESSAGE
10+
11+
export default urlPart
12+

test/mocha.opts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
--require test/setup
1+
--require test/setup -R dot

0 commit comments

Comments
 (0)