baraqex 2.0.3 → 2.0.4

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 (65) hide show
  1. package/dist/browser.js +11 -9
  2. package/dist/browser.js.map +2 -2
  3. package/dist/core/jsx-runtime.d.ts +1 -1
  4. package/dist/core/jsx-runtime.d.ts.map +1 -1
  5. package/dist/index.js +11 -9
  6. package/dist/index.js.map +2 -2
  7. package/package.json +1 -1
  8. package/templates/fullstack-app/README.md +62 -37
  9. package/templates/fullstack-app/build-wasm.js +80 -0
  10. package/templates/fullstack-app/build.mjs +133 -0
  11. package/templates/fullstack-app/go/main.go +53 -0
  12. package/templates/fullstack-app/index.html +16 -36
  13. package/templates/fullstack-app/package.json +41 -35
  14. package/templates/fullstack-app/postcss.config.js +6 -6
  15. package/templates/fullstack-app/public/wasm/.gitkeep +1 -0
  16. package/templates/fullstack-app/server.ts +220 -474
  17. package/templates/fullstack-app/src/App.tsx +77 -0
  18. package/templates/fullstack-app/src/main.tsx +31 -155
  19. package/templates/fullstack-app/src/pages/About.tsx +40 -0
  20. package/templates/fullstack-app/src/pages/Home.tsx +67 -0
  21. package/templates/fullstack-app/src/pages/WasmDemo.tsx +81 -0
  22. package/templates/fullstack-app/src/styles.css +12 -5
  23. package/templates/fullstack-app/tailwind.config.js +8 -11
  24. package/templates/fullstack-app/tsconfig.json +18 -18
  25. package/templates/fullstack-app/api/hello.js +0 -11
  26. package/templates/fullstack-app/api/hello.ts +0 -18
  27. package/templates/fullstack-app/api/users/[id].ts +0 -73
  28. package/templates/fullstack-app/api/users/index.ts +0 -32
  29. package/templates/fullstack-app/build/main.css +0 -874
  30. package/templates/fullstack-app/build/main.css.map +0 -7
  31. package/templates/fullstack-app/build/main.js +0 -967
  32. package/templates/fullstack-app/build/main.js.map +0 -7
  33. package/templates/fullstack-app/build.ts +0 -210
  34. package/templates/fullstack-app/process-tailwind.js +0 -45
  35. package/templates/fullstack-app/public/_redirects +0 -1
  36. package/templates/fullstack-app/public/route-handler.js +0 -47
  37. package/templates/fullstack-app/public/spa-fix.html +0 -17
  38. package/templates/fullstack-app/public/styles.css +0 -975
  39. package/templates/fullstack-app/public/tailwind.css +0 -15
  40. package/templates/fullstack-app/server.js +0 -267
  41. package/templates/fullstack-app/src/README.md +0 -55
  42. package/templates/fullstack-app/src/client.js +0 -87
  43. package/templates/fullstack-app/src/components/ClientHome.tsx +0 -0
  44. package/templates/fullstack-app/src/components/ErrorBoundary.tsx +0 -36
  45. package/templates/fullstack-app/src/components/Layout.tsx +0 -42
  46. package/templates/fullstack-app/src/components/StateDemo.tsx +0 -207
  47. package/templates/fullstack-app/src/components/UserList.tsx +0 -44
  48. package/templates/fullstack-app/src/config.ts +0 -42
  49. package/templates/fullstack-app/src/data/api.ts +0 -206
  50. package/templates/fullstack-app/src/middleware.ts +0 -28
  51. package/templates/fullstack-app/src/pages/404.tsx +0 -28
  52. package/templates/fullstack-app/src/pages/[id].tsx +0 -0
  53. package/templates/fullstack-app/src/pages/_app.tsx +0 -11
  54. package/templates/fullstack-app/src/pages/_document.tsx +0 -25
  55. package/templates/fullstack-app/src/pages/_error.tsx +0 -45
  56. package/templates/fullstack-app/src/pages/about/index.tsx +0 -67
  57. package/templates/fullstack-app/src/pages/about.tsx +0 -71
  58. package/templates/fullstack-app/src/pages/api/users/[id].ts +0 -73
  59. package/templates/fullstack-app/src/pages/api/users/index.ts +0 -43
  60. package/templates/fullstack-app/src/pages/index.tsx +0 -110
  61. package/templates/fullstack-app/src/pages/users/[id].tsx +0 -153
  62. package/templates/fullstack-app/src/pages/users.tsx +0 -60
  63. package/templates/fullstack-app/src/pages/wasm-demo.tsx +0 -1
  64. package/templates/fullstack-app/src/router.ts +0 -255
  65. package/templates/fullstack-app/vite.config.js +0 -87
@@ -1,15 +0,0 @@
1
- /* All Tailwind directives */
2
- @tailwind base;
3
- @tailwind components;
4
- @tailwind utilities;
5
-
6
- /* Custom styles */
7
- body {
8
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
9
- line-height: 1.6;
10
- }
11
-
12
- /* Any custom utility classes can go here */
13
- .custom-container {
14
- @apply max-w-4xl mx-auto px-4 py-8;
15
- }
@@ -1,267 +0,0 @@
1
- import express from 'express';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import fs from 'fs';
5
- import dotenv from 'dotenv';
6
- import { createServer } from 'http';
7
- import { Server as SocketServer } from 'socket.io';
8
- import compression from 'compression';
9
- import cors from 'cors';
10
-
11
- // Load environment variables
12
- dotenv.config();
13
-
14
- // Get __dirname equivalent in ESM
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = path.dirname(__filename);
17
-
18
- // Create Express app
19
- const app = express();
20
- const PORT = process.env.PORT || 3000;
21
- const httpServer = createServer(app);
22
-
23
- // Create socket.io server
24
- const io = new SocketServer(httpServer, {
25
- cors: {
26
- origin: process.env.NODE_ENV === 'production' ? false : '*',
27
- methods: ['GET', 'POST']
28
- }
29
- });
30
-
31
- // Middleware setup
32
- app.use(express.json());
33
- app.use(express.urlencoded({ extended: true }));
34
- app.use(compression()); // Add compression for better performance
35
- app.use(cors()); // Enable CORS for API access
36
-
37
- // Add request logging in development mode
38
- if (process.env.NODE_ENV !== 'production') {
39
- app.use((req, res, next) => {
40
- console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
41
- next();
42
- });
43
- }
44
-
45
- // For production, serve the built files
46
- if (process.env.NODE_ENV === 'production') {
47
- app.use(express.static(path.join(__dirname, 'dist')));
48
- } else {
49
- // In development, we'll let Vite handle the frontend
50
- console.log('Running in development mode - Vite handles the frontend');
51
- }
52
-
53
- // Global in-memory store for demo purposes
54
- // In a real app, you would use a database
55
- const store = {
56
- users: [
57
- { id: 1, name: 'User 1', email: 'user1@example.com' },
58
- { id: 2, name: 'User 2', email: 'user2@example.com' },
59
- { id: 3, name: 'User 3', email: 'user3@example.com' }
60
- ],
61
- posts: [
62
- { id: 1, title: 'Post 1', content: 'Content for post 1', authorId: 1 },
63
- { id: 2, title: 'Post 2', content: 'Content for post 2', authorId: 2 },
64
- { id: 3, title: 'Post 3', content: 'Content for post 3', authorId: 1 }
65
- ]
66
- };
67
-
68
- // Core API routes (available without file-based routing)
69
- app.get('/api/hello', (req, res) => {
70
- res.json({
71
- message: "Hello from the API!",
72
- time: new Date().toISOString(),
73
- features: [
74
- "Server-side rendering",
75
- "API routes",
76
- "Component-based UI",
77
- "React-like development experience",
78
- "WebSocket integration",
79
- "Database connectivity",
80
- "Authentication"
81
- ]
82
- });
83
- });
84
-
85
- // REST API endpoints for store data
86
- app.get('/api/users', (req, res) => {
87
- res.json(store.users);
88
- });
89
-
90
- app.get('/api/users/:id', (req, res) => {
91
- const user = store.users.find(u => u.id === parseInt(req.params.id));
92
- if (user) {
93
- res.json(user);
94
- } else {
95
- res.status(404).json({ error: 'User not found' });
96
- }
97
- });
98
-
99
- app.get('/api/posts', (req, res) => {
100
- const { authorId } = req.query;
101
-
102
- if (authorId) {
103
- const filteredPosts = store.posts.filter(p => p.authorId === parseInt(authorId));
104
- return res.json(filteredPosts);
105
- }
106
-
107
- res.json(store.posts);
108
- });
109
-
110
- // Improved dynamic API route loading with better error handling
111
- const apiDir = path.join(__dirname, 'api');
112
- if (fs.existsSync(apiDir)) {
113
- console.log('Loading API routes from directory...');
114
-
115
- // Function to map file paths to API routes
116
- const registerApiRoutes = async (dir, routePrefix = '') => {
117
- try {
118
- const entries = fs.readdirSync(dir, { withFileTypes: true });
119
-
120
- for (const entry of entries) {
121
- const fullPath = path.join(dir, entry.name);
122
-
123
- if (entry.isDirectory()) {
124
- // Process directories recursively
125
- await registerApiRoutes(fullPath, `${routePrefix}/${entry.name}`);
126
- } else if (entry.name.endsWith('.js') || entry.name.endsWith('.ts')) {
127
- // Process API file
128
- try {
129
- const fileName = entry.name.replace(/\.[^/.]+$/, ""); // Remove extension
130
- const routePath = fileName === 'index'
131
- ? routePrefix
132
- : fileName.startsWith('[') && fileName.endsWith(']')
133
- ? `${routePrefix}/:${fileName.slice(1, -1)}` // Convert [param] to :param
134
- : `${routePrefix}/${fileName}`;
135
-
136
- // Import the route module
137
- const module = await import(`file://${fullPath}`);
138
-
139
- // Register handlers for HTTP methods
140
- ['get', 'post', 'put', 'delete', 'patch'].forEach(method => {
141
- if (typeof module[method] === 'function') {
142
- console.log(` Registered ${method.toUpperCase()} ${routePath}`);
143
- app[method](`/api${routePath}`, module[method]);
144
- }
145
- });
146
-
147
- // Special case for 'delete' which might be named 'delete_' in some files
148
- if (typeof module['delete_'] === 'function') {
149
- console.log(` Registered DELETE ${routePath}`);
150
- app.delete(`/api${routePath}`, module['delete_']);
151
- }
152
- } catch (err) {
153
- console.error(`Error loading API route ${fullPath}:`, err);
154
- }
155
- }
156
- }
157
- } catch (err) {
158
- console.error(`Error reading directory ${dir}:`, err);
159
- }
160
- };
161
-
162
- // Start registering API routes
163
- registerApiRoutes(apiDir).catch(err => {
164
- console.error('Error loading API routes:', err);
165
- });
166
- } else {
167
- console.log('API directory not found, skipping API route loading');
168
- }
169
-
170
- // WebSocket setup
171
- io.on('connection', (socket) => {
172
- console.log('Client connected:', socket.id);
173
-
174
- // Send welcome message
175
- socket.emit('welcome', {
176
- message: 'Connected to WebSocket server',
177
- time: new Date().toISOString()
178
- });
179
-
180
- // Handle client messages
181
- socket.on('message', (data) => {
182
- console.log('Received message:', data);
183
- // Broadcast to all clients
184
- io.emit('broadcast', {
185
- from: socket.id,
186
- data,
187
- time: new Date().toISOString()
188
- });
189
- });
190
-
191
- // Handle disconnect
192
- socket.on('disconnect', () => {
193
- console.log('Client disconnected:', socket.id);
194
- });
195
- });
196
-
197
- // In production or if using SSR, handle all routes
198
- app.get('*', (req, res, next) => {
199
- // Skip API routes
200
- if (req.path.startsWith('/api/')) {
201
- return next();
202
- }
203
-
204
- // In production, serve the index.html
205
- if (process.env.NODE_ENV === 'production') {
206
- const indexPath = path.join(__dirname, 'dist', 'index.html');
207
- if (fs.existsSync(indexPath)) {
208
- try {
209
- // Read the index.html file
210
- let html = fs.readFileSync(indexPath, 'utf8');
211
-
212
- // Create initial state for client hydration
213
- const initialState = {
214
- route: req.path,
215
- timestamp: new Date().toISOString()
216
- };
217
-
218
- // Inject initial state for hydration
219
- html = html.replace(
220
- '</head>',
221
- `<script>window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};</script></head>`
222
- );
223
-
224
- res.send(html);
225
- } catch (error) {
226
- console.error('Error serving HTML:', error);
227
- res.status(500).send('Server Error');
228
- }
229
- } else {
230
- res.status(404).send('Not found');
231
- }
232
- } else {
233
- // In development, use Vite's dev server
234
- // Instead of redirecting, proxy the request to maintain the URL path
235
- // This allows Vite to handle the route properly
236
- const viteDevServerUrl = 'http://localhost:5173';
237
-
238
- // Tell the client which route to handle via response headers
239
- res.setHeader('x-original-route', req.path);
240
-
241
- // Forward the request to the Vite dev server with the original path
242
- res.redirect(302, `${viteDevServerUrl}${req.path}`);
243
-
244
- // Note: If the above still causes 404s, you can try this alternative
245
- // res.redirect(302, `${viteDevServerUrl}/?_path=${encodeURIComponent(req.path)}`);
246
- }
247
- });
248
-
249
- // Error handling middleware
250
- app.use((err, req, res, next) => {
251
- console.error('Server error:', err);
252
- res.status(500).json({
253
- error: process.env.NODE_ENV === 'production'
254
- ? 'Internal server error'
255
- : err.message
256
- });
257
- });
258
-
259
- // Start server
260
- httpServer.listen(PORT, () => {
261
- console.log(`Server running on http://localhost:${PORT}`);
262
-
263
- if (process.env.NODE_ENV !== 'production') {
264
- console.log(`Frontend development server will run on http://localhost:5173`);
265
- console.log(`Run 'npm run dev' to start both servers`);
266
- }
267
- });
@@ -1,55 +0,0 @@
1
- # Frontend Hamroun Fullstack Template
2
-
3
- This template uses a file-system based routing system similar to Next.js. Here's how to use it:
4
-
5
- ## Creating New Pages
6
-
7
- 1. Add new pages in the `src/pages` directory
8
- 2. File names become routes automatically:
9
- - `src/pages/index.tsx` → `/`
10
- - `src/pages/about.tsx` → `/about`
11
- - `src/pages/users/[id].tsx` → `/users/:id`
12
-
13
- ## Page Structure
14
-
15
- Each page should follow this structure:
16
-
17
- ```tsx
18
- import { jsx } from 'frontend-hamroun';
19
- import Layout from '../components/Layout';
20
-
21
- const YourPage = ({ initialState }) => (
22
- <Layout title="Your Page Title">
23
- {/* Your content here */}
24
- </Layout>
25
- );
26
-
27
- // Optional: Add data fetching
28
- YourPage.getInitialData = async (path) => {
29
- // Fetch any data your page needs
30
- return {
31
- yourData: await fetchSomething()
32
- };
33
- };
34
-
35
- export default YourPage;
36
- ```
37
-
38
- ## Data Fetching
39
-
40
- Use the API utilities in `src/data/api.ts` to fetch data in a consistent way:
41
-
42
- ```tsx
43
- import { UserApi } from '../data/api';
44
-
45
- // In your getInitialData method:
46
- const users = await UserApi.getAll();
47
- ```
48
-
49
- ## Components
50
-
51
- Store reusable components in the `src/components` directory and import them in your pages.
52
-
53
- ## Navigation
54
-
55
- Client-side navigation is handled automatically. Just use regular `<a href="...">` links.
@@ -1,87 +0,0 @@
1
- import { hydrate, createElement, jsx } from 'frontend-hamroun';
2
-
3
- // Add global jsx for compatibility
4
- window.jsx = jsx;
5
- window.createElement = createElement;
6
-
7
- // Get the initial state from the server (if available)
8
- const initialState = window.__INITIAL_STATE__ || {
9
- route: window.location.pathname
10
- };
11
-
12
- // Dynamically import the right page component based on the route
13
- async function loadAndHydrateComponent() {
14
- try {
15
- const path = initialState.route || '/';
16
- const normalizedPath = path === '/' ? '/index' : path;
17
-
18
- console.log(`Loading component for path: ${normalizedPath}`);
19
-
20
- // Try to import the page component
21
- const module = await import(`./pages${normalizedPath}.js`).catch(() =>
22
- import(`./pages${normalizedPath}/index.js`)).catch(() => {
23
- console.warn(`No component found for ${normalizedPath}, falling back to index`);
24
- return import('./pages/index.js');
25
- });
26
-
27
- const PageComponent = module.default;
28
-
29
- if (!PageComponent) {
30
- throw new Error(`No default export found in module for ${normalizedPath}`);
31
- }
32
-
33
- // Find the root element - try both 'root' and 'app' IDs
34
- const rootElement = document.getElementById('root') || document.getElementById('app');
35
-
36
- if (!rootElement) {
37
- throw new Error('Could not find root element with id "root" or "app"');
38
- }
39
-
40
- // Hydrate the application
41
- hydrate(jsx(PageComponent, { initialState }), rootElement);
42
- console.log('Hydration complete');
43
-
44
- // Add navigation event listeners if using client-side routing
45
- document.addEventListener('click', handleLinkClicks);
46
- window.addEventListener('popstate', handleRouteChange);
47
-
48
- return true;
49
- } catch (error) {
50
- console.error('Error during hydration:', error);
51
- return false;
52
- }
53
- }
54
-
55
- // Handle client-side navigation for links
56
- function handleLinkClicks(event) {
57
- // Only handle links within our app
58
- if (event.target.tagName === 'A' &&
59
- event.target.origin === window.location.origin &&
60
- !event.target.hasAttribute('external')) {
61
-
62
- event.preventDefault();
63
- const href = event.target.getAttribute('href');
64
-
65
- // Update history and load the new component
66
- window.history.pushState({}, '', href);
67
- handleRouteChange();
68
- }
69
- }
70
-
71
- // Handle route changes (back/forward navigation or pushState)
72
- function handleRouteChange() {
73
- // Update the initialState with the new route
74
- initialState.route = window.location.pathname;
75
-
76
- // Load and hydrate the new component
77
- loadAndHydrateComponent().catch(err => {
78
- console.error('Failed to load component after route change:', err);
79
- });
80
- }
81
-
82
- // Wait for DOM to be ready before hydrating
83
- if (document.readyState === 'loading') {
84
- document.addEventListener('DOMContentLoaded', loadAndHydrateComponent);
85
- } else {
86
- loadAndHydrateComponent();
87
- }
@@ -1,36 +0,0 @@
1
- import { jsx, useState, useEffect, useErrorBoundary } from 'frontend-hamroun';
2
-
3
- interface ErrorBoundaryProps {
4
- children: any;
5
- fallback?: (error: Error, reset: () => void) => any;
6
- }
7
-
8
- export function ErrorBoundary({ children, fallback }: ErrorBoundaryProps) {
9
- const [error, resetError] = useErrorBoundary();
10
-
11
- if (error) {
12
- if (fallback) {
13
- return fallback(error, resetError);
14
- }
15
-
16
- return (
17
- <div className="error-boundary p-4 border border-red-500 rounded bg-red-50">
18
- <h3 className="text-lg font-medium text-red-800 mb-2">Something went wrong</h3>
19
- <p className="text-red-600 mb-2">{error.message}</p>
20
- <button
21
- onClick={resetError}
22
- className="px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700"
23
- >
24
- Try again
25
- </button>
26
- {process.env.NODE_ENV !== 'production' && (
27
- <pre className="mt-3 text-xs overflow-auto p-2 bg-gray-100">
28
- {error.stack}
29
- </pre>
30
- )}
31
- </div>
32
- );
33
- }
34
-
35
- return children;
36
- }
@@ -1,42 +0,0 @@
1
- import { jsx } from 'frontend-hamroun';
2
-
3
- interface LayoutProps {
4
- children: any;
5
- title?: string;
6
- }
7
-
8
- export default function Layout({ children, title = 'Frontend Hamroun App' }: LayoutProps) {
9
- return (
10
- <div className="min-h-screen flex flex-col bg-gray-50">
11
- <header className="bg-blue-600 text-white">
12
- <div className="container mx-auto px-4 py-4 flex justify-between items-center">
13
- <h1 className="text-xl font-bold">
14
- <a href="/" className="hover:text-blue-100">
15
- {title}
16
- </a>
17
- </h1>
18
-
19
- <nav>
20
- <ul className="flex space-x-6">
21
- <li><a href="/" className="hover:text-blue-100">Home</a></li>
22
- <li><a href="/about" className="hover:text-blue-100">About</a></li>
23
- {/* WASM demo link removed */}
24
- </ul>
25
- </nav>
26
- </div>
27
- </header>
28
-
29
- <main className="flex-grow container mx-auto px-4 py-8">
30
- {children}
31
- </main>
32
-
33
- <footer className="bg-gray-800 text-white">
34
- <div className="container mx-auto px-4 py-6">
35
- <p className="text-center text-gray-400">
36
- &copy; {new Date().getFullYear()} Frontend Hamroun App. All rights reserved.
37
- </p>
38
- </div>
39
- </footer>
40
- </div>
41
- );
42
- }