frontend-hamroun 1.1.11 → 1.1.13

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/README.md CHANGED
@@ -8,6 +8,23 @@ A lightweight Virtual DOM and hooks implementation with JSX support.
8
8
  npm install your-package-name
9
9
  ```
10
10
 
11
+ ## Quick Start
12
+
13
+ Create a new project using:
14
+
15
+ ```bash
16
+ npx create-frontend-app my-app
17
+ # or
18
+ npm create frontend-app@latest my-app
19
+ ```
20
+ Then:
21
+
22
+ ```bash
23
+ cd my-app
24
+ npm install
25
+ npm run dev
26
+ ```
27
+
11
28
  ## Usage
12
29
 
13
30
  ```jsx
@@ -220,4 +237,4 @@ MIT License - feel free to use in any project.
220
237
  ## Contributing
221
238
 
222
239
  Contributions are welcome! Please read our contributing guidelines and submit pull requests.
223
- ````
240
+ `````
package/bin/cli.js CHANGED
@@ -2,111 +2,72 @@
2
2
 
3
3
  import { Command } from 'commander';
4
4
  import inquirer from 'inquirer';
5
- import chalk from 'chalk';
6
5
  import fs from 'fs-extra';
7
6
  import path from 'path';
8
- import { createSpinner } from 'nanospinner';
9
7
  import { fileURLToPath } from 'url';
10
- import { dirname } from 'path';
8
+ import chalk from 'chalk';
9
+ import { createSpinner } from 'nanospinner';
11
10
 
12
11
  const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ async function init() {
15
+ const program = new Command();
16
+
17
+ program
18
+ .name('create-frontend-app')
19
+ .description('Create a new Frontend Hamroun application')
20
+ .argument('[name]', 'Project name')
21
+ .action(async (name) => {
22
+ const projectName = name || await askProjectName();
23
+ await createProject(projectName);
24
+ });
14
25
 
15
- const program = new Command();
26
+ program.parse();
27
+ }
16
28
 
17
- const CHOICES = {
18
- SPA: 'Single Page Application',
19
- COMPONENT: 'Component Library'
20
- };
29
+ async function askProjectName() {
30
+ const { projectName } = await inquirer.prompt([{
31
+ type: 'input',
32
+ name: 'projectName',
33
+ message: 'What is your project named?',
34
+ default: 'my-frontend-app'
35
+ }]);
36
+ return projectName;
37
+ }
21
38
 
22
- async function createProject(projectName, options) {
39
+ async function createProject(projectName) {
23
40
  const spinner = createSpinner('Creating project...').start();
24
-
25
- try {
26
- // Validate project name
27
- if (!projectName) {
28
- spinner.error({ text: 'Project name is required' });
29
- process.exit(1);
30
- }
31
41
 
42
+ try {
43
+ const templateDir = path.join(__dirname, '..', 'templates', 'basic-app');
32
44
  const targetDir = path.join(process.cwd(), projectName);
33
45
 
34
- // Check if directory exists
35
- if (fs.existsSync(targetDir)) {
36
- spinner.error({ text: 'Directory already exists!' });
37
- process.exit(1);
38
- }
46
+ // Create project directory
47
+ await fs.ensureDir(targetDir);
39
48
 
40
- // Get template path
41
- const templatePath = path.join(__dirname, '../templates', options.template.toLowerCase());
42
-
43
- // Ensure template exists
44
- if (!fs.existsSync(templatePath)) {
45
- spinner.error({ text: 'Template not found!' });
46
- process.exit(1);
47
- }
48
-
49
- // Copy template
50
- await fs.copy(templatePath, targetDir);
49
+ // Copy template files
50
+ await fs.copy(templateDir, targetDir);
51
51
 
52
52
  // Update package.json
53
- const packageJsonPath = path.join(targetDir, 'package.json');
54
- const packageJson = await fs.readJson(packageJsonPath);
55
- packageJson.name = projectName;
56
- await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
53
+ const pkgPath = path.join(targetDir, 'package.json');
54
+ const pkg = await fs.readJson(pkgPath);
55
+ pkg.name = projectName;
56
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
57
57
 
58
58
  spinner.success({ text: `Project ${chalk.green(projectName)} created successfully!` });
59
-
59
+
60
+ // Show next steps
60
61
  console.log('\nNext steps:');
61
- console.log(` cd ${projectName}`);
62
- console.log(' npm install');
63
- console.log(' npm run dev\n');
62
+ console.log(chalk.cyan(` cd ${projectName}`));
63
+ console.log(chalk.cyan(' npm install'));
64
+ console.log(chalk.cyan(' npm run dev'));
64
65
 
65
66
  } catch (error) {
66
- spinner.error({ text: `Error: ${error.message}` });
67
+ spinner.error({ text: 'Failed to create project' });
68
+ console.error(chalk.red(error));
67
69
  process.exit(1);
68
70
  }
69
71
  }
70
72
 
71
- program
72
- .name('frontend-hamroun')
73
- .description('CLI for Frontend Hamroun Framework')
74
- .version('1.0.0');
75
-
76
- program
77
- .command('create <project-name>')
78
- .description('Create a new project')
79
- .action(async (projectName) => {
80
- const answers = await inquirer.prompt([
81
- {
82
- type: 'list',
83
- name: 'template',
84
- message: 'What type of project do you want to create?',
85
- choices: Object.values(CHOICES)
86
- }
87
- ]);
88
-
89
- await createProject(projectName, {
90
- template: answers.template === CHOICES.SPA ? 'spa' : 'component'
91
- });
92
- });
93
-
94
- program
95
- .command('dev')
96
- .description('Start development server')
97
- .action(() => {
98
- const spinner = createSpinner('Starting development server...').start();
99
- // Add dev server logic here
100
- spinner.success({ text: 'Development server started on http://localhost:3000' });
101
- });
102
-
103
- program
104
- .command('build')
105
- .description('Build for production')
106
- .action(() => {
107
- const spinner = createSpinner('Building for production...').start();
108
- // Add build logic here
109
- spinner.success({ text: 'Build complete!' });
110
- });
111
-
112
- program.parse(process.argv);
73
+ init().catch(console.error);
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "A lightweight frontend framework with hooks and virtual DOM",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>My Frontend App</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "my-app",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "dependencies": {
11
+ "frontend-hamroun": "^1.1.11"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "^5.0.0",
15
+ "vite": "^4.4.9"
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ import { useState, useEffect } from 'frontend-hamroun';
2
+
3
+ export function Counter({ initial = 0 }) {
4
+ const [count, setCount] = useState(initial);
5
+
6
+ useEffect(() => {
7
+ document.title = `Count: ${count}`;
8
+ }, [count]);
9
+
10
+ return (
11
+ <div>
12
+ <h2>Counter Component</h2>
13
+ <button onClick={() => setCount(count - 1)}>-</button>
14
+ <span style={{ margin: '0 10px' }}>{count}</span>
15
+ <button onClick={() => setCount(count + 1)}>+</button>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,18 @@
1
+ import { render, useState } from 'frontend-hamroun';
2
+
3
+ function App() {
4
+ const [count, setCount] = useState(0);
5
+
6
+ return (
7
+ <div>
8
+ <h1>Welcome to Frontend Hamroun</h1>
9
+ <div>
10
+ <button onClick={() => setCount(count - 1)}>-</button>
11
+ <span style={{ margin: '0 10px' }}>{count}</span>
12
+ <button onClick={() => setCount(count + 1)}>+</button>
13
+ </div>
14
+ </div>
15
+ );
16
+ }
17
+
18
+ render(<App />, document.getElementById('root')!);
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "jsx": "preserve",
7
+ "moduleResolution": "bundler",
8
+ "esModuleInterop": true,
9
+ "strict": true,
10
+ "skipLibCheck": true
11
+ },
12
+ "include": ["src"]
13
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vite';
2
+
3
+ export default defineConfig({
4
+ esbuild: {
5
+ jsxFactory: 'jsx',
6
+ jsxFragment: 'Fragment'
7
+ }
8
+ });