frontend-hamroun 1.1.90 → 1.2.0

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 (92) hide show
  1. package/dist/{src/backend → backend}/api-utils.d.ts +2 -2
  2. package/dist/backend/api-utils.js +135 -0
  3. package/dist/backend/auth.js +387 -0
  4. package/dist/{src/backend → backend}/database.d.ts +1 -1
  5. package/dist/backend/database.js +91 -0
  6. package/dist/{src/backend → backend}/model.d.ts +2 -2
  7. package/dist/backend/model.js +176 -0
  8. package/dist/{src/backend → backend}/router.d.ts +1 -1
  9. package/dist/backend/router.js +137 -0
  10. package/dist/backend/server.js +268 -0
  11. package/dist/batch.js +22 -0
  12. package/dist/cli/index.js +1 -0
  13. package/dist/{src/component.d.ts → component.d.ts} +1 -1
  14. package/dist/component.js +84 -0
  15. package/dist/components/Counter.js +2 -0
  16. package/dist/context.js +20 -0
  17. package/dist/frontend-hamroun.es.js +1680 -0
  18. package/dist/frontend-hamroun.es.js.map +1 -0
  19. package/dist/frontend-hamroun.umd.js +2 -0
  20. package/dist/frontend-hamroun.umd.js.map +1 -0
  21. package/dist/hooks.js +164 -0
  22. package/dist/index.d.ts +46 -0
  23. package/dist/index.js +52 -355
  24. package/dist/jsx-runtime/index.d.ts +9 -0
  25. package/dist/jsx-runtime/index.js +16 -0
  26. package/dist/jsx-runtime/jsx-dev-runtime.js +1 -0
  27. package/dist/jsx-runtime/jsx-runtime.js +91 -0
  28. package/dist/{src/jsx-runtime.d.ts → jsx-runtime.d.ts} +1 -1
  29. package/dist/jsx-runtime.js +192 -0
  30. package/dist/renderer.js +51 -0
  31. package/dist/{src/server-renderer.d.ts → server-renderer.d.ts} +3 -0
  32. package/dist/server-renderer.js +102 -0
  33. package/dist/vdom.js +27 -0
  34. package/package.json +38 -52
  35. package/scripts/generate.js +134 -0
  36. package/src/backend/api-utils.ts +178 -0
  37. package/src/backend/auth.ts +543 -0
  38. package/src/backend/database.ts +104 -0
  39. package/src/backend/model.ts +196 -0
  40. package/src/backend/router.ts +176 -0
  41. package/src/backend/server.ts +330 -0
  42. package/src/backend/types.ts +257 -0
  43. package/src/batch.ts +24 -0
  44. package/src/cli/index.js +22 -40
  45. package/src/component.ts +98 -0
  46. package/src/components/Counter.tsx +4 -0
  47. package/src/context.ts +32 -0
  48. package/src/hooks.ts +211 -0
  49. package/src/index.ts +113 -0
  50. package/src/jsx-runtime/index.ts +24 -0
  51. package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
  52. package/src/jsx-runtime/jsx-runtime.ts +99 -0
  53. package/src/jsx-runtime.ts +226 -0
  54. package/src/renderer.ts +55 -0
  55. package/src/server-renderer.ts +114 -0
  56. package/src/types/bcrypt.d.ts +30 -0
  57. package/src/types/jsonwebtoken.d.ts +55 -0
  58. package/src/types.d.ts +26 -0
  59. package/src/types.ts +21 -0
  60. package/src/vdom.ts +34 -0
  61. package/templates/basic-app/package.json +17 -15
  62. package/templates/basic-app/postcss.config.js +1 -0
  63. package/templates/basic-app/src/App.tsx +65 -0
  64. package/templates/basic-app/src/api.ts +58 -0
  65. package/templates/basic-app/src/components/Counter.tsx +26 -0
  66. package/templates/basic-app/src/components/Header.tsx +9 -0
  67. package/templates/basic-app/src/components/TodoList.tsx +90 -0
  68. package/templates/basic-app/src/main.ts +20 -0
  69. package/templates/basic-app/src/server.ts +99 -0
  70. package/templates/basic-app/tailwind.config.js +23 -2
  71. package/bin/cli.js +0 -371
  72. package/dist/index.js.map +0 -1
  73. package/dist/index.mjs +0 -139269
  74. package/dist/index.mjs.map +0 -1
  75. package/dist/src/index.d.ts +0 -16
  76. package/dist/test/setupTests.d.ts +0 -4
  77. /package/dist/{src/backend → backend}/auth.d.ts +0 -0
  78. /package/dist/{src/backend → backend}/server.d.ts +0 -0
  79. /package/dist/{src/backend → backend}/types.d.ts +0 -0
  80. /package/dist/{test/backend.test.d.ts → backend/types.js} +0 -0
  81. /package/dist/{src/batch.d.ts → batch.d.ts} +0 -0
  82. /package/dist/{src/cli → cli}/index.d.ts +0 -0
  83. /package/dist/{src/components → components}/Counter.d.ts +0 -0
  84. /package/dist/{src/context.d.ts → context.d.ts} +0 -0
  85. /package/dist/{src/hooks.d.ts → hooks.d.ts} +0 -0
  86. /package/dist/{src/jsx-runtime → jsx-runtime}/jsx-dev-runtime.d.ts +0 -0
  87. /package/dist/{src/jsx-runtime → jsx-runtime}/jsx-runtime.d.ts +0 -0
  88. /package/dist/{src/renderer.d.ts → renderer.d.ts} +0 -0
  89. /package/dist/{src/types.d.ts → types.d.ts} +0 -0
  90. /package/dist/{test/mockTest.d.ts → types.js} +0 -0
  91. /package/dist/{src/vdom.d.ts → vdom.d.ts} +0 -0
  92. /package/{dist/test/mongooseSetup.d.ts → src/cli/index.ts} +0 -0
package/bin/cli.js DELETED
@@ -1,371 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import inquirer from 'inquirer';
5
- import fs from 'fs-extra';
6
- import path from 'path';
7
- import { fileURLToPath } from 'url';
8
- import chalk from 'chalk';
9
- import { createSpinner } from 'nanospinner';
10
-
11
- const __filename = fileURLToPath(import.meta.url);
12
- const __dirname = path.dirname(__filename);
13
-
14
- // Component templates
15
- const FUNCTION_COMPONENT_TEMPLATE = (name) => `import { useState, useEffect } from 'frontend-hamroun';
16
-
17
- export function ${name}(props) {
18
- // State hooks
19
- const [state, setState] = useState(null);
20
-
21
- // Effect hooks
22
- useEffect(() => {
23
- // Component mounted
24
- return () => {
25
- // Component will unmount
26
- };
27
- }, []);
28
-
29
- return (
30
- <div className="${name.toLowerCase()}">
31
- <h2>${name} Component</h2>
32
- {/* Your JSX here */}
33
- </div>
34
- );
35
- }
36
- `;
37
-
38
- const CSS_TEMPLATE = (name) => `.${name.toLowerCase()} {
39
- display: flex;
40
- flex-direction: column;
41
- padding: 1rem;
42
- margin: 0.5rem;
43
- border-radius: 4px;
44
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
45
- }
46
- `;
47
-
48
- const TEST_TEMPLATE = (name) => `import { render, screen } from '@testing-library/frontend-hamroun';
49
- import { ${name} } from './${name}';
50
-
51
- describe('${name} Component', () => {
52
- test('renders correctly', () => {
53
- render(<${name} />);
54
- const element = screen.getByText('${name} Component');
55
- expect(element).toBeInTheDocument();
56
- });
57
- });
58
- `;
59
-
60
- // Dockerfile templates
61
- const DOCKERFILE_TEMPLATE = `# Stage 1: Build the application
62
- FROM node:18-alpine as build
63
-
64
- # Set working directory
65
- WORKDIR /app
66
-
67
- # Copy package files
68
- COPY package.json package-lock.json ./
69
-
70
- # Install dependencies
71
- RUN npm ci
72
-
73
- # Copy source files
74
- COPY . .
75
-
76
- # Build the application
77
- RUN npm run build
78
-
79
- # Stage 2: Serve the application
80
- FROM nginx:alpine
81
-
82
- # Copy the build output from the previous stage
83
- COPY --from=build /app/dist /usr/share/nginx/html
84
-
85
- # Expose port 80
86
- EXPOSE 80
87
-
88
- # Start nginx
89
- CMD ["nginx", "-g", "daemon off;"]
90
- `;
91
-
92
- const SSR_DOCKERFILE_TEMPLATE = `# Stage 1: Build the application
93
- FROM node:18-alpine as build
94
-
95
- # Set working directory
96
- WORKDIR /app
97
-
98
- # Copy package files
99
- COPY package.json package-lock.json ./
100
-
101
- # Install dependencies
102
- RUN npm ci
103
-
104
- # Copy source files
105
- COPY . .
106
-
107
- # Build the application
108
- RUN npm run build
109
-
110
- # Stage 2: Run the server
111
- FROM node:18-alpine
112
-
113
- WORKDIR /app
114
-
115
- # Copy package files and install production dependencies only
116
- COPY package.json package-lock.json ./
117
- RUN npm ci --production
118
-
119
- # Copy build artifacts
120
- COPY --from=build /app/dist ./dist
121
- COPY --from=build /app/server ./server
122
-
123
- # Expose port 3000
124
- EXPOSE 3000
125
-
126
- # Start the server
127
- CMD ["node", "server/index.js"]
128
- `;
129
-
130
- async function init() {
131
- const program = new Command();
132
-
133
- program
134
- .name('frontend-hamroun')
135
- .description('CLI for Frontend Hamroun framework')
136
- .version('1.0.0');
137
-
138
- // Create new project
139
- program
140
- .command('create')
141
- .description('Create a new Frontend Hamroun application')
142
- .argument('[name]', 'Project name')
143
- .action(async (name) => {
144
- const projectName = name || await askProjectName();
145
- await createProject(projectName);
146
- });
147
-
148
- // Generate component
149
- program
150
- .command('generate')
151
- .alias('g')
152
- .description('Generate a new component')
153
- .argument('<name>', 'Component name')
154
- .option('-d, --directory <directory>', 'Target directory', './src/components')
155
- .action(async (name, options) => {
156
- await generateComponent(name, options.directory);
157
- });
158
-
159
- // Add Dockerfile
160
- program
161
- .command('docker')
162
- .description('Add Dockerfile to project')
163
- .option('-s, --ssr', 'Use SSR-compatible Dockerfile')
164
- .action(async (options) => {
165
- await addDockerfile(options.ssr);
166
- });
167
-
168
- // Interactive mode if no command provided
169
- if (process.argv.length <= 2) {
170
- await interactiveMode();
171
- } else {
172
- program.parse();
173
- }
174
- }
175
-
176
- async function interactiveMode() {
177
- const { action } = await inquirer.prompt([{
178
- type: 'list',
179
- name: 'action',
180
- message: 'What would you like to do?',
181
- choices: [
182
- { name: 'Create a new project', value: 'create' },
183
- { name: 'Generate a component', value: 'generate' },
184
- { name: 'Add Dockerfile to project', value: 'docker' }
185
- ]
186
- }]);
187
-
188
- if (action === 'create') {
189
- const projectName = await askProjectName();
190
- await createProject(projectName);
191
- } else if (action === 'generate') {
192
- const { name } = await inquirer.prompt([{
193
- type: 'input',
194
- name: 'name',
195
- message: 'Component name:',
196
- validate: (input) => input ? true : 'Component name is required'
197
- }]);
198
-
199
- const { directory } = await inquirer.prompt([{
200
- type: 'input',
201
- name: 'directory',
202
- message: 'Target directory:',
203
- default: './src/components'
204
- }]);
205
-
206
- await generateComponent(name, directory);
207
- } else if (action === 'docker') {
208
- const { isSSR } = await inquirer.prompt([{
209
- type: 'confirm',
210
- name: 'isSSR',
211
- message: 'Is this a server-side rendered app?',
212
- default: false
213
- }]);
214
-
215
- await addDockerfile(isSSR);
216
- }
217
- }
218
-
219
- async function askProjectName() {
220
- const { projectName } = await inquirer.prompt([{
221
- type: 'input',
222
- name: 'projectName',
223
- message: 'What is your project named?',
224
- default: 'my-frontend-app'
225
- }]);
226
- return projectName;
227
- }
228
-
229
- async function askProjectType() {
230
- const { template } = await inquirer.prompt([{
231
- type: 'list',
232
- name: 'template',
233
- message: 'Select project type:',
234
- choices: [
235
- { name: 'Client Side App', value: 'basic-app' },
236
- { name: 'Server Side Rendered App', value: 'ssr-template' }
237
- ]
238
- }]);
239
- return template;
240
- }
241
-
242
- async function createProject(projectName) {
243
- const spinner = createSpinner('Creating project...').start();
244
-
245
- try {
246
- const template = await askProjectType();
247
- const templateDir = path.join(__dirname, '..', 'templates', template);
248
- const targetDir = path.join(process.cwd(), projectName);
249
-
250
- // Create project directory
251
- await fs.ensureDir(targetDir);
252
-
253
- // Copy template files
254
- await fs.copy(templateDir, targetDir);
255
-
256
- // Update package.json
257
- const pkgPath = path.join(targetDir, 'package.json');
258
- const pkg = await fs.readJson(pkgPath);
259
- pkg.name = projectName;
260
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
261
-
262
- // Automatically add Dockerfile
263
- const isSSR = template === 'ssr-template';
264
- const dockerContent = isSSR ? SSR_DOCKERFILE_TEMPLATE : DOCKERFILE_TEMPLATE;
265
- await fs.writeFile(path.join(targetDir, 'Dockerfile'), dockerContent);
266
-
267
- spinner.success({ text: `Project ${chalk.green(projectName)} created successfully with Dockerfile!` });
268
-
269
- // Show next steps
270
- console.log('\nNext steps:');
271
- console.log(chalk.cyan(` cd ${projectName}`));
272
- console.log(chalk.cyan(' npm install'));
273
- console.log(chalk.cyan(' npm run dev'));
274
- console.log(chalk.yellow('\nTo build Docker image:'));
275
- console.log(chalk.cyan(' docker build -t my-app .'));
276
- console.log(chalk.cyan(' docker run -p 3000:' + (isSSR ? '3000' : '80') + ' my-app'));
277
-
278
- } catch (error) {
279
- spinner.error({ text: 'Failed to create project' });
280
- console.error(chalk.red(error));
281
- process.exit(1);
282
- }
283
- }
284
-
285
- async function generateComponent(name, directory) {
286
- const spinner = createSpinner(`Generating ${name} component...`).start();
287
-
288
- try {
289
- const targetDir = path.join(process.cwd(), directory, name);
290
-
291
- // Create component directory
292
- await fs.ensureDir(targetDir);
293
-
294
- // Create component files
295
- await fs.writeFile(
296
- path.join(targetDir, `${name}.jsx`),
297
- FUNCTION_COMPONENT_TEMPLATE(name)
298
- );
299
-
300
- await fs.writeFile(
301
- path.join(targetDir, `${name}.css`),
302
- CSS_TEMPLATE(name)
303
- );
304
-
305
- await fs.writeFile(
306
- path.join(targetDir, `${name}.test.jsx`),
307
- TEST_TEMPLATE(name)
308
- );
309
-
310
- await fs.writeFile(
311
- path.join(targetDir, 'index.js'),
312
- `export { ${name} } from './${name}';\n`
313
- );
314
-
315
- spinner.success({ text: `Component ${chalk.green(name)} generated successfully!` });
316
-
317
- console.log('\nFiles created:');
318
- console.log(chalk.cyan(` ${path.join(directory, name, `${name}.jsx`)}`));
319
- console.log(chalk.cyan(` ${path.join(directory, name, `${name}.css`)}`));
320
- console.log(chalk.cyan(` ${path.join(directory, name, `${name}.test.jsx`)}`));
321
- console.log(chalk.cyan(` ${path.join(directory, name, 'index.js')}`));
322
-
323
- } catch (error) {
324
- spinner.error({ text: 'Failed to generate component' });
325
- console.error(chalk.red(error));
326
- process.exit(1);
327
- }
328
- }
329
-
330
- async function addDockerfile(isSSR) {
331
- const spinner = createSpinner('Adding Dockerfile...').start();
332
-
333
- try {
334
- const dockerContent = isSSR ? SSR_DOCKERFILE_TEMPLATE : DOCKERFILE_TEMPLATE;
335
- const targetPath = path.join(process.cwd(), 'Dockerfile');
336
-
337
- // Check if Dockerfile already exists
338
- if (await fs.pathExists(targetPath)) {
339
- spinner.stop();
340
- const { overwrite } = await inquirer.prompt([{
341
- type: 'confirm',
342
- name: 'overwrite',
343
- message: 'Dockerfile already exists. Overwrite?',
344
- default: false
345
- }]);
346
-
347
- if (!overwrite) {
348
- console.log(chalk.yellow('Operation cancelled.'));
349
- return;
350
- }
351
-
352
- spinner.start();
353
- }
354
-
355
- // Write Dockerfile
356
- await fs.writeFile(targetPath, dockerContent);
357
-
358
- spinner.success({ text: 'Dockerfile added successfully!' });
359
-
360
- console.log('\nTo build and run Docker image:');
361
- console.log(chalk.cyan(' docker build -t my-app .'));
362
- console.log(chalk.cyan(' docker run -p 3000:' + (isSSR ? '3000' : '80') + ' my-app'));
363
-
364
- } catch (error) {
365
- spinner.error({ text: 'Failed to add Dockerfile' });
366
- console.error(chalk.red(error));
367
- process.exit(1);
368
- }
369
- }
370
-
371
- init().catch(console.error);