import { jsonSchema } from "../../shared/src/json-schema.js";
import { literalUnion } from "../../shared/src/valita.js";
import { mutationIDSchema } from "./mutation-id.js";
import { Internal, SchemaVersionNotSupported, VersionNotSupported, Unauthorized, MutationFailed, MutationRateLimited, InvalidPush, InvalidMessage, InvalidConnectionRequestClientDeleted, InvalidConnectionRequestLastMutationID, InvalidConnectionRequestBaseCookie, InvalidConnectionRequest, ClientNotFound, AuthInvalidated, ServerOverloaded, Rehome, Rebalance, PushFailed, TransformFailed } from "./error-kind-enum.js";
import { ZeroCache, Server } from "./error-origin-enum.js";
import { Internal as Internal$1, UnsupportedPushVersion, OutOfOrderMutation, Parse, Database, HTTP, Timeout } from "./error-reason-enum.js";
import { object, string, literal, record, number, union, array, tuple } from "@badrap/valita";
const basicErrorKindSchema = literalUnion(
  AuthInvalidated,
  ClientNotFound,
  InvalidConnectionRequest,
  InvalidConnectionRequestBaseCookie,
  InvalidConnectionRequestLastMutationID,
  InvalidConnectionRequestClientDeleted,
  InvalidMessage,
  InvalidPush,
  MutationRateLimited,
  MutationFailed,
  Unauthorized,
  VersionNotSupported,
  SchemaVersionNotSupported,
  Internal
);
const basicErrorBodySchema = object({
  kind: basicErrorKindSchema,
  message: string(),
  // this is optional for backwards compatibility
  origin: literalUnion(Server, ZeroCache).optional()
});
const backoffErrorKindSchema = literalUnion(
  Rebalance,
  Rehome,
  ServerOverloaded
);
const backoffBodySchema = object({
  kind: backoffErrorKindSchema,
  message: string(),
  minBackoffMs: number().optional(),
  maxBackoffMs: number().optional(),
  // Query parameters to send in the next reconnect. In the event of
  // a conflict, these will be overridden by the parameters used by
  // the client; it is the responsibility of the server to avoid
  // parameter name conflicts.
  //
  // The parameters will only be added to the immediately following
  // reconnect, and not after that.
  reconnectParams: record(string()).optional(),
  origin: literal(ZeroCache).optional()
});
const pushFailedErrorKindSchema = literal(PushFailed);
const transformFailedErrorKindSchema = literal(TransformFailed);
const errorKindSchema = union(
  basicErrorKindSchema,
  backoffErrorKindSchema,
  pushFailedErrorKindSchema,
  transformFailedErrorKindSchema
);
const pushFailedBaseSchema = object({
  kind: pushFailedErrorKindSchema,
  details: jsonSchema.optional(),
  /**
   * The mutationIDs of the mutations that failed to process.
   * This can be a subset of the mutationIDs in the request.
   */
  mutationIDs: array(mutationIDSchema),
  message: string()
});
const pushFailedBodySchema = union(
  pushFailedBaseSchema.extend({
    origin: literal(Server),
    reason: literalUnion(
      Database,
      Parse,
      OutOfOrderMutation,
      UnsupportedPushVersion,
      Internal$1
    )
  }),
  pushFailedBaseSchema.extend({
    origin: literal(ZeroCache),
    reason: literal(HTTP),
    status: number(),
    bodyPreview: string().optional()
  }),
  pushFailedBaseSchema.extend({
    origin: literal(ZeroCache),
    reason: literalUnion(
      Timeout,
      Parse,
      Internal$1
    )
  })
);
const transformFailedBaseSchema = object({
  kind: transformFailedErrorKindSchema,
  details: jsonSchema.optional(),
  /**
   * The queryIDs of the queries that failed to transform.
   */
  queryIDs: array(string()),
  message: string()
});
const transformFailedBodySchema = union(
  transformFailedBaseSchema.extend({
    origin: literal(Server),
    reason: literalUnion(
      Database,
      Parse,
      Internal$1
    )
  }),
  transformFailedBaseSchema.extend({
    origin: literal(ZeroCache),
    reason: literal(HTTP),
    status: number(),
    bodyPreview: string().optional()
  }),
  transformFailedBaseSchema.extend({
    origin: literal(ZeroCache),
    reason: literalUnion(
      Timeout,
      Parse,
      Internal$1
    )
  })
);
const errorBodySchema = union(
  basicErrorBodySchema,
  backoffBodySchema,
  pushFailedBodySchema,
  transformFailedBodySchema
);
const errorMessageSchema = tuple([
  literal("error"),
  errorBodySchema
]);
class ProtocolError extends Error {
  errorBody;
  constructor(errorBody, options) {
    super(errorBody.message, options);
    this.name = "ProtocolError";
    this.errorBody = errorBody;
  }
  get kind() {
    return this.errorBody.kind;
  }
}
function isProtocolError(error) {
  return error instanceof ProtocolError;
}
export {
  ProtocolError,
  errorBodySchema,
  errorKindSchema,
  errorMessageSchema,
  isProtocolError,
  pushFailedBodySchema,
  transformFailedBodySchema
};
//# sourceMappingURL=error.js.map
