opticore-installer 1.2.49

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 ADDED
@@ -0,0 +1,951 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/installer.core.ts
4
+ import { intro, cancel as cancel5 } from "@clack/prompts";
5
+ import chalk6 from "chalk";
6
+ import colors9 from "ansi-colors";
7
+
8
+ // src/utils/console/welcomeMessage.util.ts
9
+ import cfonts from "cfonts";
10
+ import chalk from "chalk";
11
+ var UWelcomeMessage = () => {
12
+ cfonts.say("OpticoreJS", {
13
+ font: "block",
14
+ align: "left",
15
+ colors: ["yellow", "#FF6B35"],
16
+ background: "transparent",
17
+ letterSpacing: 1,
18
+ lineHeight: 1,
19
+ space: true,
20
+ maxLength: "0"
21
+ });
22
+ const orange = chalk.bold.hex("#FF6B35");
23
+ const dim = chalk.bold.yellow;
24
+ console.log(` ${orange("OPTICORE F R A M E W O R K I N S T A L L E R")}`);
25
+ console.log(` ${dim("Create \xB7 Configure \xB7 Deploy")}
26
+ `);
27
+ console.log(` ${chalk.bold.dim("Documentation")} ${chalk.underline.cyan("https://github.com/opticore/framework-installer")}
28
+ `);
29
+ };
30
+
31
+ // src/domains/services/prompts/select/promptSelect.service.ts
32
+ import { select, isCancel } from "@clack/prompts";
33
+
34
+ // src/utils/operationCancelled.util.ts
35
+ import { cancel } from "@clack/prompts";
36
+ import colors from "ansi-colors";
37
+ import fs from "fs";
38
+ var UOperationCancelled = (arg) => {
39
+ cancel(colors.bgRed(colors.white(" Operation cancelled ")));
40
+ if (arg) {
41
+ fs.rmSync(arg, { recursive: true, force: true });
42
+ }
43
+ process.exit(130);
44
+ };
45
+
46
+ // src/domains/services/prompts/select/promptSelect.service.ts
47
+ var SPromptSelect = async (arg) => {
48
+ const outputSelect = await select(arg);
49
+ return isCancel(outputSelect) ? UOperationCancelled : outputSelect;
50
+ };
51
+
52
+ // src/domains/services/prompts/select/outputPromptSelect.service.ts
53
+ var SOutputPromptSelect = async (arg) => {
54
+ return await SPromptSelect({
55
+ message: arg.message,
56
+ initialValue: arg.initialValue,
57
+ options: arg.options
58
+ });
59
+ };
60
+
61
+ // src/core/abstractions/enums/constants/generalMsg.constant.ts
62
+ var CGeneralMsg = {
63
+ noDbCredentials: "You will have to manually set all the variable values in the .env file.",
64
+ starterMsg: "Which starter project would you like to use ?",
65
+ starterInitValue: "restfull_api_project",
66
+ starterOptionsRestFullLabel: "RestFull API project",
67
+ starterOptionsRestFullValue: "restfull_api_project",
68
+ starterOptionsRestFullHint: "OptiCoreJS app tailored to create a RestFull APIs",
69
+ projectNameMessage: "Enter the name of project :",
70
+ projectNamePlaceholder: "opticore",
71
+ projectNameInvalidValue: "Please the project name can't be empty.",
72
+ projectNameBadPattern: "Please enter a valide project name.",
73
+ wrong: "Something went wrong.",
74
+ existingProject: "already exist, please give it another name."
75
+ };
76
+
77
+ // src/core/abstractions/enums/constants/starterOptions.constant.ts
78
+ var CStarterOptions = [
79
+ // { label: "RestFull API complete project", value: ["complete_restfull_project"], hint: "Everything you'll need to build a server render web project" },
80
+ { label: "Web project", value: ["web_project"], hint: "Everything you'll need to build a server render web project" },
81
+ { label: "Skeleton project", value: ["skeleton_project"], hint: "A lean OptiCoreJS application with the framework core" },
82
+ { label: CGeneralMsg.starterOptionsRestFullLabel, value: [CGeneralMsg.starterOptionsRestFullValue], hint: CGeneralMsg.starterOptionsRestFullHint },
83
+ // { label: "Complete restFull API project", value: ["complete_api_restfull_project"], hint: "OptiCoreJS app tailored to create a complete RestFull APIs" },
84
+ { label: "standard project", value: ["standard_project"], hint: "OptiCoreJS app tailored to create a standard Web project" }
85
+ ];
86
+
87
+ // src/presentations/starter/starterOptions.starter.ts
88
+ var StarterOptions = {
89
+ message: CGeneralMsg.starterMsg,
90
+ initialValue: [CGeneralMsg.starterInitValue],
91
+ options: CStarterOptions
92
+ };
93
+
94
+ // src/domains/services/prompts/text/promptText.service.ts
95
+ import { text, isCancel as isCancel2 } from "@clack/prompts";
96
+ var SPromptText = async (arg) => {
97
+ const textOutput = await text(arg.textOpt);
98
+ return isCancel2(textOutput) ? UOperationCancelled : textOutput;
99
+ };
100
+
101
+ // src/domains/services/validate.service.ts
102
+ var SValidate = (value, messageInvalidValue, messageBadPattern, regex) => {
103
+ let pattern = new RegExp(regex);
104
+ if (!value) {
105
+ return messageInvalidValue;
106
+ }
107
+ if (!pattern.test(value)) {
108
+ return messageBadPattern;
109
+ }
110
+ };
111
+
112
+ // src/domains/services/prompts/text/outputPromptText.service.ts
113
+ var SOutputPromptText = async (message, placeholder, messageInvalidValue, messageBadPattern, regex, projectPath, initialValue, defaultValue) => {
114
+ return await SPromptText({
115
+ textOpt: {
116
+ initialValue,
117
+ defaultValue,
118
+ message,
119
+ placeholder,
120
+ validate: (value) => SValidate(value, messageInvalidValue, messageBadPattern, regex)
121
+ },
122
+ projectPath
123
+ });
124
+ };
125
+
126
+ // src/presentations/starter/template.starter.ts
127
+ import fs2 from "fs";
128
+ import path from "path";
129
+ import { promisify } from "util";
130
+
131
+ // src/utils/logInfo.util.ts
132
+ import { log } from "@clack/prompts";
133
+ import chalk2 from "chalk";
134
+ var ULogInfo = (logMessage) => {
135
+ log.info(chalk2.dim(logMessage));
136
+ };
137
+
138
+ // src/utils/logError.util.ts
139
+ import { log as log2 } from "@clack/prompts";
140
+ import chalk3 from "chalk";
141
+ var ULogError = (logMessage) => {
142
+ log2.error(chalk3.red(logMessage));
143
+ };
144
+
145
+ // src/presentations/starter/template.starter.ts
146
+ var templateStarter = async (projectName) => {
147
+ const mkdir = promisify(fs2.mkdir);
148
+ if (projectName) {
149
+ const currentPath = process.cwd();
150
+ const projectPath = path.join(currentPath, projectName);
151
+ if (fs2.existsSync(projectPath)) {
152
+ ULogInfo(`${projectName} ${CGeneralMsg.existingProject}`);
153
+ fs2.rmSync(projectPath, { recursive: true, force: true });
154
+ process.exit(1);
155
+ } else {
156
+ fs2.mkdirSync(projectPath);
157
+ }
158
+ const normalizedPath = path.normalize(projectPath);
159
+ await mkdir(normalizedPath, { recursive: true });
160
+ const normalizedCurrentPath = path.normalize(currentPath);
161
+ await mkdir(normalizedCurrentPath, { recursive: true });
162
+ return { normalizedCurrentPath, normalizedPath };
163
+ } else {
164
+ ULogError(CGeneralMsg.wrong);
165
+ process.exit();
166
+ }
167
+ };
168
+
169
+ // src/core/installer.core.ts
170
+ import * as process5 from "process";
171
+
172
+ // src/presentations/middlewares/selectDB.middleware.ts
173
+ import { cancel as cancel4 } from "@clack/prompts";
174
+ import colors8 from "ansi-colors";
175
+ import process4 from "process";
176
+
177
+ // src/core/abstractions/enums/constants/selectDBMessage.constant.ts
178
+ var CSelectDBMessage = {
179
+ dbSelect: "Which database would you use ?",
180
+ dbCredentials: "Do you want create database credentials in .env file ?",
181
+ createDBCredentialsLabel: "Create database credentials",
182
+ createDBCredentialsValue: "create_db_credentials",
183
+ noDBCredentialsLabel: "No database credentials",
184
+ noDBCredentialsValue: "no_db_credentials"
185
+ };
186
+
187
+ // src/core/abstractions/enums/constants/dbNameLabel.constant.ts
188
+ var CDbNameLabel = {
189
+ mysql: "MySQL",
190
+ mongodb: "Mongo DB",
191
+ postgresql: "Postgres",
192
+ oracle: "Oracle",
193
+ otherDb: "Other database",
194
+ createDbCredentials: "Create database credentials",
195
+ noDbCredentials: "No database credentials",
196
+ messageDBUser: "Enter your user database :",
197
+ messageDBPwd: "Enter the password of database :",
198
+ messageDBName: "Enter the name of database :",
199
+ placeholderDBUser: "user",
200
+ placeholderDBHost: "localhost",
201
+ placeholderDBName: "db_toto",
202
+ pwdMask: "*",
203
+ dbUserInvalidValue: "Please user database can't be empty.",
204
+ dbPwdInvalidValue: "Please a database password can't be empty.",
205
+ dbHostInvalidValue: "Please a database host can't be empty.",
206
+ dbNameInvalidValue: "Please database name can't be empty.",
207
+ dbUserBadPattern: "Please enter a valide user database.",
208
+ dbHostBadPattern: "Please enter a valide database host.",
209
+ dbPwdBadPattern: "Please enter a valide database password.",
210
+ dbNameBadPattern: "Please enter a valide database name.",
211
+ messageDBHost: "Enter the host of database :",
212
+ messageDBPort: "Enter the port of database :",
213
+ placeholderDBPort: "mysql: 3306",
214
+ dbPortInvalidValue: "Please a database port can't be empty.",
215
+ dbPortBadPattern: "Please enter a valide database port."
216
+ };
217
+
218
+ // src/core/abstractions/enums/constants/dbNameValue.constant.ts
219
+ var CDbNameValue = {
220
+ mysql: "mysql",
221
+ mongodb: "mongodb",
222
+ postgresql: "postgresql",
223
+ oracle: "oracle",
224
+ otherDb: "other_db",
225
+ createDbCredentials: "create_db_credentials",
226
+ noDbCredentials: "no_db_credentials"
227
+ };
228
+
229
+ // src/presentations/middlewares/dbCredentials.middleware.ts
230
+ import colors3 from "ansi-colors";
231
+ import process3 from "process";
232
+ import { cancel as cancel3 } from "@clack/prompts";
233
+
234
+ // src/domains/services/promptsDBCredentials.service.ts
235
+ import process2 from "process";
236
+ import { cancel as cancel2 } from "@clack/prompts";
237
+ import colors2 from "ansi-colors";
238
+
239
+ // src/domains/services/prompts/password/promptPassword.service.ts
240
+ import { password, isCancel as isCancel3 } from "@clack/prompts";
241
+ var SPromptPassword = async (arg) => {
242
+ const outputConfirm = await password(arg);
243
+ return isCancel3(outputConfirm) ? UOperationCancelled : outputConfirm;
244
+ };
245
+
246
+ // src/domains/services/prompts/password/outputPromptPassword.service.ts
247
+ var SOutputPromptPassword = async (message) => {
248
+ return await SPromptPassword({
249
+ message,
250
+ mask: "*",
251
+ validate: (value) => SValidate(
252
+ value,
253
+ "The password is required",
254
+ "The password can not be blank",
255
+ "[a-zA-Z0-9\\P{Z}]"
256
+ )
257
+ });
258
+ };
259
+
260
+ // src/domains/services/promptsDBCredentials.service.ts
261
+ var SPromptsDBCredentials = class {
262
+ projectPath;
263
+ constructor(projectPath) {
264
+ this.projectPath = projectPath;
265
+ }
266
+ async promptTextDatabaseUser() {
267
+ const user = await SOutputPromptText(
268
+ CDbNameLabel.messageDBUser,
269
+ CDbNameLabel.placeholderDBUser,
270
+ CDbNameLabel.dbUserInvalidValue,
271
+ CDbNameLabel.dbUserBadPattern,
272
+ "^[a-zA-Z0-9]+$",
273
+ this.projectPath
274
+ );
275
+ if (user instanceof Function) {
276
+ cancel2(colors2.bgRed(colors2.white(" Operation cancelled ")));
277
+ process2.exit(130);
278
+ } else {
279
+ return user;
280
+ }
281
+ }
282
+ async promptPasswordDatabasePWD() {
283
+ const password2 = await SOutputPromptPassword(
284
+ CDbNameLabel.messageDBPwd
285
+ );
286
+ if (password2 instanceof Function) {
287
+ cancel2(colors2.bgRed(colors2.white(" Operation cancelled ")));
288
+ process2.exit(130);
289
+ } else {
290
+ return password2;
291
+ }
292
+ }
293
+ async promptTextDatabaseHost() {
294
+ const host = await SOutputPromptText(
295
+ CDbNameLabel.messageDBHost,
296
+ CDbNameLabel.placeholderDBHost,
297
+ CDbNameLabel.dbHostInvalidValue,
298
+ CDbNameLabel.dbHostBadPattern,
299
+ "^[a-zA-Z]+$",
300
+ this.projectPath
301
+ );
302
+ if (host instanceof Function) {
303
+ cancel2(colors2.bgRed(colors2.white(" Operation cancelled ")));
304
+ process2.exit(130);
305
+ } else {
306
+ return host;
307
+ }
308
+ }
309
+ async promptTextDatabasePort() {
310
+ const port = await SOutputPromptText(
311
+ CDbNameLabel.messageDBPort,
312
+ CDbNameLabel.placeholderDBPort,
313
+ CDbNameLabel.dbPortInvalidValue,
314
+ CDbNameLabel.dbPortBadPattern,
315
+ "^[0-9]+$",
316
+ this.projectPath
317
+ );
318
+ if (port instanceof Function) {
319
+ cancel2(colors2.bgRed(colors2.white(" Operation cancelled ")));
320
+ process2.exit(130);
321
+ } else {
322
+ return port;
323
+ }
324
+ }
325
+ async promptTextDatabaseName() {
326
+ const dbName = await SOutputPromptText(
327
+ CDbNameLabel.messageDBName,
328
+ CDbNameLabel.placeholderDBName,
329
+ CDbNameLabel.dbNameInvalidValue,
330
+ CDbNameLabel.dbNameBadPattern,
331
+ "^[a-zA-Z0-9]+$",
332
+ this.projectPath
333
+ );
334
+ if (dbName instanceof Function) {
335
+ cancel2(colors2.bgRed(colors2.white(" Operation cancelled ")));
336
+ process2.exit(130);
337
+ } else {
338
+ return dbName;
339
+ }
340
+ }
341
+ };
342
+
343
+ // src/presentations/middlewares/dbCredentials.middleware.ts
344
+ var MDbCredentials = async (projectPath, currentPath, projectName) => {
345
+ const outputDBCredentials = await SOutputPromptSelect({
346
+ message: CSelectDBMessage.dbCredentials,
347
+ initialValue: [CDbNameLabel.createDbCredentials],
348
+ options: [
349
+ { label: CDbNameLabel.createDbCredentials, value: [CDbNameValue.createDbCredentials] },
350
+ { label: CDbNameLabel.noDbCredentials, value: [CDbNameValue.noDbCredentials] }
351
+ ]
352
+ });
353
+ let databaseUser;
354
+ let databasePassword;
355
+ let databaseHost;
356
+ let databasePort;
357
+ let databaseName;
358
+ if (outputDBCredentials instanceof Function) {
359
+ cancel3(colors3.bgRed(colors3.white(" Operation cancelled ")));
360
+ process3.exit(130);
361
+ } else {
362
+ let credentials;
363
+ outputDBCredentials.map(async (outputDBCredential) => {
364
+ credentials = outputDBCredential;
365
+ });
366
+ if (credentials === CDbNameValue.noDbCredentials) {
367
+ return CDbNameValue.noDbCredentials;
368
+ } else {
369
+ const dbCredentials = new SPromptsDBCredentials(projectPath);
370
+ databaseUser = await dbCredentials.promptTextDatabaseUser();
371
+ databasePassword = await dbCredentials.promptPasswordDatabasePWD();
372
+ databasePort = await dbCredentials.promptTextDatabasePort();
373
+ databaseHost = await dbCredentials.promptTextDatabaseHost();
374
+ databaseName = await dbCredentials.promptTextDatabaseName();
375
+ return {
376
+ credentials,
377
+ databaseUser,
378
+ databasePassword,
379
+ databasePort,
380
+ databaseHost,
381
+ databaseName
382
+ };
383
+ }
384
+ }
385
+ };
386
+
387
+ // src/domains/services/transformDbCredentialsToFusedParams.service.ts
388
+ function transformDbCredentialsToFusedParams(credentials) {
389
+ if (credentials === CDbNameValue.noDbCredentials) {
390
+ return CDbNameValue.noDbCredentials;
391
+ } else {
392
+ return credentials;
393
+ }
394
+ }
395
+
396
+ // src/domains/services/fetchCredentials.service.ts
397
+ var SFetchCredentials = async (projectPath, currentPath, projectName) => {
398
+ let dbParams;
399
+ let envParams;
400
+ let fetchParams = "";
401
+ const dbCredentials = await MDbCredentials(projectPath, currentPath, projectName);
402
+ const params = transformDbCredentialsToFusedParams(dbCredentials);
403
+ if (params === CDbNameValue.noDbCredentials) {
404
+ return params;
405
+ } else {
406
+ const credParams = params;
407
+ dbParams = {
408
+ databaseHost: credParams.databaseHost,
409
+ databaseName: credParams.databaseName,
410
+ databasePassword: credParams.databasePassword,
411
+ databasePort: credParams.databasePort,
412
+ databaseUser: credParams.databaseUser,
413
+ projectPath
414
+ };
415
+ envParams = {
416
+ dbName: credParams.databaseName,
417
+ dbUser: credParams.databaseUser,
418
+ dbPwd: credParams.databasePassword,
419
+ dbHost: credParams.databaseHost,
420
+ dbPort: credParams.databasePort
421
+ };
422
+ const allParams = { dbCredentials, fetchParams, dbParams, envParams };
423
+ return allParams;
424
+ }
425
+ };
426
+
427
+ // src/presentations/starter/projectCreation.starter.ts
428
+ import path2 from "path";
429
+ import fs3 from "fs";
430
+ import cp from "child_process";
431
+
432
+ // src/utils/console/endingMessage.info.ts
433
+ import chalk4 from "chalk";
434
+ import { outro, log as log3 } from "@clack/prompts";
435
+ function endingMessageInfo(projectName) {
436
+ log3.success(chalk4.green.bold("Your OpticoreJs project has been created successfully!"));
437
+ console.log(`
438
+ ${chalk4.bold("Next steps:")}`);
439
+ console.log(` ${chalk4.dim("\u276F")} cd ${chalk4.cyan(projectName)}`);
440
+ console.log(` ${chalk4.dim("\u276F")} ${chalk4.cyan("npm run start:dev")}
441
+ `);
442
+ console.log(` ${chalk4.dim("NB: Before running app, make sure to define in .env file application host and port.")}
443
+ `);
444
+ outro(chalk4.dim("To install opticore components: ") + chalk4.green("npx opticore list"));
445
+ }
446
+
447
+ // src/presentations/starter/projectCreation.starter.ts
448
+ import { promisify as promisify2 } from "util";
449
+
450
+ // src/applications/services/packagesVersion.service.ts
451
+ var GetLatestVersion = async (exec, pkgName) => {
452
+ try {
453
+ const { stdout } = await exec(`npm view ${pkgName} version`);
454
+ return stdout.trim();
455
+ } catch {
456
+ return null;
457
+ }
458
+ };
459
+
460
+ // src/applications/services/updateDependencies.service.ts
461
+ var UpdateOpticoreDeps = async (exec, deps) => {
462
+ const updated = { ...deps };
463
+ const opticorePackages = Object.keys(deps).filter((name) => name.startsWith("opticore-"));
464
+ await Promise.all(opticorePackages.map(async (name) => {
465
+ const latest = await GetLatestVersion(exec, name);
466
+ if (latest) updated[name] = `^${latest}`;
467
+ }));
468
+ return updated;
469
+ };
470
+
471
+ // src/presentations/starter/projectCreation.starter.ts
472
+ var SProjectCreation = async (gitRepo, projectPath, currentPath, projectName) => {
473
+ let ora = (await import("ora")).default;
474
+ const exec = promisify2(cp.exec);
475
+ const rm = promisify2(fs3.rm);
476
+ const gitSpinner = ora("Downloading files and project creation").start();
477
+ try {
478
+ await exec(`git clone --depth 1 ${gitRepo} ${projectPath} --quiet`);
479
+ gitSpinner.succeed();
480
+ const cleanSpinner = ora("Removing useless files").start();
481
+ await exec(`rm -rf ${path2.join(projectPath, ".git")}`);
482
+ const rmGit = rm(path2.join(projectPath, ".git"), { recursive: true, force: true });
483
+ const rmBin = rm(path2.join(currentPath, "opticore-installer"), { recursive: true, force: true });
484
+ await Promise.all([rmGit, rmBin]);
485
+ const escapedPath = projectPath.replace(/^"(.*)"$/, "$1");
486
+ process.chdir(escapedPath);
487
+ const pkgPath = path2.join(escapedPath, "package.json");
488
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
489
+ if (pkg.dependencies?.["opticore-feature-module"]) {
490
+ pkg.dependencies["opticore-feature-component"] = pkg.dependencies["opticore-feature-module"];
491
+ delete pkg.dependencies["opticore-feature-module"];
492
+ }
493
+ if (pkg.dependencies) pkg.dependencies = await UpdateOpticoreDeps(exec, pkg.dependencies);
494
+ if (pkg.devDependencies) pkg.devDependencies = await UpdateOpticoreDeps(exec, pkg.devDependencies);
495
+ fs3.writeFileSync(pkgPath, JSON.stringify(pkg, null, 4));
496
+ const lockPath = path2.join(escapedPath, "package-lock.json");
497
+ if (fs3.existsSync(lockPath)) fs3.unlinkSync(lockPath);
498
+ await exec("npm uninstall ora ansi-colors cli-spinner dotenv gradient-string util tsup path fs node ts-node tslib @types/cli-spinner @clack/prompts");
499
+ cleanSpinner.succeed();
500
+ const npmSpinner = ora("Installing dependencies").start();
501
+ await exec("npm install");
502
+ npmSpinner.succeed();
503
+ fs3.writeFileSync(path2.join(escapedPath, ".npmrc"), "loglevel=silent\n");
504
+ endingMessageInfo(projectName);
505
+ } catch (err) {
506
+ console.log("err is : ", err);
507
+ process.exit();
508
+ }
509
+ };
510
+
511
+ // src/core/abstractions/enums/constants/projectTemplatePath.constant.ts
512
+ var CProjectTemplatePath = {
513
+ mysql: "https://github.com/guyzoum77/opticore-api-restfull-template-mysql.git",
514
+ postgresql: "https://github.com/guyzoum77/opticore-api-restfull-template-postgresdb.git",
515
+ mongodb: "https://github.com/guyzoum77/opticore-api-restfull-template-mongodb.git",
516
+ oracle: "https://github.com/guyzoum77/opticore-api-restfull-template-oracle.git",
517
+ nodbcredentials: "https://github.com/guyzoum77/opticore-api-restfull-template-no-db-credential.git",
518
+ otherdb: "https://github.com/guyzoum77/opticore-api-restfull-template-other-db.git"
519
+ };
520
+
521
+ // src/domains/services/updateEnv.service.ts
522
+ import fs4 from "fs";
523
+ var SUpdateEnv = class {
524
+ arg;
525
+ argumentConnection;
526
+ constructor(arg, argumentConnection) {
527
+ this.arg = arg;
528
+ this.argumentConnection = argumentConnection;
529
+ this.__init();
530
+ }
531
+ /**
532
+ *
533
+ * @private
534
+ */
535
+ __init() {
536
+ const envFileLines = fs4.readFileSync("config/env/.env", "utf8").split("\n");
537
+ this.updateDatabaseSection(envFileLines, this.arg);
538
+ this.updateArgConnexionSection(envFileLines, this.argumentConnection);
539
+ fs4.writeFileSync("config/env/.env", envFileLines.join("\n"));
540
+ }
541
+ /**
542
+ *
543
+ * @param envFileLines
544
+ * @param arg
545
+ * @protected
546
+ */
547
+ updateDatabaseSection(envFileLines, arg) {
548
+ const sectionHeader = "#DATABASE";
549
+ const sectionStart = envFileLines.findIndex((line) => line.trim() === sectionHeader);
550
+ if (sectionStart === -1) {
551
+ console.warn(`Section ${sectionHeader} not found in .env file`);
552
+ return;
553
+ }
554
+ for (let i = sectionStart + 1; i < envFileLines.length; i++) {
555
+ const line = envFileLines[i].trim();
556
+ if (line.startsWith("#") && line !== sectionHeader) {
557
+ break;
558
+ }
559
+ if (!line || line.startsWith("#")) {
560
+ continue;
561
+ }
562
+ const [key] = line.split("=");
563
+ switch (key) {
564
+ case "DATA_BASE_NAME":
565
+ envFileLines[i] = `${key}=${arg.dbName ?? ""}`;
566
+ break;
567
+ case "DATA_BASE_USER":
568
+ envFileLines[i] = `${key}=${arg.dbUser ?? ""}`;
569
+ break;
570
+ case "DATA_BASE_PASSWORD":
571
+ envFileLines[i] = `${key}=${arg.dbPwd ?? ""}`;
572
+ break;
573
+ case "DATA_BASE_HOST":
574
+ envFileLines[i] = `${key}=${arg.dbHost ?? ""}`;
575
+ break;
576
+ case "DATA_BASE_PORT":
577
+ envFileLines[i] = `${key}=${arg.dbPort ?? ""}`;
578
+ break;
579
+ }
580
+ }
581
+ }
582
+ /**
583
+ *
584
+ * @param envFileLines
585
+ * @param argumentConnection
586
+ * @protected
587
+ */
588
+ updateArgConnexionSection(envFileLines, argumentConnection) {
589
+ const sectionHeader = "#ARG CONNEXION";
590
+ const sectionStart = envFileLines.findIndex((line) => line.trim() === sectionHeader);
591
+ if (sectionStart === -1) {
592
+ console.warn(`Section ${sectionHeader} not found in .env file`);
593
+ return;
594
+ }
595
+ if (argumentConnection === void 0) {
596
+ return;
597
+ }
598
+ let found = false;
599
+ for (let i = sectionStart + 1; i < envFileLines.length; i++) {
600
+ const line = envFileLines[i].trim();
601
+ if (line.startsWith("#") && line !== sectionHeader) {
602
+ break;
603
+ }
604
+ if (!line || line.startsWith("#")) {
605
+ continue;
606
+ }
607
+ const [key] = line.split("=");
608
+ if (key === "ARGUMENTS_DATABASE_CONNECTION") {
609
+ envFileLines[i] = `${key}=${argumentConnection ?? ""}`;
610
+ found = true;
611
+ break;
612
+ }
613
+ }
614
+ if (!found && argumentConnection !== null) {
615
+ const insertPosition = sectionStart + 1;
616
+ envFileLines.splice(insertPosition, 0, `ARGUMENTS_DATABASE_CONNECTION=${argumentConnection}`);
617
+ }
618
+ }
619
+ };
620
+
621
+ // src/presentations/middlewares/templateProject/templateProject.middleware.ts
622
+ var MTemplateProject = async (repoGit, projectPath, currentPath, callback, arg, projectName, argumentConnection) => {
623
+ await SProjectCreation(repoGit, projectPath, currentPath, projectName);
624
+ callback;
625
+ new SUpdateEnv(arg, argumentConnection);
626
+ };
627
+
628
+ // src/presentations/middlewares/database/createMongo.database.ts
629
+ import fs6 from "fs";
630
+ import colors5 from "ansi-colors";
631
+ import { MongoClient } from "mongodb";
632
+
633
+ // src/utils/logSuccess.util.ts
634
+ import { log as log4 } from "@clack/prompts";
635
+ import chalk5 from "chalk";
636
+ var ULogSuccess = (logMessage) => {
637
+ log4.success(chalk5.green(logMessage));
638
+ };
639
+
640
+ // src/core/abstractions/enums/constants/mongoOutputText.constant.ts
641
+ var CMongoText = {
642
+ msg: "Enter a collection of database :",
643
+ pHolder: "db_toto",
644
+ invalidValue: "Please collection's name can't be empty.",
645
+ badPattern: "Please enter a valide collection's name.",
646
+ unReachable: "Sorry, the database couldn't be created. In MongoDB, a database is not created until it gets content! MongoDB waits until you have created a collection (table), with at least one document (record) before it actually creates the database (and collection)."
647
+ };
648
+
649
+ // src/applications/exceptions/handledMongoDB.exception.ts
650
+ import colors4 from "ansi-colors";
651
+ import fs5 from "fs";
652
+ var handledMongoDBException = (e, databasePort, databaseHost, projectPath) => {
653
+ if (e.code === 18) {
654
+ console.error(`${colors4.red(`Authentication failed, be sure the credentials is correct!`)}`);
655
+ fs5.rmSync(projectPath, { recursive: true, force: true });
656
+ process.exit();
657
+ }
658
+ if (e.cause.code === "ERR_INVALID_URL") {
659
+ console.error(`${colors4.red(`Unable to parse ${databaseHost}:${databasePort} with URL`)}`);
660
+ fs5.rmSync(projectPath, { recursive: true, force: true });
661
+ process.exit();
662
+ }
663
+ if (e.code === void 0) {
664
+ console.error(`${colors4.red(`MongoServerSelectionError: getaddrinfo EAI_AGAIN (${databaseHost} is not allow to database connection)`)}`);
665
+ fs5.rmSync(projectPath, { recursive: true, force: true });
666
+ process.exit();
667
+ }
668
+ };
669
+
670
+ // src/core/config/uri/configMongoUrl.config.ts
671
+ import dotenv from "dotenv";
672
+ var configMongoUrlConfig = (databaseHost, databasePort) => {
673
+ return typeof databasePort === "number" || !isNaN(databasePort) || isFinite(databasePort) ? `mongodb://${databaseHost}:${databasePort}/` : `mongodb://${databaseHost}:${dotenv.config().parsed.DATA_BASE_PORT}/`;
674
+ };
675
+
676
+ // src/core/config/paramters/mongoClient.parameter.ts
677
+ import dotenv2 from "dotenv";
678
+ var PMongoClient = (databaseUser, databasePassword) => {
679
+ return {
680
+ auth: {
681
+ username: databaseUser ?? dotenv2.config().parsed.DATA_BASE_USER,
682
+ password: databasePassword ?? dotenv2.config().parsed.DATA_BASE_PASSWORD
683
+ }
684
+ };
685
+ };
686
+
687
+ // src/presentations/middlewares/database/createMongo.database.ts
688
+ var createMongoDatabase = async (arg) => {
689
+ try {
690
+ const client = new MongoClient(configMongoUrlConfig(arg.dbHost, arg.dbPort), PMongoClient(arg.dbUser, arg.dbPwd));
691
+ await client.connect();
692
+ const mongoOutputText = await SOutputPromptText(CMongoText.msg, CMongoText.pHolder, CMongoText.invalidValue, CMongoText.badPattern, arg.projectPath);
693
+ if (mongoOutputText) {
694
+ const db = client.db(arg.dbName);
695
+ typeof mongoOutputText === "string" ? await db.createCollection(mongoOutputText) : (() => {
696
+ console.error(mongoOutputText);
697
+ process.exit();
698
+ });
699
+ ULogSuccess(`${colors5.green(`Your database ${colors5.bgGreen(`${colors5.white(`${arg.dbName}`)}`)} has been created successfully.`)}`);
700
+ } else {
701
+ ULogInfo(CMongoText.unReachable);
702
+ fs6.rmSync(arg.projectPath, { recursive: true, force: true });
703
+ process.exit(0);
704
+ }
705
+ } catch (e) {
706
+ handledMongoDBException(e, arg.dbPort, arg.dbHost, arg.projectPath);
707
+ }
708
+ };
709
+
710
+ // src/presentations/middlewares/database/createPostgres.database.ts
711
+ import { Client } from "pg";
712
+
713
+ // src/core/config/paramters/postgres.paramaters.ts
714
+ import dotenv3 from "dotenv";
715
+ var PPostgres = (arg) => {
716
+ return {
717
+ host: arg.host ?? dotenv3.config()?.parsed?.DATA_BASE_HOST,
718
+ user: arg.user ?? dotenv3.config()?.parsed?.DATA_BASE_USER,
719
+ password: arg.password ?? dotenv3.config()?.parsed?.DATA_BASE_PASSWORD,
720
+ port: arg.port ?? dotenv3.config()?.parsed?.DATA_BASE_PORT
721
+ };
722
+ };
723
+
724
+ // src/applications/exceptions/handledPostgres.exception.ts
725
+ import colors6 from "ansi-colors";
726
+ import fs7 from "fs";
727
+ var handledPostgresException = (arg, err) => {
728
+ console.error(`${colors6.red(`An error occurred while creating the database : ${err}`)}`);
729
+ fs7.rmSync(arg.projectName, { recursive: true, force: true });
730
+ process.exit(0);
731
+ };
732
+
733
+ // src/presentations/middlewares/database/createPostgres.database.ts
734
+ async function createPostgresDatabase(arg) {
735
+ try {
736
+ const client = new Client(PPostgres(arg));
737
+ await client.connect();
738
+ await client.query(`CREATE DATABASE "${arg.database}";`);
739
+ await client.end();
740
+ } catch (err) {
741
+ handledPostgresException(arg, err);
742
+ }
743
+ }
744
+
745
+ // src/presentations/middlewares/database/createMySQL.database.ts
746
+ import mySQL from "mysql2/promise";
747
+
748
+ // src/core/config/paramters/mysql.parameters.ts
749
+ import dotenv4 from "dotenv";
750
+ var PMysql = (arg) => {
751
+ return {
752
+ host: arg.dbHost ?? dotenv4.config()?.parsed?.DATA_BASE_HOST,
753
+ user: arg.dbUser ?? dotenv4.config()?.parsed?.DATA_BASE_USER,
754
+ password: arg.dbPwd ?? dotenv4.config()?.parsed?.DATA_BASE_PASSWORD,
755
+ port: arg.dbPort ?? parseInt(dotenv4.config()?.parsed?.DATA_BASE_PORT)
756
+ };
757
+ };
758
+
759
+ // src/applications/exceptions/handledMySQL.exception.ts
760
+ import fs8 from "fs";
761
+ import colors7 from "ansi-colors";
762
+ var handledMySQLException = (arg, err) => {
763
+ fs8.rmSync(arg.projectPath, { recursive: true, force: true });
764
+ switch (err.code) {
765
+ case "ER_NOT_SUPPORTED_AUTH_MODE":
766
+ console.error(`${colors7.red(`Client does not support authentication protocol requested by server. Please try to verify your database credentials.`)}`);
767
+ break;
768
+ case "ERR_SOCKET_BAD_PORT":
769
+ console.error(`${colors7.red(`${err.message}.`)}`);
770
+ break;
771
+ case "ERR_INVALID_ARG_TYPE":
772
+ console.error(`${colors7.red(`${err.message}.`)}`);
773
+ break;
774
+ case "EAI_AGAIN":
775
+ console.error(`${colors7.red(`${err.message}.`)}`);
776
+ break;
777
+ case "ECONNREFUSED":
778
+ console.error(`${colors7.red(`${err.message}. Try to check if the port is correct.`)}`);
779
+ break;
780
+ default:
781
+ console.error();
782
+ break;
783
+ }
784
+ console.error(`${colors7.red(`An error occurred while creating the database : ${err.message}`)}`);
785
+ fs8.rmSync(arg.projectPath, { recursive: true, force: true });
786
+ process.exit(0);
787
+ };
788
+
789
+ // src/presentations/middlewares/database/createMySQL.database.ts
790
+ async function createMySQLDatabase(arg) {
791
+ let connection;
792
+ try {
793
+ connection = await mySQL.createConnection(PMysql(arg));
794
+ await connection.connect();
795
+ const createDatabaseQuery = `CREATE DATABASE IF NOT EXISTS ${arg.dbName}`;
796
+ await connection.query(createDatabaseQuery);
797
+ await connection.end();
798
+ } catch (err) {
799
+ handledMySQLException(arg, err);
800
+ }
801
+ }
802
+
803
+ // src/core/abstractions/enums/constants/connectionProperties.constant.ts
804
+ var CConnectionProperties = "connection_limit=5&socket_timeout=3";
805
+
806
+ // src/presentations/middlewares/selectDB.middleware.ts
807
+ var MSelectDB = async (projectPath, currentPath, projectName) => {
808
+ const dbSelect = await SOutputPromptSelect({
809
+ message: CSelectDBMessage.dbSelect,
810
+ initialValue: [CDbNameLabel.mysql],
811
+ options: [
812
+ { label: CDbNameLabel.mysql, value: [CDbNameValue.mysql] },
813
+ { label: CDbNameLabel.mongodb, value: [CDbNameValue.mongodb] },
814
+ { label: CDbNameLabel.postgresql, value: [CDbNameValue.postgresql] },
815
+ { label: CDbNameLabel.oracle, value: [CDbNameValue.oracle] },
816
+ { label: CDbNameLabel.otherDb, value: [CDbNameValue.otherDb] }
817
+ ]
818
+ });
819
+ if (dbSelect instanceof Function) {
820
+ cancel4(colors8.bgRed(colors8.white(" Operation cancelled ")));
821
+ process4.exit(130);
822
+ } else {
823
+ const params = await SFetchCredentials(projectPath, currentPath, projectName);
824
+ if (params.dbCredentials === void 0) {
825
+ let dbChosen = [];
826
+ dbSelect.map(async (item) => {
827
+ switch (item) {
828
+ case CDbNameValue.mysql:
829
+ await SProjectCreation(CProjectTemplatePath.mysql, projectPath, currentPath, projectName);
830
+ break;
831
+ case CDbNameValue.postgresql:
832
+ await SProjectCreation(CProjectTemplatePath.postgresql, projectPath, currentPath, projectName);
833
+ break;
834
+ case CDbNameValue.mongodb:
835
+ await SProjectCreation(CProjectTemplatePath.mongodb, projectPath, currentPath, projectName);
836
+ break;
837
+ case CDbNameValue.oracle:
838
+ await SProjectCreation(CProjectTemplatePath.oracle, projectPath, currentPath, projectName);
839
+ break;
840
+ case CDbNameValue.otherDb:
841
+ await SProjectCreation(CProjectTemplatePath.otherdb, projectPath, currentPath, projectName);
842
+ break;
843
+ }
844
+ dbChosen.push(item);
845
+ });
846
+ return dbChosen;
847
+ } else {
848
+ dbSelect.map(async (item) => {
849
+ switch (item) {
850
+ case CDbNameValue.mysql:
851
+ await MTemplateProject(
852
+ CProjectTemplatePath.mysql,
853
+ projectPath,
854
+ currentPath,
855
+ async () => await createMySQLDatabase(
856
+ //@ts-ignore
857
+ params.dbParams
858
+ ),
859
+ params.envParams,
860
+ projectName,
861
+ CConnectionProperties
862
+ );
863
+ break;
864
+ case CDbNameValue.postgresql:
865
+ await MTemplateProject(
866
+ CProjectTemplatePath.postgresql,
867
+ projectPath,
868
+ currentPath,
869
+ async () => await createPostgresDatabase(
870
+ //@ts-ignore
871
+ params.dbParams
872
+ ),
873
+ params.envParams,
874
+ projectName
875
+ );
876
+ break;
877
+ case CDbNameValue.mongodb:
878
+ await MTemplateProject(
879
+ CProjectTemplatePath.mongodb,
880
+ projectPath,
881
+ currentPath,
882
+ async () => await createMongoDatabase(params),
883
+ params.envParams,
884
+ projectName
885
+ );
886
+ break;
887
+ case CDbNameValue.oracle:
888
+ await MTemplateProject(
889
+ CProjectTemplatePath.oracle,
890
+ projectPath,
891
+ currentPath,
892
+ async () => {
893
+ },
894
+ params.envParams,
895
+ projectName
896
+ );
897
+ break;
898
+ case CDbNameValue.otherDb:
899
+ await MTemplateProject(
900
+ CProjectTemplatePath.otherdb,
901
+ projectPath,
902
+ currentPath,
903
+ async () => {
904
+ },
905
+ params.envParams,
906
+ projectName
907
+ );
908
+ break;
909
+ }
910
+ });
911
+ }
912
+ }
913
+ };
914
+
915
+ // src/domains/services/shellEscape.service.ts
916
+ var SShellEscape = (str) => {
917
+ return `"${str.replace(/(["$`\\])/g, "\\$1")}"`;
918
+ };
919
+
920
+ // src/core/installer.core.ts
921
+ var installerCore = async () => {
922
+ let projectName;
923
+ UWelcomeMessage();
924
+ intro(chalk6.bgYellow.black(" Opticore Framework Installer "));
925
+ const starter = await SOutputPromptSelect(StarterOptions);
926
+ starter instanceof Function ? (() => {
927
+ cancel5(colors9.bgRed(colors9.white(" Operation cancelled ")));
928
+ process5.exit(130);
929
+ })() : starter.map(async (value) => {
930
+ switch (value) {
931
+ case CGeneralMsg.starterInitValue:
932
+ projectName = await SOutputPromptText(
933
+ CGeneralMsg.projectNameMessage,
934
+ CGeneralMsg.projectNamePlaceholder,
935
+ CGeneralMsg.projectNameInvalidValue,
936
+ CGeneralMsg.projectNameBadPattern,
937
+ "^[a-zA-Z0-9]+$"
938
+ );
939
+ if (typeof projectName === "string") {
940
+ const tpl = await templateStarter(projectName);
941
+ const escapedProjectPath = SShellEscape(tpl.normalizedPath);
942
+ const escapedCurrentPath = SShellEscape(tpl.normalizedCurrentPath);
943
+ await MSelectDB(escapedProjectPath, escapedCurrentPath, projectName);
944
+ }
945
+ break;
946
+ }
947
+ });
948
+ };
949
+
950
+ // src/index.ts
951
+ (async () => await installerCore())();