one
Version:
One is a new React Framework that makes Vite serve both native and web.
247 lines (245 loc) • 9.53 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
value: true
}), mod);
var generateBundlerConfig_exports = {};
__export(generateBundlerConfig_exports, {
ONE_GENERATED_MARKER: () => ONE_GENERATED_MARKER,
generateBundlerConfig: () => generateBundlerConfig,
getBundlerConfigOptionsFromOneOptions: () => getBundlerConfigOptionsFromOneOptions,
isCiEnvironment: () => isCiEnvironment,
maybeGenerateBundlerConfigOnInstall: () => maybeGenerateBundlerConfigOnInstall
});
module.exports = __toCommonJS(generateBundlerConfig_exports);
var import_node_fs = require("node:fs");
var import_node_module = __toESM(require("node:module"), 1);
var import_node_path = __toESM(require("node:path"), 1);
var import_picocolors = __toESM(require("picocolors"), 1);
var import_getRouterRootFromOneOptions = require("../utils/getRouterRootFromOneOptions.cjs");
const ONE_GENERATED_MARKER = "@one/generated bundler-config";
function buildBabelConfigContent({
eject,
options
}) {
const header = eject ? `// you own this file. edit freely \u2014 \`one\` will not regenerate it.
// delegates to one/babel-preset which holds the canonical plugin chain.
` : `// ${ONE_GENERATED_MARKER}
//
// auto-generated by \`one patch\` on ci/eas workers when expo-updates is
// in deps. delegates to one/babel-preset so expo export / eas update
// use the same router/setup options as \`one dev\` and \`one build\`.
//
// to customize, delete this header and edit freely \u2014 re-runs will then
// leave this file alone.
`;
return `${header}
const oneBabelPreset = require('one/babel-preset')
const preset = oneBabelPreset.default || oneBabelPreset
const oneBundlerOptions = ${serializeBundlerConfigOptions(options)}
module.exports = function (api) {
return preset(api, oneBundlerOptions)
}
`;
}
function buildMetroConfigContent({
eject,
options
}) {
const header = eject ? `// you own this file. edit freely \u2014 \`one\` will not regenerate it.
// withOne() invokes the same Metro pipeline One uses for production bundles.
` : `// ${ONE_GENERATED_MARKER}
//
// auto-generated by \`one patch\` on ci/eas workers when expo-updates is
// in deps. delegates to one/metro-config which invokes the exact same
// metro pipeline one uses for production native bundles with your
// router/setup options \u2014 no separate expo/metro-config setup needed.
//
// to customize, delete this header and edit freely \u2014 re-runs will then
// leave this file alone.
`;
return `${header}
const { withOne } = require('one/metro-config')
const oneBundlerOptions = ${serializeBundlerConfigOptions(options)}
module.exports = withOne(__dirname, oneBundlerOptions)
`;
}
const FILES = [{
name: "babel.config.cjs",
getContent: buildBabelConfigContent,
conflicting: ["babel.config.js", "babel.config.mjs", ".babelrc", ".babelrc.js"]
}, {
name: "metro.config.cjs",
getContent: buildMetroConfigContent,
conflicting: ["metro.config.js", "metro.config.mjs"]
}];
function stripUndefined(value) {
if (Array.isArray(value)) {
return value.map(stripUndefined);
}
if (value && typeof value === "object") {
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0).map(([key, entry]) => [key, stripUndefined(entry)]));
}
return value;
}
function assertSerializable(value, keyPath = "one bundler options") {
if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
throw new Error(`[one] ${keyPath} must be JSON-serializable to generate Babel/Metro config files. Move function-valued native linking/customization into an ejected config.`);
}
if (Array.isArray(value)) {
value.forEach((entry, index) => assertSerializable(entry, `${keyPath}[${index}]`));
return;
}
if (value && typeof value === "object") {
for (const [key, entry] of Object.entries(value)) {
assertSerializable(entry, `${keyPath}.${key}`);
}
}
}
function serializeBundlerConfigOptions(options) {
const clean = stripUndefined(options);
assertSerializable(clean);
return JSON.stringify(clean, null, 2);
}
function getBundlerConfigOptionsFromOneOptions(oneOptions = {}) {
return stripUndefined({
routerRoot: (0, import_getRouterRootFromOneOptions.getRouterRootFromOneOptions)(oneOptions),
ignoredRouteFiles: oneOptions.router?.ignoredRouteFiles,
linking: oneOptions.router?.linking,
setupFile: oneOptions.setupFile
});
}
function generateBundlerConfig(args = {}) {
const cwd = import_node_path.default.resolve(args.cwd ?? process.cwd());
const force = !!args.force;
const check = !!args.check;
const quiet = !!args.quiet;
const log = msg => {
if (!quiet) console.info(msg);
};
const warn = msg => {
if (!quiet) console.warn(msg);
};
const results = [];
const eject = !!args.eject;
const bundlerOptions = getBundlerConfigOptionsFromOneOptions(args.oneOptions);
for (const file of FILES) {
const filePath = import_node_path.default.join(cwd, file.name);
const targetContent = file.getContent({
eject,
options: bundlerOptions
});
const conflict = file.conflicting.find(alt => (0, import_node_fs.existsSync)(import_node_path.default.join(cwd, alt)));
if (conflict && !(0, import_node_fs.existsSync)(filePath)) {
results.push({
filePath: import_node_path.default.join(cwd, conflict),
action: "skipped-other-format",
reason: `Found ${conflict}; not creating ${file.name}. To switch, delete ${conflict} and re-run with --force.`
});
warn(import_picocolors.default.yellow(`[one] found ${conflict} \u2014 leaving it alone. Delete it and re-run with --force to switch to ${file.name}.`));
continue;
}
if (!(0, import_node_fs.existsSync)(filePath)) {
if (check) {
results.push({
filePath,
action: "would-write"
});
log(import_picocolors.default.yellow(`[one] missing: ${file.name}`));
continue;
}
(0, import_node_fs.writeFileSync)(filePath, targetContent);
results.push({
filePath,
action: "wrote"
});
log(import_picocolors.default.green(`[one] wrote ${file.name}`));
continue;
}
const existing = (0, import_node_fs.readFileSync)(filePath, "utf8");
if (existing === targetContent) {
results.push({
filePath,
action: "kept"
});
log(import_picocolors.default.dim(`[one] up to date: ${file.name}`));
continue;
}
const hasMarker = existing.includes(ONE_GENERATED_MARKER);
if (!hasMarker && !force) {
results.push({
filePath,
action: "skipped-customized",
reason: `${file.name} has been customized (no @one marker). Re-add the marker comment or pass --force to overwrite.`
});
warn(import_picocolors.default.yellow(`[one] ${file.name} appears customized \u2014 skipping. Pass --force to overwrite.`));
continue;
}
if (check) {
results.push({
filePath,
action: "would-overwrite"
});
log(import_picocolors.default.yellow(`[one] out of date: ${file.name}`));
continue;
}
(0, import_node_fs.writeFileSync)(filePath, targetContent);
results.push({
filePath,
action: "wrote"
});
log(import_picocolors.default.green(`[one] updated ${file.name}`));
}
const acceptableAlways = /* @__PURE__ */new Set(["wrote", "kept", "skipped-other-format", "skipped-customized"]);
const acceptableInCheck = /* @__PURE__ */new Set(["kept", "skipped-other-format", "skipped-customized"]);
const ok = (check ? acceptableInCheck : acceptableAlways).size ? results.every(r => (check ? acceptableInCheck : acceptableAlways).has(r.action)) : false;
return {
results,
ok
};
}
function isCiEnvironment() {
const truthy = v => !!v && v !== "false" && v !== "0";
return truthy(process.env.EAS_BUILD) || truthy(process.env.CI);
}
function maybeGenerateBundlerConfigOnInstall(cwd = process.cwd(), oneOptions) {
if (!isCiEnvironment()) return;
try {
import_node_module.default.createRequire(cwd + "/").resolve("expo-updates/package.json");
} catch {
return;
}
generateBundlerConfig({
cwd,
quiet: false,
oneOptions
});
}