npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

circlejs

v1.0.17

Published

circlejs-framework

Readme

CircleJS - Core Framework for Micro-service

Quy trình triển khai:

1 - Cài đặt (2 cách):

  • Sử dụng bộ starter pack:
git clone https://github.com/paduvi/circle-starter-pack.git
cd circle-starter-pack
  • Nhúng thư viện Circlejs:
npm install --save circlejs

Mẫu file bootstrap:

// server.js

var Application = require('circlejs');

var app = new Application();
app.start();

2 - Chạy ở môi trường Development: npm test

3 - Chạy ở môi trường Production: npm start

Cấu trúc folder:

  • config:
    • Trọng số cho ứng dụng: config.js
    • Trọng số theo môi trường: env/config-{env}.js
    • Cấu hình thông số các kết nối: setting.js
    • Cấu hình thông số theo môi trường : env/setting-{env}.js
    • Kết nối database: database.js, có thể kết nối 1 lúc nhiều database cũng được
  • controller:
    • web: cung cấp các REST API (chủ yếu là cho phần frontend)
  • action: cung cấp các API dưới dạng hàm (command) cho Resource bên dưới. Sử dụng Seneca, có thể gọi trực tiếp ở service khác thông qua Seneca Client hoặc gọi ở local từ Controller.
  • test: thư mục viết test

Controller:

Các route sẽ được khai báo bên trong các file controller/{path}/{controllerName}/route.js. Path được khai báo trong config.js, mặc định nếu không khai báo thì sẽ lấy giá trị là 'web' Prefix URL được khai báo trong config.js, mặc định nếu không khai báo thì sẽ lấy giá trị là ''

Ví dụ route controller/web/item/route.js + prefix URL là '/api':

        "/test": {
            get: {
                handler: (req, res) => res.sendStatus(200),
                middleware: [], // optional
                cors: [] //optional,
                authenticate: {
                    name: 'jwt',
                    permissions: ['fashion_manage_all'],
                    // options: {}
                }
            }
        }

-> Đường dẫn tương ứng: /api/item/test

-> Hàm trên sẽ tương ứng với lệnh app.get('/api/item/test', [], (req, res) => res.sendStatus(200)) trong express

-> Danh sách các middleware mình khai báo ở trong phần middleware (optional)

-> Khai báo cấu hình authenticate khai báo ở trong phần authenticate (yêu cầu phải khai báopassport:true trong config.js):

-> Danh sách địa chỉ web được phép truy cập AJAX vào service khai báo ở phần cors (optional, mặc định là tất cả các request đều được cho phép):

- Tham khảo giá trị config ở trong module cors: https://github.com/expressjs/cors#configuration-options
- Lưu ý: ở chế độ development, cors sẽ bị tắt.

Database:

Phần database thay vì fix cứng dùng Sequelize như của Arrowjs.io thì mình sẽ để tự config thoải mái, rồi trả về 1 Promise return ra dbConnection bên trong file config/database.js

Ví dụ dùng MongoDB:

var MongoClient = require('mongodb').MongoClient;
var Promise = require('bluebird');

exports.beforeInitialize = function (app) {
    return new Promise(function (resolve, reject) {
        MongoClient.connect(`mongodb://${app.config.db.host}/${app.config.db.name}`, function (err, dbConnection) {
            if (err)
                return reject(err);
            resolve({mongo: dbConnection});
        });
    })
}

/* Do something after loading models */
exports.afterInitialize = (app) => {
    return Promise.resolve();
}

-> Gọi tới db bằng lệnh app.db.mongo

Ví dụ sử dụng nhiều DB 1 lúc:

var MongoClient = require('mongodb').MongoClient;
var Sequelize = require('sequelize');
var Promise = require('bluebird');

exports.beforeInitialize = function (app) {
    return Promise.all([
        connectMongo(app),
        connectPostgres(app)
    ]).then(function (results) {
        return {
            mongo: results[0],
            sequelize: results[1]
        }
    })
}

function connectMongo(app) {
    return new Promise(function (resolve, reject) {
        MongoClient.connect(`mongodb://${app.config.db.mongo.host}/${app.config.db.mongo.name}`, function (err, dbConnection) {
            if (err)
                return reject(err);
            resolve(dbConnection);
        });
    })
}

function connectPostgres(app) {
    return Promise.resolve().then(function () {
        let sequelize = new Sequelize(app.setting.db.postgres.database, app.setting.db.postgres.username,
                    app.setting.db.postgres.password, app.setting.db.postgres);
        
        return sequelize.authenticate().then(function () {
            return {sequelize};
        });
    })
}

/* Do something after loading models */
exports.afterInitialize = (app) => {
    return Promise.resolve();
}

-> Gọi tới Mongo bằng lệnh app.db.mongo và Postgres(Sequelize) bằng lệnh app.db.sequelize

Model

Các model sẽ nằm trong thư mục model/{db-name}/{model-name}.js. Ví dụ:

  • Model User của db có tên là sequelize sẽ nằm ở model/sequelize/User.js
  • Lệnh gọi ra: app.db.sequelize.models.User

Service:

Các service sẽ được load ngay sau khi load xong Database, bên trong mỗi service trả về hàm có đầu vào là app, ví dụ:

/* service/mailer.js */
const nodemailer = require('nodemailer');

module.exports = async(app) => {
    const redis = app.db.redis;

    const getConfig = async() => {
        const json = await redis.getAsync('mailer');
        return JSON.parse(json);
    }

    const setConfig = async(value) => {
        return redis.setAsync('mailer', JSON.stringify(value));
    }

    const getInstance = async() => {
        const config = await getConfig();
        return nodemailer.createTransport(config);
    }

    const cachedConfig = await getConfig();
    const staticConfig = app.setting.node_mailer;
    await setConfig(Object.assign({}, staticConfig, cachedConfig));

    return {
        getConfig,
        getInstance,
        setConfig
    }
}

Để gọi ra service trên, ta dùng cú pháp: app.services.mailer. Tên của service trùng với tên file javascript trong folder service.

Action:

Phần Action được khai báo trong folder action. Được gọi ra thông qua câu lệnh app.seneca.act (cú pháp callback async) hoặc app.seneca.exec (cú pháp Promise).

Ví dụ action/item.js:

module.exports = function (app) {

    let item = app.db.sequelize.models.item;

    return {
        findItem: function (msg, done) {
            return item.findAndCountAll(msg.options).then(function (result) {
                return done(null, result);
            }).catch(function (err) {
                return done(err);
            })
        }

    }

};

Lệnh gọi ra action được khai báo ở trên: app.seneca.exec({role: 'item', cmd: 'findItem', options: opts}), trong đó:

  • role chính là tên file: item
  • cmd chính là tên khóa: findItem
  • các tham số còn lại sẽ được Seneca gom lại vào trong 1 Object, để truyền vào trong hàm Action. Ví dụ tham số options được gọi ra thông qua biến msg.options