fwinit 1.0.1 → 1.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/index.js +116 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47,8 +47,8 @@ function findTemplate(input) {
|
|
|
47
47
|
|
|
48
48
|
// src/downloader.ts
|
|
49
49
|
import AdmZip from "adm-zip";
|
|
50
|
-
import { mkdir, rm, cp, readdir } from "fs/promises";
|
|
51
|
-
import { join } from "path";
|
|
50
|
+
import { mkdir, rm, cp, readdir, readFile, writeFile, rename } from "fs/promises";
|
|
51
|
+
import { join, extname } from "path";
|
|
52
52
|
import { tmpdir } from "os";
|
|
53
53
|
import { randomBytes } from "crypto";
|
|
54
54
|
var GITHUB_REPO = "orlandotellez/fwinit";
|
|
@@ -101,6 +101,96 @@ async function cleanTemplate(dir) {
|
|
|
101
101
|
async function cleanup(tempDir) {
|
|
102
102
|
await rm(tempDir, { recursive: true, force: true });
|
|
103
103
|
}
|
|
104
|
+
async function substituteTemplate(dir, projectName, templateFolder) {
|
|
105
|
+
if (templateFolder === "ASPNET") {
|
|
106
|
+
await substituteAspNet(dir, projectName);
|
|
107
|
+
} else {
|
|
108
|
+
await substituteNodejs(dir, projectName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function substituteNodejs(dir, projectName) {
|
|
112
|
+
const packageJsonPath = join(dir, "package.json");
|
|
113
|
+
try {
|
|
114
|
+
const content = await readFile(packageJsonPath, "utf-8");
|
|
115
|
+
const pkg = JSON.parse(content);
|
|
116
|
+
pkg.name = projectName;
|
|
117
|
+
await writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
118
|
+
} catch {
|
|
119
|
+
}
|
|
120
|
+
const appJsonPath = join(dir, "app.json");
|
|
121
|
+
try {
|
|
122
|
+
const content = await readFile(appJsonPath, "utf-8");
|
|
123
|
+
const app = JSON.parse(content);
|
|
124
|
+
if (app.expo) {
|
|
125
|
+
app.expo.name = projectName;
|
|
126
|
+
app.expo.slug = projectName;
|
|
127
|
+
if (app.expo.scheme) {
|
|
128
|
+
app.expo.scheme = toScheme(projectName);
|
|
129
|
+
}
|
|
130
|
+
await writeFile(appJsonPath, JSON.stringify(app, null, 2) + "\n");
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function toScheme(str) {
|
|
136
|
+
return str.replace(/[-_\s]+/g, "").toLowerCase();
|
|
137
|
+
}
|
|
138
|
+
async function substituteAspNet(dir, projectName) {
|
|
139
|
+
const pascalName = toPascalCase(projectName);
|
|
140
|
+
const textExtensions = /* @__PURE__ */ new Set([".cs", ".csproj", ".slnx", ".json", ".http"]);
|
|
141
|
+
const allFiles = await getAllFiles(dir);
|
|
142
|
+
for (const filePath of allFiles) {
|
|
143
|
+
const ext = extname(filePath).toLowerCase();
|
|
144
|
+
if (textExtensions.has(ext)) {
|
|
145
|
+
try {
|
|
146
|
+
const content = await readFile(filePath, "utf-8");
|
|
147
|
+
const replaced = content.replace(/Example/g, pascalName);
|
|
148
|
+
if (replaced !== content) {
|
|
149
|
+
await writeFile(filePath, replaced);
|
|
150
|
+
}
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
await renameAll(dir, pascalName);
|
|
156
|
+
}
|
|
157
|
+
async function getAllFiles(dir) {
|
|
158
|
+
const results = [];
|
|
159
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
160
|
+
for (const entry of entries) {
|
|
161
|
+
const fullPath = join(dir, entry.name);
|
|
162
|
+
if (entry.isDirectory()) {
|
|
163
|
+
results.push(...await getAllFiles(fullPath));
|
|
164
|
+
} else {
|
|
165
|
+
results.push(fullPath);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return results;
|
|
169
|
+
}
|
|
170
|
+
async function renameAll(dir, pascalName) {
|
|
171
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
172
|
+
for (const entry of entries) {
|
|
173
|
+
const oldPath = join(dir, entry.name);
|
|
174
|
+
if (entry.isDirectory()) {
|
|
175
|
+
await renameAll(oldPath, pascalName);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const entriesAfter = await readdir(dir, { withFileTypes: true });
|
|
179
|
+
for (const entry of entriesAfter) {
|
|
180
|
+
if (entry.name.includes("Example")) {
|
|
181
|
+
const oldPath = join(dir, entry.name);
|
|
182
|
+
const newName = entry.name.replace(/Example/g, pascalName);
|
|
183
|
+
const newPath = join(dir, newName);
|
|
184
|
+
try {
|
|
185
|
+
await rename(oldPath, newPath);
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function toPascalCase(str) {
|
|
192
|
+
return str.split(/[-_\s]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
193
|
+
}
|
|
104
194
|
|
|
105
195
|
// src/prompts.ts
|
|
106
196
|
import inquirer from "inquirer";
|
|
@@ -109,7 +199,7 @@ async function selectTemplate() {
|
|
|
109
199
|
{
|
|
110
200
|
type: "list",
|
|
111
201
|
name: "template",
|
|
112
|
-
message: "
|
|
202
|
+
message: "\xBFQu\xE9 proyecto quer\xE9s crear?",
|
|
113
203
|
choices: TEMPLATES.map((t) => ({
|
|
114
204
|
name: `${t.name} \u2014 ${t.description}`,
|
|
115
205
|
value: t
|
|
@@ -123,11 +213,11 @@ async function askProjectName() {
|
|
|
123
213
|
{
|
|
124
214
|
type: "input",
|
|
125
215
|
name: "name",
|
|
126
|
-
message: "
|
|
216
|
+
message: "Nombre del proyecto:",
|
|
127
217
|
validate: (input) => {
|
|
128
|
-
if (!input.trim()) return "
|
|
218
|
+
if (!input.trim()) return "El nombre no puede estar vac\xEDo";
|
|
129
219
|
if (!/^[a-zA-Z0-9_-]+$/.test(input)) {
|
|
130
|
-
return "
|
|
220
|
+
return "Solo letras, n\xFAmeros, guiones y guiones bajos";
|
|
131
221
|
}
|
|
132
222
|
return true;
|
|
133
223
|
}
|
|
@@ -149,10 +239,10 @@ function printSuccess(projectName, templateName, postInit) {
|
|
|
149
239
|
const installCmd = postInit?.install || "npm install";
|
|
150
240
|
const devCmd = postInit?.dev || "npm run dev";
|
|
151
241
|
console.log(`
|
|
152
|
-
\x1B[32m\u2714\x1B[0m Template
|
|
153
|
-
\x1B[32m\u2714\x1B[0m
|
|
242
|
+
\x1B[32m\u2714\x1B[0m Template descargado
|
|
243
|
+
\x1B[32m\u2714\x1B[0m Proyecto creado en ./${projectName}
|
|
154
244
|
|
|
155
|
-
\x1B[
|
|
245
|
+
\x1B[1mPr\xF3ximos pasos:\x1B[0m
|
|
156
246
|
|
|
157
247
|
\x1B[36mcd ${projectName}\x1B[0m
|
|
158
248
|
\x1B[36m${installCmd}\x1B[0m
|
|
@@ -162,10 +252,10 @@ function printSuccess(projectName, templateName, postInit) {
|
|
|
162
252
|
|
|
163
253
|
// src/index.ts
|
|
164
254
|
var program = new Command();
|
|
165
|
-
program.name("fwinit").description("CLI
|
|
166
|
-
program.command("list").description("
|
|
255
|
+
program.name("fwinit").description("CLI para crear proyectos desde templates").version("1.0.0");
|
|
256
|
+
program.command("list").description("Mostrar templates disponibles").action(() => {
|
|
167
257
|
console.log(
|
|
168
|
-
chalk.bold("\
|
|
258
|
+
chalk.bold("\nTemplates disponibles:\n")
|
|
169
259
|
);
|
|
170
260
|
TEMPLATES.forEach((t) => {
|
|
171
261
|
console.log(
|
|
@@ -174,7 +264,7 @@ program.command("list").description("Show available templates").action(() => {
|
|
|
174
264
|
});
|
|
175
265
|
console.log();
|
|
176
266
|
});
|
|
177
|
-
program.argument("[template]", "Template
|
|
267
|
+
program.argument("[template]", "Template a usar").argument("[project-name]", "Nombre del proyecto").action(
|
|
178
268
|
async (templateArg, projectNameArg) => {
|
|
179
269
|
try {
|
|
180
270
|
let template = templateArg ? findTemplate(templateArg) : void 0;
|
|
@@ -183,11 +273,11 @@ program.argument("[template]", "Template to use").argument("[project-name]", "Pr
|
|
|
183
273
|
console.error(
|
|
184
274
|
chalk.red(
|
|
185
275
|
`
|
|
186
|
-
\u2716 Template "${templateArg}"
|
|
276
|
+
\u2716 Template "${templateArg}" no encontrado.
|
|
187
277
|
`
|
|
188
278
|
)
|
|
189
279
|
);
|
|
190
|
-
console.log("
|
|
280
|
+
console.log("Templates disponibles:");
|
|
191
281
|
TEMPLATES.forEach(
|
|
192
282
|
(t) => console.log(` - ${t.folder.toLowerCase()}`)
|
|
193
283
|
);
|
|
@@ -203,28 +293,33 @@ program.argument("[template]", "Template to use").argument("[project-name]", "Pr
|
|
|
203
293
|
console.error(
|
|
204
294
|
chalk.red(
|
|
205
295
|
`
|
|
206
|
-
\u2716
|
|
296
|
+
\u2716 El directorio "${projectName}" ya existe.`
|
|
207
297
|
)
|
|
208
298
|
);
|
|
209
299
|
process.exit(1);
|
|
210
300
|
}
|
|
211
301
|
const spinner = ora(
|
|
212
|
-
`
|
|
302
|
+
`Descargando template ${template.name}...`
|
|
213
303
|
).start();
|
|
214
304
|
const { tempDir, templatePath } = await downloadAndExtract(template.folder);
|
|
215
|
-
spinner.text = "
|
|
305
|
+
spinner.text = "Creando proyecto...";
|
|
216
306
|
await copyTemplate(
|
|
217
307
|
templatePath,
|
|
218
308
|
getProjectPath(projectName)
|
|
219
309
|
);
|
|
310
|
+
await substituteTemplate(
|
|
311
|
+
getProjectPath(projectName),
|
|
312
|
+
projectName,
|
|
313
|
+
template.folder
|
|
314
|
+
);
|
|
220
315
|
await cleanup(tempDir);
|
|
221
|
-
spinner.succeed("Template
|
|
316
|
+
spinner.succeed("Template descargado");
|
|
222
317
|
let postInit;
|
|
223
318
|
try {
|
|
224
|
-
const { readFile } = await import("fs/promises");
|
|
319
|
+
const { readFile: readFile2 } = await import("fs/promises");
|
|
225
320
|
const { join: join2 } = await import("path");
|
|
226
321
|
const tj = JSON.parse(
|
|
227
|
-
await
|
|
322
|
+
await readFile2(
|
|
228
323
|
join2(getProjectPath(projectName), "template.json"),
|
|
229
324
|
"utf-8"
|
|
230
325
|
)
|