-
Notifications
You must be signed in to change notification settings - Fork 29
/
index.js
100 lines (80 loc) · 3 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* Copyright (c) 2014, Yahoo Inc. All rights reserved.
* Copyrights licensed under the New BSD License.
* See the accompanying LICENSE file for terms.
*/
'use strict';
var Exposed = require('./lib/exposed');
exports.local = 'state';
exports.namespace = null;
exports.extend = extendApp;
function extendApp(app) {
if (app['@state']) { return app; }
// Brand.
Object.defineProperty(app, '@state', {value: exports});
// Modifies the Express `app` and its `response` prototype by adding the
// `expose()` method.
app.expose = expose;
app.response.expose = expose;
return app;
}
function expose(obj, namespace, options) {
/* jshint validthis:true */
var app = this.app || this,
appLocals = app.locals,
locals = this.locals,
rootNamespace = app.get('state namespace') || exports.namespace,
local, appExposed, exposed, type;
// Massage arguments to support the following signatures:
// expose( obj [[, namespace [, options]] | [, options]] )
// expose( obj [, namespace [, local]] )
if (namespace && typeof namespace === 'object') {
options = namespace;
namespace = options.namespace;
local = options.local;
} else if (options && typeof options === 'string') {
local = options;
options = null;
// Warn about deprecated API signature:
// expose( obj [, namespace [, local]] )
console.warn('(express-state) warning: ' +
'`expose( obj, namespace, local)` signature has been deprecated.');
} else {
local = options && options.local;
}
if (!local) {
local = app.get('state local') || exports.local;
}
appExposed = appLocals[local];
exposed = locals[local];
// Makes sure there's an `Exposed` instance, and that all request-scoped
// instances are *always* linked to their corresponding app-scoped objects.
if (!Exposed.isExposed(exposed)) {
if (!(app === this || Exposed.isExposed(appExposed))) {
appExposed = appLocals[local] = Exposed.create();
}
exposed = locals[local] = Exposed.create(appExposed);
}
// When no namespace is provided, expose each value of the specified `obj`
// at each of its keys, then return early.
if (!(namespace || rootNamespace)) {
type = typeof obj;
// Only get the keys of enumerable objects.
if ((type === 'object' || type === 'function') && obj !== null) {
Object.keys(obj).forEach(function (key) {
exposed.add(key, obj[key], options);
});
}
return;
}
if (namespace) {
if (/^window\..+/.test(namespace)) {
namespace = namespace.replace('window.', '');
} else if (rootNamespace && namespace.indexOf(rootNamespace) !== 0) {
namespace = rootNamespace + '.' + namespace;
}
} else {
namespace = rootNamespace;
}
exposed.add(namespace, obj, options);
}