import { Filesystem, nodeFs } from "../../bundler";
import * as Sentry from "@sentry/node";
import { Ora } from "ora";

// Annotate an error as "fs" if it's due to bad state on the local filesystem
// (e.g. `tsc` fails due to a syntax error). The `convex dev` command will
// then print out the error and wait for the file to change before retrying.
//
// Annotate an error as "network" if it's due to a transient network error.
// This will then cause a retry after an exponential backoff.
export type ErrorReason = "fs" | "network";

export interface Context {
  fs: Filesystem;
  deprecationMessagePrinted: boolean;
  spinner: Ora | undefined;
  // Reports to Sentry and either throws FatalError or exits the process.
  // Does not print the error.
  fatalError(exitCode: number, reason?: ErrorReason, err?: any): Promise<never>;
}

export const oneoffContext: Context = {
  fs: nodeFs,
  deprecationMessagePrinted: false,
  spinner: undefined,
  async fatalError(exitCode: number, _reason?: ErrorReason, err?: any) {
    return await flushAndExit(exitCode, err);
  },
};

async function flushAndExit(exitCode: number, err?: any) {
  if (err) {
    Sentry.captureException(err);
  }
  await Sentry.close();
  // eslint-disable-next-line no-restricted-syntax
  return process.exit(exitCode);
}
