UNPKG

5.21 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = dev;
7
8var _project = require("./project");
9
10var _logger = require("./logger");
11
12var _utils = require("./utils");
13
14var babel = _interopRequireWildcard(require("@babel/core"));
15
16var fs = _interopRequireWildcard(require("fs-extra"));
17
18var _path = _interopRequireDefault(require("path"));
19
20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
23
24let tsExtensionPattern = /tsx?$/;
25
26function cjsOnlyReexportTemplate(pathToSource) {
27 return `// 👋 hey!!
28// you might be reading this and seeing .esm in the filename
29// and being confused why there is commonjs below this filename
30// DON'T WORRY!
31// this is intentional
32// it's only commonjs with \`preconstruct dev\`
33// when you run \`preconstruct build\`, it will be ESM
34// why is it commonjs?
35// we need to re-export every export from the source file
36// but we can't do that with ESM without knowing what the exports are (because default exports aren't included in export/import *)
37// and they could change after running \`preconstruct dev\` so we can't look at the file without forcing people to
38// run preconstruct dev again which wouldn't be ideal
39// this solution could change but for now, it's working
40
41module.exports = require("${pathToSource}")
42`;
43}
44
45async function getTypeSystem(entrypoint) {
46 let content = await fs.readFile(entrypoint.source, "utf8");
47
48 if (tsExtensionPattern.test(entrypoint.source)) {
49 return ["typescript", content];
50 } // TODO: maybe we should write the flow symlink even if there isn't an
51 // comment so that if someone adds an comment they don't have to run preconstruct dev again
52
53
54 if (content.includes("@flow")) {
55 return ["flow", content];
56 }
57
58 return [null, content];
59}
60
61async function writeFlowFile(typeSystemPromise, entrypoint) {
62 let [typeSystem, content] = await typeSystemPromise;
63 if (typeSystem === null) return;
64
65 let cjsDistPath = _path.default.join(entrypoint.directory, entrypoint.main);
66
67 if (typeSystem === "flow") {
68 await fs.symlink(entrypoint.source, cjsDistPath + ".flow");
69 }
70
71 if (typeSystem === "typescript") {
72 let ast = await babel.parseAsync(content, {
73 filename: entrypoint.source,
74 sourceType: "module",
75 cwd: entrypoint.package.project.directory
76 });
77 let hasDefaultExport = false;
78
79 for (let statement of ast.program.body) {
80 if (statement.type === "ExportDefaultDeclaration" || statement.type === "ExportNamedDeclaration" && statement.specifiers.some(specifier => specifier.type === "ExportSpecifier" && specifier.exported.name === "default")) {
81 hasDefaultExport = true;
82 break;
83 }
84 }
85
86 await fs.writeFile(cjsDistPath + ".ts", (0, _utils.tsTemplate)(hasDefaultExport, _path.default.relative(_path.default.dirname(cjsDistPath), entrypoint.source).replace(/\.tsx?$/, "")));
87 }
88}
89
90async function dev(projectDir) {
91 let project = await _project.Project.create(projectDir);
92 project.packages.forEach(({
93 entrypoints
94 }) => entrypoints.forEach(x => x.strict()));
95 (0, _logger.info)("project is valid!");
96 let promises = [];
97 await Promise.all(project.packages.map(pkg => {
98 return Promise.all(pkg.entrypoints.map(async _entrypoint => {
99 let entrypoint = _entrypoint.strict();
100
101 let typeSystemPromise = getTypeSystem(entrypoint);
102 await fs.remove(_path.default.join(entrypoint.directory, "dist"));
103 await fs.ensureDir(_path.default.join(entrypoint.directory, "dist"));
104 let promises = [writeFlowFile(typeSystemPromise, entrypoint), fs.writeFile(_path.default.join(entrypoint.directory, entrypoint.main), `'use strict';
105
106let unregister = require('${require.resolve("@preconstruct/hook")}').___internalHook('${project.directory}');
107
108module.exports = require('${entrypoint.source}');
109
110unregister();
111`)];
112
113 if (entrypoint.module) {
114 promises.push(fs.writeFile(_path.default.join(entrypoint.directory, entrypoint.module), cjsOnlyReexportTemplate(entrypoint.source)));
115 }
116
117 let browserField = entrypoint.browser;
118
119 if (browserField) {
120 for (let key of Object.keys(browserField)) {
121 promises.push(fs.writeFile(_path.default.join(entrypoint.directory, browserField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
122 }
123 }
124
125 let rnField = entrypoint.reactNative;
126
127 if (rnField) {
128 for (let key of Object.keys(rnField)) {
129 promises.push(fs.writeFile(_path.default.join(entrypoint.directory, rnField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
130 }
131 }
132
133 return Promise.all(promises);
134 }));
135 }));
136 await Promise.all(promises);
137 (0, _logger.success)("created links!");
138}
\No newline at end of file