baraqex 1.0.49 ā 1.0.51
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/dist/index.js +189 -251
- package/dist/index.js.map +4 -4
- package/dist/server.js +849 -1282
- package/dist/server.js.map +4 -4
- package/package.json +1 -1
- package/templates/basic-app/.eslintignore +5 -0
- package/templates/basic-app/.eslintrc.json +25 -0
- package/templates/basic-app/README.md +166 -0
- package/templates/basic-app/esbuild.config.js +37 -0
- package/templates/basic-app/favicon.ico +0 -0
- package/templates/basic-app/index.html +13 -0
- package/templates/basic-app/main.css +3 -0
- package/templates/basic-app/package-lock.json +6856 -0
- package/templates/basic-app/package.json +31 -20
- package/templates/basic-app/postcss.config.js +6 -0
- package/templates/basic-app/public/logo.png +0 -0
- package/templates/basic-app/src/main.css +77 -0
- package/templates/basic-app/src/main.tsx +465 -0
- package/templates/basic-app/tailwind.config.js +38 -0
- package/templates/basic-app/tsconfig.json +13 -0
- package/templates/basic-app/vite.config.ts +8 -0
- package/templates/fullstack-template/package.json +5 -23
- package/templates/fullstack-template/server.js +11 -572
- package/templates/basic-app/public/index.html +0 -13
- package/templates/basic-app/public/styles.css +0 -158
- package/templates/basic-app/server.js +0 -15
- package/templates/basic-app/src/App.jsx +0 -68
- package/templates/basic-template/README.md +0 -24
- package/templates/basic-template/package.json +0 -13
- package/templates/basic-template/server.js +0 -36
- package/templates/fullstack-template/package-lock.json +0 -1895
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fullstack-app",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "A fullstack application built with Baraqex",
|
|
5
4
|
"type": "module",
|
|
6
|
-
"main": "server.js",
|
|
7
5
|
"scripts": {
|
|
8
6
|
"dev": "node server.js",
|
|
9
|
-
"start": "
|
|
10
|
-
"build": "echo
|
|
11
|
-
"test": "echo 'No tests specified' && exit 0"
|
|
7
|
+
"start": "node server.js",
|
|
8
|
+
"build": "echo \"No build step required\""
|
|
12
9
|
},
|
|
13
10
|
"dependencies": {
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"frontend-hamroun": "latest"
|
|
18
|
-
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"@types/cors": "^2.8.13",
|
|
21
|
-
"@types/express": "^4.17.17"
|
|
22
|
-
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"baraqex",
|
|
25
|
-
"fullstack",
|
|
26
|
-
"express",
|
|
27
|
-
"api",
|
|
28
|
-
"ssr"
|
|
29
|
-
],
|
|
30
|
-
"author": "",
|
|
31
|
-
"license": "MIT"
|
|
11
|
+
"frontend-hamroun": "latest",
|
|
12
|
+
"baraqex": "latest"
|
|
13
|
+
}
|
|
32
14
|
}
|
|
@@ -1,577 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import cors from 'cors';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
1
|
+
import { createDevServer } from 'baraqex/server';
|
|
6
2
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
async function startServer() {
|
|
11
|
-
try {
|
|
12
|
-
console.log('š Starting Baraqex fullstack server...');
|
|
13
|
-
|
|
14
|
-
const app = express();
|
|
15
|
-
const port = process.env.PORT || 3000;
|
|
16
|
-
|
|
17
|
-
// Basic middleware
|
|
18
|
-
app.use(express.json());
|
|
19
|
-
app.use(express.urlencoded({ extended: true }));
|
|
20
|
-
app.use(cors());
|
|
21
|
-
|
|
22
|
-
// Request logging
|
|
23
|
-
app.use((req, res, next) => {
|
|
24
|
-
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
|
25
|
-
next();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Serve static files from public directory
|
|
29
|
-
const publicDir = path.join(process.cwd(), 'public');
|
|
30
|
-
if (fs.existsSync(publicDir)) {
|
|
31
|
-
app.use(express.static(publicDir));
|
|
32
|
-
console.log('š Serving static files from /public');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Auto-discover and register API routes
|
|
36
|
-
await setupApiRoutes(app);
|
|
37
|
-
|
|
38
|
-
// Auto-discover and register page routes (SSR)
|
|
39
|
-
await setupPageRoutes(app);
|
|
40
|
-
|
|
41
|
-
// Root route fallback
|
|
42
|
-
app.get('/', async (req, res) => {
|
|
43
|
-
try {
|
|
44
|
-
// Try to render the index page component if it exists
|
|
45
|
-
const indexPagePath = path.join(process.cwd(), 'src/pages/index.js');
|
|
46
|
-
if (fs.existsSync(indexPagePath)) {
|
|
47
|
-
const pageHtml = await renderPageComponent(indexPagePath, {
|
|
48
|
-
path: '/',
|
|
49
|
-
query: req.query
|
|
50
|
-
});
|
|
51
|
-
res.send(pageHtml);
|
|
52
|
-
} else {
|
|
53
|
-
// Fallback to basic HTML
|
|
54
|
-
res.send(generateWelcomePage());
|
|
55
|
-
}
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error('Error rendering root page:', error);
|
|
58
|
-
res.status(500).send(generateErrorPage(500, 'Server Error'));
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// 404 handler
|
|
63
|
-
app.use((req, res) => {
|
|
64
|
-
res.status(404).json({
|
|
65
|
-
error: 'Not Found',
|
|
66
|
-
message: `Route ${req.method} ${req.path} not found`,
|
|
67
|
-
timestamp: new Date().toISOString()
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Error handler
|
|
72
|
-
app.use((err, req, res, next) => {
|
|
73
|
-
console.error('Server Error:', err);
|
|
74
|
-
res.status(500).json({
|
|
75
|
-
error: 'Internal Server Error',
|
|
76
|
-
message: process.env.NODE_ENV === 'production' ? 'Something went wrong' : err.message,
|
|
77
|
-
timestamp: new Date().toISOString()
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Start server
|
|
82
|
-
app.listen(port, () => {
|
|
83
|
-
console.log('ā
Fullstack server is running!');
|
|
84
|
-
console.log(`š Server: http://localhost:${port}`);
|
|
85
|
-
console.log('š API routes available at /api/*');
|
|
86
|
-
console.log('š Pages available at /*');
|
|
87
|
-
console.log('š Static files served from /public');
|
|
88
|
-
console.log('\nš Quick links:');
|
|
89
|
-
console.log(` - Homepage: http://localhost:${port}`);
|
|
90
|
-
console.log(` - API Hello: http://localhost:${port}/api/hello`);
|
|
91
|
-
console.log(` - API Users: http://localhost:${port}/api/users`);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.error('ā Failed to start server:', error.message);
|
|
96
|
-
|
|
97
|
-
if (error.code === 'MODULE_NOT_FOUND') {
|
|
98
|
-
console.error('\nš” Please install dependencies: npm install express cors');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Auto-discover API routes in src/api
|
|
106
|
-
async function setupApiRoutes(app) {
|
|
107
|
-
const apiDir = path.join(process.cwd(), 'src/api');
|
|
108
|
-
|
|
109
|
-
if (!fs.existsSync(apiDir)) {
|
|
110
|
-
console.log('š Creating src/api directory...');
|
|
111
|
-
fs.mkdirSync(apiDir, { recursive: true });
|
|
112
|
-
|
|
113
|
-
// Create example API files
|
|
114
|
-
await createExampleApiFiles(apiDir);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
console.log('š Scanning for API routes...');
|
|
118
|
-
await scanApiDirectory(app, apiDir, '/api');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Recursively scan API directory and register routes
|
|
122
|
-
async function scanApiDirectory(app, dirPath, routePrefix) {
|
|
123
|
-
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
124
|
-
|
|
125
|
-
for (const entry of entries) {
|
|
126
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
127
|
-
|
|
128
|
-
if (entry.isDirectory()) {
|
|
129
|
-
await scanApiDirectory(app, fullPath, `${routePrefix}/${entry.name}`);
|
|
130
|
-
} else if (entry.name.endsWith('.js')) {
|
|
131
|
-
const routePath = getApiRoutePath(entry.name, routePrefix);
|
|
132
|
-
await registerApiRoute(app, fullPath, routePath);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Convert filename to route path
|
|
138
|
-
function getApiRoutePath(filename, routePrefix) {
|
|
139
|
-
const baseName = path.basename(filename, '.js');
|
|
140
|
-
|
|
141
|
-
if (baseName === 'index') {
|
|
142
|
-
return routePrefix === '/api' ? '/api' : routePrefix;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Handle dynamic routes [param]
|
|
146
|
-
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
147
|
-
if (paramMatch) {
|
|
148
|
-
return `${routePrefix}/:${paramMatch[1]}`;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return `${routePrefix}/${baseName}`;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Register API route handlers
|
|
155
|
-
async function registerApiRoute(app, filePath, routePath) {
|
|
156
|
-
try {
|
|
157
|
-
// Import the API module with cache busting
|
|
158
|
-
const apiModule = await import(`${filePath}?t=${Date.now()}`);
|
|
159
|
-
|
|
160
|
-
const methods = ['get', 'post', 'put', 'delete', 'patch', 'options'];
|
|
161
|
-
let registeredMethods = [];
|
|
162
|
-
|
|
163
|
-
for (const method of methods) {
|
|
164
|
-
if (typeof apiModule[method] === 'function') {
|
|
165
|
-
app[method](routePath, async (req, res, next) => {
|
|
166
|
-
try {
|
|
167
|
-
await apiModule[method](req, res, next);
|
|
168
|
-
} catch (error) {
|
|
169
|
-
console.error(`Error in ${method.toUpperCase()} ${routePath}:`, error);
|
|
170
|
-
next(error);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
registeredMethods.push(method.toUpperCase());
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (registeredMethods.length > 0) {
|
|
178
|
-
console.log(`š” API: ${routePath} [${registeredMethods.join(', ')}]`);
|
|
179
|
-
}
|
|
180
|
-
} catch (error) {
|
|
181
|
-
console.error(`Error registering API route ${routePath}:`, error.message);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Setup page routes for SSR
|
|
186
|
-
async function setupPageRoutes(app) {
|
|
187
|
-
const pagesDir = path.join(process.cwd(), 'src/pages');
|
|
188
|
-
|
|
189
|
-
if (!fs.existsSync(pagesDir)) {
|
|
190
|
-
console.log('š Creating src/pages directory...');
|
|
191
|
-
fs.mkdirSync(pagesDir, { recursive: true });
|
|
192
|
-
|
|
193
|
-
// Create example page
|
|
194
|
-
await createExamplePageFile(pagesDir);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
console.log('š Scanning for page routes...');
|
|
198
|
-
await scanPagesDirectory(app, pagesDir, '');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Scan pages directory for SSR routes
|
|
202
|
-
async function scanPagesDirectory(app, dirPath, routePrefix) {
|
|
203
|
-
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
204
|
-
|
|
205
|
-
for (const entry of entries) {
|
|
206
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
207
|
-
|
|
208
|
-
if (entry.isDirectory()) {
|
|
209
|
-
await scanPagesDirectory(app, fullPath, `${routePrefix}/${entry.name}`);
|
|
210
|
-
} else if (entry.name.endsWith('.js')) {
|
|
211
|
-
const routePath = getPageRoutePath(entry.name, routePrefix);
|
|
212
|
-
await registerPageRoute(app, fullPath, routePath);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Convert page filename to route path
|
|
218
|
-
function getPageRoutePath(filename, routePrefix) {
|
|
219
|
-
const baseName = path.basename(filename, '.js');
|
|
220
|
-
|
|
221
|
-
if (baseName === 'index') {
|
|
222
|
-
return routePrefix || '/';
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Handle dynamic routes [param]
|
|
226
|
-
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
227
|
-
if (paramMatch) {
|
|
228
|
-
return `${routePrefix}/:${paramMatch[1]}`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return `${routePrefix}/${baseName}`;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Register page route for SSR
|
|
235
|
-
async function registerPageRoute(app, filePath, routePath) {
|
|
236
|
-
try {
|
|
237
|
-
// Only register if not root route (we handle that separately)
|
|
238
|
-
if (routePath !== '/') {
|
|
239
|
-
app.get(routePath, async (req, res) => {
|
|
240
|
-
try {
|
|
241
|
-
const pageHtml = await renderPageComponent(filePath, {
|
|
242
|
-
path: req.path,
|
|
243
|
-
query: req.query,
|
|
244
|
-
params: req.params
|
|
245
|
-
});
|
|
246
|
-
res.send(pageHtml);
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error(`Error rendering page ${routePath}:`, error);
|
|
249
|
-
res.status(500).send(generateErrorPage(500, 'Page rendering error'));
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
console.log(`š Page: ${routePath}`);
|
|
254
|
-
}
|
|
255
|
-
} catch (error) {
|
|
256
|
-
console.error(`Error registering page route ${routePath}:`, error.message);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Render page component to HTML
|
|
261
|
-
async function renderPageComponent(filePath, props) {
|
|
262
|
-
try {
|
|
263
|
-
const pageModule = await import(`${filePath}?t=${Date.now()}`);
|
|
264
|
-
const PageComponent = pageModule.default;
|
|
265
|
-
|
|
266
|
-
if (typeof PageComponent !== 'function') {
|
|
267
|
-
throw new Error('Page component must export a default function');
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Simple JSX to HTML conversion
|
|
271
|
-
const componentResult = PageComponent(props);
|
|
272
|
-
let htmlContent = '';
|
|
273
|
-
|
|
274
|
-
if (typeof componentResult === 'string') {
|
|
275
|
-
htmlContent = componentResult;
|
|
276
|
-
} else {
|
|
277
|
-
// Convert JSX-like structure to HTML
|
|
278
|
-
htmlContent = jsxToHtml(componentResult);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Get page metadata
|
|
282
|
-
const title = PageComponent.title || 'Baraqex App';
|
|
283
|
-
const description = PageComponent.description || 'A Baraqex fullstack application';
|
|
284
|
-
|
|
285
|
-
return generateDocument(htmlContent, { title, description, props });
|
|
286
|
-
|
|
287
|
-
} catch (error) {
|
|
288
|
-
console.error('Error rendering page component:', error);
|
|
289
|
-
return generateErrorPage(500, 'Failed to render page component');
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Simple JSX to HTML converter
|
|
294
|
-
function jsxToHtml(jsx) {
|
|
295
|
-
if (typeof jsx === 'string') {
|
|
296
|
-
return jsx;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (typeof jsx === 'number') {
|
|
300
|
-
return jsx.toString();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (jsx === null || jsx === undefined || jsx === false) {
|
|
304
|
-
return '';
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (Array.isArray(jsx)) {
|
|
308
|
-
return jsx.map(item => jsxToHtml(item)).join('');
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (jsx && typeof jsx === 'object') {
|
|
312
|
-
const { type, props } = jsx;
|
|
313
|
-
|
|
314
|
-
if (!type) return '';
|
|
315
|
-
|
|
316
|
-
const { children, ...attrs } = props || {};
|
|
317
|
-
|
|
318
|
-
// Convert attributes to HTML
|
|
319
|
-
const attrStr = Object.entries(attrs)
|
|
320
|
-
.filter(([key, value]) => value != null && key !== 'children')
|
|
321
|
-
.map(([key, value]) => {
|
|
322
|
-
// Handle special attributes
|
|
323
|
-
if (key === 'className') key = 'class';
|
|
324
|
-
if (key === 'htmlFor') key = 'for';
|
|
325
|
-
if (key.startsWith('on')) return ''; // Skip event handlers
|
|
326
|
-
if (typeof value === 'object') {
|
|
327
|
-
// Handle style objects
|
|
328
|
-
if (key === 'style') {
|
|
329
|
-
const styleStr = Object.entries(value)
|
|
330
|
-
.map(([prop, val]) => `${prop.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${val}`)
|
|
331
|
-
.join('; ');
|
|
332
|
-
return `style="${styleStr}"`;
|
|
333
|
-
}
|
|
334
|
-
return '';
|
|
335
|
-
}
|
|
336
|
-
return `${key}="${String(value)}"`;
|
|
337
|
-
})
|
|
338
|
-
.filter(Boolean)
|
|
339
|
-
.join(' ');
|
|
340
|
-
|
|
341
|
-
const attrString = attrStr ? ` ${attrStr}` : '';
|
|
342
|
-
|
|
343
|
-
// Handle self-closing tags
|
|
344
|
-
if (['img', 'br', 'hr', 'input', 'meta', 'link'].includes(type)) {
|
|
345
|
-
return `<${type}${attrString} />`;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const childrenHtml = children ? jsxToHtml(children) : '';
|
|
349
|
-
return `<${type}${attrString}>${childrenHtml}</${type}>`;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return String(jsx);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Create example API files
|
|
356
|
-
async function createExampleApiFiles(apiDir) {
|
|
357
|
-
// Create hello.js
|
|
358
|
-
const helloApiContent = `// Example API endpoint: GET/POST /api/hello
|
|
359
|
-
|
|
360
|
-
export async function get(req, res) {
|
|
361
|
-
res.json({
|
|
362
|
-
message: 'Hello from Baraqex API!',
|
|
363
|
-
timestamp: new Date().toISOString(),
|
|
364
|
-
method: 'GET',
|
|
365
|
-
path: req.path
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
export async function post(req, res) {
|
|
370
|
-
const { name = 'World' } = req.body;
|
|
371
|
-
|
|
372
|
-
res.json({
|
|
373
|
-
message: \`Hello \${name} from Baraqex API!\`,
|
|
374
|
-
timestamp: new Date().toISOString(),
|
|
375
|
-
method: 'POST',
|
|
376
|
-
body: req.body
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
`;
|
|
380
|
-
|
|
381
|
-
// Create users/index.js
|
|
382
|
-
const usersDir = path.join(apiDir, 'users');
|
|
383
|
-
fs.mkdirSync(usersDir, { recursive: true });
|
|
384
|
-
|
|
385
|
-
const usersApiContent = `// Example API endpoint: /api/users
|
|
386
|
-
|
|
387
|
-
const users = [
|
|
388
|
-
{ id: 1, name: 'John Doe', email: 'john@example.com' },
|
|
389
|
-
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
|
|
390
|
-
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com' }
|
|
391
|
-
];
|
|
392
|
-
|
|
393
|
-
export async function get(req, res) {
|
|
394
|
-
res.json({
|
|
395
|
-
success: true,
|
|
396
|
-
data: users,
|
|
397
|
-
count: users.length
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
export async function post(req, res) {
|
|
402
|
-
const { name, email } = req.body;
|
|
403
|
-
|
|
404
|
-
if (!name || !email) {
|
|
405
|
-
return res.status(400).json({
|
|
406
|
-
success: false,
|
|
407
|
-
message: 'Name and email are required'
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const newUser = {
|
|
412
|
-
id: users.length + 1,
|
|
413
|
-
name,
|
|
414
|
-
email
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
users.push(newUser);
|
|
418
|
-
|
|
419
|
-
res.status(201).json({
|
|
420
|
-
success: true,
|
|
421
|
-
message: 'User created successfully',
|
|
422
|
-
data: newUser
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
`;
|
|
426
|
-
|
|
427
|
-
fs.writeFileSync(path.join(apiDir, 'hello.js'), helloApiContent);
|
|
428
|
-
fs.writeFileSync(path.join(usersDir, 'index.js'), usersApiContent);
|
|
429
|
-
|
|
430
|
-
console.log('š Created example API files');
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Create example page file
|
|
434
|
-
async function createExamplePageFile(pagesDir) {
|
|
435
|
-
// Use the existing index.js content but ensure it's properly formatted
|
|
436
|
-
const indexPagePath = path.join(pagesDir, 'index.js');
|
|
437
|
-
if (!fs.existsSync(indexPagePath)) {
|
|
438
|
-
// Copy from the existing file or create a new one
|
|
439
|
-
const existingIndexPath = path.join(process.cwd(), 'src/pages/index.js');
|
|
440
|
-
if (fs.existsSync(existingIndexPath)) {
|
|
441
|
-
fs.copyFileSync(existingIndexPath, indexPagePath);
|
|
442
|
-
}
|
|
443
|
-
console.log('š Page component ready at src/pages/index.js');
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Generate complete HTML document
|
|
448
|
-
function generateDocument(content, options = {}) {
|
|
449
|
-
const { title = 'Baraqex App', description = '', props = {} } = options;
|
|
450
|
-
|
|
451
|
-
return `<!DOCTYPE html>
|
|
452
|
-
<html lang="en">
|
|
453
|
-
<head>
|
|
454
|
-
<meta charset="UTF-8">
|
|
455
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
456
|
-
<title>${escapeHtml(title)}</title>
|
|
457
|
-
${description ? `<meta name="description" content="${escapeHtml(description)}">` : ''}
|
|
458
|
-
<style>
|
|
459
|
-
body {
|
|
460
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
461
|
-
margin: 0;
|
|
462
|
-
padding: 0;
|
|
463
|
-
background-color: #f5f5f5;
|
|
464
|
-
}
|
|
465
|
-
.app-container {
|
|
466
|
-
min-height: 100vh;
|
|
467
|
-
}
|
|
468
|
-
</style>
|
|
469
|
-
</head>
|
|
470
|
-
<body>
|
|
471
|
-
<div id="app-root" class="app-container">
|
|
472
|
-
${content}
|
|
473
|
-
</div>
|
|
474
|
-
|
|
475
|
-
<!-- Initial props for hydration -->
|
|
476
|
-
<script id="__APP_DATA__" type="application/json">
|
|
477
|
-
${JSON.stringify(props)}
|
|
478
|
-
</script>
|
|
479
|
-
|
|
480
|
-
<!-- Add any client-side scripts here -->
|
|
481
|
-
</body>
|
|
482
|
-
</html>`;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Generate welcome page
|
|
486
|
-
function generateWelcomePage() {
|
|
487
|
-
const content = `
|
|
488
|
-
<div style="text-align: center; padding: 2rem; max-width: 800px; margin: 0 auto;">
|
|
489
|
-
<h1 style="color: #2c3e50; font-size: 2.5rem; margin-bottom: 1rem;">
|
|
490
|
-
š Welcome to Baraqex!
|
|
491
|
-
</h1>
|
|
492
|
-
|
|
493
|
-
<p style="font-size: 1.2rem; color: #666; margin-bottom: 2rem;">
|
|
494
|
-
Your fullstack application is running successfully!
|
|
495
|
-
</p>
|
|
496
|
-
|
|
497
|
-
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); margin: 2rem 0;">
|
|
498
|
-
<div style="background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
499
|
-
<h3 style="margin-top: 0; color: #3498db;">š” API Routes</h3>
|
|
500
|
-
<p>Your API endpoints are ready to use.</p>
|
|
501
|
-
<ul style="text-align: left;">
|
|
502
|
-
<li><a href="/api/hello" style="color: #3498db;">GET /api/hello</a></li>
|
|
503
|
-
<li><a href="/api/users" style="color: #3498db;">GET /api/users</a></li>
|
|
504
|
-
</ul>
|
|
505
|
-
</div>
|
|
506
|
-
|
|
507
|
-
<div style="background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
508
|
-
<h3 style="margin-top: 0; color: #e74c3c;">š Pages</h3>
|
|
509
|
-
<p>Create pages in <code>src/pages/</code></p>
|
|
510
|
-
<p style="font-size: 0.9rem; color: #666;">
|
|
511
|
-
Each .js file becomes a route automatically.
|
|
512
|
-
</p>
|
|
513
|
-
</div>
|
|
514
|
-
|
|
515
|
-
<div style="background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
516
|
-
<h3 style="margin-top: 0; color: #27ae60;">š ļø Development</h3>
|
|
517
|
-
<p>Edit files and see changes instantly.</p>
|
|
518
|
-
<p style="font-size: 0.9rem; color: #666;">
|
|
519
|
-
Server automatically reloads on file changes.
|
|
520
|
-
</p>
|
|
521
|
-
</div>
|
|
522
|
-
</div>
|
|
523
|
-
|
|
524
|
-
<div style="margin-top: 2rem; padding: 1rem; background: #fff3cd; border-radius: 8px; border-left: 4px solid #ffc107;">
|
|
525
|
-
<p style="margin: 0; color: #856404;">
|
|
526
|
-
<strong>Next steps:</strong> Create your first page component in <code>src/pages/index.js</code>
|
|
527
|
-
</p>
|
|
528
|
-
</div>
|
|
529
|
-
</div>
|
|
530
|
-
`;
|
|
531
|
-
|
|
532
|
-
return generateDocument(content, {
|
|
533
|
-
title: 'Welcome to Baraqex',
|
|
534
|
-
description: 'A fullstack application framework'
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Generate error page
|
|
539
|
-
function generateErrorPage(statusCode, message) {
|
|
540
|
-
const content = `
|
|
541
|
-
<div style="text-align: center; padding: 2rem;">
|
|
542
|
-
<h1 style="font-size: 4rem; color: #e74c3c; margin: 0;">${statusCode}</h1>
|
|
543
|
-
<h2 style="color: #333; margin: 1rem 0;">Something went wrong</h2>
|
|
544
|
-
<p style="color: #666; font-size: 1.1rem;">${escapeHtml(message)}</p>
|
|
545
|
-
<a href="/" style="color: #3498db; text-decoration: none; font-weight: bold;">ā Back to Home</a>
|
|
546
|
-
</div>
|
|
547
|
-
`;
|
|
548
|
-
|
|
549
|
-
return generateDocument(content, {
|
|
550
|
-
title: `Error ${statusCode}`,
|
|
551
|
-
description: 'An error occurred'
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// Escape HTML special characters
|
|
556
|
-
function escapeHtml(text) {
|
|
557
|
-
return String(text)
|
|
558
|
-
.replace(/&/g, '&')
|
|
559
|
-
.replace(/</g, '<')
|
|
560
|
-
.replace(/>/g, '>')
|
|
561
|
-
.replace(/"/g, '"')
|
|
562
|
-
.replace(/'/g, ''');
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// Handle graceful shutdown
|
|
566
|
-
process.on('SIGINT', () => {
|
|
567
|
-
console.log('\nš Shutting down server...');
|
|
568
|
-
process.exit(0);
|
|
3
|
+
const server = createDevServer({
|
|
4
|
+
port: 3000,
|
|
5
|
+
enableCors: true
|
|
569
6
|
});
|
|
570
7
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
process.exit(0);
|
|
574
|
-
});
|
|
8
|
+
// Enable SSR with hydration
|
|
9
|
+
server.enableSSR({ hydratable: true });
|
|
575
10
|
|
|
576
11
|
// Start the server
|
|
577
|
-
|
|
12
|
+
server.start().then(() => {
|
|
13
|
+
console.log('Full-stack server started!');
|
|
14
|
+
console.log('Visit http://localhost:3000');
|
|
15
|
+
console.log('API available at http://localhost:3000/api');
|
|
16
|
+
});
|
|
@@ -1,13 +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>Baraqex Basic App</title>
|
|
7
|
-
<link rel="stylesheet" href="/styles.css">
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="app-root"></div>
|
|
11
|
-
<script src="/src/App.jsx" type="module"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|