UNPKG

@datadog/mobile-react-native

Version:

A client-side React Native module to interact with Datadog

213 lines (196 loc) 7.83 kB
/* * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. * This product includes software developed at Datadog (https://www.datadoghq.com/). * Copyright 2016-Present Datadog, Inc. */ /** * Lazy-init cache for modules loaded through `safeRequireDefaultExport`. */ const lazyLoadedModules = {}; /** * Lazy-init reference for {@link getSourceMapStringFunction} resolved function. */ let sourceMapStringFunction; /** * Safely loads and returns the `baseJSBundle` function from Metro's internal modules. * Supports multiple Metro versions with different internal paths. */ export const getBaseJSBundleFunction = () => lazyRequireDefaultExport(['metro/private/DeltaBundler/Serializers/baseJSBundle', 'metro/src/DeltaBundler/Serializers/baseJSBundle']); /** * Safely loads and returns the `countLines` function from Metro's internal modules. * Supports multiple Metro versions with different internal paths. */ export const getCountLinesFunction = () => lazyRequireDefaultExport(['metro/private/lib/countLines', 'metro/src/lib/countLines']); /** * Safely loads and returns the `bundleToString` function from Metro's internal modules. * Supports multiple Metro versions with different internal paths. */ export const getBundleToStringFunction = () => lazyRequireDefaultExport(['metro/private/lib/bundleToString', 'metro/src/lib/bundleToString']); /** * CountingSet was added in Metro 0.71.2 - a modified `Set` that only deletes items when the * number of `delete(item)` calls matches the number of `add(item)` calls. * * https://github.com/facebook/metro/commit/fc29a1177f883144674cf85a813b58567f69d545 */ export const getCreateCountingSetFunction = () => { const CountingSetClass = safeLazyRequireDefaultExport(['metro/private/lib/CountingSet', 'metro/src/lib/CountingSet']); return CountingSetClass ? () => new CountingSetClass() : () => new Set(); }; /** * Lazy-init reference for {@link getDefaultExpoConfig} resolved function. */ let getDefaultExpoConfigFunc; /** * In Metro versions prior to v0.80.10, `sourceMapString` was exported as a default export. * Starting with v0.80.10, it became a named export. * * @returns The resolved `sourceMapString` function, of type {@link sourceMapString} */ export const getSourceMapStringFunction = () => { if (sourceMapStringFunction) { return sourceMapStringFunction; } const sourceMapStringModule = safeRequireDefaultExport(['metro/private/DeltaBundler/Serializers/sourceMapString', 'metro/src/DeltaBundler/Serializers/sourceMapString']); if (typeof sourceMapStringModule === 'function') { sourceMapStringFunction = sourceMapStringModule; } else if (sourceMapStringModule && typeof sourceMapStringModule === 'object' && typeof sourceMapStringModule['sourceMapString'] === 'function') { sourceMapStringFunction = sourceMapStringModule.sourceMapString; } if (!sourceMapStringFunction) { throw new Error("[DATADOG METRO PLUGIN] Unexpected error: Cannot resolve sourceMapString function from Metro's internal modules."); } return sourceMapStringFunction; }; /** * This function ensures that modules in source maps are sorted in the same * order as in a plain JS bundle. * * https://github.com/facebook/metro/blob/76413561abb3757285e0cb0305f1f9f616fa2b6c/packages/metro/src/Server.js#L1086C1-L1095C7 */ export function getSortedModules(graph, { createModuleId }) { const modules = [...graph.dependencies.values()]; // Assign IDs to modules in a consistent order for (const module of modules) { createModuleId(module.path); } // Sort by IDs return modules.sort((a, b) => createModuleId(a.path) - createModuleId(b.path)); } /** * Converts the serializer result of type {@link MetroSerializerOutput} to {@link MetroBundleWithMap}. */ export const convertSerializerOutput = async output => { const parse = obj => { // Plain String if (typeof obj === 'string') { return { code: obj, map: '{}' }; } // Dictionary if ('map' in obj) { return { code: obj.code, map: obj.map }; } return undefined; }; const value = parse(output); if (!value) { return parse(await output) ?? { code: '', map: '{}' }; } else { return value; } }; /** * Gets the default Expo configuration options. */ export const getDefaultExpoConfig = (projectRoot, options) => { if (getDefaultExpoConfigFunc) { return getDefaultExpoConfigFunc(projectRoot, options); } try { // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires const metroConfig = require('expo/metro-config'); getDefaultExpoConfigFunc = metroConfig.getDefaultConfig; return metroConfig.getDefaultConfig(projectRoot, options); } catch (e) { throw new Error('Cannot load `expo/metro-config`. Make sure Expo is properly set up in your project.'); } }; /** * Safely requires a module from multiple possible paths, returning its default export if found. * Caches the result to avoid redundant requires. * Useful for supporting multiple Metro versions with different internal paths. * @param modulePaths The list of possible module paths to try. * @returns the default export of the first successfully required module. * @throws if none of the module paths could be resolved. */ export const lazyRequireDefaultExport = modulePaths => { const resolvedModule = safeLazyRequireDefaultExport(modulePaths); if (!resolvedModule) { throw new Error(`[DATADOG METRO PLUGIN] Unexpected error: cannot find module in any of the following paths: ${modulePaths.join(', ')}`); } return resolvedModule; }; /** * Safely requires a module from multiple possible paths, returning its default export if found. * Caches the result to avoid redundant requires. * Useful for supporting multiple Metro versions with different internal paths. * @param modulePaths The list of possible module paths to try. * @returns the default export of the first successfully required module, or `undefined` if none could be resolved. */ export const safeLazyRequireDefaultExport = modulePaths => { const cacheKey = modulePaths.join('|'); if (lazyLoadedModules[cacheKey]) { return lazyLoadedModules[cacheKey]; } const resolvedModule = safeRequireDefaultExport(modulePaths); lazyLoadedModules[cacheKey] = resolvedModule; return resolvedModule; }; /** * Safely requires a module from multiple possible paths, returning its default export if found. * Useful for supporting multiple Metro versions with different internal paths. * @param modulePaths The list of possible module paths to try. * @returns the default export of the first successfully required module, or `undefined` if none could be resolved. */ export function safeRequireDefaultExport(modulePaths) { let resolvedModule; for (const modulePath of modulePaths) { try { // eslint-disable-next-line global-require, import/no-extraneous-dependencies, @typescript-eslint/no-var-requires, import/no-dynamic-require const mod = require(modulePath); const defaultExport = getDefaultExport(mod); if (defaultExport) { return defaultExport; } } catch (_) { // Try next path } } return resolvedModule; } /** * Safely extracts the default export from a module, if it exists. * Useful for supporting both CommonJS and ESM-syntax exports. * Supports upcoming Metro v0.83.2 https://github.com/facebook/metro/commit/5d301d7177af455fc6a94a0ba464639677cdf4b4. */ export function getDefaultExport(module) { if (!module) { return undefined; } if (typeof module === 'object' && 'default' in module) { return module.default; } else { return module; } } //# sourceMappingURL=utils.js.map