UNPKG

@nx/expo

Version:

The Expo Plugin for Nx contains executors and generators for managing and developing an expo application within your workspace. For example, you can directly build for different target platforms as well as generate projects and publish your code.

151 lines (149 loc) 5.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = update; const devkit_1 = require("@nx/devkit"); const jest_1 = require("@nx/jest"); const path_1 = require("path"); /** * Update Jest configuration for Expo SDK 54. * * Expo 54 requires a different approach for Jest configuration: * - Remove the custom resolver from jest.config * - Delete the jest.resolver.js file * - Add ImportMetaRegistry mock and structuredClone polyfill to test-setup.ts * - Update tsconfig files to remove jest.resolver.js references */ async function update(tree) { const projects = (0, devkit_1.getProjects)(tree); for (const [projectName, config] of projects.entries()) { if (!isExpoProject(tree, config.root)) { continue; } // Check if this project has Jest configured const jestConfigPath = findJestConfigPath(tree, config.root); if (!jestConfigPath) { continue; } const jestConfigContent = tree.read(jestConfigPath, 'utf-8'); // Only process if this is an Expo project with jest-expo preset and custom resolver if (!jestConfigContent.includes('jest-expo') || !jestConfigContent.includes('jest.resolver.js')) { continue; } // Remove resolver property from jest.config using AST (0, jest_1.removePropertyFromJestConfig)(tree, jestConfigPath, 'resolver'); // Delete jest.resolver.js file const resolverPath = (0, path_1.join)(config.root, 'jest.resolver.js'); if (tree.exists(resolverPath)) { tree.delete(resolverPath); } // Update test-setup.ts with new mocks updateTestSetup(tree, config.root); // Update tsconfig files to remove jest.resolver.js references updateTsConfigFilesForV54(tree, config.root); devkit_1.logger.info(`Updated Jest configuration for ${projectName} to support Expo SDK 54`); } await (0, devkit_1.formatFiles)(tree); } function findJestConfigPath(tree, projectRoot) { const possiblePaths = [ (0, path_1.join)(projectRoot, 'jest.config.ts'), (0, path_1.join)(projectRoot, 'jest.config.cts'), (0, path_1.join)(projectRoot, 'jest.config.js'), ]; for (const configPath of possiblePaths) { if (tree.exists(configPath)) { return configPath; } } return null; } function updateTestSetup(tree, projectRoot) { const testSetupTsPath = (0, path_1.join)(projectRoot, 'src/test-setup.ts'); const testSetupJsPath = (0, path_1.join)(projectRoot, 'src/test-setup.js'); let testSetupPath = testSetupTsPath; if (!tree.exists(testSetupTsPath)) { if (tree.exists(testSetupJsPath)) { testSetupPath = testSetupJsPath; } else { // Create test-setup.ts if it doesn't exist tree.write(testSetupPath, ''); } } let existingContent = tree.read(testSetupPath, 'utf-8') || ''; // Add ImportMetaRegistry mock if not already present if (!existingContent.includes('ImportMetaRegistry')) { const importMetaRegistryMock = `jest.mock('expo/src/winter/ImportMetaRegistry', () => ({ ImportMetaRegistry: { get url() { return null; }, }, })); `; existingContent = importMetaRegistryMock + existingContent; } // Add structuredClone polyfill if not already present if (!existingContent.includes('structuredClone')) { const structuredClonePolyfill = `if (typeof global.structuredClone === 'undefined') { global.structuredClone = (object) => JSON.parse(JSON.stringify(object)); } `; existingContent = existingContent + '\n' + structuredClonePolyfill; } tree.write(testSetupPath, existingContent); } function updateTsConfigFilesForV54(tree, projectRoot) { // Update main tsconfig (app or lib) to remove jest.resolver.js from excludes const mainTsConfigFiles = [ 'tsconfig.app.json', 'tsconfig.lib.json', 'tsconfig.json', ]; for (const configFile of mainTsConfigFiles) { const configPath = (0, path_1.join)(projectRoot, configFile); if (tree.exists(configPath)) { try { (0, devkit_1.updateJson)(tree, configPath, (json) => { if (json.exclude && Array.isArray(json.exclude)) { json.exclude = json.exclude.filter((item) => item !== 'jest.resolver.js'); } return json; }); } catch { // Skip if JSON is invalid } break; } } // Update tsconfig.spec.json to remove jest.resolver.js from includes const specTsConfigPath = (0, path_1.join)(projectRoot, 'tsconfig.spec.json'); if (tree.exists(specTsConfigPath)) { try { (0, devkit_1.updateJson)(tree, specTsConfigPath, (json) => { if (json.include && Array.isArray(json.include)) { json.include = json.include.filter((item) => item !== 'jest.resolver.js'); } return json; }); } catch { // Skip if JSON is invalid } } } function isExpoProject(tree, projectRoot) { const packageJsonPath = (0, devkit_1.joinPathFragments)(projectRoot, 'package.json'); if (!tree.exists(packageJsonPath)) { return false; } try { const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath); return Boolean(packageJson.dependencies?.expo || packageJson.devDependencies?.expo); } catch { return false; } }