@expo/cli
Version:
274 lines (273 loc) • 10.6 kB
JavaScript
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, {
ResponseContentType: ()=>ResponseContentType,
ExpoGoManifestHandlerMiddleware: ()=>ExpoGoManifestHandlerMiddleware
});
function _configPlugins() {
const data = require("@expo/config-plugins");
_configPlugins = function() {
return data;
};
return data;
}
function _accepts() {
const data = /*#__PURE__*/ _interopRequireDefault(require("accepts"));
_accepts = function() {
return data;
};
return data;
}
function _crypto() {
const data = /*#__PURE__*/ _interopRequireDefault(require("crypto"));
_crypto = function() {
return data;
};
return data;
}
function _formData() {
const data = /*#__PURE__*/ _interopRequireDefault(require("form-data"));
_formData = function() {
return data;
};
return data;
}
function _structuredHeaders() {
const data = require("structured-headers");
_structuredHeaders = function() {
return data;
};
return data;
}
const _manifestMiddleware = require("./ManifestMiddleware");
const _resolvePlatform = require("./resolvePlatform");
const _userSettings = /*#__PURE__*/ _interopRequireDefault(require("../../../api/user/UserSettings"));
const _user = require("../../../api/user/user");
const _codesigning = require("../../../utils/codesigning");
const _errors = require("../../../utils/errors");
const _telemetry = require("../../../utils/telemetry");
const _url = require("../../../utils/url");
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const debug = require("debug")("expo:start:server:middleware:ExpoGoManifestHandlerMiddleware");
var ResponseContentType;
(function(ResponseContentType) {
ResponseContentType[ResponseContentType["TEXT_PLAIN"] = 0] = "TEXT_PLAIN";
ResponseContentType[ResponseContentType["APPLICATION_JSON"] = 1] = "APPLICATION_JSON";
ResponseContentType[ResponseContentType["APPLICATION_EXPO_JSON"] = 2] = "APPLICATION_EXPO_JSON";
ResponseContentType[ResponseContentType["MULTIPART_MIXED"] = 3] = "MULTIPART_MIXED";
})(ResponseContentType || (ResponseContentType = {}));
class ExpoGoManifestHandlerMiddleware extends _manifestMiddleware.ManifestMiddleware {
getParsedHeaders(req) {
let platform = (0, _resolvePlatform.parsePlatformHeader)(req);
if (!platform) {
debug(`No "expo-platform" header or "platform" query parameter specified. Falling back to "ios".`);
platform = "ios";
}
(0, _resolvePlatform.assertRuntimePlatform)(platform);
// Expo Updates clients explicitly accept "multipart/mixed" responses while browsers implicitly
// accept them with "accept: */*". To make it easier to debug manifest responses by visiting their
// URLs in a browser, we denote the response as "text/plain" if the user agent appears not to be
// an Expo Updates client.
const accept = (0, _accepts().default)(req);
const acceptedType = accept.types([
"unknown/unknown",
"multipart/mixed",
"application/json",
"application/expo+json",
"text/plain",
]);
let responseContentType;
switch(acceptedType){
case "multipart/mixed":
responseContentType = 3;
break;
case "application/json":
responseContentType = 1;
break;
case "application/expo+json":
responseContentType = 2;
break;
default:
responseContentType = 0;
break;
}
const expectSignature = req.headers["expo-expect-signature"];
return {
responseContentType,
platform,
expectSignature: expectSignature ? String(expectSignature) : null,
hostname: (0, _url.stripPort)(req.headers["host"]),
protocol: req.headers["x-forwarded-proto"]
};
}
getDefaultResponseHeaders() {
const headers = new Map();
// set required headers for Expo Updates manifest specification
headers.set("expo-protocol-version", 0);
headers.set("expo-sfv-version", 0);
headers.set("cache-control", "private, max-age=0");
return headers;
}
async _getManifestResponseAsync(requestOptions) {
var ref, ref1;
const { exp , hostUri , expoGoConfig , bundleUrl } = await this._resolveProjectSettingsAsync(requestOptions);
var _runtimeVersion;
const runtimeVersion = await _configPlugins().Updates.getRuntimeVersionAsync(this.projectRoot, {
...exp,
runtimeVersion: (_runtimeVersion = exp.runtimeVersion) != null ? _runtimeVersion : {
policy: "sdkVersion"
}
}, requestOptions.platform);
if (!runtimeVersion) {
throw new _errors.CommandError("MANIFEST_MIDDLEWARE", `Unable to determine runtime version for platform '${requestOptions.platform}'`);
}
const codeSigningInfo = await (0, _codesigning.getCodeSigningInfoAsync)(exp, requestOptions.expectSignature, this.options.privateKeyPath);
const easProjectId = (ref = exp.extra) == null ? void 0 : (ref1 = ref.eas) == null ? void 0 : ref1.projectId;
const scopeKey = await ExpoGoManifestHandlerMiddleware.getScopeKeyAsync({
slug: exp.slug,
codeSigningInfo
});
const expoUpdatesManifest = {
id: _crypto().default.randomUUID(),
createdAt: new Date().toISOString(),
runtimeVersion,
launchAsset: {
key: "bundle",
contentType: "application/javascript",
url: bundleUrl
},
assets: [],
metadata: {},
extra: {
eas: {
projectId: easProjectId != null ? easProjectId : undefined
},
expoClient: {
...exp,
hostUri
},
expoGo: expoGoConfig,
scopeKey
}
};
const stringifiedManifest = JSON.stringify(expoUpdatesManifest);
let manifestPartHeaders = null;
let certificateChainBody = null;
if (codeSigningInfo) {
const signature = (0, _codesigning.signManifestString)(stringifiedManifest, codeSigningInfo);
manifestPartHeaders = {
"expo-signature": (0, _structuredHeaders().serializeDictionary)(convertToDictionaryItemsRepresentation({
keyid: codeSigningInfo.keyId,
sig: signature,
alg: "rsa-v1_5-sha256"
}))
};
certificateChainBody = codeSigningInfo.certificateChainForResponse.join("\n");
}
const headers = this.getDefaultResponseHeaders();
switch(requestOptions.responseContentType){
case 3:
{
const form = this.getFormData({
stringifiedManifest,
manifestPartHeaders,
certificateChainBody
});
headers.set("content-type", `multipart/mixed; boundary=${form.getBoundary()}`);
return {
body: form.getBuffer().toString(),
version: runtimeVersion,
headers
};
}
case 2:
case 1:
case 0:
{
headers.set("content-type", ExpoGoManifestHandlerMiddleware.getContentTypeForResponseContentType(requestOptions.responseContentType));
if (manifestPartHeaders) {
Object.entries(manifestPartHeaders).forEach(([key, value])=>{
headers.set(key, value);
});
}
return {
body: stringifiedManifest,
version: runtimeVersion,
headers
};
}
}
}
static getContentTypeForResponseContentType(responseContentType) {
switch(responseContentType){
case 3:
return "multipart/mixed";
case 2:
return "application/expo+json";
case 1:
return "application/json";
case 0:
return "text/plain";
}
}
getFormData({ stringifiedManifest , manifestPartHeaders , certificateChainBody }) {
const form = new (_formData()).default();
form.append("manifest", stringifiedManifest, {
contentType: "application/json",
header: {
...manifestPartHeaders
}
});
if (certificateChainBody && certificateChainBody.length > 0) {
form.append("certificate_chain", certificateChainBody, {
contentType: "application/x-pem-file"
});
}
return form;
}
trackManifest(version) {
(0, _telemetry.logEventAsync)("Serve Expo Updates Manifest", {
runtimeVersion: version
});
}
static async getScopeKeyAsync({ slug , codeSigningInfo }) {
const scopeKeyFromCodeSigningInfo = codeSigningInfo == null ? void 0 : codeSigningInfo.scopeKey;
if (scopeKeyFromCodeSigningInfo) {
return scopeKeyFromCodeSigningInfo;
}
// Log.warn(
// env.EXPO_OFFLINE
// ? 'Using anonymous scope key in manifest for offline mode.'
// : 'Using anonymous scope key in manifest.'
// );
return await getAnonymousScopeKeyAsync(slug);
}
}
async function getAnonymousScopeKeyAsync(slug) {
const userAnonymousIdentifier = await _userSettings.default.getAnonymousIdentifierAsync();
return `@${_user.ANONYMOUS_USERNAME}/${slug}-${userAnonymousIdentifier}`;
}
function convertToDictionaryItemsRepresentation(obj) {
return new Map(Object.entries(obj).map(([k, v])=>{
return [
k,
[
v,
new Map()
]
];
}));
}
//# sourceMappingURL=ExpoGoManifestHandlerMiddleware.js.map
;