UNPKG

openapi-ts-mock-generator

Version:
1 lines 15.9 kB
{"version":3,"sources":["../../src/utils/string-utils.ts","../../src/utils/code-utils.ts","../../src/core/config.ts","../../src/utils/array-utils.ts","../../src/utils/file-utils.ts","../../src/utils/validation.ts"],"sourcesContent":["/**\n * 문자열 처리 관련 유틸리티 함수들\n */\n\n/**\n * UUID를 Base64 형태로 변환\n * URL-safe Base64 인코딩을 사용하여 패딩 제거\n */\nexport const uuidToB64 = (uuid: string): string => {\n const uuidBuffer = Buffer.from(uuid.replace(/-/g, \"\"), \"hex\")\n const base64Uuid = uuidBuffer\n .toString(\"base64\")\n .replace(/\\+/g, \"-\") // + 를 - 로\n .replace(/\\//g, \"_\") // / 를 _ 로\n .replace(/=/g, \"\") // 패딩 제거\n return base64Uuid\n}\n\n/**\n * camelCase 문자열을 kebab-case로 변환\n */\nexport const camelToKebab = (str: string): string => {\n return str.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase()\n}\n\n/**\n * 문자열이 URL인지 확인\n */\nexport const isUrl = (str: string): boolean => {\n return str.startsWith(\"http://\") || str.startsWith(\"https://\")\n}\n\n/**\n * 파일 확장자 추출\n */\nexport const getFileExtension = (filename: string): string => {\n return filename.split(\".\").pop() || \"\"\n}\n","/**\n * 코드 생성 관련 유틸리티 함수들\n */\n\nimport { ParseSchemaType, TypeScriptCodeOptions, CodeFormatOptions } from \"../core\"\n\n/**\n * 객체를 TypeScript 코드로 변환 (nullable 타입 확장 지원)\n * 동적 모킹에서 optional 필드를 지원하는 코드를 생성\n */\nexport const toTypeScriptCode = (\n param: ParseSchemaType,\n options: TypeScriptCodeOptions\n): string => {\n const { depth = 0, isStatic } = options\n\n const prefixSpace = \" \".repeat(depth * 2) // 들여쓰기용\n\n if (param === null) {\n return \"null\"\n }\n\n if (Array.isArray(param)) {\n const results = param\n .map((elem) => toTypeScriptCode(elem, { ...options, depth: depth + 1 }))\n .join(\",\\n\" + prefixSpace)\n return [\"[\", results, \"]\"].join(\"\\n\" + prefixSpace)\n }\n\n if (typeof param === \"object\") {\n const results = Object.entries(param)\n .map(([key, value]) => {\n return generateObjectProperty(key, value, options, prefixSpace)\n })\n .join(\"\\n\" + prefixSpace)\n\n return [\"{\", `${results}`, \"}\"].join(\"\\n\" + prefixSpace)\n }\n\n // 문자열 처리\n if (typeof param === \"string\") {\n // 동적 faker 호출은 그대로 유지\n if (\n isStatic === false &&\n (param.startsWith(\"faker\") || param.startsWith(\"Buffer.from(faker\"))\n ) {\n return param\n }\n\n // \" as const\" 분리하여 처리\n if (param.endsWith(\" as const\")) {\n return `\"${param.slice(0, -\" as const\".length)}\" as const`\n }\n }\n\n return JSON.stringify(param)\n}\n\n/**\n * nullable 타입 확장 여부 확인\n */\nconst shouldApplyNullableExtension = (value: any, isOptional: boolean): boolean => {\n if (!isOptional) return false\n\n // 값이 null인 경우\n if (value === null) return true\n\n // 문자열 및 null을 포함한 경우\n if (typeof value === \"string\" && value.includes(\",null\")) {\n return true\n }\n\n return false\n}\n\n/**\n * 객체 프로퍼티를 생성 (nullable 타입 확장 포함)\n */\nconst generateObjectProperty = (\n key: string,\n value: any,\n options: TypeScriptCodeOptions,\n prefixSpace: string\n): string => {\n const { isOptional, depth = 0 } = options\n\n // nullable 타입 확장 로직\n const shouldApplyNullable = shouldApplyNullableExtension(value, isOptional)\n const nullableTypeExtensionStart = shouldApplyNullable\n ? `...(faker.datatype.boolean() ? {\\n${prefixSpace}`\n : \"\"\n const nullableTypeExtensionEnd = shouldApplyNullable ? `\\n${prefixSpace}} : {})` : \"\"\n\n const propertyValue = toTypeScriptCode(value, {\n ...options,\n depth: depth + 1,\n })\n\n return `${nullableTypeExtensionStart}${prefixSpace}${key}: ${propertyValue}${nullableTypeExtensionEnd},`\n}\n\n/**\n * 멀티라인 코드를 한 줄로 압축\n */\nexport const compressCode = (code: string): string => {\n return code\n .replace(/\\n/g, \" \") // 줄바꿈을 공백으로\n .replace(/\\s+/g, \" \") // 연속된 공백을 하나로\n .replace(/\\s\\./g, \".\") // 공백 + 점을 점으로\n .trim()\n}\n\n/**\n * TypeScript 인터페이스 코드 생성\n */\nexport const generateInterface = (name: string, properties: Record<string, string>): string => {\n const props = Object.entries(properties)\n .map(([key, type]) => ` ${key}: ${type}`)\n .join(\"\\n\")\n\n return `interface ${name} {\\n${props}\\n}`\n}\n\n/**\n * TypeScript 타입 별칭 코드 생성\n */\nexport const generateTypeAlias = (name: string, type: string): string => {\n return `type ${name} = ${type}`\n}\n","import { Faker, ko } from \"@faker-js/faker\"\nimport { Options } from \"./types\"\n\n/**\n * 기본 옵션 설정\n */\nexport const defaultOptions: Options = {\n path: \"\",\n arrayMinLength: 1,\n arrayMaxLength: 3,\n includeCodes: undefined,\n baseDir: \"./\",\n specialPath: undefined,\n handlerUrl: \"*\",\n fakerLocale: \"ko\",\n generateTarget: \"api,schema\",\n clear: false,\n // TypeScriptCodeOptions\n isStatic: false,\n isOptional: false,\n}\n\n/**\n * 배열 길이 관련 상수\n */\nexport const ARRAY_MIN_LENGTH = 1\nexport const ARRAY_MAX_LENGTH = 3\n\n/**\n * 문자열 길이 관련 상수\n */\nexport const MIN_STRING_LENGTH = 3\nexport const MAX_STRING_LENGTH = 20\n\n/**\n * 정수 범위 관련 상수\n */\nexport const MIN_INTEGER = 1\nexport const MAX_INTEGER = 100000\n\n/**\n * 소수 범위 관련 상수\n */\nexport const MIN_NUMBER = 0\nexport const MAX_NUMBER = 100\n\n/**\n * 단어 길이 관련 상수\n */\nexport const MIN_WORD_LENGTH = 0\nexport const MAX_WORD_LENGTH = 3\n\n/**\n * Faker 시드값 (일관된 결과를 위함)\n */\nconst FAKER_SEED = 1\n\n/**\n * 전역 Faker 인스턴스\n * 한국어 로케일을 기본으로 설정하고 시드를 고정하여 일관된 결과 제공\n */\nexport const faker = new Faker({\n locale: [ko],\n})\nfaker.seed(FAKER_SEED)\n\n/**\n * 생성된 파일의 상단에 추가되는 주석\n */\nexport const GEN_COMMENT =\n \"/* Do not edit this file. */\\n/* This file generated by openapi-ts-mock-generator. */\\n\\n\"\n","/**\n * 배열 처리 관련 유틸리티 함수들\n */\n\nimport { faker } from \"../core\"\n\n/**\n * 지정된 범위 내에서 랜덤한 길이의 배열을 생성\n * 배열의 각 요소는 인덱스 값으로 초기화됨\n */\nexport const getRandomLengthArray = (min: number = 1, max: number = 3): number[] => {\n const length = faker.number.int({ min, max })\n return Array.from({ length }, (_, i) => i)\n}\n\n/**\n * 배열을 지정된 크기로 청크 단위로 분할\n */\nexport const chunkArray = <T>(array: T[], size: number): T[][] => {\n const chunks: T[][] = []\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size))\n }\n return chunks\n}\n\n/**\n * 배열에서 중복 제거 (primitive 타입용)\n */\nexport const unique = <T>(array: T[]): T[] => {\n return [...new Set(array)]\n}\n\n/**\n * 배열에서 중복 제거 (객체용, 키 기준)\n */\nexport const uniqueBy = <T>(array: T[], keyFn: (item: T) => any): T[] => {\n const seen = new Set()\n return array.filter((item) => {\n const key = keyFn(item)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n","/**\n * 파일 시스템 관련 유틸리티 함수들\n */\n\nimport { existsSync, mkdirSync, writeFileSync, rmSync, readdirSync, readFileSync } from \"fs\"\nimport * as path from \"path\"\n\n/**\n * 디렉토리가 존재하지 않으면 생성\n */\nexport const ensureDir = (dirPath: string): void => {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true })\n }\n}\n\n/**\n * 디렉토리를 비우고 정리\n */\nexport const clearDirectory = (dirPath: string): void => {\n if (existsSync(dirPath)) {\n readdirSync(dirPath).forEach((file) => {\n rmSync(path.join(dirPath, file))\n })\n }\n}\n\n/**\n * 안전하게 파일 쓰기 (디렉토리 자동 생성)\n */\nexport const safeWriteFile = (filePath: string, content: string): void => {\n const dir = path.dirname(filePath)\n ensureDir(dir)\n writeFileSync(filePath, content)\n}\n\n/**\n * JSON 파일 읽기 (파일이 없으면 기본값 반환)\n */\nexport const readJsonFile = <T>(filePath: string, defaultValue: T): T => {\n if (!existsSync(filePath)) {\n return defaultValue\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\")\n return JSON.parse(content)\n } catch (error) {\n console.warn(`Failed to read JSON file ${filePath}:`, error)\n return defaultValue\n }\n}\n\n/**\n * 파일 경로가 URL인지 로컬 파일인지 확인하여 절대 경로 반환\n */\nexport const resolveFilePath = (inputPath: string, baseDir?: string): string => {\n if (inputPath.startsWith(\"http\")) {\n return inputPath\n }\n\n if (baseDir) {\n return path.join(baseDir, inputPath)\n }\n\n return inputPath\n}\n\n/**\n * 여러 파일명 조합하여 고유한 파일명 생성\n */\nexport const createUniqueFileName = (baseName: string, extension: string): string => {\n const timestamp = Date.now()\n return `${baseName}-${timestamp}.${extension}`\n}\n","/**\n * 검증 관련 유틸리티 함수들\n */\n\n/**\n * 값이 null이나 undefined가 아닌지 확인하는 타입 가드\n * core/types.ts의 isNotNullish와 동일하지만 utils에서 독립적으로 사용\n */\nexport const isNotEmpty = <T>(value: T | null | undefined): value is T => {\n return value !== null && value !== undefined\n}\n\n/**\n * 문자열이 비어있지 않은지 확인\n */\nexport const isNonEmptyString = (value: any): value is string => {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\n/**\n * 숫자가 유효한 범위 내에 있는지 확인\n */\nexport const isInRange = (value: number, min: number, max: number): boolean => {\n return value >= min && value <= max\n}\n\n/**\n * 배열이 비어있지 않은지 확인\n */\nexport const isNonEmptyArray = <T>(value: any): value is T[] => {\n return Array.isArray(value) && value.length > 0\n}\n\n/**\n * 객체가 비어있지 않은지 확인\n */\nexport const isNonEmptyObject = (value: any): value is Record<string, any> => {\n return typeof value === \"object\" && value !== null && Object.keys(value).length > 0\n}\n\n/**\n * HTTP 상태 코드가 유효한지 확인\n */\nexport const isValidStatusCode = (code: number): boolean => {\n return isInRange(code, 100, 599)\n}\n\n/**\n * 파일 확장자가 허용된 목록에 있는지 확인\n */\nexport const hasValidExtension = (filename: string, allowedExtensions: string[]): boolean => {\n const extension = filename.split(\".\").pop()?.toLowerCase()\n return extension ? allowedExtensions.includes(extension) : false\n}\n\n/**\n * URL 형식이 올바른지 간단히 확인\n */\nexport const isValidUrl = (url: string): boolean => {\n try {\n new URL(url)\n return true\n } catch {\n return false\n }\n}\n"],"mappings":"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","names":[]}