fwinit 1.0.3 → 1.0.4
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/index.js +152 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,31 +11,36 @@ var TEMPLATES = [
|
|
|
11
11
|
name: "ASP.NET",
|
|
12
12
|
alias: ["aspnet", "dotnet", "csharp"],
|
|
13
13
|
description: "API REST con ASP.NET Core, Clean Architecture y C#",
|
|
14
|
-
folder: "ASPNET"
|
|
14
|
+
folder: "ASPNET",
|
|
15
|
+
runtime: "dotnet"
|
|
15
16
|
},
|
|
16
17
|
{
|
|
17
18
|
name: "Express",
|
|
18
19
|
alias: ["express"],
|
|
19
20
|
description: "API REST con Express, Prisma, TypeScript y Bun",
|
|
20
|
-
folder: "EXPRESS"
|
|
21
|
+
folder: "EXPRESS",
|
|
22
|
+
runtime: "bun"
|
|
21
23
|
},
|
|
22
24
|
{
|
|
23
25
|
name: "Fastify",
|
|
24
26
|
alias: ["fastify"],
|
|
25
27
|
description: "API REST con Fastify, Prisma, TypeScript y Bun",
|
|
26
|
-
folder: "FASTIFY"
|
|
28
|
+
folder: "FASTIFY",
|
|
29
|
+
runtime: "bun"
|
|
27
30
|
},
|
|
28
31
|
{
|
|
29
32
|
name: "Node.js Vanilla",
|
|
30
33
|
alias: ["nodejs", "vanilla", "node"],
|
|
31
34
|
description: "API con Node.js puro, Prisma, TypeScript y tsx",
|
|
32
|
-
folder: "NODEJS-VANILLA"
|
|
35
|
+
folder: "NODEJS-VANILLA",
|
|
36
|
+
runtime: "node"
|
|
33
37
|
},
|
|
34
38
|
{
|
|
35
39
|
name: "React Native",
|
|
36
40
|
alias: ["react-native", "rn", "expo"],
|
|
37
41
|
description: "App m\xF3vil con React Native, Expo y TypeScript",
|
|
38
|
-
folder: "REACT-NATIVE"
|
|
42
|
+
folder: "REACT-NATIVE",
|
|
43
|
+
runtime: "node"
|
|
39
44
|
}
|
|
40
45
|
];
|
|
41
46
|
function findTemplate(input) {
|
|
@@ -208,6 +213,22 @@ async function selectTemplate() {
|
|
|
208
213
|
]);
|
|
209
214
|
return template;
|
|
210
215
|
}
|
|
216
|
+
async function selectPackageManager() {
|
|
217
|
+
const { pm } = await inquirer.prompt([
|
|
218
|
+
{
|
|
219
|
+
type: "list",
|
|
220
|
+
name: "pm",
|
|
221
|
+
message: "\xBFQu\xE9 package manager quer\xE9s usar?",
|
|
222
|
+
choices: [
|
|
223
|
+
{ name: "pnpm (recomendado)", value: "pnpm" },
|
|
224
|
+
{ name: "npm", value: "npm" },
|
|
225
|
+
{ name: "bun", value: "bun" }
|
|
226
|
+
],
|
|
227
|
+
default: "pnpm"
|
|
228
|
+
}
|
|
229
|
+
]);
|
|
230
|
+
return pm;
|
|
231
|
+
}
|
|
211
232
|
async function askProjectName() {
|
|
212
233
|
const { name } = await inquirer.prompt([
|
|
213
234
|
{
|
|
@@ -229,15 +250,67 @@ async function askProjectName() {
|
|
|
229
250
|
// src/utils.ts
|
|
230
251
|
import { existsSync } from "fs";
|
|
231
252
|
import { resolve } from "path";
|
|
253
|
+
var PM_RUNNER = {
|
|
254
|
+
npm: "npm",
|
|
255
|
+
pnpm: "pnpm",
|
|
256
|
+
bun: "bun"
|
|
257
|
+
};
|
|
258
|
+
var PM_EXEC = {
|
|
259
|
+
npm: "npx",
|
|
260
|
+
pnpm: "pnpm exec",
|
|
261
|
+
bun: "bunx"
|
|
262
|
+
};
|
|
263
|
+
var BUN_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
264
|
+
"install",
|
|
265
|
+
"add",
|
|
266
|
+
"remove",
|
|
267
|
+
"update",
|
|
268
|
+
"upgrade",
|
|
269
|
+
"run",
|
|
270
|
+
"x",
|
|
271
|
+
"link",
|
|
272
|
+
"unlink",
|
|
273
|
+
"init",
|
|
274
|
+
"create",
|
|
275
|
+
"pm",
|
|
276
|
+
"outdated",
|
|
277
|
+
"why",
|
|
278
|
+
"publish",
|
|
279
|
+
"prune",
|
|
280
|
+
"rebuild"
|
|
281
|
+
]);
|
|
232
282
|
function getProjectPath(name) {
|
|
233
283
|
return resolve(process.cwd(), name);
|
|
234
284
|
}
|
|
235
285
|
function projectExists(name) {
|
|
236
286
|
return existsSync(getProjectPath(name));
|
|
237
287
|
}
|
|
238
|
-
function
|
|
239
|
-
const
|
|
240
|
-
const
|
|
288
|
+
function resolveCommand(cmd, pm) {
|
|
289
|
+
const tokens = cmd.trim().split(/\s+/);
|
|
290
|
+
const [runner, ...rest] = tokens;
|
|
291
|
+
switch (runner) {
|
|
292
|
+
case "pnpm":
|
|
293
|
+
return [PM_RUNNER[pm], ...rest].join(" ");
|
|
294
|
+
case "npm":
|
|
295
|
+
return [PM_RUNNER[pm], ...rest].join(" ");
|
|
296
|
+
case "bun": {
|
|
297
|
+
if (pm === "bun") return cmd;
|
|
298
|
+
const sub = rest[0];
|
|
299
|
+
if (sub && !BUN_SUBCOMMANDS.has(sub)) {
|
|
300
|
+
return [PM_RUNNER[pm], "run", ...rest].join(" ");
|
|
301
|
+
}
|
|
302
|
+
return [PM_RUNNER[pm], ...rest].join(" ");
|
|
303
|
+
}
|
|
304
|
+
case "npx":
|
|
305
|
+
case "bunx":
|
|
306
|
+
return [PM_EXEC[pm], ...rest].join(" ");
|
|
307
|
+
default:
|
|
308
|
+
return cmd;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function printSuccess(projectName, templateName, pm, postInit) {
|
|
312
|
+
const installCmd = postInit?.install ? resolveCommand(postInit.install, pm) : `${pm} install`;
|
|
313
|
+
const devCmd = postInit?.dev ? resolveCommand(postInit.dev, pm) : `${pm} run dev`;
|
|
241
314
|
console.log(`
|
|
242
315
|
\x1B[32m\u2714\x1B[0m Template descargado
|
|
243
316
|
\x1B[32m\u2714\x1B[0m Proyecto creado en ./${projectName}
|
|
@@ -249,9 +322,60 @@ function printSuccess(projectName, templateName, postInit) {
|
|
|
249
322
|
\x1B[36m${devCmd}\x1B[0m
|
|
250
323
|
`);
|
|
251
324
|
}
|
|
325
|
+
function adaptScriptToNode(script) {
|
|
326
|
+
let s = script.trim();
|
|
327
|
+
if (/^bun test\b/.test(s)) {
|
|
328
|
+
s = s.replace(/^bun test\b/, "vitest run");
|
|
329
|
+
}
|
|
330
|
+
s = s.replace(/^bun --hot /, "tsx watch ").replace(/^bunx /, "").replace(/^bun /, "tsx ");
|
|
331
|
+
return s;
|
|
332
|
+
}
|
|
333
|
+
async function adaptToNodeRuntime(projectPath) {
|
|
334
|
+
const { readFile: readFile2, writeFile: writeFile2, readdir: readdir2 } = await import("fs/promises");
|
|
335
|
+
const { join: join2 } = await import("path");
|
|
336
|
+
const pkgPath = join2(projectPath, "package.json");
|
|
337
|
+
const pkg = JSON.parse(await readFile2(pkgPath, "utf-8"));
|
|
338
|
+
for (const key of Object.keys(pkg.scripts ?? {})) {
|
|
339
|
+
pkg.scripts[key] = adaptScriptToNode(pkg.scripts[key]);
|
|
340
|
+
}
|
|
341
|
+
pkg.devDependencies ??= {};
|
|
342
|
+
pkg.devDependencies.tsx = "^4.0.0";
|
|
343
|
+
pkg.devDependencies.vitest = "^3.0.0";
|
|
344
|
+
delete pkg.devDependencies["bun-types"];
|
|
345
|
+
await writeFile2(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
346
|
+
async function walk(dir) {
|
|
347
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
348
|
+
for (const entry of entries) {
|
|
349
|
+
const full = join2(dir, entry.name);
|
|
350
|
+
if (entry.isDirectory()) {
|
|
351
|
+
if (entry.name !== "node_modules") await walk(full);
|
|
352
|
+
} else if (entry.name.endsWith(".test.ts")) {
|
|
353
|
+
const content = await readFile2(full, "utf-8");
|
|
354
|
+
if (content.includes("bun:test")) {
|
|
355
|
+
await writeFile2(full, content.replaceAll('from "bun:test"', 'from "vitest"'));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
const srcDir = join2(projectPath, "src");
|
|
361
|
+
try {
|
|
362
|
+
await walk(srcDir);
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
const tsconfigPath = join2(projectPath, "tsconfig.json");
|
|
366
|
+
try {
|
|
367
|
+
const tsconfig = JSON.parse(await readFile2(tsconfigPath, "utf-8"));
|
|
368
|
+
if (tsconfig.compilerOptions?.types?.includes("bun-types")) {
|
|
369
|
+
delete tsconfig.compilerOptions.types;
|
|
370
|
+
await writeFile2(tsconfigPath, JSON.stringify(tsconfig, null, 2) + "\n");
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
252
375
|
|
|
253
376
|
// src/index.ts
|
|
254
377
|
var program = new Command();
|
|
378
|
+
var PACKAGE_MANAGERS = ["npm", "pnpm", "bun"];
|
|
255
379
|
program.name("fwinit").description("CLI para crear proyectos desde templates").version("1.0.0");
|
|
256
380
|
program.command("list").description("Mostrar templates disponibles").action(() => {
|
|
257
381
|
console.log(
|
|
@@ -264,11 +388,23 @@ program.command("list").description("Mostrar templates disponibles").action(() =
|
|
|
264
388
|
});
|
|
265
389
|
console.log();
|
|
266
390
|
});
|
|
267
|
-
program.argument("[template]", "Template a usar").argument("[project-name]", "Nombre del proyecto").action(
|
|
391
|
+
program.argument("[template]", "Template a usar").argument("[project-name]", "Nombre del proyecto").option("-p, --pm <package-manager>", "Package manager a usar: npm, pnpm o bun").action(
|
|
268
392
|
async (templateArg, projectNameArg) => {
|
|
269
393
|
try {
|
|
394
|
+
const { pm: pmArg } = program.opts();
|
|
395
|
+
if (pmArg && !PACKAGE_MANAGERS.includes(pmArg)) {
|
|
396
|
+
console.error(
|
|
397
|
+
chalk.red(
|
|
398
|
+
`
|
|
399
|
+
\u2716 Package manager "${pmArg}" inv\xE1lido. Us\xE1: npm, pnpm o bun.
|
|
400
|
+
`
|
|
401
|
+
)
|
|
402
|
+
);
|
|
403
|
+
process.exit(1);
|
|
404
|
+
}
|
|
270
405
|
let template = templateArg ? findTemplate(templateArg) : void 0;
|
|
271
406
|
let projectName = projectNameArg;
|
|
407
|
+
let pm = pmArg;
|
|
272
408
|
if (templateArg && !template) {
|
|
273
409
|
console.error(
|
|
274
410
|
chalk.red(
|
|
@@ -289,6 +425,9 @@ program.argument("[template]", "Template a usar").argument("[project-name]", "No
|
|
|
289
425
|
if (!projectName) {
|
|
290
426
|
projectName = await askProjectName();
|
|
291
427
|
}
|
|
428
|
+
if (!pm && template.runtime !== "dotnet") {
|
|
429
|
+
pm = await selectPackageManager();
|
|
430
|
+
}
|
|
292
431
|
if (projectExists(projectName)) {
|
|
293
432
|
console.error(
|
|
294
433
|
chalk.red(
|
|
@@ -312,6 +451,9 @@ program.argument("[template]", "Template a usar").argument("[project-name]", "No
|
|
|
312
451
|
projectName,
|
|
313
452
|
template.folder
|
|
314
453
|
);
|
|
454
|
+
if (template.runtime === "bun" && pm && pm !== "bun") {
|
|
455
|
+
await adaptToNodeRuntime(getProjectPath(projectName));
|
|
456
|
+
}
|
|
315
457
|
await cleanup(tempDir);
|
|
316
458
|
spinner.succeed("Template descargado");
|
|
317
459
|
let postInit;
|
|
@@ -327,7 +469,7 @@ program.argument("[template]", "Template a usar").argument("[project-name]", "No
|
|
|
327
469
|
postInit = tj.postInit;
|
|
328
470
|
} catch {
|
|
329
471
|
}
|
|
330
|
-
printSuccess(projectName, template.name, postInit);
|
|
472
|
+
printSuccess(projectName, template.name, pm ?? "npm", postInit);
|
|
331
473
|
} catch (error) {
|
|
332
474
|
console.error(
|
|
333
475
|
chalk.red(
|