alchemymvc 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/lib/app/assets/scripts/.gitkeep +0 -0
  4. package/lib/app/assets/stylesheets/alchemy-info.less +0 -0
  5. package/lib/app/behaviour/publishable_behaviour.js +0 -0
  6. package/lib/app/behaviour/revision_behaviour.js +0 -0
  7. package/lib/app/behaviour/sluggable_behaviour.js +0 -0
  8. package/lib/app/component/.gitkeep +0 -0
  9. package/lib/app/conduit/electron_conduit.js +0 -0
  10. package/lib/app/conduit/http_conduit.js +173 -173
  11. package/lib/app/conduit/loopback_conduit.js +2 -3
  12. package/lib/app/conduit/socket_conduit.js +620 -620
  13. package/lib/app/controller/alchemy_info_controller.js +0 -0
  14. package/lib/app/datasource/mongo_datasource.js +0 -0
  15. package/lib/app/element/time_ago.js +2 -4
  16. package/lib/app/helper/alchemy_helper.js +22 -11
  17. package/lib/app/helper/client_collection.js +0 -0
  18. package/lib/app/helper/pagination_helper.js +0 -0
  19. package/lib/app/helper/router_helper.js +20 -7
  20. package/lib/app/helper/socket_helper.js +613 -613
  21. package/lib/app/helper_component/paginate_component.js +0 -0
  22. package/lib/app/helper_controller/component.js +0 -0
  23. package/lib/app/helper_controller/conduit.js +0 -0
  24. package/lib/app/helper_controller/controller.js +0 -0
  25. package/lib/app/helper_datasource/00-nosql_datasource.js +0 -0
  26. package/lib/app/helper_datasource/05-fallback_datasource.js +0 -0
  27. package/lib/app/helper_datasource/idb_datasource.js +0 -0
  28. package/lib/app/helper_datasource/indexed_db.js +0 -0
  29. package/lib/app/helper_field/00-objectid_field.js +0 -0
  30. package/lib/app/helper_field/06-text_field.js +0 -0
  31. package/lib/app/helper_field/10-number_field.js +0 -0
  32. package/lib/app/helper_field/boolean_field.js +0 -0
  33. package/lib/app/helper_field/date_field.js +0 -0
  34. package/lib/app/helper_field/datetime_field.js +0 -0
  35. package/lib/app/helper_field/enum_field.js +0 -0
  36. package/lib/app/helper_field/geopoint_field.js +0 -0
  37. package/lib/app/helper_field/habtm_field.js +0 -0
  38. package/lib/app/helper_field/hasoneparent_field.js +0 -0
  39. package/lib/app/helper_field/html_field.js +0 -0
  40. package/lib/app/helper_field/integer_field.js +0 -0
  41. package/lib/app/helper_field/object_field.js +0 -0
  42. package/lib/app/helper_field/regexp_field.js +0 -0
  43. package/lib/app/helper_field/schema_field.js +23 -2
  44. package/lib/app/helper_field/time_field.js +0 -0
  45. package/lib/app/helper_field/url_field.js +0 -0
  46. package/lib/app/helper_model/criteria.js +21 -3
  47. package/lib/app/helper_model/db_query.js +0 -0
  48. package/lib/app/helper_model/document_list.js +0 -0
  49. package/lib/app/helper_model/field_config.js +2 -2
  50. package/lib/app/helper_model/model.js +72 -5
  51. package/lib/app/model/alchemy_task_model.js +0 -0
  52. package/lib/app/routes.js +0 -0
  53. package/lib/app/view/alchemy/info.ejs +0 -0
  54. package/lib/app/view/error/unknown.ejs +0 -0
  55. package/lib/app/view/paginate/navlist.ejs +0 -0
  56. package/lib/bootstrap.js +0 -0
  57. package/lib/class/behaviour.js +0 -0
  58. package/lib/class/component.js +0 -0
  59. package/lib/class/conduit.js +2572 -2552
  60. package/lib/class/controller.js +4 -1
  61. package/lib/class/document.js +18 -4
  62. package/lib/class/document_list.js +0 -0
  63. package/lib/class/helper.js +0 -0
  64. package/lib/class/inode.js +0 -0
  65. package/lib/class/inode_dir.js +0 -0
  66. package/lib/class/inode_file.js +136 -112
  67. package/lib/class/inode_list.js +0 -0
  68. package/lib/class/model.js +1740 -1769
  69. package/lib/class/path_definition.js +0 -0
  70. package/lib/class/route.js +0 -0
  71. package/lib/class/router.js +6 -3
  72. package/lib/class/session.js +0 -0
  73. package/lib/class/task.js +0 -0
  74. package/lib/core/base.js +41 -18
  75. package/lib/core/client_alchemy.js +48 -2
  76. package/lib/core/discovery.js +0 -0
  77. package/lib/core/middleware.js +6 -4
  78. package/lib/core/routing.js +0 -0
  79. package/lib/core/socket.js +159 -159
  80. package/lib/init/alchemy.js +1848 -1823
  81. package/lib/init/constants.js +0 -0
  82. package/lib/init/functions.js +8 -4
  83. package/lib/init/load_functions.js +0 -0
  84. package/lib/init/requirements.js +101 -101
  85. package/lib/stages.js +10 -2
  86. package/package.json +74 -74
File without changes
File without changes
@@ -1145,9 +1145,9 @@ RouterClass.setMethod(function getOptions(result) {
1145
1145
  /**
1146
1146
  * Get an object of all the routes in this router and its children
1147
1147
  *
1148
- * @author Jelle De Loecker <jelle@develry.be>
1148
+ * @author Jelle De Loecker <jelle@elevenways.be>
1149
1149
  * @since 0.2.0
1150
- * @version 1.1.0
1150
+ * @version 1.2.7
1151
1151
  *
1152
1152
  * @param {Object} result Optional object to store sectioned results in
1153
1153
  *
@@ -1190,7 +1190,10 @@ RouterClass.setMethod(function getRoutes(result) {
1190
1190
  controller : route.controller,
1191
1191
  action : route.action,
1192
1192
  keys : route.keys,
1193
- has_breadcrumb_assignments : route.has_breadcrumb_assignments
1193
+ has_breadcrumb_assignments : route.has_breadcrumb_assignments || undefined,
1194
+ methods : route.methods,
1195
+ permission : route.permission || undefined,
1196
+ has_permission_assignments : route.has_permission_assignments || undefined,
1194
1197
  };
1195
1198
  }
1196
1199
 
File without changes
package/lib/class/task.js CHANGED
File without changes
package/lib/core/base.js CHANGED
@@ -35,7 +35,7 @@ __Protoblast.getGroup = function getGroup(name) {
35
35
  *
36
36
  * @author Jelle De Loecker <jelle@develry.be>
37
37
  * @since 0.3.0
38
- * @version 1.0.0
38
+ * @version 1.2.6
39
39
  */
40
40
  Base.constitute(function setBasicBehaviour() {
41
41
 
@@ -79,12 +79,12 @@ Base.constitute(function setBasicBehaviour() {
79
79
 
80
80
  // Set the title on the class itself, don't let children inherit it
81
81
  if (!this.hasOwnProperty('title')) {
82
- this.setStatic('title', this.name.titleize(), false);
82
+ this.setStatic('title', this.createClassTitle(), false);
83
83
  }
84
84
 
85
85
  // See if the type_name needs to be set automatically
86
86
  if (!this.hasOwnProperty('type_name')) {
87
- this.setStatic('type_name', this.name.underscore(), false);
87
+ this.setStatic('type_name', this.createClassTypeName(), false);
88
88
  }
89
89
 
90
90
  return;
@@ -98,12 +98,12 @@ Base.constitute(function setBasicBehaviour() {
98
98
 
99
99
  // See if the type_name needs to be set automatically
100
100
  if (!this.hasOwnProperty('type_name')) {
101
- this.setStatic('type_name', this.name.underscore(), false);
101
+ this.setStatic('type_name', this.createClassTypeName(), false);
102
102
  }
103
103
 
104
104
  // Do the same for the title
105
105
  if (!this.hasOwnProperty('title')) {
106
- this.setStatic('title', this.name.titleize(), false);
106
+ this.setStatic('title', this.createClassTitle(), false);
107
107
  }
108
108
 
109
109
  return;
@@ -126,12 +126,12 @@ Base.constitute(function setBasicBehaviour() {
126
126
 
127
127
  // See if the type_name needs to be set automatically
128
128
  if (!this.hasOwnProperty('type_name')) {
129
- this.setStatic('type_name', name.underscore(), false);
129
+ this.setStatic('type_name', this.createClassTypeName(name), false);
130
130
  }
131
131
 
132
132
  // Do the same for the title
133
133
  if (!this.hasOwnProperty('title')) {
134
- this.setStatic('title', name.titleize(), false);
134
+ this.setStatic('title', this.createClassTitle(name), false);
135
135
  }
136
136
 
137
137
  // Add this class to the shared group
@@ -139,21 +139,44 @@ Base.constitute(function setBasicBehaviour() {
139
139
  });
140
140
 
141
141
  /**
142
- * Make this an abstract class
142
+ * Create a type name for this class
143
+ * (An underscored key used in shared groups & enums)
143
144
  *
144
- * @author Jelle De Loecker <jelle@develry.be>
145
- * @since 1.0.0
146
- * @version 1.0.0
145
+ * @author Jelle De Loecker <jelle@elevenways.be>
146
+ * @since 1.2.6
147
+ * @version 1.2.6
147
148
  *
148
- * @param {Boolean} value
149
+ * @param {string} suggested_root
150
+ *
151
+ * @return {string}
149
152
  */
150
- Base.setStatic(function makeAbstractClass(value) {
153
+ Base.setStatic(function createClassTypeName(suggested_root) {
151
154
 
152
- if (value == null) {
153
- value = true;
155
+ if (!suggested_root) {
156
+ suggested_root = this.name;
154
157
  }
155
158
 
156
- this.setStatic('is_abstract_class', value, false);
159
+ return suggested_root.underscore();
160
+ });
161
+
162
+ /**
163
+ * Create a title for this class
164
+ *
165
+ * @author Jelle De Loecker <jelle@elevenways.be>
166
+ * @since 1.2.6
167
+ * @version 1.2.6
168
+ *
169
+ * @param {string} suggested_root
170
+ *
171
+ * @return {string}
172
+ */
173
+ Base.setStatic(function createClassTitle(suggested_root) {
174
+
175
+ if (!suggested_root) {
176
+ suggested_root = this.name;
177
+ }
178
+
179
+ return suggested_root.titleize();
157
180
  });
158
181
 
159
182
  /**
@@ -345,7 +368,7 @@ Base.setStatic('starts_new_group', false);
345
368
  *
346
369
  * @author Jelle De Loecker <jelle@elevenways.be>
347
370
  * @since 1.1.8
348
- * @version 1.2.4
371
+ * @version 1.2.6
349
372
  *
350
373
  * @type {Conduit}
351
374
  */
@@ -359,7 +382,7 @@ Base.setProperty(function conduit() {
359
382
  result;
360
383
 
361
384
  if (Blast.isBrowser || !(this instanceof Classes.Alchemy.Controller)) {
362
- renderer = this.renderer || this.view || this.hawkejs_view;
385
+ renderer = this.hawkejs_renderer || this.hawkejs_view || this.renderer || this.view;
363
386
  }
364
387
 
365
388
  if (renderer?.conduit) {
@@ -403,8 +403,6 @@ Alchemy.setMethod(function checksum(value) {
403
403
  */
404
404
  Alchemy.setMethod(function markLinkElement(element, active_nr) {
405
405
 
406
- var mark_wrapper;
407
-
408
406
  // Always remove the current classes
409
407
  element.classList.remove('active-link');
410
408
  element.classList.remove('active-sublink');
@@ -424,6 +422,30 @@ Alchemy.setMethod(function markLinkElement(element, active_nr) {
424
422
  }
425
423
  });
426
424
 
425
+ /**
426
+ * Get the configuration for the given route
427
+ *
428
+ * @author Jelle De Loecker <jelle@elevenways.be>
429
+ * @since 1.2.7
430
+ * @version 1.2.7
431
+ *
432
+ * @param {String} name The route name
433
+ *
434
+ * @return {Object}
435
+ */
436
+ Alchemy.setMethod(function routeConfig(name) {
437
+
438
+ let result;
439
+
440
+ if (Blast.isNode) {
441
+ result = Classes.Alchemy.Helper.Router.prototype.routeConfig.call({}, name);
442
+ } else {
443
+ result = hawkejs.scene.general_renderer.helpers.Router.routeConfig(name);
444
+ }
445
+
446
+ return result;
447
+ });
448
+
427
449
  const markLinkElement = Alchemy.prototype.markLinkElement;
428
450
 
429
451
  // From here on, only client-side code is added
@@ -1112,4 +1134,28 @@ Alchemy.setMethod(function createSchema(parent) {
1112
1134
  */
1113
1135
  Alchemy.setMethod(function getClientModel(name, init, options) {
1114
1136
  return Classes.Alchemy.Client.Base.prototype.getModel.call(this, name, init, options);
1137
+ });
1138
+
1139
+ /**
1140
+ * Check if the current client-side user has a certain permission
1141
+ *
1142
+ * @author Jelle De Loecker <jelle@elevenways.be>
1143
+ * @since 1.2.7
1144
+ * @version 1.2.7
1145
+ *
1146
+ * @param {String} permission
1147
+ *
1148
+ * @return {Boolean}
1149
+ */
1150
+ Alchemy.setMethod(function hasPermission(permission) {
1151
+
1152
+ let user_data = hawkejs.scene.exposed['acl-user-data'];
1153
+
1154
+ if (user_data && user_data.permissions) {
1155
+ if (user_data.permissions.hasPermission?.(permission)) {
1156
+ return true;
1157
+ }
1158
+ }
1159
+
1160
+ return false;
1115
1161
  });
File without changes
@@ -128,7 +128,7 @@ function getMiddlePaths(paths, ext, new_ext) {
128
128
  *
129
129
  * @author Jelle De Loecker <jelle@develry.be>
130
130
  * @since 0.2.0
131
- * @version 0.5.0
131
+ * @version 1.2.7
132
132
  */
133
133
  Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
134
134
 
@@ -243,7 +243,7 @@ Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
243
243
  }
244
244
 
245
245
  if (!compiled || !compiled.path) {
246
- return req.conduit.notFound();
246
+ return nextMiddleware();
247
247
  }
248
248
 
249
249
  return req.conduit.serveFile(compiled.path, {onError: function onError(err) {
@@ -306,7 +306,7 @@ Alchemy.setMethod(function sourcemapMiddleware(req, res, nextMiddleware) {
306
306
  *
307
307
  * @author Jelle De Loecker <jelle@develry.be>
308
308
  * @since 0.2.0
309
- * @version 1.0.4
309
+ * @version 1.2.7
310
310
  *
311
311
  * @param {String} path
312
312
  * @param {Object} options
@@ -414,6 +414,7 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
414
414
  compress: {
415
415
  keep_fargs : true,
416
416
  keep_fnames : true,
417
+ keep_classnames : true,
417
418
  hoist_funs : false,
418
419
  drop_console : !alchemy.settings.debug,
419
420
  dead_code : true,
@@ -423,7 +424,8 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
423
424
  }
424
425
  },
425
426
  mangle: {
426
- keep_fnames : true
427
+ keep_fnames : true,
428
+ keep_classnames : true,
427
429
  }
428
430
  };
429
431
 
File without changes
@@ -1,160 +1,160 @@
1
- 'use strict';
2
-
3
- var types = alchemy.shared('Socket.types'),
4
- iostream,
5
- path = alchemy.use('path'),
6
- fs = alchemy.use('fs');
7
-
8
- /**
9
- * The "socket" stage:
10
- *
11
- * Create the socket.io listener
12
- *
13
- * @author Jelle De Loecker <jelle@develry.be>
14
- * @since 0.1.0
15
- * @version 1.1.3
16
- */
17
- alchemy.sputnik.add(function socket() {
18
-
19
- var clientPath,
20
- streamPath,
21
- io;
22
-
23
- if (!alchemy.settings.websockets) {
24
- log.info('Websockets have been disabled');
25
- return;
26
- } else {
27
- if (alchemy.settings.websockets == 'optional') {
28
- log.info('Websockets have been enabled optionally');
29
- } else {
30
- log.info('Websockets have been enabled, clients will automatically connect');
31
- }
32
- }
33
-
34
- io = alchemy.use('socket.io');
35
-
36
- if (!io) {
37
- return log.error('Could not load socket.io!');
38
- }
39
-
40
- iostream = alchemy.use('socket.io-stream');
41
-
42
- // Create the Socket.io listener
43
- alchemy.io = io.listen(alchemy.server, {serveClient: false});
44
-
45
- // Get the core client path
46
- clientPath = path.dirname(alchemy.findModule('socket.io-client').module_path);
47
- clientPath = path.resolve(clientPath, '..', 'dist', 'socket.io.slim.js');
48
-
49
- // Get the stream client path
50
- streamPath = path.dirname(alchemy.findModule('@11ways/socket.io-stream').module_path);
51
- streamPath = path.resolve(streamPath, 'socket.io-stream.js');
52
-
53
- // Serve the socket io core file
54
- Router.use('/scripts/socket.io.js', function getSocketIo(req, res, next) {
55
- alchemy.minifyScript(clientPath, function gotMinifiedPath(err, mpath) {
56
- req.conduit.serveFile(mpath || clientPath);
57
- });
58
- });
59
-
60
- // Serve the socket io stream file
61
- Router.use('/scripts/socket.io-stream.js', function getSocketStream(req, res, next) {
62
- alchemy.minifyScript(streamPath, function gotMinifiedPath(err, mpath) {
63
- req.conduit.serveFile(mpath || streamPath);
64
- });
65
- });
66
-
67
- /**
68
- * Handle connections
69
- *
70
- * @author Jelle De Loecker <jelle@develry.be>
71
- * @since 0.0.1
72
- * @version 0.2.0
73
- */
74
- alchemy.io.sockets.on('connection', function onConnect(socket){
75
-
76
- var syncs = {},
77
- latencies = [],
78
- latency_avg = 2,
79
- offset = 0;
80
-
81
- socket.on('timesync', function gotTimesyncRequest(data) {
82
-
83
- var received = Date.now(),
84
- latency;
85
-
86
- // This is the initial request
87
- if (data.count == null) {
88
- data.count = 0;
89
- data.latency_trip = 0;
90
-
91
- // Reset the latencies array
92
- latencies.length = 0;
93
- }
94
-
95
- // Do 8 round trips to determine latency
96
- if (data.latency_trip <= 8) {
97
-
98
- if (data.last_sent) {
99
-
100
- // Latency is the timestamp when we received the response
101
- // minus the timestamp when we sent the request
102
- latency = received - data.last_sent;
103
- latencies.push(latency);
104
- }
105
-
106
- // Wait before responding
107
- setTimeout(function waitForLatency() {
108
- data.last_sent = Date.now();
109
- socket.emit('timesync', data);
110
- }, 100 + (data.latency_trip * 150));
111
-
112
- data.latency_trip++;
113
- } else if (data.latency_trip) {
114
-
115
- latency_avg = ~~(Math.median(latencies) / 2);
116
- offset = (received - latency_avg) - data.client_time;
117
-
118
- socket.emit('timesync', {offset: offset, latency: latency_avg});
119
- }
120
- });
121
-
122
- // Wait for the announcement
123
- socket.once('announce', function gotAnnouncement(data) {
124
-
125
- var SocketClass,
126
- class_name;
127
-
128
- // Try getting the socket class of this type
129
- if (typeof data.type == 'string') {
130
- class_name = data.type.classify();
131
- SocketClass = Classes.Alchemy.Conduit[class_name + 'Socket'];
132
- }
133
-
134
- // If no socket class was found get the regular class
135
- if (!SocketClass) {
136
- SocketClass = Classes.Alchemy.Conduit.Socket;
137
- }
138
-
139
- new SocketClass(socket, data);
140
- });
141
- });
142
- });
143
-
144
- /**
145
- * Connect to another alchemy instance
146
- *
147
- * @author Jelle De Loecker <jelle@develry.be>
148
- * @since 0.1.0
149
- * @version 0.4.0
150
- */
151
- Alchemy.setMethod(function callServer(address, data, callback) {
152
-
153
- var server = new Classes.ClientSocket();
154
-
155
- server.reconnect = false;
156
-
157
- server.connect(address, data, callback);
158
-
159
- return server;
1
+ 'use strict';
2
+
3
+ var types = alchemy.shared('Socket.types'),
4
+ iostream,
5
+ path = alchemy.use('path'),
6
+ fs = alchemy.use('fs');
7
+
8
+ /**
9
+ * The "socket" stage:
10
+ *
11
+ * Create the socket.io listener
12
+ *
13
+ * @author Jelle De Loecker <jelle@develry.be>
14
+ * @since 0.1.0
15
+ * @version 1.1.3
16
+ */
17
+ alchemy.sputnik.add(function socket() {
18
+
19
+ var clientPath,
20
+ streamPath,
21
+ io;
22
+
23
+ if (!alchemy.settings.websockets) {
24
+ log.info('Websockets have been disabled');
25
+ return;
26
+ } else {
27
+ if (alchemy.settings.websockets == 'optional') {
28
+ log.info('Websockets have been enabled optionally');
29
+ } else {
30
+ log.info('Websockets have been enabled, clients will automatically connect');
31
+ }
32
+ }
33
+
34
+ io = alchemy.use('socket.io');
35
+
36
+ if (!io) {
37
+ return log.error('Could not load socket.io!');
38
+ }
39
+
40
+ iostream = alchemy.use('socket.io-stream');
41
+
42
+ // Create the Socket.io listener
43
+ alchemy.io = io.listen(alchemy.server, {serveClient: false});
44
+
45
+ // Get the core client path
46
+ clientPath = path.dirname(alchemy.findModule('socket.io-client').module_path);
47
+ clientPath = path.resolve(clientPath, '..', 'dist', 'socket.io.slim.js');
48
+
49
+ // Get the stream client path
50
+ streamPath = path.dirname(alchemy.findModule('@11ways/socket.io-stream').module_path);
51
+ streamPath = path.resolve(streamPath, 'socket.io-stream.js');
52
+
53
+ // Serve the socket io core file
54
+ Router.use('/scripts/socket.io.js', function getSocketIo(req, res, next) {
55
+ alchemy.minifyScript(clientPath, function gotMinifiedPath(err, mpath) {
56
+ req.conduit.serveFile(mpath || clientPath);
57
+ });
58
+ });
59
+
60
+ // Serve the socket io stream file
61
+ Router.use('/scripts/socket.io-stream.js', function getSocketStream(req, res, next) {
62
+ alchemy.minifyScript(streamPath, function gotMinifiedPath(err, mpath) {
63
+ req.conduit.serveFile(mpath || streamPath);
64
+ });
65
+ });
66
+
67
+ /**
68
+ * Handle connections
69
+ *
70
+ * @author Jelle De Loecker <jelle@develry.be>
71
+ * @since 0.0.1
72
+ * @version 0.2.0
73
+ */
74
+ alchemy.io.sockets.on('connection', function onConnect(socket){
75
+
76
+ var syncs = {},
77
+ latencies = [],
78
+ latency_avg = 2,
79
+ offset = 0;
80
+
81
+ socket.on('timesync', function gotTimesyncRequest(data) {
82
+
83
+ var received = Date.now(),
84
+ latency;
85
+
86
+ // This is the initial request
87
+ if (data.count == null) {
88
+ data.count = 0;
89
+ data.latency_trip = 0;
90
+
91
+ // Reset the latencies array
92
+ latencies.length = 0;
93
+ }
94
+
95
+ // Do 8 round trips to determine latency
96
+ if (data.latency_trip <= 8) {
97
+
98
+ if (data.last_sent) {
99
+
100
+ // Latency is the timestamp when we received the response
101
+ // minus the timestamp when we sent the request
102
+ latency = received - data.last_sent;
103
+ latencies.push(latency);
104
+ }
105
+
106
+ // Wait before responding
107
+ setTimeout(function waitForLatency() {
108
+ data.last_sent = Date.now();
109
+ socket.emit('timesync', data);
110
+ }, 100 + (data.latency_trip * 150));
111
+
112
+ data.latency_trip++;
113
+ } else if (data.latency_trip) {
114
+
115
+ latency_avg = ~~(Math.median(latencies) / 2);
116
+ offset = (received - latency_avg) - data.client_time;
117
+
118
+ socket.emit('timesync', {offset: offset, latency: latency_avg});
119
+ }
120
+ });
121
+
122
+ // Wait for the announcement
123
+ socket.once('announce', function gotAnnouncement(data) {
124
+
125
+ var SocketClass,
126
+ class_name;
127
+
128
+ // Try getting the socket class of this type
129
+ if (typeof data.type == 'string') {
130
+ class_name = data.type.classify();
131
+ SocketClass = Classes.Alchemy.Conduit[class_name + 'Socket'];
132
+ }
133
+
134
+ // If no socket class was found get the regular class
135
+ if (!SocketClass) {
136
+ SocketClass = Classes.Alchemy.Conduit.Socket;
137
+ }
138
+
139
+ new SocketClass(socket, data);
140
+ });
141
+ });
142
+ });
143
+
144
+ /**
145
+ * Connect to another alchemy instance
146
+ *
147
+ * @author Jelle De Loecker <jelle@develry.be>
148
+ * @since 0.1.0
149
+ * @version 0.4.0
150
+ */
151
+ Alchemy.setMethod(function callServer(address, data, callback) {
152
+
153
+ var server = new Classes.ClientSocket();
154
+
155
+ server.reconnect = false;
156
+
157
+ server.connect(address, data, callback);
158
+
159
+ return server;
160
160
  });