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.
- package/bin/falak-app-duo +96 -6
- 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
|
-
|
|
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(
|
|
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.
|
|
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
|
}
|