UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

310 lines (308 loc) • 12.3 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var updatesPublish_exports = {}; __export(updatesPublish_exports, { runUpdatesPublish: () => runUpdatesPublish }); module.exports = __toCommonJS(updatesPublish_exports); var import_child_process = require("child_process"); var import_crypto = require("crypto"); var import_fs = require("fs"); var import_module = require("module"); var import_os = require("os"); var import_path = require("path"); var import_appManifest = require("../native/appManifest.native.js"); var import_loadConfig = require("../vite/loadConfig.native.js"); function lastValue(value) { return Array.isArray(value) ? value[value.length - 1] : value; } function allValues(value) { if (value === void 0) return []; return Array.isArray(value) ? value : [value]; } function base64Url(bytes) { return bytes.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); } function sha256Base64Url(path) { return base64Url((0, import_crypto.createHash)("sha256").update((0, import_fs.readFileSync)(path)).digest()); } function parseMetadata(entries) { var metadata = {}; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var entry = _step.value; var equals = entry.indexOf("="); if (equals <= 0) { throw new Error(`[one] --metadata must look like key=value, got "${entry}"`); } var key = entry.slice(0, equals); var raw = entry.slice(equals + 1); var value = raw; try { var parsed = JSON.parse(raw); if (typeof parsed === "string" || typeof parsed === "number" || typeof parsed === "boolean") { value = parsed; } } catch (unused) {} metadata[key] = value; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return metadata; } function collectFiles(root) { var files = []; var visit = function visit1(dir) { var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = (0, import_fs.readdirSync)(dir, { withFileTypes: true })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var entry = _step.value; var path = (0, import_path.join)(dir, entry.name); if (entry.isDirectory()) visit(path); else if (entry.isFile()) files.push(path); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } }; if ((0, import_fs.existsSync)(root)) visit(root); return files.sort(); } function resolveCliJs(root) { var require2 = (0, import_module.createRequire)((0, import_path.join)(root, "package.json")); var packageJson = require2.resolve("react-native/package.json"); return (0, import_path.join)(packageJson.slice(0, -"package.json".length), "cli.js"); } function resolveNpmHermesc(root) { var require2 = (0, import_module.createRequire)((0, import_path.join)(root, "package.json")); var reactNativeJson = require2.resolve("react-native/package.json"); var nested = (0, import_module.createRequire)(reactNativeJson); var compilerJson = nested.resolve("hermes-compiler/package.json"); var dir = compilerJson.slice(0, -"package.json".length); var bin = process.platform === "darwin" ? "osx-bin" : process.platform === "win32" ? "win64-bin" : "linux64-bin"; return (0, import_path.join)(dir, "hermesc", bin, process.platform === "win32" ? "hermesc.exe" : "hermesc"); } function resolveHermesc(root, platform) { if (platform === "ios") { var pod = (0, import_path.join)(root, "ios", "Pods", "hermes-engine", "destroot", "bin", "hermesc"); if ((0, import_fs.existsSync)(pod)) return pod; } var npm = resolveNpmHermesc(root); if (!(0, import_fs.existsSync)(npm)) { throw new Error(`[one] hermesc not found at ${npm}: install dependencies${platform === "ios" ? " and run one prebuild with pod install" : ""} first`); } return npm; } async function resolveRuntimeVersion(platform, flag) { var _app_updates; var { oneOptions } = await (0, import_loadConfig.loadUserOneOptions)("build", true); var native = oneOptions === null || oneOptions === void 0 ? void 0 : oneOptions.native; var app = typeof native === "object" ? native.app : void 0; if (!app) { if (!flag) { throw new Error("[one] one updates publish needs native.app.updates.runtimeVersion, or --runtime-version for an app built with expo prebuild: the binary only takes updates published for its own runtime version"); } return flag; } (0, import_appManifest.validateNativeApp)(app, platform); var runtimeVersion = (_app_updates = app.updates) === null || _app_updates === void 0 ? void 0 : _app_updates.runtimeVersion; if (!runtimeVersion) { throw new Error("[one] one updates publish needs native.app.updates.runtimeVersion: the binary only takes updates published for its own runtime version"); } if (flag !== void 0 && flag !== runtimeVersion) { throw new Error(`[one] --runtime-version ${flag} differs from native.app.updates.runtimeVersion ${runtimeVersion}`); } return runtimeVersion; } async function runUpdatesPublish(args) { var platform = lastValue(args.platform); if (platform !== "ios" && platform !== "android") { throw new Error("[one] one updates publish needs --platform ios|android"); } var out = lastValue(args.out); if (!out) { throw new Error("[one] one updates publish needs --out <dir>"); } var intermediatesOut = lastValue(args.intermediatesOut); if (intermediatesOut) { var published = (0, import_path.resolve)(out); var debug = (0, import_path.resolve)(intermediatesOut); if (published === debug || published.startsWith(`${debug}${import_path.sep}`) || debug.startsWith(`${published}${import_path.sep}`)) { throw new Error("[one] --intermediates-out must be separate from --out"); } if ((0, import_fs.existsSync)(debug) && (0, import_fs.readdirSync)(debug).length > 0) { throw new Error(`[one] refusing to write intermediates into non-empty ${debug}`); } } var root = process.cwd(); var runtimeVersion = await resolveRuntimeVersion(platform, lastValue(args.runtimeVersion)); if ((0, import_fs.existsSync)(out) && (0, import_fs.readdirSync)(out).length > 0) { throw new Error(`[one] refusing to publish into non-empty ${out}: every publish writes a fresh directory`); } (0, import_fs.mkdirSync)(out, { recursive: true }); if (intermediatesOut) { (0, import_fs.mkdirSync)(intermediatesOut, { recursive: true }); var published1 = (0, import_fs.realpathSync)(out); var debug1 = (0, import_fs.realpathSync)(intermediatesOut); if (published1 === debug1 || published1.startsWith(`${debug1}${import_path.sep}`) || debug1.startsWith(`${published1}${import_path.sep}`)) { throw new Error("[one] --intermediates-out must be separate from --out"); } } var assetsOut = (0, import_path.join)(out, "assets"); (0, import_fs.mkdirSync)(assetsOut, { recursive: true }); var metadata = parseMetadata(allValues(args.metadata)); var work = (0, import_fs.mkdtempSync)((0, import_path.join)((0, import_os.tmpdir)(), "one-updates-publish-")); var bundleJs = (0, import_path.join)(work, "bundle.js"); var packagerMap = (0, import_path.join)(work, "bundle.js.map"); var assetsDir = (0, import_path.join)(work, "assets"); var bytecode = (0, import_path.join)(work, "main.jsbundle"); var composedMap = (0, import_path.join)(work, "main.jsbundle.map"); try { (0, import_child_process.execFileSync)(process.execPath, [ resolveCliJs(root), "bundle", "--entry-file", "index.js", "--platform", platform, "--dev", "false", "--reset-cache", "--bundle-output", bundleJs, ...intermediatesOut ? ["--sourcemap-output", packagerMap] : [], "--assets-dest", assetsDir, "--minify", platform === "ios" ? "true" : "false" ], { cwd: root, stdio: "inherit" }); var hermesc = resolveHermesc(root, platform); var hermescArgs = ["-emit-binary", "-max-diagnostic-width=80"]; if (platform === "android") hermescArgs.push("-w"); hermescArgs.push("-O"); if (intermediatesOut) hermescArgs.push("-output-source-map"); hermescArgs.push("-out", bytecode, bundleJs); try { (0, import_child_process.execFileSync)(hermesc, hermescArgs, { cwd: root, stdio: "inherit" }); } catch (error) { throw new Error(`[one] hermesc failed to compile the ${platform} update bundle${error instanceof Error ? `: ${error.message}` : ""}`); } if (intermediatesOut) { var require2 = (0, import_module.createRequire)((0, import_path.join)(root, "package.json")); var reactNativeJson = require2.resolve("react-native/package.json"); var composeSourceMaps = (0, import_path.join)(reactNativeJson.slice(0, -"package.json".length), "scripts", "compose-source-maps.js"); (0, import_child_process.execFileSync)(process.execPath, [ composeSourceMaps, packagerMap, `${bytecode}.map`, "-o", composedMap ], { cwd: root, stdio: "inherit" }); (0, import_fs.writeFileSync)((0, import_path.join)(intermediatesOut, "bundle.js"), (0, import_fs.readFileSync)(bundleJs)); (0, import_fs.writeFileSync)((0, import_path.join)(intermediatesOut, "main.jsbundle.map"), (0, import_fs.readFileSync)(composedMap)); } var bundleHash = sha256Base64Url(bytecode); (0, import_fs.writeFileSync)((0, import_path.join)(assetsOut, bundleHash), (0, import_fs.readFileSync)(bytecode)); var assets = []; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = collectFiles(assetsDir)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var file = _step.value; var hash = sha256Base64Url(file); var target = (0, import_path.join)(assetsOut, hash); if (!(0, import_fs.existsSync)(target)) (0, import_fs.writeFileSync)(target, (0, import_fs.readFileSync)(file)); assets.push({ hash, url: `assets/${hash}`, path: (0, import_path.relative)(assetsDir, file).split(import_path.sep).join("/") }); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } assets.sort(function(a, b) { return a.path < b.path ? -1 : a.path > b.path ? 1 : 0; }); var manifest = { id: (0, import_crypto.randomUUID)(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), runtimeVersion, launchAsset: { hash: bundleHash, url: `assets/${bundleHash}`, path: "main.jsbundle" }, assets, metadata }; (0, import_fs.writeFileSync)((0, import_path.join)(out, "manifest.json"), `${JSON.stringify(manifest, null, 2)} `); console.info(`[one] published ${platform} update ${manifest.id} (${assets.length} assets) to ${out}`); } finally { (0, import_fs.rmSync)(work, { recursive: true, force: true }); } }