| "use strict"; |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| var desc = Object.getOwnPropertyDescriptor(m, k); |
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { |
| desc = { enumerable: true, get: function() { return m[k]; } }; |
| } |
| Object.defineProperty(o, k2, desc); |
| }) : (function(o, m, k, k2) { |
| if (k2 === undefined) k2 = k; |
| o[k2] = m[k]; |
| })); |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { |
| Object.defineProperty(o, "default", { enumerable: true, value: v }); |
| }) : function(o, v) { |
| o["default"] = v; |
| }); |
| var __importStar = (this && this.__importStar) || (function () { |
| var ownKeys = function(o) { |
| ownKeys = Object.getOwnPropertyNames || function (o) { |
| var ar = []; |
| for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; |
| return ar; |
| }; |
| return ownKeys(o); |
| }; |
| return function (mod) { |
| if (mod && mod.__esModule) return mod; |
| var result = {}; |
| if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); |
| __setModuleDefault(result, mod); |
| return result; |
| }; |
| })(); |
| var __importDefault = (this && this.__importDefault) || function (mod) { |
| return (mod && mod.__esModule) ? mod : { "default": mod }; |
| }; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.loadWorkspaceConfig = loadWorkspaceConfig; |
| exports.buildWorkspaceImage = buildWorkspaceImage; |
| const promises_1 = __importDefault(require("fs/promises")); |
| const path_1 = __importDefault(require("path")); |
| const tar = __importStar(require("tar-fs")); |
| |
| |
| |
| |
| function parseBasicNix(nixContent) { |
| var _a, _b, _c, _d; |
| const config = { packages: { apt: [], npm: [] }, env: {} }; |
| |
| const pkgMatches = nixContent.matchAll(/pkgs\.([a-zA-Z0-9_\-]+)/g); |
| for (const match of pkgMatches) { |
| let pkgName = match[1]; |
| |
| if (pkgName.startsWith('nodejs')) |
| pkgName = 'nodejs npm'; |
| else if (pkgName.startsWith('python')) |
| pkgName = 'python3 python3-pip'; |
| else if (pkgName === 'go') |
| pkgName = 'golang'; |
| else if (pkgName === 'rust') |
| pkgName = 'rustc cargo'; |
| |
| const split = pkgName.split(' '); |
| for (const p of split) { |
| if (!((_b = (_a = config.packages) === null || _a === void 0 ? void 0 : _a.apt) === null || _b === void 0 ? void 0 : _b.includes(p))) { |
| (_d = (_c = config.packages) === null || _c === void 0 ? void 0 : _c.apt) === null || _d === void 0 ? void 0 : _d.push(p); |
| } |
| } |
| } |
| |
| const envBlockMatch = nixContent.match(/env\s*=\s*{([^}]+)}/); |
| if (envBlockMatch) { |
| const envLines = envBlockMatch[1].split('\n'); |
| for (const line of envLines) { |
| const kvMatch = line.trim().match(/([a-zA-Z0-9_]+)\s*=\s*['"]?([^'";]+)['"]?\s*;/); |
| if (kvMatch) { |
| if (config.env) |
| config.env[kvMatch[1]] = kvMatch[2]; |
| } |
| } |
| } |
| return config; |
| } |
| async function loadWorkspaceConfig(workspacePath) { |
| const codeverseJsonPath = path_1.default.join( workspacePath, 'codeverse.json'); |
| const idxNixPath = path_1.default.join( workspacePath, '.idx', 'dev.nix'); |
| |
| try { |
| const nixContent = await promises_1.default.readFile(idxNixPath, 'utf-8'); |
| return parseBasicNix(nixContent); |
| } |
| catch (_a) { |
| |
| } |
| |
| try { |
| const jsonContent = await promises_1.default.readFile(codeverseJsonPath, 'utf-8'); |
| return JSON.parse(jsonContent); |
| } |
| catch (err) { |
| const fsErr = err; |
| if (fsErr.code === 'ENOENT') { |
| |
| const defaultConfig = { |
| "env": { "PORT": "3000" }, |
| "packages": { "apt": [], "npm": [] } |
| }; |
| await promises_1.default.writeFile(codeverseJsonPath, JSON.stringify(defaultConfig, null, 2)); |
| return defaultConfig; |
| } |
| throw err; |
| } |
| } |
| |
| |
| |
| |
| async function buildWorkspaceImage(workspaceId, workspacePath, onLog, docker) { |
| var _a, _b, _c; |
| onLog("Loading workspace configuration (codeverse.json or dev.nix)..."); |
| const config = await loadWorkspaceConfig(workspacePath); |
| |
| let dockerfile = `FROM codercom/code-server:latest\n`; |
| dockerfile += `USER root\n`; |
| |
| if (((_a = config.packages) === null || _a === void 0 ? void 0 : _a.apt) && config.packages.apt.length > 0) { |
| const aptList = config.packages.apt.join(' '); |
| dockerfile += `RUN apt-get update && apt-get install -y ${aptList} && rm -rf /var/lib/apt/lists/*\n`; |
| } |
| |
| if (((_b = config.packages) === null || _b === void 0 ? void 0 : _b.npm) && config.packages.npm.length > 0) { |
| |
| if (!((_c = config.packages.apt) === null || _c === void 0 ? void 0 : _c.some(p => p.includes('npm')))) { |
| dockerfile += `RUN apt-get update && apt-get install -y nodejs npm && rm -rf /var/lib/apt/lists/*\n`; |
| } |
| const npmList = config.packages.npm.join(' '); |
| dockerfile += `RUN npm install -g ${npmList}\n`; |
| } |
| |
| |
| if (config.env) { |
| for (const [k, v] of Object.entries(config.env)) { |
| dockerfile += `ENV ${k}="${v}"\n`; |
| dockerfile += `RUN echo 'export ${k}="${v}"' >> /home/coder/.bashrc\n`; |
| } |
| } |
| dockerfile += `USER coder\n`; |
| |
| dockerfile += `WORKDIR /home/coder/project\n`; |
| |
| const buildDir = path_1.default.join( workspacePath, '.codeverse'); |
| await promises_1.default.mkdir(buildDir, { recursive: true }); |
| const dockerfilePath = path_1.default.join( buildDir, 'Dockerfile'); |
| await promises_1.default.writeFile(dockerfilePath, dockerfile); |
| const imageName = `codeverse-workspace-${workspaceId}`; |
| onLog(`Building image ${imageName}...`); |
| return new Promise((resolve, reject) => { |
| |
| const pack = tar.pack(buildDir); |
| docker.buildImage(pack, { t: imageName }, (err, stream) => { |
| if (err) |
| return reject(err); |
| if (!stream) |
| return reject(new Error("No stream returned from Docker build")); |
| docker.modem.followProgress(stream, (err2) => { |
| if (err2) |
| return reject(err2); |
| onLog(`Image ${imageName} built successfully.`); |
| resolve({ imageName, config }); |
| }, (event) => { |
| if (event.stream) |
| onLog(event.stream.trim()); |
| else if (event.status) |
| onLog(event.status.trim()); |
| else if (event.error) |
| onLog(`Build Error: ${event.error}`); |
| }); |
| }); |
| }); |
| } |
|
|