{"version":3,"file":"index.mjs","names":[],"sources":["../../src/node/exec.ts","../../src/node/fs.ts","../../src/node/context.ts"],"sourcesContent":["import { type ChildProcess, type CommonSpawnOptions, spawn } from 'node:child_process'\nimport os from 'node:os'\nimport pc from 'picocolors'\nimport { createPromise } from '../core'\n\nexport interface ExecOptions extends Omit<CommonSpawnOptions, 'env' | 'stdio'> {\n  /**\n   * default is false\n   */\n  collectOutput?: boolean\n  /**\n   * if collectOutput is true, then this is true, otherwise, this is false\n   */\n  silent?: boolean\n  /**\n   * default is `process.env`\n   */\n  env?: NodeJS.ProcessEnv\n}\n\n/**\n *\n * @example\n *\n * ```ts\n * await run('echo \"hello world\" && echo cool things') // will print `hello world\\ncool\\nthings\\n`\n * ```\n */\nexport async function exec(cmd: string, opt: ExecOptions = {}) {\n  const { env = process.env, collectOutput = false, silent = collectOutput, ...other } = opt\n\n  if (!silent) {\n    console.log(pc.dim('$'), pc.dim(cmd))\n  }\n\n  const commands = cmd\n    .split('&&')\n    .map((n) => n.trim())\n    .filter(Boolean)\n\n  let output = ''\n\n  for (const cmd of commands) {\n    const [_cmd, ...args] = _parseArgs(cmd)\n    if (!_cmd) {\n      throw new Error(`Parse args failed: ${cmd}`)\n    }\n\n    const p = await _exec(_cmd, args, {\n      ...other,\n      stdio: collectOutput ? 'pipe' : 'inherit',\n      env: env,\n    })\n\n    if (collectOutput) {\n      output += p.stdio.stdout\n    }\n  }\n\n  return output\n}\n\nexport function _parseArgs(cmd: string) {\n  const args: string[] = []\n\n  const _cmd = cmd.replace(/(['\"]).+?\\1/g, (n) => {\n    const idx = args.length\n    args.push(n.slice(1, -1))\n    return `__$${idx}`\n  })\n\n  const normalized = _cmd.split(/\\s+/).map((_part) => {\n    const part = _part.trim()\n\n    if (part.startsWith('__$')) {\n      return args[+part.slice(3)]!\n    }\n    return part\n  })\n\n  return normalized\n}\n\nexport interface ExecResult {\n  process: ChildProcess\n  stdio: {\n    stdout: string\n    stderr: string\n  }\n}\n\nexport async function _exec(cmd: string, args: readonly string[], opt?: CommonSpawnOptions) {\n  const p = createPromise<ExecResult>()\n\n  const win = os.platform() === 'win32'\n\n  const childProcess = win\n    ? spawn('cmd', ['/c', cmd, ...args], { ...opt })\n    : spawn(cmd, args, { ...opt })\n\n  const stdio = {\n    stdout: '',\n    stderr: '',\n  }\n\n  childProcess.stdout?.on('data', (chunk) => {\n    if (chunk instanceof Buffer) {\n      stdio.stdout += chunk.toString()\n    } else {\n      stdio.stdout += String(chunk)\n    }\n  })\n\n  childProcess.stderr?.on('data', (chunk) => {\n    if (chunk instanceof Buffer) {\n      stdio.stderr += chunk.toString()\n    } else {\n      stdio.stderr += String(chunk)\n    }\n  })\n\n  childProcess.on('close', (code) => {\n    const result = {\n      process: childProcess,\n      stdio,\n    }\n\n    if (code !== 0) {\n      p.reject(result)\n    } else {\n      p.resolve(result)\n    }\n  })\n\n  return p.promise\n}\n","import type { PathLike } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { type ParesJsonOption, parseJson } from '../json'\n\nexport function readText(path: PathLike) {\n  return readFile(path, { encoding: 'utf8' })\n}\n\nexport interface ReadJsonOption<T> extends ParesJsonOption<T> {}\n\n/**\n * @returns Undefined if parse failed\n */\nexport async function readJson<T>(path: PathLike, opt?: ReadJsonOption<T>) {\n  const text = await readText(path)\n\n  return parseJson(text, opt)\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Awaitable, Factory } from '../types'\nimport { toValue } from '../utils'\n\ntype ASLStore = Map<ContextImplementSymbol, any>\n\nlet als: AsyncLocalStorage<ASLStore> | undefined\n\nexport type ContextImplementSymbol = symbol\n\nexport type ContextImplement<Value = unknown> = [ContextImplementSymbol, Value]\n\nexport interface ContextInstance<T> {\n  name: string\n\n  /**\n   * Get current context\n   */\n  get(): T\n\n  /**\n   * Implement the context\n   * @param service\n   */\n  impl(service: T): ContextImplement<T>\n}\n\nexport type ContextRunFn = <T>(fn: () => T, serviceImplements?: ContextImplement[]) => T\n\nexport interface BindContext {\n  /**\n   * Run with context implements\n   */\n  run: ContextRunFn\n\n  /**\n    Bind the context implementations in advance\n\n    ```ts\n    const bind = Context.bind(() => [CounterService.impl({ count: 1 })])\n\n    bind.run(() => {\n      const c = CounterService.get() // c.count === 1\n    })\n    ```\n   */\n  bind: (serviceImplements?: Factory<ContextImplement[]>) => BindContext\n}\n\nexport namespace Context {\n  /**\n    Create a context instance, then you can use the instance to get the context in async scope\n\n    @param name Context name\n    @param defaultImpl The default implement will applied if the `run` function not provide the implement\n    @returns\n   */\n  export function create<Service>(name: string, defaultImpl?: Factory<Service>) {\n    const ContextImpl: ContextInstance<Service> = {\n      name,\n      get() {\n        const v = getAls().getStore()\n\n        if (!v) {\n          throw new Error('Please Use `Context.run` to run the main function')\n        }\n\n        const key = toContextSymbol(ContextImpl)\n\n        if (v.has(key)) {\n          return v.get(key)\n        }\n\n        if (defaultImpl) {\n          const value = toValue(defaultImpl)\n\n          v.set(key, value)\n          return value\n        }\n\n        throw new Error(`Implement not found for: ${name}`)\n      },\n      impl(service) {\n        return [toContextSymbol(ContextImpl), service]\n      },\n    }\n\n    return ContextImpl\n  }\n\n  /**\n    Execute a function by provide context implements, support async scope.\n\n    @example\n\n    ```ts\n    interface CounterService {\n      count: number\n    }\n\n    const CounterService = Context.create<CounterService>('counter')\n\n    const main = () => {\n      const c = CounterService.get()\n      console.log(c.count) // => 1\n\n      setTimeout(() => {\n        const c1 = CounterService.get()\n\n        console.log(c1.count) // => 1\n      }, 100)\n    }\n\n    Context.run(main, [\n      CounterService.impl({\n        count: 1,\n      }),\n    ])\n\n    ```\n\n    @param fn\n    @param serviceImplements\n    @returns\n   */\n  export function run<T>(fn: () => T, serviceImplements?: ContextImplement[]) {\n    const als = getAls()\n\n    const ctx: ASLStore = new Map()\n\n    for (const [key, value] of serviceImplements || []) {\n      ctx.set(key, value)\n    }\n\n    return als.run(ctx, fn)\n  }\n\n  /**\n    Exit the current context\n\n    @example\n\n    ```ts\n    Context.run(() => {\n      const c = CounterService.get() // Works\n\n      Context.exit(() => {\n        const c = CounterService.get() // This will throw error, because current scope is not in the context scope\n      })\n\n      const c1 = CounterService.get() // Works\n    })\n    ```\n   */\n  export function exit(fn: () => Awaitable<void>) {\n    return getAls().exit(() => fn())\n  }\n\n  /**\n    Bind the context implementations in advance\n\n    ```ts\n    const bind = Context.bind(() => [CounterService.impl({ count: 1 })])\n\n    bind.run(() => {\n      const c = CounterService.get() // c.count === 1\n    })\n    ```\n   */\n  export function bind(serviceImplements?: Factory<ContextImplement[]>): BindContext {\n    return new BindContextImpl(serviceImplements && [serviceImplements])\n  }\n}\n\nclass BindContextImpl implements BindContext {\n  implFactories: Factory<ContextImplement[]>[] = []\n\n  constructor(implFactories?: Factory<ContextImplement[]>[]) {\n    this.implFactories.push(...(implFactories || []))\n  }\n\n  /**\n      Execute the function by context implementations\n     */\n  run<T>(fn: () => T, contextImplements?: ContextImplement[]) {\n    const allImplements = contextImplements\n      ? [...this.implFactories, contextImplements]\n      : this.implFactories\n\n    const normalizedImplements = allImplements.flatMap((f) => toValue(f))\n\n    return Context.run(fn, normalizedImplements)\n  }\n\n  /**\n      Bind the context implementations in advance\n\n      ```ts\n      const bind = Context.bind(() => [CounterService.impl({ count: 1 })])\n\n      bind.run(() => {\n        const c = CounterService.get() // c.count === 1\n      })\n      ```\n     */\n  bind: (serviceImplements?: Factory<ContextImplement[]>) => BindContext = (implFactories) => {\n    const allImplements = implFactories\n      ? [...this.implFactories, implFactories]\n      : this.implFactories\n\n    return new BindContextImpl(allImplements)\n  }\n}\n\nfunction toContextSymbol(v: unknown): ContextImplementSymbol {\n  return v as ContextImplementSymbol\n}\n\nfunction getAls() {\n  return (als ??= new AsyncLocalStorage())\n}\n"],"mappings":"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"}