frontend-hamroun 1.2.15 → 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.
Files changed (158) hide show
  1. package/README.md +4 -0
  2. package/bin/cli.js +673 -0
  3. package/dist/component.d.ts +1 -1
  4. package/dist/context.d.ts +4 -3
  5. package/dist/index.client.d.ts +11 -0
  6. package/dist/index.d.ts +9 -89
  7. package/dist/index.js +396 -67
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +392 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.ts +0 -1
  12. package/dist/jsx-runtime.d.ts +1 -1
  13. package/dist/renderer.d.ts +0 -10
  14. package/dist/server-renderer.d.ts +0 -3
  15. package/dist/server-types.d.ts +42 -0
  16. package/package.json +69 -50
  17. package/templates/basic-app/index.html +6 -6
  18. package/templates/basic-app/package.json +15 -11
  19. package/templates/basic-app/postcss.config.js +0 -1
  20. package/templates/basic-app/src/main.tsx +1 -10
  21. package/templates/basic-app/tailwind.config.js +2 -23
  22. package/templates/basic-app/tsconfig.json +4 -17
  23. package/templates/basic-app/vite.config.ts +3 -54
  24. package/templates/fullstack-app/api/hello.ts +18 -0
  25. package/templates/fullstack-app/api/users/[id].ts +73 -0
  26. package/templates/fullstack-app/api/users/index.ts +32 -0
  27. package/templates/fullstack-app/package.json +31 -0
  28. package/templates/fullstack-app/server.ts +46 -0
  29. package/templates/fullstack-app/src/pages/index.tsx +59 -0
  30. package/templates/ssr-template/vite.config.ts +1 -11
  31. package/bin/cli.cjs +0 -16
  32. package/bin/cli.mjs +0 -237
  33. package/dist/backend/api-utils.d.ts +0 -38
  34. package/dist/backend/api-utils.js +0 -135
  35. package/dist/backend/auth.d.ts +0 -134
  36. package/dist/backend/auth.js +0 -387
  37. package/dist/backend/database.d.ts +0 -27
  38. package/dist/backend/database.js +0 -91
  39. package/dist/backend/model.d.ts +0 -43
  40. package/dist/backend/model.js +0 -178
  41. package/dist/backend/router.d.ts +0 -27
  42. package/dist/backend/router.js +0 -137
  43. package/dist/backend/server.d.ts +0 -19
  44. package/dist/backend/server.js +0 -268
  45. package/dist/backend/types.d.ts +0 -217
  46. package/dist/backend/types.js +0 -1
  47. package/dist/batch.js +0 -22
  48. package/dist/cli/index.d.ts +0 -2
  49. package/dist/cli/index.js +0 -215
  50. package/dist/component.js +0 -84
  51. package/dist/components/Counter.js +0 -2
  52. package/dist/context.js +0 -18
  53. package/dist/frontend-hamroun.es.js +0 -1378
  54. package/dist/frontend-hamroun.umd.js +0 -66
  55. package/dist/hooks.js +0 -164
  56. package/dist/jsx-runtime/index.d.ts +0 -11
  57. package/dist/jsx-runtime/index.js +0 -19
  58. package/dist/jsx-runtime/jsx-dev-runtime.js +0 -1
  59. package/dist/jsx-runtime/jsx-runtime.js +0 -95
  60. package/dist/jsx-runtime.js +0 -192
  61. package/dist/renderer.js +0 -51
  62. package/dist/server-renderer.js +0 -102
  63. package/dist/types.js +0 -1
  64. package/dist/vdom.js +0 -27
  65. package/scripts/build-cli.js +0 -1107
  66. package/scripts/generate.js +0 -134
  67. package/src/backend/api-utils.ts +0 -178
  68. package/src/backend/auth.ts +0 -544
  69. package/src/backend/database.ts +0 -104
  70. package/src/backend/model.ts +0 -198
  71. package/src/backend/router.ts +0 -176
  72. package/src/backend/server.ts +0 -330
  73. package/src/backend/types.ts +0 -257
  74. package/src/batch.ts +0 -24
  75. package/src/cli/index.js +0 -554
  76. package/src/cli/index.ts +0 -257
  77. package/src/component.ts +0 -98
  78. package/src/components/Counter.tsx +0 -4
  79. package/src/context.ts +0 -29
  80. package/src/hooks.ts +0 -211
  81. package/src/index.ts +0 -144
  82. package/src/jsx-runtime/index.ts +0 -27
  83. package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
  84. package/src/jsx-runtime/jsx-runtime.ts +0 -104
  85. package/src/jsx-runtime.ts +0 -226
  86. package/src/renderer.ts +0 -55
  87. package/src/server-renderer.ts +0 -114
  88. package/src/shims.d.ts +0 -20
  89. package/src/types/bcrypt.d.ts +0 -30
  90. package/src/types/jsonwebtoken.d.ts +0 -55
  91. package/src/types.d.ts +0 -26
  92. package/src/types.ts +0 -21
  93. package/src/vdom.ts +0 -34
  94. package/templates/basic/.eslintignore +0 -5
  95. package/templates/basic/.eslintrc.json +0 -25
  96. package/templates/basic/docs/rapport_pfe.aux +0 -27
  97. package/templates/basic/docs/rapport_pfe.log +0 -399
  98. package/templates/basic/docs/rapport_pfe.out +0 -10
  99. package/templates/basic/docs/rapport_pfe.pdf +0 -0
  100. package/templates/basic/docs/rapport_pfe.tex +0 -68
  101. package/templates/basic/docs/rapport_pfe.toc +0 -14
  102. package/templates/basic/index.html +0 -12
  103. package/templates/basic/jsconfig.json +0 -14
  104. package/templates/basic/package.json +0 -20
  105. package/templates/basic/postcss.config.js +0 -7
  106. package/templates/basic/src/App.js +0 -105
  107. package/templates/basic/src/App.tsx +0 -65
  108. package/templates/basic/src/api.ts +0 -58
  109. package/templates/basic/src/components/Counter.tsx +0 -26
  110. package/templates/basic/src/components/Header.tsx +0 -9
  111. package/templates/basic/src/components/TodoList.tsx +0 -90
  112. package/templates/basic/src/main.css +0 -3
  113. package/templates/basic/src/main.js +0 -11
  114. package/templates/basic/src/main.ts +0 -20
  115. package/templates/basic/src/main.tsx +0 -144
  116. package/templates/basic/src/server.ts +0 -99
  117. package/templates/basic/tailwind.config.js +0 -32
  118. package/templates/basic/tsconfig.json +0 -20
  119. package/templates/basic/tsconfig.node.json +0 -10
  120. package/templates/basic/vite.config.js +0 -18
  121. package/templates/basic/vite.config.ts +0 -86
  122. package/templates/basic-app/src/App.js +0 -105
  123. package/templates/basic-app/src/App.tsx +0 -143
  124. package/templates/basic-app/src/api.ts +0 -58
  125. package/templates/basic-app/src/components/Counter.tsx +0 -26
  126. package/templates/basic-app/src/components/Header.tsx +0 -9
  127. package/templates/basic-app/src/components/TodoList.tsx +0 -90
  128. package/templates/basic-app/src/main.js +0 -10
  129. package/templates/basic-app/src/main.ts +0 -21
  130. package/templates/basic-app/src/react/index.ts +0 -35
  131. package/templates/basic-app/src/react/jsx-dev-runtime.ts +0 -13
  132. package/templates/basic-app/src/react/jsx-runtime.ts +0 -12
  133. package/templates/basic-app/src/server.ts +0 -99
  134. package/templates/basic-app/src/shims.ts +0 -9
  135. package/templates/basic-app/tsconfig.node.json +0 -10
  136. package/templates/basic-app/vite.config.js +0 -22
  137. package/templates/full-stack/.env.example +0 -11
  138. package/templates/full-stack/README.md +0 -51
  139. package/templates/full-stack/index.html +0 -12
  140. package/templates/full-stack/jsconfig.json +0 -14
  141. package/templates/full-stack/package.json +0 -20
  142. package/templates/full-stack/src/App.js +0 -105
  143. package/templates/full-stack/src/client/App.tsx +0 -50
  144. package/templates/full-stack/src/client/components/Header.tsx +0 -42
  145. package/templates/full-stack/src/client/components/UserList.tsx +0 -29
  146. package/templates/full-stack/src/client/main.tsx +0 -5
  147. package/templates/full-stack/src/main.css +0 -3
  148. package/templates/full-stack/src/main.js +0 -11
  149. package/templates/full-stack/src/main.ts +0 -20
  150. package/templates/full-stack/src/server/index.ts +0 -99
  151. package/templates/full-stack/src/server/routes/auth.ts +0 -39
  152. package/templates/full-stack/src/server/routes/users.ts +0 -48
  153. package/templates/full-stack/src/shims.ts +0 -9
  154. package/templates/full-stack/tsconfig.json +0 -20
  155. package/templates/full-stack/tsconfig.node.json +0 -10
  156. package/templates/full-stack/tsconfig.server.json +0 -15
  157. package/templates/full-stack/vite.config.js +0 -18
  158. package/templates/full-stack/vite.config.ts +0 -85
@@ -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,32 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- export default {
3
- content: [
4
- "./index.html",
5
- "./src/**/*.{js,ts,jsx,tsx}",
6
- ],
7
- theme: {
8
- extend: {
9
- colors: {
10
- primary: {
11
- 50: '#f0f9ff',
12
- 100: '#e0f2fe',
13
- 200: '#bae6fd',
14
- 300: '#7dd3fc',
15
- 400: '#38bdf8',
16
- 500: '#0ea5e9',
17
- 600: '#0284c7',
18
- 700: '#0369a1',
19
- 800: '#075985',
20
- 900: '#0c4a6e',
21
- },
22
- },
23
- fontFamily: {
24
- sans: ['Inter var', 'sans-serif'],
25
- },
26
- },
27
- },
28
- plugins: [
29
- require('@tailwindcss/forms'),
30
- require('@tailwindcss/typography'),
31
- ],
32
- }
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "useDefineForClassFields": true,
5
- "module": "ESNext",
6
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
- "skipLibCheck": true,
8
- "moduleResolution": "bundler",
9
- "allowImportingTsExtensions": true,
10
- "resolveJsonModule": true,
11
- "isolatedModules": true,
12
- "noEmit": true,
13
- "strict": true,
14
- "noUnusedLocals": true,
15
- "noUnusedParameters": true,
16
- "noFallthroughCasesInSwitch": true
17
- },
18
- "include": ["src"],
19
- "references": [{ "path": "./tsconfig.node.json" }]
20
- }
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "skipLibCheck": true,
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "allowSyntheticDefaultImports": true
8
- },
9
- "include": ["vite.config.ts"]
10
- }
@@ -1,18 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import { nodePolyfills } from 'vite-plugin-node-polyfills';
3
-
4
- export default defineConfig({
5
- build: {
6
- outDir: 'dist',
7
- emptyOutDir: true
8
- },
9
- server: {
10
- port: 3000,
11
- open: true
12
- },
13
- plugins: [
14
- nodePolyfills({
15
- protocolImports: true,
16
- }),
17
- ]
18
- });
@@ -1,86 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import { nodePolyfills } from 'vite-plugin-node-polyfills';
3
-
4
- export default defineConfig({
5
- esbuild: {
6
- jsxFactory: 'jsx',
7
- jsxFragment: 'Fragment'
8
- },
9
- build: {
10
- outDir: 'dist',
11
- emptyOutDir: true,
12
- rollupOptions: {
13
- // Mark testing dependencies and Node.js dependencies as external
14
- external: [
15
- 'mock-aws-s3',
16
- 'aws-sdk',
17
- 'nock',
18
- 'jest',
19
- 'jest-mock',
20
- '@testing-library/react',
21
- '@testing-library/jest-dom',
22
- '@mswjs/interceptors',
23
- 'node-pre-gyp',
24
- 'bcrypt',
25
- 'jsonwebtoken',
26
- 'mongoose',
27
- 'express',
28
- 'compression',
29
- 'helmet',
30
- 'morgan',
31
- /node:.*/
32
- ]
33
- }
34
- },
35
- server: {
36
- port: 3000,
37
- open: true
38
- },
39
- optimizeDeps: {
40
- esbuildOptions: {
41
- // Node.js global to browser globalThis
42
- define: {
43
- global: 'globalThis'
44
- },
45
- // Enable esbuild polyfill plugins
46
- plugins: [
47
- {
48
- name: 'node-modules-polyfill',
49
- setup(build) {
50
- // Exclude node:* imports and html files
51
- build.onResolve({ filter: /^node:/ }, () => {
52
- return { external: true };
53
- });
54
- build.onResolve({ filter: /\.html$/ }, () => {
55
- return { external: true };
56
- });
57
- }
58
- }
59
- ]
60
- },
61
- // Exclude problematic dependencies from optimization
62
- exclude: [
63
- 'mock-aws-s3',
64
- 'aws-sdk',
65
- 'nock',
66
- '@mswjs/interceptors',
67
- 'node-pre-gyp',
68
- 'bcrypt'
69
- ]
70
- },
71
- plugins: [
72
- // Add node polyfills for browser environment
73
- nodePolyfills({
74
- // Whether to polyfill `node:` protocol imports
75
- protocolImports: true,
76
- }),
77
- ],
78
- resolve: {
79
- // Add node compatibility
80
- alias: {
81
- // Handle missing imports specifically
82
- '@mswjs/interceptors/presets/node': { find: /^@mswjs\/interceptors\/presets\/node/, replacement: '{}' },
83
- './util/nw-pre-gyp/index.html': { find: './util/nw-pre-gyp/index.html', replacement: '{}' }
84
- }
85
- }
86
- });
@@ -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
- // Using plain JS objects instead of JSX
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,143 +0,0 @@
1
- import { useState, useEffect, useContext, useRef } from 'frontend-hamroun';
2
- import { Header } from './components/Header';
3
- import { Counter } from './components/Counter';
4
- import { ApiClient } from './api.js';
5
- import { TodoList } from './components/TodoList.js';
6
- import { AppContext } from './main';
7
-
8
- interface AppProps {
9
- api: ApiClient;
10
- }
11
-
12
- // Use function declaration style instead of JSX component syntax
13
- export function App(props: any) {
14
- const [count, setCount] = useState(0);
15
- const [theme, setTheme] = useState('light');
16
- const renderCount = useRef(0);
17
-
18
- renderCount.current++;
19
-
20
- // Return a standard object structure rather than JSX
21
- return {
22
- type: 'div',
23
- props: {
24
- style: {
25
- fontFamily: 'Arial, sans-serif',
26
- maxWidth: '600px',
27
- margin: '0 auto',
28
- padding: '2rem',
29
- backgroundColor: theme === 'dark' ? '#222' : '#fff',
30
- color: theme === 'dark' ? '#fff' : '#222'
31
- },
32
- children: [
33
- {
34
- type: 'h1',
35
- props: {
36
- style: { textAlign: 'center' },
37
- children: 'Frontend Hamroun App'
38
- }
39
- },
40
- {
41
- type: 'p',
42
- props: {
43
- style: { textAlign: 'center' },
44
- children: `This component has rendered ${renderCount.current} times`
45
- }
46
- },
47
- {
48
- type: 'div',
49
- props: {
50
- style: {
51
- display: 'flex',
52
- justifyContent: 'center',
53
- marginBottom: '1rem'
54
- },
55
- children: {
56
- type: 'button',
57
- props: {
58
- onClick: () => setTheme(theme === 'light' ? 'dark' : 'light'),
59
- style: {
60
- padding: '8px 16px',
61
- backgroundColor: '#4b5563',
62
- color: 'white',
63
- border: 'none',
64
- borderRadius: '4px',
65
- cursor: 'pointer'
66
- },
67
- children: `Switch to ${theme === 'light' ? 'dark' : 'light'} mode`
68
- }
69
- }
70
- }
71
- },
72
- {
73
- type: 'div',
74
- props: {
75
- style: {
76
- display: 'flex',
77
- flexDirection: 'column',
78
- alignItems: 'center',
79
- padding: '1rem',
80
- border: '1px solid #ccc',
81
- borderRadius: '8px'
82
- },
83
- children: [
84
- {
85
- type: 'h2',
86
- props: {
87
- children: 'Counter Example'
88
- }
89
- },
90
- {
91
- type: 'p',
92
- props: {
93
- children: `Count: ${count}`
94
- }
95
- },
96
- {
97
- type: 'div',
98
- props: {
99
- style: {
100
- display: 'flex',
101
- gap: '8px'
102
- },
103
- children: [
104
- {
105
- type: 'button',
106
- props: {
107
- onClick: () => setCount(count - 1),
108
- style: {
109
- padding: '8px 16px',
110
- backgroundColor: '#ff4d4d',
111
- color: 'white',
112
- border: 'none',
113
- borderRadius: '4px',
114
- cursor: 'pointer'
115
- },
116
- children: 'Decrement'
117
- }
118
- },
119
- {
120
- type: 'button',
121
- props: {
122
- onClick: () => setCount(count + 1),
123
- style: {
124
- padding: '8px 16px',
125
- backgroundColor: '#4d79ff',
126
- color: 'white',
127
- border: 'none',
128
- borderRadius: '4px',
129
- cursor: 'pointer'
130
- },
131
- children: 'Increment'
132
- }
133
- }
134
- ]
135
- }
136
- }
137
- ]
138
- }
139
- }
140
- ]
141
- }
142
- };
143
- }
@@ -1,58 +0,0 @@
1
- export interface Todo {
2
- id: string;
3
- title: string;
4
- completed: boolean;
5
- }
6
-
7
- export interface ApiClientOptions {
8
- baseUrl: string;
9
- }
10
-
11
- export interface ApiClient {
12
- getTodos: () => Promise<Todo[]>;
13
- getTodo: (id: string) => Promise<Todo>;
14
- addTodo: (todo: Omit<Todo, 'id'>) => Promise<Todo>;
15
- updateTodo: (id: string, updates: Partial<Omit<Todo, 'id'>>) => Promise<Todo>;
16
- deleteTodo: (id: string) => Promise<void>;
17
- }
18
-
19
- export function createApiClient(options: ApiClientOptions): ApiClient {
20
- const { baseUrl } = options;
21
-
22
- async function fetchJson<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
23
- const response = await fetch(`${baseUrl}${endpoint}`, {
24
- ...options,
25
- headers: {
26
- 'Content-Type': 'application/json',
27
- ...options.headers,
28
- },
29
- });
30
-
31
- if (!response.ok) {
32
- const error = await response.text();
33
- throw new Error(error || `API request failed with status ${response.status}`);
34
- }
35
-
36
- return response.json();
37
- }
38
-
39
- return {
40
- getTodos: () => fetchJson<Todo[]>('/todos'),
41
-
42
- getTodo: (id: string) => fetchJson<Todo>(`/todos/${id}`),
43
-
44
- addTodo: (todo) => fetchJson<Todo>('/todos', {
45
- method: 'POST',
46
- body: JSON.stringify(todo),
47
- }),
48
-
49
- updateTodo: (id: string, updates) => fetchJson<Todo>(`/todos/${id}`, {
50
- method: 'PATCH',
51
- body: JSON.stringify(updates),
52
- }),
53
-
54
- deleteTodo: (id: string) => fetchJson<void>(`/todos/${id}`, {
55
- method: 'DELETE',
56
- }),
57
- };
58
- }
@@ -1,26 +0,0 @@
1
- import { useState } from 'front-package';
2
-
3
- export function Counter() {
4
- const [count, setCount] = useState(0);
5
-
6
- return (
7
- <div className="text-center">
8
- <h2 className="text-xl font-bold mb-4">Counter Example</h2>
9
- <p className="mb-4">Count: <span className="font-bold">{count}</span></p>
10
- <div className="flex justify-center gap-2">
11
- <button
12
- onClick={() => setCount(count - 1)}
13
- className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition"
14
- >
15
- Decrement
16
- </button>
17
- <button
18
- onClick={() => setCount(count + 1)}
19
- className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition"
20
- >
21
- Increment
22
- </button>
23
- </div>
24
- </div>
25
- );
26
- }
@@ -1,9 +0,0 @@
1
- export function Header({ title }: { title: string }) {
2
- return (
3
- <header className="bg-primary-600 text-white shadow-lg">
4
- <div className="container mx-auto px-4 py-6">
5
- <h1 className="text-2xl font-bold">{title}</h1>
6
- </div>
7
- </header>
8
- );
9
- }