var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
  for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
  return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
  var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
  var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
  var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
  var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
    return __privateGet(this, extra);
  }, set [name](x) {
    return __privateSet(this, extra, x);
  } }, name));
  k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
  for (var i = decorators.length - 1; i >= 0; i--) {
    ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
    if (k) {
      ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
      if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
      if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
    }
    it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
    if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
    else if (typeof it !== "object" || it === null) __typeError("Object expected");
    else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
  }
  return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);

// src/core/run/index.ts
import { dirname, join, relative } from "node:path";
import pmap from "p-map";
import { ok } from "node:assert";
import { constants as fsConstants } from "node:fs/promises";
import { glob } from "glob";
import { bounded, isSubPath, normalizePath, wait } from "@diplodoc/cli/lib/utils";
import { LogLevel, Logger } from "@diplodoc/cli/lib/logger";

// src/core/run/fs.ts
import {
  copyFile,
  link,
  mkdir,
  readFile,
  readdir,
  realpath,
  rename,
  rm,
  rmdir,
  stat,
  unlink,
  writeFile
} from "node:fs/promises";
import { realpathSync, statSync } from "node:fs";
var fs = {
  stat,
  statSync,
  realpathSync,
  realpath,
  rm,
  rmdir,
  link,
  unlink,
  copyFile,
  mkdir,
  readdir,
  readFile,
  writeFile,
  rename
};

// src/core/run/errors.ts
var InsecureAccessError = class extends Error {
  constructor(file, realpath2, scopes) {
    const message = [
      `Requested file '${file}' is out of project scope.`,
      realpath2 && "File resolved to:\n	" + realpath2,
      scopes && "Allowed scopes:\n	" + scopes.join("\n	")
    ].filter(Boolean).join("\n");
    super(message);
    this.path = file;
    this.realpath = realpath2;
  }
};

// src/core/run/index.ts
var RunLogger = class extends Logger {
  constructor() {
    super(...arguments);
    this.proc = this.topic(LogLevel.INFO, "PROC");
    this.copy = this.topic(LogLevel.INFO, "COPY");
  }
};
var _realpathSync_dec, _realpath_dec, _remove_dec, _copy_dec, _glob_dec, _write_dec, _read_dec, _exists_dec, _init;
_exists_dec = [bounded], _read_dec = [bounded], _write_dec = [bounded], _glob_dec = [bounded], _copy_dec = [bounded], _remove_dec = [bounded], _realpath_dec = [bounded], _realpathSync_dec = [bounded];
var Run = class {
  constructor(config) {
    __runInitializers(_init, 5, this);
    this.logger = void 0;
    this.config = void 0;
    this.fs = fs;
    this.normalize = normalizePath;
    this.input = void 0;
    this.originalInput = void 0;
    this.scopes = /* @__PURE__ */ new Map();
    this.config = config;
    this.input = config.input;
    this.originalInput = config.input;
    this.logger = new RunLogger(config, [
      (_level, message) => {
        for (const [alias, scope] of this.scopes.entries()) {
          const clean = message.replace(new RegExp(scope, "ig"), alias);
          if (clean === alias) {
            return message;
          }
          message = clean;
        }
        return message;
      }
    ]);
  }
  exists(path) {
    try {
      this.fs.statSync(path);
      return true;
    } catch {
      return false;
    }
  }
  async read(path) {
    await this.assertProjectScope(path);
    return this.fs.readFile(path, "utf8");
  }
  async write(path, content, force = false) {
    await this.assertProjectScope(path);
    await wait(1);
    if (!force && this.exists(path)) {
      return;
    }
    await this.fs.mkdir(dirname(path), { recursive: true });
    const tempPath = `${path}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
    try {
      await this.fs.writeFile(tempPath, content, "utf8");
      try {
        await this.fs.rename(tempPath, path);
      } catch (renameError) {
        const error = renameError;
        if (error?.code === "ENOENT" || error?.code === "EEXIST") {
          await this.fs.unlink(path).catch(() => {
          });
          await this.fs.rename(tempPath, path);
        } else {
          throw renameError;
        }
      }
    } catch (error) {
      await this.fs.unlink(tempPath).catch(() => {
      });
      throw error;
    }
  }
  async glob(pattern, options) {
    const paths = await glob(pattern, {
      dot: true,
      nodir: true,
      follow: true,
      ...options
    });
    return paths.map(normalizePath);
  }
  async copy(from, to, ignore = []) {
    const isFile = (await this.fs.stat(from)).isFile();
    if (from === to) {
      return [];
    }
    if (!isFile && isSubPath(from, to)) {
      ignore = [...ignore, `${relative(from, to)}/**`];
    }
    const files = isFile ? [[from, to]] : (await this.glob("**", { cwd: from, ignore })).map((file) => [
      join(from, file),
      join(to, file)
    ]);
    const mkdirPromises = /* @__PURE__ */ new Map();
    const ensureDir = (dir) => {
      let promise = mkdirPromises.get(dir);
      if (!promise) {
        promise = this.fs.mkdir(dir, { recursive: true }).then(() => {
        });
        mkdirPromises.set(dir, promise);
      }
      return promise;
    };
    const mode = this.config.copyOnWrite ? fsConstants.COPYFILE_FICLONE : 0;
    await pmap(
      files,
      async ([src, dest]) => {
        const dir = dirname(dest);
        await ensureDir(dir);
        await this.fs.copyFile(src, dest, mode);
      },
      { concurrency: 30 }
    );
    return files;
  }
  async remove(path) {
    try {
      await this.fs.rm(path, { recursive: true, force: true });
    } catch {
    }
  }
  async realpath(path) {
    try {
      return await this.fs.realpath(path);
    } catch {
      return path;
    }
  }
  realpathSync(path) {
    try {
      return this.fs.realpathSync(path);
    } catch {
      return path;
    }
  }
  async assertProjectScope(path) {
    const scopes = [...this.scopes.values()].map(normalizePath);
    const realpath2 = normalizePath(await this.realpath(path));
    const isInScope = scopes.some((scope) => realpath2.startsWith(scope));
    ok(isInScope, new InsecureAccessError(path, realpath2, scopes));
  }
};
_init = __decoratorStart(null);
__decorateElement(_init, 1, "exists", _exists_dec, Run);
__decorateElement(_init, 1, "read", _read_dec, Run);
__decorateElement(_init, 1, "write", _write_dec, Run);
__decorateElement(_init, 1, "glob", _glob_dec, Run);
__decorateElement(_init, 1, "copy", _copy_dec, Run);
__decorateElement(_init, 1, "remove", _remove_dec, Run);
__decorateElement(_init, 1, "realpath", _realpath_dec, Run);
__decorateElement(_init, 1, "realpathSync", _realpathSync_dec, Run);
__decoratorMetadata(_init, Run);
export {
  Run,
  RunLogger
};
//# sourceMappingURL=index.mjs.map
