c4e23ae31d
Remove the screenshot image link from the generated README.md template as it references a non-existent asset path that would cause broken image links in new projects. Bump version to 1.3.1.
146 lines
4.5 KiB
JavaScript
146 lines
4.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { execSync } from 'child_process';
|
|
import fs from 'fs-extra';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const c = {
|
|
reset: '\x1b[0m',
|
|
dim: '\x1b[2m',
|
|
green: '\x1b[32m',
|
|
cyan: '\x1b[36m',
|
|
red: '\x1b[31m',
|
|
bold: '\x1b[1m',
|
|
};
|
|
|
|
const step = (msg) => process.stdout.write(` ${c.dim}◆${c.reset} ${msg}...\n`);
|
|
const done = (msg) => process.stdout.write(` ${c.green}✓${c.reset} ${msg}\n`);
|
|
const fail = (msg) => process.stdout.write(` ${c.red}✗${c.reset} ${msg}\n`);
|
|
|
|
// Templates zen (inline pour éviter des dépendances externes)
|
|
const zenTemplates = {
|
|
instrumentation: `export async function register() {
|
|
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
const { initializeZen } = await import('@zen/core');
|
|
await initializeZen();
|
|
}
|
|
}
|
|
`,
|
|
authRedirect: `import { redirect } from 'next/navigation';
|
|
|
|
export default function Redirect() {
|
|
redirect('/auth/login/');
|
|
}
|
|
`,
|
|
authCatchAll: `export { default } from '@zen/core/auth/page';
|
|
`,
|
|
adminRedirect: `import { redirect } from 'next/navigation';
|
|
|
|
export default function Redirect() {
|
|
redirect('/admin/dashboard');
|
|
}
|
|
`,
|
|
adminCatchAll: `export { default } from '@zen/core/admin/page';
|
|
`,
|
|
zenApiRoute: `export { GET, POST, PUT, DELETE, PATCH } from '@zen/core/zen/api';
|
|
`,
|
|
zenPageRoute: `export { default, generateMetadata } from '@zen/core/modules/page';
|
|
`,
|
|
};
|
|
|
|
// Fichiers zen à créer dans le projet cible
|
|
const zenFiles = [
|
|
{ path: 'instrumentation.js', template: 'instrumentation' },
|
|
{ path: 'app/(auth)/auth/page.js', template: 'authRedirect' },
|
|
{ path: 'app/(auth)/auth/[...auth]/page.js', template: 'authCatchAll' },
|
|
{ path: 'app/(admin)/admin/page.js', template: 'adminRedirect' },
|
|
{ path: 'app/(admin)/admin/[...admin]/page.js', template: 'adminCatchAll' },
|
|
{ path: 'app/zen/api/[...path]/route.js', template: 'zenApiRoute' },
|
|
{ path: 'app/zen/[...zen]/page.js', template: 'zenPageRoute' },
|
|
];
|
|
|
|
async function createZenFile(filePath, content) {
|
|
const fullPath = path.resolve(process.cwd(), filePath);
|
|
await fs.ensureDir(path.dirname(fullPath));
|
|
await fs.writeFile(fullPath, content, 'utf-8');
|
|
}
|
|
|
|
async function initProject() {
|
|
try {
|
|
console.log(`\n ${c.bold}${c.cyan}zen-start${c.reset}\n`);
|
|
|
|
step('Creating Next.js project');
|
|
execSync('npx create-next-app@latest ./ --javascript --tailwind --app --empty', { stdio: 'inherit' });
|
|
done('Next.js project created');
|
|
|
|
if (fs.existsSync('./app')) {
|
|
fs.removeSync('./app');
|
|
}
|
|
done('Cleaned default /app directory');
|
|
|
|
fs.writeJsonSync('./jsconfig.json', {
|
|
compilerOptions: { paths: { '@*': ['./*'] } },
|
|
}, { spaces: 2 });
|
|
done('Configured path aliases');
|
|
|
|
fs.writeFileSync('./next.config.mjs', `/** @type {import('next').NextConfig} */
|
|
const nextConfig = {
|
|
\tdevIndicators: false,
|
|
\texperimental: {
|
|
\t\tinstrumentationHook: true,
|
|
\t},
|
|
};
|
|
|
|
export default nextConfig;
|
|
`);
|
|
done('Configured next.config.mjs');
|
|
|
|
const packageJsonPath = './package.json';
|
|
if (fs.existsSync(packageJsonPath)) {
|
|
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
const projectName = packageJson.name || 'project';
|
|
fs.writeFileSync('README.md', `# ${projectName}\n\nBuilt with Next.js, Tailwind CSS and @zen/core.`);
|
|
packageJson.scripts ??= {};
|
|
packageJson.scripts['make-favicon'] = 'node dev/icons/make-favicon.js';
|
|
fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
|
|
}
|
|
done('Updated README and package.json');
|
|
|
|
const templatesPath = path.join(__dirname, '..', 'templates');
|
|
if (!fs.existsSync(templatesPath)) {
|
|
fail('Templates directory not found in zen-start package');
|
|
process.exit(1);
|
|
}
|
|
fs.copySync(templatesPath, './', { overwrite: true });
|
|
done('Copied template files');
|
|
|
|
for (const file of zenFiles) {
|
|
await createZenFile(file.path, zenTemplates[file.template]);
|
|
}
|
|
done('Created @zen/core route files');
|
|
|
|
fs.writeFileSync('./.npmrc', '@zen:registry=https://git.hyko.cx/api/packages/zen/npm/\n');
|
|
done('Configured npm registry');
|
|
|
|
step('Installing @zen/core');
|
|
execSync('npm install @zen/core', { stdio: 'inherit' });
|
|
done('@zen/core installed');
|
|
|
|
console.log(`\n ${c.green}${c.bold}Project ready.${c.reset} Next steps:\n`);
|
|
console.log(` ${c.dim}1.${c.reset} Configure environment variables`);
|
|
console.log(` ${c.dim}https://git.hyko.cx/zen/core${c.reset}`);
|
|
console.log(` ${c.dim}2.${c.reset} Initialize the database`);
|
|
console.log(` ${c.dim}npx zen-db init${c.reset}\n`);
|
|
|
|
} catch (error) {
|
|
fail(error.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
initProject();
|