express-project-init 1.0.0 → 1.2.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.
- package/LICENSE.md +21 -0
- package/README.md +57 -75
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/services/prompts.service.js +29 -0
- package/dist/services/prompts.service.js.map +1 -1
- package/dist/services/template.service.js +65 -17
- package/dist/services/template.service.js.map +1 -1
- package/docs/express-project-init-v1.1.0-demo.gif +0 -0
- package/docs/express-project-init-v1.1.0-demo.jpg +0 -0
- package/docs/express-project-init-v1.1.0-demo.mp4 +0 -0
- package/package.json +5 -2
- package/templates/format/biome/both/biome.json +17 -0
- package/templates/format/biome/both/package.json +12 -0
- package/templates/format/biome/format/biome.json +14 -0
- package/templates/format/biome/format/package.json +9 -0
- package/templates/format/prettier/.prettierignore +3 -0
- package/templates/format/prettier/.prettierrc +6 -0
- package/templates/format/prettier/package.json +9 -0
- package/templates/javascript/error-handler/src/middleware/error.middleware.js +2 -2
- package/templates/javascript/error-handler/src/middleware/notFound.middleware.js +1 -1
- package/templates/lint/biome/biome.json +15 -0
- package/templates/lint/biome/package.json +9 -0
- package/templates/lint/eslint/eslint.config.js +36 -0
- package/templates/lint/eslint/package.json +12 -0
- package/templates/lint/oxlint/.oxlintrc.json +13 -0
- package/templates/lint/oxlint/package.json +9 -0
- package/templates/typescript/base/tsconfig.json +13 -13
- package/templates/typescript/error-handler/src/middleware/error.middleware.ts +1 -1
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Raunak Ray
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,33 +1,42 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
ExpressKit
|
|
1
|
+
# express-project-init
|
|
2
|
+
|
|
3
|
+
Set up a clean Express 5 API in seconds. Pick JavaScript or TypeScript, your linter, and your formatter. Then run it.
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<video
|
|
7
|
+
src="https://cdn.jsdelivr.net/gh/raunak-ray/ExpressKit@main/docs/express-project-init-v1.1.0-demo.mp4"
|
|
8
|
+
poster="https://cdn.jsdelivr.net/gh/raunak-ray/ExpressKit@main/docs/express-project-init-v1.1.0-demo.jpg"
|
|
9
|
+
autoplay
|
|
10
|
+
muted
|
|
11
|
+
loop
|
|
12
|
+
playsinline
|
|
13
|
+
controls
|
|
14
|
+
width="100%"
|
|
15
|
+
>
|
|
16
|
+
<img
|
|
17
|
+
src="https://cdn.jsdelivr.net/gh/raunak-ray/ExpressKit@main/docs/express-project-init-v1.1.0-demo.gif"
|
|
18
|
+
alt="express-project-init demo"
|
|
19
|
+
width="100%"
|
|
20
|
+
/>
|
|
21
|
+
</video>
|
|
22
|
+
</p>
|
|
8
23
|
|
|
9
24
|
## Quick start
|
|
10
25
|
|
|
11
|
-
Requires
|
|
26
|
+
Requires Node.js 20 or newer.
|
|
12
27
|
|
|
13
28
|
```bash
|
|
14
|
-
|
|
29
|
+
npx express-project-init@latest
|
|
15
30
|
```
|
|
16
31
|
|
|
17
|
-
|
|
32
|
+
It asks six quick questions:
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
? Project name › my-api
|
|
27
|
-
? Language › TypeScript
|
|
28
|
-
? Create central error handling middleware? › Yes
|
|
29
|
-
? Install dependencies? › Yes
|
|
30
|
-
```
|
|
34
|
+
1. Project name
|
|
35
|
+
2. JavaScript or TypeScript
|
|
36
|
+
3. Central error handling
|
|
37
|
+
4. Linter
|
|
38
|
+
5. Formatter
|
|
39
|
+
6. Install dependencies
|
|
31
40
|
|
|
32
41
|
Then:
|
|
33
42
|
|
|
@@ -38,72 +47,45 @@ npm run dev
|
|
|
38
47
|
|
|
39
48
|
Open <http://localhost:3000/health>.
|
|
40
49
|
|
|
41
|
-
Use `.`
|
|
50
|
+
Use `.` as the project name to set up in the current folder. Existing files are never overwritten.
|
|
42
51
|
|
|
43
52
|
## What you get
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
├── middleware/ # with the optional error handler
|
|
53
|
-
│ ├── error.middleware.ts
|
|
54
|
-
│ └── notFound.middleware.ts
|
|
55
|
-
└── utils/
|
|
56
|
-
├── helpers.ts
|
|
57
|
-
├── responseHelpers.ts
|
|
58
|
-
└── AppError.ts # with the optional error handler
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
JavaScript projects use the same layout with `.js` files and no `tsconfig.json`.
|
|
62
|
-
|
|
63
|
-
### Scripts
|
|
64
|
-
|
|
65
|
-
| Command | JavaScript | TypeScript |
|
|
66
|
-
| --- | --- | --- |
|
|
67
|
-
| `npm run dev` | `node --watch` | `tsx watch` |
|
|
68
|
-
| `npm start` | `node` | `tsx` |
|
|
69
|
-
| `npm run typecheck` | — | `tsc --noEmit` |
|
|
54
|
+
- A small Express 5 API with a `/health` route
|
|
55
|
+
- JavaScript or TypeScript
|
|
56
|
+
- Optional central error handling with one response format
|
|
57
|
+
- ESLint, Biome, or Oxlint
|
|
58
|
+
- Prettier or Biome
|
|
59
|
+
- Real config files, dependencies, and npm scripts
|
|
60
|
+
- Dependencies installed for you, if you want
|
|
70
61
|
|
|
71
|
-
|
|
62
|
+
TypeScript projects also get `tsconfig.json` and `npm run typecheck`.
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
{
|
|
77
|
-
"success": false,
|
|
78
|
-
"message": "Route not found",
|
|
79
|
-
"code": "NOT_FOUND"
|
|
80
|
-
}
|
|
81
|
-
```
|
|
64
|
+
## Scripts
|
|
82
65
|
|
|
83
|
-
|
|
66
|
+
The scripts you get depend on your choices.
|
|
84
67
|
|
|
85
|
-
|
|
68
|
+
| Command | What it does |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `npm run dev` | Start the API and watch for changes |
|
|
71
|
+
| `npm start` | Run the API |
|
|
72
|
+
| `npm run lint` | Check your code |
|
|
73
|
+
| `npm run format` | Format your code |
|
|
74
|
+
| `npm run typecheck` | Check TypeScript types |
|
|
86
75
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
## Local development
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
npm install
|
|
93
|
-
npm run build
|
|
94
|
-
npm link
|
|
95
|
-
```
|
|
76
|
+
## Publish
|
|
96
77
|
|
|
97
|
-
|
|
78
|
+
Commit your changes first. If this version is already on npm, bump it with `npm version patch` before publishing.
|
|
98
79
|
|
|
99
80
|
```bash
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
81
|
+
npm login
|
|
82
|
+
npm pack --dry-run # check what goes into the package
|
|
83
|
+
npm publish
|
|
84
|
+
npm view express-project-init version
|
|
103
85
|
```
|
|
104
86
|
|
|
105
|
-
|
|
87
|
+
`npm publish` builds the package first.
|
|
106
88
|
|
|
107
89
|
## License
|
|
108
90
|
|
|
109
|
-
MIT
|
|
91
|
+
[MIT](LICENSE.md) © 2026 Raunak Ray
|
package/dist/index.js
CHANGED
|
@@ -13,11 +13,15 @@ async function main() {
|
|
|
13
13
|
const language = await promptService.askLanguage();
|
|
14
14
|
const availableFeatures = await templateService.getAvailableFeatures(language);
|
|
15
15
|
const features = await promptService.askFeatureAnswers(availableFeatures);
|
|
16
|
+
const linter = await promptService.askLinter();
|
|
17
|
+
const formatter = await promptService.askFormatter();
|
|
16
18
|
const installDependencies = await promptService.askShouldInstall();
|
|
17
19
|
const answers = {
|
|
18
20
|
projectName,
|
|
19
21
|
language,
|
|
20
22
|
features,
|
|
23
|
+
linter,
|
|
24
|
+
formatter,
|
|
21
25
|
installDependencies,
|
|
22
26
|
};
|
|
23
27
|
// 2. Run the commands behind a spinner
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,KAAK,UAAU,IAAI;IACjB,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAE9C,qFAAqF;IACrF,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,iBAAiB,GACrB,MAAM,eAAe,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAC1E,MAAM,mBAAmB,GAAG,MAAM,aAAa,CAAC,gBAAgB,EAAE,CAAC;IAEnE,MAAM,OAAO,GAAmB;QAC9B,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,mBAAmB;KACpB,CAAC;IAEF,uCAAuC;IACvC,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QAErC,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAC3C,MAAM,cAAc,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,WAAW,QAAQ,eAAe,WAAW,EAAE,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;IAEtE,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,KAAK,UAAU,IAAI;IACjB,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAE9C,qFAAqF;IACrF,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,cAAc,EAAE,CAAC;IACzD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,iBAAiB,GACrB,MAAM,eAAe,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,CAAC;IACrD,MAAM,mBAAmB,GAAG,MAAM,aAAa,CAAC,gBAAgB,EAAE,CAAC;IAEnE,MAAM,OAAO,GAAmB;QAC9B,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,SAAS;QACT,mBAAmB;KACpB,CAAC;IAEF,uCAAuC;IACvC,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QAErC,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;YAC3C,MAAM,cAAc,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,WAAW,QAAQ,eAAe,WAAW,EAAE,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;IAEtE,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -5,6 +5,17 @@ export class PromptService {
|
|
|
5
5
|
{ value: "javascript", label: "JavaScript" },
|
|
6
6
|
{ value: "typescript", label: "TypeScript" },
|
|
7
7
|
];
|
|
8
|
+
LINTER_OPTIONS = [
|
|
9
|
+
{ value: "none", label: "None" },
|
|
10
|
+
{ value: "eslint", label: "ESLint" },
|
|
11
|
+
{ value: "biome", label: "Biome" },
|
|
12
|
+
{ value: "oxlint", label: "Oxlint" },
|
|
13
|
+
];
|
|
14
|
+
FORMATTER_OPTIONS = [
|
|
15
|
+
{ value: "none", label: "None" },
|
|
16
|
+
{ value: "prettier", label: "Prettier" },
|
|
17
|
+
{ value: "biome", label: "Biome" },
|
|
18
|
+
];
|
|
8
19
|
async askProjectName() {
|
|
9
20
|
const response = await text({
|
|
10
21
|
message: "What would you like to name your project?",
|
|
@@ -44,6 +55,24 @@ export class PromptService {
|
|
|
44
55
|
}
|
|
45
56
|
return answers;
|
|
46
57
|
}
|
|
58
|
+
async askLinter() {
|
|
59
|
+
const response = await select({
|
|
60
|
+
message: "Which linter would you like to use?",
|
|
61
|
+
options: this.LINTER_OPTIONS,
|
|
62
|
+
initialValue: "oxlint",
|
|
63
|
+
});
|
|
64
|
+
this.handleCancel(response);
|
|
65
|
+
return response;
|
|
66
|
+
}
|
|
67
|
+
async askFormatter() {
|
|
68
|
+
const response = await select({
|
|
69
|
+
message: "Which formatter would you like to use?",
|
|
70
|
+
options: this.FORMATTER_OPTIONS,
|
|
71
|
+
initialValue: "biome",
|
|
72
|
+
});
|
|
73
|
+
this.handleCancel(response);
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
47
76
|
async askShouldInstall() {
|
|
48
77
|
const response = await confirm({
|
|
49
78
|
message: "Install dependencies?",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.service.js","sourceRoot":"","sources":["../../src/services/prompts.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAgB,MAAM,gBAAgB,CAAC;AAGxD,MAAM,OAAO,aAAa;IACP,gBAAgB,GAG3B;QACJ,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;QAC5C,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;KAC7C,CAAC;IAEK,KAAK,CAAC,cAAc;QACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC;YAC1B,OAAO,EAAE,2CAA2C;YACpD,WAAW,EAAE,QAAQ;YACrB,YAAY,EAAE,GAAG;YACjB,QAAQ,CAAC,KAAK;gBACZ,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;oBACnB,OAAO,kEAAkE,CAAC;gBAC5E,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAS,QAAQ,CAAC,CAAC;QAEpC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAEM,KAAK,CAAC,WAAW;QACtB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;YAC5B,OAAO,EAAE,uCAAuC;YAChD,OAAO,EAAE,IAAI,CAAC,gBAAgB;YAC9B,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAW,QAAQ,CAAC,CAAC;QAEtC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,iBAAiB,CAC5B,iBAAqC;QAErC,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAC7B,CAAC;QAEpB,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;gBAC7B,OAAO,EAAE,OAAO,CAAC,MAAM;gBACvB,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,CAAU,QAAQ,CAAC,CAAC;YAErC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC;QACjC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,KAAK,CAAC,gBAAgB;QAC3B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC7B,OAAO,EAAE,uBAAuB;YAChC,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAU,QAAQ,CAAC,CAAC;QAErC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,qEAAqE;IAC7D,YAAY,CAAI,QAAiB;QACvC,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,0BAA0B,CAAC,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"prompts.service.js","sourceRoot":"","sources":["../../src/services/prompts.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,18 +27,43 @@ export class TemplateService {
|
|
|
27
27
|
catch (error) {
|
|
28
28
|
throw new Error(`Unable to read templates for "${language}" at "${languageDirectory}".`, { cause: error });
|
|
29
29
|
}
|
|
30
|
-
const folders = new Set(entries
|
|
31
|
-
.filter((entry) => entry.isDirectory())
|
|
32
|
-
.map((entry) => entry.name));
|
|
30
|
+
const folders = new Set(entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name));
|
|
33
31
|
return FEATURES.filter((feature) => folders.has(feature.id));
|
|
34
32
|
}
|
|
33
|
+
resolveToolLayers(linter, formatter) {
|
|
34
|
+
if (linter === "biome" && formatter === "biome") {
|
|
35
|
+
return ["format/biome/both"];
|
|
36
|
+
}
|
|
37
|
+
const layers = [];
|
|
38
|
+
switch (linter) {
|
|
39
|
+
case "oxlint":
|
|
40
|
+
layers.push("lint/oxlint");
|
|
41
|
+
break;
|
|
42
|
+
case "eslint":
|
|
43
|
+
layers.push("lint/eslint");
|
|
44
|
+
break;
|
|
45
|
+
case "biome":
|
|
46
|
+
layers.push("lint/biome");
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
switch (formatter) {
|
|
50
|
+
case "prettier":
|
|
51
|
+
layers.push("format/prettier");
|
|
52
|
+
break;
|
|
53
|
+
case "biome":
|
|
54
|
+
layers.push("format/biome/format");
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
return layers;
|
|
58
|
+
}
|
|
35
59
|
/**
|
|
36
60
|
* Builds the complete project in memory.
|
|
37
61
|
*
|
|
38
62
|
* Base files come first. Each enabled feature is then layered on top:
|
|
39
63
|
* feature files replace base files with the same relative path, while new
|
|
40
|
-
* paths are added.
|
|
41
|
-
*
|
|
64
|
+
* paths are added. Tool layers (linters and formatters) are applied next.
|
|
65
|
+
* package.json is the exception — feature and tool package.json files are
|
|
66
|
+
* fragments merged into the base package.json.
|
|
42
67
|
*/
|
|
43
68
|
async buildFilePlan(answers) {
|
|
44
69
|
const baseFiles = await this.readLayer(answers.language, "base");
|
|
@@ -52,29 +77,52 @@ export class TemplateService {
|
|
|
52
77
|
if (!answers.features[feature.id]) {
|
|
53
78
|
continue;
|
|
54
79
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
const applied = await this.applyLayer(path.join(answers.language, feature.id), files, packageJson);
|
|
81
|
+
files = applied.files;
|
|
82
|
+
packageJson = applied.packageJson;
|
|
83
|
+
}
|
|
84
|
+
for (const toolLayer of this.resolveToolLayers(answers.linter, answers.formatter)) {
|
|
85
|
+
const applied = await this.applyLayer(toolLayer, files, packageJson);
|
|
86
|
+
files = applied.files;
|
|
87
|
+
packageJson = applied.packageJson;
|
|
88
|
+
}
|
|
89
|
+
if (answers.linter === "eslint" && answers.formatter === "prettier") {
|
|
90
|
+
packageJson = this.mergePackageJson(packageJson, {
|
|
91
|
+
devDependencies: {
|
|
92
|
+
"eslint-config-prettier": "^10.1.8",
|
|
93
|
+
},
|
|
94
|
+
}, "eslint-prettier-compatibility");
|
|
64
95
|
}
|
|
65
96
|
files["package.json"] = `${JSON.stringify(packageJson, null, 2)}\n`;
|
|
66
97
|
return files;
|
|
67
98
|
}
|
|
68
|
-
async readLayer(
|
|
69
|
-
const layerDirectory = path.join(this.templateRoot,
|
|
99
|
+
async readLayer(...segments) {
|
|
100
|
+
const layerDirectory = path.join(this.templateRoot, ...segments);
|
|
70
101
|
try {
|
|
71
102
|
await access(layerDirectory);
|
|
72
103
|
}
|
|
73
104
|
catch (error) {
|
|
74
|
-
throw new Error(`Template folder not found: "${
|
|
105
|
+
throw new Error(`Template folder not found: "${segments.join("/")}".`, {
|
|
106
|
+
cause: error,
|
|
107
|
+
});
|
|
75
108
|
}
|
|
76
109
|
return this.readDirectory(layerDirectory);
|
|
77
110
|
}
|
|
111
|
+
async applyLayer(layerPath, files, packageJson) {
|
|
112
|
+
const layer = await this.readLayer(layerPath);
|
|
113
|
+
const fragmentSource = layer["package.json"];
|
|
114
|
+
let updatedPackageJson = packageJson;
|
|
115
|
+
if (fragmentSource !== undefined) {
|
|
116
|
+
const fragment = this.parsePackageFragment(fragmentSource, layerPath);
|
|
117
|
+
updatedPackageJson = this.mergePackageJson(packageJson, fragment, layerPath);
|
|
118
|
+
// The merged package.json is written last, not copied from the layer.
|
|
119
|
+
delete layer["package.json"];
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
files: { ...files, ...layer },
|
|
123
|
+
packageJson: updatedPackageJson,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
78
126
|
async readDirectory(root, relativeDirectory = "") {
|
|
79
127
|
const directory = path.join(root, relativeDirectory);
|
|
80
128
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.service.js","sourceRoot":"","sources":["../../src/services/template.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAgB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"template.service.js","sourceRoot":"","sources":["../../src/services/template.service.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-project-init",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Create production-ready Express.js API projects with JavaScript or TypeScript using clean, reusable starter templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"templates",
|
|
13
13
|
"README.md",
|
|
14
|
-
"LICENSE"
|
|
14
|
+
"LICENSE.md",
|
|
15
|
+
"docs/express-project-init-v1.1.0-demo.mp4",
|
|
16
|
+
"docs/express-project-init-v1.1.0-demo.jpg",
|
|
17
|
+
"docs/express-project-init-v1.1.0-demo.gif"
|
|
15
18
|
],
|
|
16
19
|
"engines": {
|
|
17
20
|
"node": ">=20"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.6.4/schema.json",
|
|
3
|
+
"files": {
|
|
4
|
+
"ignoreUnknown": false
|
|
5
|
+
},
|
|
6
|
+
"formatter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"indentStyle": "space",
|
|
9
|
+
"indentWidth": 2
|
|
10
|
+
},
|
|
11
|
+
"linter": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"rules": {
|
|
14
|
+
"preset": "recommended"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AppError, BadRequestError } from "../utils/AppError.js";
|
|
2
|
-
import { errorResponse } from "../utils/responseHelpers.js";
|
|
3
2
|
import { getTimeStamp } from "../utils/helpers.js";
|
|
3
|
+
import { errorResponse } from "../utils/responseHelpers.js";
|
|
4
4
|
|
|
5
5
|
// Express error handler — needs all 4 params, that's how Express recognizes it.
|
|
6
|
-
export default function errorMiddleware(error, req, res,
|
|
6
|
+
export default function errorMiddleware(error, req, res, _next) {
|
|
7
7
|
const timeStamp = getTimeStamp();
|
|
8
8
|
|
|
9
9
|
// Expected errors — log them and send their details
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import globals from "globals";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
|
|
5
|
+
let prettier = [];
|
|
6
|
+
try {
|
|
7
|
+
const prettierConfig = await import("eslint-config-prettier");
|
|
8
|
+
prettier = [prettierConfig.default];
|
|
9
|
+
} catch (error) {
|
|
10
|
+
// eslint-config-prettier is optional, used when Prettier is also configured
|
|
11
|
+
void error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default tseslint.config(
|
|
15
|
+
{
|
|
16
|
+
languageOptions: {
|
|
17
|
+
globals: {
|
|
18
|
+
...globals.node,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
js.configs.recommended,
|
|
23
|
+
...tseslint.configs.recommended,
|
|
24
|
+
{
|
|
25
|
+
rules: {
|
|
26
|
+
"@typescript-eslint/no-unused-vars": [
|
|
27
|
+
"error",
|
|
28
|
+
{
|
|
29
|
+
argsIgnorePattern: "^_",
|
|
30
|
+
varsIgnorePattern: "^_",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
...prettier,
|
|
36
|
+
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
3
|
+
"plugins": ["typescript", "unicorn", "oxc"],
|
|
4
|
+
"categories": {
|
|
5
|
+
"correctness": "error"
|
|
6
|
+
},
|
|
7
|
+
"rules": {},
|
|
8
|
+
"env": {
|
|
9
|
+
"builtin": true,
|
|
10
|
+
"node": true
|
|
11
|
+
},
|
|
12
|
+
"ignorePatterns": ["node_modules", "dist"]
|
|
13
|
+
}
|
|
@@ -3,28 +3,28 @@
|
|
|
3
3
|
// Imports / modules
|
|
4
4
|
// "bundler" is THE setting that lets you import WITHOUT extensions:
|
|
5
5
|
// import app from "./app" (not "./app.ts")
|
|
6
|
-
"module": "esnext",
|
|
6
|
+
"module": "esnext", // emit modern ES module syntax
|
|
7
7
|
"moduleResolution": "bundler", // resolve imports without ".ts" extensions
|
|
8
|
-
"moduleDetection": "force",
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"verbatimModuleSyntax": true,
|
|
8
|
+
"moduleDetection": "force", // treat every file as an ES module (no CommonJS guessing)
|
|
9
|
+
"esModuleInterop": true, // allow normal default imports from CJS packages (express)
|
|
10
|
+
"verbatimModuleSyntax": true, // keep imports exactly as written; type-only imports must use "import type"
|
|
11
11
|
|
|
12
12
|
// Language level
|
|
13
|
-
"target": "esnext",
|
|
13
|
+
"target": "esnext", // allow the newest JS features, no downleveling
|
|
14
14
|
|
|
15
15
|
// Type checking
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"skipLibCheck": true,
|
|
16
|
+
"strict": true, // turn on all strict type checks
|
|
17
|
+
"noUnusedLocals": true, // error on declared-but-unused variables
|
|
18
|
+
"noUnusedParameters": true, // error on unused function parameters
|
|
19
|
+
"skipLibCheck": true, // don't type-check ".d.ts" files inside node_modules (faster)
|
|
20
20
|
|
|
21
21
|
// Runtime types
|
|
22
|
-
"types": ["node"],
|
|
22
|
+
"types": ["node"], // auto-include ONLY Node types (no stray umbrella types)
|
|
23
23
|
|
|
24
24
|
// Output
|
|
25
|
-
"noEmit": true
|
|
25
|
+
"noEmit": true // tsx runs the code directly, so tsc only type-checks, never writes files
|
|
26
26
|
},
|
|
27
27
|
// Files in scope
|
|
28
|
-
"include": ["src"],
|
|
29
|
-
"exclude": ["node_modules"]
|
|
28
|
+
"include": ["src"], // the compiler only looks at src/
|
|
29
|
+
"exclude": ["node_modules"] // never scan dependencies
|
|
30
30
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NextFunction, Request, Response } from "express";
|
|
2
2
|
import { AppError, BadRequestError } from "../utils/AppError";
|
|
3
|
-
import { errorResponse } from "../utils/responseHelpers";
|
|
4
3
|
import { getTimeStamp } from "../utils/helpers";
|
|
4
|
+
import { errorResponse } from "../utils/responseHelpers";
|
|
5
5
|
|
|
6
6
|
// Express error handler — needs all 4 params, that's how Express recognizes it.
|
|
7
7
|
export default function errorMiddleware(
|