-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
317 additions
and
6 deletions.
There are no files selected for viewing
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
196 changes: 196 additions & 0 deletions
196
x-pack/legacy/plugins/monitoring/public/np_imports/angular/providers/private.js
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,196 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/** | ||
* # `Private()` | ||
* Private module loader, used to merge angular and require js dependency styles | ||
* by allowing a require.js module to export a single provider function that will | ||
* create a value used within an angular application. This provider can declare | ||
* angular dependencies by listing them as arguments, and can be require additional | ||
* Private modules. | ||
* | ||
* ## Define a private module provider: | ||
* ```js | ||
* export default function PingProvider($http) { | ||
* this.ping = function () { | ||
* return $http.head('/health-check'); | ||
* }; | ||
* }; | ||
* ``` | ||
* | ||
* ## Require a private module: | ||
* ```js | ||
* export default function ServerHealthProvider(Private, Promise) { | ||
* let ping = Private(require('ui/ping')); | ||
* return { | ||
* check: Promise.method(function () { | ||
* let attempts = 0; | ||
* return (function attempt() { | ||
* attempts += 1; | ||
* return ping.ping() | ||
* .catch(function (err) { | ||
* if (attempts < 3) return attempt(); | ||
* }) | ||
* }()) | ||
* .then(function () { | ||
* return true; | ||
* }) | ||
* .catch(function () { | ||
* return false; | ||
* }); | ||
* }) | ||
* } | ||
* }; | ||
* ``` | ||
* | ||
* # `Private.stub(provider, newInstance)` | ||
* `Private.stub()` replaces the instance of a module with another value. This is all we have needed until now. | ||
* | ||
* ```js | ||
* beforeEach(inject(function ($injector, Private) { | ||
* Private.stub( | ||
* // since this module just exports a function, we need to change | ||
* // what Private returns in order to modify it's behavior | ||
* require('ui/agg_response/hierarchical/_build_split'), | ||
* sinon.stub().returns(fakeSplit) | ||
* ); | ||
* })); | ||
* ``` | ||
* | ||
* # `Private.swap(oldProvider, newProvider)` | ||
* This new method does an 1-for-1 swap of module providers, unlike `stub()` which replaces a modules instance. | ||
* Pass the module you want to swap out, and the one it should be replaced with, then profit. | ||
* | ||
* Note: even though this example shows `swap()` being called in a config | ||
* function, it can be called from anywhere. It is particularly useful | ||
* in this scenario though. | ||
* | ||
* ```js | ||
* beforeEach(module('kibana', function (PrivateProvider) { | ||
* PrivateProvider.swap( | ||
* function StubbedRedirectProvider($decorate) { | ||
* // $decorate is a function that will instantiate the original module when called | ||
* return sinon.spy($decorate()); | ||
* } | ||
* ); | ||
* })); | ||
* ``` | ||
* | ||
* @param {[type]} prov [description] | ||
*/ | ||
import _ from 'lodash'; | ||
|
||
const nextId = _.partial(_.uniqueId, 'privateProvider#'); | ||
|
||
function name(fn) { | ||
return ( | ||
fn.name || | ||
fn | ||
.toString() | ||
.split('\n') | ||
.shift() | ||
); | ||
} | ||
|
||
export function PrivateProvider() { | ||
const provider = this; | ||
|
||
// one cache/swaps per Provider | ||
const cache = {}; | ||
const swaps = {}; | ||
|
||
// return the uniq id for this function | ||
function identify(fn) { | ||
if (typeof fn !== 'function') { | ||
throw new TypeError('Expected private module "' + fn + '" to be a function'); | ||
} | ||
|
||
if (fn.$$id) return fn.$$id; | ||
else return (fn.$$id = nextId()); | ||
} | ||
|
||
provider.stub = function(fn, instance) { | ||
cache[identify(fn)] = instance; | ||
return instance; | ||
}; | ||
|
||
provider.swap = function(fn, prov) { | ||
const id = identify(fn); | ||
swaps[id] = prov; | ||
}; | ||
|
||
provider.$get = [ | ||
'$injector', | ||
function PrivateFactory($injector) { | ||
// prevent circular deps by tracking where we came from | ||
const privPath = []; | ||
const pathToString = function() { | ||
return privPath.map(name).join(' -> '); | ||
}; | ||
|
||
// call a private provider and return the instance it creates | ||
function instantiate(prov, locals) { | ||
if (~privPath.indexOf(prov)) { | ||
throw new Error( | ||
'Circular reference to "' + | ||
name(prov) + | ||
'"' + | ||
' found while resolving private deps: ' + | ||
pathToString() | ||
); | ||
} | ||
|
||
privPath.push(prov); | ||
|
||
const context = {}; | ||
let instance = $injector.invoke(prov, context, locals); | ||
if (!_.isObject(instance)) instance = context; | ||
|
||
privPath.pop(); | ||
return instance; | ||
} | ||
|
||
// retrieve an instance from cache or create and store on | ||
function get(id, prov, $delegateId, $delegateProv) { | ||
if (cache[id]) return cache[id]; | ||
|
||
let instance; | ||
|
||
if ($delegateId != null && $delegateProv != null) { | ||
instance = instantiate(prov, { | ||
$decorate: _.partial(get, $delegateId, $delegateProv), | ||
}); | ||
} else { | ||
instance = instantiate(prov); | ||
} | ||
|
||
return (cache[id] = instance); | ||
} | ||
|
||
// main api, get the appropriate instance for a provider | ||
function Private(prov) { | ||
let id = identify(prov); | ||
let $delegateId; | ||
let $delegateProv; | ||
|
||
if (swaps[id]) { | ||
$delegateId = id; | ||
$delegateProv = prov; | ||
|
||
prov = swaps[$delegateId]; | ||
id = identify(prov); | ||
} | ||
|
||
return get(id, prov, $delegateId, $delegateProv); | ||
} | ||
|
||
Private.stub = provider.stub; | ||
Private.swap = provider.swap; | ||
|
||
return Private; | ||
}, | ||
]; | ||
} |
116 changes: 116 additions & 0 deletions
116
x-pack/legacy/plugins/monitoring/public/np_imports/angular/providers/promises.js
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,116 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import _ from 'lodash'; | ||
|
||
export function PromiseServiceCreator($q, $timeout) { | ||
function Promise(fn) { | ||
if (typeof this === 'undefined') | ||
throw new Error('Promise constructor must be called with "new"'); | ||
|
||
const defer = $q.defer(); | ||
try { | ||
fn(defer.resolve, defer.reject); | ||
} catch (e) { | ||
defer.reject(e); | ||
} | ||
return defer.promise; | ||
} | ||
|
||
Promise.all = Promise.props = $q.all; | ||
Promise.resolve = function(val) { | ||
const defer = $q.defer(); | ||
defer.resolve(val); | ||
return defer.promise; | ||
}; | ||
Promise.reject = function(reason) { | ||
const defer = $q.defer(); | ||
defer.reject(reason); | ||
return defer.promise; | ||
}; | ||
Promise.cast = $q.when; | ||
Promise.delay = function(ms) { | ||
return $timeout(_.noop, ms); | ||
}; | ||
Promise.method = function(fn) { | ||
return function() { | ||
const args = Array.prototype.slice.call(arguments); | ||
return Promise.try(fn, args, this); | ||
}; | ||
}; | ||
Promise.nodeify = function(promise, cb) { | ||
promise.then(function(val) { | ||
cb(void 0, val); | ||
}, cb); | ||
}; | ||
Promise.map = function(arr, fn) { | ||
return Promise.all( | ||
arr.map(function(i, el, list) { | ||
return Promise.try(fn, [i, el, list]); | ||
}) | ||
); | ||
}; | ||
Promise.each = function(arr, fn) { | ||
const queue = arr.slice(0); | ||
let i = 0; | ||
return (function next() { | ||
if (!queue.length) return arr; | ||
return Promise.try(fn, [arr.shift(), i++]).then(next); | ||
})(); | ||
}; | ||
Promise.is = function(obj) { | ||
// $q doesn't create instances of any constructor, promises are just objects with a then function | ||
// https://github.com/angular/angular.js/blob/58f5da86645990ef984353418cd1ed83213b111e/src/ng/q.js#L335 | ||
return obj && typeof obj.then === 'function'; | ||
}; | ||
Promise.halt = _.once(function() { | ||
const promise = new Promise(() => {}); | ||
promise.then = _.constant(promise); | ||
promise.catch = _.constant(promise); | ||
return promise; | ||
}); | ||
Promise.try = function(fn, args, ctx) { | ||
if (typeof fn !== 'function') { | ||
return Promise.reject(new TypeError('fn must be a function')); | ||
} | ||
|
||
let value; | ||
|
||
if (Array.isArray(args)) { | ||
try { | ||
value = fn.apply(ctx, args); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} else { | ||
try { | ||
value = fn.call(ctx, args); | ||
} catch (e) { | ||
return Promise.reject(e); | ||
} | ||
} | ||
|
||
return Promise.resolve(value); | ||
}; | ||
Promise.fromNode = function(takesCbFn) { | ||
return new Promise(function(resolve, reject) { | ||
takesCbFn(function(err, ...results) { | ||
if (err) reject(err); | ||
else if (results.length > 1) resolve(results); | ||
else resolve(results[0]); | ||
}); | ||
}); | ||
}; | ||
Promise.race = function(iterable) { | ||
return new Promise((resolve, reject) => { | ||
for (const i of iterable) { | ||
Promise.resolve(i).then(resolve, reject); | ||
} | ||
}); | ||
}; | ||
|
||
return Promise; | ||
} |
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