Files
Fluxup_PAP/node_modules/babel-preset-expo/build/expo-inline-manifest-plugin.js
2026-03-10 16:18:05 +00:00

192 lines
7.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.expoInlineManifestPlugin = expoInlineManifestPlugin;
const common_1 = require("./common");
const debug = require('debug')('expo:babel:inline-manifest');
// Convert expo value to PWA value
function ensurePWAOrientation(orientation) {
if (orientation) {
const webOrientation = orientation.toLowerCase();
if (webOrientation !== 'default') {
return webOrientation;
}
}
return undefined;
}
const RESTRICTED_MANIFEST_FIELDS = [
'androidNavigationBar',
'androidStatusBar',
'privacy',
// Remove iOS and Android.
'ios',
'android',
// Hide internal / build values
'plugins',
'hooks', // hooks no longer exists in the typescript type but should still be removed
'_internal',
// Remove metro-specific values
'assetBundlePatterns',
];
function getExpoConstantsManifest(projectRoot) {
const config = getConfigMemo(projectRoot);
if (!config)
return null;
const manifest = applyWebDefaults(config);
for (const field of RESTRICTED_MANIFEST_FIELDS) {
delete manifest[field];
}
return manifest;
}
function applyWebDefaults({ config, appName, webName }) {
const appJSON = config.exp;
// For RN CLI support
const { web: webManifest = {}, splash = {}, ios = {}, android = {} } = appJSON;
const languageISOCode = webManifest.lang;
const primaryColor = appJSON.primaryColor;
const description = appJSON.description;
// The theme_color sets the color of the tool bar, and may be reflected in the app's preview in task switchers.
const webThemeColor = webManifest.themeColor || primaryColor;
const dir = webManifest.dir;
const shortName = webManifest.shortName || webName;
const display = webManifest.display;
const startUrl = webManifest.startUrl;
const { scope, crossorigin } = webManifest;
const barStyle = webManifest.barStyle;
const orientation = ensurePWAOrientation(webManifest.orientation || appJSON.orientation);
/**
* **Splash screen background color**
* `https://developers.google.com/web/fundamentals/web-app-manifest/#splash-screen`
* The background_color should be the same color as the load page,
* to provide a smooth transition from the splash screen to your app.
*/
const backgroundColor = webManifest.backgroundColor || splash.backgroundColor; // No default background color
return {
...appJSON,
name: appName,
description,
primaryColor,
// Ensure these objects exist
ios: {
...ios,
},
android: {
...android,
},
web: {
...webManifest,
meta: undefined,
build: undefined,
scope,
crossorigin,
description,
startUrl,
shortName,
display,
orientation,
dir,
barStyle,
backgroundColor,
themeColor: webThemeColor,
lang: languageISOCode,
name: webName,
},
};
}
function getExpoAppManifest(projectRoot) {
if (process.env.APP_MANIFEST) {
return process.env.APP_MANIFEST;
}
const exp = getExpoConstantsManifest(projectRoot);
if (exp) {
debug('public manifest', exp);
return JSON.stringify(exp);
}
else {
debug('public manifest is null. `expo/config` is not available');
return null;
}
}
let configMemo;
function getConfigMemo(projectRoot) {
if (configMemo === undefined) {
let expoConfig;
try {
// This is an optional dependency. In practice, it will resolve in all Expo projects/apps
// since `expo` is a direct dependency in those. If `babel-preset-expo` is used independently
// this will fail and we won't return a config
expoConfig = require('expo/config');
}
catch (error) {
if ('code' in error && error.code === 'MODULE_NOT_FOUND') {
return (configMemo = null);
}
throw error;
}
const { getConfig, getNameFromConfig } = expoConfig;
const config = getConfig(projectRoot, {
isPublicConfig: true,
skipSDKVersionRequirement: true,
});
// rn-cli apps use a displayName value as well.
const { appName, webName } = getNameFromConfig(config.exp);
configMemo = {
config,
appName,
webName,
};
}
return configMemo;
}
// Convert `process.env.APP_MANIFEST` to a modified web-specific variation of the app.json public manifest.
function expoInlineManifestPlugin(api) {
const { types: t } = api;
const isReactServer = api.caller(common_1.getIsReactServer);
const platform = api.caller(common_1.getPlatform);
const possibleProjectRoot = api.caller(common_1.getPossibleProjectRoot);
const shouldInline = platform === 'web' || isReactServer;
// Early exit: return a no-op plugin if we're not going to inline anything
if (!shouldInline) {
return {
name: 'expo-inline-manifest-plugin',
visitor: {},
};
}
return {
name: 'expo-inline-manifest-plugin',
pre() {
this.projectRoot = possibleProjectRoot || this.file.opts.root || '';
},
visitor: {
MemberExpression(path, state) {
// We're looking for: process.env.APP_MANIFEST
// This visitor is called on every MemberExpression, so we need fast checks
// Quick check: the property we're looking for is 'APP_MANIFEST'
// The parent must be a MemberExpression with property 'APP_MANIFEST'
const parent = path.parentPath;
if (!parent?.isMemberExpression())
return;
// Check if parent's property is APP_MANIFEST (most selective check first)
const parentProp = parent.node.property;
if (!t.isIdentifier(parentProp) || parentProp.name !== 'APP_MANIFEST')
return;
// Now verify this is process.env
const obj = path.node.object;
const prop = path.node.property;
if (!t.isIdentifier(obj) || obj.name !== 'process')
return;
if (!t.isIdentifier(prop) || prop.name !== 'env')
return;
// Skip if this is an assignment target
if (parent.parentPath?.isAssignmentExpression())
return;
// Surfaces the `app.json` (config) as an environment variable which is then parsed by
// `expo-constants` https://docs.expo.dev/versions/latest/sdk/constants/
const manifest = getExpoAppManifest(state.projectRoot);
if (manifest !== null) {
parent.replaceWith(t.stringLiteral(manifest));
}
},
},
};
}