alchemymvc 1.2.8 → 1.3.0
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.
- package/lib/app/behaviour/sluggable_behaviour.js +4 -2
- package/lib/app/conduit/loopback_conduit.js +2 -2
- package/lib/app/helper/router_helper.js +82 -17
- package/lib/app/helper_controller/controller.js +45 -30
- package/lib/app/helper_datasource/00-nosql_datasource.js +44 -10
- package/lib/app/helper_field/enum_field.js +4 -4
- package/lib/app/helper_field/schema_field.js +6 -6
- package/lib/app/helper_model/document.js +41 -10
- package/lib/app/helper_model/field_set.js +11 -0
- package/lib/app/helper_model/model.js +35 -10
- package/lib/bootstrap.js +1 -0
- package/lib/class/conduit.js +231 -244
- package/lib/class/datasource.js +6 -2
- package/lib/class/document.js +3 -3
- package/lib/class/field.js +13 -0
- package/lib/class/inode.js +27 -0
- package/lib/class/inode_file.js +204 -4
- package/lib/class/model.js +4 -4
- package/lib/class/path_definition.js +76 -120
- package/lib/class/path_param_definition.js +202 -0
- package/lib/class/route.js +176 -32
- package/lib/class/router.js +17 -3
- package/lib/class/schema.js +11 -11
- package/lib/class/schema_client.js +52 -19
- package/lib/class/sitemap.js +341 -0
- package/lib/core/base.js +6 -2
- package/lib/core/client_alchemy.js +76 -7
- package/lib/core/client_base.js +16 -10
- package/lib/core/middleware.js +56 -45
- package/lib/init/alchemy.js +12 -9
- package/lib/init/constants.js +11 -0
- package/lib/init/functions.js +134 -83
- package/package.json +5 -5
package/lib/core/middleware.js
CHANGED
|
@@ -7,7 +7,7 @@ var publicDirs = alchemy.shared('public.directories', new Deck()),
|
|
|
7
7
|
imageDirs = alchemy.shared('images.directories', new Deck()),
|
|
8
8
|
rootDirs = alchemy.shared('root.directories', new Deck()),
|
|
9
9
|
fontDirs = alchemy.shared('font.directories', new Deck()),
|
|
10
|
-
|
|
10
|
+
asset_cache= alchemy.getCache('files.assets'),
|
|
11
11
|
fileCache = alchemy.shared('files.fileCache'),
|
|
12
12
|
minifyMap = alchemy.shared('files.minifyMap'),
|
|
13
13
|
Nodent = alchemy.use('nodent-compiler'),
|
|
@@ -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 1.
|
|
131
|
+
* @version 1.3.0
|
|
132
132
|
*/
|
|
133
133
|
Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
|
|
134
134
|
|
|
@@ -145,10 +145,10 @@ Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
|
|
|
145
145
|
path = url.path;
|
|
146
146
|
|
|
147
147
|
// If this file has already been found & compiled, serve it to the user
|
|
148
|
-
if (
|
|
149
|
-
return req.conduit.serveFile(
|
|
148
|
+
if (asset_cache.has(path)) {
|
|
149
|
+
return req.conduit.serveFile(asset_cache.get(path).path, {onError: function onError() {
|
|
150
150
|
// Unset asset
|
|
151
|
-
|
|
151
|
+
asset_cache.remove(path);
|
|
152
152
|
alchemy.styleMiddleware(req, res, nextMiddleware);
|
|
153
153
|
}});
|
|
154
154
|
}
|
|
@@ -246,17 +246,20 @@ Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
|
|
|
246
246
|
return nextMiddleware();
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
return req.conduit.serveFile(compiled.path, {
|
|
250
|
-
|
|
251
|
-
|
|
249
|
+
return req.conduit.serveFile(compiled.path, {
|
|
250
|
+
mimetype: 'text/css',
|
|
251
|
+
onError: function onError(err) {
|
|
252
|
+
if (fileCache[compiled.path]) {
|
|
253
|
+
fileCache[compiled.path] = null;
|
|
252
254
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
if (o_stats && fileCache[o_stats.path]) {
|
|
256
|
+
fileCache[o_stats.path] = null;
|
|
257
|
+
}
|
|
256
258
|
|
|
257
|
-
|
|
259
|
+
alchemy.styleMiddleware(req, res, nextMiddleware);
|
|
260
|
+
}
|
|
258
261
|
}
|
|
259
|
-
}
|
|
262
|
+
});
|
|
260
263
|
});
|
|
261
264
|
});
|
|
262
265
|
|
|
@@ -266,7 +269,7 @@ Alchemy.setMethod(function styleMiddleware(req, res, nextMiddleware) {
|
|
|
266
269
|
*
|
|
267
270
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
268
271
|
* @since 1.1.0
|
|
269
|
-
* @version 1.
|
|
272
|
+
* @version 1.3.0
|
|
270
273
|
*/
|
|
271
274
|
Alchemy.setMethod(function sourcemapMiddleware(req, res, nextMiddleware) {
|
|
272
275
|
|
|
@@ -297,7 +300,9 @@ Alchemy.setMethod(function sourcemapMiddleware(req, res, nextMiddleware) {
|
|
|
297
300
|
return nextMiddleware();
|
|
298
301
|
}
|
|
299
302
|
|
|
300
|
-
req.conduit.serveFile(stats.path
|
|
303
|
+
req.conduit.serveFile(stats.path, {
|
|
304
|
+
mimetype: 'application/json',
|
|
305
|
+
});
|
|
301
306
|
});
|
|
302
307
|
});
|
|
303
308
|
|
|
@@ -503,7 +508,7 @@ Alchemy.setMethod(function minifyScript(path, options, callback) {
|
|
|
503
508
|
*
|
|
504
509
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
505
510
|
* @since 0.2.0
|
|
506
|
-
* @version 1.0
|
|
511
|
+
* @version 1.3.0
|
|
507
512
|
*/
|
|
508
513
|
Alchemy.setMethod(function scriptMiddleware(req, res, nextMiddleware) {
|
|
509
514
|
|
|
@@ -517,15 +522,15 @@ Alchemy.setMethod(function scriptMiddleware(req, res, nextMiddleware) {
|
|
|
517
522
|
return next();
|
|
518
523
|
}
|
|
519
524
|
|
|
520
|
-
if (
|
|
521
|
-
source =
|
|
525
|
+
if (asset_cache.has(req.url)) {
|
|
526
|
+
source = asset_cache.get(req.url);
|
|
522
527
|
return next();
|
|
523
528
|
}
|
|
524
529
|
|
|
525
530
|
alchemy.findAssetPath(req.middlePath, scriptDirs.getSorted(), function gotAssetPath(err, stats) {
|
|
526
531
|
|
|
527
532
|
// @todo: error stuff, 404
|
|
528
|
-
|
|
533
|
+
asset_cache.set(req.url, stats);
|
|
529
534
|
source = stats;
|
|
530
535
|
|
|
531
536
|
next();
|
|
@@ -566,22 +571,25 @@ Alchemy.setMethod(function scriptMiddleware(req, res, nextMiddleware) {
|
|
|
566
571
|
return nextMiddleware();
|
|
567
572
|
}
|
|
568
573
|
|
|
569
|
-
req.conduit.serveFile(source.path, {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
+
req.conduit.serveFile(source.path, {
|
|
575
|
+
mimetype: 'text/javascript',
|
|
576
|
+
onError: function onError() {
|
|
577
|
+
// Unset asset
|
|
578
|
+
if (fileCache[req.url]) {
|
|
579
|
+
fileCache[req.url] = null;
|
|
580
|
+
}
|
|
574
581
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
582
|
+
if (asset_cache.has(req.url)) {
|
|
583
|
+
asset_cache.remove(req.url);
|
|
584
|
+
}
|
|
578
585
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
586
|
+
if (source && minifyMap[source.path]) {
|
|
587
|
+
minifyMap[source.path] = null;
|
|
588
|
+
}
|
|
582
589
|
|
|
583
|
-
|
|
584
|
-
|
|
590
|
+
alchemy.scriptMiddleware(req, res, nextMiddleware);
|
|
591
|
+
}
|
|
592
|
+
});
|
|
585
593
|
});
|
|
586
594
|
});
|
|
587
595
|
|
|
@@ -622,15 +630,15 @@ Alchemy.setMethod(function assetInDirsMiddleware(req, res, directories, nextMidd
|
|
|
622
630
|
|
|
623
631
|
Function.series(function getPath(next) {
|
|
624
632
|
|
|
625
|
-
if (
|
|
626
|
-
source =
|
|
633
|
+
if (asset_cache.has(req.url)) {
|
|
634
|
+
source = asset_cache.get(req.url);
|
|
627
635
|
return next();
|
|
628
636
|
}
|
|
629
637
|
|
|
630
638
|
alchemy.findAssetPath(req.middlePath, directories, function gotAssetPath(err, stats) {
|
|
631
639
|
|
|
632
640
|
// @todo: error stuff, 404
|
|
633
|
-
|
|
641
|
+
asset_cache.set(req.url, stats);
|
|
634
642
|
source = stats;
|
|
635
643
|
|
|
636
644
|
next();
|
|
@@ -654,7 +662,7 @@ Alchemy.setMethod(function assetInDirsMiddleware(req, res, directories, nextMidd
|
|
|
654
662
|
*
|
|
655
663
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
656
664
|
* @since 0.2.0
|
|
657
|
-
* @version 1.
|
|
665
|
+
* @version 1.3.0
|
|
658
666
|
*/
|
|
659
667
|
Alchemy.setMethod(function rootMiddleware(req, res, nextMiddleware) {
|
|
660
668
|
|
|
@@ -663,8 +671,8 @@ Alchemy.setMethod(function rootMiddleware(req, res, nextMiddleware) {
|
|
|
663
671
|
|
|
664
672
|
Function.series(function getPath(next) {
|
|
665
673
|
|
|
666
|
-
if (
|
|
667
|
-
source =
|
|
674
|
+
if (asset_cache.has(req.url)) {
|
|
675
|
+
source = asset_cache.get(req.url);
|
|
668
676
|
cached = true;
|
|
669
677
|
return next();
|
|
670
678
|
}
|
|
@@ -672,7 +680,10 @@ Alchemy.setMethod(function rootMiddleware(req, res, nextMiddleware) {
|
|
|
672
680
|
alchemy.findAssetPath(req.middlePath, rootDirs.getSorted(), function gotAssetPath(err, stats) {
|
|
673
681
|
|
|
674
682
|
// @todo: error stuff, 404
|
|
675
|
-
|
|
683
|
+
if (stats?.path) {
|
|
684
|
+
asset_cache.set(req.url, stats);
|
|
685
|
+
}
|
|
686
|
+
|
|
676
687
|
source = stats;
|
|
677
688
|
|
|
678
689
|
next();
|
|
@@ -689,7 +700,7 @@ Alchemy.setMethod(function rootMiddleware(req, res, nextMiddleware) {
|
|
|
689
700
|
onError: function onError() {
|
|
690
701
|
|
|
691
702
|
if (cached) {
|
|
692
|
-
|
|
703
|
+
asset_cache.remove(req.url);
|
|
693
704
|
alchemy.rootMiddleware(req, res, nextMiddleware);
|
|
694
705
|
return;
|
|
695
706
|
}
|
|
@@ -704,7 +715,7 @@ Alchemy.setMethod(function rootMiddleware(req, res, nextMiddleware) {
|
|
|
704
715
|
*
|
|
705
716
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
706
717
|
* @since 0.2.0
|
|
707
|
-
* @version 1.
|
|
718
|
+
* @version 1.3.0
|
|
708
719
|
*
|
|
709
720
|
* @param {String} image_path
|
|
710
721
|
* @param {Function} callback
|
|
@@ -723,8 +734,8 @@ Alchemy.setMethod(function findImagePath(image_path, callback) {
|
|
|
723
734
|
|
|
724
735
|
let id = 'image-' + image_path;
|
|
725
736
|
|
|
726
|
-
if (alchemy.settings.cache &&
|
|
727
|
-
pledge.resolve(
|
|
737
|
+
if (alchemy.settings.cache && asset_cache.has(id)) {
|
|
738
|
+
pledge.resolve(asset_cache.get(id).path);
|
|
728
739
|
} else {
|
|
729
740
|
|
|
730
741
|
alchemy.findAssetPath(image_path, imageDirs.getSorted(), function gotImagePath(err, stats) {
|
|
@@ -732,7 +743,7 @@ Alchemy.setMethod(function findImagePath(image_path, callback) {
|
|
|
732
743
|
if (err) {
|
|
733
744
|
pledge.reject(err);
|
|
734
745
|
} else {
|
|
735
|
-
|
|
746
|
+
asset_cache.set(id, stats);
|
|
736
747
|
pledge.resolve(stats.path);
|
|
737
748
|
}
|
|
738
749
|
});
|
|
@@ -869,7 +880,7 @@ Alchemy.setMethod(function findAssetPath(assetFile, directories, callback) {
|
|
|
869
880
|
}, function lastly() {
|
|
870
881
|
|
|
871
882
|
// Return an empty object when nothing was found,
|
|
872
|
-
// so we'll cache that in the
|
|
883
|
+
// so we'll cache that in the asset_cache
|
|
873
884
|
// Otherwise it'll keep checking for every request
|
|
874
885
|
if (found == null) {
|
|
875
886
|
found = {};
|
package/lib/init/alchemy.js
CHANGED
|
@@ -92,6 +92,9 @@ global.Alchemy = Function.inherits('Informer', 'Alchemy', function Alchemy() {
|
|
|
92
92
|
// Also store the version of the app
|
|
93
93
|
process.versions.alchemy_app = this.package.version;
|
|
94
94
|
|
|
95
|
+
// Distinct problems
|
|
96
|
+
this.distinct_problems = new Map();
|
|
97
|
+
|
|
95
98
|
// Load the settings
|
|
96
99
|
this.loadSettings();
|
|
97
100
|
|
|
@@ -1113,7 +1116,7 @@ Alchemy.setMethod(function isStream(obj) {
|
|
|
1113
1116
|
*
|
|
1114
1117
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1115
1118
|
* @since 1.0.0
|
|
1116
|
-
* @version 1.0
|
|
1119
|
+
* @version 1.3.0
|
|
1117
1120
|
*
|
|
1118
1121
|
* @param {String} name
|
|
1119
1122
|
* @param {Number|Object} options
|
|
@@ -1144,12 +1147,11 @@ Alchemy.setMethod(function getCache(name, options) {
|
|
|
1144
1147
|
}
|
|
1145
1148
|
|
|
1146
1149
|
config = Object.assign({
|
|
1150
|
+
name,
|
|
1147
1151
|
max_length : 5000,
|
|
1148
1152
|
}, options);
|
|
1149
1153
|
|
|
1150
|
-
|
|
1151
|
-
instance = new Blast.Classes.Develry.Cache();
|
|
1152
|
-
Object.assign(instance, config);
|
|
1154
|
+
instance = new Blast.Classes.Develry.Cache(config);
|
|
1153
1155
|
|
|
1154
1156
|
this.caches[name] = instance;
|
|
1155
1157
|
|
|
@@ -1161,16 +1163,17 @@ Alchemy.setMethod(function getCache(name, options) {
|
|
|
1161
1163
|
*
|
|
1162
1164
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1163
1165
|
* @since 1.1.3
|
|
1164
|
-
* @version 1.
|
|
1166
|
+
* @version 1.3.0
|
|
1165
1167
|
*
|
|
1166
1168
|
* @param {String} href The href or route name
|
|
1167
1169
|
* @param {Object} parameters Route parameters
|
|
1170
|
+
* @param {Object} options
|
|
1168
1171
|
*
|
|
1169
1172
|
* @return {String}
|
|
1170
1173
|
*/
|
|
1171
|
-
Alchemy.setMethod(function routeUrl(href, parameters) {
|
|
1174
|
+
Alchemy.setMethod(function routeUrl(href, parameters, options) {
|
|
1172
1175
|
|
|
1173
|
-
let temp = Router.getUrl(href, parameters);
|
|
1176
|
+
let temp = Router.getUrl(href, parameters, options);
|
|
1174
1177
|
|
|
1175
1178
|
if (temp && temp.href) {
|
|
1176
1179
|
temp = String(temp);
|
|
@@ -1382,7 +1385,7 @@ Alchemy.setMethod(function addAppcacheEntry(entry) {
|
|
|
1382
1385
|
*
|
|
1383
1386
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1384
1387
|
* @since 1.1.0
|
|
1385
|
-
* @version 1.
|
|
1388
|
+
* @version 1.3.0
|
|
1386
1389
|
*
|
|
1387
1390
|
* @param {IncomingMessage} req
|
|
1388
1391
|
* @param {OutgoingMessage} res Optional
|
|
@@ -1410,7 +1413,7 @@ Alchemy.setMethod(function parseRequestBody(req, res, callback) {
|
|
|
1410
1413
|
|
|
1411
1414
|
let form = new formidable.IncomingForm({
|
|
1412
1415
|
multiples : true,
|
|
1413
|
-
hashAlgorithm : '
|
|
1416
|
+
hashAlgorithm : alchemy.settings.file_hash_algorithm || 'sha1',
|
|
1414
1417
|
});
|
|
1415
1418
|
|
|
1416
1419
|
form.parse(req, function parsedMultipart(err, form_fields, form_files) {
|
package/lib/init/constants.js
CHANGED
|
@@ -48,6 +48,17 @@ DEFINE('Blast', __Protoblast);
|
|
|
48
48
|
*/
|
|
49
49
|
DEFINE('Classes', Blast.Classes);
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Available types
|
|
53
|
+
*
|
|
54
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
55
|
+
* @since 1.3.0
|
|
56
|
+
* @version 1.3.0
|
|
57
|
+
*
|
|
58
|
+
* @type {Object}
|
|
59
|
+
*/
|
|
60
|
+
DEFINE('Types', Blast.Types);
|
|
61
|
+
|
|
51
62
|
/**
|
|
52
63
|
* Path to the directory of the server.js file
|
|
53
64
|
*
|
package/lib/init/functions.js
CHANGED
|
@@ -11,8 +11,9 @@ var mkdirp = alchemy.use('mkdirp'),
|
|
|
11
11
|
timers = {},
|
|
12
12
|
lpQueue = 0,
|
|
13
13
|
moduledirs,
|
|
14
|
-
spawnQueue
|
|
15
|
-
|
|
14
|
+
spawnQueue;
|
|
15
|
+
|
|
16
|
+
const HAS_EXPOSED = Symbol('has_exposed');
|
|
16
17
|
|
|
17
18
|
// Create a queue for functions opening files
|
|
18
19
|
spawnQueue = Function.createQueue();
|
|
@@ -519,25 +520,22 @@ alchemy.ObjectId = mongo.ObjectID;
|
|
|
519
520
|
|
|
520
521
|
/**
|
|
521
522
|
* Get mimetype info of a file
|
|
523
|
+
*
|
|
524
|
+
* @deprecated Use Classes.Alchemy.Inode.File.getMimetype(path)
|
|
522
525
|
*
|
|
523
526
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
524
527
|
* @since 0.2.0
|
|
525
|
-
* @version
|
|
528
|
+
* @version 1.3.0
|
|
526
529
|
*
|
|
527
|
-
* @param {String}
|
|
530
|
+
* @param {String} filepath A path to the file
|
|
528
531
|
* @param {Function} callback
|
|
532
|
+
*
|
|
533
|
+
* @return {Pledge<String>}
|
|
529
534
|
*/
|
|
530
|
-
Alchemy.setMethod(function getMimetype(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (!mmm) {
|
|
536
|
-
return callback(new Error('The mmmagic module is not available'));
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE);
|
|
540
|
-
magic.detectFile(filePath, callback);
|
|
535
|
+
Alchemy.setMethod(function getMimetype(filepath, callback) {
|
|
536
|
+
const pledge = Classes.Alchemy.Inode.File.getMimetype(filepath);
|
|
537
|
+
pledge.done(callback);
|
|
538
|
+
return pledge;
|
|
541
539
|
});
|
|
542
540
|
|
|
543
541
|
/**
|
|
@@ -687,9 +685,9 @@ Alchemy.setMethod(function getMedhash(file_path, options) {
|
|
|
687
685
|
/**
|
|
688
686
|
* Hash the given file_path using the given hash
|
|
689
687
|
*
|
|
690
|
-
* @author Jelle De Loecker <jelle@
|
|
688
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
691
689
|
* @since 1.0.7
|
|
692
|
-
* @version 1.0
|
|
690
|
+
* @version 1.3.0
|
|
693
691
|
*
|
|
694
692
|
* @param {String} file_path
|
|
695
693
|
* @param {Object} options
|
|
@@ -698,7 +696,7 @@ Alchemy.setMethod(function hashFile(file_path, options) {
|
|
|
698
696
|
|
|
699
697
|
var stream_options = {},
|
|
700
698
|
digest_type,
|
|
701
|
-
|
|
699
|
+
hash_algorithm;
|
|
702
700
|
|
|
703
701
|
if (!options) {
|
|
704
702
|
options = {};
|
|
@@ -710,10 +708,10 @@ Alchemy.setMethod(function hashFile(file_path, options) {
|
|
|
710
708
|
};
|
|
711
709
|
}
|
|
712
710
|
|
|
713
|
-
|
|
711
|
+
hash_algorithm = options.algorithm || options.type || alchemy.settings.file_hash_algorithm || 'sha1';
|
|
714
712
|
digest_type = options.digest_type || 'hex';
|
|
715
713
|
|
|
716
|
-
let checksum = crypto.createHash(
|
|
714
|
+
let checksum = crypto.createHash(hash_algorithm),
|
|
717
715
|
pledge = new Pledge(),
|
|
718
716
|
stream;
|
|
719
717
|
|
|
@@ -781,7 +779,7 @@ Alchemy.setMethod(function statPath(path, options) {
|
|
|
781
779
|
*
|
|
782
780
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
783
781
|
* @since 0.0.1
|
|
784
|
-
* @version 1.0
|
|
782
|
+
* @version 1.3.0
|
|
785
783
|
*
|
|
786
784
|
* @param {String} filePath A path to the file
|
|
787
785
|
* @param {Object} options
|
|
@@ -802,7 +800,7 @@ Alchemy.setMethod(function getFileInfo(filePath, options, callback) {
|
|
|
802
800
|
|
|
803
801
|
// Use sha1 as hashing default
|
|
804
802
|
if (typeof options.hash == 'undefined' || options.hash === true) {
|
|
805
|
-
options.hash = 'sha1';
|
|
803
|
+
options.hash = alchemy.settings.file_hash_algorithm || 'sha1';
|
|
806
804
|
}
|
|
807
805
|
|
|
808
806
|
// Get basic file information
|
|
@@ -1011,42 +1009,45 @@ Alchemy.setMethod(function request(url, options, callback) {
|
|
|
1011
1009
|
});
|
|
1012
1010
|
|
|
1013
1011
|
/**
|
|
1014
|
-
* Download a
|
|
1012
|
+
* Download a file
|
|
1015
1013
|
*
|
|
1016
|
-
* @author Jelle De Loecker <jelle@
|
|
1017
|
-
* @since
|
|
1018
|
-
* @version 1.
|
|
1014
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1015
|
+
* @since 1.3.0
|
|
1016
|
+
* @version 1.3.0
|
|
1019
1017
|
*
|
|
1020
|
-
* @param {String} url
|
|
1021
|
-
*
|
|
1022
|
-
* @
|
|
1018
|
+
* @param {String} url
|
|
1019
|
+
*
|
|
1020
|
+
* @return {Pledge<File>}
|
|
1023
1021
|
*/
|
|
1024
|
-
Alchemy.setMethod(function
|
|
1022
|
+
Alchemy.setMethod(function download(url, options) {
|
|
1025
1023
|
|
|
1026
|
-
|
|
1027
|
-
options,
|
|
1028
|
-
name,
|
|
1029
|
-
file,
|
|
1030
|
-
res;
|
|
1031
|
-
|
|
1032
|
-
if (typeof options === 'function') {
|
|
1033
|
-
callback = options;
|
|
1034
|
-
options = {};
|
|
1035
|
-
} else if (!options && typeof options !== 'object') {
|
|
1036
|
-
options = {};
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
if (typeof callback !== 'function') {
|
|
1040
|
-
callback = Function.thrower;
|
|
1041
|
-
}
|
|
1024
|
+
const pledge = new Pledge();
|
|
1042
1025
|
|
|
1043
1026
|
// Get the file
|
|
1044
|
-
Blast.fetch({url, get_stream: true}, function gotStream(err, res, output) {
|
|
1027
|
+
Blast.fetch({url, get_stream: true}, async function gotStream(err, res, output) {
|
|
1045
1028
|
|
|
1046
1029
|
if (err) {
|
|
1047
|
-
return
|
|
1030
|
+
return pledge.reject(err);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
if (res.statusCode == 404) {
|
|
1034
|
+
err = new Error('Path "' + url + '" does not exist');
|
|
1035
|
+
err.number = 404;
|
|
1036
|
+
return pledge.reject(err);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
if (options?.type && res.headers['content-type']) {
|
|
1040
|
+
if (res.headers['content-type'].indexOf(options.type) < 0) {
|
|
1041
|
+
|
|
1042
|
+
err = new Error('Received unexpected filetype');
|
|
1043
|
+
err.number = 500;
|
|
1044
|
+
|
|
1045
|
+
return pledge.reject(err);
|
|
1046
|
+
}
|
|
1048
1047
|
}
|
|
1049
1048
|
|
|
1049
|
+
let name;
|
|
1050
|
+
|
|
1050
1051
|
if (res.headers['content-disposition']) {
|
|
1051
1052
|
let disposition = res.headers['content-disposition'],
|
|
1052
1053
|
pieces = disposition.split(';'),
|
|
@@ -1075,44 +1076,60 @@ Alchemy.setMethod(function downloadFile(url, options, callback) {
|
|
|
1075
1076
|
}
|
|
1076
1077
|
}
|
|
1077
1078
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
// Open the temp file
|
|
1082
|
-
file = fs.createWriteStream(filepath);
|
|
1083
|
-
|
|
1084
|
-
if (res.statusCode == 404) {
|
|
1085
|
-
err = new Error('Path "' + url + '" does not exist');
|
|
1086
|
-
err.number = 404;
|
|
1087
|
-
|
|
1088
|
-
return callback(err);
|
|
1079
|
+
if (name.indexOf('/') > -1) {
|
|
1080
|
+
name = name.replaceAll('/', '-');
|
|
1089
1081
|
}
|
|
1090
1082
|
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
err.number = 500;
|
|
1096
|
-
|
|
1097
|
-
return callback(err);
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1083
|
+
let temp_dir = await Blast.createTempDir({prefix: 'aldl'}),
|
|
1084
|
+
full_path = libpath.resolve(temp_dir, name);
|
|
1085
|
+
|
|
1086
|
+
let write_stream = fs.createWriteStream(full_path);
|
|
1100
1087
|
|
|
1101
1088
|
if (output) {
|
|
1102
1089
|
// Pipe the response stream into the file
|
|
1103
|
-
output.pipe(
|
|
1090
|
+
output.pipe(write_stream);
|
|
1104
1091
|
} else {
|
|
1105
|
-
|
|
1092
|
+
write_stream.end('');
|
|
1106
1093
|
}
|
|
1107
1094
|
|
|
1108
|
-
//
|
|
1109
|
-
|
|
1095
|
+
// Wait for it to finish writing to the temp file
|
|
1096
|
+
write_stream.on('finish', async function writeFinished() {
|
|
1110
1097
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1098
|
+
try {
|
|
1099
|
+
let file = await Classes.Alchemy.Inode.Inode.from(full_path);
|
|
1100
|
+
pledge.resolve(file);
|
|
1101
|
+
} catch (err) {
|
|
1102
|
+
pledge.reject(err);
|
|
1103
|
+
}
|
|
1114
1104
|
});
|
|
1115
1105
|
});
|
|
1106
|
+
|
|
1107
|
+
return pledge;
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Download a url to a temporary location
|
|
1112
|
+
*
|
|
1113
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1114
|
+
* @since 0.1.0
|
|
1115
|
+
* @version 1.3.0
|
|
1116
|
+
*
|
|
1117
|
+
* @deprecated Use `download` instead
|
|
1118
|
+
*
|
|
1119
|
+
* @param {String} url The url
|
|
1120
|
+
* @param {Object} options
|
|
1121
|
+
* @param {Function} callback Callback
|
|
1122
|
+
*/
|
|
1123
|
+
Alchemy.setMethod(function downloadFile(url, options, callback) {
|
|
1124
|
+
|
|
1125
|
+
if (typeof options == 'function') {
|
|
1126
|
+
callback = options;
|
|
1127
|
+
options = null;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
let pledge = this.download(url, options);
|
|
1131
|
+
pledge.done(callback);
|
|
1132
|
+
return pledge;
|
|
1116
1133
|
});
|
|
1117
1134
|
|
|
1118
1135
|
/**
|
|
@@ -1345,14 +1362,7 @@ Alchemy.setMethod(function exposeDefaultStaticVariables() {
|
|
|
1345
1362
|
// Expose the model configuration
|
|
1346
1363
|
hawkejs.exposeStatic('model_info', model_info);
|
|
1347
1364
|
|
|
1348
|
-
|
|
1349
|
-
hawkejs.exposeStatic('router_options', Router.getOptions());
|
|
1350
|
-
|
|
1351
|
-
// Expose basic HTTP routes
|
|
1352
|
-
hawkejs.exposeStatic('routes', Router.getRoutes());
|
|
1353
|
-
|
|
1354
|
-
// Expose socket routes
|
|
1355
|
-
hawkejs.exposeStatic('socket_routes', Router.getSocketRoutes());
|
|
1365
|
+
this.exposeRouteData();
|
|
1356
1366
|
|
|
1357
1367
|
// Expose breadcrumb info
|
|
1358
1368
|
hawkejs.exposeStatic('breadcrumb_info', Router.getBreadcrumbInfo());
|
|
@@ -1379,6 +1389,47 @@ Alchemy.setMethod(function exposeDefaultStaticVariables() {
|
|
|
1379
1389
|
|
|
1380
1390
|
// Emit as a global event so plugins can also expose their data
|
|
1381
1391
|
this.emit('generate_static_variables', hawkejs);
|
|
1392
|
+
|
|
1393
|
+
this[HAS_EXPOSED] = true;
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
/**
|
|
1397
|
+
* Regenerate exposed route data
|
|
1398
|
+
*
|
|
1399
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1400
|
+
* @since 1.3.0
|
|
1401
|
+
* @version 1.3.0
|
|
1402
|
+
*/
|
|
1403
|
+
Alchemy.setMethod(function exposeRouteData() {
|
|
1404
|
+
|
|
1405
|
+
const hawkejs = alchemy.hawkejs;
|
|
1406
|
+
|
|
1407
|
+
// Expose router options
|
|
1408
|
+
hawkejs.exposeStatic('router_options', Router.getOptions());
|
|
1409
|
+
|
|
1410
|
+
// Expose basic HTTP routes
|
|
1411
|
+
hawkejs.exposeStatic('routes', Router.getRoutes());
|
|
1412
|
+
|
|
1413
|
+
// Expose socket routes
|
|
1414
|
+
hawkejs.exposeStatic('socket_routes', Router.getSocketRoutes());
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
/**
|
|
1419
|
+
* Flush the exposed route data
|
|
1420
|
+
* (Will only regenerate if default static variables haven't been generated yet)
|
|
1421
|
+
*
|
|
1422
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1423
|
+
* @since 1.3.0
|
|
1424
|
+
* @version 1.3.0
|
|
1425
|
+
*/
|
|
1426
|
+
Alchemy.setMethod(function checkExposedRouteData() {
|
|
1427
|
+
|
|
1428
|
+
if (!this[HAS_EXPOSED]) {
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
this.exposeRouteData();
|
|
1382
1433
|
});
|
|
1383
1434
|
|
|
1384
1435
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemymvc",
|
|
3
3
|
"description": "MVC framework for Node.js",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"author": "Jelle De Loecker <jelle@elevenways.be>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"alchemy",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"chokidar" : "~3.5.3",
|
|
23
23
|
"formidable" : "~2.0.1",
|
|
24
24
|
"graceful-fs" : "~4.2.9",
|
|
25
|
-
"hawkejs" : "~2.2.
|
|
25
|
+
"hawkejs" : "~2.2.23",
|
|
26
26
|
"jsondiffpatch" : "~0.4.1",
|
|
27
27
|
"mime" : "~3.0.0",
|
|
28
28
|
"minimist" : "~1.2.5",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"mongodb" : "~3.6.6",
|
|
32
32
|
"ncp" : "~2.0.0",
|
|
33
33
|
"postcss" : "~8.4.6",
|
|
34
|
-
"protoblast" : "~0.7.
|
|
34
|
+
"protoblast" : "~0.7.27",
|
|
35
35
|
"semver" : "~7.3.5",
|
|
36
36
|
"socket.io" : "~2.4.0",
|
|
37
37
|
"@11ways/socket.io-stream" : "~0.9.2",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"codecov" : "~3.8.1",
|
|
57
57
|
"istanbul-lib-instrument" : "~4.0.3",
|
|
58
58
|
"mocha" : "~8.3.2",
|
|
59
|
-
"mongo-unit" : "~2.0
|
|
59
|
+
"mongo-unit" : "~3.2.0",
|
|
60
60
|
"nyc" : "^15.1.0",
|
|
61
|
-
"puppeteer" : "~
|
|
61
|
+
"puppeteer" : "~19.0.0",
|
|
62
62
|
"source-map" : "~0.7.3"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|