This repository has been archived by the owner on Jul 19, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 363
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor slate-config to simplified schema
- Refactor @shopify/slate-config to use new config structure - Replace all config schemas with new structure - Replace all usage of config items with new .get() format - Fix any exisiting tests for config items
- Loading branch information
t-kelly
committed
Sep 6, 2018
1 parent
fb7b1ac
commit fb117e0
Showing
51 changed files
with
735 additions
and
913 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,4 @@ | ||
module.exports = { | ||
testSchema: { | ||
'test-item': 'override-value', | ||
}, | ||
otherSchema: { | ||
'other-item': 'other-value', | ||
}, | ||
'some.key': 'override-value', | ||
'other.item': 'other-value', | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,98 @@ | ||
const slateConfig = require('../index'); | ||
const testSchema = require('./fixtures/testSchema'); | ||
const otherSchema = require('./fixtures/otherSchema'); | ||
|
||
describe('.generate()', () => { | ||
describe('can generate a config object', () => { | ||
test('with default values', () => { | ||
const config = slateConfig.generate(testSchema); | ||
|
||
expect(config).toHaveProperty( | ||
testSchema.items[0].id, | ||
testSchema.items[0].default, | ||
); | ||
}); | ||
|
||
test('with slaterc overrides', () => { | ||
const mockSlateRc = require('./fixtures/slate.config.js'); | ||
const config = slateConfig.generate(testSchema, mockSlateRc); | ||
|
||
expect(config).toHaveProperty(testSchema.items[0].id, 'override-value'); | ||
}); | ||
|
||
test('with namespaced settings', () => { | ||
const mockSlateRc = require('./fixtures/slate.config.js'); | ||
const config1 = slateConfig.generate(testSchema, mockSlateRc); | ||
const config2 = slateConfig.generate(otherSchema, mockSlateRc); | ||
|
||
expect(config1).toHaveProperty( | ||
testSchema.items[0].id, | ||
mockSlateRc[testSchema.id][testSchema.items[0].id], | ||
); | ||
expect(config2).toHaveProperty( | ||
otherSchema.items[0].id, | ||
mockSlateRc[otherSchema.id][otherSchema.items[0].id], | ||
); | ||
}); | ||
|
||
test('with the schema used to generate the config', () => { | ||
const config = slateConfig.generate(testSchema); | ||
|
||
expect(config).toHaveProperty('__schema'); | ||
expect(config.__schema).toEqual(testSchema); | ||
}); | ||
const path = require('path'); | ||
|
||
const originalCwd = process.cwd(); | ||
const schema = { | ||
'some.key': 'someValue', | ||
'some.other.key': 'someOtherValue', | ||
'some.function': jest.fn((config) => config.get('some.other.key')), | ||
}; | ||
|
||
describe('SlateConfig()', () => { | ||
beforeEach(() => { | ||
process.chdir(originalCwd); | ||
jest.resetModules(); | ||
global.slateUserConfig = null; | ||
}); | ||
|
||
test('requires a first argument which is assigned to this.schema', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
|
||
expect(config.schema).toMatchObject(schema); | ||
expect(() => new SlateConfig()).toThrowError(); | ||
}); | ||
|
||
test('has an optional second argument which is assigned to this.userConfig', () => { | ||
const SlateConfig = require('../index'); | ||
const userConfig = { | ||
'some.key': 'someNewValue', | ||
}; | ||
const config = new SlateConfig(schema, userConfig); | ||
|
||
expect(config.userConfig).toBe(userConfig); | ||
}); | ||
|
||
test('if a second argument is undefined, assigns the contents of a the slate.config.js file in the cwd to this.userConfig', () => { | ||
process.chdir(path.resolve(__dirname, './fixtures')); | ||
|
||
const SlateConfig = require('../index'); | ||
const userConfig = require('./fixtures/slate.config'); | ||
const config = new SlateConfig(schema); | ||
|
||
expect(config.userConfig).toMatchObject(userConfig); | ||
}); | ||
|
||
test('copies the values of this.userConfig into this.schema, replacing any exisiting values', () => { | ||
const SlateConfig = require('../index'); | ||
const userConfig = { | ||
'some.key': 'someNewValue', | ||
}; | ||
const config = new SlateConfig(schema, userConfig); | ||
|
||
expect(config.schema).toMatchObject(config.userConfig); | ||
}); | ||
}); | ||
|
||
describe('SlateConfig.get()', () => { | ||
test('fetches the value of the provided key', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
|
||
expect(config.get('some.other.key')).toBe(schema['some.other.key']); | ||
}); | ||
|
||
test('if the value is a function, the function is executed with the config instance as the only argument', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
const value = config.get('some.function'); | ||
|
||
expect(schema['some.function']).toBeCalledWith(config); | ||
expect(value).toBe(schema['some.other.key']); | ||
}); | ||
|
||
test('if the value is a function, it is replaced with the returned value of that function after .get() has been called', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
const value = config.get('some.function'); | ||
|
||
expect(config.schema['some.function']).toBe(value); | ||
}); | ||
}); | ||
|
||
describe('SlateConfig.set()', () => { | ||
test('sets the value of a config for a given key', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
|
||
config.set('some.new.key', 'someNewValue'); | ||
|
||
expect(config.schema['some.new.key']).toBe('someNewValue'); | ||
}); | ||
|
||
test('throws an error if key has already been set, unless override boolean has been explicitely set', () => { | ||
const SlateConfig = require('../index'); | ||
const config = new SlateConfig(schema); | ||
|
||
expect(() => config.set('some.key', 'someOtherValue')).toThrowError(); | ||
}); | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const path = require('path'); | ||
|
||
module.exports = { | ||
// Returns the root directory of the theme | ||
'paths.theme': process.cwd(), | ||
|
||
// Theme node_modules directory | ||
'paths.theme.nodeModules': (config) => | ||
path.join(config.get('paths.theme'), 'node_modules'), | ||
|
||
// Theme package.json file | ||
'paths.theme.packageJson': (config) => | ||
path.join(config.get('paths.theme'), 'package.json'), | ||
|
||
// Source directory of theme | ||
'paths.theme.src': (config) => path.join(config.get('paths.theme'), 'src'), | ||
|
||
// Source of theme configuration files | ||
'paths.theme.src.config': (config) => | ||
path.join(config.get('paths.theme.src'), 'config'), | ||
|
||
// Source font directory for theme | ||
'paths.theme.src.fonts': (config) => | ||
path.join(config.get('paths.theme.src'), 'assets', 'fonts'), | ||
|
||
// Source of images directory | ||
'paths.theme.src.images': (config) => | ||
path.join(config.get('paths.theme.src'), 'assets', 'images'), | ||
|
||
// Source of theme liquid layout files | ||
'paths.theme.src.layouts': (config) => | ||
path.join(config.get('paths.theme.src'), 'layout'), | ||
|
||
// Source of translation locales | ||
'paths.theme.src.locales': (config) => | ||
path.join(config.get('paths.theme.src'), 'locales'), | ||
|
||
// Source scripts directory for theme | ||
'paths.theme.src.scripts': (config) => | ||
path.join(config.get('paths.theme.src'), 'assets', 'scripts'), | ||
|
||
// Source snippets directory | ||
'paths.theme.src.snippets': (config) => | ||
path.join(config.get('paths.theme.src'), 'snippets'), | ||
|
||
// Static asset directory for files that statically copied to paths.theme.dist.assets | ||
'paths.theme.src.static': (config) => | ||
path.join(config.get('paths.theme.src'), 'assets', 'static'), | ||
|
||
// Main SVG source directory for theme | ||
'paths.theme.src.svgs': (config) => | ||
path.join(config.get('paths.theme.src'), 'assets', 'svg'), | ||
|
||
// Source liquid template directory | ||
'paths.theme.src.templates': (config) => | ||
path.join(config.get('paths.theme.src'), 'templates'), | ||
|
||
// Source liquid template directory | ||
'paths.theme.src.templates.customers': (config) => | ||
path.join(config.get('paths.theme.src.templates'), 'customers'), | ||
|
||
// Distribution directory of theme | ||
'paths.theme.dist': (config) => path.join(config.get('paths.theme'), 'dist'), | ||
|
||
// Distribution assets directory | ||
'paths.theme.dist.assets': (config) => | ||
path.join(config.get('paths.theme.dist'), 'assets'), | ||
|
||
// Distribution assets directory | ||
'paths.theme.dist.config': (config) => | ||
path.join(config.get('paths.theme.dist'), 'config'), | ||
|
||
// Distribution snippets directory | ||
'paths.theme.dist.snippets': (config) => | ||
path.join(config.get('paths.theme.dist'), 'snippets'), | ||
|
||
// Distribution snippets directory | ||
'paths.theme.dist.locales': (config) => | ||
path.join(config.get('paths.theme.dist'), 'locales'), | ||
|
||
// Directory for storing all temporary and/or cache files | ||
'paths.theme.cache': (config) => | ||
path.join(config.get('paths.theme'), '.cache'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,56 @@ | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
|
||
const themeDirectory = fs.realpathSync(process.cwd()); | ||
// Fetch the contents of Slate's user config once, and only once | ||
global.slateUserConfig = global.slateUserConfig || getSlateUserConfig(); | ||
|
||
function getSlateConfig() { | ||
try { | ||
const slateRcPath = resolveTheme('slate.config.js'); | ||
return require(slateRcPath); | ||
} catch (error) { | ||
return {}; | ||
} | ||
} | ||
|
||
function generate(schema, slaterc = getSlateConfig()) { | ||
// Creates a config object of default or slaterc values | ||
const config = _generateConfig([schema], slaterc)[schema.id]; | ||
config.__schema = schema; | ||
module.exports = class SlateConfig { | ||
constructor(schema, userConfigOverride) { | ||
if (typeof schema === 'undefined') { | ||
throw new TypeError( | ||
'[slate-config]: A schema object must be provided as the first argument', | ||
); | ||
} | ||
|
||
return config; | ||
} | ||
this.userConfigOverride = userConfigOverride; | ||
this.schema = Object.assign({}, schema, this.userConfig); | ||
} | ||
|
||
function _generateConfig(items, overrides) { | ||
const config = {}; | ||
get userConfig() { | ||
return typeof this.userConfigOverride === 'object' | ||
? this.userConfigOverride | ||
: global.slateUserConfig; | ||
} | ||
|
||
items.forEach((item) => { | ||
if (Array.isArray(item.items)) { | ||
config[item.id] = _generateConfig( | ||
item.items, | ||
overrides && overrides[item.id], | ||
set(key, value, override = false) { | ||
if (typeof this.schema[key] !== 'undefined' && !override) { | ||
throw new Error( | ||
`[slate-config]: A value for '${key}' has already been set. A value can only be set once.`, | ||
); | ||
} else if (overrides && typeof overrides[item.id] !== 'undefined') { | ||
config[item.id] = overrides[item.id]; | ||
} else if (typeof item.default !== 'undefined') { | ||
config[item.id] = item.default; | ||
} | ||
}); | ||
|
||
return config; | ||
} | ||
|
||
function resolveTheme(relativePath) { | ||
return path.resolve(themeDirectory, relativePath); | ||
} | ||
this.schema[key] = value; | ||
} | ||
|
||
function resolveSelf(relativePath) { | ||
return path.resolve(__dirname, relativePath); | ||
} | ||
get(key) { | ||
const value = this.schema[key]; | ||
|
||
module.exports = { | ||
generate, | ||
resolveTheme, | ||
resolveSelf, | ||
getSlateConfig, | ||
if (typeof value === 'function') { | ||
// Set the computed value so we don't need to recompute this value multiple times | ||
return (this.schema[key] = value(this)); | ||
} else if (typeof value === 'undefined') { | ||
throw new Error( | ||
`[slate-config]: A value has not been defined for the key '${key}'`, | ||
); | ||
} else { | ||
return value; | ||
} | ||
} | ||
}; | ||
|
||
function getSlateUserConfig() { | ||
try { | ||
return require(path.join(process.cwd(), 'slate.config.js')); | ||
} catch (error) { | ||
return {}; | ||
} | ||
} |
Oops, something went wrong.