UNPKG

@expo/cli

Version:
198 lines (197 loc) 7.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { validateBundleId: ()=>validateBundleId, validatePackage: ()=>validatePackage, validatePackageWithWarning: ()=>validatePackageWithWarning, assertValidBundleId: ()=>assertValidBundleId, assertValidPackage: ()=>assertValidPackage, getBundleIdWarningInternalAsync: ()=>getBundleIdWarningInternalAsync, getBundleIdWarningAsync: ()=>getBundleIdWarningAsync, getPackageNameWarningInternalAsync: ()=>getPackageNameWarningInternalAsync, getPackageNameWarningAsync: ()=>getPackageNameWarningAsync }); function _assert() { const data = /*#__PURE__*/ _interopRequireDefault(require("assert")); _assert = function() { return data; }; return data; } function _chalk() { const data = /*#__PURE__*/ _interopRequireDefault(require("chalk")); _chalk = function() { return data; }; return data; } const _env = require("./env"); const _fn = require("./fn"); const _link = require("./link"); const _url = require("./url"); const _client = require("../api/rest/client"); const _log = require("../log"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const debug = require("debug")("expo:utils:validateApplicationId"); const IOS_BUNDLE_ID_REGEX = /^[a-zA-Z0-9-.]+$/; const ANDROID_PACKAGE_REGEX = /^(?!.*\bnative\b)[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$/; function validateBundleId(value) { return IOS_BUNDLE_ID_REGEX.test(value); } function validatePackage(value) { return validatePackageWithWarning(value) === true; } function validatePackageWithWarning(value) { const parts = value.split("."); for (const segment of parts){ if (RESERVED_ANDROID_PACKAGE_NAME_SEGMENTS.includes(segment)) { return `"${segment}" is a reserved Java keyword.`; } } if (parts.length < 2) { return `Package name must contain more than one segment, separated by ".", e.g. com.${value}`; } if (!ANDROID_PACKAGE_REGEX.test(value)) { return 'Invalid characters in Android package name. Only alphanumeric characters, "." and "_" are allowed, and each "." must be followed by a letter or number.'; } return true; } // https://en.wikipedia.org/wiki/List_of_Java_keywords // Running the following in the console and pruning the "Reserved Identifiers" section: // [...document.querySelectorAll('dl > dt > code')].map(node => node.innerText) const RESERVED_ANDROID_PACKAGE_NAME_SEGMENTS = [ // List of Java keywords "_", "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", // Reserved words for literal values "true", "false", "null", // Unused "const", "goto", "strictfp", ]; function assertValidBundleId(value) { _assert().default.match(value, IOS_BUNDLE_ID_REGEX, `The ios.bundleIdentifier defined in your Expo config is not formatted properly. Only alphanumeric characters, '.', '-', and '_' are allowed, and each '.' must be followed by a letter.`); } function assertValidPackage(value) { _assert().default.match(value, ANDROID_PACKAGE_REGEX, `Invalid format of Android package name. Only alphanumeric characters, '.' and '_' are allowed, and each '.' must be followed by a letter. The Java keyword 'native' is not allowed.`); } async function getBundleIdWarningInternalAsync(bundleId) { if (_env.env.EXPO_OFFLINE) { _log.Log.warn("Skipping Apple bundle identifier reservation validation in offline-mode."); return null; } if (!await (0, _url.isUrlAvailableAsync)("itunes.apple.com")) { debug(`Couldn't connect to iTunes Store to check bundle ID ${bundleId}. itunes.apple.com may be down.`); // If no network, simply skip the warnings since they'll just lead to more confusion. return null; } const url = `http://itunes.apple.com/lookup?bundleId=${bundleId}`; try { debug(`Checking iOS bundle ID '${bundleId}' at: ${url}`); const response = await (0, _client.fetchAsync)(url); const json = await response.json(); if (json.resultCount > 0) { const firstApp = json.results[0]; return formatInUseWarning(firstApp.trackName, firstApp.sellerName, bundleId); } } catch (error) { debug(`Error checking bundle ID ${bundleId}: ${error.message}`); // Error fetching itunes data. } return null; } const getBundleIdWarningAsync = (0, _fn.memoize)(getBundleIdWarningInternalAsync); async function getPackageNameWarningInternalAsync(packageName) { if (_env.env.EXPO_OFFLINE) { _log.Log.warn("Skipping Android package name reservation validation in offline-mode."); return null; } if (!await (0, _url.isUrlAvailableAsync)("play.google.com")) { debug(`Couldn't connect to Play Store to check package name ${packageName}. play.google.com may be down.`); // If no network, simply skip the warnings since they'll just lead to more confusion. return null; } const url = `https://play.google.com/store/apps/details?id=${packageName}`; try { debug(`Checking Android package name '${packageName}' at: ${url}`); const response = await (0, _client.fetchAsync)(url); // If the page exists, then warn the user. if (response.status === 200) { // There is no JSON API for the Play Store so we can't concisely // locate the app name and developer to match the iOS warning. return `⚠️ The package ${_chalk().default.bold(packageName)} is already in use. ${_chalk().default.dim((0, _link.learnMore)(url))}`; } } catch (error) { // Error fetching play store data or the page doesn't exist. debug(`Error checking package name ${packageName}: ${error.message}`); } return null; } function formatInUseWarning(appName, author, id) { return `⚠️ The app ${_chalk().default.bold(appName)} by ${_chalk().default.italic(author)} is already using ${_chalk().default.bold(id)}`; } const getPackageNameWarningAsync = (0, _fn.memoize)(getPackageNameWarningInternalAsync); //# sourceMappingURL=validateApplicationId.js.map