Openstatus
www.openstatus.dev
1export const FLY_REGIONS = [
2 "ams",
3 "arn",
4 "atl",
5 "bog",
6 "bom",
7 "bos",
8 "cdg",
9 "den",
10 "dfw",
11 "ewr",
12 "eze",
13 "fra",
14 "gdl",
15 "gig",
16 "gru",
17 "hkg",
18 "iad",
19 "jnb",
20 "lax",
21 "lhr",
22 "mad",
23 "mia",
24 "nrt",
25 "ord",
26 "otp",
27 "phx",
28 "qro",
29 "scl",
30 "sjc",
31 "sea",
32 "sin",
33 "syd",
34 "waw",
35 "yul",
36 "yyz",
37] as const;
38
39export const KOYEB_REGIONS = [
40 "koyeb_fra",
41 "koyeb_was",
42 "koyeb_sin",
43 "koyeb_tyo",
44 "koyeb_par",
45 "koyeb_sfo",
46] as const;
47
48export const RAILWAY_REGIONS = [
49 "railway_europe-west4-drams3a",
50 "railway_us-east4-eqdc4a",
51 "railway_asia-southeast1-eqsg3a",
52 "railway_us-west2",
53] as const;
54
55export const FREE_FLY_REGIONS = [
56 "iad",
57 "ams",
58 "gru",
59 "syd",
60 "sin",
61 "jnb",
62] as const satisfies (typeof FLY_REGIONS)[number][];
63
64export const ALL_REGIONS = [
65 ...FLY_REGIONS,
66 ...KOYEB_REGIONS,
67 ...RAILWAY_REGIONS,
68] as const;
69
70export type Region = (typeof ALL_REGIONS)[number];
71
72export type Continent =
73 | "Europe"
74 | "North America"
75 | "South America"
76 | "Asia"
77 | "Africa"
78 | "Oceania";
79
80export type RegionInfo = {
81 code: Region;
82 location: string;
83 flag: string;
84 continent: Continent;
85 deprecated: boolean;
86 provider: "fly" | "koyeb" | "railway" | "private";
87};
88
89// TODO: we could think of doing the inverse and use "EU" as key
90export const continentDict: Record<Continent, { code: string }> = {
91 Europe: { code: "EU" },
92 "North America": { code: "NA" },
93 "South America": { code: "SA" },
94 Asia: { code: "AS" },
95 Africa: { code: "AF" },
96 Oceania: { code: "OC" },
97};
98
99export const regionDict: Record<Region, RegionInfo> = {
100 ams: {
101 code: "ams",
102 location: "Amsterdam, Netherlands",
103 flag: "🇳🇱",
104 continent: "Europe",
105 deprecated: false,
106 provider: "fly",
107 },
108 arn: {
109 code: "arn",
110 location: "Stockholm, Sweden",
111 flag: "🇸🇪",
112 continent: "Europe",
113 deprecated: false,
114 provider: "fly",
115 },
116
117 atl: {
118 code: "atl",
119 location: "Atlanta, Georgia, USA",
120 flag: "🇺🇸",
121 continent: "North America",
122 deprecated: true,
123 provider: "fly",
124 },
125 bog: {
126 code: "bog",
127 location: "Bogotá, Colombia",
128 flag: "🇨🇴",
129 continent: "South America",
130 deprecated: true,
131 provider: "fly",
132 },
133 bom: {
134 code: "bom",
135 location: "Mumbai, India",
136 flag: "🇮🇳",
137 continent: "Asia",
138 deprecated: false,
139 provider: "fly",
140 },
141 bos: {
142 code: "bos",
143 location: "Boston, Massachusetts, USA",
144 flag: "🇺🇸",
145 continent: "North America",
146 deprecated: true,
147 provider: "fly",
148 },
149 cdg: {
150 code: "cdg",
151 location: "Paris, France",
152 flag: "🇫🇷",
153 continent: "Europe",
154 deprecated: false,
155 provider: "fly",
156 },
157 den: {
158 code: "den",
159 location: "Denver, Colorado, USA",
160 flag: "🇺🇸",
161 continent: "North America",
162 deprecated: true,
163 provider: "fly",
164 },
165 dfw: {
166 code: "dfw",
167 location: "Dallas, Texas, USA",
168 flag: "🇺🇸",
169 continent: "North America",
170 deprecated: false,
171 provider: "fly",
172 },
173 ewr: {
174 code: "ewr",
175 location: "Secaucus, New Jersey, USA",
176 flag: "🇺🇸",
177 continent: "North America",
178 deprecated: false,
179 provider: "fly",
180 },
181 eze: {
182 code: "eze",
183 location: "Ezeiza, Argentina",
184 flag: "🇦🇷",
185 continent: "South America",
186 deprecated: true,
187 provider: "fly",
188 },
189 fra: {
190 code: "fra",
191 location: "Frankfurt, Germany",
192 flag: "🇩🇪",
193 continent: "Europe",
194 deprecated: false,
195 provider: "fly",
196 },
197 gdl: {
198 code: "gdl",
199 location: "Guadalajara, Mexico",
200 flag: "🇲🇽",
201 continent: "North America",
202 deprecated: true,
203 provider: "fly",
204 },
205 gig: {
206 code: "gig",
207 location: "Rio de Janeiro, Brazil",
208 flag: "🇧🇷",
209 continent: "South America",
210 deprecated: true,
211 provider: "fly",
212 },
213 gru: {
214 code: "gru",
215 location: "Sao Paulo, Brazil",
216 flag: "🇧🇷",
217 continent: "South America",
218 deprecated: false,
219 provider: "fly",
220 },
221 hkg: {
222 code: "hkg",
223 location: "Hong Kong, Hong Kong",
224 flag: "🇭🇰",
225 continent: "Asia",
226 deprecated: true,
227 provider: "fly",
228 },
229 iad: {
230 code: "iad",
231 location: "Ashburn, Virginia, USA",
232 flag: "🇺🇸",
233 continent: "North America",
234 deprecated: false,
235 provider: "fly",
236 },
237 jnb: {
238 code: "jnb",
239 location: "Johannesburg, South Africa",
240 flag: "🇿🇦",
241 continent: "Africa",
242 deprecated: false,
243 provider: "fly",
244 },
245 lax: {
246 code: "lax",
247 location: "Los Angeles, California, USA",
248 flag: "🇺🇸",
249 continent: "North America",
250 deprecated: false,
251 provider: "fly",
252 },
253 lhr: {
254 code: "lhr",
255 location: "London, United Kingdom",
256 flag: "🇬🇧",
257 continent: "Europe",
258 deprecated: false,
259 provider: "fly",
260 },
261 mad: {
262 code: "mad",
263 location: "Madrid, Spain",
264 flag: "🇪🇸",
265 continent: "Europe",
266 deprecated: true,
267 provider: "fly",
268 },
269 mia: {
270 code: "mia",
271 location: "Miami, Florida, USA",
272 flag: "🇺🇸",
273 continent: "North America",
274 deprecated: true,
275 provider: "fly",
276 },
277 nrt: {
278 code: "nrt",
279 location: "Tokyo, Japan",
280 flag: "🇯🇵",
281 continent: "Asia",
282 deprecated: false,
283 provider: "fly",
284 },
285 ord: {
286 code: "ord",
287 location: "Chicago, Illinois, USA",
288 flag: "🇺🇸",
289 continent: "North America",
290 deprecated: false,
291 provider: "fly",
292 },
293 otp: {
294 code: "otp",
295 location: "Bucharest, Romania",
296 flag: "🇷🇴",
297 continent: "Europe",
298 deprecated: true,
299 provider: "fly",
300 },
301 phx: {
302 code: "phx",
303 location: "Phoenix, Arizona, USA",
304 flag: "🇺🇸",
305 continent: "North America",
306 deprecated: true,
307 provider: "fly",
308 },
309 qro: {
310 code: "qro",
311 location: "Querétaro, Mexico",
312 flag: "🇲🇽",
313 continent: "North America",
314 deprecated: true,
315 provider: "fly",
316 },
317 scl: {
318 code: "scl",
319 location: "Santiago, Chile",
320 flag: "🇨🇱",
321 continent: "South America",
322 deprecated: true,
323 provider: "fly",
324 },
325 sjc: {
326 code: "sjc",
327 location: "San Jose, California, USA",
328 flag: "🇺🇸",
329 continent: "North America",
330 deprecated: false,
331 provider: "fly",
332 },
333 sea: {
334 code: "sea",
335 location: "Seattle, Washington, USA",
336 flag: "🇺🇸",
337 continent: "North America",
338 deprecated: true,
339 provider: "fly",
340 },
341 sin: {
342 code: "sin",
343 location: "Singapore, Singapore",
344 flag: "🇸🇬",
345 continent: "Asia",
346 deprecated: false,
347 provider: "fly",
348 },
349 syd: {
350 code: "syd",
351 location: "Sydney, Australia",
352 flag: "🇦🇺",
353 continent: "Oceania",
354 deprecated: false,
355 provider: "fly",
356 },
357 waw: {
358 code: "waw",
359 location: "Warsaw, Poland",
360 flag: "🇵🇱",
361 continent: "Europe",
362 deprecated: true,
363 provider: "fly",
364 },
365 yul: {
366 code: "yul",
367 location: "Montreal, Canada",
368 flag: "🇨🇦",
369 continent: "North America",
370 deprecated: true,
371 provider: "fly",
372 },
373 yyz: {
374 code: "yyz",
375 location: "Toronto, Canada",
376 flag: "🇨🇦",
377 continent: "North America",
378 deprecated: false,
379 provider: "fly",
380 },
381 koyeb_fra: {
382 code: "koyeb_fra",
383 location: "Frankfurt, Germany",
384 flag: "🇩🇪",
385 continent: "Europe",
386 deprecated: false,
387 provider: "koyeb",
388 },
389 koyeb_par: {
390 code: "koyeb_par",
391 location: "Paris, France",
392 flag: "🇫🇷",
393 continent: "Europe",
394 deprecated: false,
395 provider: "koyeb",
396 },
397 koyeb_sfo: {
398 code: "koyeb_sfo",
399 location: "San Francisco, USA",
400 flag: "🇺🇸",
401 continent: "North America",
402 deprecated: false,
403 provider: "koyeb",
404 },
405 koyeb_sin: {
406 code: "koyeb_sin",
407 location: "Singapore, Singapore",
408 flag: "🇸🇬",
409 continent: "Asia",
410 deprecated: false,
411 provider: "koyeb",
412 },
413 koyeb_tyo: {
414 code: "koyeb_tyo",
415 location: "Tokyo, Japan",
416 flag: "🇯🇵",
417 continent: "Asia",
418 deprecated: false,
419 provider: "koyeb",
420 },
421 koyeb_was: {
422 code: "koyeb_was",
423 location: "Washington, USA",
424 flag: "🇺🇸",
425 continent: "North America",
426 deprecated: false,
427 provider: "koyeb",
428 },
429 "railway_us-west2": {
430 code: "railway_us-west2",
431 location: "California, USA",
432 flag: "🇺🇸",
433 continent: "North America",
434 deprecated: false,
435 provider: "railway",
436 },
437 "railway_us-east4-eqdc4a": {
438 code: "railway_us-east4-eqdc4a",
439 location: "Virginia, USA",
440 flag: "🇺🇸",
441 continent: "North America",
442 deprecated: false,
443 provider: "railway",
444 },
445 "railway_europe-west4-drams3a": {
446 code: "railway_europe-west4-drams3a",
447 location: "Amsterdam, Netherlands",
448 flag: "🇳🇱",
449 continent: "Europe",
450 deprecated: false,
451 provider: "railway",
452 },
453 "railway_asia-southeast1-eqsg3a": {
454 code: "railway_asia-southeast1-eqsg3a",
455 location: "Singapore, Singapore",
456 flag: "🇸🇬",
457 continent: "Asia",
458 deprecated: false,
459 provider: "railway",
460 },
461} as const;
462
463export const AVAILABLE_REGIONS = ALL_REGIONS.filter(
464 (r) => !regionDict[r].deprecated,
465);
466
467export function formatRegionCode(region: RegionInfo | Region | string) {
468 const r = typeof region === "string" ? getRegionInfo(region) : region;
469 const suffix = r.code.replace(/(koyeb_|railway_|fly_)/g, "");
470
471 if (r.provider === "railway") {
472 return suffix.replace(/(-eqdc4a|-eqsg3a|-drams3a)/g, "");
473 }
474
475 return suffix;
476}
477
478// NOTE: opts is used to override the location for private locations
479export function getRegionInfo(region: string, opts?: { location?: string }) {
480 if (region in regionDict) {
481 return regionDict[region as Region];
482 }
483
484 return {
485 code: region,
486 location: opts?.location ?? "Private Location",
487 flag: "🌐",
488 continent: "Private",
489 deprecated: false,
490 provider: "private",
491 } satisfies Omit<RegionInfo, "code" | "continent"> & {
492 code: string;
493 continent: "Private";
494 };
495}
496
497export const groupByContinent = Object.entries(regionDict).reduce<
498 Record<Continent, RegionInfo[]>
499>(
500 (acc, [_key, value]) => {
501 if (value.deprecated) {
502 return acc;
503 }
504 Object.assign(acc, {
505 [value.continent]: [...acc[value.continent], value],
506 });
507 return acc;
508 },
509 {
510 "North America": [],
511 Europe: [],
512 "South America": [],
513 Oceania: [],
514 Asia: [],
515 Africa: [],
516 },
517);