nsgm-cli 2.1.13 → 2.1.14

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 (113) hide show
  1. package/README.md +370 -155
  2. package/client/components/Button.tsx +3 -5
  3. package/client/components/__tests__/Button.test.tsx +10 -10
  4. package/client/layout/index.tsx +149 -137
  5. package/client/redux/reducers.ts +1 -1
  6. package/client/redux/store.ts +2 -1
  7. package/client/redux/template/manage/actions.ts +77 -88
  8. package/client/redux/template/manage/reducers.ts +25 -37
  9. package/client/redux/template/manage/types.ts +1 -1
  10. package/client/service/template/manage.ts +20 -21
  11. package/client/styled/common.ts +12 -13
  12. package/client/styled/layout/index.ts +19 -19
  13. package/client/styled/template/manage.ts +14 -13
  14. package/client/utils/common.ts +23 -21
  15. package/client/utils/cookie.ts +18 -19
  16. package/client/utils/fetch.ts +64 -100
  17. package/client/utils/menu.tsx +16 -3
  18. package/client/utils/sso.ts +74 -84
  19. package/eslint.config.js +38 -1
  20. package/generation/README.md +25 -6
  21. package/generation/__tests__/example.test.js +41 -0
  22. package/generation/client/utils/menu.tsx +9 -2
  23. package/generation/env.example +3 -0
  24. package/generation/eslint.config.js +112 -0
  25. package/generation/gitignore +6 -1
  26. package/generation/jest.config.js +40 -0
  27. package/generation/package.json +24 -3
  28. package/jest.config.js +23 -6
  29. package/lib/args.js +9 -1
  30. package/lib/cli/app.d.ts +28 -0
  31. package/lib/cli/app.js +99 -0
  32. package/lib/cli/commands/build.d.ts +2 -0
  33. package/lib/cli/commands/build.js +29 -0
  34. package/lib/cli/commands/create.d.ts +2 -0
  35. package/lib/cli/commands/create.js +113 -0
  36. package/lib/cli/commands/delete.d.ts +3 -0
  37. package/lib/cli/commands/delete.js +151 -0
  38. package/lib/cli/commands/export.d.ts +2 -0
  39. package/lib/cli/commands/export.js +42 -0
  40. package/lib/cli/commands/help.d.ts +2 -0
  41. package/lib/cli/commands/help.js +42 -0
  42. package/lib/cli/commands/init.d.ts +2 -0
  43. package/lib/cli/commands/init.js +115 -0
  44. package/lib/cli/commands/server.d.ts +3 -0
  45. package/lib/cli/commands/server.js +26 -0
  46. package/lib/cli/commands/upgrade.d.ts +2 -0
  47. package/lib/cli/commands/upgrade.js +38 -0
  48. package/lib/cli/commands/version.d.ts +2 -0
  49. package/lib/cli/commands/version.js +24 -0
  50. package/lib/cli/index.d.ts +16 -0
  51. package/lib/cli/index.js +33 -0
  52. package/lib/cli/parser.d.ts +22 -0
  53. package/lib/cli/parser.js +115 -0
  54. package/lib/cli/registry.d.ts +33 -0
  55. package/lib/cli/registry.js +81 -0
  56. package/lib/cli/types/project.d.ts +10 -0
  57. package/lib/cli/types/project.js +2 -0
  58. package/lib/cli/types.d.ts +31 -0
  59. package/lib/cli/types.js +20 -0
  60. package/lib/cli/utils/console.d.ts +62 -0
  61. package/lib/cli/utils/console.js +148 -0
  62. package/lib/cli/utils/index.d.ts +2 -0
  63. package/lib/cli/utils/index.js +7 -0
  64. package/lib/cli/utils/prompt.d.ts +83 -0
  65. package/lib/cli/utils/prompt.js +368 -0
  66. package/lib/constants.d.ts +58 -0
  67. package/lib/constants.js +162 -0
  68. package/lib/generate.d.ts +25 -3
  69. package/lib/generate.js +97 -621
  70. package/lib/generate_create.d.ts +9 -0
  71. package/lib/generate_create.js +326 -0
  72. package/lib/generate_delete.d.ts +8 -0
  73. package/lib/generate_delete.js +156 -0
  74. package/lib/generate_init.d.ts +50 -0
  75. package/lib/generate_init.js +492 -0
  76. package/lib/generators/base-generator.d.ts +47 -0
  77. package/lib/generators/base-generator.js +92 -0
  78. package/lib/generators/generator-factory.d.ts +20 -0
  79. package/lib/generators/generator-factory.js +25 -0
  80. package/lib/generators/page-generator.d.ts +41 -0
  81. package/lib/generators/page-generator.js +552 -0
  82. package/lib/generators/resolver-generator.d.ts +12 -0
  83. package/lib/generators/resolver-generator.js +303 -0
  84. package/lib/generators/schema-generator.d.ts +7 -0
  85. package/lib/generators/schema-generator.js +57 -0
  86. package/lib/generators/service-generator.d.ts +7 -0
  87. package/lib/generators/service-generator.js +119 -0
  88. package/lib/generators/sql-generator.d.ts +8 -0
  89. package/lib/generators/sql-generator.js +52 -0
  90. package/lib/index.d.ts +1 -1
  91. package/lib/index.js +14 -173
  92. package/lib/server/csrf.js +9 -16
  93. package/lib/server/db.js +6 -7
  94. package/lib/server/graphql.js +5 -6
  95. package/lib/server/plugins/date.js +1 -1
  96. package/lib/server/utils/graphql-cache.js +3 -3
  97. package/lib/tsconfig.build.tsbuildinfo +1 -1
  98. package/lib/utils/project-config.d.ts +5 -0
  99. package/lib/utils/project-config.js +145 -0
  100. package/lib/utils.js +1 -1
  101. package/next.config.js +12 -8
  102. package/package.json +10 -7
  103. package/pages/_app.tsx +23 -28
  104. package/pages/_document.tsx +39 -19
  105. package/pages/index.tsx +84 -39
  106. package/pages/login.tsx +21 -21
  107. package/pages/template/manage.tsx +114 -89
  108. package/public/fonts/font-awesome.min.css +4 -0
  109. package/public/fonts/fontawesome-webfont.woff +0 -0
  110. package/public/fonts/fontawesome-webfont.woff2 +0 -0
  111. package/public/slbhealthcheck.html +1 -1
  112. package/server/apis/template.js +0 -2
  113. package/generation/eslintrc.js +0 -16
@@ -5,16 +5,16 @@ import _ from 'lodash'
5
5
 
6
6
  const env = getLocalEnv()
7
7
 
8
- const LOGIN_COOKIE_ID = env + '_cas_nsgm'
9
- const LOGIN_COOKIE_USER = env + '_nsgm_user'
8
+ const LOGIN_COOKIE_ID = `${env}_cas_nsgm`
9
+ const LOGIN_COOKIE_USER = `${env}_nsgm_user`
10
10
 
11
11
  const getPrincipalUrl = () => {
12
- const url = getLocalApiPrefix() + '/rest/sso/sessionCheck'
12
+ const url = `${getLocalApiPrefix()}/rest/sso/sessionCheck`
13
13
  return url
14
14
  }
15
15
 
16
16
  const getValidateUrl = () => {
17
- const url = getLocalApiPrefix() + '/rest/sso/ticketCheck'
17
+ const url = `${getLocalApiPrefix()}/rest/sso/ticketCheck`
18
18
  return url
19
19
  }
20
20
 
@@ -33,18 +33,17 @@ const handleLocationHref = () => {
33
33
  if (paramStr.indexOf('&') !== -1) {
34
34
  const paramArr = paramStr.split('&')
35
35
 
36
- _.each(paramArr, (item, index) => {
36
+ _.each(paramArr, (item) => {
37
37
  if (item.indexOf('=') !== -1) {
38
38
  const itemArr = item.split('=')
39
39
  const itemArrLen = itemArr.length
40
40
 
41
41
  const key = itemArr[0]
42
42
  let value = ''
43
- if (itemArrLen > 1)
44
- value = itemArr[1]
43
+ if (itemArrLen > 1) value = itemArr[1]
45
44
 
46
45
  if ('ticket' !== key) {
47
- newParamStr += key + '=' + value + '&'
46
+ newParamStr += `${key}=${value}&`
48
47
  }
49
48
  }
50
49
  })
@@ -58,16 +57,12 @@ const handleLocationHref = () => {
58
57
  }
59
58
 
60
59
  const locationHrefArrFirst = locationHrefArr[0]
61
- if (newParamStr !== '')
62
- newHref = locationHrefArrFirst + '?' + newParamStr
63
- else
64
- newHref = locationHrefArrFirst
60
+ if (newParamStr !== '') newHref = `${locationHrefArrFirst}?${newParamStr}`
61
+ else newHref = locationHrefArrFirst
65
62
  } else {
66
63
  newHref = locationHref
67
64
  }
68
65
  }
69
-
70
- // console.log('newHref', newHref)
71
66
  return encodeURIComponent(newHref)
72
67
  }
73
68
 
@@ -76,16 +71,7 @@ const jumpToLogin = () => {
76
71
  delCookie(LOGIN_COOKIE_USER)
77
72
 
78
73
  if (typeof window !== 'undefined') {
79
- window.location.href = window.location.origin + '/login'
80
- }
81
- }
82
-
83
- const jumpToLogout = () => {
84
- delCookie(LOGIN_COOKIE_ID)
85
- delCookie(LOGIN_COOKIE_USER)
86
-
87
- if (typeof window !== 'undefined') {
88
- window.location.href = window.location.origin
74
+ window.location.href = `${window.location.origin}/login`
89
75
  }
90
76
  }
91
77
 
@@ -93,44 +79,50 @@ const principalLogin = (cookie: string, callback: any) => {
93
79
  let url = getPrincipalUrl()
94
80
 
95
81
  if (typeof window !== 'undefined') {
96
- url += '?cookieValue=' + cookie + '&redirectUrl=' + handleLocationHref()
82
+ url += `?cookieValue=${cookie}&redirectUrl=${handleLocationHref()}`
97
83
  }
98
84
 
99
- // console.log('principalLogin_url', url)
100
- axios.get(url, { params: { credentials: 'include' } }).then((res: any) => {
101
- // console.log('principalLogin_res', res)
102
- const { data } = res
103
- if (data) {
104
- const { returnCode, userAttr } = data
105
- if (returnCode !== 0) {
106
- jumpToLogin()
85
+ axios
86
+ .get(url, { params: { credentials: 'include' } })
87
+ .then((res: any) => {
88
+ const { data } = res
89
+ if (data) {
90
+ const { returnCode, userAttr } = data
91
+ if (returnCode !== 0) {
92
+ jumpToLogin()
93
+ } else {
94
+ storeLoginUser(userAttr, callback)
95
+ }
107
96
  } else {
108
- storeLoginUser(userAttr, callback)
97
+ jumpToLogin()
109
98
  }
110
- } else {
99
+ })
100
+ .catch((e) => {
101
+ console.error('principalLogin_exception', e)
111
102
  jumpToLogin()
112
- }
113
- }).catch((e) => {
114
- console.log('principalLogin_exception', e)
115
- jumpToLogin()
116
- })
103
+ })
117
104
  }
118
105
 
119
106
  const storeLoginUser = (userAttr: any, callback: any) => {
120
- // console.log('storeLoginUser', userAttr)
121
-
122
107
  if (userAttr) {
123
- const user = JSON.stringify(userAttr, ['city', 'company', 'department', 'displayName', 'employee', 'mail', 'name', 'sn'])
108
+ const user = JSON.stringify(userAttr, [
109
+ 'city',
110
+ 'company',
111
+ 'department',
112
+ 'displayName',
113
+ 'employee',
114
+ 'mail',
115
+ 'name',
116
+ 'sn',
117
+ ])
124
118
  setCookie(LOGIN_COOKIE_USER, user, null)
125
- callback && callback(JSON.parse(user))
119
+ callback?.(JSON.parse(user))
126
120
  } else {
127
- callback && callback()
121
+ callback?.()
128
122
  }
129
123
  }
130
124
 
131
125
  const storeLogin = (cookie: any, cookieExpire: any, userAttr: any, callback: any) => {
132
- // console.log('storeLogin_cookie', cookie)
133
-
134
126
  if (cookie) {
135
127
  setCookie(LOGIN_COOKIE_ID, cookie, cookieExpire)
136
128
  }
@@ -138,51 +130,50 @@ const storeLogin = (cookie: any, cookieExpire: any, userAttr: any, callback: any
138
130
  storeLoginUser(userAttr, callback)
139
131
  }
140
132
 
141
- const validateLogin = (ticket: string, name: string = '', callback: any) => {
133
+ const validateLogin = (ticket: string, name = '', callback: any) => {
142
134
  let url = getValidateUrl()
143
135
 
144
136
  if (typeof window !== 'undefined') {
145
- url += '?ticket=' + ticket
137
+ url += `?ticket=${ticket}`
146
138
 
147
139
  if (name !== '') {
148
- url += '&name=' + name
140
+ url += `&name=${name}`
149
141
  }
150
142
  }
151
143
 
152
- // console.log('validateLogin_url', url)
153
- axios.get(url, { params: { credentials: 'include' } }).then((res: any) => {
154
- // console.log('validateLogin_res', res)
155
-
156
- if (res) {
157
- const { data } = res
158
- if (data) {
159
- const { cookieValue, cookieExpire, returnCode, userAttr } = data
160
- if (returnCode === 0) {
161
- storeLogin(cookieValue, cookieExpire, userAttr, callback)
144
+ axios
145
+ .get(url, { params: { credentials: 'include' } })
146
+ .then((res: any) => {
147
+ if (res) {
148
+ const { data } = res
149
+ if (data) {
150
+ const { cookieValue, cookieExpire, returnCode, userAttr } = data
151
+ if (returnCode === 0) {
152
+ storeLogin(cookieValue, cookieExpire, userAttr, callback)
153
+ } else {
154
+ jumpToLogin()
155
+ }
162
156
  } else {
163
157
  jumpToLogin()
164
158
  }
165
159
  } else {
166
160
  jumpToLogin()
167
161
  }
168
- } else {
169
- jumpToLogin()
170
- }
171
- }).catch((e) => {
172
- console.log('validateLogin_exception', e)
173
- })
162
+ })
163
+ .catch((e) => {
164
+ console.error('validateLogin_exception', e)
165
+ })
174
166
  }
175
167
 
176
168
  export const login = (callback: any) => {
177
169
  const cookieLoginValue = getCookie(LOGIN_COOKIE_ID)
178
- // console.log('cookieLoginValue', cookieLoginValue)
179
170
 
180
171
  if (typeof window !== 'undefined') {
181
172
  const locationHref = window.location.href
182
173
 
183
174
  // 如果已经在登录页面,不需要进行登录检查
184
175
  if (locationHref.indexOf('/login') !== -1) {
185
- callback && callback()
176
+ callback?.()
186
177
  return
187
178
  }
188
179
 
@@ -204,42 +195,41 @@ export const login = (callback: any) => {
204
195
  principalLogin(cookieLoginValue, callback)
205
196
  }
206
197
  } else {
207
- callback && callback()
198
+ callback?.()
208
199
  }
209
200
  }
210
201
 
211
202
  export const directLogin = (userName: string, userPassword: string, callback: any) => {
212
203
  if (userName === '') {
213
- return { success: false, message: '请输入用户名' };
204
+ return { success: false, message: '请输入用户名' }
214
205
  }
215
206
  if (userPassword === '') {
216
- return { success: false, message: '请输入密码' };
207
+ return { success: false, message: '请输入密码' }
217
208
  }
218
209
 
219
210
  // 使用 encodeURIComponent 处理可能的特殊字符,然后再进行 Base64 编码
220
- const safeStr = handleXSS(userName + "," + userPassword);
221
- const encodedName = btoa(encodeURIComponent(safeStr));
222
- const url = `${getLocalApiPrefix()}/rest/sso/ticketCheck?ticket=XXX&name=${encodedName}`;
211
+ const safeStr = handleXSS(`${userName},${userPassword}`)
212
+ const encodedName = btoa(encodeURIComponent(safeStr))
213
+ const url = `${getLocalApiPrefix()}/rest/sso/ticketCheck?ticket=XXX&name=${encodedName}`
223
214
 
224
215
  return fetch(url)
225
- .then(response => response.json())
226
- .then(data => {
216
+ .then((response) => response.json())
217
+ .then((data) => {
227
218
  if (data && data.returnCode === 0) {
228
219
  // 登录成功,设置cookie
229
220
  if (typeof window !== 'undefined') {
230
- storeLogin(data.cookieValue, data.cookieExpire, data.userAttr, callback);
231
- return { success: true };
221
+ storeLogin(data.cookieValue, data.cookieExpire, data.userAttr, callback)
222
+ return { success: true }
232
223
  }
233
224
  }
234
- return { success: false, message: '用户名或密码错误' };
225
+ return { success: false, message: '用户名或密码错误' }
226
+ })
227
+ .catch((error) => {
228
+ console.error('登录请求失败:', error)
229
+ return { success: false, message: '登录请求失败,请稍后重试' }
235
230
  })
236
- .catch(error => {
237
- console.error('登录请求失败:', error);
238
- return { success: false, message: '登录请求失败,请稍后重试' };
239
- });
240
231
  }
241
232
 
242
233
  export const logout = () => {
243
234
  jumpToLogin()
244
235
  }
245
-
package/eslint.config.js CHANGED
@@ -6,7 +6,8 @@ const prettier = require('eslint-plugin-prettier');
6
6
  module.exports = [
7
7
  js.configs.recommended,
8
8
  {
9
- files: ['src/**/*.{ts,tsx}'],
9
+ files: ['src/**/*.{ts,tsx}', 'client/**/*.{ts,tsx}', 'pages/**/*.{ts,tsx}'],
10
+ ignores: ['**/__tests__/**/*'],
10
11
  languageOptions: {
11
12
  parser: typescriptParser,
12
13
  parserOptions: {
@@ -55,6 +56,42 @@ module.exports = [
55
56
  'prettier/prettier': 'error'
56
57
  }
57
58
  },
59
+ {
60
+ files: ['**/__tests__/**/*.{ts,tsx}', '**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'],
61
+ languageOptions: {
62
+ parser: typescriptParser,
63
+ parserOptions: {
64
+ ecmaVersion: 2022,
65
+ sourceType: 'module'
66
+ },
67
+ globals: {
68
+ describe: 'readonly',
69
+ test: 'readonly',
70
+ expect: 'readonly',
71
+ beforeEach: 'readonly',
72
+ afterEach: 'readonly',
73
+ beforeAll: 'readonly',
74
+ afterAll: 'readonly',
75
+ jest: 'readonly',
76
+ __dirname: 'readonly',
77
+ __filename: 'readonly',
78
+ process: 'readonly',
79
+ Buffer: 'readonly',
80
+ console: 'readonly'
81
+ }
82
+ },
83
+ plugins: {
84
+ '@typescript-eslint': typescript,
85
+ 'prettier': prettier
86
+ },
87
+ rules: {
88
+ 'no-console': 'off',
89
+ 'no-undef': 'off',
90
+ 'no-unused-vars': 'off',
91
+ '@typescript-eslint/no-explicit-any': 'off',
92
+ 'prettier/prettier': 'error'
93
+ }
94
+ },
58
95
  {
59
96
  files: ['**/*.js'],
60
97
  languageOptions: {
@@ -8,6 +8,7 @@
8
8
  - [Styled-components](https://github.com/styled-components/styled-components) - CSS-in-JS 解决方案
9
9
  - [GraphQL](https://graphql.org/) - API 查询语言
10
10
  - [MySQL](https://www.mysql.com/) - 关系型数据库
11
+ - [Jest](https://jestjs.io/) - JavaScript 测试框架
11
12
  - 安全登录系统 - 基于 bcrypt 加密
12
13
 
13
14
  ## 快速入门
@@ -21,6 +22,14 @@
21
22
  | `npm run build` | 编译项目 |
22
23
  | `npm run export` | 导出静态页面 |
23
24
 
25
+ ### 测试命令
26
+
27
+ | 命令 | 说明 |
28
+ | ----------------------- | ---------------- |
29
+ | `npm test` | 运行所有测试 |
30
+ | `npm run test:watch` | 监视模式运行测试 |
31
+ | `npm run test:coverage` | 生成覆盖率报告 |
32
+
24
33
  ### 代码生成命令
25
34
 
26
35
  | 命令 | 说明 |
@@ -30,10 +39,10 @@
30
39
 
31
40
  ### 项目维护命令
32
41
 
33
- | 命令 | 说明 |
34
- | ----------------------------------- | ---------------- |
35
- | `npm run upgrade` | 升级项目基础文件 |
36
- | `npm run generate-password [密码]` | 生成安全密码哈希 |
42
+ | 命令 | 说明 |
43
+ | ---------------------------------- | ---------------- |
44
+ | `npm run upgrade` | 升级项目基础文件 |
45
+ | `npm run generate-password [密码]` | 生成安全密码哈希 |
37
46
 
38
47
  ## 参数说明
39
48
 
@@ -70,6 +79,7 @@
70
79
  ## 项目结构
71
80
 
72
81
  ```
82
+ ├── __tests__/ # 测试文件
73
83
  ├── components/ # 公共组件
74
84
  ├── pages/ # 页面文件
75
85
  │ ├── api/ # API 路由
@@ -80,6 +90,8 @@
80
90
  │ ├── modules/ # GraphQL 解析器和模式
81
91
  │ └── plugins/ # GraphQL 插件
82
92
  ├── styles/ # 全局样式
93
+ ├── coverage/ # 测试覆盖率报告
94
+ ├── jest.config.js # Jest 测试配置
83
95
  ├── next.config.js # Next.js 配置
84
96
  ├── mysql.config.js # MySQL 配置
85
97
  └── project.config.js # 项目配置
@@ -180,8 +192,15 @@ module.exports = {
180
192
 
181
193
  1. **创建新页面**:使用 `npm run create [controller] [action]` 命令
182
194
  2. **启动开发服务器**:运行 `npm run dev`
183
- 3. **构建生产版本**:运行 `npm run build` 然后 `npm run start`
184
- 4. **导出静态网站**:运行 `npm run export`
195
+ 3. **运行测试**:使用 `npm test` 运行测试,`npm run test:watch` 进行开发时的实时测试
196
+ 4. **构建生产版本**:运行 `npm run build` 然后 `npm run start`
197
+ 5. **导出静态网站**:运行 `npm run export`
198
+
199
+ ### 测试开发
200
+
201
+ - 测试文件放在 `__tests__/` 目录下
202
+ - 测试文件以 `.test.js`、`.test.ts`、`.spec.js` 或 `.spec.ts` 结尾
203
+ - 查看测试覆盖率报告:运行 `npm run test:coverage` 后打开 `coverage/index.html`
185
204
 
186
205
  ## 更多资源
187
206
 
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Example test file to demonstrate Jest configuration
3
+ * This file can be removed or modified according to your project needs
4
+ */
5
+
6
+ describe('Jest Configuration Test', () => {
7
+ test('Jest is properly configured', () => {
8
+ expect(true).toBe(true)
9
+ })
10
+
11
+ test('Basic math operations', () => {
12
+ expect(2 + 2).toBe(4)
13
+ expect(5 * 3).toBe(15)
14
+ expect(10 / 2).toBe(5)
15
+ })
16
+
17
+ test('String operations', () => {
18
+ const testString = 'Hello, World!'
19
+ expect(testString).toContain('World')
20
+ expect(testString.length).toBe(13)
21
+ })
22
+
23
+ test('Array operations', () => {
24
+ const testArray = [1, 2, 3, 4, 5]
25
+ expect(testArray).toHaveLength(5)
26
+ expect(testArray).toContain(3)
27
+ expect(testArray[0]).toBe(1)
28
+ })
29
+
30
+ test('Object operations', () => {
31
+ const testObject = {
32
+ name: 'Test',
33
+ version: '1.0.0',
34
+ active: true
35
+ }
36
+
37
+ expect(testObject).toHaveProperty('name')
38
+ expect(testObject.name).toBe('Test')
39
+ expect(testObject.active).toBeTruthy()
40
+ })
41
+ })
@@ -5,7 +5,14 @@ let key = 1
5
5
 
6
6
  export default [
7
7
  {
8
- key: key.toString(),
8
+ key: (++key).toString(),
9
+ text: '', // 空目录不显示,为了使用 SolutionOutlined 而不报错
10
+ url: '/',
11
+ icon: <SolutionOutlined rev={undefined} />,
12
+ subMenus: null
13
+ },
14
+ {
15
+ key: (++key).toString(),
9
16
  text: '介绍',
10
17
  url: '/',
11
18
  icon: <BookOutlined rev={undefined} />,
@@ -23,5 +30,5 @@ export default [
23
30
  url: '/template/manage'
24
31
  }
25
32
  ]
26
- },*/
33
+ }*/
27
34
  ]
@@ -0,0 +1,3 @@
1
+ # Login Configuration
2
+ LOGIN_USERNAME=admin
3
+ LOGIN_PASSWORD_HASH=$2b$10$example_bcrypt_hash_here
@@ -0,0 +1,112 @@
1
+ const js = require('@eslint/js');
2
+ const typescript = require('@typescript-eslint/eslint-plugin');
3
+ const typescriptParser = require('@typescript-eslint/parser');
4
+ const prettier = require('eslint-plugin-prettier');
5
+
6
+ module.exports = [
7
+ js.configs.recommended,
8
+ {
9
+ files: ['client/**/*.{ts,tsx}', 'pages/**/*.{ts,tsx}', 'src/**/*.{ts,tsx}'],
10
+ languageOptions: {
11
+ parser: typescriptParser,
12
+ parserOptions: {
13
+ ecmaVersion: 2022,
14
+ sourceType: 'module',
15
+ project: './tsconfig.json'
16
+ },
17
+ globals: {
18
+ __dirname: 'readonly',
19
+ __filename: 'readonly',
20
+ process: 'readonly',
21
+ Buffer: 'readonly',
22
+ console: 'readonly'
23
+ }
24
+ },
25
+ plugins: {
26
+ '@typescript-eslint': typescript,
27
+ 'prettier': prettier
28
+ },
29
+ rules: {
30
+ 'no-console': 'off',
31
+ 'no-undef': 'off',
32
+ 'no-unused-vars': 'off',
33
+ 'prefer-const': 'warn',
34
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
35
+ '@typescript-eslint/no-var-requires': 'off',
36
+ '@typescript-eslint/no-explicit-any': 'warn',
37
+ '@typescript-eslint/no-unused-vars': ['warn', {
38
+ argsIgnorePattern: '^_',
39
+ varsIgnorePattern: '^_'
40
+ }],
41
+ 'prettier/prettier': 'error',
42
+ 'no-unreachable': 'error',
43
+ 'no-duplicate-imports': 'error',
44
+ 'prefer-template': 'warn',
45
+ '@typescript-eslint/prefer-optional-chain': 'warn'
46
+ }
47
+ },
48
+ {
49
+ files: ['**/__tests__/**/*.{ts,tsx,js}', '**/*.test.{ts,tsx,js}', '**/*.spec.{ts,tsx,js}'],
50
+ languageOptions: {
51
+ parser: typescriptParser,
52
+ parserOptions: {
53
+ ecmaVersion: 2022,
54
+ sourceType: 'module'
55
+ },
56
+ globals: {
57
+ describe: 'readonly',
58
+ test: 'readonly',
59
+ expect: 'readonly',
60
+ beforeEach: 'readonly',
61
+ afterEach: 'readonly',
62
+ beforeAll: 'readonly',
63
+ afterAll: 'readonly',
64
+ jest: 'readonly',
65
+ __dirname: 'readonly',
66
+ __filename: 'readonly',
67
+ process: 'readonly',
68
+ Buffer: 'readonly',
69
+ console: 'readonly'
70
+ }
71
+ },
72
+ plugins: {
73
+ '@typescript-eslint': typescript,
74
+ 'prettier': prettier
75
+ },
76
+ rules: {
77
+ 'no-console': 'off',
78
+ 'no-undef': 'off',
79
+ 'no-unused-vars': 'off',
80
+ '@typescript-eslint/no-explicit-any': 'off',
81
+ 'prettier/prettier': 'error'
82
+ }
83
+ },
84
+ {
85
+ files: ['**/*.js'],
86
+ languageOptions: {
87
+ ecmaVersion: 2022,
88
+ sourceType: 'commonjs',
89
+ globals: {
90
+ require: 'readonly',
91
+ module: 'readonly',
92
+ exports: 'readonly',
93
+ __dirname: 'readonly',
94
+ __filename: 'readonly',
95
+ process: 'readonly',
96
+ Buffer: 'readonly',
97
+ console: 'readonly'
98
+ }
99
+ },
100
+ rules: {
101
+ 'no-console': 'off'
102
+ }
103
+ },
104
+ {
105
+ ignores: [
106
+ 'node_modules/**',
107
+ '.next/**',
108
+ 'coverage/**',
109
+ '*.config.js'
110
+ ]
111
+ }
112
+ ];
@@ -2,4 +2,9 @@ node_modules
2
2
  .next
3
3
  out
4
4
  build
5
- scripts/dump.*
5
+ scripts/dump.*
6
+ .env
7
+ .env.local
8
+ .env.production
9
+ .env.development
10
+ *.log
@@ -0,0 +1,40 @@
1
+ module.exports = {
2
+ testEnvironment: 'jsdom',
3
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
4
+ transform: {
5
+ '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }]
6
+ },
7
+ transformIgnorePatterns: ['/node_modules/', '^.+\\.module\\.(css|sass|scss|less)$'],
8
+ moduleNameMapper: {
9
+ '^@/(.*)$': '<rootDir>/$1',
10
+ '^~/(.*)$': '<rootDir>/$1'
11
+ },
12
+ setupFiles: ['<rootDir>/jest.setup-globals.js'],
13
+ testMatch: [
14
+ '**/__tests__/**/*.(ts|tsx|js)',
15
+ '**/*.(test|spec).(ts|tsx|js)'
16
+ ],
17
+ collectCoverage: true,
18
+ collectCoverageFrom: [
19
+ 'client/**/*.{js,jsx,ts,tsx}',
20
+ 'pages/**/*.{js,jsx,ts,tsx}',
21
+ 'server/**/*.{js,jsx,ts,tsx}',
22
+ '!**/*.d.ts',
23
+ '!**/node_modules/**',
24
+ '!**/.next/**',
25
+ '!**/coverage/**',
26
+ '!**/*.config.js'
27
+ ],
28
+ coverageDirectory: 'coverage',
29
+ coverageReporters: ['json', 'lcov', 'text', 'clover', 'html'],
30
+ coverageThreshold: {
31
+ global: {
32
+ branches: 70,
33
+ functions: 70,
34
+ lines: 70,
35
+ statements: 70
36
+ }
37
+ },
38
+ testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
39
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
40
+ }
@@ -2,7 +2,7 @@
2
2
  "name": "nsgm-cli-project",
3
3
  "version": "1.0.0",
4
4
  "description": "",
5
- "main": "index.js",
5
+ "main": "app.js",
6
6
  "scripts": {
7
7
  "dev": "nsgm dev",
8
8
  "build": "nsgm build",
@@ -15,8 +15,29 @@
15
15
  "deletedb": "nsgm deletedb",
16
16
  "generate-password": "node scripts/generate-password-hash.js",
17
17
  "postversion": "git push && git push --tags",
18
- "test": "echo \"Error: no test specified\" && exit 1"
18
+ "test": "jest",
19
+ "test:watch": "jest --watch",
20
+ "test:coverage": "jest --coverage"
19
21
  },
20
22
  "author": "",
21
- "license": "ISC"
23
+ "license": "ISC",
24
+ "dependencies": {
25
+ "nsgm-cli": "^2"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20",
29
+ "@types/react": "^18",
30
+ "@types/lodash": "^4",
31
+ "typescript": "^5",
32
+ "jest": "^30",
33
+ "jest-environment-jsdom": "^30",
34
+ "@testing-library/jest-dom": "^6",
35
+ "@testing-library/react": "^14",
36
+ "@testing-library/user-event": "^14",
37
+ "@types/jest": "^30",
38
+ "eslint": "^9",
39
+ "eslint-config-prettier": "^10",
40
+ "eslint-plugin-prettier": "^5",
41
+ "prettier": "^3"
42
+ }
22
43
  }