UNPKG

60 kBJavaScriptView Raw
1"use strict";
2
3function _interopDefault(ex) {
4 return ex && "object" == typeof ex && "default" in ex ? ex.default : ex;
5}
6
7var meow = _interopDefault(require("meow")), _defineProperty = _interopDefault(require("@babel/runtime/helpers/defineProperty")), is = _interopDefault(require("sarcastic")), globby = _interopDefault(require("globby")), fs = require("fs-extra"), path = _interopDefault(require("path")), util = _interopDefault(require("util")), _objectSpread = _interopDefault(require("@babel/runtime/helpers/objectSpread")), inquirer = _interopDefault(require("inquirer")), pLimit = _interopDefault(require("p-limit")), DataLoader = _interopDefault(require("dataloader")), chalk = _interopDefault(require("chalk")), resolveFrom = _interopDefault(require("resolve-from")), packlist = _interopDefault(require("npm-packlist")), equal = _interopDefault(require("fast-deep-equal")), resolve = _interopDefault(require("resolve")), resolve$1 = _interopDefault(require("rollup-plugin-node-resolve")), alias = _interopDefault(require("rollup-plugin-alias")), cjs = _interopDefault(require("rollup-plugin-commonjs")), replace = _interopDefault(require("rollup-plugin-replace")), builtInModules = _interopDefault(require("builtin-modules")), rollup$1 = require("rollup"), fs$1 = require("fs"), json = _interopDefault(require("rollup-plugin-json")), _objectWithoutProperties = _interopDefault(require("@babel/runtime/helpers/objectWithoutProperties")), babel = require("@babel/core"), rollupPluginutils = require("rollup-pluginutils"), Worker = _interopDefault(require("jest-worker")), initHasher = _interopDefault(require("xxhash-wasm")), QuickLRU = _interopDefault(require("quick-lru")), codeFrame = require("@babel/code-frame"), installPackages = _interopDefault(require("install-packages")), ms = _interopDefault(require("ms"));
8
9let EXTENSIONS = [ ".js", ".jsx", ".ts", ".tsx" ], PKG_JSON_CONFIG_FIELD = "preconstruct", itemsByPath = {};
10
11class Item {
12 constructor(filePath, contents) {
13 _defineProperty(this, "_contents", void 0), _defineProperty(this, "_stringifiedSavedJson", void 0),
14 _defineProperty(this, "path", void 0), _defineProperty(this, "directory", void 0),
15 _defineProperty(this, "json", void 0), _defineProperty(this, "_config", void 0),
16 this.json = is(JSON.parse(contents), is.object), this._stringifiedSavedJson = JSON.stringify(this.json, null, 2),
17 this._contents = contents, this.path = filePath, this.directory = path.dirname(filePath),
18 this._config = this.json[PKG_JSON_CONFIG_FIELD] || {}, void 0 === itemsByPath[this.path] && (itemsByPath[this.path] = new Set()),
19 itemsByPath[this.path].add(this);
20 }
21 updater(json) {
22 this.json = json;
23 }
24 async refresh() {
25 let contents = await fs.readFile(this.path, "utf-8"), json = is(JSON.parse(contents), is.object);
26 for (let item of itemsByPath[this.path]) item.updater(json);
27 }
28 async save() {
29 Object.keys(this._config).length ? this.json[PKG_JSON_CONFIG_FIELD] = this._config : delete this.json[PKG_JSON_CONFIG_FIELD];
30 let stringified = JSON.stringify(this.json, null, 2);
31 if (stringified !== this._stringifiedSavedJson) {
32 await fs.writeFile(this.path, JSON.stringify(this.json, null, 2) + "\n"), this._config = this.json[PKG_JSON_CONFIG_FIELD] || {};
33 for (let item of itemsByPath[this.path]) item.updater(this.json);
34 return this._stringifiedSavedJson = stringified, !0;
35 }
36 return !1;
37 }
38}
39
40class FatalError extends Error {
41 constructor(message, scope) {
42 super(message), _defineProperty(this, "scope", void 0), this.scope = scope;
43 }
44}
45
46class UnexpectedBuildError extends FatalError {
47 constructor(error, pkgName) {
48 super(`${util.format("", error).trim()}`, pkgName);
49 }
50}
51
52class FixableError extends FatalError {}
53
54let limit = pLimit(1), prefix = `🎁 ${chalk.green("?")}`;
55
56function createPromptConfirmLoader(message) {
57 let loader = new DataLoader(pkgs => limit(() => (async () => {
58 if (1 === pkgs.length) {
59 let {confirm: confirm} = await inquirer.prompt([ {
60 type: "confirm",
61 name: "confirm",
62 message: message,
63 prefix: prefix + " " + pkgs[0].name
64 } ]);
65 return [ confirm ];
66 }
67 let {answers: answers} = await inquirer.prompt([ {
68 type: "checkbox",
69 name: "answers",
70 message: message,
71 choices: pkgs.map(pkg => ({
72 name: pkg.name,
73 checked: !0
74 })),
75 prefix: prefix
76 } ]);
77 return pkgs.map(pkg => answers.includes(pkg.name));
78 })(), {
79 cache: !1
80 }));
81 return pkg => loader.load(pkg);
82}
83
84let promptConfirm = async message => {
85 let {confirm: confirm} = await inquirer.prompt([ {
86 type: "confirm",
87 name: "confirm",
88 message: message,
89 prefix: prefix
90 } ]);
91 return confirm;
92}, doPromptInput = async (message, pkg, defaultAnswer) => {
93 let {input: input} = await inquirer.prompt([ {
94 type: "input",
95 name: "input",
96 message: message,
97 prefix: prefix + " " + pkg.name,
98 default: defaultAnswer
99 } ]);
100 return input;
101}, promptInput = (message, pkg, defaultAnswer) => limit(() => doPromptInput(message, pkg, defaultAnswer));
102
103function format(args, messageType, scope) {
104 let fullPrefix = "🎁 " + {
105 error: chalk.red("error"),
106 success: chalk.green("success"),
107 info: chalk.cyan("info")
108 }[messageType] + (void 0 === scope ? "" : " " + chalk.cyan(scope));
109 return fullPrefix + util.format("", ...args).split("\n").join("\n" + fullPrefix + " ");
110}
111
112function error(message, scope) {
113 console.error(format([ message ], "error", scope));
114}
115
116function success(message, scope) {
117 console.log(format([ message ], "success", scope));
118}
119
120function info(message, scope) {
121 console.log(format([ message ], "info", scope));
122}
123
124async function validateIncludedFiles(pkg) {
125 try {
126 await Promise.all(pkg.entrypoints.map(async entrypoint => {
127 let filename = path.join(entrypoint.directory, "dist", "preconstruct-test-file");
128 return await fs.ensureFile(filename), fs.writeFile(filename, "test content");
129 }));
130 let result = await packlist({
131 path: pkg.directory
132 }), messages = [];
133 if (pkg.entrypoints.forEach(entrypoint => {
134 let pkgJsonPath = path.relative(pkg.directory, path.resolve(entrypoint.directory, "package.json")), distFilePath = path.relative(pkg.directory, path.resolve(entrypoint.directory, "dist", "preconstruct-test-file")), entrypointName = path.relative(pkg.directory, entrypoint.directory);
135 result.includes(pkgJsonPath) ? result.includes(distFilePath) || 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`) : 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`);
136 }), messages.length) throw new FatalError(messages.join("\n"), pkg.name);
137 } finally {
138 await Promise.all(pkg.entrypoints.map(entrypoint => fs.remove(path.join(entrypoint.directory, "dist", "preconstruct-test-file"))));
139 }
140}
141
142let unsafeRequire = require, askGlobalLimit = pLimit(1);
143
144class Project extends Item {
145 constructor(...args) {
146 super(...args), _defineProperty(this, "packages", void 0);
147 }
148 get configPackages() {
149 return is(this._config.packages, is.default(is.arrayOf(is.string), [ "." ]));
150 }
151 get isBolt() {
152 let hasBolt = !!this.json.bolt, hasYarnWorkspaces = !!this.json.workspaces;
153 return hasBolt && !hasYarnWorkspaces;
154 }
155 static async create(directory) {
156 let filePath = path.join(directory, "package.json"), contents = await fs.readFile(filePath, "utf-8"), project = new Project(filePath, contents);
157 return project.packages = await project._packages(), project;
158 }
159 get name() {
160 return is(this.json.name, is.string);
161 }
162 set name(name) {
163 this.json.name = name;
164 }
165 async _packages() {
166 if (!this._config.packages && this.json.workspaces) {
167 let _workspaces;
168 Array.isArray(this.json.workspaces) ? _workspaces = this.json.workspaces : Array.isArray(this.json.workspaces.packages) && (_workspaces = this.json.workspaces.packages);
169 let workspaces = is(_workspaces, is.arrayOf(is.string)), packages = await promptInput("what packages should preconstruct build?", this, workspaces.join(","));
170 this._config.packages = packages.split(","), await this.save();
171 }
172 try {
173 let lastErr, filenames = await globby(this.configPackages, {
174 cwd: this.directory,
175 onlyDirectories: !0,
176 absolute: !0,
177 expandDirectories: !1
178 }), dirsWithoutPkgJson = [], packages = await Promise.all(filenames.map(async x => {
179 try {
180 let pkg = await Package.create(x);
181 return pkg.project = this, pkg;
182 } catch (err) {
183 if ("ENOENT" === err.code && err.path === path.join(x, "package.json")) return lastErr = err,
184 void dirsWithoutPkgJson.push(x);
185 throw err;
186 }
187 }));
188 if (dirsWithoutPkgJson.length) {
189 if (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"),
190 !await promptConfirm("would you like preconstruct to delete these directories automatically?")) throw lastErr;
191 return await Promise.all(dirsWithoutPkgJson.map(dir => fs.remove(dir))), this._packages();
192 }
193 return await Promise.all(packages.map(pkg => validateIncludedFiles(pkg))), packages;
194 } catch (error) {
195 if (error instanceof is.AssertionError) return [];
196 throw error;
197 }
198 }
199 global(pkg) {
200 if (void 0 !== this._config.globals && this._config.globals[pkg]) return this._config.globals[pkg];
201 try {
202 let pkgJson = unsafeRequire(resolveFrom(this.directory, path.join(pkg, "package.json")));
203 if (pkgJson && pkgJson[PKG_JSON_CONFIG_FIELD] && pkgJson[PKG_JSON_CONFIG_FIELD].umdName) return pkgJson[PKG_JSON_CONFIG_FIELD].umdName;
204 } catch (err) {
205 if ("MODULE_NOT_FOUND" !== err.code) throw err;
206 }
207 throw askGlobalLimit(() => (async () => {
208 if (void 0 !== this._config.globals && this._config.globals[pkg]) return;
209 let response = await promptInput(`What should the umdName of ${pkg} be?`, this);
210 this._addGlobal(pkg, response), await this.save();
211 })());
212 }
213 _addGlobal(pkg, name) {
214 this._config.globals || (this._config.globals = {}), this._config.globals[pkg] = name;
215 }
216}
217
218let errors = {
219 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`,
220 deniedWriteMainField: "changing the main field is required to build",
221 invalidModuleField: "module field is invalid",
222 invalidMainField: "main field is invalid",
223 invalidUmdMainField: "umd:main field is invalid",
224 invalidBrowserField: "browser field is invalid",
225 invalidReactNativeField: "react-native field is invalid",
226 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`,
227 deniedWriteBrowserField: "building browser bundles for modules that include typeof window or typeof document is currently required",
228 noEntrypointPkgJson: "There is a missing package.json for an entrypoint",
229 noEntrypoints: "packages must have at least one entrypoint, this package has no entrypoints"
230}, confirms = {
231 writeMainField: createPromptConfirmLoader("preconstruct is going to change the main field in your package.json, are you okay with that?"),
232 writeModuleField: createPromptConfirmLoader("would you like to generate module builds? this will write to the module field in your package.json"),
233 fixModuleField: createPromptConfirmLoader("would you like to fix the module field?"),
234 fixUmdBuild: createPromptConfirmLoader("would you like to fix the umd field?"),
235 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?"),
236 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?"),
237 addBrowserField: createPromptConfirmLoader("typeof window or typeof document is used in this package. would you like build seperate browser builds for better browser bundle sizes?"),
238 fixBrowserField: createPromptConfirmLoader("would you like to fix the browser build?"),
239 createEntrypointPkgJson: createPromptConfirmLoader("A package.json file does not exist for this entrypoint, would you like to create one automatically?")
240}, inputs = {
241 getUmdName: "what should the name used for UMD bundles be?"
242}, infos = {
243 validMainField: "main field is valid",
244 validModuleField: "module field is valid",
245 validUmdMainField: "umd:main field is valid",
246 validEntrypoint: "a valid entry point exists.",
247 validBrowserField: "browser field is valid",
248 validReactNativeField: "react-native field is valid",
249 validPackageEntrypoints: "package entrypoints are valid"
250}, successes = {
251 validProject: "project is valid!",
252 startedWatching: "started watching!"
253};
254
255function getNameForDist(name) {
256 return name.replace(/.*\//, "");
257}
258
259function getValidStringFieldContentForBuildType(type, pkgName) {
260 let safeName = getNameForDist(pkgName);
261 switch (type) {
262 case "main":
263 return `dist/${safeName}.cjs.js`;
264
265 case "module":
266 return `dist/${safeName}.esm.js`;
267
268 case "umd:main":
269 return `dist/${safeName}.umd.min.js`;
270 }
271 throw new Error(`unknown string build type: ${type}. this is likely a bug in preconstruct.`);
272}
273
274function getValidObjectFieldContentForBuildType(type, pkgName, hasModuleBuild) {
275 let safeName = getNameForDist(pkgName);
276 switch (type) {
277 case "browser":
278 {
279 let obj = {
280 [`./dist/${safeName}.cjs.js`]: `./dist/${safeName}.browser.cjs.js`
281 };
282 return hasModuleBuild && (obj[`./dist/${safeName}.esm.js`] = `./dist/${safeName}.browser.esm.js`),
283 obj;
284 }
285
286 case "react-native":
287 {
288 let obj = {
289 [`./dist/${safeName}.cjs.js`]: `./dist/${safeName}.native.cjs.js`
290 };
291 return hasModuleBuild && (obj[`./dist/${safeName}.esm.js`] = `./dist/${safeName}.native.esm.js`),
292 obj;
293 }
294 }
295 throw new Error(`unknown object build type: ${type}. this is likely a bug in preconstruct.`);
296}
297
298function flowTemplate(hasDefaultExport, relativePath) {
299 return `// @flow\nexport * from "${relativePath}";${hasDefaultExport ? `\nexport { default } from "${relativePath}";` : ""}\n`;
300}
301
302function tsTemplate(hasDefaultExport, relativePath) {
303 return `export * from "${relativePath}";${hasDefaultExport ? `\nexport { default } from "${relativePath}";` : ""}\n`;
304}
305
306let camelToPkgJsonField = {
307 main: "main",
308 module: "module",
309 umdMain: "umd:main",
310 browser: "browser",
311 reactNative: "react-native"
312};
313
314async function fixPackage(pkg) {
315 if (0 === pkg.entrypoints.length) throw new FatalError(errors.noEntrypoints, pkg.name);
316 let fields = {
317 main: !0,
318 module: pkg.entrypoints.some(x => x.module),
319 umdMain: pkg.entrypoints.some(x => x.umdMain),
320 browser: pkg.entrypoints.some(x => x.browser),
321 reactNative: pkg.entrypoints.some(x => x.reactNative)
322 };
323 return Object.keys(fields).filter(x => fields[x]).forEach(field => {
324 pkg.setFieldOnEntrypoints(field);
325 }), (await Promise.all(pkg.entrypoints.map(x => x.save()))).some(x => x);
326}
327
328let unsafeRequire$1 = require;
329
330function validatePackage(pkg) {
331 if (0 === pkg.entrypoints.length) throw new FatalError(errors.noEntrypoints, pkg.name);
332 let fields = {
333 module: !!pkg.entrypoints[0].module,
334 umdMain: !!pkg.entrypoints[0].umdMain,
335 browser: !!pkg.entrypoints[0].browser,
336 reactNative: !!pkg.entrypoints[0].reactNative
337 };
338 if (pkg.entrypoints.forEach(entrypoint => {
339 Object.keys(fields).forEach(field => {
340 if (entrypoint[field] && !fields[field]) 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);
341 if (!entrypoint[field] && fields[field]) 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);
342 });
343 }), fields.umdMain) {
344 let sortaAllDeps = new Set([ ...pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : [], ...pkg.dependencies ? Object.keys(pkg.dependencies) : [] ]);
345 for (let depName in pkg.dependencies) {
346 let depPkgJson = unsafeRequire$1(resolveFrom(pkg.directory, depName + "/package.json"));
347 if (depPkgJson.peerDependencies) for (let pkgName in depPkgJson.peerDependencies) if (!sortaAllDeps.has(pkgName)) 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);
348 }
349 }
350}
351
352function validateEntrypointSource(entrypoint) {
353 try {
354 if (!entrypoint.source.startsWith(entrypoint.package.directory)) 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);
355 } catch (e) {
356 if ("MODULE_NOT_FOUND" === e.code) throw new FatalError(errors.noSource(entrypoint.configSource), entrypoint.name);
357 throw e;
358 }
359}
360
361function isMainFieldValid(entrypoint) {
362 return entrypoint.main === getValidStringFieldContentForBuildType("main", entrypoint.package.name);
363}
364
365function isModuleFieldValid(entrypoint) {
366 return entrypoint.module === getValidStringFieldContentForBuildType("module", entrypoint.package.name);
367}
368
369function isUmdMainFieldValid(entrypoint) {
370 return entrypoint.umdMain === getValidStringFieldContentForBuildType("umd:main", entrypoint.package.name);
371}
372
373function isBrowserFieldValid(entrypoint) {
374 return equal(entrypoint.browser, getValidObjectFieldContentForBuildType("browser", entrypoint.package.name, null !== entrypoint.module));
375}
376
377function isReactNativeFieldValid(entrypoint) {
378 return equal(entrypoint.reactNative, getValidObjectFieldContentForBuildType("react-native", entrypoint.package.name, null !== entrypoint.module));
379}
380
381function isUmdNameSpecified(entrypoint) {
382 return "string" == typeof entrypoint._config.umdName;
383}
384
385function validateEntrypoint(entrypoint, log) {
386 if (validateEntrypointSource(entrypoint), log && info(infos.validEntrypoint, entrypoint.name),
387 !isMainFieldValid(entrypoint)) throw new FixableError(errors.invalidMainField, entrypoint.name);
388 if (log && info(infos.validMainField, entrypoint.name), null !== entrypoint.module) {
389 if (!isModuleFieldValid(entrypoint)) throw new FixableError(errors.invalidModuleField, entrypoint.name);
390 log && info(infos.validModuleField, entrypoint.name);
391 }
392 if (null !== entrypoint.umdMain) {
393 if (!isUmdMainFieldValid(entrypoint)) throw new FixableError(errors.invalidUmdMainField, entrypoint.name);
394 if (!isUmdNameSpecified(entrypoint)) throw new FixableError(errors.umdNameNotSpecified, entrypoint.name);
395 log && info(infos.validUmdMainField, entrypoint.name);
396 }
397 if (null !== entrypoint.browser) {
398 if ("string" == typeof entrypoint.browser || !isBrowserFieldValid(entrypoint)) throw new FixableError(errors.invalidBrowserField, entrypoint.name);
399 log && info(infos.validBrowserField, entrypoint.name);
400 }
401 if (null !== entrypoint.reactNative) {
402 if ("string" == typeof entrypoint.reactNative || !isReactNativeFieldValid(entrypoint)) throw new FixableError(errors.invalidReactNativeField, entrypoint.name);
403 log && info(infos.validReactNativeField, entrypoint.name);
404 }
405}
406
407async function validate(directory) {
408 let project = await Project.create(directory);
409 for (let pkg of project.packages) {
410 validatePackage(pkg);
411 for (let entrypoint of pkg.entrypoints) validateEntrypoint(entrypoint, !0);
412 info(infos.validPackageEntrypoints, pkg.name);
413 }
414 success(successes.validProject);
415}
416
417let fields = [ "version", "description", "main", "module", "umd:main", "browser", "react-native" ];
418
419function setFieldInOrder(obj, field, value) {
420 if (field in obj) return _objectSpread({}, obj, {
421 [field]: value
422 });
423 let fieldIndex = fields.indexOf(field), idealField = fields.slice(0, fieldIndex).reverse().find(key => key in obj);
424 if (void 0 === idealField) return _objectSpread({}, obj, {
425 [field]: value
426 });
427 let newObj = {};
428 for (let key in obj) newObj[key] = obj[key], key === idealField && (newObj[field] = value);
429 return newObj;
430}
431
432class Entrypoint extends Item {
433 constructor(filePath, contents, pkg) {
434 super(filePath, contents), _defineProperty(this, "package", void 0), _defineProperty(this, "_strict", void 0),
435 this.package = pkg;
436 }
437 get name() {
438 return path.join(this.package.name, path.relative(this.package.directory, this.directory));
439 }
440 get main() {
441 return is(this.json.main, is.maybe(is.string));
442 }
443 set main(path) {
444 this.json = setFieldInOrder(this.json, "main", path);
445 }
446 get module() {
447 return is(this.json.module, is.maybe(is.string));
448 }
449 set module(path) {
450 this.json = setFieldInOrder(this.json, "module", path);
451 }
452 get browser() {
453 return is(this.json.browser, is.maybe(is.either(is.string, is.objectOf(is.string))));
454 }
455 set browser(option) {
456 this.json = setFieldInOrder(this.json, "browser", option);
457 }
458 get reactNative() {
459 return is(this.json["react-native"], is.maybe(is.either(is.string, is.objectOf(is.string))));
460 }
461 set reactNative(option) {
462 this.json = setFieldInOrder(this.json, "react-native", option);
463 }
464 get umdMain() {
465 return is(this.json["umd:main"], is.maybe(is.string));
466 }
467 set umdMain(path) {
468 this.json = setFieldInOrder(this.json, "umd:main", path);
469 }
470 get configSource() {
471 return is(this._config.source, is.default(is.string, "src/index"));
472 }
473 get source() {
474 return resolve.sync(path.join(this.directory, this.configSource), {
475 extensions: EXTENSIONS
476 });
477 }
478 get umdName() {
479 return is(this._config.umdName, is.maybe(is.string));
480 }
481 set umdName(umdName) {
482 null === umdName ? delete this._config.umdName : this._config.umdName = umdName;
483 }
484 strict() {
485 return this._strict || (validatePackage(this.package), validateEntrypoint(this, !1),
486 this._strict = new StrictEntrypoint(this.path, this._contents, this.package)), this._strict;
487 }
488}
489
490class StrictEntrypoint extends Entrypoint {
491 get main() {
492 return is(this.json.main, is.string);
493 }
494 set main(path) {
495 this.json = setFieldInOrder(this.json, "main", path);
496 }
497 get browser() {
498 return is(this.json.browser, is.maybe(is.objectOf(is.string)));
499 }
500 set browser(option) {
501 this.json = setFieldInOrder(this.json, "browser", option);
502 }
503 get reactNative() {
504 return is(this.json["react-native"], is.maybe(is.objectOf(is.string)));
505 }
506 set reactNative(option) {
507 this.json = setFieldInOrder(this.json, "react-native", option);
508 }
509 updater(json) {
510 super.updater(json), validatePackage(this.package), validateEntrypoint(this, !1);
511 }
512 strict() {
513 return this;
514 }
515}
516
517class Package extends Item {
518 constructor(...args) {
519 super(...args), _defineProperty(this, "project", void 0), _defineProperty(this, "entrypoints", void 0);
520 }
521 get configEntrypoints() {
522 return is(this._config.entrypoints, is.default(is.arrayOf(is.string), [ "." ]));
523 }
524 static async create(directory) {
525 let filePath = path.join(directory, "package.json"), contents = await fs.readFile(filePath, "utf-8"), pkg = new Package(filePath, contents), entrypointDirectories = await globby(pkg.configEntrypoints, {
526 cwd: pkg.directory,
527 onlyDirectories: !0,
528 absolute: !0,
529 expandDirectories: !1
530 });
531 return pkg.entrypoints = await Promise.all(entrypointDirectories.map(async directory => {
532 let filename = path.join(directory, "package.json"), contents = null;
533 try {
534 contents = await fs.readFile(filename, "utf-8");
535 } catch (e) {
536 if ("ENOENT" !== e.code) throw e;
537 }
538 return {
539 filename: filename,
540 contents: contents
541 };
542 })).then(descriptors => {
543 let getPlainEntrypointContent = () => {
544 let plainEntrypointObj = {
545 main: getValidStringFieldContentForBuildType("main", pkg.name)
546 };
547 for (let descriptor of descriptors) if (null !== descriptor.contents) {
548 let parsed = JSON.parse(descriptor.contents);
549 for (let field of [ "module", "umd:main" ]) void 0 !== parsed[field] && (plainEntrypointObj[field] = getValidStringFieldContentForBuildType(field, pkg.name));
550 for (let field of [ "browser", "react-native" ]) void 0 !== parsed[field] && (plainEntrypointObj[field] = getValidObjectFieldContentForBuildType(field, pkg.name, void 0 !== plainEntrypointObj.module));
551 }
552 let plainEntrypointContents = JSON.stringify(plainEntrypointObj);
553 return getPlainEntrypointContent = (() => plainEntrypointContents), plainEntrypointContents;
554 };
555 return Promise.all(descriptors.map(async ({filename: filename, contents: contents}) => {
556 if (null === contents) {
557 if (!await confirms.createEntrypointPkgJson({
558 name: path.join(pkg.name, path.relative(pkg.directory, directory))
559 })) throw new FatalError(errors.noEntrypointPkgJson, path.join(pkg.name, path.relative(pkg.directory, directory)));
560 contents = getPlainEntrypointContent(), await fs.writeFile(filename, contents);
561 }
562 return new Entrypoint(filename, contents, pkg);
563 }));
564 }), pkg;
565 }
566 setFieldOnEntrypoints(field) {
567 this.entrypoints.forEach(entrypoint => {
568 switch (field) {
569 case "main":
570 entrypoint.main = getValidStringFieldContentForBuildType("main", this.name);
571 break;
572
573 case "module":
574 entrypoint.module = getValidStringFieldContentForBuildType("module", this.name);
575 break;
576
577 case "browser":
578 entrypoint.browser = getValidObjectFieldContentForBuildType("browser", this.name, null !== entrypoint.module);
579 break;
580
581 case "umdMain":
582 entrypoint.umdMain = getValidStringFieldContentForBuildType("umd:main", this.name);
583 break;
584
585 case "reactNative":
586 entrypoint.reactNative = getValidObjectFieldContentForBuildType("react-native", this.name, null !== entrypoint.module);
587 }
588 });
589 }
590 get name() {
591 return is(this.json.name, is.string);
592 }
593 set name(name) {
594 this.json.name = name;
595 }
596 get dependencies() {
597 return is(this.json.dependencies, is.maybe(is.objectOf(is.string)));
598 }
599 get peerDependencies() {
600 return is(this.json.peerDependencies, is.maybe(is.objectOf(is.string)));
601 }
602}
603
604async function doInit(pkg) {
605 if (pkg.entrypoints.forEach(entrypoint => {
606 validateEntrypointSource(entrypoint);
607 }), pkg.entrypoints.every(entrypoint => isMainFieldValid(entrypoint))) info(infos.validMainField, pkg.name); else {
608 if (!await confirms.writeMainField(pkg)) throw new FatalError(errors.deniedWriteMainField, pkg.name);
609 pkg.setFieldOnEntrypoints("main");
610 }
611 let allEntrypointsAreMissingAModuleField = pkg.entrypoints.every(entrypoint => null === entrypoint.module), someEntrypointsAreNotValid = pkg.entrypoints.some(entrypoint => !isModuleFieldValid(entrypoint));
612 if (allEntrypointsAreMissingAModuleField || someEntrypointsAreNotValid) {
613 if (await confirms.writeModuleField(pkg)) pkg.setFieldOnEntrypoints("module"); else if (!allEntrypointsAreMissingAModuleField) throw new FixableError(errors.invalidModuleField, pkg.name);
614 } else info(infos.validModuleField, pkg.name);
615 let someEntrypointsHaveAMaybeInvalidUmdBuild = pkg.entrypoints.some(entrypoint => null !== entrypoint.umdMain), someUmdMainFieldsAreInvalid = pkg.entrypoints.some(entrypoint => !isUmdMainFieldValid(entrypoint)), someUmdNamesAreNotSpecified = pkg.entrypoints.some(entrypoint => !isUmdNameSpecified(entrypoint));
616 if (someEntrypointsHaveAMaybeInvalidUmdBuild && (someUmdMainFieldsAreInvalid || someUmdNamesAreNotSpecified)) {
617 if (!await confirms.fixUmdBuild(pkg)) throw new FixableError(errors.invalidUmdMainField, pkg.name);
618 pkg.setFieldOnEntrypoints("umdMain");
619 for (let entrypoint of pkg.entrypoints) {
620 let umdName = await promptInput(inputs.getUmdName, entrypoint);
621 entrypoint.umdName = umdName;
622 }
623 }
624 let someEntrypointsHaveABrowserField = pkg.entrypoints.some(entrypoint => null !== entrypoint.browser), someEntrypointsHaveAnInvalidBrowserField = pkg.entrypoints.some(entrypoint => !isBrowserFieldValid(entrypoint));
625 if (someEntrypointsHaveABrowserField && someEntrypointsHaveAnInvalidBrowserField) {
626 if (!await confirms.fixBrowserField(pkg)) throw new FixableError(errors.invalidBrowserField, pkg.name);
627 pkg.setFieldOnEntrypoints("browser");
628 }
629 await Promise.all(pkg.entrypoints.map(x => x.save()));
630}
631
632async function init(directory) {
633 let project = await Project.create(directory);
634 await Promise.all(project.packages.map(doInit)), success("initialised project!");
635}
636
637const pattern = /require\((["'])@babel\/runtime\/helpers\/esm\/(\w+)["']\)/g;
638
639function rewriteCjsRuntimeHelpers() {
640 return {
641 name: "rewrite-cjs-runtime-helpers",
642 renderChunk: (code, chunkInfo, {format: format}) => "cjs" !== format ? null : code.replace(pattern, (_, quote, path) => `require(${quote}@babel/runtime/helpers/${path}${quote})`)
643 };
644}
645
646function getDevPath(cjsPath) {
647 return cjsPath.replace(/\.js$/, ".dev.js");
648}
649
650function getProdPath(cjsPath) {
651 return cjsPath.replace(/\.js$/, ".prod.js");
652}
653
654function flowAndNodeDevProdEntry(pkg) {
655 return {
656 name: "flow-and-prod-dev-entry",
657 async resolveId(source, importer) {
658 let resolved = await this.resolve(source, importer, {
659 skipSelf: !0
660 });
661 if (resolved.id.startsWith("\0") || resolved.id.startsWith(pkg.directory)) return resolved;
662 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);
663 },
664 async generateBundle(opts, bundle, something) {
665 for (const n in bundle) {
666 const file = bundle[n];
667 let facadeModuleId = file.facadeModuleId;
668 if (file.isAsset || !file.isEntry || null == facadeModuleId) continue;
669 let mainFieldPath = file.fileName.replace(/\.prod\.js$/, ".js"), relativeToSource = path.relative(path.dirname(path.join(opts.dir, file.fileName)), facadeModuleId);
670 if (!/\.tsx?$/.test(facadeModuleId)) {
671 let flowMode = !1;
672 if ((await fs.readFile(facadeModuleId, "utf8")).includes("@flow") && (flowMode = file.exports.includes("default") ? "all" : "named"),
673 !1 !== flowMode) {
674 let flowFileSource = flowTemplate("all" === flowMode, relativeToSource), flowFileName = mainFieldPath + ".flow";
675 bundle[flowFileName] = {
676 fileName: flowFileName,
677 isAsset: !0,
678 source: flowFileSource
679 };
680 }
681 }
682 let mainEntrySource = `'use strict';\n\nif (process.env.NODE_ENV === "production") {\n module.exports = require("./${path.basename(getProdPath(mainFieldPath))}");\n} else {\n module.exports = require("./${path.basename(getDevPath(mainFieldPath))}");\n}\n`;
683 bundle[mainFieldPath] = {
684 fileName: mainFieldPath,
685 isAsset: !0,
686 source: mainEntrySource
687 };
688 }
689 }
690 };
691}
692
693function normalize(fileName) {
694 return fileName.split("\\").join("/");
695}
696
697let createLanguageServiceHostClass = typescript => (class {
698 constructor(parsedConfig, transformers) {
699 this.parsedConfig = parsedConfig, this.transformers = transformers, this.cwd = process.cwd(),
700 this.snapshots = {}, this.versions = {}, this.fileNames = new Set(parsedConfig.fileNames);
701 }
702 reset() {
703 this.snapshots = {}, this.versions = {};
704 }
705 setLanguageService(service) {
706 this.service = service;
707 }
708 getProjectVersion() {
709 return 1;
710 }
711 setSnapshot(fileName, data) {
712 fileName = normalize(fileName);
713 const snapshot = typescript.ScriptSnapshot.fromString(data);
714 return this.snapshots[fileName] = snapshot, this.versions[fileName] = (this.versions[fileName] || 0) + 1,
715 this.fileNames.add(fileName), snapshot;
716 }
717 getScriptSnapshot(fileName) {
718 return fileName = normalize(fileName), this.snapshots[fileName] ? this.snapshots[fileName] : fs$1.existsSync(fileName) ? (this.snapshots[fileName] = typescript.ScriptSnapshot.fromString(typescript.sys.readFile(fileName)),
719 this.versions[fileName] = (this.versions[fileName] || 0) + 1, this.snapshots[fileName]) : void 0;
720 }
721 getCurrentDirectory() {
722 return this.cwd;
723 }
724 getScriptVersion(fileName) {
725 return fileName = normalize(fileName), (this.versions[fileName] || 0).toString();
726 }
727 getScriptFileNames() {
728 return Array.from(this.fileNames.values());
729 }
730 getCompilationSettings() {
731 return this.parsedConfig.options;
732 }
733 getDefaultLibFileName(opts) {
734 return typescript.getDefaultLibFilePath(opts);
735 }
736 useCaseSensitiveFileNames() {
737 return typescript.sys.useCaseSensitiveFileNames;
738 }
739 readDirectory(path, extensions, exclude, include) {
740 return typescript.sys.readDirectory(path, extensions, exclude, include);
741 }
742 readFile(path, encoding) {
743 return typescript.sys.readFile(path, encoding);
744 }
745 fileExists(path) {
746 return typescript.sys.fileExists(path);
747 }
748 getTypeRootsVersion() {
749 return 0;
750 }
751 directoryExists(directoryName) {
752 return typescript.sys.directoryExists(directoryName);
753 }
754 getDirectories(directoryName) {
755 return typescript.sys.getDirectories(directoryName);
756 }
757 getCustomTransformers() {}
758}), unsafeRequire$2 = require, weakMemoize = function(func) {
759 let cache = new WeakMap();
760 return arg => {
761 if (cache.has(arg)) return cache.get(arg);
762 let ret = func(arg);
763 return cache.set(arg, ret), ret;
764 };
765};
766
767function memoize(fn) {
768 const cache = {};
769 return arg => (void 0 === cache[arg] && (cache[arg] = fn(arg)), cache[arg]);
770}
771
772let getService = weakMemoize(typescript => memoize(async configFileName => {
773 let configFileContents = await fs.readFile(configFileName, "utf8");
774 const result = typescript.parseConfigFileTextToJson(configFileName, configFileContents);
775 let thing = typescript.parseJsonConfigFileContent(result, typescript.sys, process.cwd(), void 0, configFileName), servicesHost = new (createLanguageServiceHostClass(typescript))(thing, []), service = typescript.createLanguageService(servicesHost, typescript.createDocumentRegistry());
776 return servicesHost.setLanguageService(service), {
777 service: service,
778 options: thing.options
779 };
780}));
781
782async function createDeclarationCreator(dirname) {
783 let typescript;
784 try {
785 typescript = unsafeRequire$2(resolveFrom(dirname, "typescript"));
786 } catch (err) {
787 if ("MODULE_NOT_FOUND" === err.code) 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.");
788 throw err;
789 }
790 let configFileName = typescript.findConfigFile(dirname, typescript.sys.fileExists);
791 if (!configFileName) throw new Error("an entrypoint source file ends with the .ts extension but no TypeScript config exists, please create one.");
792 let {service: service, options: options} = await getService(typescript)(configFileName), moduleResolutionCache = typescript.createModuleResolutionCache(dirname, x => x, options);
793 return {
794 getDeps: entrypoints => {
795 let program = service.getProgram();
796 if (!program) throw new Error("This is an internal error, please open an issue if you see this: program not found");
797 let resolvedEntrypointPaths = entrypoints.map(x => {
798 let {resolvedModule: resolvedModule} = typescript.resolveModuleName(path.join(path.dirname(x), path.basename(x, path.extname(x))), dirname, options, typescript.sys, moduleResolutionCache);
799 if (!resolvedModule) throw new Error("This is an internal error, please open an issue if you see this: ts could not resolve module");
800 return resolvedModule.resolvedFileName;
801 }), allDeps = new Set(resolvedEntrypointPaths);
802 return function searchDeps(deps) {
803 for (let dep of deps) {
804 let sourceFile = program.getSourceFile(dep);
805 if (!sourceFile) throw new Error("This is an internal error, please open an issue if you see this: source file not found");
806 let internalDeps = new Set();
807 for (let _ref of sourceFile.imports) {
808 let {text: text} = _ref, {resolvedModule: resolvedModule} = typescript.resolveModuleName(text, dep, options, typescript.sys, moduleResolutionCache);
809 resolvedModule && (allDeps.has(resolvedModule.resolvedFileName) || resolvedModule.isExternalLibraryImport || !resolvedModule.resolvedFileName.includes(dirname) || (internalDeps.add(resolvedModule.resolvedFileName),
810 allDeps.add(resolvedModule.resolvedFileName)));
811 }
812 searchDeps(internalDeps);
813 }
814 }(new Set(resolvedEntrypointPaths)), allDeps;
815 },
816 getDeclarationFile: async filename => {
817 if (filename.endsWith(".d.ts")) return {
818 name: filename.replace(dirname, path.join(dirname, "dist", "declarations")),
819 content: await fs.readFile(filename, "utf8")
820 };
821 let output = service.getEmitOutput(filename, !0);
822 return {
823 name: output.outputFiles[0].name.replace(dirname, path.join(dirname, "dist", "declarations")),
824 content: output.outputFiles[0].text
825 };
826 }
827 };
828}
829
830let isTsPath = source => /\.tsx?/.test(source);
831
832function typescriptDeclarations(pkg) {
833 return pkg.entrypoints.some(({source: source}) => isTsPath(source)) ? {
834 name: "typescript-declarations",
835 async generateBundle(opts, bundle, something) {
836 let creator = await createDeclarationCreator(pkg.directory), srcFilenameToDtsFilenameMap = new Map(), deps = creator.getDeps(pkg.entrypoints.map(x => x.source));
837 await Promise.all([ ...deps ].map(async dep => {
838 let {name: name, content: content} = await creator.getDeclarationFile(dep);
839 srcFilenameToDtsFilenameMap.set(dep, name), bundle[name] = {
840 fileName: name,
841 isAsset: !0,
842 source: content
843 };
844 }));
845 for (const n in bundle) {
846 const file = bundle[n];
847 let facadeModuleId = file.facadeModuleId;
848 if (file.isAsset || !file.isEntry || null == facadeModuleId) continue;
849 let dtsFilename = srcFilenameToDtsFilenameMap.get(facadeModuleId);
850 if (!dtsFilename) throw new FatalError(`no .d.ts file was found for the entrypoint at ${facadeModuleId}`, pkg.name);
851 let mainFieldPath = file.fileName.replace(/\.prod\.js$/, ""), relativeToSource = path.relative(path.dirname(path.join(opts.dir, file.fileName)), dtsFilename.replace(/\.d\.ts$/, ""));
852 relativeToSource.startsWith(".") || (relativeToSource = `./${relativeToSource}`);
853 let tsFileSource = tsTemplate(file.exports.includes("default"), relativeToSource), tsFileName = mainFieldPath + ".d.ts";
854 bundle[tsFileName] = {
855 fileName: tsFileName,
856 isAsset: !0,
857 source: tsFileSource
858 };
859 }
860 }
861 } : {
862 name: "typescript-declarations"
863 };
864}
865
866let worker, shouldUseWorker = "true" !== process.env.DISABLE_PRECONSTRUCT_WORKER, unsafeRequire$3 = require;
867
868function createWorker() {
869 worker = shouldUseWorker ? new Worker(require.resolve("preconstruct/worker")) : unsafeRequire$3("preconstruct/worker");
870}
871
872function destroyWorker() {
873 void 0 !== worker && shouldUseWorker && (worker.end(), worker = void 0);
874}
875
876function getWorker() {
877 if (void 0 === worker) throw new Error("worker not defined");
878 return worker;
879}
880
881const regExpCharactersRegExp = /[\\^$.*+?()[\]{}|]/g, escapeRegExpCharacters = str => str.replace(regExpCharactersRegExp, "\\$&"), unpackOptions = (_ref = {}) => {
882 let {extensions: extensions = babel.DEFAULT_EXTENSIONS, sourcemap: sourcemap = !0, sourcemaps: sourcemaps = !0, sourceMap: sourceMap = !0, sourceMaps: sourceMaps = !0} = _ref, rest = _objectWithoutProperties(_ref, [ "extensions", "sourcemap", "sourcemaps", "sourceMap", "sourceMaps" ]);
883 return _objectSpread({
884 extensions: extensions,
885 plugins: [],
886 sourceMaps: sourcemap && sourcemaps && sourceMap && sourceMaps
887 }, rest, {
888 caller: _objectSpread({
889 name: "rollup-plugin-babel",
890 supportsStaticESM: !0,
891 supportsDynamicImport: !0
892 }, rest.caller)
893 });
894}, lru = new QuickLRU({
895 maxSize: 1e3
896});
897
898let hasher, hasherPromise = initHasher().then(({h64: h64}) => {
899 hasher = h64;
900}), rollupPluginBabel = pluginOptions => {
901 const _unpackOptions = unpackOptions(pluginOptions), {exclude: exclude, extensions: extensions, include: include} = _unpackOptions, babelOptions = _objectWithoutProperties(_unpackOptions, [ "exclude", "extensions", "include" ]), extensionRegExp = new RegExp(`(${extensions.map(escapeRegExpCharacters).join("|")})$`), includeExcludeFilter = rollupPluginutils.createFilter(include, exclude);
902 return {
903 name: "babel",
904 transform(code, filename) {
905 if (!(id => extensionRegExp.test(id) && includeExcludeFilter(id))(filename)) return Promise.resolve(null);
906 let hash = hasher(filename);
907 if (lru.has(hash)) {
908 let cachedResult = lru.get(hash);
909 if (code === cachedResult.code) return cachedResult.promise;
910 }
911 let options = JSON.stringify(_objectSpread({}, babelOptions, {
912 filename: filename
913 })), promise = getWorker().transformBabel(code, options);
914 return lru.set(hash, {
915 code: code,
916 promise: promise
917 }), promise;
918 }
919 };
920};
921
922function terser(userOptions = {}) {
923 if (null != userOptions.sourceMap) throw Error("sourceMap option is removed, use sourcemap instead");
924 return {
925 name: "terser",
926 renderChunk(code, chunk, outputOptions) {
927 const normalizedOptions = _objectSpread({}, userOptions, {
928 sourceMap: !1 !== userOptions.sourcemap,
929 module: "es" === outputOptions.format || "esm" === outputOptions.format
930 });
931 return normalizedOptions.hasOwnProperty("sourcemap") && delete normalizedOptions.sourcemap,
932 getWorker().transformTerser(code, JSON.stringify(normalizedOptions)).catch(error => {
933 const {message: message, line: line, col: column} = error;
934 throw console.error(codeFrame.codeFrameColumns(code, {
935 start: {
936 line: line,
937 column: column
938 }
939 }, {
940 message: message
941 })), error;
942 });
943 }
944 };
945}
946
947const makeExternalPredicate = externalArr => {
948 if (0 === externalArr.length) return () => !1;
949 const pattern = new RegExp(`^(${externalArr.join("|")})($|/)`);
950 return id => pattern.test(id);
951};
952
953let rollup = rollup$1.rollup;
954
955function toUnsafeRollupConfig(config) {
956 return config;
957}
958
959let getRollupConfig = (pkg, entrypoints, aliases, type) => {
960 let external = [];
961 pkg.peerDependencies && external.push(...Object.keys(pkg.peerDependencies)), pkg.dependencies && "umd" !== type && external.push(...Object.keys(pkg.dependencies)),
962 "node-dev" !== type && "node-prod" !== type || external.push(...builtInModules);
963 let rollupAliases = {};
964 Object.keys(aliases).forEach(key => {
965 try {
966 rollupAliases[key] = resolveFrom(pkg.directory, aliases[key]);
967 } catch (err) {
968 if ("MODULE_NOT_FOUND" !== err.code) throw err;
969 }
970 });
971 let input = {};
972 return entrypoints.forEach(entrypoint => {
973 input[path.relative(pkg.directory, path.join(entrypoint.directory, "dist", getNameForDist(pkg.name)))] = entrypoint.strict().source;
974 }), {
975 input: input,
976 external: makeExternalPredicate(external),
977 onwarn: warning => {
978 switch (warning.code) {
979 case "EMPTY_BUNDLE":
980 case "CIRCULAR_DEPENDENCY":
981 case "UNUSED_EXTERNAL_IMPORT":
982 break;
983
984 case "UNRESOLVED_IMPORT":
985 if (/^@babel\/runtime\/helpers\//.test(warning.source)) throw (async () => {
986 if (!await confirms.shouldInstallBabelRuntime(pkg)) throw new FatalError(`@babel/runtime should be in dependencies of ${pkg.name}`, pkg.name);
987 await limit(() => installPackages({
988 packages: [ "@babel/runtime" ],
989 cwd: pkg.directory,
990 installPeers: !1,
991 packageManager: pkg.project.isBolt ? "bolt" : void 0
992 })), await pkg.refresh();
993 })();
994 if (!warning.source.startsWith(".")) 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);
995
996 default:
997 throw new FatalError(`There was an error compiling ${pkg.name}: ${chalk.red(warning.toString())}`, pkg.name);
998 }
999 },
1000 plugins: [ "node-prod" === type && flowAndNodeDevProdEntry(pkg), "node-prod" === type && typescriptDeclarations(pkg), rollupPluginBabel({
1001 cwd: pkg.project.directory,
1002 plugins: [ [ require.resolve("@babel/plugin-transform-runtime"), {
1003 useESModules: !0
1004 } ] ],
1005 extensions: EXTENSIONS
1006 }), "umd" === type && cjs({
1007 include: [ "**/node_modules/**", "node_modules/**" ]
1008 }), ("browser" === type || "umd" === type) && replace({
1009 "typeof document": JSON.stringify("object"),
1010 "typeof window": JSON.stringify("object")
1011 }), rewriteCjsRuntimeHelpers(), json({
1012 namedExports: !1
1013 }), "umd" === type && alias(rollupAliases), resolve$1({
1014 extensions: EXTENSIONS,
1015 customResolveOptions: {
1016 moduleDirectory: "umd" === type ? "node_modules" : []
1017 }
1018 }), ("umd" === type || "node-prod" === type) && replace({
1019 "process.env.NODE_ENV": '"production"'
1020 }), "umd" === type && terser(), "node-prod" === type && terser({
1021 mangle: !1,
1022 output: {
1023 beautify: !0,
1024 indent_level: 2
1025 }
1026 }) ].filter(Boolean)
1027 };
1028};
1029
1030function getAliases(project, getKey = (x => x)) {
1031 let aliases = {};
1032 return project.packages.forEach(pkg => {
1033 pkg.entrypoints.map(x => x.strict()).forEach(entrypoint => {
1034 aliases[getKey(entrypoint.name)] = path.join(pkg.name, path.relative(entrypoint.directory, entrypoint.source));
1035 });
1036 }), aliases;
1037}
1038
1039function getGlobals(pkg) {
1040 let stuff = [];
1041 return pkg.peerDependencies && stuff.push(...Object.keys(pkg.peerDependencies)),
1042 pkg.dependencies && stuff.push(...Object.keys(pkg.dependencies)), 0 === stuff.length ? {} : (pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : []).reduce((obj, pkgName) => (obj[pkgName] = pkg.project.global(pkgName),
1043 obj), {});
1044}
1045
1046function getRollupConfigs(pkg, aliases) {
1047 let configs = [], strictEntrypoints = pkg.entrypoints.map(x => x.strict()), hasModuleField = null !== strictEntrypoints[0].module;
1048 return configs.push({
1049 config: getRollupConfig(pkg, strictEntrypoints, aliases, "node-dev"),
1050 outputs: [ {
1051 format: "cjs",
1052 entryFileNames: "[name].cjs.dev.js",
1053 chunkFileNames: "dist/[name]-[hash].cjs.dev.js",
1054 dir: pkg.directory,
1055 exports: "named"
1056 }, ...hasModuleField ? [ {
1057 format: "es",
1058 entryFileNames: "[name].esm.js",
1059 chunkFileNames: "dist/[name]-[hash].esm.js",
1060 dir: pkg.directory
1061 } ] : [] ]
1062 }), configs.push({
1063 config: getRollupConfig(pkg, strictEntrypoints, aliases, "node-prod"),
1064 outputs: [ {
1065 format: "cjs",
1066 entryFileNames: "[name].cjs.prod.js",
1067 chunkFileNames: "dist/[name]-[hash].cjs.prod.js",
1068 dir: pkg.directory,
1069 exports: "named"
1070 } ]
1071 }), null !== strictEntrypoints[0].umdMain && pkg.entrypoints.map(x => x.strict()).forEach(entrypoint => {
1072 let umdName = is(entrypoint._config.umdName, is.string);
1073 is(entrypoint.umdMain, is.string), configs.push({
1074 config: getRollupConfig(pkg, [ entrypoint ], aliases, "umd"),
1075 outputs: [ {
1076 format: "umd",
1077 sourcemap: !0,
1078 entryFileNames: "[name].umd.min.js",
1079 name: umdName,
1080 dir: pkg.directory,
1081 globals: getGlobals(pkg)
1082 } ]
1083 });
1084 }), null !== strictEntrypoints[0].browser && configs.push({
1085 config: getRollupConfig(pkg, strictEntrypoints, aliases, "browser"),
1086 outputs: [ {
1087 format: "cjs",
1088 entryFileNames: "[name].browser.cjs.js",
1089 chunkFileNames: "dist/[name]-[hash].browser.cjs.js",
1090 dir: pkg.directory,
1091 exports: "named"
1092 }, ...hasModuleField ? [ {
1093 format: "es",
1094 entryFileNames: "[name].browser.esm.js",
1095 chunkFileNames: "dist/[name]-[hash].browser.esm.js",
1096 dir: pkg.directory
1097 } ] : [] ]
1098 }), null !== strictEntrypoints[0].reactNative && configs.push({
1099 config: getRollupConfig(pkg, strictEntrypoints, aliases, "react-native"),
1100 outputs: [ {
1101 format: "cjs",
1102 entryFileNames: "[name].native.cjs.js",
1103 chunkFileNames: "dist/[name]-[hash].native.cjs.js",
1104 dir: pkg.directory,
1105 exports: "named"
1106 }, ...hasModuleField ? [ {
1107 format: "es",
1108 entryFileNames: "[name].native.esm.js",
1109 chunkFileNames: "dist/[name]-[hash].native.esm.js",
1110 dir: pkg.directory
1111 } ] : [] ]
1112 }), configs;
1113}
1114
1115let browserPattern = /typeof\s+(window|document)/;
1116
1117async function buildPackage(pkg, aliases) {
1118 let configs = getRollupConfigs(pkg, aliases);
1119 await Promise.all([ fs.remove(path.join(pkg.directory, "dist")), ...pkg.entrypoints.map(entrypoint => fs.remove(path.join(entrypoint.directory, "dist"))) ]);
1120 let hasCheckedBrowser = null !== pkg.entrypoints[0].browser;
1121 await Promise.all(configs.map(async ({config: config, outputs: outputs}) => {
1122 let bundle = await rollup(config);
1123 const nodeDevOutput = (await Promise.all(outputs.map(outputConfig => bundle.write(outputConfig))))[0].output;
1124 if (!hasCheckedBrowser) {
1125 let allCode = nodeDevOutput.map(({code: code}) => code).join("\n");
1126 if (hasCheckedBrowser = !0, browserPattern.test(allCode)) throw (async () => {
1127 if (!await confirms.addBrowserField(pkg)) throw new FatalError(errors.deniedWriteBrowserField, pkg.name);
1128 pkg.setFieldOnEntrypoints("browser"), await Promise.all(pkg.entrypoints.map(x => x.save()));
1129 })();
1130 }
1131 }));
1132}
1133
1134async function retryableBuild(pkg, aliases) {
1135 try {
1136 await buildPackage(pkg, aliases);
1137 } catch (err) {
1138 if (err instanceof Promise) return await err, void await retryableBuild(pkg, aliases);
1139 if (err instanceof FatalError) throw err;
1140 throw new UnexpectedBuildError(err, pkg.name);
1141 }
1142}
1143
1144async function build(directory) {
1145 try {
1146 createWorker(), await hasherPromise;
1147 let project = await Project.create(directory);
1148 info("building bundles!");
1149 let aliases = getAliases(project);
1150 await Promise.all(project.packages.map(pkg => retryableBuild(pkg, aliases))), success("built bundles!");
1151 } finally {
1152 destroyWorker();
1153 }
1154}
1155
1156function relativePath(id) {
1157 return path.relative(process.cwd(), id);
1158}
1159
1160async function watchPackage(pkg, aliases) {
1161 const _configs = getRollupConfigs(pkg, aliases);
1162 await fs.remove(path.join(pkg.directory, "dist"));
1163 let configs = _configs.map(config => _objectSpread({}, toUnsafeRollupConfig(config.config), {
1164 output: config.outputs
1165 }));
1166 const watcher = rollup$1.watch(configs);
1167 let reject, startResolve, errPromise = new Promise((resolve, _reject) => {
1168 reject = _reject;
1169 }), startPromise = new Promise(resolve => {
1170 startResolve = resolve;
1171 });
1172 return watcher.on("event", event => {
1173 switch (event.code) {
1174 case "FATAL":
1175 case "ERROR":
1176 reject(event.error);
1177 break;
1178
1179 case "START":
1180 startResolve();
1181 break;
1182
1183 case "BUNDLE_START":
1184 info(chalk.cyan(`bundles ${chalk.bold("string" == typeof event.input ? relativePath(event.input) : Array.isArray(event.input) ? event.input.map(relativePath).join(", ") : Object.values(event.input).map(relativePath).join(", "))}${chalk.bold(event.output.map(relativePath).join(", "))}...`), pkg.name);
1185 break;
1186
1187 case "BUNDLE_END":
1188 info(chalk.green(`created ${chalk.bold(event.output.map(relativePath).join(", "))} in ${chalk.bold(ms(event.duration))}`), pkg.name);
1189 break;
1190
1191 case "END":
1192 info("waiting for changes...", pkg.name);
1193 }
1194 }), {
1195 error: errPromise,
1196 start: startPromise
1197 };
1198}
1199
1200async function retryableWatch(pkg, aliases, getPromises, depth) {
1201 try {
1202 let {error: error, start: start} = await watchPackage(pkg, aliases);
1203 0 === depth && getPromises({
1204 start: start
1205 }), await error;
1206 } catch (err) {
1207 if (err instanceof Promise) return await err, void await retryableWatch(pkg, aliases, getPromises, depth + 1);
1208 throw err;
1209 }
1210}
1211
1212async function build$1(directory) {
1213 createWorker();
1214 let project = await Project.create(directory), aliases = getAliases(project), startCount = 0;
1215 await Promise.all(project.packages.map(pkg => retryableWatch(pkg, aliases, async ({start: start}) => {
1216 await start, ++startCount === project.packages.length && success(successes.startedWatching);
1217 }, 0)));
1218}
1219
1220async function fixEntrypoint(entrypoint) {
1221 if (validateEntrypointSource(entrypoint), null !== entrypoint.umdMain && !isUmdNameSpecified(entrypoint)) {
1222 let umdName = await promptInput(inputs.getUmdName, entrypoint);
1223 return entrypoint.umdName = umdName, await entrypoint.save(), !0;
1224 }
1225 return !1;
1226}
1227
1228async function fix(directory) {
1229 let {packages: packages} = await Project.create(directory);
1230 success((await Promise.all(packages.map(async pkg => {
1231 let didModifyInPkgFix = await fixPackage(pkg), didModifyInEntrypointsFix = (await Promise.all(pkg.entrypoints.map(fixEntrypoint))).some(x => x);
1232 return didModifyInPkgFix || didModifyInEntrypointsFix;
1233 }))).some(x => x) ? "fixed project!" : "project already valid!");
1234}
1235
1236let tsExtensionPattern = /tsx?$/;
1237
1238function cjsOnlyReexportTemplate(pathToSource) {
1239 return `// 👋 hey!!\n// you might be reading this and seeing .esm in the filename\n// and being confused why there is commonjs below this filename\n// DON'T WORRY!\n// this is intentional\n// it's only commonjs with \`preconstruct dev\`\n// when you run \`preconstruct build\`, it will be ESM\n// why is it commonjs?\n// we need to re-export every export from the source file\n// but we can't do that with ESM without knowing what the exports are (because default exports aren't included in export/import *)\n// and they could change after running \`preconstruct dev\` so we can't look at the file without forcing people to\n// run preconstruct dev again which wouldn't be ideal\n// this solution could change but for now, it's working\n\nmodule.exports = require(${JSON.stringify(pathToSource)})\n`;
1240}
1241
1242async function getTypeSystem(entrypoint) {
1243 let content = await fs.readFile(entrypoint.source, "utf8");
1244 return tsExtensionPattern.test(entrypoint.source) ? [ "typescript", content ] : content.includes("@flow") ? [ "flow", content ] : [ null, content ];
1245}
1246
1247async function writeFlowFile(typeSystemPromise, entrypoint) {
1248 let [typeSystem, content] = await typeSystemPromise;
1249 if (null === typeSystem) return;
1250 let cjsDistPath = path.join(entrypoint.directory, entrypoint.main);
1251 if ("flow" === typeSystem && await fs.symlink(entrypoint.source, cjsDistPath + ".flow"),
1252 "typescript" === typeSystem) {
1253 let ast = await babel.parseAsync(content, {
1254 filename: entrypoint.source,
1255 sourceType: "module",
1256 cwd: entrypoint.package.project.directory
1257 }), hasDefaultExport = !1;
1258 for (let statement of ast.program.body) if ("ExportDefaultDeclaration" === statement.type || "ExportNamedDeclaration" === statement.type && statement.specifiers.some(specifier => "ExportSpecifier" === specifier.type && "default" === specifier.exported.name)) {
1259 hasDefaultExport = !0;
1260 break;
1261 }
1262 await fs.writeFile(cjsDistPath + ".ts", tsTemplate(hasDefaultExport, path.relative(path.dirname(cjsDistPath), entrypoint.source).replace(/\.tsx?$/, "")));
1263 }
1264}
1265
1266async function dev(projectDir) {
1267 let project = await Project.create(projectDir);
1268 project.packages.forEach(({entrypoints: entrypoints}) => entrypoints.forEach(x => x.strict())),
1269 info("project is valid!");
1270 await Promise.all(project.packages.map(pkg => Promise.all(pkg.entrypoints.map(async _entrypoint => {
1271 let entrypoint = _entrypoint.strict(), typeSystemPromise = getTypeSystem(entrypoint);
1272 await fs.remove(path.join(entrypoint.directory, "dist")), await fs.ensureDir(path.join(entrypoint.directory, "dist"));
1273 let promises = [ writeFlowFile(typeSystemPromise, entrypoint), fs.writeFile(path.join(entrypoint.directory, entrypoint.main), `"use strict";\n\nlet unregister = require(${JSON.stringify(require.resolve("@preconstruct/hook"))}).___internalHook(${JSON.stringify(project.directory)});\n\nmodule.exports = require(${JSON.stringify(entrypoint.source)});\n\nunregister();\n`) ];
1274 entrypoint.module && promises.push(fs.writeFile(path.join(entrypoint.directory, entrypoint.module), cjsOnlyReexportTemplate(entrypoint.source)));
1275 let browserField = entrypoint.browser;
1276 if (browserField) for (let key of Object.keys(browserField)) promises.push(fs.writeFile(path.join(entrypoint.directory, browserField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
1277 let rnField = entrypoint.reactNative;
1278 if (rnField) for (let key of Object.keys(rnField)) promises.push(fs.writeFile(path.join(entrypoint.directory, rnField[key]), cjsOnlyReexportTemplate(entrypoint.source)));
1279 return Promise.all(promises);
1280 })))), await Promise.all([]), success("created links!");
1281}
1282
1283process.env.NODE_ENV = "production";
1284
1285let {input: input} = meow("\nUsage\n $ preconstruct [command]\nCommands\n init initialise a project\n build build the project\n watch start a watch process to build the project\n validate validate the project\n fix infer as much information as possible and fix the project\n dev create links so entrypoints can be imported\n\n", {}), errors$1 = {
1286 commandNotFound: "Command not found"
1287};
1288
1289class CommandNotFoundError extends Error {}
1290
1291(async () => {
1292 if (1 !== input.length) throw new CommandNotFoundError();
1293 switch (input[0]) {
1294 case "init":
1295 return void await init(process.cwd());
1296
1297 case "validate":
1298 return void await validate(process.cwd());
1299
1300 case "build":
1301 return void await build(process.cwd());
1302
1303 case "watch":
1304 return void await build$1(process.cwd());
1305
1306 case "fix":
1307 return void await fix(process.cwd());
1308
1309 case "dev":
1310 return void await dev(process.cwd());
1311
1312 default:
1313 throw new CommandNotFoundError();
1314 }
1315})().catch(err => {
1316 err instanceof FixableError ? (error(err.message, err.scope), info("The above error can be fixed automatically by running preconstruct fix", err.item)) : err instanceof FatalError ? error(err.message, err.scope) : err instanceof CommandNotFoundError ? error(errors$1.commandNotFound) : err instanceof UnexpectedBuildError ? error(err, err.scope) : error(err),
1317 process.exit(1);
1318});