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.
- package/dist/{src/backend → backend}/api-utils.d.ts +2 -2
- package/dist/backend/api-utils.js +135 -0
- package/dist/backend/auth.js +387 -0
- package/dist/{src/backend → backend}/database.d.ts +1 -1
- package/dist/backend/database.js +91 -0
- package/dist/{src/backend → backend}/model.d.ts +2 -2
- package/dist/backend/model.js +176 -0
- package/dist/{src/backend → backend}/router.d.ts +1 -1
- package/dist/backend/router.js +137 -0
- package/dist/backend/server.js +268 -0
- package/dist/batch.js +22 -0
- package/dist/cli/index.js +1 -0
- package/dist/{src/component.d.ts → component.d.ts} +1 -1
- package/dist/component.js +84 -0
- package/dist/components/Counter.js +2 -0
- package/dist/context.js +20 -0
- package/dist/frontend-hamroun.es.js +1680 -0
- package/dist/frontend-hamroun.es.js.map +1 -0
- package/dist/frontend-hamroun.umd.js +2 -0
- package/dist/frontend-hamroun.umd.js.map +1 -0
- package/dist/hooks.js +164 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +52 -355
- package/dist/jsx-runtime/index.d.ts +9 -0
- package/dist/jsx-runtime/index.js +16 -0
- package/dist/jsx-runtime/jsx-dev-runtime.js +1 -0
- package/dist/jsx-runtime/jsx-runtime.js +91 -0
- package/dist/{src/jsx-runtime.d.ts → jsx-runtime.d.ts} +1 -1
- package/dist/jsx-runtime.js +192 -0
- package/dist/renderer.js +51 -0
- package/dist/{src/server-renderer.d.ts → server-renderer.d.ts} +3 -0
- package/dist/server-renderer.js +102 -0
- package/dist/vdom.js +27 -0
- package/package.json +38 -52
- package/scripts/generate.js +134 -0
- package/src/backend/api-utils.ts +178 -0
- package/src/backend/auth.ts +543 -0
- package/src/backend/database.ts +104 -0
- package/src/backend/model.ts +196 -0
- package/src/backend/router.ts +176 -0
- package/src/backend/server.ts +330 -0
- package/src/backend/types.ts +257 -0
- package/src/batch.ts +24 -0
- package/src/cli/index.js +22 -40
- package/src/component.ts +98 -0
- package/src/components/Counter.tsx +4 -0
- package/src/context.ts +32 -0
- package/src/hooks.ts +211 -0
- package/src/index.ts +113 -0
- package/src/jsx-runtime/index.ts +24 -0
- package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
- package/src/jsx-runtime/jsx-runtime.ts +99 -0
- package/src/jsx-runtime.ts +226 -0
- package/src/renderer.ts +55 -0
- package/src/server-renderer.ts +114 -0
- package/src/types/bcrypt.d.ts +30 -0
- package/src/types/jsonwebtoken.d.ts +55 -0
- package/src/types.d.ts +26 -0
- package/src/types.ts +21 -0
- package/src/vdom.ts +34 -0
- package/templates/basic-app/package.json +17 -15
- package/templates/basic-app/postcss.config.js +1 -0
- package/templates/basic-app/src/App.tsx +65 -0
- package/templates/basic-app/src/api.ts +58 -0
- package/templates/basic-app/src/components/Counter.tsx +26 -0
- package/templates/basic-app/src/components/Header.tsx +9 -0
- package/templates/basic-app/src/components/TodoList.tsx +90 -0
- package/templates/basic-app/src/main.ts +20 -0
- package/templates/basic-app/src/server.ts +99 -0
- package/templates/basic-app/tailwind.config.js +23 -2
- package/bin/cli.js +0 -371
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -139269
- package/dist/index.mjs.map +0 -1
- package/dist/src/index.d.ts +0 -16
- package/dist/test/setupTests.d.ts +0 -4
- /package/dist/{src/backend → backend}/auth.d.ts +0 -0
- /package/dist/{src/backend → backend}/server.d.ts +0 -0
- /package/dist/{src/backend → backend}/types.d.ts +0 -0
- /package/dist/{test/backend.test.d.ts → backend/types.js} +0 -0
- /package/dist/{src/batch.d.ts → batch.d.ts} +0 -0
- /package/dist/{src/cli → cli}/index.d.ts +0 -0
- /package/dist/{src/components → components}/Counter.d.ts +0 -0
- /package/dist/{src/context.d.ts → context.d.ts} +0 -0
- /package/dist/{src/hooks.d.ts → hooks.d.ts} +0 -0
- /package/dist/{src/jsx-runtime → jsx-runtime}/jsx-dev-runtime.d.ts +0 -0
- /package/dist/{src/jsx-runtime → jsx-runtime}/jsx-runtime.d.ts +0 -0
- /package/dist/{src/renderer.d.ts → renderer.d.ts} +0 -0
- /package/dist/{src/types.d.ts → types.d.ts} +0 -0
- /package/dist/{test/mockTest.d.ts → types.js} +0 -0
- /package/dist/{src/vdom.d.ts → vdom.d.ts} +0 -0
- /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);
|