frontend-hamroun 1.2.7 → 1.2.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "A lightweight frontend and backend framework for building modern web applications",
5
5
  "type": "module",
6
6
  "main": "dist/frontend-hamroun.umd.js",
@@ -491,3 +491,245 @@ fs.chmodSync(path.join(binDir, 'cli.cjs'), '755');
491
491
  console.log('✅ Created CJS wrapper: bin/cli.cjs');
492
492
 
493
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
+ }
@@ -0,0 +1,10 @@
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,4 +1,4 @@
1
- import { useState, useEffect, useContext } from 'frontend-hamroun';
1
+ import { useState, useEffect, useContext, useRef } from 'frontend-hamroun';
2
2
  import { Header } from './components/Header';
3
3
  import { Counter } from './components/Counter';
4
4
  import { ApiClient } from './api.js';
@@ -9,109 +9,135 @@ interface AppProps {
9
9
  api: ApiClient;
10
10
  }
11
11
 
12
- export function App({ api }: AppProps) {
13
- const [todos, setTodos] = useState([]);
14
- const [isLoading, setIsLoading] = useState(true);
15
- const [error, setError] = useState<string | null>(null);
12
+ // Use function declaration style instead of JSX component syntax
13
+ export function App(props: any) {
16
14
  const [count, setCount] = useState(0);
17
- const { theme } = useContext(AppContext);
18
-
19
- useEffect(() => {
20
- // Fetch data when component mounts
21
- async function fetchData() {
22
- try {
23
- setIsLoading(true);
24
- const data = await api.getTodos();
25
- setTodos(data);
26
- setError(null);
27
- } catch (err) {
28
- setError('Failed to fetch todos');
29
- console.error(err);
30
- } finally {
31
- setIsLoading(false);
32
- }
33
- }
34
-
35
- fetchData();
36
- }, [api]);
37
-
38
- return (
39
- <div className="min-h-screen bg-gray-50">
40
- <Header title="My Front Package App" />
41
-
42
- <main className="container mx-auto px-4 py-8">
43
- <h1 className="text-3xl font-bold text-center mb-8">
44
- Welcome to your Front Package app!
45
- </h1>
46
-
47
- <div className="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl mb-8">
48
- <div className="p-8">
49
- <Counter />
50
- </div>
51
- </div>
52
-
53
- <div className="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
54
- <div className="p-8">
55
- <h2 className="text-xl font-bold mb-4">Todo List</h2>
56
- {isLoading ? (
57
- <div className="text-center py-4">Loading...</div>
58
- ) : error ? (
59
- <div className="text-red-500 py-4">{error}</div>
60
- ) : (
61
- <TodoList todos={todos} api={api} setTodos={setTodos} />
62
- )}
63
- </div>
64
- </div>
65
-
66
- <div style={{ fontFamily: 'Arial, sans-serif', maxWidth: '600px', margin: '0 auto', padding: '2rem' }}>
67
- <h1 style={{ color: '#333', textAlign: 'center' }}>Frontend Hamroun App</h1>
68
- <p style={{ textAlign: 'center' }}>
69
- Current theme: <strong>{theme}</strong>
70
- </p>
71
- <div style={{
72
- display: 'flex',
73
- flexDirection: 'column',
74
- alignItems: 'center',
75
- marginTop: '2rem',
76
- padding: '1rem',
77
- border: '1px solid #ccc',
78
- borderRadius: '8px',
79
- backgroundColor: theme === 'dark' ? '#333' : '#fff',
80
- color: theme === 'dark' ? '#fff' : '#333'
81
- }}>
82
- <h2>Counter Example</h2>
83
- <p>Count: {count}</p>
84
- <div style={{ display: 'flex', gap: '8px' }}>
85
- <button
86
- onClick={() => setCount(count - 1)}
87
- style={{
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: {
88
60
  padding: '8px 16px',
89
- background: '#ff4d4d',
61
+ backgroundColor: '#4b5563',
90
62
  color: 'white',
91
63
  border: 'none',
92
64
  borderRadius: '4px',
93
65
  cursor: 'pointer'
94
- }}
95
- >
96
- Decrement
97
- </button>
98
- <button
99
- onClick={() => setCount(count + 1)}
100
- style={{
101
- padding: '8px 16px',
102
- background: '#4d79ff',
103
- color: 'white',
104
- border: 'none',
105
- borderRadius: '4px',
106
- cursor: 'pointer'
107
- }}
108
- >
109
- Increment
110
- </button>
111
- </div>
112
- </div>
113
- </div>
114
- </main>
115
- </div>
116
- );
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
+ };
117
143
  }
@@ -141,21 +141,13 @@ function ContextConsumer() {
141
141
  );
142
142
  }
143
143
 
144
- import { render, createContext } from 'frontend-hamroun';
144
+ import { render } from 'frontend-hamroun';
145
145
  import { App } from './App';
146
146
 
147
- // Create an example context
148
- export const AppContext = createContext({ theme: 'light' });
149
-
150
147
  document.addEventListener('DOMContentLoaded', () => {
151
148
  const rootElement = document.getElementById('app');
152
149
  if (rootElement) {
153
- render(
154
- <AppContext.Provider value={{ theme: 'light' }}>
155
- <App />
156
- </AppContext.Provider>,
157
- rootElement
158
- );
150
+ render(App({}), rootElement);
159
151
  console.log('App rendered successfully');
160
152
  }
161
153
  });
@@ -10,9 +10,6 @@
10
10
  "resolveJsonModule": true,
11
11
  "isolatedModules": true,
12
12
  "noEmit": true,
13
- "jsx": "react-jsx",
14
- "jsxFactory": "jsx",
15
- "jsxFragmentFactory": "Fragment",
16
13
  "strict": true,
17
14
  "noUnusedLocals": true,
18
15
  "noUnusedParameters": true,
@@ -0,0 +1,10 @@
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
+ }
@@ -2,31 +2,19 @@ import { defineConfig } from 'vite';
2
2
  import { nodePolyfills } from 'vite-plugin-node-polyfills';
3
3
 
4
4
  export default defineConfig({
5
- esbuild: {
6
- jsxFactory: 'jsx',
7
- jsxFragment: 'Fragment',
8
- jsxInject: `import { jsx, Fragment } from 'frontend-hamroun'`
9
- },
10
5
  build: {
11
6
  outDir: 'dist',
12
7
  emptyOutDir: true,
13
8
  rollupOptions: {
14
- // Mark server dependencies as external
9
+ // Mark server-side dependencies as external
15
10
  external: [
16
- 'mock-aws-s3',
17
- 'aws-sdk',
18
- 'nock',
19
- 'jest',
20
- 'jest-mock',
21
- '@testing-library/react',
22
- '@testing-library/jest-dom',
23
- 'bcrypt',
24
- 'jsonwebtoken',
25
- 'mongoose',
26
11
  'express',
27
12
  'compression',
28
13
  'helmet',
29
14
  'morgan',
15
+ 'bcrypt',
16
+ 'jsonwebtoken',
17
+ 'mongoose',
30
18
  /node:.*/
31
19
  ]
32
20
  }
@@ -0,0 +1,10 @@
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
+ }