create-sprint 0.0.1

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 (2) hide show
  1. package/bin/cli.ts +282 -0
  2. package/package.json +34 -0
package/bin/cli.ts ADDED
@@ -0,0 +1,282 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { select, input } from '@inquirer/prompts';
4
+ import { mkdir, writeFile } from 'fs/promises';
5
+ import { existsSync } from 'fs';
6
+ import { join } from 'path';
7
+
8
+ const args = process.argv.slice(2);
9
+ const initIndex = args.indexOf('init');
10
+ const isInitCommand = initIndex !== -1;
11
+
12
+ if (!isInitCommand) {
13
+ console.log('\nšŸš€ Sprint - Quickly API Framework\n');
14
+ console.log('Usage: sprint init [options]');
15
+ console.log('\nOptions:');
16
+ console.log(' --ts, --typescript Create TypeScript project');
17
+ console.log(' --js, --javascript Create JavaScript project');
18
+ console.log(' --name <name> Project name');
19
+ console.log(' --current Create in current directory');
20
+ console.log('\nExamples:');
21
+ console.log(' sprint init Interactive mode');
22
+ console.log(' sprint init --ts Create TypeScript project');
23
+ console.log(' sprint init --ts --name my-api');
24
+ console.log(' sprint init --js --current\n');
25
+ process.exit(0);
26
+ }
27
+
28
+ const hasTs = args.includes('--ts') || args.includes('--typescript');
29
+ const hasJs = args.includes('--js') || args.includes('--javascript');
30
+ const hasName = args.indexOf('--name');
31
+ const projectNameArg = hasName !== -1 ? args[hasName + 1] : null;
32
+ const useCurrentDirArg = args.includes('--current');
33
+
34
+ async function main() {
35
+ console.log('\nšŸš€ Welcome to Sprint - Quickly API Framework\n');
36
+
37
+ let projectName: string;
38
+ let language: 'typescript' | 'javascript';
39
+
40
+ if (projectNameArg) {
41
+ projectName = projectNameArg;
42
+ } else if (useCurrentDirArg) {
43
+ projectName = '.';
44
+ } else {
45
+ projectName = await getProjectName();
46
+ }
47
+
48
+ if (hasTs) {
49
+ language = 'typescript';
50
+ } else if (hasJs) {
51
+ language = 'javascript';
52
+ } else {
53
+ language = await selectLanguage();
54
+ }
55
+
56
+ console.log(`\nāœ… Creating Sprint project: ${projectName === '.' ? 'current directory' : projectName} with ${language === 'typescript' ? 'TypeScript' : 'JavaScript'}\n`);
57
+
58
+ await createProject(projectName, language);
59
+
60
+ console.log('\nāœ… Project created successfully!');
61
+ console.log(`\nšŸ“¦ Next steps:`);
62
+ console.log(` cd ${projectName === '.' ? '' : projectName}${projectName === '.' ? '' : ' '}(if created new directory)`);
63
+ console.log(` npm install`);
64
+ console.log(` npm run dev`);
65
+ console.log('\n');
66
+ }
67
+
68
+ async function getProjectName(): Promise<string> {
69
+ const useCurrentDir = await select({
70
+ message: 'Where would you like to create your project?',
71
+ choices: [
72
+ {
73
+ name: 'Current directory',
74
+ value: 'current',
75
+ },
76
+ {
77
+ name: 'New directory',
78
+ value: 'new',
79
+ },
80
+ ],
81
+ });
82
+
83
+ if (useCurrentDir === 'current') {
84
+ return '.';
85
+ }
86
+
87
+ const name = await input({
88
+ message: 'Enter project name:',
89
+ validate: (value: string) => {
90
+ if (!value.trim()) return 'Please enter a project name';
91
+ return true;
92
+ },
93
+ });
94
+
95
+ return name;
96
+ }
97
+
98
+ async function selectLanguage(): Promise<'typescript' | 'javascript'> {
99
+ const language: 'typescript' | 'javascript' = await select({
100
+ message: 'Select your preferred language:',
101
+ choices: [
102
+ {
103
+ name: 'TypeScript',
104
+ value: 'typescript',
105
+ description: 'Recommended - Type safety and better developer experience',
106
+ },
107
+ {
108
+ name: 'JavaScript',
109
+ value: 'javascript',
110
+ description: 'Vanilla JavaScript for simpler projects',
111
+ },
112
+ ],
113
+ });
114
+
115
+ return language;
116
+ }
117
+
118
+ async function createProject(projectName: string, language: 'typescript' | 'javascript') {
119
+ const isCurrentDir = projectName === '.';
120
+ const targetDir = isCurrentDir ? process.cwd() : join(process.cwd(), projectName);
121
+
122
+ if (!isCurrentDir && existsSync(targetDir)) {
123
+ console.error(`Error: Directory ${projectName} already exists`);
124
+ process.exit(1);
125
+ }
126
+
127
+ if (!isCurrentDir) {
128
+ await mkdir(targetDir, { recursive: true });
129
+ }
130
+
131
+ const pkgJson = language === 'typescript'
132
+ ? getTypeScriptPackageJson(projectName)
133
+ : getJavaScriptPackageJson(projectName);
134
+
135
+ await writeFile(join(targetDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
136
+
137
+ if (language === 'typescript') {
138
+ await writeFile(join(targetDir, 'tsconfig.json'), getTsConfig());
139
+ }
140
+
141
+ const srcDir = join(targetDir, 'src');
142
+ await mkdir(srcDir, { recursive: true });
143
+
144
+ await writeFile(join(srcDir, 'index.' + (language === 'typescript' ? 'ts' : 'js')), getMainFile(language));
145
+
146
+ if (language === 'typescript') {
147
+ await writeFile(join(srcDir, 'app.' + (language === 'typescript' ? 'ts' : 'js')), getAppFile(language));
148
+ }
149
+
150
+ await writeFile(join(targetDir, '.env.example'), getEnvExample());
151
+ }
152
+
153
+ function getTypeScriptPackageJson(name: string) {
154
+ return {
155
+ name: name === '.' ? 'sprint-app' : name,
156
+ version: '0.0.1',
157
+ description: 'Sprint API',
158
+ main: 'dist/index.js',
159
+ scripts: {
160
+ build: 'tsc',
161
+ start: 'node dist/index.js',
162
+ dev: 'tsx watch src/index.ts',
163
+ },
164
+ dependencies: {
165
+ 'sprint-es': '^0.0.23',
166
+ dotenv: '^17.0.0',
167
+ },
168
+ devDependencies: {
169
+ '@types/node': '^22.0.0',
170
+ 'tsx': '^4.19.0',
171
+ typescript: '^5.6.0',
172
+ },
173
+ };
174
+ }
175
+
176
+ function getJavaScriptPackageJson(name: string) {
177
+ return {
178
+ name: name === '.' ? 'sprint-app' : name,
179
+ version: '0.0.1',
180
+ description: 'Sprint API',
181
+ main: 'src/index.js',
182
+ type: 'module',
183
+ scripts: {
184
+ start: 'node src/index.js',
185
+ dev: 'node --watch src/index.js',
186
+ },
187
+ dependencies: {
188
+ 'sprint-es': '^0.0.23',
189
+ dotenv: '^17.0.0',
190
+ },
191
+ };
192
+ }
193
+
194
+ function getTsConfig() {
195
+ return JSON.stringify({
196
+ compilerOptions: {
197
+ target: 'ES2020',
198
+ module: 'ESNext',
199
+ moduleResolution: 'bundler',
200
+ lib: ['ES2020'],
201
+ outDir: './dist',
202
+ rootDir: './src',
203
+ strict: true,
204
+ esModuleInterop: true,
205
+ skipLibCheck: true,
206
+ forceConsistentCasingInFileNames: true,
207
+ resolveJsonModule: true,
208
+ declaration: true,
209
+ declarationMap: true,
210
+ sourceMap: true,
211
+ },
212
+ include: ['src/**/*'],
213
+ exclude: ['node_modules', 'dist'],
214
+ }, null, 2);
215
+ }
216
+
217
+ function getMainFile(language: 'typescript' | 'javascript') {
218
+ if (language === 'typescript') {
219
+ return `import Sprint from 'sprint-es';
220
+ import dotenv from 'dotenv';
221
+
222
+ dotenv.config();
223
+
224
+ const app = new Sprint({
225
+ port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
226
+ favicon: process.env.FAVICON || undefined,
227
+ bodyParser: {
228
+ limit: '10mb'
229
+ }
230
+ });
231
+
232
+ app.get('/', (req, res) => {
233
+ res.send('Hello from Sprint!');
234
+ });
235
+
236
+ app.listen();
237
+ `;
238
+ }
239
+ return `import Sprint from 'sprint-es';
240
+ import dotenv from 'dotenv';
241
+
242
+ dotenv.config();
243
+
244
+ const app = new Sprint({
245
+ port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
246
+ favicon: process.env.FAVICON || undefined,
247
+ bodyParser: {
248
+ limit: '10mb'
249
+ }
250
+ });
251
+
252
+ app.get('/', (req, res) => {
253
+ res.send('Hello from Sprint!');
254
+ });
255
+
256
+ app.listen();
257
+ `;
258
+ }
259
+
260
+ function getAppFile(language: 'typescript' | 'javascript') {
261
+ if (language === 'typescript') {
262
+ return `import type { SprintOptions } from 'sprint-es';
263
+
264
+ export const options: SprintOptions = {
265
+ port: 3000,
266
+ bodyParser: {
267
+ limit: '10mb'
268
+ }
269
+ };
270
+ `;
271
+ }
272
+ return '';
273
+ }
274
+
275
+ function getEnvExample() {
276
+ return `PORT=3000
277
+ FAVICON=./public/favicon.ico
278
+ NODE_ENV=development
279
+ `;
280
+ }
281
+
282
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "create-sprint",
3
+ "version": "0.0.1",
4
+ "description": "Create a new Sprint API project",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-sprint": "tsx bin/cli.ts",
8
+ "sprint": "tsx bin/cli.ts"
9
+ },
10
+ "files": [
11
+ "bin/**/*"
12
+ ],
13
+ "scripts": {
14
+ "start": "tsx bin/cli.ts"
15
+ },
16
+ "keywords": [
17
+ "sprint",
18
+ "api",
19
+ "framework",
20
+ "init",
21
+ "create"
22
+ ],
23
+ "author": "TPEOficial LLC",
24
+ "license": "Apache-2.0",
25
+ "dependencies": {
26
+ "@inquirer/prompts": "^7.10.1"
27
+ },
28
+ "devDependencies": {
29
+ "tsx": "^4.19.0"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ }
34
+ }