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
@@ -0,0 +1,77 @@
1
+ import { jsx, useState } from 'baraqex';
2
+ import { HomePage } from './pages/Home';
3
+ import { AboutPage } from './pages/About';
4
+ import { WasmDemo } from './pages/WasmDemo';
5
+
6
+ export interface AppProps {
7
+ route?: string;
8
+ initialState?: any;
9
+ }
10
+
11
+ function parseRoute(pathname: string): string {
12
+ const p = pathname || '/';
13
+ if (p.startsWith('/wasm')) return 'wasm';
14
+ if (p.startsWith('/about')) return 'about';
15
+ return 'home';
16
+ }
17
+
18
+ export function App({ route, initialState }: AppProps) {
19
+ const [current, setCurrent] = useState<string>(parseRoute(route || (typeof window !== 'undefined' ? window.location.pathname : '/')));
20
+
21
+ const navigate = (target: string) => {
22
+ setCurrent(target);
23
+ if (typeof window !== 'undefined') {
24
+ const path = target === 'home' ? '/' : `/${target}`;
25
+ window.history.pushState(null, '', path);
26
+ }
27
+ };
28
+
29
+ const navItems = [
30
+ { key: 'home', label: 'Home', href: '/' },
31
+ { key: 'about', label: 'About', href: '/about' },
32
+ { key: 'wasm', label: 'WASM (Go)', href: '/wasm' }
33
+ ];
34
+
35
+ return (
36
+ <div className="min-h-screen flex flex-col bg-gray-50">
37
+ <header className="bg-blue-700 text-white shadow">
38
+ <div className="max-w-5xl mx-auto px-4 py-4 flex items-center justify-between">
39
+ <button onClick={() => navigate('home')} className="text-xl font-bold hover:text-blue-100">
40
+ Baraqex Full-Stack
41
+ </button>
42
+ <nav>
43
+ <ul className="flex space-x-6">
44
+ {navItems.map((item) => (
45
+ <li key={item.key}>
46
+ <button
47
+ onClick={() => navigate(item.key)}
48
+ className={
49
+ 'hover:text-blue-200 ' +
50
+ (current === item.key ? 'underline font-semibold' : '')
51
+ }
52
+ >
53
+ {item.label}
54
+ </button>
55
+ </li>
56
+ ))}
57
+ </ul>
58
+ </nav>
59
+ </div>
60
+ </header>
61
+
62
+ <main className="flex-grow max-w-5xl w-full mx-auto px-4 py-8">
63
+ {current === 'home' && <HomePage initialState={initialState} />}
64
+ {current === 'about' && <AboutPage />}
65
+ {current === 'wasm' && <WasmDemo />}
66
+ </main>
67
+
68
+ <footer className="bg-gray-800 text-white">
69
+ <div className="max-w-5xl mx-auto px-4 py-6 text-center text-gray-400">
70
+ © {new Date().getFullYear()} Baraqex — SSR + WASM + Full-Stack in one template
71
+ </div>
72
+ </footer>
73
+ </div>
74
+ );
75
+ }
76
+
77
+ export default App;
@@ -1,155 +1,31 @@
1
- import { render, hydrate, jsx } from 'frontend-hamroun';
2
- // Import Tailwind CSS
3
- import './styles.css';
4
-
5
- // Type declaration for window.__INITIAL_STATE__
6
- declare global {
7
- interface Window {
8
- __INITIAL_STATE__?: any;
9
- }
10
- }
11
-
12
- // Get initial state from server
13
- const initialState = window.__INITIAL_STATE__ || {
14
- route: window.location.pathname,
15
- timestamp: new Date().toISOString(),
16
- serverRendered: false,
17
- data: {
18
- users: null,
19
- posts: null
20
- }
21
- };
22
-
23
- console.log('[Client] Initial state:', initialState);
24
-
25
- // Create a mutable variable for hydration state
26
- let isHydrating = document.getElementById('root')?.innerHTML.trim() !== '';
27
-
28
- // Function to handle navigation
29
- async function handleRouteChange(path: string, isPushState = true) {
30
- try {
31
- console.log(`[Router] Navigating to: ${path}`);
32
-
33
- // Update URL if needed
34
- if (isPushState) {
35
- window.history.pushState(null, '', path);
36
- }
37
-
38
- // Dynamically load the page component based on the path
39
- const normalizedPath = path === '/' ? 'index' : path.replace(/^\//, '');
40
-
41
- let Page;
42
- try {
43
- // Dynamic import for the page component
44
- const module = await import(`./pages/${normalizedPath}.tsx`);
45
- Page = module.default;
46
- } catch (error) {
47
- console.warn(`[Router] Could not load page for ${path}, trying index file`);
48
- try {
49
- // Try loading index file in directory
50
- const module = await import(`./pages/${normalizedPath}/index.tsx`);
51
- Page = module.default;
52
- } catch (innerError) {
53
- console.error(`[Router] Failed to load page component for ${path}`);
54
-
55
- // Try to load 404 page
56
- try {
57
- const notFoundModule = await import(`./pages/404.tsx`);
58
- Page = notFoundModule.default;
59
- } catch (notFoundError) {
60
- // If all fails, render a simple not found message
61
- const rootElement = document.getElementById('root');
62
- if (rootElement) {
63
- render(
64
- <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
65
- <h1>Page Not Found</h1>
66
- <p>The page you requested could not be found.</p>
67
- <a href="/" style={{ color: '#0066cc' }}>Go to Home</a>
68
- </div>,
69
- rootElement
70
- );
71
- }
72
- return;
73
- }
74
- }
75
- }
76
-
77
- // Get the current page props
78
- let pageProps = initialState.pageProps || {};
79
-
80
- // If the page defines getServerSideProps, fetch data
81
- if (Page.getServerSideProps) {
82
- try {
83
- const response = await fetch(`/api/__props${path}`);
84
- if (response.ok) {
85
- const data = await response.json();
86
- pageProps = data.props || {};
87
- }
88
- } catch (error) {
89
- console.error('[Router] Error fetching page props:', error);
90
- }
91
- }
92
-
93
- // Update the state with current route
94
- const updatedState = {
95
- ...initialState,
96
- route: path,
97
- pageProps
98
- };
99
-
100
- // Render the page
101
- const rootElement = document.getElementById('root');
102
- if (!rootElement) return;
103
-
104
- if (isHydrating && path === initialState.route) {
105
- console.log('[Client] Hydrating server-rendered content');
106
- hydrate(<Page {...pageProps} initialState={updatedState} />, rootElement);
107
- isHydrating = false;
108
- } else {
109
- console.log('[Client] Rendering client-side');
110
- render(<Page {...pageProps} initialState={updatedState} />, rootElement);
111
- }
112
- } catch (error) {
113
- console.error('[Router] Navigation error:', error);
114
- }
115
- }
116
-
117
- // Handle initial route
118
- handleRouteChange(window.location.pathname, false);
119
-
120
- // Handle client-side navigation
121
- document.addEventListener('click', (e) => {
122
- let target = e.target as HTMLElement | null;
123
-
124
- // Find closest anchor element
125
- while (target && target.tagName !== 'A') {
126
- target = target.parentElement;
127
- if (!target) break;
128
- }
129
-
130
- if (target &&
131
- target.tagName === 'A' &&
132
- target.getAttribute('href') &&
133
- target.getAttribute('href')?.startsWith('/') &&
134
- !target.getAttribute('href')?.startsWith('//') &&
135
- !target.getAttribute('target')) {
136
-
137
- e.preventDefault();
138
- const href = target.getAttribute('href') || '/';
139
- handleRouteChange(href);
140
- }
141
- });
142
-
143
- // Handle back/forward navigation
144
- window.addEventListener('popstate', () => {
145
- handleRouteChange(window.location.pathname, false);
146
- });
147
-
148
- // Set up socket.io for live reload in development
149
- if (typeof io !== 'undefined') {
150
- const socket = io();
151
- socket.on('reload', () => {
152
- console.log('[Dev] Reloading page due to file changes');
153
- window.location.reload();
154
- });
155
- }
1
+ import { hydrate, jsx } from 'baraqex';
2
+ import { App } from './App';
3
+ import './styles.css';
4
+
5
+ declare global {
6
+ interface Window {
7
+ __INITIAL_STATE__?: any;
8
+ }
9
+ }
10
+
11
+ const initialState = window.__INITIAL_STATE__ || {};
12
+ const route = window.location.pathname;
13
+
14
+ const root = document.getElementById('root');
15
+ if (root) {
16
+ hydrate(jsx(App, { route, initialState }), root);
17
+ }
18
+
19
+ // Socket.IO live reload (dev)
20
+ const w = window as any;
21
+ if (w.io) {
22
+ const socket = w.io();
23
+ socket.on('reload', () => window.location.reload());
24
+ }
25
+
26
+ // Handle back/forward navigation
27
+ window.addEventListener('popstate', () => {
28
+ const r = document.getElementById('root');
29
+ if (r) hydrate(jsx(App, { route: window.location.pathname, initialState }), r);
30
+ });
31
+
@@ -0,0 +1,40 @@
1
+ import { jsx } from 'baraqex';
2
+
3
+ export function AboutPage() {
4
+ return (
5
+ <div className="bg-white rounded-lg shadow p-6 space-y-6">
6
+ <h1 className="text-3xl font-bold text-gray-900">About this template</h1>
7
+ <div className="grid md:grid-cols-2 gap-6">
8
+ <div className="p-4 border border-blue-100 rounded-lg bg-blue-50">
9
+ <h3 className="font-semibold text-blue-800 mb-2">Frontend + SSR</h3>
10
+ <p className="text-sm text-blue-900">
11
+ The same <code className="bg-blue-100 px-1 rounded">App</code> component is rendered
12
+ server-side with <code>baraqex</code> and hydrated on the client. Initial page HTML
13
+ arrives fully formed.
14
+ </p>
15
+ </div>
16
+ <div className="p-4 border border-green-100 rounded-lg bg-green-50">
17
+ <h3 className="font-semibold text-green-800 mb-2">Backend (Express API)</h3>
18
+ <p className="text-sm text-green-900">
19
+ API endpoints under <code>/api/*</code> are served by an Express server bundled
20
+ alongside the app. Refresh users from <code>/api/users</code>.
21
+ </p>
22
+ </div>
23
+ <div className="p-4 border border-purple-100 rounded-lg bg-purple-50">
24
+ <h3 className="font-semibold text-purple-800 mb-2">WebAssembly (Go)</h3>
25
+ <p className="text-sm text-purple-900">
26
+ Go source in <code>go/main.go</code> compiles to WASM via{' '}
27
+ <code>npm run build:wasm</code>. Call Go functions straight from the browser.
28
+ </p>
29
+ </div>
30
+ <div className="p-4 border border-amber-100 rounded-lg bg-amber-50">
31
+ <h3 className="font-semibold text-amber-800 mb-2">Live reload (dev)</h3>
32
+ <p className="text-sm text-amber-900">
33
+ <code>npm run dev</code> bundles with esbuild and streams reload events over
34
+ Socket.IO when files change.
35
+ </p>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ );
40
+ }
@@ -0,0 +1,67 @@
1
+ import { jsx, useState } from 'baraqex';
2
+
3
+ export interface HomeState {
4
+ users?: any[];
5
+ posts?: any[];
6
+ serverTime?: string;
7
+ }
8
+
9
+ export function HomePage({ initialState }: { initialState?: any }) {
10
+ const initial: HomeState = initialState || { users: [], posts: [] };
11
+ const [users, setUsers] = useState<any[]>(initial.users || []);
12
+ const [message, setMessage] = useState('');
13
+
14
+ const refresh = async () => {
15
+ try {
16
+ const res = await fetch('/api/users');
17
+ const data = await res.json();
18
+ setUsers(data);
19
+ setMessage('Data refreshed from /api/users');
20
+ } catch (e: any) {
21
+ setMessage('Failed to load data: ' + e.message);
22
+ }
23
+ };
24
+
25
+ return (
26
+ <div className="space-y-8">
27
+ <section>
28
+ <h1 className="text-3xl font-bold text-gray-900 mb-2">
29
+ Welcome to Baraqex
30
+ </h1>
31
+ <p className="text-gray-600">
32
+ This template wires together server-side rendering (SSR), a REST API, WebAssembly
33
+ compiled from Go, and hydration — all through the baraqex framework.
34
+ </p>
35
+ {initial.serverTime && (
36
+ <p className="text-sm text-gray-500 mt-2">
37
+ Server-rendered at: {initial.serverTime}
38
+ </p>
39
+ )}
40
+ </section>
41
+
42
+ <section className="bg-white rounded-lg shadow p-6">
43
+ <div className="flex items-center justify-between mb-4">
44
+ <h2 className="text-xl font-semibold text-gray-800">Users (fetched via API)</h2>
45
+ <button
46
+ onClick={refresh}
47
+ className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
48
+ >
49
+ Refresh
50
+ </button>
51
+ </div>
52
+ {message && <p className="text-green-700 text-sm mb-3">{message}</p>}
53
+ <ul className="divide-y divide-gray-200">
54
+ {(users || []).map((user: any) => (
55
+ <li key={user.id} className="py-2 flex items-center justify-between">
56
+ <span className="font-medium">{user.name}</span>
57
+ <span className="text-sm text-gray-500">{user.email}</span>
58
+ </li>
59
+ ))}
60
+ </ul>
61
+ {(users || []).length === 0 && (
62
+ <p className="text-gray-500 text-sm">No users loaded yet. Click Refresh.</p>
63
+ )}
64
+ </section>
65
+ </div>
66
+ );
67
+ }
@@ -0,0 +1,81 @@
1
+ import { jsx, useState, useEffect, batchUpdates } from 'baraqex';
2
+ import { loadGoWasm } from 'baraqex';
3
+
4
+ export function WasmDemo() {
5
+ const [ready, setReady] = useState(false);
6
+ const [status, setStatus] = useState('Loading Go WASM...');
7
+ const [output, setOutput] = useState('');
8
+ const [a, setA] = useState('5');
9
+ const [b, setB] = useState('7');
10
+ const [n, setN] = useState('10');
11
+
12
+ useEffect(() => {
13
+ let cancelled = false;
14
+ (async () => {
15
+ try {
16
+ await loadGoWasm('/wasm/example.wasm');
17
+ if (cancelled) return;
18
+ batchUpdates(() => {
19
+ setReady(true);
20
+ setStatus('✅ Go WASM module loaded!');
21
+ setOutput('Go functions available: goAdd, goMultiply, goFibonacci, goProcessArray');
22
+ });
23
+ } catch (e: any) {
24
+ if (cancelled) return;
25
+ setStatus('❌ Failed to load WASM: ' + e.message);
26
+ setOutput('Run `npm run build:wasm` (requires Go) and ensure /wasm/example.wasm is served.');
27
+ }
28
+ })();
29
+ return () => { cancelled = true; };
30
+ }, []);
31
+
32
+ const call = (fn: string, ...args: any[]) => (window as any)[fn](...args);
33
+
34
+ const add = () => setOutput(`goAdd(${a}, ${b}) = ${call('goAdd', parseFloat(a), parseFloat(b))}`);
35
+ const multiply = () => setOutput(`goMultiply(${a}, ${b}) = ${call('goMultiply', parseFloat(a), parseFloat(b))}`);
36
+ const fib = () => setOutput(`goFibonacci(${n}) = ${call('goFibonacci', parseInt(n, 10))}`);
37
+ const processArr = () => {
38
+ const result = call('goProcessArray', [1, 2, 3, 4, 5]);
39
+ setOutput(`goProcessArray([1,2,3,4,5]) = [${Array.from(result).join(', ')}]`);
40
+ };
41
+
42
+ const disabled = !ready;
43
+
44
+ return (
45
+ <div className="bg-white rounded-lg shadow p-6 space-y-6">
46
+ <h1 className="text-3xl font-bold text-gray-900">Go WebAssembly Demo</h1>
47
+ <p className={`font-medium ${ready ? 'text-green-700' : 'text-amber-600'}`}>{status}</p>
48
+ <div className="grid md:grid-cols-2 gap-6">
49
+ <div className="p-4 border rounded-lg bg-gray-50">
50
+ <h3 className="font-semibold text-gray-700 mb-3">Arithmetic</h3>
51
+ <div className="flex items-center gap-2 mb-3">
52
+ <input value={a} onChange={(e: any) => setA(e.target.value)} className="w-20 px-2 py-1 border rounded" />
53
+ <input value={b} onChange={(e: any) => setB(e.target.value)} className="w-20 px-2 py-1 border rounded" />
54
+ </div>
55
+ <div className="flex gap-2">
56
+ <button onClick={add} disabled={disabled} className="px-3 py-1 bg-blue-600 text-white rounded disabled:opacity-40">Add</button>
57
+ <button onClick={multiply} disabled={disabled} className="px-3 py-1 bg-blue-600 text-white rounded disabled:opacity-40">Multiply</button>
58
+ </div>
59
+ </div>
60
+ <div className="p-4 border rounded-lg bg-gray-50">
61
+ <h3 className="font-semibold text-gray-700 mb-3">Fibonacci</h3>
62
+ <input value={n} onChange={(e: any) => setN(e.target.value)} className="w-24 px-2 py-1 border rounded mb-3" />
63
+ <div>
64
+ <button onClick={fib} disabled={disabled} className="px-3 py-1 bg-purple-600 text-white rounded disabled:opacity-40">Fibonacci(n)</button>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ <div className="p-4 border rounded-lg bg-gray-50">
69
+ <h3 className="font-semibold text-gray-700 mb-3">Arrays (Int32)</h3>
70
+ <button onClick={processArr} disabled={disabled} className="px-3 py-1 bg-green-600 text-white rounded disabled:opacity-40">
71
+ Process array
72
+ </button>
73
+ </div>
74
+ {output && (
75
+ <pre className="p-4 bg-gray-900 text-green-400 rounded-lg overflow-auto text-sm">
76
+ {output}
77
+ </pre>
78
+ )}
79
+ </div>
80
+ );
81
+ }
@@ -1,5 +1,12 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- /* Your custom styles can go here */
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ body {
6
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
7
+ 'Open Sans', 'Helvetica Neue', sans-serif;
8
+ }
9
+
10
+ code {
11
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
12
+ }
@@ -1,11 +1,8 @@
1
- /** @type {import('tailwindcss').Config} */
2
- module.exports = {
3
- content: [
4
- "./index.html",
5
- "./src/**/*.{js,ts,jsx,tsx}",
6
- ],
7
- theme: {
8
- extend: {},
9
- },
10
- plugins: [],
11
- }
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: ['./index.html', './src/**/*.{ts,tsx,js,jsx}'],
4
+ theme: {
5
+ extend: {}
6
+ },
7
+ plugins: []
8
+ };
@@ -1,18 +1,18 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "esModuleInterop": true,
7
- "sourceMap": true,
8
- "outDir": "dist",
9
- "strict": true,
10
- "lib": ["ES2020"],
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "allowSyntheticDefaultImports": true,
14
- "resolveJsonModule": true
15
- },
16
- "include": ["**/*.ts"],
17
- "exclude": ["node_modules", "dist"]
18
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "jsx": "preserve",
7
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "types": ["node"]
16
+ },
17
+ "include": ["src", "server.ts", "build.mjs", "build-wasm.js"]
18
+ }
@@ -1,11 +0,0 @@
1
- export const get = (req, res) => {
2
- res.json({
3
- message: 'Hello from the API!',
4
- time: new Date().toISOString(),
5
- features: [
6
- 'Server-side rendering',
7
- 'API integration',
8
- 'No build step required'
9
- ]
10
- });
11
- };
@@ -1,18 +0,0 @@
1
- import { Request, Response } from 'express';
2
-
3
- export const get = (req: Request, res: Response) => {
4
- res.json({
5
- message: 'Hello from the API!',
6
- timestamp: new Date().toISOString()
7
- });
8
- };
9
-
10
- export const post = (req: Request, res: Response) => {
11
- const { name = 'Guest' } = req.body;
12
-
13
- res.json({
14
- message: `Hello, ${name}!`,
15
- timestamp: new Date().toISOString(),
16
- receivedData: req.body
17
- });
18
- };
@@ -1,73 +0,0 @@
1
- import { Request, Response } from 'express';
2
-
3
- // Mock user database - same as in index.ts for simplicity
4
- const users = [
5
- { id: 1, name: 'User 1', email: 'user1@example.com' },
6
- { id: 2, name: 'User 2', email: 'user2@example.com' },
7
- { id: 3, name: 'User 3', email: 'user3@example.com' }
8
- ];
9
-
10
- export const get = (req: Request, res: Response) => {
11
- const userId = parseInt(req.params.id);
12
-
13
- if (isNaN(userId)) {
14
- return res.status(400).json({ error: 'Invalid user ID' });
15
- }
16
-
17
- const user = users.find(u => u.id === userId);
18
-
19
- if (!user) {
20
- return res.status(404).json({ error: 'User not found' });
21
- }
22
-
23
- res.json(user);
24
- };
25
-
26
- export const put = (req: Request, res: Response) => {
27
- const userId = parseInt(req.params.id);
28
-
29
- if (isNaN(userId)) {
30
- return res.status(400).json({ error: 'Invalid user ID' });
31
- }
32
-
33
- const userIndex = users.findIndex(u => u.id === userId);
34
-
35
- if (userIndex === -1) {
36
- return res.status(404).json({ error: 'User not found' });
37
- }
38
-
39
- const { name, email } = req.body;
40
-
41
- if (!name && !email) {
42
- return res.status(400).json({ error: 'Name or email must be provided' });
43
- }
44
-
45
- // Update the user
46
- users[userIndex] = {
47
- ...users[userIndex],
48
- ...(name && { name }),
49
- ...(email && { email })
50
- };
51
-
52
- res.json(users[userIndex]);
53
- };
54
-
55
- export const delete_ = (req: Request, res: Response) => {
56
- const userId = parseInt(req.params.id);
57
-
58
- if (isNaN(userId)) {
59
- return res.status(400).json({ error: 'Invalid user ID' });
60
- }
61
-
62
- const userIndex = users.findIndex(u => u.id === userId);
63
-
64
- if (userIndex === -1) {
65
- return res.status(404).json({ error: 'User not found' });
66
- }
67
-
68
- // Remove the user
69
- const deletedUser = users[userIndex];
70
- users.splice(userIndex, 1);
71
-
72
- res.json({ success: true, deletedUser });
73
- };
@@ -1,32 +0,0 @@
1
- import { Request, Response } from 'express';
2
-
3
- // Mock user database
4
- const users = [
5
- { id: 1, name: 'User 1', email: 'user1@example.com' },
6
- { id: 2, name: 'User 2', email: 'user2@example.com' },
7
- { id: 3, name: 'User 3', email: 'user3@example.com' }
8
- ];
9
-
10
- export const get = (req: Request, res: Response) => {
11
- // Return users without sensitive information
12
- const safeUsers = users.map(({ id, name, email }) => ({ id, name, email }));
13
- res.json(safeUsers);
14
- };
15
-
16
- export const post = (req: Request, res: Response) => {
17
- const { name, email } = req.body;
18
-
19
- if (!name || !email) {
20
- return res.status(400).json({ error: 'Name and email are required' });
21
- }
22
-
23
- // In a real app, validate data and save to database
24
- const newUser = {
25
- id: users.length + 1,
26
- name,
27
- email
28
- };
29
-
30
- users.push(newUser);
31
- res.status(201).json(newUser);
32
- };