nsgm-cli 2.1.9 → 2.1.11

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
@@ -16,26 +16,28 @@ A full-stack development framework with code template generation capabilities, h
16
16
  - Rapid development workflow
17
17
  - Integrated GraphQL API
18
18
  - MySQL database support
19
+ - Secure login system with bcrypt encryption
19
20
 
20
21
  ## Command Line Tools
21
22
 
22
23
  ### Basic Commands
23
24
 
24
- | Command | Description |
25
- |------|------|
26
- | `nsgm init` | Initialize project |
27
- | `nsgm upgrade` | Upgrade project base files |
28
- | `nsgm create` | Create template page |
29
- | `nsgm delete` | Delete template page |
25
+ | Command | Description |
26
+ | --------------- | --------------------------------------- |
27
+ | `nsgm init` | Initialize project |
28
+ | `nsgm upgrade` | Upgrade project base files |
29
+ | `nsgm create` | Create template page |
30
+ | `nsgm delete` | Delete template page |
30
31
  | `nsgm deletedb` | Delete template page and database table |
31
- | `nsgm dev` | Development mode |
32
- | `nsgm start` | Production mode |
33
- | `nsgm build` | Build project |
34
- | `nsgm export` | Export static pages |
32
+ | `nsgm dev` | Development mode |
33
+ | `nsgm start` | Production mode |
34
+ | `nsgm build` | Build project |
35
+ | `nsgm export` | Export static pages |
35
36
 
36
37
  ### Parameter Description
37
38
 
38
39
  - **dictionary**: Used with `export`/`init` commands, default value is `webapp`
40
+
39
41
  ```
40
42
  nsgm init dictionary=webapp
41
43
  # or simplified as
@@ -43,6 +45,7 @@ A full-stack development framework with code template generation capabilities, h
43
45
  ```
44
46
 
45
47
  - **controller**: Used with `create`/`delete` commands, required parameter
48
+
46
49
  ```
47
50
  nsgm create math
48
51
  ```
@@ -52,6 +55,29 @@ A full-stack development framework with code template generation capabilities, h
52
55
  nsgm create math test
53
56
  ```
54
57
 
58
+ ## Security Configuration
59
+
60
+ For security setup and login configuration, please refer to [SECURITY.md](./SECURITY.md).
61
+
62
+ ### Quick Setup
63
+
64
+ 1. Generate password hash:
65
+
66
+ ```bash
67
+ npm run generate-password yourSecurePassword
68
+ ```
69
+
70
+ 2. Create `.env` file:
71
+
72
+ ```bash
73
+ LOGIN_USERNAME=admin
74
+ LOGIN_PASSWORD_HASH=your_generated_hash_here
75
+ ```
76
+
77
+ 3. Make sure `.env` is in your `.gitignore` file.
78
+
79
+ **⚠️ Important:** Never commit passwords or `.env` files to version control.
80
+
55
81
  ## Project Configuration
56
82
 
57
83
  ### next.config.js
@@ -60,14 +86,17 @@ A full-stack development framework with code template generation capabilities, h
60
86
  const { nextConfig } = require('nsgm-cli')
61
87
  const projectConfig = require('./project.config')
62
88
 
63
- const { version, prefix, protocol, host } = projectConfig
89
+ const { version, prefix, protocol, host } = projectConfig
64
90
 
65
91
  module.exports = (phase, defaultConfig) => {
66
- let configObj = nextConfig(phase, defaultConfig, {
67
- version, prefix, protocol, host
68
- })
92
+ let configObj = nextConfig(phase, defaultConfig, {
93
+ version,
94
+ prefix,
95
+ protocol,
96
+ host
97
+ })
69
98
 
70
- return configObj
99
+ return configObj
71
100
  }
72
101
  ```
73
102
 
@@ -79,13 +108,13 @@ const { mysqlOptions } = mysqlConfig
79
108
  const { user, password, host, port, database } = mysqlOptions
80
109
 
81
110
  module.exports = {
82
- mysqlOptions: {
83
- user,
84
- password,
85
- host,
86
- port,
87
- database
88
- }
111
+ mysqlOptions: {
112
+ user,
113
+ password,
114
+ host,
115
+ port,
116
+ database
117
+ }
89
118
  }
90
119
  ```
91
120
 
@@ -99,11 +128,11 @@ const { prefix, protocol, host, port } = projectConfig
99
128
  const { version } = pkg
100
129
 
101
130
  module.exports = {
102
- version,
103
- prefix,
104
- protocol,
105
- host,
106
- port
131
+ version,
132
+ prefix,
133
+ protocol,
134
+ host,
135
+ port
107
136
  }
108
137
  ```
109
138
 
@@ -116,11 +145,11 @@ The `server` folder in the project root contains the following:
116
145
  - `apis/` - Stores REST API interfaces
117
146
  - `modules/` - Stores GraphQL resolvers and schemas
118
147
  - `plugins/` - Stores GraphQL plugins
119
- - `*.js` - Route files, e.g., `test.js` handles requests to `/test/*` and `${prefix}/test/*`
148
+ - `*.js` - Route files, e.g., `csrf-test.js` handles requests to `/csrf-test/*` and `${prefix}/csrf-test/*`
120
149
 
121
150
  ### Example Code
122
151
 
123
- #### Route File Example (server/test.js)
152
+ #### Route File Example (server/csrf-test.js)
124
153
 
125
154
  ```javascript
126
155
  const express = require('express')
@@ -129,14 +158,14 @@ const moment = require('moment')
129
158
  const router = express.Router()
130
159
 
131
160
  router.use((req, res, next) => {
132
- const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
133
- console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ' ' + fullUrl)
134
- next()
161
+ const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
162
+ console.log(moment().format('YYYY-MM-DD HH:mm:ss') + ' ' + fullUrl)
163
+ next()
135
164
  })
136
165
 
137
166
  router.get('/*', (req, res) => {
138
- res.statusCode = 200
139
- res.json({ name: 'TEST' })
167
+ res.statusCode = 200
168
+ res.json({ name: 'TEST' })
140
169
  })
141
170
 
142
171
  module.exports = router
@@ -149,8 +178,8 @@ const express = require('express')
149
178
  const router = express.Router()
150
179
 
151
180
  router.get('/*', (req, res) => {
152
- res.statusCode = 200
153
- res.json({ name: 'Hello' })
181
+ res.statusCode = 200
182
+ res.json({ name: 'Hello' })
154
183
  })
155
184
 
156
185
  module.exports = router
@@ -160,15 +189,15 @@ module.exports = router
160
189
 
161
190
  ```javascript
162
191
  module.exports = {
163
- query: `
192
+ query: `
164
193
  link: String
165
194
  `,
166
- mutation: `
195
+ mutation: `
167
196
  linkUpdate(link: Date): String
168
197
  `,
169
- subscription: ``,
170
- type: ``
171
- }
198
+ subscription: ``,
199
+ type: ``
200
+ }
172
201
  ```
173
202
 
174
203
  #### GraphQL Resolver Example (server/modules/link/resolver.js)
@@ -177,14 +206,14 @@ module.exports = {
177
206
  let localLink = ''
178
207
 
179
208
  module.exports = {
180
- link: () => {
181
- return localLink
182
- },
183
- linkUpdate: ({ link }) => {
184
- console.log('link', link)
185
- localLink = link
186
- return localLink
187
- }
209
+ link: () => {
210
+ return localLink
211
+ },
212
+ linkUpdate: ({ link }) => {
213
+ console.log('link', link)
214
+ localLink = link
215
+ return localLink
216
+ }
188
217
  }
189
218
  ```
190
219
 
@@ -196,14 +225,12 @@ const { Kind } = require('graphql/language')
196
225
  const { GraphQLScalarType } = require('graphql')
197
226
 
198
227
  const customScalarDate = new GraphQLScalarType({
199
- name: 'Date',
200
- description: 'Date custom scalar type',
201
- parseValue: value => moment(value).valueOf(),
202
- serialize: value => moment(value).format('YYYY-MM-DD HH:mm:ss:SSS'),
203
- parseLiteral: ast => (ast.kind === Kind.INT)
204
- ? parseInt(ast.value, 10)
205
- : null
228
+ name: 'Date',
229
+ description: 'Date custom scalar type',
230
+ parseValue: (value) => moment(value).valueOf(),
231
+ serialize: (value) => moment(value).format('YYYY-MM-DD HH:mm:ss:SSS'),
232
+ parseLiteral: (ast) => (ast.kind === Kind.INT ? parseInt(ast.value, 10) : null)
206
233
  })
207
234
 
208
235
  module.exports = { Date: customScalarDate }
209
- ```
236
+ ```
@@ -15,6 +15,19 @@ if (reducersKeysLen > 0) {
15
15
 
16
16
  export type RootState = ReturnType<typeof combineReducer>
17
17
 
18
+ // 创建一个临时 store 实例来获取正确的 dispatch 类型
19
+ const tempStore = configureStore({
20
+ reducer: combineReducer,
21
+ middleware: (getDefaultMiddleware) =>
22
+ getDefaultMiddleware({
23
+ serializableCheck: {
24
+ ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE'],
25
+ },
26
+ }),
27
+ })
28
+
29
+ export type AppDispatch = typeof tempStore.dispatch
30
+
18
31
  function initStore(initialState?: any): EnhancedStore {
19
32
  return configureStore({
20
33
  reducer: combineReducer,
@@ -1,11 +1,9 @@
1
1
  import * as types from './types'
2
2
  import { getTemplateService, addTemplateService, updateTemplateService, deleteTemplateService, searchTemplateService, batchDeleteTemplateService } from '@/service/template/manage'
3
+ import { AppDispatch } from '@/redux/store'
3
4
 
4
5
  export const getTemplate = (page=0, pageSize=10) => (
5
- dispatch: (arg0: {
6
- type: string
7
- payload?: { template: any }
8
- }) => void
6
+ dispatch: AppDispatch
9
7
  ) => {
10
8
  dispatch({
11
9
  type: types.GET_TEMPLATE
@@ -30,10 +28,7 @@ export const getTemplate = (page=0, pageSize=10) => (
30
28
  }
31
29
 
32
30
  export const searchTemplate = (page=0, pageSize=10, data: any) => (
33
- dispatch: (arg0: {
34
- type: string
35
- payload?: { template: any }
36
- }) => void
31
+ dispatch: AppDispatch
37
32
  ) => {
38
33
  dispatch({
39
34
  type: types.SEARCH_TEMPLATE
@@ -58,10 +53,7 @@ export const searchTemplate = (page=0, pageSize=10, data: any) => (
58
53
  }
59
54
 
60
55
  export const updateSSRTemplate = (template: any) => (
61
- dispatch: (arg0: {
62
- type: string
63
- payload?: { template: any }
64
- }) => void
56
+ dispatch: AppDispatch
65
57
  ) => {
66
58
  dispatch({
67
59
  type: types.UPDATE_SSR_TEMPLATE,
@@ -72,10 +64,7 @@ export const updateSSRTemplate = (template: any) => (
72
64
  }
73
65
 
74
66
  export const addTemplate = (obj:any) => (
75
- dispatch: (arg0: {
76
- type: string
77
- payload?: { template: any }
78
- }) => void
67
+ dispatch: AppDispatch
79
68
  ) => {
80
69
  dispatch({
81
70
  type: types.ADD_TEMPLATE
@@ -104,10 +93,7 @@ export const addTemplate = (obj:any) => (
104
93
  }
105
94
 
106
95
  export const modTemplate = (id: number, obj: any) => (
107
- dispatch: (arg0: {
108
- type: string
109
- payload?: { template: any }
110
- }) => void
96
+ dispatch: AppDispatch
111
97
  ) => {
112
98
  dispatch({
113
99
  type: types.MOD_TEMPLATE
@@ -135,10 +121,7 @@ export const modTemplate = (id: number, obj: any) => (
135
121
  }
136
122
 
137
123
  export const delTemplate = (id: number) => (
138
- dispatch: (arg0: {
139
- type: string
140
- payload?: { id: number }
141
- }) => void
124
+ dispatch: AppDispatch
142
125
  ) => {
143
126
  dispatch({
144
127
  type: types.DEL_TEMPLATE
@@ -163,10 +146,7 @@ export const delTemplate = (id: number) => (
163
146
  }
164
147
 
165
148
  export const batchDelTemplate = (ids:any) => (
166
- dispatch: (arg0: {
167
- type: string
168
- payload?: { ids: any }
169
- }) => void
149
+ dispatch: AppDispatch
170
150
  ) => {
171
151
  dispatch({
172
152
  type: types.BATCH_DEL_TEMPLATE
@@ -12,7 +12,7 @@ export const getTemplateService = (page = 0, pageSize = 10) => {
12
12
  return getLocalGraphql(getTemplateQuery, {
13
13
  page,
14
14
  pageSize
15
- })
15
+ }, true) // 启用缓存,因为这是查询操作
16
16
  }
17
17
 
18
18
  export const searchTemplateByIdService = (id: number) => {
@@ -24,7 +24,7 @@ export const searchTemplateByIdService = (id: number) => {
24
24
 
25
25
  return getLocalGraphql(searchTemplateByIdQuery, {
26
26
  id
27
- })
27
+ }, true) // 启用缓存,因为这是查询操作
28
28
  }
29
29
 
30
30
  export const searchTemplateService = (page = 0, pageSize = 10, data: any) => {
@@ -44,7 +44,7 @@ export const searchTemplateService = (page = 0, pageSize = 10, data: any) => {
44
44
  data: {
45
45
  name
46
46
  }
47
- })
47
+ }, true) // 启用缓存,因为这是查询操作
48
48
  }
49
49
 
50
50
  export const addTemplateService = (data: any) => {
@@ -56,7 +56,7 @@ export const addTemplateService = (data: any) => {
56
56
  data: {
57
57
  name
58
58
  }
59
- })
59
+ }, false) // 不使用缓存,因为这是变更操作,会自动添加 CSRF token
60
60
  }
61
61
 
62
62
  export const updateTemplateService = (id: number, data: any) => {
@@ -69,7 +69,7 @@ export const updateTemplateService = (id: number, data: any) => {
69
69
  data: {
70
70
  name
71
71
  }
72
- })
72
+ }, false) // 不使用缓存,因为这是变更操作,会自动添加 CSRF token
73
73
  }
74
74
 
75
75
  export const deleteTemplateService = (id: number) => {
@@ -77,7 +77,7 @@ export const deleteTemplateService = (id: number) => {
77
77
 
78
78
  return getLocalGraphql(deleteTemplateQuery, {
79
79
  id
80
- })
80
+ }, false) // 不使用缓存,因为这是变更操作,会自动添加 CSRF token
81
81
  }
82
82
 
83
83
  export const batchAddTemplateService = (datas: any) => {
@@ -85,7 +85,7 @@ export const batchAddTemplateService = (datas: any) => {
85
85
 
86
86
  return getLocalGraphql(batchAddTemplateQuery, {
87
87
  datas
88
- })
88
+ }, false) // 不使用缓存,因为这是变更操作,会自动添加 CSRF token
89
89
  }
90
90
 
91
91
  export const batchDeleteTemplateService = (ids: any) => {
@@ -93,5 +93,5 @@ export const batchDeleteTemplateService = (ids: any) => {
93
93
 
94
94
  return getLocalGraphql(batchDeleteTemplateQuery, {
95
95
  ids
96
- })
96
+ }, false) // 不使用缓存,因为这是变更操作,会自动添加 CSRF token
97
97
  }
@@ -18,8 +18,8 @@ export const getLocalApiPrefix = () => {
18
18
 
19
19
  if(!isExport){
20
20
  if (typeof window !== 'undefined') {
21
+ // 客户端:使用当前页面的 location
21
22
  const location = window.location
22
- // console.log('location', location)
23
23
 
24
24
  protocol = location.protocol
25
25
  if (protocol.indexOf(':') != -1) {
@@ -28,10 +28,10 @@ export const getLocalApiPrefix = () => {
28
28
  host = location.hostname
29
29
  port = location.port || (protocol.indexOf('https') !== -1 ? "443" : "80")
30
30
  }
31
+ // 服务器端:直接使用配置中的值,无需额外处理
31
32
  }
32
33
 
33
34
  localApiPrefix = protocol + '://' + host + ':' + port + prefix
34
- // console.log('localApiPrefix', localApiPrefix)
35
35
  return localApiPrefix
36
36
  }
37
37