frontend-hamroun 1.2.16 → 1.2.17
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 +4 -0
- package/bin/cli.js +673 -0
- package/dist/component.d.ts +1 -1
- package/dist/context.d.ts +4 -3
- package/dist/index.client.d.ts +11 -0
- package/dist/index.d.ts +9 -89
- package/dist/index.js +396 -67
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +392 -0
- package/dist/index.mjs.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts +0 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/renderer.d.ts +0 -10
- package/dist/server-renderer.d.ts +0 -3
- package/dist/server-types.d.ts +42 -0
- package/package.json +69 -41
- package/templates/basic-app/index.html +6 -6
- package/templates/basic-app/package.json +18 -7
- package/templates/basic-app/postcss.config.js +0 -1
- package/templates/basic-app/src/main.tsx +1 -10
- package/templates/basic-app/tailwind.config.js +2 -23
- package/templates/basic-app/tsconfig.json +4 -17
- package/templates/basic-app/vite.config.ts +3 -54
- package/templates/fullstack-app/api/hello.ts +18 -0
- package/templates/fullstack-app/api/users/[id].ts +73 -0
- package/templates/fullstack-app/api/users/index.ts +32 -0
- package/templates/fullstack-app/package.json +31 -0
- package/templates/fullstack-app/server.ts +46 -0
- package/templates/fullstack-app/src/pages/index.tsx +59 -0
- package/templates/ssr-template/vite.config.ts +1 -11
- package/bin/cli.cjs +0 -16
- package/bin/cli.mjs +0 -237
- package/dist/backend/api-utils.d.ts +0 -38
- package/dist/backend/api-utils.js +0 -135
- package/dist/backend/auth.d.ts +0 -134
- package/dist/backend/auth.js +0 -387
- package/dist/backend/database.d.ts +0 -27
- package/dist/backend/database.js +0 -91
- package/dist/backend/model.d.ts +0 -43
- package/dist/backend/model.js +0 -178
- package/dist/backend/router.d.ts +0 -27
- package/dist/backend/router.js +0 -137
- package/dist/backend/server.d.ts +0 -19
- package/dist/backend/server.js +0 -268
- package/dist/backend/types.d.ts +0 -217
- package/dist/backend/types.js +0 -1
- package/dist/batch.js +0 -22
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.js +0 -215
- package/dist/component.js +0 -84
- package/dist/components/Counter.js +0 -2
- package/dist/context.js +0 -18
- package/dist/frontend-hamroun.es.js +0 -1378
- package/dist/frontend-hamroun.umd.js +0 -66
- package/dist/hooks.js +0 -164
- package/dist/jsx-runtime/index.d.ts +0 -11
- package/dist/jsx-runtime/index.js +0 -19
- package/dist/jsx-runtime/jsx-dev-runtime.js +0 -1
- package/dist/jsx-runtime/jsx-runtime.js +0 -95
- package/dist/jsx-runtime.js +0 -192
- package/dist/renderer.js +0 -51
- package/dist/server-renderer.js +0 -102
- package/dist/types.js +0 -1
- package/dist/vdom.js +0 -27
- package/scripts/build-cli.js +0 -1199
- package/scripts/generate.js +0 -134
- package/src/backend/api-utils.ts +0 -178
- package/src/backend/auth.ts +0 -544
- package/src/backend/database.ts +0 -104
- package/src/backend/model.ts +0 -198
- package/src/backend/router.ts +0 -176
- package/src/backend/server.ts +0 -330
- package/src/backend/types.ts +0 -257
- package/src/batch.ts +0 -24
- package/src/cli/index.js +0 -554
- package/src/cli/index.ts +0 -257
- package/src/component.ts +0 -98
- package/src/components/Counter.tsx +0 -4
- package/src/context.ts +0 -29
- package/src/hooks.ts +0 -211
- package/src/index.ts +0 -144
- package/src/jsx-runtime/index.ts +0 -27
- package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
- package/src/jsx-runtime/jsx-runtime.ts +0 -104
- package/src/jsx-runtime.ts +0 -226
- package/src/renderer.ts +0 -55
- package/src/server-renderer.ts +0 -114
- package/src/shims.d.ts +0 -20
- package/src/types/bcrypt.d.ts +0 -30
- package/src/types/jsonwebtoken.d.ts +0 -55
- package/src/types.d.ts +0 -26
- package/src/types.ts +0 -21
- package/src/vdom.ts +0 -34
- package/templates/basic/.eslintignore +0 -5
- package/templates/basic/.eslintrc.json +0 -25
- package/templates/basic/docs/rapport_pfe.aux +0 -27
- package/templates/basic/docs/rapport_pfe.log +0 -399
- package/templates/basic/docs/rapport_pfe.out +0 -10
- package/templates/basic/docs/rapport_pfe.pdf +0 -0
- package/templates/basic/docs/rapport_pfe.tex +0 -68
- package/templates/basic/docs/rapport_pfe.toc +0 -14
- package/templates/basic/index.html +0 -12
- package/templates/basic/jsconfig.json +0 -14
- package/templates/basic/package.json +0 -18
- package/templates/basic/postcss.config.js +0 -7
- package/templates/basic/src/App.js +0 -105
- package/templates/basic/src/App.tsx +0 -65
- package/templates/basic/src/api.ts +0 -58
- package/templates/basic/src/components/Counter.tsx +0 -26
- package/templates/basic/src/components/Header.tsx +0 -9
- package/templates/basic/src/components/TodoList.tsx +0 -90
- package/templates/basic/src/main.css +0 -3
- package/templates/basic/src/main.js +0 -11
- package/templates/basic/src/main.ts +0 -20
- package/templates/basic/src/main.tsx +0 -144
- package/templates/basic/src/server.ts +0 -99
- package/templates/basic/tailwind.config.js +0 -32
- package/templates/basic/tsconfig.json +0 -20
- package/templates/basic/tsconfig.node.json +0 -10
- package/templates/basic/vite.config.js +0 -18
- package/templates/basic/vite.config.ts +0 -86
- package/templates/basic-app/src/App.js +0 -105
- package/templates/basic-app/src/App.tsx +0 -143
- package/templates/basic-app/src/api.ts +0 -58
- package/templates/basic-app/src/components/Counter.tsx +0 -26
- package/templates/basic-app/src/components/Header.tsx +0 -9
- package/templates/basic-app/src/components/TodoList.tsx +0 -90
- package/templates/basic-app/src/main.js +0 -10
- package/templates/basic-app/src/main.ts +0 -21
- package/templates/basic-app/src/react/index.ts +0 -35
- package/templates/basic-app/src/react/jsx-dev-runtime.ts +0 -13
- package/templates/basic-app/src/react/jsx-runtime.ts +0 -12
- package/templates/basic-app/src/server.ts +0 -99
- package/templates/basic-app/src/shims.ts +0 -9
- package/templates/basic-app/tsconfig.node.json +0 -10
- package/templates/basic-app/vite.config.js +0 -22
- package/templates/full-stack/.env.example +0 -11
- package/templates/full-stack/README.md +0 -51
- package/templates/full-stack/index.html +0 -12
- package/templates/full-stack/jsconfig.json +0 -14
- package/templates/full-stack/package.json +0 -21
- package/templates/full-stack/src/App.js +0 -105
- package/templates/full-stack/src/client/App.tsx +0 -50
- package/templates/full-stack/src/client/components/Header.tsx +0 -42
- package/templates/full-stack/src/client/components/UserList.tsx +0 -29
- package/templates/full-stack/src/client/main.tsx +0 -5
- package/templates/full-stack/src/main.css +0 -3
- package/templates/full-stack/src/main.js +0 -11
- package/templates/full-stack/src/main.ts +0 -20
- package/templates/full-stack/src/server/index.ts +0 -99
- package/templates/full-stack/src/server/routes/auth.ts +0 -39
- package/templates/full-stack/src/server/routes/users.ts +0 -48
- package/templates/full-stack/src/shims.ts +0 -9
- package/templates/full-stack/tsconfig.json +0 -20
- package/templates/full-stack/tsconfig.node.json +0 -10
- package/templates/full-stack/tsconfig.server.json +0 -15
- package/templates/full-stack/vite.config.js +0 -18
- package/templates/full-stack/vite.config.ts +0 -85
@@ -1,90 +0,0 @@
|
|
1
|
-
import { useState } from 'front-package';
|
2
|
-
import { ApiClient, Todo } from '../api';
|
3
|
-
|
4
|
-
interface TodoListProps {
|
5
|
-
todos: Todo[];
|
6
|
-
api: ApiClient;
|
7
|
-
setTodos: (todos: Todo[]) => void;
|
8
|
-
}
|
9
|
-
|
10
|
-
export function TodoList({ todos, api, setTodos }: TodoListProps) {
|
11
|
-
const [newTodoText, setNewTodoText] = useState('');
|
12
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
13
|
-
|
14
|
-
async function handleAddTodo(e: Event) {
|
15
|
-
e.preventDefault();
|
16
|
-
if (!newTodoText.trim()) return;
|
17
|
-
|
18
|
-
try {
|
19
|
-
setIsSubmitting(true);
|
20
|
-
const newTodo = await api.addTodo({
|
21
|
-
title: newTodoText,
|
22
|
-
completed: false
|
23
|
-
});
|
24
|
-
|
25
|
-
setTodos([...todos, newTodo]);
|
26
|
-
setNewTodoText('');
|
27
|
-
} catch (err) {
|
28
|
-
console.error('Failed to add todo:', err);
|
29
|
-
} finally {
|
30
|
-
setIsSubmitting(false);
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
async function handleToggleTodo(id: string, completed: boolean) {
|
35
|
-
try {
|
36
|
-
await api.updateTodo(id, { completed });
|
37
|
-
setTodos(
|
38
|
-
todos.map(todo =>
|
39
|
-
todo.id === id ? { ...todo, completed } : todo
|
40
|
-
)
|
41
|
-
);
|
42
|
-
} catch (err) {
|
43
|
-
console.error('Failed to update todo:', err);
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
return (
|
48
|
-
<div>
|
49
|
-
<form onSubmit={handleAddTodo} className="mb-4">
|
50
|
-
<div className="flex gap-2">
|
51
|
-
<input
|
52
|
-
type="text"
|
53
|
-
value={newTodoText}
|
54
|
-
onChange={(e) => setNewTodoText(e.target.value)}
|
55
|
-
placeholder="Add a new todo..."
|
56
|
-
className="flex-1 border rounded px-3 py-2"
|
57
|
-
disabled={isSubmitting}
|
58
|
-
/>
|
59
|
-
<button
|
60
|
-
type="submit"
|
61
|
-
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition"
|
62
|
-
disabled={isSubmitting || !newTodoText.trim()}
|
63
|
-
>
|
64
|
-
{isSubmitting ? 'Adding...' : 'Add'}
|
65
|
-
</button>
|
66
|
-
</div>
|
67
|
-
</form>
|
68
|
-
|
69
|
-
<ul className="space-y-2">
|
70
|
-
{todos.length === 0 ? (
|
71
|
-
<li className="text-center py-2 text-gray-500">No todos yet</li>
|
72
|
-
) : (
|
73
|
-
todos.map(todo => (
|
74
|
-
<li key={todo.id} className="flex items-center gap-2 p-2 border-b">
|
75
|
-
<input
|
76
|
-
type="checkbox"
|
77
|
-
checked={todo.completed}
|
78
|
-
onChange={(e) => handleToggleTodo(todo.id, e.target.checked)}
|
79
|
-
className="h-5 w-5 text-blue-600"
|
80
|
-
/>
|
81
|
-
<span className={todo.completed ? 'line-through text-gray-500' : ''}>
|
82
|
-
{todo.title}
|
83
|
-
</span>
|
84
|
-
</li>
|
85
|
-
))
|
86
|
-
)}
|
87
|
-
</ul>
|
88
|
-
</div>
|
89
|
-
);
|
90
|
-
}
|
@@ -1,10 +0,0 @@
|
|
1
|
-
import { render } from 'frontend-hamroun';
|
2
|
-
import { App } from './App.js';
|
3
|
-
|
4
|
-
document.addEventListener('DOMContentLoaded', () => {
|
5
|
-
const rootElement = document.getElementById('app');
|
6
|
-
if (rootElement) {
|
7
|
-
render(App(), rootElement);
|
8
|
-
console.log('App rendered successfully');
|
9
|
-
}
|
10
|
-
});
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import './main.css';
|
2
|
-
import { render } from 'frontend-hamroun';
|
3
|
-
import { App } from './App';
|
4
|
-
import { createApiClient } from './api';
|
5
|
-
|
6
|
-
// Initialize API client
|
7
|
-
const api = createApiClient({
|
8
|
-
baseUrl: import.meta.env.VITE_API_URL || '/api'
|
9
|
-
});
|
10
|
-
|
11
|
-
// Render the app into the DOM
|
12
|
-
document.addEventListener('DOMContentLoaded', () => {
|
13
|
-
const rootElement = document.getElementById('app');
|
14
|
-
if (rootElement) {
|
15
|
-
// Call App as a function to create the VDOM structure
|
16
|
-
render(App({ api }), rootElement);
|
17
|
-
console.log('App rendered successfully');
|
18
|
-
} else {
|
19
|
-
console.error('Root element #app not found');
|
20
|
-
}
|
21
|
-
});
|
@@ -1,35 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
useState,
|
3
|
-
useEffect,
|
4
|
-
useRef,
|
5
|
-
useMemo,
|
6
|
-
useContext,
|
7
|
-
createContext,
|
8
|
-
jsx
|
9
|
-
} from 'frontend-hamroun';
|
10
|
-
|
11
|
-
// Provide React compatibility layer
|
12
|
-
const React = {
|
13
|
-
createElement: jsx,
|
14
|
-
Fragment: Symbol('Fragment'),
|
15
|
-
useState,
|
16
|
-
useEffect,
|
17
|
-
useRef,
|
18
|
-
useMemo,
|
19
|
-
useContext,
|
20
|
-
createContext
|
21
|
-
};
|
22
|
-
|
23
|
-
// Export hooks directly for named imports
|
24
|
-
export {
|
25
|
-
useState,
|
26
|
-
useEffect,
|
27
|
-
useRef,
|
28
|
-
useMemo,
|
29
|
-
useContext,
|
30
|
-
createContext,
|
31
|
-
jsx as createElement
|
32
|
-
};
|
33
|
-
|
34
|
-
// Default export
|
35
|
-
export default React;
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { jsx } from 'frontend-hamroun';
|
2
|
-
|
3
|
-
// Export jsx as jsxDEV for React compatibility
|
4
|
-
export const jsxDEV = jsx;
|
5
|
-
export const Fragment = Symbol('Fragment');
|
6
|
-
export const jsxs = jsx;
|
7
|
-
|
8
|
-
// Default export
|
9
|
-
export default {
|
10
|
-
jsxDEV,
|
11
|
-
Fragment,
|
12
|
-
jsxs
|
13
|
-
};
|
@@ -1,99 +0,0 @@
|
|
1
|
-
import { createServer, Router, Database, ApiRoute } from 'front-package';
|
2
|
-
import { fileURLToPath } from 'url';
|
3
|
-
import { dirname, join } from 'path';
|
4
|
-
import fs from 'fs';
|
5
|
-
|
6
|
-
// Setup paths for server
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
8
|
-
const __dirname = dirname(__filename);
|
9
|
-
const DIST_PATH = process.env.NODE_ENV === 'production'
|
10
|
-
? join(__dirname, '..')
|
11
|
-
: join(__dirname, '../dist');
|
12
|
-
|
13
|
-
// Initialize database
|
14
|
-
const db = new Database({
|
15
|
-
filePath: join(__dirname, '../data/db.json'),
|
16
|
-
defaultData: {
|
17
|
-
todos: [
|
18
|
-
{ id: '1', title: 'Learn Front Package', completed: false },
|
19
|
-
{ id: '2', title: 'Build an app', completed: false },
|
20
|
-
{ id: '3', title: 'Deploy to production', completed: false }
|
21
|
-
]
|
22
|
-
}
|
23
|
-
});
|
24
|
-
|
25
|
-
// Create API routes
|
26
|
-
const apiRouter = new Router();
|
27
|
-
|
28
|
-
// GET /api/todos
|
29
|
-
apiRouter.get('/todos', async (req, res) => {
|
30
|
-
const todos = await db.getAll('todos');
|
31
|
-
res.json(todos);
|
32
|
-
});
|
33
|
-
|
34
|
-
// GET /api/todos/:id
|
35
|
-
apiRouter.get('/todos/:id', async (req, res) => {
|
36
|
-
const todo = await db.getById('todos', req.params.id);
|
37
|
-
if (!todo) {
|
38
|
-
return res.status(404).json({ error: 'Todo not found' });
|
39
|
-
}
|
40
|
-
res.json(todo);
|
41
|
-
});
|
42
|
-
|
43
|
-
// POST /api/todos
|
44
|
-
apiRouter.post('/todos', async (req, res) => {
|
45
|
-
const { title, completed = false } = req.body;
|
46
|
-
|
47
|
-
if (!title) {
|
48
|
-
return res.status(400).json({ error: 'Title is required' });
|
49
|
-
}
|
50
|
-
|
51
|
-
const newTodo = {
|
52
|
-
id: Date.now().toString(),
|
53
|
-
title,
|
54
|
-
completed
|
55
|
-
};
|
56
|
-
|
57
|
-
await db.insert('todos', newTodo);
|
58
|
-
res.status(201).json(newTodo);
|
59
|
-
});
|
60
|
-
|
61
|
-
// PATCH /api/todos/:id
|
62
|
-
apiRouter.patch('/todos/:id', async (req, res) => {
|
63
|
-
const todo = await db.getById('todos', req.params.id);
|
64
|
-
if (!todo) {
|
65
|
-
return res.status(404).json({ error: 'Todo not found' });
|
66
|
-
}
|
67
|
-
|
68
|
-
const updatedTodo = { ...todo, ...req.body };
|
69
|
-
await db.update('todos', req.params.id, updatedTodo);
|
70
|
-
res.json(updatedTodo);
|
71
|
-
});
|
72
|
-
|
73
|
-
// DELETE /api/todos/:id
|
74
|
-
apiRouter.delete('/todos/:id', async (req, res) => {
|
75
|
-
const todo = await db.getById('todos', req.params.id);
|
76
|
-
if (!todo) {
|
77
|
-
return res.status(404).json({ error: 'Todo not found' });
|
78
|
-
}
|
79
|
-
|
80
|
-
await db.delete('todos', req.params.id);
|
81
|
-
res.status(204).end();
|
82
|
-
});
|
83
|
-
|
84
|
-
// Create server
|
85
|
-
const server = createServer({
|
86
|
-
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
|
87
|
-
staticDir: DIST_PATH,
|
88
|
-
routes: [
|
89
|
-
new ApiRoute('/api', apiRouter)
|
90
|
-
]
|
91
|
-
});
|
92
|
-
|
93
|
-
// Start server
|
94
|
-
server.start().then(() => {
|
95
|
-
console.log(`Server running at http://localhost:${server.port}`);
|
96
|
-
}).catch(err => {
|
97
|
-
console.error('Failed to start server:', err);
|
98
|
-
process.exit(1);
|
99
|
-
});
|
@@ -1,9 +0,0 @@
|
|
1
|
-
// This file provides compatibility shims for React JSX imports
|
2
|
-
|
3
|
-
import { jsx } from 'frontend-hamroun';
|
4
|
-
|
5
|
-
// Export the jsx function as jsxDEV for React compatibility
|
6
|
-
export const jsxDEV = jsx;
|
7
|
-
|
8
|
-
// Export a Fragment symbol
|
9
|
-
export const Fragment = Symbol('Fragment');
|
@@ -1,22 +0,0 @@
|
|
1
|
-
import { defineConfig } from 'vite';
|
2
|
-
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
3
|
-
|
4
|
-
export default defineConfig({
|
5
|
-
// No JSX-specific configuration
|
6
|
-
build: {
|
7
|
-
outDir: 'dist',
|
8
|
-
emptyOutDir: true
|
9
|
-
},
|
10
|
-
server: {
|
11
|
-
port: 3000,
|
12
|
-
open: true
|
13
|
-
},
|
14
|
-
optimizeDeps: {
|
15
|
-
include: ['frontend-hamroun']
|
16
|
-
},
|
17
|
-
plugins: [
|
18
|
-
nodePolyfills({
|
19
|
-
protocolImports: true,
|
20
|
-
}),
|
21
|
-
]
|
22
|
-
});
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# Server Configuration
|
2
|
-
PORT=3000
|
3
|
-
NODE_ENV=development
|
4
|
-
|
5
|
-
# Database Configuration
|
6
|
-
MONGODB_URI=mongodb://localhost:27017
|
7
|
-
MONGODB_NAME={{projectName}}
|
8
|
-
|
9
|
-
# Authentication
|
10
|
-
JWT_SECRET=your-jwt-secret-key-change-me
|
11
|
-
REFRESH_SECRET=your-refresh-token-secret-change-me
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# {{appName}}
|
2
|
-
|
3
|
-
{{description}}
|
4
|
-
|
5
|
-
## Getting Started
|
6
|
-
|
7
|
-
1. Clone this repository
|
8
|
-
2. Install dependencies:
|
9
|
-
```
|
10
|
-
npm install
|
11
|
-
```
|
12
|
-
3. Copy the environment variables file:
|
13
|
-
```
|
14
|
-
cp .env.example .env
|
15
|
-
```
|
16
|
-
4. Start the development server:
|
17
|
-
```
|
18
|
-
npm run dev
|
19
|
-
```
|
20
|
-
|
21
|
-
## Scripts
|
22
|
-
|
23
|
-
- `npm run dev` - Start the development server
|
24
|
-
- `npm run dev:server` - Start the backend server only
|
25
|
-
- `npm run dev:client` - Start the frontend development server only
|
26
|
-
- `npm run build` - Build for production
|
27
|
-
- `npm start` - Start the production server
|
28
|
-
- `npm test` - Run tests
|
29
|
-
|
30
|
-
## Project Structure
|
31
|
-
|
32
|
-
```
|
33
|
-
├── src/
|
34
|
-
│ ├── client/ # Frontend code
|
35
|
-
│ │ ├── components/ # UI components
|
36
|
-
│ │ ├── App.tsx # Main app component
|
37
|
-
│ │ └── main.tsx # Entry point
|
38
|
-
│ └── server/ # Backend code
|
39
|
-
│ ├── routes/ # API routes
|
40
|
-
│ └── index.ts # Server entry point
|
41
|
-
├── .env.example # Environment variables example
|
42
|
-
├── package.json # Dependencies and scripts
|
43
|
-
└── tsconfig.json # TypeScript configuration
|
44
|
-
```
|
45
|
-
|
46
|
-
## Created with Hamroun
|
47
|
-
|
48
|
-
This project was generated using the Hamroun framework.
|
49
|
-
|
50
|
-
Author: {{author}}
|
51
|
-
Created: {{creationDate}}
|
@@ -1,12 +0,0 @@
|
|
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>Frontend Hamroun App</title>
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div id="app"></div>
|
10
|
-
<script type="module" src="/src/main.js"></script>
|
11
|
-
</body>
|
12
|
-
</html>
|
@@ -1,14 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"compilerOptions": {
|
3
|
-
"target": "ES2020",
|
4
|
-
"useDefineForClassFields": true,
|
5
|
-
"module": "ESNext",
|
6
|
-
"moduleResolution": "node",
|
7
|
-
"allowSyntheticDefaultImports": true,
|
8
|
-
"resolveJsonModule": true,
|
9
|
-
"checkJs": false,
|
10
|
-
"strict": false
|
11
|
-
},
|
12
|
-
"include": ["src/**/*.js"],
|
13
|
-
"exclude": ["node_modules"]
|
14
|
-
}
|
@@ -1,21 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"name": "frontend-hamroun-app",
|
3
|
-
"private": true,
|
4
|
-
"version": "0.1.0",
|
5
|
-
"type": "module",
|
6
|
-
"scripts": {
|
7
|
-
"dev": "node src/server.js",
|
8
|
-
"build": "tsc",
|
9
|
-
"start": "node dist/server.js"
|
10
|
-
},
|
11
|
-
"dependencies": {
|
12
|
-
"express": "^4.18.2",
|
13
|
-
"compression": "^1.7.4",
|
14
|
-
"helmet": "^7.1.0",
|
15
|
-
"morgan": "^1.10.0"
|
16
|
-
},
|
17
|
-
"devDependencies": {
|
18
|
-
"@types/node": "^20.10.0",
|
19
|
-
"typescript": "^5.3.2"
|
20
|
-
}
|
21
|
-
}
|
@@ -1,105 +0,0 @@
|
|
1
|
-
import { useState, useRef } from 'frontend-hamroun';
|
2
|
-
|
3
|
-
export function App() {
|
4
|
-
const [count, setCount] = useState(0);
|
5
|
-
const renderCount = useRef(0);
|
6
|
-
|
7
|
-
renderCount.current++;
|
8
|
-
|
9
|
-
// Return a plain JavaScript object representation of the UI
|
10
|
-
return {
|
11
|
-
type: 'div',
|
12
|
-
props: {
|
13
|
-
style: {
|
14
|
-
fontFamily: 'Arial, sans-serif',
|
15
|
-
maxWidth: '600px',
|
16
|
-
margin: '0 auto',
|
17
|
-
padding: '2rem'
|
18
|
-
},
|
19
|
-
children: [
|
20
|
-
{
|
21
|
-
type: 'h1',
|
22
|
-
props: {
|
23
|
-
style: { textAlign: 'center' },
|
24
|
-
children: 'Frontend Hamroun App'
|
25
|
-
}
|
26
|
-
},
|
27
|
-
{
|
28
|
-
type: 'p',
|
29
|
-
props: {
|
30
|
-
style: { textAlign: 'center' },
|
31
|
-
children: `Render count: ${renderCount.current}`
|
32
|
-
}
|
33
|
-
},
|
34
|
-
{
|
35
|
-
type: 'div',
|
36
|
-
props: {
|
37
|
-
style: {
|
38
|
-
display: 'flex',
|
39
|
-
flexDirection: 'column',
|
40
|
-
alignItems: 'center',
|
41
|
-
padding: '1rem',
|
42
|
-
border: '1px solid #ccc',
|
43
|
-
borderRadius: '8px'
|
44
|
-
},
|
45
|
-
children: [
|
46
|
-
{
|
47
|
-
type: 'h2',
|
48
|
-
props: {
|
49
|
-
children: 'Counter Example'
|
50
|
-
}
|
51
|
-
},
|
52
|
-
{
|
53
|
-
type: 'p',
|
54
|
-
props: {
|
55
|
-
children: `Count: ${count}`
|
56
|
-
}
|
57
|
-
},
|
58
|
-
{
|
59
|
-
type: 'div',
|
60
|
-
props: {
|
61
|
-
style: {
|
62
|
-
display: 'flex',
|
63
|
-
gap: '8px'
|
64
|
-
},
|
65
|
-
children: [
|
66
|
-
{
|
67
|
-
type: 'button',
|
68
|
-
props: {
|
69
|
-
onClick: () => setCount(count - 1),
|
70
|
-
style: {
|
71
|
-
padding: '8px 16px',
|
72
|
-
backgroundColor: '#ff4d4d',
|
73
|
-
color: 'white',
|
74
|
-
border: 'none',
|
75
|
-
borderRadius: '4px',
|
76
|
-
cursor: 'pointer'
|
77
|
-
},
|
78
|
-
children: 'Decrement'
|
79
|
-
}
|
80
|
-
},
|
81
|
-
{
|
82
|
-
type: 'button',
|
83
|
-
props: {
|
84
|
-
onClick: () => setCount(count + 1),
|
85
|
-
style: {
|
86
|
-
padding: '8px 16px',
|
87
|
-
backgroundColor: '#4d79ff',
|
88
|
-
color: 'white',
|
89
|
-
border: 'none',
|
90
|
-
borderRadius: '4px',
|
91
|
-
cursor: 'pointer'
|
92
|
-
},
|
93
|
-
children: 'Increment'
|
94
|
-
}
|
95
|
-
}
|
96
|
-
]
|
97
|
-
}
|
98
|
-
}
|
99
|
-
]
|
100
|
-
}
|
101
|
-
}
|
102
|
-
]
|
103
|
-
}
|
104
|
-
};
|
105
|
-
}
|
@@ -1,50 +0,0 @@
|
|
1
|
-
import { useState, useEffect } from 'frontend-hamroun';
|
2
|
-
import { Header } from './components/Header';
|
3
|
-
import { UserList } from './components/UserList';
|
4
|
-
|
5
|
-
export function App() {
|
6
|
-
const [users, setUsers] = useState([]);
|
7
|
-
const [loading, setLoading] = useState(true);
|
8
|
-
const [error, setError] = useState(null);
|
9
|
-
|
10
|
-
useEffect(() => {
|
11
|
-
// Fetch users from API
|
12
|
-
fetch('/api/users')
|
13
|
-
.then(response => {
|
14
|
-
if (!response.ok) {
|
15
|
-
throw new Error('Failed to fetch users');
|
16
|
-
}
|
17
|
-
return response.json();
|
18
|
-
})
|
19
|
-
.then(data => {
|
20
|
-
setUsers(data.data || []);
|
21
|
-
setLoading(false);
|
22
|
-
})
|
23
|
-
.catch(err => {
|
24
|
-
setError(err.message);
|
25
|
-
setLoading(false);
|
26
|
-
});
|
27
|
-
}, []);
|
28
|
-
|
29
|
-
return (
|
30
|
-
<div className="app">
|
31
|
-
<Header title="{{appName}}" />
|
32
|
-
|
33
|
-
<main>
|
34
|
-
<h2>Welcome to your Hamroun Application</h2>
|
35
|
-
|
36
|
-
{loading ? (
|
37
|
-
<p>Loading users...</p>
|
38
|
-
) : error ? (
|
39
|
-
<p className="error">Error: {error}</p>
|
40
|
-
) : (
|
41
|
-
<UserList users={users} />
|
42
|
-
)}
|
43
|
-
</main>
|
44
|
-
|
45
|
-
<footer>
|
46
|
-
<p>© {new Date().getFullYear()} {{appName}}. Created with Hamroun.</p>
|
47
|
-
</footer>
|
48
|
-
</div>
|
49
|
-
);
|
50
|
-
}
|
@@ -1,42 +0,0 @@
|
|
1
|
-
import { useState } from 'frontend-hamroun';
|
2
|
-
|
3
|
-
interface HeaderProps {
|
4
|
-
title: string;
|
5
|
-
}
|
6
|
-
|
7
|
-
export function Header({ title }: HeaderProps) {
|
8
|
-
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
9
|
-
|
10
|
-
const handleLogin = () => {
|
11
|
-
// In a real app, this would authenticate with the server
|
12
|
-
setIsLoggedIn(true);
|
13
|
-
};
|
14
|
-
|
15
|
-
const handleLogout = () => {
|
16
|
-
setIsLoggedIn(false);
|
17
|
-
};
|
18
|
-
|
19
|
-
return (
|
20
|
-
<header className="header">
|
21
|
-
<div className="logo">
|
22
|
-
<h1>{title}</h1>
|
23
|
-
</div>
|
24
|
-
|
25
|
-
<nav>
|
26
|
-
<ul>
|
27
|
-
<li><a href="/">Home</a></li>
|
28
|
-
<li><a href="/about">About</a></li>
|
29
|
-
<li><a href="/contact">Contact</a></li>
|
30
|
-
</ul>
|
31
|
-
</nav>
|
32
|
-
|
33
|
-
<div className="auth">
|
34
|
-
{isLoggedIn ? (
|
35
|
-
<button onClick={handleLogout}>Logout</button>
|
36
|
-
) : (
|
37
|
-
<button onClick={handleLogin}>Login</button>
|
38
|
-
)}
|
39
|
-
</div>
|
40
|
-
</header>
|
41
|
-
);
|
42
|
-
}
|
@@ -1,29 +0,0 @@
|
|
1
|
-
interface User {
|
2
|
-
id: string;
|
3
|
-
name: string;
|
4
|
-
email: string;
|
5
|
-
role: string;
|
6
|
-
}
|
7
|
-
|
8
|
-
interface UserListProps {
|
9
|
-
users: User[];
|
10
|
-
}
|
11
|
-
|
12
|
-
export function UserList({ users }: UserListProps) {
|
13
|
-
if (!users.length) {
|
14
|
-
return <p>No users found.</p>;
|
15
|
-
}
|
16
|
-
|
17
|
-
return (
|
18
|
-
<div className="user-list">
|
19
|
-
<h3>Users</h3>
|
20
|
-
<ul>
|
21
|
-
{users.map(user => (
|
22
|
-
<li key={user.id}>
|
23
|
-
<strong>{user.name}</strong> ({user.email}) - {user.role}
|
24
|
-
</li>
|
25
|
-
))}
|
26
|
-
</ul>
|
27
|
-
</div>
|
28
|
-
);
|
29
|
-
}
|