UNPKG

68.4 kBJavaScriptView Raw
1'use strict';
2
3function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
4
5var meow = _interopDefault(require('meow'));
6var _defineProperty = _interopDefault(require('@babel/runtime/helpers/defineProperty'));
7var is = _interopDefault(require('sarcastic'));
8var globby = _interopDefault(require('globby'));
9var fs = require('fs-extra');
10var path = _interopDefault(require('path'));
11var util = _interopDefault(require('util'));
12var _objectSpread = _interopDefault(require('@babel/runtime/helpers/objectSpread'));
13var inquirer = _interopDefault(require('inquirer'));
14var pLimit = _interopDefault(require('p-limit'));
15var DataLoader = _interopDefault(require('dataloader'));
16var chalk = _interopDefault(require('chalk'));
17var resolveFrom = _interopDefault(require('resolve-from'));
18var packlist = _interopDefault(require('npm-packlist'));
19var equal = _interopDefault(require('fast-deep-equal'));
20var resolve = _interopDefault(require('resolve'));
21var resolve$1 = _interopDefault(require('rollup-plugin-node-resolve'));
22var alias = _interopDefault(require('rollup-plugin-alias'));
23var cjs = _interopDefault(require('rollup-plugin-commonjs'));
24var replace = _interopDefault(require('rollup-plugin-replace'));
25var builtInModules = _interopDefault(require('builtin-modules'));
26var rollup$1 = require('rollup');
27var fs$1 = require('fs');
28var json = _interopDefault(require('rollup-plugin-json'));
29var _objectWithoutProperties = _interopDefault(require('@babel/runtime/helpers/objectWithoutProperties'));
30var babel = require('@babel/core');
31var rollupPluginutils = require('rollup-pluginutils');
32var Worker = _interopDefault(require('jest-worker'));
33var initHasher = _interopDefault(require('xxhash-wasm'));
34var QuickLRU = _interopDefault(require('quick-lru'));
35var codeFrame = require('@babel/code-frame');
36var installPackages = _interopDefault(require('install-packages'));
37var ms = _interopDefault(require('ms'));
38
39let EXTENSIONS = [".js", ".jsx", ".ts", ".tsx"];
40let PKG_JSON_CONFIG_FIELD = "preconstruct";
41
42let itemsByPath = {};
43class Item {
44 constructor(filePath, contents) {
45 _defineProperty(this, "_contents", void 0);
46
47 _defineProperty(this, "_stringifiedSavedJson", void 0);
48
49 _defineProperty(this, "path", void 0);
50
51 _defineProperty(this, "directory", void 0);
52
53 _defineProperty(this, "json", void 0);
54
55 _defineProperty(this, "_config", void 0);
56
57 this.json = is(JSON.parse(contents), is.object);
58 this._stringifiedSavedJson = JSON.stringify(this.json, null, 2);
59 this._contents = contents;
60 this.path = filePath;
61 this.directory = path.dirname(filePath);
62 this._config = this.json[PKG_JSON_CONFIG_FIELD] || {};
63
64 if (itemsByPath[this.path] === undefined) {
65 itemsByPath[this.path] = new Set();
66 }
67
68 itemsByPath[this.path].add(this);
69 }
70
71 updater(json) {
72 this.json = json;
73 }
74
75 async refresh() {
76 let contents = await fs.readFile(this.path, "utf-8");
77 let json = is(JSON.parse(contents), is.object);
78
79 for (let item of itemsByPath[this.path]) {
80 item.updater(json);
81 }
82 }
83
84 async save() {
85 if (Object.keys(this._config).length) {
86 this.json[PKG_JSON_CONFIG_FIELD] = this._config;
87 } else {
88 delete this.json[PKG_JSON_CONFIG_FIELD];
89 }
90
91 let stringified = JSON.stringify(this.json, null, 2);
92
93 if (stringified !== this._stringifiedSavedJson) {
94 await fs.writeFile(this.path, JSON.stringify(this.json, null, 2) + "\n");
95 this._config = this.json[PKG_JSON_CONFIG_FIELD] || {};
96
97 for (let item of itemsByPath[this.path]) {
98 item.updater(this.json);
99 }
100
101 this._stringifiedSavedJson = stringified;
102 return true;
103 }
104
105 return false;
106 }
107
108}
109
110class FatalError extends Error {
111 constructor(message, scope) {
112 super(message);
113
114 _defineProperty(this, "scope", void 0);
115
116 this.scope = scope;
117 }
118
119}
120class UnexpectedBuildError extends FatalError {
121 constructor(error, pkgName) {
122 super(`${util.format("", error).trim()}`, pkgName);
123 }
124
125}
126class FixableError extends FatalError {}
127
128let limit = pLimit(1); // there might be a simpler solution to this than using dataloader but it works so ¯\_(ツ)_/¯
129
130let prefix = `🎁 ${chalk.green("?")}`;
131function createPromptConfirmLoader(message) {
132 let loader = new DataLoader(pkgs => limit(() => (async () => {
133 if (pkgs.length === 1) {
134 let {
135 confirm
136 } = await inquirer.prompt([{
137 type: "confirm",
138 name: "confirm",
139 message,
140 prefix: prefix + " " + pkgs[0].name
141 }]);
142 return [confirm];
143 }
144
145 let {
146 answers
147 } = await inquirer.prompt([{
148 type: "checkbox",
149 name: "answers",
150 message,
151 choices: pkgs.map(pkg => ({
152 name: pkg.name,
153 checked: true
154 })),
155 prefix
156 }]);
157 return pkgs.map(pkg => {
158 return answers.includes(pkg.name);
159 });
160 })(), {
161 cache: false
162 }));
163 return pkg => loader.load(pkg);
164}
165let promptConfirm = async message => {
166 let {
167 confirm
168 } = await inquirer.prompt([{
169 type: "confirm",
170 name: "confirm",
171 message,
172 prefix: prefix
173 }]);
174 return confirm;
175};
176
177let doPromptInput = async (message, pkg, defaultAnswer) => {
178 let {
179 input
180 } = await inquirer.prompt([{
181 type: "input",
182 name: "input",
183 message,
184 prefix: prefix + " " + pkg.name,
185 default: defaultAnswer
186 }]);
187 return input;
188};
189
190let promptInput = (message, pkg, defaultAnswer) => limit(() => doPromptInput(message, pkg, defaultAnswer));
191
192function format(args, messageType, scope) {
193 let prefix = {
194 error: chalk.red("error"),
195 success: chalk.green("success"),
196 info: chalk.cyan("info")
197 }[messageType];
198 let fullPrefix = "🎁 " + prefix + (scope === undefined ? "" : " " + chalk.cyan(scope));
199 return fullPrefix + util.format("", ...args).split("\n").join("\n" + fullPrefix + " ");
200}
201function error(message, scope) {
202 console.error(format([message], "error", scope));
203}
204function success(message, scope) {
205 console.log(format([message], "success", scope));
206}
207function info(message, scope) {
208 console.log(format([message], "info", scope));
209}
210
211async function validateIncludedFiles(pkg) {
212 try {
213 await Promise.all(pkg.entrypoints.map(async entrypoint => {
214 let filename = path.join(entrypoint.directory, "dist", "preconstruct-test-file");
215 await fs.ensureFile(filename);
216 return fs.writeFile(filename, "test content");
217 }));
218 let result = await packlist({
219 path: pkg.directory
220 }); // check that we're including the package.json and main file
221 // TODO: add Flow and TS check and if they're ignored, don't write them
222
223 let messages = [];
224 pkg.entrypoints.forEach(entrypoint => {
225 let pkgJsonPath = path.relative(pkg.directory, path.resolve(entrypoint.directory, "package.json"));
226 let distFilePath = path.relative(pkg.directory, path.resolve(entrypoint.directory, "dist", "preconstruct-test-file"));
227 let entrypointName = path.relative(pkg.directory, entrypoint.directory);
228
229 if (!result.includes(pkgJsonPath)) {
230 messages.push(`the entrypoint ${chalk.cyan(entrypointName)} isn't included in the published files for this package, please add it to the files field in the package's package.json`);
231 } else if (!result.includes(distFilePath)) {
232 messages.push(`the dist directory ${entrypointName === "" ? "" : `for entrypoint ${chalk.cyan(entrypointName)} `}isn't included in the published files for this package, please add it to the files field in the package's package.json`);
233 }
234 });
235
236 if (messages.length) {
237 throw new FatalError(messages.join("\n"), pkg.name);
238 }
239 } finally {
240 await Promise.all(pkg.entrypoints.map(entrypoint => fs.remove(path.join(entrypoint.directory, "dist", "preconstruct-test-file"))));
241 }
242}
243
244let unsafeRequire = require;
245let askGlobalLimit = pLimit(1);
246class Project extends Item {
247 constructor(...args) {
248 super(...args);
249
250 _defineProperty(this, "packages", void 0);
251 }
252
253 get configPackages() {
254 return is(this._config.packages, is.default(is.arrayOf(is.string), ["."]));
255 } // probably gonna be irrelevant later but i want it for now
256
257
258 get isBolt() {
259 // we only want to return true when there is bolt config
260 // AND no yarn workspaces config
261 // because emotion has a bolt config and yarn workspaces
262 // and if you have both, you probably want workspaces
263 let hasBolt = !!this.json.bolt;
264 let hasYarnWorkspaces = !!this.json.workspaces;
265 return hasBolt && !hasYarnWorkspaces;
266 }
267
268 static async create(directory) {
269 let filePath = path.join(directory, "package.json");
270 let contents = await fs.readFile(filePath, "utf-8");
271 let project = new Project(filePath, contents);
272 project.packages = await project._packages();
273 return project;
274 }
275
276 get name() {
277 return is(this.json.name, is.string);
278 }
279
280 set name(name) {
281 this.json.name = name;
282 }
283
284 async _packages() {
285 // suport bolt later probably
286 // maybe lerna too though probably not
287 if (!this._config.packages && this.json.workspaces) {
288 let _workspaces;
289
290 if (Array.isArray(this.json.workspaces)) {
291 _workspaces = this.json.workspaces;
292 } else if (Array.isArray(this.json.workspaces.packages)) {
293 _workspaces = this.json.workspaces.packages;
294 }
295
296 let workspaces = is(_workspaces, is.arrayOf(is.string));
297 let packages = await promptInput("what packages should preconstruct build?", this, workspaces.join(","));
298 this._config.packages = packages.split(",");
299 await this.save();
300 }
301
302 try {
303 let filenames = await globby(this.configPackages, {
304 cwd: this.directory,
305 onlyDirectories: true,
306 absolute: true,
307 expandDirectories: false
308 });
309 let dirsWithoutPkgJson = [];
310 let lastErr;
311 let packages = await Promise.all(filenames.map(async x => {
312 try {
313 let pkg = await Package.create(x);
314 pkg.project = this;
315 return pkg;
316 } catch (err) {
317 if (err.code === "ENOENT" && err.path === path.join(x, "package.json")) {
318 lastErr = err;
319 dirsWithoutPkgJson.push(x);
320 return undefined;
321 }
322
323 throw err;
324 }
325 }));
326
327 if (dirsWithoutPkgJson.length) {
328 error("there are some package directories that do not have package.jsons\nthis is often caused by switching branches.\n\n" + dirsWithoutPkgJson.join("\n") + "\n");
329
330 if (!(await promptConfirm("would you like preconstruct to delete these directories automatically?"))) {
331 throw lastErr;
332 }
333
334 await Promise.all(dirsWithoutPkgJson.map(dir => fs.remove(dir)));
335 return this._packages();
336 }
337
338 await Promise.all(packages.map(pkg => validateIncludedFiles(pkg)));
339 return packages;
340 } catch (error) {
341 if (error instanceof is.AssertionError) {
342 return [];
343 }
344
345 throw error;
346 }
347 }
348
349 global(pkg) {
350 if (this._config.globals !== undefined && this._config.globals[pkg]) {
351 return this._config.globals[pkg];
352 } else {
353 try {
354 let pkgJson = unsafeRequire(resolveFrom(this.directory, path.join(pkg, "package.json")));
355
356 if (pkgJson && pkgJson[PKG_JSON_CONFIG_FIELD] && pkgJson[PKG_JSON_CONFIG_FIELD].umdName) {
357 return pkgJson[PKG_JSON_CONFIG_FIELD].umdName;
358 }
359 } catch (err) {
360 if (err.code !== "MODULE_NOT_FOUND") {
361 throw err;
362 }
363 }
364
365 throw askGlobalLimit(() => (async () => {
366 // if while we were waiting, that global was added, return
367 if (this._config.globals !== undefined && this._config.globals[pkg]) {
368 return;
369 }
370
371 let response = await promptInput(`What should the umdName of ${pkg} be?`, this);
372
373 this._addGlobal(pkg, response);
374
375 await this.save();
376 })());
377 }
378 }
379
380 _addGlobal(pkg, name) {
381 if (!this._config.globals) {
382 this._config.globals = {};
383 }
384
385 this._config.globals[pkg] = name;
386 }
387
388}
389
390let errors = {
391 noSource: source => `no source file was provided, please create a file at ${source} or specify a custom source file with the ${PKG_JSON_CONFIG_FIELD} source option`,
392 deniedWriteMainField: "changing the main field is required to build",
393 invalidModuleField: "module field is invalid",
394 invalidMainField: "main field is invalid",
395 invalidUmdMainField: "umd:main field is invalid",
396 invalidBrowserField: "browser field is invalid",
397 invalidReactNativeField: "react-native field is invalid",
398 umdNameNotSpecified: `the umd:main field is specified but a umdName option is not specified. please add it to the ${PKG_JSON_CONFIG_FIELD} field in your package.json`,
399 deniedWriteBrowserField: "building browser bundles for modules that include typeof" + " window or typeof" + " document is currently required",
400 noEntrypointPkgJson: "There is a missing package.json for an entrypoint",
401 noEntrypoints: "packages must have at least one entrypoint, this package has no entrypoints"
402};
403let confirms = {
404 writeMainField: createPromptConfirmLoader("preconstruct is going to change the main field in your package.json, are you okay with that?"),
405 writeModuleField: createPromptConfirmLoader("would you like to generate module builds? this will write to the module field in your package.json"),
406 fixModuleField: createPromptConfirmLoader("would you like to fix the module field?"),
407 fixUmdBuild: createPromptConfirmLoader("would you like to fix the umd field?"),
408 shouldInstallObjectAssign: createPromptConfirmLoader("Object.assign is polyfilled with object-assign to reduce bundle size when used with react. would you like to install object-assign automatically?"),
409 shouldInstallBabelRuntime: createPromptConfirmLoader("Babel helpers (functions inserted by babel transforms) should be imported from a @babel/runtime package (which has to be in your dependencies) to reduce bundle size. would you like to install @babel/runtime automatically?"),
410 addBrowserField: createPromptConfirmLoader("typeof" + " window or typeof" + " document is used in this package. would you like build seperate browser builds for better browser bundle sizes?"),
411 fixBrowserField: createPromptConfirmLoader("would you like to fix the browser build?"),
412 createEntrypointPkgJson: createPromptConfirmLoader("A package.json file does not exist for this entrypoint, would you like to create one automatically?")
413};
414let inputs = {
415 getUmdName: "what should the name used for UMD bundles be?"
416};
417let infos = {
418 validMainField: "main field is valid",
419 validModuleField: "module field is valid",
420 validUmdMainField: "umd:main field is valid",
421 validEntrypoint: "a valid entry point exists.",
422 validBrowserField: "browser field is valid",
423 validReactNativeField: "react-native field is valid",
424 validPackageEntrypoints: "package entrypoints are valid"
425};
426let successes = {
427 validProject: "project is valid!",
428 startedWatching: "started watching!"
429};
430
431function getNameForDist(name) {
432 return name.replace(/.*\//, "");
433}
434function getValidStringFieldContentForBuildType(type, pkgName) {
435 let safeName = getNameForDist(pkgName);
436
437 switch (type) {
438 case "main":
439 {
440 return `dist/${safeName}.cjs.js`;
441 }
442
443 case "module":
444 {
445 return `dist/${safeName}.esm.js`;
446 }
447
448 case "umd:main":
449 {
450 return `dist/${safeName}.umd.min.js`;
451 }
452 }
453
454 throw new Error(`unknown string build type: ${type}. this is likely a bug in preconstruct.`);
455}
456function getValidObjectFieldContentForBuildType(type, pkgName, hasModuleBuild) {
457 let safeName = getNameForDist(pkgName);
458
459 switch (type) {
460 case "browser":
461 {
462 let obj = {
463 [`./dist/${safeName}.cjs.js`]: `./dist/${safeName}.browser.cjs.js`
464 };
465
466 if (hasModuleBuild) {
467 obj[`./dist/${safeName}.esm.js`] = `./dist/${safeName}.browser.esm.js`;
468 }
469
470 return obj;
471 }
472
473 case "react-native":
474 {
475 let obj = {
476 [`./dist/${safeName}.cjs.js`]: `./dist/${safeName}.native.cjs.js`
477 };
478
479 if (hasModuleBuild) {
480 obj[`./dist/${safeName}.esm.js`] = `./dist/${safeName}.native.esm.js`;
481 }
482
483 return obj;
484 }
485 }
486
487 throw new Error(`unknown object build type: ${type}. this is likely a bug in preconstruct.`);
488}
489function flowTemplate(hasDefaultExport, relativePath) {
490 return `// @flow
491export * from "${relativePath}";${hasDefaultExport ? `\nexport { default } from "${relativePath}";` : ""}\n`;
492}
493function tsTemplate(hasDefaultExport, relativePath) {
494 return `export * from "${relativePath}";${hasDefaultExport ? `\nexport { default } from "${relativePath}";` : ""}\n`;
495}
496
497/*::
498import { Package } from "./package";
499*/
500
501let camelToPkgJsonField = {
502 main: "main",
503 module: "module",
504 umdMain: "umd:main",
505 browser: "browser",
506 reactNative: "react-native"
507};
508async function fixPackage(pkg) {
509 if (pkg.entrypoints.length === 0) {
510 throw new FatalError(errors.noEntrypoints, pkg.name);
511 }
512
513 let fields = {
514 main: true,
515 module: pkg.entrypoints.some(x => x.module),
516 umdMain: pkg.entrypoints.some(x => x.umdMain),
517 browser: pkg.entrypoints.some(x => x.browser),
518 reactNative: pkg.entrypoints.some(x => x.reactNative)
519 };
520 Object.keys(fields).filter(x => fields[x]).forEach(field => {
521 pkg.setFieldOnEntrypoints(field);
522 });
523 return (await Promise.all(pkg.entrypoints.map(x => x.save()))).some(x => x);
524}
525let unsafeRequire$1 = require;
526function validatePackage(pkg) {
527 if (pkg.entrypoints.length === 0) {
528 throw new FatalError(errors.noEntrypoints, pkg.name);
529 }
530
531 let fields = {
532 // main is intentionally not here, since it's always required
533 // it will be validated in validateEntrypoint and the case
534 // which this function validates will never happen
535 module: !!pkg.entrypoints[0].module,
536 umdMain: !!pkg.entrypoints[0].umdMain,
537 browser: !!pkg.entrypoints[0].browser,
538 reactNative: !!pkg.entrypoints[0].reactNative
539 };
540 pkg.entrypoints.forEach(entrypoint => {
541 Object.keys(fields).forEach(field => {
542 if ( // $FlowFixMe
543 entrypoint[field] && !fields[field]) {
544 throw new FixableError(`${pkg.entrypoints[0].name} has a ${camelToPkgJsonField[field]} build but ${entrypoint.name} does not have a ${camelToPkgJsonField[field]} build. Entrypoints in a package must either all have a particular build type or all not have a particular build type.`, pkg.name);
545 }
546
547 if ( // $FlowFixMe
548 !entrypoint[field] && fields[field]) {
549 throw new FixableError(`${entrypoint.name} has a ${camelToPkgJsonField[field]} build but ${pkg.entrypoints[0].name} does not have a ${camelToPkgJsonField[field]} build. Entrypoints in a package must either all have a particular build type or all not have a particular build type.`, pkg.name);
550 }
551 });
552 }); // TODO: do this well
553
554 if (fields.umdMain) {
555 // this is a sorta naive check
556 // but it's handling the most common case
557 // i don't think it's worth implementing this well at this exact moment
558 // because i'm guessing doing it well would cause more problems than it would solve
559 // this will likely change in the future
560 let sortaAllDeps = new Set([...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : []), ...(pkg.dependencies ? Object.keys(pkg.dependencies) : [])]);
561
562 for (let depName in pkg.dependencies) {
563 let depPkgJson = unsafeRequire$1(resolveFrom(pkg.directory, depName + "/package.json"));
564
565 if (depPkgJson.peerDependencies) {
566 for (let pkgName in depPkgJson.peerDependencies) {
567 if (!sortaAllDeps.has(pkgName)) {
568 throw new FatalError(`the package ${chalk.blue(pkg.name)} depends on ${chalk.blue(depName)} which has a peerDependency on ${chalk.blue(pkgName)} but ${chalk.blue(pkgName)} is not specified in the dependencies or peerDependencies of ${chalk.blue(pkg.name)}. please add ${chalk.blue(pkgName)} to the dependencies or peerDependencies of ${chalk.blue(pkg.name)}`, pkg.name);
569 }
570 }
571 }
572 }
573 }
574}
575
576// just does validation
577// used in build and watch
578
579function validateEntrypointSource(entrypoint) {
580 try {
581 if (!entrypoint.source.startsWith(entrypoint.package.directory)) {
582 throw new FatalError(`entrypoint source files must be inside their respective package directory but this entrypoint has specified its source file as ${entrypoint.configSource}`, entrypoint.name);
583 }
584 } catch (e) {
585 if (e.code === "MODULE_NOT_FOUND") {
586 throw new FatalError(errors.noSource(entrypoint.configSource), entrypoint.name);
587 }
588
589 throw e;
590 }
591}
592function isMainFieldValid(entrypoint) {
593 return entrypoint.main === getValidStringFieldContentForBuildType("main", entrypoint.package.name);
594}
595function isModuleFieldValid(entrypoint) {
596 return entrypoint.module === getValidStringFieldContentForBuildType("module", entrypoint.package.name);
597}
598function isUmdMainFieldValid(entrypoint) {
599 return entrypoint.umdMain === getValidStringFieldContentForBuildType("umd:main", entrypoint.package.name);
600}
601function isBrowserFieldValid(entrypoint) {
602 return equal(entrypoint.browser, getValidObjectFieldContentForBuildType("browser", entrypoint.package.name, entrypoint.module !== null));
603}
604function isReactNativeFieldValid(entrypoint) {
605 return equal(entrypoint.reactNative, getValidObjectFieldContentForBuildType("react-native", entrypoint.package.name, entrypoint.module !== null));
606}
607function isUmdNameSpecified(entrypoint) {
608 return typeof entrypoint._config.umdName === "string";
609}
610function validateEntrypoint(entrypoint, log) {
611 validateEntrypointSource(entrypoint);
612
613 if (log) {
614 info(infos.validEntrypoint, entrypoint.name);
615 }
616
617 if (!isMainFieldValid(entrypoint)) {
618 throw new FixableError(errors.invalidMainField, entrypoint.name);
619 }
620
621 if (log) {
622 info(infos.validMainField, entrypoint.name);
623 }
624
625 if (entrypoint.module !== null) {
626 if (isModuleFieldValid(entrypoint)) {
627 if (log) {
628 info(infos.validModuleField, entrypoint.name);
629 }
630 } else {
631 throw new FixableError(errors.invalidModuleField, entrypoint.name);
632 }
633 }
634
635 if (entrypoint.umdMain !== null) {
636 if (isUmdMainFieldValid(entrypoint)) {
637 if (isUmdNameSpecified(entrypoint)) {
638 if (log) {
639 info(infos.validUmdMainField, entrypoint.name);
640 }
641 } else {
642 throw new FixableError(errors.umdNameNotSpecified, entrypoint.name);
643 }
644 } else {
645 throw new FixableError(errors.invalidUmdMainField, entrypoint.name);
646 }
647 }
648
649 if (entrypoint.browser !== null) {
650 if (typeof entrypoint.browser === "string" || !isBrowserFieldValid(entrypoint)) {
651 throw new FixableError(errors.invalidBrowserField, entrypoint.name);
652 } else if (log) {
653 info(infos.validBrowserField, entrypoint.name);
654 }
655 }
656
657 if (entrypoint.reactNative !== null) {
658 if (typeof entrypoint.reactNative === "string" || !isReactNativeFieldValid(entrypoint)) {
659 throw new FixableError(errors.invalidReactNativeField, entrypoint.name);
660 } else if (log) {
661 info(infos.validReactNativeField, entrypoint.name);
662 }
663 }
664}
665async function validate(directory) {
666 let project = await Project.create(directory);
667
668 for (let pkg of project.packages) {
669 validatePackage(pkg);
670
671 for (let entrypoint of pkg.entrypoints) {
672 validateEntrypoint(entrypoint, true);
673 }
674
675 info(infos.validPackageEntrypoints, pkg.name);
676 }
677
678 success(successes.validProject);
679}
680
681let fields = ["version", "description", "main", "module", "umd:main", "browser", "react-native"];
682
683function setFieldInOrder(obj, field, value) {
684 if (field in obj) {
685 return _objectSpread({}, obj, {
686 [field]: value
687 });
688 }
689
690 let fieldIndex = fields.indexOf(field);
691 let idealField = fields.slice(0, fieldIndex).reverse().find(key => {
692 return key in obj;
693 });
694
695 if (idealField === undefined) {
696 return _objectSpread({}, obj, {
697 [field]: value
698 });
699 }
700
701 let newObj = {};
702
703 for (let key in obj) {
704 newObj[key] = obj[key];
705
706 if (key === idealField) {
707 newObj[field] = value;
708 }
709 }
710
711 return newObj;
712}
713/*::
714import { Package } from './package'
715*/
716
717
718class Entrypoint extends Item {
719 constructor(filePath, contents, pkg) {
720 super(filePath, contents);
721
722 _defineProperty(this, "package", void 0);
723
724 _defineProperty(this, "_strict", void 0);
725
726 this.package = pkg;
727 }
728
729 get name() {
730 return path.join(this.package.name, path.relative(this.package.directory, this.directory));
731 }
732
733 get main() {
734 return is(this.json.main, is.maybe(is.string));
735 }
736
737 set main(path) {
738 this.json = setFieldInOrder(this.json, "main", path);
739 }
740
741 get module() {
742 return is(this.json.module, is.maybe(is.string));
743 }
744
745 set module(path) {
746 this.json = setFieldInOrder(this.json, "module", path);
747 }
748
749 get browser() {
750 return is(this.json.browser, is.maybe(is.either(is.string, is.objectOf(is.string))));
751 }
752
753 set browser(option) {
754 this.json = setFieldInOrder(this.json, "browser", option);
755 }
756
757 get reactNative() {
758 return is(this.json["react-native"], is.maybe(is.either(is.string, is.objectOf(is.string))));
759 }
760
761 set reactNative(option) {
762 this.json = setFieldInOrder(this.json, "react-native", option);
763 }
764
765 get umdMain() {
766 return is(this.json["umd:main"], is.maybe(is.string));
767 }
768
769 set umdMain(path) {
770 this.json = setFieldInOrder(this.json, "umd:main", path);
771 }
772
773 get configSource() {
774 return is(this._config.source, is.default(is.string, "src/index"));
775 }
776
777 get source() {
778 return resolve.sync(path.join(this.directory, this.configSource), {
779 extensions: EXTENSIONS
780 });
781 }
782
783 get umdName() {
784 return is(this._config.umdName, is.maybe(is.string));
785 }
786
787 set umdName(umdName) {
788 if (umdName === null) {
789 delete this._config.umdName;
790 } else {
791 this._config.umdName = umdName;
792 }
793 }
794
795 strict() {
796 if (!this._strict) {
797 validatePackage(this.package);
798 validateEntrypoint(this, false);
799 this._strict = new StrictEntrypoint(this.path, this._contents, this.package);
800 }
801
802 return this._strict;
803 }
804
805}
806class StrictEntrypoint extends Entrypoint {
807 get main() {
808 return is(this.json.main, is.string);
809 }
810
811 set main(path) {
812 this.json = setFieldInOrder(this.json, "main", path);
813 }
814
815 get browser() {
816 return is(this.json.browser, is.maybe(is.objectOf(is.string)));
817 }
818
819 set browser(option) {
820 this.json = setFieldInOrder(this.json, "browser", option);
821 }
822
823 get reactNative() {
824 return is(this.json["react-native"], is.maybe(is.objectOf(is.string)));
825 }
826
827 set reactNative(option) {
828 this.json = setFieldInOrder(this.json, "react-native", option);
829 }
830
831 updater(json) {
832 super.updater(json);
833 validatePackage(this.package);
834 validateEntrypoint(this, false);
835 }
836
837 strict() {
838 return this;
839 }
840
841}
842
843/*::
844import {Project} from './project'
845*/
846
847class Package extends Item {
848 constructor(...args) {
849 super(...args);
850
851 _defineProperty(this, "project", void 0);
852
853 _defineProperty(this, "entrypoints", void 0);
854 }
855
856 get configEntrypoints() {
857 return is(this._config.entrypoints, is.default(is.arrayOf(is.string), ["."]));
858 }
859
860 static async create(directory) {
861 let filePath = path.join(directory, "package.json");
862 let contents = await fs.readFile(filePath, "utf-8");
863 let pkg = new Package(filePath, contents);
864 let entrypointDirectories = await globby(pkg.configEntrypoints, {
865 cwd: pkg.directory,
866 onlyDirectories: true,
867 absolute: true,
868 expandDirectories: false
869 });
870 pkg.entrypoints = await Promise.all(entrypointDirectories.map(async directory => {
871 let filename = path.join(directory, "package.json");
872 let contents = null;
873
874 try {
875 contents = await fs.readFile(filename, "utf-8");
876 } catch (e) {
877 if (e.code !== "ENOENT") {
878 throw e;
879 }
880 }
881
882 return {
883 filename,
884 contents
885 };
886 })).then(descriptors => {
887 let getPlainEntrypointContent = () => {
888 let plainEntrypointObj = {
889 main: getValidStringFieldContentForBuildType("main", pkg.name)
890 };
891
892 for (let descriptor of descriptors) {
893 if (descriptor.contents !== null) {
894 let parsed = JSON.parse(descriptor.contents);
895
896 for (let field of ["module", "umd:main"]) {
897 if (parsed[field] !== undefined) {
898 plainEntrypointObj[field] = getValidStringFieldContentForBuildType(field, pkg.name);
899 }
900 }
901
902 for (let field of ["browser", "react-native"]) {
903 if (parsed[field] !== undefined) {
904 plainEntrypointObj[field] = getValidObjectFieldContentForBuildType(field, pkg.name, plainEntrypointObj.module !== undefined);
905 }
906 }
907 }
908 }
909
910 let plainEntrypointContents = JSON.stringify(plainEntrypointObj);
911
912 getPlainEntrypointContent = () => plainEntrypointContents;
913
914 return plainEntrypointContents;
915 };
916
917 return Promise.all(descriptors.map(async ({
918 filename,
919 contents
920 }) => {
921 if (contents === null) {
922 let shouldCreateEntrypointPkgJson = await confirms.createEntrypointPkgJson({
923 name: path.join(pkg.name, path.relative(pkg.directory, directory))
924 });
925
926 if (!shouldCreateEntrypointPkgJson) {
927 throw new FatalError(errors.noEntrypointPkgJson, path.join(pkg.name, path.relative(pkg.directory, directory)));
928 }
929
930 contents = getPlainEntrypointContent();
931 await fs.writeFile(filename, contents);
932 }
933
934 return new Entrypoint(filename, contents, pkg);
935 }));
936 });
937 return pkg;
938 }
939
940 setFieldOnEntrypoints(field) {
941 this.entrypoints.forEach(entrypoint => {
942 switch (field) {
943 case "main":
944 {
945 entrypoint.main = getValidStringFieldContentForBuildType("main", this.name);
946 break;
947 }
948
949 case "module":
950 {
951 entrypoint.module = getValidStringFieldContentForBuildType("module", this.name);
952 break;
953 }
954
955 case "browser":
956 {
957 entrypoint.browser = getValidObjectFieldContentForBuildType("browser", this.name, entrypoint.module !== null);
958 break;
959 }
960
961 case "umdMain":
962 {
963 entrypoint.umdMain = getValidStringFieldContentForBuildType("umd:main", this.name);
964 break;
965 }
966
967 case "reactNative":
968 {
969 entrypoint.reactNative = getValidObjectFieldContentForBuildType("react-native", this.name, entrypoint.module !== null);
970 break;
971 }
972 }
973 });
974 }
975
976 get name() {
977 return is(this.json.name, is.string);
978 }
979
980 set name(name) {
981 this.json.name = name;
982 }
983
984 get dependencies() {
985 return is(this.json.dependencies, is.maybe(is.objectOf(is.string)));
986 }
987
988 get peerDependencies() {
989 return is(this.json.peerDependencies, is.maybe(is.objectOf(is.string)));
990 }
991
992}
993
994async function doInit(pkg) {
995 pkg.entrypoints.forEach(entrypoint => {
996 validateEntrypointSource(entrypoint);
997 });
998
999 if (pkg.entrypoints.every(entrypoint => isMainFieldValid(entrypoint))) {
1000 info(infos.validMainField, pkg.name);
1001 } else {
1002 let canWriteMainField = await confirms.writeMainField(pkg);
1003
1004 if (!canWriteMainField) {
1005 throw new FatalError(errors.deniedWriteMainField, pkg.name);
1006 }
1007
1008 pkg.setFieldOnEntrypoints("main");
1009 }
1010
1011 let allEntrypointsAreMissingAModuleField = pkg.entrypoints.every(entrypoint => entrypoint.module === null);
1012 let someEntrypointsAreNotValid = pkg.entrypoints.some(entrypoint => !isModuleFieldValid(entrypoint));
1013
1014 if (allEntrypointsAreMissingAModuleField || someEntrypointsAreNotValid) {
1015 let canWriteModuleField = await confirms.writeModuleField(pkg);
1016
1017 if (canWriteModuleField) {
1018 pkg.setFieldOnEntrypoints("module");
1019 } else if (!allEntrypointsAreMissingAModuleField) {
1020 throw new FixableError(errors.invalidModuleField, pkg.name);
1021 }
1022 } else {
1023 info(infos.validModuleField, pkg.name);
1024 }
1025
1026 let someEntrypointsHaveAMaybeInvalidUmdBuild = pkg.entrypoints.some(entrypoint => entrypoint.umdMain !== null);
1027 let someUmdMainFieldsAreInvalid = pkg.entrypoints.some(entrypoint => !isUmdMainFieldValid(entrypoint));
1028 let someUmdNamesAreNotSpecified = pkg.entrypoints.some(entrypoint => !isUmdNameSpecified(entrypoint));
1029
1030 if (someEntrypointsHaveAMaybeInvalidUmdBuild && (someUmdMainFieldsAreInvalid || someUmdNamesAreNotSpecified)) {
1031 let shouldWriteUMDBuilds = await confirms.fixUmdBuild(pkg);
1032
1033 if (shouldWriteUMDBuilds) {
1034 pkg.setFieldOnEntrypoints("umdMain");
1035
1036 for (let entrypoint of pkg.entrypoints) {
1037 let umdName = await promptInput(inputs.getUmdName, entrypoint);
1038 entrypoint.umdName = umdName;
1039 }
1040 } else {
1041 throw new FixableError(errors.invalidUmdMainField, pkg.name);
1042 }
1043 }
1044
1045 let someEntrypointsHaveABrowserField = pkg.entrypoints.some(entrypoint => entrypoint.browser !== null);
1046 let someEntrypointsHaveAnInvalidBrowserField = pkg.entrypoints.some(entrypoint => !isBrowserFieldValid(entrypoint));
1047
1048 if (someEntrypointsHaveABrowserField && someEntrypointsHaveAnInvalidBrowserField) {
1049 let shouldFixBrowserField = await confirms.fixBrowserField(pkg);
1050
1051 if (shouldFixBrowserField) {
1052 pkg.setFieldOnEntrypoints("browser");
1053 } else {
1054 throw new FixableError(errors.invalidBrowserField, pkg.name);
1055 }
1056 }
1057
1058 await Promise.all(pkg.entrypoints.map(x => x.save()));
1059}
1060
1061async function init(directory) {
1062 let project = await Project.create(directory);
1063 await Promise.all(project.packages.map(doInit));
1064 success("initialised project!");
1065}
1066
1067const pattern = /require\((["'])@babel\/runtime\/helpers\/esm\/(\w+)["']\)/g;
1068function rewriteCjsRuntimeHelpers() {
1069 return {
1070 name: "rewrite-cjs-runtime-helpers",
1071
1072 renderChunk(code, chunkInfo, {
1073 format
1074 }) {
1075 if (format !== "cjs") {
1076 return null;
1077 }
1078
1079 return code.replace(pattern, (_, quote, path) => {
1080 return `require(${quote}@babel/runtime/helpers/${path}${quote})`;
1081 });
1082 }
1083
1084 };
1085}
1086
1087function getDevPath(cjsPath) {
1088 return cjsPath.replace(/\.js$/, ".dev.js");
1089}
1090function getProdPath(cjsPath) {
1091 return cjsPath.replace(/\.js$/, ".prod.js");
1092}
1093
1094function flowAndNodeDevProdEntry(pkg) {
1095 return {
1096 name: "flow-and-prod-dev-entry",
1097
1098 async resolveId(source, importer) {
1099 let resolved = await this.resolve(source, importer, {
1100 skipSelf: true
1101 });
1102
1103 if (resolved.id.startsWith("\0") || resolved.id.startsWith(pkg.directory)) {
1104 return resolved;
1105 }
1106
1107 throw new FatalError(`all relative imports in a package should only import modules inside of their package directory but "${path.relative(pkg.directory, importer)}" is importing "${source}"`, pkg.name);
1108 },
1109
1110 // eslint-disable-next-line no-unused-vars
1111 async generateBundle(opts, bundle, something) {
1112 for (const n in bundle) {
1113 const file = bundle[n]; // $FlowFixMe
1114
1115 let facadeModuleId = file.facadeModuleId;
1116
1117 if (file.isAsset || !file.isEntry || facadeModuleId == null) {
1118 continue;
1119 }
1120
1121 let mainFieldPath = file.fileName.replace(/\.prod\.js$/, ".js");
1122 let relativeToSource = path.relative(path.dirname(path.join(opts.dir, file.fileName)), facadeModuleId);
1123 let isEntrySourceTypeScript = /\.tsx?$/.test(facadeModuleId);
1124
1125 if (!isEntrySourceTypeScript) {
1126 let flowMode = false;
1127 let source = await fs.readFile(facadeModuleId, "utf8");
1128
1129 if (source.includes("@flow")) {
1130 flowMode = file.exports.includes("default") ? "all" : "named";
1131 }
1132
1133 if (flowMode !== false) {
1134 let flowFileSource = flowTemplate(flowMode === "all", relativeToSource);
1135 let flowFileName = mainFieldPath + ".flow";
1136 bundle[flowFileName] = {
1137 fileName: flowFileName,
1138 isAsset: true,
1139 source: flowFileSource
1140 };
1141 }
1142 }
1143
1144 let mainEntrySource = `'use strict';
1145
1146if (${// tricking static analysis is fun...
1147 "process" + ".env.NODE_ENV"} === "production") {
1148 module.exports = require("./${path.basename(getProdPath(mainFieldPath))}");
1149} else {
1150 module.exports = require("./${path.basename(getDevPath(mainFieldPath))}");
1151}\n`;
1152 bundle[mainFieldPath] = {
1153 fileName: mainFieldPath,
1154 isAsset: true,
1155 source: mainEntrySource
1156 };
1157 }
1158 }
1159
1160 };
1161}
1162
1163function normalize(fileName) {
1164 return fileName.split("\\").join("/");
1165}
1166let createLanguageServiceHostClass = typescript => class LanguageServiceHost {
1167 constructor(parsedConfig, transformers) {
1168 this.parsedConfig = parsedConfig;
1169 this.transformers = transformers;
1170 this.cwd = process.cwd();
1171 this.snapshots = {};
1172 this.versions = {};
1173 this.fileNames = new Set(parsedConfig.fileNames);
1174 }
1175
1176 reset() {
1177 this.snapshots = {};
1178 this.versions = {};
1179 }
1180
1181 setLanguageService(service) {
1182 this.service = service;
1183 }
1184
1185 getProjectVersion() {
1186 return 1;
1187 }
1188
1189 setSnapshot(fileName, data) {
1190 fileName = normalize(fileName);
1191 const snapshot = typescript.ScriptSnapshot.fromString(data);
1192 this.snapshots[fileName] = snapshot;
1193 this.versions[fileName] = (this.versions[fileName] || 0) + 1;
1194 this.fileNames.add(fileName);
1195 return snapshot;
1196 }
1197
1198 getScriptSnapshot(fileName) {
1199 fileName = normalize(fileName);
1200 if (this.snapshots[fileName]) return this.snapshots[fileName];
1201
1202 if (fs$1.existsSync(fileName)) {
1203 this.snapshots[fileName] = typescript.ScriptSnapshot.fromString(typescript.sys.readFile(fileName));
1204 this.versions[fileName] = (this.versions[fileName] || 0) + 1;
1205 return this.snapshots[fileName];
1206 }
1207
1208 return undefined;
1209 }
1210
1211 getCurrentDirectory() {
1212 return this.cwd;
1213 }
1214
1215 getScriptVersion(fileName) {
1216 fileName = normalize(fileName);
1217 return (this.versions[fileName] || 0).toString();
1218 }
1219
1220 getScriptFileNames() {
1221 return Array.from(this.fileNames.values());
1222 }
1223
1224 getCompilationSettings() {
1225 return this.parsedConfig.options;
1226 }
1227
1228 getDefaultLibFileName(opts) {
1229 return typescript.getDefaultLibFilePath(opts);
1230 }
1231
1232 useCaseSensitiveFileNames() {
1233 return typescript.sys.useCaseSensitiveFileNames;
1234 }
1235
1236 readDirectory(path, extensions, exclude, include) {
1237 return typescript.sys.readDirectory(path, extensions, exclude, include);
1238 }
1239
1240 readFile(path, encoding) {
1241 return typescript.sys.readFile(path, encoding);
1242 }
1243
1244 fileExists(path) {
1245 return typescript.sys.fileExists(path);
1246 }
1247
1248 getTypeRootsVersion() {
1249 return 0;
1250 }
1251
1252 directoryExists(directoryName) {
1253 return typescript.sys.directoryExists(directoryName);
1254 }
1255
1256 getDirectories(directoryName) {
1257 return typescript.sys.getDirectories(directoryName);
1258 }
1259
1260 getCustomTransformers() {
1261 return undefined;
1262 }
1263
1264};
1265
1266let unsafeRequire$2 = require;
1267
1268let weakMemoize = function (func) {
1269 // $FlowFixMe flow doesn't include all non-primitive types as allowed for weakmaps
1270 let cache = new WeakMap();
1271 return arg => {
1272 if (cache.has(arg)) {
1273 // $FlowFixMe
1274 return cache.get(arg);
1275 }
1276
1277 let ret = func(arg);
1278 cache.set(arg, ret);
1279 return ret;
1280 };
1281};
1282
1283function memoize(fn) {
1284 const cache = {};
1285 return arg => {
1286 if (cache[arg] === undefined) cache[arg] = fn(arg);
1287 return cache[arg];
1288 };
1289}
1290
1291let getService = weakMemoize(typescript => memoize(async configFileName => {
1292 let configFileContents = await fs.readFile(configFileName, "utf8");
1293 const result = typescript.parseConfigFileTextToJson(configFileName, configFileContents);
1294 let thing = typescript.parseJsonConfigFileContent(result, typescript.sys, process.cwd(), undefined, configFileName);
1295 let LanguageServiceHostClass = createLanguageServiceHostClass(typescript);
1296 let servicesHost = new LanguageServiceHostClass(thing, []);
1297 let service = typescript.createLanguageService(servicesHost, typescript.createDocumentRegistry());
1298 servicesHost.setLanguageService(service);
1299 return {
1300 service,
1301 options: thing.options
1302 };
1303}));
1304async function createDeclarationCreator(dirname) {
1305 let typescript;
1306
1307 try {
1308 typescript = unsafeRequire$2(resolveFrom(dirname, "typescript"));
1309 } catch (err) {
1310 if (err.code === "MODULE_NOT_FOUND") {
1311 throw new Error("an entrypoint source file ends with the .ts or .tsx extension but the typescript module could not be resolved from the project directory, please install it.");
1312 }
1313
1314 throw err;
1315 }
1316
1317 let configFileName = typescript.findConfigFile(dirname, typescript.sys.fileExists);
1318
1319 if (!configFileName) {
1320 throw new Error("an entrypoint source file ends with the .ts extension but no TypeScript config exists, please create one.");
1321 }
1322
1323 let {
1324 service,
1325 options
1326 } = await getService(typescript)(configFileName);
1327 let moduleResolutionCache = typescript.createModuleResolutionCache(dirname, x => x, options);
1328 return {
1329 getDeps: entrypoints => {
1330 let program = service.getProgram();
1331
1332 if (!program) {
1333 throw new Error("This is an internal error, please open an issue if you see this: program not found");
1334 }
1335
1336 let resolvedEntrypointPaths = entrypoints.map(x => {
1337 let {
1338 resolvedModule
1339 } = typescript.resolveModuleName(path.join(path.dirname(x), path.basename(x, path.extname(x))), dirname, options, typescript.sys, moduleResolutionCache);
1340
1341 if (!resolvedModule) {
1342 throw new Error("This is an internal error, please open an issue if you see this: ts could not resolve module");
1343 }
1344
1345 return resolvedModule.resolvedFileName;
1346 });
1347 let allDeps = new Set(resolvedEntrypointPaths);
1348
1349 function searchDeps(deps) {
1350 for (let dep of deps) {
1351 let sourceFile = program.getSourceFile(dep);
1352
1353 if (!sourceFile) {
1354 throw new Error("This is an internal error, please open an issue if you see this: source file not found");
1355 }
1356
1357 let internalDeps = new Set();
1358
1359 for (let _ref of sourceFile.imports) {
1360 let {
1361 text
1362 } = _ref;
1363 let {
1364 resolvedModule
1365 } = typescript.resolveModuleName(text, dep, options, typescript.sys, moduleResolutionCache);
1366
1367 if (resolvedModule) {
1368 if (!allDeps.has(resolvedModule.resolvedFileName) && !resolvedModule.isExternalLibraryImport && resolvedModule.resolvedFileName.includes(dirname)) {
1369 internalDeps.add(resolvedModule.resolvedFileName);
1370 allDeps.add(resolvedModule.resolvedFileName);
1371 }
1372 }
1373 }
1374
1375 searchDeps(internalDeps);
1376 }
1377 }
1378
1379 searchDeps(new Set(resolvedEntrypointPaths));
1380 return allDeps;
1381 },
1382 getDeclarationFile: async filename => {
1383 if (filename.endsWith(".d.ts")) {
1384 return {
1385 name: filename.replace(dirname, path.join(dirname, "dist", "declarations")),
1386 content: await fs.readFile(filename, "utf8")
1387 };
1388 }
1389
1390 let output = service.getEmitOutput(filename, true);
1391 return {
1392 name: output.outputFiles[0].name.replace(dirname, path.join(dirname, "dist", "declarations")),
1393 content: output.outputFiles[0].text
1394 };
1395 }
1396 };
1397}
1398
1399let isTsPath = source => /\.tsx?/.test(source);
1400
1401function typescriptDeclarations(pkg) {
1402 if (!pkg.entrypoints.some(({
1403 source
1404 }) => isTsPath(source))) {
1405 return {
1406 name: "typescript-declarations"
1407 };
1408 }
1409
1410 return {
1411 name: "typescript-declarations",
1412
1413 // eslint-disable-next-line no-unused-vars
1414 async generateBundle(opts, bundle, something) {
1415 let creator = await createDeclarationCreator(pkg.directory);
1416 let srcFilenameToDtsFilenameMap = new Map();
1417 let deps = creator.getDeps(pkg.entrypoints.map(x => x.source));
1418 await Promise.all([...deps].map(async dep => {
1419 let {
1420 name,
1421 content
1422 } = await creator.getDeclarationFile(dep);
1423 srcFilenameToDtsFilenameMap.set(dep, name);
1424 bundle[name] = {
1425 fileName: name,
1426 isAsset: true,
1427 source: content
1428 };
1429 }));
1430
1431 for (const n in bundle) {
1432 const file = bundle[n]; // $FlowFixMe
1433
1434 let facadeModuleId = file.facadeModuleId;
1435
1436 if (file.isAsset || !file.isEntry || facadeModuleId == null) {
1437 continue;
1438 }
1439
1440 let dtsFilename = srcFilenameToDtsFilenameMap.get(facadeModuleId);
1441
1442 if (!dtsFilename) {
1443 throw new FatalError(`no .d.ts file was found for the entrypoint at ${facadeModuleId}`, pkg.name);
1444 }
1445
1446 let mainFieldPath = file.fileName.replace(/\.prod\.js$/, "");
1447 let relativeToSource = path.relative(path.dirname(path.join(opts.dir, file.fileName)), dtsFilename.replace(/\.d\.ts$/, ""));
1448
1449 if (!relativeToSource.startsWith(".")) {
1450 relativeToSource = `./${relativeToSource}`;
1451 }
1452
1453 let tsFileSource = tsTemplate(file.exports.includes("default"), relativeToSource);
1454 let tsFileName = mainFieldPath + ".d.ts";
1455 bundle[tsFileName] = {
1456 fileName: tsFileName,
1457 isAsset: true,
1458 source: tsFileSource
1459 };
1460 }
1461 }
1462
1463 };
1464}
1465
1466let shouldUseWorker = process.env.DISABLE_PRECONSTRUCT_WORKER !== "true";
1467let worker;
1468let unsafeRequire$3 = require;
1469function createWorker() {
1470 if (shouldUseWorker) {
1471 worker = new Worker(require.resolve("preconstruct/worker"));
1472 } else {
1473 worker = unsafeRequire$3("preconstruct/worker");
1474 }
1475}
1476function destroyWorker() {
1477 if (worker !== undefined && shouldUseWorker) {
1478 worker.end();
1479 worker = undefined;
1480 }
1481}
1482function getWorker() {
1483 if (worker === undefined) {
1484 throw new Error("worker not defined");
1485 }
1486
1487 return worker;
1488}
1489
1490const regExpCharactersRegExp = /[\\^$.*+?()[\]{}|]/g;
1491
1492const escapeRegExpCharacters = str => str.replace(regExpCharactersRegExp, "\\$&");
1493
1494const unpackOptions = (_ref = {}) => {
1495 let {
1496 extensions = babel.DEFAULT_EXTENSIONS,
1497 // rollup uses sourcemap, babel uses sourceMaps
1498 // just normalize them here so people don't have to worry about it
1499 sourcemap = true,
1500 sourcemaps = true,
1501 sourceMap = true,
1502 sourceMaps = true
1503 } = _ref,
1504 rest = _objectWithoutProperties(_ref, ["extensions", "sourcemap", "sourcemaps", "sourceMap", "sourceMaps"]);
1505
1506 return _objectSpread({
1507 extensions,
1508 plugins: [],
1509 sourceMaps: sourcemap && sourcemaps && sourceMap && sourceMaps
1510 }, rest, {
1511 caller: _objectSpread({
1512 name: "rollup-plugin-babel",
1513 supportsStaticESM: true,
1514 supportsDynamicImport: true
1515 }, rest.caller)
1516 });
1517};
1518
1519const lru = new QuickLRU({
1520 maxSize: 1000
1521});
1522let hasher;
1523let hasherPromise = initHasher().then(({
1524 h64
1525}) => {
1526 hasher = h64;
1527});
1528
1529let rollupPluginBabel = pluginOptions => {
1530 const _unpackOptions = unpackOptions(pluginOptions),
1531 {
1532 exclude,
1533 extensions,
1534 include
1535 } = _unpackOptions,
1536 babelOptions = _objectWithoutProperties(_unpackOptions, ["exclude", "extensions", "include"]);
1537
1538 const extensionRegExp = new RegExp(`(${extensions.map(escapeRegExpCharacters).join("|")})$`);
1539 const includeExcludeFilter = rollupPluginutils.createFilter(include, exclude);
1540
1541 const filter = id => extensionRegExp.test(id) && includeExcludeFilter(id);
1542
1543 return {
1544 name: "babel",
1545
1546 transform(code, filename) {
1547 if (!filter(filename)) return Promise.resolve(null);
1548 let hash = hasher(filename);
1549
1550 if (lru.has(hash)) {
1551 let cachedResult = lru.get(hash);
1552
1553 if (code === cachedResult.code) {
1554 return cachedResult.promise;
1555 }
1556 }
1557
1558 let options = JSON.stringify(_objectSpread({}, babelOptions, {
1559 filename
1560 }));
1561 let promise = getWorker().transformBabel(code, options);
1562 lru.set(hash, {
1563 code,
1564 promise
1565 });
1566 return promise;
1567 }
1568
1569 };
1570};
1571
1572function terser(userOptions = {}) {
1573 if (userOptions.sourceMap != null) {
1574 throw Error("sourceMap option is removed, use sourcemap instead");
1575 }
1576
1577 return {
1578 name: "terser",
1579
1580 renderChunk(code, chunk, outputOptions) {
1581 // TODO rewrite with object spread after node6 drop
1582 const normalizedOptions = _objectSpread({}, userOptions, {
1583 sourceMap: userOptions.sourcemap !== false,
1584 module: outputOptions.format === "es" || outputOptions.format === "esm"
1585 });
1586
1587 if (normalizedOptions.hasOwnProperty("sourcemap")) {
1588 delete normalizedOptions["sourcemap"];
1589 }
1590
1591 const result = getWorker().transformTerser(code, JSON.stringify(normalizedOptions)).catch(error => {
1592 const {
1593 message,
1594 line,
1595 col: column
1596 } = error;
1597 console.error(codeFrame.codeFrameColumns(code, {
1598 start: {
1599 line,
1600 column
1601 }
1602 }, {
1603 message
1604 }));
1605 throw error;
1606 });
1607 return result;
1608 }
1609
1610 };
1611}
1612
1613const makeExternalPredicate = externalArr => {
1614 if (externalArr.length === 0) {
1615 return () => false;
1616 }
1617
1618 const pattern = new RegExp(`^(${externalArr.join("|")})($|/)`);
1619 return id => pattern.test(id);
1620};
1621
1622let rollup = rollup$1.rollup;
1623function toUnsafeRollupConfig(config) {
1624 return config;
1625}
1626let getRollupConfig = (pkg, entrypoints, aliases, type) => {
1627 let external = [];
1628
1629 if (pkg.peerDependencies) {
1630 external.push(...Object.keys(pkg.peerDependencies));
1631 }
1632
1633 if (pkg.dependencies && type !== "umd") {
1634 external.push(...Object.keys(pkg.dependencies));
1635 }
1636
1637 if (type === "node-dev" || type === "node-prod") {
1638 external.push(...builtInModules);
1639 }
1640
1641 let rollupAliases = {};
1642 Object.keys(aliases).forEach(key => {
1643 try {
1644 rollupAliases[key] = resolveFrom(pkg.directory, aliases[key]);
1645 } catch (err) {
1646 if (err.code !== "MODULE_NOT_FOUND") {
1647 throw err;
1648 }
1649 }
1650 });
1651 let input = {};
1652 entrypoints.forEach(entrypoint => {
1653 input[path.relative(pkg.directory, path.join(entrypoint.directory, "dist", getNameForDist(pkg.name)))] = entrypoint.strict().source;
1654 });
1655 const config = {
1656 input,
1657 external: makeExternalPredicate(external),
1658 onwarn: warning => {
1659 switch (warning.code) {
1660 case "EMPTY_BUNDLE":
1661 case "CIRCULAR_DEPENDENCY":
1662 case "UNUSED_EXTERNAL_IMPORT":
1663 {
1664 break;
1665 }
1666
1667 case "UNRESOLVED_IMPORT":
1668 {
1669 if (/^@babel\/runtime\/helpers\//.test(warning.source)) {
1670 throw (async () => {
1671 let shouldInstallBabelRuntime = await confirms.shouldInstallBabelRuntime(pkg);
1672
1673 if (shouldInstallBabelRuntime) {
1674 await limit(() => installPackages({
1675 packages: ["@babel/runtime"],
1676 cwd: pkg.directory,
1677 installPeers: false,
1678 packageManager: pkg.project.isBolt ? "bolt" : undefined
1679 }));
1680 await pkg.refresh();
1681 } else {
1682 throw new FatalError(`@babel/runtime should be in dependencies of ${pkg.name}`, pkg.name);
1683 }
1684 })();
1685 }
1686
1687 if (!warning.source.startsWith(".")) {
1688 throw new FatalError(`"${warning.source}" is imported by "${path.relative(pkg.directory, warning.importer)}" but it is not specified in dependencies or peerDependencies`, pkg.name);
1689 }
1690 }
1691
1692 default:
1693 {
1694 throw new FatalError(`There was an error compiling ${pkg.name}: ${chalk.red(warning.toString())}`, pkg.name);
1695 }
1696 }
1697 },
1698 plugins: [type === "node-prod" && flowAndNodeDevProdEntry(pkg), type === "node-prod" && typescriptDeclarations(pkg), rollupPluginBabel({
1699 cwd: pkg.project.directory,
1700 plugins: [[require.resolve("@babel/plugin-transform-runtime"), {
1701 useESModules: true
1702 }]],
1703 extensions: EXTENSIONS
1704 }), type === "umd" && cjs({
1705 include: ["**/node_modules/**", "node_modules/**"]
1706 }), (type === "browser" || type === "umd") && replace({
1707 ["typeof " + "document"]: JSON.stringify("object"),
1708 ["typeof " + "window"]: JSON.stringify("object")
1709 }), rewriteCjsRuntimeHelpers(), json({
1710 namedExports: false
1711 }), type === "umd" && alias(rollupAliases), resolve$1({
1712 extensions: EXTENSIONS,
1713 customResolveOptions: {
1714 moduleDirectory: type === "umd" ? "node_modules" : []
1715 }
1716 }), (type === "umd" || type === "node-prod") && replace({
1717 // tricking static analysis is fun...
1718 ["process" + ".env.NODE_ENV"]: '"production"'
1719 }), type === "umd" && terser(), type === "node-prod" && terser({
1720 mangle: false,
1721 output: {
1722 beautify: true,
1723 indent_level: 2
1724 }
1725 })].filter(Boolean)
1726 };
1727 return config;
1728};
1729
1730function getAliases(project, getKey = x => x) {
1731 let aliases = {};
1732 project.packages.forEach(pkg => {
1733 pkg.entrypoints.map(x => x.strict()).forEach(entrypoint => {
1734 aliases[getKey(entrypoint.name)] = path.join(pkg.name, path.relative(entrypoint.directory, entrypoint.source));
1735 });
1736 });
1737 return aliases;
1738}
1739
1740function getGlobals(pkg) {
1741 let stuff = [];
1742
1743 if (pkg.peerDependencies) {
1744 stuff.push(...Object.keys(pkg.peerDependencies));
1745 }
1746
1747 if (pkg.dependencies) {
1748 stuff.push(...Object.keys(pkg.dependencies));
1749 }
1750
1751 if (stuff.length === 0) {
1752 return {};
1753 }
1754
1755 let peerDeps = pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : [];
1756 return peerDeps.reduce((obj, pkgName) => {
1757 obj[pkgName] = pkg.project.global(pkgName);
1758 return obj;
1759 }, {});
1760}
1761
1762function getRollupConfigs(pkg, aliases) {
1763 let configs = [];
1764 let strictEntrypoints = pkg.entrypoints.map(x => x.strict());
1765 let hasModuleField = strictEntrypoints[0].module !== null;
1766 configs.push({
1767 config: getRollupConfig(pkg, strictEntrypoints, aliases, "node-dev"),
1768 outputs: [{
1769 format: "cjs",
1770 entryFileNames: "[name].cjs.dev.js",
1771 chunkFileNames: "dist/[name]-[hash].cjs.dev.js",
1772 dir: pkg.directory,
1773 exports: "named"
1774 }, ...(hasModuleField ? [{
1775 format: "es",
1776 entryFileNames: "[name].esm.js",
1777 chunkFileNames: "dist/[name]-[hash].esm.js",
1778 dir: pkg.directory
1779 }] : [])]
1780 });
1781 configs.push({
1782 config: getRollupConfig(pkg, strictEntrypoints, aliases, "node-prod"),
1783 outputs: [{
1784 format: "cjs",
1785 entryFileNames: "[name].cjs.prod.js",
1786 chunkFileNames: "dist/[name]-[hash].cjs.prod.js",
1787 dir: pkg.directory,
1788 exports: "named"
1789 }]
1790 }); // umd builds are a bit special
1791 // we don't guarantee that shared modules are shared across umd builds
1792 // this is just like dependencies, they're bundled into the umd build
1793
1794 if (strictEntrypoints[0].umdMain !== null) pkg.entrypoints.map(x => x.strict()).forEach(entrypoint => {
1795 let umdName = is(entrypoint._config.umdName, is.string);
1796 is(entrypoint.umdMain, is.string);
1797 configs.push({
1798 config: getRollupConfig(pkg, [entrypoint], aliases, "umd"),
1799 outputs: [{
1800 format: "umd",
1801 sourcemap: true,
1802 entryFileNames: "[name].umd.min.js",
1803 name: umdName,
1804 dir: pkg.directory,
1805 globals: getGlobals(pkg)
1806 }]
1807 });
1808 });
1809 let hasBrowserField = strictEntrypoints[0].browser !== null;
1810
1811 if (hasBrowserField) {
1812 configs.push({
1813 config: getRollupConfig(pkg, strictEntrypoints, aliases, "browser"),
1814 outputs: [{
1815 format: "cjs",
1816 entryFileNames: "[name].browser.cjs.js",
1817 chunkFileNames: "dist/[name]-[hash].browser.cjs.js",
1818 dir: pkg.directory,
1819 exports: "named"
1820 }, ...(hasModuleField ? [{
1821 format: "es",
1822 entryFileNames: "[name].browser.esm.js",
1823 chunkFileNames: "dist/[name]-[hash].browser.esm.js",
1824 dir: pkg.directory
1825 }] : [])]
1826 });
1827 }
1828
1829 if (strictEntrypoints[0].reactNative !== null) {
1830 configs.push({
1831 config: getRollupConfig(pkg, strictEntrypoints, aliases, "react-native"),
1832 outputs: [{
1833 format: "cjs",
1834 entryFileNames: "[name].native.cjs.js",
1835 chunkFileNames: "dist/[name]-[hash].native.cjs.js",
1836 dir: pkg.directory,
1837 exports: "named"
1838 }, ...(hasModuleField ? [{
1839 format: "es",
1840 entryFileNames: "[name].native.esm.js",
1841 chunkFileNames: "dist/[name]-[hash].native.esm.js",
1842 dir: pkg.directory
1843 }] : [])]
1844 });
1845 }
1846
1847 return configs;
1848}
1849
1850let browserPattern = /typeof\s+(window|document)/;
1851
1852async function buildPackage(pkg, aliases) {
1853 let configs = getRollupConfigs(pkg, aliases);
1854 await Promise.all([fs.remove(path.join(pkg.directory, "dist")), ...pkg.entrypoints.map(entrypoint => {
1855 return fs.remove(path.join(entrypoint.directory, "dist"));
1856 })]); // TODO: Fix all this stuff to work with multiple entrypoints
1857
1858 let hasCheckedBrowser = pkg.entrypoints[0].browser !== null;
1859 await Promise.all(configs.map(async ({
1860 config,
1861 outputs
1862 }) => {
1863 // $FlowFixMe this is not a problem with flow, i did something wrong but it's not worth fixing right now
1864 let bundle = await rollup(config);
1865 let result = await Promise.all(outputs.map(outputConfig => {
1866 return bundle.write(outputConfig);
1867 }));
1868 const nodeDevOutput = result[0].output;
1869
1870 if (!hasCheckedBrowser) {
1871 let allCode = nodeDevOutput.map(({
1872 code
1873 }) => code).join("\n");
1874 hasCheckedBrowser = true;
1875
1876 if (browserPattern.test(allCode)) {
1877 throw (async () => {
1878 let shouldAddBrowserField = await confirms.addBrowserField(pkg);
1879
1880 if (shouldAddBrowserField) {
1881 pkg.setFieldOnEntrypoints("browser");
1882 await Promise.all(pkg.entrypoints.map(x => x.save()));
1883 } else {
1884 throw new FatalError(errors.deniedWriteBrowserField, pkg.name);
1885 }
1886 })();
1887 }
1888 }
1889 }));
1890}
1891
1892async function retryableBuild(pkg, aliases) {
1893 try {
1894 await buildPackage(pkg, aliases);
1895 } catch (err) {
1896 if (err instanceof Promise) {
1897 await err;
1898 await retryableBuild(pkg, aliases);
1899 return;
1900 }
1901
1902 if (err instanceof FatalError) {
1903 throw err;
1904 }
1905
1906 throw new UnexpectedBuildError(err, pkg.name);
1907 }
1908}
1909
1910async function build(directory) {
1911 // do more stuff with checking whether the repo is using yarn workspaces or bolt
1912 try {
1913 createWorker();
1914 await hasherPromise;
1915 let project = await Project.create(directory);
1916 info("building bundles!");
1917 let aliases = getAliases(project);
1918 await Promise.all(project.packages.map(pkg => retryableBuild(pkg, aliases)));
1919 success("built bundles!");
1920 } finally {
1921 destroyWorker();
1922 }
1923}
1924
1925function relativePath(id) {
1926 return path.relative(process.cwd(), id);
1927}
1928
1929async function watchPackage(pkg, aliases) {
1930 const _configs = getRollupConfigs(pkg, aliases);
1931
1932 await fs.remove(path.join(pkg.directory, "dist"));
1933
1934 let configs = _configs.map(config => {
1935 return _objectSpread({}, toUnsafeRollupConfig(config.config), {
1936 output: config.outputs
1937 });
1938 });
1939
1940 const watcher = rollup$1.watch(configs);
1941 let reject;
1942 let errPromise = new Promise((resolve, _reject) => {
1943 reject = _reject;
1944 });
1945 let startResolve;
1946 let startPromise = new Promise(resolve => {
1947 startResolve = resolve;
1948 });
1949 watcher.on("event", event => {
1950 // https://github.com/rollup/rollup/blob/aed954e4e6e8beabd47268916ff0955fbb20682d/bin/src/run/watch.ts#L71-L115
1951 switch (event.code) {
1952 case "FATAL":
1953 {
1954 reject(event.error);
1955 break;
1956 }
1957
1958 case "ERROR":
1959 {
1960 reject(event.error);
1961 break;
1962 }
1963
1964 case "START":
1965 startResolve();
1966 break;
1967
1968 case "BUNDLE_START":
1969 {
1970 info(chalk.cyan(`bundles ${chalk.bold(typeof event.input === "string" ? relativePath(event.input) : Array.isArray(event.input) ? event.input.map(relativePath).join(", ") : Object.values(event.input) // $FlowFixMe
1971 .map(relativePath).join(", "))}${chalk.bold(event.output.map(relativePath).join(", "))}...`), pkg.name);
1972 break;
1973 }
1974
1975 case "BUNDLE_END":
1976 {
1977 info(chalk.green(`created ${chalk.bold(event.output.map(relativePath).join(", "))} in ${chalk.bold(ms(event.duration))}`), pkg.name);
1978 break;
1979 }
1980
1981 case "END":
1982 {
1983 info("waiting for changes...", pkg.name);
1984 }
1985 }
1986 });
1987 return {
1988 error: errPromise,
1989 start: startPromise
1990 };
1991}
1992
1993async function retryableWatch(pkg, aliases, getPromises, depth) {
1994 try {
1995 let {
1996 error,
1997 start
1998 } = await watchPackage(pkg, aliases);
1999
2000 if (depth === 0) {
2001 getPromises({
2002 start
2003 });
2004 }
2005
2006 await error;
2007 } catch (err) {
2008 if (err instanceof Promise) {
2009 await err;
2010 await retryableWatch(pkg, aliases, getPromises, depth + 1);
2011 return;
2012 }
2013
2014 throw err;
2015 }
2016}
2017
2018async function build$1(directory) {
2019 createWorker();
2020 let project = await Project.create(directory); // do more stuff with checking whether the repo is using yarn workspaces or bolt
2021
2022 let aliases = getAliases(project);
2023 let startCount = 0;
2024 await Promise.all(project.packages.map(pkg => retryableWatch(pkg, aliases, async ({
2025 start
2026 }) => {
2027 await start;
2028 startCount++;
2029
2030 if (startCount === project.packages.length) {
2031 success(successes.startedWatching);
2032 }
2033 }, 0)));
2034}
2035
2036async function fixEntrypoint(entrypoint) {
2037 validateEntrypointSource(entrypoint);
2038
2039 if (entrypoint.umdMain !== null && !isUmdNameSpecified(entrypoint)) {
2040 let umdName = await promptInput(inputs.getUmdName, entrypoint);
2041 entrypoint.umdName = umdName;
2042 await entrypoint.save();
2043 return true;
2044 }
2045
2046 return false;
2047}
2048
2049async function fix(directory) {
2050 let {
2051 packages
2052 } = await Project.create(directory);
2053 let didModify = (await Promise.all(packages.map(async pkg => {
2054 let didModifyInPkgFix = await fixPackage(pkg);
2055 let didModifyInEntrypointsFix = (await Promise.all(pkg.entrypoints.map(fixEntrypoint))).some(x => x);
2056 return didModifyInPkgFix || didModifyInEntrypointsFix;
2057 }))).some(x => x);
2058 success(didModify ? "fixed project!" : "project already valid!");
2059}
2060
2061let tsExtensionPattern = /tsx?$/;
2062
2063function cjsOnlyReexportTemplate(pathToSource) {
2064 return `// 👋 hey!!
2065// you might be reading this and seeing .esm in the filename
2066// and being confused why there is commonjs below this filename
2067// DON'T WORRY!
2068// this is intentional
2069// it's only commonjs with \`preconstruct dev\`
2070// when you run \`preconstruct build\`, it will be ESM
2071// why is it commonjs?
2072// we need to re-export every export from the source file
2073// but we can't do that with ESM without knowing what the exports are (because default exports aren't included in export/import *)
2074// and they could change after running \`preconstruct dev\` so we can't look at the file without forcing people to
2075// run preconstruct dev again which wouldn't be ideal
2076// this solution could change but for now, it's working
2077
2078module.exports = require(${JSON.stringify(pathToSource)})
2079`;
2080}
2081
2082async function getTypeSystem(entrypoint) {
2083 let content = await fs.readFile(entrypoint.source, "utf8");
2084
2085 if (tsExtensionPattern.test(entrypoint.source)) {
2086 return ["typescript", content];
2087 } // TODO: maybe we should write the flow symlink even if there isn't an
2088 // comment so that if someone adds an comment they don't have to run preconstruct dev again
2089
2090
2091 if (content.includes("@flow")) {
2092 return ["flow", content];
2093 }
2094
2095 return [null, content];
2096}
2097
2098async function writeFlowFile(typeSystemPromise, entrypoint) {
2099 let [typeSystem, content] = await typeSystemPromise;
2100 if (typeSystem === null) return;
2101 let cjsDistPath = path.join(entrypoint.directory, entrypoint.main);
2102
2103 if (typeSystem === "flow") {
2104 await fs.symlink(entrypoint.source, cjsDistPath + ".flow");
2105 }
2106
2107 if (typeSystem === "typescript") {
2108 let ast = await babel.parseAsync(content, {
2109 filename: entrypoint.source,
2110 sourceType: "module",
2111 cwd: entrypoint.package.project.directory
2112 });
2113 let hasDefaultExport = false;
2114
2115 for (let statement of ast.program.body) {
2116 if (statement.type === "ExportDefaultDeclaration" || statement.type === "ExportNamedDeclaration" && statement.specifiers.some(specifier => specifier.type === "ExportSpecifier" && specifier.exported.name === "default")) {
2117 hasDefaultExport = true;
2118 break;
2119 }
2120 }
2121
2122 await fs.writeFile(cjsDistPath + ".ts", tsTemplate(hasDefaultExport, path.relative(path.dirname(cjsDistPath), entrypoint.source).replace(/\.tsx?$/, "")));
2123 }
2124}
2125
2126async function dev(projectDir) {
2127 let project = await Project.create(projectDir);
2128 project.packages.forEach(({
2129 entrypoints
2130 }) => entrypoints.forEach(x => x.strict()));
2131 info("project is valid!");
2132 let promises = [];
2133 await Promise.all(project.packages.map(pkg => {
2134 return Promise.all(pkg.entrypoints.map(async _entrypoint => {
2135 let entrypoint = _entrypoint.strict();
2136
2137 let typeSystemPromise = getTypeSystem(entrypoint);
2138 await fs.remove(path.join(entrypoint.directory, "dist"));
2139 await fs.ensureDir(path.join(entrypoint.directory, "dist"));
2140 let promises = [writeFlowFile(typeSystemPromise, entrypoint), fs.writeFile(path.join(entrypoint.directory, entrypoint.main), `"use strict";
2141
2142let unregister = require(${JSON.stringify(require.resolve("@preconstruct/hook"))}).___internalHook(${JSON.stringify(project.directory)});
2143
2144module.exports = require(${JSON.stringify(entrypoint.source)});
2145
2146unregister();
2147`)];
2148
2149 if (entrypoint.module) {
2150 promises.push(fs.writeFile(path.join(entrypoint.directory, entrypoint.module), cjsOnlyReexportTemplate(entrypoint.source)));
2151 }
2152
2153 let browserField = entrypoint.browser;
2154
2155 if (browserField) {
2156 for (let key of Object.keys(browserField)) {
2157 promises.push(fs.writeFile(path.join(entrypoint.directory, browserField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
2158 }
2159 }
2160
2161 let rnField = entrypoint.reactNative;
2162
2163 if (rnField) {
2164 for (let key of Object.keys(rnField)) {
2165 promises.push(fs.writeFile(path.join(entrypoint.directory, rnField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
2166 }
2167 }
2168
2169 return Promise.all(promises);
2170 }));
2171 }));
2172 await Promise.all(promises);
2173 success("created links!");
2174}
2175
2176// $FlowFixMe
2177
2178process["e" + "nv"].NODE_ENV = "production";
2179let {
2180 input
2181} = meow(`
2182Usage
2183 $ preconstruct [command]
2184Commands
2185 init initialise a project
2186 build build the project
2187 watch start a watch process to build the project
2188 validate validate the project
2189 fix infer as much information as possible and fix the project
2190 dev create links so entrypoints can be imported
2191
2192`, {});
2193let errors$1 = {
2194 commandNotFound: "Command not found"
2195};
2196
2197class CommandNotFoundError extends Error {}
2198
2199(async () => {
2200 if (input.length === 1) {
2201 switch (input[0]) {
2202 case "init":
2203 {
2204 await init(process.cwd());
2205 return;
2206 }
2207
2208 case "validate":
2209 {
2210 await validate(process.cwd());
2211 return;
2212 }
2213
2214 case "build":
2215 {
2216 await build(process.cwd());
2217 return;
2218 }
2219
2220 case "watch":
2221 {
2222 await build$1(process.cwd());
2223 return;
2224 }
2225
2226 case "fix":
2227 {
2228 await fix(process.cwd());
2229 return;
2230 }
2231
2232 case "dev":
2233 {
2234 await dev(process.cwd());
2235 return;
2236 }
2237
2238 default:
2239 {
2240 throw new CommandNotFoundError();
2241 }
2242 }
2243 } else {
2244 throw new CommandNotFoundError();
2245 }
2246})().catch(err => {
2247 if (err instanceof FixableError) {
2248 error(err.message, err.scope);
2249 info("The above error can be fixed automatically by running preconstruct fix", err.item);
2250 } else if (err instanceof FatalError) {
2251 error(err.message, err.scope);
2252 } else if (err instanceof CommandNotFoundError) {
2253 error(errors$1.commandNotFound);
2254 } else if (err instanceof UnexpectedBuildError) {
2255 error(err, err.scope);
2256 } else {
2257 error(err);
2258 }
2259
2260 process.exit(1);
2261});