{"version":3,"sources":["../src/lib/type.ts","../src/lib/loader.ts","../src/lib/clone.ts","../src/lib/export.ts","../src/index.ts"],"names":["convert","key","promises","resolve"],"mappings":"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","sourcesContent":["export type Extension = 'json' | 'yaml'\n\nexport type Primitive = string | number | boolean | null | undefined\n\nexport function isPrimitive(value: unknown): value is Primitive {\n  return (\n    typeof value === 'string' ||\n    typeof value === 'number' ||\n    typeof value === 'boolean' ||\n    value === null ||\n    value === undefined\n  )\n}\n\nexport function isPureObject(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\ntype Pattern = string\n\n/**\n *\n * @params value\n * @params context\n * @returns Primitive | Promise<Primitive>\n */\nexport type Converter = (\n  value: Primitive,\n  context: ConvertContext\n) => Primitive | Promise<Primitive>\n\n/**\n *\n */\nexport interface Config {\n  /**\n   *\n   * @default process.cwd()\n   */\n  cwd?: string\n\n  /**\n   *\n   */\n  src: string\n\n  /**\n   *\n   */\n  dist: string\n\n  /**\n   *\n   */\n  ignore?: Pattern[]\n\n  /**\n   *\n   * @param value\n   * @param context\n   */\n  convert: Converter\n\n  /**\n   *\n   * @default ['json']\n   */\n  extensions?: Extension[]\n\n  /**\n   *\n   * @default true\n   */\n  cache?: boolean\n\n  /**\n   * @default false\n   */\n  parallel?: number | false\n}\n\nexport const defaultConfig = {\n  cwd: process.cwd(),\n  extensions: ['json'],\n  cache: true,\n  parallel: false\n} satisfies Omit<Config, 'src' | 'dist' | 'convert'>\n\nexport type FixedConfig = Config & typeof defaultConfig\n\nexport interface ConvertContext {\n  /**\n   *\n   */\n  key: string\n\n  /**\n   *\n   */\n  value: Primitive\n\n  /**\n   *\n   */\n  file: FileContext\n}\n\nexport interface FileContext {\n  /**\n   *\n   */\n  filePath: string\n\n  /**\n   *\n   */\n  fileName: string\n\n  /**\n   *\n   */\n  extension: Extension\n\n  /**\n   *\n   */\n  outputFile: string\n\n  /**\n   *\n   */\n  json: unknown\n}\n\nexport interface MimicTreeContxt {\n  /**\n   *\n   */\n  files: FileContext[]\n\n  /**\n   *\n   */\n  config: FixedConfig\n}\n","import type { MimicTreeContxt, FixedConfig, Extension } from './type'\nimport { resolve } from 'path'\nimport { promises } from 'fs'\nimport globby from 'globby'\nimport { FileContext } from './type'\n\nconst { readFile } = promises\n\nexport async function loadContext(config: FixedConfig): Promise<MimicTreeContxt> {\n  const baseDir = resolve(config.cwd ?? process.cwd(), config.src)\n\n  const [founds, ignores] = await Promise.all([\n    globFiles(baseDir, config),\n    ignoreFiles(baseDir, config)\n  ])\n\n  const files = founds.filter((file) => !ignores.includes(file))\n\n  return {\n    files: await loadAllFiles(baseDir, files, config),\n    config\n  }\n}\n\nconst extensionAliases = {\n  yaml: ['yml', 'yaml'],\n  json: ['json']\n} satisfies Record<Extension, string[]>\nObject.freeze(extensionAliases)\n\nconst extensions = Object.keys(extensionAliases) as Extension[]\nObject.freeze(extensions)\n\nfunction globFiles(baseDir: string, config: FixedConfig): Promise<string[]> {\n  return globby(baseDir, {\n    expandDirectories: {\n      extensions: (config.extensions ?? ['json']).flatMap((ext) => extensionAliases[ext])\n    },\n    gitignore: false,\n    cwd: config.cwd\n  })\n}\n\nasync function ignoreFiles(baseDir: string, config: FixedConfig): Promise<string[]> {\n  if ((config.ignore ?? []).length <= 0) {\n    return []\n  }\n\n  return globby(config.ignore!, {\n    gitignore: true,\n    cwd: config.cwd\n  })\n}\n\nasync function loadAllFiles(\n  baseDir: string,\n  files: string[],\n  config: FixedConfig\n): Promise<FileContext[]> {\n  const loader = new JsonLoader(baseDir, config)\n  await loader.init()\n\n  const load = async (filePath: string) => loader.load(filePath)\n\n  const results = await Promise.all(files.map(load))\n\n  if (results.some((result) => result.error)) {\n    throw new Error()\n  }\n\n  const outputBaseDir = resolve(config.cwd ?? process.cwd(), config.dist)\n  console.log(outputBaseDir)\n\n  return results.map((result) => ({\n    ...(result as Omit<FileContext, 'outputFile'>),\n    outputFile: resolve(outputBaseDir, result.filePath, result.fileName).replace(outputBaseDir, '.')\n  }))\n}\n\ntype LoadJsonResult = Omit<FileContext, 'outputFile' | 'json'> & { json?: unknown; error?: string }\n\ntype Parser = (raw: string) => unknown\n\nclass JsonLoader {\n  constructor(\n    private readonly baseDir: string,\n    private readonly config: FixedConfig\n  ) {}\n\n  #parsers: Partial<Record<Extension, Parser>> = {\n    json: (raw) => JSON.parse(raw)\n  }\n\n  async init() {\n    if (this.config.extensions?.includes('yaml')) {\n      this.#parsers['yaml'] = await this.#createYamlParser()\n    }\n  }\n\n  async #createYamlParser(): Promise<Parser> {\n    const { parse } = await import('yaml')\n    return (raw) => parse(raw, { prettyErrors: true })\n  }\n\n  #assertSupportedExtension(ext: string): asserts ext is Extension {\n    if (!(this.config.extensions ?? ['json']).includes(ext as Extension)) {\n      throw new Error(`Unsupported file extension: ${ext}`)\n    }\n  }\n\n  #getPath(fullpath: string): string {\n    return (\n      './' +\n      fullpath\n        .replace(/^\\.\\//, '')\n        .replace(new RegExp(`^${this.baseDir.replace(/^\\.\\//, '')}/`), '')\n        .replace(getFileName(fullpath), '')\n    )\n  }\n\n  #parse(raw: string, ext: Extension): unknown {\n    const parser = this.#parsers[ext]\n    if (!parser) {\n      throw new Error(`Unsupported file extension: ${ext}`)\n    }\n    return parser(raw)\n  }\n\n  #errorToString(e: unknown): string {\n    if (e instanceof Error) {\n      return `${e.name}: ${e.message}`\n    }\n    return String(e)\n  }\n\n  async load(filePath: string): Promise<LoadJsonResult> {\n    const importPath = resolve(this.baseDir, filePath)\n    const fileName = getFileName(filePath)\n    const extension = getExtension(filePath)\n    this.#assertSupportedExtension(extension)\n    const fixedFilePath = this.#getPath(filePath)\n\n    const raw = await readFile(importPath, 'utf-8')\n\n    try {\n      return {\n        filePath: fixedFilePath,\n        fileName,\n        extension: extension,\n        json: this.#parse(raw, extension)\n      }\n    } catch (e) {\n      return {\n        filePath: fixedFilePath,\n        fileName,\n        extension,\n        error: this.#errorToString(e)\n      }\n    }\n  }\n}\n\nfunction getExtension(filePath: string): Extension {\n  const ext = filePath.split('.').pop() ?? ''\n  const found = Object.entries(extensionAliases).find(([, aliases]) =>\n    (aliases as readonly string[]).includes(ext)\n  )\n  return (found?.[0] as Extension) ?? ext\n}\n\nfunction getFileName(filePath: string): string {\n  return filePath.split('/').pop() ?? ''\n}\n","import {\n  FixedConfig,\n  ConvertContext,\n  FileContext,\n  isPrimitive,\n  isPureObject,\n  Primitive\n} from './type'\nimport { PromisePool } from '@supercharge/promise-pool'\n\nconst ROOT_KEY = '[ROOT]'\n\nexport async function convert(fileContext: FileContext, config: FixedConfig): Promise<FileContext> {\n  const convertTargets = convertFlattenKV('', fileContext.json)\n\n  const { results, errors } = await createWorker(config)\n    .for(convertTargets)\n    .process(async ({ key, value }) => {\n      const { convert } = config\n      const context: ConvertContext = { key, value, file: fileContext }\n      const result = await convert(value, context)\n\n      return { key, value: result }\n    })\n\n  if (errors.length > 0) {\n    throw errors[0]\n  }\n\n  return {\n    ...fileContext,\n    json: toObject(results)\n  }\n}\n\n/**\n *\n * @param keyPrefix\n * @param value\n */\nfunction convertFlattenKV(\n  keyPrefix: string,\n  value: unknown\n): Array<{ key: string; value: Primitive }> {\n  if (isPrimitive(value)) {\n    // root の場合 keyPrefix は空文字列\n    return [{ key: keyPrefix || ROOT_KEY, value }]\n  }\n\n  if (Array.isArray(value)) {\n    return value.flatMap((v, i) => convertFlattenKV(`${keyPrefix}[${i}]`, v))\n  }\n\n  if (isPureObject(value)) {\n    const requiredDot = keyPrefix !== '' && !keyPrefix.endsWith(']')\n\n    return Object.entries(value).flatMap(([k, v]) =>\n      convertFlattenKV(`${keyPrefix}${requiredDot ? '.' : ''}${k}`, v)\n    )\n  }\n\n  return []\n}\n\n/**\n *\n * @param flattenKVs\n */\nfunction toObject(flattenKVs: Array<{ key: string; value: Primitive }>): unknown {\n  if (flattenKVs.length <= 1) {\n    return undefined\n  }\n\n  if (flattenKVs.length === 1 && flattenKVs[0]!.key === ROOT_KEY) {\n    return flattenKVs[0]!.value\n  }\n\n  if (flattenKVs[0]!.key.startsWith('[')) {\n    // 先に sort しているので、index 順になっている\n    const indexes = flattenKVs\n      .map(({ key }) => key.match(/^\\[(\\d+)\\]/)![1]!)\n      .map(Number)\n      .filter((v, i, self) => self.indexOf(v) === i)\n\n    const pickByIndex = (index: number) =>\n      flattenKVs.filter(({ key }) => key.startsWith(`[${index}]`))\n\n    return indexes.reduce((acc, index) => {\n      const picked = pickByIndex(index).map(({ key, value }) => ({\n        key: key.replace(/^\\[\\d+\\]/, ''),\n        value\n      }))\n      return [...acc, toObject(picked)]\n    }, [] as unknown[])\n  }\n\n  const keys = flattenKVs\n    .map(({ key }) => (key.includes('.') ? key.split('.')[0]! : key))\n    .filter((v, i, self) => self.indexOf(v) === i)\n\n  return keys.reduce((acc, key) => {\n    const exactMatch = flattenKVs.find(({ key: k }) => k === key)\n    if (exactMatch) {\n      return { ...acc, [key]: exactMatch.value }\n    }\n\n    const picked = flattenKVs\n      .filter(({ key: k }) => k.startsWith(`${key}.`))\n      .map(({ key, value }) => ({ key: key.replace(/^.+\\./, ''), value }))\n    return { ...acc, [key]: toObject(picked) }\n  }, {})\n}\n\n/**\n *\n * @param param0\n */\nfunction createWorker({ parallel }: FixedConfig): typeof PromisePool {\n  let pool = PromisePool\n\n  if (typeof parallel === 'number') {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    pool = pool.withConcurrency(parallel) as any\n  }\n\n  return pool\n}\n","import { promises } from 'fs'\nimport { resolve } from 'path'\nimport { Extension, FileContext, FixedConfig } from './type'\n\nconst { writeFile, mkdir } = promises\n\nexport async function exportFile(fileContext: FileContext, config: FixedConfig): Promise<void> {\n  const outputData = await stringifyStrategy[fileContext.extension](fileContext)\n\n  await write(fileContext, outputData, config)\n}\n\ntype Stringify = (fileContext: FileContext) => string | Promise<string>\n\nasync function write(fileContext: FileContext, data: string, config: FixedConfig): Promise<void> {\n  const outputBaseDir = resolve(config.cwd ?? process.cwd(), config.dist)\n  const filePath = fileContext.outputFile.split('/').slice(0, -1).join('/')\n\n  await mkdir(resolve(outputBaseDir, filePath), { recursive: true })\n\n  await writeFile(resolve(outputBaseDir, fileContext.outputFile), data)\n}\nconst stringifyStrategy = {\n  json: (fileContext) => JSON.stringify(fileContext.json, null, 2),\n  yaml: async (fileContext) => {\n    const yaml = await import('yaml')\n    return yaml.stringify(fileContext.json)\n  }\n} as Record<Extension, Stringify>\n","import { defaultConfig, type Config, FixedConfig } from './lib/type'\nimport { loadContext } from './lib/loader'\nimport { convert } from './lib/clone'\nimport { exportFile } from './lib/export'\n\nexport type { Config as Option }\n\nexport async function mimicTree(config: Config): Promise<void> {\n  const fixedConfig = {\n    ...defaultConfig,\n    ...config\n  } as FixedConfig\n\n  const context = await loadContext(fixedConfig)\n\n  for (const f of context.files) {\n    const result = await convert(f, context.config)\n    await exportFile(result, context.config)\n  }\n}\n"]}