Unify order of properties and methods in services (#3353)
I find having these in a consistent order makes the services much faster to read. This is the order I’ve generally been using: 1. Category 2. Route 3. Examples 4. Rendering 5. Other helpers (`fetch()`, `transform()`) 6. `handle()`
This commit is contained in:
@@ -70,26 +70,6 @@ const serviceDataSchema = Joi.object({
|
||||
.required()
|
||||
|
||||
module.exports = class BaseService {
|
||||
constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
|
||||
this._requestFetcher = sendAndCacheRequest
|
||||
this._handleInternalErrors = handleInternalErrors
|
||||
}
|
||||
|
||||
static render(props) {
|
||||
throw new Error(`render() function not implemented for ${this.name}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous function to handle requests for this service. Take the route
|
||||
* parameters (as defined in the `route` property), perform a request using
|
||||
* `this._sendAndCacheRequest`, and return the badge data.
|
||||
*/
|
||||
async handle(namedParams, queryParams) {
|
||||
throw new Error(`Handler not implemented for ${this.constructor.name}`)
|
||||
}
|
||||
|
||||
// Metadata
|
||||
|
||||
/**
|
||||
* Name of the category to sort this badge into (eg. "build"). Used to sort
|
||||
* the badges on the main shields.io website.
|
||||
@@ -98,6 +78,10 @@ module.exports = class BaseService {
|
||||
throw new Error(`Category not set for ${this.name}`)
|
||||
}
|
||||
|
||||
static get isDeprecated() {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object:
|
||||
* - base: (Optional) The base path of the routes for this service. This is
|
||||
@@ -127,17 +111,14 @@ module.exports = class BaseService {
|
||||
throw new Error(`Route not defined for ${this.name}`)
|
||||
}
|
||||
|
||||
static get isDeprecated() {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Default data for the badge. Can include label, logo, and color. These
|
||||
* defaults are used if the value is neither included in the service data
|
||||
* from the handler nor overridden by the user via query parameters.
|
||||
*/
|
||||
static get defaultBadgeData() {
|
||||
return {}
|
||||
static get _cacheLength() {
|
||||
const cacheLengths = {
|
||||
build: 30,
|
||||
license: 3600,
|
||||
version: 300,
|
||||
debug: 60,
|
||||
}
|
||||
return cacheLengths[this.category]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,6 +153,15 @@ module.exports = class BaseService {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Default data for the badge. Can include label, logo, and color. These
|
||||
* defaults are used if the value is neither included in the service data
|
||||
* from the handler nor overridden by the user via query parameters.
|
||||
*/
|
||||
static get defaultBadgeData() {
|
||||
return {}
|
||||
}
|
||||
|
||||
static validateDefinition() {
|
||||
assertValidCategory(this.category, `Category for ${this.name}`)
|
||||
|
||||
@@ -219,14 +209,53 @@ module.exports = class BaseService {
|
||||
return result
|
||||
}
|
||||
|
||||
static get _cacheLength() {
|
||||
const cacheLengths = {
|
||||
build: 30,
|
||||
license: 3600,
|
||||
version: 300,
|
||||
debug: 60,
|
||||
}
|
||||
return cacheLengths[this.category]
|
||||
static render(props) {
|
||||
throw new Error(`render() function not implemented for ${this.name}`)
|
||||
}
|
||||
|
||||
constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
|
||||
this._requestFetcher = sendAndCacheRequest
|
||||
this._handleInternalErrors = handleInternalErrors
|
||||
}
|
||||
|
||||
async _request({ url, options = {}, errorMessages = {} }) {
|
||||
const logTrace = (...args) => trace.logTrace('fetch', ...args)
|
||||
logTrace(emojic.bowAndArrow, 'Request', url, '\n', options)
|
||||
const { res, buffer } = await this._requestFetcher(url, options)
|
||||
logTrace(emojic.dart, 'Response status code', res.statusCode)
|
||||
return checkErrorResponse.asPromise(errorMessages)({ buffer, res })
|
||||
}
|
||||
|
||||
static _validate(
|
||||
data,
|
||||
schema,
|
||||
{
|
||||
prettyErrorMessage = 'invalid response data',
|
||||
includeKeys = false,
|
||||
allowAndStripUnknownKeys = true,
|
||||
} = {}
|
||||
) {
|
||||
return validate(
|
||||
{
|
||||
ErrorClass: InvalidResponse,
|
||||
prettyErrorMessage,
|
||||
includeKeys,
|
||||
traceErrorMessage: 'Response did not match schema',
|
||||
traceSuccessMessage: 'Response after validation',
|
||||
allowAndStripUnknownKeys,
|
||||
},
|
||||
data,
|
||||
schema
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous function to handle requests for this service. Take the route
|
||||
* parameters (as defined in the `route` property), perform a request using
|
||||
* `this._sendAndCacheRequest`, and return the badge data.
|
||||
*/
|
||||
async handle(namedParams, queryParams) {
|
||||
throw new Error(`Handler not implemented for ${this.constructor.name}`)
|
||||
}
|
||||
|
||||
_handleError(error) {
|
||||
@@ -398,35 +427,4 @@ module.exports = class BaseService {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
static _validate(
|
||||
data,
|
||||
schema,
|
||||
{
|
||||
prettyErrorMessage = 'invalid response data',
|
||||
includeKeys = false,
|
||||
allowAndStripUnknownKeys = true,
|
||||
} = {}
|
||||
) {
|
||||
return validate(
|
||||
{
|
||||
ErrorClass: InvalidResponse,
|
||||
prettyErrorMessage,
|
||||
includeKeys,
|
||||
traceErrorMessage: 'Response did not match schema',
|
||||
traceSuccessMessage: 'Response after validation',
|
||||
allowAndStripUnknownKeys,
|
||||
},
|
||||
data,
|
||||
schema
|
||||
)
|
||||
}
|
||||
|
||||
async _request({ url, options = {}, errorMessages = {} }) {
|
||||
const logTrace = (...args) => trace.logTrace('fetch', ...args)
|
||||
logTrace(emojic.bowAndArrow, 'Request', url, '\n', options)
|
||||
const { res, buffer } = await this._requestFetcher(url, options)
|
||||
logTrace(emojic.dart, 'Response status code', res.statusCode)
|
||||
return checkErrorResponse.asPromise(errorMessages)({ buffer, res })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,22 +25,16 @@ const queryParamSchema = Joi.object({
|
||||
.required()
|
||||
|
||||
class DummyService extends BaseService {
|
||||
static render({ namedParamA, queryParamA }) {
|
||||
return {
|
||||
message: `Hello namedParamA: ${namedParamA} with queryParamA: ${queryParamA}`,
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ namedParamA }, { queryParamA }) {
|
||||
return this.constructor.render({ namedParamA, queryParamA })
|
||||
}
|
||||
|
||||
static get category() {
|
||||
return 'other'
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'cat', namedLogo: 'appveyor' }
|
||||
static get route() {
|
||||
return {
|
||||
base: 'foo',
|
||||
pattern: ':namedParamA',
|
||||
queryParamSchema,
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
@@ -54,13 +48,19 @@ class DummyService extends BaseService {
|
||||
]
|
||||
}
|
||||
|
||||
static get route() {
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'cat', namedLogo: 'appveyor' }
|
||||
}
|
||||
|
||||
static render({ namedParamA, queryParamA }) {
|
||||
return {
|
||||
base: 'foo',
|
||||
pattern: ':namedParamA',
|
||||
queryParamSchema,
|
||||
message: `Hello namedParamA: ${namedParamA} with queryParamA: ${queryParamA}`,
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ namedParamA }, { queryParamA }) {
|
||||
return this.constructor.render({ namedParamA, queryParamA })
|
||||
}
|
||||
}
|
||||
|
||||
describe('BaseService', function() {
|
||||
|
||||
@@ -38,22 +38,22 @@ function deprecatedService(attrs) {
|
||||
return category
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return route
|
||||
}
|
||||
|
||||
static get isDeprecated() {
|
||||
return true
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label }
|
||||
static get route() {
|
||||
return route
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return examples
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label }
|
||||
}
|
||||
|
||||
async handle() {
|
||||
throw new Deprecated({ prettyMessage: message })
|
||||
}
|
||||
|
||||
@@ -40,18 +40,6 @@ module.exports = function redirector(attrs) {
|
||||
} = Joi.attempt(attrs, attrSchema, `Redirector for ${attrs.route.base}`)
|
||||
|
||||
return class Redirector extends BaseService {
|
||||
static get category() {
|
||||
return category
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return route
|
||||
}
|
||||
|
||||
static get isDeprecated() {
|
||||
return true
|
||||
}
|
||||
|
||||
static get name() {
|
||||
if (name) {
|
||||
return name
|
||||
@@ -62,6 +50,18 @@ module.exports = function redirector(attrs) {
|
||||
}
|
||||
}
|
||||
|
||||
static get category() {
|
||||
return category
|
||||
}
|
||||
|
||||
static get isDeprecated() {
|
||||
return true
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return route
|
||||
}
|
||||
|
||||
static register({ camp, requestCounter }) {
|
||||
const { regex, captureNames } = prepareRoute(this.route)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user