Merge pull request #2559 from strongloop/deprecate/getCurrentContext
Deprecate current-context API
This commit is contained in:
commit
bb1af5a691
|
@ -44,9 +44,6 @@ module.exports = function(grunt) {
|
|||
common: {
|
||||
src: ['common/**/*.js']
|
||||
},
|
||||
browser: {
|
||||
src: ['browser/**/*.js']
|
||||
},
|
||||
server: {
|
||||
src: ['server/**/*.js']
|
||||
},
|
||||
|
@ -59,7 +56,6 @@ module.exports = function(grunt) {
|
|||
lib: ['lib/**/*.js'],
|
||||
common: ['common/**/*.js'],
|
||||
server: ['server/**/*.js'],
|
||||
browser: ['browser/**/*.js'],
|
||||
test: ['test/**/*.js']
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright IBM Corp. 2015,2016. All Rights Reserved.
|
||||
// Node module: loopback
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
module.exports = function(loopback) {
|
||||
loopback.getCurrentContext = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
loopback.runInContext =
|
||||
loopback.createContext = function() {
|
||||
throw new Error(g.f('Current context is not supported in the browser.'));
|
||||
};
|
||||
};
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright IBM Corp. 2015,2016. All Rights Reserved.
|
||||
// Node module: loopback
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var juggler = require('loopback-datasource-juggler');
|
||||
var remoting = require('strong-remoting');
|
||||
var LoopBackContext = require('loopback-context');
|
||||
var deprecated = require('depd')('loopback');
|
||||
var g = require('strong-globalize')();
|
||||
|
||||
module.exports = function(loopback) {
|
||||
|
||||
/**
|
||||
* Get the current context object. The context is preserved
|
||||
* across async calls, it behaves like a thread-local storage.
|
||||
*
|
||||
* @returns {ChainedContext} The context object or null.
|
||||
*/
|
||||
loopback.getCurrentContext = function() {
|
||||
// NOTE(bajtos) LoopBackContext.getCurrentContext is overriden whenever
|
||||
// the context changes, therefore we cannot simply assign
|
||||
// LoopBackContext.getCurrentContext() to loopback.getCurrentContext()
|
||||
deprecated(g.f('%s is deprecated. See %s for more details.',
|
||||
'loopback.getCurrentContext()',
|
||||
'https://docs.strongloop.com/display/APIC/Using%20current%20context'));
|
||||
return LoopBackContext.getCurrentContext();
|
||||
};
|
||||
|
||||
juggler.getCurrentContext =
|
||||
remoting.getCurrentContext = loopback.getCurrentContext;
|
||||
|
||||
/**
|
||||
* Run the given function in such way that
|
||||
* `loopback.getCurrentContext` returns the
|
||||
* provided context object.
|
||||
*
|
||||
* **NOTE**
|
||||
*
|
||||
* The method is supported on the server only, it does not work
|
||||
* in the browser at the moment.
|
||||
*
|
||||
* @param {Function} fn The function to run, it will receive arguments
|
||||
* (currentContext, currentDomain).
|
||||
* @param {ChainedContext} context An optional context object.
|
||||
* When no value is provided, then the default global context is used.
|
||||
*/
|
||||
loopback.runInContext = function(fn, ctx) {
|
||||
deprecated(g.f('%s is deprecated. See %s for more details.',
|
||||
'loopback.runInContext()',
|
||||
'https://docs.strongloop.com/display/APIC/Using%20current%20context'));
|
||||
return LoopBackContext.runInContext(fn, ctx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new LoopBackContext instance that can be used
|
||||
* for `loopback.runInContext`.
|
||||
*
|
||||
* **NOTES**
|
||||
*
|
||||
* At the moment, `loopback.getCurrentContext` supports
|
||||
* a single global context instance only. If you call `createContext()`
|
||||
* multiple times, `getCurrentContext` will return the last context
|
||||
* created.
|
||||
*
|
||||
* The method is supported on the server only, it does not work
|
||||
* in the browser at the moment.
|
||||
*
|
||||
* @param {String} scopeName An optional scope name.
|
||||
* @return {ChainedContext} The new context object.
|
||||
*/
|
||||
loopback.createContext = function(scopeName) {
|
||||
deprecated(g.f('%s is deprecated. See %s for more details.',
|
||||
'loopback.createContext()',
|
||||
'https://docs.strongloop.com/display/APIC/Using%20current%20context'));
|
||||
return LoopBackContext.createContext(scopeName);
|
||||
};
|
||||
};
|
|
@ -222,7 +222,7 @@ loopback.template = function(file) {
|
|||
});
|
||||
};
|
||||
|
||||
require('../server/current-context')(loopback);
|
||||
require('../lib/current-context')(loopback);
|
||||
|
||||
/**
|
||||
* Create a named vanilla JavaScript class constructor with an attached
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
"bcryptjs": "^2.1.0",
|
||||
"body-parser": "^1.12.0",
|
||||
"canonical-json": "0.0.4",
|
||||
"continuation-local-storage": "^3.1.3",
|
||||
"cookie-parser": "^1.3.4",
|
||||
"debug": "^2.1.2",
|
||||
"depd": "^1.0.0",
|
||||
|
@ -45,6 +44,7 @@
|
|||
"express": "^4.12.2",
|
||||
"inflection": "^1.6.0",
|
||||
"loopback-connector-remote": "^1.0.3",
|
||||
"loopback-context": "^1.0.0",
|
||||
"loopback-phase": "^1.2.0",
|
||||
"nodemailer": "^2.5.0",
|
||||
"nodemailer-stub-transport": "^1.0.0",
|
||||
|
@ -100,7 +100,6 @@
|
|||
"browser": {
|
||||
"express": "./lib/browser-express.js",
|
||||
"./lib/server-app.js": "./lib/browser-express.js",
|
||||
"./server/current-context.js": "./browser/current-context.js",
|
||||
"connect": false,
|
||||
"nodemailer": false,
|
||||
"supertest": false,
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright IBM Corp. 2015,2016. All Rights Reserved.
|
||||
// Node module: loopback
|
||||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var juggler = require('loopback-datasource-juggler');
|
||||
var remoting = require('strong-remoting');
|
||||
var cls = require('continuation-local-storage');
|
||||
var domain = require('domain');
|
||||
|
||||
module.exports = function(loopback) {
|
||||
|
||||
/**
|
||||
* Get the current context object. The context is preserved
|
||||
* across async calls, it behaves like a thread-local storage.
|
||||
*
|
||||
* @returns {ChainedContext} The context object or null.
|
||||
*/
|
||||
loopback.getCurrentContext = function() {
|
||||
// A placeholder method, see loopback.createContext() for the real version
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the given function in such way that
|
||||
* `loopback.getCurrentContext` returns the
|
||||
* provided context object.
|
||||
*
|
||||
* **NOTE**
|
||||
*
|
||||
* The method is supported on the server only, it does not work
|
||||
* in the browser at the moment.
|
||||
*
|
||||
* @param {Function} fn The function to run, it will receive arguments
|
||||
* (currentContext, currentDomain).
|
||||
* @param {ChainedContext} context An optional context object.
|
||||
* When no value is provided, then the default global context is used.
|
||||
*/
|
||||
loopback.runInContext = function(fn, context) {
|
||||
var currentDomain = domain.create();
|
||||
currentDomain.oldBind = currentDomain.bind;
|
||||
currentDomain.bind = function(callback, context) {
|
||||
return currentDomain.oldBind(ns.bind(callback, context), context);
|
||||
};
|
||||
|
||||
var ns = context || loopback.createContext('loopback');
|
||||
|
||||
currentDomain.run(function() {
|
||||
ns.run(function executeInContext(context) {
|
||||
fn(ns, currentDomain);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new LoopBackContext instance that can be used
|
||||
* for `loopback.runInContext`.
|
||||
*
|
||||
* **NOTES**
|
||||
*
|
||||
* At the moment, `loopback.getCurrentContext` supports
|
||||
* a single global context instance only. If you call `createContext()`
|
||||
* multiple times, `getCurrentContext` will return the last context
|
||||
* created.
|
||||
*
|
||||
* The method is supported on the server only, it does not work
|
||||
* in the browser at the moment.
|
||||
*
|
||||
* @param {String} scopeName An optional scope name.
|
||||
* @return {ChainedContext} The new context object.
|
||||
*/
|
||||
loopback.createContext = function(scopeName) {
|
||||
// Make the namespace globally visible via the process.context property
|
||||
process.context = process.context || {};
|
||||
var ns = process.context[scopeName];
|
||||
if (!ns) {
|
||||
ns = cls.createNamespace(scopeName);
|
||||
process.context[scopeName] = ns;
|
||||
// Set up loopback.getCurrentContext()
|
||||
loopback.getCurrentContext = function() {
|
||||
return ns && ns.active ? ns : null;
|
||||
};
|
||||
|
||||
chain(juggler);
|
||||
chain(remoting);
|
||||
}
|
||||
return ns;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a chained context
|
||||
* @param {Object} child The child context
|
||||
* @param {Object} parent The parent context
|
||||
* @private
|
||||
* @constructor
|
||||
*/
|
||||
function ChainedContext(child, parent) {
|
||||
this.child = child;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value by name from the context. If it doesn't exist in the child
|
||||
* context, try the parent one
|
||||
* @param {String} name Name of the context property
|
||||
* @returns {*} Value of the context property
|
||||
* @private
|
||||
*/
|
||||
ChainedContext.prototype.get = function(name) {
|
||||
var val = this.child && this.child.get(name);
|
||||
if (val === undefined) {
|
||||
return this.parent && this.parent.get(name);
|
||||
}
|
||||
};
|
||||
|
||||
ChainedContext.prototype.set = function(name, val) {
|
||||
if (this.child) {
|
||||
return this.child.set(name, val);
|
||||
} else {
|
||||
return this.parent && this.parent.set(name, val);
|
||||
}
|
||||
};
|
||||
|
||||
ChainedContext.prototype.reset = function(name, val) {
|
||||
if (this.child) {
|
||||
return this.child.reset(name, val);
|
||||
} else {
|
||||
return this.parent && this.parent.reset(name, val);
|
||||
}
|
||||
};
|
||||
|
||||
function chain(child) {
|
||||
if (typeof child.getCurrentContext === 'function') {
|
||||
var childContext = new ChainedContext(child.getCurrentContext(),
|
||||
loopback.getCurrentContext());
|
||||
child.getCurrentContext = function() {
|
||||
return childContext;
|
||||
};
|
||||
} else {
|
||||
child.getCurrentContext = loopback.getCurrentContext;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -3,55 +3,13 @@
|
|||
// This file is licensed under the MIT License.
|
||||
// License text available at https://opensource.org/licenses/MIT
|
||||
|
||||
var loopback = require('../../lib/loopback');
|
||||
var deprecated = require('depd')('loopback');
|
||||
var g = require('strong-globalize')();
|
||||
var perRequestContext = require('loopback-context').perRequest;
|
||||
|
||||
module.exports = context;
|
||||
|
||||
var name = 'loopback';
|
||||
|
||||
/**
|
||||
* Context middleware.
|
||||
* ```js
|
||||
* var app = loopback();
|
||||
* app.use(loopback.context(options);
|
||||
* app.use(loopback.rest());
|
||||
* app.listen();
|
||||
* ```
|
||||
* @options {Object} [options] Options for context
|
||||
* @property {String} name Context scope name.
|
||||
* @property {Boolean} enableHttpContext Whether HTTP context is enabled. Default is false.
|
||||
* @header loopback.context([options])
|
||||
*/
|
||||
|
||||
function context(options) {
|
||||
options = options || {};
|
||||
var scope = options.name || name;
|
||||
var enableHttpContext = options.enableHttpContext || false;
|
||||
var ns = loopback.createContext(scope);
|
||||
|
||||
// Return the middleware
|
||||
return function contextHandler(req, res, next) {
|
||||
if (req.loopbackContext) {
|
||||
return next();
|
||||
}
|
||||
|
||||
loopback.runInContext(function processRequestInContext(ns, domain) {
|
||||
req.loopbackContext = ns;
|
||||
|
||||
// Bind req/res event emitters to the given namespace
|
||||
ns.bindEmitter(req);
|
||||
ns.bindEmitter(res);
|
||||
|
||||
// Add req/res event emitters to the current domain
|
||||
domain.add(req);
|
||||
domain.add(res);
|
||||
|
||||
// Run the code in the context of the namespace
|
||||
if (enableHttpContext) {
|
||||
// Set up the transport context
|
||||
ns.set('http', {req: req, res: res});
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
}
|
||||
module.exports = function() {
|
||||
deprecated(g.f('%s middleware is deprecated. See %s for more details.',
|
||||
'loopback#context',
|
||||
'https://docs.strongloop.com/display/APIC/Using%20current%20context'));
|
||||
return perRequestContext.apply(this, arguments);
|
||||
};
|
||||
|
|
|
@ -477,7 +477,8 @@ describe('app.enableAuth()', function() {
|
|||
it('stores token in the context', function(done) {
|
||||
var TestModel = loopback.createModel('TestModel', { base: 'Model' });
|
||||
TestModel.getToken = function(cb) {
|
||||
cb(null, loopback.getCurrentContext().get('accessToken') || null);
|
||||
var ctx = loopback.getCurrentContext();
|
||||
cb(null, ctx && ctx.get('accessToken') || null);
|
||||
};
|
||||
TestModel.remoteMethod('getToken', {
|
||||
returns: { arg: 'token', type: 'object' },
|
||||
|
|
Loading…
Reference in New Issue