frontend-hamroun 1.2.1 → 1.2.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/bin/cli.cjs ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ // This file is a CommonJS wrapper for the ES module CLI
3
+ // It loads the actual CLI implementation using dynamic import()
4
+
5
+ async function main() {
6
+ try {
7
+ // Use dynamic import to load the ES module CLI
8
+ const cliPath = new URL('../bin/cli.mjs', import.meta.url).href;
9
+ await import(cliPath);
10
+ } catch (error) {
11
+ console.error('Error loading CLI:', error);
12
+ process.exit(1);
13
+ }
14
+ }
15
+
16
+ main();
package/bin/cli.mjs ADDED
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { execSync } from 'child_process';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+
11
+ // Templates available
12
+ const TEMPLATES = {
13
+ 'basic': 'Basic frontend only template',
14
+ 'full-stack': 'Complete frontend and backend template'
15
+ };
16
+
17
+ // Colors for CLI output
18
+ const colors = {
19
+ reset: '\x1b[0m',
20
+ bright: '\x1b[1m',
21
+ green: '\x1b[32m',
22
+ blue: '\x1b[34m',
23
+ red: '\x1b[31m',
24
+ yellow: '\x1b[33m'
25
+ };
26
+
27
+ // Get package.json to read version
28
+ const packageJsonPath = path.resolve(__dirname, '../package.json');
29
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
30
+
31
+ // Print banner
32
+ function printBanner() {
33
+ console.log(`
34
+ ${colors.blue}${colors.bright}╔══════════════════════════════════════════════╗
35
+ ║ ║
36
+ ║ Frontend Hamroun v${packageJson.version.padEnd(25)}║
37
+ ║ A lightweight frontend & backend framework ║
38
+ ║ ║
39
+ ╚══════════════════════════════════════════════╝${colors.reset}
40
+ `);
41
+ }
42
+
43
+ // Print help
44
+ function printHelp() {
45
+ console.log(`
46
+ ${colors.bright}USAGE:${colors.reset}
47
+ ${colors.blue}npx frontend-hamroun${colors.reset} [command] [options]
48
+
49
+ ${colors.bright}COMMANDS:${colors.reset}
50
+ ${colors.blue}create${colors.reset} <project-name> [options] Create a new project
51
+ ${colors.blue}help${colors.reset} Display this help message
52
+ ${colors.blue}version${colors.reset} Display version information
53
+
54
+ ${colors.bright}OPTIONS:${colors.reset}
55
+ ${colors.blue}--template${colors.reset}, ${colors.blue}-t${colors.reset} <template> Specify template (default: basic)
56
+ ${colors.blue}--skip-install${colors.reset}, ${colors.blue}-s${colors.reset} Skip package installation
57
+
58
+ ${colors.bright}AVAILABLE TEMPLATES:${colors.reset}
59
+ ${Object.entries(TEMPLATES).map(([name, desc]) => ` ${colors.blue}${name.padEnd(12)}${colors.reset} ${desc}`).join('\n')}
60
+
61
+ ${colors.bright}EXAMPLES:${colors.reset}
62
+ ${colors.blue}npx frontend-hamroun create${colors.reset} my-app
63
+ ${colors.blue}npx frontend-hamroun create${colors.reset} my-app --template full-stack
64
+ `);
65
+ }
66
+
67
+ // Create project from template
68
+ function createProject(projectName, options) {
69
+ const template = options.template || 'basic';
70
+
71
+ // Check if template exists
72
+ if (!Object.keys(TEMPLATES).includes(template)) {
73
+ console.error(`${colors.red}error:${colors.reset} Template "${template}" not found.`);
74
+ console.log(`Available templates: ${Object.keys(TEMPLATES).join(', ')}`);
75
+ process.exit(1);
76
+ }
77
+
78
+ // Check if project directory already exists
79
+ const projectPath = path.resolve(process.cwd(), projectName);
80
+ if (fs.existsSync(projectPath)) {
81
+ console.error(`${colors.red}error:${colors.reset} Directory ${projectName} already exists.`);
82
+ process.exit(1);
83
+ }
84
+
85
+ console.log(`
86
+ ${colors.bright}Creating a new project with Frontend Hamroun...${colors.reset}
87
+ ${colors.blue}• Project name:${colors.reset} ${projectName}
88
+ ${colors.blue}• Template:${colors.reset} ${template}
89
+ ${colors.blue}• Directory:${colors.reset} ${projectPath}
90
+ `);
91
+
92
+ try {
93
+ // Find templates directory
94
+ const templateDir = path.resolve(__dirname, '../templates', template);
95
+
96
+ if (!fs.existsSync(templateDir)) {
97
+ console.error(`${colors.red}error:${colors.reset} Template directory not found: ${templateDir}`);
98
+ // Try to find template with -app suffix as fallback
99
+ const fallbackTemplateDir = path.resolve(__dirname, '../templates', `${template}-app`);
100
+ if (fs.existsSync(fallbackTemplateDir)) {
101
+ console.log(`${colors.yellow}Using fallback template:${colors.reset} ${template}-app`);
102
+ templateDir = fallbackTemplateDir;
103
+ } else {
104
+ process.exit(1);
105
+ }
106
+ }
107
+
108
+ // Create project directory
109
+ fs.mkdirSync(projectPath, { recursive: true });
110
+
111
+ // Copy template files (recursive function)
112
+ function copyDir(src, dest) {
113
+ const entries = fs.readdirSync(src, { withFileTypes: true });
114
+
115
+ for (const entry of entries) {
116
+ const srcPath = path.join(src, entry.name);
117
+ const destPath = path.join(dest, entry.name);
118
+
119
+ if (entry.isDirectory()) {
120
+ fs.mkdirSync(destPath, { recursive: true });
121
+ copyDir(srcPath, destPath);
122
+ } else {
123
+ fs.copyFileSync(srcPath, destPath);
124
+ }
125
+ }
126
+ }
127
+
128
+ // Copy the files
129
+ copyDir(templateDir, projectPath);
130
+ console.log(`${colors.green}•${colors.reset} Copied template files`);
131
+
132
+ // Update package.json with project name
133
+ const projectPackageJsonPath = path.join(projectPath, 'package.json');
134
+ if (fs.existsSync(projectPackageJsonPath)) {
135
+ const projectPackageJson = JSON.parse(fs.readFileSync(projectPackageJsonPath, 'utf8'));
136
+ projectPackageJson.name = projectName;
137
+ fs.writeFileSync(
138
+ projectPackageJsonPath,
139
+ JSON.stringify(projectPackageJson, null, 2)
140
+ );
141
+ }
142
+
143
+ // Install dependencies
144
+ if (!options.skipInstall) {
145
+ console.log(`\n${colors.blue}Installing dependencies...${colors.reset}`);
146
+
147
+ try {
148
+ execSync(`npm install`, {
149
+ cwd: projectPath,
150
+ stdio: 'inherit'
151
+ });
152
+ } catch (error) {
153
+ console.error(`\n${colors.red}Failed to install dependencies. You can install them manually:${colors.reset}`);
154
+ console.log(` cd ${projectName} && npm install`);
155
+ }
156
+ }
157
+
158
+ // Success message
159
+ console.log(`
160
+ ${colors.green}${colors.bright}Success!${colors.reset} Created ${projectName} at ${projectPath}
161
+
162
+ ${colors.blue}Inside that directory, you can run several commands:${colors.reset}
163
+
164
+ ${colors.bright}npm run dev${colors.reset}
165
+ Starts the development server.
166
+
167
+ ${colors.bright}npm run build${colors.reset}
168
+ Builds the app for production.
169
+
170
+ ${colors.bright}npm start${colors.reset}
171
+ Runs the built app in production mode.
172
+
173
+ ${colors.blue}We suggest that you begin by typing:${colors.reset}
174
+
175
+ ${colors.bright}cd${colors.reset} ${projectName}
176
+ ${colors.bright}npm run dev${colors.reset}
177
+
178
+ ${colors.green}Happy coding!${colors.reset}
179
+ `);
180
+
181
+ } catch (error) {
182
+ console.error(`${colors.red}Failed to create project:${colors.reset}`, error);
183
+ process.exit(1);
184
+ }
185
+ }
186
+
187
+ // Parse command line arguments
188
+ function parseArgs() {
189
+ const args = process.argv.slice(2);
190
+ const command = args[0];
191
+
192
+ if (!command || command === 'help') {
193
+ printBanner();
194
+ printHelp();
195
+ process.exit(0);
196
+ }
197
+
198
+ if (command === 'version') {
199
+ console.log(`frontend-hamroun v${packageJson.version}`);
200
+ process.exit(0);
201
+ }
202
+
203
+ if (command === 'create') {
204
+ const projectName = args[1];
205
+
206
+ if (!projectName) {
207
+ console.error(`${colors.red}error:${colors.reset} Project name is required.`);
208
+ console.log(`Run ${colors.blue}npx frontend-hamroun help${colors.reset} for usage information.`);
209
+ process.exit(1);
210
+ }
211
+
212
+ // Parse options
213
+ const options = {
214
+ template: 'basic',
215
+ skipInstall: false
216
+ };
217
+
218
+ for (let i = 2; i < args.length; i++) {
219
+ if (args[i] === '--template' || args[i] === '-t') {
220
+ options.template = args[++i];
221
+ } else if (args[i] === '--skip-install' || args[i] === '-s') {
222
+ options.skipInstall = true;
223
+ }
224
+ }
225
+
226
+ printBanner();
227
+ createProject(projectName, options);
228
+ return;
229
+ }
230
+
231
+ console.error(`${colors.red}error:${colors.reset} Unknown command: ${command}`);
232
+ console.log(`Run ${colors.blue}npx frontend-hamroun help${colors.reset} for usage information.`);
233
+ process.exit(1);
234
+ }
235
+
236
+ // Run CLI
237
+ parseArgs();
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli/index.js CHANGED
@@ -1 +1,215 @@
1
- "use strict";
1
+ #!/usr/bin/env node
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import { execSync } from 'child_process';
6
+ import readline from 'readline';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ // Get package.json to read version
10
+ const packageJsonPath = path.resolve(__dirname, '../../package.json');
11
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
12
+ // Available templates
13
+ const TEMPLATES = {
14
+ 'basic': 'Basic frontend only template',
15
+ 'full-stack': 'Complete frontend and backend template',
16
+ 'api-only': 'Backend API only template'
17
+ };
18
+ // CLI colors
19
+ const colors = {
20
+ reset: '\x1b[0m',
21
+ bright: '\x1b[1m',
22
+ green: '\x1b[32m',
23
+ blue: '\x1b[34m',
24
+ red: '\x1b[31m',
25
+ yellow: '\x1b[33m'
26
+ };
27
+ // Create readline interface
28
+ function createInterface() {
29
+ return readline.createInterface({
30
+ input: process.stdin,
31
+ output: process.stdout
32
+ });
33
+ }
34
+ // Print banner
35
+ function printBanner() {
36
+ console.log(`
37
+ ${colors.blue}${colors.bright}╔══════════════════════════════════════════════╗
38
+ ║ ║
39
+ ║ Frontend Hamroun v${packageJson.version.padEnd(25)}║
40
+ ║ A lightweight frontend & backend framework ║
41
+ ║ ║
42
+ ╚══════════════════════════════════════════════╝${colors.reset}
43
+ `);
44
+ }
45
+ // Print help
46
+ function printHelp() {
47
+ console.log(`
48
+ ${colors.bright}USAGE:${colors.reset}
49
+ ${colors.blue}npx frontend-hamroun${colors.reset} [command] [options]
50
+
51
+ ${colors.bright}COMMANDS:${colors.reset}
52
+ ${colors.blue}create${colors.reset} <project-name> [options] Create a new project
53
+ ${colors.blue}help${colors.reset} Display this help message
54
+ ${colors.blue}version${colors.reset} Display version information
55
+
56
+ ${colors.bright}OPTIONS:${colors.reset}
57
+ ${colors.blue}--template${colors.reset}, ${colors.blue}-t${colors.reset} <template> Specify template (default: basic)
58
+ ${colors.blue}--skip-install${colors.reset}, ${colors.blue}-s${colors.reset} Skip package installation
59
+
60
+ ${colors.bright}AVAILABLE TEMPLATES:${colors.reset}
61
+ ${Object.entries(TEMPLATES).map(([name, desc]) => ` ${colors.blue}${name.padEnd(12)}${colors.reset} ${desc}`).join('\n')}
62
+
63
+ ${colors.bright}EXAMPLES:${colors.reset}
64
+ ${colors.blue}npx frontend-hamroun create${colors.reset} my-app
65
+ ${colors.blue}npx frontend-hamroun create${colors.reset} my-app --template full-stack
66
+ ${colors.blue}npx frontend-hamroun create${colors.reset} my-api -t api-only --skip-install
67
+ `);
68
+ }
69
+ // Create project from template
70
+ async function createProject(projectName, options) {
71
+ const template = options.template || 'basic';
72
+ // Check if template exists
73
+ if (!Object.keys(TEMPLATES).includes(template)) {
74
+ console.error(`${colors.red}error:${colors.reset} Template "${template}" not found.`);
75
+ console.log(`Available templates: ${Object.keys(TEMPLATES).join(', ')}`);
76
+ process.exit(1);
77
+ }
78
+ // Check if project directory already exists
79
+ const projectPath = path.resolve(process.cwd(), projectName);
80
+ if (fs.existsSync(projectPath)) {
81
+ console.error(`${colors.red}error:${colors.reset} Directory ${projectName} already exists.`);
82
+ process.exit(1);
83
+ }
84
+ console.log(`
85
+ ${colors.bright}Creating a new project with Frontend Hamroun...${colors.reset}
86
+ ${colors.blue}• Project name:${colors.reset} ${projectName}
87
+ ${colors.blue}• Template:${colors.reset} ${template}
88
+ ${colors.blue}• Directory:${colors.reset} ${projectPath}
89
+ `);
90
+ try {
91
+ // Find templates directory
92
+ const templateDir = path.resolve(__dirname, '../../templates', template);
93
+ // Create project directory
94
+ fs.mkdirSync(projectPath, { recursive: true });
95
+ // Copy template files
96
+ copyTemplateFiles(templateDir, projectPath);
97
+ // Update package.json with project name
98
+ const projectPackageJsonPath = path.join(projectPath, 'package.json');
99
+ if (fs.existsSync(projectPackageJsonPath)) {
100
+ const projectPackageJson = JSON.parse(fs.readFileSync(projectPackageJsonPath, 'utf8'));
101
+ projectPackageJson.name = projectName;
102
+ fs.writeFileSync(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2));
103
+ }
104
+ // Install dependencies
105
+ if (!options.skipInstall) {
106
+ console.log(`\n${colors.blue}Installing dependencies...${colors.reset}`);
107
+ const command = getPackageManager() === 'yarn'
108
+ ? 'yarn'
109
+ : 'npm install';
110
+ execSync(command, {
111
+ cwd: projectPath,
112
+ stdio: 'inherit'
113
+ });
114
+ }
115
+ // Success message
116
+ console.log(`
117
+ ${colors.green}${colors.bright}Success!${colors.reset} Created ${projectName} at ${projectPath}
118
+
119
+ ${colors.blue}Inside that directory, you can run several commands:${colors.reset}
120
+
121
+ ${colors.bright}npm run dev${colors.reset}
122
+ Starts the development server.
123
+
124
+ ${colors.bright}npm run build${colors.reset}
125
+ Builds the app for production.
126
+
127
+ ${colors.bright}npm start${colors.reset}
128
+ Runs the built app in production mode.
129
+
130
+ ${colors.blue}We suggest that you begin by typing:${colors.reset}
131
+
132
+ ${colors.bright}cd${colors.reset} ${projectName}
133
+ ${colors.bright}npm run dev${colors.reset}
134
+
135
+ ${colors.green}Happy coding!${colors.reset}
136
+ `);
137
+ }
138
+ catch (error) {
139
+ console.error(`${colors.red}Failed to create project:${colors.reset}`, error);
140
+ process.exit(1);
141
+ }
142
+ }
143
+ // Copy template files recursively
144
+ function copyTemplateFiles(source, destination) {
145
+ const files = fs.readdirSync(source);
146
+ for (const file of files) {
147
+ const sourcePath = path.join(source, file);
148
+ const destPath = path.join(destination, file);
149
+ const stats = fs.statSync(sourcePath);
150
+ if (stats.isDirectory()) {
151
+ fs.mkdirSync(destPath, { recursive: true });
152
+ copyTemplateFiles(sourcePath, destPath);
153
+ }
154
+ else {
155
+ fs.copyFileSync(sourcePath, destPath);
156
+ }
157
+ }
158
+ console.log(`${colors.green}•${colors.reset} Copied template files`);
159
+ }
160
+ // Detect package manager
161
+ function getPackageManager() {
162
+ try {
163
+ const userAgent = process.env.npm_config_user_agent;
164
+ if (userAgent && userAgent.startsWith('yarn')) {
165
+ return 'yarn';
166
+ }
167
+ return 'npm';
168
+ }
169
+ catch (error) {
170
+ return 'npm';
171
+ }
172
+ }
173
+ // Parse command line arguments
174
+ function parseArgs() {
175
+ const args = process.argv.slice(2);
176
+ const command = args[0];
177
+ if (!command || command === 'help') {
178
+ printBanner();
179
+ printHelp();
180
+ process.exit(0);
181
+ }
182
+ if (command === 'version') {
183
+ console.log(`frontend-hamroun v${packageJson.version}`);
184
+ process.exit(0);
185
+ }
186
+ if (command === 'create') {
187
+ const projectName = args[1];
188
+ if (!projectName) {
189
+ console.error(`${colors.red}error:${colors.reset} Project name is required.`);
190
+ console.log(`Run ${colors.blue}npx frontend-hamroun help${colors.reset} for usage information.`);
191
+ process.exit(1);
192
+ }
193
+ // Parse options
194
+ const options = {
195
+ template: 'basic',
196
+ skipInstall: false
197
+ };
198
+ for (let i = 2; i < args.length; i++) {
199
+ if (args[i] === '--template' || args[i] === '-t') {
200
+ options.template = args[++i];
201
+ }
202
+ else if (args[i] === '--skip-install' || args[i] === '-s') {
203
+ options.skipInstall = true;
204
+ }
205
+ }
206
+ printBanner();
207
+ createProject(projectName, options);
208
+ return;
209
+ }
210
+ console.error(`${colors.red}error:${colors.reset} Unknown command: ${command}`);
211
+ console.log(`Run ${colors.blue}npx frontend-hamroun help${colors.reset} for usage information.`);
212
+ process.exit(1);
213
+ }
214
+ // Run CLI
215
+ parseArgs();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "A lightweight frontend and backend framework for building modern web applications",
5
5
  "type": "module",
6
6
  "main": "dist/frontend-hamroun.umd.js",
@@ -11,6 +11,7 @@
11
11
  "src",
12
12
  "templates",
13
13
  "scripts",
14
+ "bin",
14
15
  "LICENSE",
15
16
  "README.md"
16
17
  ],
@@ -22,17 +23,19 @@
22
23
  }
23
24
  },
24
25
  "bin": {
25
- "hamroun": "./dist/cli/index.js",
26
- "frontend-hamroun": "./dist/cli/index.js"
26
+ "hamroun": "./bin/cli.mjs",
27
+ "frontend-hamroun": "./bin/cli.mjs"
27
28
  },
28
29
  "scripts": {
29
30
  "dev": "vite",
30
- "build": "vite build && tsc && node scripts/build-cli.js",
31
+ "build": "vite build && tsc && npm run build:cli",
32
+ "build:cli": "node scripts/build-cli.js",
33
+ "prepublishOnly": "npm run build",
31
34
  "test": "jest",
32
- "clean": "rimraf dist",
35
+ "clean": "rimraf dist bin",
33
36
  "prebuild": "npm run clean",
34
- "prepublish": "npm run build",
35
- "generate": "node scripts/generate.js"
37
+ "generate": "node scripts/generate.js",
38
+ "publish:next": "npm publish --tag next"
36
39
  },
37
40
  "keywords": [
38
41
  "frontend",