larvitcms 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/dataWriter.js CHANGED
@@ -1,25 +1,15 @@
1
1
  'use strict';
2
2
 
3
- const EventEmitter = require('events').EventEmitter;
4
- const topLogPrefix = 'larvitcms: dataWriter.js: ';
5
- const DbMigration = require('larvitdbmigration');
6
- const slugify = require('larvitslugify');
7
- const LUtils = require('larvitutils');
8
- const amsync = require('larvitamsync');
9
- const async = require('async');
3
+ const { DbMigration } = require('larvitdbmigration');
4
+ const { slugify } = require('larvitslugify');
5
+ const { Utils, Log } = require('larvitutils');
10
6
 
11
- let isReady = false;
12
- let readyInProgress = false;
13
- let emitter = new EventEmitter();
7
+ const topLogPrefix = 'larvitcms: dataWriter.js: ';
14
8
 
15
9
  class DataWriter {
16
- static get emitter() { return emitter; }
17
-
18
10
  constructor(options) {
19
11
  if (!options.log) {
20
- const tmpLUtils = new LUtils();
21
-
22
- options.log = new tmpLUtils.Log();
12
+ options.log = new Log();
23
13
  }
24
14
 
25
15
  this.options = options;
@@ -28,339 +18,113 @@ class DataWriter {
28
18
  this[key] = options[key];
29
19
  }
30
20
 
31
- this.lUtils = new LUtils({log: this.log});
32
-
33
- this.listenToQueue();
34
- }
35
-
36
- listenToQueue(retries, cb) {
37
- const logPrefix = topLogPrefix + 'listenToQueue() - ';
38
- const options = {exchange: this.exchangeName};
39
- const tasks = [];
40
-
41
- let listenMethod;
42
-
43
- if (typeof retries === 'function') {
44
- cb = retries;
45
- retries = 0;
46
- }
47
-
48
- if (typeof cb !== 'function') {
49
- cb = function () {};
50
- }
51
-
52
- if (retries === undefined) {
53
- retries = 0;
54
- }
55
-
56
- tasks.push(cb => {
57
- if (this.mode === 'master') {
58
- listenMethod = 'consume';
59
- options.exclusive = true; // It is important no other client tries to sneak
60
- // out messages from us, and we want "consume"
61
- // since we want the queue to persist even if this
62
- // minion goes offline.
63
- } else if (this.mode === 'slave' || this.mode === 'noSync') {
64
- listenMethod = 'subscribe';
65
- } else {
66
- const err = new Error('Invalid this.mode. Must be either "master", "slave" or "noSync"');
67
-
68
- this.log.error(logPrefix + err.message);
69
-
70
- return cb(err);
71
- }
72
-
73
- this.log.info(logPrefix + 'listenMethod: ' + listenMethod);
74
-
75
- cb();
76
- });
77
-
78
- tasks.push(cb => {
79
- this.ready(cb);
80
- });
81
-
82
- tasks.push(cb => {
83
- this.intercom[listenMethod](options, (message, ack, deliveryTag) => {
84
- ack(); // Ack first, if something goes wrong we log it and handle it manually
85
-
86
- if (typeof message !== 'object') {
87
- this.log.error(logPrefix + 'intercom.' + listenMethod + '() - Invalid message received, is not an object! deliveryTag: "' + deliveryTag + '"');
88
-
89
- return;
90
- }
91
-
92
- if (typeof this[message.action] === 'function') {
93
- this[message.action](message.params, deliveryTag, message.uuid);
94
- } else {
95
- this.log.warn(logPrefix + 'intercom.' + listenMethod + '() - Unknown message.action received: "' + message.action + '"');
96
- }
97
- }, cb);
98
- });
99
-
100
- async.series(tasks, cb);
21
+ this.lUtils = new Utils({log: this.log});
101
22
  }
102
23
 
103
- // This is ran before each incoming message on the queue is handeled
104
- ready(retries, cb) {
105
- const logPrefix = topLogPrefix + 'ready() - ';
106
- const tasks = [];
107
-
108
- if (typeof retries === 'function') {
109
- cb = retries;
110
- retries = 0;
111
- }
112
-
113
- if (typeof cb !== 'function') {
114
- cb = function () {};
115
- }
116
-
117
- if (retries === undefined) {
118
- retries = 0;
119
- }
24
+ async runDbMigrations() {
25
+ const options = {};
120
26
 
121
- if (isReady === true) return cb();
27
+ options.dbType = 'mariadb';
28
+ options.dbDriver = this.db;
29
+ options.tableName = 'cms_db_version';
30
+ options.migrationScriptsPath = __dirname + '/dbmigration';
31
+ const dbMigration = new DbMigration(options);
122
32
 
123
- if (readyInProgress === true) {
124
- DataWriter.emitter.on('ready', cb);
125
-
126
- return;
127
- }
128
-
129
- readyInProgress = true;
130
-
131
- tasks.push(cb => {
132
- if (this.mode === 'slave') {
133
- this.log.verbose(logPrefix + 'this.mode: "' + this.mode + '", so read');
134
-
135
- amsync.mariadb({
136
- exchange: this.exchangeName + '_dataDump',
137
- intercom: this.intercom
138
- }, cb);
139
- } else {
140
- cb();
141
- }
142
- });
143
-
144
- // Migrate database
145
- tasks.push(cb => {
146
- const options = {};
147
-
148
- let dbMigration;
149
-
150
- options.dbType = 'mariadb';
151
- options.dbDriver = this.db;
152
- options.tableName = 'cms_db_version';
153
- options.migrationScriptsPath = __dirname + '/dbmigration';
154
- dbMigration = new DbMigration(options);
155
-
156
- dbMigration.run(err => {
157
- if (err) {
158
- this.log.error(logPrefix + 'Database error: ' + err.message);
159
- }
160
-
161
- cb(err);
162
- });
163
- });
164
-
165
- async.series(tasks, err => {
166
- if (err) return;
167
-
168
- isReady = true;
169
- DataWriter.emitter.emit('ready');
170
-
171
- if (this.mode === 'master') {
172
- this.runDumpServer(cb);
173
- } else {
174
- cb();
175
- }
176
- });
33
+ await dbMigration.run();
177
34
  }
178
35
 
179
- runDumpServer(cb) {
180
- const options = {
181
- exchange: this.exchangeName + '_dataDump',
182
- host: this.options.amsync ? this.options.amsync.host : null,
183
- minPort: this.options.amsync ? this.options.amsync.minPort : null,
184
- maxPort: this.options.amsync ? this.options.amsync.maxPort : null
185
- };
186
-
187
- const args = [];
188
-
189
- if (this.db.conf.host) {
190
- args.push('-h');
191
- args.push(this.db.conf.host);
192
- }
193
-
194
- args.push('-u');
195
- args.push(this.db.conf.user);
196
-
197
- if (this.db.conf.password) {
198
- args.push('-p' + this.db.conf.password);
199
- }
200
-
201
- args.push('--single-transaction');
202
- args.push('--hex-blob');
203
- args.push(this.db.conf.database);
204
-
205
- // Tables
206
- args.push('cms_db_version');
207
- args.push('cms_pages');
208
- args.push('cms_pagesData');
209
- args.push('cms_snippets');
210
-
211
- options.dataDumpCmd = {
212
- command: 'mysqldump',
213
- args: args
214
- };
215
-
216
- options['Content-Type'] = 'application/sql';
217
- options.intercom = this.intercom;
218
-
219
- new amsync.SyncServer(options, cb);
220
- }
221
-
222
- rmPage(params, deliveryTag, msgUuid) {
36
+ async rmPage(uuid) {
223
37
  const logPrefix = topLogPrefix + 'rmPage() - ';
224
- const options = params.data;
225
- const uuidBuffer = this.lUtils.uuidToBuffer(options.uuid);
226
- const tasks = [];
38
+ const uuidBuffer = this.lUtils.uuidToBuffer(uuid);
227
39
 
228
- if (options.uuid === undefined) {
40
+ if (uuid === undefined) {
229
41
  const err = new Error('pageUuid not provided');
230
-
231
42
  this.log.warn(logPrefix + err.message);
232
-
233
- return DataWriter.emitter.emit(msgUuid, err);
43
+ throw err;
234
44
  }
235
45
 
236
46
  if (uuidBuffer === false) {
237
47
  const err = new Error('Inavlid pageUuid provided');
238
-
239
48
  this.log.warn(logPrefix + err.message);
240
-
241
- return DataWriter.emitter.emit(msgUuid, err);
49
+ throw err;
242
50
  }
243
51
 
244
- tasks.push(cb => this.ready(cb));
245
-
246
- tasks.push(cb => {
247
- this.db.query('DELETE FROM cms_pagesData WHERE pageUuid = ?', [uuidBuffer], cb);
248
- });
249
-
250
- tasks.push(cb => {
251
- this.db.query('DELETE FROM cms_pages WHERE uuid = ?', [uuidBuffer], cb);
252
- });
253
-
254
- async.series(tasks, err => {
255
- DataWriter.emitter.emit(msgUuid, err);
256
- });
52
+ await this.db.query('DELETE FROM cms_pagesData WHERE pageUuid = ?', [uuidBuffer]);
53
+ await this.db.query('DELETE FROM cms_pages WHERE uuid = ?', [uuidBuffer]);
257
54
  }
258
55
 
259
- rmSnippet(params, deliveryTag, msgUuid) {
56
+ async rmSnippet(name) {
260
57
  const logPrefix = topLogPrefix + 'rmSnippet() - ';
261
- const options = params.data;
262
- const tasks = [];
263
58
 
264
- if (!options.name) {
59
+ if (!name) {
265
60
  const err = new Error('snippet name not provided');
266
-
267
61
  this.log.warn(logPrefix + err.message);
268
-
269
- return DataWriter.emitter.emit(msgUuid, err);
62
+ throw err;
270
63
  }
271
64
 
272
- tasks.push(cb => this.ready(cb));
273
-
274
- tasks.push(cb => {
275
- this.db.query('DELETE FROM cms_snippets WHERE name = ?', [options.name], cb);
276
- });
277
-
278
- async.series(tasks, err => {
279
- DataWriter.emitter.emit(msgUuid, err);
280
- });
65
+ await this.db.query('DELETE FROM cms_snippets WHERE name = ?', [name]);
281
66
  }
282
67
 
283
- savePage(params, deliveryTag, msgUuid) {
68
+ async savePage(options) {
284
69
  const logPrefix = topLogPrefix + 'savePage() - ';
285
- const options = params.data;
286
70
  const uuidBuffer = this.lUtils.uuidToBuffer(options.uuid);
287
- const tasks = [];
288
-
289
- let lang;
290
71
 
291
72
  if (options.uuid === undefined) {
292
73
  const err = new Error('pageUuid not provided');
293
-
294
74
  this.log.warn(logPrefix + err.message);
295
-
296
- return DataWriter.emitter.emit(msgUuid, err);
75
+ throw err;
297
76
  }
298
77
 
299
78
  if (uuidBuffer === false) {
300
79
  const err = new Error('Inavlid pageUuid provided');
301
-
302
80
  this.log.warn(logPrefix + err.message);
303
-
304
- return DataWriter.emitter.emit(msgUuid, err);
81
+ throw err;
305
82
  }
306
83
 
307
- this.log.debug(logPrefix + 'Running with data. "' + JSON.stringify(params.data) + '"');
84
+ this.log.debug(logPrefix + 'Running with data. "' + JSON.stringify(options) + '"');
308
85
 
309
- tasks.push(cb => this.ready(cb));
86
+ await this.db.query('DELETE FROM cms_pagesData WHERE pageUuid = ?', [uuidBuffer]);
87
+ await this.db.query('DELETE FROM cms_pages WHERE uuid = ?', [uuidBuffer]);
310
88
 
311
- tasks.push(cb => {
312
- this.db.query('DELETE FROM cms_pagesData WHERE pageUuid = ?', [uuidBuffer], cb);
313
- });
89
+ // Insert page
90
+ const dbFields = [uuidBuffer, options.name];
314
91
 
315
- tasks.push(cb => {
316
- this.db.query('DELETE FROM cms_pages WHERE uuid = ?', [uuidBuffer], cb);
317
- });
92
+ let sql = 'INSERT INTO cms_pages (uuid,name';
318
93
 
319
- tasks.push(cb => {
320
- const dbFields = [uuidBuffer, options.name];
321
-
322
- let sql = 'INSERT INTO cms_pages (uuid,name';
323
-
324
- if (options.published) {
325
- sql += ', published';
326
- }
94
+ if (options.published) {
95
+ sql += ', published';
96
+ }
327
97
 
328
- if (options.template) {
329
- sql += ', template';
330
- }
98
+ if (options.template) {
99
+ sql += ', template';
100
+ }
331
101
 
332
- sql += ') VALUES(?,?';
102
+ sql += ') VALUES(?,?';
333
103
 
334
- if (options.published) {
335
- sql += ',?';
336
- dbFields.push(options.published);
337
- }
104
+ if (options.published) {
105
+ sql += ',?';
106
+ dbFields.push(options.published);
107
+ }
338
108
 
339
- if (options.template) {
340
- sql += ',?';
341
- dbFields.push(options.template);
342
- }
109
+ if (options.template) {
110
+ sql += ',?';
111
+ dbFields.push(options.template);
112
+ }
343
113
 
344
- sql += ');';
114
+ sql += ');';
345
115
 
346
- this.db.query(sql, dbFields, cb);
347
- });
116
+ await this.db.query(sql, dbFields);
348
117
 
349
118
  // We need to declare this outside the loop because of async operations
350
- const addEntryData = (lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug) => {
351
- tasks.push(cb => {
352
- const dbFields = [uuidBuffer, lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug];
353
-
354
-
355
- const sql = 'INSERT INTO cms_pagesData (pageUuid, lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug) VALUES(?,?,?,?,?,?,?,?,?,?);';
356
-
357
- this.db.query(sql, dbFields, cb);
358
- });
119
+ const addEntryData = async (lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug) => {
120
+ const dbFields = [uuidBuffer, lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug];
121
+ const sql = 'INSERT INTO cms_pagesData (pageUuid, lang, htmlTitle, body1, body2, body3, body4, body5, body6, slug) VALUES(?,?,?,?,?,?,?,?,?,?);';
122
+ await this.db.query(sql, dbFields);
359
123
  };
360
124
 
361
125
  // Add content data
362
126
  if (options.langs) {
363
- for (lang in options.langs) {
127
+ for (const lang in options.langs) {
364
128
  if (options.langs[lang].slug) {
365
129
  options.langs[lang].slug = slugify(options.langs[lang].slug, {save: ['_', '-', '/']});
366
130
  }
@@ -377,39 +141,23 @@ class DataWriter {
377
141
  if (!options.langs[lang].body5) options.langs[lang].body5 = '';
378
142
  if (!options.langs[lang].body6) options.langs[lang].body6 = '';
379
143
 
380
- addEntryData(lang, options.langs[lang].htmlTitle, options.langs[lang].body1, options.langs[lang].body2, options.langs[lang].body3, options.langs[lang].body4, options.langs[lang].body5, options.langs[lang].body6, options.langs[lang].slug);
144
+ await addEntryData(lang, options.langs[lang].htmlTitle, options.langs[lang].body1, options.langs[lang].body2, options.langs[lang].body3, options.langs[lang].body4, options.langs[lang].body5, options.langs[lang].body6, options.langs[lang].slug);
381
145
  }
382
146
  }
383
-
384
- async.series(tasks, err => {
385
- DataWriter.emitter.emit(msgUuid, err);
386
- });
387
147
  }
388
148
 
389
- saveSnippet(params, deliveryTag, msgUuid) {
149
+ async saveSnippet(options) {
390
150
  const logPrefix = topLogPrefix + 'saveSnippet() - ';
391
- const options = params.data;
392
151
  const sql = 'REPLACE INTO cms_snippets (body, name, lang) VALUES(?,?,?);';
393
152
  const dbFields = [options.body, options.name, options.lang];
394
- const tasks = [];
395
153
 
396
154
  if (options.name === undefined) {
397
155
  const err = new Error('Name not provided');
398
-
399
156
  this.log.warn(logPrefix + err.message);
400
-
401
- return DataWriter.emitter.emit(msgUuid, err);
157
+ throw err;
402
158
  }
403
159
 
404
- tasks.push(cb => this.ready(cb));
405
-
406
- tasks.push(cb => {
407
- this.db.query(sql, dbFields, cb);
408
- });
409
-
410
- async.series(tasks, err => {
411
- DataWriter.emitter.emit(msgUuid, err);
412
- });
160
+ await this.db.query(sql, dbFields);
413
161
  }
414
162
  }
415
163
 
package/dbmigration/5.js CHANGED
@@ -1,30 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  const uuidLib = require('uuid');
4
- const lUtils = require('larvitutils');
5
- const async = require('async');
6
- const db = require('larvitdb');
4
+ const { Utils } = require('larvitutils');
7
5
 
8
- exports = module.exports = function (cb) {
9
- const tasks = [];
6
+ exports = module.exports = async context => {
7
+ const { db } = context;
10
8
 
11
- db.query('SELECT id FROM cms_pages WHERE uuid IS NULL', function (err, rows) {
12
- if (err) return cb(err);
9
+ const { rows } = await db.query('SELECT id FROM cms_pages WHERE uuid IS NULL');
10
+ if (rows.length === 0) return;
13
11
 
14
- if (rows.length === 0) return cb();
12
+ const lUtils = new Utils();
15
13
 
16
- for (const r of rows) {
17
- const uuid = lUtils.uuidToBuffer(uuidLib.v1());
14
+ for (const r of rows) {
15
+ const uuid = lUtils.uuidToBuffer(uuidLib.v1());
18
16
 
19
- tasks.push(function (cb) {
20
- db.query('UPDATE cms_pages SET uuid = ? WHERE id = ?', [uuid, r.id], cb);
21
- });
22
-
23
- tasks.push(function (cb) {
24
- db.query('UPDATE cms_pagesData SET pageUuid = ? WHERE pageId = ?', [uuid, r.id], cb);
25
- });
26
- }
27
-
28
- async.series(tasks, cb);
29
- });
17
+ await db.query('UPDATE cms_pages SET uuid = ? WHERE id = ?', [uuid, r.id]);
18
+ await db.query('UPDATE cms_pagesData SET pageUuid = ? WHERE pageId = ?', [uuid, r.id]);
19
+ }
30
20
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larvitcms",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "Simple blog module with admin GUI for larvitadmingui",
5
5
  "author": {
6
6
  "name": "Mikael 'Lilleman' Göransson",
@@ -9,25 +9,17 @@
9
9
  },
10
10
  "private": false,
11
11
  "dependencies": {
12
- "async": "^3.0.1",
13
- "larvitamintercom": "^0.3.4",
14
- "larvitamsync": "^0.7.3",
15
- "larvitdb": "^2.1.1",
16
- "larvitdbmigration": "^4.0.2",
17
- "larvitfs": "^2.3.1",
18
- "larvitslugify": "^1.0.0",
19
- "larvitutils": "^2.1.0",
20
- "lodash": "^4.17.4",
21
- "randomstring": "^1.1.5",
22
- "uuid": "^3.1.0"
12
+ "larvitdb": "3.2.0",
13
+ "larvitdbmigration": "6.1.0",
14
+ "larvitslugify": "2.0.1",
15
+ "larvitutils": "5.0.0",
16
+ "lodash": "4.17.21",
17
+ "uuid": "8.3.2"
23
18
  },
24
19
  "devDependencies": {
25
- "larvitruncmd": "github:larvit/larvitruncmd",
26
- "mocha": "6.1.4",
27
- "mocha-eslint": "5.0.0",
28
- "request": "2.88.0",
29
- "validator": "11.0.0",
30
- "wait-for-port": "0.0.2"
20
+ "eslint": "8.10.0",
21
+ "mocha": "9.2.1",
22
+ "nyc": "15.1.0"
31
23
  },
32
24
  "keywords": [
33
25
  "cms"
@@ -43,7 +35,10 @@
43
35
  },
44
36
  "homepage": "https://github.com/larvit/larvitcms",
45
37
  "scripts": {
46
- "test": "mocha"
38
+ "lint": "eslint *.js test/*.js dbmigration/*.js",
39
+ "test:unit": "mocha --exit --bail './test/*.js'",
40
+ "coverage": "nyc --reporter lcov npm run test:unit",
41
+ "test": "npm run lint && npm run coverage"
47
42
  },
48
43
  "license": "MIT",
49
44
  "maintainers": [