xref: /expo/packages/@expo/cli/taskfile-swc.js (revision 8d307f52)
1*8d307f52SEvan Bacon// Based on Next.js swc taskr file.
2*8d307f52SEvan Bacon// https://github.com/vercel/next.js/blob/5378db8f807dbb9ff0993662f0a39d0f6cba2452/packages/next/taskfile-swc.js
3*8d307f52SEvan Bacon
4*8d307f52SEvan Baconconst path = require('path');
5*8d307f52SEvan Baconconst assert = require('assert');
6*8d307f52SEvan Bacon
7*8d307f52SEvan Baconconst transform = require('@swc/core').transform;
8*8d307f52SEvan Bacon
9*8d307f52SEvan Baconmodule.exports = function (task) {
10*8d307f52SEvan Bacon  const ENVIRONMENTS = {
11*8d307f52SEvan Bacon    // Settings for compiling the CLI code that runs in Node.js environments.
12*8d307f52SEvan Bacon    cli: {
13*8d307f52SEvan Bacon      output: 'build',
14*8d307f52SEvan Bacon      options: {
15*8d307f52SEvan Bacon        module: {
16*8d307f52SEvan Bacon          type: 'commonjs',
17*8d307f52SEvan Bacon        },
18*8d307f52SEvan Bacon        env: {
19*8d307f52SEvan Bacon          targets: {
20*8d307f52SEvan Bacon            node: '12.13.0',
21*8d307f52SEvan Bacon          },
22*8d307f52SEvan Bacon        },
23*8d307f52SEvan Bacon        jsc: {
24*8d307f52SEvan Bacon          loose: true,
25*8d307f52SEvan Bacon          parser: {
26*8d307f52SEvan Bacon            syntax: 'typescript',
27*8d307f52SEvan Bacon            dynamicImport: true,
28*8d307f52SEvan Bacon          },
29*8d307f52SEvan Bacon        },
30*8d307f52SEvan Bacon      },
31*8d307f52SEvan Bacon    },
32*8d307f52SEvan Bacon  };
33*8d307f52SEvan Bacon  // Like `/^(cli|sdk)$/`
34*8d307f52SEvan Bacon  const matcher = new RegExp(`^(${Object.keys(ENVIRONMENTS).join('|')})$`);
35*8d307f52SEvan Bacon
36*8d307f52SEvan Bacon  task.plugin('swc', {}, function* (file, environment, { stripExtension } = {}) {
37*8d307f52SEvan Bacon    // Don't compile .d.ts
38*8d307f52SEvan Bacon    if (file.base.endsWith('.d.ts')) return;
39*8d307f52SEvan Bacon
40*8d307f52SEvan Bacon    // Environment assertion
41*8d307f52SEvan Bacon    assert.match(environment, matcher);
42*8d307f52SEvan Bacon
43*8d307f52SEvan Bacon    const setting = ENVIRONMENTS[environment];
44*8d307f52SEvan Bacon    const filePath = path.join(file.dir, file.base);
45*8d307f52SEvan Bacon    const inputFilePath = path.join(__dirname, filePath);
46*8d307f52SEvan Bacon    const outputFilePath = path.dirname(path.join(__dirname, setting.output, filePath));
47*8d307f52SEvan Bacon
48*8d307f52SEvan Bacon    const options = {
49*8d307f52SEvan Bacon      filename: path.join(file.dir, file.base),
50*8d307f52SEvan Bacon      sourceMaps: true,
51*8d307f52SEvan Bacon      sourceFileName: path.relative(outputFilePath, inputFilePath),
52*8d307f52SEvan Bacon      ...setting.options,
53*8d307f52SEvan Bacon    };
54*8d307f52SEvan Bacon
55*8d307f52SEvan Bacon    const output = yield transform(file.data.toString('utf-8'), options);
56*8d307f52SEvan Bacon    const ext = path.extname(file.base);
57*8d307f52SEvan Bacon
58*8d307f52SEvan Bacon    // Replace `.ts|.tsx` with `.js` in files with an extension
59*8d307f52SEvan Bacon    if (ext) {
60*8d307f52SEvan Bacon      const extRegex = new RegExp(ext.replace('.', '\\.') + '$', 'i');
61*8d307f52SEvan Bacon      // Remove the extension if stripExtension is enabled or replace it with `.js`
62*8d307f52SEvan Bacon      file.base = file.base.replace(extRegex, stripExtension ? '' : '.js');
63*8d307f52SEvan Bacon    }
64*8d307f52SEvan Bacon
65*8d307f52SEvan Bacon    if (output.map) {
66*8d307f52SEvan Bacon      const map = `${file.base}.map`;
67*8d307f52SEvan Bacon
68*8d307f52SEvan Bacon      output.code += Buffer.from(`\n//# sourceMappingURL=${map}`);
69*8d307f52SEvan Bacon
70*8d307f52SEvan Bacon      // add sourcemap to `files` array
71*8d307f52SEvan Bacon      this._.files.push({
72*8d307f52SEvan Bacon        base: map,
73*8d307f52SEvan Bacon        dir: file.dir,
74*8d307f52SEvan Bacon        data: Buffer.from(output.map),
75*8d307f52SEvan Bacon      });
76*8d307f52SEvan Bacon    }
77*8d307f52SEvan Bacon
78*8d307f52SEvan Bacon    file.data = Buffer.from(setVersionCode(output.code));
79*8d307f52SEvan Bacon  });
80*8d307f52SEvan Bacon};
81*8d307f52SEvan Bacon
82*8d307f52SEvan Baconfunction setVersionCode(code) {
83*8d307f52SEvan Bacon  return code.replace(/process\.env\.__EXPO_VERSION/g, `"${require('./package.json').version}"`);
84*8d307f52SEvan Bacon}
85