#!/usr/bin/env node
import {
  CLIENT_PROBLEM_TYPES,
  SERVER_PROBLEM_TYPES,
  zProblemDetails
} from "./chunk-C3VW3DTA.mjs";

// src/utils/problem-types.ts
var CLI_PROBLEM_TYPES = {
  ...SERVER_PROBLEM_TYPES,
  ...CLIENT_PROBLEM_TYPES
};

// src/utils/errors.ts
var STALE_CONTRACT_ARTIFACT_CODE = "STALE_CONTRACT_ARTIFACT";
var STALE_CONTRACT_ARTIFACT_EXIT_CODE = 42;
function isProblemViolationArray(value) {
  return Array.isArray(value) && value.every(
    (entry) => typeof entry === "object" && entry !== null && typeof entry.message === "string"
  );
}
function isProblemDetails(value) {
  return zProblemDetails.safeParse(value).success;
}
function coerceViolations(value) {
  if (isProblemViolationArray(value)) {
    return value;
  }
  if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
    return value.map((message) => ({ message }));
  }
  return void 0;
}
function getRequestId(response) {
  return response?.headers?.get?.("X-Correlation-ID") ?? response?.headers?.get?.("x-correlation-id") ?? void 0;
}
function toApiProblem(error, response, fallback) {
  if (isProblemDetails(error)) {
    return {
      ...error,
      status: error.status || response?.status || 0,
      requestId: error.requestId ?? getRequestId(response)
    };
  }
  if (error instanceof Error) {
    return {
      type: CLI_PROBLEM_TYPES.TRANSPORT_ERROR,
      title: response?.statusText || "API error",
      status: response?.status ?? 0,
      detail: error.message || fallback,
      requestId: getRequestId(response)
    };
  }
  if (error && typeof error === "object") {
    const obj = error;
    const detail2 = typeof obj.detail === "string" ? obj.detail : typeof obj.message === "string" ? obj.message : void 0;
    const title = typeof obj.title === "string" ? obj.title : response?.statusText || "API error";
    const violations = coerceViolations(obj.violations) ?? coerceViolations(obj.errors);
    if (detail2) {
      return {
        type: typeof obj.type === "string" ? obj.type : CLI_PROBLEM_TYPES.UNKNOWN_API_ERROR,
        title,
        status: typeof obj.status === "number" ? obj.status : response?.status ?? 0,
        detail: detail2,
        requestId: typeof obj.requestId === "string" ? obj.requestId : getRequestId(response),
        retryable: typeof obj.retryable === "boolean" ? obj.retryable : void 0,
        context: typeof obj.context === "object" && obj.context !== null ? obj.context : void 0,
        violations,
        timestamp: typeof obj.timestamp === "string" ? obj.timestamp : void 0,
        instance: typeof obj.instance === "string" ? obj.instance : void 0
      };
    }
  }
  const detail = typeof error === "string" ? error.trim() || fallback : fallback;
  return {
    type: CLI_PROBLEM_TYPES.UNKNOWN_API_ERROR,
    title: response?.statusText || "API error",
    status: response?.status ?? 0,
    detail,
    requestId: getRequestId(response)
  };
}
function formatProblem(problem) {
  const base = problem.detail || problem.title;
  const violations = problem.violations && problem.violations.length > 0 ? ` (${problem.violations.map((entry) => entry.message).join("; ")})` : "";
  const statusSuffix = problem.status && problem.status > 0 ? ` (HTTP ${problem.status})` : "";
  return `${base}${violations}${statusSuffix}`;
}
var DreamboardApiError = class extends Error {
  problem;
  status;
  requestId;
  retryable;
  constructor(problem, cause) {
    super(formatProblem(problem), { cause });
    this.name = "DreamboardApiError";
    this.problem = problem;
    this.status = problem.status;
    this.requestId = problem.requestId;
    this.retryable = problem.retryable;
  }
};
function toDreamboardApiError(error, response, fallback) {
  return new DreamboardApiError(toApiProblem(error, response, fallback), error);
}
function isDreamboardApiError(error) {
  return error instanceof DreamboardApiError;
}
function getObjectStringProperty(value, property) {
  return value && typeof value === "object" && typeof value[property] === "string" ? value[property] : void 0;
}
function isStaleContractArtifactMessage(message) {
  return message.includes(STALE_CONTRACT_ARTIFACT_CODE) || message.includes("StaleContractArtifactError") || message.toLowerCase().includes("stale contract artifact");
}
function isStaleContractArtifactError(error) {
  if (getObjectStringProperty(error, "code") === STALE_CONTRACT_ARTIFACT_CODE) {
    return true;
  }
  if (getObjectStringProperty(error, "name") === "StaleContractArtifactError") {
    return true;
  }
  const message = getObjectStringProperty(error, "message");
  return message ? isStaleContractArtifactMessage(message) : false;
}
function isGameNotFoundProblem(problem) {
  return problem.status === 404 && (problem.detail?.startsWith("Game not found: ") === true || problem.instance?.includes("/source-blobs/upload-sessions") === true);
}
function getProblemResolution(problem) {
  if (isGameNotFoundProblem(problem)) {
    return [
      "Run `dreamboard sync --force` to recreate the remote game state from your current local files if this is a local workspace.",
      "If you meant to use an existing remote game, check that your selected `--env` points at the backend that has that game."
    ].join(" ");
  }
  switch (problem.type) {
    case CLI_PROBLEM_TYPES.UNAUTHORIZED:
      return "Run `dreamboard login` to authenticate again.";
    case CLI_PROBLEM_TYPES.FORBIDDEN:
      return "Check that the signed-in account has access to this game, or run `dreamboard login` with the correct account.";
    case CLI_PROBLEM_TYPES.TOO_MANY_REQUESTS:
      return "Wait a moment, then retry the command.";
    case CLI_PROBLEM_TYPES.TRANSPORT_ERROR:
      return "Check that the selected Dreamboard server is reachable and try again later.";
    case CLI_PROBLEM_TYPES.VALIDATION_FAILED:
      return "Fix the validation issue above, then retry the command.";
    case CLI_PROBLEM_TYPES.ACTIVE_JOB_CONFLICT:
      return "Wait for the active job to finish, then retry the command.";
    case CLI_PROBLEM_TYPES.GAME_SLUG_CONFLICT:
      return "Choose a different game slug, or use the existing workspace for that slug.";
    case CLI_PROBLEM_TYPES.SOURCE_REVISION_NOT_FOUND:
      return "Run `dreamboard sync --force` to recreate the remote source revision from your current local files.";
    case CLI_PROBLEM_TYPES.SOURCE_REVISION_DRIFT:
    case CLI_PROBLEM_TYPES.AUTHORING_STATE_DRIFT:
    case CLI_PROBLEM_TYPES.STATE_CONFLICT:
      return "Run `dreamboard pull` to reconcile remote changes before retrying. If this local workspace is the source of truth, rerun the command with `--force` when supported.";
    case CLI_PROBLEM_TYPES.SOURCE_REVISION_BASE_MISSING:
    case CLI_PROBLEM_TYPES.AUTHORING_STATE_BASE_MISSING:
      return "Run `dreamboard pull --force` in a clean workspace to recover the remote authored state. If the remote has no authored state, run `dreamboard sync --force` from the local source-of-truth workspace.";
    case CLI_PROBLEM_TYPES.INTERNAL_ERROR:
      return "Retry the command. If it still fails, include the request id when asking for help.";
    default:
      return void 0;
  }
}
function getProblemDetails(problem) {
  return [
    `Problem: ${problem.type}`,
    problem.instance ? `Endpoint: ${problem.instance}` : void 0,
    problem.requestId ? `Request ID: ${problem.requestId}` : void 0,
    problem.timestamp ? `Timestamp: ${problem.timestamp}` : void 0
  ].filter((detail) => Boolean(detail));
}
function presentCliError(error) {
  if (isDreamboardApiError(error)) {
    return {
      message: formatProblem(error.problem),
      resolution: getProblemResolution(error.problem),
      details: getProblemDetails(error.problem)
    };
  }
  if (error instanceof Error) {
    return {
      message: error.message,
      details: []
    };
  }
  if (typeof error === "object" && error !== null) {
    let serialized;
    try {
      serialized = JSON.stringify(error);
    } catch {
      serialized = String(error);
    }
    return {
      message: serialized,
      details: []
    };
  }
  return {
    message: String(error),
    details: []
  };
}
function formatCliError(error) {
  const presentation = presentCliError(error);
  return [
    presentation.message,
    presentation.resolution ? `Resolution: ${presentation.resolution}` : void 0,
    ...presentation.details
  ].filter((line) => Boolean(line)).join("\n");
}

export {
  STALE_CONTRACT_ARTIFACT_CODE,
  STALE_CONTRACT_ARTIFACT_EXIT_CODE,
  toDreamboardApiError,
  isDreamboardApiError,
  isStaleContractArtifactMessage,
  isStaleContractArtifactError,
  formatCliError
};
//# sourceMappingURL=chunk-IDVQXGAO.mjs.map