chanjs 1.0.46 → 1.1.1

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  # Chanjs
3
3
 
4
- Chanjs 是一个基于 Express 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。
4
+ Chanjs 是一个基于 Express5+ 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。
5
5
 
6
6
  ## 特点
7
7
 
@@ -86,14 +86,16 @@ Chanjs 是一个基于 Express 构建的轻量级 MVC 框架,完全使用 Java
86
86
  ### 运行
87
87
 
88
88
  ```javascript
89
- const Chanjs = require("chanjs");
89
+ import Chanjs from "chanjs";
90
90
  const chan = new Chanjs();
91
- // 加载中间件
91
+ // 前置钩子
92
92
  chan.beforeStart(fn);
93
- // 扫描模块
94
- chan.start();
95
- // 启动服务器
96
- chan.run();
93
+ // 开始加载
94
+ await chan.start();
95
+ chan.run((port) => {
96
+ console.log(`ChanCMS is running on ${port}`);
97
+ });
98
+
97
99
  ```
98
100
 
99
101
  该框架专为寻求简单与功能之间平衡的开发者设计,为构建 Web 应用程序提供了一个强大的基础。
package/core/config.js CHANGED
@@ -1,33 +1,40 @@
1
- const path = require('path');
1
+ import path from 'path';
2
+ import { createRequire } from 'module';
3
+ import { pathToFileURL } from 'url';
2
4
 
3
5
  /**
4
- * @description 根目录
6
+ * @description 根目录(ESM 兼容写法)
5
7
  */
8
+ const __dirname = path.dirname(new URL(import.meta.url).pathname);
9
+ console.log(__dirname)
6
10
  const ROOT_PATH = process.cwd();
7
- // 读取package.json文件
8
- const {version='1.0.0',author='明空'} = require(path.join(ROOT_PATH, 'package.json'));
11
+
12
+ // 异步读取 package.json(ESM 标准方式)
13
+ const packageUrl = pathToFileURL(path.join(ROOT_PATH, 'package.json')).href;
14
+ const { default: pkg } = await import(packageUrl,{ assert: { type: 'json' } });
15
+ const { version = '1.0.0', author = '明空' } = pkg;
9
16
 
10
17
  /**
11
18
  * @description 程序目录
12
19
  */
13
20
  const APP_PATH = path.join(ROOT_PATH, 'app');
14
21
 
15
- let config = {
16
- JSON_LIMIT:"100kb",
17
- logger : {
22
+ const baseConfig = {
23
+ JSON_LIMIT: "100kb",
24
+ logger: {
18
25
  level: 'dev',
19
26
  },
20
27
  version,
21
28
  author,
22
- env:'dev',
23
- template:'default',
24
- views:[], //模板路径
25
- static:[{ //静态文件路径
29
+ env: 'dev',
30
+ template: 'default',
31
+ views: [],
32
+ static: [{
26
33
  prefix: "/public/",
27
34
  dir: ["app/public"],
28
35
  maxAge: 0,
29
36
  }],
30
- database:{
37
+ database: {
31
38
  client: "mysql2",
32
39
  host: "localhost",
33
40
  port: "3306",
@@ -36,10 +43,11 @@ let config = {
36
43
  database: "chancms",
37
44
  charset: "utf8mb4",
38
45
  }
39
- }
46
+ };
40
47
 
41
- module.exports = {
48
+ // 导出配置对象
49
+ export default {
42
50
  ROOT_PATH,
43
- APP_PATH,
44
- ...config
45
- }
51
+ APP_PATH,
52
+ ...baseConfig
53
+ };
package/core/helper.js CHANGED
@@ -1,11 +1,11 @@
1
- const knex = require('knex');
1
+ import knex from 'knex';
2
2
 
3
3
  /**
4
4
  * @description 实例化一个类,并将该类的所有方法绑定到一个新的对象上。
5
5
  * @param {Function} className - 需要实例化的类。
6
6
  *@returns {Object} 包含绑定方法的对象。
7
7
  */
8
- exports.bindClass = function(className) {
8
+ export const bindClass = function(className) {
9
9
  let obj = {};
10
10
  const cls = new className();
11
11
  Object.getOwnPropertyNames(cls.constructor.prototype).forEach(
@@ -22,7 +22,7 @@ exports.bindClass = function(className) {
22
22
  }
23
23
 
24
24
 
25
- exports.createKnex = function(opt) {
25
+ export const createKnex = function(opt) {
26
26
  let config = {
27
27
  host:"localhost",
28
28
  port:"3306",
@@ -63,7 +63,7 @@ exports.createKnex = function(opt) {
63
63
  * @returns Array
64
64
  * @description 将web模块放到最后加载
65
65
  */
66
- exports.loadWebToEnd = function(module=[]){
66
+ export const loadWebToEnd = function(module=[]){
67
67
  const index = module.indexOf('web');
68
68
  if (index !== -1) {
69
69
  const web = module.splice(index, 1);
package/core/lib/cache.js CHANGED
@@ -104,7 +104,7 @@ class Cache {
104
104
  }
105
105
  }
106
106
 
107
- module.exports = new Cache();
107
+ export default new Cache();
108
108
 
109
109
  // // 示例用法
110
110
  // const cache = new SimpleCache(100); // 设置缓存最大容量为 100
@@ -65,4 +65,4 @@ class Controller {
65
65
  }
66
66
  }
67
67
 
68
- module.exports = Controller;
68
+ export default Controller;
@@ -1,8 +1,10 @@
1
- const express = require("express");
2
- module.exports = (app)=>{
1
+ import express from "express";
2
+ export default (app)=>{
3
3
  app.plus = {
4
4
  setStatic:function ({prefix,dir,maxAge}) {
5
5
  app.use(prefix, express.static(dir, { maxAge: maxAge || 0 }));
6
6
  }
7
7
  }
8
- }
8
+ }
9
+
10
+
package/core/lib/index.js CHANGED
@@ -1,11 +1,12 @@
1
- const express = require("express");
2
- const cookieParser = require("cookie-parser");
3
- const favicon = require("serve-favicon");
4
- const morgan = require("morgan");
5
- const path = require("path");
6
- const view = require("./view.js");
7
- module.exports = async function (app, config) {
8
- const { logger, APP_PATH, cookieKey, static, JSON_LIMIT, appName, version } =
1
+ import express from "express";
2
+ import cookieParser from "cookie-parser";
3
+ import favicon from "serve-favicon";
4
+
5
+ import morgan from "morgan";
6
+ import path from "path";
7
+ import view from "./view.js";
8
+ export default async function (app, config) {
9
+ const { logger, APP_PATH, cookieKey, statics, JSON_LIMIT, appName, version } =
9
10
  config;
10
11
 
11
12
  app.use(morgan(logger.level));
@@ -14,8 +15,8 @@ module.exports = async function (app, config) {
14
15
  app.use(express.json({ limit: JSON_LIMIT }));
15
16
  app.use(express.urlencoded({ extended: false }));
16
17
  view(app, config);
17
- if (static.length > 0) {
18
- static.forEach((item) => {
18
+ if (statics.length > 0) {
19
+ statics.forEach((item) => {
19
20
  const { prefix, dir, maxAge } = item;
20
21
  app.use(prefix, express.static(dir, { maxAge: maxAge || 0 }));
21
22
  });
@@ -196,5 +196,4 @@ async updateMany(updates = []) {
196
196
  }
197
197
 
198
198
  }
199
-
200
- module.exports = BaseService;
199
+ export default BaseService;
package/core/lib/view.js CHANGED
@@ -1,7 +1,10 @@
1
- const path = require("path");
2
- const template = require("art-template");
3
- const dayjs = require("dayjs");
1
+ import path from "path";
2
+ import dayjs from 'dayjs';
3
+ import { createRequire } from 'module';
4
+
5
+ const require = createRequire(import.meta.url);
4
6
 
7
+ const template = require("art-template");
5
8
  // 注册 dateFormat 函数
6
9
  template.defaults.imports.dateFormat = function (date, format) {
7
10
  if (!date) {
@@ -20,7 +23,7 @@ template.defaults.imports.dateFormat = function (date, format) {
20
23
  return date.format(format);
21
24
  };
22
25
 
23
- module.exports = (app, config) => {
26
+ export default (app, config) => {
24
27
  const { APP_PATH, views, env } = config;
25
28
  //合并插件中的view
26
29
  const all = [...views, 'app/modules/web/view'];
package/index.js CHANGED
@@ -1,14 +1,17 @@
1
- const express = require("express");
2
- const path = require("path");
3
- const fs = require("fs");
4
- const cors = require("cors");
5
- const config = require("./core/config.js");
6
- const {bindClass,createKnex,loadWebToEnd} = require("./core/helper.js");
7
- const Controller = require("./core/lib/controller.js");
8
- const Service = require("./core/lib/service.js");
9
- const cache = require('./core/lib/cache.js');
10
- const core = require("./core/lib/index.js");
11
- const extend = require("./core/lib/extend.js");
1
+ import express from "express";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import cors from "cors";
5
+ import { pathToFileURL } from 'url'; // 新增顶部导入
6
+ import config from "./core/config.js";
7
+ import {bindClass,createKnex,loadWebToEnd} from "./core/helper.js";
8
+
9
+ import Controller from "./core/lib/controller.js";
10
+
11
+ import Service from "./core/lib/service.js";
12
+ import cache from './core/lib/cache.js';
13
+ import core from "./core/lib/index.js";
14
+ import extend from "./core/lib/extend.js";
12
15
  /**
13
16
  * @description 基于express封装的mvc框架,遵循约定优于配置原则
14
17
  */
@@ -21,45 +24,38 @@ class Chan {
21
24
  static Controller = Controller;
22
25
 
23
26
  constructor() {
24
- this.init();
27
+ this.app = express();
28
+ this.router = express.Router();
25
29
  }
26
30
 
27
- init() {
28
- const startTime = performance.now();
29
- this.app = express();
31
+ async init() {
30
32
  extend(this.app);
31
- this.router = express.Router();
32
- this.loadConfig();
33
- this.loadExtends();
33
+ await this.loadConfig();
34
+ await this.loadExtends();
34
35
  this.loadCore();
35
36
  this.loadKnex();
36
37
  this.loadCors();
37
- // 记录结束时间
38
- const endTime = performance.now();
39
- console.log(`Chanjs init: ${endTime - startTime} ms`);
40
38
  }
41
39
 
42
40
 
43
-
44
- loadConfig() {
41
+ async loadConfig() {
45
42
  const configPath = path.join(Chan.config.APP_PATH, "config/index.js");
46
43
  if (fs.existsSync(configPath)) {
47
- const config = require(configPath);
48
- Chan.config = { ...Chan.config, ...config };
44
+ const configUrl = pathToFileURL(configPath).href; // 新增转换
45
+ const configModule = await import(configUrl); // 使用 URL 导入
46
+ Chan.config = { ...Chan.config, ...configModule.default }; // 注意 default
49
47
  }
50
48
  }
51
49
 
52
- loadExtends() {
50
+ async loadExtends() {
53
51
  const extendPath = path.join(Chan.config.APP_PATH, "extend");
54
52
  if (fs.existsSync(extendPath)) {
55
- let controllers = fs
56
- .readdirSync(extendPath)
57
- .filter((file) => file.endsWith(".js"));
58
- for (let i = 0, file; i < controllers.length; i++) {
59
- file = controllers[i];
60
- const helper = require(path.join(extendPath, file));
61
- const fileName = file.replace(".js", "");
62
- Chan.helper[fileName] = helper;
53
+ const files = fs.readdirSync(extendPath).filter(file => file.endsWith(".js"));
54
+ for (const file of files) {
55
+ const filePath = path.join(extendPath, file);
56
+ const fileUrl = pathToFileURL(filePath).href; // 转换路径
57
+ const helperModule = await import(fileUrl); // 使用 URL 导入
58
+ Chan.helper[file.replace(".js", "")] = helperModule?.default || helperModule; // 注意 default
63
59
  }
64
60
  }
65
61
  }
@@ -90,14 +86,11 @@ class Chan {
90
86
  cb && cb();
91
87
  }
92
88
  //启动
93
- start(cb) {
94
- const startTime = performance.now();
95
- this.loadModules();
96
- this.loadPlugins();
97
- this.loadCommonRouter();
98
- // 记录结束时间
99
- const endTime = performance.now();
100
- console.log(`Chanjs load modules: ${endTime - startTime} ms`);
89
+ async start(cb) {
90
+ await this.init();
91
+ await this.loadPlugins();
92
+ await this.loadModules();
93
+ await this.loadCommonRouter();
101
94
  cb && cb();
102
95
  }
103
96
 
@@ -107,63 +100,69 @@ class Chan {
107
100
  }
108
101
 
109
102
  // 加载插件
110
- loadPlugins() {
111
- this.loadModules("plugins");
103
+ async loadPlugins() {
104
+ await this.loadModules("plugins");
112
105
  }
113
106
 
114
107
  /**
115
108
  * @description 模块加载入口(路由&控制器& 服务)
116
109
  */
117
- loadModules(modules = "modules") {
110
+ async loadModules(modules = "modules") {
118
111
  const configPath = path.join(Chan.config.APP_PATH, modules);
112
+ console.log('configPath',configPath);
119
113
  if (fs.existsSync(configPath)) {
120
- //模块名称
121
114
  const dirs = loadWebToEnd(Chan.config[modules]);
115
+ console.log('dirs',dirs);
122
116
  Chan[modules] = {};
117
+
123
118
  // 先加载所有服务
124
- dirs.forEach((item) => {
119
+ for (const item of dirs) {
125
120
  Chan[modules][item] = {
126
121
  service: {},
127
122
  controller: {},
128
123
  };
129
- this.loadServices(modules, item);
130
- });
131
-
124
+ await this.loadServices(modules, item); // 确保每个模块的服务加载完成
125
+ }
126
+
132
127
  // 加载控制器和路由
133
- dirs.forEach((item) => {
134
- this.loadModule(modules, item);
135
- });
128
+ for (const item of dirs) {
129
+ await this.loadModule(modules, item); // 确保每个模块的加载完成
130
+ }
136
131
  }
137
132
  }
133
+
138
134
 
139
135
  /**
140
136
  * @description 加载模块,包括 controller service router
141
137
  * @param {String} moduleName 模块名称
142
138
  */
143
- loadModule(modules, moduleName) {
144
- this.loadControllers(modules, moduleName);
145
- this.loadRoutes(modules, moduleName);
139
+ async loadModule(modules, moduleName) {
140
+ await this.loadControllers(modules, moduleName); // 确保控制器加载完成
141
+ await this.loadRoutes(modules, moduleName); // 然后加载路由
146
142
  }
147
143
 
148
- loadFiles(modules, moduleName, type) {
144
+ async loadFiles(modules, moduleName, type) {
149
145
  const dir = path.join(Chan.config.APP_PATH, modules, moduleName, type);
150
146
  if (fs.existsSync(dir)) {
151
147
  const files = fs.readdirSync(dir).filter(file => file.endsWith(".js"));
152
- files.forEach(file => {
153
- const module = require(path.join(dir, file));
148
+ for (const file of files) { // 使用 for...of 确保异步操作顺序
149
+ const filePath = path.join(dir, file);
150
+ const fileUrl = pathToFileURL(filePath).href;
151
+ const module = await import(fileUrl);
154
152
  const name = file.replace(".js", "");
155
- Chan[modules][moduleName][type][name] = { ...bindClass(module) };
156
- });
153
+ Chan[modules][moduleName][type][name] = { ...bindClass(module.default) };
154
+ }
157
155
  }
158
156
  }
157
+
159
158
 
160
159
  /**
161
160
  * @description 扫描模块下所有service
162
161
  * @param {*} moduleDir 模块路径
163
162
  * @param {*} moduleName 模块名称
164
163
  */
165
- loadServices(modules, moduleName) {
166
- this.loadFiles(modules, moduleName, "service");
164
+ async loadServices(modules, moduleName) {
165
+ await this.loadFiles(modules, moduleName, "service");
167
166
  }
168
167
 
169
168
  /**
@@ -171,8 +170,8 @@ class Chan {
171
170
  * @param {*} moduleDir 模块路径
172
171
  * @param {*} moduleName 模块名称
173
172
  */
174
- loadControllers(modules, moduleName) {
175
- this.loadFiles(modules, moduleName, "controller");
173
+ async loadControllers(modules, moduleName) {
174
+ await this.loadFiles(modules, moduleName, "controller");
176
175
  }
177
176
 
178
177
  /**
@@ -180,26 +179,23 @@ class Chan {
180
179
  * @param {*} moduleDir 模块路径
181
180
  * @param {*} moduleName 模块名称
182
181
  */
183
- loadRoutes(modules, moduleName) {
184
- const routersDir = path.join(
185
- Chan.config.APP_PATH,
186
- modules,
187
- moduleName,
188
- "router.js"
189
- );
182
+ async loadRoutes(modules, moduleName) {
183
+ const routersDir = path.join(Chan.config.APP_PATH, modules, moduleName, "router.js");
190
184
  if (fs.existsSync(routersDir)) {
191
- const routes = require(routersDir);
192
- routes({ router: this.router, modules: Chan[modules], app: this.app });
185
+ const routeUrl = pathToFileURL(routersDir).href; // 转换路径
186
+ const routes = await import(routeUrl); // 使用 URL 导入
187
+ routes.default({ router: this.router, modules: Chan[modules], app: this.app });
193
188
  }
194
189
  }
195
190
 
196
191
  //通用路由,加载错误处理和500路由和爬虫处理
197
- loadCommonRouter() {
192
+ async loadCommonRouter() {
198
193
  try {
199
194
  const baseRouterPath = path.join(Chan.config.APP_PATH, "router.js");
200
195
  if (fs.existsSync(baseRouterPath)) {
201
- const _router = require(baseRouterPath);
202
- _router(this.app, this.router, Chan.config);
196
+ const routerUrl = pathToFileURL(baseRouterPath).href; // 转换路径
197
+ const _router = await import(routerUrl); // 使用 URL 导入
198
+ _router.default(this.app, this.router, Chan.config); // 注意 default
203
199
  }
204
200
  } catch (error) {
205
201
  console.log(error);
@@ -214,4 +210,4 @@ class Chan {
214
210
  }
215
211
  }
216
212
  global.Chan = Chan;
217
- module.exports = Chan;
213
+ export default Chan;
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
+ "type": "module",
2
3
  "name": "chanjs",
3
- "version": "1.0.46",
4
- "description": "chanjs基于express 纯js研发的轻量级mvc框架。",
4
+ "version": "1.1.1",
5
+ "description": "chanjs基于express5 纯js研发的轻量级mvc框架。",
5
6
  "main": "index.js",
6
7
  "module": "index.js",
7
8
  "keywords": [
@@ -12,18 +13,19 @@
12
13
  "chancms",
13
14
  "nodejs"
14
15
  ],
16
+ "engines": { "node": ">=20.0.0" },
15
17
  "author": "明空",
16
18
  "license": "ISC",
17
19
  "dependencies": {
18
- "art-template": "4.13.2",
19
- "body-parser": "1.20.2",
20
- "cookie-parser": "1.4.6",
20
+ "art-template": "4.13.4",
21
+ "body-parser": "2.2.0",
22
+ "cookie-parser": "1.4.7",
21
23
  "cors": "2.8.5",
22
- "express": "4.19.2",
24
+ "express": "5.1.0",
23
25
  "express-art-template": "1.0.1",
24
26
  "knex": "3.1.0",
25
27
  "morgan": "1.10.0",
26
- "mysql2": "3.11.0",
27
- "dayjs": "1.11.12"
28
+ "mysql2": "3.14.0",
29
+ "dayjs": "1.11.13"
28
30
  }
29
31
  }