@jiangliffey/elpis 1.0.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.
Files changed (81) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc +55 -0
  3. package/CLAUDE.md +81 -0
  4. package/README.md +200 -0
  5. package/app/controller/base.js +38 -0
  6. package/app/controller/project.js +74 -0
  7. package/app/controller/view.js +22 -0
  8. package/app/extend/logger.js +35 -0
  9. package/app/middleware/api-params-verify.js +81 -0
  10. package/app/middleware/api-sign-verify.js +35 -0
  11. package/app/middleware/error-handler.js +33 -0
  12. package/app/middleware/project-handler.js +27 -0
  13. package/app/middleware.js +37 -0
  14. package/app/pages/asserts/custom.css +12 -0
  15. package/app/pages/boot.js +50 -0
  16. package/app/pages/common/curl.js +89 -0
  17. package/app/pages/common/utils.js +2 -0
  18. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +21 -0
  19. package/app/pages/dashboard/complex-view/header-view/header-view.vue +123 -0
  20. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
  21. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +40 -0
  22. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +124 -0
  23. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
  24. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +87 -0
  25. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
  26. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +118 -0
  27. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
  28. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +80 -0
  29. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
  30. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
  31. package/app/pages/dashboard/dashboard.vue +96 -0
  32. package/app/pages/dashboard/entry.dashboard.js +45 -0
  33. package/app/pages/dashboard/todo/todo.vue +11 -0
  34. package/app/pages/store/index.js +4 -0
  35. package/app/pages/store/menu.js +58 -0
  36. package/app/pages/store/project.js +14 -0
  37. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  38. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  39. package/app/pages/widgets/header-container/header-container.vue +106 -0
  40. package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
  41. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +136 -0
  42. package/app/pages/widgets/schema-form/complex-view/select/select.vue +116 -0
  43. package/app/pages/widgets/schema-form/form-item-config.js +23 -0
  44. package/app/pages/widgets/schema-form/schema-form.vue +135 -0
  45. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
  46. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
  47. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +44 -0
  48. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +51 -0
  49. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +129 -0
  50. package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
  51. package/app/pages/widgets/schema-table/schema-table.vue +235 -0
  52. package/app/pages/widgets/sider-container/sider-container.vue +31 -0
  53. package/app/public/static/logo.png +0 -0
  54. package/app/public/static/normalize.css +239 -0
  55. package/app/router/project.js +6 -0
  56. package/app/router/view.js +8 -0
  57. package/app/router-schema/project.js +30 -0
  58. package/app/service/base.js +11 -0
  59. package/app/service/project.js +56 -0
  60. package/app/view/entry.tpl +26 -0
  61. package/app/webpack/config/webpack.base.js +203 -0
  62. package/app/webpack/config/webpack.dev.js +59 -0
  63. package/app/webpack/config/webpack.prod.js +107 -0
  64. package/app/webpack/dev.js +53 -0
  65. package/app/webpack/libs/blank.js +3 -0
  66. package/app/webpack/prod.js +17 -0
  67. package/config/config.default.js +3 -0
  68. package/docs/dashboard-model.js +153 -0
  69. package/elpis-core/env.js +23 -0
  70. package/elpis-core/index.js +96 -0
  71. package/elpis-core/loader/config.js +50 -0
  72. package/elpis-core/loader/controller.js +54 -0
  73. package/elpis-core/loader/extend.js +49 -0
  74. package/elpis-core/loader/middleware.js +53 -0
  75. package/elpis-core/loader/router-schema.js +41 -0
  76. package/elpis-core/loader/router.js +45 -0
  77. package/elpis-core/loader/service.js +54 -0
  78. package/index.js +40 -0
  79. package/model/index.js +99 -0
  80. package/package.json +92 -0
  81. package/test/controller/project.test.js +225 -0
@@ -0,0 +1,225 @@
1
+ const assert = require('assert');
2
+ const supertest = require('supertest');
3
+ const md5 = require('md5');
4
+ const elpisCore = require('../../elpis-core');
5
+
6
+ const signKey = 'dftgyh84adsuh462wef46ef5s6d4fiop';
7
+
8
+ /**
9
+ * 设置接口签名请求头
10
+ * 每次请求动态生成 s_t,避免时间戳过期
11
+ */
12
+ function setSignHeaders(req) {
13
+ const st = Date.now();
14
+
15
+ return req
16
+ .set('s_t', st)
17
+ .set('s_sign', md5(`${signKey}_${st}`));
18
+ }
19
+
20
+ describe('测试 project 相关接口', function() {
21
+ this.timeout(60000);
22
+
23
+ let modelList;
24
+ const projectList = [];
25
+
26
+ let request;
27
+
28
+ // it('启动服务', async () => {
29
+ // const app = await elpisCore.start();
30
+ // request = supertest(app.listen());
31
+ // });
32
+ before('启动服务',async function () {
33
+ console.log('---- 启动服务');
34
+ const app = await elpisCore.start();
35
+ modelList = require('../../model/index.js')(app);
36
+ modelList.forEach(modelItem => {
37
+ const { project } = modelItem;
38
+ for(const pKey in project) {
39
+ projectList.push(project[pKey]);
40
+ }
41
+ });
42
+ // 使用 app.callback(),避免真正监听端口
43
+ request = supertest(app.callback());
44
+ });
45
+
46
+ it('GET /api/project without proj_key', async function () {
47
+ const res = await setSignHeaders(
48
+ request.get('/api/project')
49
+ );
50
+
51
+ const resBody = res.body;
52
+ assert.strictEqual(resBody.success, false);
53
+ assert.strictEqual(resBody.code, 442);
54
+ assert.ok(
55
+ resBody.message.includes(`data should have required property 'proj_key'`)
56
+ );
57
+ })
58
+
59
+ it('GET /api/project fail', async function () {
60
+ const res = await setSignHeaders(
61
+ request.get('/api/project').query({
62
+ proj_key: 'not_exist_project'
63
+ })
64
+ );
65
+
66
+ const resBody = res.body;
67
+ assert.strictEqual(resBody.success, false);
68
+ assert.strictEqual(resBody.code, 50000);
69
+ assert.strictEqual(resBody.message, '获取项目异常');
70
+ })
71
+
72
+ it('GET /api/project with proj_key', async function () {
73
+ for(let i = 0; i < projectList.length; i++) {
74
+ const projItem = projectList[i];
75
+ const { key: projKey } = projItem;
76
+
77
+ console.log(`--------GET /api/project with proj_key: ${projKey}`);
78
+
79
+ const res = await setSignHeaders(
80
+ request.get('/api/project').query({
81
+ proj_key: projKey
82
+ })
83
+ );
84
+
85
+ assert.strictEqual(res.body.success, true);
86
+ const resData = res.body.data;
87
+ assert.strictEqual(resData.key, projKey);
88
+ assert.ok(resData.modelKey);
89
+ assert.ok(resData.name);
90
+ assert.ok(resData.desc !== undefined);
91
+ assert.ok(resData.homePage !== undefined);
92
+
93
+ const { menu } = resData;
94
+ menu.forEach(menuItem => {
95
+ checkMenuItem(menuItem);
96
+ })
97
+ }
98
+
99
+ // 校验 menu 菜单
100
+ function checkMenuItem (menuItem) {
101
+ console.log('--------GET /api/project with proj_key - menuKey:', menuItem.key);
102
+ assert.ok(menuItem.key);
103
+ assert.ok(menuItem.name);
104
+ assert.ok(menuItem.menuType);
105
+
106
+ if(menuItem.menuType === 'group') {
107
+ assert.ok(menuItem.subMenu !== undefined);
108
+ menuItem.subMenu.forEach(subMenuItem => {
109
+ checkMenuItem(subMenuItem);
110
+ })
111
+ }
112
+
113
+ if(menuItem.menuType === 'module') {
114
+ checkModule(menuItem);
115
+ }
116
+ }
117
+
118
+ // 校验 module 菜单配置
119
+ function checkModule (menuItem) {
120
+ const { moduleType } = menuItem;
121
+ assert(moduleType);
122
+
123
+ if(moduleType === 'sider') {
124
+ const { siderConfig } = menuItem;
125
+ assert.ok(siderConfig);
126
+ assert.ok(Array.isArray(siderConfig.menu));
127
+ siderConfig.menu.forEach(siderMenuItem => {
128
+ checkMenuItem(siderMenuItem);
129
+ })
130
+ }
131
+
132
+ if(moduleType === 'iframe') {
133
+ const { iframeConfig } = menuItem;
134
+ assert.ok(iframeConfig);
135
+ assert.ok(iframeConfig.path !== undefined);
136
+ }
137
+
138
+ if(moduleType === 'custom') {
139
+ const { customConfig } = menuItem;
140
+ assert.ok(customConfig);
141
+ assert.ok(customConfig.path !== undefined);
142
+ }
143
+
144
+ if(moduleType === 'schema') {
145
+ const { schemaConfig } = menuItem;
146
+ assert.ok(schemaConfig);
147
+ assert.ok(schemaConfig.api !== undefined);
148
+ assert.ok(schemaConfig.schema);
149
+ }
150
+ }
151
+
152
+ });
153
+
154
+ it('GET /api/project/list without proj_key', async function () {
155
+ const res = await setSignHeaders(
156
+ request.get('/api/project/list')
157
+ );
158
+
159
+ assert.strictEqual(res.body.success, true);
160
+
161
+ const resData = res.body.data;
162
+ assert.strictEqual(resData.length, projectList.length);
163
+ for(let i = 0; i < resData.length; i++) {
164
+ // modelKey, key, name, desc, homePage
165
+ const item = resData[i];
166
+ assert.ok(item.modelKey);
167
+ assert.ok(item.key);
168
+ assert.ok(item.name);
169
+ assert.ok(item.desc !== undefined);
170
+ assert.ok(item.homePage !== undefined);
171
+ }
172
+ });
173
+
174
+ it('GET /api/project/list with proj_key', async function () {
175
+ const { key: projKey } = projectList[Math.floor(Math.random() * projectList.length)];
176
+ const { modelKey } = projectList.find(item => item.key == projKey );
177
+ // 和当前 projKey 属于同一个 modelKey 的项目列表
178
+ const expectedProjectList = projectList.filter(item => {
179
+ return item.modelKey === modelKey;
180
+ });
181
+ const res = await setSignHeaders(
182
+ request.get('/api/project/list').query({
183
+ proj_key: projKey
184
+ })
185
+ );
186
+
187
+ assert.strictEqual(res.body.success, true);
188
+
189
+ const resData = res.body.data;
190
+ assert.strictEqual(resData.length, expectedProjectList.length);
191
+ for(let i = 0; i < resData.length; i++) {
192
+ // modelKey, key, name, desc, homePage
193
+ const item = resData[i];
194
+ assert.strictEqual(item.modelKey, modelKey);
195
+ assert.ok(item.key);
196
+ assert.ok(item.name);
197
+ assert.ok(item.desc !== undefined);
198
+ assert.ok(item.homePage !== undefined);
199
+ }
200
+ });
201
+
202
+ it('GET /api/project/model_list', async function () {
203
+ const res = await setSignHeaders(
204
+ request.get('/api/project/model_list')
205
+ );
206
+
207
+ assert.strictEqual(res.body.success, true);
208
+
209
+ const resData = res.body.data;
210
+ assert.ok(resData.length > 0);
211
+
212
+ for(let i = 0; i < resData.length; i++) {
213
+ const item = resData[i];
214
+ assert.ok(item.model);
215
+ assert.ok(item.model.key);
216
+ assert.ok(item.model.name);
217
+ assert.ok(item.project);
218
+ for(const projKey in item.project) {
219
+ const project = item.project[projKey];
220
+ assert.ok(project.key);
221
+ assert.ok(project.name);
222
+ }
223
+ }
224
+ })
225
+ });