nails-boilerplate 1.0.0 → 1.1.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/bin/lib/init.js CHANGED
@@ -2,9 +2,7 @@
2
2
  // to the path
3
3
  import path from 'node:path';
4
4
  import fs from 'node:fs';
5
- // TODO: wrench is deprecated. check out node-fs-extra
6
- import wrench from 'wrench';
7
- // var wrench = require('wrench');
5
+ import {copySync} from 'fs-extra/esm';
8
6
  import {exec} from 'child_process';
9
7
  // var exec = require('child_process').exec;
10
8
  var args = process.argv.slice(2);
@@ -51,12 +49,12 @@ function createApp( name ) {
51
49
  fs.writeFileSync(name + '/NAILS', '/* This marks the root of the NAILS app */');
52
50
  fs.closeSync(fd);
53
51
 
54
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './server'), name + '/server');
55
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './client'), name + '/client');
56
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './config'), name + '/config');
57
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './common'), name + '/common');
58
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './spec'), name + '/spec');
59
- wrench.copyDirSyncRecursive(path.resolve(templateRoot, './bin'), name + '/bin');
52
+ copySync(path.resolve(templateRoot, './server'), name + '/server');
53
+ copySync(path.resolve(templateRoot, './client'), name + '/client');
54
+ copySync(path.resolve(templateRoot, './config'), name + '/config');
55
+ copySync(path.resolve(templateRoot, './common'), name + '/common');
56
+ copySync(path.resolve(templateRoot, './spec'), name + '/spec');
57
+ copySync(path.resolve(templateRoot, './bin'), name + '/bin');
60
58
 
61
59
  checkWrites();
62
60
  });
@@ -0,0 +1,11 @@
1
+ export default class DbConnector {
2
+ async connect() {
3
+ throw 'DbConnector#connect not implemented'
4
+ }
5
+ generateModelSuperclass() {
6
+ throw 'GenerateModelSuperclass not implemented'
7
+ }
8
+ async afterInitialization() {
9
+ console.warn("DbConnector#afterInitialization not implemented");
10
+ }
11
+ }
@@ -1,7 +1,8 @@
1
1
  // const mongoose = require('mongoose');
2
2
  import mongoose from 'mongoose';
3
+ import DbConnector from './database_connector.js';
3
4
 
4
- class MongooseDbConnector {
5
+ class MongooseDbConnector extends DbConnector{
5
6
  async connect(options) {
6
7
  if (options.uri) {
7
8
  this.connection = await mongoose.createConnection(options.uri/*, mongooseOptions*/).asPromise();
package/lib/nails.js CHANGED
@@ -84,6 +84,8 @@ async function configure( app_config ) {
84
84
  console.log("Generating model superclass...");
85
85
  await DBConnector.connect(app_config.db);
86
86
  ModelV2.setConnector(DBConnector);
87
+ init_models_v2(app_config.config.MODELS_ROOT);
88
+ DBConnector.afterInitialization();
87
89
  } else {
88
90
  console.log("Instantiating DBConnector...");
89
91
  // Try to instantiate DBConnector
@@ -166,6 +168,27 @@ async function init_app_lib(superclass, abs_path) {
166
168
  });
167
169
  }
168
170
 
171
+ async function init_models_v2(abs_path) {
172
+ if (!fs.existsSync(abs_path))
173
+ return console.log('Cannot initialize. Path not found.', abs_path);
174
+ if (fs.statSync(abs_path).isFile()) {
175
+ console.log('attempting to import:', abs_path);
176
+ // We just need to import each model once so the generateSuperclass
177
+ // method is called at least once for each model.
178
+ let modelClass = (await import(abs_path)).default;
179
+ console.log('imported model:', modelClass.name);
180
+ // // Constructor function was provided
181
+ // if (!superclass.isPrototypeOf(subclass))
182
+ // return superclass.extend(subclass);
183
+ // ES6 Class was provided
184
+ return;
185
+ }
186
+ const directory_contents = fs.readdirSync(abs_path);
187
+ for (const rel_path of directory_contents) {
188
+ await init_models_v2(path.join(abs_path, rel_path));
189
+ };
190
+ }
191
+
169
192
  // retrieves the connector object. If cannot
170
193
  // require the module with the same name,
171
194
  // try grabbing connector from lib
@@ -0,0 +1,25 @@
1
+ import DbConnector from './database_connector.js';
2
+ import { Sequelize } from 'sequelize';
3
+ // const { Sequelize } = require('sequelize');
4
+
5
+ export default class SequelizeConnector extends DbConnector {
6
+ sequelize;
7
+
8
+ async connect(options) {
9
+ this.sequelize = new Sequelize(options.address);
10
+ try {
11
+ await this.sequelize.authenticate();
12
+ console.log('Connection has been established successfully.');
13
+ } catch (error) {
14
+ console.error('Unable to connect to the database:', error);
15
+ }
16
+ }
17
+
18
+ generateModelSuperclass(name, options) {
19
+ return this.sequelize.define(name, options);
20
+ }
21
+
22
+ async afterInitialization() {
23
+ this.sequelize.sync({alter: true});
24
+ }
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nails-boilerplate",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A node.js webserver scaffold",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -31,14 +31,16 @@
31
31
  "ejs": "*",
32
32
  "express": "*",
33
33
  "express-ws": "*",
34
+ "fs-extra": "^11.3.2",
34
35
  "mime": "*",
35
36
  "mongodb": "^4.17.2",
36
37
  "mongodb-memory-server": "^8.16.0",
37
38
  "mongoose": "^6.13.0",
38
39
  "react": "*",
39
40
  "react-dom": "^16.13.1",
41
+ "sequelize": "^6.37.7",
40
42
  "showdown": "^2.1.0",
41
- "wrench": "*"
43
+ "sqlite3": "^5.1.7"
42
44
  },
43
45
  "devDependencies": {
44
46
  "chai": "*",
@@ -0,0 +1,38 @@
1
+ // import SequelizeConnector from '../lib/sequelize_connector.js';
2
+ import assert from 'assert';
3
+ import Model from '../lib/model_v2.js';
4
+ import { DataTypes } from 'sequelize';
5
+ import SequelizeConnectorUtil from './sequelize_connector.util.js';
6
+
7
+ const TEST_SCHEMA = {
8
+ name: DataTypes.STRING,
9
+ favoriteColor: {
10
+ type: DataTypes.STRING,
11
+ defaultValue: 'green',
12
+ },
13
+ age: DataTypes.INTEGER,
14
+ cash: DataTypes.INTEGER,
15
+ }
16
+ let TestSequelizeModel = null;
17
+
18
+ describe('ModelV2 using SequelizeConnector', function() {
19
+ let util;
20
+ beforeEach(async function() {
21
+ util = new SequelizeConnectorUtil();
22
+ let connector = await util.getTestConnector();
23
+ Model.setConnector(connector);
24
+ TestSequelizeModel =
25
+ class TestSequelizeModel extends new Model("TestSequelizeModel", TEST_SCHEMA) {
26
+ };
27
+ await connector.sequelize.sync({ force: true });
28
+ });
29
+
30
+ it("Should be able to create, save, and retrieve a model", async function() {
31
+ const MODEL_NAME = "First test model created";
32
+ const testModel = TestSequelizeModel.build({name: MODEL_NAME});
33
+ await testModel.save();
34
+ const models = await TestSequelizeModel.findAll();
35
+ assert(models.length == 1, "Should have one model");
36
+ assert(models[0].name == MODEL_NAME, "Name should be consistent");
37
+ });
38
+ });
@@ -0,0 +1,18 @@
1
+ import SequelizeConnector from '../lib/sequelize_connector.js';
2
+
3
+ class SequelizeConnectorUtil {
4
+ constructor() {
5
+ }
6
+
7
+ async getTestConnector() {
8
+ const dbConnector = new SequelizeConnector();
9
+ this.connection = await dbConnector.connect({address: 'sqlite::memory:'});
10
+ debugger;
11
+ return dbConnector;
12
+ }
13
+ async cleanup() {
14
+ debugger;
15
+ }
16
+ }
17
+
18
+ export default SequelizeConnectorUtil;
@@ -0,0 +1,9 @@
1
+ SCRIPT_DIR=$(dirname "$0")
2
+ echo "Script directory (relative): $SCRIPT_DIR"
3
+
4
+
5
+ SCRIPT_PATH=$(readlink -f "$0")
6
+ SCRIPT_DIR=$(dirname "$SCRIPT_PATH")
7
+ echo "Script directory (absolute, resolved): $SCRIPT_DIR"
8
+
9
+ npm --prefix=$SCRIPT_DIR/.. start
@@ -1,14 +1,22 @@
1
1
  export default {
2
- //connector: 'sqlite3_connector.js',
2
+ /**
3
+ * For the sqlite3 connector. Unless a filename is defined, an in-memory
4
+ * database is used. In-memory databases are not persisted, and will be lost
5
+ * when the server is restarted.
6
+ */
7
+ // connector: 'sqlite3_connector.js',
8
+ // filename: ':memory:'
9
+
10
+ /** Mongoose Connector */
3
11
  // connector: 'mongoose_connector.js',
4
- connector: 'mongoose_mem_connector.js',
5
- //url: 'mongodb://localhost',
6
- //port: '27017',
12
+ // url: 'mongodb://localhost',
13
+ // port: '27017',
7
14
 
8
- database: 'development',
15
+ /** Mongoose Memory Server Connector */
16
+ // connector: 'mongoose_mem_connector.js',
17
+ // database: 'development',
9
18
 
10
- // For the sqlite3 connector. Unless a filename is defined, an in-memory
11
- // database is used. In-memory databases are not persisted, and will be lost
12
- // when the server is restarted.
13
- //filename: ':memory:'
19
+ /** Sequelize Connector */
20
+ connector: 'sequelize_connector.js',
21
+ address: 'sqlite::memory:',
14
22
  }
@@ -4,6 +4,7 @@
4
4
  "description": "A basic nails application",
5
5
  "main": "server.js",
6
6
  "type": "module",
7
+ "bin": "./bin/start.sh",
7
8
  "scripts": {
8
9
  "test": "echo \"Error: no test specified\" && exit 1",
9
10
  "start": "vite build & node bin/server.js",
@@ -23,19 +24,20 @@
23
24
  },
24
25
  "dependencies": {
25
26
  "nails-boilerplate": ">=0.1.0",
27
+ "vite": "^6.3.5",
28
+ "@vitejs/plugin-legacy": "^6.1.1",
29
+ "@vitejs/plugin-react": "^4.7.0",
26
30
  "react": "^19.1.0",
27
31
  "react-dom": "^19.1.0",
28
- "react-router-dom": "^7.7.0"
32
+ "react-router-dom": "^7.7.0",
33
+ "sequelize": "^6.37.7",
34
+ "@mui/material": "^7.3.1",
35
+ "@mui/icons-material": "^7.3.1"
29
36
  },
30
37
  "devDependencies": {
31
- "vite": "^6.3.5",
32
38
  "vitest": "^3.2.4",
33
- "@vitejs/plugin-legacy": "^6.1.1",
34
- "@vitejs/plugin-react": "^4.7.0",
35
39
  "@emotion/react": "^11.14.0",
36
40
  "@emotion/styled": "^11.14.1",
37
- "@mui/material": "^7.3.1",
38
- "@mui/icons-material": "^7.3.1",
39
41
  "@mui/types": "^7.4.5"
40
42
  }
41
43
  }
@@ -1,9 +1,18 @@
1
1
  import nails from "nails-boilerplate";
2
+ import { DataTypes } from 'sequelize';
2
3
  const Model = nails.Model;
3
4
 
4
- const userSchema = {
5
- name: String,
6
- verified: Boolean,
7
- email: String
8
- };
9
- export default class User extends new Model("User", {schema: userSchema}) {};
5
+ const sequelizeUserSchema = {
6
+ name: DataTypes.STRING,
7
+ verified: DataTypes.BOOLEAN,
8
+ email: DataTypes.STRING
9
+ }
10
+ export default class User extends new Model("User", sequelizeUserSchema) {};
11
+
12
+ /** If using a mongoose connector */
13
+ // const mongooseUserSchema = {
14
+ // name: String,
15
+ // verified: Boolean,
16
+ // email: String
17
+ // };
18
+ // export default class User extends new Model("User", {schema: mongooseUserSchema}) {};