alchemymvc 1.1.10 → 1.2.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/datasource/mongo_datasource.js +75 -10
- package/lib/app/helper_datasource/00-nosql_datasource.js +73 -19
- package/lib/app/helper_model/criteria.js +73 -18
- package/lib/app/helper_model/field_config.js +24 -5
- package/lib/app/helper_model/model.js +45 -7
- package/lib/app/model/alchemy_migration_model.js +33 -0
- package/lib/bootstrap.js +9 -0
- package/lib/class/datasource.js +2 -2
- package/lib/class/field.js +7 -1
- package/lib/class/migration.js +138 -0
- package/lib/class/model.js +11 -19
- package/lib/class/schema.js +14 -12
- package/lib/init/alchemy.js +1779 -1779
- package/lib/init/load_functions.js +8 -2
- package/package.json +11 -11
- package/CHANGELOG.md +0 -462
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
const libpath = alchemy.use('path');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Migrations
|
|
5
|
+
*
|
|
6
|
+
* @constructor
|
|
7
|
+
*
|
|
8
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
9
|
+
* @since 1.2.0
|
|
10
|
+
* @version 1.2.0
|
|
11
|
+
*/
|
|
12
|
+
const Migration = Function.inherits('Alchemy.Base', function Migration(document) {
|
|
13
|
+
this.document = document;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Start the necesary migrations
|
|
18
|
+
*
|
|
19
|
+
* @constructor
|
|
20
|
+
*
|
|
21
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
22
|
+
* @since 1.2.0
|
|
23
|
+
* @version 1.2.0
|
|
24
|
+
*/
|
|
25
|
+
Migration.setStatic(async function start() {
|
|
26
|
+
|
|
27
|
+
const AlchemyMigration = Model.get('AlchemyMigration');
|
|
28
|
+
|
|
29
|
+
console.log('Starting migration task...');
|
|
30
|
+
|
|
31
|
+
let dir = new Classes.Alchemy.Inode.Directory(libpath.resolve(PATH_APP, 'migrations'));
|
|
32
|
+
|
|
33
|
+
await dir.loadContents();
|
|
34
|
+
|
|
35
|
+
for (let entry of dir) {
|
|
36
|
+
|
|
37
|
+
let name = entry.name.beforeLast('.js');
|
|
38
|
+
|
|
39
|
+
if (!name) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let crit = AlchemyMigration.find();
|
|
44
|
+
crit.where('name').equals(name);
|
|
45
|
+
|
|
46
|
+
let record = await AlchemyMigration.find('first', crit);
|
|
47
|
+
|
|
48
|
+
if (record) {
|
|
49
|
+
if (record.ended) {
|
|
50
|
+
console.log(' »» Migration "' + name + '" already finished on ' + record.ended.format('Y-m-d H:i'));
|
|
51
|
+
} else if (record.error) {
|
|
52
|
+
console.log(' »» Migration "' + name + '" failed with error: ' + record.error);
|
|
53
|
+
console.log('Migrations stopped');
|
|
54
|
+
return;
|
|
55
|
+
} else {
|
|
56
|
+
console.log(' »» Migration "' + name + '" has not yet finished!');
|
|
57
|
+
console.log('Migrations stopped');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
record = AlchemyMigration.createDocument();
|
|
65
|
+
record.name = name;
|
|
66
|
+
record.path = entry.path;
|
|
67
|
+
|
|
68
|
+
await record.save();
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
|
|
72
|
+
console.log(' »» Starting migration "' + name + '"');
|
|
73
|
+
|
|
74
|
+
let migration = new Migration(record);
|
|
75
|
+
|
|
76
|
+
await Blast.require(entry.path, {
|
|
77
|
+
client: false,
|
|
78
|
+
async : true,
|
|
79
|
+
arguments: {
|
|
80
|
+
names : [
|
|
81
|
+
'Blast',
|
|
82
|
+
'Collection',
|
|
83
|
+
'Bound',
|
|
84
|
+
'Obj',
|
|
85
|
+
'Fn',
|
|
86
|
+
'migration'
|
|
87
|
+
],
|
|
88
|
+
values : [
|
|
89
|
+
Blast,
|
|
90
|
+
Blast.Collection,
|
|
91
|
+
Blast.Bound,
|
|
92
|
+
Blast.Bound.Object,
|
|
93
|
+
Blast.Collection.Function,
|
|
94
|
+
migration,
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
record.ended = new Date();
|
|
100
|
+
await record.save();
|
|
101
|
+
|
|
102
|
+
} catch (err) {
|
|
103
|
+
console.log(' »» Migration error:', err);
|
|
104
|
+
record.error = err.message + '\n' + err.stack;
|
|
105
|
+
await record.save();
|
|
106
|
+
console.log('Migrations stopped');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log('Executed all migrations');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Migrate methods
|
|
116
|
+
*
|
|
117
|
+
* @constructor
|
|
118
|
+
*
|
|
119
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
120
|
+
* @since 1.2.0
|
|
121
|
+
* @version 1.2.0
|
|
122
|
+
*/
|
|
123
|
+
Migration.setMethod(function processRecords(model_name, fnc) {
|
|
124
|
+
|
|
125
|
+
const model = Model.get(model_name);
|
|
126
|
+
|
|
127
|
+
let options = {
|
|
128
|
+
document : false,
|
|
129
|
+
parallel_limit : 1,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return model.eachRecord(options, async (record, index, next) => {
|
|
133
|
+
await fnc(model, record[model_name], index);
|
|
134
|
+
next();
|
|
135
|
+
}, (err) => {
|
|
136
|
+
// Done!
|
|
137
|
+
});
|
|
138
|
+
});
|
package/lib/class/model.js
CHANGED
|
@@ -800,7 +800,7 @@ Model.setMethod(function ensureIds(list, callback) {
|
|
|
800
800
|
*
|
|
801
801
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
802
802
|
* @since 0.0.1
|
|
803
|
-
* @version 1.
|
|
803
|
+
* @version 1.2.0
|
|
804
804
|
*
|
|
805
805
|
* @param {Document} document
|
|
806
806
|
* @param {Object} options
|
|
@@ -853,7 +853,14 @@ Model.setMethod(function saveRecord(document, options, callback) {
|
|
|
853
853
|
}, function doBeforeSave(next) {
|
|
854
854
|
|
|
855
855
|
if (typeof that.beforeSave == 'function') {
|
|
856
|
-
that.beforeSave(document, options, next);
|
|
856
|
+
let promise = that.beforeSave(document, options, next);
|
|
857
|
+
|
|
858
|
+
if (promise) {
|
|
859
|
+
Pledge.done(promise, next);
|
|
860
|
+
} else if (that.beforeSave.length < 3) {
|
|
861
|
+
// If the method accepts no `next` callback, call it now
|
|
862
|
+
next();
|
|
863
|
+
}
|
|
857
864
|
} else {
|
|
858
865
|
next();
|
|
859
866
|
}
|
|
@@ -1133,21 +1140,6 @@ Model.setMethod(function processDatasourceFormat(ds_data, options, callback) {
|
|
|
1133
1140
|
return pledge;
|
|
1134
1141
|
});
|
|
1135
1142
|
|
|
1136
|
-
/**
|
|
1137
|
-
* Get a field instance from the schema
|
|
1138
|
-
*
|
|
1139
|
-
* @author Jelle De Loecker <jelle@develry.be>
|
|
1140
|
-
* @since 0.2.0
|
|
1141
|
-
* @version 0.2.0
|
|
1142
|
-
*
|
|
1143
|
-
* @param {String} name The name of the field
|
|
1144
|
-
*
|
|
1145
|
-
* @return {FieldType}
|
|
1146
|
-
*/
|
|
1147
|
-
Model.setMethod(function getField(name) {
|
|
1148
|
-
return this.schema.getField(name);
|
|
1149
|
-
});
|
|
1150
|
-
|
|
1151
1143
|
/**
|
|
1152
1144
|
* Get the title to display for this record
|
|
1153
1145
|
*
|
|
@@ -1317,7 +1309,7 @@ Model.setMethod(function remove(id, callback) {
|
|
|
1317
1309
|
*
|
|
1318
1310
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
1319
1311
|
* @since 0.5.0
|
|
1320
|
-
* @version 1.0
|
|
1312
|
+
* @version 1.2.0
|
|
1321
1313
|
*
|
|
1322
1314
|
* @param {Object} options Find options
|
|
1323
1315
|
* @param {Function} task Task to perform on each record
|
|
@@ -1382,7 +1374,7 @@ Model.setMethod(function eachRecord(options, task, callback) {
|
|
|
1382
1374
|
|
|
1383
1375
|
var record_index = index++;
|
|
1384
1376
|
|
|
1385
|
-
last_id = record[that.primary_key];
|
|
1377
|
+
last_id = record[that.model_name][that.primary_key];
|
|
1386
1378
|
|
|
1387
1379
|
tasks.push(function doSave(next) {
|
|
1388
1380
|
pledge.reportProgress(((record_index - 1) / available) * 100);
|
package/lib/class/schema.js
CHANGED
|
@@ -184,7 +184,7 @@ Schema.setMethod(function eachAlternateIndex(data, fnc) {
|
|
|
184
184
|
*
|
|
185
185
|
* @author Jelle De Loecker <jelle@develry.be>
|
|
186
186
|
* @since 1.1.0
|
|
187
|
-
* @version 1.
|
|
187
|
+
* @version 1.2.0
|
|
188
188
|
*
|
|
189
189
|
* @return {Pledge}
|
|
190
190
|
*/
|
|
@@ -192,20 +192,24 @@ Schema.setMethod(function getDatasource() {
|
|
|
192
192
|
|
|
193
193
|
var that = this;
|
|
194
194
|
|
|
195
|
-
return Function.
|
|
196
|
-
that.afterOnce('has_model_class',
|
|
197
|
-
next();
|
|
198
|
-
});
|
|
195
|
+
return Function.series(function waitForModelClass(next) {
|
|
196
|
+
that.afterOnce('has_model_class', next);
|
|
199
197
|
}, function waitForDatasources(next) {
|
|
200
198
|
|
|
201
199
|
alchemy.sputnik.after('datasources', function afterDs() {
|
|
202
200
|
|
|
203
|
-
|
|
201
|
+
let datasource;
|
|
204
202
|
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
203
|
+
if (that.model_class) {
|
|
204
|
+
datasource = Datasource.get(that.model_class.prototype.dbConfig);
|
|
205
|
+
|
|
206
|
+
if (!datasource) {
|
|
207
|
+
console.log('Failed to get', that.model_class.prototype.dbConfig, 'datasource?');
|
|
208
|
+
return next(new Error('Could not get datasource "' + that.model_class.prototype.dbConfig + '"'));
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
return next(new Error('Unable to get datasource for this sub-schema'));
|
|
212
|
+
}
|
|
209
213
|
|
|
210
214
|
next(null, datasource);
|
|
211
215
|
});
|
|
@@ -218,8 +222,6 @@ Schema.setMethod(function getDatasource() {
|
|
|
218
222
|
|
|
219
223
|
return result[1];
|
|
220
224
|
});
|
|
221
|
-
|
|
222
|
-
return pledge;
|
|
223
225
|
});
|
|
224
226
|
|
|
225
227
|
/**
|