import { createRequire as _createRequire } from 'node:module';
const require = _createRequire(import.meta.url);
import {
  loadProjectGridAppContent
} from "./chunk-4YAR43FD.js";
import {
  createLogger
} from "./chunk-YKAYM32Q.js";
import {
  httpRequest
} from "./chunk-HTRGINHM.js";
import {
  createI18nT
} from "./chunk-PPRKUU25.js";
import "./chunk-HEANTKSX.js";
import {
  createVeloCLIServer,
  debounceQueue,
  require_chokidar
} from "./chunk-UILWMVUO.js";
import {
  require_normalize_path
} from "./chunk-ICJSZGEK.js";
import {
  getPagesFolder,
  getSourceFolder,
  getTypesDir
} from "./chunk-DZ3U3XXP.js";
import {
  saveProjectModel
} from "./chunk-75INKCQL.js";
import "./chunk-4BLGYECY.js";
import {
  syncTypesWithAuth
} from "./chunk-FE66UX45.js";
import {
  authenticate
} from "./chunk-II4C4GML.js";
import "./chunk-JNRWJBN3.js";
import {
  TunnelClient,
  launchTunnel
} from "./chunk-SVSXYROI.js";
import "./chunk-SR7TTQEG.js";
import {
  updateFiles
} from "./chunk-DLEBD2WZ.js";
import {
  AppType,
  GridAppLayout as GridAppLayout2,
  createApp,
  pagesDiff
} from "./chunk-RTNIG6ZW.js";
import {
  GridAppLayout
} from "./chunk-QRGKMYDD.js";
import "./chunk-3QMRQKKR.js";
import "./chunk-NMCF7XG5.js";
import "./chunk-MHV22UIU.js";
import "./chunk-K6JLY75P.js";
import "./chunk-WFQIXGJV.js";
import "./chunk-ECBO3UFC.js";
import "./chunk-YNEGRO3E.js";
import "./chunk-VC5Q2AI5.js";
import {
  ErrorViewer,
  createHttpClient,
  isHttpError,
  openBrowser,
  pLimit,
  writeCrashReport
} from "./chunk-HWT3LUJJ.js";
import {
  extractHttpError,
  wixCliCliMessageDisplayed,
  wixCliCodeHasBeenChanged,
  wixCliFileFolderCreatedRenamedDeleted,
  wixCliReadyForReloadAfterCodeChange,
  wixCliUserResponseToCliMessage
} from "./chunk-TOBTRYZF.js";
import "./chunk-7WVNO7VU.js";
import "./chunk-RPTAJN5Y.js";
import {
  renderSync
} from "./chunk-YL4347CI.js";
import {
  require_react
} from "./chunk-TODKQSCF.js";
import "./chunk-AFPDHQYI.js";
import "./chunk-HYKBBZLS.js";
import "./chunk-C5RTKQVL.js";
import "./chunk-SVUXJRFD.js";
import {
  getDebugLogFilePath
} from "./chunk-YT5BPQDJ.js";
import "./chunk-LU3R3EBR.js";
import {
  getTestOverrides
} from "./chunk-XZUGLEBK.js";
import {
  outputFile,
  pathExists
} from "./chunk-VASURI4S.js";
import "./chunk-SDLCFZRL.js";
import {
  CliError,
  CliErrorCode
} from "./chunk-MTT3QXBC.js";
import {
  __toESM,
  init_esm_shims
} from "./chunk-EXLZF52D.js";

// ../cli-site-old/src/dev/index.ts
init_esm_shims();

// ../cli-site-old/src/dev/dev.ts
init_esm_shims();

// ../../node_modules/exit-hook/index.js
init_esm_shims();
import process from "node:process";
var asyncCallbacks = /* @__PURE__ */ new Set();
var callbacks = /* @__PURE__ */ new Set();
var isCalled = false;
var isRegistered = false;
async function exit(shouldManuallyExit, isSynchronous, signal) {
  if (isCalled) {
    return;
  }
  isCalled = true;
  if (asyncCallbacks.size > 0 && isSynchronous) {
    console.error([
      "SYNCHRONOUS TERMINATION NOTICE:",
      "When explicitly exiting the process via process.exit or via a parent process,",
      "asynchronous tasks in your exitHooks will not run. Either remove these tasks,",
      "use gracefulExit() instead of process.exit(), or ensure your parent process",
      "sends a SIGINT to the process running this code."
    ].join(" "));
  }
  const exitCode = 128 + signal;
  const done = (force = false) => {
    if (force === true || shouldManuallyExit === true) {
      process.exit(exitCode);
    }
  };
  for (const callback of callbacks) {
    callback(exitCode);
  }
  if (isSynchronous) {
    done();
    return;
  }
  const promises = [];
  let forceAfter = 0;
  for (const [callback, wait] of asyncCallbacks) {
    forceAfter = Math.max(forceAfter, wait);
    promises.push(Promise.resolve(callback(exitCode)));
  }
  const asyncTimer = setTimeout(() => {
    done(true);
  }, forceAfter);
  await Promise.all(promises);
  clearTimeout(asyncTimer);
  done();
}
function addHook(options) {
  const { onExit, wait, isSynchronous } = options;
  const asyncCallbackConfig = [onExit, wait];
  if (isSynchronous) {
    callbacks.add(onExit);
  } else {
    asyncCallbacks.add(asyncCallbackConfig);
  }
  if (!isRegistered) {
    isRegistered = true;
    process.once("beforeExit", exit.bind(void 0, true, false, -128));
    process.once("SIGINT", exit.bind(void 0, true, false, 2));
    process.once("SIGTERM", exit.bind(void 0, true, false, 15));
    process.once("exit", exit.bind(void 0, false, true, 0));
    process.on("message", (message) => {
      if (message === "shutdown") {
        exit(true, true, -128);
      }
    });
  }
  return () => {
    if (isSynchronous) {
      callbacks.delete(onExit);
    } else {
      asyncCallbacks.delete(asyncCallbackConfig);
    }
  };
}
function asyncExitHook(onExit, options = {}) {
  if (typeof onExit !== "function") {
    throw new TypeError("onExit must be a function");
  }
  if (!(typeof options.wait === "number" && options.wait > 0)) {
    throw new TypeError("wait must be set to a positive numeric value");
  }
  return addHook({
    onExit,
    wait: options.wait,
    isSynchronous: false
  });
}

// ../cli-site-old/src/dev/dev.ts
var import_react = __toESM(require_react(), 1);

// ../cli-site-old/src/environment.ts
init_esm_shims();
var DEV_EDITOR_BASE_URL = "https://wix.com/editor/";
function getDevEditorBaseUrl() {
  return getTestOverrides().devEditorBaseUrl ?? DEV_EDITOR_BASE_URL;
}

// ../cli-site-old/src/gridapp/createGridApp.ts
init_esm_shims();

// ../cli-site-old/src/gridapp/error-handlers/maxFileSizeErrorHandler.ts
init_esm_shims();
function catchFilesMaxSizeError(err, files = []) {
  if (!files.length) {
    return;
  }
  const httpError = extractHttpError(err);
  if (!httpError) {
    return;
  }
  const filesMaxSizeRawViolations = httpError.response?.data?.details?.validationError?.fieldViolations?.filter(
    (v) => v.violatedRule === "MAX_LENGTH"
  );
  if (!filesMaxSizeRawViolations?.length) {
    return;
  }
  const maxSizeViolationsData = tryExtractMaxSizeViolationMetadata(
    filesMaxSizeRawViolations
  );
  throw new CliError({
    code: CliErrorCode.GridAppFilesMaxLengthExceeded({
      maxSizeViolationsData,
      filePaths: files.map((f) => f.path ?? "[unknown file path]")
    }),
    cause: httpError
  });
}
function tryExtractMaxSizeViolationMetadata(filesMaxSizeViolations) {
  const fileIndexRegex = /\[(?<fileIndex>\d+)\].content/;
  const expectedAndReceivedSizeRegex = /has size (?<receivedSize>\d+), expected (?<expectedSize>\d+) or less/;
  const violationsData = {
    expectedSize: void 0,
    files: []
  };
  for (const filesMaxSizeViolation of filesMaxSizeViolations) {
    const fileIndexMatchResult = fileIndexRegex.exec(
      filesMaxSizeViolation.field
    );
    const expectedAndReceivedSizeMatchResult = expectedAndReceivedSizeRegex.exec(filesMaxSizeViolation.description);
    if (!(fileIndexMatchResult?.groups?.fileIndex && expectedAndReceivedSizeMatchResult?.groups?.receivedSize && expectedAndReceivedSizeMatchResult.groups.expectedSize)) {
      return null;
    }
    violationsData.expectedSize ??= Math.trunc(
      parseInt(expectedAndReceivedSizeMatchResult.groups.expectedSize, 10) / 1e3
    );
    violationsData.files.push({
      receivedSize: Math.trunc(
        parseInt(expectedAndReceivedSizeMatchResult.groups.receivedSize, 10) / 1e3
      ),
      fileIndex: parseInt(fileIndexMatchResult.groups.fileIndex, 10)
    });
  }
  return violationsData;
}

// ../cli-site-old/src/gridapp/createGridApp.ts
async function createAppWithParams(params, opts) {
  let app;
  try {
    const response = await httpRequest(
      { type: "code", authState: opts.authState },
      createApp(params)
    );
    app = response.data.app;
  } catch (err) {
    catchFilesMaxSizeError(err, params.content?.files);
    throw err;
  }
  if (!app?.id) {
    throw new CliError({
      code: CliErrorCode.InvalidCreateAppResponse(),
      info: { app },
      cause: null
    });
  }
  return app.id;
}
async function createMutableGridApp(projectFolder, opts) {
  const content = await loadProjectGridAppContent(projectFolder);
  return createAppWithParams(
    {
      app: {
        mutable: true,
        appType: AppType.VELO_ISOLATED
      },
      content
    },
    opts
  );
}

// ../cli-site-old/src/gridapp/startGridAppUpdater.ts
init_esm_shims();
import { readFile } from "node:fs/promises";
import { join } from "node:path";
var import_chokidar = __toESM(require_chokidar(), 1);
var import_normalize_path = __toESM(require_normalize_path(), 1);
var WATCH_FS_EVENTS_DEBOUNCE_TIME = 1e3;
var getSectionName = (path) => {
  if (path.startsWith("src/pages")) {
    return "public";
  }
  if (path.startsWith("src/backend")) {
    return "backend";
  }
  return "other";
};
function startGridAppUpdater(model, gridAppId, opts, logger, biEvents) {
  const { projectFolder } = model;
  const limit = pLimit(1);
  const watcher = (0, import_chokidar.watch)(getSourceFolder(projectFolder), {
    disableGlobbing: true,
    cwd: projectFolder,
    ignoreInitial: true
  }).on(
    "all",
    debounceQueue(async (events) => {
      await limit(async () => {
        const logSynced = logger.logSyncingLocalCode();
        const { added, changed, removed } = normalizeChokidarBatchedEvents(events);
        const addedArray = Array.from(added.values()).map((path) => ({
          path,
          type: "create"
        }));
        const changedArray = Array.from(changed.values()).map((path) => ({
          path,
          type: "update"
        }));
        const removedArray = Array.from(removed.values()).map((path) => ({
          path,
          type: "delete"
        }));
        for (const val of [...addedArray, ...changedArray, ...removedArray]) {
          biEvents.file({
            model,
            action: val.type,
            path: val.path,
            oldPath: "",
            sectionName: getSectionName(val.path)
          });
          if (val.type === "update") {
            biEvents.codeChanged(model, val.path);
          }
        }
        try {
          await writeFiles({
            filesToUpdate: await Promise.all(
              addedArray.concat(changedArray).map(async (val) => ({
                path: (0, import_normalize_path.default)(val.path),
                content: await readFile(
                  join(projectFolder, val.path),
                  "utf8"
                )
              }))
            ),
            removedArray,
            gridAppId,
            authState: opts.authState
          });
          const message = logSynced.success();
          biEvents.messageDisplayed({ message, model });
          biEvents.readyForReloadAfterCodeChanged(model);
        } catch (e) {
          logSynced.fail();
          const error = new CliError({
            code: CliErrorCode.GridAppFailedToUpdateFiles(),
            cause: e,
            info: {
              added,
              changed,
              removed
            }
          });
          opts.onError(error);
        }
      });
    }, WATCH_FS_EVENTS_DEBOUNCE_TIME)
  ).on("error", (e) => {
    const error = new CliError({
      code: CliErrorCode.FailedToWatchFiles(),
      cause: e
    });
    opts.onError(error);
  });
  return { close: () => watcher.close() };
}
function normalizeChokidarBatchedEvents(events) {
  return events.reduce(
    (result, [eventType, filePath]) => {
      switch (eventType) {
        case "add": {
          result.added.add(filePath);
          break;
        }
        case "change": {
          result.changed.add(filePath);
          break;
        }
        case "unlink": {
          result.added.delete(filePath);
          result.changed.delete(filePath);
          result.removed.add(filePath);
          break;
        }
        case "unlinkDir": {
          const filePathAsDir = filePath.endsWith("/") ? filePath : `${filePath}/`;
          for (const filePath2 of result.added) {
            if (filePath2.startsWith(filePathAsDir)) {
              result.added.delete(filePath2);
            }
          }
          for (const filePath2 of result.changed) {
            if (filePath2.startsWith(filePathAsDir)) {
              result.changed.delete(filePath2);
            }
          }
          result.removed.add(filePath);
          break;
        }
        case "addDir": {
          break;
        }
      }
      return result;
    },
    {
      added: /* @__PURE__ */ new Set(),
      changed: /* @__PURE__ */ new Set(),
      removed: /* @__PURE__ */ new Set()
    }
  );
}
async function writeFiles({
  filesToUpdate,
  removedArray,
  gridAppId,
  authState
}) {
  try {
    await httpRequest(
      {
        type: "code",
        authState
      },
      updateFiles({
        gridAppId,
        layout: GridAppLayout.GITHUB,
        filesToUpdate,
        ignoreForbiddenPaths: true,
        pathsToDelete: removedArray.map((val) => val.path)
      })
    );
  } catch (err) {
    catchFilesMaxSizeError(err, filesToUpdate);
    throw err;
  }
}

// ../cli-site-old/src/key-watcher.ts
init_esm_shims();
import readline from "node:readline";
import { stdin } from "node:process";
var KeyWatcher = class {
  actions = /* @__PURE__ */ new Map();
  watchExitProcess() {
    return new Promise((resolve) => {
      this.on("c", (key) => {
        if (key.ctrl) {
          resolve();
        }
      });
    });
  }
  on(key, callback) {
    this.actions.set(key, callback);
  }
  watch() {
    const rl = readline.createInterface(stdin);
    readline.emitKeypressEvents(stdin, rl);
    if (stdin.isTTY) {
      stdin.setRawMode(true);
      stdin.setEncoding("utf8");
    }
    stdin.on("keypress", this.handleKeyPress);
    return {
      ctrlCPromise: this.watchExitProcess()
    };
  }
  unwatch() {
    if (stdin.isTTY) {
      stdin.setRawMode(false);
    }
    stdin.off("keypress", this.handleKeyPress);
    stdin.pause();
    this.actions.clear();
  }
  handleKeyPress = (_, key) => {
    this.actions.get(key.name)?.(key);
  };
};

// ../cli-site-old/src/bi.ts
init_esm_shims();
import { randomUUID } from "node:crypto";
var sitesBiEvents = (biLogger) => ({
  file: ({
    model,
    action,
    path,
    sectionName,
    oldPath
  }) => {
    void biLogger.report(
      wixCliFileFolderCreatedRenamedDeleted({
        action,
        path,
        sectionName,
        oldPath,
        siteRevision: Number(model.revision)
      })
    );
  },
  codeChanged: (model, fileName) => {
    void biLogger.report(
      wixCliCodeHasBeenChanged({
        fileName,
        siteRevision: Number(model.revision)
      })
    );
  },
  readyForReloadAfterCodeChanged: (model) => {
    void biLogger.report(
      wixCliReadyForReloadAfterCodeChange({
        siteRevision: Number(model.revision)
      })
    );
  },
  messageDisplayed: ({
    message,
    model
  }) => {
    void biLogger.report(
      wixCliCliMessageDisplayed({
        message,
        messageId: randomUUID(),
        siteRevision: Number(model.revision)
      })
    );
  },
  userResponse: ({
    model,
    action,
    message
  }) => {
    void biLogger.report(
      wixCliUserResponseToCliMessage({
        action,
        message,
        messageId: randomUUID(),
        siteRevision: Number(model.revision)
      })
    );
  }
});

// ../cli-site-old/src/dev/sync-all-to-revision.ts
init_esm_shims();
import { rm as rm2 } from "node:fs/promises";

// ../cli-site-old/src/sources/index.ts
init_esm_shims();
import { readdir } from "node:fs/promises";

// ../cli-site-old/src/sources/pages-diff.ts
init_esm_shims();
import { join as join2 } from "node:path";
import { rm, rename } from "node:fs/promises";
async function createPages(projectFolder, pages) {
  await Promise.all(
    pages.map((page) => {
      if (!page.pageId?.path || !page.content) {
        return Promise.resolve();
      }
      return outputFile(join2(projectFolder, page.pageId.path), page.content);
    })
  );
}
async function renamePages(projectFolder, pages) {
  await Promise.all(
    pages.map(async (page) => {
      if (!page.sourcePath?.path || !page.targetPath?.path) {
        return;
      }
      const sourcePath = join2(projectFolder, page.sourcePath.path);
      const targetPath = join2(projectFolder, page.targetPath.path);
      if (await pathExists(targetPath)) {
        return rm(sourcePath, { force: true });
      }
      return rename(sourcePath, targetPath);
    })
  );
}
async function deletePages(projectFolder, pages) {
  await Promise.all(
    pages.map((page) => {
      if (!page.path) {
        return Promise.resolve();
      }
      return rm(join2(projectFolder, page.path), { force: true });
    })
  );
}

// ../cli-site-old/src/sources/index.ts
async function syncPages(model, opts) {
  const pagesFolder = getPagesFolder(model.projectFolder);
  if (!await pathExists(pagesFolder)) {
    throw new CliError({
      code: CliErrorCode.NoPagesDirectoryFound({
        srcDir: getSourceFolder(model.projectFolder)
      }),
      cause: null
    });
  }
  const params = {
    layout: GridAppLayout2.GITHUB,
    sourcePagesPaths: await readdir(pagesFolder),
    targetRevision: model.revision
  };
  const { data } = await httpRequest(
    {
      authState: opts.authState,
      type: "code"
    },
    pagesDiff(params)
  ).catch((e) => {
    throw new CliError({
      code: CliErrorCode.FailedToGetPagesDiff(),
      cause: e,
      info: { ...params }
    });
  });
  await Promise.all([
    createPages(model.projectFolder, data.pagesDiff?.created ?? []),
    renamePages(model.projectFolder, data.pagesDiff?.renamed ?? []),
    deletePages(model.projectFolder, data.pagesDiff?.deleted ?? [])
  ]);
}

// ../cli-site-old/src/dev/sync-all-to-revision.ts
async function syncAllToRevision(model, opts, logger) {
  const logTypesSynced = logger.logSyncingTypesToRevision(model.revision);
  try {
    await syncTypesWithAuth(model, { authState: opts.authState });
    logTypesSynced.success();
  } catch (error) {
    writeCrashReport(
      getDebugLogFilePath(model.projectFolder),
      error,
      /* @__PURE__ */ new Date()
    );
    logTypesSynced.fail();
    await rm2(getTypesDir(model.projectFolder), {
      recursive: true,
      force: true
    }).catch((e) => {
      writeCrashReport(getDebugLogFilePath(model.projectFolder), e, /* @__PURE__ */ new Date());
      logger.logRecoverableFailureToRemoveTypesDir(e);
    });
  }
  const logPagesSynced = logger.logSyncingPagesToRevision(model.revision);
  try {
    await syncPages(model, { authState: opts.authState });
    logPagesSynced.success();
  } catch (error) {
    logPagesSynced.fail();
    throw error;
  }
}

// ../cli-site-old/src/dev/dev.ts
async function dev(initialModel, { biLogger, errorReporter }, {
  https = false,
  tunnel: useTunnel = false
}) {
  let model = initialModel;
  const authState = await authenticate({
    metaSiteId: model.metaSiteId,
    biLogger,
    errorReporter
  });
  const t = createI18nT();
  const logger = createLogger({ t });
  const biEvents = sitesBiEvents(biLogger);
  const server = createVeloCLIServer({ https });
  let gridAppId;
  try {
    gridAppId = await createMutableGridApp(model.projectFolder, {
      authState
    });
  } catch (error) {
    const message = isHttpError(error) ? error.response?.data?.message : void 0;
    throw new CliError({
      code: CliErrorCode.FailedToCreateGridApp({
        error: message
      }),
      cause: error
    });
  }
  await syncAllToRevision(model, { authState }, logger);
  const { close } = startGridAppUpdater(
    model,
    gridAppId,
    {
      authState,
      onError(error) {
        logger.logNewLine();
        errorReporter.reportError(error);
        writeCrashReport(
          getDebugLogFilePath(model.projectFolder),
          error,
          /* @__PURE__ */ new Date()
        );
        renderSync((0, import_react.createElement)(ErrorViewer, { error }));
      }
    },
    logger,
    biEvents
  );
  const onServerDisconnected = (devEditorUrl) => {
    const message = logger.logNoOpenedTab(devEditorUrl);
    biEvents.messageDisplayed({ model, message });
  };
  const onSyncDevEditorChanges = async (revision) => {
    if (revision !== model.revision) {
      const newModel = { ...model, revision };
      await saveProjectModel(newModel);
      const message = logger.logUpdatedLocalCodeToRevision({
        revision: newModel.revision
      });
      biEvents.messageDisplayed({ message, model });
      await syncAllToRevision(newModel, { authState }, logger);
      model = newModel;
    }
  };
  const openLocalEditor = async (serverPort) => {
    biEvents.userResponse({
      action: "Browser opened",
      message: "Opening the Local Editor",
      model
    });
    const devEditorUrl = getDevEditorUrl(serverPort);
    if (https) {
      await openBrowser(new URL(`https://localhost:${serverPort}`).href);
    } else {
      await openBrowser(devEditorUrl);
    }
  };
  let keyWatcher;
  let tunnel;
  const getDevEditorUrl = (serverPort) => {
    const url = new URL(model.metaSiteId, getDevEditorBaseUrl());
    if (tunnel) {
      url.searchParams.append("localEditorDestination", tunnel.domain);
    } else {
      url.searchParams.append("localPort", serverPort.toString());
    }
    url.searchParams.append("secureSocket", https.toString());
    return url.toString();
  };
  try {
    const { port: serverPort } = await server.serve(gridAppId, {
      getDevEditorUrl
    });
    if (useTunnel) {
      const httpClient = createHttpClient({
        type: "backoffice",
        getAppToken: authState.getAccessToken
      });
      const tunnelClient = new TunnelClient(httpClient);
      tunnel = await launchTunnel(serverPort, tunnelClient);
    }
    const devEditorUrl = getDevEditorUrl(serverPort);
    server.on("disconnected", () => onServerDisconnected(devEditorUrl));
    server.on("syncDevEditorChanges", onSyncDevEditorChanges);
    keyWatcher = new KeyWatcher();
    logger.logOpeningBrowser(https);
    await openLocalEditor(serverPort);
    const { ctrlCPromise } = keyWatcher.watch();
    keyWatcher.on("e", () => openLocalEditor(serverPort));
    asyncExitHook(
      async () => {
        await server.close();
        tunnel?.close();
      },
      { wait: 500 }
    );
    await ctrlCPromise;
  } finally {
    keyWatcher?.unwatch();
    await Promise.all([server.close(), close(), tunnel?.close()]);
  }
}
export {
  dev
};
//# sourceMappingURL=dev-YX2DUOQH.js.map