forked from carlos8f/node-relations
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
151 lines (134 loc) · 3.78 KB
/
index.js
File metadata and controls
151 lines (134 loc) · 3.78 KB
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
var relations = module.exports = require('eventflow')()
, parser = require('./parser')
, Context = require('./context')
relations.define = function (name, structure) {
var ctx = new Context(name, structure);
relations[name] = function () {
var args = [].slice.call(arguments);
var str = args.shift();
var str, named, unnamed, fn, raised = false;
do {
var arg = args.shift();
if (Array.isArray(arg)) {
unnamed = arg;
}
else if (typeof arg === 'object') {
named = arg;
}
else if (typeof arg === 'string' || typeof arg === 'number') {
if (typeof arg === 'string' && !str) {
str = arg;
continue;
}
unnamed || (unnamed = []);
unnamed.push(arg);
}
else if (typeof arg === 'function') {
fn = arg;
}
} while (args.length);
function raiseErr (err) {
if (raised) return;
raised = true;
if (typeof err === 'string') err = new Error(err);
if (fn) return fn(err);
throw err;
}
if (!str) {
return raiseErr('must pass a string to parse');
}
try {
var cmd = parser.parse(str);
}
catch (e) {
return raiseErr(e.message);
}
cmd.fn = function (err, value) {
if (err) return raiseErr(err);
if (fn) fn(null, value);
};
if (named && unnamed) {
return cmd.fn('cannot mix named and unnamed tokens');
}
['subject', 'role', 'verb', 'object'].forEach(function (k) {
if (cmd[k]) {
if (cmd[k].name) {
if (typeof named[cmd[k].name] === 'undefined') {
return cmd.fn('no data for named token :' + cmd[k].name);
}
cmd[k] = named[cmd[k].name];
}
else if (cmd[k].type) {
if (typeof unnamed[cmd[k].index] === 'undefined') {
return cmd.fn('no data for unnamed token (index: ' + cmd[k].index + ')');
}
cmd[k] = unnamed[cmd[k].index];
if (cmd[k].type === 'number') {
cmd[k] = parseFloat(cmd[k]);
}
}
else if (cmd[k].value) {
cmd[k] = cmd[k].value;
}
else {
return cmd.fn('weird error parsing "' + str + '"');
}
if (k === 'role' && !ctx.roles[cmd.role]) {
return cmd.fn('role not defined: "' + cmd.role + '"');
}
else if (k === 'verb' && !ctx.verbs[cmd.verb]) {
return cmd.fn('verb not defined: "' + cmd.verb + '"');
}
}
});
if (raised) return;
cmd.ctx = ctx;
queue(cmd);
};
['addRole', 'updateRole', 'removeRole', 'getRoles'].forEach(function (method) {
relations[name][method] = ctx[method].bind(ctx);
});
};
relations.stores = {
memory: require('./stores/memory'),
mysql: require('./stores/mysql'),
redis: require('./stores/redis'),
mongoose: require('./stores/mongoose_backend')
};
relations.use = function (store, options) {
relations._ready = false;
relations.store = store;
store.invoke('init', options || {}, function (err) {
if (err) throw err;
relations._ready = true;
});
};
relations.tearDown = function (cb) {
if (relations.store.listeners('reset').length) {
relations.store.invoke('reset', cb);
}
else cb();
};
relations._queue = [];
function queue (fn) {
if (!relations._queue.length) doQueue();
relations._queue.push(fn);
}
function doQueue () {
function _doQueue () {
if (!relations.store) {
relations.use(relations.stores.memory);
}
if (relations._ready && relations._queue.length) {
var cmd = relations._queue.shift();
relations.store.invoke(cmd.type, cmd, cmd.fn);
}
if (relations._queue.length) doQueue();
}
if (typeof setImmediate !== 'undefined') {
setImmediate(_doQueue);
}
else {
process.nextTick(_doQueue);
}
}