Deno
Executive Summary
Goal: Migrate penguins-eggs from Node.js + OCLIF to Deno + Cliffy while maintaining full compatibility and improving performance.
Key Benefits:
- 🚀 Startup Performance: 5-10x faster (1000ms → 100-200ms)
- 💾 Memory Usage: 50-70% reduction (120MB → 40MB)
- 📦 Binary Size: Smaller single binary (~50-80MB vs 200MB)
- 🔒 Security: Granular permissions by default
- 🛠️ Tooling: Built-in TypeScript, testing, formatting, linting
- 📚 Dependencies: No more npm/node_modules hell
Current Architecture Analysis
Current Stack:
- Language: TypeScript
- Runtime: Node.js 18+
- CLI Framework: OCLIF v4.2.7
- UI: Ink v5.0.1 (React for terminal)
- Package Manager: pnpm
- Dependencies: 20+ packages including axios, inquirer, js-yaml, mustache
Core Dependencies to Migrate:
// Current (Node.js)
"@oclif/core": "^4.2.7"
"ink": "^5.0.1"
"inquirer": "^9.3.7"
"axios": "^1.7.9"
"js-yaml": "^4.1.0"
"mustache": "^4.2.0"
"react": "^18.3.1"
// Target (Deno)
"@cliffy/command" // CLI framework
"@cliffy/prompt" // Interactive prompts
"@std/yaml" // YAML parsing
"@std/http" // HTTP client
"mustache" // Template engine (compatible)
Migration Strategy: Gradual Transition
Phase 1: Foundation Setup (Week 1-2)
Goal: Establish Deno infrastructure alongside existing Node.js code
1.1 Project Structure Setup
penguins-eggs/
├── src/ # 📁 Existing Node.js code
├── deno-src/ # 📁 New Deno implementation
├── shared/ # 📁 Common utilities
├── scripts/ # 📁 Build and migration scripts
├── package.json # 📦 Node.js dependencies
├── deno.json # 🦕 Deno configuration
├── deps.ts # 📦 Centralized Deno dependencies
└── import_map.json # 🗺️ Import mappings
1.2 Deno Configuration
// deno.json
{
"tasks": {
"dev": "deno run --allow-all --watch deno-src/main.ts",
"build": "deno compile --allow-all --output dist/eggs deno-src/main.ts",
"test": "deno test --allow-all",
"fmt": "deno fmt",
"lint": "deno lint",
"check": "deno check deno-src/main.ts"
},
"compilerOptions": {
"strict": true,
"lib": ["deno.window"]
},
"imports": {
"@cliffy/": "https://deno.land/x/cliffy@v1.0.0-rc.3/",
"@std/": "https://deno.land/std@0.220.0/"
}
}
1.3 Dependencies Management
// deps.ts - Centralized dependency management
export { Command, EnumType } from "@cliffy/command";
export { Input, Select, Toggle, Confirm } from "@cliffy/prompt";
export { Table, Cell } from "@cliffy/table";
export { colors } from "@cliffy/ansi/colors";
export { parse as parseYaml, stringify as stringifyYaml } from "@std/yaml";
export { ensureDir, exists, copy } from "@std/fs";
export { join, dirname, basename } from "@std/path";
export { render } from "https://deno.land/x/mustache@v0.3.0/mod.ts";
Phase 2: Core Infrastructure (Week 3-4)
Goal: Migrate essential utilities and services
2.1 Configuration Service
// deno-src/services/ConfigService.ts
import { parseYaml, stringifyYaml, ensureDir, exists } from "../deps.ts";
export class ConfigService {
private configPath = "/etc/penguins-eggs.d/eggs.yaml";
async load(): Promise<EggsConfig> {
if (await exists(this.configPath)) {
const content = await Deno.readTextFile(this.configPath);
return parseYaml(content) as EggsConfig;
}
return this.getDefaults();
}
async save(config: EggsConfig): Promise<void> {
await ensureDir(dirname(this.configPath));
const content = stringifyYaml(config);
await Deno.writeTextFile(this.configPath, content);
}
}
2.2 Shell Service
// deno-src/services/ShellService.ts
export class ShellService {
async run(cmd: string[], options?: Deno.CommandOptions): Promise<Deno.CommandOutput> {
const command = new Deno.Command(cmd[0], {
args: cmd.slice(1),
...options
});
return await command.output();
}
async checkCommand(command: string): Promise<boolean> {
try {
const result = await this.run(["which", command]);
return result.success;
} catch {
return false;
}
}
}
2.3 Progress UI Components
// deno-src/ui/Progress.ts
import { colors } from "../deps.ts";
export class ProgressBar {
private current = 0;
private total = 100;
private width = 40;
update(current: number, message?: string) {
this.current = current;
const percent = Math.round((current / this.total) * 100);
const filled = Math.round((current / this.total) * this.width);
const empty = this.width - filled;
const bar = colors.green("█".repeat(filled)) + colors.gray("░".repeat(empty));
const line = `\r${bar} ${percent}% ${message || ""}`;
Deno.stdout.writeSync(new TextEncoder().encode(line));
if (current >= this.total) {
console.log(); // New line when complete
}
}
}
Phase 3: Command Migration (Week 5-8)
Goal: Migrate commands one by one, starting with simple ones
3.1 Basic Commands (Week 5)
Priority Order:
eggs version
- Simple, no dependencieseggs status
- System info gatheringeggs config
- Configuration management
// deno-src/commands/version.ts
import { Command } from "../deps.ts";
export const versionCommand = new Command()
.name("version")
.description("Show eggs version")
.action(() => {
console.log("penguins-eggs 11.0.0-deno");
});
3.2 Interactive Commands (Week 6)
eggs dad
- Configuration TUIeggs mom
- Help system
// deno-src/commands/dad.ts
import { Command, Input, Select, Confirm } from "../deps.ts";
import { ConfigService } from "../services/ConfigService.ts";
export const dadCommand = new Command()
.name("dad")
.description("Configuration helper")
.option("-d, --default", "Reset to defaults")
.action(async (options) => {
const configService = new ConfigService();
if (options.default) {
await configService.save(configService.getDefaults());
console.log("Configuration reset to defaults");
return;
}
// Interactive configuration
const config = await configService.load();
const compression = await Select.prompt({
message: "Select compression method:",
options: [
{ name: "Fast (zstd)", value: "zstd" },
{ name: "Standard (xz)", value: "xz" },
{ name: "Maximum (xz -Xbcj)", value: "max" }
],
default: config.compression
});
config.compression = compression;
await configService.save(config);
});
3.3 Utility Commands (Week 7)
eggs tools clean
- System cleanupeggs tools yolk
- Package managementeggs kill
- ISO cleanup
3.4 Wardrobe System (Week 8)
eggs wardrobe get
eggs wardrobe wear
eggs wardrobe list
Phase 4: Core Features (Week 9-12)
Goal: Migrate the most complex and critical functionality
4.1 ISO Production (Week 9-10)
The heart of penguins-eggs:
// deno-src/commands/produce.ts
import { Command, EnumType } from "../deps.ts";
import { ISOBuilder } from "../services/ISOBuilder.ts";
import { ProgressBar } from "../ui/Progress.ts";
const compressionType = new EnumType(["zstd", "xz", "max"]);
export const produceCommand = new Command()
.name("produce")
.description("Produce a live image from your system")
.type("compression", compressionType)
.option("-c, --clone", "Include user data")
.option("-C, --cryptedclone", "Include encrypted user data")
.option("--compression <type:compression>", "Compression method", { default: "zstd" })
.option("--basename <name>", "ISO basename")
.option("--theme <theme>", "Theme for live system")
.action(async (options) => {
const progress = new ProgressBar();
const builder = new ISOBuilder(options);
progress.update(0, "Initializing...");
await builder.initialize();
progress.update(20, "Copying system files...");
await builder.copySystem();
progress.update(60, "Creating squashfs...");
await builder.createSquashfs();
progress.update(80, "Building ISO...");
await builder.buildISO();
progress.update(100, "Complete!");
});
4.2 Installation System (Week 11)
eggs install
/eggs krill
- System installer
4.3 Network Features (Week 12)
eggs cuckoo
- PXE servereggs syncto
/eggs syncfrom
- LUKS encryption
Phase 5: Advanced Features (Week 13-16)
Goal: Complete feature parity and optimization
5.1 Calamares Integration
- Configuration generation
- Theme management
- Multi-architecture support
5.2 Package Detection & Distribution Support
// deno-src/services/DistroDetector.ts
export class DistroDetector {
async detect(): Promise<DistroInfo> {
const osRelease = await Deno.readTextFile("/etc/os-release");
// Parse and detect distribution
}
async getPackageManager(): Promise<PackageManager> {
// Detect apt, pacman, dnf, zypper, etc.
}
}
5.3 Build System Integration
- Replace perrisbrewery with Deno compile
- Create native packages for different distributions
- CI/CD pipeline updates
Migration Checklist
Development Environment
- Set up Deno development environment
- Configure VS Code with Deno extension
- Create development scripts and tasks
- Set up testing framework
Core Infrastructure
- Migrate configuration system
- Implement shell service
- Create progress UI components
- Set up error handling and logging
Command Migration
- Migrate simple commands (version, status, config)
- Migrate interactive commands (dad, mom)
- Migrate utility commands (tools, kill)
- Migrate wardrobe system
- Migrate core ISO production
- Migrate installation system
- Migrate network features
Testing & Quality Assurance
- Unit tests for all services
- Integration tests for commands
- Cross-platform testing
- Performance benchmarks
- Memory usage analysis
Documentation & Distribution
- Update documentation
- Create migration guide
- Update build scripts
- Package for distributions
- Update CI/CD pipelines
Performance Expectations
Metric | Node.js (Current) | Deno (Target) | Improvement |
---|---|---|---|
Cold Start | 1000-1500ms | 100-200ms | 5-10x faster |
Memory Usage | 80-120MB | 20-40MB | 50-70% less |
Binary Size | ~200MB | 50-80MB | 60-75% smaller |
Dependencies | 20+ packages | Built-in + few | Simplified |
Risk Mitigation
Technical Risks
-
Dependency Compatibility: Some Node.js packages may not have Deno equivalents
- Mitigation: Identify alternatives early, contribute to Deno ecosystem if needed
-
Platform Compatibility: Ensure all Linux distributions are supported
- Mitigation: Extensive testing on target distributions
-
Performance Regressions: Some operations might be slower in Deno
- Mitigation: Benchmark critical operations, optimize bottlenecks
Business Risks
-
User Adoption: Users may resist change
- Mitigation: Gradual rollout, maintain Node.js version until Deno is stable
-
Distribution Packaging: Need to update all distribution packages
- Mitigation: Coordinate with distribution maintainers
Timeline Summary
Phase | Duration | Milestone |
---|---|---|
Phase 1 | Week 1-2 | Foundation & Setup |
Phase 2 | Week 3-4 | Core Infrastructure |
Phase 3 | Week 5-8 | Command Migration |
Phase 4 | Week 9-12 | Core Features |
Phase 5 | Week 13-16 | Advanced Features |
Total Duration: 16 weeks (~4 months)
Success Metrics
- Functional Parity: All current features working in Deno version
- Performance: 5x+ faster startup, 50%+ less memory usage
- User Experience: Seamless migration for end users
- Maintainability: Cleaner codebase, better developer experience
- Distribution: Available in all currently supported Linux distributions
Next Steps
- Week 1: Set up development environment and create PoC
- Week 2: Migrate first simple command (version/status)
- Week 3: Establish CI/CD pipeline for Deno
- Week 4: Begin core service migrations
Ready to start the journey from Node.js to Deno! 🚀