Comparing version 0.1.8 to 0.1.9
@@ -78,3 +78,4 @@ import Service from './service.js' | ||
} catch (err) { | ||
goException(err, name, service, this) | ||
throw err | ||
// goException(err, name, service, this) | ||
} | ||
@@ -81,0 +82,0 @@ } |
{ | ||
"name": "apicase", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"description": "Create, group and manage your APIs with json declaration", | ||
@@ -5,0 +5,0 @@ "author": "kelin2025", |
361
service.js
@@ -9,4 +9,7 @@ import pick from 'lodash/pick' | ||
import isFunction from 'lodash/isFunction' | ||
import pathToRegexp from 'path-to-regexp' | ||
import isPlainObject from 'lodash/isPlainObject' | ||
import Result from './result' | ||
import * as Utils from './utils' | ||
@@ -19,117 +22,295 @@ | ||
this.container = container | ||
this.success = false | ||
this.pending = false | ||
this.query = null | ||
this.headers = null | ||
this.body = null | ||
this.response = null | ||
this.result = null | ||
this.calls = null | ||
this.config.mixins = config.mixins || {} | ||
this.config.hooks = config.hooks || {} | ||
this.config.children = mapValues(this.config.children || {}, child => new Service(child, container)) | ||
if (config.url) { | ||
Object.defineProperties(this, { | ||
status: { | ||
get () { | ||
return this.response.status | ||
}, | ||
configurable: false, | ||
enumerable: false | ||
} | ||
}) | ||
this.lastResult = null | ||
this.calls = 0 | ||
this.state = { | ||
normalized: false | ||
} | ||
this.normalizeConfig() | ||
} | ||
normalizeConfig () { | ||
if (this.state.normalized) return | ||
this.config.mixins = this.config.mixins || {} | ||
this.config.hooks = Utils.mergeHooksList( | ||
Utils.normalizeHooks(this.config.hooks || {}) | ||
) | ||
this.config.children = mapValues( | ||
this.config.children || {}, | ||
child => new Service(child, this.container) | ||
) | ||
this.state.normalized = true | ||
} | ||
addHook (name, hook) { | ||
this.hooks[name].push(normalizeHook(hook)) | ||
this.config.hooks = Utils.mergeHooksList( | ||
this.config.hooks, | ||
Utils.normalizeHooks({ [name]: hook }) | ||
) | ||
} | ||
addHooks (list) { | ||
this.hooks = Utils.mergeHooksList( | ||
this.hooks, | ||
list | ||
async go (data = {}, params = {}) { | ||
let hooks = this.prepareHooks(params.hooks) | ||
let mixins = this.prepareMixins(params.mixins) | ||
let result = new Result() | ||
result.setMixins(mixins) | ||
result.setQuery(data) | ||
let callback = this.prepareCallback(omit(params, ['hooks', 'mixins'])) | ||
let queue = [ | ||
...hooks.before.map(this.prepareBeforeHook), | ||
callback | ||
] | ||
try { | ||
await compose([ | ||
...queue, | ||
...hooks.success.map(this.prepareAfterHook), | ||
...hooks.finished.map(this.prepareAfterHook) | ||
])(result) | ||
} catch (err) { | ||
throw err | ||
await compose([ | ||
...hooks.error.map(this.prepareAfterHook), | ||
...hooks.finished.map(this.prepareAfterHook) | ||
])(result) | ||
} | ||
this.calls++ | ||
return result | ||
} | ||
prepareHooks (hooks = {}) { | ||
return Utils.mergeHooksList( | ||
this.container.hooks, | ||
this.config.hooks, | ||
Utils.normalizeHooks(hooks) | ||
) | ||
} | ||
async go (data, params = {}) { | ||
prepareMixins (mixins = {}) { | ||
return assign( | ||
this.container.mixins, | ||
this.config.mixins, | ||
mixins | ||
) | ||
} | ||
let clone = assign({}, this) | ||
prepareUrl (data = {}) { | ||
let url = `${this.container.base}${this.config.url}` | ||
return pathToRegexp.compile( | ||
this.config.method === 'GET' | ||
? url + Utils.jsonToQueryString(data) | ||
: url | ||
) | ||
} | ||
clone.hooks = Utils.normalizeHooks(Utils.mergeHooksList( | ||
clone.container.hooks, | ||
clone.config.hooks, | ||
params.hooks || {} | ||
)) | ||
clone.config.mixins = mapValues(assign( | ||
clone.container.mixins, | ||
clone.config.mixins, | ||
params.mixins || {} | ||
), Utils.normalizeMixin) | ||
prepareOptions (data, headers) { | ||
return { | ||
method: this.config.method || 'GET', | ||
headers: this.prepareHeaders(headers), | ||
body: this.prepareBody(data) | ||
} | ||
} | ||
let callback = async function callService (ctx, next) { | ||
prepareHeaders (headers = {}) { | ||
let normalizeHeaders = (headers) => | ||
!headers | ||
? null | ||
: isFunction(headers) | ||
? headers(this) | ||
: headers | ||
return assign( | ||
normalizeHeaders(this.container.headers), | ||
normalizeHeaders(this.config.headers), | ||
normalizeHeaders(headers) | ||
) | ||
} | ||
prepareBody (data = {}) { | ||
return this.config.method === 'GET' | ||
? undefined | ||
: data instanceof FormData | ||
? data | ||
: JSON.stringify(data) | ||
} | ||
prepareCallback (params) { | ||
let self = this | ||
return async function callService (ctx, next) { | ||
ctx.pending = true | ||
try { | ||
ctx.success = false | ||
ctx.pending = true | ||
ctx.query = params.data || {} | ||
if (ctx.config.callback) { | ||
ctx.response = await ctx.config.callback(ctx.query) | ||
ctx.result = ctx.response | ||
if (self.config.callback) { | ||
ctx.setResult(await self.config.callback(data, ctx)) | ||
} else { | ||
let url = Utils.getUrl(ctx, ctx.query)(params.params || {}) | ||
let options = { | ||
method: ctx.config.method || 'GET', | ||
headers: Utils.getHeaders(ctx, params.headers || {}), | ||
body: Utils.getBody(ctx, ctx.query) | ||
let url = self.prepareUrl(ctx.query)(params.params || {}) | ||
let options = self.prepareOptions(ctx.query, params.headers) | ||
ctx.setHeaders(options.headers) | ||
let res = await fetch(url, options) | ||
ctx.setResult( | ||
res, | ||
res.ok ? await res.json() : null | ||
) | ||
if (!res.ok) { | ||
throw new Error(`Failed to fetch ${url}`) | ||
} | ||
ctx.headers = options.headers | ||
ctx.response = await fetch(url, options) | ||
if (ctx.response.ok) { | ||
ctx.result = await ctx.response.json() | ||
} else { | ||
throw new Error('Failed to fetch') | ||
} | ||
} | ||
ctx.success = true | ||
forEach(ctx.config.mixins, (mixin, name) => { | ||
Object.defineProperty(ctx, name, assign( | ||
{ | ||
enumerable: true, | ||
configurable: false | ||
}, | ||
mapValues(pick(mixin, ['get', 'set']), mixin => mixin.bind(ctx)) | ||
)) | ||
}) | ||
next() | ||
ctx.ok = true | ||
} catch (err) { | ||
Utils.goException(err.message, null, ctx, ctx.container) | ||
ctx.success = false | ||
throw new Error(err.message) | ||
ctx.ok = false | ||
throw err | ||
} | ||
ctx.pending = false | ||
ctx.calls++ | ||
next() | ||
} | ||
} | ||
let queue = [ | ||
...clone.hooks.before.map(Utils.wrapBeforeHook), | ||
callback, | ||
...clone.hooks.success.map(Utils.wrapAfterHook), | ||
...clone.hooks.finished.map(Utils.wrapAfterHook) | ||
] | ||
return new Promise(async resolve => { | ||
try { | ||
await compose(queue)(clone) | ||
resolve(omit(clone, ['config', 'container'])) | ||
} catch (e) { | ||
compose([ | ||
...clone.hooks.error.map(Utils.wrapAfterHook), | ||
...clone.hooks.finished.map(Utils.wrapAfterHook) | ||
])(clone) | ||
resolve(omit(clone, ['config', 'container'])) | ||
prepareBeforeHook (hook) { | ||
return (ctx, next) => hook.handler( | ||
ctx, | ||
data => { | ||
if (data === false) return | ||
ctx.setQuery(data) | ||
next() | ||
} | ||
}) | ||
) | ||
} | ||
prepareAfterHook (hook) { | ||
return async (ctx, next) => { | ||
await hook.handler(ctx) | ||
next() | ||
} | ||
} | ||
} | ||
// | ||
// export default class Service { | ||
// | ||
// constructor (config, container) { | ||
// this.config = config | ||
// this.container = container | ||
// this.ok = false | ||
// this.pending = false | ||
// this.query = null | ||
// this.headers = null | ||
// this.body = null | ||
// this.response = null | ||
// this.result = null | ||
// this.calls = null | ||
// this.config.mixins = config.mixins || {} | ||
// this.config.hooks = config.hooks || {} | ||
// this.config.children = mapValues(this.config.children || {}, child => new Service(child, container)) | ||
// if (config.url) { | ||
// Object.defineProperties(this, { | ||
// status: { | ||
// get () { | ||
// return this.response.status | ||
// }, | ||
// configurable: false, | ||
// enumerable: false | ||
// } | ||
// }) | ||
// } | ||
// } | ||
// | ||
// addHook (name, hook) { | ||
// this.hooks[name].push(normalizeHook(hook)) | ||
// } | ||
// | ||
// addHooks (list) { | ||
// this.hooks = Utils.mergeHooksList( | ||
// this.hooks, | ||
// list | ||
// ) | ||
// } | ||
// | ||
// async go (data, params = {}) { | ||
// | ||
// let clone = assign({}, this) | ||
// | ||
// clone.config.hooks = Utils.normalizeHooks(Utils.mergeHooksList( | ||
// clone.container.hooks, | ||
// clone.config.hooks, | ||
// params.hooks || {} | ||
// )) | ||
// | ||
// clone.config.mixins = mapValues(assign( | ||
// clone.container.mixins, | ||
// clone.config.mixins, | ||
// params.mixins || {} | ||
// ), Utils.normalizeMixin) | ||
// | ||
// clone.query = data || {} | ||
// | ||
// forEach(clone.config.mixins, (mixin, name) => { | ||
// Object.defineProperty(clone, name, assign( | ||
// { | ||
// enumerable: true, | ||
// configurable: false | ||
// }, | ||
// mapValues(pick(mixin, ['get', 'set']), mixin => mixin.bind(clone)) | ||
// )) | ||
// }) | ||
// | ||
// let callback = async function callService (ctx, next) { | ||
// try { | ||
// ctx.pending = true | ||
// if (ctx.config.callback) { | ||
// // Call service from callback | ||
// ctx.response = await ctx.config.callback(ctx.query) | ||
// ctx.result = ctx.response | ||
// } else { | ||
// // Call service by url with fetch | ||
// // Compile url with path-to-regexp | ||
// let url = Utils.getUrl(ctx, ctx.query)(params.params || {}) | ||
// // Build options list | ||
// let options = { | ||
// method: ctx.config.method || 'GET', | ||
// headers: Utils.getHeaders(ctx, params.headers || {}), | ||
// body: Utils.getBody(ctx, ctx.query) | ||
// } | ||
// ctx.headers = options.headers | ||
// ctx.response = await fetch(url, options) | ||
// if (ctx.response.ok) { | ||
// ctx.result = await ctx.response.json() | ||
// } else { | ||
// throw new Error('Failed to fetch') | ||
// } | ||
// } | ||
// ctx.ok = true | ||
// next() | ||
// } catch (err) { | ||
// ctx.ok = false | ||
// Utils.goException(err.message, null, ctx, ctx.container) | ||
// throw new Error(err.message) | ||
// } | ||
// ctx.pending = false | ||
// ctx.calls++ | ||
// } | ||
// | ||
// let queue = [ | ||
// ...clone.config.hooks.before.map(Utils.wrapBeforeHook), | ||
// callback, | ||
// ...clone.config.hooks.success.map(Utils.wrapAfterHook), | ||
// ...clone.config.hooks.finished.map(Utils.wrapAfterHook) | ||
// ] | ||
// | ||
// return new Promise(async resolve => { | ||
// try { | ||
// await compose(queue)(clone) | ||
// resolve(omit(clone, ['config', 'container'])) | ||
// } catch (e) { | ||
// compose([ | ||
// ...clone.config.hooks.error.map(Utils.wrapAfterHook), | ||
// ...clone.config.hooks.finished.map(Utils.wrapAfterHook) | ||
// ])(clone) | ||
// resolve(omit(clone, ['config', 'container'])) | ||
// } | ||
// }) | ||
// | ||
// } | ||
// | ||
// } |
@@ -16,3 +16,5 @@ import has from 'lodash/has' | ||
return { | ||
get: mixin | ||
get: mixin, | ||
enumerable: true, | ||
configurable: false | ||
} | ||
@@ -23,3 +25,6 @@ } | ||
} | ||
return pick(mixin, ['get', 'set']) | ||
return assign({ | ||
enumerable: true, | ||
configurable: false | ||
}, pick(mixin, ['get', 'set'])) | ||
} | ||
@@ -26,0 +31,0 @@ |
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
15835
8
537