create-skweb 2.1.0 → 3.0.3
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/{dist/cli.cjs → .rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/dist/cli.js} +7 -125
- package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/dist/index.js +106 -0
- package/.rollup.cache/Users/stayknight/projects/skweb-mono/tools/create-skweb/tsconfig.tsbuildinfo +1 -0
- package/.turbo/turbo-build.log +9 -10
- package/.turbo/turbo-check.log +5 -4
- package/.turbo/turbo-lint.log +12 -4
- package/CHANGELOG.md +48 -0
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +109 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/package.json +10 -18
- package/rollup.config.mjs +23 -22
- package/scripts/inject-shebang.mjs +1 -1
- package/src/cli.ts +7 -7
- package/src/index.ts +2 -2
- package/templates/cjs/package.json +18 -18
- package/templates/cjs/src/app.js +16 -11
- package/templates/cjs/src/controllers/hello.js +43 -31
- package/templates/cjs/src/controllers/user.js +199 -86
- package/templates/cjs/src/cronWorker.js +7 -9
- package/templates/mjs/package.json +18 -18
- package/templates/mjs/src/app.js +8 -10
- package/templates/mjs/src/controllers/hello.js +43 -31
- package/templates/mjs/src/controllers/user.js +199 -86
- package/templates/mjs/src/cronWorker.js +7 -9
- package/templates/ts/package.json +24 -24
- package/templates/ts/rollup.config.mjs +2 -0
- package/templates/ts/src/app.ts +9 -10
- package/templates/ts/src/controllers/hello.ts +43 -31
- package/templates/ts/src/controllers/user.ts +199 -86
- package/templates/ts/src/cronWorker.ts +7 -9
- package/templates/ts/tsconfig.json +4 -5
- package/test/index.mjs +24 -13
- package/tsconfig.json +6 -6
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/index.cjs +0 -123
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
|
@@ -3,99 +3,212 @@ import { db } from '../services/database.js'
|
|
|
3
3
|
|
|
4
4
|
const { SysUser } = db.sequelize.models
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @swagger
|
|
8
|
+
* /api/users:
|
|
9
|
+
* get:
|
|
10
|
+
* summary: 获取用户列表
|
|
11
|
+
* tags: [Users]
|
|
12
|
+
* parameters:
|
|
13
|
+
* - in: query
|
|
14
|
+
* name: page
|
|
15
|
+
* schema: { type: integer, minimum: 1, default: 1 }
|
|
16
|
+
* description: 页码
|
|
17
|
+
* - in: query
|
|
18
|
+
* name: limit
|
|
19
|
+
* schema: { type: integer, minimum: 1, default: 10 }
|
|
20
|
+
* description: 每页条数
|
|
21
|
+
* responses:
|
|
22
|
+
* 200:
|
|
23
|
+
* description: OK
|
|
24
|
+
*/
|
|
25
|
+
const userList = {
|
|
26
|
+
method: 'get',
|
|
27
|
+
path: '/api/users',
|
|
28
|
+
async handler(req: any) {
|
|
29
|
+
const { page = 1, limit = 10 } = req.query
|
|
30
|
+
const users = await SysUser.findAndCountAll({
|
|
31
|
+
offset: (Number(page) - 1) * Number(limit),
|
|
32
|
+
limit: Number(limit)
|
|
33
|
+
})
|
|
34
|
+
return {
|
|
35
|
+
list: users.rows,
|
|
36
|
+
total: users.count
|
|
20
37
|
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @swagger
|
|
43
|
+
* /api/users/{id}:
|
|
44
|
+
* get:
|
|
45
|
+
* summary: 获取单个用户
|
|
46
|
+
* tags: [Users]
|
|
47
|
+
* parameters:
|
|
48
|
+
* - in: path
|
|
49
|
+
* name: id
|
|
50
|
+
* required: true
|
|
51
|
+
* schema: { type: integer, minimum: 1 }
|
|
52
|
+
* responses:
|
|
53
|
+
* 200:
|
|
54
|
+
* description: OK
|
|
55
|
+
* 404:
|
|
56
|
+
* description: 用户不存在
|
|
57
|
+
*/
|
|
58
|
+
const userGet = {
|
|
59
|
+
method: 'get',
|
|
60
|
+
path: '/api/users/:id',
|
|
61
|
+
paramsSchema: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
required: ['id'],
|
|
64
|
+
properties: { id: { type: 'integer', minimum: 1 } }
|
|
21
65
|
},
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
66
|
+
async handler(req: any) {
|
|
67
|
+
const { id } = req.validatedParams
|
|
68
|
+
const user = await SysUser.findByPk(id)
|
|
69
|
+
if (!user) {
|
|
70
|
+
throw new createHttpError.NotFound('User not found')
|
|
71
|
+
}
|
|
72
|
+
return user
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @swagger
|
|
78
|
+
* /api/users:
|
|
79
|
+
* post:
|
|
80
|
+
* summary: 创建用户
|
|
81
|
+
* tags: [Users]
|
|
82
|
+
* requestBody:
|
|
83
|
+
* required: true
|
|
84
|
+
* content:
|
|
85
|
+
* application/json:
|
|
86
|
+
* schema:
|
|
87
|
+
* type: object
|
|
88
|
+
* required: [username, password]
|
|
89
|
+
* properties:
|
|
90
|
+
* username: { type: string, minLength: 3 }
|
|
91
|
+
* password: { type: string, minLength: 6 }
|
|
92
|
+
* email: { type: string, format: email }
|
|
93
|
+
* phone: { type: string }
|
|
94
|
+
* responses:
|
|
95
|
+
* 200:
|
|
96
|
+
* description: 创建成功
|
|
97
|
+
*/
|
|
98
|
+
const userCreate = {
|
|
99
|
+
method: 'post',
|
|
100
|
+
path: '/api/users',
|
|
101
|
+
bodySchema: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
required: ['username', 'password'],
|
|
104
|
+
properties: {
|
|
105
|
+
username: { type: 'string', minLength: 3 },
|
|
106
|
+
password: { type: 'string', minLength: 6 },
|
|
107
|
+
email: { type: 'string', format: 'email' },
|
|
108
|
+
phone: { type: 'string' }
|
|
37
109
|
}
|
|
38
110
|
},
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
111
|
+
async handler(req: any) {
|
|
112
|
+
return await SysUser.create(req.validatedBody)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @swagger
|
|
118
|
+
* /api/users/{id}:
|
|
119
|
+
* put:
|
|
120
|
+
* summary: 更新用户
|
|
121
|
+
* tags: [Users]
|
|
122
|
+
* parameters:
|
|
123
|
+
* - in: path
|
|
124
|
+
* name: id
|
|
125
|
+
* required: true
|
|
126
|
+
* schema: { type: integer, minimum: 1 }
|
|
127
|
+
* requestBody:
|
|
128
|
+
* required: true
|
|
129
|
+
* content:
|
|
130
|
+
* application/json:
|
|
131
|
+
* schema:
|
|
132
|
+
* type: object
|
|
133
|
+
* properties:
|
|
134
|
+
* password: { type: string, minLength: 6 }
|
|
135
|
+
* email: { type: string, format: email }
|
|
136
|
+
* phone: { type: string }
|
|
137
|
+
* status: { type: integer }
|
|
138
|
+
* responses:
|
|
139
|
+
* 200:
|
|
140
|
+
* description: OK
|
|
141
|
+
* 404:
|
|
142
|
+
* description: 用户不存在
|
|
143
|
+
*/
|
|
144
|
+
const userUpdate = {
|
|
145
|
+
method: 'put',
|
|
146
|
+
path: '/api/users/:id',
|
|
147
|
+
paramsSchema: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
required: ['id'],
|
|
150
|
+
properties: { id: { type: 'integer', minimum: 1 } }
|
|
151
|
+
},
|
|
152
|
+
bodySchema: {
|
|
153
|
+
type: 'object',
|
|
154
|
+
properties: {
|
|
155
|
+
password: { type: 'string', minLength: 6 },
|
|
156
|
+
email: { type: 'string', format: 'email' },
|
|
157
|
+
phone: { type: 'string' },
|
|
158
|
+
status: { type: 'integer' }
|
|
54
159
|
}
|
|
55
160
|
},
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
required: ['id'],
|
|
62
|
-
properties: { id: { type: 'integer', minimum: 1 } }
|
|
63
|
-
},
|
|
64
|
-
bodySchema: {
|
|
65
|
-
type: 'object',
|
|
66
|
-
properties: {
|
|
67
|
-
password: { type: 'string', minLength: 6 },
|
|
68
|
-
email: { type: 'string', format: 'email' },
|
|
69
|
-
phone: { type: 'string' },
|
|
70
|
-
status: { type: 'integer' }
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
async handler(req: any) {
|
|
74
|
-
const { id } = req.validatedParams
|
|
75
|
-
const user = await SysUser.findByPk(id)
|
|
76
|
-
if (!user) {
|
|
77
|
-
throw new createHttpError.NotFound('User not found')
|
|
78
|
-
}
|
|
79
|
-
await user.update(req.validatedBody)
|
|
80
|
-
return user
|
|
161
|
+
async handler(req: any) {
|
|
162
|
+
const { id } = req.validatedParams
|
|
163
|
+
const user = await SysUser.findByPk(id)
|
|
164
|
+
if (!user) {
|
|
165
|
+
throw new createHttpError.NotFound('User not found')
|
|
81
166
|
}
|
|
167
|
+
await user.update(req.validatedBody)
|
|
168
|
+
return user
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @swagger
|
|
174
|
+
* /api/users/{id}:
|
|
175
|
+
* delete:
|
|
176
|
+
* summary: 删除用户
|
|
177
|
+
* tags: [Users]
|
|
178
|
+
* parameters:
|
|
179
|
+
* - in: path
|
|
180
|
+
* name: id
|
|
181
|
+
* required: true
|
|
182
|
+
* schema: { type: integer, minimum: 1 }
|
|
183
|
+
* responses:
|
|
184
|
+
* 200:
|
|
185
|
+
* description: OK
|
|
186
|
+
* 404:
|
|
187
|
+
* description: 用户不存在
|
|
188
|
+
*/
|
|
189
|
+
const userDelete = {
|
|
190
|
+
method: 'delete',
|
|
191
|
+
path: '/api/users/:id',
|
|
192
|
+
paramsSchema: {
|
|
193
|
+
type: 'object',
|
|
194
|
+
required: ['id'],
|
|
195
|
+
properties: { id: { type: 'integer', minimum: 1 } }
|
|
82
196
|
},
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
required: ['id'],
|
|
89
|
-
properties: { id: { type: 'integer', minimum: 1 } }
|
|
90
|
-
},
|
|
91
|
-
async handler(req: any) {
|
|
92
|
-
const { id } = req.validatedParams
|
|
93
|
-
const user = await SysUser.findByPk(id)
|
|
94
|
-
if (!user) {
|
|
95
|
-
throw new createHttpError.NotFound('User not found')
|
|
96
|
-
}
|
|
97
|
-
await user.destroy()
|
|
98
|
-
return { message: 'User deleted' }
|
|
197
|
+
async handler(req: any) {
|
|
198
|
+
const { id } = req.validatedParams
|
|
199
|
+
const user = await SysUser.findByPk(id)
|
|
200
|
+
if (!user) {
|
|
201
|
+
throw new createHttpError.NotFound('User not found')
|
|
99
202
|
}
|
|
203
|
+
await user.destroy()
|
|
204
|
+
return { message: 'User deleted' }
|
|
100
205
|
}
|
|
101
|
-
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export default {
|
|
209
|
+
userList,
|
|
210
|
+
userGet,
|
|
211
|
+
userCreate,
|
|
212
|
+
userUpdate,
|
|
213
|
+
userDelete
|
|
214
|
+
}
|
|
@@ -66,16 +66,14 @@ async function startCronWorker(): Promise<void> {
|
|
|
66
66
|
framework.start()
|
|
67
67
|
logger.info('[cron-worker] Cron worker started')
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
process.exit(
|
|
69
|
+
// 未捕获异常:打印堆栈后直接退出。OS / 进程管理器负责回收资源。
|
|
70
|
+
process.on('uncaughtException', (err) => {
|
|
71
|
+
logger.error(`[cron-worker] uncaughtException: ${err.stack || err.message}`)
|
|
72
|
+
process.exit(1)
|
|
73
73
|
})
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await framework.stop()
|
|
78
|
-
process.exit(0)
|
|
74
|
+
process.on('unhandledRejection', (reason) => {
|
|
75
|
+
logger.error(`[cron-worker] unhandledRejection: ${reason instanceof Error ? reason.stack : String(reason)}`)
|
|
76
|
+
process.exit(1)
|
|
79
77
|
})
|
|
80
78
|
}
|
|
81
79
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
3
|
+
"target": "ES2022",
|
|
4
4
|
"module": "ESNext",
|
|
5
|
-
"lib": ["
|
|
6
|
-
"moduleResolution": "
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
7
|
"strict": true,
|
|
8
8
|
"esModuleInterop": true,
|
|
9
9
|
"skipLibCheck": true,
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
"declaration": true,
|
|
13
13
|
"sourceMap": true,
|
|
14
14
|
"rootDir": "src",
|
|
15
|
-
"outDir": "dist"
|
|
16
|
-
"baseUrl": "."
|
|
15
|
+
"outDir": "dist"
|
|
17
16
|
},
|
|
18
17
|
"include": ["src/**/*.ts"],
|
|
19
18
|
"exclude": ["node_modules", "dist", "test"]
|
package/test/index.mjs
CHANGED
|
@@ -8,6 +8,12 @@ import { createProject, printBanner, printSuccess } from '../dist/index.js'
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url)
|
|
9
9
|
const __dirname = path.dirname(__filename)
|
|
10
10
|
|
|
11
|
+
// helper: createProject 把项目放在 <dest>/<name> 下,
|
|
12
|
+
// 测试断言用的所有路径都要走 <dest>/<name>。
|
|
13
|
+
function projectPath(tmpDir, name = 'my-app') {
|
|
14
|
+
return path.join(tmpDir, name)
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
describe('create-skweb', () => {
|
|
12
18
|
describe('createProject()', () => {
|
|
13
19
|
let tmpDir
|
|
@@ -21,42 +27,47 @@ describe('create-skweb', () => {
|
|
|
21
27
|
})
|
|
22
28
|
|
|
23
29
|
it('should create TypeScript project from template', async () => {
|
|
30
|
+
const root = projectPath(tmpDir)
|
|
24
31
|
await createProject({
|
|
25
32
|
name: 'my-app',
|
|
26
33
|
template: 'ts',
|
|
27
34
|
dest: tmpDir
|
|
28
35
|
})
|
|
29
36
|
|
|
30
|
-
expect(fs.existsSync(path.join(
|
|
31
|
-
expect(fs.existsSync(path.join(
|
|
32
|
-
expect(fs.existsSync(path.join(
|
|
37
|
+
expect(fs.existsSync(path.join(root, 'package.json'))).to.be.true
|
|
38
|
+
expect(fs.existsSync(path.join(root, 'src', 'app.ts'))).to.be.true
|
|
39
|
+
expect(fs.existsSync(path.join(root, 'src', 'utils', 'logger.ts'))).to.be.true
|
|
33
40
|
})
|
|
34
41
|
|
|
35
42
|
it('should create MJS project from template', async () => {
|
|
43
|
+
const root = projectPath(tmpDir)
|
|
36
44
|
await createProject({
|
|
37
45
|
name: 'my-app',
|
|
38
46
|
template: 'mjs',
|
|
39
47
|
dest: tmpDir
|
|
40
48
|
})
|
|
41
49
|
|
|
42
|
-
expect(fs.existsSync(path.join(
|
|
43
|
-
expect(fs.existsSync(path.join(
|
|
50
|
+
expect(fs.existsSync(path.join(root, 'package.json'))).to.be.true
|
|
51
|
+
expect(fs.existsSync(path.join(root, 'src', 'app.js'))).to.be.true
|
|
44
52
|
})
|
|
45
53
|
|
|
46
54
|
it('should create CJS project from template', async () => {
|
|
55
|
+
const root = projectPath(tmpDir)
|
|
47
56
|
await createProject({
|
|
48
57
|
name: 'my-app',
|
|
49
58
|
template: 'cjs',
|
|
50
59
|
dest: tmpDir
|
|
51
60
|
})
|
|
52
61
|
|
|
53
|
-
expect(fs.existsSync(path.join(
|
|
54
|
-
expect(fs.existsSync(path.join(
|
|
62
|
+
expect(fs.existsSync(path.join(root, 'package.json'))).to.be.true
|
|
63
|
+
expect(fs.existsSync(path.join(root, 'src', 'app.js'))).to.be.true
|
|
55
64
|
})
|
|
56
65
|
|
|
57
66
|
it('should reject non-empty destination directory', async () => {
|
|
58
|
-
//
|
|
59
|
-
|
|
67
|
+
// 在目标项目目录 (tmpDir/my-app) 里创建一个文件,createProject 应拒绝
|
|
68
|
+
const target = projectPath(tmpDir)
|
|
69
|
+
fs.mkdirsSync(target)
|
|
70
|
+
fs.writeFileSync(path.join(target, 'existing.txt'), 'x')
|
|
60
71
|
|
|
61
72
|
try {
|
|
62
73
|
await createProject({
|
|
@@ -79,7 +90,7 @@ describe('create-skweb', () => {
|
|
|
79
90
|
template,
|
|
80
91
|
dest: tmpDir
|
|
81
92
|
})
|
|
82
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'))
|
|
93
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(projectPath(tmpDir), 'package.json'), 'utf-8'))
|
|
83
94
|
expect(pkg.dependencies.winston, `${template} should have winston dep`).to.exist
|
|
84
95
|
}
|
|
85
96
|
})
|
|
@@ -93,7 +104,7 @@ describe('create-skweb', () => {
|
|
|
93
104
|
template,
|
|
94
105
|
dest: tmpDir
|
|
95
106
|
})
|
|
96
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'))
|
|
107
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(projectPath(tmpDir), 'package.json'), 'utf-8'))
|
|
97
108
|
expect(pkg.dependencies['@dotenvx/dotenvx'], `${template} should have dotenvx`).to.exist
|
|
98
109
|
}
|
|
99
110
|
})
|
|
@@ -107,7 +118,7 @@ describe('create-skweb', () => {
|
|
|
107
118
|
template,
|
|
108
119
|
dest: tmpDir
|
|
109
120
|
})
|
|
110
|
-
expect(fs.existsSync(path.join(tmpDir, 'ecosystem.config.js')), `${template} should have pm2 ecosystem`).to.be.true
|
|
121
|
+
expect(fs.existsSync(path.join(projectPath(tmpDir), 'ecosystem.config.js')), `${template} should have pm2 ecosystem`).to.be.true
|
|
111
122
|
}
|
|
112
123
|
})
|
|
113
124
|
|
|
@@ -117,7 +128,7 @@ describe('create-skweb', () => {
|
|
|
117
128
|
template: 'ts',
|
|
118
129
|
dest: tmpDir
|
|
119
130
|
})
|
|
120
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'))
|
|
131
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(projectPath(tmpDir, 'my-custom-app'), 'package.json'), 'utf-8'))
|
|
121
132
|
expect(pkg.name).to.equal('my-custom-app')
|
|
122
133
|
expect(pkg.name).to.not.match(/\{\{name\}\}/)
|
|
123
134
|
})
|
package/tsconfig.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"
|
|
3
|
+
"composite": true,
|
|
4
|
+
"target": "ES2022",
|
|
4
5
|
"module": "ESNext",
|
|
5
|
-
"lib": ["
|
|
6
|
-
"moduleResolution": "
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"moduleResolution": "Bundler",
|
|
7
8
|
"strict": true,
|
|
8
9
|
"esModuleInterop": true,
|
|
9
10
|
"skipLibCheck": true,
|
|
10
11
|
"forceConsistentCasingInFileNames": true,
|
|
11
12
|
"resolveJsonModule": true,
|
|
12
13
|
"declaration": true,
|
|
13
|
-
"declarationMap":
|
|
14
|
-
"sourceMap":
|
|
14
|
+
"declarationMap": false,
|
|
15
|
+
"sourceMap": false,
|
|
15
16
|
"rootDir": "src",
|
|
16
17
|
"outDir": "dist",
|
|
17
|
-
"baseUrl": ".",
|
|
18
18
|
"types": ["node"]
|
|
19
19
|
},
|
|
20
20
|
"include": ["src/**/*.ts"],
|