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,1107 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { execSync } from 'child_process';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
- const rootDir = path.resolve(__dirname, '..');
9
- const binDir = path.resolve(rootDir, 'bin');
10
-
11
- // Ensure bin directory exists
12
- if (!fs.existsSync(binDir)) {
13
- fs.mkdirSync(binDir, { recursive: true });
14
- }
15
-
16
- // Create CLI entrypoint using ES modules
17
- const cliContent = `#!/usr/bin/env node
18
-
19
- import fs from 'fs';
20
- import path from 'path';
21
- import { fileURLToPath } from 'url';
22
- import { execSync } from 'child_process';
23
-
24
- const __filename = fileURLToPath(import.meta.url);
25
- const __dirname = path.dirname(__filename);
26
-
27
- // Templates available
28
- const TEMPLATES = {
29
- 'basic': 'Basic frontend only template',
30
- 'full-stack': 'Complete frontend and backend template'
31
- };
32
-
33
- // Colors for CLI output
34
- const colors = {
35
- reset: '\\x1b[0m',
36
- bright: '\\x1b[1m',
37
- green: '\\x1b[32m',
38
- blue: '\\x1b[34m',
39
- red: '\\x1b[31m',
40
- yellow: '\\x1b[33m'
41
- };
42
-
43
- // Get package.json to read version
44
- const packageJsonPath = path.resolve(__dirname, '../package.json');
45
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
46
-
47
- // Print banner
48
- function printBanner() {
49
- console.log(\`
50
- \${colors.blue}\${colors.bright}╔══════════════════════════════════════════════╗
51
- ║ ║
52
- ║ Frontend Hamroun v\${packageJson.version.padEnd(25)}║
53
- ║ A lightweight frontend & backend framework ║
54
- ║ ║
55
- ╚══════════════════════════════════════════════╝\${colors.reset}
56
- \`);
57
- }
58
-
59
- // Print help
60
- function printHelp() {
61
- console.log(\`
62
- \${colors.bright}USAGE:\${colors.reset}
63
- \${colors.blue}npx frontend-hamroun\${colors.reset} [command] [options]
64
-
65
- \${colors.bright}COMMANDS:\${colors.reset}
66
- \${colors.blue}create\${colors.reset} <project-name> [options] Create a new project
67
- \${colors.blue}help\${colors.reset} Display this help message
68
- \${colors.blue}version\${colors.reset} Display version information
69
-
70
- \${colors.bright}OPTIONS:\${colors.reset}
71
- \${colors.blue}--template\${colors.reset}, \${colors.blue}-t\${colors.reset} <template> Specify template (default: basic)
72
- \${colors.blue}--skip-install\${colors.reset}, \${colors.blue}-s\${colors.reset} Skip package installation
73
-
74
- \${colors.bright}AVAILABLE TEMPLATES:\${colors.reset}
75
- \${Object.entries(TEMPLATES).map(([name, desc]) => \` \${colors.blue}\${name.padEnd(12)}\${colors.reset} \${desc}\`).join('\\n')}
76
-
77
- \${colors.bright}EXAMPLES:\${colors.reset}
78
- \${colors.blue}npx frontend-hamroun create\${colors.reset} my-app
79
- \${colors.blue}npx frontend-hamroun create\${colors.reset} my-app --template full-stack
80
- \`);
81
- }
82
-
83
- // Create project from template
84
- function createProject(projectName, options) {
85
- const template = options.template || 'basic';
86
-
87
- // Check if template exists
88
- if (!Object.keys(TEMPLATES).includes(template)) {
89
- console.error(\`\${colors.red}error:\${colors.reset} Template "\${template}" not found.\`);
90
- console.log(\`Available templates: \${Object.keys(TEMPLATES).join(', ')}\`);
91
- process.exit(1);
92
- }
93
-
94
- // Check if project directory already exists
95
- const projectPath = path.resolve(process.cwd(), projectName);
96
- if (fs.existsSync(projectPath)) {
97
- console.error(\`\${colors.red}error:\${colors.reset} Directory \${projectName} already exists.\`);
98
- process.exit(1);
99
- }
100
-
101
- console.log(\`
102
- \${colors.bright}Creating a new project with Frontend Hamroun...\${colors.reset}
103
- \${colors.blue}• Project name:\${colors.reset} \${projectName}
104
- \${colors.blue}• Template:\${colors.reset} \${template}
105
- \${colors.blue}• Directory:\${colors.reset} \${projectPath}
106
- \`);
107
-
108
- try {
109
- // Find templates directory
110
- const templateDir = path.resolve(__dirname, '../templates', template);
111
-
112
- if (!fs.existsSync(templateDir)) {
113
- console.error(\`\${colors.red}error:\${colors.reset} Template directory not found: \${templateDir}\`);
114
- // Try to find template with -app suffix as fallback
115
- const fallbackTemplateDir = path.resolve(__dirname, '../templates', \`\${template}-app\`);
116
- if (fs.existsSync(fallbackTemplateDir)) {
117
- console.log(\`\${colors.yellow}Using fallback template:\${colors.reset} \${template}-app\`);
118
- templateDir = fallbackTemplateDir;
119
- } else {
120
- process.exit(1);
121
- }
122
- }
123
-
124
- // Create project directory
125
- fs.mkdirSync(projectPath, { recursive: true });
126
-
127
- // Copy template files (recursive function)
128
- function copyDir(src, dest) {
129
- const entries = fs.readdirSync(src, { withFileTypes: true });
130
-
131
- for (const entry of entries) {
132
- const srcPath = path.join(src, entry.name);
133
- const destPath = path.join(dest, entry.name);
134
-
135
- if (entry.isDirectory()) {
136
- fs.mkdirSync(destPath, { recursive: true });
137
- copyDir(srcPath, destPath);
138
- } else {
139
- fs.copyFileSync(srcPath, destPath);
140
- }
141
- }
142
- }
143
-
144
- // Copy the files
145
- copyDir(templateDir, projectPath);
146
- console.log(\`\${colors.green}•\${colors.reset} Copied template files\`);
147
-
148
- // Update package.json with project name
149
- const projectPackageJsonPath = path.join(projectPath, 'package.json');
150
- if (fs.existsSync(projectPackageJsonPath)) {
151
- const projectPackageJson = JSON.parse(fs.readFileSync(projectPackageJsonPath, 'utf8'));
152
- projectPackageJson.name = projectName;
153
- fs.writeFileSync(
154
- projectPackageJsonPath,
155
- JSON.stringify(projectPackageJson, null, 2)
156
- );
157
- }
158
-
159
- // Install dependencies
160
- if (!options.skipInstall) {
161
- console.log(\`\\n\${colors.blue}Installing dependencies...\${colors.reset}\`);
162
-
163
- try {
164
- execSync(\`npm install\`, {
165
- cwd: projectPath,
166
- stdio: 'inherit'
167
- });
168
- } catch (error) {
169
- console.error(\`\\n\${colors.red}Failed to install dependencies. You can install them manually:\${colors.reset}\`);
170
- console.log(\` cd \${projectName} && npm install\`);
171
- }
172
- }
173
-
174
- // Success message
175
- console.log(\`
176
- \${colors.green}\${colors.bright}Success!\${colors.reset} Created \${projectName} at \${projectPath}
177
-
178
- \${colors.blue}Inside that directory, you can run several commands:\${colors.reset}
179
-
180
- \${colors.bright}npm run dev\${colors.reset}
181
- Starts the development server.
182
-
183
- \${colors.bright}npm run build\${colors.reset}
184
- Builds the app for production.
185
-
186
- \${colors.bright}npm start\${colors.reset}
187
- Runs the built app in production mode.
188
-
189
- \${colors.blue}We suggest that you begin by typing:\${colors.reset}
190
-
191
- \${colors.bright}cd\${colors.reset} \${projectName}
192
- \${colors.bright}npm run dev\${colors.reset}
193
-
194
- \${colors.green}Happy coding!\${colors.reset}
195
- \`);
196
-
197
- } catch (error) {
198
- console.error(\`\${colors.red}Failed to create project:\${colors.reset}\`, error);
199
- process.exit(1);
200
- }
201
- }
202
-
203
- // Parse command line arguments
204
- function parseArgs() {
205
- const args = process.argv.slice(2);
206
- const command = args[0];
207
-
208
- if (!command || command === 'help') {
209
- printBanner();
210
- printHelp();
211
- process.exit(0);
212
- }
213
-
214
- if (command === 'version') {
215
- console.log(\`frontend-hamroun v\${packageJson.version}\`);
216
- process.exit(0);
217
- }
218
-
219
- if (command === 'create') {
220
- const projectName = args[1];
221
-
222
- if (!projectName) {
223
- console.error(\`\${colors.red}error:\${colors.reset} Project name is required.\`);
224
- console.log(\`Run \${colors.blue}npx frontend-hamroun help\${colors.reset} for usage information.\`);
225
- process.exit(1);
226
- }
227
-
228
- // Parse options
229
- const options = {
230
- template: 'basic',
231
- skipInstall: false
232
- };
233
-
234
- for (let i = 2; i < args.length; i++) {
235
- if (args[i] === '--template' || args[i] === '-t') {
236
- options.template = args[++i];
237
- } else if (args[i] === '--skip-install' || args[i] === '-s') {
238
- options.skipInstall = true;
239
- }
240
- }
241
-
242
- printBanner();
243
- createProject(projectName, options);
244
- return;
245
- }
246
-
247
- console.error(\`\${colors.red}error:\${colors.reset} Unknown command: \${command}\`);
248
- console.log(\`Run \${colors.blue}npx frontend-hamroun help\${colors.reset} for usage information.\`);
249
- process.exit(1);
250
- }
251
-
252
- // Run CLI
253
- parseArgs();
254
- `;
255
-
256
- // Write CLI file with .mjs extension for ES modules
257
- fs.writeFileSync(path.join(binDir, 'cli.mjs'), cliContent, 'utf8');
258
-
259
- // Make CLI executable
260
- try {
261
- fs.chmodSync(path.join(binDir, 'cli.mjs'), '755');
262
- console.log('✅ CLI built successfully: bin/cli.mjs');
263
- } catch (error) {
264
- console.warn('⚠️ Could not make CLI executable:', error);
265
- }
266
-
267
- // Let's make sure we also have template directories
268
- const templatesDir = path.resolve(rootDir, 'templates');
269
- const templateList = ['basic', 'full-stack'];
270
-
271
- console.log('🔍 Checking template directories...');
272
- for (const template of templateList) {
273
- const templateDir = path.join(templatesDir, template);
274
- const appTemplateDir = path.join(templatesDir, `${template}-app`);
275
-
276
- // Check if either directory exists
277
- if (!fs.existsSync(templateDir) && !fs.existsSync(appTemplateDir)) {
278
- console.log(`⚠️ Template directory "${template}" not found at: ${templateDir}`);
279
- console.log(`⚠️ Template directory "${template}-app" not found at: ${appTemplateDir}`);
280
-
281
- // Create the template directory
282
- console.log(`📁 Creating template directory: ${template}`);
283
- fs.mkdirSync(templateDir, { recursive: true });
284
-
285
- // Create a minimal template
286
- console.log(`📝 Creating minimal ${template} template`);
287
-
288
- // Create package.json
289
- const packageJson = {
290
- "name": "frontend-hamroun-app",
291
- "private": true,
292
- "version": "0.1.0",
293
- "type": "module",
294
- "scripts": {
295
- "dev": "vite",
296
- "build": "tsc && vite build",
297
- "preview": "vite preview"
298
- },
299
- "dependencies": {
300
- "frontend-hamroun": "latest"
301
- },
302
- "devDependencies": {
303
- "@types/node": "^20.10.0",
304
- "typescript": "^5.3.2",
305
- "vite": "^5.0.0"
306
- }
307
- };
308
-
309
- fs.writeFileSync(
310
- path.join(templateDir, 'package.json'),
311
- JSON.stringify(packageJson, null, 2)
312
- );
313
-
314
- // Create minimal files for the template
315
- fs.writeFileSync(
316
- path.join(templateDir, 'index.html'),
317
- `<!DOCTYPE html>
318
- <html lang="en">
319
- <head>
320
- <meta charset="UTF-8">
321
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
322
- <title>Frontend Hamroun App</title>
323
- </head>
324
- <body>
325
- <div id="app"></div>
326
- <script type="module" src="/src/main.ts"></script>
327
- </body>
328
- </html>`
329
- );
330
-
331
- // Create src directory
332
- const srcDir = path.join(templateDir, 'src');
333
- fs.mkdirSync(srcDir, { recursive: true });
334
-
335
- // Create basic files
336
- fs.writeFileSync(
337
- path.join(srcDir, 'main.ts'),
338
- `import { render } from 'frontend-hamroun';
339
- import { App } from './App';
340
-
341
- document.addEventListener('DOMContentLoaded', () => {
342
- const rootElement = document.getElementById('app');
343
- if (rootElement) {
344
- render(<App />, rootElement);
345
- }
346
- });`
347
- );
348
-
349
- fs.writeFileSync(
350
- path.join(srcDir, 'App.tsx'),
351
- `import { useState } from 'frontend-hamroun';
352
-
353
- export function App() {
354
- const [count, setCount] = useState(0);
355
-
356
- return (
357
- <div style={{ fontFamily: 'Arial, sans-serif', maxWidth: '600px', margin: '0 auto', padding: '2rem' }}>
358
- <h1 style={{ color: '#333', textAlign: 'center' }}>Frontend Hamroun App</h1>
359
- <div style={{
360
- display: 'flex',
361
- flexDirection: 'column',
362
- alignItems: 'center',
363
- marginTop: '2rem',
364
- padding: '1rem',
365
- border: '1px solid #ccc',
366
- borderRadius: '8px'
367
- }}>
368
- <h2>Counter Example</h2>
369
- <p>Count: {count}</p>
370
- <div style={{ display: 'flex', gap: '8px' }}>
371
- <button
372
- onClick={() => setCount(count - 1)}
373
- style={{
374
- padding: '8px 16px',
375
- background: '#ff4d4d',
376
- color: 'white',
377
- border: 'none',
378
- borderRadius: '4px',
379
- cursor: 'pointer'
380
- }}
381
- >
382
- Decrement
383
- </button>
384
- <button
385
- onClick={() => setCount(count + 1)}
386
- style={{
387
- padding: '8px 16px',
388
- background: '#4d79ff',
389
- color: 'white',
390
- border: 'none',
391
- borderRadius: '4px',
392
- cursor: 'pointer'
393
- }}
394
- >
395
- Increment
396
- </button>
397
- </div>
398
- </div>
399
- </div>
400
- );
401
- }`
402
- );
403
-
404
- // Create vite.config.ts
405
- fs.writeFileSync(
406
- path.join(templateDir, 'vite.config.ts'),
407
- `import { defineConfig } from 'vite';
408
-
409
- export default defineConfig({
410
- esbuild: {
411
- jsxFactory: 'jsx',
412
- jsxFragment: 'Fragment'
413
- },
414
- build: {
415
- outDir: 'dist',
416
- emptyOutDir: true
417
- }
418
- });`
419
- );
420
-
421
- // Create tsconfig files
422
- fs.writeFileSync(
423
- path.join(templateDir, 'tsconfig.json'),
424
- `{
425
- "compilerOptions": {
426
- "target": "ES2020",
427
- "useDefineForClassFields": true,
428
- "module": "ESNext",
429
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
430
- "skipLibCheck": true,
431
- "moduleResolution": "bundler",
432
- "allowImportingTsExtensions": true,
433
- "resolveJsonModule": true,
434
- "isolatedModules": true,
435
- "noEmit": true,
436
- "jsx": "preserve",
437
- "strict": true,
438
- "noUnusedLocals": true,
439
- "noUnusedParameters": true,
440
- "noFallthroughCasesInSwitch": true
441
- },
442
- "include": ["src"],
443
- "references": [{ "path": "./tsconfig.node.json" }]
444
- }`
445
- );
446
-
447
- fs.writeFileSync(
448
- path.join(templateDir, 'tsconfig.node.json'),
449
- `{
450
- "compilerOptions": {
451
- "composite": true,
452
- "module": "ESNext",
453
- "moduleResolution": "bundler",
454
- "allowSyntheticDefaultImports": true
455
- },
456
- "include": ["vite.config.ts"]
457
- }`
458
- );
459
-
460
- console.log(`✅ Created minimal ${template} template`);
461
- } else {
462
- if (fs.existsSync(templateDir)) {
463
- console.log(`✅ Template found: ${template}`);
464
- } else {
465
- console.log(`✅ Template found: ${template}-app (will use as fallback)`);
466
- }
467
- }
468
- }
469
-
470
- // Create a CJS wrapper for environments that don't support ESM out of the box
471
- const cjsWrapper = `#!/usr/bin/env node
472
- // This file is a CommonJS wrapper for the ES module CLI
473
- // It loads the actual CLI implementation using dynamic import()
474
-
475
- async function main() {
476
- try {
477
- // Use dynamic import to load the ES module CLI
478
- const cliPath = new URL('../bin/cli.mjs', import.meta.url).href;
479
- await import(cliPath);
480
- } catch (error) {
481
- console.error('Error loading CLI:', error);
482
- process.exit(1);
483
- }
484
- }
485
-
486
- main();
487
- `;
488
-
489
- fs.writeFileSync(path.join(binDir, 'cli.cjs'), cjsWrapper, 'utf8');
490
- fs.chmodSync(path.join(binDir, 'cli.cjs'), '755');
491
- console.log('✅ Created CJS wrapper: bin/cli.cjs');
492
-
493
- console.log('✅ CLI build process completed');
494
-
495
- // Create a minimal basic template (update existing code)
496
- function createBasicTemplate(templateDir) {
497
- console.log(`📝 Creating minimal basic template at ${templateDir}`);
498
-
499
- // Create package.json
500
- const packageJson = {
501
- "name": "frontend-hamroun-app",
502
- "private": true,
503
- "version": "0.1.0",
504
- "type": "module",
505
- "scripts": {
506
- "dev": "vite",
507
- "build": "tsc && vite build",
508
- "preview": "vite preview"
509
- },
510
- "dependencies": {
511
- "frontend-hamroun": "latest"
512
- },
513
- "devDependencies": {
514
- "@types/node": "^20.10.0",
515
- "typescript": "^5.3.2",
516
- "vite": "^5.0.0",
517
- "vite-plugin-node-polyfills": "^0.21.0"
518
- }
519
- };
520
-
521
- fs.writeFileSync(
522
- path.join(templateDir, 'package.json'),
523
- JSON.stringify(packageJson, null, 2)
524
- );
525
-
526
- // Create index.html
527
- fs.writeFileSync(
528
- path.join(templateDir, 'index.html'),
529
- `<!DOCTYPE html>
530
- <html lang="en">
531
- <head>
532
- <meta charset="UTF-8">
533
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
534
- <title>Frontend Hamroun App</title>
535
- </head>
536
- <body>
537
- <div id="app"></div>
538
- <script type="module" src="/src/main.ts"></script>
539
- </body>
540
- </html>`
541
- );
542
-
543
- // Create src directory
544
- const srcDir = path.join(templateDir, 'src');
545
- fs.mkdirSync(srcDir, { recursive: true });
546
-
547
- // Create main.ts
548
- fs.writeFileSync(
549
- path.join(srcDir, 'main.ts'),
550
- `import { render } from 'frontend-hamroun';
551
- import { App } from './App';
552
-
553
- document.addEventListener('DOMContentLoaded', () => {
554
- const rootElement = document.getElementById('app');
555
- if (rootElement) {
556
- render(App({}), rootElement);
557
- console.log('App rendered successfully');
558
- }
559
- });`
560
- );
561
-
562
- // Create App.ts (not App.tsx)
563
- fs.writeFileSync(
564
- path.join(srcDir, 'App.ts'),
565
- `import { useState, useRef } from 'frontend-hamroun';
566
-
567
- export function App(props) {
568
- const [count, setCount] = useState(0);
569
- const renderCount = useRef(0);
570
-
571
- renderCount.current++;
572
-
573
- return {
574
- type: 'div',
575
- props: {
576
- style: {
577
- fontFamily: 'Arial, sans-serif',
578
- maxWidth: '600px',
579
- margin: '0 auto',
580
- padding: '2rem'
581
- },
582
- children: [
583
- {
584
- type: 'h1',
585
- props: {
586
- style: { textAlign: 'center' },
587
- children: 'Frontend Hamroun App'
588
- }
589
- },
590
- {
591
- type: 'p',
592
- props: {
593
- style: { textAlign: 'center' },
594
- children: \`Render count: \${renderCount.current}\`
595
- }
596
- },
597
- {
598
- type: 'div',
599
- props: {
600
- style: {
601
- display: 'flex',
602
- flexDirection: 'column',
603
- alignItems: 'center',
604
- padding: '1rem',
605
- border: '1px solid #ccc',
606
- borderRadius: '8px'
607
- },
608
- children: [
609
- {
610
- type: 'h2',
611
- props: {
612
- children: 'Counter Example'
613
- }
614
- },
615
- {
616
- type: 'p',
617
- props: {
618
- children: \`Count: \${count}\`
619
- }
620
- },
621
- {
622
- type: 'div',
623
- props: {
624
- style: {
625
- display: 'flex',
626
- gap: '8px'
627
- },
628
- children: [
629
- {
630
- type: 'button',
631
- props: {
632
- onClick: () => setCount(count - 1),
633
- style: {
634
- padding: '8px 16px',
635
- backgroundColor: '#ff4d4d',
636
- color: 'white',
637
- border: 'none',
638
- borderRadius: '4px',
639
- cursor: 'pointer'
640
- },
641
- children: 'Decrement'
642
- }
643
- },
644
- {
645
- type: 'button',
646
- props: {
647
- onClick: () => setCount(count + 1),
648
- style: {
649
- padding: '8px 16px',
650
- backgroundColor: '#4d79ff',
651
- color: 'white',
652
- border: 'none',
653
- borderRadius: '4px',
654
- cursor: 'pointer'
655
- },
656
- children: 'Increment'
657
- }
658
- }
659
- ]
660
- }
661
- }
662
- ]
663
- }
664
- }
665
- ]
666
- }
667
- };
668
- }`
669
- );
670
-
671
- // Create vite.config.ts
672
- fs.writeFileSync(
673
- path.join(templateDir, 'vite.config.ts'),
674
- `import { defineConfig } from 'vite';
675
- import { nodePolyfills } from 'vite-plugin-node-polyfills';
676
-
677
- export default defineConfig({
678
- build: {
679
- outDir: 'dist',
680
- emptyOutDir: true
681
- },
682
- server: {
683
- port: 3000,
684
- open: true
685
- },
686
- plugins: [
687
- nodePolyfills({
688
- protocolImports: true,
689
- }),
690
- ]
691
- });`
692
- );
693
-
694
- // Create tsconfig.json
695
- fs.writeFileSync(
696
- path.join(templateDir, 'tsconfig.json'),
697
- `{
698
- "compilerOptions": {
699
- "target": "ES2020",
700
- "useDefineForClassFields": true,
701
- "module": "ESNext",
702
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
703
- "skipLibCheck": true,
704
- "moduleResolution": "bundler",
705
- "allowImportingTsExtensions": true,
706
- "resolveJsonModule": true,
707
- "isolatedModules": true,
708
- "noEmit": true,
709
- "strict": true,
710
- "noUnusedLocals": true,
711
- "noUnusedParameters": true,
712
- "noFallthroughCasesInSwitch": true
713
- },
714
- "include": ["src"],
715
- "references": [{ "path": "./tsconfig.node.json" }]
716
- }`
717
- );
718
-
719
- // Create tsconfig.node.json
720
- fs.writeFileSync(
721
- path.join(templateDir, 'tsconfig.node.json'),
722
- `{
723
- "compilerOptions": {
724
- "composite": true,
725
- "skipLibCheck": true,
726
- "module": "ESNext",
727
- "moduleResolution": "bundler",
728
- "allowSyntheticDefaultImports": true
729
- },
730
- "include": ["vite.config.ts"]
731
- }`
732
- );
733
-
734
- console.log(`✅ Created minimal basic template at ${templateDir}`);
735
-
736
- // Create React compatibility layer
737
- createReactCompatibilityLayer(templateDir);
738
- }
739
-
740
- // Create React compatibility layer
741
- function createReactCompatibilityLayer(templateDir) {
742
- // Create React compatibility directory
743
- const reactDir = path.join(templateDir, 'src/react');
744
- if (!fs.existsSync(reactDir)) {
745
- fs.mkdirSync(reactDir, { recursive: true });
746
- }
747
-
748
- // Create jsx-dev-runtime.ts
749
- fs.writeFileSync(
750
- path.join(reactDir, 'jsx-dev-runtime.ts'),
751
- `import { jsx } from 'frontend-hamroun';
752
-
753
- // Export jsx as jsxDEV for React compatibility
754
- export const jsxDEV = jsx;
755
- export const Fragment = Symbol('Fragment');
756
- export const jsxs = jsx;
757
-
758
- // Default export
759
- export default {
760
- jsxDEV,
761
- Fragment,
762
- jsxs
763
- };`
764
- );
765
-
766
- // Create jsx-runtime.ts
767
- fs.writeFileSync(
768
- path.join(reactDir, 'jsx-runtime.ts'),
769
- `import { jsx } from 'frontend-hamroun';
770
-
771
- // Export jsx functions for React compatibility
772
- export const jsxs = jsx;
773
- export const Fragment = Symbol('Fragment');
774
-
775
- // Default export
776
- export default {
777
- jsx,
778
- jsxs,
779
- Fragment
780
- };`
781
- );
782
-
783
- // Create index.ts
784
- fs.writeFileSync(
785
- path.join(reactDir, 'index.ts'),
786
- `import {
787
- useState,
788
- useEffect,
789
- useRef,
790
- useMemo,
791
- useContext,
792
- createContext,
793
- jsx
794
- } from 'frontend-hamroun';
795
-
796
- // Provide React compatibility layer
797
- const React = {
798
- createElement: jsx,
799
- Fragment: Symbol('Fragment'),
800
- useState,
801
- useEffect,
802
- useRef,
803
- useMemo,
804
- useContext,
805
- createContext
806
- };
807
-
808
- // Export hooks directly for named imports
809
- export {
810
- useState,
811
- useEffect,
812
- useRef,
813
- useMemo,
814
- useContext,
815
- createContext,
816
- jsx as createElement
817
- };
818
-
819
- // Default export
820
- export default React;`
821
- );
822
-
823
- console.log(`✅ Created React compatibility layer in ${templateDir}`);
824
- }
825
-
826
- // Create React compatibility shims
827
- function createTemplateShims(templateDir) {
828
- // Create src directory if it doesn't exist
829
- const srcDir = path.join(templateDir, 'src');
830
- if (!fs.existsSync(srcDir)) {
831
- fs.mkdirSync(srcDir, { recursive: true });
832
- }
833
-
834
- // Create shims.ts file for React JSX compatibility
835
- fs.writeFileSync(
836
- path.join(srcDir, 'shims.ts'),
837
- `// This file provides compatibility shims for React JSX imports
838
-
839
- import { jsx } from 'frontend-hamroun';
840
-
841
- // Export the jsx function as jsxDEV for React compatibility
842
- export const jsxDEV = jsx;
843
-
844
- // Export a Fragment symbol
845
- export const Fragment = Symbol('Fragment');
846
-
847
- // Default export as React compatibility layer
848
- export default {
849
- createElement: jsx,
850
- Fragment
851
- };
852
- `
853
- );
854
-
855
- console.log(`✅ Created React compatibility shims in ${templateDir}`);
856
- }
857
-
858
- // Create a function to create a pure non-JSX template
859
- function createPureTemplate(templateDir) {
860
- console.log(`📝 Creating pure JS template at ${templateDir}`);
861
-
862
- // Create package.json without React dependencies
863
- const packageJson = {
864
- "name": "frontend-hamroun-app",
865
- "private": true,
866
- "version": "0.1.0",
867
- "type": "module",
868
- "scripts": {
869
- "dev": "vite",
870
- "build": "tsc && vite build",
871
- "preview": "vite preview"
872
- },
873
- "dependencies": {
874
- "frontend-hamroun": "latest"
875
- },
876
- "devDependencies": {
877
- "@types/node": "^20.10.0",
878
- "typescript": "^5.3.2",
879
- "vite": "^5.0.0",
880
- "vite-plugin-node-polyfills": "^0.21.0"
881
- }
882
- };
883
-
884
- fs.writeFileSync(
885
- path.join(templateDir, 'package.json'),
886
- JSON.stringify(packageJson, null, 2)
887
- );
888
-
889
- // Create index.html
890
- fs.writeFileSync(
891
- path.join(templateDir, 'index.html'),
892
- `<!DOCTYPE html>
893
- <html lang="en">
894
- <head>
895
- <meta charset="UTF-8">
896
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
897
- <title>Frontend Hamroun App</title>
898
- </head>
899
- <body>
900
- <div id="app"></div>
901
- <script type="module" src="/src/main.js"></script>
902
- </body>
903
- </html>`
904
- );
905
-
906
- // Create src directory
907
- const srcDir = path.join(templateDir, 'src');
908
- fs.mkdirSync(srcDir, { recursive: true });
909
-
910
- // Create pure JS main.js without any JSX
911
- fs.writeFileSync(
912
- path.join(srcDir, 'main.js'),
913
- `import { render } from 'frontend-hamroun';
914
- import { App } from './App.js';
915
-
916
- document.addEventListener('DOMContentLoaded', () => {
917
- const rootElement = document.getElementById('app');
918
- if (rootElement) {
919
- // Call App as a function to create the VDOM structure
920
- render(App(), rootElement);
921
- console.log('App rendered successfully');
922
- }
923
- });`
924
- );
925
-
926
- // Create App.js with pure JS (no JSX or TS)
927
- fs.writeFileSync(
928
- path.join(srcDir, 'App.js'),
929
- `import { useState, useRef } from 'frontend-hamroun';
930
-
931
- export function App() {
932
- const [count, setCount] = useState(0);
933
- const renderCount = useRef(0);
934
-
935
- renderCount.current++;
936
-
937
- // Return a plain JavaScript object representation of the UI
938
- return {
939
- type: 'div',
940
- props: {
941
- style: {
942
- fontFamily: 'Arial, sans-serif',
943
- maxWidth: '600px',
944
- margin: '0 auto',
945
- padding: '2rem'
946
- },
947
- children: [
948
- {
949
- type: 'h1',
950
- props: {
951
- style: { textAlign: 'center' },
952
- children: 'Frontend Hamroun App'
953
- }
954
- },
955
- {
956
- type: 'p',
957
- props: {
958
- style: { textAlign: 'center' },
959
- children: \`Render count: \${renderCount.current}\`
960
- }
961
- },
962
- {
963
- type: 'div',
964
- props: {
965
- style: {
966
- display: 'flex',
967
- flexDirection: 'column',
968
- alignItems: 'center',
969
- padding: '1rem',
970
- border: '1px solid #ccc',
971
- borderRadius: '8px'
972
- },
973
- children: [
974
- {
975
- type: 'h2',
976
- props: {
977
- children: 'Counter Example'
978
- }
979
- },
980
- {
981
- type: 'p',
982
- props: {
983
- children: \`Count: \${count}\`
984
- }
985
- },
986
- {
987
- type: 'div',
988
- props: {
989
- style: {
990
- display: 'flex',
991
- gap: '8px'
992
- },
993
- children: [
994
- {
995
- type: 'button',
996
- props: {
997
- onClick: () => setCount(count - 1),
998
- style: {
999
- padding: '8px 16px',
1000
- backgroundColor: '#ff4d4d',
1001
- color: 'white',
1002
- border: 'none',
1003
- borderRadius: '4px',
1004
- cursor: 'pointer'
1005
- },
1006
- children: 'Decrement'
1007
- }
1008
- },
1009
- {
1010
- type: 'button',
1011
- props: {
1012
- onClick: () => setCount(count + 1),
1013
- style: {
1014
- padding: '8px 16px',
1015
- backgroundColor: '#4d79ff',
1016
- color: 'white',
1017
- border: 'none',
1018
- borderRadius: '4px',
1019
- cursor: 'pointer'
1020
- },
1021
- children: 'Increment'
1022
- }
1023
- }
1024
- ]
1025
- }
1026
- }
1027
- ]
1028
- }
1029
- }
1030
- ]
1031
- }
1032
- };
1033
- }`
1034
- );
1035
-
1036
- // Create vite.config.js - No TypeScript, no JSX
1037
- fs.writeFileSync(
1038
- path.join(templateDir, 'vite.config.js'),
1039
- `import { defineConfig } from 'vite';
1040
- import { nodePolyfills } from 'vite-plugin-node-polyfills';
1041
-
1042
- export default defineConfig({
1043
- build: {
1044
- outDir: 'dist',
1045
- emptyOutDir: true
1046
- },
1047
- server: {
1048
- port: 3000,
1049
- open: true
1050
- },
1051
- plugins: [
1052
- nodePolyfills({
1053
- protocolImports: true,
1054
- }),
1055
- ]
1056
- });`
1057
- );
1058
-
1059
- // Create jsconfig.json instead of tsconfig.json
1060
- fs.writeFileSync(
1061
- path.join(templateDir, 'jsconfig.json'),
1062
- `{
1063
- "compilerOptions": {
1064
- "target": "ES2020",
1065
- "useDefineForClassFields": true,
1066
- "module": "ESNext",
1067
- "moduleResolution": "node",
1068
- "allowSyntheticDefaultImports": true,
1069
- "resolveJsonModule": true,
1070
- "checkJs": false,
1071
- "strict": false
1072
- },
1073
- "include": ["src/**/*.js"],
1074
- "exclude": ["node_modules"]
1075
- }`
1076
- );
1077
-
1078
- console.log(`✅ Created pure JS template at ${templateDir}`);
1079
- }
1080
-
1081
- // Update the main CLI function to create only pure JS templates
1082
- console.log('🔍 Checking template directories...');
1083
- for (const template of templateList) {
1084
- const templateDir = path.join(templatesDir, template);
1085
-
1086
- if (!fs.existsSync(templateDir)) {
1087
- console.log(`⚠️ Template directory "${template}" not found at: ${templateDir}`);
1088
- console.log(`📁 Creating template directory: ${template}`);
1089
- fs.mkdirSync(templateDir, { recursive: true });
1090
-
1091
- // Create a pure JS template (no React, no JSX)
1092
- createPureTemplate(templateDir);
1093
- } else {
1094
- console.log(`✅ Template found: ${template}`);
1095
-
1096
- // Update existing template to use pure JS
1097
- const mainFile = path.join(templateDir, 'src/main.js');
1098
- if (!fs.existsSync(mainFile)) {
1099
- console.log(`⚠️ Updating template ${template} to use pure JS`);
1100
- // Create a pure JS template in this location
1101
- createPureTemplate(templateDir);
1102
- }
1103
- }
1104
- }
1105
-
1106
- // Call this function when creating templates
1107
- // ...existing code...