@patel.ajay745/exinit 1.0.0 → 1.0.2
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 +171 -0
- package/dist/cli.js +6 -6
- package/dist/core/scaffolder.js +58 -0
- package/dist/core/validation.js +57 -0
- package/dist/messages.js +1 -0
- package/dist/scaffolder.js +7 -4
- package/dist/ui/messages.js +34 -0
- package/dist/ui/prompt.js +99 -0
- package/dist/utils/fs.js +99 -0
- package/dist/utils/installer.js +15 -0
- package/dist/utils/naming.js +10 -0
- package/dist/utils/packageManager.js +59 -0
- package/dist/utils/versions.js +69 -0
- package/dist/versions.js +69 -0
- package/package.json +8 -2
- package/templates/js-cjs/package.json.template +4 -4
- package/templates/js-esm/package.json.template +3 -3
- package/templates/ts/package.json.template +8 -8
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# exinit
|
|
2
|
+
|
|
3
|
+
Every time you start a new Express backend you end up doing the same thing. Create a folder, set up TypeScript, write the same error handler, the same async wrapper, the same response class, and then finally start working on the actual feature you wanted to build. That setup easily takes 30 minutes and it is the same 30 minutes every single time.
|
|
4
|
+
|
|
5
|
+
exinit fixes that. One command and your project is ready to go.
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
When you run exinit it asks you three questions and then creates a complete Express project for you. You choose the language (TypeScript or JavaScript), the module system if you picked JavaScript (CommonJS or ES Modules), and the package manager you want to use. After that it sets everything up and installs the dependencies automatically.
|
|
10
|
+
|
|
11
|
+
The generated project comes with four utility files that most Express apps need anyway.
|
|
12
|
+
|
|
13
|
+
**ApiError** is a custom error class. Instead of throwing generic errors you throw an ApiError with a status code and a message. Your error handler knows how to deal with it and sends a clean JSON response.
|
|
14
|
+
|
|
15
|
+
**ApiResponse** is a response wrapper. Every successful response goes through it so your API always returns data in the same shape. The client always knows what to expect.
|
|
16
|
+
|
|
17
|
+
**asyncHandler** is a wrapper for async route handlers. You wrap your async functions with it and you never have to write try catch inside a route again. Errors are automatically passed to Express.
|
|
18
|
+
|
|
19
|
+
**errorHandler** is an Express error middleware. It catches every error in your app, handles ApiError instances specially, and falls back to a generic 500 for anything unexpected.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
You do not need to install anything globally. Just use npx.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx @patel.ajay745/exinit my-app
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If you are already inside the folder where you want your project, you can run it without a name and it will use the current folder.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx @patel.ajay745/exinit
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Both of these also work.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx @patel.ajay745/exinit .
|
|
39
|
+
cd my-project && npx @patel.ajay745/exinit
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Interactive prompts
|
|
43
|
+
|
|
44
|
+
When you run the command you will see three prompts. Use the arrow keys to move between options and press Enter to select.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
? Select language: TypeScript / JavaScript
|
|
48
|
+
? Choose module system: CommonJS / ES Modules (only appears for JavaScript)
|
|
49
|
+
? Choose package manager: npm / bun / pnpm / yarn
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Package managers that are not installed on your machine will show up as greyed out and cannot be selected.
|
|
53
|
+
|
|
54
|
+
## Project structure
|
|
55
|
+
|
|
56
|
+
After exinit finishes you will have this structure inside your project folder.
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
my-app/
|
|
60
|
+
├── src/
|
|
61
|
+
│ ├── controllers/
|
|
62
|
+
│ ├── middlewares/
|
|
63
|
+
│ ├── models/
|
|
64
|
+
│ ├── routes/
|
|
65
|
+
│ │ └── index.ts (sample health check route)
|
|
66
|
+
│ ├── services/
|
|
67
|
+
│ ├── config/
|
|
68
|
+
│ ├── dto/ (TypeScript only)
|
|
69
|
+
│ ├── types/ (TypeScript only)
|
|
70
|
+
│ ├── utils/
|
|
71
|
+
│ │ ├── apiError.ts
|
|
72
|
+
│ │ ├── apiResponse.ts
|
|
73
|
+
│ │ ├── asyncHandler.ts
|
|
74
|
+
│ │ └── errorHandler.ts
|
|
75
|
+
│ └── index.ts (Express app entry point)
|
|
76
|
+
├── .env.example
|
|
77
|
+
├── .gitignore
|
|
78
|
+
├── package.json
|
|
79
|
+
└── tsconfig.json (TypeScript only)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Starting your project
|
|
83
|
+
|
|
84
|
+
After the scaffold finishes, go into your project folder and start the dev server.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd my-app
|
|
88
|
+
npm run dev
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Once it is running, hit this endpoint to confirm everything is working.
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
GET http://localhost:3000/api/health
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
You should get back something like this.
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"statusCode": 200,
|
|
102
|
+
"message": "Server is healthy",
|
|
103
|
+
"data": { "status": "ok" },
|
|
104
|
+
"success": true
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Available scripts
|
|
109
|
+
|
|
110
|
+
The generated project comes with these scripts.
|
|
111
|
+
|
|
112
|
+
**TypeScript projects**
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm run dev # starts the dev server with hot reload
|
|
116
|
+
npm run build # compiles TypeScript to JavaScript in dist/
|
|
117
|
+
npm start # runs the compiled output
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**JavaScript projects**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm run dev # starts the dev server with hot reload via nodemon
|
|
124
|
+
npm start # runs the project directly with Node
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If you chose bun, pnpm, or yarn, replace `npm run` with your package manager. For example `pnpm dev` or `bun dev`.
|
|
128
|
+
|
|
129
|
+
## Using the utilities
|
|
130
|
+
|
|
131
|
+
Here is a quick example of how the utilities work together in a real route.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { Router } from "express";
|
|
135
|
+
import { asyncHandler } from "@/utils/asyncHandler";
|
|
136
|
+
import { ApiResponse } from "@/utils/apiResponse";
|
|
137
|
+
import { ApiError } from "@/utils/apiError";
|
|
138
|
+
|
|
139
|
+
const router = Router();
|
|
140
|
+
|
|
141
|
+
router.get("/user/:id", asyncHandler(async (req, res) => {
|
|
142
|
+
const user = await getUserById(req.params.id);
|
|
143
|
+
|
|
144
|
+
if (!user) {
|
|
145
|
+
throw new ApiError(404, "User not found");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
res.status(200).json(new ApiResponse(200, "User fetched successfully", user));
|
|
149
|
+
}));
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
If `getUserById` throws or `user` is not found, the error flows to the errorHandler automatically. No try catch needed.
|
|
153
|
+
|
|
154
|
+
## Environment variables
|
|
155
|
+
|
|
156
|
+
Copy the example file and fill in your values.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
cp .env.example .env
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The default variables are:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
PORT=3000
|
|
166
|
+
NODE_ENV=development
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Requirements
|
|
170
|
+
|
|
171
|
+
Node.js version 18 or higher is required.
|
package/dist/cli.js
CHANGED
|
@@ -35,11 +35,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
|
-
const validation_1 = require("./validation");
|
|
39
|
-
const naming_1 = require("./naming");
|
|
40
|
-
const prompt_1 = require("./prompt");
|
|
41
|
-
const packageManager_1 = require("./packageManager");
|
|
42
|
-
const scaffolder_1 = require("./scaffolder");
|
|
38
|
+
const validation_1 = require("./core/validation");
|
|
39
|
+
const naming_1 = require("./utils/naming");
|
|
40
|
+
const prompt_1 = require("./ui/prompt");
|
|
41
|
+
const packageManager_1 = require("./utils/packageManager");
|
|
42
|
+
const scaffolder_1 = require("./core/scaffolder");
|
|
43
43
|
function resolveTemplateDir(baseDir, lang, moduleSystem) {
|
|
44
44
|
if (lang === "ts")
|
|
45
45
|
return path.join(baseDir, "ts");
|
|
@@ -63,7 +63,7 @@ async function main() {
|
|
|
63
63
|
const packageManager = await (0, prompt_1.promptPackageManager)((0, packageManager_1.detectPackageManagers)());
|
|
64
64
|
const routerName = (0, naming_1.toRouterName)(projectName);
|
|
65
65
|
const templateDir = resolveTemplateDir(path.join(__dirname, "..", "templates"), lang, moduleSystem);
|
|
66
|
-
(0, scaffolder_1.scaffoldProject)({ projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir });
|
|
66
|
+
await (0, scaffolder_1.scaffoldProject)({ projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir });
|
|
67
67
|
}
|
|
68
68
|
catch (err) {
|
|
69
69
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.scaffoldProject = scaffoldProject;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const messages_1 = require("../ui/messages");
|
|
39
|
+
const fs_1 = require("../utils/fs");
|
|
40
|
+
const installer_1 = require("../utils/installer");
|
|
41
|
+
const packageManager_1 = require("../utils/packageManager");
|
|
42
|
+
const versions_1 = require("../utils/versions");
|
|
43
|
+
async function scaffoldProject(config) {
|
|
44
|
+
const { projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir } = config;
|
|
45
|
+
const baseReplacements = {
|
|
46
|
+
"{{PROJECT_NAME}}": projectName,
|
|
47
|
+
"{{ROUTER_NAME}}": routerName,
|
|
48
|
+
};
|
|
49
|
+
console.log(messages_1.Messages.creatingProject(lang, projectName));
|
|
50
|
+
(0, fs_1.copyTemplate)(templateDir, targetDir);
|
|
51
|
+
console.log(messages_1.Messages.resolvingVersions());
|
|
52
|
+
const versionReplacements = await (0, versions_1.resolveVersionReplacements)(templateDir);
|
|
53
|
+
(0, fs_1.finalizePackageJson)(targetDir, { ...baseReplacements, ...versionReplacements });
|
|
54
|
+
(0, fs_1.applyReplacementsInSources)(path.join(targetDir, "src"), baseReplacements);
|
|
55
|
+
(0, fs_1.renameGitignore)(targetDir);
|
|
56
|
+
(0, installer_1.installDependencies)(targetDir, projectName, packageManager);
|
|
57
|
+
console.log(messages_1.Messages.success(projectName, (0, packageManager_1.getDevCommand)(packageManager), (0, packageManager_1.getProdCommand)(packageManager, lang), isCurrentDir));
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.validateProjectName = validateProjectName;
|
|
37
|
+
exports.validateNewDir = validateNewDir;
|
|
38
|
+
exports.validateCurrentDir = validateCurrentDir;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const messages_1 = require("../ui/messages");
|
|
42
|
+
function isValidPackageName(name) {
|
|
43
|
+
return /^[a-z0-9]([a-z0-9\-_]*[a-z0-9])?$/.test(name);
|
|
44
|
+
}
|
|
45
|
+
function validateProjectName(name) {
|
|
46
|
+
if (!isValidPackageName(name))
|
|
47
|
+
throw new Error(messages_1.Messages.invalidName(name));
|
|
48
|
+
}
|
|
49
|
+
function validateNewDir(targetDir, projectName) {
|
|
50
|
+
if (fs.existsSync(targetDir))
|
|
51
|
+
throw new Error(messages_1.Messages.dirExists(projectName));
|
|
52
|
+
}
|
|
53
|
+
function validateCurrentDir(targetDir) {
|
|
54
|
+
if (fs.existsSync(path.join(targetDir, "package.json"))) {
|
|
55
|
+
throw new Error(messages_1.Messages.alreadyInitialized());
|
|
56
|
+
}
|
|
57
|
+
}
|
package/dist/messages.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.Messages = {
|
|
|
15
15
|
const label = lang === "ts" ? "TypeScript" : "JavaScript";
|
|
16
16
|
return `\nCreating ${label} project "${name}"...`;
|
|
17
17
|
},
|
|
18
|
+
resolvingVersions: () => "Resolving latest package versions...",
|
|
18
19
|
installingDeps: () => "Installing dependencies...\n",
|
|
19
20
|
installFailed: (name, installCmd) => `\nWarning: install failed. Run it manually:\n cd ${name} && ${installCmd}`,
|
|
20
21
|
success: (name, devCmd, prodCmd, isCurrentDir) => {
|
package/dist/scaffolder.js
CHANGED
|
@@ -39,16 +39,19 @@ const messages_1 = require("./messages");
|
|
|
39
39
|
const fs_1 = require("./fs");
|
|
40
40
|
const installer_1 = require("./installer");
|
|
41
41
|
const packageManager_1 = require("./packageManager");
|
|
42
|
-
|
|
42
|
+
const versions_1 = require("./versions");
|
|
43
|
+
async function scaffoldProject(config) {
|
|
43
44
|
const { projectName, lang, packageManager, routerName, targetDir, templateDir, isCurrentDir } = config;
|
|
44
|
-
const
|
|
45
|
+
const baseReplacements = {
|
|
45
46
|
"{{PROJECT_NAME}}": projectName,
|
|
46
47
|
"{{ROUTER_NAME}}": routerName,
|
|
47
48
|
};
|
|
48
49
|
console.log(messages_1.Messages.creatingProject(lang, projectName));
|
|
49
50
|
(0, fs_1.copyTemplate)(templateDir, targetDir);
|
|
50
|
-
(
|
|
51
|
-
(0,
|
|
51
|
+
console.log(messages_1.Messages.resolvingVersions());
|
|
52
|
+
const versionReplacements = await (0, versions_1.resolveVersionReplacements)(templateDir);
|
|
53
|
+
(0, fs_1.finalizePackageJson)(targetDir, { ...baseReplacements, ...versionReplacements });
|
|
54
|
+
(0, fs_1.applyReplacementsInSources)(path.join(targetDir, "src"), baseReplacements);
|
|
52
55
|
(0, fs_1.renameGitignore)(targetDir);
|
|
53
56
|
(0, installer_1.installDependencies)(targetDir, projectName, packageManager);
|
|
54
57
|
console.log(messages_1.Messages.success(projectName, (0, packageManager_1.getDevCommand)(packageManager), (0, packageManager_1.getProdCommand)(packageManager, lang), isCurrentDir));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Messages = void 0;
|
|
4
|
+
exports.Messages = {
|
|
5
|
+
usage: () => "Usage: npx exinit [project-name]\n" +
|
|
6
|
+
"Omit the name to scaffold in the current directory.",
|
|
7
|
+
invalidName: (name) => `Error: "${name}" is not a valid project name.\n` +
|
|
8
|
+
`Use lowercase letters, numbers, and hyphens only (e.g., my-app).`,
|
|
9
|
+
dirExists: (name) => `Error: Directory "${name}" already exists.\n` +
|
|
10
|
+
`Choose a different name or remove the existing directory.`,
|
|
11
|
+
alreadyInitialized: () => "Error: This directory already has a package.json.\n" +
|
|
12
|
+
"Run in an empty directory or provide a project name to create a new one.",
|
|
13
|
+
copyFailed: (err) => `Error: Failed to copy template files. ${err}`,
|
|
14
|
+
creatingProject: (lang, name) => {
|
|
15
|
+
const label = lang === "ts" ? "TypeScript" : "JavaScript";
|
|
16
|
+
return `\nCreating ${label} project "${name}"...`;
|
|
17
|
+
},
|
|
18
|
+
resolvingVersions: () => "Resolving latest package versions...",
|
|
19
|
+
installingDeps: () => "Installing dependencies...\n",
|
|
20
|
+
installFailed: (name, installCmd) => `\nWarning: install failed. Run it manually:\n cd ${name} && ${installCmd}`,
|
|
21
|
+
success: (name, devCmd, prodCmd, isCurrentDir) => {
|
|
22
|
+
const nav = isCurrentDir ? ` ${devCmd}` : ` cd ${name}\n ${devCmd}`;
|
|
23
|
+
return `
|
|
24
|
+
Done! Your project "${name}" is ready.
|
|
25
|
+
|
|
26
|
+
${nav}
|
|
27
|
+
|
|
28
|
+
Next steps:
|
|
29
|
+
- Copy .env.example to .env and set your environment variables
|
|
30
|
+
- Add routes in src/routes/
|
|
31
|
+
- Production: ${prodCmd}
|
|
32
|
+
`;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptLanguage = promptLanguage;
|
|
4
|
+
exports.promptModuleSystem = promptModuleSystem;
|
|
5
|
+
exports.promptPackageManager = promptPackageManager;
|
|
6
|
+
function renderMenu(title, options, selectedIndex, firstRender) {
|
|
7
|
+
if (!firstRender) {
|
|
8
|
+
process.stdout.write(`\x1B[${options.length + 1}A\r`);
|
|
9
|
+
}
|
|
10
|
+
process.stdout.write(`? ${title}: (Use arrow keys)\n`);
|
|
11
|
+
options.forEach((opt, i) => {
|
|
12
|
+
const hint = opt.hint ? ` ${opt.hint}` : "";
|
|
13
|
+
const isSelected = i === selectedIndex;
|
|
14
|
+
if (opt.disabled) {
|
|
15
|
+
process.stdout.write(` \x1B[2m${opt.label}${hint}\x1B[0m\n`);
|
|
16
|
+
}
|
|
17
|
+
else if (isSelected) {
|
|
18
|
+
process.stdout.write(` \x1B[36m> ${opt.label}${hint}\x1B[0m\n`);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
process.stdout.write(` ${opt.label}${hint}\n`);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function findNextEnabled(options, current, direction) {
|
|
26
|
+
let next = current + direction;
|
|
27
|
+
while (next >= 0 && next < options.length) {
|
|
28
|
+
if (!options[next].disabled)
|
|
29
|
+
return next;
|
|
30
|
+
next += direction;
|
|
31
|
+
}
|
|
32
|
+
return current;
|
|
33
|
+
}
|
|
34
|
+
function promptSelection(title, options) {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const defaultIndex = options.findIndex((opt) => !opt.disabled);
|
|
37
|
+
let selected = defaultIndex >= 0 ? defaultIndex : 0;
|
|
38
|
+
renderMenu(title, options, selected, true);
|
|
39
|
+
if (!process.stdin.isTTY) {
|
|
40
|
+
resolve(selected);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
process.stdin.setRawMode(true);
|
|
44
|
+
process.stdin.resume();
|
|
45
|
+
const handleKey = (key) => {
|
|
46
|
+
const isUpArrow = key[0] === 0x1b && key[1] === 0x5b && key[2] === 0x41;
|
|
47
|
+
const isDownArrow = key[0] === 0x1b && key[1] === 0x5b && key[2] === 0x42;
|
|
48
|
+
const isEnter = key[0] === 0x0d || key[0] === 0x0a;
|
|
49
|
+
const isCtrlC = key[0] === 0x03;
|
|
50
|
+
if (isUpArrow) {
|
|
51
|
+
selected = findNextEnabled(options, selected, -1);
|
|
52
|
+
renderMenu(title, options, selected, false);
|
|
53
|
+
}
|
|
54
|
+
else if (isDownArrow) {
|
|
55
|
+
selected = findNextEnabled(options, selected, 1);
|
|
56
|
+
renderMenu(title, options, selected, false);
|
|
57
|
+
}
|
|
58
|
+
else if (isEnter) {
|
|
59
|
+
process.stdin.setRawMode(false);
|
|
60
|
+
process.stdin.pause();
|
|
61
|
+
process.stdin.removeListener("data", handleKey);
|
|
62
|
+
process.stdout.write(`\x1B[${options.length + 1}A\r\x1B[J`);
|
|
63
|
+
process.stdout.write(`? ${title}: \x1B[36m${options[selected].label}\x1B[0m\n`);
|
|
64
|
+
resolve(selected);
|
|
65
|
+
}
|
|
66
|
+
else if (isCtrlC) {
|
|
67
|
+
process.stdin.setRawMode(false);
|
|
68
|
+
process.stdin.removeListener("data", handleKey);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
process.stdin.on("data", handleKey);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function promptLanguage() {
|
|
76
|
+
const options = [
|
|
77
|
+
{ label: "TypeScript" },
|
|
78
|
+
{ label: "JavaScript" },
|
|
79
|
+
];
|
|
80
|
+
const index = await promptSelection("Select language", options);
|
|
81
|
+
return index === 0 ? "ts" : "js";
|
|
82
|
+
}
|
|
83
|
+
async function promptModuleSystem() {
|
|
84
|
+
const options = [
|
|
85
|
+
{ label: "CommonJS", hint: "(require / module.exports)" },
|
|
86
|
+
{ label: "ES Modules", hint: "(import / export)" },
|
|
87
|
+
];
|
|
88
|
+
const index = await promptSelection("Choose module system", options);
|
|
89
|
+
return index === 0 ? "cjs" : "esm";
|
|
90
|
+
}
|
|
91
|
+
async function promptPackageManager(managers) {
|
|
92
|
+
const options = managers.map((m) => ({
|
|
93
|
+
label: m.name,
|
|
94
|
+
disabled: !m.installed,
|
|
95
|
+
hint: !m.installed ? "(not installed)" : m.name === "npm" ? "(default)" : undefined,
|
|
96
|
+
}));
|
|
97
|
+
const index = await promptSelection("Choose package manager", options);
|
|
98
|
+
return managers[index].name;
|
|
99
|
+
}
|
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.copyDir = copyDir;
|
|
37
|
+
exports.copyTemplate = copyTemplate;
|
|
38
|
+
exports.applyReplacementsInSources = applyReplacementsInSources;
|
|
39
|
+
exports.finalizePackageJson = finalizePackageJson;
|
|
40
|
+
exports.renameGitignore = renameGitignore;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const messages_1 = require("../ui/messages");
|
|
44
|
+
function copyDir(src, dest) {
|
|
45
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
46
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
47
|
+
const srcPath = path.join(src, entry.name);
|
|
48
|
+
const destPath = path.join(dest, entry.name);
|
|
49
|
+
if (entry.isDirectory()) {
|
|
50
|
+
copyDir(srcPath, destPath);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
fs.copyFileSync(srcPath, destPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function copyTemplate(templateDir, targetDir) {
|
|
58
|
+
try {
|
|
59
|
+
copyDir(templateDir, targetDir);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
63
|
+
throw new Error(messages_1.Messages.copyFailed(err));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function escapeForRegex(str) {
|
|
67
|
+
return str.replace(/[{}.*+?^$|[\]\\]/g, "\\$&");
|
|
68
|
+
}
|
|
69
|
+
function applyReplacements(content, replacements) {
|
|
70
|
+
return Object.entries(replacements).reduce((result, [placeholder, value]) => {
|
|
71
|
+
return result.replace(new RegExp(escapeForRegex(placeholder), "g"), value);
|
|
72
|
+
}, content);
|
|
73
|
+
}
|
|
74
|
+
function applyReplacementsInSources(srcDir, replacements) {
|
|
75
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
76
|
+
const fullPath = path.join(srcDir, entry.name);
|
|
77
|
+
if (entry.isDirectory()) {
|
|
78
|
+
applyReplacementsInSources(fullPath, replacements);
|
|
79
|
+
}
|
|
80
|
+
else if ([".ts", ".js"].includes(path.extname(entry.name))) {
|
|
81
|
+
const updated = applyReplacements(fs.readFileSync(fullPath, "utf-8"), replacements);
|
|
82
|
+
fs.writeFileSync(fullPath, updated);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function finalizePackageJson(targetDir, replacements) {
|
|
87
|
+
const templatePath = path.join(targetDir, "package.json.template");
|
|
88
|
+
const outputPath = path.join(targetDir, "package.json");
|
|
89
|
+
const content = applyReplacements(fs.readFileSync(templatePath, "utf-8"), replacements);
|
|
90
|
+
fs.writeFileSync(outputPath, content);
|
|
91
|
+
fs.unlinkSync(templatePath);
|
|
92
|
+
}
|
|
93
|
+
function renameGitignore(targetDir) {
|
|
94
|
+
const src = path.join(targetDir, "gitignore");
|
|
95
|
+
const dest = path.join(targetDir, ".gitignore");
|
|
96
|
+
if (fs.existsSync(src)) {
|
|
97
|
+
fs.renameSync(src, dest);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.installDependencies = installDependencies;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const messages_1 = require("../ui/messages");
|
|
6
|
+
const packageManager_1 = require("./packageManager");
|
|
7
|
+
function installDependencies(targetDir, projectName, pm) {
|
|
8
|
+
console.log(messages_1.Messages.installingDeps());
|
|
9
|
+
try {
|
|
10
|
+
(0, child_process_1.execSync)((0, packageManager_1.getInstallCommand)(pm), { cwd: targetDir, stdio: "inherit" });
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
console.warn(messages_1.Messages.installFailed(projectName, (0, packageManager_1.getInstallCommand)(pm)));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toCamelCase = toCamelCase;
|
|
4
|
+
exports.toRouterName = toRouterName;
|
|
5
|
+
function toCamelCase(name) {
|
|
6
|
+
return name.replace(/-([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
7
|
+
}
|
|
8
|
+
function toRouterName(projectName) {
|
|
9
|
+
return toCamelCase(projectName) + "Router";
|
|
10
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectPackageManagers = detectPackageManagers;
|
|
4
|
+
exports.getInstallCommand = getInstallCommand;
|
|
5
|
+
exports.getDevCommand = getDevCommand;
|
|
6
|
+
exports.getProdCommand = getProdCommand;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const ALL_PACKAGE_MANAGERS = ["npm", "bun", "pnpm", "yarn"];
|
|
9
|
+
function isInstalled(pm) {
|
|
10
|
+
try {
|
|
11
|
+
(0, child_process_1.execSync)(`${pm} --version`, { stdio: "ignore" });
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function detectPackageManagers() {
|
|
19
|
+
return ALL_PACKAGE_MANAGERS.map((name) => ({
|
|
20
|
+
name,
|
|
21
|
+
installed: isInstalled(name),
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
function getInstallCommand(pm) {
|
|
25
|
+
const commands = {
|
|
26
|
+
npm: "npm install",
|
|
27
|
+
bun: "bun install",
|
|
28
|
+
pnpm: "pnpm install",
|
|
29
|
+
yarn: "yarn",
|
|
30
|
+
};
|
|
31
|
+
return commands[pm];
|
|
32
|
+
}
|
|
33
|
+
function getDevCommand(pm) {
|
|
34
|
+
const commands = {
|
|
35
|
+
npm: "npm run dev",
|
|
36
|
+
bun: "bun dev",
|
|
37
|
+
pnpm: "pnpm dev",
|
|
38
|
+
yarn: "yarn dev",
|
|
39
|
+
};
|
|
40
|
+
return commands[pm];
|
|
41
|
+
}
|
|
42
|
+
function getProdCommand(pm, lang) {
|
|
43
|
+
if (lang === "js") {
|
|
44
|
+
const startCmds = {
|
|
45
|
+
npm: "npm start",
|
|
46
|
+
bun: "bun start",
|
|
47
|
+
pnpm: "pnpm start",
|
|
48
|
+
yarn: "yarn start",
|
|
49
|
+
};
|
|
50
|
+
return startCmds[pm];
|
|
51
|
+
}
|
|
52
|
+
const buildAndStartCmds = {
|
|
53
|
+
npm: "npm run build && npm start",
|
|
54
|
+
bun: "bun run build && bun start",
|
|
55
|
+
pnpm: "pnpm build && pnpm start",
|
|
56
|
+
yarn: "yarn build && yarn start",
|
|
57
|
+
};
|
|
58
|
+
return buildAndStartCmds[pm];
|
|
59
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveVersionReplacements = resolveVersionReplacements;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const util_1 = require("util");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
42
|
+
async function fetchLatestVersion(packageName) {
|
|
43
|
+
try {
|
|
44
|
+
const { stdout } = await execAsync(`npm show ${packageName} version`);
|
|
45
|
+
return `^${stdout.trim()}`;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return "latest";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function extractPackageNames(templateContent) {
|
|
52
|
+
const pattern = /\{\{VERSION:([^}]+)\}\}/g;
|
|
53
|
+
const packages = new Set();
|
|
54
|
+
let match;
|
|
55
|
+
while ((match = pattern.exec(templateContent)) !== null) {
|
|
56
|
+
packages.add(match[1]);
|
|
57
|
+
}
|
|
58
|
+
return [...packages];
|
|
59
|
+
}
|
|
60
|
+
async function resolveVersionReplacements(templateDir) {
|
|
61
|
+
const templatePath = path.join(templateDir, "package.json.template");
|
|
62
|
+
const content = fs.readFileSync(templatePath, "utf-8");
|
|
63
|
+
const packages = extractPackageNames(content);
|
|
64
|
+
const resolved = await Promise.all(packages.map(async (pkg) => ({
|
|
65
|
+
placeholder: `{{VERSION:${pkg}}}`,
|
|
66
|
+
version: await fetchLatestVersion(pkg),
|
|
67
|
+
})));
|
|
68
|
+
return Object.fromEntries(resolved.map(({ placeholder, version }) => [placeholder, version]));
|
|
69
|
+
}
|
package/dist/versions.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveVersionReplacements = resolveVersionReplacements;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const util_1 = require("util");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
42
|
+
async function fetchLatestVersion(packageName) {
|
|
43
|
+
try {
|
|
44
|
+
const { stdout } = await execAsync(`npm show ${packageName} version`);
|
|
45
|
+
return `^${stdout.trim()}`;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return "latest";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function extractPackageNames(templateContent) {
|
|
52
|
+
const pattern = /\{\{VERSION:([^}]+)\}\}/g;
|
|
53
|
+
const packages = new Set();
|
|
54
|
+
let match;
|
|
55
|
+
while ((match = pattern.exec(templateContent)) !== null) {
|
|
56
|
+
packages.add(match[1]);
|
|
57
|
+
}
|
|
58
|
+
return [...packages];
|
|
59
|
+
}
|
|
60
|
+
async function resolveVersionReplacements(templateDir) {
|
|
61
|
+
const templatePath = path.join(templateDir, "package.json.template");
|
|
62
|
+
const content = fs.readFileSync(templatePath, "utf-8");
|
|
63
|
+
const packages = extractPackageNames(content);
|
|
64
|
+
const resolved = await Promise.all(packages.map(async (pkg) => ({
|
|
65
|
+
placeholder: `{{VERSION:${pkg}}}`,
|
|
66
|
+
version: await fetchLatestVersion(pkg),
|
|
67
|
+
})));
|
|
68
|
+
return Object.fromEntries(resolved.map(({ placeholder, version }) => [placeholder, version]));
|
|
69
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patel.ajay745/exinit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Scaffold a production-ready Express project in seconds",
|
|
5
5
|
"bin": {
|
|
6
6
|
"exinit": "./dist/cli.js"
|
|
@@ -18,7 +18,13 @@
|
|
|
18
18
|
"engines": {
|
|
19
19
|
"node": ">=18.0.0"
|
|
20
20
|
},
|
|
21
|
-
"keywords": [
|
|
21
|
+
"keywords": [
|
|
22
|
+
"express",
|
|
23
|
+
"typescript",
|
|
24
|
+
"boilerplate",
|
|
25
|
+
"scaffold",
|
|
26
|
+
"starter"
|
|
27
|
+
],
|
|
22
28
|
"license": "MIT",
|
|
23
29
|
"devDependencies": {
|
|
24
30
|
"typescript": "^5.4.5",
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
"start": "node src/index.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"express": "
|
|
15
|
-
"dotenv": "
|
|
16
|
-
"module-alias": "
|
|
14
|
+
"express": "{{VERSION:express}}",
|
|
15
|
+
"dotenv": "{{VERSION:dotenv}}",
|
|
16
|
+
"module-alias": "{{VERSION:module-alias}}"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"nodemon": "
|
|
19
|
+
"nodemon": "{{VERSION:nodemon}}"
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"start": "node src/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"express": "
|
|
13
|
-
"dotenv": "
|
|
12
|
+
"express": "{{VERSION:express}}",
|
|
13
|
+
"dotenv": "{{VERSION:dotenv}}"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"nodemon": "
|
|
16
|
+
"nodemon": "{{VERSION:nodemon}}"
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
"start": "node dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"express": "
|
|
13
|
-
"dotenv": "
|
|
12
|
+
"express": "{{VERSION:express}}",
|
|
13
|
+
"dotenv": "{{VERSION:dotenv}}"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"typescript": "
|
|
17
|
-
"@types/express": "
|
|
18
|
-
"@types/node": "
|
|
19
|
-
"ts-node-dev": "
|
|
20
|
-
"tsconfig-paths": "
|
|
21
|
-
"tsc-alias": "
|
|
16
|
+
"typescript": "{{VERSION:typescript}}",
|
|
17
|
+
"@types/express": "{{VERSION:@types/express}}",
|
|
18
|
+
"@types/node": "{{VERSION:@types/node}}",
|
|
19
|
+
"ts-node-dev": "{{VERSION:ts-node-dev}}",
|
|
20
|
+
"tsconfig-paths": "{{VERSION:tsconfig-paths}}",
|
|
21
|
+
"tsc-alias": "{{VERSION:tsc-alias}}"
|
|
22
22
|
}
|
|
23
23
|
}
|