nails-boilerplate 1.3.1 → 2.0.2

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 (35) hide show
  1. package/lib/nails.js +16 -29
  2. package/lib/sequelize_connector.js +1 -1
  3. package/package.json +1 -1
  4. package/spec/mongodb_connector.util.js +2 -2
  5. package/spec/services/integration_sequelize/README.md +5 -0
  6. package/spec/services/integration_sequelize/client/css/styles.css +0 -0
  7. package/spec/services/integration_sequelize/client/download.jpg +0 -0
  8. package/spec/services/integration_sequelize/client/favicon.ico +0 -0
  9. package/spec/services/integration_sequelize/client/index.html +9 -0
  10. package/spec/services/integration_sequelize/client/js/client.js +0 -0
  11. package/spec/services/integration_sequelize/client/js/components/app.jsx +15 -0
  12. package/spec/services/integration_sequelize/config/db.js +4 -0
  13. package/spec/services/integration_sequelize/config/mimes.js +61 -0
  14. package/spec/services/integration_sequelize/config/routes.js +25 -0
  15. package/spec/services/integration_sequelize/config/service.js +48 -0
  16. package/spec/services/integration_sequelize/config/ssl/certificate.pem +22 -0
  17. package/spec/services/integration_sequelize/config/ssl/csr.csr +17 -0
  18. package/spec/services/integration_sequelize/config/ssl/key.pem +28 -0
  19. package/spec/services/integration_sequelize/config/ssl/private_key.pem +30 -0
  20. package/spec/services/integration_sequelize/config/ssl/public_key.pem +9 -0
  21. package/spec/services/integration_sequelize/package.json +23 -0
  22. package/spec/services/integration_sequelize/server/controllers/default_json_controller.js +21 -0
  23. package/spec/services/integration_sequelize/server/controllers/home_controller.js +39 -0
  24. package/spec/services/integration_sequelize/server/models/dog.js +7 -0
  25. package/spec/services/integration_sequelize/server/models/owner.js +10 -0
  26. package/spec/services/integration_sequelize/server/views/defaultjson/testnojson.ejs +1 -0
  27. package/spec/services/integration_sequelize/server/views/testreact/testreact.ejs +15 -0
  28. package/spec/services/integration_sequelize/server.js +9 -0
  29. package/spec/services.integration_sequelize.spec.js +67 -0
  30. package/templates/config/service.js +1 -1
  31. package/lib/model.js +0 -167
  32. package/lib/mongodb_connector.js +0 -100
  33. package/lib/sqlite3_connector.js +0 -88
  34. package/spec/model.spec.js +0 -95
  35. package/spec/mongodb_connector.spec.js +0 -66
package/lib/nails.js CHANGED
@@ -15,14 +15,10 @@ import { EventEmitter } from 'node:events';
15
15
 
16
16
 
17
17
  import Controller from './controller.js';
18
- import Model from './model.js';
19
18
  import ModelV2 from './model_v2.js';
20
19
  import Router from './router.js';
21
20
 
22
21
  import express_app from './application.js';
23
- import DbConnector from './database_connector.js';
24
-
25
- const models = {};
26
22
 
27
23
  // TODO: add key value pairs to express app singleton.
28
24
  var application = {};
@@ -42,8 +38,8 @@ export default async function nails(app_config) {
42
38
  nails.application = express_app;
43
39
  nails.Controller = Controller;
44
40
  nails.Model = ModelV2;
45
- nails.ModelDeprecated = Model;
46
41
  nails.events = new EventEmitter();
42
+ nails._dbConnector = null;
47
43
 
48
44
  async function configure( app_config ) {
49
45
  express_app.set('nails_config', application);
@@ -75,26 +71,16 @@ async function configure( app_config ) {
75
71
  console.log("Initializing DB connection...");
76
72
  var DBConnector = await get_dbconnector(app_config.db.connector);
77
73
 
78
- // TODO: deprecate the old Model style
79
- if (app_config.config.MODELS_ROOT) {
80
- Model.set_connector(DBConnector, app_config.db);
81
- await init_models(app_config.config.MODELS_ROOT);
82
- }
83
- // TODO: make this Model style mandatory
84
- console.log("Connecting to DB...");
85
- if (DBConnector instanceof DbConnector) {
86
- console.log("Generating model superclass...");
87
- await DBConnector.connect(app_config.db);
88
- ModelV2.setConnector(DBConnector);
89
- await init_models_v2(app_config.config.MODELS_ROOT);
90
- DBConnector.afterInitialization();
91
- } else {
92
- console.log("Instantiating DBConnector...");
93
- // Try to instantiate DBConnector
94
- let dbConnector = new DBConnector();
95
- await dbConnector.connect(app_config.db);
96
- ModelV2.setConnector(dbConnector);
97
- }
74
+ console.log("Instantiating DBConnector and Connecting to DB...");
75
+ // Try to instantiate DBConnector
76
+ const dbConnector = new DBConnector();
77
+ nails._dbConnector = dbConnector;
78
+ await dbConnector.connect(app_config.db);
79
+ console.log("Generating model superclass...");
80
+ ModelV2.setConnector(dbConnector);
81
+ await init_models_v2(app_config.config.MODELS_ROOT);
82
+ console.log("Done importing models")
83
+ await dbConnector.afterInitialization();
98
84
  console.log("DB Connection complete");
99
85
 
100
86
  // init Controllers
@@ -151,9 +137,9 @@ function startServer(config) {
151
137
  async function init_controllers(controller_lib) {
152
138
  await init_app_lib(Controller, controller_lib);
153
139
  }
154
- async function init_models(model_lib) {
155
- await init_app_lib(Model, model_lib);
156
- }
140
+ // async function init_models(model_lib) {
141
+ // await init_app_lib(Model, model_lib);
142
+ // }
157
143
  async function init_app_lib(superclass, abs_path) {
158
144
  console.log('attempting to import:', abs_path);
159
145
  if (!fs.existsSync(abs_path))
@@ -183,7 +169,8 @@ async function init_models_v2(abs_path) {
183
169
  // We just need to import each model once so the generateSuperclass
184
170
  // method is called at least once for each model.
185
171
  let modelClass = (await import(abs_path)).default;
186
- console.log('imported model:', modelClass.name);
172
+ if (modelClass && modelClass.name) console.log('imported model:', modelClass.name);
173
+ else console.warn("No model found at:", abs_path);
187
174
  // // Constructor function was provided
188
175
  // if (!superclass.isPrototypeOf(subclass))
189
176
  // return superclass.extend(subclass);
@@ -21,6 +21,6 @@ export default class SequelizeConnector extends DbConnector {
21
21
 
22
22
  async afterInitialization() {
23
23
  console.log("SEQUELIZE::Writing changes to SQL Database");
24
- await this.sequelize.sync({alter: true});
24
+ await this.sequelize.sync();
25
25
  }
26
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nails-boilerplate",
3
- "version": "1.3.1",
3
+ "version": "2.0.2",
4
4
  "description": "A node.js webserver scaffold",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -1,4 +1,4 @@
1
- import MongoDBConnector from '../lib/mongodb_connector.js';
1
+ import MongooseConnector from '../lib/mongoose_connector.js';
2
2
  import {MongoMemoryServer} from 'mongodb-memory-server';
3
3
 
4
4
  let singularInstanceCreated = false;
@@ -19,7 +19,7 @@ class MongoDBConnectorUtil {
19
19
  const dbConfig =
20
20
  {uri: uri, port: port, database: dbName, dbPath: dbPath};
21
21
  //console.log(JSON.stringify(dbConfig));
22
- return new MongoDBConnector(dbConfig);
22
+ return new MongooseConnector(dbConfig);
23
23
  }
24
24
 
25
25
  async cleanup() {
@@ -0,0 +1,5 @@
1
+ Integration testing (Sans DB Connector)
2
+ ==============
3
+
4
+ The package.json was copied from the example app. This is for integration
5
+ testing nails.
@@ -0,0 +1,9 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ </head>
5
+ <body>
6
+ <h1>Welcome</h1>
7
+ <div></div>
8
+ </body>
9
+ </html>
@@ -0,0 +1,15 @@
1
+ // Use frontend React components to build a single-page webapp
2
+ class App extends React.Component {
3
+ render() {
4
+ return (
5
+ <div>
6
+ Successfully rendered your homepage!
7
+ </div>
8
+ );
9
+ }
10
+ }
11
+
12
+ ReactDOM.render(
13
+ <App />,
14
+ document.getElementById('app')
15
+ );
@@ -0,0 +1,4 @@
1
+ export default {
2
+ connector: 'sequelize_connector.js',
3
+ address: 'sqlite::memory:',
4
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * This file uses file extensions in the request to determine
3
+ * the type of an asset and, therefore, where it can be found
4
+ * in the file system.
5
+ *
6
+ * Currently, the supported types are: 'js', 'css', 'html',
7
+ * 'img'
8
+ * TODO: Add supported types pdf ( or document ), and video
9
+ * TODO: move this file into nails. Too annoying for the dev
10
+ * to see and they shouldn't need to have to change it
11
+ */
12
+ /*
13
+ var mimes = {
14
+ // <ext>: '<type>'
15
+ js: 'js',
16
+ jpg: 'image',
17
+ css: 'css',
18
+ html: 'html'
19
+ };
20
+ */
21
+
22
+ var mimes = {
23
+ html: {
24
+ type: 'page',
25
+ contentType: 'text/html'
26
+ },
27
+ js: {
28
+ type: 'script', // the type of the script,
29
+ contentType: 'application/javascript' // Header info
30
+ },
31
+ css: {
32
+ type: 'style',
33
+ contentType: 'text/css'
34
+ },
35
+ ico: {
36
+ type: 'image',
37
+ contentType: 'image/x-icon'
38
+ },
39
+ jpg: {
40
+ type: 'image',
41
+ contentType: 'image/jpeg'
42
+ },
43
+ png: {
44
+ type: 'image',
45
+ contentType: 'image/png'
46
+ },
47
+ pdf: {
48
+ type: 'document',
49
+ contentType: 'application/pdf'
50
+ },
51
+ xml: {
52
+ type: 'data',
53
+ contentType: 'text/xml'
54
+ },
55
+ json: {
56
+ type: 'data',
57
+ contentType: 'application/json'
58
+ }
59
+ }
60
+
61
+ export default mimes;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Routes specifies the array of route definitions to be passed to the router
3
+ *
4
+ * Routes are checked in series, and the first matching route is applied.
5
+ * A route definition is as follows:
6
+ * ['METHOD', 'MATCHER', 'OPTIONS']
7
+ *
8
+ * METHOD => crud methods (GET, PUT, POST, DELETE)
9
+ * MATCHER => to be matched against the path. Captured elements will be passed to options. Delegates to express application routing.
10
+ * OPTIONS => an object with parametes deciding how the route will be handled in order of execution:
11
+ * path: => the path to a static file ( index.html f/e)
12
+ * controller: => controller to route the request to. TODO: May implement a resource definition for automatically routing cruds
13
+ * action: => the method to run in the controller. If not specified, the index method will be called.
14
+ * [1..n]: => each numerical definition defines a parameter in which to store the value of the captured elements in the regex.
15
+ * controller, and action are protected names and will apply the cature to controller name and method respectively.
16
+ * f/e: ['get', /\/(home)/, {0: 'controller'}] => routes to home controller
17
+ * ['get, '/\/home\/(5)/, {controller: 'home', 0: 'id'}] => routes to home controller and adds {id: 5} to the params hash.
18
+ */
19
+
20
+ var routes = [
21
+ // Routes the root request to index.html, as well as all other requests to static
22
+ ['get', "/", {controller: 'home'}],
23
+ ];
24
+
25
+ export default routes;
@@ -0,0 +1,48 @@
1
+ // Initializes application before server starts
2
+ // Each of these is REQUIRED
3
+
4
+ import routes from './routes.js';
5
+ import mimes from './mimes.js';
6
+ import db from './db.js';
7
+
8
+ var SERVER_ROOT = import.meta.dirname + '/..';
9
+ var APP_ROOT = SERVER_ROOT + '/server';
10
+
11
+ // Only for reading the certificates for SSL
12
+ import fs from 'node:fs';
13
+ // const fs = require('fs');
14
+ const PRIVATE_KEY_FILE = fs.readFileSync(`${import.meta.dirname}/ssl/key.pem`);
15
+ const CERTIFICATE_FILE = fs.readFileSync(`${import.meta.dirname}/ssl/certificate.pem`);
16
+
17
+ var config = {
18
+ APP_ROOT: APP_ROOT,
19
+ // root directory for delivering static assets
20
+ PUBLIC_ROOT: SERVER_ROOT + '/client',
21
+ CONTROLLERS_ROOT: APP_ROOT + '/controllers',
22
+ VIEWS_ROOT: APP_ROOT + '/views',
23
+ MODELS_ROOT: APP_ROOT + '/models',
24
+ SERVER_ROOT: SERVER_ROOT,
25
+
26
+ ENABLE_HTTP: true,
27
+ //IP: "0.0.0.0",
28
+ PORT: 3333,
29
+
30
+ ASYNC: false,
31
+
32
+ // For HTTPS
33
+ ENABLE_HTTPS: true,
34
+ SSL_PORT: 3334,
35
+ PRIVATE_KEY: PRIVATE_KEY_FILE,
36
+ CERTIFICATE: CERTIFICATE_FILE,
37
+ };
38
+
39
+ // module.exports.routes = require('./routes.js');
40
+ // module.exports.mimes = require('./mimes.js');
41
+ // module.exports.db = require('./db.js');
42
+
43
+ export default {
44
+ config,
45
+ routes,
46
+ db,
47
+ mimes,
48
+ }
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIUR04h3qlfhW5SYQrnm0VjDSLQrwUwDQYJKoZIhvcNAQEL
3
+ BQAwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ4wDAYDVQQKDAVOYWlsczES
4
+ MBAGA1UEAwwJbG9jYWxob3N0MScwJQYJKoZIhvcNAQkBFhhhZG1pbkBwcm9qZWN0
5
+ aW52aWN0YS5jb20wHhcNMjMwODMwMDE1MzUzWhcNMjQwODI5MDE1MzUzWjBnMQsw
6
+ CQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDjAMBgNVBAoMBU5haWxzMRIwEAYDVQQD
7
+ DAlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHByb2plY3RpbnZpY3Rh
8
+ LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALP54rGDg1Lo7FSs
9
+ q4xvvOeisWLJzbTZN+hsxL3ytcxvk3oidVoZDDfkDJ1QBoPFjIyHlJZCvC6mJMeY
10
+ 3Nibn1zZAtsST84DCYS8c0bQAbEUc+OwSmNpVLQElnTAKyoY/7izj579p5uR7WLD
11
+ mSk2c4igeqjOAQn/rrC3Lr+Dr6HA3lcEQD7g87OQz7JCRY6p5E980HO81gknnxod
12
+ veQogbreiQ+MOwC9qPOwfJjAX/qkTWc1SXIiV2SskoIANTbGujMHZZZIaY5a5oWZ
13
+ 9pAKR0basSAjECMmr1/UCKGZeot0AZRKMBSHp6mlHlE5LLFIH56PaRTguSBhsrle
14
+ BWcuUcUCAwEAAaNTMFEwHQYDVR0OBBYEFCigQMRd+cKymXdHgew3JMEcokv0MB8G
15
+ A1UdIwQYMBaAFCigQMRd+cKymXdHgew3JMEcokv0MA8GA1UdEwEB/wQFMAMBAf8w
16
+ DQYJKoZIhvcNAQELBQADggEBAD5ZtQ3XLBzOiJoICcRA0evC/59gt2kKw1owOLJy
17
+ Ji4rtoWCis8nr3R1U62KUENZ//WRy09uNPHfjsaFwuvgO+GWn53Q3breCEO1r2lH
18
+ z5qWUAdb7WpoZWZJdj6wZoJQeKQoK8fVCVNNPNHwhZRK2P2SWhn5v/7Qco5JMP8+
19
+ qpIbAzjKOoHiz1238JYXJ5G1tMVMfVvQpC1E+KM9p9Bohtuc51pYMssT31WPBoOv
20
+ TBcIarZ8ri6VBAh/+aUpce0BqOEtZ1oa6Mnd2w5GeqgtV+G7ir5g0uXZjOFrh5A7
21
+ c6J3QmpeF3kfs+Ggsxh/fRrnK1VDDtWQ/mF/3Jrq43JoP0E=
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,17 @@
1
+ -----BEGIN CERTIFICATE REQUEST-----
2
+ MIICrDCCAZQCAQAwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ4wDAYDVQQK
3
+ DAVOYWlsczESMBAGA1UEAwwJbG9jYWxob3N0MScwJQYJKoZIhvcNAQkBFhhhZG1p
4
+ bkBwcm9qZWN0aW52aWN0YS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
5
+ AoIBAQCz+eKxg4NS6OxUrKuMb7znorFiyc202TfobMS98rXMb5N6InVaGQw35Ayd
6
+ UAaDxYyMh5SWQrwupiTHmNzYm59c2QLbEk/OAwmEvHNG0AGxFHPjsEpjaVS0BJZ0
7
+ wCsqGP+4s4+e/aebke1iw5kpNnOIoHqozgEJ/66wty6/g6+hwN5XBEA+4POzkM+y
8
+ QkWOqeRPfNBzvNYJJ58aHb3kKIG63okPjDsAvajzsHyYwF/6pE1nNUlyIldkrJKC
9
+ ADU2xrozB2WWSGmOWuaFmfaQCkdG2rEgIxAjJq9f1AihmXqLdAGUSjAUh6eppR5R
10
+ OSyxSB+ej2kU4LkgYbK5XgVnLlHFAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEA
11
+ U9LsZPK6UDQJFNCVAwDQszIE8Jt5LsNR/h7/ljp98T2BEW5+i7kPGCF+sIzkafQR
12
+ 1NEKrwq8nAHOoS7cbzTQCtRLHgKQ5edj/dWVEzDmhf07uvq2wc9QmBjw9DIWD9Hd
13
+ 7P4FsOHEp++4h+CupNwLaMrisggsWtVihvqpSJxWt3IzvoqWKldBfIZfR1nf2Tl+
14
+ 2N1taAX+LHWQwzoq5xMMxmtQgabZk5kbeJ2K+NyxP3msjmREsRn0+TWzw9sTU6qu
15
+ 9EZtiW6xje2KlvjSmRP7pvJg17GbtqCHSVWamcHqs/HE69SZhgY/iWJk7eIJhSY3
16
+ /b5srd0URvtlTivyQgsfUg==
17
+ -----END CERTIFICATE REQUEST-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz+eKxg4NS6OxU
3
+ rKuMb7znorFiyc202TfobMS98rXMb5N6InVaGQw35AydUAaDxYyMh5SWQrwupiTH
4
+ mNzYm59c2QLbEk/OAwmEvHNG0AGxFHPjsEpjaVS0BJZ0wCsqGP+4s4+e/aebke1i
5
+ w5kpNnOIoHqozgEJ/66wty6/g6+hwN5XBEA+4POzkM+yQkWOqeRPfNBzvNYJJ58a
6
+ Hb3kKIG63okPjDsAvajzsHyYwF/6pE1nNUlyIldkrJKCADU2xrozB2WWSGmOWuaF
7
+ mfaQCkdG2rEgIxAjJq9f1AihmXqLdAGUSjAUh6eppR5ROSyxSB+ej2kU4LkgYbK5
8
+ XgVnLlHFAgMBAAECggEAJRJufyk7VkszTxfIOGPV0hLhnhs6e6uYyBALkKLbjtJW
9
+ 2vwZFyd8rFCVxpuy09bP5iyRT0hM0gEYJ2MV7qpTr8DlxTFm7eUTQ1u8FRSInKy9
10
+ WGO6VvLd5zzgrwjce03t8uJNza6rJTDwaH0o4ePc9YI08euJLEGV/sGk5/8coOEr
11
+ sdczGdxxumLEew9vwjDbIFuuVr4YHn/qs6h8DzEg595jWBibWxqVx4JvKTAMCmeM
12
+ oLi251i2y3NLoKRd/+MOQ1WW9fLMiA1/cbhICqp3hGCGRv/g71bM0DVPsfmSPwGt
13
+ Jm+Wtv12gmRqfDw5N+hJxAIUiW1CqU9SAZDmrPV+ewKBgQD373V/fBV1x73Mhbsr
14
+ +4IZxmp4CbLeT2aUFMThLfTCfs7zNL4VRfHwSw6n503YNANmBqBq8bKcNQqmTnXH
15
+ EKvc7liSfSn0STLZtrubHkNe5t2TvUUQNOQBENsU0S8nS+ei+E0xJ6wey2TjN23F
16
+ 0CoEbh8/xhH0hoLT3B3GcAwNtwKBgQC51IjKPdlo1jmIUjNcGz76SpcMowkWp0+s
17
+ qAEh0ksSCh1Pn4G+YhgoFmFcUahwkyP2CmAtHUrL+atw4b22/jHiJN/IfyhUPP31
18
+ 0ereRpi33m2dImz6PzistyM0jPdMAKz+W2wEBmOF6Z78MgaxUZm3s0CeXGYkzWoH
19
+ iLQGJyMcYwKBgQDjtusTy8NqCaooziq6mqVDRxlCZqYByKtOFkU9DBhhClbIyQhM
20
+ QZGUQVuUmrzEdgEpE60CjDqffZfqZuWFj6pJoB95a7u8wf4SN+LW9VSrNR8NMijc
21
+ WbePwwt0cyv7y5tT8vnyy50qK2Tdy2rm4+mzZ/ELgb+79k7yhphSSVbIwQKBgC1u
22
+ LjrzP/GHXe1b2z6LUqwyDBeEzDYDlVDqicxQ8xVn756Fqlx28tzqC8dcF0feUQ5X
23
+ nweof566XRVtusm//0YAKc2EeMGPX673MOpCbBeXg0jFH8tWJW7kHvE7/UFRcPmG
24
+ NDQPs8kLQlj5ifVTs7bbVdLhV/9rUJ6i5xASBV1tAoGAAess1DjK1jnX+v6h0/OP
25
+ GFgg2cFB1ZarAstYHgLrLu+1Iuj9RDuTNwyiQDwT8gbz4i43o4zWE0NhQwlhJ84K
26
+ EY5BgS8a7sILoZjo+Mfd06bQy0AhgmYtW8mojh9/9vfg42mE2bIlSVLnbWnSkvID
27
+ jTFVReA7tpBS7h/Q6rW2hM8=
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,30 @@
1
+ -----BEGIN ENCRYPTED PRIVATE KEY-----
2
+ MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIcpza33KNpC0CAggA
3
+ MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBH4EXXxNpaRGmSXdx4SZI9BIIE
4
+ 0OiJGDq7wPbvMDc41zoOOD9dKozvlWJ6I7SXehwFmUrQFQSFyT9NiIw9bhnzQxnL
5
+ F8osKdEHAknXKFVEVG4q64fDOiyaUojsBUavuUC1HG9MU9tBJ+gt118LYFTr0zrG
6
+ WlFOl/p8kpwtAwrI+qRIrWFADzZExp2vX2b5qnapj9f/26BdjRTJvZtjDC10mBAJ
7
+ UYoCAPyjtIOiBmkCQUCtwHJywpMLFZlGyrg+8WiTk2vW3vz+D5KWBYXb9BaLFTu+
8
+ E/oeHJH30NDZewhlgi5vUjYE36fXi9TGaz8Zcron4wTUrtrAbV7bTWv8t0AnY7wp
9
+ aM8zpsaULZ4XK0xSSA0LYRYYj5EYiYAv3OpQE/cjzRD6pbaAIzifRpsgLSh3UAp5
10
+ 45OqzbA3/JkrdsANGspUkrb/x3O6sSg6vgz/ocSlzRaiGcJ0qkFSETcHUCvpWSZD
11
+ ltOLsYckgtFpcEzST+HG+hqORNoe4Sx/moJgMOfvlThr32GImj8wgi/czXze85bO
12
+ v3HYffLxoQIfaz8XpYmcAfUgw3PMRTfPj5+pqmKXtRmemUHPNIDVFOD0eQWI61af
13
+ og4f2OO0c0abELI7V5OlNrqWzAKoV1HtszedffPHNE5eJ+ENbbp68sFKmFLjZzOh
14
+ GwhHkauaG9OW0F/wS03fJQdEMVXc8vvW8NAU3438o85Por0fiFfSgJ3Z9281IHBJ
15
+ rEJ0nuqDCXJorX/On17qTF7EaXLzidpobdQ4vTg4N+/Q5l+Ep5zYby8Oiu/Hl618
16
+ T7R4s3r4ceUHAJeyDli8C7fw761Qwd73qpB9RgbHY5HVZUALNk+TG4aS7kwcZ7CT
17
+ MW6/PR+6RkMrwAPsfZwJnErzcrmhodxP3HRP0ikAfX9qbK8n8TIDt7Lb4WIZpqKu
18
+ vGNnGScnBVmaGfrbqk6WeK9iAH3XXGYWcsGOFwxPYMl0YymW/MThDS+eIqJhqI4Z
19
+ a2mjB/w6g5ANX5YOMbTWqjnsYdqobPRDPN5PEk1wWCYGZq9Hwbt0bHi1bKev/itw
20
+ RyK60j25fsVf8RDkrMFaCgP/x/6iMl26TCi3R3W4cW5NlesxWYwNcOxnUwL7OQQT
21
+ 8aY1iR/Cn/RoRiZ90D4anCOTYLPX6pTHAPsTHBuU+odAUhXBGvIhSknvCf3xhahW
22
+ hUY1yUnEYhgXbYLRCEsa7q48BoSFMibmwbt07YRJXNAGjgcc7bzCV43vc/GeUgdZ
23
+ RrS1GNuzO0+S1TfvxfMBNBpoPbkeY2yHlUr+A8j6KHQw5mr3GnoOoeQTdZYK594m
24
+ N6J/gxF1emQqJoP+i+mx7iSdf5i2DmV9ACl/tyU92PKocIcsYoIevSmhtliBnsdG
25
+ R1kPkoUWuEVZujxzlIXcj0vEtOxyKJmzlBXKKO7B8U4HociBNMM41acX9WsIYdsA
26
+ QFjZTyU2DkpOCPRcBFbgQFPwfrkC93hndiByWPCkmAjeHJ0O74fnBCUP5BhmFuuc
27
+ /L0WWAVKp8HGgFmiq+i+rznJZEEEEoZClDFNkOBp4yfGZL9yZ2Ot3IRb2HNIJaj1
28
+ 69CX7ukHVHPLgiOcRSbFyuZZyqO++kWgEQm5jKlFFqGyFNpHmkGL8CGFlq7x9sF7
29
+ ONozML/sxGNw4Ubo6TAPflvl7KOd9bcYJdpODqtJgngi
30
+ -----END ENCRYPTED PRIVATE KEY-----
@@ -0,0 +1,9 @@
1
+ ---- BEGIN SSH2 PUBLIC KEY ----
2
+ Comment: "2048-bit RSA, converted by stantonwjones@darkmatter.lan from"
3
+ AAAAB3NzaC1yc2EAAAADAQABAAABAQDPJQsK/daFi/b+7bOSEJcKdzjvNJygX3BvMQ4HY+
4
+ JJaiSDyQgtwc8K85XDH0/eWyu5a6OzbadU3SkSdYP+0+uTdxfxRUCChKoASIoAaAfwB/BW
5
+ WOIdsuGPhJjYiLnPL4SScFdjUbJXGP5JOSQ6wgsRdqsDeQezUjF0CvR1CXoJaqRQt7p5T9
6
+ TlRzzuhN5Vf6BDpXBPTcNyUGKCaUwGQn2QmpXzRXrAZNb7XpzBSXdpUWm9W7U9zCFHva7J
7
+ XCuXsC9yMy3w1mpbL+oFBx7Wvic5FqwnATXjM7xBSqcG4tYzrISyn5pj13cIzzk9aEPRI3
8
+ qhV6kiA62JofiX1RkxMP+j
9
+ ---- END SSH2 PUBLIC KEY ----
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "nails_app",
3
+ "version": "0.0.0",
4
+ "description": "A basic nails application",
5
+ "main": "server.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1",
9
+ "start": "node server.js"
10
+ },
11
+ "author": "",
12
+ "license": "BSD",
13
+ "bugs": {
14
+ "url": "https://github.com/stantonwjones/nails-boilerplate/issues"
15
+ },
16
+ "config": {
17
+ "mongodbMemoryServer": {
18
+ "version": "latest"
19
+ }
20
+ },
21
+ "dependencies": {
22
+ }
23
+ }
@@ -0,0 +1,21 @@
1
+ import nails from "../../../../../index.js";
2
+ import Dog from "../models/dog.js";
3
+ import Owner from "../models/owner.js";
4
+
5
+ export default class DefaultJsonController extends nails.Controller {
6
+ json = true;
7
+ routes = [
8
+ ['get', '/listowners'],
9
+ ['get', '/listowneddogs'],
10
+ ];
11
+
12
+ async listowners(params, request, response) {
13
+ return await Owner.findAll();
14
+ }
15
+
16
+ async listowneddogs(params, request, response) {
17
+ // await nails._dbConnector.afterInitialization();
18
+ // await Dog.sync({alter: true});
19
+ return await Dog.findAll();
20
+ }
21
+ }
@@ -0,0 +1,39 @@
1
+ export default function HomeController() {
2
+ this.index = function(params, request, response) {
3
+ console.log("HOME::INDEX");
4
+ response.json({
5
+ home_index: true
6
+ });
7
+ };
8
+ this.testaction = function(params, request, response) {
9
+ response.json({
10
+ home_testaction: true
11
+ });
12
+ }
13
+ this.test_ejs = function() {
14
+ };
15
+ /*
16
+ this.public_index = function(params, request, response) {
17
+ response.public({path: 'index.html'});
18
+ };
19
+ this.json = function(params, request, response) {
20
+ response.json({test: 'json'});
21
+ };
22
+ // By setting a method to asynchronous, Nails will wait for an
23
+ // explicit response to the client. Otherwise, it will attempt
24
+ // to respond with a view immediately after the action terminates.
25
+ this.json.async = true;
26
+
27
+ this.test_model = function(params, request, response) {
28
+ var u = new User();
29
+ u.set('created_at', (new Date()).getTime());
30
+ u.save();
31
+ response.json({new_user_id: u.id.toString()});
32
+ };
33
+ this.test_id_template = function(params, request, response) {
34
+ var varz = {};
35
+ varz.id = params.id || "no id set";
36
+ response.render('test_id', varz);
37
+ };
38
+ */
39
+ }
@@ -0,0 +1,7 @@
1
+ import nails from '../../../../../index.js';
2
+ import { DataTypes } from 'sequelize';
3
+ const dogSchema = {
4
+ good: DataTypes.BOOLEAN,
5
+ name: DataTypes.STRING,
6
+ };
7
+ export default class Dog extends new nails.Model("Dog", dogSchema) {};
@@ -0,0 +1,10 @@
1
+ import nails from '../../../../../index.js';
2
+ import { DataTypes } from 'sequelize';
3
+ import Dog from './dog.js';
4
+ const ownerSchema = {
5
+ name: DataTypes.STRING,
6
+ };
7
+ class Owner extends new nails.Model("Owner", ownerSchema) {};
8
+ Owner.hasMany(Dog);
9
+ await Dog.sync();
10
+ export default Owner;
@@ -0,0 +1,15 @@
1
+ /* jshint esversion: 6 */
2
+ var React = require('react');
3
+
4
+ class TestReact extends React.Component {
5
+ render() {
6
+ return (
7
+ <html>
8
+ <head><title>react</title></head>
9
+ <body>react works!</body>
10
+ </html>
11
+ );
12
+ }
13
+ }
14
+
15
+ module.exports = TestReact;
@@ -0,0 +1,9 @@
1
+ // var nails = require('../../../index.js');
2
+ import nails from '../../../index.js';
3
+ import service_config from './config/service.js';
4
+
5
+ // See self-documented config files
6
+ // var service_config = require('./config/service.js');
7
+ // console.log("starting server")
8
+ (await nails( service_config )).startServer();
9
+ export default nails; // export nails for testing
@@ -0,0 +1,67 @@
1
+ import * as chai from 'chai';
2
+ import { default as chaiHttp, request } from "chai-http";
3
+ // import chaiHttp from 'chai-http';
4
+ import { assert } from 'chai';
5
+ // import { WebSocket } from 'ws';
6
+ import WebSocket from 'ws';
7
+ // const WebSocket = require('ws');
8
+
9
+ var express_app;
10
+ // const {MongoMemoryServer} = require('mongodb-memory-server');
11
+ let mongod = null;
12
+
13
+ // Configure chai
14
+ chai.use(chaiHttp);
15
+ chai.should();
16
+
17
+ describe("Integration", function () {
18
+ before(async function () {
19
+ try {
20
+ var nails = (await import('./services/integration_sequelize/server.js')).default;
21
+ } catch (e) {
22
+ console.log("could not import server");
23
+ console.log(e);
24
+ }
25
+ console.log("got here");
26
+ express_app = nails.application;
27
+ return new Promise((resolve, reject) => {
28
+ nails.events.on("ready", () => {
29
+ console.log("ready was emitted!");
30
+ resolve();
31
+ });
32
+ });
33
+ });
34
+ describe("GET /", function () {
35
+ it('should return the expected JSON from index', function (done) {
36
+ request.execute(express_app)
37
+ .get('/')
38
+ .end((err, res) => {
39
+ res.should.have.status(200);
40
+ assert(res.text == JSON.stringify({ home_index: true }));
41
+ done();
42
+ });
43
+ });
44
+ });
45
+ describe("/listowners", function() {
46
+ it('should return an empty array if no owners', function(done) {
47
+ request.execute(express_app)
48
+ .get('/listowners')
49
+ .end((err, res) => {
50
+ res.should.have.status(200);
51
+ assert(JSON.parse(res.text).length == 0);
52
+ done();
53
+ });
54
+ })
55
+ })
56
+ describe("/listowneddogs", function() {
57
+ it('should return an empty array if no owned dogs', function(done) {
58
+ request.execute(express_app)
59
+ .get('/listowneddogs')
60
+ .end((err, res) => {
61
+ res.should.have.status(200);
62
+ assert(JSON.parse(res.text).length == 0);
63
+ done();
64
+ });
65
+ })
66
+ })
67
+ });
@@ -19,7 +19,7 @@ var config = {
19
19
  PUBLIC_ROOT: SERVER_ROOT + '/public',
20
20
  CONTROLLERS_ROOT: APP_ROOT + '/controllers',
21
21
  VIEWS_ROOT: APP_ROOT + '/views',
22
- //MODELS_ROOT: APP_ROOT + '/models',
22
+ MODELS_ROOT: APP_ROOT + '/models',
23
23
  SERVER_ROOT: SERVER_ROOT,
24
24
 
25
25
  ENABLE_HTTP: true,
package/lib/model.js DELETED
@@ -1,167 +0,0 @@
1
- // This is the base definition for a model / collection
2
- // ideally used as a wrapper for database integration
3
- // should use promise objects to allow for method chaining
4
- // eventful. emits ready event passing itself
5
- // start with mongodb
6
- import util from 'util';
7
- import controller_base from './controller.js';
8
- // var controller_base = require('./controller.js');
9
- // var util = require('util');
10
-
11
- /** TODO: what persistence methods does a model need?
12
- * save/post => saves record to db
13
- * fetch/get => updates model from database
14
- * patch/put(?) => only changes specific methods and saves to database...
15
- * destroy/delete => remove model from db
16
- *
17
- ** On Constructor:
18
- *
19
- * get => get a single model by id
20
- * find => get a collection of models by parameters
21
- */
22
- /** TODO: define a collection
23
- *
24
- * will likely want to put collection constructor as attribute on Model
25
- * f/e Model.Collection
26
- *
27
- ** Persistence methods:
28
- *
29
- * save/post => save collection in database by batch command
30
- * will want to minimize number of db requests, but can probably
31
- * start with saving each individually for now
32
- * fetch/get => updates collection from database
33
- * a collection should have a saved query attribute which
34
- * was used to get the collection. Will make updating easy.
35
- */
36
-
37
- // init references to model base objects for use by controllers
38
- // and models
39
- controller_base.prototype.models = {};
40
- Model.prototype.models = {};
41
-
42
- var model_prot = Model.prototype;
43
- var db;
44
-
45
- var NAME_REQUIRED_ERROR = function() {
46
- return new Error(
47
- 'FATAL ERROR::: Named function required for Model constructor method'
48
- );
49
- }
50
-
51
- export default function Model(){
52
- };
53
-
54
- Model.extend = function(constructor) {
55
- //console.log('extending', constructor.name);
56
- if ( !constructor.name ) throw NAME_REQUIRED_ERROR();
57
- //model_proto = model_proto || new Model();
58
- constructor.prototype.__proto__ = model_prot;
59
-
60
- // TODO: bind collection-specific methods to the constructor
61
- //Model.set_db_access_methods(contructor);
62
-
63
- // make models available to controller and other models
64
- Model.prototype.models[constructor.name] = constructor;
65
- controller_base.prototype.models[constructor.name] = constructor;
66
-
67
- };
68
- Model.set_connector = function(DBConnector, config) {
69
- if (!config) {
70
- this.prototype.connector = DBConnector;
71
- } else {
72
- this.prototype.connector = new DBConnector(config);
73
- }
74
- };
75
- Model.set_db_access_methods = function(constructor) {
76
- constructor.find = Model.find;
77
- };
78
- Model.find = function() {
79
- var args = Array.prototype.slice.call(arguments, 0);
80
- return this.connector.find.apply(connector, args);
81
- };
82
-
83
- Object.defineProperty(Model.prototype, 'id', {
84
- get: function() {
85
- return this.attributes[this.id_attribute];
86
- },
87
- set: function(new_val) {
88
- this.set(this.id_attribute, new_val);
89
- return new_val;
90
- }
91
- });
92
- Object.defineProperty(Model.prototype, 'attributes', {
93
- get: function() {
94
- if (!this._attributes) this._attributes = {};
95
- return this._attributes;
96
- },
97
- set: function(new_val) {
98
- if (typeof new_val != 'object' && util.isArray(new_val))
99
- throw 'Model#attributes cannot be set to non-object or array value';
100
- this._extend_deeply(this.attributes, new_val, true);
101
- return this.attributes;
102
- }
103
- });
104
- Model.prototype.id_attribute = '_id';
105
- Model.prototype.is_model = true;
106
- /**
107
- * returns the name of the collection or table in the db.
108
- * override this by setting collection attribute on the model.
109
- */
110
- Model.prototype._collection_name = function() {
111
- return this.collection || this.constructor.name;
112
- };
113
- /**
114
- * pointer to the database connector
115
- */
116
- Model.prototype.connector = {};
117
-
118
- Model.prototype.save = function() {
119
- // this should create the model if it does not exist
120
- // (uses an id to check existence)
121
- // or it should update the model
122
- if (this.id) return this.connector.put(this);
123
- return this.connector.post(this);
124
- };
125
- Model.prototype.fetch = function() {
126
- if (!this.id) throw 'cannot fetch model with id: ' + this.id.toString();
127
- return this.connector.get(this);
128
- // TODO: give model backbone-like sync event
129
- };
130
- /*
131
- Model.prototype.patch = function() {
132
- // should try to update the model's changed attributes if no
133
- // arguments given. Otherwise should attempt to set attributes
134
- // on model and then update
135
- Model.connector.update(this);
136
- };
137
- */
138
- Model.prototype.destroy = function() {
139
- // should delete the model from the database if it has been
140
- // persisted
141
- if (this.id) return false;
142
- this.connector.delete(this);
143
- };
144
- Model.prototype.set = function(attr, val) {
145
- this.attributes[attr] = val;
146
- };
147
- /**
148
- * merge a hash of attributes into the current set
149
- */
150
- Model.prototype._merge_attributes = function(attr) {
151
- this._extend_deeply(this.attributes, attr);
152
- };
153
- Model.prototype._extend_deeply = function(obj0, obj1, should_prune) {
154
- if (typeof obj0 != 'object' || typeof obj1 != 'object' ||
155
- util.isArray(obj0) || util.isArray(obj1))
156
- throw 'Attempting to extend a non-object entity';
157
- for(var key in obj1) {
158
- if (typeof obj0[key] == 'object' && typeof obj1[key] == 'object' && !util.isArray(obj0[key]))
159
- this._extend_deeply(obj0[key], obj1[key], should_prune);
160
- else obj0[key] = obj1[key];
161
- }
162
- if (!should_prune) return;
163
- for (key in obj0) {
164
- if (key in obj1) continue;
165
- delete obj0[key];
166
- }
167
- };
@@ -1,100 +0,0 @@
1
- // TODO: multiple async requests here... need to
2
- // consider how this will be used by the models
3
- import {EventEmitter} from 'node:events';
4
- // var EventEmitter = require('events').EventEmitter;
5
- // const MongoClient = require('mongodb').MongoClient;
6
- import { MongoClient } from 'mongodb';
7
-
8
- export default MongoDBConnector;
9
-
10
- // TODO: need to deal with clustered databases...
11
-
12
- MongoDBConnector.prototype.__proto__ = EventEmitter.prototype;
13
- function MongoDBConnector(config) {
14
- EventEmitter.call(this);
15
- var url = config.url || 'mongodb://localhost';
16
- var port = config.port || '27017';
17
- var database = config.database || 'nails';
18
- var uri =
19
- config.uri ? config.uri : `${url}:${port}/${database}`;
20
- this.exec_once_connected = [];
21
- var that = this;
22
- MongoClient.connect(uri)
23
- .then(client => {
24
- this._client = client;
25
- this._db = client.db(database);
26
- this.emit("connected");
27
- }).catch(error => {
28
- // TODO: better handling of the failed connection
29
- console.error(error);
30
- throw error;
31
- });
32
- }
33
-
34
- /**
35
- * Need to implement these methods for a connector to work
36
- */
37
- // maybe use rest methods as names for any database connector used...
38
- MongoDBConnector.prototype.post = function(model_or_collection) {
39
- if (model_or_collection.is_model)
40
- return this._post_one(model_or_collection._collection_name(),
41
- model_or_collection.attributes);
42
- }
43
- MongoDBConnector.prototype._post_one = function(collection_name, doc_attributes, callback) {
44
- return this._db.collection(collection_name).insert(doc_attributes);
45
- }
46
- MongoDBConnector.prototype._post_many = function(collection) {
47
- return this._db.collection(collection.name())
48
- .save(collection.model_attributes());
49
- }
50
-
51
- // update a record in the collection
52
- MongoDBConnector.prototype.put = function(model_or_collection) {
53
- if (model_or_collection.is_model)
54
- return this._put_one(
55
- model_or_collection._collection_name(),
56
- model_or_collection.attributes);
57
- }
58
- MongoDBConnector.prototype._put_one = function(collection_name, doc) {
59
- // TODO: replacing document completely is sow
60
- // will want to only send changed attr
61
- // TODO: write concerns?
62
- return this._db.collection(collection_name).replaceOne({_id: doc._id}, doc);
63
- }
64
- /**
65
- * _put_many will call _update on each individual object in collection
66
- * if that object has changed
67
- */
68
- MongoDBConnector.prototype._put_many = function(collection) {
69
- }
70
-
71
- // return a single record from a collection
72
- // or a collection of records if requested...
73
- // if a model or collection is passed,
74
- MongoDBConnector.prototype.get = function(model_or_collection) {
75
- if (model_or_collection.is_model)
76
- return this._get_one(model_or_collection._collection_name(), model_or_collection.id, null)
77
- .then(doc => this._on_doc_response(model_or_collection, doc));
78
- }
79
- MongoDBConnector.prototype._get_one = function(collection_name, id, options) {
80
- options = options || {};
81
- return this._db.collection(collection_name).findOne(id, options);
82
- }
83
- MongoDBConnector.prototype._get_many = function(collection) {
84
- return this._db.collection(collection.name()).find({
85
- _id: collection.collect('_id')});
86
- }
87
-
88
- // delete a record from a collection
89
- MongoDBConnector.prototype.delete = function(model) {
90
- return this._db.collection(model.collection_name())
91
- .remove(model.attributes._id);
92
- }
93
- // MongoDBConnector.prototype._delete_one
94
- // MongoDBConnector.prototype._delete_many
95
-
96
- MongoDBConnector.prototype._on_doc_response = function(model_or_collection, doc) {
97
- // move this to the promise catch block: if (err) return console.log('error retrieving from', collection_name, '\n', err);
98
- delete doc._id;
99
- model_or_collection._merge_attributes(doc);
100
- }
@@ -1,88 +0,0 @@
1
- // TODO: multiple async requests here... need to
2
- // consider how this will be used by the models
3
- import { EventEmitter } from 'events';
4
- import DBClient from 'node:sqlite';
5
- // var EventEmitter = require('events').EventEmitter;
6
- // const DBClient = require('sqlite3');
7
- import test from 'node:assert';
8
- // const test = require('assert');
9
-
10
- module.exports = SQLite3Connector;
11
-
12
- // TODO: need to deal with clustered databases...
13
-
14
- SQLite3Connector.prototype.__proto__ = EventEmitter.prototype;
15
- function SQLite3Connector(config) {
16
- EventEmitter.call(this);
17
- var url = config.url || 'mongodb://localhost';
18
- var port = config.port || '27017';
19
- var database = config.database || 'nails';
20
- this.exec_once_connected = [];
21
- this._db = new DBClient.Database(config.filename);
22
- }
23
-
24
- /**
25
- * Need to implement these methods for a connector to work
26
- */
27
- // maybe use rest methods as names for any database connector used...
28
- SQLite3Connector.prototype.post = function(model_or_collection) {
29
- if (model_or_collection.is_model)
30
- this._post_one(model_or_collection._collection_name(),
31
- model_or_collection.attributes);
32
- }
33
- SQLite3Connector.prototype._post_one = function(collection_name, doc_attributes, callback) {
34
- this._db.collection(collection_name).insert(doc_attributes);
35
- }
36
- SQLite3Connector.prototype._post_many = function(collection) {
37
- this._db.collection(collection.name())
38
- .save(collection.model_attributes());
39
- }
40
-
41
- // update a record in the collection
42
- SQLite3Connector.prototype.put = function(model_or_collection) {
43
- if (model_or_collection.is_model)
44
- this._put_one(model_or_collection._collection_name(), model_or_collection.attributes);
45
- }
46
- SQLite3Connector.prototype._put_one = function(collection_name, doc) {
47
- // TODO: replacing document completely is sow
48
- // will want to only send changed attr
49
- // TODO: write concerns?
50
- this._db.collection(collection_name).update({_id: doc._id}, doc);
51
- }
52
- /**
53
- * _put_many will call _update on each individual object in collection
54
- * if that object has changed
55
- */
56
- SQLite3Connector.prototype._put_many = function(collection) {
57
- }
58
-
59
- // return a single record from a collection
60
- // or a collection of records if requested...
61
- // if a model or collection is passed,
62
- SQLite3Connector.prototype.get = function(model_or_collection) {
63
- if (model_or_collection.is_model)
64
- this._get_one(model_or_collection._collection_name(), model_or_collection.id, null,
65
- this._on_doc_response.bind(model_or_collection));
66
- }
67
- SQLite3Connector.prototype._get_one = function(collection_name, id, options, callback) {
68
- options = options || {};
69
- this._db.collection(collection_name).findOne(id, options, callback);
70
- }
71
- SQLite3Connector.prototype._get_many = function(collection) {
72
- return this._db.collection(collection.name()).find({
73
- _id: collection.collect('_id')});
74
- }
75
-
76
- // delete a record from a collection
77
- SQLite3Connector.prototype.delete = function(model) {
78
- return this._db.collection(model.collection_name())
79
- .remove(model.attributes._id);
80
- }
81
- // SQLite3Connector.prototype._delete_one
82
- // SQLite3Connector.prototype._delete_many
83
-
84
- SQLite3Connector.prototype._on_doc_response = function(err, doc) {
85
- if (err) return console.log('error retrieving from', collection_name, '\n', err);
86
- delete doc._id;
87
- this._merge_attributes(doc);
88
- }
@@ -1,95 +0,0 @@
1
- import assert from 'assert';
2
- import Model from '../lib/model.js';
3
- import MongoDBConnectorUtil from './mongodb_connector.util.js';
4
-
5
- var test_model = new Model();
6
- var model_prot = Model.prototype;
7
- describe('Model', function() {
8
- var util;
9
- beforeEach(function(done) {
10
- util = new MongoDBConnectorUtil();
11
- util.getTestConnector().then(connector => {
12
- Model.set_connector(connector);
13
- connector.on("connected", done);
14
- });
15
- });
16
- afterEach(function(done) {
17
- util.cleanup().then(() => done());
18
- });
19
- describe('#_merge_attributes', function() {
20
- });
21
- describe('#_extend_deeply', function() {
22
- var attr0;
23
- var attr1;
24
- beforeEach(function() {
25
- attr0 = {a:7, b:'test', c:null, o: {}};
26
- attr1 = {a:8, c:'test0', o: {a:0}};
27
- });
28
- it('should rewrite non object attributes', function() {
29
- model_prot._extend_deeply(attr0, attr1);
30
- // these should change
31
- assert(attr0.a == attr1.a);
32
- assert(attr0.c == attr1.c);
33
- // these should not
34
- assert(attr0.b == attr0.b);
35
- assert(attr0.o == attr0.o);
36
- });
37
- it('should merge two attributes if they are both non-array objects',
38
- function() {
39
- model_prot._extend_deeply(attr0, attr1);
40
- assert(attr0.o.a == attr1.o.a);
41
- });
42
- it('should delete attributes not present in obj1 if prune is true',
43
- function() {
44
- model_prot._extend_deeply(attr0, attr1, true);
45
- assert(!('b' in attr0));
46
- });
47
- it('should not delete attributes absent present in obj1 if prune is falsey', function() {
48
- model_prot._extend_deeply(attr0, attr1);
49
- assert(attr0.o.a == attr1.o.a);
50
- });
51
- });
52
- describe('#save', function() {
53
- it('should save a new model to the database and update id',
54
- async function() {
55
- var model0 = new Model();
56
- var model_name = 'testname0';
57
- model0.attributes = {
58
- name: model_name
59
- };
60
- await model0.save();
61
- assert.ok(model0.attributes._id);
62
- assert.ok(model_name == model0.attributes.name);
63
- });
64
- it('should save changes to an existing model to the database',
65
- async function() {
66
- var model0 = new Model();
67
- model0.attributes = {
68
- name: 'testname1'
69
- };
70
- await model0.save();
71
- model0.set('x', 5);
72
- await model0.save();
73
- var model1 = new Model();
74
- model1.id = model0.id;
75
- await model1.fetch();
76
- assert.ok(model1.attributes.x == 5);
77
- });
78
- });
79
- describe('#fetch', function() {
80
- it('should retrieve attributes for this model id from the database',
81
- async function() {
82
- var model0 = new Model();
83
- model0.set('x', 7);
84
- await model0.save();
85
- var model1 = new Model();
86
- model1.id = model0.id;
87
- await model1.fetch();
88
- assert.ok(model1.attributes.x == 7);
89
- });
90
- });
91
- describe('#attributes', function() {
92
- it('should be a plain object');
93
- it('should not change by reference if set to a different attributes hash');
94
- });
95
- });
@@ -1,66 +0,0 @@
1
- import assert from 'assert';
2
- import MongoDBConnectorUtil from './mongodb_connector.util.js';
3
-
4
- describe('MongoDBConnector', function() {
5
- var util;
6
- var mdbc;
7
- beforeEach(function(done) {
8
- util = new MongoDBConnectorUtil();
9
- util.getTestConnector().then(connector => {
10
- mdbc = connector;
11
- connector.on("connected", done);
12
- });
13
- });
14
- afterEach(function(done) {
15
- util.cleanup().then(() => done());
16
- });
17
- it('should create a new connection to mongodb', function(done) {
18
- assert.notEqual(mdbc._db, null);
19
- done();
20
- });
21
- describe('#put', function() {
22
- it('should be ok, updating the record in the database');
23
- });
24
- describe('Document retrieval', function() {
25
- describe('#get', function() {
26
- it('should return a single document when model is passed');
27
- it('should return an array of docments when collection is passed');
28
- });
29
- describe('#_get_one', function() {
30
- it('should return a single document with the matching _id', async function() {
31
- var test_model = get_test_model('custom0');
32
- var test_attr = test_model.attributes;
33
- await mdbc._post_one(test_model.collection_name(), test_attr);
34
- let doc = await mdbc._get_one(test_model.collection_name(),
35
- test_model.attributes._id, null);
36
- assert.ok(doc.custom_attr == test_attr.custom_attr);
37
- assert.ok(doc._id.equals(test_attr._id));
38
- return null;
39
- });
40
- });
41
- describe('#_get_many', function() {
42
- it('should return all documents matching the collection._query field');
43
- });
44
- });
45
- describe('Document Creation', function(){
46
- describe('#_post_one', function() {
47
- it('should set an _id attribute on the given attributes hash', function(done) {
48
- var test_model = get_test_model();
49
- mdbc._post_one(test_model.collection_name(), test_model.attributes)
50
- .then(() => {
51
- assert.ok(test_model.attributes._id);
52
- done();
53
- });
54
- });
55
- });
56
- });
57
- });
58
- function get_test_model(custom_attr) {
59
- return {
60
- collection_name: function() {return 'test_model'},
61
- attributes: {
62
- x: 'x',
63
- custom_attr: custom_attr
64
- }
65
- }
66
- }