UNPKG

@dhlab/e2e-autogen

Version:

Google 스프레드시트 기반 시나리오를 Playwright 테스트 스텁 코드로 자동 생성하고, 테스트 실행 결과를 다시 시트에 업데이트하는 CLI 도구

193 lines (191 loc) 8.14 kB
'use strict'; var _UserConfig_instances, _UserConfig_configPath, _UserConfig_fileExists, _UserConfig_loadConfig, _UserConfig_loadWithTsx, _UserConfig_loadWithTsNode, _UserConfig_loadWithDynamicImport, _UserConfig_validateConfig; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadUserConfig = void 0; const tslib_1 = require("tslib"); const child_process_1 = require("child_process"); const path_1 = tslib_1.__importDefault(require("path")); const util_1 = require("util"); const execAsync = (0, util_1.promisify)(child_process_1.exec); class UserConfig { constructor(configPath = "e2e-autogen.config.ts") { _UserConfig_instances.add(this); _UserConfig_configPath.set(this, void 0); tslib_1.__classPrivateFieldSet(this, _UserConfig_configPath, path_1.default.resolve(configPath), "f"); } async load() { if (!tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_fileExists).call(this)) { throw new Error(`Config file not found: ${tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f")}`); } return tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_loadConfig).call(this); } } _UserConfig_configPath = new WeakMap(), _UserConfig_instances = new WeakSet(), _UserConfig_fileExists = function _UserConfig_fileExists() { try { const fs = require("fs"); return fs.existsSync(tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f")); } catch { return false; } }, _UserConfig_loadConfig = async function _UserConfig_loadConfig() { // 방법 1: tsx 사용 try { return await tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_loadWithTsx).call(this); } catch (error) { } // 방법 2: ts-node 사용 try { return await tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_loadWithTsNode).call(this); } catch (error) { } // 방법 3: 직접 파일 읽기 후 동적 import try { return await tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_loadWithDynamicImport).call(this); } catch (error) { } throw new Error(`Failed to load config from ${tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f")}. All methods failed.`); }, _UserConfig_loadWithTsx = async function _UserConfig_loadWithTsx() { const command = `tsx -e " import('${tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f")}').then(module => { const config = module.default || module; console.log(JSON.stringify(config)); }).catch(err => { console.error('Import error:', err.message); process.exit(1); }) "`; const { stdout } = await execAsync(command); const output = stdout.trim(); if (!output) { throw new Error("Empty output from tsx"); } try { const parsed = JSON.parse(output); const config = parsed.default || parsed; tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_validateConfig).call(this, config); return config; } catch (parseError) { // JSON 파싱이 실패하면 수동으로 추출 시도 try { const jsonMatch = output.match(/\{[\s\S]*\}/); if (jsonMatch) { const manualParsed = JSON.parse(jsonMatch[0]); const config = manualParsed.default || manualParsed; tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_validateConfig).call(this, config); return config; } } catch { // 무시 } throw new Error(`Failed to parse tsx output: ${parseError.message}`); } }, _UserConfig_loadWithTsNode = async function _UserConfig_loadWithTsNode() { const command = `npx ts-node --esm -e " import('${tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f").replace(".ts", "")}').then(module => { const config = module.default || module; console.log(JSON.stringify(config)); }).catch(err => { console.error('Import error:', err.message); process.exit(1); }) "`; try { const { stdout } = await execAsync(command); const output = stdout.trim(); if (!output) { throw new Error("Empty output from ts-node"); } const parsed = JSON.parse(output); const config = parsed.default || parsed; tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_validateConfig).call(this, config); return config; } catch (execError) { // ts-node가 실패하면 다른 방법 시도 try { const fallbackCommand = `npx ts-node -e " const fs = require('fs'); const content = fs.readFileSync('${tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f")}', 'utf-8'); const config = eval('(' + content.replace(/export\\s+default\\s+/, '') + ')'); console.log(JSON.stringify(config)); "`; const { stdout } = await execAsync(fallbackCommand); const output = stdout.trim(); const config = JSON.parse(output); tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_validateConfig).call(this, config); return config; } catch { throw new Error(`Failed to parse ts-node output: ${execError.message}`); } } }, _UserConfig_loadWithDynamicImport = async function _UserConfig_loadWithDynamicImport() { const fs = await import('fs'); const content = fs.readFileSync(tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f"), "utf-8"); // export default를 찾아서 추출 const defaultExportPatterns = [ /export\s+default\s+({[\s\S]*?});?$/m, /export\s+default\s+([^;]+);?$/m, /const\s+config\s*=\s*({[\s\S]*?});?\s*export\s+default\s+config;?$/m, /export\s+default\s+([^;]+);?$/m, ]; let defaultExportMatch = null; for (const pattern of defaultExportPatterns) { defaultExportMatch = content.match(pattern); if (defaultExportMatch) { break; } } if (!defaultExportMatch) { // export default가 없으면 전체 파일에서 객체를 찾기 const objectPattern = /({[\s\S]*?});?$/m; const objectMatch = content.match(objectPattern); if (objectMatch) { defaultExportMatch = objectMatch; } else { throw new Error("No default export or object found in config file"); } } // 임시 JS 파일 생성 const tempJsPath = tslib_1.__classPrivateFieldGet(this, _UserConfig_configPath, "f").replace(".ts", ".temp.js"); const jsContent = ` const config = ${defaultExportMatch[1]}; console.log(JSON.stringify(config)); `; fs.writeFileSync(tempJsPath, jsContent); try { const { stdout } = await execAsync(`node ${tempJsPath}`); const output = stdout.trim(); const config = JSON.parse(output); tslib_1.__classPrivateFieldGet(this, _UserConfig_instances, "m", _UserConfig_validateConfig).call(this, config); return config; } finally { // 임시 파일 정리 try { fs.unlinkSync(tempJsPath); } catch { // 무시 } } }, _UserConfig_validateConfig = function _UserConfig_validateConfig(config) { if (!config || typeof config !== "object") { throw new Error("Config must be an object"); } const requiredFields = ["sheetsUrl", "framework", "stubOutputFolder"]; for (const field of requiredFields) { if (!(field in config)) { throw new Error(`Missing required config field: ${field}`); } } }; const loadUserConfig = async () => { const loader = new UserConfig(); return loader.load(); }; exports.loadUserConfig = loadUserConfig;