1*082815dcSEvan Baconimport assert from 'assert';
2*082815dcSEvan Bacon
3*082815dcSEvan Baconexport type LanguageOptions = {
4*082815dcSEvan Bacon  isTS: boolean;
5*082815dcSEvan Bacon  isModern: boolean;
6*082815dcSEvan Bacon  isReact: boolean;
7*082815dcSEvan Bacon};
8*082815dcSEvan Bacon
9*082815dcSEvan Baconexport function getExtensions(
10*082815dcSEvan Bacon  platforms: string[],
11*082815dcSEvan Bacon  extensions: string[],
12*082815dcSEvan Bacon  workflows: string[]
13*082815dcSEvan Bacon): string[] {
14*082815dcSEvan Bacon  // In the past we used spread operators to collect the values so now we enforce type safety on them.
15*082815dcSEvan Bacon  assert(Array.isArray(platforms), 'Expected: `platforms: string[]`');
16*082815dcSEvan Bacon  assert(Array.isArray(extensions), 'Expected: `extensions: string[]`');
17*082815dcSEvan Bacon  assert(Array.isArray(workflows), 'Expected: `workflows: string[]`');
18*082815dcSEvan Bacon
19*082815dcSEvan Bacon  const fileExtensions = [];
20*082815dcSEvan Bacon  // support .expo files
21*082815dcSEvan Bacon  for (const workflow of [...workflows, '']) {
22*082815dcSEvan Bacon    // Ensure order is correct: [platformA.js, platformB.js, js]
23*082815dcSEvan Bacon    for (const platform of [...platforms, '']) {
24*082815dcSEvan Bacon      // Support both TypeScript and JavaScript
25*082815dcSEvan Bacon      for (const extension of extensions) {
26*082815dcSEvan Bacon        fileExtensions.push([platform, workflow, extension].filter(Boolean).join('.'));
27*082815dcSEvan Bacon      }
28*082815dcSEvan Bacon    }
29*082815dcSEvan Bacon  }
30*082815dcSEvan Bacon  return fileExtensions;
31*082815dcSEvan Bacon}
32*082815dcSEvan Bacon
33*082815dcSEvan Baconexport function getLanguageExtensionsInOrder({
34*082815dcSEvan Bacon  isTS,
35*082815dcSEvan Bacon  isModern,
36*082815dcSEvan Bacon  isReact,
37*082815dcSEvan Bacon}: LanguageOptions): string[] {
38*082815dcSEvan Bacon  // @ts-ignore: filter removes false type
39*082815dcSEvan Bacon  const addLanguage = (lang: string): string[] => [lang, isReact && `${lang}x`].filter(Boolean);
40*082815dcSEvan Bacon
41*082815dcSEvan Bacon  // Support JavaScript
42*082815dcSEvan Bacon  let extensions = addLanguage('js');
43*082815dcSEvan Bacon
44*082815dcSEvan Bacon  if (isModern) {
45*082815dcSEvan Bacon    extensions.unshift('mjs');
46*082815dcSEvan Bacon  }
47*082815dcSEvan Bacon  if (isTS) {
48*082815dcSEvan Bacon    extensions = [...addLanguage('ts'), ...extensions];
49*082815dcSEvan Bacon  }
50*082815dcSEvan Bacon
51*082815dcSEvan Bacon  return extensions;
52*082815dcSEvan Bacon}
53*082815dcSEvan Bacon
54*082815dcSEvan Baconexport function getBareExtensions(
55*082815dcSEvan Bacon  platforms: string[],
56*082815dcSEvan Bacon  languageOptions: LanguageOptions = { isTS: true, isModern: true, isReact: true }
57*082815dcSEvan Bacon): string[] {
58*082815dcSEvan Bacon  const fileExtensions = getExtensions(
59*082815dcSEvan Bacon    platforms,
60*082815dcSEvan Bacon    getLanguageExtensionsInOrder(languageOptions),
61*082815dcSEvan Bacon    []
62*082815dcSEvan Bacon  );
63*082815dcSEvan Bacon  // Always add these last
64*082815dcSEvan Bacon  _addMiscellaneousExtensions(platforms, fileExtensions);
65*082815dcSEvan Bacon  return fileExtensions;
66*082815dcSEvan Bacon}
67*082815dcSEvan Bacon
68*082815dcSEvan Baconfunction _addMiscellaneousExtensions(platforms: string[], fileExtensions: string[]): string[] {
69*082815dcSEvan Bacon  // Always add these with no platform extension
70*082815dcSEvan Bacon  // In the future we may want to add platform and workspace extensions to json.
71*082815dcSEvan Bacon  fileExtensions.push('json');
72*082815dcSEvan Bacon  // Native doesn't currently support web assembly.
73*082815dcSEvan Bacon  if (platforms.includes('web')) {
74*082815dcSEvan Bacon    fileExtensions.push('wasm');
75*082815dcSEvan Bacon  }
76*082815dcSEvan Bacon  return fileExtensions;
77*082815dcSEvan Bacon}
78