polymer-project-config
Advanced tools
Comparing version 1.2.0 to 2.0.0
@@ -8,4 +8,9 @@ # Change Log | ||
## Unreleased - Breaking Changes | ||
## Unreleased | ||
## [2.0.0] - 2017-02-10 | ||
* [BREAKING] polymer.json is validated upon being read and an error will be thrown if any fields are of the wrong type. All toplevel fields are optional, and no error is thrown on encountering extra fields. | ||
* Added "lint" config option for configuring polymer-lint. | ||
## [1.2.0] - 2017-01-27 | ||
@@ -12,0 +17,0 @@ |
@@ -22,2 +22,14 @@ /** | ||
} | ||
export interface LintOptions { | ||
/** | ||
* The lint rules to run. Can be the code of a collection of rules like | ||
* "polymer-2" or an individual rule like "dom-module-invalid-attrs". | ||
*/ | ||
rules: string[]; | ||
/** | ||
* Warnings to ignore. After the rules are run, any warning that matches | ||
* one of these codes is ignored, project-wide. | ||
*/ | ||
ignoreWarnings?: string[]; | ||
} | ||
export interface ProjectOptions { | ||
@@ -58,2 +70,6 @@ /** | ||
builds?: ProjectBuildOptions[]; | ||
/** | ||
* Options for the Polymer Linter. | ||
*/ | ||
lint?: LintOptions; | ||
} | ||
@@ -69,2 +85,3 @@ export declare class ProjectConfig { | ||
readonly allFragments: string[]; | ||
readonly lint: LintOptions | undefined; | ||
/** | ||
@@ -74,2 +91,4 @@ * Given an absolute file path to a polymer.json-like ProjectOptions object, | ||
* but there is a problem reading or parsing it, throw an exception. | ||
* | ||
* TODO: make this method and the one below async. | ||
*/ | ||
@@ -76,0 +95,0 @@ static loadOptionsFromFile(filepath: string): ProjectOptions; |
@@ -14,2 +14,3 @@ /** | ||
const logging = require("plylog"); | ||
const jsonschema = require("jsonschema"); | ||
const minimatchAll = require("minimatch-all"); | ||
@@ -62,33 +63,2 @@ const logger = logging.getLogger('polymer-project-config'); | ||
/** | ||
* Given an absolute file path to a polymer.json-like ProjectOptions object, | ||
* read that file. If no file exists, null is returned. If the file exists | ||
* but there is a problem reading or parsing it, throw an exception. | ||
*/ | ||
static loadOptionsFromFile(filepath) { | ||
try { | ||
const configContent = fs.readFileSync(filepath, 'utf-8'); | ||
return JSON.parse(configContent); | ||
} | ||
catch (error) { | ||
// swallow "not found" errors because they are so common / expected | ||
if (error.code === 'ENOENT') { | ||
logger.debug('no polymer config file found', { file: filepath }); | ||
return null; | ||
} | ||
// otherwise, throw an exception | ||
throw error; | ||
} | ||
} | ||
/** | ||
* Given an absolute file path to a polymer.json-like ProjectOptions object, | ||
* return a new ProjectConfig instance created with those options. | ||
*/ | ||
static loadConfigFromFile(filepath) { | ||
let configParsed = ProjectConfig.loadOptionsFromFile(filepath); | ||
if (!configParsed) { | ||
return null; | ||
} | ||
return new ProjectConfig(configParsed); | ||
} | ||
/** | ||
* constructor - given a ProjectOptions object, create the correct project | ||
@@ -100,2 +70,3 @@ * configuration for those options. This involves setting the correct | ||
constructor(options) { | ||
this.lint = undefined; | ||
options = (options) ? fixDeprecatedOptions(options) : {}; | ||
@@ -166,2 +137,5 @@ /** | ||
} | ||
if (options.lint) { | ||
this.lint = options.lint; | ||
} | ||
/** | ||
@@ -174,2 +148,44 @@ * builds | ||
} | ||
/** | ||
* Given an absolute file path to a polymer.json-like ProjectOptions object, | ||
* read that file. If no file exists, null is returned. If the file exists | ||
* but there is a problem reading or parsing it, throw an exception. | ||
* | ||
* TODO: make this method and the one below async. | ||
*/ | ||
static loadOptionsFromFile(filepath) { | ||
try { | ||
const configContent = fs.readFileSync(filepath, 'utf-8'); | ||
const contents = JSON.parse(configContent); | ||
const validator = new jsonschema.Validator(); | ||
const result = validator.validate(contents, getSchema()); | ||
if (result.throwError) { | ||
throw result.throwError; | ||
} | ||
if (result.errors.length > 0) { | ||
throw result.errors[0]; | ||
} | ||
return contents; | ||
} | ||
catch (error) { | ||
// swallow "not found" errors because they are so common / expected | ||
if (error && error.code === 'ENOENT') { | ||
logger.debug('no polymer config file found', { file: filepath }); | ||
return null; | ||
} | ||
// otherwise, throw an exception | ||
throw error; | ||
} | ||
} | ||
/** | ||
* Given an absolute file path to a polymer.json-like ProjectOptions object, | ||
* return a new ProjectConfig instance created with those options. | ||
*/ | ||
static loadConfigFromFile(filepath) { | ||
let configParsed = ProjectConfig.loadOptionsFromFile(filepath); | ||
if (!configParsed) { | ||
return null; | ||
} | ||
return new ProjectConfig(configParsed); | ||
} | ||
isFragment(filepath) { | ||
@@ -231,1 +247,13 @@ return this.allFragments.indexOf(filepath) !== -1; | ||
exports.ProjectConfig = ProjectConfig; | ||
// Gets the json schema for polymer.json, generated from the typescript | ||
// interface for runtime validation. See the build script in package.json for | ||
// more info. | ||
const getSchema = (() => { | ||
let schema = undefined; | ||
return () => { | ||
if (schema === undefined) { | ||
schema = JSON.parse(fs.readFileSync(path.join(__dirname, 'schema.json'), 'utf-8')); | ||
} | ||
return schema; | ||
}; | ||
})(); |
{ | ||
"name": "polymer-project-config", | ||
"version": "1.2.0", | ||
"version": "2.0.0", | ||
"description": "reads, validates, and shapes your polymer.json project configuration", | ||
@@ -18,3 +18,3 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"build": "tsc", | ||
"build": "tsc && typescript-json-schema src/index.ts ProjectOptions --ignoreErrors -o lib/schema.json", | ||
"test": "npm run build && mocha --ui tdd" | ||
@@ -24,2 +24,3 @@ }, | ||
"@types/node": "^6.0.41", | ||
"jsonschema": "^1.1.1", | ||
"minimatch-all": "^1.1.0", | ||
@@ -31,4 +32,5 @@ "plylog": "^0.4.0" | ||
"mocha": "^3.0.2", | ||
"typescript": "^2.0.2" | ||
"typescript": "^2.0.2", | ||
"typescript-json-schema": "^0.9.0" | ||
} | ||
} |
@@ -14,2 +14,4 @@ /** | ||
import * as logging from 'plylog'; | ||
import * as jsonschema from 'jsonschema'; | ||
import minimatchAll = require('minimatch-all'); | ||
@@ -75,2 +77,16 @@ | ||
export interface LintOptions { | ||
/** | ||
* The lint rules to run. Can be the code of a collection of rules like | ||
* "polymer-2" or an individual rule like "dom-module-invalid-attrs". | ||
*/ | ||
rules: string[]; | ||
/** | ||
* Warnings to ignore. After the rules are run, any warning that matches | ||
* one of these codes is ignored, project-wide. | ||
*/ | ||
ignoreWarnings?: string[]; | ||
} | ||
export interface ProjectOptions { | ||
@@ -117,2 +133,7 @@ /** | ||
builds?: ProjectBuildOptions[]; | ||
/** | ||
* Options for the Polymer Linter. | ||
*/ | ||
lint?: LintOptions; | ||
} | ||
@@ -131,2 +152,3 @@ | ||
readonly allFragments: string[]; | ||
readonly lint: LintOptions | undefined = undefined; | ||
@@ -137,2 +159,4 @@ /** | ||
* but there is a problem reading or parsing it, throw an exception. | ||
* | ||
* TODO: make this method and the one below async. | ||
*/ | ||
@@ -142,6 +166,15 @@ static loadOptionsFromFile(filepath: string): ProjectOptions { | ||
const configContent = fs.readFileSync(filepath, 'utf-8'); | ||
return JSON.parse(configContent); | ||
const contents = JSON.parse(configContent); | ||
const validator = new jsonschema.Validator(); | ||
const result = validator.validate(contents, getSchema()); | ||
if (result.throwError) { | ||
throw result.throwError; | ||
} | ||
if (result.errors.length > 0) { | ||
throw result.errors[0]; | ||
} | ||
return contents; | ||
} catch (error) { | ||
// swallow "not found" errors because they are so common / expected | ||
if (error.code === 'ENOENT') { | ||
if (error && error.code === 'ENOENT') { | ||
logger.debug('no polymer config file found', {file: filepath}); | ||
@@ -243,2 +276,6 @@ return null; | ||
if (options.lint) { | ||
this.lint = options.lint; | ||
} | ||
/** | ||
@@ -325,1 +362,16 @@ * builds | ||
} | ||
// Gets the json schema for polymer.json, generated from the typescript | ||
// interface for runtime validation. See the build script in package.json for | ||
// more info. | ||
const getSchema: () => jsonschema.Schema = (() => { | ||
let schema: jsonschema.Schema | undefined = undefined; | ||
return () => { | ||
if (schema === undefined) { | ||
schema = JSON.parse( | ||
fs.readFileSync(path.join(__dirname, 'schema.json'), 'utf-8')); | ||
} | ||
return schema; | ||
} | ||
})(); |
@@ -37,2 +37,3 @@ /** | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -57,2 +58,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -80,2 +82,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -104,2 +107,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -132,2 +136,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -156,2 +161,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -185,2 +191,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -217,2 +224,3 @@ }); | ||
], | ||
lint: undefined, | ||
}); | ||
@@ -469,7 +477,12 @@ }); | ||
test('throws an exception for invalid polymer.json', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid.json'); | ||
test('throws an exception for polymer.json with invalid syntax', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid-syntax.json'); | ||
assert.throws(() => ProjectConfig.loadOptionsFromFile(filepath)); | ||
}); | ||
test('throws an exception for polymer.json with invalid data', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid-type.json'); | ||
assert.throws(() => ProjectConfig.loadOptionsFromFile(filepath)); | ||
}); | ||
test('returns null if file is missing', () => { | ||
@@ -491,2 +504,8 @@ const filepath = path.join(__dirname, 'this-file-does-not-exist.json'); | ||
test('reads options from a file with just {} in it', () => { | ||
const options = ProjectConfig.loadOptionsFromFile( | ||
path.join(__dirname, 'polymer-minimal.json')); | ||
assert.deepEqual(options, {}); | ||
}); | ||
}); | ||
@@ -496,7 +515,12 @@ | ||
test('throws an exception for invalid polymer.json', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid.json'); | ||
test('throws an exception for polymer.json with invalid syntax', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid-syntax.json'); | ||
assert.throws(() => ProjectConfig.loadConfigFromFile(filepath)); | ||
}); | ||
test('throws an exception for polymer.json with invalid data', () => { | ||
const filepath = path.join(__dirname, 'polymer-invalid-type.json'); | ||
assert.throws(() => ProjectConfig.loadConfigFromFile(filepath)); | ||
}); | ||
test('returns null if file is missing', () => { | ||
@@ -524,8 +548,16 @@ const filepath = path.join(__dirname, 'this-file-does-not-exist.json'); | ||
path.resolve(absoluteRoot, 'bar.html'), | ||
] | ||
], | ||
lint: undefined, | ||
}); | ||
}); | ||
test('reads a valid config from a file with just {} in it', () => { | ||
const config = ProjectConfig.loadConfigFromFile( | ||
path.join(__dirname, 'polymer-minimal.json')); | ||
config.validate(); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
51813
18
1354
4
4
+ Addedjsonschema@^1.1.1
+ Addedjsonschema@1.4.1(transitive)