first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.cleanAssetCatalog = cleanAssetCatalog;
exports.getImageSet = getImageSet;
exports.isCatalogAsset = isCatalogAsset;
exports.writeImageSet = writeImageSet;
var _assetPathUtils = _interopRequireDefault(require("./assetPathUtils"));
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
function cleanAssetCatalog(catalogDir) {
const files = _fs.default
.readdirSync(catalogDir)
.filter((file) => file.endsWith(".imageset"));
for (const file of files) {
_fs.default.rmSync(_path.default.join(catalogDir, file), {
recursive: true,
force: true,
});
}
}
function getImageSet(catalogDir, asset, scales) {
const fileName = _assetPathUtils.default.getResourceIdentifier(asset);
return {
basePath: _path.default.join(catalogDir, `${fileName}.imageset`),
files: scales.map((scale, idx) => {
const suffix = scale === 1 ? "" : `@${scale}x`;
return {
name: `${fileName + suffix}.${asset.type}`,
scale,
src: asset.files[idx],
};
}),
};
}
function isCatalogAsset(asset) {
return asset.type === "png" || asset.type === "jpg" || asset.type === "jpeg";
}
function writeImageSet(imageSet) {
_fs.default.mkdirSync(imageSet.basePath, {
recursive: true,
});
for (const file of imageSet.files) {
const dest = _path.default.join(imageSet.basePath, file.name);
_fs.default.copyFileSync(file.src, dest);
}
_fs.default.writeFileSync(
_path.default.join(imageSet.basePath, "Contents.json"),
JSON.stringify({
images: imageSet.files.map((file) => ({
filename: file.name,
idiom: "universal",
scale: `${file.scale}x`,
})),
info: {
author: "xcode",
version: 1,
},
}),
);
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { AssetData } from "metro";
declare export function cleanAssetCatalog(catalogDir: string): void;
type ImageSet = {
basePath: string,
files: { name: string, src: string, scale: number }[],
};
declare export function getImageSet(
catalogDir: string,
asset: AssetData,
scales: $ReadOnlyArray<number>,
): ImageSet;
declare export function isCatalogAsset(asset: AssetData): boolean;
declare export function writeImageSet(imageSet: ImageSet): void;

View File

@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
function getAndroidAssetSuffix(scale) {
switch (scale) {
case 0.75:
return "ldpi";
case 1:
return "mdpi";
case 1.5:
return "hdpi";
case 2:
return "xhdpi";
case 3:
return "xxhdpi";
case 4:
return "xxxhdpi";
default:
return "";
}
}
const drawableFileTypes = new Set(["gif", "jpeg", "jpg", "png", "webp", "xml"]);
function getAndroidResourceFolderName(asset, scale) {
if (!drawableFileTypes.has(asset.type)) {
return "raw";
}
const suffix = getAndroidAssetSuffix(scale);
if (!suffix) {
throw new Error(
`Don't know which android drawable suffix to use for asset: ${JSON.stringify(asset)}`,
);
}
return `drawable-${suffix}`;
}
function getResourceIdentifier(asset) {
const folderPath = getBasePath(asset);
return `${folderPath}/${asset.name}`
.toLowerCase()
.replace(/\//g, "_")
.replace(/([^a-z0-9_])/g, "")
.replace(/^(?:assets|assetsunstable_path)_/, "");
}
function getBasePath(asset) {
let basePath = asset.httpServerLocation;
if (basePath[0] === "/") {
basePath = basePath.substr(1);
}
return basePath;
}
var _default = (exports.default = {
drawableFileTypes,
getAndroidAssetSuffix,
getAndroidResourceFolderName,
getResourceIdentifier,
getBasePath,
});

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
export type PackagerAsset = $ReadOnly<{
httpServerLocation: string,
name: string,
type: string,
...
}>;
/**
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
* floating point numbers imprecision.
*/
declare function getAndroidAssetSuffix(scale: number): string;
// See https://developer.android.com/guide/topics/resources/drawable-resource.html
declare const drawableFileTypes: Set<string>;
declare function getAndroidResourceFolderName(
asset: PackagerAsset,
scale: number,
): string;
declare function getResourceIdentifier(asset: PackagerAsset): string;
declare function getBasePath(asset: PackagerAsset): string;
declare export default {
drawableFileTypes: typeof drawableFileTypes,
getAndroidAssetSuffix: typeof getAndroidAssetSuffix,
getAndroidResourceFolderName: typeof getAndroidResourceFolderName,
getResourceIdentifier: typeof getResourceIdentifier,
getBasePath: typeof getBasePath,
};

View File

@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.unstable_buildBundleWithConfig = exports.default = void 0;
var _loadMetroConfig = _interopRequireDefault(
require("../../utils/loadMetroConfig"),
);
var _parseKeyValueParamArray = _interopRequireDefault(
require("../../utils/parseKeyValueParamArray"),
);
var _saveAssets = _interopRequireDefault(require("./saveAssets"));
var _fs = require("fs");
var _metro = require("metro");
var _path = _interopRequireDefault(require("path"));
var _util = require("util");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
async function buildBundle(_argv, ctx, args, bundleImpl) {
const config = await (0, _loadMetroConfig.default)(ctx, {
maxWorkers: args.maxWorkers,
resetCache: args.resetCache,
config: args.config,
});
return buildBundleWithConfig(args, config, bundleImpl);
}
async function buildBundleWithConfig(args, config, bundleImpl) {
const customResolverOptions = (0, _parseKeyValueParamArray.default)(
args.resolverOption ?? [],
);
if (config.resolver.platforms.indexOf(args.platform) === -1) {
console.error(
`${(0, _util.styleText)("red", "error")}: Invalid platform ${args.platform ? `"${(0, _util.styleText)("bold", args.platform)}" ` : ""}selected.`,
);
console.info(
`Available platforms are: ${config.resolver.platforms.map((x) => `"${(0, _util.styleText)("bold", x)}"`).join(", ")}. If you are trying to bundle for an out-of-tree platform, it may not be installed.`,
);
throw new Error("Bundling failed");
}
process.env.NODE_ENV = args.dev ? "development" : "production";
let sourceMapUrl = args.sourcemapOutput;
if (sourceMapUrl != null && !args.sourcemapUseAbsolutePath) {
sourceMapUrl = _path.default.basename(sourceMapUrl);
}
const runBuildOptions = {
assets: args.assetsDest != null,
bundleOut: args.bundleOutput,
customResolverOptions,
dev: args.dev,
entry: args.entryFile,
minify: args.minify !== undefined ? args.minify : !args.dev,
output: bundleImpl,
platform: args.platform,
sourceMap: args.sourcemapOutput != null,
sourceMapOut: args.sourcemapOutput,
sourceMapUrl,
unstable_transformProfile: args.unstableTransformProfile,
};
await _fs.promises.mkdir(_path.default.dirname(args.bundleOutput), {
recursive: true,
mode: 0o755,
});
const result = await (0, _metro.runBuild)(config, runBuildOptions);
if (args.assetsDest == null) {
console.warn("Warning: Assets destination folder is not set, skipping...");
return;
}
if (result.assets == null) {
throw new Error("Assets missing from Metro's runBuild result");
}
const outputAssets = result.assets;
await (0, _saveAssets.default)(
outputAssets,
args.platform,
args.assetsDest,
args.assetCatalogDest,
);
}
const unstable_buildBundleWithConfig = (exports.unstable_buildBundleWithConfig =
buildBundleWithConfig);
var _default = (exports.default = buildBundle);

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { Config } from "@react-native-community/cli-types";
import type { RunBuildOptions } from "metro";
import type { ConfigT } from "metro-config";
export type BundleCommandArgs = {
assetsDest?: string,
assetCatalogDest?: string,
entryFile: string,
resetCache: boolean,
resetGlobalCache: boolean,
transformer?: string,
minify?: boolean,
config?: string,
platform: string,
dev: boolean,
bundleOutput: string,
bundleEncoding?: "utf8" | "utf16le" | "ascii",
maxWorkers?: number,
sourcemapOutput?: string,
sourcemapSourcesRoot?: string,
sourcemapUseAbsolutePath: boolean,
verbose: boolean,
unstableTransformProfile: "hermes-stable" | "hermes-canary" | "default",
indexedRamBundle?: boolean,
resolverOption?: Array<string>,
};
declare function buildBundle(
_argv: Array<string>,
ctx: Config,
args: BundleCommandArgs,
bundleImpl?: RunBuildOptions["output"],
): Promise<void>;
declare function buildBundleWithConfig(
args: BundleCommandArgs,
config: ConfigT,
bundleImpl?: RunBuildOptions["output"],
): Promise<void>;
/**
* UNSTABLE: This function is likely to be relocated and its API changed in
* the near future. `@react-native/community-cli-plugin` should not be directly
* depended on by projects or integrators -- this is exported for legacy
* compatibility.
*
* Create a bundle using a pre-loaded Metro config. The config can be
* re-used for several bundling calls if multiple platforms are being
* bundled.
*/
declare export const unstable_buildBundleWithConfig: typeof buildBundleWithConfig;
declare export default typeof buildBundle;

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _assetPathUtils = _interopRequireDefault(require("./assetPathUtils"));
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
async function createKeepFileAsync(assets, outputDirectory) {
if (!assets.length) {
return;
}
const assetsList = [];
for (const asset of assets) {
const prefix = _assetPathUtils.default.drawableFileTypes.has(asset.type)
? "drawable"
: "raw";
assetsList.push(
`@${prefix}/${_assetPathUtils.default.getResourceIdentifier(asset)}`,
);
}
const keepPath = _path.default.join(outputDirectory, "raw/keep.xml");
const content = `<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="${assetsList.join(",")}" />\n`;
await _fs.default.promises.mkdir(_path.default.dirname(keepPath), {
recursive: true,
});
await _fs.default.promises.writeFile(keepPath, content);
}
var _default = (exports.default = createKeepFileAsync);

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { AssetData } from "metro";
declare function createKeepFileAsync(
assets: $ReadOnlyArray<AssetData>,
outputDirectory: string,
): Promise<void>;
declare export default typeof createKeepFileAsync;

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
const ALLOWED_SCALES = {
ios: [1, 2, 3],
};
function filterPlatformAssetScales(platform, scales) {
const whitelist = ALLOWED_SCALES[platform];
if (!whitelist) {
return scales;
}
const result = scales.filter((scale) => whitelist.indexOf(scale) > -1);
if (result.length === 0 && scales.length > 0) {
const maxScale = whitelist[whitelist.length - 1];
for (const scale of scales) {
if (scale > maxScale) {
result.push(scale);
break;
}
}
if (result.length === 0) {
result.push(scales[scales.length - 1]);
}
}
return result;
}
var _default = (exports.default = filterPlatformAssetScales);

View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
declare function filterPlatformAssetScales(
platform: string,
scales: $ReadOnlyArray<number>,
): $ReadOnlyArray<number>;
declare export default typeof filterPlatformAssetScales;

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _assetPathUtils = _interopRequireDefault(require("./assetPathUtils"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
function getAssetDestPathAndroid(asset, scale) {
const androidFolder = _assetPathUtils.default.getAndroidResourceFolderName(
asset,
scale,
);
const fileName = _assetPathUtils.default.getResourceIdentifier(asset);
return _path.default.join(androidFolder, `${fileName}.${asset.type}`);
}
var _default = (exports.default = getAssetDestPathAndroid);

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { PackagerAsset } from "./assetPathUtils";
declare function getAssetDestPathAndroid(
asset: PackagerAsset,
scale: number,
): string;
declare export default typeof getAssetDestPathAndroid;

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
function getAssetDestPathIOS(asset, scale) {
const suffix = scale === 1 ? "" : `@${scale}x`;
const fileName = `${asset.name + suffix}.${asset.type}`;
return _path.default.join(
asset.httpServerLocation.substr(1).replace(/\.\.\//g, "_"),
fileName,
);
}
var _default = (exports.default = getAssetDestPathIOS);

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { PackagerAsset } from "./assetPathUtils";
declare function getAssetDestPathIOS(
asset: PackagerAsset,
scale: number,
): string;
declare export default typeof getAssetDestPathIOS;

View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _buildBundle = _interopRequireDefault(require("./buildBundle"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
const bundleCommand = {
name: "bundle",
description: "Build the bundle for the provided JavaScript entry file.",
func: _buildBundle.default,
options: [
{
name: "--entry-file <path>",
description:
"Path to the root JS file, either absolute or relative to JS root",
},
{
name: "--platform <string>",
description: 'Either "ios" or "android"',
default: "ios",
},
{
name: "--transformer <string>",
description: "Specify a custom transformer to be used",
},
{
name: "--dev [boolean]",
description: "If false, warnings are disabled and the bundle is minified",
parse: (val) => val !== "false",
default: true,
},
{
name: "--minify [boolean]",
description:
"Allows overriding whether bundle is minified. This defaults to " +
"false if dev is true, and true if dev is false. Disabling minification " +
"can be useful for speeding up production builds for testing purposes.",
parse: (val) => val !== "false",
},
{
name: "--bundle-output <string>",
description:
"File name where to store the resulting bundle, ex. /tmp/groups.bundle",
},
{
name: "--bundle-encoding <string>",
description:
"Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).",
default: "utf8",
},
{
name: "--max-workers <number>",
description:
"Specifies the maximum number of workers the worker-pool " +
"will spawn for transforming files. This defaults to the number of the " +
"cores available on your machine.",
parse: (workers) => Number(workers),
},
{
name: "--sourcemap-output <string>",
description:
"File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map",
},
{
name: "--sourcemap-sources-root <string>",
description:
"Path to make sourcemap's sources entries relative to, ex. /root/dir",
},
{
name: "--sourcemap-use-absolute-path",
description: "Report SourceMapURL using its full path",
default: false,
},
{
name: "--assets-dest <string>",
description:
"Directory name where to store assets referenced in the bundle",
},
{
name: "--unstable-transform-profile <string>",
description:
"Experimental, transform JS for a specific JS engine. Currently supported: hermes, hermes-canary, default",
default: "default",
},
{
name: "--asset-catalog-dest [string]",
description: "Path where to create an iOS Asset Catalog for images",
},
{
name: "--reset-cache",
description: "Removes cached files",
default: false,
},
{
name: "--read-global-cache",
description:
"Try to fetch transformed JS code from the global cache, if configured.",
default: false,
},
{
name: "--config <string>",
description: "Path to the CLI configuration file",
parse: (val) => _path.default.resolve(val),
},
{
name: "--resolver-option <string...>",
description:
"Custom resolver options of the form key=value. URL-encoded. May be specified multiple times.",
parse: (val, previous = []) => previous.concat([val]),
},
],
};
var _default = (exports.default = bundleCommand);

View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { Command } from "@react-native-community/cli-types";
export type { BundleCommandArgs } from "./buildBundle";
declare const bundleCommand: Command;
declare export default typeof bundleCommand;

View File

@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _assetCatalogIOS = require("./assetCatalogIOS");
var _createKeepFileAsync = _interopRequireDefault(
require("./createKeepFileAsync"),
);
var _filterPlatformAssetScales = _interopRequireDefault(
require("./filterPlatformAssetScales"),
);
var _getAssetDestPathAndroid = _interopRequireDefault(
require("./getAssetDestPathAndroid"),
);
var _getAssetDestPathIOS = _interopRequireDefault(
require("./getAssetDestPathIOS"),
);
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _util = require("util");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
async function saveAssets(assets, platform, assetsDest, assetCatalogDest) {
if (assetsDest == null) {
console.warn("Warning: Assets destination folder is not set, skipping...");
return;
}
const filesToCopy = {};
const getAssetDestPath =
platform === "android"
? _getAssetDestPathAndroid.default
: _getAssetDestPathIOS.default;
const addAssetToCopy = (asset) => {
const validScales = new Set(
(0, _filterPlatformAssetScales.default)(platform, asset.scales),
);
asset.scales.forEach((scale, idx) => {
if (!validScales.has(scale)) {
return;
}
const src = asset.files[idx];
const dest = _path.default.join(
assetsDest,
getAssetDestPath(asset, scale),
);
filesToCopy[src] = dest;
});
};
if (platform === "ios" && assetCatalogDest != null) {
const catalogDir = _path.default.join(
assetCatalogDest,
"RNAssets.xcassets",
);
if (!_fs.default.existsSync(catalogDir)) {
console.error(
`${(0, _util.styleText)("red", "error")}: Could not find asset catalog 'RNAssets.xcassets' in ${assetCatalogDest}. Make sure to create it if it does not exist.`,
);
return;
}
console.info("Adding images to asset catalog", catalogDir);
(0, _assetCatalogIOS.cleanAssetCatalog)(catalogDir);
for (const asset of assets) {
if ((0, _assetCatalogIOS.isCatalogAsset)(asset)) {
const imageSet = (0, _assetCatalogIOS.getImageSet)(
catalogDir,
asset,
(0, _filterPlatformAssetScales.default)(platform, asset.scales),
);
(0, _assetCatalogIOS.writeImageSet)(imageSet);
} else {
addAssetToCopy(asset);
}
}
console.info("Done adding images to asset catalog");
} else {
assets.forEach(addAssetToCopy);
}
if (platform === "android") {
await (0, _createKeepFileAsync.default)(assets, assetsDest);
}
return copyAll(filesToCopy);
}
function copyAll(filesToCopy) {
const queue = Object.keys(filesToCopy);
if (queue.length === 0) {
return Promise.resolve();
}
console.info(`Copying ${queue.length} asset files`);
return new Promise((resolve, reject) => {
const copyNext = (error) => {
if (error) {
reject(error);
return;
}
if (queue.length === 0) {
console.info("Done copying assets");
resolve();
} else {
const src = queue.shift();
const dest = filesToCopy[src];
copy(src, dest, copyNext);
}
};
copyNext();
});
}
function copy(src, dest, callback) {
const destDir = _path.default.dirname(dest);
_fs.default.mkdir(
destDir,
{
recursive: true,
},
(err) => {
if (err) {
callback(err);
return;
}
_fs.default
.createReadStream(src)
.pipe(_fs.default.createWriteStream(dest))
.on("finish", callback);
},
);
}
var _default = (exports.default = saveAssets);

View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type { AssetData } from "metro";
declare function saveAssets(
assets: $ReadOnlyArray<AssetData>,
platform: string,
assetsDest?: string,
assetCatalogDest?: string,
): Promise<void>;
declare export default typeof saveAssets;