1import { ExternalModule } from './ExternalModule';
2
3export interface NgrokClientError {
4  body: {
5    error_code: number;
6    status_code: number;
7    msg: string;
8    details: {
9      err: string;
10    };
11  };
12}
13
14export interface NgrokOptions {
15  authtoken?: string;
16  port?: string | number | null;
17  host?: string;
18  httpauth?: string;
19  region?: string;
20  configPath?: string;
21
22  proto?: 'http' | 'tcp' | 'tls';
23  addr?: string;
24  inspect?: boolean;
25  auth?: string;
26  host_header?: string;
27  bind_tls?: true | false | 'both';
28  subdomain?: string;
29  hostname?: string;
30  crt?: string;
31  key?: string;
32  client_cas?: string;
33  remote_addr?: string;
34}
35
36export interface NgrokInstance {
37  getActiveProcess(): { pid: number };
38  connect(
39    props: {
40      hostname?: string;
41      configPath: string;
42      onStatusChange: (status: string) => void;
43    } & NgrokOptions
44  ): Promise<string>;
45  kill(): Promise<void>;
46}
47
48/** Resolves the ngrok instance from local or globally installed package. */
49export class NgrokResolver extends ExternalModule<NgrokInstance> {
50  constructor(projectRoot: string) {
51    super(
52      projectRoot,
53      {
54        name: '@expo/ngrok',
55        versionRange: '^4.1.0',
56      },
57      (packageName) =>
58        `The package ${packageName} is required to use tunnels, would you like to install it globally?`
59    );
60  }
61}
62
63export function isNgrokClientError(error: any): error is NgrokClientError {
64  return error?.body?.msg;
65}
66