hylius 1.0.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/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # hylius
2
+
3
+ A CLI tool to initialize and manage Docker configurations for development projects with beautiful colored terminal output.
4
+
5
+ ## Features
6
+
7
+ - 🔍 Automatic project type detection (Node.js, Python, Go, Java, PHP)
8
+ - 🐳 Optimized Docker configurations for different frameworks
9
+ - 🚀 Quick development environment setup
10
+ - 📦 Production-ready build configurations
11
+ - ⚙️ Automatic CI/CD workflow generation
12
+ - 🎨 **Beautiful colored terminal output with spinners**
13
+ - 📊 **Real-time streaming command output**
14
+
15
+ ## Installation
16
+
17
+
18
+ ### Using npm
19
+
20
+ ```bash
21
+ npm install -g hylius
22
+ ```
23
+
24
+ ### From Source
25
+
26
+ ```bash
27
+ # Clone the repository
28
+ git clone https://github.com/isaac-hash/hylius.git
29
+ cd hylius
30
+
31
+ # Install dependencies
32
+ npm install
33
+
34
+ # Build the project
35
+ npm run build
36
+
37
+ # Link globally (optional)
38
+ npm link
39
+ ```
40
+
41
+
42
+ ## Usage
43
+
44
+ ### Initialize a Project
45
+
46
+ ```bash
47
+ # Initialize with automatic detection
48
+ hylius init
49
+
50
+ # Skip Docker initialization
51
+ hylius init --skip-docker
52
+
53
+ # Skip CI workflow generation
54
+ hylius init --skip-ci
55
+ ```
56
+
57
+ ### Start Development Environment
58
+
59
+ ```bash
60
+ # Start in foreground
61
+ hylius dev
62
+
63
+ # Start in detached mode
64
+ hylius dev -d
65
+
66
+ # Enable hot-reload (watch mode)
67
+ hylius dev --watch
68
+ ```
69
+
70
+ ### Build Production Image
71
+
72
+ ```bash
73
+ hylius build
74
+ ```
75
+
76
+ This will create Docker images with tags:
77
+ - `<project-name>:latest`
78
+ - `<project-name>:<git-hash>` (if in a git repository)
79
+
80
+ ## Supported Project Types
81
+
82
+ - **Next.js** - Server-side rendered React applications
83
+ - **Vite** - Modern frontend tooling (React, Vue, Svelte)
84
+ - **Node.js** - Express, NestJS, and other Node.js frameworks
85
+ - **Python** - Flask, Django, FastAPI
86
+ - **Go** - Go applications with hot-reload
87
+ - **Java** - Maven-based Spring Boot applications
88
+ - **PHP** - Apache-based PHP applications
89
+
90
+ ## Project Structure
91
+
92
+ ```
93
+ hylius/
94
+ ├── src/
95
+ │ ├── commands/
96
+ │ │ ├── root.ts # Main CLI program
97
+ │ │ ├── init.ts # Init command
98
+ │ │ ├── dev.ts # Dev command
99
+ │ │ └── build.ts # Build command
100
+ │ ├── utils/
101
+ │ │ ├── config.ts # Config file handling
102
+ │ │ └── detect.ts # Project type detection
103
+ │ ├── templates/
104
+ │ │ └── index.ts # Docker/compose templates
105
+ │ └── index.ts # Entry point
106
+ ├── package.json
107
+ ├── tsconfig.json
108
+ └── README.md
109
+ ```
110
+
111
+ ## Development
112
+
113
+ ```bash
114
+ # Run in development mode
115
+ npm run dev
116
+
117
+ # Build TypeScript
118
+ npm run build
119
+
120
+ # Run built version
121
+ npm start
122
+
123
+ # Try the colored output examples
124
+ npx tsx examples/colored-output.ts
125
+ ```
126
+
127
+ ## Terminal Output Features
128
+
129
+ This CLI uses **chalk** for colored output and **ora** for loading spinners:
130
+
131
+ - ✅ Success messages in green
132
+ - ❌ Error messages in red
133
+ - ⚠️ Warnings in yellow
134
+ - 📘 Info messages in blue/cyan
135
+ - 🔄 Animated spinners for long-running operations
136
+ - 📊 Real-time streaming output from Docker commands
137
+
138
+ See `examples/colored-output.ts` for comprehensive examples of all coloring options.
139
+
140
+ ## Configuration
141
+
142
+ hylius creates a `hylius.yaml` file in your project:
143
+
144
+ ```yaml
145
+ project_name: my-app
146
+ type: node
147
+ ```
148
+
149
+ ## License
150
+
151
+ MIT
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const buildCommand: Command;
3
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,YAAY,SAoDrB,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { Command } from 'commander';
2
+ import { execSync } from 'child_process';
3
+ import chalk from 'chalk';
4
+ import ora from 'ora';
5
+ import { loadConfig, getProjectName } from '../utils/config.js';
6
+ export const buildCommand = new Command('build')
7
+ .description('Build production Docker image with standardized tags')
8
+ .action(() => {
9
+ const config = loadConfig();
10
+ let projectName = config?.project_name || getProjectName();
11
+ const tags = [`${projectName}:latest`];
12
+ // Add git short hash if in a repo
13
+ try {
14
+ const gitHash = execSync('git rev-parse --short HEAD', { encoding: 'utf8' }).trim();
15
+ tags.push(`${projectName}:${gitHash}`);
16
+ }
17
+ catch {
18
+ // Not in a git repo or git not available
19
+ }
20
+ const tagArgs = tags.flatMap(t => ['-t', t]);
21
+ const buildArgs = ['build', ...tagArgs, '.'];
22
+ console.log(chalk.blue.bold('🔨 Building Docker image...\n'));
23
+ console.log(chalk.cyan('Tags:'));
24
+ tags.forEach(tag => {
25
+ console.log(chalk.white(` • ${chalk.bold(tag)}`));
26
+ });
27
+ console.log();
28
+ const spinner = ora('Building image...').start();
29
+ try {
30
+ // Build with streaming output
31
+ execSync(`docker ${buildArgs.join(' ')}`, {
32
+ stdio: ['inherit', 'pipe', 'pipe'],
33
+ encoding: 'utf8'
34
+ });
35
+ spinner.succeed(chalk.green('Image built successfully!'));
36
+ console.log(chalk.cyan('\nYour image is ready:'));
37
+ tags.forEach(tag => {
38
+ console.log(chalk.white(` ${chalk.bold(tag)}`));
39
+ });
40
+ console.log();
41
+ console.log(chalk.gray('To run: ') + chalk.bold(`docker run -p 8080:8080 ${tags[0]}`));
42
+ console.log(chalk.gray('To push: ') + chalk.bold(`docker push ${tags[0]}\n`));
43
+ }
44
+ catch (error) {
45
+ spinner.fail(chalk.red('Build failed'));
46
+ if (error instanceof Error && 'stdout' in error) {
47
+ console.error(chalk.red(error.stdout || error.message));
48
+ }
49
+ process.exit(1);
50
+ }
51
+ });
52
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const devCommand: Command;
3
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,UAAU,SA0DnB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { Command } from 'commander';
2
+ import { spawn } from 'child_process';
3
+ import chalk from 'chalk';
4
+ import ora from 'ora';
5
+ import { loadConfig } from '../utils/config.js';
6
+ export const devCommand = new Command('dev')
7
+ .description('Start the development environment')
8
+ .option('-d, --detach', 'Run in detached mode')
9
+ .option('--watch', 'Enable hot-reload (Docker Compose watch)')
10
+ .action((options) => {
11
+ console.log(chalk.blue.bold('🚀 Starting development environment...\n'));
12
+ // Load config to show project name
13
+ const config = loadConfig();
14
+ if (config && config.project_name) {
15
+ console.log(chalk.cyan(`Project: ${chalk.bold(config.project_name)}\n`));
16
+ }
17
+ const dockerArgs = ['compose', 'up', '--build'];
18
+ if (options.detach) {
19
+ dockerArgs.push('--detach');
20
+ }
21
+ if (options.watch) {
22
+ dockerArgs.push('--watch');
23
+ }
24
+ const spinner = ora('Building and starting containers...').start();
25
+ // Use spawn instead of execSync for real-time streaming output
26
+ const dockerProcess = spawn('docker', dockerArgs, {
27
+ stdio: options.detach ? 'pipe' : 'inherit'
28
+ });
29
+ if (options.detach) {
30
+ dockerProcess.stdout?.on('data', (data) => {
31
+ spinner.text = data.toString().trim();
32
+ });
33
+ dockerProcess.stderr?.on('data', (data) => {
34
+ spinner.text = chalk.yellow(data.toString().trim());
35
+ });
36
+ }
37
+ else {
38
+ spinner.stop();
39
+ }
40
+ dockerProcess.on('close', (code) => {
41
+ if (code === 0) {
42
+ if (options.detach) {
43
+ spinner.succeed(chalk.green('Containers started in detached mode'));
44
+ console.log(chalk.cyan('\nTo view logs: ') + chalk.bold('docker compose logs -f'));
45
+ console.log(chalk.cyan('To stop: ') + chalk.bold('docker compose down\n'));
46
+ }
47
+ }
48
+ else {
49
+ spinner.fail(chalk.red(`Docker compose exited with code ${code}`));
50
+ process.exit(code || 1);
51
+ }
52
+ });
53
+ dockerProcess.on('error', (error) => {
54
+ spinner.fail(chalk.red('Failed to start docker compose'));
55
+ console.error(chalk.red(error.message));
56
+ process.exit(1);
57
+ });
58
+ });
59
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { program } from './root';
3
+ program.parse(process.argv);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const initCommand: Command;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,WAAW,SAwEpB,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { Command } from 'commander';
2
+ import { execSync } from 'child_process';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import chalk from 'chalk';
6
+ import ora from 'ora';
7
+ import { detectProjectType } from '../utils/detect.js';
8
+ import { writeConfig, getProjectName } from '../utils/config.js';
9
+ import * as templates from '../templates/index.js';
10
+ export const initCommand = new Command('init')
11
+ .description('Initialize a new anvil project')
12
+ .option('--skip-docker', "Don't run docker init")
13
+ .option('--skip-ci', "Don't generate GitHub Actions workflow")
14
+ .action(async (options) => {
15
+ console.log(chalk.blue.bold('🔍 Detecting project type...\n'));
16
+ const projectType = detectProjectType();
17
+ if (projectType === 'unknown') {
18
+ console.log(chalk.yellow('⚠️ Could not detect project type automatically.\n'));
19
+ }
20
+ // Run docker init unless skipped
21
+ if (!options.skipDocker) {
22
+ if (projectType !== 'unknown') {
23
+ console.log(chalk.green(`✨ ${capitalize(projectType)} detected. Using anvil optimized setup...\n`));
24
+ const spinner = ora('Generating Docker configuration...').start();
25
+ try {
26
+ generateConfig(projectType);
27
+ spinner.succeed(chalk.green('Docker configuration generated'));
28
+ }
29
+ catch (error) {
30
+ spinner.fail(chalk.red('Failed to generate config'));
31
+ console.error(chalk.red(error instanceof Error ? error.message : String(error)));
32
+ process.exit(1);
33
+ }
34
+ }
35
+ else {
36
+ console.log(chalk.cyan('🐳 Running standard docker init...\n'));
37
+ try {
38
+ execSync('docker init', { stdio: 'inherit' });
39
+ }
40
+ catch (error) {
41
+ console.error(chalk.red('❌ docker init failed'));
42
+ process.exit(1);
43
+ }
44
+ }
45
+ }
46
+ // Generate anvil.yaml
47
+ const spinner = ora('Creating anvil.yaml...').start();
48
+ const config = {
49
+ project_name: getProjectName(),
50
+ type: projectType,
51
+ };
52
+ writeConfig(config);
53
+ spinner.succeed(chalk.green('Created anvil.yaml'));
54
+ // Generate basic GitHub Actions CI
55
+ if (!options.skipCi) {
56
+ const ciSpinner = ora('Creating GitHub Actions workflow...').start();
57
+ const workflowDir = '.github/workflows';
58
+ fs.mkdirSync(workflowDir, { recursive: true });
59
+ const ciContent = `name: CI
60
+ on: [push, pull_request]
61
+ jobs:
62
+ build-and-test:
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+ - name: Build Docker image
67
+ run: docker build -t \${{ secrets.DOCKER_REPO }} .
68
+ `;
69
+ const ciPath = path.join(workflowDir, 'ci.yaml');
70
+ fs.writeFileSync(ciPath, ciContent, 'utf8');
71
+ ciSpinner.succeed(chalk.green('Created .github/workflows/ci.yaml'));
72
+ }
73
+ console.log(chalk.green.bold('\n🚀 anvil initialization complete!'));
74
+ console.log(chalk.cyan(`\nNext steps:`));
75
+ console.log(chalk.white(` $ ${chalk.bold('anvil dev')} ${chalk.dim('# Start development environment')}`));
76
+ console.log(chalk.white(` $ ${chalk.bold('anvil build')} ${chalk.dim('# Build production image')}\n`));
77
+ });
78
+ function capitalize(str) {
79
+ return str.charAt(0).toUpperCase() + str.slice(1);
80
+ }
81
+ function generateConfig(projectType) {
82
+ let dockerfile;
83
+ let compose;
84
+ let dockerignore = templates.nodeDockerignore; // Default ignore list
85
+ switch (projectType) {
86
+ case 'vite':
87
+ dockerfile = templates.viteDockerfile;
88
+ compose = templates.viteCompose;
89
+ break;
90
+ case 'next':
91
+ dockerfile = templates.nextDockerfile;
92
+ compose = templates.nextCompose;
93
+ break;
94
+ case 'node':
95
+ dockerfile = templates.nodeDockerfile;
96
+ compose = templates.nodeCompose;
97
+ break;
98
+ case 'python':
99
+ dockerfile = templates.pythonDockerfile;
100
+ compose = templates.pythonCompose;
101
+ break;
102
+ case 'go':
103
+ dockerfile = templates.goDockerfile;
104
+ compose = templates.goCompose;
105
+ break;
106
+ case 'java':
107
+ dockerfile = templates.javaDockerfile;
108
+ compose = templates.javaCompose;
109
+ break;
110
+ case 'php':
111
+ dockerfile = templates.phpDockerfile;
112
+ compose = templates.phpCompose;
113
+ break;
114
+ default:
115
+ throw new Error(`Unsupported project type: ${projectType}`);
116
+ }
117
+ fs.writeFileSync('Dockerfile', dockerfile, 'utf8');
118
+ fs.writeFileSync('compose.yaml', compose, 'utf8');
119
+ fs.writeFileSync('.dockerignore', dockerignore, 'utf8');
120
+ console.log(chalk.gray(` Created: Dockerfile, compose.yaml, .dockerignore`));
121
+ }
122
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const program: Command;
3
+ //# sourceMappingURL=root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/commands/root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,OAAO,SAGD,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { initCommand } from './init.js';
4
+ import { devCommand } from './dev.js';
5
+ import { buildCommand } from './build.js';
6
+ export const program = new Command()
7
+ .name('anvil')
8
+ .description(chalk.cyan('A CLI tool to initialize and manage Docker configurations for development'))
9
+ .version('1.0.0');
10
+ // Add subcommands
11
+ program.addCommand(initCommand);
12
+ program.addCommand(devCommand);
13
+ program.addCommand(buildCommand);
14
+ //# sourceMappingURL=root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/commands/root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KACjC,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;KACpG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,kBAAkB;AAClB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { program } from './commands/root.js';
3
+ program.parse(process.argv);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ export declare const viteDockerfile = "# Development stage\nFROM node:22-alpine AS development\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install\nCOPY . .\nEXPOSE 5173\nCMD [\"npm\", \"run\", \"dev\", \"--\", \"--host\"]\n\n# Build stage\nFROM development AS builder\nRUN npm run build\n\n# Production stage\nFROM nginx:alpine AS production\nCOPY --from=builder /app/dist /usr/share/nginx/html\nEXPOSE 80\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n";
2
+ export declare const viteCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"5173:5173\"\n volumes:\n - .:/app\n - /app/node_modules\n environment:\n - NODE_ENV=development\n";
3
+ export declare const nextDockerfile = "# Development stage\nFROM node:22-alpine AS development\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install\nCOPY . .\nEXPOSE 3000\n# Ensure Host is 0.0.0.0 for Docker\nCMD [\"npm\", \"run\", \"dev\", \"--\", \"-H\", \"0.0.0.0\"]\n\n# Production stage\nFROM node:22-alpine AS production\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --omit=dev\nCOPY . .\nRUN npm run build\nCMD [\"npm\", \"start\"]\n";
4
+ export declare const nextCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"3000:3000\"\n volumes:\n - .:/app\n - /app/node_modules\n environment:\n - NODE_ENV=development\n";
5
+ export declare const nodeDockerfile = "# Development stage\nFROM node:22-alpine AS development\nWORKDIR /app\nCOPY package*.json ./\nRUN npm install\nCOPY . .\nEXPOSE 3000\nCMD [\"npm\", \"run\", \"dev\"]\n\n# Production stage\nFROM node:22-alpine AS production\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --omit=dev\nCOPY . .\nCMD [\"npm\", \"start\"]\n";
6
+ export declare const nodeCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"3000:3000\"\n volumes:\n - .:/app\n - /app/node_modules\n environment:\n - NODE_ENV=development\n";
7
+ export declare const nodeDockerignore = "node_modules\ndist\n.git\n.github\n.vscode\n.next\n";
8
+ export declare const pythonDockerfile = "# Development stage\nFROM python:3.11-slim AS development\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\nEXPOSE 8000\n# Adjust CMD based on your framework:\n# FastAPI: CMD [\"uvicorn\", \"main:app\", \"--reload\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]\n# Flask: CMD [\"flask\", \"run\", \"--host=0.0.0.0\", \"--port=8000\"]\n# Django: CMD [\"python\", \"manage.py\", \"runserver\", \"0.0.0.0:8000\"]\nCMD [\"python\", \"-m\", \"http.server\", \"8000\"]\n\n# Production stage\nFROM python:3.11-slim AS production\nWORKDIR /app\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\n# Adjust CMD for production:\n# FastAPI: CMD [\"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]\n# Flask: CMD [\"gunicorn\", \"-b\", \"0.0.0.0:8000\", \"app:app\"]\n# Django: CMD [\"gunicorn\", \"-b\", \"0.0.0.0:8000\", \"myproject.wsgi:application\"]\nCMD [\"python\", \"-m\", \"http.server\", \"8000\"]\n";
9
+ export declare const pythonCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"8000:8000\"\n volumes:\n - .:/app\n environment:\n - FLASK_ENV=development\n - PYTHONUNBUFFERED=1\n";
10
+ export declare const goDockerfile = "# Development stage\nFROM golang:1.22-alpine AS development\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\n# Install Air for hot reload\nRUN go install github.com/air-verse/air@latest\nCMD [\"air\"]\n\n# Build stage\nFROM golang:1.22-alpine AS builder\nWORKDIR /app\nCOPY . .\nRUN go build -o main .\n\n# Production stage\nFROM alpine:latest AS production\nWORKDIR /app\nCOPY --from=builder /app/main .\nCMD [\"./main\"]\n";
11
+ export declare const goCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"8080:8080\"\n volumes:\n - .:/app\n - /go/pkg/mod\n";
12
+ export declare const javaDockerfile = "# Development stage\nFROM maven:3.9-eclipse-temurin-21 AS development\nWORKDIR /app\nCOPY pom.xml .\nRUN mvn dependency:go-offline\nCOPY src ./src\nCMD [\"mvn\", \"spring-boot:run\"]\n\n# Production stage\nFROM eclipse-temurin:21-jre-alpine AS production\nWORKDIR /app\nCOPY --from=development /app/target/*.jar app.jar\nCMD [\"java\", \"-jar\", \"app.jar\"]\n";
13
+ export declare const javaCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"8080:8080\"\n volumes:\n - .:/app\n - ~/.m2:/root/.m2\n";
14
+ export declare const phpDockerfile = "# Development stage\nFROM php:8.2-apache AS development\nWORKDIR /var/www/html\nCOPY composer.json composer.lock ./\nRUN apt-get update && apt-get install -y unzip\nRUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer\nRUN composer install\nCOPY . .\nCMD [\"apache2-foreground\"]\n\n# Production stage\nFROM php:8.2-apache AS production\nWORKDIR /var/www/html\nCOPY . .\nRUN chown -R www-data:www-data /var/www/html\n";
15
+ export declare const phpCompose = "services:\n app:\n build:\n context: .\n target: development\n ports:\n - \"80:80\"\n volumes:\n - .:/var/www/html\n";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,kaAkB1B,CAAC;AAEF,eAAO,MAAM,WAAW,6NAYvB,CAAC;AAGF,eAAO,MAAM,cAAc,0ZAkB1B,CAAC;AAEF,eAAO,MAAM,WAAW,6NAYvB,CAAC;AAGF,eAAO,MAAM,cAAc,qUAgB1B,CAAC;AAEF,eAAO,MAAM,WAAW,6NAYvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,wDAM5B,CAAC;AAKF,eAAO,MAAM,gBAAgB,igCAwB5B,CAAC;AAEF,eAAO,MAAM,aAAa,+NAYzB,CAAC;AAGF,eAAO,MAAM,YAAY,icAqBxB,CAAC;AAEF,eAAO,MAAM,SAAS,uKAUrB,CAAC;AAGF,eAAO,MAAM,cAAc,6WAa1B,CAAC;AAEF,eAAO,MAAM,WAAW,2KAUvB,CAAC;AAGF,eAAO,MAAM,aAAa,0dAezB,CAAC;AAEF,eAAO,MAAM,UAAU,uJAStB,CAAC"}
@@ -0,0 +1,233 @@
1
+ // --- JavaScript / TypeScript Ecosystem ---
2
+ // Vite Template (React, Vue, Svelte, etc.) - CSR
3
+ export const viteDockerfile = `# Development stage
4
+ FROM node:22-alpine AS development
5
+ WORKDIR /app
6
+ COPY package*.json ./
7
+ RUN npm install
8
+ COPY . .
9
+ EXPOSE 5173
10
+ CMD ["npm", "run", "dev", "--", "--host"]
11
+
12
+ # Build stage
13
+ FROM development AS builder
14
+ RUN npm run build
15
+
16
+ # Production stage
17
+ FROM nginx:alpine AS production
18
+ COPY --from=builder /app/dist /usr/share/nginx/html
19
+ EXPOSE 80
20
+ CMD ["nginx", "-g", "daemon off;"]
21
+ `;
22
+ export const viteCompose = `services:
23
+ app:
24
+ build:
25
+ context: .
26
+ target: development
27
+ ports:
28
+ - "5173:5173"
29
+ volumes:
30
+ - .:/app
31
+ - /app/node_modules
32
+ environment:
33
+ - NODE_ENV=development
34
+ `;
35
+ // Next.js Template - SSR
36
+ export const nextDockerfile = `# Development stage
37
+ FROM node:22-alpine AS development
38
+ WORKDIR /app
39
+ COPY package*.json ./
40
+ RUN npm install
41
+ COPY . .
42
+ EXPOSE 3000
43
+ # Ensure Host is 0.0.0.0 for Docker
44
+ CMD ["npm", "run", "dev", "--", "-H", "0.0.0.0"]
45
+
46
+ # Production stage
47
+ FROM node:22-alpine AS production
48
+ WORKDIR /app
49
+ COPY package*.json ./
50
+ RUN npm ci --omit=dev
51
+ COPY . .
52
+ RUN npm run build
53
+ CMD ["npm", "start"]
54
+ `;
55
+ export const nextCompose = `services:
56
+ app:
57
+ build:
58
+ context: .
59
+ target: development
60
+ ports:
61
+ - "3000:3000"
62
+ volumes:
63
+ - .:/app
64
+ - /app/node_modules
65
+ environment:
66
+ - NODE_ENV=development
67
+ `;
68
+ // Generic Node Template (Express, NestJS, etc.)
69
+ export const nodeDockerfile = `# Development stage
70
+ FROM node:22-alpine AS development
71
+ WORKDIR /app
72
+ COPY package*.json ./
73
+ RUN npm install
74
+ COPY . .
75
+ EXPOSE 3000
76
+ CMD ["npm", "run", "dev"]
77
+
78
+ # Production stage
79
+ FROM node:22-alpine AS production
80
+ WORKDIR /app
81
+ COPY package*.json ./
82
+ RUN npm ci --omit=dev
83
+ COPY . .
84
+ CMD ["npm", "start"]
85
+ `;
86
+ export const nodeCompose = `services:
87
+ app:
88
+ build:
89
+ context: .
90
+ target: development
91
+ ports:
92
+ - "3000:3000"
93
+ volumes:
94
+ - .:/app
95
+ - /app/node_modules
96
+ environment:
97
+ - NODE_ENV=development
98
+ `;
99
+ export const nodeDockerignore = `node_modules
100
+ dist
101
+ .git
102
+ .github
103
+ .vscode
104
+ .next
105
+ `;
106
+ // --- Generic Language Families ---
107
+ // Python Template (Flask, Django, FastAPI)
108
+ export const pythonDockerfile = `# Development stage
109
+ FROM python:3.11-slim AS development
110
+ WORKDIR /app
111
+ COPY requirements.txt .
112
+ RUN pip install --no-cache-dir -r requirements.txt
113
+ COPY . .
114
+ EXPOSE 8000
115
+ # Adjust CMD based on your framework:
116
+ # FastAPI: CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
117
+ # Flask: CMD ["flask", "run", "--host=0.0.0.0", "--port=8000"]
118
+ # Django: CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
119
+ CMD ["python", "-m", "http.server", "8000"]
120
+
121
+ # Production stage
122
+ FROM python:3.11-slim AS production
123
+ WORKDIR /app
124
+ COPY requirements.txt .
125
+ RUN pip install --no-cache-dir -r requirements.txt
126
+ COPY . .
127
+ # Adjust CMD for production:
128
+ # FastAPI: CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
129
+ # Flask: CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]
130
+ # Django: CMD ["gunicorn", "-b", "0.0.0.0:8000", "myproject.wsgi:application"]
131
+ CMD ["python", "-m", "http.server", "8000"]
132
+ `;
133
+ export const pythonCompose = `services:
134
+ app:
135
+ build:
136
+ context: .
137
+ target: development
138
+ ports:
139
+ - "8000:8000"
140
+ volumes:
141
+ - .:/app
142
+ environment:
143
+ - FLASK_ENV=development
144
+ - PYTHONUNBUFFERED=1
145
+ `;
146
+ // Go Template (Generic)
147
+ export const goDockerfile = `# Development stage
148
+ FROM golang:1.22-alpine AS development
149
+ WORKDIR /app
150
+ COPY go.mod go.sum ./
151
+ RUN go mod download
152
+ COPY . .
153
+ # Install Air for hot reload
154
+ RUN go install github.com/air-verse/air@latest
155
+ CMD ["air"]
156
+
157
+ # Build stage
158
+ FROM golang:1.22-alpine AS builder
159
+ WORKDIR /app
160
+ COPY . .
161
+ RUN go build -o main .
162
+
163
+ # Production stage
164
+ FROM alpine:latest AS production
165
+ WORKDIR /app
166
+ COPY --from=builder /app/main .
167
+ CMD ["./main"]
168
+ `;
169
+ export const goCompose = `services:
170
+ app:
171
+ build:
172
+ context: .
173
+ target: development
174
+ ports:
175
+ - "8080:8080"
176
+ volumes:
177
+ - .:/app
178
+ - /go/pkg/mod
179
+ `;
180
+ // Java Template (Maven/Gradle generic-ish)
181
+ export const javaDockerfile = `# Development stage
182
+ FROM maven:3.9-eclipse-temurin-21 AS development
183
+ WORKDIR /app
184
+ COPY pom.xml .
185
+ RUN mvn dependency:go-offline
186
+ COPY src ./src
187
+ CMD ["mvn", "spring-boot:run"]
188
+
189
+ # Production stage
190
+ FROM eclipse-temurin:21-jre-alpine AS production
191
+ WORKDIR /app
192
+ COPY --from=development /app/target/*.jar app.jar
193
+ CMD ["java", "-jar", "app.jar"]
194
+ `;
195
+ export const javaCompose = `services:
196
+ app:
197
+ build:
198
+ context: .
199
+ target: development
200
+ ports:
201
+ - "8080:8080"
202
+ volumes:
203
+ - .:/app
204
+ - ~/.m2:/root/.m2
205
+ `;
206
+ // PHP Template (Apache)
207
+ export const phpDockerfile = `# Development stage
208
+ FROM php:8.2-apache AS development
209
+ WORKDIR /var/www/html
210
+ COPY composer.json composer.lock ./
211
+ RUN apt-get update && apt-get install -y unzip
212
+ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
213
+ RUN composer install
214
+ COPY . .
215
+ CMD ["apache2-foreground"]
216
+
217
+ # Production stage
218
+ FROM php:8.2-apache AS production
219
+ WORKDIR /var/www/html
220
+ COPY . .
221
+ RUN chown -R www-data:www-data /var/www/html
222
+ `;
223
+ export const phpCompose = `services:
224
+ app:
225
+ build:
226
+ context: .
227
+ target: development
228
+ ports:
229
+ - "80:80"
230
+ volumes:
231
+ - .:/var/www/html
232
+ `;
233
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;CAkB7B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;CAY1B,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;CAkB7B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;CAY1B,CAAC;AAEF,gDAAgD;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;CAgB7B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;CAY1B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;CAM/B,CAAC;AAEF,oCAAoC;AAEpC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwB/B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;CAY5B,CAAC;AAEF,wBAAwB;AACxB,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;CAqB3B,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;CAUxB,CAAC;AAEF,2CAA2C;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;CAa7B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;CAU1B,CAAC;AAEF,wBAAwB;AACxB,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;CAe5B,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;CASzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface Config {
2
+ project_name: string;
3
+ type?: string;
4
+ }
5
+ export declare function loadConfig(): Config | null;
6
+ export declare function writeConfig(config: Config): void;
7
+ export declare function getProjectName(): string;
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAO1C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGhD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
@@ -0,0 +1,20 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as yaml from 'js-yaml';
4
+ export function loadConfig() {
5
+ try {
6
+ const data = fs.readFileSync('anvil.yaml', 'utf8');
7
+ return yaml.load(data);
8
+ }
9
+ catch (error) {
10
+ return null;
11
+ }
12
+ }
13
+ export function writeConfig(config) {
14
+ const yamlStr = yaml.dump(config);
15
+ fs.writeFileSync('anvil.yaml', yamlStr, 'utf8');
16
+ }
17
+ export function getProjectName() {
18
+ return path.basename(process.cwd());
19
+ }
20
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAOhC,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAW,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function checkFileExists(filename: string): boolean;
2
+ export declare function detectProjectType(): string;
3
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/utils/detect.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAwB1C"}
@@ -0,0 +1,66 @@
1
+ import * as fs from 'fs';
2
+ export function checkFileExists(filename) {
3
+ try {
4
+ fs.statSync(filename);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ export function detectProjectType() {
12
+ if (checkFileExists('package.json')) {
13
+ // Differentiate between JS frameworks based on build tools
14
+ if (isNextApp()) {
15
+ return 'next'; // Next.js (SSR, Port 3000)
16
+ }
17
+ if (isViteApp()) {
18
+ return 'vite'; // React/Vue/Svelte + Vite (CSR, Port 5173)
19
+ }
20
+ return 'node'; // Generic Node.js (Express/Nest, Port 3000)
21
+ }
22
+ if (checkFileExists('requirements.txt') || checkFileExists('pyproject.toml')) {
23
+ return 'python';
24
+ }
25
+ if (checkFileExists('go.mod')) {
26
+ return 'go';
27
+ }
28
+ if (checkFileExists('pom.xml') || checkFileExists('build.gradle')) {
29
+ return 'java';
30
+ }
31
+ if (checkFileExists('composer.json')) {
32
+ return 'php';
33
+ }
34
+ return 'unknown';
35
+ }
36
+ function isNextApp() {
37
+ return checkDependency('next');
38
+ }
39
+ function isViteApp() {
40
+ return checkDependency('vite');
41
+ }
42
+ function checkDependency(depName) {
43
+ try {
44
+ const data = fs.readFileSync('package.json', 'utf8');
45
+ const pkg = JSON.parse(data);
46
+ if (pkg.dependencies) {
47
+ for (const key in pkg.dependencies) {
48
+ if (key.includes(depName)) {
49
+ return true;
50
+ }
51
+ }
52
+ }
53
+ if (pkg.devDependencies) {
54
+ for (const key in pkg.devDependencies) {
55
+ if (key.includes(depName)) {
56
+ return true;
57
+ }
58
+ }
59
+ }
60
+ return false;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/utils/detect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;QACpC,2DAA2D;QAC3D,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,OAAO,MAAM,CAAC,CAAC,2BAA2B;QAC5C,CAAC;QACD,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,OAAO,MAAM,CAAC,CAAC,2CAA2C;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC,CAAC,4CAA4C;IAC7D,CAAC;IACD,IAAI,eAAe,CAAC,kBAAkB,CAAC,IAAI,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC7E,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,eAAe,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,cAAc,CAAC,EAAE,CAAC;QAClE,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,eAAe,CAAC,eAAe,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAG1B,CAAC;QAEF,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;YACrB,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;gBACnC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;gBACtC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "hylius",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A CLI tool to initialize and manage Docker configurations for development",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "hylius": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js"
14
+ },
15
+ "keywords": [
16
+ "docker",
17
+ "cli",
18
+ "development",
19
+ "devops",
20
+ "docker-config",
21
+ "development-environment"
22
+ ],
23
+ "author": "Your Name Chukwudulue Isaac",
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/isaac-hash/hylius.git"
28
+ },
29
+ "homepage": "https://github.com/isaac-hash/hylius#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/isaac-hash/hylius/issues"
32
+ },
33
+ "engines": {
34
+ "node": ">=18.0.0"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "dependencies": {
42
+ "chalk": "^5.3.0",
43
+ "commander": "^12.0.0",
44
+ "js-yaml": "^4.1.0",
45
+ "ora": "^8.0.1"
46
+ },
47
+ "devDependencies": {
48
+ "@types/js-yaml": "^4.0.9",
49
+ "@types/node": "^20.11.0",
50
+ "tsx": "^4.7.0",
51
+ "typescript": "^5.3.3"
52
+ }
53
+ }