frontend-hamroun 1.2.2 → 1.2.3
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/bin/cli.cjs +16 -0
- package/bin/cli.mjs +237 -0
- package/package.json +3 -3
- package/scripts/build-cli.js +409 -121
- package/templates/basic/.eslintignore +5 -0
- package/templates/basic/.eslintrc.json +25 -0
- package/templates/basic/docs/rapport_pfe.aux +27 -0
- package/templates/basic/docs/rapport_pfe.log +399 -0
- package/templates/basic/docs/rapport_pfe.out +10 -0
- package/templates/basic/docs/rapport_pfe.pdf +0 -0
- package/templates/basic/docs/rapport_pfe.tex +68 -0
- package/templates/basic/docs/rapport_pfe.toc +14 -0
- package/templates/basic/index.html +12 -0
- package/templates/basic/package.json +30 -0
- package/templates/basic/postcss.config.js +7 -0
- package/templates/basic/src/App.tsx +65 -0
- package/templates/basic/src/api.ts +58 -0
- package/templates/basic/src/components/Counter.tsx +26 -0
- package/templates/basic/src/components/Header.tsx +9 -0
- package/templates/basic/src/components/TodoList.tsx +90 -0
- package/templates/basic/src/main.css +3 -0
- package/templates/basic/src/main.ts +20 -0
- package/templates/basic/src/main.tsx +144 -0
- package/templates/basic/src/server.ts +99 -0
- package/templates/basic/tailwind.config.js +32 -0
- package/templates/basic/tsconfig.json +13 -0
- package/templates/basic/vite.config.ts +28 -0
- package/templates/basic-app/vite.config.ts +6 -0
- package/bin/cli.js +0 -16
package/scripts/build-cli.js
CHANGED
@@ -13,179 +13,255 @@ if (!fs.existsSync(binDir)) {
|
|
13
13
|
fs.mkdirSync(binDir, { recursive: true });
|
14
14
|
}
|
15
15
|
|
16
|
-
// Create
|
16
|
+
// Create CLI entrypoint using ES modules
|
17
17
|
const cliContent = `#!/usr/bin/env node
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
// Try to load the ESM version
|
24
|
-
import('../dist/cli/index.js')
|
25
|
-
.catch(err => {
|
26
|
-
console.error('Failed to load CLI:', err);
|
27
|
-
process.exit(1);
|
28
|
-
});
|
29
|
-
} catch (error) {
|
30
|
-
console.error('Error loading CLI:', error);
|
31
|
-
process.exit(1);
|
32
|
-
}
|
33
|
-
`;
|
34
|
-
|
35
|
-
// Write CLI file
|
36
|
-
fs.writeFileSync(path.join(binDir, 'cli.js'), cliContent, 'utf8');
|
37
|
-
|
38
|
-
// Make CLI executable
|
39
|
-
try {
|
40
|
-
fs.chmodSync(path.join(binDir, 'cli.js'), '755');
|
41
|
-
console.log('✅ CLI wrapper built successfully: bin/cli.js');
|
42
|
-
} catch (error) {
|
43
|
-
console.warn('⚠️ Could not make CLI executable:', error);
|
44
|
-
}
|
45
|
-
|
46
|
-
// Copy the CLI code to dist directory and compile it
|
47
|
-
console.log('🔨 Compiling CLI TypeScript...');
|
48
|
-
try {
|
49
|
-
// Ensure dist/cli directory exists
|
50
|
-
const distCliDir = path.resolve(rootDir, 'dist/cli');
|
51
|
-
if (!fs.existsSync(distCliDir)) {
|
52
|
-
fs.mkdirSync(distCliDir, { recursive: true });
|
53
|
-
}
|
54
|
-
|
55
|
-
// Extract TypeScript files needed for CLI
|
56
|
-
const tscCommand = `npx tsc src/cli/index.ts --outDir dist/cli --esModuleInterop --target ES2020 --module NodeNext --moduleResolution NodeNext`;
|
57
|
-
|
58
|
-
// Execute TypeScript compilation
|
59
|
-
execSync(tscCommand, { stdio: 'inherit' });
|
60
|
-
|
61
|
-
console.log('✅ CLI TypeScript compiled successfully');
|
62
|
-
} catch (error) {
|
63
|
-
console.error('❌ Failed to compile CLI TypeScript:', error);
|
64
|
-
|
65
|
-
// Create a fallback CLI if TypeScript compilation fails
|
66
|
-
console.log('⚠️ Creating fallback CommonJS CLI...');
|
67
|
-
|
68
|
-
const fallbackCli = `
|
69
|
-
// This is a fallback CLI implementation when TypeScript compilation fails
|
70
|
-
const fs = require('fs');
|
71
|
-
const path = require('path');
|
72
|
-
const { execSync } = require('child_process');
|
19
|
+
import fs from 'fs';
|
20
|
+
import path from 'path';
|
21
|
+
import { fileURLToPath } from 'url';
|
22
|
+
import { execSync } from 'child_process';
|
73
23
|
|
74
|
-
const
|
75
|
-
const
|
24
|
+
const __filename = fileURLToPath(import.meta.url);
|
25
|
+
const __dirname = path.dirname(__filename);
|
76
26
|
|
77
|
-
//
|
27
|
+
// Templates available
|
78
28
|
const TEMPLATES = {
|
79
29
|
'basic': 'Basic frontend only template',
|
80
30
|
'full-stack': 'Complete frontend and backend template'
|
81
31
|
};
|
82
32
|
|
83
|
-
// Colors for
|
33
|
+
// Colors for CLI output
|
84
34
|
const colors = {
|
85
35
|
reset: '\\x1b[0m',
|
86
36
|
bright: '\\x1b[1m',
|
87
37
|
green: '\\x1b[32m',
|
88
38
|
blue: '\\x1b[34m',
|
89
|
-
red: '\\x1b[31m'
|
39
|
+
red: '\\x1b[31m',
|
40
|
+
yellow: '\\x1b[33m'
|
90
41
|
};
|
91
42
|
|
92
|
-
|
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(\`
|
93
50
|
\${colors.blue}\${colors.bright}╔══════════════════════════════════════════════╗
|
94
51
|
║ ║
|
95
52
|
║ Frontend Hamroun v\${packageJson.version.padEnd(25)}║
|
96
53
|
║ A lightweight frontend & backend framework ║
|
97
54
|
║ ║
|
98
55
|
╚══════════════════════════════════════════════╝\${colors.reset}
|
99
|
-
\`);
|
100
|
-
|
101
|
-
const args = process.argv.slice(2);
|
102
|
-
const command = args[0];
|
56
|
+
\`);
|
57
|
+
}
|
103
58
|
|
104
|
-
|
59
|
+
// Print help
|
60
|
+
function printHelp() {
|
105
61
|
console.log(\`
|
106
62
|
\${colors.bright}USAGE:\${colors.reset}
|
107
|
-
\${colors.blue}npx frontend-hamroun\${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
|
108
73
|
|
109
74
|
\${colors.bright}AVAILABLE TEMPLATES:\${colors.reset}
|
110
|
-
\${colors.blue}
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
+
\`);
|
114
81
|
}
|
115
82
|
|
116
|
-
|
117
|
-
|
83
|
+
// Create project from template
|
84
|
+
function createProject(projectName, options) {
|
85
|
+
const template = options.template || 'basic';
|
118
86
|
|
119
|
-
if
|
120
|
-
|
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(', ')}\`);
|
121
91
|
process.exit(1);
|
122
92
|
}
|
123
93
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
if (!Object.keys(TEMPLATES).includes(template)) {
|
132
|
-
console.error(\`\${colors.red}Error:\${colors.reset} Template "\${template}" not found\`);
|
133
|
-
console.log(\`Available templates: \${Object.keys(TEMPLATES).join(', ')}\`);
|
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.\`);
|
134
98
|
process.exit(1);
|
135
99
|
}
|
136
100
|
|
137
|
-
console.log(\`
|
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
|
+
\`);
|
138
107
|
|
139
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
|
+
|
140
124
|
// Create project directory
|
141
|
-
const projectPath = path.resolve(process.cwd(), projectName);
|
142
125
|
fs.mkdirSync(projectPath, { recursive: true });
|
143
126
|
|
144
|
-
//
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
+
}
|
155
141
|
}
|
156
|
-
}
|
142
|
+
}
|
157
143
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
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
|
+
}
|
162
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
|
163
175
|
console.log(\`
|
164
|
-
\${colors.green}\${colors.bright}Success!\${colors.reset} Created
|
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}
|
165
179
|
|
166
|
-
\${colors.
|
167
|
-
|
168
|
-
|
169
|
-
npm run
|
170
|
-
|
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
|
+
\`);
|
171
196
|
|
172
197
|
} catch (error) {
|
173
198
|
console.error(\`\${colors.red}Failed to create project:\${colors.reset}\`, error);
|
174
199
|
process.exit(1);
|
175
200
|
}
|
176
|
-
} else {
|
177
|
-
console.error(\`\${colors.red}Unknown command:\${colors.reset} \${command}\`);
|
178
|
-
process.exit(1);
|
179
201
|
}
|
180
|
-
`;
|
181
202
|
|
182
|
-
|
183
|
-
|
184
|
-
|
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);
|
185
217
|
}
|
186
218
|
|
187
|
-
|
188
|
-
|
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);
|
189
265
|
}
|
190
266
|
|
191
267
|
// Let's make sure we also have template directories
|
@@ -195,11 +271,223 @@ const templateList = ['basic', 'full-stack'];
|
|
195
271
|
console.log('🔍 Checking template directories...');
|
196
272
|
for (const template of templateList) {
|
197
273
|
const templateDir = path.join(templatesDir, template);
|
198
|
-
|
199
|
-
|
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`);
|
200
461
|
} else {
|
201
|
-
|
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);
|
202
483
|
}
|
203
484
|
}
|
204
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
|
+
|
205
493
|
console.log('✅ CLI build process completed');
|
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"root": true,
|
3
|
+
"env": {
|
4
|
+
"browser": true,
|
5
|
+
"es2020": true
|
6
|
+
},
|
7
|
+
"extends": [
|
8
|
+
"eslint:recommended",
|
9
|
+
"plugin:@typescript-eslint/recommended"
|
10
|
+
],
|
11
|
+
"ignorePatterns": ["dist", ".eslintrc.json"],
|
12
|
+
"parser": "@typescript-eslint/parser",
|
13
|
+
"plugins": [
|
14
|
+
"@typescript-eslint",
|
15
|
+
"react-refresh"
|
16
|
+
],
|
17
|
+
"rules": {
|
18
|
+
"react-refresh/only-export-components": [
|
19
|
+
"warn",
|
20
|
+
{ "allowConstantExport": true }
|
21
|
+
],
|
22
|
+
"@typescript-eslint/no-explicit-any": "off",
|
23
|
+
"@typescript-eslint/ban-ts-comment": "off"
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
\relax
|
2
|
+
\providecommand\babel@aux[2]{}
|
3
|
+
\@nameuse{bbl@beforestart}
|
4
|
+
\catcode `:\active
|
5
|
+
\catcode `;\active
|
6
|
+
\catcode `!\active
|
7
|
+
\catcode `?\active
|
8
|
+
\providecommand\hyper@newdestlabel[2]{}
|
9
|
+
\providecommand\HyField@AuxAddToFields[1]{}
|
10
|
+
\providecommand\HyField@AuxAddToCoFields[2]{}
|
11
|
+
\babel@aux{french}{}
|
12
|
+
\@writefile{toc}{\contentsline {chapter}{\numberline {1}ÉTUDE PREALABLE}{2}{chapter.1}\protected@file@percent }
|
13
|
+
\@writefile{lof}{\addvspace {10\p@ }}
|
14
|
+
\@writefile{lot}{\addvspace {10\p@ }}
|
15
|
+
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Introduction}{2}{section.1.1}\protected@file@percent }
|
16
|
+
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Organisme d'accueil}{2}{section.1.2}\protected@file@percent }
|
17
|
+
\@writefile{toc}{\contentsline {section}{\numberline {1.3}Étude et critique de l'existant}{2}{section.1.3}\protected@file@percent }
|
18
|
+
\@writefile{toc}{\contentsline {subsection}{\numberline {1.3.1}Critique de l'existant}{2}{subsection.1.3.1}\protected@file@percent }
|
19
|
+
\@writefile{toc}{\contentsline {subsection}{\numberline {1.3.2}Solution proposée}{2}{subsection.1.3.2}\protected@file@percent }
|
20
|
+
\@writefile{toc}{\contentsline {section}{\numberline {1.4}Choix méthodologique}{3}{section.1.4}\protected@file@percent }
|
21
|
+
\@writefile{toc}{\contentsline {subsection}{\numberline {1.4.1}Formalisme de modélisation}{3}{subsection.1.4.1}\protected@file@percent }
|
22
|
+
\@writefile{toc}{\contentsline {subsection}{\numberline {1.4.2}Méthodologie}{3}{subsection.1.4.2}\protected@file@percent }
|
23
|
+
\@writefile{toc}{\contentsline {subsubsection}{Présentation de la méthode SCRUM}{3}{section*.2}\protected@file@percent }
|
24
|
+
\@writefile{toc}{\contentsline {subsubsection}{La répartition des rôles dans la méthode SCRUM}{3}{section*.3}\protected@file@percent }
|
25
|
+
\@writefile{toc}{\contentsline {subsubsection}{Le processus de SCRUM}{3}{section*.4}\protected@file@percent }
|
26
|
+
\@writefile{toc}{\contentsline {section}{\numberline {1.5}Conclusion}{3}{section.1.5}\protected@file@percent }
|
27
|
+
\gdef \@abspage@last{4}
|