-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
158 lines (130 loc) · 3.5 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
var url = require('url');
var async = require('async');
var Model = require('./lib/model');
/**
* Xylem server constructor.
*
* @constructor
*/
function Server() {
this.adapters = {};
// Connections are adapter instances.
this.connections = {};
this.models = {};
this.initialized = false;
};
/**
* Initialize all connections.
*
* @param {Function} callback Callback to run when sucessfull initialized.
*/
Server.prototype.init = function(callback) {
var self = this;
async.each(Object.keys(this.connections), function(connName, next) {
var connection = self.connections[connName];
connection.init(next);
},
function(error) {
if (error) {
return callback(error);
}
self.initialized = true;
callback();
});
};
/**
* Add or get an adapter.
*
* @param {String} name Adapter name.
* @param {Object} [constructor] Adapter constructor.
* @return {Function|Server} Adapter constructor if constructor argument is
* omitted or the Server instance itself so method calls can be chained.
*/
Server.prototype.adapter = function(name, constructor) {
if (!constructor) {
return this.adapters[name];
}
this.adapters[name] = constructor;
return this;
};
/**
* Add or get a connection.
*
* @param {String} name Connection name.
* @param {String} url Connection settings URL.
* @return {Adapter|Server} Adapter instance (connection) if url argument is
* omitted or the Server instance itself so method calls can be chained.
*/
Server.prototype.connection = function(name, url) {
if (!url) {
return this.connections[name];
}
var settings = this.parseSettingsURL(url);
if (!(settings.adapter in this.adapters)) {
return this.error('Unknown adapter ' + settings.adapter + '.');
}
var adapter = this.adapters[settings.adapter];
var connection = new adapter(settings);
this.connections[name] = connection;
return this;
};
/**
* Add or get a model.
*
* @param {String} name Model name.
* @param {Object} settings Model settings object.
* @return {Function|Server} Model constructor if settings argument is omitted
* or the Server instance itself so method calls can be chained.
*/
Server.prototype.model = function(name, settings) {
if (!settings) {
return this.models[name];
}
var connection = this.connection(settings.connection);
if (!connection) {
return this.error('Unknown connection ' + settings.connection + '.');
}
// Add name to model settings.
settings.name = name;
this.models[name] = Model.compile(connection, settings);
return this;
};
/**
* Parse settings URL into setting object.
*
* @param {String} settingsURL Connection settings URL.
* @return {Object} Settings object.
*/
Server.prototype.parseSettingsURL = function(settingsURL) {
var settings = {};
var urlInfo = url.parse(settingsURL);
var settingsMap = {
adapter: 'protocol',
hostname: 'hostname',
port: 'port',
database: 'pathname'
};
for (var setting in settingsMap) {
var property = settingsMap[setting];
var value = urlInfo[property];
if (property == 'protocol') {
// Remove colon from protocol.
value = value.substring(0, value.length - 1);
}
if (property == 'pathname') {
// Remove slash from pathname.
value = value.substring(1, value.length);
}
if (property in urlInfo) {
settings[setting] = value;
}
}
return settings;
};
/**
* Throw an error.
*/
Server.prototype.error = function(message) {
throw new Error(message);
};
module.exports = Server