falak-app-duo 1.0.0 → 1.1.0

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/falak-app-duo +96 -6
  2. package/package.json +7 -2
package/bin/falak-app-duo CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
+ import { spawn } from "node:child_process";
4
5
  import fs from "fs-extra";
5
6
  import prompts from "prompts";
6
7
  import chalk from "chalk";
7
8
  import { Command } from "commander";
8
9
  import crypto from "node:crypto";
10
+ import figlet from "figlet";
11
+ import gradient from "gradient-string";
9
12
 
10
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
14
  const TEMPLATE_DIR = path.join(__dirname, "..", "templates", "default");
@@ -16,6 +19,7 @@ program
16
19
  .description("Scaffold a Vue 3 app with Ably, Brevo, AES-256 and a Laravel API client baked in.")
17
20
  .argument("[project-name]", "Directory to create the project in")
18
21
  .option("-y, --yes", "Skip prompts and use defaults (all services enabled)")
22
+ .option("--no-rtl", "Disable Arabic/RTL default (English/LTR) instead")
19
23
  .parse(process.argv);
20
24
 
21
25
  const [argProjectName] = program.args;
@@ -25,14 +29,39 @@ function randomHex(bytes) {
25
29
  return crypto.randomBytes(bytes).toString("hex");
26
30
  }
27
31
 
32
+ function runInProject(dir, command, args) {
33
+ return new Promise((resolve, reject) => {
34
+ const child = spawn(command, args, {
35
+ cwd: dir,
36
+ stdio: "inherit",
37
+ shell: process.platform === "win32",
38
+ });
39
+ child.on("error", reject);
40
+ child.on("close", (code) => {
41
+ if (code === 0) resolve();
42
+ else reject(new Error(`\`${command} ${args.join(" ")}\` exited with code ${code}`));
43
+ });
44
+ });
45
+ }
46
+
47
+ async function printBanner() {
48
+ const art = (await figlet("Falak Duo", { font: "ANSI Shadow" }).catch(() => null)) || "Falak Duo";
49
+ console.log("\n" + gradient("#a78bfa", "#22d3ee", "#2dd4bf")(art));
50
+ console.log(
51
+ chalk.gray(" Vue 3 boilerplate \u2014 Ably \u00b7 Brevo \u00b7 AES-256 \u00b7 Arabic/RTL")
52
+ );
53
+ console.log("\n");
54
+ }
55
+
28
56
  async function main() {
29
- console.log(chalk.cyanBright("\n falak-app \u2014 Vue 3 scaffolder\n"));
57
+ await printBanner();
30
58
 
31
59
  const answers = opts.yes
32
60
  ? {
33
61
  projectName: argProjectName || "falak-app-duo",
34
62
  services: ["ably", "brevo"],
35
63
  apiBaseUrl: "http://localhost:8000/api",
64
+ rtl: opts.rtl,
36
65
  }
37
66
  : await prompts(
38
67
  [
@@ -58,10 +87,22 @@ async function main() {
58
87
  message: "Laravel API base URL:",
59
88
  initial: "http://localhost:8000/api",
60
89
  },
90
+ ...(opts.rtl
91
+ ? [
92
+ {
93
+ type: "confirm",
94
+ name: "rtl",
95
+ message: "Enable Arabic / RTL by default?",
96
+ initial: true,
97
+ },
98
+ ]
99
+ : []),
61
100
  ],
62
101
  { onCancel: () => process.exit(1) }
63
102
  );
64
103
 
104
+ const rtlEnabled = opts.yes ? answers.rtl : opts.rtl ? answers.rtl : false;
105
+
65
106
  const projectName = argProjectName || answers.projectName;
66
107
  const services = answers.services || [];
67
108
  const targetDir = path.resolve(process.cwd(), projectName);
@@ -97,6 +138,21 @@ async function main() {
97
138
  }
98
139
  }
99
140
 
141
+ // RTL off: flip the hard-coded Arabic/LTR defaults to English/LTR
142
+ if (!rtlEnabled) {
143
+ const htmlPath = path.join(targetDir, "index.html");
144
+ const html = await fs.readFile(htmlPath, "utf-8");
145
+ await fs.writeFile(htmlPath, html.replace('<html lang="ar" dir="rtl">', '<html lang="en" dir="ltr">'));
146
+
147
+ const i18nPath = path.join(targetDir, "src", "i18n", "index.js");
148
+ const i18n = await fs.readFile(i18nPath, "utf-8");
149
+ await fs.writeFile(
150
+ i18nPath,
151
+ i18n.replace('getItem(STORAGE_KEY) || "ar"', 'getItem(STORAGE_KEY) || "en"')
152
+ );
153
+ console.log(chalk.gray(" RTL disabled \u2014 English (LTR) set as the default locale."));
154
+ }
155
+
100
156
  // Generate a real .env from .env.example with a fresh encryption key
101
157
  const envExamplePath = path.join(targetDir, ".env.example");
102
158
  let envContent = await fs.readFile(envExamplePath, "utf-8");
@@ -106,18 +162,52 @@ async function main() {
106
162
  .replace("__AES_IV__", randomHex(16)); // 128-bit IV, hex-encoded
107
163
  await fs.writeFile(path.join(targetDir, ".env"), envContent);
108
164
 
109
- console.log(chalk.green(" Done! Next steps:\n"));
110
- console.log(chalk.white(` cd ${projectName}`));
111
- console.log(chalk.white(" npm install"));
112
- console.log(chalk.white(" npm run dev\n"));
165
+ console.log(chalk.green(`\n Scaffolded ./${projectName} successfully.\n`));
113
166
  console.log(
114
167
  chalk.gray(
115
168
  " Fill in VITE_API_KEY, VITE_ABLY_PUBLIC_KEY, Brevo backend routes, and review .env before shipping.\n"
116
169
  )
117
170
  );
171
+
172
+ const runChoice = opts.yes
173
+ ? "install"
174
+ : (
175
+ await prompts(
176
+ {
177
+ type: "select",
178
+ name: "run",
179
+ message: "Ready to start coding?",
180
+ choices: [
181
+ { title: "Install dependencies, then start the dev server", value: "dev" },
182
+ { title: "Install dependencies only", value: "install" },
183
+ { title: "Skip \u2014 I'll run it myself", value: "skip" },
184
+ ],
185
+ initial: 0,
186
+ },
187
+ { onCancel: () => process.exit(1) }
188
+ )
189
+ ).run;
190
+
191
+ if (runChoice === "skip") {
192
+ console.log(chalk.white(` cd ${projectName}`));
193
+ console.log(chalk.white(" npm install"));
194
+ console.log(chalk.white(" npm run dev\n"));
195
+ return;
196
+ }
197
+
198
+ console.log(chalk.cyan("\n Installing dependencies...\n"));
199
+ await runInProject(targetDir, "npm", ["install"]);
200
+
201
+ if (runChoice === "install") {
202
+ console.log(chalk.white("\n Next: cd into the project and run `npm run dev`\n"));
203
+ return;
204
+ }
205
+
206
+ console.log(chalk.cyan("\n Starting the dev server (Ctrl+C to stop)...\n"));
207
+ await runInProject(targetDir, "npm", ["run", "dev"]).catch(() => {});
118
208
  }
119
209
 
120
210
  main().catch((err) => {
121
211
  console.error(chalk.red(err));
122
212
  process.exit(1);
123
- });
213
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "falak-app-duo",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Vue 3 boilerplate scaffolder — Ably (realtime), Brevo, AES-256, Arabic/RTL, and a Laravel API client (API key + user token auth). No Firebase, no Groq/Paymob on the frontend (Groq is backend-only; Paymob dropped).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,9 @@
16
16
  "dependencies": {
17
17
  "chalk": "^5.3.0",
18
18
  "commander": "^12.1.0",
19
+ "figlet": "^1.11.4",
19
20
  "fs-extra": "^11.2.0",
21
+ "gradient-string": "^3.0.0",
20
22
  "prompts": "^2.4.2"
21
23
  },
22
24
  "keywords": [
@@ -30,5 +32,8 @@
30
32
  "ably",
31
33
  "realtime"
32
34
  ],
33
- "license": "MIT"
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ }
34
39
  }