Skip to content

Commit

Permalink
Split BaseService and BaseJsonService into separate modules (#1889)
Browse files Browse the repository at this point in the history
There’s a lot of behavior here, and going to be even more, so I think it makes sense to split these up as I’ve done with the tests.
  • Loading branch information
paulmelnikow authored Aug 11, 2018
1 parent ed81dcb commit db4bffb
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 71 deletions.
2 changes: 1 addition & 1 deletion services/apm/apm.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { InvalidResponse } = require('../errors')
const { version: versionColor } = require('../../lib/color-formatters')
const { metric, addv } = require('../../lib/text-formatters')
Expand Down
2 changes: 1 addition & 1 deletion services/appveyor/appveyor.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')

const appVeyorSchema = Joi.object({
build: Joi.object({
Expand Down
62 changes: 62 additions & 0 deletions services/base-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict'

// See available emoji at http://emoji.muan.co/
const emojic = require('emojic')
const Joi = require('joi')
const { checkErrorResponse, asJson } = require('../lib/error-helper')
const BaseService = require('./base')
const { InvalidResponse } = require('./errors')

class BaseJsonService extends BaseService {
static _validate(json, schema) {
const { error, value } = Joi.validate(json, schema, {
allowUnknown: true,
stripUnknown: true,
})
if (error) {
this.logTrace(
'error',
emojic.womanShrugging,
'Response did not match schema',
error.message
)
throw new InvalidResponse({
prettyMessage: 'invalid json response',
underlyingError: error,
})
} else {
this.logTrace('validate', emojic.bathtub, 'JSON after validation', value)
return value
}
}

async _requestJson({ schema, url, options = {}, notFoundMessage }) {
const logTrace = (...args) => this.constructor.logTrace('fetch', ...args)
if (!schema || !schema.isJoi) {
throw Error('A Joi schema is required')
}
const mergedOptions = {
...{ headers: { Accept: 'application/json' } },
...options,
}
logTrace(emojic.bowAndArrow, 'Request', url, '\n', mergedOptions)
return this._sendAndCacheRequest(url, mergedOptions)
.then(({ res, buffer }) => {
logTrace(emojic.dart, 'Response status code', res.statusCode)
return { res, buffer }
})
.then(
checkErrorResponse.asPromise(
notFoundMessage ? { notFoundMessage: notFoundMessage } : undefined
)
)
.then(asJson)
.then(json => {
logTrace(emojic.dart, 'Response JSON (before validation)', json)
return json
})
.then(json => this.constructor._validate(json, schema))
}
}

module.exports = BaseJsonService
2 changes: 1 addition & 1 deletion services/base-json.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const Joi = require('joi')
const chai = require('chai')
const { expect } = chai

const { BaseJsonService } = require('./base')
const BaseJsonService = require('./base-json')
const { invalidJSON } = require('./response-fixtures')

chai.use(require('chai-as-promised'))
Expand Down
59 changes: 1 addition & 58 deletions services/base.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const Joi = require('joi')
// See available emoji at http://emoji.muan.co/
const emojic = require('emojic')
const chalk = require('chalk')
Expand All @@ -12,7 +11,6 @@ const {
makeColor,
setBadgeColor,
} = require('../lib/badge-data')
const { checkErrorResponse, asJson } = require('../lib/error-helper')
// Config is loaded globally but it would be better to inject it. To do that,
// there needs to be one instance of the service created at registration time,
// which gets the config injected into it, instead of one instance per request.
Expand Down Expand Up @@ -308,59 +306,4 @@ class BaseService {
}
}

class BaseJsonService extends BaseService {
static _validate(json, schema) {
const { error, value } = Joi.validate(json, schema, {
allowUnknown: true,
stripUnknown: true,
})
if (error) {
this.logTrace(
'error',
emojic.womanShrugging,
'Response did not match schema',
error.message
)
throw new InvalidResponse({
prettyMessage: 'invalid json response',
underlyingError: error,
})
} else {
this.logTrace('validate', emojic.bathtub, 'JSON after validation', value)
return value
}
}

async _requestJson({ schema, url, options = {}, notFoundMessage }) {
const logTrace = (...args) => this.constructor.logTrace('fetch', ...args)
if (!schema || !schema.isJoi) {
throw Error('A Joi schema is required')
}
const mergedOptions = {
...{ headers: { Accept: 'application/json' } },
...options,
}
logTrace(emojic.bowAndArrow, 'Request', url, '\n', mergedOptions)
return this._sendAndCacheRequest(url, mergedOptions)
.then(({ res, buffer }) => {
logTrace(emojic.dart, 'Response status code', res.statusCode)
return { res, buffer }
})
.then(
checkErrorResponse.asPromise(
notFoundMessage ? { notFoundMessage: notFoundMessage } : undefined
)
)
.then(asJson)
.then(json => {
logTrace(emojic.dart, 'Response JSON (before validation)', json)
return json
})
.then(json => this.constructor._validate(json, schema))
}
}

module.exports = {
BaseService,
BaseJsonService,
}
module.exports = BaseService
2 changes: 1 addition & 1 deletion services/base.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { expect } = require('chai')
const { test, given, forCases } = require('sazerac')
const sinon = require('sinon')

const { BaseService } = require('./base')
const BaseService = require('./base')

require('../lib/register-chai-plugins.spec')

Expand Down
2 changes: 1 addition & 1 deletion services/cdnjs/cdnjs.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { NotFound } = require('../errors')
const { addv: versionText } = require('../../lib/text-formatters')
const { version: versionColor } = require('../../lib/color-formatters')
Expand Down
2 changes: 1 addition & 1 deletion services/clojars/clojars.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { NotFound } = require('../errors')
const { version: versionColor } = require('../../lib/color-formatters')

Expand Down
2 changes: 1 addition & 1 deletion services/gem/gem-downloads.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const semver = require('semver')
const Joi = require('joi')

const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { InvalidResponse } = require('../errors')
const {
downloadCount: downloadCountColor,
Expand Down
2 changes: 1 addition & 1 deletion services/gem/gem-owner.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const Joi = require('joi')

const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { floorCount: floorCountColor } = require('../../lib/color-formatters')

const ownerSchema = Joi.array().required()
Expand Down
2 changes: 1 addition & 1 deletion services/gem/gem-rank.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const Joi = require('joi')

const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { floorCount: floorCountColor } = require('../../lib/color-formatters')
const { ordinalNumber } = require('../../lib/text-formatters')
const { nonNegativeInteger } = require('../validators.js')
Expand Down
2 changes: 1 addition & 1 deletion services/gem/gem-version.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const Joi = require('joi')

const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { addv: versionText } = require('../../lib/text-formatters')
const { version: versionColor } = require('../../lib/color-formatters')

Expand Down
2 changes: 1 addition & 1 deletion services/npm/npm-base.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { InvalidResponse, NotFound } = require('../errors')

const deprecatedLicenseObjectSchema = Joi.object({
Expand Down
2 changes: 1 addition & 1 deletion services/npm/npm-downloads.service.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const Joi = require('joi')
const { BaseJsonService } = require('../base')
const BaseJsonService = require('../base-json')
const { metric } = require('../../lib/text-formatters')
const { nonNegativeInteger } = require('../validators.js')

Expand Down
2 changes: 1 addition & 1 deletion services/time/time.service.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { BaseService } = require('../base')
const BaseService = require('../base')

module.exports = class Time extends BaseService {
async handle() {
Expand Down

0 comments on commit db4bffb

Please sign in to comment.