You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
14 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.actionAsync = actionAsync;
exports.isInvalidReleaseChannel = isInvalidReleaseChannel;
exports.logBareWorkflowWarnings = logBareWorkflowWarnings;
exports.logExpoUpdatesWarnings = logExpoUpdatesWarnings;
function _config() {
const data = require("@expo/config");
_config = function () {
return data;
};
return data;
}
function _spawnAsync() {
const data = _interopRequireDefault(require("@expo/spawn-async"));
_spawnAsync = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _resolveFrom() {
const data = _interopRequireDefault(require("resolve-from"));
_resolveFrom = function () {
return data;
};
return data;
}
function _xdl() {
const data = require("xdl");
_xdl = function () {
return data;
};
return data;
}
function _CommandError() {
const data = _interopRequireWildcard(require("../../CommandError"));
_CommandError = function () {
return data;
};
return data;
}
function _log() {
const data = _interopRequireDefault(require("../../log"));
_log = function () {
return data;
};
return data;
}
function _ora() {
const data = require("../../utils/ora");
_ora = function () {
return data;
};
return data;
}
function _prompts() {
const data = require("../../utils/prompts");
_prompts = function () {
return data;
};
return data;
}
function TerminalLink() {
const data = _interopRequireWildcard(require("../utils/TerminalLink"));
TerminalLink = function () {
return data;
};
return data;
}
function _logConfigWarnings() {
const data = require("../utils/logConfigWarnings");
_logConfigWarnings = function () {
return data;
};
return data;
}
function sendTo() {
const data = _interopRequireWildcard(require("../utils/sendTo"));
sendTo = function () {
return data;
};
return data;
}
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const EAS_UPDATE_URL = 'https://u.expo.dev';
async function actionAsync(projectRoot, options = {}) {
var _options$target;
assertValidReleaseChannel(options.releaseChannel);
const {
exp,
pkg
} = (0, _config().getConfig)(projectRoot, {
skipSDKVersionRequirement: true
});
await confirmExpoUpdatesInstalledAsync(projectRoot);
assertUpdateURLCorrectlyConfigured(exp);
const {
sdkVersion,
runtimeVersion
} = exp;
// TODO(@jkhales): remove this check when runtimeVersion policies are supported, if they are ever supported
if (typeof runtimeVersion !== 'undefined' && typeof runtimeVersion !== 'string') {
throw new (_CommandError().default)(_CommandError().ErrorCodes.INVALID_RUNTIME_VERSION, `Runtime version policies are not supported by the publish command.`);
}
const target = (_options$target = options.target) !== null && _options$target !== void 0 ? _options$target : (0, _config().getDefaultTarget)(projectRoot);
// note: this validates the exp.owner when the user is a robot
const user = await _xdl().UserManager.ensureLoggedInAsync();
const owner = _xdl().UserManager.getProjectOwner(user, exp);
_log().default.addNewLineIfNone();
// Log building info before building.
// This gives the user sometime to bail out if the info is unexpected.
if (runtimeVersion) {
_log().default.log(`\u203A Runtime version: ${_chalk().default.bold(runtimeVersion)}`);
} else if (sdkVersion) {
_log().default.log(`\u203A Expo SDK: ${_chalk().default.bold(sdkVersion)}`);
}
_log().default.log(`\u203A Release channel: ${_chalk().default.bold(options.releaseChannel)}`);
_log().default.log(`\u203A Workflow: ${_chalk().default.bold(target.replace(/\b\w/g, l => l.toUpperCase()))}`);
if (user.kind === 'robot') {
_log().default.log(`\u203A Owner: ${_chalk().default.bold(owner)}`);
}
_log().default.newLine();
// Log warnings.
logExpoUpdatesWarnings(pkg);
if (!options.target && target === 'bare' && (0, _config().isLegacyImportsEnabled)(exp)) {
logBareWorkflowWarnings(pkg);
}
_log().default.addNewLineIfNone();
// Build and publish the project.
let spinner = null;
if (options.quiet) {
spinner = (0, _ora().logNewSection)(`Building optimized bundles and generating sourcemaps...`);
} else {
_log().default.log(`Building optimized bundles and generating sourcemaps...`);
}
const result = await _xdl().Project.publishAsync(projectRoot, {
releaseChannel: options.releaseChannel,
quiet: options.quiet,
maxWorkers: options.maxWorkers,
target,
resetCache: options.clear
});
const url = result.url;
const projectPageUrl = result.projectPageUrl;
if (options.quiet && spinner) {
spinner.succeed();
}
_log().default.log('Publish complete');
_log().default.newLine();
logManifestUrl({
url,
sdkVersion,
runtimeVersion
});
if (target === 'managed' && projectPageUrl) {
// note(brentvatne): disable copy to clipboard functionality for now, need to think more about
// whether this is desirable.
//
// Attempt to copy the URL to the clipboard, if it succeeds then append a notice to the log.
// const copiedToClipboard = copyToClipboard(websiteUrl);
logProjectPageUrl({
url: projectPageUrl,
copiedToClipboard: false
});
// Only send the link for managed projects.
const recipient = await sendTo().getRecipient(options.sendTo);
if (recipient) {
await sendTo().sendUrlAsync(projectPageUrl, recipient);
}
}
_log().default.newLine();
return result;
}
function isInvalidReleaseChannel(releaseChannel) {
const channelRe = new RegExp(/^[a-z\d][a-z\d._-]*$/);
return !!releaseChannel && !channelRe.test(releaseChannel);
}
// TODO(Bacon): should we prompt with a normalized value?
function assertValidReleaseChannel(releaseChannel) {
if (isInvalidReleaseChannel(releaseChannel)) {
throw new (_CommandError().default)('Release channel name can only contain lowercase letters, numbers and special characters . _ and -');
}
}
async function isExpoUpdatesInstalledAsync(projectDir) {
try {
(0, _resolveFrom().default)(projectDir, 'expo-updates/package.json');
return true;
} catch (err) {
_log().default.debug(err);
return false;
}
}
async function installExpoUpdatesAsync(projectDir) {
const expoCliPath = (0, _resolveFrom().default)(projectDir, 'expo/bin/cli.js');
_log().default.newLine();
_log().default.log(`Running ${_chalk().default.bold('expo install expo-updates')}`);
_log().default.newLine();
await (0, _spawnAsync().default)(expoCliPath, ['install', 'expo-updates']);
_log().default.newLine();
}
async function confirmExpoUpdatesInstalledAsync(projectDir) {
if (await isExpoUpdatesInstalledAsync(projectDir)) {
return;
}
const isBare = (0, _config().getDefaultTarget)(projectDir) === 'bare';
if (isBare) {
throw new (_CommandError().default)(`This project is missing ${_chalk().default.bold('expo-updates')}. Please install it in order to publish an update. ${_chalk().default.dim(TerminalLink().learnMore('https://docs.expo.dev/bare/installing-updates/'))}`);
}
const install = await (0, _prompts().confirmAsync)({
message: `In order to publish an update, ${_chalk().default.bold('expo-updates')} needs to be installed. Do you want to install it now?`
});
if (install) {
await installExpoUpdatesAsync(projectDir);
} else {
throw new (_CommandError().default)(`This project is missing ${_chalk().default.bold('expo-updates')}. Please install it in order to publish an update.`);
}
}
function isMaybeAnEASUrl(url) {
return url.includes(EAS_UPDATE_URL);
}
function assertUpdateURLCorrectlyConfigured(exp) {
var _exp$updates;
const configuredURL = (_exp$updates = exp.updates) === null || _exp$updates === void 0 ? void 0 : _exp$updates.url;
if (!configuredURL) {
// If no URL is configured, we generate a classic updates URL in the expo-updates config-plugin.
return;
}
if (isMaybeAnEASUrl(configuredURL)) {
throw new (_CommandError().default)(_CommandError().ErrorCodes.INVALID_UPDATE_URL, `It seems like your project is configured for EAS Update. Please use 'eas update' instead.`);
}
}
/**
* @example 📝 Manifest: https://exp.host/@bacon/my-app/index.exp?sdkVersion=38.0.0 Learn more: https://expo.fyi/manifest-url
* @param options
*/
function logManifestUrl({
url,
sdkVersion,
runtimeVersion
}) {
var _getExampleManifestUr;
const manifestUrl = (_getExampleManifestUr = getExampleManifestUrl(url, {
sdkVersion,
runtimeVersion
})) !== null && _getExampleManifestUr !== void 0 ? _getExampleManifestUr : url;
_log().default.log(`📝 Manifest: ${_chalk().default.bold(TerminalLink().fallbackToUrl(url, manifestUrl))} ${_chalk().default.dim(TerminalLink().learnMore('https://expo.fyi/manifest-url'))}`);
}
/**
*
* @example ⚙️ Project page: https://expo.dev/@bacon/projects/my-app [copied to clipboard] Learn more: https://expo.fyi/project-page
* @param options
*/
function logProjectPageUrl({
url,
copiedToClipboard
}) {
let productionMessage = `⚙️ Project page: ${_chalk().default.bold(TerminalLink().fallbackToUrl(url, url))}`;
if (copiedToClipboard) {
productionMessage += ` ${_chalk().default.gray(`[copied to clipboard]`)}`;
}
productionMessage += ` ${_chalk().default.dim(TerminalLink().learnMore('https://expo.fyi/project-page'))}`;
_log().default.log(productionMessage);
}
function getExampleManifestUrl(url, {
sdkVersion,
runtimeVersion
}) {
if (!(sdkVersion || runtimeVersion)) {
return null;
}
if (url.includes('release-channel') && url.includes('?release-channel')) {
const urlWithIndexSuffix = url.replace('?release-channel', '/index.exp?release-channel');
return runtimeVersion ? urlWithIndexSuffix + `&runtimeVersion=${runtimeVersion}` : urlWithIndexSuffix + `&sdkVersion=${sdkVersion}`;
} else if (url.includes('?') && !url.includes('release-channel')) {
// This is the only relevant url query param we are aware of at the time of
// writing this code, so if there is some other param included we don't know
// how to deal with it and log nothing.
return null;
} else {
return runtimeVersion ? `${url}/index.exp?runtimeVersion=${runtimeVersion}` : `${url}/index.exp?sdkVersion=${sdkVersion}`;
}
}
function logExpoUpdatesWarnings(pkg) {
var _pkg$dependencies, _pkg$dependencies2;
const hasConflictingUpdatesPackages = ((_pkg$dependencies = pkg.dependencies) === null || _pkg$dependencies === void 0 ? void 0 : _pkg$dependencies['expo-updates']) && ((_pkg$dependencies2 = pkg.dependencies) === null || _pkg$dependencies2 === void 0 ? void 0 : _pkg$dependencies2['expokit']);
if (!hasConflictingUpdatesPackages) {
return;
}
_log().default.nestedWarn((0, _logConfigWarnings().formatNamedWarning)('Conflicting Updates', `You have both the ${_chalk().default.bold('expokit')} and ${_chalk().default.bold('expo-updates')} packages installed in package.json.\n These two packages are incompatible and ${_chalk().default.bold('publishing updates with expo-updates will not work if expokit is installed')}.\n If you intend to use ${_chalk().default.bold('expo-updates')}, please remove ${_chalk().default.bold('expokit')} from your dependencies.`));
}
/**
* Warn users if they attempt to publish in a bare project that may also be
* using Expo Go and does not If the developer does not have the Expo
* package installed then we do not need to warn them as there is no way that
* it will run in Expo Go in development even. We should revisit this with
* dev client, and possibly also by excluding SDK version for bare
* expo-updates usage in the future (and then surfacing this as an error in
* the Expo Go app instead)
*
* Related: https://github.com/expo/expo/issues/9517
*
* @param pkg package.json
*/
function logBareWorkflowWarnings(pkg) {
var _pkg$dependencies3;
const hasExpoInstalled = (_pkg$dependencies3 = pkg.dependencies) === null || _pkg$dependencies3 === void 0 ? void 0 : _pkg$dependencies3['expo'];
if (!hasExpoInstalled) {
return;
}
_log().default.nestedWarn((0, _logConfigWarnings().formatNamedWarning)('Workflow target', `This is a ${_chalk().default.bold('bare workflow')} project. The resulting publish will only run properly inside of a native build of your project. If you want to publish a version of your app that will run in Expo Go, please use ${_chalk().default.bold('expo publish --target managed')}. You can skip this warning by explicitly running ${_chalk().default.bold('expo publish --target bare')} in the future.`));
}
//# sourceMappingURL=publishAsync.js.map