import fs from 'node:fs'; import path from 'node:path'; function fileExists(root, names) { return names.some((name) => fs.existsSync(path.join(root, name))); } function readRequirements(root) { for (const name of ['requirements.txt', 'requirements-dev.txt', 'pyproject.toml']) { const file = path.join(root, name); if (fs.existsSync(file)) return fs.readFileSync(file, 'utf8').toLowerCase(); } return ''; } /** * Django detection stub: install/dev/test via manage.py / common Python tooling. * Deeper generators land in a later phase. */ export class DjangoAdapter { root; kind = 'django'; label = 'Django'; constructor(root) { this.root = root; } installCommand() { if (fileExists(this.root, ['pyproject.toml']) && fileExists(this.root, ['uv.lock'])) { return { command: 'uv', args: ['sync'], cwd: this.root }; } if (fileExists(this.root, ['poetry.lock', 'pyproject.toml'])) { return { command: 'poetry', args: ['install'], cwd: this.root }; } if (fileExists(this.root, ['requirements.txt'])) { return { command: 'pip', args: ['install', '-r', 'requirements.txt'], cwd: this.root }; } throw new Error(`No Django dependency file found at "${this.root}" (expected requirements.txt, poetry.lock, or uv.lock).`); } devCommand() { if (!fileExists(this.root, ['manage.py'])) { throw new Error(`No manage.py found at "${this.root}".`); } return { command: 'python', args: ['manage.py', 'runserver', '127.0.0.1:8000'], cwd: this.root }; } buildCommand() { if (!fileExists(this.root, ['manage.py'])) return null; return { command: 'python', args: ['manage.py', 'collectstatic', '--noinput'], cwd: this.root }; } testCommand(extraArgs = []) { if (!fileExists(this.root, ['manage.py'])) return null; return { command: 'python', args: ['manage.py', 'test', ...extraArgs], cwd: this.root }; } lintCommand() { return null; } readyPattern() { return /Starting development server at (https?:\/\/\S+)/i; } describe() { const req = readRequirements(this.root); return { kind: this.kind, label: this.label, root: this.root, hasManagePy: fileExists(this.root, ['manage.py']), notes: 'install/dev/test + generate_*_resource stubs available.', hintsDjango: /django/.test(req), }; } } /** * Rails detection stub: bundle install + bin/rails server / test. */ export class RailsAdapter { root; kind = 'rails'; label = 'Rails'; constructor(root) { this.root = root; } installCommand() { return { command: 'bundle', args: ['install'], cwd: this.root }; } devCommand() { const binRails = path.join(this.root, 'bin', 'rails'); if (fs.existsSync(binRails)) { return { command: 'ruby', args: [binRails, 'server', '-b', '127.0.0.1', '-p', '3000'], cwd: this.root }; } return { command: 'rails', args: ['server', '-b', '127.0.0.1', '-p', '3000'], cwd: this.root }; } buildCommand() { const binRails = path.join(this.root, 'bin', 'rails'); if (fs.existsSync(binRails)) { return { command: 'ruby', args: [binRails, 'assets:precompile'], cwd: this.root }; } return { command: 'rails', args: ['assets:precompile'], cwd: this.root }; } testCommand(extraArgs = []) { const binRails = path.join(this.root, 'bin', 'rails'); if (fs.existsSync(binRails)) { return { command: 'ruby', args: [binRails, 'test', ...extraArgs], cwd: this.root }; } return { command: 'rails', args: ['test', ...extraArgs], cwd: this.root }; } lintCommand() { return null; } readyPattern() { return /Listening on (https?:\/\/\S+)|Puma starting/i; } describe() { return { kind: this.kind, label: this.label, root: this.root, hasBinRails: fs.existsSync(path.join(this.root, 'bin', 'rails')), notes: 'install/dev/test + generate_*_resource stubs available.', }; } } /** * Symfony detection stub: composer + symfony CLI / php -S patterns via composer scripts when present. */ export class SymfonyAdapter { root; kind = 'symfony'; label = 'Symfony'; constructor(root) { this.root = root; } installCommand() { return { command: 'composer', args: ['install'], cwd: this.root }; } devCommand() { // Prefer composer script when present; otherwise PHP built-in server on public/ const composerPath = path.join(this.root, 'composer.json'); if (fs.existsSync(composerPath)) { try { const pkg = JSON.parse(fs.readFileSync(composerPath, 'utf8')); if (pkg.scripts?.['serve'] || pkg.scripts?.dev) { const script = pkg.scripts.dev ? 'dev' : 'serve'; return { command: 'composer', args: ['run', script], cwd: this.root }; } } catch { // fall through } } return { command: 'php', args: ['-S', '127.0.0.1:8000', '-t', 'public'], cwd: this.root, }; } buildCommand() { return { command: 'composer', args: ['install', '--no-dev', '--optimize-autoloader'], cwd: this.root }; } testCommand(extraArgs = []) { const phpunit = path.join(this.root, 'bin', 'phpunit'); if (fs.existsSync(phpunit) || fs.existsSync(`${phpunit}.bat`)) { return { command: 'php', args: ['bin/phpunit', ...extraArgs], cwd: this.root }; } const vendor = path.join(this.root, 'vendor', 'bin', 'phpunit'); if (fs.existsSync(vendor) || fs.existsSync(`${vendor}.bat`)) { return { command: 'php', args: [path.join('vendor', 'bin', 'phpunit'), ...extraArgs], cwd: this.root }; } return null; } lintCommand() { return null; } readyPattern() { return /(?:Development Server|started|listening).*(https?:\/\/\S+)/i; } describe() { return { kind: this.kind, label: this.label, root: this.root, notes: 'install/dev/test + generate_*_resource stubs available.', }; } } //# sourceMappingURL=djangoRailsSymfony.js.map