nsgm-cli 2.0.11 → 2.0.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 (65) hide show
  1. package/.babelrc +12 -12
  2. package/LICENSE +201 -201
  3. package/README.md +161 -161
  4. package/client/layout/index.tsx +248 -248
  5. package/client/redux/reducers.ts +4 -4
  6. package/client/redux/store.ts +50 -50
  7. package/client/redux/template/manage/actions.ts +190 -190
  8. package/client/redux/template/manage/reducers.ts +118 -118
  9. package/client/redux/template/manage/types.ts +24 -24
  10. package/client/service/template/manage.ts +96 -96
  11. package/client/styled/common.ts +60 -60
  12. package/client/styled/layout/index.ts +25 -25
  13. package/client/styled/template/manage.ts +51 -51
  14. package/client/utils/common.ts +89 -89
  15. package/client/utils/cookie.ts +51 -51
  16. package/client/utils/fetch.ts +25 -25
  17. package/client/utils/menu.tsx +27 -27
  18. package/client/utils/sso.ts +205 -205
  19. package/generation/.babelrc +10 -10
  20. package/generation/README.md +19 -19
  21. package/generation/app.js +2 -2
  22. package/generation/client/redux/reducers.ts +4 -4
  23. package/generation/client/utils/menu.tsx +27 -27
  24. package/generation/gitignore +4 -4
  25. package/generation/mysql.config.js +12 -12
  26. package/generation/next.config.js +6 -6
  27. package/generation/package.json +24 -24
  28. package/generation/project.config.js +13 -13
  29. package/generation/server/rest.js +23 -23
  30. package/generation/server/utils/common.js +6 -6
  31. package/generation/tsconfig.json +30 -30
  32. package/index.js +10 -10
  33. package/lib/args.d.ts +6 -6
  34. package/lib/args.js +53 -53
  35. package/lib/generate.d.ts +3 -3
  36. package/lib/generate.js +751 -751
  37. package/lib/index.d.ts +2 -2
  38. package/lib/index.js +272 -272
  39. package/lib/server/db.d.ts +5 -5
  40. package/lib/server/db.js +110 -110
  41. package/lib/server/graphql.d.ts +7 -7
  42. package/lib/server/graphql.js +119 -119
  43. package/lib/server/plugins/date.d.ts +5 -5
  44. package/lib/server/plugins/date.js +16 -16
  45. package/lib/tsconfig.build.tsbuildinfo +1 -1
  46. package/mysql.config.js +14 -14
  47. package/next-env.d.ts +5 -5
  48. package/next.config.js +231 -231
  49. package/package.json +127 -126
  50. package/pages/_app.tsx +54 -54
  51. package/pages/_document.tsx +55 -55
  52. package/pages/index.tsx +68 -68
  53. package/pages/login.tsx +78 -78
  54. package/pages/template/manage.tsx +299 -278
  55. package/project.config.js +16 -16
  56. package/public/slbhealthcheck.html +9 -9
  57. package/scripts/shutdown.sh +9 -9
  58. package/scripts/startup.sh +34 -34
  59. package/server/apis/sso.js +43 -43
  60. package/server/apis/template.js +37 -17
  61. package/server/modules/template/resolver.js +225 -225
  62. package/server/modules/template/schema.js +33 -33
  63. package/server/rest.js +24 -24
  64. package/server/sql/template.sql +8 -8
  65. package/server/utils/common.js +6 -6
@@ -1,279 +1,300 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { ConfigProvider, Table, Modal, Button, Input, Space, Upload, message } from 'antd'
3
- import { Container, SearchRow, ModalContainer } from '../../client/styled/template/manage'
4
- import { useDispatch, useSelector } from 'react-redux'
5
- import { getTemplate, addTemplate, modTemplate, delTemplate, updateSSRTemplate, searchTemplate, batchDelTemplate } from '../../client/redux/template/manage/actions'
6
- import { getTemplateService } from '../../client/service/template/manage'
7
- import { RootState } from '../../client/redux/store'
8
- import _ from 'lodash'
9
- import moment from 'moment'
10
- import locale from 'antd/lib/locale/zh_CN'
11
- import { handleXSS, checkModalObj } from '../../client/utils/common'
12
- import XLSX from 'xlsx'
13
- import { UploadOutlined } from '@ant-design/icons'
14
-
15
- const pageSize = 100
16
- const dateFormat = 'YYYY-MM-DD'
17
- const currentDate = moment().format(dateFormat)
18
- console.log('currentDate', currentDate)
19
-
20
- const keyTitles = {
21
- name: '名称'
22
- }
23
-
24
- const Page = ({ template }) => {
25
- const dispatch = useDispatch()
26
- const [isModalVisiable, setIsModalVisible] = useState(false)
27
- const [modalId, setModalId] = useState(0)
28
- const [modalName, setModalName] = useState('')
29
- const [searchName, setSearchName] = useState('')
30
- const [batchDelIds, setBatchDelIds] = useState([])
31
-
32
- useEffect(() => {
33
- dispatch(updateSSRTemplate(template))
34
- }, [dispatch])
35
-
36
- const state = useSelector((state: RootState) => state)
37
- const { templateManage }:any = state
38
- console.log('templateManage', templateManage)
39
-
40
- if (!templateManage.firstLoadFlag) {
41
- template = templateManage.template
42
- }
43
-
44
- const { totalCounts, items:templateItems } = template
45
- console.log('template', template)
46
-
47
- _.each(templateItems, (item, index) => {
48
- const { id } = item
49
- item.key = id
50
- })
51
-
52
- const dataSource = templateItems
53
- const columns:any = [
54
- {
55
- title: 'ID',
56
- dataIndex: 'id',
57
- key: 'id',
58
- sorter: (a: any, b: any) => a.id - b.id,
59
- sortDirections: ['descend', 'ascend'],
60
- showSorterTooltip: false
61
- },
62
- {
63
- title: keyTitles.name,
64
- dataIndex: 'name',
65
- key: 'name',
66
- sorter: (a: any, b: any) => a.name.length - b.name.length,
67
- sortDirections: ['descend', 'ascend'],
68
- showSorterTooltip: false
69
- },
70
- {
71
- title: '操作',
72
- dataIndex: '',
73
- render: (_:any, record:any) => {
74
- return (
75
- <Space>
76
- <Button onClick={() => {
77
- console.log('record', record)
78
- updateTemplate(record)
79
- }}>修改</Button>
80
- <Button onClick={() => {
81
- console.log('record', record)
82
- const { id } = record
83
- deleteTemplate(id)
84
- }}>删除</Button>
85
- </Space>
86
- )
87
- }
88
- }
89
- ]
90
-
91
- const rowSelection = {
92
- onChange: (selectedRowKeys: any, selectedRows: any) => {
93
- console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows)
94
- setBatchDelIds(selectedRowKeys)
95
- }
96
- }
97
-
98
- const createTemplate = () => {
99
- setModalId(0)
100
- setModalName('')
101
- showModal()
102
- }
103
-
104
- const updateTemplate = (record:any) => {
105
- let { id, name } = record
106
-
107
- setModalId(id)
108
- setModalName(name)
109
- showModal()
110
- }
111
-
112
- const deleteTemplate = (id:number) => {
113
- Modal.confirm({
114
- title: '提示',
115
- content: '确认删除吗',
116
- okText: '确认',
117
- cancelText: '取消',
118
- onOk : (e) => {
119
- dispatch(delTemplate(id))
120
- Modal.destroyAll()
121
- }
122
- })
123
- }
124
-
125
- const showModal = () => {
126
- setIsModalVisible(true)
127
- }
128
-
129
- const getMessageTitle = (key: string) => {
130
- let result = keyTitles[key]
131
- if (result == undefined)
132
- result = key
133
- return result
134
- }
135
-
136
- const handleOk = () => {
137
- const modalObj = {
138
- name: handleXSS(modalName)
139
- }
140
- console.log('handleOk', modalObj)
141
-
142
- const checkResult = checkModalObj(modalObj)
143
-
144
- if (!checkResult) {
145
- if (modalId == 0) { // 新增
146
- dispatch(addTemplate(modalObj))
147
- } else {
148
- dispatch(modTemplate(modalId, modalObj))
149
- }
150
-
151
- setIsModalVisible(false)
152
- } else {
153
- message.info(getMessageTitle(checkResult.key) + checkResult.reason)
154
- }
155
- }
156
-
157
- const handleCancel = () => {
158
- setIsModalVisible(false)
159
- }
160
-
161
- const doSearch = () => {
162
- dispatch(searchTemplate(0, pageSize, { name: handleXSS(searchName) }))
163
- }
164
-
165
- const exportTemplate = () => {
166
- if (templateItems.length > 0) {
167
- const wb = XLSX.utils.book_new()
168
- const jsonData = _.map(templateItems, (item) => _.omit(item, ['key']))
169
- //console.log('jsonData', jsonData)
170
- const ws = XLSX.utils.json_to_sheet(jsonData)
171
-
172
- /* add worksheet to workbook */
173
- XLSX.utils.book_append_sheet(wb, ws, "Template")
174
-
175
- /* write workbook */
176
- XLSX.writeFile(wb, "Template.xlsx")
177
- } else {
178
- message.info("没有数据无需导出")
179
- }
180
- }
181
-
182
- const uploadProps = {
183
- name: 'file',
184
- action: '/rest/template/import',
185
- onChange(info:any) {
186
- if (info.file.status !== 'uploading') {
187
- console.log(info.file, info.fileList)
188
- }
189
-
190
- if (info.file.status === 'done') {
191
- message.success(`${info.file.name} 文件上传成功`)
192
- window.location.reload()
193
- } else if (info.file.status === 'error') {
194
- message.error(`${info.file.name} 文件上传失败`)
195
- }
196
- }
197
- }
198
-
199
- const batchDeleteTemplate = () => {
200
- if (batchDelIds.length > 0) {
201
- Modal.confirm({
202
- title: '提示',
203
- content: '确认批量删除吗',
204
- okText: '确认',
205
- cancelText: '取消',
206
- onOk : (e) => {
207
- dispatch(batchDelTemplate(batchDelIds))
208
- Modal.destroyAll()
209
- }
210
- })
211
- } else {
212
- message.info("没有数据不能批量删除")
213
- }
214
- }
215
-
216
- return (
217
- <Container>
218
- <ConfigProvider locale={locale}>
219
- <SearchRow>
220
- <Space>
221
- <Button type="primary" onClick={createTemplate}>
222
- 新增
223
- </Button>
224
- <Input value={searchName} placeholder="" onChange={(e) => setSearchName(e.target.value)} />
225
- <Button type="primary" onClick={doSearch}>
226
- 搜索
227
- </Button>
228
- <Button type="primary" onClick={exportTemplate}>
229
- 导出
230
- </Button>
231
- <Upload {...uploadProps}>
232
- <Button icon={<UploadOutlined rev={undefined} />}>导入</Button>
233
- </Upload>
234
- <Button type="primary" onClick={batchDeleteTemplate}>
235
- 批量删除
236
- </Button>
237
- </Space>
238
- </SearchRow>
239
- <Table rowSelection={{
240
- type: 'checkbox',
241
- ...rowSelection,
242
- }} dataSource={dataSource} columns={columns} pagination={{
243
- total: totalCounts,
244
- pageSize: pageSize,
245
- onChange: (page, pageSize) => {
246
- console.log('onChange', page, pageSize)
247
- dispatch(searchTemplate(page - 1, pageSize, { name: handleXSS(searchName) }))
248
- }
249
- }} />
250
- <Modal title={(modalId == 0 ? "新增" : "修改") + " template"} open={isModalVisiable} onOk={handleOk} onCancel={handleCancel} okText="确认" cancelText="取消">
251
- <ModalContainer>
252
- <div className="line">
253
- <label>{keyTitles.name}</label>
254
- <Input value={modalName} placeholder="" onChange={(e) => setModalName(e.target.value)} />
255
- </div>
256
- </ModalContainer>
257
- </Modal>
258
- </ConfigProvider>
259
- </Container>
260
- )
261
- }
262
-
263
- Page.getInitialProps = async () => {
264
- let template = null
265
-
266
- await getTemplateService(0, pageSize).then((res: any) => {
267
- console.log('res', res)
268
- const { data } = res
269
- template = data.template
270
- })
271
-
272
- console.log('template-getInitialProps', template)
273
-
274
- return {
275
- template
276
- }
277
- }
278
-
1
+ import React, { useEffect, useState } from 'react'
2
+ import { ConfigProvider, Table, Modal, Button, Input, Space, Upload, message } from 'antd'
3
+ import { Container, SearchRow, ModalContainer } from '../../client/styled/template/manage'
4
+ import { useDispatch, useSelector } from 'react-redux'
5
+ import { getTemplate, addTemplate, modTemplate, delTemplate, updateSSRTemplate, searchTemplate, batchDelTemplate } from '../../client/redux/template/manage/actions'
6
+ import { getTemplateService } from '../../client/service/template/manage'
7
+ import { RootState } from '../../client/redux/store'
8
+ import _ from 'lodash'
9
+ import moment from 'moment'
10
+ import locale from 'antd/lib/locale/zh_CN'
11
+ import { handleXSS, checkModalObj } from '../../client/utils/common'
12
+ import { UploadOutlined } from '@ant-design/icons'
13
+ import ExcelJS from 'exceljs'
14
+ import { saveAs } from 'file-saver'
15
+
16
+ const pageSize = 100
17
+ const dateFormat = 'YYYY-MM-DD'
18
+ const currentDate = moment().format(dateFormat)
19
+ console.log('currentDate', currentDate)
20
+
21
+ const keyTitles = {
22
+ name: '名称'
23
+ }
24
+
25
+ const Page = ({ template }) => {
26
+ const dispatch = useDispatch()
27
+ const [isModalVisiable, setIsModalVisible] = useState(false)
28
+ const [modalId, setModalId] = useState(0)
29
+ const [modalName, setModalName] = useState('')
30
+ const [searchName, setSearchName] = useState('')
31
+ const [batchDelIds, setBatchDelIds] = useState([])
32
+
33
+ useEffect(() => {
34
+ dispatch(updateSSRTemplate(template))
35
+ }, [dispatch])
36
+
37
+ const state = useSelector((state: RootState) => state)
38
+ const { templateManage }: any = state
39
+ console.log('templateManage', templateManage)
40
+
41
+ if (!templateManage.firstLoadFlag) {
42
+ template = templateManage.template
43
+ }
44
+
45
+ const { totalCounts, items: templateItems } = template
46
+ console.log('template', template)
47
+
48
+ _.each(templateItems, (item, index) => {
49
+ const { id } = item
50
+ item.key = id
51
+ })
52
+
53
+ const dataSource = templateItems
54
+ const columns: any = [
55
+ {
56
+ title: 'ID',
57
+ dataIndex: 'id',
58
+ key: 'id',
59
+ sorter: (a: any, b: any) => a.id - b.id,
60
+ sortDirections: ['descend', 'ascend'],
61
+ showSorterTooltip: false
62
+ },
63
+ {
64
+ title: keyTitles.name,
65
+ dataIndex: 'name',
66
+ key: 'name',
67
+ sorter: (a: any, b: any) => a.name.length - b.name.length,
68
+ sortDirections: ['descend', 'ascend'],
69
+ showSorterTooltip: false
70
+ },
71
+ {
72
+ title: '操作',
73
+ dataIndex: '',
74
+ render: (_: any, record: any) => {
75
+ return (
76
+ <Space>
77
+ <Button onClick={() => {
78
+ console.log('record', record)
79
+ updateTemplate(record)
80
+ }}>修改</Button>
81
+ <Button onClick={() => {
82
+ console.log('record', record)
83
+ const { id } = record
84
+ deleteTemplate(id)
85
+ }}>删除</Button>
86
+ </Space>
87
+ )
88
+ }
89
+ }
90
+ ]
91
+
92
+ const rowSelection = {
93
+ onChange: (selectedRowKeys: any, selectedRows: any) => {
94
+ console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows)
95
+ setBatchDelIds(selectedRowKeys)
96
+ }
97
+ }
98
+
99
+ const createTemplate = () => {
100
+ setModalId(0)
101
+ setModalName('')
102
+ showModal()
103
+ }
104
+
105
+ const updateTemplate = (record: any) => {
106
+ let { id, name } = record
107
+
108
+ setModalId(id)
109
+ setModalName(name)
110
+ showModal()
111
+ }
112
+
113
+ const deleteTemplate = (id: number) => {
114
+ Modal.confirm({
115
+ title: '提示',
116
+ content: '确认删除吗',
117
+ okText: '确认',
118
+ cancelText: '取消',
119
+ onOk: (e) => {
120
+ dispatch(delTemplate(id))
121
+ Modal.destroyAll()
122
+ }
123
+ })
124
+ }
125
+
126
+ const showModal = () => {
127
+ setIsModalVisible(true)
128
+ }
129
+
130
+ const getMessageTitle = (key: string) => {
131
+ let result = keyTitles[key]
132
+ if (result == undefined)
133
+ result = key
134
+ return result
135
+ }
136
+
137
+ const handleOk = () => {
138
+ const modalObj = {
139
+ name: handleXSS(modalName)
140
+ }
141
+ console.log('handleOk', modalObj)
142
+
143
+ const checkResult = checkModalObj(modalObj)
144
+
145
+ if (!checkResult) {
146
+ if (modalId == 0) { // 新增
147
+ dispatch(addTemplate(modalObj))
148
+ } else {
149
+ dispatch(modTemplate(modalId, modalObj))
150
+ }
151
+
152
+ setIsModalVisible(false)
153
+ } else {
154
+ message.info(getMessageTitle(checkResult.key) + checkResult.reason)
155
+ }
156
+ }
157
+
158
+ const handleCancel = () => {
159
+ setIsModalVisible(false)
160
+ }
161
+
162
+ const doSearch = () => {
163
+ dispatch(searchTemplate(0, pageSize, { name: handleXSS(searchName) }))
164
+ }
165
+
166
+ const exportTemplate = () => {
167
+ if (templateItems.length > 0) {
168
+ const wb = new ExcelJS.Workbook();
169
+ const ws = wb.addWorksheet("Template")
170
+ const jsonData = _.map(templateItems, (item) => _.omit(item, ['key']))
171
+
172
+ // 提取表头
173
+ const headers = Object.keys(jsonData[0]);
174
+
175
+ // JSON 数据转换为二维数组
176
+ const data = [headers, ...jsonData.map(item => headers.map(header => item[header]))];
177
+
178
+ // 将数据写入工作表
179
+ ws.addRows(data)
180
+
181
+ // 设置表头样式加粗
182
+ ws.getRow(1).eachCell((cell) => {
183
+ cell.font = { bold: true };
184
+ });
185
+
186
+ // 设置列宽
187
+ ws.columns = [
188
+ { header: 'ID', key: 'header1', width: 20 },
189
+ { header: 'NAME', key: 'header2', width: 30 },
190
+ ];
191
+
192
+ wb.xlsx.writeBuffer().then((data) => {
193
+ const blob = new Blob([data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
194
+ saveAs(blob, "Template.xlsx")
195
+ }).catch((error) => {
196
+ console.error('导出失败', error?.message)
197
+ })
198
+ } else {
199
+ message.info("没有数据无需导出")
200
+ }
201
+ }
202
+
203
+ const uploadProps = {
204
+ name: 'file',
205
+ action: '/rest/template/import',
206
+ onChange(info: any) {
207
+ if (info.file.status !== 'uploading') {
208
+ console.log(info.file, info.fileList)
209
+ }
210
+
211
+ if (info.file.status === 'done') {
212
+ message.success(`${info.file.name} 文件上传成功`)
213
+ window.location.reload()
214
+ } else if (info.file.status === 'error') {
215
+ message.error(`${info.file.name} 文件上传失败`)
216
+ }
217
+ }
218
+ }
219
+
220
+ const batchDeleteTemplate = () => {
221
+ if (batchDelIds.length > 0) {
222
+ Modal.confirm({
223
+ title: '提示',
224
+ content: '确认批量删除吗',
225
+ okText: '确认',
226
+ cancelText: '取消',
227
+ onOk: (e) => {
228
+ dispatch(batchDelTemplate(batchDelIds))
229
+ Modal.destroyAll()
230
+ }
231
+ })
232
+ } else {
233
+ message.info("没有数据不能批量删除")
234
+ }
235
+ }
236
+
237
+ return (
238
+ <Container>
239
+ <ConfigProvider locale={locale}>
240
+ <SearchRow>
241
+ <Space>
242
+ <Button type="primary" onClick={createTemplate}>
243
+ 新增
244
+ </Button>
245
+ <Input value={searchName} placeholder="" onChange={(e) => setSearchName(e.target.value)} />
246
+ <Button type="primary" onClick={doSearch}>
247
+ 搜索
248
+ </Button>
249
+ <Button type="primary" onClick={exportTemplate}>
250
+ 导出
251
+ </Button>
252
+ <Upload {...uploadProps}>
253
+ <Button icon={<UploadOutlined rev={undefined} />}>导入</Button>
254
+ </Upload>
255
+ <Button type="primary" onClick={batchDeleteTemplate}>
256
+ 批量删除
257
+ </Button>
258
+ </Space>
259
+ </SearchRow>
260
+ <Table rowSelection={{
261
+ type: 'checkbox',
262
+ ...rowSelection,
263
+ }} dataSource={dataSource} columns={columns} pagination={{
264
+ total: totalCounts,
265
+ pageSize: pageSize,
266
+ onChange: (page, pageSize) => {
267
+ console.log('onChange', page, pageSize)
268
+ dispatch(searchTemplate(page - 1, pageSize, { name: handleXSS(searchName) }))
269
+ }
270
+ }} />
271
+ <Modal title={(modalId == 0 ? "新增" : "修改") + " template"} open={isModalVisiable} onOk={handleOk} onCancel={handleCancel} okText="确认" cancelText="取消">
272
+ <ModalContainer>
273
+ <div className="line">
274
+ <label>{keyTitles.name}</label>
275
+ <Input value={modalName} placeholder="" onChange={(e) => setModalName(e.target.value)} />
276
+ </div>
277
+ </ModalContainer>
278
+ </Modal>
279
+ </ConfigProvider>
280
+ </Container>
281
+ )
282
+ }
283
+
284
+ Page.getInitialProps = async () => {
285
+ let template = null
286
+
287
+ await getTemplateService(0, pageSize).then((res: any) => {
288
+ console.log('res', res)
289
+ const { data } = res
290
+ template = data.template
291
+ })
292
+
293
+ console.log('template-getInitialProps', template)
294
+
295
+ return {
296
+ template
297
+ }
298
+ }
299
+
279
300
  export default Page
package/project.config.js CHANGED
@@ -1,17 +1,17 @@
1
- const pkg = require('./package.json')
2
-
3
- const { version } = pkg
4
- const protocol = 'http'
5
- const prefix = ''
6
- const host = '127.0.0.1'
7
- const port = 8080
8
- const env = 'fat'
9
-
10
- module.exports = {
11
- env,
12
- version,
13
- prefix,
14
- protocol,
15
- host,
16
- port
1
+ const pkg = require('./package.json')
2
+
3
+ const { version } = pkg
4
+ const protocol = 'http'
5
+ const prefix = ''
6
+ const host = '127.0.0.1'
7
+ const port = 8080
8
+ const env = 'fat'
9
+
10
+ module.exports = {
11
+ env,
12
+ version,
13
+ prefix,
14
+ protocol,
15
+ host,
16
+ port
17
17
  }
@@ -1,10 +1,10 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>nsgm-cli</title>
6
- </head>
7
- <body>
8
- SLBHEALTHCHECK
9
- </body>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>nsgm-cli</title>
6
+ </head>
7
+ <body>
8
+ SLBHEALTHCHECK
9
+ </body>
10
10
  </html>
@@ -1,10 +1,10 @@
1
- #!/bin/sh
2
-
3
- cd $(dirname $BASH_SOURCE)
4
- cd ..
5
- appid=$(basename $(pwd))
6
- cd current
7
- appname=node-app-$appid
8
-
9
- pm2 delete $appname
1
+ #!/bin/sh
2
+
3
+ cd $(dirname $BASH_SOURCE)
4
+ cd ..
5
+ appid=$(basename $(pwd))
6
+ cd current
7
+ appname=node-app-$appid
8
+
9
+ pm2 delete $appname
10
10
  pm2 dump