§2024-06-09

機器: hc4nas02.yushei.net

¶Step 1. nodejs eviromental control, fnm

alexlai@hc4nas02:~$ which node npm npx
/run/user/1026/fnm_multishells/15667_1717891102554/bin/node
/run/user/1026/fnm_multishells/15667_1717891102554/bin/npm
/run/user/1026/fnm_multishells/15667_1717891102554/bin/npx
alexlai@hc4nas02:~$ fnm list
* v20.14.0 default, lts-latest
* system

¶Step2. create project directory

alexlai@hc4nas02:~$ cd
alexlai@hc4nas02:~$ mkdir -p nodejs_proj/yushei_blog && cd $_
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (yushei_blog) 
version: (1.0.0) 
description: A blog for YuShei using nodeJs, mongoDB
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: alexlai@h2jammy.yushei.net
license: (ISC) 
About to write to /home/alexlai/nodejs_proj/yushei_blog/package.json:

{
  "name": "yushei_blog",
  "version": "1.0.0",
  "description": "A blog for YuShei using nodeJs, mongoDB",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "alexlai@h2jammy.yushei.net",
  "license": "ISC"
}


Is this OK? (yes) 

¶Step3. install NodeJs modules

$ npm install express mongoose body-parser inversify reflect-metadata  --save
$ ls
node_modules  package.json  package-lock.json
$ cat package.json 
{
  "name": "yushei_blog",
  "version": "1.0.0",
  "description": "A blog for YuShei using nodeJs, mongoDB",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "alexlai@h2jammy.yushei.net",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.20.2",
    "express": "^4.19.2",
    "inversify": "^6.0.2",
    "mongoose": "^8.4.1",
    "reflect-metadata": "^0.2.2"
  }
}

starting from npm version 5 (released in 2017), the --save flag is no longer necessary because it is the default behavior.

¶Step 3: MVC, Model-View-Controller

The MVC design pattern separates the application into three main components: Model, View, and Controller. This separation helps to organize the codebase and improve maintainability. Let’s create the necessary files for each component:

const mongoose = require('mongoose');

const blogSchema = new mongoose.Schema({
  title: { type: String, required: true },
  content: { type: String, required: true },
});

module.exports = mongoose.model('Blog', blogSchema);
function renderBlog(blog) {
  console.log(`Title: ${blog.title}`);
  console.log(`Content: ${blog.content}`);
}

module.exports = renderBlog;
const Blog = require('../models/Blog');
const renderBlog = require('../views/blogView');

async function createBlog(title, content) {
  try {
    const blog = new Blog({ title, content });
    await blog.save();
    renderBlog(blog);
  } catch (error) {
    console.error(error);
  }
}

module.exports = createBlog;¥

¶Step 4: Configuring MongoDB Connection

Let’s configure the MongoDB connection in our project. Create a config directory and a database.js file inside it. Add the following code to establish the connection:

alexlai@MacMini ~ % dig +short _mongodb._tcp.inLaneCatch.yushei.com.tw  SRV
0 0 27017 hc4Jammy.yushei.com.tw.
0 0 27017 x8664Arch.yushei.com.tw.
0 0 27017 n2Boookworm.yushei.com.tw.
0 0 27017 n2Jammy.yushei.com.tw.
alexlai@MacMini ~ % dig +short _mongodb._tcp.ys20220318.yushei.com.tw  SRV 
0 0 27017 redisMongo03.yushei.com.tw.
0 0 27017 redisMongo05.yushei.com.tw.
0 0 27017 redisMongo04.yushei.com.tw.

use ys_blog
db.createUser(
  {
    user: "alexlai",
    pwd:  "alex1765",   // or passwordPrompt(),
    roles: [ { role: "readWrite", db: "ys_blog" },
             { role: "read", db: "reporting" } // if any
    ]
  }
)
alexlai@n2Bookworm:~$ mongosh  "mongodb+srv://siteRootAdmin:b23258585@inlaneCatch.yushei.com.tw/ys_blog?replicaSet=odroid01&authSource=admin&tls=false"
Current Mongosh Log ID: 6665318be4112959ba8db5fa
Connecting to:          mongodb+srv://<credentials>@inlaneCatch.yushei.com.tw/ys_blog?replicaSet=odroid01&authSource=admin&tls=false&appName=mongosh+2.2.6
Using MongoDB:          7.0.0-rc8
Using Mongosh:          2.2.6

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

odroid01 [primary] ys_blog> 
alexlai@n2Bookworm:~$ mongosh  "mongodb+srv://siteRootAdmin:b23258585@inlaneCatch.yushei.com.tw/admin?replicaSet=odroid01&authSource=admin&tls=false"
Current Mongosh Log ID: 6665319df1b8918f178db5fa
Connecting to:          mongodb+srv://<credentials>@inlaneCatch.yushei.com.tw/admin?replicaSet=odroid01&authSource=admin&tls=false&appName=mongosh+2.2.6
Using MongoDB:          7.0.0-rc8
Using Mongosh:          2.2.6

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

odroid01 [primary] admin> use ys_blog
switched to db ys_blog
odroid01 [primary] ys_blog> db.createUser(
...   {
...     user: "alexlai",
...     pwd:  "alex1765",   // or passwordPrompt(),
...     roles: [ { role: "readWrite", db: "ys_blog" }]
...   }
... )
{
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1717902561, i: 1 }),
    signature: {
      hash: Binary(Buffer.from("d554451f8b1a7ea07bfb0d8df6e5083c4ebbd9ab", "hex"), 0),
      keyId: Long("7326325939019710465")
    }
  },
  operationTime: Timestamp({ t: 1717902561, i: 1 })
}
alexlai@n2Bookworm:~$ mongosh  "mongodb+srv://alexlai:alex1765@inlaneCatch.yushei.com.tw/ys_blog?replicaSet=odroid01&authSource=ys_blog&tls=false"
Current Mongosh Log ID: 6665320e5a39d3fde88db5fa
Connecting to:          mongodb+srv://<credentials>@inlaneCatch.yushei.com.tw/ys_blog?replicaSet=odroid01&authSource=ys_blog&tls=false&appName=mongosh+2.2.6
Using MongoDB:          7.0.0-rc8
Using Mongosh:          2.2.6

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

odroid01 [primary] ys_blog> db.runCommand({connectionStatus : 1})
{
  authInfo: {
    authenticatedUsers: [ { user: 'alexlai', db: 'ys_blog' } ],
    authenticatedUserRoles: [ { role: 'readWrite', db: 'ys_blog' } ]
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1717908087, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('+eEWpjkc8jW28VIZq5WukI3/FLQ=', 0),
      keyId: Long('7326325939019710465')
    }
  },
  operationTime: Timestamp({ t: 1717908087, i: 1 })
}
const mongoose = require('mongoose');

async function connectToDatabase() {
  try {
    await mongoose.connect('mongodb+srv://alexlai:alex1765@inlaneCatch.yushei.com.tw/ys_blog?replicaSet=odroid01&authSource=ys_blog&tls=false',
      {
        useNewUrlParser: true,
        useUnifiedTopology: true,
      }
    );
    console.log('Connected to MongoDB');
  } catch (error) {
    console.error('Failed to connect to MongoDB', error);
  }
}

module.exports = connectToDatabase;

Step 5: Implementing Dependency Injection with InversifyJS

InversifyJS and InversifyJS enhances the modularity, maintainability, and testability of your Node.js applications by providing a robust framework for dependency injection. It is especially beneficial for large-scale applications where managing dependencies becomes complex and challenging.