"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.constructBundleUrlAsync = constructBundleUrlAsync; exports.constructManifestUrlAsync = constructManifestUrlAsync; exports.constructHostUriAsync = constructHostUriAsync; exports.constructLogUrlAsync = constructLogUrlAsync; exports.constructUrlWithExtensionAsync = constructUrlWithExtensionAsync; exports.constructPublishUrlAsync = constructPublishUrlAsync; exports.constructSourceMapUrlAsync = constructSourceMapUrlAsync; exports.constructAssetsUrlAsync = constructAssetsUrlAsync; exports.constructDebuggerHostAsync = constructDebuggerHostAsync; exports.constructBundleQueryParamsAsync = constructBundleQueryParamsAsync; exports.constructWebAppUrlAsync = constructWebAppUrlAsync; exports.constructUrlAsync = constructUrlAsync; exports.guessMainModulePath = guessMainModulePath; exports.randomIdentifier = randomIdentifier; exports.sevenDigitIdentifier = sevenDigitIdentifier; exports.randomIdentifierForUser = randomIdentifierForUser; exports.someRandomness = someRandomness; exports.domainify = domainify; exports.getPlatformSpecificBundleUrl = getPlatformSpecificBundleUrl; exports.isHttps = isHttps; function _joi() { const data = _interopRequireDefault(require("joi")); _joi = function () { return data; }; return data; } function _os() { const data = _interopRequireDefault(require("os")); _os = function () { return data; }; return data; } function _url() { const data = _interopRequireDefault(require("url")); _url = function () { return data; }; return data; } function _validator() { const data = _interopRequireDefault(require("validator")); _validator = function () { return data; }; return data; } function ConfigUtils() { const data = _interopRequireWildcard(require("@expo/config")); ConfigUtils = function () { return data; }; return data; } function _ip() { const data = _interopRequireDefault(require("./ip")); _ip = function () { return data; }; return data; } function _Config() { const data = _interopRequireDefault(require("./Config")); _Config = function () { return data; }; return data; } function Exp() { const data = _interopRequireWildcard(require("./Exp")); Exp = function () { return data; }; return data; } function ProjectSettings() { const data = _interopRequireWildcard(require("./ProjectSettings")); ProjectSettings = function () { return data; }; return data; } function ProjectUtils() { const data = _interopRequireWildcard(require("./project/ProjectUtils")); ProjectUtils = function () { return data; }; return data; } function Versions() { const data = _interopRequireWildcard(require("./Versions")); Versions = function () { return data; }; return data; } function _XDLError() { const data = _interopRequireDefault(require("./XDLError")); _XDLError = function () { return data; }; return data; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } async function constructBundleUrlAsync(projectRoot, opts, requestHostname) { return constructUrlAsync(projectRoot, opts, true, requestHostname); } async function constructManifestUrlAsync(projectRoot, opts, requestHostname) { return constructUrlAsync(projectRoot, opts, false, requestHostname); } // gets the base manifest URL and removes the scheme async function constructHostUriAsync(projectRoot, requestHostname) { let urlString = await constructUrlAsync(projectRoot, null, false, requestHostname); // we need to use node's legacy urlObject api since the newer one doesn't like empty protocols let urlObj = _url().default.parse(urlString); urlObj.protocol = ''; urlObj.slashes = false; return _url().default.format(urlObj); } async function constructLogUrlAsync(projectRoot, requestHostname) { let baseUrl = await constructUrlAsync(projectRoot, { urlType: 'http' }, false, requestHostname); return `${baseUrl}/logs`; } async function constructUrlWithExtensionAsync(projectRoot, entryPoint, ext, requestHostname, opts) { const defaultOpts = { dev: false, minify: true }; opts = opts || defaultOpts; let bundleUrl = await constructBundleUrlAsync(projectRoot, { hostType: 'localhost', urlType: 'http' }, requestHostname); let mainModulePath = guessMainModulePath(entryPoint); bundleUrl += `/${mainModulePath}.${ext}`; let queryParams = await constructBundleQueryParamsAsync(projectRoot, opts); return `${bundleUrl}?${queryParams}`; } async function constructPublishUrlAsync(projectRoot, entryPoint, requestHostname, opts) { return await constructUrlWithExtensionAsync(projectRoot, entryPoint, 'bundle', requestHostname, opts); } async function constructSourceMapUrlAsync(projectRoot, entryPoint, requestHostname) { return await constructUrlWithExtensionAsync(projectRoot, entryPoint, 'map', requestHostname); } async function constructAssetsUrlAsync(projectRoot, entryPoint, requestHostname) { return await constructUrlWithExtensionAsync(projectRoot, entryPoint, 'assets', requestHostname); } async function constructDebuggerHostAsync(projectRoot, requestHostname) { return constructUrlAsync(projectRoot, { urlType: 'no-protocol' }, true, requestHostname); } async function constructBundleQueryParamsAsync(projectRoot, opts) { let queryParams = `dev=${encodeURIComponent(!!opts.dev)}`; if (opts.hasOwnProperty('strict')) { queryParams += `&strict=${encodeURIComponent(!!opts.strict)}`; } if (opts.hasOwnProperty('minify')) { queryParams += `&minify=${encodeURIComponent(!!opts.minify)}`; } queryParams += '&hot=false'; let { exp } = await ConfigUtils().readConfigJsonAsync(projectRoot); // SDK11 to SDK32 require us to inject hashAssetFiles through the params, but this is not // needed with SDK33+ let supportsAssetPlugins = Versions().gteSdkVersion(exp, '11.0.0'); let usesAssetPluginsQueryParam = supportsAssetPlugins && Versions().lteSdkVersion(exp, '32.0.0'); if (usesAssetPluginsQueryParam) { // Use an absolute path here so that we can not worry about symlinks/relative requires let pluginModule = ConfigUtils().resolveModule('expo/tools/hashAssetFiles', projectRoot, exp); queryParams += `&assetPlugin=${encodeURIComponent(pluginModule)}`; } else if (!supportsAssetPlugins) { // Only sdk-10.1.0+ supports the assetPlugin parameter. We use only the // major version in the sdkVersion field, so check for 11.0.0 to be sure. if (!supportsAssetPlugins) { queryParams += '&includeAssetFileHashes=true'; } } return queryParams; } async function constructWebAppUrlAsync(projectRoot) { let packagerInfo = await ProjectSettings().readPackagerInfoAsync(projectRoot); if (!packagerInfo.webpackServerPort) { return null; } const host = _ip().default.address(); const { https } = await ProjectSettings().readAsync(projectRoot); let urlType = 'http'; if (https === true) { urlType = 'https'; } return `${urlType}://${host}:${packagerInfo.webpackServerPort}`; } async function constructUrlAsync(projectRoot, opts, isPackager, requestHostname) { if (opts) { let schema = _joi().default.object().keys({ urlType: _joi().default.any().valid('exp', 'http', 'redirect', 'no-protocol'), lanType: _joi().default.any().valid('ip', 'hostname'), hostType: _joi().default.any().valid('localhost', 'lan', 'tunnel'), dev: _joi().default.boolean(), strict: _joi().default.boolean(), minify: _joi().default.boolean(), https: _joi().default.boolean().optional(), urlRandomness: _joi().default.string().optional().allow(null) }); const { error } = _joi().default.validate(opts, schema); if (error) { throw new (_XDLError().default)('INVALID_OPTIONS', error.toString()); } } let defaultOpts = await ProjectSettings().getPackagerOptsAsync(projectRoot); if (!opts) { opts = defaultOpts; } else { opts = Object.assign({}, defaultOpts, opts); } let packagerInfo = await ProjectSettings().readPackagerInfoAsync(projectRoot); let protocol; if (opts.urlType === 'http') { protocol = 'http'; } else if (opts.urlType === 'no-protocol') { protocol = null; } else { protocol = 'exp'; let { exp } = await ConfigUtils().readConfigJsonAsync(projectRoot); if (exp.detach) { if (exp.scheme && Versions().gteSdkVersion(exp, '27.0.0')) { protocol = exp.scheme; } else if (exp.detach.scheme) { // must keep this fallback in place for older projects // and those detached with an older version of xdl protocol = exp.detach.scheme; } } } let hostname; let port; const proxyURL = isPackager ? process.env.EXPO_PACKAGER_PROXY_URL : process.env.EXPO_MANIFEST_PROXY_URL; if (proxyURL) { const parsedProxyURL = _url().default.parse(proxyURL); hostname = parsedProxyURL.hostname; port = parsedProxyURL.port; if (parsedProxyURL.protocol === 'https:') { if (protocol === 'http') { protocol = 'https'; } if (!port) { port = '443'; } } } else if (opts.hostType === 'localhost' || requestHostname === 'localhost') { hostname = '127.0.0.1'; port = isPackager ? packagerInfo.packagerPort : packagerInfo.expoServerPort; } else if (opts.hostType === 'lan' || _Config().default.offline) { if (process.env.EXPO_PACKAGER_HOSTNAME) { hostname = process.env.EXPO_PACKAGER_HOSTNAME.trim(); } else if (process.env.REACT_NATIVE_PACKAGER_HOSTNAME) { hostname = process.env.REACT_NATIVE_PACKAGER_HOSTNAME.trim(); } else if (opts.lanType === 'ip') { if (requestHostname) { hostname = requestHostname; } else { hostname = _ip().default.address(); } } else { // Some old versions of OSX work with hostname but not local ip address. hostname = _os().default.hostname(); } port = isPackager ? packagerInfo.packagerPort : packagerInfo.expoServerPort; } else { let ngrokUrl = isPackager ? packagerInfo.packagerNgrokUrl : packagerInfo.expoServerNgrokUrl; if (!ngrokUrl || typeof ngrokUrl !== 'string') { ProjectUtils().logWarning(projectRoot, 'expo', 'Tunnel URL not found, falled back to LAN URL.', 'tunnel-url-not-found'); return constructUrlAsync(projectRoot, { ...opts, hostType: 'lan' }, isPackager, requestHostname); } else { ProjectUtils().clearNotification(projectRoot, 'tunnel-url-not-found'); let pnu = _url().default.parse(ngrokUrl); hostname = pnu.hostname; port = pnu.port; } } let url_ = ''; if (protocol) { url_ += `${protocol}://`; } if (!hostname) { throw new Error('Hostname cannot be inferred.'); } url_ += hostname; if (port) { url_ += `:${port}`; } else { // Android HMR breaks without this :| url_ += ':80'; } if (opts.urlType === 'redirect') { return `https://exp.host/--/to-exp/${encodeURIComponent(url_)}`; } return url_; } function guessMainModulePath(entryPoint) { return entryPoint.replace(/\.js$/, ''); } function randomIdentifier(length = 6) { let alphabet = '23456789qwertyuipasdfghjkzxcvbnm'; let result = ''; for (let i = 0; i < length; i++) { let j = Math.floor(Math.random() * alphabet.length); let c = alphabet.substr(j, 1); result += c; } return result; } function sevenDigitIdentifier() { return `${randomIdentifier(3)}-${randomIdentifier(4)}`; } function randomIdentifierForUser(username) { return `${username}-${randomIdentifier(3)}-${randomIdentifier(2)}`; } function someRandomness() { return [randomIdentifier(2), randomIdentifier(3)].join('-'); } function domainify(s) { return s.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/^-+/, '').replace(/-+$/, ''); } function getPlatformSpecificBundleUrl(url, platform) { if (url.includes(Exp().ENTRY_POINT_PLATFORM_TEMPLATE_STRING)) { return url.replace(Exp().ENTRY_POINT_PLATFORM_TEMPLATE_STRING, platform); } else { return url; } } function isHttps(url) { return _validator().default.isURL(url, { protocols: ['https'] }); } //# sourceMappingURL=__sourcemaps__/UrlUtils.js.map