From accf6e1e7e5c606f4f51e87767ce717a71473865 Mon Sep 17 00:00:00 2001 From: Hirbod <504909+hirbod@users.noreply.github.com> Date: Wed, 18 Feb 2026 22:55:15 +0100 Subject: [PATCH 1/3] [docs] Add cookie consent banner (#43197) # Why Add cookie consent functionality to the Expo documentation site to comply with privacy regulations. This integrates the `@expo/styleguide-cookie-consent` package to manage user consent for analytics and marketing cookies. > [!NOTE] > CI forced me to lint and format a bunch of files that were totally unrelated to my work, but wouldn't build otherwise. > [!IMPORTANT] > **Should be merged after it landed on Expo.dev, as it has absolute URLs to new pages that need to deploy first.** # How - Added `@expo/styleguide-cookie-consent` package to dependencies - Integrated `CookieConsentProvider` in the app layout - Refactored analytics implementation to respect user consent preferences: - Replaced `AnalyticsProvider` with `useAnalyticsPageTracking` hook - Modified analytics functions to check consent status before tracking - Added event queueing for pending consent - Implemented replay functionality to process queued events when consent is granted - Updated the newsletter signup to respect marketing consent - Added privacy choices button to the footer # Test Plan - Verified the cookie consent banner appears on first visit - Confirmed analytics events are only sent when consent is granted - Tested that the privacy choices button in the footer opens the consent management UI - Ensured newsletter signup respects marketing consent settings # Checklist - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- docs/common/utilities.ts | 2 +- docs/components/plugins/APISection.tsx | 4 +- .../plugins/api/APISectionCompoundNames.ts | 2 +- .../plugins/api/APISectionEnums.tsx | 2 +- .../plugins/api/APISectionUtils.tsx | 2 +- .../plugins/api/components/APIDataType.tsx | 2 +- docs/jest.config.js | 3 + docs/package.json | 1 + docs/pages/_app.tsx | 12 +- docs/providers/Analytics.tsx | 158 ++- docs/tailwind.config.cjs | 1 + docs/ui/components/Footer/Footer.tsx | 2 + .../ui/components/Footer/NewsletterSignUp.tsx | 4 + docs/ui/components/Tabs/Tabs.tsx | 2 +- docs/yarn.lock | 950 ++++-------------- 15 files changed, 358 insertions(+), 789 deletions(-) diff --git a/docs/common/utilities.ts b/docs/common/utilities.ts index 72172e81a8111b..015a21234c5f4b 100644 --- a/docs/common/utilities.ts +++ b/docs/common/utilities.ts @@ -183,7 +183,7 @@ export function versionToText(version: string): string { return 'Next (unversioned)'; } else if (version === 'latest') { return `${formatSdkVersion(LATEST_VERSION)} (latest)`; - } else if (BETA_VERSION && version === BETA_VERSION.toString()) { + } else if (version === BETA_VERSION?.toString()) { return `${formatSdkVersion(BETA_VERSION.toString())} (beta)`; } diff --git a/docs/components/plugins/APISection.tsx b/docs/components/plugins/APISection.tsx index 9d2be22f8f992c..f15c409e4c14cc 100644 --- a/docs/components/plugins/APISection.tsx +++ b/docs/components/plugins/APISection.tsx @@ -130,8 +130,8 @@ const isComponent = (entry: GeneratedData) => { } else if (signatures?.length) { const mainSignature = signatures[0]; if ( - (mainSignature.parameters && mainSignature.parameters[0].name === 'props') || - (mainSignature.parameters && mainSignature.parameters[0].name === '__namedParameters') + mainSignature.parameters?.[0].name === 'props' || + mainSignature.parameters?.[0].name === '__namedParameters' ) { return true; } diff --git a/docs/components/plugins/api/APISectionCompoundNames.ts b/docs/components/plugins/api/APISectionCompoundNames.ts index 9cc0f0795445ef..da55af959542cf 100644 --- a/docs/components/plugins/api/APISectionCompoundNames.ts +++ b/docs/components/plugins/api/APISectionCompoundNames.ts @@ -34,7 +34,7 @@ export const getComponentPropertyChildren = (entry: GeneratedData): PropData[] = const seen = new Set(); return candidates.filter(child => { - if (!child || child.kind !== TypeDocKind.Property) { + if (child?.kind !== TypeDocKind.Property) { return false; } const id = `${child.name ?? ''}-${child.kind ?? ''}`; diff --git a/docs/components/plugins/api/APISectionEnums.tsx b/docs/components/plugins/api/APISectionEnums.tsx index f8bb86efa3d788..67caf20e284959 100644 --- a/docs/components/plugins/api/APISectionEnums.tsx +++ b/docs/components/plugins/api/APISectionEnums.tsx @@ -14,7 +14,7 @@ export type APISectionEnumsProps = { }; const sortByValue = (a: EnumValueData, b: EnumValueData) => { - if (a.type && a.type.value !== undefined && b.type && b.type.value !== undefined) { + if (a.type?.value !== undefined && b.type?.value !== undefined) { if (typeof a.type.value === 'string' && typeof b.type.value === 'string') { return a.type.value.localeCompare(b.type.value); } else if (typeof a.type.value === 'number' && typeof b.type.value === 'number') { diff --git a/docs/components/plugins/api/APISectionUtils.tsx b/docs/components/plugins/api/APISectionUtils.tsx index 21bdd4a0f94df1..23af41f4c12131 100644 --- a/docs/components/plugins/api/APISectionUtils.tsx +++ b/docs/components/plugins/api/APISectionUtils.tsx @@ -270,7 +270,7 @@ export const resolveTypeName = ( return 'See description for available values.'; } return renderUnion(types, { sdkVersion }); - } else if (elementType && elementType.type === 'union' && elementType?.types?.length) { + } else if (elementType?.type === 'union' && elementType?.types?.length) { const unionTypes = elementType?.types ?? []; return ( <> diff --git a/docs/components/plugins/api/components/APIDataType.tsx b/docs/components/plugins/api/components/APIDataType.tsx index 030fb8451f5643..f1844187fc3f7f 100644 --- a/docs/components/plugins/api/components/APIDataType.tsx +++ b/docs/components/plugins/api/components/APIDataType.tsx @@ -20,7 +20,7 @@ export const APIDataType = ({ typeDefinition, sdkVersion, inline = true }: APIDa const isIntersectionWithObject = type === 'intersection' && types?.filter(typeDefinitionContainsObject).length; const isUnionWithObject = - (type === 'union' || (elementType && elementType.type === 'union')) && + (type === 'union' || elementType?.type === 'union') && (types?.filter(typeDefinitionContainsObject)?.length ?? 0) > 0; const isObjectWrapped = type === 'reference' && diff --git a/docs/jest.config.js b/docs/jest.config.js index 40e6da9bedd977..ee6e8d68c5dc42 100644 --- a/docs/jest.config.js +++ b/docs/jest.config.js @@ -20,6 +20,9 @@ const jestConfig = { '^nanoid/index.browser.js$': '/node_modules/nanoid/index.browser.cjs', '^nanoid$': '/node_modules/nanoid/index.cjs', '^nanoid/non-secure$': '/node_modules/nanoid/non-secure/index.cjs', + // c15t (used by our cookie consent) bundles CSS modules that jsdom cannot parse + '^@expo/styleguide-cookie-consent$': + '/node_modules/@expo/styleguide-cookie-consent/mock.js', }, transform: {}, extensionsToTreatAsEsm: ['.ts', '.tsx'], diff --git a/docs/package.json b/docs/package.json index 81b5afc2e06ddd..db6311a07b014a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -35,6 +35,7 @@ "dependencies": { "@expo/styleguide": "^9.3.1", "@expo/styleguide-base": "^2.0.5", + "@expo/styleguide-cookie-consent": "^0.1.11", "@expo/styleguide-icons": "^2.3.4", "@expo/styleguide-search-ui": "^3.3.3", "@kapaai/react-sdk": "^0.9.0", diff --git a/docs/pages/_app.tsx b/docs/pages/_app.tsx index 0ab1292908ea1c..05e1274139dceb 100644 --- a/docs/pages/_app.tsx +++ b/docs/pages/_app.tsx @@ -1,4 +1,5 @@ import { ThemeProvider } from '@expo/styleguide'; +import { CookieConsentProvider } from '@expo/styleguide-cookie-consent'; import { KapaProvider } from '@kapaai/react-sdk'; import { MDXProvider } from '@mdx-js/react'; import * as Sentry from '@sentry/react'; @@ -9,7 +10,7 @@ import { Inter, JetBrains_Mono } from 'next/font/google'; import { preprocessSentryError } from '~/common/sentry-utilities'; import { useNProgress } from '~/common/useNProgress'; import { DocumentationPageWrapper } from '~/components/DocumentationPageWrapper'; -import { AnalyticsProvider } from '~/providers/Analytics'; +import { useAnalyticsPageTracking } from '~/providers/Analytics'; import { CodeBlockSettingsProvider } from '~/providers/CodeBlockSettingsProvider'; import { TutorialChapterCompletionProvider } from '~/providers/TutorialChapterCompletionProvider'; import { markdownComponents } from '~/ui/components/Markdown'; @@ -60,6 +61,7 @@ export { reportWebVitals } from '~/providers/Analytics'; export default function App({ Component, pageProps }: AppProps) { useNProgress(); + useAnalyticsPageTracking(); return ( <> {/* eslint-disable-next-line react/no-unknown-property */} @@ -81,8 +83,8 @@ export default function App({ Component, pageProps }: AppProps) { } `} - - + + @@ -94,8 +96,8 @@ export default function App({ Component, pageProps }: AppProps) { - - + + ); diff --git a/docs/providers/Analytics.tsx b/docs/providers/Analytics.tsx index 67d0c842c0cd3c..b1df36e0ec4651 100644 --- a/docs/providers/Analytics.tsx +++ b/docs/providers/Analytics.tsx @@ -1,18 +1,22 @@ +import { + isAnalyticsConsented, + enqueueAnalyticsEvent, + setAnalyticsReplayFn, + getAnalyticsConsentStatus, +} from '@expo/styleguide-cookie-consent'; +import type { QueuedEvent } from '@expo/styleguide-cookie-consent'; import { NextWebVitalsMetric } from 'next/app'; import { useRouter } from 'next/compat/router'; -import Script from 'next/script'; -import React, { PropsWithChildren, useEffect } from 'react'; +import { useEffect } from 'react'; /** The global analytics measurement ID */ const MEASUREMENT_ID = 'G-YKNPYCMLWY'; -type AnalyticsProps = PropsWithChildren; - /** - * @see https://nextjs.org/docs/messages/next-script-for-ga - * @see https://nextjs.org/docs/basic-features/script#lazyonload + * Hook that subscribes to Next.js router events and reports page views. + * Call this from the App component in _app.tsx. */ -export function AnalyticsProvider(props: AnalyticsProps) { +export function useAnalyticsPageTracking() { const router = useRouter(); useEffect(function didMount() { @@ -21,67 +25,129 @@ export function AnalyticsProvider(props: AnalyticsProps) { router?.events.off('routeChangeComplete', reportPageView); }; }, []); - - return ( - <> - - {props.children} - - ); } export function reportPageView(url: string) { - window?.gtag?.('config', MEASUREMENT_ID, { - page_path: url, - transport_type: 'beacon', - anonymize_ip: true, - }); + if (isAnalyticsConsented()) { + window?.gtag?.('config', MEASUREMENT_ID, { + page_path: url, + transport_type: 'beacon', + anonymize_ip: true, + }); + return; + } + + if (getAnalyticsConsentStatus() === 'pending') { + enqueueAnalyticsEvent({ + type: 'track', + args: ['pageview', url], + timestamp: Date.now(), + }); + } } export function reportWebVitals({ id, name, label, value }: NextWebVitalsMetric) { - window?.gtag?.('event', name, { + const payload = { event_category: label === 'web-vital' ? 'Web Vitals' : 'Next.js custom metric', - // Google Analytics metrics must be integers, so the value is rounded. - // For CLS the value is first multiplied by 1000 for greater precision - // (note: increase the multiplier for greater precision if needed). value: Math.round(name === 'CLS' ? value * 1000 : value), - // The `id` value will be unique to the current page load. When sending - // multiple values from the same page (e.g. for CLS), Google Analytics can - // compute a total by grouping on this ID (note: requires `eventLabel` to - // be a dimension in your report). event_label: id, - // Use a non-interaction event to avoid affecting bounce rate. non_interaction: true, anonymize_ip: true, - }); + }; + + if (isAnalyticsConsented()) { + window?.gtag?.('event', name, payload); + return; + } + + if (getAnalyticsConsentStatus() === 'pending') { + enqueueAnalyticsEvent({ + type: 'track', + args: ['webvitals', { name, ...payload }], + timestamp: Date.now(), + }); + } } export function reportPageVote({ status }: { status: boolean }) { - window?.gtag?.('event', status ? 'page_vote_up' : 'page_vote_down', { + const eventName = status ? 'page_vote_up' : 'page_vote_down'; + const payload = { event_category: 'Page vote', - value: window?.location.pathname, - // Use a non-interaction event to avoid affecting bounce rate. + value: typeof window !== 'undefined' ? window.location.pathname : '', non_interaction: true, anonymize_ip: true, - }); + }; + + if (isAnalyticsConsented()) { + window?.gtag?.('event', eventName, payload); + return; + } + + if (getAnalyticsConsentStatus() === 'pending') { + enqueueAnalyticsEvent({ + type: 'track', + args: ['pagevote', { status, eventName, ...payload }], + timestamp: Date.now(), + }); + } } export function reportEasTutorialCompleted() { - window?.gtag?.('event', 'eas_tutorial', { + const payload = { event_category: 'EAS Tutorial Completed', event_label: 'All chapters in EAS Tutorial completed', - // Use a non-interaction event to avoid affecting bounce rate. non_interaction: true, anonymize_ip: true, - }); + }; + + if (isAnalyticsConsented()) { + window?.gtag?.('event', 'eas_tutorial', payload); + return; + } + + if (getAnalyticsConsentStatus() === 'pending') { + enqueueAnalyticsEvent({ + type: 'track', + args: ['eas_tutorial', payload], + timestamp: Date.now(), + }); + } } + +// Register the replay function so queued events are dispatched when consent is granted. +setAnalyticsReplayFn((events: QueuedEvent[]) => { + for (const event of events) { + if (event.type !== 'track') { + continue; + } + + const [eventType, data] = event.args as [string, unknown]; + + switch (eventType) { + case 'pageview': { + const url = data as string; + window?.gtag?.('config', MEASUREMENT_ID, { + page_path: url, + transport_type: 'beacon', + anonymize_ip: true, + }); + break; + } + case 'webvitals': { + const { name, ...payload } = data as Record; + window?.gtag?.('event', name as string, payload); + break; + } + case 'pagevote': { + const { eventName, ...payload } = data as Record; + window?.gtag?.('event', eventName as string, payload); + break; + } + case 'eas_tutorial': { + const payload = data as Record; + window?.gtag?.('event', 'eas_tutorial', payload); + break; + } + } + } +}); diff --git a/docs/tailwind.config.cjs b/docs/tailwind.config.cjs index 82ede4f6408cac..d00f4086e70078 100644 --- a/docs/tailwind.config.cjs +++ b/docs/tailwind.config.cjs @@ -18,6 +18,7 @@ module.exports = { './scenes/**/*.{js,ts,jsx,tsx}', './node_modules/@expo/styleguide/dist/**/*.{js,ts,jsx,tsx}', './node_modules/@expo/styleguide-search-ui/dist/**/*.{js,ts,jsx,tsx}', + './node_modules/@expo/styleguide-cookie-consent/dist/**/*.{js,ts,jsx,tsx}', ], ...getExpoTheme({ backgroundColor: { diff --git a/docs/ui/components/Footer/Footer.tsx b/docs/ui/components/Footer/Footer.tsx index e71ec7132df432..b221fc4bdb59c2 100644 --- a/docs/ui/components/Footer/Footer.tsx +++ b/docs/ui/components/Footer/Footer.tsx @@ -1,4 +1,5 @@ import { LinkBase, mergeClasses } from '@expo/styleguide'; +import { PrivacyChoicesButton } from '@expo/styleguide-cookie-consent'; import { ArrowLeftIcon } from '@expo/styleguide-icons/outline/ArrowLeftIcon'; import { ArrowRightIcon } from '@expo/styleguide-icons/outline/ArrowRightIcon'; import { useRouter } from 'next/compat/router'; @@ -131,6 +132,7 @@ export const Footer = ({ + ); }; diff --git a/docs/ui/components/Footer/NewsletterSignUp.tsx b/docs/ui/components/Footer/NewsletterSignUp.tsx index 080b2fc4903106..6eb4880d2d839a 100644 --- a/docs/ui/components/Footer/NewsletterSignUp.tsx +++ b/docs/ui/components/Footer/NewsletterSignUp.tsx @@ -1,4 +1,5 @@ import { Button, mergeClasses } from '@expo/styleguide'; +import { isMarketingConsented } from '@expo/styleguide-cookie-consent'; import { Mail01Icon } from '@expo/styleguide-icons/outline/Mail01Icon'; import { useState } from 'react'; @@ -9,6 +10,9 @@ const PORTAL_ID = '22007177'; const FORM_GUID = '6a213eb9-5e86-4a8e-8607-33f9ac1e07d6'; function getHutk() { + if (!isMarketingConsented()) { + return ''; + } return ( document.cookie .split('; ') diff --git a/docs/ui/components/Tabs/Tabs.tsx b/docs/ui/components/Tabs/Tabs.tsx index adb02127abfb78..f3151017917da0 100644 --- a/docs/ui/components/Tabs/Tabs.tsx +++ b/docs/ui/components/Tabs/Tabs.tsx @@ -64,7 +64,7 @@ const InnerTabs = ({ setIndex, }: Props & { index: number; setIndex: (index: number) => void }) => { const tabPanels = useMemo(() => collectTabPanels(children), [children]); - const tabTitles = tabs && tabs.length === tabPanels.length ? tabs : generateTabLabels(tabPanels); + const tabTitles = tabs?.length === tabPanels.length ? tabs : generateTabLabels(tabPanels); const layoutId = useMemo( () => tabTitles.reduce((acc, tab) => acc + tab, `${Math.random().toString(36).slice(5)}-`), diff --git a/docs/yarn.lock b/docs/yarn.lock index 5ba5aaa77e82c0..67afef5025fc1a 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -19,16 +19,6 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.2.0": - version: 2.3.0 - resolution: "@ampproject/remapping@npm:2.3.0" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed - languageName: node - linkType: hard - "@apidevtools/json-schema-ref-parser@npm:^11.9.3": version: 11.9.3 resolution: "@apidevtools/json-schema-ref-parser@npm:11.9.3" @@ -58,18 +48,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/code-frame@npm:7.27.1" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.27.1" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.1.1" - checksum: 10c0/5dd9a18baa5fce4741ba729acc3a3272c49c25cb8736c4b18e113099520e7ef7b545a4096a26d600e4416157e63e87d66db46aa3fbf0a5f2286da2705c12da00 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.28.6": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.28.6": version: 7.28.6 resolution: "@babel/code-frame@npm:7.28.6" dependencies: @@ -80,13 +59,6 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.27.2": - version: 7.28.0 - resolution: "@babel/compat-data@npm:7.28.0" - checksum: 10c0/c4e527302bcd61052423f757355a71c3bc62362bac13f7f130de16e439716f66091ff5bdecda418e8fa0271d4c725f860f0ee23ab7bf6e769f7a8bb16dfcb531 - languageName: node - linkType: hard - "@babel/compat-data@npm:^7.28.6": version: 7.28.6 resolution: "@babel/compat-data@npm:7.28.6" @@ -94,30 +66,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.18.5, @babel/core@npm:^7.23.9": - version: 7.28.0 - resolution: "@babel/core@npm:7.28.0" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.0" - "@babel/helper-compilation-targets": "npm:^7.27.2" - "@babel/helper-module-transforms": "npm:^7.27.3" - "@babel/helpers": "npm:^7.27.6" - "@babel/parser": "npm:^7.28.0" - "@babel/template": "npm:^7.27.2" - "@babel/traverse": "npm:^7.28.0" - "@babel/types": "npm:^7.28.0" - convert-source-map: "npm:^2.0.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: 10c0/423302e7c721e73b1c096217880272e02020dfb697a55ccca60ad01bba90037015f84d0c20c6ce297cf33a19bb704bc5c2b3d3095f5284dfa592bd1de0b9e8c3 - languageName: node - linkType: hard - -"@babel/core@npm:^7.24.4": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.18.5, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4": version: 7.28.6 resolution: "@babel/core@npm:7.28.6" dependencies: @@ -140,20 +89,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.28.0, @babel/generator@npm:^7.7.2": - version: 7.28.0 - resolution: "@babel/generator@npm:7.28.0" - dependencies: - "@babel/parser": "npm:^7.28.0" - "@babel/types": "npm:^7.28.0" - "@jridgewell/gen-mapping": "npm:^0.3.12" - "@jridgewell/trace-mapping": "npm:^0.3.28" - jsesc: "npm:^3.0.2" - checksum: 10c0/1b3d122268ea3df50fde707ad864d9a55c72621357d5cebb972db3dd76859c45810c56e16ad23123f18f80cc2692f5a015d2858361300f0f224a05dc43d36a92 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.28.6": +"@babel/generator@npm:^7.28.6, @babel/generator@npm:^7.7.2": version: 7.28.6 resolution: "@babel/generator@npm:7.28.6" dependencies: @@ -166,19 +102,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/helper-compilation-targets@npm:7.27.2" - dependencies: - "@babel/compat-data": "npm:^7.27.2" - "@babel/helper-validator-option": "npm:^7.27.1" - browserslist: "npm:^4.24.0" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.1" - checksum: 10c0/f338fa00dcfea931804a7c55d1a1c81b6f0a09787e528ec580d5c21b3ecb3913f6cb0f361368973ce953b824d910d3ac3e8a8ee15192710d3563826447193ad1 - languageName: node - linkType: hard - "@babel/helper-compilation-targets@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-compilation-targets@npm:7.28.6" @@ -199,16 +122,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-module-imports@npm:7.27.1" - dependencies: - "@babel/traverse": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/e00aace096e4e29290ff8648455c2bc4ed982f0d61dbf2db1b5e750b9b98f318bf5788d75a4f974c151bd318fd549e81dbcab595f46b14b81c12eda3023f51e8 - languageName: node - linkType: hard - "@babel/helper-module-imports@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-imports@npm:7.28.6" @@ -219,19 +132,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/helper-module-transforms@npm:7.27.3" - dependencies: - "@babel/helper-module-imports": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.3" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/fccb4f512a13b4c069af51e1b56b20f54024bcf1591e31e978a30f3502567f34f90a80da6a19a6148c249216292a8074a0121f9e52602510ef0f32dbce95ca01 - languageName: node - linkType: hard - "@babel/helper-module-transforms@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-transforms@npm:7.28.6" @@ -259,13 +159,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-identifier@npm:7.27.1" - checksum: 10c0/c558f11c4871d526498e49d07a84752d1800bf72ac0d3dad100309a2eaba24efbf56ea59af5137ff15e3a00280ebe588560534b0e894a4750f8b1411d8f78b84 - languageName: node - linkType: hard - "@babel/helper-validator-identifier@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-validator-identifier@npm:7.28.5" @@ -280,16 +173,6 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.27.6": - version: 7.28.2 - resolution: "@babel/helpers@npm:7.28.2" - dependencies: - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.2" - checksum: 10c0/f3e7b21517e2699c4ca193663ecfb1bf1b2ae2762d8ba4a9f1786feaca0d6984537fc60bf2206e92c43640a6dada6b438f523cc1ad78610d0151aeb061b37f63 - languageName: node - linkType: hard - "@babel/helpers@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helpers@npm:7.28.6" @@ -300,18 +183,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/parser@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.0" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/c2ef81d598990fa949d1d388429df327420357cb5200271d0d0a2784f1e6d54afc8301eb8bdf96d8f6c77781e402da93c7dc07980fcc136ac5b9d5f1fce701b5 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6": version: 7.28.6 resolution: "@babel/parser@npm:7.28.6" dependencies: @@ -516,18 +388,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": - version: 7.27.2 - resolution: "@babel/template@npm:7.27.2" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/parser": "npm:^7.27.2" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/ed9e9022651e463cc5f2cc21942f0e74544f1754d231add6348ff1b472985a3b3502041c0be62dc99ed2d12cfae0c51394bf827452b98a2f8769c03b87aadc81 - languageName: node - linkType: hard - -"@babel/template@npm:^7.28.6": +"@babel/template@npm:^7.28.6, @babel/template@npm:^7.3.3": version: 7.28.6 resolution: "@babel/template@npm:7.28.6" dependencies: @@ -538,21 +399,6 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.27.3, @babel/traverse@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/traverse@npm:7.28.0" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.0" - "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.28.0" - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.0" - debug: "npm:^4.3.1" - checksum: 10c0/32794402457827ac558173bcebdcc0e3a18fa339b7c41ca35621f9f645f044534d91bb923ff385f5f960f2e495f56ce18d6c7b0d064d2f0ccb55b285fa6bc7b9 - languageName: node - linkType: hard - "@babel/traverse@npm:^7.28.6": version: 7.28.6 resolution: "@babel/traverse@npm:7.28.6" @@ -568,17 +414,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.28.0, @babel/types@npm:^7.28.2, @babel/types@npm:^7.3.3": - version: 7.28.2 - resolution: "@babel/types@npm:7.28.2" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10c0/24b11c9368e7e2c291fe3c1bcd1ed66f6593a3975f479cbb9dd7b8c8d8eab8a962b0d2fca616c043396ce82500ac7d23d594fbbbd013828182c01596370a0b10 - languageName: node - linkType: hard - -"@babel/types@npm:^7.28.6": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.28.6, @babel/types@npm:^7.3.3": version: 7.28.6 resolution: "@babel/types@npm:7.28.6" dependencies: @@ -850,18 +686,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.0": - version: 4.9.0 - resolution: "@eslint-community/eslint-utils@npm:4.9.0" - dependencies: - eslint-visitor-keys: "npm:^3.4.3" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/8881e22d519326e7dba85ea915ac7a143367c805e6ba1374c987aa2fbdd09195cc51183d2da72c0e2ff388f84363e1b220fd0d19bef10c272c63455162176817 - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.9.1": +"@eslint-community/eslint-utils@npm:^4.1.2, @eslint-community/eslint-utils@npm:^4.5.0, @eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.0, @eslint-community/eslint-utils@npm:^4.9.1": version: 4.9.1 resolution: "@eslint-community/eslint-utils@npm:4.9.1" dependencies: @@ -872,14 +697,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.12.1": - version: 4.12.1 - resolution: "@eslint-community/regexpp@npm:4.12.1" - checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6 - languageName: node - linkType: hard - -"@eslint-community/regexpp@npm:^4.12.2": +"@eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.12.2": version: 4.12.2 resolution: "@eslint-community/regexpp@npm:4.12.2" checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d @@ -906,15 +724,6 @@ __metadata: languageName: node linkType: hard -"@eslint/core@npm:^0.16.0": - version: 0.16.0 - resolution: "@eslint/core@npm:0.16.0" - dependencies: - "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/f27496a244ccfdca3e0fbc3331f9da3f603bdf1aa431af0045a3205826789a54493bc619ad6311a9090eaf7bc25798ff4e265dea1eccd2df9ce3b454f7e7da27 - languageName: node - linkType: hard - "@eslint/core@npm:^0.17.0": version: 0.17.0 resolution: "@eslint/core@npm:0.17.0" @@ -955,17 +764,7 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.4.0": - version: 0.4.0 - resolution: "@eslint/plugin-kit@npm:0.4.0" - dependencies: - "@eslint/core": "npm:^0.16.0" - levn: "npm:^0.4.1" - checksum: 10c0/125614e902bb34c041da859794c47ac2ec4a814f5d9e7c4d37fcd34b38d8ee5cf1f97020d38d168885d9bf4046a9a7decb86b4cee8dac9eedcc6ad08ebafe204 - languageName: node - linkType: hard - -"@eslint/plugin-kit@npm:^0.4.1": +"@eslint/plugin-kit@npm:^0.4.0, @eslint/plugin-kit@npm:^0.4.1": version: 0.4.1 resolution: "@eslint/plugin-kit@npm:0.4.1" dependencies: @@ -995,6 +794,21 @@ __metadata: languageName: node linkType: hard +"@expo/styleguide-cookie-consent@npm:^0.1.11": + version: 0.1.11 + resolution: "@expo/styleguide-cookie-consent@npm:0.1.11" + dependencies: + "@radix-ui/react-accordion": "npm:^1.2.4" + "@radix-ui/react-slot": "npm:^1.2.0" + "@radix-ui/react-switch": "npm:^1.1.4" + clsx: "npm:^2.1.1" + zustand: "npm:^5.0.3" + peerDependencies: + react: ">= 19" + checksum: 10c0/a5eea96abb9716b42eb9aa498898c472e771e81d7c10a7e47bb980c6b609b8a5728505eafb5e2a80323f0184b5883dbfebfc50c1e8d776fdb7615b1e98fa2e29 + languageName: node + linkType: hard + "@expo/styleguide-icons@npm:^2.3.4": version: 2.3.4 resolution: "@expo/styleguide-icons@npm:2.3.4" @@ -2143,7 +1957,7 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/core@npm:2.5.0, @opentelemetry/core@npm:^2.5.0": +"@opentelemetry/core@npm:2.5.0": version: 2.5.0 resolution: "@opentelemetry/core@npm:2.5.0" dependencies: @@ -2154,14 +1968,14 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/core@npm:^2.0.0": - version: 2.1.0 - resolution: "@opentelemetry/core@npm:2.1.0" +"@opentelemetry/core@npm:2.5.1, @opentelemetry/core@npm:^2.0.0, @opentelemetry/core@npm:^2.5.0": + version: 2.5.1 + resolution: "@opentelemetry/core@npm:2.5.1" dependencies: "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/562c44c89150ef9cc7be4fcbfccfb62f71eb95d487de79b6a2716bb960da7d181f5e2ae3354ed6bd0bba0a3903fe5b7dad14b9a4a92fa90ab1b9172f11a3743d + checksum: 10c0/cbaf36953364d1295ef2ff4587c3f99eca121c7c2dbd2553699100ccbd91017f20fb1a710ac76fad832d9762dc98ae009ce0e96ab8fb00e5b539dc401d57f217 languageName: node linkType: hard @@ -2477,46 +2291,32 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/resources@npm:2.5.0, @opentelemetry/resources@npm:^2.5.0": - version: 2.5.0 - resolution: "@opentelemetry/resources@npm:2.5.0" +"@opentelemetry/resources@npm:2.5.1, @opentelemetry/resources@npm:^2.5.0": + version: 2.5.1 + resolution: "@opentelemetry/resources@npm:2.5.1" dependencies: - "@opentelemetry/core": "npm:2.5.0" + "@opentelemetry/core": "npm:2.5.1" "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/30073a5db368e5ed8c44ac87e6ebd4da53b5050e14e367610fa79a049eee3e5e5a82c4fbc1a9cc539d845b68983b74643c094e111baf114159e75ded1d67db08 + checksum: 10c0/c336d5066fa7457272bcffb5a9826f090e1e07c2a70c5976942cf2bb188be685842658982a0f323ddfc1d6fbc364f123b6b0e433e230b023aefd88ec60062ba4 languageName: node linkType: hard "@opentelemetry/sdk-trace-base@npm:^2.5.0": - version: 2.5.0 - resolution: "@opentelemetry/sdk-trace-base@npm:2.5.0" + version: 2.5.1 + resolution: "@opentelemetry/sdk-trace-base@npm:2.5.1" dependencies: - "@opentelemetry/core": "npm:2.5.0" - "@opentelemetry/resources": "npm:2.5.0" + "@opentelemetry/core": "npm:2.5.1" + "@opentelemetry/resources": "npm:2.5.1" "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/5b9f90f128dbdfdda4ccd17a3fa7580cf8389d30c0b5be34d810d5cf2873954c6c662241d0a88caa217e691720c40daebb189e1baf4ba93620c153ae9ee4672a - languageName: node - linkType: hard - -"@opentelemetry/semantic-conventions@npm:^1.24.0, @opentelemetry/semantic-conventions@npm:^1.33.0, @opentelemetry/semantic-conventions@npm:^1.36.0": - version: 1.38.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.38.0" - checksum: 10c0/ae93e39ac18bf47df2b11d43e9a0dc1673b9d33e5f1e7f357c92968e6329fb9a67cf8a447e9a7150948ee3f8178b38274db365b8fa775a8c54802e0c6ccdd2ca - languageName: node - linkType: hard - -"@opentelemetry/semantic-conventions@npm:^1.27.0, @opentelemetry/semantic-conventions@npm:^1.29.0, @opentelemetry/semantic-conventions@npm:^1.30.0, @opentelemetry/semantic-conventions@npm:^1.33.1, @opentelemetry/semantic-conventions@npm:^1.34.0, @opentelemetry/semantic-conventions@npm:^1.37.0": - version: 1.37.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.37.0" - checksum: 10c0/ddce99f36e390603d6bbc556a50c070e41303d764a830808a4c451f02f4e6a3d989dbde8bcfac15e4e5bba13686b36c6664a323321c9259f9030eb70522a7c68 + checksum: 10c0/a1833343cc030f435339e795c20e3e3507e144fd72079325dd4ee2677eccc3602f0e47fc768278ba6b45d18ee03a6700b38db7756eaa8f084dd18d6c26a17bc8 languageName: node linkType: hard -"@opentelemetry/semantic-conventions@npm:^1.39.0": +"@opentelemetry/semantic-conventions@npm:^1.24.0, @opentelemetry/semantic-conventions@npm:^1.27.0, @opentelemetry/semantic-conventions@npm:^1.29.0, @opentelemetry/semantic-conventions@npm:^1.30.0, @opentelemetry/semantic-conventions@npm:^1.33.0, @opentelemetry/semantic-conventions@npm:^1.33.1, @opentelemetry/semantic-conventions@npm:^1.34.0, @opentelemetry/semantic-conventions@npm:^1.36.0, @opentelemetry/semantic-conventions@npm:^1.37.0, @opentelemetry/semantic-conventions@npm:^1.39.0": version: 1.39.0 resolution: "@opentelemetry/semantic-conventions@npm:1.39.0" checksum: 10c0/1a8cc16e83ccd80aeb910e78146e8cde8482ac45feb3693348eec5983d8ad254f977f2b61db76f043ab0fa6009a27df610a9cff286a217d6cd4c114216861d0f @@ -2623,6 +2423,33 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-accordion@npm:^1.2.4": + version: 1.2.12 + resolution: "@radix-ui/react-accordion@npm:1.2.12" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-collapsible": "npm:1.1.12" + "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/c64a53ce766a1ef529cf6413ed7382598c94f78879b3a83ceda27cb1894ed6eb6e8ad61f6a550ca3c7fa813657045dadfc7328dbf1d736a37e1cf3c446db43de + languageName: node + linkType: hard + "@radix-ui/react-arrow@npm:1.1.7": version: 1.1.7 resolution: "@radix-ui/react-arrow@npm:1.1.7" @@ -2642,6 +2469,32 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-collapsible@npm:1.1.12": + version: 1.1.12 + resolution: "@radix-ui/react-collapsible@npm:1.1.12" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/777cced73fbbec9cfafe6325aa5605e90f49d889af2778f4c4a6be101c07cacd69ae817d0b41cc27e3181f49392e2c06db7f32d6b084db047a51805ec70729b3 + languageName: node + linkType: hard + "@radix-ui/react-collection@npm:1.1.7": version: 1.1.7 resolution: "@radix-ui/react-collection@npm:1.1.7" @@ -3191,6 +3044,46 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-slot@npm:^1.2.0": + version: 1.2.4 + resolution: "@radix-ui/react-slot@npm:1.2.4" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/8b719bb934f1ae5ac0e37214783085c17c2f1080217caf514c1c6cc3d9ca56c7e19d25470b26da79aa6e605ab36589edaade149b76f5fc0666f1063e2fc0a0dc + languageName: node + linkType: hard + +"@radix-ui/react-switch@npm:^1.1.4": + version: 1.2.6 + resolution: "@radix-ui/react-switch@npm:1.2.6" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + "@radix-ui/react-use-previous": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/888303cbeb0e69ebba5676b225f9ea0f00f61453c6b8a6b66384b5c5c4c7fb0ccc53493c1eb14ec6d436e5b867b302aadd6af51a1f2e6c04581c583fd9be65be + languageName: node + linkType: hard + "@radix-ui/react-tooltip@npm:^1.2.8": version: 1.2.8 resolution: "@radix-ui/react-tooltip@npm:1.2.8" @@ -4503,12 +4396,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^22.0.0, @types/node@npm:^22.18.11": - version: 22.18.11 - resolution: "@types/node@npm:22.18.11" +"@types/node@npm:*": + version: 25.2.3 + resolution: "@types/node@npm:25.2.3" dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/3802f598608638e13ca350fbe2db0db5dde9a0b6704295fa1b6cec6defe24f9baf6a891eee6eaecd016bcd5ea18edecdaf71679d87079fe468913701adb61387 + undici-types: "npm:~7.16.0" + checksum: 10c0/925833029ce0bb4a72c36f90b93287184d3511aeb0fa60a994ae94b5430c22f9be6693d67d210df79267cb54c6f6978caaefb149d99ab5f83af5827ba7cb9822 languageName: node linkType: hard @@ -4519,6 +4412,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^22.0.0, @types/node@npm:^22.18.11": + version: 22.18.11 + resolution: "@types/node@npm:22.18.11" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10c0/3802f598608638e13ca350fbe2db0db5dde9a0b6704295fa1b6cec6defe24f9baf6a891eee6eaecd016bcd5ea18edecdaf71679d87079fe468913701adb61387 + languageName: node + linkType: hard + "@types/nprogress@npm:^0.2.3": version: 0.2.3 resolution: "@types/nprogress@npm:0.2.3" @@ -4535,18 +4437,7 @@ __metadata: languageName: node linkType: hard -"@types/pg@npm:*": - version: 8.15.5 - resolution: "@types/pg@npm:8.15.5" - dependencies: - "@types/node": "npm:*" - pg-protocol: "npm:*" - pg-types: "npm:^2.2.0" - checksum: 10c0/19a3cc1811918753f8c827733648c3a85c7b0355bf207c44eb1a3b79b2e6a0d85cb5457ec550d860fc9be7e88c7587a3600958ec8c61fa1ad573061c63af93f0 - languageName: node - linkType: hard - -"@types/pg@npm:8.15.6": +"@types/pg@npm:*, @types/pg@npm:8.15.6": version: 8.15.6 resolution: "@types/pg@npm:8.15.6" dependencies: @@ -4672,7 +4563,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.54.0": +"@typescript-eslint/eslint-plugin@npm:8.54.0, @typescript-eslint/eslint-plugin@npm:^8.29.1": version: 8.54.0 resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0" dependencies: @@ -4692,28 +4583,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.29.1" - dependencies: - "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/type-utils": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.3.1" - natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/a3ed7556edcac374cab622862f2f9adedc91ca305d6937db6869a0253d675858c296cb5413980e8404fc39737117faaf35b00c6804664b3c542bdc417502532f - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:8.54.0": +"@typescript-eslint/parser@npm:8.54.0, @typescript-eslint/parser@npm:^8.29.1": version: 8.54.0 resolution: "@typescript-eslint/parser@npm:8.54.0" dependencies: @@ -4729,22 +4599,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/parser@npm:8.29.1" - dependencies: - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - debug: "npm:^4.3.4" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/af3570ff58c42c2014e5c117bebf91120737fb139d94415ca2711844990e95252c3006ccc699871fe3f592cc1a3f4ebfdc9dd5f6cb29b6b128c2524fcf311b75 - languageName: node - linkType: hard - "@typescript-eslint/project-service@npm:8.54.0": version: 8.54.0 resolution: "@typescript-eslint/project-service@npm:8.54.0" @@ -4758,17 +4612,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.29.1, @typescript-eslint/scope-manager@npm:^8.15.0": - version: 8.29.1 - resolution: "@typescript-eslint/scope-manager@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - checksum: 10c0/8b87a04f01ebc13075e352509bca8f31c757c3220857fa473ac155f6bdf7f30fe82765d0c3d8e790f7fad394a32765bd9f716b97c08e17581d358c76086d51af - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.54.0": +"@typescript-eslint/scope-manager@npm:8.54.0, @typescript-eslint/scope-manager@npm:^8.15.0": version: 8.54.0 resolution: "@typescript-eslint/scope-manager@npm:8.54.0" dependencies: @@ -4787,21 +4631,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/type-utils@npm:8.29.1" - dependencies: - "@typescript-eslint/typescript-estree": "npm:8.29.1" - "@typescript-eslint/utils": "npm:8.29.1" - debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/72cc01dbac866b0a7c7b1f637ad03ffd22f6d3617f70f06f485cf3096fddfc821fdc56de1a072cc6af70250c63698a3e5a910f67fe46eea941955b6e0da1b2bd - languageName: node - linkType: hard - "@typescript-eslint/type-utils@npm:8.54.0": version: 8.54.0 resolution: "@typescript-eslint/type-utils@npm:8.54.0" @@ -4818,13 +4647,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/types@npm:8.29.1" - checksum: 10c0/bbcb9e4f38df4485092b51ac6bb62d65f321d914ab58dc0ff1eaa7787dc0b4a39e237c2617b9f2c2bcb91a343f30de523e3544f69affa1ee4287a3ef2fc10ce7 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.54.0": version: 8.54.0 resolution: "@typescript-eslint/types@npm:8.54.0" @@ -4832,24 +4654,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/visitor-keys": "npm:8.29.1" - debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/33c46c667d9262e5625d5d0064338711b342e62c5675ded6811a2cb13ee5de2f71b90e9d0be5cb338b11b1a329c376a6bbf6c3d24fa8fb457b2eefc9f3298513 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:8.54.0": version: 8.54.0 resolution: "@typescript-eslint/typescript-estree@npm:8.54.0" @@ -4869,22 +4673,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.29.1, @typescript-eslint/utils@npm:^8.15.0": - version: 8.29.1 - resolution: "@typescript-eslint/utils@npm:8.29.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.29.1" - "@typescript-eslint/types": "npm:8.29.1" - "@typescript-eslint/typescript-estree": "npm:8.29.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/1b2704b769b0c9353cf26a320ecf9775ba51c94c7c30e2af80ca31f4cb230f319762ab06535fcb26b6963144bbeaa53233b34965907c506283861b013f5b95fc - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:8.54.0": +"@typescript-eslint/utils@npm:8.54.0, @typescript-eslint/utils@npm:^8.15.0": version: 8.54.0 resolution: "@typescript-eslint/utils@npm:8.54.0" dependencies: @@ -4899,16 +4688,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.29.1": - version: 8.29.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.29.1" - dependencies: - "@typescript-eslint/types": "npm:8.29.1" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/0c12e83c84a754161c89e594a96454799669979c7021a8936515ec574a1fa1d6e3119e0eacf502e07a0fa7254974558ea7a48901c8bfed3c46579a61b655e4f5 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:8.54.0": version: 8.54.0 resolution: "@typescript-eslint/visitor-keys@npm:8.54.0" @@ -5032,7 +4811,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": +"acorn@npm:^8.0.0, acorn@npm:^8.1.0, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.8.1": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -5190,21 +4969,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - is-string: "npm:^1.0.7" - checksum: 10c0/5b1004d203e85873b96ddc493f090c9672fd6c80d7a60b798da8a14bff8a670ff95db5aafc9abc14a211943f05220dacf8ea17638ae0af1a6a47b8c0b48ce370 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.9": +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8, array-includes@npm:^3.1.9": version: 3.1.9 resolution: "array-includes@npm:3.1.9" dependencies: @@ -5234,20 +4999,6 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.5": - version: 1.2.5 - resolution: "array.prototype.findlastindex@npm:1.2.5" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/962189487728b034f3134802b421b5f39e42ee2356d13b42d2ddb0e52057ffdcc170b9524867f4f0611a6f638f4c19b31e14606e8bcbda67799e26685b195aa3 - languageName: node - linkType: hard - "array.prototype.findlastindex@npm:^1.2.6": version: 1.2.6 resolution: "array.prototype.findlastindex@npm:1.2.6" @@ -5263,7 +5014,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.2, array.prototype.flat@npm:^1.3.3": +"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.3": version: 1.3.3 resolution: "array.prototype.flat@npm:1.3.3" dependencies: @@ -5611,21 +5362,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.24.0, browserslist@npm:^4.24.4": - version: 4.24.4 - resolution: "browserslist@npm:4.24.4" - dependencies: - caniuse-lite: "npm:^1.0.30001688" - electron-to-chromium: "npm:^1.5.73" - node-releases: "npm:^2.0.19" - update-browserslist-db: "npm:^1.1.1" - bin: - browserslist: cli.js - checksum: 10c0/db7ebc1733cf471e0b490b4f47e3e2ea2947ce417192c9246644e92c667dd56a71406cc58f62ca7587caf828364892e9952904a02b7aead752bc65b62a37cfe9 - languageName: node - linkType: hard - -"browserslist@npm:^4.28.0": +"browserslist@npm:^4.24.0, browserslist@npm:^4.24.4, browserslist@npm:^4.28.0": version: 4.28.0 resolution: "browserslist@npm:4.28.0" dependencies: @@ -5757,14 +5494,7 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702": - version: 1.0.30001709 - resolution: "caniuse-lite@npm:1.0.30001709" - checksum: 10c0/0acf91f59f52661fc47042e4eee1b527deb54044ae4c79ae7464d0789b79146ad587153a76d78b09157261b9fad89235eb161cd8ea7a58d36fc7f25a2e937df5 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001754": +"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001754": version: 1.0.30001755 resolution: "caniuse-lite@npm:1.0.30001755" checksum: 10c0/7b8e32a4ec307b50f557d30176651cf69f20a0ea4de6f5f34149ea65a1f0cfcc0677b403484aea3661c7469ab11f2df6528027b9ec2d0265635ede9d5b517380 @@ -5816,9 +5546,9 @@ __metadata: linkType: hard "chalk@npm:^5.0.0": - version: 5.4.1 - resolution: "chalk@npm:5.4.1" - checksum: 10c0/b23e88132c702f4855ca6d25cb5538b1114343e41472d5263ee8a37cccfccd9c4216d111e1097c6a27830407a1dc81fecdf2a56f2c63033d4dbbd88c10b0dcef + version: 5.6.2 + resolution: "chalk@npm:5.6.2" + checksum: 10c0/99a4b0f0e7991796b1e7e3f52dceb9137cae2a9dfc8fc0784a550dc4c558e15ab32ed70b14b21b52beb2679b4892b41a0aa44249bcb996f01e125d58477c6976 languageName: node linkType: hard @@ -5937,21 +5667,14 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.0.0": - version: 4.2.0 - resolution: "ci-info@npm:4.2.0" - checksum: 10c0/37a2f4b6a213a5cf835890eb0241f0d5b022f6cfefde58a69e9af8e3a0e71e06d6ad7754b0d4efb9cd2613e58a7a33996d71b56b0d04242722e86666f3f3d058 - languageName: node - linkType: hard - -"ci-info@npm:^4.3.1": +"ci-info@npm:^4.0.0, ci-info@npm:^4.3.1": version: 4.3.1 resolution: "ci-info@npm:4.3.1" checksum: 10c0/7dd82000f514d76ddfe7775e4cb0d66e5c638f5fa0e2a3be29557e898da0d32ac04f231217d414d07fb968b1fbc6d980ee17ddde0d2c516f23da9cfff608f6c1 languageName: node linkType: hard -"cjs-module-lexer@npm:^1.0.0, cjs-module-lexer@npm:^1.2.2": +"cjs-module-lexer@npm:^1.0.0": version: 1.4.3 resolution: "cjs-module-lexer@npm:1.4.3" checksum: 10c0/076b3af85adc4d65dbdab1b5b240fe5b45d44fcf0ef9d429044dd94d19be5589376805c44fb2d4b3e684e5fe6a9b7cf3e426476a6507c45283c5fc6ff95240be @@ -6020,7 +5743,7 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^2.0.0": +"clsx@npm:^2.0.0, clsx@npm:^2.1.1": version: 2.1.1 resolution: "clsx@npm:2.1.1" checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 @@ -6723,13 +6446,6 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.73": - version: 1.5.76 - resolution: "electron-to-chromium@npm:1.5.76" - checksum: 10c0/5a977be9fd5810769a7b4eae0e4b41b6beca65f2b3f3b7442819f6c93366d767d183cfbf408714f944a9bf3aa304f8c9ab9d0cdfd8e878ab8f2cbb61f8b22acd - languageName: node - linkType: hard - "emittery@npm:^0.13.1": version: 0.13.1 resolution: "emittery@npm:0.13.1" @@ -6787,7 +6503,7 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.2.0, entities@npm:^4.5.0": +"entities@npm:^4.2.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 @@ -6838,66 +6554,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" - dependencies: - array-buffer-byte-length: "npm:^1.0.2" - arraybuffer.prototype.slice: "npm:^1.0.4" - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - data-view-buffer: "npm:^1.0.2" - data-view-byte-length: "npm:^1.0.2" - data-view-byte-offset: "npm:^1.0.1" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-set-tostringtag: "npm:^2.1.0" - es-to-primitive: "npm:^1.3.0" - function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.0" - get-symbol-description: "npm:^1.1.0" - globalthis: "npm:^1.0.4" - gopd: "npm:^1.2.0" - has-property-descriptors: "npm:^1.0.2" - has-proto: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - internal-slot: "npm:^1.1.0" - is-array-buffer: "npm:^3.0.5" - is-callable: "npm:^1.2.7" - is-data-view: "npm:^1.0.2" - is-regex: "npm:^1.2.1" - is-shared-array-buffer: "npm:^1.0.4" - is-string: "npm:^1.1.1" - is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.0" - math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.3" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.7" - own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.3" - safe-array-concat: "npm:^1.1.3" - safe-push-apply: "npm:^1.0.0" - safe-regex-test: "npm:^1.1.0" - set-proto: "npm:^1.0.0" - string.prototype.trim: "npm:^1.2.10" - string.prototype.trimend: "npm:^1.0.9" - string.prototype.trimstart: "npm:^1.0.8" - typed-array-buffer: "npm:^1.0.3" - typed-array-byte-length: "npm:^1.0.3" - typed-array-byte-offset: "npm:^1.0.4" - typed-array-length: "npm:^1.0.7" - unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.18" - checksum: 10c0/1de229c9e08fe13c17fe5abaec8221545dfcd57e51f64909599a6ae896df84b8fd2f7d16c60cb00d7bf495b9298ca3581aded19939d4b7276854a4b066f8422b - languageName: node - linkType: hard - -"es-abstract@npm:^1.24.0": +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": version: 1.24.1 resolution: "es-abstract@npm:1.24.1" dependencies: @@ -7018,16 +6675,7 @@ __metadata: languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.2": - version: 1.0.2 - resolution: "es-shim-unscopables@npm:1.0.2" - dependencies: - hasown: "npm:^2.0.0" - checksum: 10c0/f495af7b4b7601a4c0cfb893581c352636e5c08654d129590386a33a0432cf13a7bdc7b6493801cadd990d838e2839b9013d1de3b880440cb537825e834fe783 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.1.0": +"es-shim-unscopables@npm:^1.0.2, es-shim-unscopables@npm:^1.1.0": version: 1.1.0 resolution: "es-shim-unscopables@npm:1.1.0" dependencies: @@ -7345,18 +6993,6 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.12.0": - version: 2.12.0 - resolution: "eslint-module-utils@npm:2.12.0" - dependencies: - debug: "npm:^3.2.7" - peerDependenciesMeta: - eslint: - optional: true - checksum: 10c0/4d8b46dcd525d71276f9be9ffac1d2be61c9d54cc53c992e6333cf957840dee09381842b1acbbb15fc6b255ebab99cd481c5007ab438e5455a14abe1a0468558 - languageName: node - linkType: hard - "eslint-module-utils@npm:^2.12.1": version: 2.12.1 resolution: "eslint-module-utils@npm:2.12.1" @@ -7394,36 +7030,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-import@npm:^2.31.0": - version: 2.31.0 - resolution: "eslint-plugin-import@npm:2.31.0" - dependencies: - "@rtsao/scc": "npm:^1.1.0" - array-includes: "npm:^3.1.8" - array.prototype.findlastindex: "npm:^1.2.5" - array.prototype.flat: "npm:^1.3.2" - array.prototype.flatmap: "npm:^1.3.2" - debug: "npm:^3.2.7" - doctrine: "npm:^2.1.0" - eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.12.0" - hasown: "npm:^2.0.2" - is-core-module: "npm:^2.15.1" - is-glob: "npm:^4.0.3" - minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.8" - object.groupby: "npm:^1.0.3" - object.values: "npm:^1.2.0" - semver: "npm:^6.3.1" - string.prototype.trimend: "npm:^1.0.8" - tsconfig-paths: "npm:^3.15.0" - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - checksum: 10c0/e21d116ddd1900e091ad120b3eb68c5dd5437fe2c930f1211781cd38b246f090a6b74d5f3800b8255a0ed29782591521ad44eb21c5534960a8f1fb4040fd913a - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.32.0": +"eslint-plugin-import@npm:^2.31.0, eslint-plugin-import@npm:^2.32.0": version: 2.32.0 resolution: "eslint-plugin-import@npm:2.32.0" dependencies: @@ -7699,7 +7306,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^4.2.0, eslint-visitor-keys@npm:^4.2.1": +"eslint-visitor-keys@npm:^4.2.1": version: 4.2.1 resolution: "eslint-visitor-keys@npm:4.2.1" checksum: 10c0/fcd43999199d6740db26c58dbe0c2594623e31ca307e616ac05153c9272f12f1364f5a0b1917a8e962268fdecc6f3622c1c2908b4fcc2e047a106fe6de69dc43 @@ -7958,6 +7565,7 @@ __metadata: "@expo/spawn-async": "npm:^1.7.2" "@expo/styleguide": "npm:^9.3.1" "@expo/styleguide-base": "npm:^2.0.5" + "@expo/styleguide-cookie-consent": "npm:^0.1.11" "@expo/styleguide-icons": "npm:^2.3.4" "@expo/styleguide-search-ui": "npm:^3.3.3" "@kapaai/react-sdk": "npm:^0.9.0" @@ -8151,19 +7759,7 @@ __metadata: languageName: node linkType: hard -"fdir@npm:^6.2.0": - version: 6.4.6 - resolution: "fdir@npm:6.4.6" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/45b559cff889934ebb8bc498351e5acba40750ada7e7d6bde197768d2fa67c149be8ae7f8ff34d03f4e1eb20f2764116e56440aaa2f6689e9a4aa7ef06acafe9 - languageName: node - linkType: hard - -"fdir@npm:^6.5.0": +"fdir@npm:^6.2.0, fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" peerDependencies: @@ -8247,16 +7843,7 @@ __metadata: languageName: node linkType: hard -"for-each@npm:^0.3.3": - version: 0.3.3 - resolution: "for-each@npm:0.3.3" - dependencies: - is-callable: "npm:^1.1.3" - checksum: 10c0/22330d8a2db728dbf003ec9182c2d421fbcd2969b02b4f97ec288721cda63eb28f2c08585ddccd0f77cb2930af8d958005c9e72f47141dc51816127a118f39aa - languageName: node - linkType: hard - -"for-each@npm:^0.3.5": +"for-each@npm:^0.3.3, for-each@npm:^0.3.5": version: 0.3.5 resolution: "for-each@npm:0.3.5" dependencies: @@ -8564,23 +8151,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"glob@npm:^10.5.0": +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.5.0": version: 10.5.0 resolution: "glob@npm:10.5.0" dependencies: @@ -8631,14 +8202,7 @@ __metadata: languageName: node linkType: hard -"globals@npm:^16.0.0": - version: 16.0.0 - resolution: "globals@npm:16.0.0" - checksum: 10c0/8906d5f01838df64a81d6c2a7b7214312e2216cf65c5ed1546dc9a7d0febddf55ffa906cf04efd5b01eec2534d6f14859a89535d1a68241832810e41ef3fd5bb - languageName: node - linkType: hard - -"globals@npm:^16.4.0": +"globals@npm:^16.0.0, globals@npm:^16.4.0": version: 16.5.0 resolution: "globals@npm:16.5.0" checksum: 10c0/615241dae7851c8012f5aa0223005b1ed6607713d6813de0741768bd4ddc39353117648f1a7086b4b0fa45eae733f1c0a0fe369aa4e543bb63f8de8990178ea9 @@ -8669,13 +8233,6 @@ __metadata: languageName: node linkType: hard -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: 10c0/e951259d8cd2e0d196c72ec711add7115d42eb9a8146c8eeda5b8d3ac91e5dd816b9cd68920726d9fd4490368e7ed86e9c423f40db87e2d8dfafa00fa17c3a31 - languageName: node - linkType: hard - "has-bigints@npm:^1.0.2": version: 1.1.0 resolution: "has-bigints@npm:1.1.0" @@ -8724,7 +8281,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.2": +"hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" dependencies: @@ -8999,7 +8556,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.3.1, ignore@npm:^5.3.2": +"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.3.2": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 @@ -9037,19 +8594,7 @@ __metadata: languageName: node linkType: hard -"import-in-the-middle@npm:^2.0.0": - version: 2.0.0 - resolution: "import-in-the-middle@npm:2.0.0" - dependencies: - acorn: "npm:^8.14.0" - acorn-import-attributes: "npm:^1.9.5" - cjs-module-lexer: "npm:^1.2.2" - module-details-from-path: "npm:^1.0.3" - checksum: 10c0/b4349a1bac96a5ffb584564c24bb5ff70085d1e6f0a614392f7cd2321c9a1871bc6c3e93a01cbc0eeb7663ae572b717b808e9d24fe213b4ce373dd87d59ca8c5 - languageName: node - linkType: hard - -"import-in-the-middle@npm:^2.0.1": +"import-in-the-middle@npm:^2.0.0, import-in-the-middle@npm:^2.0.1": version: 2.0.6 resolution: "import-in-the-middle@npm:2.0.6" dependencies: @@ -9262,14 +8807,14 @@ __metadata: languageName: node linkType: hard -"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7": +"is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -9467,7 +9012,7 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": +"is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" dependencies: @@ -9504,16 +9049,7 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": - version: 1.1.0 - resolution: "is-weakref@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.2" - checksum: 10c0/aa835f62e29cb60132ecb3ec7d11bd0f39ec7322325abe8412b805aef47153ec2daefdb21759b049711c674f49b13202a31d8d126bcdff7d8671c78babd4ae5b - languageName: node - linkType: hard - -"is-weakref@npm:^1.1.1": +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": version: 1.1.1 resolution: "is-weakref@npm:1.1.1" dependencies: @@ -10446,14 +9982,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.14, lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c - languageName: node - linkType: hard - -"lodash@npm:^4.17.23": +"lodash@npm:^4.17.14, lodash@npm:^4.17.21, lodash@npm:^4.17.23": version: 4.17.23 resolution: "lodash@npm:4.17.23" checksum: 10c0/1264a90469f5bb95d4739c43eb6277d15b6d9e186df4ac68c3620443160fc669e2f14c11e7d8b2ccf078b81d06147c01a8ccced9aab9f9f63d50dcf8cace6bf6 @@ -10843,20 +10372,13 @@ __metadata: languageName: node linkType: hard -"media-tracks@npm:^0.3.4": +"media-tracks@npm:^0.3.4, media-tracks@npm:~0.3.3": version: 0.3.4 resolution: "media-tracks@npm:0.3.4" checksum: 10c0/5d42013c1dfe885c3c4642edf35273df62412fdd36e19bf9741e09e33cde8134ad80ff742e99868cf53dc226ae9a938b09d61237e0205c9a8d2763fd564bc07f languageName: node linkType: hard -"media-tracks@npm:~0.3.3": - version: 0.3.3 - resolution: "media-tracks@npm:0.3.3" - checksum: 10c0/ecd57e628222b6e0611f21813a291a47b30c96aa1c9d7e13546932b59e8bb206651961a36360cc5584bf76bf890ce01be3bb0c045facf76ab8b1cfacecf9808b - languageName: node - linkType: hard - "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -11805,13 +11327,6 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 10c0/52a0dbd25ccf545892670d1551690fe0facb6a471e15f2cfa1b20142a5b255b3aa254af5f59d6ecb69c2bec7390bc643c43aa63b13bf5e64b6075952e716b1aa - languageName: node - linkType: hard - "node-releases@npm:^2.0.27": version: 2.0.27 resolution: "node-releases@npm:2.0.27" @@ -11952,14 +11467,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": - version: 1.13.3 - resolution: "object-inspect@npm:1.13.3" - checksum: 10c0/cc3f15213406be89ffdc54b525e115156086796a515410a8d390215915db9f23c8eab485a06f1297402f440a33715fe8f71a528c1dcbad6e1a3bcaf5a46921d4 - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.4": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 @@ -12022,7 +11530,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.6, object.values@npm:^1.2.0, object.values@npm:^1.2.1": +"object.values@npm:^1.1.6, object.values@npm:^1.2.1": version: 1.2.1 resolution: "object.values@npm:1.2.1" dependencies: @@ -12211,16 +11719,7 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0, parse5@npm:^7.1.1": - version: 7.2.1 - resolution: "parse5@npm:7.2.1" - dependencies: - entities: "npm:^4.5.0" - checksum: 10c0/829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80 - languageName: node - linkType: hard - -"parse5@npm:^7.3.0": +"parse5@npm:^7.0.0, parse5@npm:^7.1.1, parse5@npm:^7.3.0": version: 7.3.0 resolution: "parse5@npm:7.3.0" dependencies: @@ -12315,7 +11814,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": +"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 @@ -13715,12 +13214,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3, semver@npm:^7.7.3": - version: 7.7.3 - resolution: "semver@npm:7.7.3" +"semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.3": + version: 7.7.4 + resolution: "semver@npm:7.7.4" bin: semver: bin/semver.js - checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e + checksum: 10c0/5215ad0234e2845d4ea5bb9d836d42b03499546ddafb12075566899fc617f68794bb6f146076b6881d755de17d6c6cc73372555879ec7dce2c2feee947866ad2 languageName: node linkType: hard @@ -14230,7 +13729,7 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.8, string.prototype.trimend@npm:^1.0.9": +"string.prototype.trimend@npm:^1.0.9": version: 1.0.9 resolution: "string.prototype.trimend@npm:1.0.9" dependencies: @@ -14684,15 +14183,6 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.0.1": - version: 2.0.1 - resolution: "ts-api-utils@npm:2.0.1" - peerDependencies: - typescript: ">=4.8.4" - checksum: 10c0/23fd56a958b332cac00150a652e4c84730df30571bd2faa1ba6d7b511356d1a61656621492bb6c7f15dd6e18847a1408357a0e406671d358115369a17f5bfedd - languageName: node - linkType: hard - "ts-api-utils@npm:^2.4.0": version: 2.4.0 resolution: "ts-api-utils@npm:2.4.0" @@ -14920,6 +14410,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~7.16.0": + version: 7.16.0 + resolution: "undici-types@npm:7.16.0" + checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a + languageName: node + linkType: hard + "undici@npm:7.18.2": version: 7.18.2 resolution: "undici@npm:7.18.2" @@ -15219,20 +14716,6 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.1.1": - version: 1.1.1 - resolution: "update-browserslist-db@npm:1.1.1" - dependencies: - escalade: "npm:^3.2.0" - picocolors: "npm:^1.1.0" - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: 10c0/536a2979adda2b4be81b07e311bd2f3ad5e978690987956bc5f514130ad50cac87cd22c710b686d79731e00fbee8ef43efe5fcd72baa241045209195d43dcc80 - languageName: node - linkType: hard - "update-browserslist-db@npm:^1.1.4": version: 1.1.4 resolution: "update-browserslist-db@npm:1.1.4" @@ -15641,21 +15124,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18": - version: 1.1.18 - resolution: "which-typed-array@npm:1.1.18" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - for-each: "npm:^0.3.3" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/0412f4a91880ca1a2a63056187c2e3de6b129b2b5b6c17bc3729f0f7041047ae48fb7424813e51506addb2c97320003ee18b8c57469d2cde37983ef62126143c - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.19": +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": version: 1.1.20 resolution: "which-typed-array@npm:1.1.20" dependencies: @@ -15997,6 +15466,27 @@ __metadata: languageName: node linkType: hard +"zustand@npm:^5.0.3": + version: 5.0.11 + resolution: "zustand@npm:5.0.11" + peerDependencies: + "@types/react": ">=18.0.0" + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" + peerDependenciesMeta: + "@types/react": + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + checksum: 10c0/61836b48dac5978c9d1b8289d5162a151bee77828371b9aba6431a079b77faca0635ba53da3f7b331295fbc4e78318a109a4527f7a051cb63abfe79b69ccbecf + languageName: node + linkType: hard + "zwitch@npm:^2.0.0": version: 2.0.4 resolution: "zwitch@npm:2.0.4" From 56a8ee612c665cda3cea4e6a2df1d69bece09774 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 18 Feb 2026 22:05:24 +0000 Subject: [PATCH 2/3] refactor(autolinking): Free memoized values after autolinking operations (#42947) # Why We currently hold on to a lot of memory globally due to the `memoize` function. The idea was to temporarily limit this usage by a `MAX_SIZE`. However, this still means that the new `expo-modules-autolinking` implementation has a higher memory impact than it used to. Instead, we'd like to free up memory after a full run, while making sure that the entire async context shares a cache. This will allow us to use `memoize` in more places and also ensure that we don't hold on to memory for longer than we need to. (**Note:** This was an optimization that @byCedric and I talked about, but didn't immediately implement) # How Initially, the `createMemoizer` used an `AsyncLocalStorage`. This basically kept the runtime of `expo-modules-autolinking verify` within a neutral range for `apps/router-e2e` (+/-10ms). However, it's expected that we should be able to reduce more cacheable calls with this approach. Swapping the memoizer out for a globally shared one that is instead reference counting its users, we see a drop in runtime of -20ms/-8% (measured with Hyperfine). The memoizer is an instance that holds on to our function result cache (`Map>`). It still adheres to the `MAX_SIZE` limit per function. Every function that's wrapped with `memoize` checks the `currentMemoizer` for a `Memoizer.call` wrapper. The `Memoizer.withMemoizer` wrapper counts up the ref counter, then proceeds with the callback logic, like `AsyncLocalStorage.run`. After a run, if the ref counter drops to zero, it resets to `currentMemoizer = undefined`. The `Memoizer.call` function returns a cached value, or calls the memoized function with the `currentMemoizer` set to the memoizer. Since the ref counter drops to zero after all `withMemoizer` calls resolve, and this resets `currentMemoizer = undefined`; when the memoizer leaves any function context, garbage collection will free it from memory. ### Granular changes - Swap out `memoize` with the new `memoize` call - Add `Memoizer` to `CachedDependenciesLinker` - Hoist file utilities from `src/dependencies`, so the memoized `loadPackageJson` may also be used in `src/reactNativeConfig/androidResolver.ts` - Wrap commands in memoizers ### Notes - Limiting `fs.promises` concurrency doesn't really seem to change the runtime much - On Bluesky (current `main`) the runtime of `verify` drops by ~22% (657->529ms in my testing) # Test Plan To verify that the memoizer is used correctly, a `console.warn` was added when `NODE_ENV === 'test'`. This means, all tests in Jest are verified to be wrapped in memoizer `withMemoizer` context calls. The same has been manually verified for each command. **Note:** At worst, when a memoizer isn't provided, we fall back to calling the function without memoization. - Tests added for `memoizer.ts` - Tests updated to add memoizers where needed - Ran all commands with `NODE_ENV=test` set, to verify they are memoized # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- .../expo-modules-autolinking/CHANGELOG.md | 2 + .../build/ExpoModuleConfig.d.ts | 2 +- .../build/ExpoModuleConfig.js | 4 +- .../build/ExpoModuleConfig.js.map | 2 +- .../build/autolinking/findModules.js | 12 +- .../build/autolinking/findModules.js.map | 2 +- .../CachedDependenciesLinker.d.ts | 2 + .../dependencies/CachedDependenciesLinker.js | 82 ++++---- .../CachedDependenciesLinker.js.map | 2 +- .../build/dependencies/resolution.js | 11 +- .../build/dependencies/resolution.js.map | 2 +- .../build/dependencies/rncliLocal.js | 5 +- .../build/dependencies/rncliLocal.js.map | 2 +- .../build/dependencies/scanning.js | 15 +- .../build/dependencies/scanning.js.map | 2 +- .../build/dependencies/utils.d.ts | 6 - .../build/dependencies/utils.js | 28 --- .../build/dependencies/utils.js.map | 2 +- .../expo-modules-autolinking/build/index.js | 5 +- .../build/index.js.map | 2 +- .../build/memoize.d.ts | 16 ++ .../expo-modules-autolinking/build/memoize.js | 84 +++++++++ .../build/memoize.js.map | 1 + .../reactNativeConfig/androidResolver.js | 7 +- .../reactNativeConfig/androidResolver.js.map | 2 +- .../build/reactNativeConfig/config.d.ts | 5 +- .../build/reactNativeConfig/config.js | 3 +- .../build/reactNativeConfig/config.js.map | 2 +- .../expo-modules-autolinking/build/utils.d.ts | 8 +- .../expo-modules-autolinking/build/utils.js | 46 +++-- .../build/utils.js.map | 2 +- .../src/ExpoModuleConfig.ts | 2 +- .../src/__tests__/memoize.test.ts | 47 +++++ .../src/autolinking/findModules.ts | 22 ++- .../dependencies/CachedDependenciesLinker.ts | 105 ++++++----- .../dependencies/__tests__/resolution-test.ts | 30 +-- .../dependencies/__tests__/scanning-test.ts | 24 ++- .../src/dependencies/resolution.ts | 10 +- .../src/dependencies/rncliLocal.ts | 3 +- .../src/dependencies/scanning.ts | 5 +- .../src/dependencies/utils.ts | 33 +--- .../expo-modules-autolinking/src/index.ts | 5 +- .../expo-modules-autolinking/src/memoize.ts | 104 ++++++++++ .../__tests__/androidResolver-test.ts | 131 +++++++------ .../__tests__/config-test.ts | 16 +- .../__tests__/reactNativeConfig-test.ts | 177 ++++++++++-------- .../src/reactNativeConfig/androidResolver.ts | 12 +- .../src/reactNativeConfig/config.ts | 14 +- .../expo-modules-autolinking/src/utils.ts | 49 +++-- 49 files changed, 741 insertions(+), 414 deletions(-) create mode 100644 packages/expo-modules-autolinking/build/memoize.d.ts create mode 100644 packages/expo-modules-autolinking/build/memoize.js create mode 100644 packages/expo-modules-autolinking/build/memoize.js.map create mode 100644 packages/expo-modules-autolinking/src/__tests__/memoize.test.ts create mode 100644 packages/expo-modules-autolinking/src/memoize.ts diff --git a/packages/expo-modules-autolinking/CHANGELOG.md b/packages/expo-modules-autolinking/CHANGELOG.md index c08ed1ba7cbd6a..6d8a6a2b3cd270 100644 --- a/packages/expo-modules-autolinking/CHANGELOG.md +++ b/packages/expo-modules-autolinking/CHANGELOG.md @@ -10,6 +10,8 @@ ### 💡 Others +- Reduce memory retained after autolinking runs ([#42947](https://github.com/expo/expo/pull/42947) by [@kitten](https://github.com/kitten)) + ## 55.0.5 — 2026-02-16 _This version does not introduce any user-facing changes._ diff --git a/packages/expo-modules-autolinking/build/ExpoModuleConfig.d.ts b/packages/expo-modules-autolinking/build/ExpoModuleConfig.d.ts index 97639d5993d8f9..4d3363a924d021 100644 --- a/packages/expo-modules-autolinking/build/ExpoModuleConfig.d.ts +++ b/packages/expo-modules-autolinking/build/ExpoModuleConfig.d.ts @@ -85,4 +85,4 @@ export declare class ExpoModuleConfig { */ toJSON(): RawExpoModuleConfig; } -export declare const discoverExpoModuleConfigAsync: (input: string, ...args: any[]) => Promise; +export declare const discoverExpoModuleConfigAsync: import("./memoize").MemoizableAsyncFn; diff --git a/packages/expo-modules-autolinking/build/ExpoModuleConfig.js b/packages/expo-modules-autolinking/build/ExpoModuleConfig.js index eabd12a683bba7..b9718a90555ccb 100644 --- a/packages/expo-modules-autolinking/build/ExpoModuleConfig.js +++ b/packages/expo-modules-autolinking/build/ExpoModuleConfig.js @@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.discoverExpoModuleConfigAsync = exports.ExpoModuleConfig = exports.ExpoAndroidProjectConfig = exports.ExpoAndroidModuleConfig = void 0; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); -const utils_1 = require("./utils"); +const memoize_1 = require("./memoize"); function arrayize(value) { if (Array.isArray(value)) { return value; @@ -174,7 +174,7 @@ class ExpoModuleConfig { exports.ExpoModuleConfig = ExpoModuleConfig; /** Names of Expo Module config files (highest to lowest priority) */ const EXPO_MODULE_CONFIG_FILENAMES = ['expo-module.config.json', 'unimodule.json']; -exports.discoverExpoModuleConfigAsync = (0, utils_1.memoize)(async function discoverExpoModuleConfigAsync(directoryPath) { +exports.discoverExpoModuleConfigAsync = (0, memoize_1.memoize)(async function discoverExpoModuleConfigAsync(directoryPath) { for (let idx = 0; idx < EXPO_MODULE_CONFIG_FILENAMES.length; idx++) { // TODO: Validate the raw config against a schema. // TODO: Support for `*.js` files, not only static `*.json`. diff --git a/packages/expo-modules-autolinking/build/ExpoModuleConfig.js.map b/packages/expo-modules-autolinking/build/ExpoModuleConfig.js.map index 49b2d68fd558dc..29d3987db1e3cb 100644 --- a/packages/expo-modules-autolinking/build/ExpoModuleConfig.js.map +++ b/packages/expo-modules-autolinking/build/ExpoModuleConfig.js.map @@ -1 +1 @@ -{"version":3,"file":"ExpoModuleConfig.js","sourceRoot":"","sources":["../src/ExpoModuleConfig.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAUxB,mCAAkC;AAElC,SAAS,QAAQ,CAAI,KAA0B;IAC7C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,MAAa,uBAAuB;IAEzB;IACA;IAFT,YACS,UAAkB,EAClB,IAAmB;QADnB,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAe;IACzB,CAAC;CACL;AALD,0DAKC;AAED,MAAa,wBAAwB;IAE1B;IACA;IACA;IACA;IACA;IACA;IACA;IAIA;IAXT,YACS,IAAY,EACZ,IAAY,EACZ,OAAmC,EACnC,QAAmB,EACnB,WAAgC,EAChC,iBAAuD,EACvD,8BAAuC;IAC9C;;OAEG;IACI,YAAqB,KAAK;QAV1B,SAAI,GAAJ,IAAI,CAAQ;QACZ,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAA4B;QACnC,aAAQ,GAAR,QAAQ,CAAW;QACnB,gBAAW,GAAX,WAAW,CAAqB;QAChC,sBAAiB,GAAjB,iBAAiB,CAAsC;QACvD,mCAA8B,GAA9B,8BAA8B,CAAS;QAIvC,cAAS,GAAT,SAAS,CAAiB;IAChC,CAAC;CACL;AAdD,4DAcC;AAED;;GAEG;AACH,MAAa,gBAAgB;IACN;IAArB,YAAqB,SAA8B;QAA9B,cAAS,GAAT,SAAS,CAAqB;IAAG,CAAC;IAEvD;;OAEG;IACH,gBAAgB,CAAC,QAA2B;QAC1C,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC;QAE1D,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,8FAA8F;YAC9F,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,4EAA4E;YAC5E,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,EAAE;gBACnD,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YACvE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,KAAK,CAAC;YACX,KAAK,OAAO,CAAC;YACb,KAAK,MAAM;gBACT,yFAAyF;gBACzF,OAAO,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACvF;gBACE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,YAAY;QACV,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,WAAW,EAAE,OAAO,IAAI,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,2BAA2B;QACzB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,sBAAsB,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,0BAA0B;QACxB,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,qBAAqB,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,OAAO,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,OAAO,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,IAAI,KAAK,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,kBAA0B;QACxC,MAAM,eAAe,GAA+B,EAAE,CAAC;QAEvD,8DAA8D;QAC9D,eAAe,CAAC,IAAI,CAClB,IAAI,wBAAwB,CAC1B,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAClD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,IAAI,SAAS,EACzC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9C,OAAO,MAAM,KAAK,QAAQ;YACxB,CAAC,CAAC,IAAI,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC;YAC3C,CAAC,CAAC,IAAI,uBAAuB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAC3D,EACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,EAChC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,EACnC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,iBAAiB,EACzC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,8BAA8B,EACtD,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,mDAAmD;SAClF,CACF,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACpD,eAAe,CAAC,IAAI,CAClB,IAAI,wBAAwB,CAC1B,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,OAAO,MAAM,KAAK,QAAQ;gBACxB,CAAC,CAAC,IAAI,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC;gBAC3C,CAAC,CAAC,IAAI,uBAAuB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAC3D,EACD,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,iBAAiB,EACzB,OAAO,CAAC,8BAA8B,CACvC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,wBAAwB;QACtB,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AA9JD,4CA8JC;AAED,qEAAqE;AACrE,MAAM,4BAA4B,GAAG,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAAC;AAEtE,QAAA,6BAA6B,GAAG,IAAA,eAAO,EAAC,KAAK,UAAU,6BAA6B,CAC/F,aAAqB;IAErB,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,4BAA4B,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;QACnE,kDAAkD;QAClD,4DAA4D;QAC5D,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,4BAA4B,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/E,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;YACpB,SAAS;QACX,CAAC;QACD,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAwB,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC,CAAC","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport {\n AndroidGradleAarProjectDescriptor,\n AndroidGradlePluginDescriptor,\n AndroidPublication,\n RawExpoModuleConfig,\n RawModuleConfigApple,\n SupportedPlatform,\n} from './types';\nimport { memoize } from './utils';\n\nfunction arrayize(value: T[] | T | undefined): T[] {\n if (Array.isArray(value)) {\n return value;\n }\n return value != null ? [value] : [];\n}\n\nexport class ExpoAndroidModuleConfig {\n constructor(\n public classifier: string,\n public name: string | null\n ) {}\n}\n\nexport class ExpoAndroidProjectConfig {\n constructor(\n public name: string,\n public path: string,\n public modules?: ExpoAndroidModuleConfig[],\n public services?: string[],\n public publication?: AndroidPublication,\n public gradleAarProjects?: AndroidGradleAarProjectDescriptor[],\n public shouldUsePublicationScriptPath?: string,\n /**\n * Whether this project is the root one.\n */\n public isDefault: boolean = false\n ) {}\n}\n\n/**\n * A class that wraps the raw config (`expo-module.json` or `unimodule.json`).\n */\nexport class ExpoModuleConfig {\n constructor(readonly rawConfig: RawExpoModuleConfig) {}\n\n /**\n * Whether the module supports given platform.\n */\n supportsPlatform(platform: SupportedPlatform): boolean {\n const supportedPlatforms = this.rawConfig.platforms ?? [];\n\n if (platform === 'web') {\n // Web platform is implicitly supported for autolinking resolution but has no special behavior\n return true;\n } else if (platform === 'apple') {\n // Apple platform is supported when any of iOS, macOS and tvOS is supported.\n return supportedPlatforms.some((supportedPlatform) => {\n return ['apple', 'ios', 'macos', 'tvos'].includes(supportedPlatform);\n });\n }\n switch (platform) {\n case 'ios':\n case 'macos':\n case 'tvos':\n // ios|macos|tvos are supported when the module supports \"apple\" as a platform in general\n return supportedPlatforms.includes(platform) || supportedPlatforms.includes('apple');\n default:\n return supportedPlatforms.includes(platform);\n }\n }\n\n /**\n * Returns the generic config for all Apple platforms with a fallback to the legacy iOS config.\n */\n getAppleConfig(): RawModuleConfigApple | null {\n return this.rawConfig.apple ?? this.rawConfig.ios ?? null;\n }\n\n /**\n * Returns a list of names of Swift native modules classes to put to the generated modules provider file.\n */\n appleModules() {\n const appleConfig = this.getAppleConfig();\n return appleConfig?.modules ?? [];\n }\n\n /**\n * Returns a list of names of Swift classes that receives AppDelegate life-cycle events.\n */\n appleAppDelegateSubscribers(): string[] {\n return this.getAppleConfig()?.appDelegateSubscribers ?? [];\n }\n\n /**\n * Returns a list of names of Swift classes that implement `ExpoReactDelegateHandler`.\n */\n appleReactDelegateHandlers(): string[] {\n return this.getAppleConfig()?.reactDelegateHandlers ?? [];\n }\n\n /**\n * Returns podspec paths defined by the module author.\n */\n applePodspecPaths(): string[] {\n return arrayize(this.getAppleConfig()?.podspecPath);\n }\n\n /**\n * Returns the product module names, if defined by the module author.\n */\n appleSwiftModuleNames(): string[] {\n return arrayize(this.getAppleConfig()?.swiftModuleName);\n }\n\n /**\n * Returns whether this module will be added only to the debug configuration\n */\n appleDebugOnly(): boolean {\n return this.getAppleConfig()?.debugOnly ?? false;\n }\n\n /**\n * Returns information about Android projects defined by the module author.\n */\n androidProjects(defaultProjectName: string): ExpoAndroidProjectConfig[] {\n const androidProjects: ExpoAndroidProjectConfig[] = [];\n\n // Adding the \"root\" Android project - it might not be valide.\n androidProjects.push(\n new ExpoAndroidProjectConfig(\n this.rawConfig.android?.name ?? defaultProjectName,\n this.rawConfig.android?.path ?? 'android',\n this.rawConfig.android?.modules?.map((module) =>\n typeof module === 'string'\n ? new ExpoAndroidModuleConfig(module, null)\n : new ExpoAndroidModuleConfig(module.class, module.name)\n ),\n this.rawConfig.android?.services,\n this.rawConfig.android?.publication,\n this.rawConfig.android?.gradleAarProjects,\n this.rawConfig.android?.shouldUsePublicationScriptPath,\n !this.rawConfig.android?.path // it's default project because path is not defined\n )\n );\n\n this.rawConfig.android?.projects?.forEach((project) => {\n androidProjects.push(\n new ExpoAndroidProjectConfig(\n project.name,\n project.path,\n project.modules?.map((module) =>\n typeof module === 'string'\n ? new ExpoAndroidModuleConfig(module, null)\n : new ExpoAndroidModuleConfig(module.class, module.name)\n ),\n project.services,\n project.publication,\n project.gradleAarProjects,\n project.shouldUsePublicationScriptPath\n )\n );\n });\n\n return androidProjects;\n }\n\n /**\n * Returns gradle plugins descriptors defined by the module author.\n */\n androidGradlePlugins(): AndroidGradlePluginDescriptor[] {\n return arrayize(this.rawConfig.android?.gradlePlugins ?? []);\n }\n\n /**\n * Returns gradle projects containing AAR files defined by the module author.\n */\n androidGradleAarProjects(): AndroidGradleAarProjectDescriptor[] {\n return arrayize(this.rawConfig.android?.gradleAarProjects ?? []);\n }\n\n /**\n * Returns the publication config for Android.\n */\n androidPublication(): AndroidPublication | undefined {\n return this.rawConfig.android?.publication;\n }\n\n /**\n * Returns core features required by the module author.\n */\n coreFeatures(): string[] {\n return arrayize(this.rawConfig.coreFeatures ?? []);\n }\n\n /**\n * Returns serializable raw config.\n */\n toJSON(): RawExpoModuleConfig {\n return this.rawConfig;\n }\n}\n\n/** Names of Expo Module config files (highest to lowest priority) */\nconst EXPO_MODULE_CONFIG_FILENAMES = ['expo-module.config.json', 'unimodule.json'];\n\nexport const discoverExpoModuleConfigAsync = memoize(async function discoverExpoModuleConfigAsync(\n directoryPath: string\n): Promise {\n for (let idx = 0; idx < EXPO_MODULE_CONFIG_FILENAMES.length; idx++) {\n // TODO: Validate the raw config against a schema.\n // TODO: Support for `*.js` files, not only static `*.json`.\n const targetPath = path.join(directoryPath, EXPO_MODULE_CONFIG_FILENAMES[idx]);\n let text: string;\n try {\n text = await fs.promises.readFile(targetPath, 'utf8');\n } catch {\n // try the next file\n continue;\n }\n return new ExpoModuleConfig(JSON.parse(text) as RawExpoModuleConfig);\n }\n return null;\n});\n"]} \ No newline at end of file +{"version":3,"file":"ExpoModuleConfig.js","sourceRoot":"","sources":["../src/ExpoModuleConfig.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from './memoize';\nimport {\n AndroidGradleAarProjectDescriptor,\n AndroidGradlePluginDescriptor,\n AndroidPublication,\n RawExpoModuleConfig,\n RawModuleConfigApple,\n SupportedPlatform,\n} from './types';\n\nfunction arrayize(value: T[] | T | undefined): T[] {\n if (Array.isArray(value)) {\n return value;\n }\n return value != null ? [value] : [];\n}\n\nexport class ExpoAndroidModuleConfig {\n constructor(\n public classifier: string,\n public name: string | null\n ) {}\n}\n\nexport class ExpoAndroidProjectConfig {\n constructor(\n public name: string,\n public path: string,\n public modules?: ExpoAndroidModuleConfig[],\n public services?: string[],\n public publication?: AndroidPublication,\n public gradleAarProjects?: AndroidGradleAarProjectDescriptor[],\n public shouldUsePublicationScriptPath?: string,\n /**\n * Whether this project is the root one.\n */\n public isDefault: boolean = false\n ) {}\n}\n\n/**\n * A class that wraps the raw config (`expo-module.json` or `unimodule.json`).\n */\nexport class ExpoModuleConfig {\n constructor(readonly rawConfig: RawExpoModuleConfig) {}\n\n /**\n * Whether the module supports given platform.\n */\n supportsPlatform(platform: SupportedPlatform): boolean {\n const supportedPlatforms = this.rawConfig.platforms ?? [];\n\n if (platform === 'web') {\n // Web platform is implicitly supported for autolinking resolution but has no special behavior\n return true;\n } else if (platform === 'apple') {\n // Apple platform is supported when any of iOS, macOS and tvOS is supported.\n return supportedPlatforms.some((supportedPlatform) => {\n return ['apple', 'ios', 'macos', 'tvos'].includes(supportedPlatform);\n });\n }\n switch (platform) {\n case 'ios':\n case 'macos':\n case 'tvos':\n // ios|macos|tvos are supported when the module supports \"apple\" as a platform in general\n return supportedPlatforms.includes(platform) || supportedPlatforms.includes('apple');\n default:\n return supportedPlatforms.includes(platform);\n }\n }\n\n /**\n * Returns the generic config for all Apple platforms with a fallback to the legacy iOS config.\n */\n getAppleConfig(): RawModuleConfigApple | null {\n return this.rawConfig.apple ?? this.rawConfig.ios ?? null;\n }\n\n /**\n * Returns a list of names of Swift native modules classes to put to the generated modules provider file.\n */\n appleModules() {\n const appleConfig = this.getAppleConfig();\n return appleConfig?.modules ?? [];\n }\n\n /**\n * Returns a list of names of Swift classes that receives AppDelegate life-cycle events.\n */\n appleAppDelegateSubscribers(): string[] {\n return this.getAppleConfig()?.appDelegateSubscribers ?? [];\n }\n\n /**\n * Returns a list of names of Swift classes that implement `ExpoReactDelegateHandler`.\n */\n appleReactDelegateHandlers(): string[] {\n return this.getAppleConfig()?.reactDelegateHandlers ?? [];\n }\n\n /**\n * Returns podspec paths defined by the module author.\n */\n applePodspecPaths(): string[] {\n return arrayize(this.getAppleConfig()?.podspecPath);\n }\n\n /**\n * Returns the product module names, if defined by the module author.\n */\n appleSwiftModuleNames(): string[] {\n return arrayize(this.getAppleConfig()?.swiftModuleName);\n }\n\n /**\n * Returns whether this module will be added only to the debug configuration\n */\n appleDebugOnly(): boolean {\n return this.getAppleConfig()?.debugOnly ?? false;\n }\n\n /**\n * Returns information about Android projects defined by the module author.\n */\n androidProjects(defaultProjectName: string): ExpoAndroidProjectConfig[] {\n const androidProjects: ExpoAndroidProjectConfig[] = [];\n\n // Adding the \"root\" Android project - it might not be valide.\n androidProjects.push(\n new ExpoAndroidProjectConfig(\n this.rawConfig.android?.name ?? defaultProjectName,\n this.rawConfig.android?.path ?? 'android',\n this.rawConfig.android?.modules?.map((module) =>\n typeof module === 'string'\n ? new ExpoAndroidModuleConfig(module, null)\n : new ExpoAndroidModuleConfig(module.class, module.name)\n ),\n this.rawConfig.android?.services,\n this.rawConfig.android?.publication,\n this.rawConfig.android?.gradleAarProjects,\n this.rawConfig.android?.shouldUsePublicationScriptPath,\n !this.rawConfig.android?.path // it's default project because path is not defined\n )\n );\n\n this.rawConfig.android?.projects?.forEach((project) => {\n androidProjects.push(\n new ExpoAndroidProjectConfig(\n project.name,\n project.path,\n project.modules?.map((module) =>\n typeof module === 'string'\n ? new ExpoAndroidModuleConfig(module, null)\n : new ExpoAndroidModuleConfig(module.class, module.name)\n ),\n project.services,\n project.publication,\n project.gradleAarProjects,\n project.shouldUsePublicationScriptPath\n )\n );\n });\n\n return androidProjects;\n }\n\n /**\n * Returns gradle plugins descriptors defined by the module author.\n */\n androidGradlePlugins(): AndroidGradlePluginDescriptor[] {\n return arrayize(this.rawConfig.android?.gradlePlugins ?? []);\n }\n\n /**\n * Returns gradle projects containing AAR files defined by the module author.\n */\n androidGradleAarProjects(): AndroidGradleAarProjectDescriptor[] {\n return arrayize(this.rawConfig.android?.gradleAarProjects ?? []);\n }\n\n /**\n * Returns the publication config for Android.\n */\n androidPublication(): AndroidPublication | undefined {\n return this.rawConfig.android?.publication;\n }\n\n /**\n * Returns core features required by the module author.\n */\n coreFeatures(): string[] {\n return arrayize(this.rawConfig.coreFeatures ?? []);\n }\n\n /**\n * Returns serializable raw config.\n */\n toJSON(): RawExpoModuleConfig {\n return this.rawConfig;\n }\n}\n\n/** Names of Expo Module config files (highest to lowest priority) */\nconst EXPO_MODULE_CONFIG_FILENAMES = ['expo-module.config.json', 'unimodule.json'];\n\nexport const discoverExpoModuleConfigAsync = memoize(async function discoverExpoModuleConfigAsync(\n directoryPath: string\n): Promise {\n for (let idx = 0; idx < EXPO_MODULE_CONFIG_FILENAMES.length; idx++) {\n // TODO: Validate the raw config against a schema.\n // TODO: Support for `*.js` files, not only static `*.json`.\n const targetPath = path.join(directoryPath, EXPO_MODULE_CONFIG_FILENAMES[idx]);\n let text: string;\n try {\n text = await fs.promises.readFile(targetPath, 'utf8');\n } catch {\n // try the next file\n continue;\n }\n return new ExpoModuleConfig(JSON.parse(text) as RawExpoModuleConfig);\n }\n return null;\n});\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/autolinking/findModules.js b/packages/expo-modules-autolinking/build/autolinking/findModules.js index f907746d6dc898..d4ba449206366a 100644 --- a/packages/expo-modules-autolinking/build/autolinking/findModules.js +++ b/packages/expo-modules-autolinking/build/autolinking/findModules.js @@ -4,6 +4,7 @@ exports.resolveExpoModule = resolveExpoModule; exports.findModulesAsync = findModulesAsync; const ExpoModuleConfig_1 = require("../ExpoModuleConfig"); const dependencies_1 = require("../dependencies"); +const memoize_1 = require("../memoize"); async function resolveExpoModule(resolution, platform, excludeNames) { if (excludeNames.has(resolution.name)) { return null; @@ -28,14 +29,17 @@ async function resolveExpoModule(resolution, platform, excludeNames) { } /** Searches for modules to link based on given config. */ async function findModulesAsync({ appRoot, autolinkingOptions, }) { + const memoizer = (0, memoize_1.createMemoizer)(); const excludeNames = new Set(autolinkingOptions.exclude); // custom native modules should be resolved first so that they can override other modules const searchPaths = autolinkingOptions.nativeModulesDir ? [autolinkingOptions.nativeModulesDir, ...autolinkingOptions.searchPaths] : autolinkingOptions.searchPaths; - return (0, dependencies_1.filterMapResolutionResult)((0, dependencies_1.mergeResolutionResults)(await Promise.all([ - ...searchPaths.map((searchPath) => (0, dependencies_1.scanDependenciesInSearchPath)(searchPath)), - (0, dependencies_1.scanDependenciesRecursively)(appRoot), - ])), (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames)); + return memoizer.withMemoizer(async () => { + return (0, dependencies_1.filterMapResolutionResult)((0, dependencies_1.mergeResolutionResults)(await Promise.all([ + ...searchPaths.map((searchPath) => (0, dependencies_1.scanDependenciesInSearchPath)(searchPath)), + (0, dependencies_1.scanDependenciesRecursively)(appRoot), + ])), (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames)); + }); } //# sourceMappingURL=findModules.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/autolinking/findModules.js.map b/packages/expo-modules-autolinking/build/autolinking/findModules.js.map index 0cc6b3bc6628a2..41e9cb2d4dd280 100644 --- a/packages/expo-modules-autolinking/build/autolinking/findModules.js.map +++ b/packages/expo-modules-autolinking/build/autolinking/findModules.js.map @@ -1 +1 @@ -{"version":3,"file":"findModules.js","sourceRoot":"","sources":["../../src/autolinking/findModules.ts"],"names":[],"mappings":";;AAWA,8CAyBC;AAQD,4CAoBC;AAhED,0DAAoE;AAEpE,kDAMyB;AAGlB,KAAK,UAAU,iBAAiB,CACrC,UAAgC,EAChC,QAA2B,EAC3B,YAAyB;IAEzB,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,IAAA,gDAA6B,EAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9E,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpE,OAAO;YACL,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,MAAM,EAAE,gBAAgB;YACxB,UAAU,EACR,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC,CAAC,IAAI,EAAE;SACZ,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAOD,0DAA0D;AACnD,KAAK,UAAU,gBAAgB,CAAC,EACrC,OAAO,EACP,kBAAkB,GACA;IAClB,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEzD,yFAAyF;IACzF,MAAM,WAAW,GAAG,kBAAkB,CAAC,gBAAgB;QACrD,CAAC,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,GAAG,kBAAkB,CAAC,WAAW,CAAC;QAC1E,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC;IAEnC,OAAO,IAAA,wCAAyB,EAC9B,IAAA,qCAAsB,EACpB,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAA,2CAA4B,EAAC,UAAU,CAAC,CAAC;QAC5E,IAAA,0CAA2B,EAAC,OAAO,CAAC;KACrC,CAAC,CACH,EACD,CAAC,UAAU,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,QAAQ,EAAE,YAAY,CAAC,CACzF,CAAC;AACJ,CAAC","sourcesContent":["import { discoverExpoModuleConfigAsync } from '../ExpoModuleConfig';\nimport { AutolinkingOptions } from '../commands/autolinkingOptions';\nimport {\n type DependencyResolution,\n scanDependenciesRecursively,\n scanDependenciesInSearchPath,\n filterMapResolutionResult,\n mergeResolutionResults,\n} from '../dependencies';\nimport { PackageRevision, SearchResults, SupportedPlatform } from '../types';\n\nexport async function resolveExpoModule(\n resolution: DependencyResolution,\n platform: SupportedPlatform,\n excludeNames: Set\n): Promise {\n if (excludeNames.has(resolution.name)) {\n return null;\n }\n const expoModuleConfig = await discoverExpoModuleConfigAsync(resolution.path);\n if (expoModuleConfig && expoModuleConfig.supportsPlatform(platform)) {\n return {\n name: resolution.name,\n path: resolution.path,\n version: resolution.version,\n config: expoModuleConfig,\n duplicates:\n resolution.duplicates?.map((duplicate) => ({\n name: duplicate.name,\n path: duplicate.path,\n version: duplicate.version,\n })) ?? [],\n };\n } else {\n return null;\n }\n}\n\ninterface FindModulesParams {\n appRoot: string;\n autolinkingOptions: AutolinkingOptions & { platform: SupportedPlatform };\n}\n\n/** Searches for modules to link based on given config. */\nexport async function findModulesAsync({\n appRoot,\n autolinkingOptions,\n}: FindModulesParams): Promise {\n const excludeNames = new Set(autolinkingOptions.exclude);\n\n // custom native modules should be resolved first so that they can override other modules\n const searchPaths = autolinkingOptions.nativeModulesDir\n ? [autolinkingOptions.nativeModulesDir, ...autolinkingOptions.searchPaths]\n : autolinkingOptions.searchPaths;\n\n return filterMapResolutionResult(\n mergeResolutionResults(\n await Promise.all([\n ...searchPaths.map((searchPath) => scanDependenciesInSearchPath(searchPath)),\n scanDependenciesRecursively(appRoot),\n ])\n ),\n (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames)\n );\n}\n"]} \ No newline at end of file +{"version":3,"file":"findModules.js","sourceRoot":"","sources":["../../src/autolinking/findModules.ts"],"names":[],"mappings":";;AAYA,8CAyBC;AAQD,4CAuBC;AApED,0DAAoE;AAEpE,kDAMyB;AACzB,wCAA4C;AAGrC,KAAK,UAAU,iBAAiB,CACrC,UAAgC,EAChC,QAA2B,EAC3B,YAAyB;IAEzB,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,IAAA,gDAA6B,EAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9E,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpE,OAAO;YACL,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,OAAO,EAAE,UAAU,CAAC,OAAO;YAC3B,MAAM,EAAE,gBAAgB;YACxB,UAAU,EACR,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC,CAAC,IAAI,EAAE;SACZ,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAOD,0DAA0D;AACnD,KAAK,UAAU,gBAAgB,CAAC,EACrC,OAAO,EACP,kBAAkB,GACA;IAClB,MAAM,QAAQ,GAAG,IAAA,wBAAc,GAAE,CAAC;IAClC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEzD,yFAAyF;IACzF,MAAM,WAAW,GAAG,kBAAkB,CAAC,gBAAgB;QACrD,CAAC,CAAC,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,GAAG,kBAAkB,CAAC,WAAW,CAAC;QAC1E,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC;IAEnC,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;QACtC,OAAO,IAAA,wCAAyB,EAC9B,IAAA,qCAAsB,EACpB,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAA,2CAA4B,EAAC,UAAU,CAAC,CAAC;YAC5E,IAAA,0CAA2B,EAAC,OAAO,CAAC;SACrC,CAAC,CACH,EACD,CAAC,UAAU,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,QAAQ,EAAE,YAAY,CAAC,CACzF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { discoverExpoModuleConfigAsync } from '../ExpoModuleConfig';\nimport { AutolinkingOptions } from '../commands/autolinkingOptions';\nimport {\n type DependencyResolution,\n scanDependenciesRecursively,\n scanDependenciesInSearchPath,\n filterMapResolutionResult,\n mergeResolutionResults,\n} from '../dependencies';\nimport { createMemoizer } from '../memoize';\nimport { PackageRevision, SearchResults, SupportedPlatform } from '../types';\n\nexport async function resolveExpoModule(\n resolution: DependencyResolution,\n platform: SupportedPlatform,\n excludeNames: Set\n): Promise {\n if (excludeNames.has(resolution.name)) {\n return null;\n }\n const expoModuleConfig = await discoverExpoModuleConfigAsync(resolution.path);\n if (expoModuleConfig && expoModuleConfig.supportsPlatform(platform)) {\n return {\n name: resolution.name,\n path: resolution.path,\n version: resolution.version,\n config: expoModuleConfig,\n duplicates:\n resolution.duplicates?.map((duplicate) => ({\n name: duplicate.name,\n path: duplicate.path,\n version: duplicate.version,\n })) ?? [],\n };\n } else {\n return null;\n }\n}\n\ninterface FindModulesParams {\n appRoot: string;\n autolinkingOptions: AutolinkingOptions & { platform: SupportedPlatform };\n}\n\n/** Searches for modules to link based on given config. */\nexport async function findModulesAsync({\n appRoot,\n autolinkingOptions,\n}: FindModulesParams): Promise {\n const memoizer = createMemoizer();\n const excludeNames = new Set(autolinkingOptions.exclude);\n\n // custom native modules should be resolved first so that they can override other modules\n const searchPaths = autolinkingOptions.nativeModulesDir\n ? [autolinkingOptions.nativeModulesDir, ...autolinkingOptions.searchPaths]\n : autolinkingOptions.searchPaths;\n\n return memoizer.withMemoizer(async () => {\n return filterMapResolutionResult(\n mergeResolutionResults(\n await Promise.all([\n ...searchPaths.map((searchPath) => scanDependenciesInSearchPath(searchPath)),\n scanDependenciesRecursively(appRoot),\n ])\n ),\n (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames)\n );\n });\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.d.ts b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.d.ts index 975b6bd6e9b51b..74ad968e852a02 100644 --- a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.d.ts +++ b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.d.ts @@ -1,11 +1,13 @@ import { PackageRevision, SupportedPlatform } from '../types'; import { type ResolutionResult } from './types'; +import { type Memoizer } from '../memoize'; import { RNConfigReactNativeProjectConfig } from '../reactNativeConfig'; export interface CachedDependenciesSearchOptions { excludeNames: Set; searchPaths: string[]; } export interface CachedDependenciesLinker { + memoizer: Memoizer; getOptionsForPlatform(platform: SupportedPlatform): Promise; loadReactNativeProjectConfig(): Promise; scanDependenciesFromRNProjectConfig(): Promise; diff --git a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js index 8a53754f615863..a7c36078b2277d 100644 --- a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js +++ b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js @@ -13,9 +13,11 @@ const scanning_1 = require("./scanning"); const utils_1 = require("./utils"); const findModules_1 = require("../autolinking/findModules"); const autolinkingOptions_1 = require("../commands/autolinkingOptions"); +const memoize_1 = require("../memoize"); const reactNativeConfig_1 = require("../reactNativeConfig"); const config_1 = require("../reactNativeConfig/config"); function makeCachedDependenciesLinker(params) { + const memoizer = (0, memoize_1.createMemoizer)(); const autolinkingOptionsLoader = (0, autolinkingOptions_1.createAutolinkingOptionsLoader)({ projectRoot: params.projectRoot, }); @@ -26,29 +28,37 @@ function makeCachedDependenciesLinker(params) { let reactNativeProjectConfigDependencies; let recursiveDependencies; return { + memoizer, async getOptionsForPlatform(platform) { const options = await autolinkingOptionsLoader.getPlatformOptions(platform); return makeCachedDependenciesSearchOptions(options); }, async loadReactNativeProjectConfig() { if (reactNativeProjectConfig === undefined) { - reactNativeProjectConfig = (0, config_1.loadConfigAsync)(await getAppRoot()); + reactNativeProjectConfig = memoizer.call(config_1.loadConfigAsync, await getAppRoot()); } return reactNativeProjectConfig; }, async scanDependenciesFromRNProjectConfig() { - const reactNativeProjectConfig = await this.loadReactNativeProjectConfig(); - return (reactNativeProjectConfigDependencies || - (reactNativeProjectConfigDependencies = (0, rncliLocal_1.scanDependenciesFromRNProjectConfig)(await getAppRoot(), reactNativeProjectConfig))); + if (reactNativeProjectConfigDependencies === undefined) { + reactNativeProjectConfigDependencies = memoizer.withMemoizer(async () => { + return await (0, rncliLocal_1.scanDependenciesFromRNProjectConfig)(await getAppRoot(), await this.loadReactNativeProjectConfig()); + }); + } + return reactNativeProjectConfigDependencies; }, async scanDependenciesRecursively() { - return (recursiveDependencies || - (recursiveDependencies = (0, resolution_1.scanDependenciesRecursively)(await getAppRoot()))); + if (recursiveDependencies === undefined) { + recursiveDependencies = memoizer.withMemoizer(async () => { + return (0, resolution_1.scanDependenciesRecursively)(await getAppRoot()); + }); + } + return recursiveDependencies; }, async scanDependenciesInSearchPath(searchPath) { let result = dependenciesResultBySearchPath.get(searchPath); if (!result) { - dependenciesResultBySearchPath.set(searchPath, (result = (0, scanning_1.scanDependenciesInSearchPath)(searchPath))); + dependenciesResultBySearchPath.set(searchPath, (result = memoizer.withMemoizer(scanning_1.scanDependenciesInSearchPath, searchPath))); } return result; }, @@ -65,33 +75,35 @@ async function scanDependencyResolutionsForPlatform(linker, platform, include) { }), linker.scanDependenciesRecursively(), ])); - const dependencies = await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => { - if (excludeNames.has(resolution.name)) { - return null; - } - else if (includeNames.has(resolution.name)) { - return resolution; - } - else if (resolution.source === 2 /* DependencyResolutionSource.RN_CLI_LOCAL */) { - // If the dependency was resolved frpom the React Native project config, we'll only - // attempt to resolve it as a React Native module - const reactNativeModuleDesc = await (0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames); - if (!reactNativeModuleDesc) { + return await linker.memoizer.withMemoizer(async () => { + const dependencies = await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => { + if (excludeNames.has(resolution.name)) { return null; } - } - else { - const [reactNativeModule, expoModule] = await Promise.all([ - (0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames), - (0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames), - ]); - if (!reactNativeModule && !expoModule) { - return null; + else if (includeNames.has(resolution.name)) { + return resolution; } - } - return resolution; + else if (resolution.source === 2 /* DependencyResolutionSource.RN_CLI_LOCAL */) { + // If the dependency was resolved frpom the React Native project config, we'll only + // attempt to resolve it as a React Native module + const reactNativeModuleDesc = await (0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames); + if (!reactNativeModuleDesc) { + return null; + } + } + else { + const [reactNativeModule, expoModule] = await Promise.all([ + (0, reactNativeConfig_1.resolveReactNativeModule)(resolution, reactNativeProjectConfig, platform, excludeNames), + (0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames), + ]); + if (!reactNativeModule && !expoModule) { + return null; + } + } + return resolution; + }); + return dependencies; }); - return dependencies; } async function scanExpoModuleResolutionsForPlatform(linker, platform) { const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform); @@ -101,10 +113,12 @@ async function scanExpoModuleResolutionsForPlatform(linker, platform) { }), linker.scanDependenciesRecursively(), ].filter((x) => x != null))); - return await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => { - return !excludeNames.has(resolution.name) - ? await (0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames) - : null; + return await linker.memoizer.withMemoizer(async () => { + return await (0, utils_1.filterMapResolutionResult)(resolutions, async (resolution) => { + return !excludeNames.has(resolution.name) + ? await (0, findModules_1.resolveExpoModule)(resolution, platform, excludeNames) + : null; + }); }); } const makeCachedDependenciesSearchOptions = (options) => ({ diff --git a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js.map b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js.map index f31498b102ee47..fa4d1576983ad9 100644 --- a/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/CachedDependenciesLinker.js.map @@ -1 +1 @@ -{"version":3,"file":"CachedDependenciesLinker.js","sourceRoot":"","sources":["../../src/dependencies/CachedDependenciesLinker.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport { PackageRevision, SupportedPlatform } from '../types';\nimport { scanDependenciesRecursively } from './resolution';\nimport { scanDependenciesFromRNProjectConfig } from './rncliLocal';\nimport { scanDependenciesInSearchPath } from './scanning';\nimport { type ResolutionResult, DependencyResolutionSource } from './types';\nimport { filterMapResolutionResult, mergeResolutionResults } from './utils';\nimport { resolveExpoModule } from '../autolinking/findModules';\nimport { AutolinkingOptions, createAutolinkingOptionsLoader } from '../commands/autolinkingOptions';\nimport { resolveReactNativeModule, RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { loadConfigAsync } from '../reactNativeConfig/config';\n\nexport interface CachedDependenciesSearchOptions {\n excludeNames: Set;\n searchPaths: string[];\n}\n\nexport interface CachedDependenciesLinker {\n getOptionsForPlatform(platform: SupportedPlatform): Promise;\n loadReactNativeProjectConfig(): Promise;\n scanDependenciesFromRNProjectConfig(): Promise;\n scanDependenciesRecursively(): Promise;\n scanDependenciesInSearchPath(searchPath: string): Promise;\n}\n\nexport function makeCachedDependenciesLinker(params: {\n projectRoot: string;\n}): CachedDependenciesLinker {\n const autolinkingOptionsLoader = createAutolinkingOptionsLoader({\n projectRoot: params.projectRoot,\n });\n\n let appRoot: Promise | undefined;\n const getAppRoot = () => appRoot || (appRoot = autolinkingOptionsLoader.getAppRoot());\n\n const dependenciesResultBySearchPath = new Map>();\n let reactNativeProjectConfig: Promise | undefined;\n let reactNativeProjectConfigDependencies: Promise | undefined;\n let recursiveDependencies: Promise | undefined;\n\n return {\n async getOptionsForPlatform(platform) {\n const options = await autolinkingOptionsLoader.getPlatformOptions(platform);\n return makeCachedDependenciesSearchOptions(options);\n },\n async loadReactNativeProjectConfig() {\n if (reactNativeProjectConfig === undefined) {\n reactNativeProjectConfig = loadConfigAsync(\n await getAppRoot()\n ) as Promise;\n }\n return reactNativeProjectConfig;\n },\n async scanDependenciesFromRNProjectConfig() {\n const reactNativeProjectConfig = await this.loadReactNativeProjectConfig();\n return (\n reactNativeProjectConfigDependencies ||\n (reactNativeProjectConfigDependencies = scanDependenciesFromRNProjectConfig(\n await getAppRoot(),\n reactNativeProjectConfig\n ))\n );\n },\n async scanDependenciesRecursively() {\n return (\n recursiveDependencies ||\n (recursiveDependencies = scanDependenciesRecursively(await getAppRoot()))\n );\n },\n async scanDependenciesInSearchPath(searchPath: string) {\n let result = dependenciesResultBySearchPath.get(searchPath);\n if (!result) {\n dependenciesResultBySearchPath.set(\n searchPath,\n (result = scanDependenciesInSearchPath(searchPath))\n );\n }\n return result;\n },\n };\n}\n\nexport async function scanDependencyResolutionsForPlatform(\n linker: CachedDependenciesLinker,\n platform: SupportedPlatform,\n include?: string[]\n): Promise {\n const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);\n const includeNames = new Set(include);\n const reactNativeProjectConfig = await linker.loadReactNativeProjectConfig();\n\n const resolutions = mergeResolutionResults(\n await Promise.all([\n linker.scanDependenciesFromRNProjectConfig(),\n ...searchPaths.map((searchPath) => {\n return linker.scanDependenciesInSearchPath(searchPath);\n }),\n linker.scanDependenciesRecursively(),\n ])\n );\n\n const dependencies = await filterMapResolutionResult(resolutions, async (resolution) => {\n if (excludeNames.has(resolution.name)) {\n return null;\n } else if (includeNames.has(resolution.name)) {\n return resolution;\n } else if (resolution.source === DependencyResolutionSource.RN_CLI_LOCAL) {\n // If the dependency was resolved frpom the React Native project config, we'll only\n // attempt to resolve it as a React Native module\n const reactNativeModuleDesc = await resolveReactNativeModule(\n resolution,\n reactNativeProjectConfig,\n platform,\n excludeNames\n );\n if (!reactNativeModuleDesc) {\n return null;\n }\n } else {\n const [reactNativeModule, expoModule] = await Promise.all([\n resolveReactNativeModule(resolution, reactNativeProjectConfig, platform, excludeNames),\n resolveExpoModule(resolution, platform, excludeNames),\n ]);\n if (!reactNativeModule && !expoModule) {\n return null;\n }\n }\n return resolution;\n });\n\n return dependencies;\n}\n\nexport async function scanExpoModuleResolutionsForPlatform(\n linker: CachedDependenciesLinker,\n platform: SupportedPlatform\n): Promise> {\n const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);\n const resolutions = mergeResolutionResults(\n await Promise.all(\n [\n ...searchPaths.map((searchPath) => {\n return linker.scanDependenciesInSearchPath(searchPath);\n }),\n linker.scanDependenciesRecursively(),\n ].filter((x) => x != null)\n )\n );\n return await filterMapResolutionResult(resolutions, async (resolution) => {\n return !excludeNames.has(resolution.name)\n ? await resolveExpoModule(resolution, platform, excludeNames)\n : null;\n });\n}\n\nconst makeCachedDependenciesSearchOptions = (options: AutolinkingOptions) => ({\n excludeNames: new Set(options.exclude),\n searchPaths:\n options.nativeModulesDir && fs.existsSync(options.nativeModulesDir)\n ? [options.nativeModulesDir, ...(options.searchPaths ?? [])]\n : (options.searchPaths ?? []),\n});\n"]} \ No newline at end of file +{"version":3,"file":"CachedDependenciesLinker.js","sourceRoot":"","sources":["../../src/dependencies/CachedDependenciesLinker.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport { PackageRevision, SupportedPlatform } from '../types';\nimport { scanDependenciesRecursively } from './resolution';\nimport { scanDependenciesFromRNProjectConfig } from './rncliLocal';\nimport { scanDependenciesInSearchPath } from './scanning';\nimport { type ResolutionResult, DependencyResolutionSource } from './types';\nimport { filterMapResolutionResult, mergeResolutionResults } from './utils';\nimport { resolveExpoModule } from '../autolinking/findModules';\nimport { AutolinkingOptions, createAutolinkingOptionsLoader } from '../commands/autolinkingOptions';\nimport { createMemoizer, type Memoizer } from '../memoize';\nimport { resolveReactNativeModule, RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { loadConfigAsync } from '../reactNativeConfig/config';\n\nexport interface CachedDependenciesSearchOptions {\n excludeNames: Set;\n searchPaths: string[];\n}\n\nexport interface CachedDependenciesLinker {\n memoizer: Memoizer;\n getOptionsForPlatform(platform: SupportedPlatform): Promise;\n loadReactNativeProjectConfig(): Promise;\n scanDependenciesFromRNProjectConfig(): Promise;\n scanDependenciesRecursively(): Promise;\n scanDependenciesInSearchPath(searchPath: string): Promise;\n}\n\nexport function makeCachedDependenciesLinker(params: {\n projectRoot: string;\n}): CachedDependenciesLinker {\n const memoizer = createMemoizer();\n\n const autolinkingOptionsLoader = createAutolinkingOptionsLoader({\n projectRoot: params.projectRoot,\n });\n\n let appRoot: Promise | undefined;\n const getAppRoot = () => appRoot || (appRoot = autolinkingOptionsLoader.getAppRoot());\n\n const dependenciesResultBySearchPath = new Map>();\n let reactNativeProjectConfig: Promise | undefined;\n let reactNativeProjectConfigDependencies: Promise | undefined;\n let recursiveDependencies: Promise | undefined;\n\n return {\n memoizer,\n async getOptionsForPlatform(platform) {\n const options = await autolinkingOptionsLoader.getPlatformOptions(platform);\n return makeCachedDependenciesSearchOptions(options);\n },\n async loadReactNativeProjectConfig() {\n if (reactNativeProjectConfig === undefined) {\n reactNativeProjectConfig = memoizer.call(\n loadConfigAsync,\n await getAppRoot()\n ) as Promise;\n }\n return reactNativeProjectConfig;\n },\n async scanDependenciesFromRNProjectConfig() {\n if (reactNativeProjectConfigDependencies === undefined) {\n reactNativeProjectConfigDependencies = memoizer.withMemoizer(async () => {\n return await scanDependenciesFromRNProjectConfig(\n await getAppRoot(),\n await this.loadReactNativeProjectConfig()\n );\n });\n }\n return reactNativeProjectConfigDependencies;\n },\n async scanDependenciesRecursively() {\n if (recursiveDependencies === undefined) {\n recursiveDependencies = memoizer.withMemoizer(async () => {\n return scanDependenciesRecursively(await getAppRoot());\n });\n }\n return recursiveDependencies;\n },\n async scanDependenciesInSearchPath(searchPath: string) {\n let result = dependenciesResultBySearchPath.get(searchPath);\n if (!result) {\n dependenciesResultBySearchPath.set(\n searchPath,\n (result = memoizer.withMemoizer(scanDependenciesInSearchPath, searchPath))\n );\n }\n return result;\n },\n };\n}\n\nexport async function scanDependencyResolutionsForPlatform(\n linker: CachedDependenciesLinker,\n platform: SupportedPlatform,\n include?: string[]\n): Promise {\n const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);\n const includeNames = new Set(include);\n const reactNativeProjectConfig = await linker.loadReactNativeProjectConfig();\n\n const resolutions = mergeResolutionResults(\n await Promise.all([\n linker.scanDependenciesFromRNProjectConfig(),\n ...searchPaths.map((searchPath) => {\n return linker.scanDependenciesInSearchPath(searchPath);\n }),\n linker.scanDependenciesRecursively(),\n ])\n );\n\n return await linker.memoizer.withMemoizer(async () => {\n const dependencies = await filterMapResolutionResult(resolutions, async (resolution) => {\n if (excludeNames.has(resolution.name)) {\n return null;\n } else if (includeNames.has(resolution.name)) {\n return resolution;\n } else if (resolution.source === DependencyResolutionSource.RN_CLI_LOCAL) {\n // If the dependency was resolved frpom the React Native project config, we'll only\n // attempt to resolve it as a React Native module\n const reactNativeModuleDesc = await resolveReactNativeModule(\n resolution,\n reactNativeProjectConfig,\n platform,\n excludeNames\n );\n if (!reactNativeModuleDesc) {\n return null;\n }\n } else {\n const [reactNativeModule, expoModule] = await Promise.all([\n resolveReactNativeModule(resolution, reactNativeProjectConfig, platform, excludeNames),\n resolveExpoModule(resolution, platform, excludeNames),\n ]);\n if (!reactNativeModule && !expoModule) {\n return null;\n }\n }\n return resolution;\n });\n\n return dependencies;\n });\n}\n\nexport async function scanExpoModuleResolutionsForPlatform(\n linker: CachedDependenciesLinker,\n platform: SupportedPlatform\n): Promise> {\n const { excludeNames, searchPaths } = await linker.getOptionsForPlatform(platform);\n const resolutions = mergeResolutionResults(\n await Promise.all(\n [\n ...searchPaths.map((searchPath) => {\n return linker.scanDependenciesInSearchPath(searchPath);\n }),\n linker.scanDependenciesRecursively(),\n ].filter((x) => x != null)\n )\n );\n return await linker.memoizer.withMemoizer(async () => {\n return await filterMapResolutionResult(resolutions, async (resolution) => {\n return !excludeNames.has(resolution.name)\n ? await resolveExpoModule(resolution, platform, excludeNames)\n : null;\n });\n });\n}\n\nconst makeCachedDependenciesSearchOptions = (options: AutolinkingOptions) => ({\n excludeNames: new Set(options.exclude),\n searchPaths:\n options.nativeModulesDir && fs.existsSync(options.nativeModulesDir)\n ? [options.nativeModulesDir, ...(options.searchPaths ?? [])]\n : (options.searchPaths ?? []),\n});\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/resolution.js b/packages/expo-modules-autolinking/build/dependencies/resolution.js index b7e7fd73111d77..f0892c8d0990d1 100644 --- a/packages/expo-modules-autolinking/build/dependencies/resolution.js +++ b/packages/expo-modules-autolinking/build/dependencies/resolution.js @@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesRecursively = scanDependenciesRecursively; const node_module_1 = __importDefault(require("node:module")); const utils_1 = require("./utils"); +const utils_2 = require("../utils"); // NOTE(@kitten): There's no need to search very deep for modules // We don't expect native modules to be excessively nested in the dependency tree const MAX_DEPTH = 8; @@ -18,7 +19,7 @@ const createNodeModulePathsCreator = () => { const nodeModulePath = nodeModulePaths[idx]; let target = _nodeModulePathCache.get(nodeModulePath); if (target === undefined) { - target = await (0, utils_1.maybeRealpath)(nodeModulePath); + target = await (0, utils_2.maybeRealpath)(nodeModulePath); if (idx !== 0) { _nodeModulePathCache.set(nodeModulePath, target); } @@ -57,8 +58,8 @@ async function resolveDependencies(packageJson, nodeModulePaths, depth, shouldIn } const resolveDependency = async (dependencyName) => { for (let idx = 0; idx < nodeModulePaths.length; idx++) { - const originPath = (0, utils_1.fastJoin)(nodeModulePaths[idx], dependencyName); - const nodeModulePath = await (0, utils_1.maybeRealpath)(originPath); + const originPath = (0, utils_2.fastJoin)(nodeModulePaths[idx], dependencyName); + const nodeModulePath = await (0, utils_2.maybeRealpath)(originPath); if (nodeModulePath != null) { return { source: 0 /* DependencyResolutionSource.RECURSIVE_RESOLUTION */, @@ -79,7 +80,7 @@ async function resolveDependencies(packageJson, nodeModulePaths, depth, shouldIn return modules.filter((resolution) => resolution != null); } async function scanDependenciesRecursively(rawPath, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency, limitDepth } = {}) { - const rootPath = await (0, utils_1.maybeRealpath)(rawPath); + const rootPath = await (0, utils_2.maybeRealpath)(rawPath); if (!rootPath) { return {}; } @@ -96,7 +97,7 @@ async function scanDependenciesRecursively(rawPath, { shouldIncludeDependency = } const [nodeModulePaths, packageJson] = await Promise.all([ getNodeModulePaths(resolution.path), - (0, utils_1.loadPackageJson)((0, utils_1.fastJoin)(resolution.path, 'package.json')), + (0, utils_2.loadPackageJson)((0, utils_2.fastJoin)(resolution.path, 'package.json')), ]); if (!packageJson) { return searchResults; diff --git a/packages/expo-modules-autolinking/build/dependencies/resolution.js.map b/packages/expo-modules-autolinking/build/dependencies/resolution.js.map index b63c6e6c0deda4..f3eae67b2ed5f4 100644 --- a/packages/expo-modules-autolinking/build/dependencies/resolution.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/resolution.js.map @@ -1 +1 @@ -{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/dependencies/resolution.ts"],"names":[],"mappings":"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","sourcesContent":["import Module from 'node:module';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport {\n type PackageJson,\n defaultShouldIncludeDependency,\n mergeResolutionResults,\n loadPackageJson,\n maybeRealpath,\n fastJoin,\n} from './utils';\n\ndeclare module 'node:module' {\n export function _nodeModulePaths(base: string): readonly string[];\n}\n\n// NOTE(@kitten): There's no need to search very deep for modules\n// We don't expect native modules to be excessively nested in the dependency tree\nconst MAX_DEPTH = 8;\n\nconst createNodeModulePathsCreator = () => {\n const _nodeModulePathCache = new Map();\n return async function getNodeModulePaths(packagePath: string) {\n const outputPaths: string[] = [];\n const nodeModulePaths = Module._nodeModulePaths(packagePath);\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const nodeModulePath = nodeModulePaths[idx];\n let target = _nodeModulePathCache.get(nodeModulePath);\n if (target === undefined) {\n target = await maybeRealpath(nodeModulePath);\n if (idx !== 0) {\n _nodeModulePathCache.set(nodeModulePath, target);\n }\n }\n if (target != null) {\n outputPaths.push(target);\n }\n }\n return outputPaths;\n };\n};\n\nasync function resolveDependencies(\n packageJson: PackageJson,\n nodeModulePaths: readonly string[],\n depth: number,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n const dependencies: Record = Object.create(null);\n if (packageJson.dependencies != null && typeof packageJson.dependencies === 'object') {\n Object.assign(dependencies, packageJson.dependencies);\n }\n // NOTE(@kitten): Also traverse devDependencies for top-level package.json\n if (\n depth === 0 &&\n packageJson.devDependencies != null &&\n typeof packageJson.devDependencies === 'object'\n ) {\n Object.assign(dependencies, packageJson.devDependencies);\n }\n if (packageJson.peerDependencies != null && typeof packageJson.peerDependencies === 'object') {\n const peerDependenciesMeta =\n packageJson.peerDependenciesMeta != null &&\n typeof packageJson.peerDependenciesMeta === 'object'\n ? (packageJson.peerDependenciesMeta as Record)\n : undefined;\n for (const dependencyName in packageJson.peerDependencies) {\n // NOTE(@kitten): We only check peer dependencies because some package managers auto-install them\n // which would mean they'd have no reference in any dependencies. However, optional peer dependencies\n // don't auto-install and we can skip them\n if (!isOptionalPeerDependencyMeta(peerDependenciesMeta, dependencyName)) {\n dependencies[dependencyName] = '';\n }\n }\n }\n\n const resolveDependency = async (\n dependencyName: string\n ): Promise => {\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const originPath = fastJoin(nodeModulePaths[idx], dependencyName);\n const nodeModulePath = await maybeRealpath(originPath);\n if (nodeModulePath != null) {\n return {\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: dependencyName,\n version: '',\n path: nodeModulePath,\n originPath,\n duplicates: null,\n depth,\n };\n }\n }\n return null;\n };\n\n const modules = await Promise.all(\n Object.keys(dependencies)\n .filter((dependencyName) => shouldIncludeDependency(dependencyName))\n .map((dependencyName) => resolveDependency(dependencyName))\n );\n\n return modules.filter((resolution) => resolution != null);\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n limitDepth?: number;\n}\n\nexport async function scanDependenciesRecursively(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency, limitDepth }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n if (!rootPath) {\n return {};\n }\n\n const _visitedPackagePaths = new Set();\n const getNodeModulePaths = createNodeModulePathsCreator();\n const maxDepth = limitDepth != null ? limitDepth : MAX_DEPTH;\n\n const recurse = async (\n resolution: DependencyResolution,\n depth = 0\n ): Promise => {\n const searchResults: ResolutionResult = Object.create(null);\n if (_visitedPackagePaths.has(resolution.path)) {\n return searchResults;\n } else {\n _visitedPackagePaths.add(resolution.path);\n }\n const [nodeModulePaths, packageJson] = await Promise.all([\n getNodeModulePaths(resolution.path),\n loadPackageJson(fastJoin(resolution.path, 'package.json')),\n ]);\n if (!packageJson) {\n return searchResults;\n } else {\n resolution.version = packageJson.version || '';\n }\n\n const modules = await resolveDependencies(\n packageJson,\n nodeModulePaths,\n depth,\n shouldIncludeDependency\n );\n for (let idx = 0; idx < modules.length; idx++) {\n searchResults[modules[idx].name] = modules[idx];\n }\n\n if (depth + 1 < maxDepth) {\n const childResults = await Promise.all(\n modules.map((resolution) => recurse(resolution, depth + 1))\n );\n return mergeResolutionResults(childResults, searchResults);\n } else {\n return searchResults;\n }\n };\n\n const searchResults = await recurse({\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: '',\n version: '',\n path: rootPath,\n originPath: rawPath,\n duplicates: null,\n depth: -1,\n });\n\n return searchResults;\n}\n\nconst isOptionalPeerDependencyMeta = (\n peerDependenciesMeta: Record | undefined,\n packageName: string\n) => {\n return (\n peerDependenciesMeta &&\n peerDependenciesMeta[packageName] != null &&\n typeof peerDependenciesMeta[packageName] === 'object' &&\n 'optional' in peerDependenciesMeta[packageName] &&\n !!peerDependenciesMeta[packageName].optional\n );\n};\n"]} \ No newline at end of file +{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/dependencies/resolution.ts"],"names":[],"mappings":"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","sourcesContent":["import Module from 'node:module';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency, mergeResolutionResults } from './utils';\nimport { type PackageJson, loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\ndeclare module 'node:module' {\n export function _nodeModulePaths(base: string): readonly string[];\n}\n\n// NOTE(@kitten): There's no need to search very deep for modules\n// We don't expect native modules to be excessively nested in the dependency tree\nconst MAX_DEPTH = 8;\n\nconst createNodeModulePathsCreator = () => {\n const _nodeModulePathCache = new Map();\n return async function getNodeModulePaths(packagePath: string) {\n const outputPaths: string[] = [];\n const nodeModulePaths = Module._nodeModulePaths(packagePath);\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const nodeModulePath = nodeModulePaths[idx];\n let target = _nodeModulePathCache.get(nodeModulePath);\n if (target === undefined) {\n target = await maybeRealpath(nodeModulePath);\n if (idx !== 0) {\n _nodeModulePathCache.set(nodeModulePath, target);\n }\n }\n if (target != null) {\n outputPaths.push(target);\n }\n }\n return outputPaths;\n };\n};\n\nasync function resolveDependencies(\n packageJson: PackageJson,\n nodeModulePaths: readonly string[],\n depth: number,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n const dependencies: Record = Object.create(null);\n if (packageJson.dependencies != null && typeof packageJson.dependencies === 'object') {\n Object.assign(dependencies, packageJson.dependencies);\n }\n // NOTE(@kitten): Also traverse devDependencies for top-level package.json\n if (\n depth === 0 &&\n packageJson.devDependencies != null &&\n typeof packageJson.devDependencies === 'object'\n ) {\n Object.assign(dependencies, packageJson.devDependencies);\n }\n if (packageJson.peerDependencies != null && typeof packageJson.peerDependencies === 'object') {\n const peerDependenciesMeta =\n packageJson.peerDependenciesMeta != null &&\n typeof packageJson.peerDependenciesMeta === 'object'\n ? (packageJson.peerDependenciesMeta as Record)\n : undefined;\n for (const dependencyName in packageJson.peerDependencies) {\n // NOTE(@kitten): We only check peer dependencies because some package managers auto-install them\n // which would mean they'd have no reference in any dependencies. However, optional peer dependencies\n // don't auto-install and we can skip them\n if (!isOptionalPeerDependencyMeta(peerDependenciesMeta, dependencyName)) {\n dependencies[dependencyName] = '';\n }\n }\n }\n\n const resolveDependency = async (\n dependencyName: string\n ): Promise => {\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const originPath = fastJoin(nodeModulePaths[idx], dependencyName);\n const nodeModulePath = await maybeRealpath(originPath);\n if (nodeModulePath != null) {\n return {\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: dependencyName,\n version: '',\n path: nodeModulePath,\n originPath,\n duplicates: null,\n depth,\n };\n }\n }\n return null;\n };\n\n const modules = await Promise.all(\n Object.keys(dependencies)\n .filter((dependencyName) => shouldIncludeDependency(dependencyName))\n .map((dependencyName) => resolveDependency(dependencyName))\n );\n\n return modules.filter((resolution) => resolution != null);\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n limitDepth?: number;\n}\n\nexport async function scanDependenciesRecursively(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency, limitDepth }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n if (!rootPath) {\n return {};\n }\n\n const _visitedPackagePaths = new Set();\n const getNodeModulePaths = createNodeModulePathsCreator();\n const maxDepth = limitDepth != null ? limitDepth : MAX_DEPTH;\n\n const recurse = async (\n resolution: DependencyResolution,\n depth = 0\n ): Promise => {\n const searchResults: ResolutionResult = Object.create(null);\n if (_visitedPackagePaths.has(resolution.path)) {\n return searchResults;\n } else {\n _visitedPackagePaths.add(resolution.path);\n }\n const [nodeModulePaths, packageJson] = await Promise.all([\n getNodeModulePaths(resolution.path),\n loadPackageJson(fastJoin(resolution.path, 'package.json')),\n ]);\n if (!packageJson) {\n return searchResults;\n } else {\n resolution.version = packageJson.version || '';\n }\n\n const modules = await resolveDependencies(\n packageJson,\n nodeModulePaths,\n depth,\n shouldIncludeDependency\n );\n for (let idx = 0; idx < modules.length; idx++) {\n searchResults[modules[idx].name] = modules[idx];\n }\n\n if (depth + 1 < maxDepth) {\n const childResults = await Promise.all(\n modules.map((resolution) => recurse(resolution, depth + 1))\n );\n return mergeResolutionResults(childResults, searchResults);\n } else {\n return searchResults;\n }\n };\n\n const searchResults = await recurse({\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: '',\n version: '',\n path: rootPath,\n originPath: rawPath,\n duplicates: null,\n depth: -1,\n });\n\n return searchResults;\n}\n\nconst isOptionalPeerDependencyMeta = (\n peerDependenciesMeta: Record | undefined,\n packageName: string\n) => {\n return (\n peerDependenciesMeta &&\n peerDependenciesMeta[packageName] != null &&\n typeof peerDependenciesMeta[packageName] === 'object' &&\n 'optional' in peerDependenciesMeta[packageName] &&\n !!peerDependenciesMeta[packageName].optional\n );\n};\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js index 82084707f36525..9501f0d0e9f0da 100644 --- a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js +++ b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js @@ -6,8 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesFromRNProjectConfig = scanDependenciesFromRNProjectConfig; const path_1 = __importDefault(require("path")); const utils_1 = require("./utils"); +const utils_2 = require("../utils"); async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency } = {}) { - const rootPath = await (0, utils_1.maybeRealpath)(rawPath); + const rootPath = await (0, utils_2.maybeRealpath)(rawPath); const searchResults = Object.create(null); if (!rootPath || !projectConfig || !projectConfig.dependencies) { return searchResults; @@ -19,7 +20,7 @@ async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { sho const dependencyConfig = projectConfig.dependencies[dependencyName]; if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') { const originPath = path_1.default.resolve(rootPath, dependencyConfig.root); - const realPath = await (0, utils_1.maybeRealpath)(originPath); + const realPath = await (0, utils_2.maybeRealpath)(originPath); if (realPath) { searchResults[dependencyName] = { source: 2 /* DependencyResolutionSource.RN_CLI_LOCAL */, diff --git a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map index be64d01a83f1da..0f716e3f5b8bde 100644 --- a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map @@ -1 +1 @@ -{"version":3,"file":"rncliLocal.js","sourceRoot":"","sources":["../../src/dependencies/rncliLocal.ts"],"names":[],"mappings":";;;;;AAUA,kFAkCC;AA5CD,gDAAwB;AAGxB,mCAAwE;AAOjE,KAAK,UAAU,mCAAmC,CACvD,OAAe,EACf,aAAsD,EACtD,EAAE,uBAAuB,GAAG,sCAA8B,KAAwB,EAAE;IAEpF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAC/D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,KAAK,MAAM,cAAc,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;QACxD,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QACpE,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,IAAI,OAAO,gBAAgB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3F,MAAM,UAAU,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,cAAc,CAAC,GAAG;oBAC9B,MAAM,iDAAyC;oBAC/C,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU;oBACV,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,CAAC;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import path from 'path';\n\nimport { DependencyResolutionSource, type ResolutionResult } from './types';\nimport { defaultShouldIncludeDependency, maybeRealpath } from './utils';\nimport { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesFromRNProjectConfig(\n rawPath: string,\n projectConfig: RNConfigReactNativeProjectConfig | null,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath || !projectConfig || !projectConfig.dependencies) {\n return searchResults;\n }\n\n for (const dependencyName in projectConfig.dependencies) {\n if (!shouldIncludeDependency(dependencyName)) {\n continue;\n }\n const dependencyConfig = projectConfig.dependencies[dependencyName];\n if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {\n const originPath = path.resolve(rootPath, dependencyConfig.root);\n const realPath = await maybeRealpath(originPath);\n if (realPath) {\n searchResults[dependencyName] = {\n source: DependencyResolutionSource.RN_CLI_LOCAL,\n name: dependencyName,\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n }\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file +{"version":3,"file":"rncliLocal.js","sourceRoot":"","sources":["../../src/dependencies/rncliLocal.ts"],"names":[],"mappings":";;;;;AAWA,kFAkCC;AA7CD,gDAAwB;AAGxB,mCAAyD;AAEzD,oCAAyC;AAMlC,KAAK,UAAU,mCAAmC,CACvD,OAAe,EACf,aAAsD,EACtD,EAAE,uBAAuB,GAAG,sCAA8B,KAAwB,EAAE;IAEpF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAC/D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,KAAK,MAAM,cAAc,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;QACxD,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QACpE,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,IAAI,OAAO,gBAAgB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3F,MAAM,UAAU,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,cAAc,CAAC,GAAG;oBAC9B,MAAM,iDAAyC;oBAC/C,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU;oBACV,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,CAAC;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import path from 'path';\n\nimport { DependencyResolutionSource, type ResolutionResult } from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { maybeRealpath } from '../utils';\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesFromRNProjectConfig(\n rawPath: string,\n projectConfig: RNConfigReactNativeProjectConfig | null,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath || !projectConfig || !projectConfig.dependencies) {\n return searchResults;\n }\n\n for (const dependencyName in projectConfig.dependencies) {\n if (!shouldIncludeDependency(dependencyName)) {\n continue;\n }\n const dependencyConfig = projectConfig.dependencies[dependencyName];\n if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {\n const originPath = path.resolve(rootPath, dependencyConfig.root);\n const realPath = await maybeRealpath(originPath);\n if (realPath) {\n searchResults[dependencyName] = {\n source: DependencyResolutionSource.RN_CLI_LOCAL,\n name: dependencyName,\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n }\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/scanning.js b/packages/expo-modules-autolinking/build/dependencies/scanning.js index c983be03f91447..3c7624fc2d7340 100644 --- a/packages/expo-modules-autolinking/build/dependencies/scanning.js +++ b/packages/expo-modules-autolinking/build/dependencies/scanning.js @@ -6,17 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesInSearchPath = scanDependenciesInSearchPath; const fs_1 = __importDefault(require("fs")); const utils_1 = require("./utils"); +const utils_2 = require("../utils"); async function resolveDependency(basePath, dependencyName, shouldIncludeDependency) { if (dependencyName && !shouldIncludeDependency(dependencyName)) { return null; } - const originPath = dependencyName ? (0, utils_1.fastJoin)(basePath, dependencyName) : basePath; - const realPath = await (0, utils_1.maybeRealpath)(originPath); - const packageJson = await (0, utils_1.loadPackageJson)((0, utils_1.fastJoin)(realPath || originPath, 'package.json')); + const originPath = dependencyName ? (0, utils_2.fastJoin)(basePath, dependencyName) : basePath; + const realPath = await (0, utils_2.maybeRealpath)(originPath); + const packageJson = await (0, utils_2.loadPackageJson)((0, utils_2.fastJoin)(realPath || originPath, 'package.json')); if (packageJson) { return { source: 1 /* DependencyResolutionSource.SEARCH_PATH */, - name: packageJson.name, + name: packageJson.name || '', version: packageJson.version || '', path: realPath || originPath, originPath, @@ -40,13 +41,13 @@ async function resolveDependency(basePath, dependencyName, shouldIncludeDependen } } async function scanDependenciesInSearchPath(rawPath, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency } = {}) { - const rootPath = await (0, utils_1.maybeRealpath)(rawPath); + const rootPath = await (0, utils_2.maybeRealpath)(rawPath); const searchResults = Object.create(null); if (!rootPath) { return searchResults; } const resolvedDependencies = []; - const localModuleTarget = await (0, utils_1.maybeRealpath)((0, utils_1.fastJoin)(rootPath, 'package.json')); + const localModuleTarget = await (0, utils_2.maybeRealpath)((0, utils_2.fastJoin)(rootPath, 'package.json')); if (localModuleTarget) { // If we have a `package.json` file in the search path, we're already dealing with a node module // and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../` @@ -71,7 +72,7 @@ async function scanDependenciesInSearchPath(rawPath, { shouldIncludeDependency = } else if (entry.name[0] === '@') { // NOTE: We don't expect @-scope folders to be symlinks - const entryPath = (0, utils_1.fastJoin)(rootPath, entry.name); + const entryPath = (0, utils_2.fastJoin)(rootPath, entry.name); const childEntries = await fs_1.default.promises.readdir(entryPath, { withFileTypes: true }); await Promise.all(childEntries.map(async (child) => { const dependencyName = `${entry.name}/${child.name}`; diff --git a/packages/expo-modules-autolinking/build/dependencies/scanning.js.map b/packages/expo-modules-autolinking/build/dependencies/scanning.js.map index fdf9e6bd0d7b50..4cbabac216a124 100644 --- a/packages/expo-modules-autolinking/build/dependencies/scanning.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/scanning.js.map @@ -1 +1 @@ -{"version":3,"file":"scanning.js","sourceRoot":"","sources":["../../src/dependencies/scanning.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency, loadPackageJson, maybeRealpath, fastJoin } from './utils';\n\nasync function resolveDependency(\n basePath: string,\n dependencyName: string | null,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n if (dependencyName && !shouldIncludeDependency(dependencyName)) {\n return null;\n }\n const originPath = dependencyName ? fastJoin(basePath, dependencyName) : basePath;\n const realPath = await maybeRealpath(originPath);\n const packageJson = await loadPackageJson(fastJoin(realPath || originPath, 'package.json'));\n if (packageJson) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: packageJson.name,\n version: packageJson.version || '',\n path: realPath || originPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else if (dependencyName && realPath) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: dependencyName.toLowerCase(),\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else {\n return null;\n }\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesInSearchPath(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath) {\n return searchResults;\n }\n\n const resolvedDependencies: DependencyResolution[] = [];\n\n const localModuleTarget = await maybeRealpath(fastJoin(rootPath, 'package.json'));\n if (localModuleTarget) {\n // If we have a `package.json` file in the search path, we're already dealing with a node module\n // and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../`\n const resolution = await resolveDependency(rootPath, null, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else {\n const dirents = await fs.promises.readdir(rootPath!, { withFileTypes: true });\n await Promise.all(\n dirents.map(async (entry) => {\n if (entry.isSymbolicLink()) {\n const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else if (entry.isDirectory()) {\n if (entry.name === 'node_modules') {\n // Ignore nested node_modules folder\n }\n if (entry.name[0] === '.') {\n // Ignore hidden folders\n } else if (entry.name[0] === '@') {\n // NOTE: We don't expect @-scope folders to be symlinks\n const entryPath = fastJoin(rootPath, entry.name);\n const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true });\n await Promise.all(\n childEntries.map(async (child) => {\n const dependencyName = `${entry.name}/${child.name}`;\n if (child.isDirectory() || child.isSymbolicLink()) {\n const resolution = await resolveDependency(\n rootPath,\n dependencyName,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n })\n );\n } else {\n const resolution = await resolveDependency(\n rootPath,\n entry.name,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n }\n })\n );\n }\n\n for (let idx = 0; idx < resolvedDependencies.length; idx++) {\n const resolution = resolvedDependencies[idx];\n const prevEntry = searchResults[resolution.name];\n if (prevEntry != null && resolution.path !== prevEntry.path) {\n (prevEntry.duplicates ?? (prevEntry.duplicates = [])).push({\n name: resolution.name,\n version: resolution.version,\n path: resolution.path,\n originPath: resolution.originPath,\n });\n } else if (prevEntry == null) {\n searchResults[resolution.name] = resolution;\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file +{"version":3,"file":"scanning.js","sourceRoot":"","sources":["../../src/dependencies/scanning.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\nasync function resolveDependency(\n basePath: string,\n dependencyName: string | null,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n if (dependencyName && !shouldIncludeDependency(dependencyName)) {\n return null;\n }\n const originPath = dependencyName ? fastJoin(basePath, dependencyName) : basePath;\n const realPath = await maybeRealpath(originPath);\n const packageJson = await loadPackageJson(fastJoin(realPath || originPath, 'package.json'));\n if (packageJson) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: packageJson.name || '',\n version: packageJson.version || '',\n path: realPath || originPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else if (dependencyName && realPath) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: dependencyName.toLowerCase(),\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else {\n return null;\n }\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesInSearchPath(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath) {\n return searchResults;\n }\n\n const resolvedDependencies: DependencyResolution[] = [];\n\n const localModuleTarget = await maybeRealpath(fastJoin(rootPath, 'package.json'));\n if (localModuleTarget) {\n // If we have a `package.json` file in the search path, we're already dealing with a node module\n // and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../`\n const resolution = await resolveDependency(rootPath, null, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else {\n const dirents = await fs.promises.readdir(rootPath!, { withFileTypes: true });\n await Promise.all(\n dirents.map(async (entry) => {\n if (entry.isSymbolicLink()) {\n const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else if (entry.isDirectory()) {\n if (entry.name === 'node_modules') {\n // Ignore nested node_modules folder\n }\n if (entry.name[0] === '.') {\n // Ignore hidden folders\n } else if (entry.name[0] === '@') {\n // NOTE: We don't expect @-scope folders to be symlinks\n const entryPath = fastJoin(rootPath, entry.name);\n const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true });\n await Promise.all(\n childEntries.map(async (child) => {\n const dependencyName = `${entry.name}/${child.name}`;\n if (child.isDirectory() || child.isSymbolicLink()) {\n const resolution = await resolveDependency(\n rootPath,\n dependencyName,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n })\n );\n } else {\n const resolution = await resolveDependency(\n rootPath,\n entry.name,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n }\n })\n );\n }\n\n for (let idx = 0; idx < resolvedDependencies.length; idx++) {\n const resolution = resolvedDependencies[idx];\n const prevEntry = searchResults[resolution.name];\n if (prevEntry != null && resolution.path !== prevEntry.path) {\n (prevEntry.duplicates ?? (prevEntry.duplicates = [])).push({\n name: resolution.name,\n version: resolution.version,\n path: resolution.path,\n originPath: resolution.originPath,\n });\n } else if (prevEntry == null) {\n searchResults[resolution.name] = resolution;\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/utils.d.ts b/packages/expo-modules-autolinking/build/dependencies/utils.d.ts index edfa5db779b4c7..cafb74e699f772 100644 --- a/packages/expo-modules-autolinking/build/dependencies/utils.d.ts +++ b/packages/expo-modules-autolinking/build/dependencies/utils.d.ts @@ -1,11 +1,5 @@ import { type DependencyResolution, type ResolutionResult } from './types'; export declare function defaultShouldIncludeDependency(dependencyName: string): boolean; -export declare const fastJoin: (from: string, append: string) => string; -export declare const maybeRealpath: (target: string) => Promise; -export type PackageJson = Record & { - version?: string; -}; -export declare const loadPackageJson: (input: string, ...args: any[]) => Promise; export declare function mergeWithDuplicate(a: DependencyResolution, b: DependencyResolution): DependencyResolution; export declare function filterMapResolutionResult `${from}${path_1.default.sep}${append}` - : (from, append) => `${from}${path_1.default.sep}${append[0] === '@' ? append.replace('/', path_1.default.sep) : append}`; -const maybeRealpath = async (target) => { - try { - return await fs_1.default.promises.realpath(target); - } - catch { - return null; - } -}; -exports.maybeRealpath = maybeRealpath; -exports.loadPackageJson = (0, utils_1.memoize)(async function loadPackageJson(jsonPath) { - try { - const packageJsonText = await fs_1.default.promises.readFile(jsonPath, 'utf8'); - const json = JSON.parse(packageJsonText); - if (typeof json !== 'object' || json == null) { - return null; - } - return json; - } - catch { - return null; - } -}); function mergeWithDuplicate(a, b) { let target; let duplicate; diff --git a/packages/expo-modules-autolinking/build/dependencies/utils.js.map b/packages/expo-modules-autolinking/build/dependencies/utils.js.map index 8ed26617bb9f3f..286b169cfad937 100644 --- a/packages/expo-modules-autolinking/build/dependencies/utils.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/utils.js.map @@ -1 +1 @@ -{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from '../utils';\nimport {\n DependencyResolutionSource,\n type DependencyResolution,\n type ResolutionResult,\n} from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint' ||\n scopeName === 'testing-library' ||\n scopeName === 'aws-crypto' ||\n scopeName === 'aws-sdk'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/webpack-config':\n case '@expo/env':\n case '@react-native/codegen':\n case '@react-native/community-cli-plugin':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n case 'eslint-plugin-import':\n case 'jest-expo':\n case 'jest':\n case 'metro':\n case 'ts-node':\n case 'typescript':\n case 'webpack':\n return false;\n default:\n return true;\n }\n}\n\nexport const fastJoin: (from: string, append: string) => string =\n path.sep === '/'\n ? (from, append) => `${from}${path.sep}${append}`\n : (from, append) =>\n `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`;\n\nexport const maybeRealpath = async (target: string): Promise => {\n try {\n return await fs.promises.realpath(target);\n } catch {\n return null;\n }\n};\n\nexport type PackageJson = Record & { version?: string };\n\nexport const loadPackageJson = memoize(async function loadPackageJson(\n jsonPath: string\n): Promise {\n try {\n const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8');\n const json = JSON.parse(packageJsonText);\n if (typeof json !== 'object' || json == null) {\n return null;\n }\n return json;\n } catch {\n return null;\n }\n});\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n if (duplicates.every((parent) => parent.path !== duplicate.path)) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n } else if (!target.version && duplicate.version) {\n target.version = duplicate.version;\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise | T | null\n): Promise> {\n const resolutions = await Promise.all(\n Object.keys(results).map(async (key) => {\n const resolution = results[key];\n const result = resolution ? await filterMap(resolution) : null;\n // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates\n // to see if the `searchPaths` result is not a module but another is\n if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) {\n for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) {\n const duplicate = resolution.duplicates[idx];\n const duplicateResult = await filterMap({ ...resolution, ...duplicate });\n if (duplicateResult != null) {\n return duplicateResult;\n }\n }\n }\n return result;\n })\n );\n const output: Record = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(\n results: ResolutionResult[],\n base?: ResolutionResult\n): ResolutionResult {\n if (base == null && results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = base == null ? Object.create(null) : base;\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]} \ No newline at end of file +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from '../memoize';\nimport {\n DependencyResolutionSource,\n type DependencyResolution,\n type ResolutionResult,\n} from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint' ||\n scopeName === 'testing-library' ||\n scopeName === 'aws-crypto' ||\n scopeName === 'aws-sdk'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/webpack-config':\n case '@expo/env':\n case '@react-native/codegen':\n case '@react-native/community-cli-plugin':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n case 'eslint-plugin-import':\n case 'jest-expo':\n case 'jest':\n case 'metro':\n case 'ts-node':\n case 'typescript':\n case 'webpack':\n return false;\n default:\n return true;\n }\n}\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n if (duplicates.every((parent) => parent.path !== duplicate.path)) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n } else if (!target.version && duplicate.version) {\n target.version = duplicate.version;\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise | T | null\n): Promise> {\n const resolutions = await Promise.all(\n Object.keys(results).map(async (key) => {\n const resolution = results[key];\n const result = resolution ? await filterMap(resolution) : null;\n // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates\n // to see if the `searchPaths` result is not a module but another is\n if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) {\n for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) {\n const duplicate = resolution.duplicates[idx];\n const duplicateResult = await filterMap({ ...resolution, ...duplicate });\n if (duplicateResult != null) {\n return duplicateResult;\n }\n }\n }\n return result;\n })\n );\n const output: Record = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(\n results: ResolutionResult[],\n base?: ResolutionResult\n): ResolutionResult {\n if (base == null && results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = base == null ? Object.create(null) : base;\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/index.js b/packages/expo-modules-autolinking/build/index.js index 8a8d818104734a..48a509414f862e 100644 --- a/packages/expo-modules-autolinking/build/index.js +++ b/packages/expo-modules-autolinking/build/index.js @@ -9,6 +9,7 @@ const reactNativeConfigCommand_1 = require("./commands/reactNativeConfigCommand" const resolveCommand_1 = require("./commands/resolveCommand"); const searchCommand_1 = require("./commands/searchCommand"); const verifyCommand_1 = require("./commands/verifyCommand"); +const memoize_1 = require("./memoize"); async function main(args) { const cli = commander_1.default .version(require('expo-modules-autolinking/package.json').version) @@ -18,7 +19,9 @@ async function main(args) { (0, resolveCommand_1.resolveCommand)(cli); (0, generateModulesProviderCommand_1.generateModulesProviderCommand)(cli); (0, reactNativeConfigCommand_1.reactNativeConfigCommand)(cli); - await cli.parseAsync(args, { from: 'user' }); + await (0, memoize_1.createMemoizer)().withMemoizer(async () => { + await cli.parseAsync(args, { from: 'user' }); + }); } module.exports = main; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/index.js.map b/packages/expo-modules-autolinking/build/index.js.map index 95391bed428376..84b031082b1d71 100644 --- a/packages/expo-modules-autolinking/build/index.js.map +++ b/packages/expo-modules-autolinking/build/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,0DAAkC;AAElC,8FAA2F;AAC3F,kFAA+E;AAC/E,8DAA2D;AAC3D,4DAAyD;AACzD,4DAAyD;AAEzD,KAAK,UAAU,IAAI,CAAC,IAAc;IAChC,MAAM,GAAG,GAAG,mBAAS;SAClB,OAAO,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,OAAO,CAAC;SACjE,WAAW,CAAC,gEAAgE,CAAC,CAAC;IAEjF,IAAA,6BAAa,EAAC,GAAG,CAAC,CAAC;IACnB,IAAA,6BAAa,EAAC,GAAG,CAAC,CAAC;IACnB,IAAA,+BAAc,EAAC,GAAG,CAAC,CAAC;IACpB,IAAA,+DAA8B,EAAC,GAAG,CAAC,CAAC;IACpC,IAAA,mDAAwB,EAAC,GAAG,CAAC,CAAC;IAE9B,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC","sourcesContent":["import commander from 'commander';\n\nimport { generateModulesProviderCommand } from './commands/generateModulesProviderCommand';\nimport { reactNativeConfigCommand } from './commands/reactNativeConfigCommand';\nimport { resolveCommand } from './commands/resolveCommand';\nimport { searchCommand } from './commands/searchCommand';\nimport { verifyCommand } from './commands/verifyCommand';\n\nasync function main(args: string[]) {\n const cli = commander\n .version(require('expo-modules-autolinking/package.json').version)\n .description('CLI command that searches for native modules to autolink them.');\n\n verifyCommand(cli);\n searchCommand(cli);\n resolveCommand(cli);\n generateModulesProviderCommand(cli);\n reactNativeConfigCommand(cli);\n\n await cli.parseAsync(args, { from: 'user' });\n}\n\nmodule.exports = main;\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,0DAAkC;AAElC,8FAA2F;AAC3F,kFAA+E;AAC/E,8DAA2D;AAC3D,4DAAyD;AACzD,4DAAyD;AACzD,uCAA2C;AAE3C,KAAK,UAAU,IAAI,CAAC,IAAc;IAChC,MAAM,GAAG,GAAG,mBAAS;SAClB,OAAO,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,OAAO,CAAC;SACjE,WAAW,CAAC,gEAAgE,CAAC,CAAC;IAEjF,IAAA,6BAAa,EAAC,GAAG,CAAC,CAAC;IACnB,IAAA,6BAAa,EAAC,GAAG,CAAC,CAAC;IACnB,IAAA,+BAAc,EAAC,GAAG,CAAC,CAAC;IACpB,IAAA,+DAA8B,EAAC,GAAG,CAAC,CAAC;IACpC,IAAA,mDAAwB,EAAC,GAAG,CAAC,CAAC;IAE9B,MAAM,IAAA,wBAAc,GAAE,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;QAC7C,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC","sourcesContent":["import commander from 'commander';\n\nimport { generateModulesProviderCommand } from './commands/generateModulesProviderCommand';\nimport { reactNativeConfigCommand } from './commands/reactNativeConfigCommand';\nimport { resolveCommand } from './commands/resolveCommand';\nimport { searchCommand } from './commands/searchCommand';\nimport { verifyCommand } from './commands/verifyCommand';\nimport { createMemoizer } from './memoize';\n\nasync function main(args: string[]) {\n const cli = commander\n .version(require('expo-modules-autolinking/package.json').version)\n .description('CLI command that searches for native modules to autolink them.');\n\n verifyCommand(cli);\n searchCommand(cli);\n resolveCommand(cli);\n generateModulesProviderCommand(cli);\n reactNativeConfigCommand(cli);\n\n await createMemoizer().withMemoizer(async () => {\n await cli.parseAsync(args, { from: 'user' });\n });\n}\n\nmodule.exports = main;\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/memoize.d.ts b/packages/expo-modules-autolinking/build/memoize.d.ts new file mode 100644 index 00000000000000..e599ac0348d029 --- /dev/null +++ b/packages/expo-modules-autolinking/build/memoize.d.ts @@ -0,0 +1,16 @@ +export interface Memoizer { + /** Calls a function with a memoizer cache, caching its return value */ + call>(fn: Fn, input: string, ...args: Args): Promise; + /** Invokes an async context with a memoizer cache */ + withMemoizer(callback: () => R): R; + withMemoizer(callback: (...args: TArgs) => R, ...args: TArgs): R; +} +export interface MemoizableAsyncFn { + (input: string, ...args: Args): Promise; +} +/** Wraps a function in a memoizer, using the memoizer async local storage */ +export declare function memoize>(fn: Fn): MemoizableAsyncFn; +/** Creates a memoizer that can provide a cache to memoized functions */ +export declare function createMemoizer(): Memoizer; +/** @internal Used in tests to verify the memoizer was freed */ +export declare function _verifyMemoizerFreed(): boolean; diff --git a/packages/expo-modules-autolinking/build/memoize.js b/packages/expo-modules-autolinking/build/memoize.js new file mode 100644 index 00000000000000..f3232d6f0547fc --- /dev/null +++ b/packages/expo-modules-autolinking/build/memoize.js @@ -0,0 +1,84 @@ +"use strict"; +// expo-modules-autolinking has a few memoizable operations that we don't want to repeat. +// However, memoizing them naively means that we may hold on to the cached values for too long. +// Instead, we wrap all calls with a `Memoizer`. +// +// This could use AsyncLocalStorage, but those are expensive. Instead, we only share one +// cache for all calls, and assume that all memoizable return values may be memoized and +// shared globally. +// +// Memoizers are created once per run, and then shared between all subsequent calls. They +// are freed when their usage count to zero, after one tick. +// +// NOTE: If you need to debug whether the memoizer is properly used, change when the +// `console.warn` appears to see if you have any uncached calls. We allow uncached calls +// for backwards-compatibility, since, at worst, we have an uncached call, if the +// Memoizer is missing. +Object.defineProperty(exports, "__esModule", { value: true }); +exports.memoize = memoize; +exports.createMemoizer = createMemoizer; +exports._verifyMemoizerFreed = _verifyMemoizerFreed; +const MAX_SIZE = 5_000; +let currentMemoizer; +let currentContexts = 0; +/** Wraps a function in a memoizer, using the memoizer async local storage */ +function memoize(fn) { + return (input, ...args) => { + // We either use the current memoizer (sync) or the memoize context (async) + if (!currentMemoizer) { + if (process.env.NODE_ENV === 'test') { + console.warn(`expo-modules-autolinking: Memoized function called without memoize context (${fn.name})\n` + + new Error().stack); + } + return fn(input, ...args); + } + return currentMemoizer.call(fn, input, ...args); + }; +} +/** Creates a memoizer that can provide a cache to memoized functions */ +function createMemoizer() { + // If we already have a memoizer, reuse it, since we can share them globally + if (currentMemoizer) { + return currentMemoizer; + } + const cacheByFn = new Map(); + const memoizer = { + async call(fn, input, ...args) { + let cache = cacheByFn.get(fn); + if (!cache) { + cache = new Map(); + cacheByFn.set(fn, cache); + } + if (!cache.has(input)) { + const value = await memoizer.withMemoizer(fn, input, ...args); + if (cache.size > MAX_SIZE) { + cache.clear(); + } + cache.set(input, value); + return value; + } + return cache.get(input); + }, + async withMemoizer(fn, ...args) { + currentMemoizer = memoizer; + currentContexts++; + try { + return await fn(...args); + } + finally { + if (currentContexts > 0) { + currentContexts--; + } + if (currentContexts === 0) { + currentMemoizer = undefined; + } + } + }, + }; + return memoizer; +} +/** @internal Used in tests to verify the memoizer was freed */ +function _verifyMemoizerFreed() { + return currentMemoizer === undefined && currentContexts === 0; +} +//# sourceMappingURL=memoize.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/memoize.js.map b/packages/expo-modules-autolinking/build/memoize.js.map new file mode 100644 index 00000000000000..ebc365a15fc7a9 --- /dev/null +++ b/packages/expo-modules-autolinking/build/memoize.js.map @@ -0,0 +1 @@ +{"version":3,"file":"memoize.js","sourceRoot":"","sources":["../src/memoize.ts"],"names":[],"mappings":"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","sourcesContent":["// expo-modules-autolinking has a few memoizable operations that we don't want to repeat.\n// However, memoizing them naively means that we may hold on to the cached values for too long.\n// Instead, we wrap all calls with a `Memoizer`.\n//\n// This could use AsyncLocalStorage, but those are expensive. Instead, we only share one\n// cache for all calls, and assume that all memoizable return values may be memoized and\n// shared globally.\n//\n// Memoizers are created once per run, and then shared between all subsequent calls. They\n// are freed when their usage count to zero, after one tick.\n//\n// NOTE: If you need to debug whether the memoizer is properly used, change when the\n// `console.warn` appears to see if you have any uncached calls. We allow uncached calls\n// for backwards-compatibility, since, at worst, we have an uncached call, if the\n// Memoizer is missing.\n\nconst MAX_SIZE = 5_000;\n\nexport interface Memoizer {\n /** Calls a function with a memoizer cache, caching its return value */\n call>(\n fn: Fn,\n input: string,\n ...args: Args\n ): Promise;\n\n /** Invokes an async context with a memoizer cache */\n withMemoizer(callback: () => R): R;\n withMemoizer(callback: (...args: TArgs) => R, ...args: TArgs): R;\n}\n\nexport interface MemoizableAsyncFn {\n (input: string, ...args: Args): Promise;\n}\n\nlet currentMemoizer: Memoizer | undefined;\nlet currentContexts = 0;\n\n/** Wraps a function in a memoizer, using the memoizer async local storage */\nexport function memoize>(\n fn: Fn\n): MemoizableAsyncFn {\n return (input: string, ...args: Args) => {\n // We either use the current memoizer (sync) or the memoize context (async)\n if (!currentMemoizer) {\n if (process.env.NODE_ENV === 'test') {\n console.warn(\n `expo-modules-autolinking: Memoized function called without memoize context (${fn.name})\\n` +\n new Error().stack\n );\n }\n return fn(input, ...args);\n }\n return currentMemoizer.call(fn, input, ...args);\n };\n}\n\n/** Creates a memoizer that can provide a cache to memoized functions */\nexport function createMemoizer(): Memoizer {\n // If we already have a memoizer, reuse it, since we can share them globally\n if (currentMemoizer) {\n return currentMemoizer;\n }\n\n const cacheByFn = new Map>();\n const memoizer: Memoizer = {\n async call(fn, input, ...args) {\n let cache = cacheByFn.get(fn);\n if (!cache) {\n cache = new Map();\n cacheByFn.set(fn, cache);\n }\n if (!cache.has(input)) {\n const value = await memoizer.withMemoizer(fn, input, ...args);\n if (cache.size > MAX_SIZE) {\n cache.clear();\n }\n cache.set(input, value);\n return value;\n }\n return cache.get(input);\n },\n async withMemoizer(fn: (...args: TArgs) => R, ...args: TArgs) {\n currentMemoizer = memoizer;\n currentContexts++;\n try {\n return await fn(...args);\n } finally {\n if (currentContexts > 0) {\n currentContexts--;\n }\n if (currentContexts === 0) {\n currentMemoizer = undefined;\n }\n }\n },\n };\n return memoizer;\n}\n\n/** @internal Used in tests to verify the memoizer was freed */\nexport function _verifyMemoizerFreed() {\n return currentMemoizer === undefined && currentContexts === 0;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js index 104c5ee82a7ddb..9171c5187efcc2 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js @@ -53,7 +53,7 @@ async function resolveDependencyConfigImplAndroidAsync(packageRoot, reactNativeC reactNativeConfig?.packageImportPath || `import ${packageName}.${nativePackageClassName};`; packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`; } - const packageJson = JSON.parse(await promises_1.default.readFile(path_1.default.join(packageRoot, 'package.json'), 'utf8')); + const packageJson = await (0, utils_1.loadPackageJson)((0, utils_1.fastJoin)(packageRoot, 'package.json')); const buildTypes = reactNativeConfig?.buildTypes || []; const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration; const libraryName = reactNativeConfig?.libraryName || (await parseLibraryNameAsync(androidDir, packageJson)); @@ -208,7 +208,7 @@ async function parseComponentDescriptorsAsync(packageRoot, packageJson) { const results = new Set(); for await (const entry of (0, utils_1.scanFilesRecursively)(jsRoot)) { if (extRe.test(entry.name)) { - const contents = await promises_1.default.readFile(entry.path); + const contents = await promises_1.default.readFile(entry.path, 'utf8'); const matched = matchComponentDescriptors(entry.path, contents); if (matched) { results.add(matched); @@ -219,12 +219,11 @@ async function parseComponentDescriptorsAsync(packageRoot, packageJson) { } let lazyCodegenComponentRegex = null; function matchComponentDescriptors(_filePath, contents) { - const fileContents = contents.toString(); if (!lazyCodegenComponentRegex) { lazyCodegenComponentRegex = /codegenNativeComponent(<.*>)?\s*\(\s*["'`](\w+)["'`](,?[\s\S]+interfaceOnly:\s*(\w+))?/m; } - const match = fileContents.match(lazyCodegenComponentRegex); + const match = contents.match(lazyCodegenComponentRegex); if (!(match?.[4] === 'true') && match?.[2]) { return `${match[2]}ComponentDescriptor`; } diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map index 3f06cff35b5aeb..270fe5538824c4 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map @@ -1 +1 @@ -{"version":3,"file":"androidResolver.js","sourceRoot":"","sources":["../../src/reactNativeConfig/androidResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nimport type {\n RNConfigDependencyAndroid,\n RNConfigReactNativePlatformsConfigAndroid,\n} from './reactNativeConfig.types';\nimport type { ExpoModuleConfig } from '../ExpoModuleConfig';\nimport { scanFilesRecursively, fileExistsAsync } from '../utils';\n\nexport async function resolveDependencyConfigImplAndroidAsync(\n packageRoot: string,\n reactNativeConfig: RNConfigReactNativePlatformsConfigAndroid | null | undefined,\n expoModuleConfig?: ExpoModuleConfig | null\n): Promise {\n if (reactNativeConfig === null) {\n // Skip autolinking for this package.\n return null;\n }\n\n // NOTE(@kitten): We allow `reactNativeConfig === undefined` here. That indicates a missing config file\n // However, React Native modules with left out config files are explicitly supported and valid\n\n const sourceDir = reactNativeConfig?.sourceDir || 'android';\n const androidDir = path.join(packageRoot, sourceDir);\n const { gradle, manifest } = await findGradleAndManifestAsync({ androidDir, isLibrary: true });\n\n const isPureCxxDependency =\n reactNativeConfig?.cxxModuleCMakeListsModuleName != null &&\n reactNativeConfig?.cxxModuleCMakeListsPath != null &&\n reactNativeConfig?.cxxModuleHeaderName != null &&\n !manifest &&\n !gradle;\n\n if (!manifest && !gradle && !isPureCxxDependency) {\n return null;\n }\n\n if (reactNativeConfig === undefined && expoModuleConfig?.supportsPlatform('android')) {\n if (!!gradle && !expoModuleConfig?.rawConfig.android?.gradlePath) {\n // If the React Native module has a gradle file and the Expo module doesn't redirect it,\n // they will conflict and we can't link both at the same time\n return null;\n }\n }\n\n let packageInstance: string | null = null;\n let packageImportPath: string | null = null;\n if (!isPureCxxDependency) {\n const packageName =\n reactNativeConfig?.packageName || (await parsePackageNameAsync(manifest, gradle));\n if (!packageName) {\n return null;\n }\n const nativePackageClassName = await parseNativePackageClassNameAsync(packageRoot, androidDir);\n if (!nativePackageClassName) {\n return null;\n }\n packageImportPath =\n reactNativeConfig?.packageImportPath || `import ${packageName}.${nativePackageClassName};`;\n packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`;\n }\n\n const packageJson = JSON.parse(await fs.readFile(path.join(packageRoot, 'package.json'), 'utf8'));\n const buildTypes = reactNativeConfig?.buildTypes || [];\n const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration;\n const libraryName =\n reactNativeConfig?.libraryName || (await parseLibraryNameAsync(androidDir, packageJson));\n const componentDescriptors =\n reactNativeConfig?.componentDescriptors ||\n (await parseComponentDescriptorsAsync(packageRoot, packageJson));\n let cmakeListsPath = reactNativeConfig?.cmakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cmakeListsPath)\n : path.join(androidDir, 'build/generated/source/codegen/jni/CMakeLists.txt');\n const cxxModuleCMakeListsModuleName = reactNativeConfig?.cxxModuleCMakeListsModuleName || null;\n const cxxModuleHeaderName = reactNativeConfig?.cxxModuleHeaderName || null;\n let cxxModuleCMakeListsPath = reactNativeConfig?.cxxModuleCMakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cxxModuleCMakeListsPath)\n : null;\n if (process.platform === 'win32') {\n cmakeListsPath = cmakeListsPath.replace(/\\\\/g, '/');\n if (cxxModuleCMakeListsPath) {\n cxxModuleCMakeListsPath = cxxModuleCMakeListsPath.replace(/\\\\/g, '/');\n }\n }\n\n const result: RNConfigDependencyAndroid = {\n sourceDir: androidDir,\n packageImportPath,\n packageInstance,\n dependencyConfiguration,\n buildTypes,\n libraryName,\n componentDescriptors,\n cmakeListsPath,\n cxxModuleCMakeListsModuleName,\n cxxModuleCMakeListsPath,\n cxxModuleHeaderName,\n isPureCxxDependency,\n };\n if (!result.libraryName) {\n delete result.libraryName;\n }\n if (!result.dependencyConfiguration) {\n delete result.dependencyConfiguration;\n }\n return result;\n}\n\n/**\n * Parse the `RNConfigDependencyAndroid.packageName`\n */\nexport async function parsePackageNameAsync(\n manifestPath: string | null,\n gradlePath: string | null\n): Promise {\n if (gradlePath) {\n const gradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = gradleContents.match(/namespace\\s*[=]*\\s*[\"'](.+?)[\"']/);\n if (match) {\n return match[1];\n }\n }\n if (manifestPath) {\n const manifestContents = await fs.readFile(manifestPath, 'utf8');\n const match = manifestContents.match(/package=\"(.+?)\"/);\n if (match) {\n return match[1];\n }\n }\n return null;\n}\n\n/**\n * Parse the Java or Kotlin class name to for `ReactPackage` or `(Base|Turbo)ReactPackage`.\n */\nexport async function parseNativePackageClassNameAsync(\n packageRoot: string,\n androidDir: string\n): Promise {\n // Search for **/*Package.{java,kt} files first\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('Package.java') || entry.name.endsWith('Package.kt')) {\n try {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n } catch {\n continue;\n }\n }\n }\n\n // Early return if the module is an Expo module\n if (await fileExistsAsync(path.join(packageRoot, 'expo-module.config.json'))) {\n return null;\n }\n\n // Search all **/*.{java,kt} files\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('.java') || entry.name.endsWith('.kt')) {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n }\n }\n return null;\n}\n\nlet lazyReactPackageRegex: RegExp | null = null;\nlet lazyTurboReactPackageRegex: RegExp | null = null;\nexport function matchNativePackageClassName(_filePath: string, contents: Buffer): string | null {\n const fileContents = contents.toString();\n\n // [0] Match ReactPackage\n if (!lazyReactPackageRegex) {\n lazyReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+implements\\s+|:)[\\s\\w():,]*[^{]*ReactPackage/;\n }\n const matchReactPackage = fileContents.match(lazyReactPackageRegex);\n if (matchReactPackage) {\n return matchReactPackage[1];\n }\n\n // [1] Match (Base|Turbo)ReactPackage\n if (!lazyTurboReactPackageRegex) {\n lazyTurboReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+extends\\s+|:)[\\s\\w():,]*[^{]*(Base|Turbo)ReactPackage/;\n }\n const matchTurboReactPackage = fileContents.match(lazyTurboReactPackageRegex);\n if (matchTurboReactPackage) {\n return matchTurboReactPackage[1];\n }\n\n return null;\n}\n\nexport async function parseLibraryNameAsync(\n androidDir: string,\n packageJson: any\n): Promise {\n // [0] `codegenConfig.name` from package.json\n if (packageJson.codegenConfig?.name) {\n return packageJson.codegenConfig.name;\n }\n\n const libraryNameRegExp = /libraryName = [\"'](.+)[\"']/;\n const gradlePath = path.join(androidDir, 'build.gradle');\n // [1] `libraryName` from build.gradle\n if (await fileExistsAsync(gradlePath)) {\n const buildGradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n // [2] `libraryName` from build.gradle.kts\n const gradleKtsPath = path.join(androidDir, 'build.gradle.kts');\n if (await fileExistsAsync(gradleKtsPath)) {\n const buildGradleContents = await fs.readFile(gradleKtsPath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n return null;\n}\n\nexport async function parseComponentDescriptorsAsync(\n packageRoot: string,\n packageJson: any\n): Promise {\n const jsRoot = packageJson?.codegenConfig?.jsSrcsDir\n ? path.join(packageRoot, packageJson.codegenConfig.jsSrcsDir)\n : packageRoot;\n const extRe = /\\.[tj]sx?$/;\n const results = new Set();\n for await (const entry of scanFilesRecursively(jsRoot)) {\n if (extRe.test(entry.name)) {\n const contents = await fs.readFile(entry.path);\n const matched = matchComponentDescriptors(entry.path, contents);\n if (matched) {\n results.add(matched);\n }\n }\n }\n return [...results].sort((a, b) => a.localeCompare(b));\n}\n\nlet lazyCodegenComponentRegex: RegExp | null = null;\nfunction matchComponentDescriptors(_filePath: string, contents: Buffer): string | null {\n const fileContents = contents.toString();\n\n if (!lazyCodegenComponentRegex) {\n lazyCodegenComponentRegex =\n /codegenNativeComponent(<.*>)?\\s*\\(\\s*[\"'`](\\w+)[\"'`](,?[\\s\\S]+interfaceOnly:\\s*(\\w+))?/m;\n }\n const match = fileContents.match(lazyCodegenComponentRegex);\n if (!(match?.[4] === 'true') && match?.[2]) {\n return `${match[2]}ComponentDescriptor`;\n }\n return null;\n}\n\nconst findAndroidManifestsAsync = async (targetPath: string) => {\n const files = scanFilesRecursively(targetPath, (parentPath, name) => {\n switch (name) {\n case 'build':\n case 'debug':\n case 'Pods':\n return false;\n case 'Examples':\n case 'examples':\n // Only ignore top-level examples directories in `targetPath` but not nested ones\n return parentPath !== targetPath;\n case 'android':\n return !/[\\\\/]sdks[\\\\/]hermes$/.test(parentPath);\n case 'androidTest':\n case 'test':\n return !/[\\\\/]src$/.test(parentPath);\n default:\n return true;\n }\n });\n const manifestPaths: string[] = [];\n for await (const entry of files) {\n if (entry.name === 'AndroidManifest.xml') {\n manifestPaths.push(entry.path);\n }\n }\n return manifestPaths.sort((a, b) => a.localeCompare(b));\n};\n\nconst getFileCandidatesAsync = async (targetPath: string, fileNames: string[]) => {\n const gradlePaths = await Promise.all(\n fileNames.map((fileName) => fileExistsAsync(path.join(targetPath, fileName)))\n );\n return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b));\n};\n\nexport async function findGradleAndManifestAsync({\n androidDir,\n isLibrary,\n}: {\n androidDir: string;\n isLibrary: boolean;\n}): Promise<{ gradle: string | null; manifest: string | null }> {\n const [manifests, gradles] = await Promise.all([\n findAndroidManifestsAsync(androidDir),\n getFileCandidatesAsync(isLibrary ? androidDir : path.join(androidDir, 'app'), [\n 'build.gradle',\n 'build.gradle.kts',\n ]),\n ]);\n // TODO(@kitten): We can't optimise this because of the prior `includes()` pattern. Is this meant to be startsWith?\n const manifest =\n manifests.find((manifest) => manifest.includes('src/main/')) ??\n manifests.sort((a, b) => a.localeCompare(b))[0];\n const gradle = gradles.sort((a, b) => a.localeCompare(b))[0];\n return { gradle: gradle || null, manifest: manifest || null };\n}\n"]} \ No newline at end of file +{"version":3,"file":"androidResolver.js","sourceRoot":"","sources":["../../src/reactNativeConfig/androidResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nimport type {\n RNConfigDependencyAndroid,\n RNConfigReactNativePlatformsConfigAndroid,\n} from './reactNativeConfig.types';\nimport type { ExpoModuleConfig } from '../ExpoModuleConfig';\nimport { scanFilesRecursively, fileExistsAsync, fastJoin, loadPackageJson } from '../utils';\n\nexport async function resolveDependencyConfigImplAndroidAsync(\n packageRoot: string,\n reactNativeConfig: RNConfigReactNativePlatformsConfigAndroid | null | undefined,\n expoModuleConfig?: ExpoModuleConfig | null\n): Promise {\n if (reactNativeConfig === null) {\n // Skip autolinking for this package.\n return null;\n }\n\n // NOTE(@kitten): We allow `reactNativeConfig === undefined` here. That indicates a missing config file\n // However, React Native modules with left out config files are explicitly supported and valid\n\n const sourceDir = reactNativeConfig?.sourceDir || 'android';\n const androidDir = path.join(packageRoot, sourceDir);\n const { gradle, manifest } = await findGradleAndManifestAsync({ androidDir, isLibrary: true });\n\n const isPureCxxDependency =\n reactNativeConfig?.cxxModuleCMakeListsModuleName != null &&\n reactNativeConfig?.cxxModuleCMakeListsPath != null &&\n reactNativeConfig?.cxxModuleHeaderName != null &&\n !manifest &&\n !gradle;\n\n if (!manifest && !gradle && !isPureCxxDependency) {\n return null;\n }\n\n if (reactNativeConfig === undefined && expoModuleConfig?.supportsPlatform('android')) {\n if (!!gradle && !expoModuleConfig?.rawConfig.android?.gradlePath) {\n // If the React Native module has a gradle file and the Expo module doesn't redirect it,\n // they will conflict and we can't link both at the same time\n return null;\n }\n }\n\n let packageInstance: string | null = null;\n let packageImportPath: string | null = null;\n if (!isPureCxxDependency) {\n const packageName =\n reactNativeConfig?.packageName || (await parsePackageNameAsync(manifest, gradle));\n if (!packageName) {\n return null;\n }\n const nativePackageClassName = await parseNativePackageClassNameAsync(packageRoot, androidDir);\n if (!nativePackageClassName) {\n return null;\n }\n packageImportPath =\n reactNativeConfig?.packageImportPath || `import ${packageName}.${nativePackageClassName};`;\n packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`;\n }\n\n const packageJson = await loadPackageJson(fastJoin(packageRoot, 'package.json'));\n const buildTypes = reactNativeConfig?.buildTypes || [];\n const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration;\n const libraryName =\n reactNativeConfig?.libraryName || (await parseLibraryNameAsync(androidDir, packageJson));\n const componentDescriptors =\n reactNativeConfig?.componentDescriptors ||\n (await parseComponentDescriptorsAsync(packageRoot, packageJson));\n let cmakeListsPath = reactNativeConfig?.cmakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cmakeListsPath)\n : path.join(androidDir, 'build/generated/source/codegen/jni/CMakeLists.txt');\n const cxxModuleCMakeListsModuleName = reactNativeConfig?.cxxModuleCMakeListsModuleName || null;\n const cxxModuleHeaderName = reactNativeConfig?.cxxModuleHeaderName || null;\n let cxxModuleCMakeListsPath = reactNativeConfig?.cxxModuleCMakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cxxModuleCMakeListsPath)\n : null;\n if (process.platform === 'win32') {\n cmakeListsPath = cmakeListsPath.replace(/\\\\/g, '/');\n if (cxxModuleCMakeListsPath) {\n cxxModuleCMakeListsPath = cxxModuleCMakeListsPath.replace(/\\\\/g, '/');\n }\n }\n\n const result: RNConfigDependencyAndroid = {\n sourceDir: androidDir,\n packageImportPath,\n packageInstance,\n dependencyConfiguration,\n buildTypes,\n libraryName,\n componentDescriptors,\n cmakeListsPath,\n cxxModuleCMakeListsModuleName,\n cxxModuleCMakeListsPath,\n cxxModuleHeaderName,\n isPureCxxDependency,\n };\n if (!result.libraryName) {\n delete result.libraryName;\n }\n if (!result.dependencyConfiguration) {\n delete result.dependencyConfiguration;\n }\n return result;\n}\n\n/**\n * Parse the `RNConfigDependencyAndroid.packageName`\n */\nexport async function parsePackageNameAsync(\n manifestPath: string | null,\n gradlePath: string | null\n): Promise {\n if (gradlePath) {\n const gradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = gradleContents.match(/namespace\\s*[=]*\\s*[\"'](.+?)[\"']/);\n if (match) {\n return match[1];\n }\n }\n if (manifestPath) {\n const manifestContents = await fs.readFile(manifestPath, 'utf8');\n const match = manifestContents.match(/package=\"(.+?)\"/);\n if (match) {\n return match[1];\n }\n }\n return null;\n}\n\n/**\n * Parse the Java or Kotlin class name to for `ReactPackage` or `(Base|Turbo)ReactPackage`.\n */\nexport async function parseNativePackageClassNameAsync(\n packageRoot: string,\n androidDir: string\n): Promise {\n // Search for **/*Package.{java,kt} files first\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('Package.java') || entry.name.endsWith('Package.kt')) {\n try {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n } catch {\n continue;\n }\n }\n }\n\n // Early return if the module is an Expo module\n if (await fileExistsAsync(path.join(packageRoot, 'expo-module.config.json'))) {\n return null;\n }\n\n // Search all **/*.{java,kt} files\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('.java') || entry.name.endsWith('.kt')) {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n }\n }\n return null;\n}\n\nlet lazyReactPackageRegex: RegExp | null = null;\nlet lazyTurboReactPackageRegex: RegExp | null = null;\nexport function matchNativePackageClassName(_filePath: string, contents: Buffer): string | null {\n const fileContents = contents.toString();\n\n // [0] Match ReactPackage\n if (!lazyReactPackageRegex) {\n lazyReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+implements\\s+|:)[\\s\\w():,]*[^{]*ReactPackage/;\n }\n const matchReactPackage = fileContents.match(lazyReactPackageRegex);\n if (matchReactPackage) {\n return matchReactPackage[1];\n }\n\n // [1] Match (Base|Turbo)ReactPackage\n if (!lazyTurboReactPackageRegex) {\n lazyTurboReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+extends\\s+|:)[\\s\\w():,]*[^{]*(Base|Turbo)ReactPackage/;\n }\n const matchTurboReactPackage = fileContents.match(lazyTurboReactPackageRegex);\n if (matchTurboReactPackage) {\n return matchTurboReactPackage[1];\n }\n\n return null;\n}\n\nexport async function parseLibraryNameAsync(\n androidDir: string,\n packageJson: any\n): Promise {\n // [0] `codegenConfig.name` from package.json\n if (packageJson.codegenConfig?.name) {\n return packageJson.codegenConfig.name;\n }\n\n const libraryNameRegExp = /libraryName = [\"'](.+)[\"']/;\n const gradlePath = path.join(androidDir, 'build.gradle');\n // [1] `libraryName` from build.gradle\n if (await fileExistsAsync(gradlePath)) {\n const buildGradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n // [2] `libraryName` from build.gradle.kts\n const gradleKtsPath = path.join(androidDir, 'build.gradle.kts');\n if (await fileExistsAsync(gradleKtsPath)) {\n const buildGradleContents = await fs.readFile(gradleKtsPath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n return null;\n}\n\nexport async function parseComponentDescriptorsAsync(\n packageRoot: string,\n packageJson: any\n): Promise {\n const jsRoot = packageJson?.codegenConfig?.jsSrcsDir\n ? path.join(packageRoot, packageJson.codegenConfig.jsSrcsDir)\n : packageRoot;\n const extRe = /\\.[tj]sx?$/;\n const results = new Set();\n for await (const entry of scanFilesRecursively(jsRoot)) {\n if (extRe.test(entry.name)) {\n const contents = await fs.readFile(entry.path, 'utf8');\n const matched = matchComponentDescriptors(entry.path, contents);\n if (matched) {\n results.add(matched);\n }\n }\n }\n return [...results].sort((a, b) => a.localeCompare(b));\n}\n\nlet lazyCodegenComponentRegex: RegExp | null = null;\nfunction matchComponentDescriptors(_filePath: string, contents: string): string | null {\n if (!lazyCodegenComponentRegex) {\n lazyCodegenComponentRegex =\n /codegenNativeComponent(<.*>)?\\s*\\(\\s*[\"'`](\\w+)[\"'`](,?[\\s\\S]+interfaceOnly:\\s*(\\w+))?/m;\n }\n const match = contents.match(lazyCodegenComponentRegex);\n if (!(match?.[4] === 'true') && match?.[2]) {\n return `${match[2]}ComponentDescriptor`;\n }\n return null;\n}\n\nconst findAndroidManifestsAsync = async (targetPath: string) => {\n const files = scanFilesRecursively(targetPath, (parentPath, name) => {\n switch (name) {\n case 'build':\n case 'debug':\n case 'Pods':\n return false;\n case 'Examples':\n case 'examples':\n // Only ignore top-level examples directories in `targetPath` but not nested ones\n return parentPath !== targetPath;\n case 'android':\n return !/[\\\\/]sdks[\\\\/]hermes$/.test(parentPath);\n case 'androidTest':\n case 'test':\n return !/[\\\\/]src$/.test(parentPath);\n default:\n return true;\n }\n });\n const manifestPaths: string[] = [];\n for await (const entry of files) {\n if (entry.name === 'AndroidManifest.xml') {\n manifestPaths.push(entry.path);\n }\n }\n return manifestPaths.sort((a, b) => a.localeCompare(b));\n};\n\nconst getFileCandidatesAsync = async (targetPath: string, fileNames: string[]) => {\n const gradlePaths = await Promise.all(\n fileNames.map((fileName) => fileExistsAsync(path.join(targetPath, fileName)))\n );\n return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b));\n};\n\nexport async function findGradleAndManifestAsync({\n androidDir,\n isLibrary,\n}: {\n androidDir: string;\n isLibrary: boolean;\n}): Promise<{ gradle: string | null; manifest: string | null }> {\n const [manifests, gradles] = await Promise.all([\n findAndroidManifestsAsync(androidDir),\n getFileCandidatesAsync(isLibrary ? androidDir : path.join(androidDir, 'app'), [\n 'build.gradle',\n 'build.gradle.kts',\n ]),\n ]);\n // TODO(@kitten): We can't optimise this because of the prior `includes()` pattern. Is this meant to be startsWith?\n const manifest =\n manifests.find((manifest) => manifest.includes('src/main/')) ??\n manifests.sort((a, b) => a.localeCompare(b))[0];\n const gradle = gradles.sort((a, b) => a.localeCompare(b))[0];\n return { gradle: gradle || null, manifest: manifest || null };\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/config.d.ts b/packages/expo-modules-autolinking/build/reactNativeConfig/config.d.ts index 5ef920a0f32bcc..bc6c933eeabc1d 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/config.d.ts +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/config.d.ts @@ -1,4 +1,7 @@ +import type { RNConfigReactNativeConfig } from './reactNativeConfig.types'; +type LoadConfigAsync = (packageRoot: string) => Promise; /** * Load the `react-native.config.js` or `react-native.config.ts` from the package. */ -export declare const loadConfigAsync: (input: string, ...args: any[]) => Promise; +export declare const loadConfigAsync: LoadConfigAsync; +export {}; diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/config.js b/packages/expo-modules-autolinking/build/reactNativeConfig/config.js index 42df826fff8436..b6015c16d2be78 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/config.js +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/config.js @@ -7,12 +7,13 @@ exports.loadConfigAsync = void 0; const require_utils_1 = require("@expo/require-utils"); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); +const memoize_1 = require("../memoize"); const utils_1 = require("../utils"); const mockedNativeModules = path_1.default.join(__dirname, '..', '..', 'node_modules_mock'); /** * Load the `react-native.config.js` or `react-native.config.ts` from the package. */ -exports.loadConfigAsync = (0, utils_1.memoize)(async function loadConfigAsync(packageRoot) { +exports.loadConfigAsync = (0, memoize_1.memoize)(async function loadConfigAsync(packageRoot) { const configPath = (await Promise.all(['react-native.config.js', 'react-native.config.ts'].map(async (fileName) => { const file = path_1.default.join(packageRoot, fileName); return (await (0, utils_1.fileExistsAsync)(file)) ? file : null; diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/config.js.map b/packages/expo-modules-autolinking/build/reactNativeConfig/config.js.map index df95c8dd57d7ba..204b761fa778fa 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/config.js.map +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/config.js.map @@ -1 +1 @@ -{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/reactNativeConfig/config.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAiD;AACjD,2DAA6B;AAC7B,gDAAwB;AAExB,oCAAoD;AAGpD,MAAM,mBAAmB,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAElF;;GAEG;AACU,QAAA,eAAe,GAAG,IAAA,eAAO,EAAC,KAAK,UAAU,eAAe,CAEnE,WAAmB;IACnB,MAAM,UAAU,GAAG,CACjB,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,wBAAwB,EAAE,wBAAwB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC1E,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,CAAC,MAAM,IAAA,uBAAe,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC,CAAC,CACH,CACF,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAC/B,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,IAAA,0BAAU,EACpB,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,EACrC,UAAU;QACV,+DAA+D;QAC/D,0FAA0F;QAC1F,8DAA8D;QAC9D,EAAE,KAAK,EAAE,CAAC,mBAAmB,CAAC,EAAE,CACjC,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import { evalModule } from '@expo/require-utils';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nimport { memoize, fileExistsAsync } from '../utils';\nimport type { RNConfigReactNativeConfig } from './reactNativeConfig.types';\n\nconst mockedNativeModules = path.join(__dirname, '..', '..', 'node_modules_mock');\n\n/**\n * Load the `react-native.config.js` or `react-native.config.ts` from the package.\n */\nexport const loadConfigAsync = memoize(async function loadConfigAsync<\n T extends RNConfigReactNativeConfig,\n>(packageRoot: string): Promise {\n const configPath = (\n await Promise.all(\n ['react-native.config.js', 'react-native.config.ts'].map(async (fileName) => {\n const file = path.join(packageRoot, fileName);\n return (await fileExistsAsync(file)) ? file : null;\n })\n )\n ).find((path) => path != null);\n if (configPath) {\n const mod = evalModule(\n await fs.readFile(configPath, 'utf8'),\n configPath,\n // NOTE: We need to mock the Community CLI temporarily, because\n // some packages are checking the version of the CLI in the `react-native.config.js` file.\n // We can remove this once we remove this check from packages.\n { paths: [mockedNativeModules] }\n );\n return mod.default ?? mod ?? null;\n } else {\n return null;\n }\n});\n"]} \ No newline at end of file +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/reactNativeConfig/config.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAiD;AACjD,2DAA6B;AAC7B,gDAAwB;AAExB,wCAAqC;AACrC,oCAA2C;AAM3C,MAAM,mBAAmB,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAMlF;;GAEG;AACU,QAAA,eAAe,GAAoB,IAAA,iBAAO,EAAC,KAAK,UAAU,eAAe,CAEpF,WAAmB;IACnB,MAAM,UAAU,GAAG,CACjB,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,wBAAwB,EAAE,wBAAwB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC1E,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,CAAC,MAAM,IAAA,uBAAe,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACrD,CAAC,CAAC,CACH,CACF,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAC/B,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,IAAA,0BAAU,EACpB,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,EACrC,UAAU;QACV,+DAA+D;QAC/D,0FAA0F;QAC1F,8DAA8D;QAC9D,EAAE,KAAK,EAAE,CAAC,mBAAmB,CAAC,EAAE,CACjC,CAAC;QACF,OAAO,GAAG,CAAC,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import { evalModule } from '@expo/require-utils';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nimport { memoize } from '../memoize';\nimport { fileExistsAsync } from '../utils';\nimport type {\n RNConfigReactNativeConfig,\n RNConfigReactNativeProjectConfig,\n} from './reactNativeConfig.types';\n\nconst mockedNativeModules = path.join(__dirname, '..', '..', 'node_modules_mock');\n\ntype LoadConfigAsync = (\n packageRoot: string\n) => Promise;\n\n/**\n * Load the `react-native.config.js` or `react-native.config.ts` from the package.\n */\nexport const loadConfigAsync: LoadConfigAsync = memoize(async function loadConfigAsync<\n T extends RNConfigReactNativeConfig,\n>(packageRoot: string): Promise {\n const configPath = (\n await Promise.all(\n ['react-native.config.js', 'react-native.config.ts'].map(async (fileName) => {\n const file = path.join(packageRoot, fileName);\n return (await fileExistsAsync(file)) ? file : null;\n })\n )\n ).find((path) => path != null);\n if (configPath) {\n const mod = evalModule(\n await fs.readFile(configPath, 'utf8'),\n configPath,\n // NOTE: We need to mock the Community CLI temporarily, because\n // some packages are checking the version of the CLI in the `react-native.config.js` file.\n // We can remove this once we remove this check from packages.\n { paths: [mockedNativeModules] }\n );\n return mod.default ?? mod ?? null;\n } else {\n return null;\n }\n});\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/utils.d.ts b/packages/expo-modules-autolinking/build/utils.d.ts index 9ad423416f01cc..1a58b78bbf8e71 100644 --- a/packages/expo-modules-autolinking/build/utils.d.ts +++ b/packages/expo-modules-autolinking/build/utils.d.ts @@ -1,4 +1,3 @@ -export declare function memoize Promise>(fn: Fn): (input: string, ...args: any[]) => Promise; /** List filtered top-level files in `targetPath` (returns absolute paths) */ export declare function listFilesSorted(targetPath: string, filter: (basename: string) => boolean): Promise; /** List nested files in top-level directories in `targetPath` (returns relative paths) */ @@ -10,3 +9,10 @@ export declare function scanFilesRecursively(parentPath: string, includeDirector readonly name: string; }, void, unknown>; export declare const fileExistsAsync: (file: string) => Promise; +export declare const fastJoin: (from: string, append: string) => string; +export declare const maybeRealpath: (target: string) => Promise; +export type PackageJson = Record & { + name?: string; + version?: string; +}; +export declare const loadPackageJson: import("./memoize").MemoizableAsyncFn; diff --git a/packages/expo-modules-autolinking/build/utils.js b/packages/expo-modules-autolinking/build/utils.js index ce5604be7f741b..3cc18272d828af 100644 --- a/packages/expo-modules-autolinking/build/utils.js +++ b/packages/expo-modules-autolinking/build/utils.js @@ -3,30 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.fileExistsAsync = void 0; -exports.memoize = memoize; +exports.loadPackageJson = exports.maybeRealpath = exports.fastJoin = exports.fileExistsAsync = void 0; exports.listFilesSorted = listFilesSorted; exports.listFilesInDirectories = listFilesInDirectories; exports.scanFilesRecursively = scanFilesRecursively; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); -const MAX_SIZE = 5_000; -function memoize(fn) { - const cache = new Map(); - return async (input, ...args) => { - if (!cache.has(input)) { - const result = await fn(input, ...args); - if (cache.size > MAX_SIZE) { - cache.clear(); - } - cache.set(input, result); - return result; - } - else { - return cache.get(input); - } - }; -} +const memoize_1 = require("./memoize"); /** List filtered top-level files in `targetPath` (returns absolute paths) */ async function listFilesSorted(targetPath, filter) { try { @@ -89,4 +72,29 @@ const fileExistsAsync = async (file) => { return stat?.isFile() ? file : null; }; exports.fileExistsAsync = fileExistsAsync; +exports.fastJoin = path_1.default.sep === '/' + ? (from, append) => `${from}${path_1.default.sep}${append}` + : (from, append) => `${from}${path_1.default.sep}${append[0] === '@' ? append.replace('/', path_1.default.sep) : append}`; +const maybeRealpath = async (target) => { + try { + return await fs_1.default.promises.realpath(target); + } + catch { + return null; + } +}; +exports.maybeRealpath = maybeRealpath; +exports.loadPackageJson = (0, memoize_1.memoize)(async function loadPackageJson(jsonPath) { + try { + const packageJsonText = await fs_1.default.promises.readFile(jsonPath, 'utf8'); + const json = JSON.parse(packageJsonText); + if (typeof json !== 'object' || json == null) { + return null; + } + return json; + } + catch { + return null; + } +}); //# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/utils.js.map b/packages/expo-modules-autolinking/build/utils.js.map index f213bd572dd513..5f7520c1ec8762 100644 --- a/packages/expo-modules-autolinking/build/utils.js.map +++ b/packages/expo-modules-autolinking/build/utils.js.map @@ -1 +1 @@ -{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAKA,0BAcC;AAGD,0CAaC;AAGD,wDAoBC;AAGD,oDA+BC;AA5FD,4CAAoB;AACpB,gDAAwB;AAExB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB,SAAgB,OAAO,CAAmE,EAAM;IAC9F,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAChD,OAAO,KAAK,EAAE,KAAa,EAAE,GAAG,IAAW,EAAE,EAAE;QAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;YACxC,IAAI,KAAK,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC;gBAC1B,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,6EAA6E;AACtE,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,MAAqC;IAErC,IAAI,CAAC;QACH,qDAAqD;QACrD,OAAO,CAAC,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;aACpE,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;aACvD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,0FAA0F;AACnF,KAAK,UAAU,sBAAsB,CAC1C,UAAkB,EAClB,MAAqC;IAErC,OAAO,CACL,MAAM,OAAO,CAAC,GAAG,CACf,CAAC,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;SAC7D,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;SACvE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC5C,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;QACvB,MAAM,OAAO,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE;YAC/E,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QACH,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;aACvD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aAC5C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CACL,CACF,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACZ,CAAC;AAED,kGAAkG;AAC3F,KAAK,SAAS,CAAC,CAAC,oBAAoB,CACzC,UAAkB,EAClB,gBAAgE,EAChE,IAAI,GAAG,CAAC,YAAE,CAAC,OAAO;IAElB,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3B,IAAI,UAA8B,CAAC;IACnC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI;gBAClB,CAAC,CAAC,CAAC,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC7E,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAC7B;gBACH,CAAC,CAAC,MAAM,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC1C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACzD,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;wBAClE,KAAK,CAAC,IAAI,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;oBAChD,CAAC;gBACH,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC1B,MAAM;wBACJ,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC;wBACvC,UAAU,EAAE,UAAU;wBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;qBACR,CAAC;gBACb,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAEM,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAA0B,EAAE;IAC5E,MAAM,IAAI,GAAG,MAAM,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC,CAAC;AAHW,QAAA,eAAe,mBAG1B","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nconst MAX_SIZE = 5_000;\n\nexport function memoize Promise>(fn: Fn) {\n const cache = new Map>();\n return async (input: string, ...args: any[]) => {\n if (!cache.has(input)) {\n const result = await fn(input, ...args);\n if (cache.size > MAX_SIZE) {\n cache.clear();\n }\n cache.set(input, result);\n return result;\n } else {\n return cache.get(input);\n }\n };\n}\n\n/** List filtered top-level files in `targetPath` (returns absolute paths) */\nexport async function listFilesSorted(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise {\n try {\n // `readdir` isn't guaranteed to be sorted on Windows\n return (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(targetPath, entry.name));\n } catch {\n return [];\n }\n}\n\n/** List nested files in top-level directories in `targetPath` (returns relative paths) */\nexport async function listFilesInDirectories(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise {\n return (\n await Promise.all(\n (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory() && entry.name !== 'node_modules')\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(async (directory) => {\n const entries = await fs.promises.readdir(path.join(targetPath, directory.name), {\n withFileTypes: true,\n });\n return entries\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(directory.name, entry.name));\n })\n )\n ).flat(1);\n}\n\n/** Iterate folders recursively for files, optionally sorting results and filtering directories */\nexport async function* scanFilesRecursively(\n parentPath: string,\n includeDirectory?: (parentPath: string, name: string) => boolean,\n sort = !fs.opendir\n) {\n const queue = [parentPath];\n let targetPath: string | undefined;\n while (queue.length > 0 && (targetPath = queue.shift()) != null) {\n try {\n const entries = sort\n ? (await fs.promises.readdir(targetPath, { withFileTypes: true })).sort((a, b) =>\n a.name.localeCompare(b.name)\n )\n : await fs.promises.opendir(targetPath);\n for await (const entry of entries) {\n if (entry.isDirectory() && entry.name !== 'node_modules') {\n if (!includeDirectory || includeDirectory(targetPath, entry.name)) {\n queue.push(path.join(targetPath, entry.name));\n }\n } else if (entry.isFile()) {\n yield {\n path: path.join(targetPath, entry.name),\n parentPath: targetPath,\n name: entry.name,\n } as const;\n }\n }\n } catch {\n continue;\n }\n }\n}\n\nexport const fileExistsAsync = async (file: string): Promise => {\n const stat = await fs.promises.stat(file).catch(() => null);\n return stat?.isFile() ? file : null;\n};\n"]} \ No newline at end of file +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from './memoize';\n\n/** List filtered top-level files in `targetPath` (returns absolute paths) */\nexport async function listFilesSorted(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise {\n try {\n // `readdir` isn't guaranteed to be sorted on Windows\n return (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(targetPath, entry.name));\n } catch {\n return [];\n }\n}\n\n/** List nested files in top-level directories in `targetPath` (returns relative paths) */\nexport async function listFilesInDirectories(\n targetPath: string,\n filter: (basename: string) => boolean\n): Promise {\n return (\n await Promise.all(\n (await fs.promises.readdir(targetPath, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory() && entry.name !== 'node_modules')\n .sort((a, b) => a.name.localeCompare(b.name))\n .map(async (directory) => {\n const entries = await fs.promises.readdir(path.join(targetPath, directory.name), {\n withFileTypes: true,\n });\n return entries\n .filter((entry) => entry.isFile() && filter(entry.name))\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((entry) => path.join(directory.name, entry.name));\n })\n )\n ).flat(1);\n}\n\n/** Iterate folders recursively for files, optionally sorting results and filtering directories */\nexport async function* scanFilesRecursively(\n parentPath: string,\n includeDirectory?: (parentPath: string, name: string) => boolean,\n sort = !fs.opendir\n) {\n const queue = [parentPath];\n let targetPath: string | undefined;\n while (queue.length > 0 && (targetPath = queue.shift()) != null) {\n try {\n const entries = sort\n ? (await fs.promises.readdir(targetPath, { withFileTypes: true })).sort((a, b) =>\n a.name.localeCompare(b.name)\n )\n : await fs.promises.opendir(targetPath);\n for await (const entry of entries) {\n if (entry.isDirectory() && entry.name !== 'node_modules') {\n if (!includeDirectory || includeDirectory(targetPath, entry.name)) {\n queue.push(path.join(targetPath, entry.name));\n }\n } else if (entry.isFile()) {\n yield {\n path: path.join(targetPath, entry.name),\n parentPath: targetPath,\n name: entry.name,\n } as const;\n }\n }\n } catch {\n continue;\n }\n }\n}\n\nexport const fileExistsAsync = async (file: string): Promise => {\n const stat = await fs.promises.stat(file).catch(() => null);\n return stat?.isFile() ? file : null;\n};\n\nexport const fastJoin: (from: string, append: string) => string =\n path.sep === '/'\n ? (from, append) => `${from}${path.sep}${append}`\n : (from, append) =>\n `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`;\n\nexport const maybeRealpath = async (target: string): Promise => {\n try {\n return await fs.promises.realpath(target);\n } catch {\n return null;\n }\n};\n\nexport type PackageJson = Record & { name?: string; version?: string };\n\nexport const loadPackageJson = memoize(async function loadPackageJson(\n jsonPath: string\n): Promise {\n try {\n const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8');\n const json = JSON.parse(packageJsonText);\n if (typeof json !== 'object' || json == null) {\n return null;\n }\n return json;\n } catch {\n return null;\n }\n});\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/src/ExpoModuleConfig.ts b/packages/expo-modules-autolinking/src/ExpoModuleConfig.ts index e20b3a9ab00a79..55c84c7d60105f 100644 --- a/packages/expo-modules-autolinking/src/ExpoModuleConfig.ts +++ b/packages/expo-modules-autolinking/src/ExpoModuleConfig.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import path from 'path'; +import { memoize } from './memoize'; import { AndroidGradleAarProjectDescriptor, AndroidGradlePluginDescriptor, @@ -9,7 +10,6 @@ import { RawModuleConfigApple, SupportedPlatform, } from './types'; -import { memoize } from './utils'; function arrayize(value: T[] | T | undefined): T[] { if (Array.isArray(value)) { diff --git a/packages/expo-modules-autolinking/src/__tests__/memoize.test.ts b/packages/expo-modules-autolinking/src/__tests__/memoize.test.ts new file mode 100644 index 00000000000000..9c04fbc5e58caf --- /dev/null +++ b/packages/expo-modules-autolinking/src/__tests__/memoize.test.ts @@ -0,0 +1,47 @@ +import { createMemoizer, memoize, _verifyMemoizerFreed } from '../memoize'; + +it('provides cached value for memoizer', async () => { + const memoizer = createMemoizer(); + + let num = 0; + const fn = memoize(async () => ++num); + + await memoizer.withMemoizer(async () => { + expect(await fn('test')).toBe(1); + expect(await fn('test')).toBe(1); + expect(num).toBe(1); + // Busts cache + expect(await fn('test-2')).toBe(2); + expect(await fn('test-2')).toBe(2); + expect(num).toBe(2); + }); + + expect(_verifyMemoizerFreed()).toBe(true); +}); + +it('allows uncached calls', async () => { + // NOTE: This is to mute the `console.warn` log + process.env.NODE_ENV = 'not-test'; + + let num = 0; + const fn = memoize(async () => ++num); + + expect(await fn('test')).toBe(1); + expect(await fn('test')).toBe(2); + expect(num).toBe(2); + + expect(_verifyMemoizerFreed()).toBe(true); +}); + +it('allows direct calls without async context', async () => { + const memoizer = createMemoizer(); + + let num = 0; + const fn = memoize(async () => ++num); + + expect(await memoizer.call(fn, 'test')).toBe(1); + expect(await memoizer.call(fn, 'test')).toBe(1); + expect(num).toBe(1); + + expect(_verifyMemoizerFreed()).toBe(true); +}); diff --git a/packages/expo-modules-autolinking/src/autolinking/findModules.ts b/packages/expo-modules-autolinking/src/autolinking/findModules.ts index 77c2779f071844..5a71f79b4c66fd 100644 --- a/packages/expo-modules-autolinking/src/autolinking/findModules.ts +++ b/packages/expo-modules-autolinking/src/autolinking/findModules.ts @@ -7,6 +7,7 @@ import { filterMapResolutionResult, mergeResolutionResults, } from '../dependencies'; +import { createMemoizer } from '../memoize'; import { PackageRevision, SearchResults, SupportedPlatform } from '../types'; export async function resolveExpoModule( @@ -46,6 +47,7 @@ export async function findModulesAsync({ appRoot, autolinkingOptions, }: FindModulesParams): Promise { + const memoizer = createMemoizer(); const excludeNames = new Set(autolinkingOptions.exclude); // custom native modules should be resolved first so that they can override other modules @@ -53,13 +55,15 @@ export async function findModulesAsync({ ? [autolinkingOptions.nativeModulesDir, ...autolinkingOptions.searchPaths] : autolinkingOptions.searchPaths; - return filterMapResolutionResult( - mergeResolutionResults( - await Promise.all([ - ...searchPaths.map((searchPath) => scanDependenciesInSearchPath(searchPath)), - scanDependenciesRecursively(appRoot), - ]) - ), - (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames) - ); + return memoizer.withMemoizer(async () => { + return filterMapResolutionResult( + mergeResolutionResults( + await Promise.all([ + ...searchPaths.map((searchPath) => scanDependenciesInSearchPath(searchPath)), + scanDependenciesRecursively(appRoot), + ]) + ), + (resolution) => resolveExpoModule(resolution, autolinkingOptions.platform, excludeNames) + ); + }); } diff --git a/packages/expo-modules-autolinking/src/dependencies/CachedDependenciesLinker.ts b/packages/expo-modules-autolinking/src/dependencies/CachedDependenciesLinker.ts index 5ca5c7f074b731..84ef57f0fe3d96 100644 --- a/packages/expo-modules-autolinking/src/dependencies/CachedDependenciesLinker.ts +++ b/packages/expo-modules-autolinking/src/dependencies/CachedDependenciesLinker.ts @@ -8,6 +8,7 @@ import { type ResolutionResult, DependencyResolutionSource } from './types'; import { filterMapResolutionResult, mergeResolutionResults } from './utils'; import { resolveExpoModule } from '../autolinking/findModules'; import { AutolinkingOptions, createAutolinkingOptionsLoader } from '../commands/autolinkingOptions'; +import { createMemoizer, type Memoizer } from '../memoize'; import { resolveReactNativeModule, RNConfigReactNativeProjectConfig } from '../reactNativeConfig'; import { loadConfigAsync } from '../reactNativeConfig/config'; @@ -17,6 +18,7 @@ export interface CachedDependenciesSearchOptions { } export interface CachedDependenciesLinker { + memoizer: Memoizer; getOptionsForPlatform(platform: SupportedPlatform): Promise; loadReactNativeProjectConfig(): Promise; scanDependenciesFromRNProjectConfig(): Promise; @@ -27,6 +29,8 @@ export interface CachedDependenciesLinker { export function makeCachedDependenciesLinker(params: { projectRoot: string; }): CachedDependenciesLinker { + const memoizer = createMemoizer(); + const autolinkingOptionsLoader = createAutolinkingOptionsLoader({ projectRoot: params.projectRoot, }); @@ -40,40 +44,45 @@ export function makeCachedDependenciesLinker(params: { let recursiveDependencies: Promise | undefined; return { + memoizer, async getOptionsForPlatform(platform) { const options = await autolinkingOptionsLoader.getPlatformOptions(platform); return makeCachedDependenciesSearchOptions(options); }, async loadReactNativeProjectConfig() { if (reactNativeProjectConfig === undefined) { - reactNativeProjectConfig = loadConfigAsync( + reactNativeProjectConfig = memoizer.call( + loadConfigAsync, await getAppRoot() - ) as Promise; + ) as Promise; } return reactNativeProjectConfig; }, async scanDependenciesFromRNProjectConfig() { - const reactNativeProjectConfig = await this.loadReactNativeProjectConfig(); - return ( - reactNativeProjectConfigDependencies || - (reactNativeProjectConfigDependencies = scanDependenciesFromRNProjectConfig( - await getAppRoot(), - reactNativeProjectConfig - )) - ); + if (reactNativeProjectConfigDependencies === undefined) { + reactNativeProjectConfigDependencies = memoizer.withMemoizer(async () => { + return await scanDependenciesFromRNProjectConfig( + await getAppRoot(), + await this.loadReactNativeProjectConfig() + ); + }); + } + return reactNativeProjectConfigDependencies; }, async scanDependenciesRecursively() { - return ( - recursiveDependencies || - (recursiveDependencies = scanDependenciesRecursively(await getAppRoot())) - ); + if (recursiveDependencies === undefined) { + recursiveDependencies = memoizer.withMemoizer(async () => { + return scanDependenciesRecursively(await getAppRoot()); + }); + } + return recursiveDependencies; }, async scanDependenciesInSearchPath(searchPath: string) { let result = dependenciesResultBySearchPath.get(searchPath); if (!result) { dependenciesResultBySearchPath.set( searchPath, - (result = scanDependenciesInSearchPath(searchPath)) + (result = memoizer.withMemoizer(scanDependenciesInSearchPath, searchPath)) ); } return result; @@ -100,36 +109,38 @@ export async function scanDependencyResolutionsForPlatform( ]) ); - const dependencies = await filterMapResolutionResult(resolutions, async (resolution) => { - if (excludeNames.has(resolution.name)) { - return null; - } else if (includeNames.has(resolution.name)) { - return resolution; - } else if (resolution.source === DependencyResolutionSource.RN_CLI_LOCAL) { - // If the dependency was resolved frpom the React Native project config, we'll only - // attempt to resolve it as a React Native module - const reactNativeModuleDesc = await resolveReactNativeModule( - resolution, - reactNativeProjectConfig, - platform, - excludeNames - ); - if (!reactNativeModuleDesc) { - return null; - } - } else { - const [reactNativeModule, expoModule] = await Promise.all([ - resolveReactNativeModule(resolution, reactNativeProjectConfig, platform, excludeNames), - resolveExpoModule(resolution, platform, excludeNames), - ]); - if (!reactNativeModule && !expoModule) { + return await linker.memoizer.withMemoizer(async () => { + const dependencies = await filterMapResolutionResult(resolutions, async (resolution) => { + if (excludeNames.has(resolution.name)) { return null; + } else if (includeNames.has(resolution.name)) { + return resolution; + } else if (resolution.source === DependencyResolutionSource.RN_CLI_LOCAL) { + // If the dependency was resolved frpom the React Native project config, we'll only + // attempt to resolve it as a React Native module + const reactNativeModuleDesc = await resolveReactNativeModule( + resolution, + reactNativeProjectConfig, + platform, + excludeNames + ); + if (!reactNativeModuleDesc) { + return null; + } + } else { + const [reactNativeModule, expoModule] = await Promise.all([ + resolveReactNativeModule(resolution, reactNativeProjectConfig, platform, excludeNames), + resolveExpoModule(resolution, platform, excludeNames), + ]); + if (!reactNativeModule && !expoModule) { + return null; + } } - } - return resolution; - }); + return resolution; + }); - return dependencies; + return dependencies; + }); } export async function scanExpoModuleResolutionsForPlatform( @@ -147,10 +158,12 @@ export async function scanExpoModuleResolutionsForPlatform( ].filter((x) => x != null) ) ); - return await filterMapResolutionResult(resolutions, async (resolution) => { - return !excludeNames.has(resolution.name) - ? await resolveExpoModule(resolution, platform, excludeNames) - : null; + return await linker.memoizer.withMemoizer(async () => { + return await filterMapResolutionResult(resolutions, async (resolution) => { + return !excludeNames.has(resolution.name) + ? await resolveExpoModule(resolution, platform, excludeNames) + : null; + }); }); } diff --git a/packages/expo-modules-autolinking/src/dependencies/__tests__/resolution-test.ts b/packages/expo-modules-autolinking/src/dependencies/__tests__/resolution-test.ts index 9e5381112d117c..f4397e34d9acd0 100644 --- a/packages/expo-modules-autolinking/src/dependencies/__tests__/resolution-test.ts +++ b/packages/expo-modules-autolinking/src/dependencies/__tests__/resolution-test.ts @@ -2,6 +2,7 @@ import { vol } from 'memfs'; import type { NestedDirectoryJSON } from 'memfs/lib/volume'; import path from 'path'; +import { createMemoizer, _verifyMemoizerFreed } from '../../memoize'; import { scanDependenciesRecursively } from '../resolution'; function mockedNodeModule( @@ -33,12 +34,19 @@ const symlinkMany = (symlinks: Record) => { const projectRoot = '/fake/project'; +const itWithMemoize = (name: string, fn: () => Promise) => { + return it(name, async () => { + await createMemoizer().withMemoizer(fn); + expect(_verifyMemoizerFreed()).toBe(true); + }); +}; + describe(scanDependenciesRecursively, () => { afterEach(() => { vol.reset(); }); - it('discovers flat dependencies', async () => { + itWithMemoize('discovers flat dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -68,7 +76,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers transitive dependencies', async () => { + itWithMemoize('discovers transitive dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -116,7 +124,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers transitive, hoisted dependencies', async () => { + itWithMemoize('discovers transitive, hoisted dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -158,7 +166,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers transitive, isolated dependencies', async () => { + itWithMemoize('discovers transitive, isolated dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -213,7 +221,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers dependencies on nameless package.json', async () => { + itWithMemoize('discovers dependencies on nameless package.json', async () => { vol.fromNestedJSON( { 'package.json': JSON.stringify({ @@ -246,7 +254,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('ignores transitive, hoisted dependencies without dependents', async () => { + itWithMemoize('ignores transitive, hoisted dependencies without dependents', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -277,7 +285,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('ignores dependency names from filter', async () => { + itWithMemoize('ignores dependency names from filter', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -310,7 +318,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers transitive, duplicate dependencies', async () => { + itWithMemoize('discovers transitive, duplicate dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -380,7 +388,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('allows depth to be limited', async () => { + itWithMemoize('allows depth to be limited', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -419,7 +427,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('discovers transitive peer dependencies', async () => { + itWithMemoize('discovers transitive peer dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -467,7 +475,7 @@ describe(scanDependenciesRecursively, () => { `); }); - it('ignores transitive optional peer dependencies', async () => { + itWithMemoize('ignores transitive optional peer dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { diff --git a/packages/expo-modules-autolinking/src/dependencies/__tests__/scanning-test.ts b/packages/expo-modules-autolinking/src/dependencies/__tests__/scanning-test.ts index 5963a45f177993..e65ec23017a4aa 100644 --- a/packages/expo-modules-autolinking/src/dependencies/__tests__/scanning-test.ts +++ b/packages/expo-modules-autolinking/src/dependencies/__tests__/scanning-test.ts @@ -2,6 +2,7 @@ import { vol } from 'memfs'; import type { NestedDirectoryJSON } from 'memfs/lib/volume'; import path from 'path'; +import { createMemoizer, _verifyMemoizerFreed } from '../../memoize'; import { scanDependenciesInSearchPath } from '../scanning'; function mockedNodeModule( @@ -30,12 +31,19 @@ const symlinkMany = (symlinks: Record) => { const projectRoot = '/fake/project'; const projectRootNodeModules = '/fake/project/node_modules'; +const itWithMemoize = (name: string, fn: () => Promise) => { + return it(name, async () => { + await createMemoizer().withMemoizer(fn); + expect(_verifyMemoizerFreed()).toBe(true); + }); +}; + describe(scanDependenciesInSearchPath, () => { afterEach(() => { vol.reset(); }); - it('discovers unscoped and scoped dependencies', async () => { + itWithMemoize('discovers unscoped and scoped dependencies', async () => { vol.fromNestedJSON( { node_modules: { @@ -72,7 +80,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('discovers symlinked dependencies', async () => { + itWithMemoize('discovers symlinked dependencies', async () => { vol.fromNestedJSON( { 'react-native-third-party': mockedNodeModule('react-native-third-party'), @@ -104,7 +112,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('discovers transitive, isolated dependencies', async () => { + itWithMemoize('discovers transitive, isolated dependencies', async () => { vol.fromNestedJSON( { ...mockedNodeModule('root', { @@ -143,7 +151,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('resolves conflicts as duplicates', async () => { + itWithMemoize('resolves conflicts as duplicates', async () => { vol.fromNestedJSON( { node_modules: { @@ -178,7 +186,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('ignores missing package.json files on dependencies', async () => { + itWithMemoize('ignores missing package.json files on dependencies', async () => { vol.fromNestedJSON( { node_modules: { @@ -215,7 +223,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('ignores files', async () => { + itWithMemoize('ignores files', async () => { vol.fromNestedJSON( { node_modules: { @@ -230,7 +238,7 @@ describe(scanDependenciesInSearchPath, () => { expect(result).toEqual({}); }); - it('ignores dependency names from filter', async () => { + itWithMemoize('ignores dependency names from filter', async () => { vol.fromNestedJSON( { node_modules: { @@ -260,7 +268,7 @@ describe(scanDependenciesInSearchPath, () => { `); }); - it('supports direct path to node module', async () => { + itWithMemoize('supports direct path to node module', async () => { vol.fromNestedJSON( { node_modules: { diff --git a/packages/expo-modules-autolinking/src/dependencies/resolution.ts b/packages/expo-modules-autolinking/src/dependencies/resolution.ts index 323b4193ec0992..7391b9cd68246e 100644 --- a/packages/expo-modules-autolinking/src/dependencies/resolution.ts +++ b/packages/expo-modules-autolinking/src/dependencies/resolution.ts @@ -5,14 +5,8 @@ import { type DependencyResolution, DependencyResolutionSource, } from './types'; -import { - type PackageJson, - defaultShouldIncludeDependency, - mergeResolutionResults, - loadPackageJson, - maybeRealpath, - fastJoin, -} from './utils'; +import { defaultShouldIncludeDependency, mergeResolutionResults } from './utils'; +import { type PackageJson, loadPackageJson, maybeRealpath, fastJoin } from '../utils'; declare module 'node:module' { export function _nodeModulePaths(base: string): readonly string[]; diff --git a/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts b/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts index 49c4297ee8f5ec..ff0dd7f58daf7d 100644 --- a/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts +++ b/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts @@ -1,8 +1,9 @@ import path from 'path'; import { DependencyResolutionSource, type ResolutionResult } from './types'; -import { defaultShouldIncludeDependency, maybeRealpath } from './utils'; +import { defaultShouldIncludeDependency } from './utils'; import { RNConfigReactNativeProjectConfig } from '../reactNativeConfig'; +import { maybeRealpath } from '../utils'; interface ResolutionOptions { shouldIncludeDependency?(name: string): boolean; diff --git a/packages/expo-modules-autolinking/src/dependencies/scanning.ts b/packages/expo-modules-autolinking/src/dependencies/scanning.ts index 264e3ca81c7b1e..9a8b9f914feae5 100644 --- a/packages/expo-modules-autolinking/src/dependencies/scanning.ts +++ b/packages/expo-modules-autolinking/src/dependencies/scanning.ts @@ -5,7 +5,8 @@ import { type DependencyResolution, DependencyResolutionSource, } from './types'; -import { defaultShouldIncludeDependency, loadPackageJson, maybeRealpath, fastJoin } from './utils'; +import { defaultShouldIncludeDependency } from './utils'; +import { loadPackageJson, maybeRealpath, fastJoin } from '../utils'; async function resolveDependency( basePath: string, @@ -21,7 +22,7 @@ async function resolveDependency( if (packageJson) { return { source: DependencyResolutionSource.SEARCH_PATH, - name: packageJson.name, + name: packageJson.name || '', version: packageJson.version || '', path: realPath || originPath, originPath, diff --git a/packages/expo-modules-autolinking/src/dependencies/utils.ts b/packages/expo-modules-autolinking/src/dependencies/utils.ts index a173d24d40f289..ca32ed61f6fb68 100644 --- a/packages/expo-modules-autolinking/src/dependencies/utils.ts +++ b/packages/expo-modules-autolinking/src/dependencies/utils.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; -import { memoize } from '../utils'; +import { memoize } from '../memoize'; import { DependencyResolutionSource, type DependencyResolution, @@ -51,37 +51,6 @@ export function defaultShouldIncludeDependency(dependencyName: string): boolean } } -export const fastJoin: (from: string, append: string) => string = - path.sep === '/' - ? (from, append) => `${from}${path.sep}${append}` - : (from, append) => - `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`; - -export const maybeRealpath = async (target: string): Promise => { - try { - return await fs.promises.realpath(target); - } catch { - return null; - } -}; - -export type PackageJson = Record & { version?: string }; - -export const loadPackageJson = memoize(async function loadPackageJson( - jsonPath: string -): Promise { - try { - const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8'); - const json = JSON.parse(packageJsonText); - if (typeof json !== 'object' || json == null) { - return null; - } - return json; - } catch { - return null; - } -}); - export function mergeWithDuplicate( a: DependencyResolution, b: DependencyResolution diff --git a/packages/expo-modules-autolinking/src/index.ts b/packages/expo-modules-autolinking/src/index.ts index c6790b8b658b1c..3359f3b5bc7aac 100644 --- a/packages/expo-modules-autolinking/src/index.ts +++ b/packages/expo-modules-autolinking/src/index.ts @@ -5,6 +5,7 @@ import { reactNativeConfigCommand } from './commands/reactNativeConfigCommand'; import { resolveCommand } from './commands/resolveCommand'; import { searchCommand } from './commands/searchCommand'; import { verifyCommand } from './commands/verifyCommand'; +import { createMemoizer } from './memoize'; async function main(args: string[]) { const cli = commander @@ -17,7 +18,9 @@ async function main(args: string[]) { generateModulesProviderCommand(cli); reactNativeConfigCommand(cli); - await cli.parseAsync(args, { from: 'user' }); + await createMemoizer().withMemoizer(async () => { + await cli.parseAsync(args, { from: 'user' }); + }); } module.exports = main; diff --git a/packages/expo-modules-autolinking/src/memoize.ts b/packages/expo-modules-autolinking/src/memoize.ts new file mode 100644 index 00000000000000..0f4767a9808be8 --- /dev/null +++ b/packages/expo-modules-autolinking/src/memoize.ts @@ -0,0 +1,104 @@ +// expo-modules-autolinking has a few memoizable operations that we don't want to repeat. +// However, memoizing them naively means that we may hold on to the cached values for too long. +// Instead, we wrap all calls with a `Memoizer`. +// +// This could use AsyncLocalStorage, but those are expensive. Instead, we only share one +// cache for all calls, and assume that all memoizable return values may be memoized and +// shared globally. +// +// Memoizers are created once per run, and then shared between all subsequent calls. They +// are freed when their usage count to zero, after one tick. +// +// NOTE: If you need to debug whether the memoizer is properly used, change when the +// `console.warn` appears to see if you have any uncached calls. We allow uncached calls +// for backwards-compatibility, since, at worst, we have an uncached call, if the +// Memoizer is missing. + +const MAX_SIZE = 5_000; + +export interface Memoizer { + /** Calls a function with a memoizer cache, caching its return value */ + call>( + fn: Fn, + input: string, + ...args: Args + ): Promise; + + /** Invokes an async context with a memoizer cache */ + withMemoizer(callback: () => R): R; + withMemoizer(callback: (...args: TArgs) => R, ...args: TArgs): R; +} + +export interface MemoizableAsyncFn { + (input: string, ...args: Args): Promise; +} + +let currentMemoizer: Memoizer | undefined; +let currentContexts = 0; + +/** Wraps a function in a memoizer, using the memoizer async local storage */ +export function memoize>( + fn: Fn +): MemoizableAsyncFn { + return (input: string, ...args: Args) => { + // We either use the current memoizer (sync) or the memoize context (async) + if (!currentMemoizer) { + if (process.env.NODE_ENV === 'test') { + console.warn( + `expo-modules-autolinking: Memoized function called without memoize context (${fn.name})\n` + + new Error().stack + ); + } + return fn(input, ...args); + } + return currentMemoizer.call(fn, input, ...args); + }; +} + +/** Creates a memoizer that can provide a cache to memoized functions */ +export function createMemoizer(): Memoizer { + // If we already have a memoizer, reuse it, since we can share them globally + if (currentMemoizer) { + return currentMemoizer; + } + + const cacheByFn = new Map>(); + const memoizer: Memoizer = { + async call(fn, input, ...args) { + let cache = cacheByFn.get(fn); + if (!cache) { + cache = new Map(); + cacheByFn.set(fn, cache); + } + if (!cache.has(input)) { + const value = await memoizer.withMemoizer(fn, input, ...args); + if (cache.size > MAX_SIZE) { + cache.clear(); + } + cache.set(input, value); + return value; + } + return cache.get(input); + }, + async withMemoizer(fn: (...args: TArgs) => R, ...args: TArgs) { + currentMemoizer = memoizer; + currentContexts++; + try { + return await fn(...args); + } finally { + if (currentContexts > 0) { + currentContexts--; + } + if (currentContexts === 0) { + currentMemoizer = undefined; + } + } + }, + }; + return memoizer; +} + +/** @internal Used in tests to verify the memoizer was freed */ +export function _verifyMemoizerFreed() { + return currentMemoizer === undefined && currentContexts === 0; +} diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/androidResolver-test.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/androidResolver-test.ts index 378d15d7b0cca8..1fdf240321c211 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/androidResolver-test.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/androidResolver-test.ts @@ -1,5 +1,6 @@ import { vol } from 'memfs'; +import { createMemoizer, _verifyMemoizerFreed } from '../../memoize'; import { matchNativePackageClassName, parseComponentDescriptorsAsync, @@ -11,13 +12,20 @@ import { jest.mock('fs/promises'); +const itWithMemoize = (name: string, fn: () => Promise) => { + return it(name, async () => { + await createMemoizer().withMemoizer(fn); + expect(_verifyMemoizerFreed()).toBe(true); + }); +}; + describe(resolveDependencyConfigImplAndroidAsync, () => { afterEach(() => { jest.resetAllMocks(); vol.reset(); }); - it('should return android config if all native files found', async () => { + itWithMemoize('should return android config if all native files found', async () => { vol.fromJSON({ '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), '/app/node_modules/react-native-test/android/build.gradle': ` @@ -59,10 +67,12 @@ public class TestPackage implements ReactPackage { `); }); - it('should return android config if gradle found but not AndroidManifest.xml', async () => { - vol.fromJSON({ - '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), - '/app/node_modules/react-native-test/android/build.gradle': ` + itWithMemoize( + 'should return android config if gradle found but not AndroidManifest.xml', + async () => { + vol.fromJSON({ + '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), + '/app/node_modules/react-native-test/android/build.gradle': ` android { namespace "com.test" defaultConfig { @@ -70,7 +80,7 @@ android { } } `, - '/app/node_modules/react-native-test/android/src/main/com/test/TestPackage.java': `\ + '/app/node_modules/react-native-test/android/src/main/com/test/TestPackage.java': `\ package com.test; import com.facebook.react.ReactPackage; @@ -78,30 +88,33 @@ import com.facebook.react.ReactPackage; public class TestPackage implements ReactPackage { } `, - }); - const result = await resolveDependencyConfigImplAndroidAsync( - '/app/node_modules/react-native-test', - undefined - ); - expect(result).not.toBeNull(); - }); - - it('should return C++-only config without AndroidManifest.xml and gradle file', async () => { - vol.fromJSON({ - '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), - '/app/node_modules/react-native-test/android/build.gradle': '', - '/app/node_modules/react-native-test/android/src/main/AndroidManifest.xml': '', - }); - const result = await resolveDependencyConfigImplAndroidAsync( - '/app/node_modules/react-native-test', - { - cxxModuleCMakeListsModuleName: 'TestMod', - cxxModuleCMakeListsPath: 'CMakeLists.txt', - cxxModuleHeaderName: 'TestModSpec', - sourceDir: 'cpp', - } - ); - expect(result).toMatchInlineSnapshot(` + }); + const result = await resolveDependencyConfigImplAndroidAsync( + '/app/node_modules/react-native-test', + undefined + ); + expect(result).not.toBeNull(); + } + ); + + itWithMemoize( + 'should return C++-only config without AndroidManifest.xml and gradle file', + async () => { + vol.fromJSON({ + '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), + '/app/node_modules/react-native-test/android/build.gradle': '', + '/app/node_modules/react-native-test/android/src/main/AndroidManifest.xml': '', + }); + const result = await resolveDependencyConfigImplAndroidAsync( + '/app/node_modules/react-native-test', + { + cxxModuleCMakeListsModuleName: 'TestMod', + cxxModuleCMakeListsPath: 'CMakeLists.txt', + cxxModuleHeaderName: 'TestModSpec', + sourceDir: 'cpp', + } + ); + expect(result).toMatchInlineSnapshot(` { "buildTypes": [], "cmakeListsPath": "/app/node_modules/react-native-test/cpp/build/generated/source/codegen/jni/CMakeLists.txt", @@ -115,23 +128,27 @@ public class TestPackage implements ReactPackage { "sourceDir": "/app/node_modules/react-native-test/cpp", } `); - }); - - it('should not misdetect an Expo module as a C++-only React Native module', async () => { - vol.fromJSON({ - '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), - '/app/node_modules/react-native-test/android/build.gradle': '', - '/app/node_modules/react-native-test/android/src/main/AndroidManifest.xml': '', - '/app/node_modules/react-native-test/expo-module.config.json': '{}', - }); - const result = await resolveDependencyConfigImplAndroidAsync( - '/app/node_modules/react-native-test', - undefined - ); - expect(result).toBe(null); - }); + } + ); + + itWithMemoize( + 'should not misdetect an Expo module as a C++-only React Native module', + async () => { + vol.fromJSON({ + '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), + '/app/node_modules/react-native-test/android/build.gradle': '', + '/app/node_modules/react-native-test/android/src/main/AndroidManifest.xml': '', + '/app/node_modules/react-native-test/expo-module.config.json': '{}', + }); + const result = await resolveDependencyConfigImplAndroidAsync( + '/app/node_modules/react-native-test', + undefined + ); + expect(result).toBe(null); + } + ); - it('should return android config from custom sourceDir', async () => { + itWithMemoize('should return android config from custom sourceDir', async () => { vol.fromJSON({ '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), '/app/node_modules/react-native-test/custom/android/build.gradle': ` @@ -160,7 +177,7 @@ public class TestPackage implements ReactPackage { expect(result?.sourceDir).toBe('/app/node_modules/react-native-test/custom/android'); }); - it('should return null if gradle found but without namespace', async () => { + itWithMemoize('should return null if gradle found but without namespace', async () => { vol.fromJSON({ '/app/node_modules/react-native-test/package.json': JSON.stringify({ version: '1.0.0' }), '/app/node_modules/react-native-test/android/build.gradle': ` @@ -186,7 +203,7 @@ public class TestPackage implements ReactPackage { expect(result).toBeNull(); }); - it('should return null if reactNativeConfig is null', async () => { + itWithMemoize('should return null if reactNativeConfig is null', async () => { const result = await resolveDependencyConfigImplAndroidAsync( '/app/node_modules/react-native-test', null @@ -194,7 +211,7 @@ public class TestPackage implements ReactPackage { expect(result).toBeNull(); }); - it('should return null if no gradle and AndroidManifest found', async () => { + itWithMemoize('should return null if no gradle and AndroidManifest found', async () => { const result = await resolveDependencyConfigImplAndroidAsync( '/app/node_modules/react-native-test', undefined @@ -208,7 +225,7 @@ describe(parsePackageNameAsync, () => { vol.reset(); }); - it('should parse package name from build.gradle', async () => { + itWithMemoize('should parse package name from build.gradle', async () => { vol.fromJSON({ '/app/node_modules/test/src/main/AndroidManifest.xml': '', '/app/node_modules/test/build.gradle': `\ @@ -227,7 +244,7 @@ android { expect(result).toEqual('com.test'); }); - it('should parse package name from AndroidManifest.xml', async () => { + itWithMemoize('should parse package name from AndroidManifest.xml', async () => { vol.fromJSON({ '/app/node_modules/test/src/main/AndroidManifest.xml': `\ @@ -248,7 +265,7 @@ describe(parseNativePackageClassNameAsync, () => { vol.reset(); }); - it('should parse component descriptors from java file', async () => { + itWithMemoize('should parse component descriptors from java file', async () => { vol.fromJSON({ '/app/node_modules/test/android/src/main/com/test/TestPackage.java': `\ package com.test; @@ -267,7 +284,7 @@ public class TestPackage implements ReactPackage { expect(result).toEqual('TestPackage'); }); - it('should parse component descriptors from kotlin file', async () => { + itWithMemoize('should parse component descriptors from kotlin file', async () => { vol.fromJSON({ '/app/node_modules/test/android/src/main/com/test/TestPackage.kt': `\ package com.test @@ -292,7 +309,7 @@ describe(parseLibraryNameAsync, () => { vol.reset(); }); - it('should parse library name from package.json', async () => { + itWithMemoize('should parse library name from package.json', async () => { const result = await parseLibraryNameAsync('/app/node_modules/test', { codegenConfig: { name: 'test', @@ -301,7 +318,7 @@ describe(parseLibraryNameAsync, () => { expect(result).toBe('test'); }); - it('should parse library name from build.gradle', async () => { + itWithMemoize('should parse library name from build.gradle', async () => { vol.fromJSON({ '/app/node_modules/test/build.gradle': `\ ext { @@ -313,7 +330,7 @@ ext { expect(result).toBe('test'); }); - it('should parse library name from build.gradle.kts', async () => { + itWithMemoize('should parse library name from build.gradle.kts', async () => { vol.fromJSON({ '/app/node_modules/test/build.gradle.kts': `\ ext { @@ -332,7 +349,7 @@ describe(parseComponentDescriptorsAsync, () => { vol.reset(); }); - it('should parse component descriptors', async () => { + itWithMemoize('should parse component descriptors', async () => { vol.fromJSON({ // not matched: no `codegenNativeComponent` pattern '/app/node_modules/test/Test.ts': `export default {};`, diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/config-test.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/config-test.ts index 363f1e793ac76d..f41f8741c38700 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/config-test.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/config-test.ts @@ -1,18 +1,26 @@ import { vol } from 'memfs'; import path from 'path'; +import { createMemoizer, _verifyMemoizerFreed } from '../../memoize'; import { loadConfigAsync } from '../config'; jest.mock('fs/promises'); const EXPO_MONOREPO_ROOT = path.resolve(__dirname, '../../../../..'); -describe(loadConfigAsync, () => { +const itWithMemoize = (name: string, fn: () => Promise) => { + return it(name, async () => { + await createMemoizer().withMemoizer(fn); + expect(_verifyMemoizerFreed()).toBe(true); + }); +}; + +describe('loadConfigAsync', () => { afterEach(() => { vol.reset(); }); - it('should load react-native.config.js', async () => { + itWithMemoize('should load react-native.config.js', async () => { await jest.isolateModulesAsync(async () => { vol.fromJSON({ '/app/react-native.config.js': 'module.exports = { version: "1.0.0" };', @@ -22,7 +30,7 @@ describe(loadConfigAsync, () => { }); }); - it('should load react-native.config.ts', async () => { + itWithMemoize('should load react-native.config.ts', async () => { await jest.isolateModulesAsync(async () => { vol.fromJSON({ '/app/react-native.config.ts': 'export default { version: "1.0.0" };', @@ -32,7 +40,7 @@ describe(loadConfigAsync, () => { }); }); - it('should load react-native.config.ts with cjs exports', async () => { + itWithMemoize('should load react-native.config.ts with cjs exports', async () => { await jest.isolateModulesAsync(async () => { vol.fromJSON({ '/app/react-native.config.ts': 'module.exports = { version: "1.0.0" };', diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/reactNativeConfig-test.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/reactNativeConfig-test.ts index e0f5f38fd74786..3968316a89cc52 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/reactNativeConfig-test.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/__tests__/reactNativeConfig-test.ts @@ -1,6 +1,7 @@ import { vol } from 'memfs'; import { AutolinkingOptions } from '../../commands/autolinkingOptions'; +import { createMemoizer, _verifyMemoizerFreed } from '../../memoize'; import { findGradleAndManifestAsync, parsePackageNameAsync } from '../androidResolver'; import { loadConfigAsync } from '../config'; import { resolveDependencyConfigImplIosAsync } from '../iosResolver'; @@ -31,6 +32,13 @@ const BASE_AUTOLINKING_OPTIONS: AutolinkingOptions = { exclude: [], }; +const itWithMemoize = (name: string, fn: () => Promise) => { + return it(name, async () => { + await createMemoizer().withMemoizer(fn); + expect(_verifyMemoizerFreed()).toBe(true); + }); +}; + describe(createReactNativeConfigAsync, () => { const mockPlatformResolverIos = resolveDependencyConfigImplIosAsync as jest.MockedFunction< typeof resolveDependencyConfigImplIosAsync @@ -40,7 +48,7 @@ describe(createReactNativeConfigAsync, () => { vol.reset(); }); - it('should return config', async () => { + itWithMemoize('should return config', async () => { const packageJson = { name: 'test', version: '1.0.0', @@ -120,7 +128,7 @@ describe(createReactNativeConfigAsync, () => { `); }); - it('should return config with local dependencies', async () => { + itWithMemoize('should return config with local dependencies', async () => { const packageJson = { name: 'test', version: '1.0.0', @@ -171,7 +179,7 @@ describe(createReactNativeConfigAsync, () => { expect(result.dependencies['react-native-test'].root).toBe('/app/modules/react-native-test'); }); - it('should return config if local dependencies are not specified', async () => { + itWithMemoize('should return config if local dependencies are not specified', async () => { const packageJson = { name: 'test', version: '1.0.0', @@ -203,7 +211,7 @@ describe(createReactNativeConfigAsync, () => { }); describe(resolveAppProjectConfigAsync, () => { - it('should return app project config for android', async () => { + itWithMemoize('should return app project config for android', async () => { const androidResolver = require('../androidResolver'); const mockFindGradleAndManifestAsync = jest.spyOn( androidResolver, @@ -231,7 +239,7 @@ describe(resolveAppProjectConfigAsync, () => { `); }); - it('should return app project config for android with custom sourceDir', async () => { + itWithMemoize('should return app project config for android with custom sourceDir', async () => { vol.fromJSON({ '/brownfield/app/src/main/AndroidManifest.xml': `\ @@ -254,26 +262,29 @@ describe(resolveAppProjectConfigAsync, () => { `); }); - it('should return empty project config for android if no gradle files or manifest files', async () => { - const androidResolver = require('../androidResolver'); - const mockFindGradleAndManifestAsync = jest.spyOn( - androidResolver, - 'findGradleAndManifestAsync' - ) as jest.MockedFunction; - mockFindGradleAndManifestAsync.mockResolvedValueOnce({ - gradle: null, - manifest: null, - }); - const mockParsePackageNameAsync = jest.spyOn( - androidResolver, - 'parsePackageNameAsync' - ) as jest.MockedFunction; - mockParsePackageNameAsync.mockResolvedValueOnce('com.test'); - const config = await resolveAppProjectConfigAsync('/app', 'android'); - expect(config).toEqual({}); - }); + itWithMemoize( + 'should return empty project config for android if no gradle files or manifest files', + async () => { + const androidResolver = require('../androidResolver'); + const mockFindGradleAndManifestAsync = jest.spyOn( + androidResolver, + 'findGradleAndManifestAsync' + ) as jest.MockedFunction; + mockFindGradleAndManifestAsync.mockResolvedValueOnce({ + gradle: null, + manifest: null, + }); + const mockParsePackageNameAsync = jest.spyOn( + androidResolver, + 'parsePackageNameAsync' + ) as jest.MockedFunction; + mockParsePackageNameAsync.mockResolvedValueOnce('com.test'); + const config = await resolveAppProjectConfigAsync('/app', 'android'); + expect(config).toEqual({}); + } + ); - it('should return app project config for ios', async () => { + itWithMemoize('should return app project config for ios', async () => { const config = await resolveAppProjectConfigAsync('/app', 'ios'); expect(config).toMatchInlineSnapshot(` { @@ -284,7 +295,7 @@ describe(resolveAppProjectConfigAsync, () => { `); }); - it('should return app project config with custom sourceDir', async () => { + itWithMemoize('should return app project config with custom sourceDir', async () => { const androidResolver = require('../androidResolver'); const mockFindGradleAndManifestAsync = jest.spyOn( androidResolver, @@ -328,7 +339,7 @@ describe(resolveReactNativeModule, () => { typeof resolveDependencyConfigImplIosAsync >; - it('should return config with platform config', async () => { + itWithMemoize('should return config with platform config', async () => { mockPlatformResolverIos.mockResolvedValueOnce({ podspecPath: '/app/node_modules/react-native-test/RNTest.podspec', version: '1.0.0', @@ -365,7 +376,7 @@ describe(resolveReactNativeModule, () => { `); }); - it('should call the platform resolver', async () => { + itWithMemoize('should call the platform resolver', async () => { await resolveReactNativeModule( { name: 'react-native-test', @@ -386,7 +397,7 @@ describe(resolveReactNativeModule, () => { ); }); - it('should call platform resolver with config from library', async () => { + itWithMemoize('should call platform resolver with config from library', async () => { const libraryConfig: RNConfigReactNativeLibraryConfig = { dependency: { platforms: { @@ -422,63 +433,69 @@ describe(resolveReactNativeModule, () => { ); }); - it('should call platform resolver with merged config and project config will override library config', async () => { - const projectConfig: RNConfigReactNativeProjectConfig = { - dependencies: { - 'react-native-test': { - platforms: { - ios: null, + itWithMemoize( + 'should call platform resolver with merged config and project config will override library config', + async () => { + const projectConfig: RNConfigReactNativeProjectConfig = { + dependencies: { + 'react-native-test': { + platforms: { + ios: null, + }, }, }, - }, - }; - const libraryConfig: RNConfigReactNativeLibraryConfig = { - dependency: { - platforms: { - ios: { - configurations: ['Debug'], - scriptPhases: [{ name: 'test', path: './test.js' }], + }; + const libraryConfig: RNConfigReactNativeLibraryConfig = { + dependency: { + platforms: { + ios: { + configurations: ['Debug'], + scriptPhases: [{ name: 'test', path: './test.js' }], + }, }, }, - }, - }; - mockLoadReactNativeConfigAsync.mockResolvedValueOnce(libraryConfig); + }; + mockLoadReactNativeConfigAsync.mockResolvedValueOnce(libraryConfig); - await resolveReactNativeModule( - { - name: 'react-native-test', - version: '', - path: '/app/node_modules/react-native-test', - originPath: '/app/node_modules/react-native-test', - duplicates: null, - depth: 0, - }, - projectConfig, - 'ios', - new Set() - ); + await resolveReactNativeModule( + { + name: 'react-native-test', + version: '', + path: '/app/node_modules/react-native-test', + originPath: '/app/node_modules/react-native-test', + duplicates: null, + depth: 0, + }, + projectConfig, + 'ios', + new Set() + ); - expect(mockPlatformResolverIos).toHaveBeenCalledWith( - expect.objectContaining({ path: '/app/node_modules/react-native-test' }), - null, - undefined - ); - }); + expect(mockPlatformResolverIos).toHaveBeenCalledWith( + expect.objectContaining({ path: '/app/node_modules/react-native-test' }), + null, + undefined + ); + } + ); - it(`should return null for the react-native because it's a platform package`, async () => { - const result = await resolveReactNativeModule( - { - name: 'react-native', - version: '', - path: '/app/node_modules/react-native', - originPath: '/app/node_modules/react-native', - duplicates: null, - depth: 0, - }, - null, - 'ios', - new Set() - ); - expect(result).toBe(null); - }); + itWithMemoize( + `should return null for the react-native because it's a platform package`, + async () => { + const result = await resolveReactNativeModule( + { + name: 'react-native', + version: '', + path: '/app/node_modules/react-native', + originPath: '/app/node_modules/react-native', + duplicates: null, + depth: 0, + }, + null, + 'ios', + new Set() + ); + expect(result).toBe(null); + } + ); }); diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts index c4dbdcc7d284bc..57b7da3e75a970 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts @@ -6,7 +6,7 @@ import type { RNConfigReactNativePlatformsConfigAndroid, } from './reactNativeConfig.types'; import type { ExpoModuleConfig } from '../ExpoModuleConfig'; -import { scanFilesRecursively, fileExistsAsync } from '../utils'; +import { scanFilesRecursively, fileExistsAsync, fastJoin, loadPackageJson } from '../utils'; export async function resolveDependencyConfigImplAndroidAsync( packageRoot: string, @@ -61,7 +61,7 @@ export async function resolveDependencyConfigImplAndroidAsync( packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`; } - const packageJson = JSON.parse(await fs.readFile(path.join(packageRoot, 'package.json'), 'utf8')); + const packageJson = await loadPackageJson(fastJoin(packageRoot, 'package.json')); const buildTypes = reactNativeConfig?.buildTypes || []; const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration; const libraryName = @@ -243,7 +243,7 @@ export async function parseComponentDescriptorsAsync( const results = new Set(); for await (const entry of scanFilesRecursively(jsRoot)) { if (extRe.test(entry.name)) { - const contents = await fs.readFile(entry.path); + const contents = await fs.readFile(entry.path, 'utf8'); const matched = matchComponentDescriptors(entry.path, contents); if (matched) { results.add(matched); @@ -254,14 +254,12 @@ export async function parseComponentDescriptorsAsync( } let lazyCodegenComponentRegex: RegExp | null = null; -function matchComponentDescriptors(_filePath: string, contents: Buffer): string | null { - const fileContents = contents.toString(); - +function matchComponentDescriptors(_filePath: string, contents: string): string | null { if (!lazyCodegenComponentRegex) { lazyCodegenComponentRegex = /codegenNativeComponent(<.*>)?\s*\(\s*["'`](\w+)["'`](,?[\s\S]+interfaceOnly:\s*(\w+))?/m; } - const match = fileContents.match(lazyCodegenComponentRegex); + const match = contents.match(lazyCodegenComponentRegex); if (!(match?.[4] === 'true') && match?.[2]) { return `${match[2]}ComponentDescriptor`; } diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/config.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/config.ts index ee50318c0bbddb..cdb221edeb93f6 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/config.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/config.ts @@ -2,15 +2,23 @@ import { evalModule } from '@expo/require-utils'; import fs from 'fs/promises'; import path from 'path'; -import { memoize, fileExistsAsync } from '../utils'; -import type { RNConfigReactNativeConfig } from './reactNativeConfig.types'; +import { memoize } from '../memoize'; +import { fileExistsAsync } from '../utils'; +import type { + RNConfigReactNativeConfig, + RNConfigReactNativeProjectConfig, +} from './reactNativeConfig.types'; const mockedNativeModules = path.join(__dirname, '..', '..', 'node_modules_mock'); +type LoadConfigAsync = ( + packageRoot: string +) => Promise; + /** * Load the `react-native.config.js` or `react-native.config.ts` from the package. */ -export const loadConfigAsync = memoize(async function loadConfigAsync< +export const loadConfigAsync: LoadConfigAsync = memoize(async function loadConfigAsync< T extends RNConfigReactNativeConfig, >(packageRoot: string): Promise { const configPath = ( diff --git a/packages/expo-modules-autolinking/src/utils.ts b/packages/expo-modules-autolinking/src/utils.ts index 8767915fb076f2..c9b63996a2f679 100644 --- a/packages/expo-modules-autolinking/src/utils.ts +++ b/packages/expo-modules-autolinking/src/utils.ts @@ -1,23 +1,7 @@ import fs from 'fs'; import path from 'path'; -const MAX_SIZE = 5_000; - -export function memoize Promise>(fn: Fn) { - const cache = new Map>(); - return async (input: string, ...args: any[]) => { - if (!cache.has(input)) { - const result = await fn(input, ...args); - if (cache.size > MAX_SIZE) { - cache.clear(); - } - cache.set(input, result); - return result; - } else { - return cache.get(input); - } - }; -} +import { memoize } from './memoize'; /** List filtered top-level files in `targetPath` (returns absolute paths) */ export async function listFilesSorted( @@ -96,3 +80,34 @@ export const fileExistsAsync = async (file: string): Promise => { const stat = await fs.promises.stat(file).catch(() => null); return stat?.isFile() ? file : null; }; + +export const fastJoin: (from: string, append: string) => string = + path.sep === '/' + ? (from, append) => `${from}${path.sep}${append}` + : (from, append) => + `${from}${path.sep}${append[0] === '@' ? append.replace('/', path.sep) : append}`; + +export const maybeRealpath = async (target: string): Promise => { + try { + return await fs.promises.realpath(target); + } catch { + return null; + } +}; + +export type PackageJson = Record & { name?: string; version?: string }; + +export const loadPackageJson = memoize(async function loadPackageJson( + jsonPath: string +): Promise { + try { + const packageJsonText = await fs.promises.readFile(jsonPath, 'utf8'); + const json = JSON.parse(packageJsonText); + if (typeof json !== 'object' || json == null) { + return null; + } + return json; + } catch { + return null; + } +}); From 8e4e532f49441add6bba74184efe3ef25c62f615 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 18 Feb 2026 22:31:21 +0000 Subject: [PATCH 3/3] refactor(autolinking): Add concurrency limits to IO-bound tasks (#42968) # Why Branched off of #42947 This adds code from `@expo/fingerprint` (See: #42487) to add concurrency limits to IO-bound tasks. The amount of tasks we have queued up can put a pressure on the IO-scheduling in Node.js that's slightly undesirable and limiting this seems to yield an improvement. This isn't purely CPU or disk speed bound, but seems to be just the number of IO tasks that are queued up in general, and the amount of work that's leftover for the GC to deal with. # How - Add `concurrency.ts` from `@expo/fingerprint` and add `taskAll` helper - **Note:** This was done because every `Promise.all` that's unbound is a good candidate for conversion - Add a hard-coded limit of `8` to the limiter - **Note:** Explanation in comment; experimentally, this seems to do fine on a few machines. This will likely heavily depend on CPU speed and disk speed (rather than any constant available to us). But `8` seems to do quite well universally. - Add `taskAll` to all `Promise.all` candidates in module resolution and dependency scanning This doesn't limit concurrency globally, to avoid keeping track of concurrent and nested `taskAll` calls. Instead, it'll give a concurrency of `8` to every new task group. This seems to be sufficient to lower autolinking times by up to ~20%-30%. # Test Plan - CI covers this # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- .../expo-modules-autolinking/CHANGELOG.md | 1 + .../build/autolinking/resolveModules.js | 5 +- .../build/autolinking/resolveModules.js.map | 2 +- .../build/concurrency.d.ts | 5 + .../build/concurrency.js | 59 +++++++++++ .../build/concurrency.js.map | 1 + .../build/dependencies/resolution.js | 7 +- .../build/dependencies/resolution.js.map | 2 +- .../build/dependencies/rncliLocal.js | 8 +- .../build/dependencies/rncliLocal.js.map | 2 +- .../build/dependencies/scanning.js | 5 +- .../build/dependencies/scanning.js.map | 2 +- .../build/dependencies/utils.js | 5 +- .../build/dependencies/utils.js.map | 2 +- .../build/platforms/android/android.js | 5 +- .../build/platforms/android/android.js.map | 2 +- .../reactNativeConfig/androidResolver.js | 3 +- .../reactNativeConfig/androidResolver.js.map | 2 +- .../src/__tests__/concurrency-test.ts | 71 +++++++++++++ .../src/autolinking/resolveModules.ts | 8 +- .../src/concurrency.ts | 67 +++++++++++++ .../src/dependencies/resolution.ts | 12 +-- .../src/dependencies/rncliLocal.ts | 41 ++++---- .../src/dependencies/scanning.ts | 67 ++++++------- .../src/dependencies/utils.ts | 33 +++---- .../src/platforms/android/android.ts | 99 +++++++++---------- .../src/reactNativeConfig/androidResolver.ts | 5 +- 27 files changed, 361 insertions(+), 160 deletions(-) create mode 100644 packages/expo-modules-autolinking/build/concurrency.d.ts create mode 100644 packages/expo-modules-autolinking/build/concurrency.js create mode 100644 packages/expo-modules-autolinking/build/concurrency.js.map create mode 100644 packages/expo-modules-autolinking/src/__tests__/concurrency-test.ts create mode 100644 packages/expo-modules-autolinking/src/concurrency.ts diff --git a/packages/expo-modules-autolinking/CHANGELOG.md b/packages/expo-modules-autolinking/CHANGELOG.md index 6d8a6a2b3cd270..f9c512b8edfe9b 100644 --- a/packages/expo-modules-autolinking/CHANGELOG.md +++ b/packages/expo-modules-autolinking/CHANGELOG.md @@ -11,6 +11,7 @@ ### 💡 Others - Reduce memory retained after autolinking runs ([#42947](https://github.com/expo/expo/pull/42947) by [@kitten](https://github.com/kitten)) +- Add concurrency limits to IO-bound autolinking tasks ([#42968](https://github.com/expo/expo/pull/42968) by [@kitten](https://github.com/kitten)) ## 55.0.5 — 2026-02-16 diff --git a/packages/expo-modules-autolinking/build/autolinking/resolveModules.js b/packages/expo-modules-autolinking/build/autolinking/resolveModules.js index 20dced0ad7e6c4..2b34a6ef99ea13 100644 --- a/packages/expo-modules-autolinking/build/autolinking/resolveModules.js +++ b/packages/expo-modules-autolinking/build/autolinking/resolveModules.js @@ -2,13 +2,14 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.resolveModulesAsync = resolveModulesAsync; exports.resolveExtraBuildDependenciesAsync = resolveExtraBuildDependenciesAsync; +const concurrency_1 = require("../concurrency"); const platforms_1 = require("../platforms"); /** Resolves search results to a list of platform-specific configuration. */ async function resolveModulesAsync(searchResults, autolinkingOptions) { const platformLinking = (0, platforms_1.getLinkingImplementationForPlatform)(autolinkingOptions.platform); // Additional output property for Cocoapods flags const extraOutput = { flags: autolinkingOptions.flags }; - const moduleDescriptorList = await Promise.all(Object.entries(searchResults).map(async ([packageName, revision]) => { + const moduleDescriptorList = await (0, concurrency_1.taskAll)(Object.entries(searchResults), async ([packageName, revision]) => { const resolvedModule = await platformLinking.resolveModuleAsync(packageName, revision, extraOutput); return resolvedModule ? { @@ -17,7 +18,7 @@ async function resolveModulesAsync(searchResults, autolinkingOptions) { packageName: resolvedModule.packageName ?? packageName, } : null; - })); + }); return moduleDescriptorList .filter((moduleDescriptor) => moduleDescriptor != null) .sort((a, b) => a.packageName.localeCompare(b.packageName)); diff --git a/packages/expo-modules-autolinking/build/autolinking/resolveModules.js.map b/packages/expo-modules-autolinking/build/autolinking/resolveModules.js.map index f8969869d184af..d9ac2a98209817 100644 --- a/packages/expo-modules-autolinking/build/autolinking/resolveModules.js.map +++ b/packages/expo-modules-autolinking/build/autolinking/resolveModules.js.map @@ -1 +1 @@ -{"version":3,"file":"resolveModules.js","sourceRoot":"","sources":["../../src/autolinking/resolveModules.ts"],"names":[],"mappings":";;AAUA,kDA4BC;AAQD,gFAYC;AAzDD,4CAAmE;AAQnE,4EAA4E;AACrE,KAAK,UAAU,mBAAmB,CACvC,aAA4B,EAC5B,kBAAwE;IAExE,MAAM,eAAe,GAAG,IAAA,+CAAmC,EAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzF,iDAAiD;IACjD,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAExD,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,GAAG,CAC5C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE;QAClE,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC,kBAAkB,CAC7D,WAAW,EACX,QAAQ,EACR,WAAW,CACZ,CAAC;QACF,OAAO,cAAc;YACnB,CAAC,CAAC;gBACE,GAAG,cAAc;gBACjB,cAAc,EAAE,QAAQ,CAAC,OAAO;gBAChC,WAAW,EAAE,cAAc,CAAC,WAAW,IAAI,WAAW;aACvD;YACH,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,oBAAoB;SACxB,MAAM,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,IAAI,IAAI,CAAC;SACtD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAChE,CAAC;AAOD,sHAAsH;AAC/G,KAAK,UAAU,kCAAkC,CAAC,EACvD,WAAW,EACX,QAAQ,GAC4B;IACpC,MAAM,eAAe,GAAG,IAAA,+CAAmC,EAAC,QAAQ,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,MAAM,eAAe,CAAC,kCAAkC;IAChF,2DAA2D;IAC3D,oGAAoG;IACpG,iCAAiC;IACjC,WAAW,CACZ,CAAC;IACF,OAAO,iBAAiB,IAAI,EAAE,CAAC;AACjC,CAAC","sourcesContent":["import { AutolinkingOptions } from '../commands/autolinkingOptions';\nimport { getLinkingImplementationForPlatform } from '../platforms';\nimport type {\n ExtraDependencies,\n ModuleDescriptor,\n SearchResults,\n SupportedPlatform,\n} from '../types';\n\n/** Resolves search results to a list of platform-specific configuration. */\nexport async function resolveModulesAsync(\n searchResults: SearchResults,\n autolinkingOptions: AutolinkingOptions & { platform: SupportedPlatform }\n): Promise {\n const platformLinking = getLinkingImplementationForPlatform(autolinkingOptions.platform);\n // Additional output property for Cocoapods flags\n const extraOutput = { flags: autolinkingOptions.flags };\n\n const moduleDescriptorList = await Promise.all(\n Object.entries(searchResults).map(async ([packageName, revision]) => {\n const resolvedModule = await platformLinking.resolveModuleAsync(\n packageName,\n revision,\n extraOutput\n );\n return resolvedModule\n ? {\n ...resolvedModule,\n packageVersion: revision.version,\n packageName: resolvedModule.packageName ?? packageName,\n }\n : null;\n })\n );\n\n return moduleDescriptorList\n .filter((moduleDescriptor) => moduleDescriptor != null)\n .sort((a, b) => a.packageName.localeCompare(b.packageName));\n}\n\ninterface ResolveExtraBuildDependenciesParams {\n commandRoot: string;\n platform: SupportedPlatform;\n}\n\n/** Resolves the extra build dependencies for the project, such as additional Maven repositories or CocoaPods pods. */\nexport async function resolveExtraBuildDependenciesAsync({\n commandRoot,\n platform,\n}: ResolveExtraBuildDependenciesParams): Promise {\n const platformLinking = getLinkingImplementationForPlatform(platform);\n const extraDependencies = await platformLinking.resolveExtraBuildDependenciesAsync(\n // NOTE: We assume we must be inside the native folder here\n // The `resolve` command either is invoked in the CWD of `./{android,ios}` or has a `--project-root`\n // that's in the native directory\n commandRoot\n );\n return extraDependencies ?? [];\n}\n"]} \ No newline at end of file +{"version":3,"file":"resolveModules.js","sourceRoot":"","sources":["../../src/autolinking/resolveModules.ts"],"names":[],"mappings":";;AAWA,kDA6BC;AAQD,gFAYC;AA3DD,gDAAyC;AACzC,4CAAmE;AAQnE,4EAA4E;AACrE,KAAK,UAAU,mBAAmB,CACvC,aAA4B,EAC5B,kBAAwE;IAExE,MAAM,eAAe,GAAG,IAAA,+CAAmC,EAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzF,iDAAiD;IACjD,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAExD,MAAM,oBAAoB,GAAG,MAAM,IAAA,qBAAO,EACxC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAC7B,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE;QAChC,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC,kBAAkB,CAC7D,WAAW,EACX,QAAQ,EACR,WAAW,CACZ,CAAC;QACF,OAAO,cAAc;YACnB,CAAC,CAAC;gBACE,GAAG,cAAc;gBACjB,cAAc,EAAE,QAAQ,CAAC,OAAO;gBAChC,WAAW,EAAE,cAAc,CAAC,WAAW,IAAI,WAAW;aACvD;YACH,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,CACF,CAAC;IAEF,OAAO,oBAAoB;SACxB,MAAM,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,IAAI,IAAI,CAAC;SACtD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;AAChE,CAAC;AAOD,sHAAsH;AAC/G,KAAK,UAAU,kCAAkC,CAAC,EACvD,WAAW,EACX,QAAQ,GAC4B;IACpC,MAAM,eAAe,GAAG,IAAA,+CAAmC,EAAC,QAAQ,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,MAAM,eAAe,CAAC,kCAAkC;IAChF,2DAA2D;IAC3D,oGAAoG;IACpG,iCAAiC;IACjC,WAAW,CACZ,CAAC;IACF,OAAO,iBAAiB,IAAI,EAAE,CAAC;AACjC,CAAC","sourcesContent":["import { AutolinkingOptions } from '../commands/autolinkingOptions';\nimport { taskAll } from '../concurrency';\nimport { getLinkingImplementationForPlatform } from '../platforms';\nimport type {\n ExtraDependencies,\n ModuleDescriptor,\n SearchResults,\n SupportedPlatform,\n} from '../types';\n\n/** Resolves search results to a list of platform-specific configuration. */\nexport async function resolveModulesAsync(\n searchResults: SearchResults,\n autolinkingOptions: AutolinkingOptions & { platform: SupportedPlatform }\n): Promise {\n const platformLinking = getLinkingImplementationForPlatform(autolinkingOptions.platform);\n // Additional output property for Cocoapods flags\n const extraOutput = { flags: autolinkingOptions.flags };\n\n const moduleDescriptorList = await taskAll(\n Object.entries(searchResults),\n async ([packageName, revision]) => {\n const resolvedModule = await platformLinking.resolveModuleAsync(\n packageName,\n revision,\n extraOutput\n );\n return resolvedModule\n ? {\n ...resolvedModule,\n packageVersion: revision.version,\n packageName: resolvedModule.packageName ?? packageName,\n }\n : null;\n }\n );\n\n return moduleDescriptorList\n .filter((moduleDescriptor) => moduleDescriptor != null)\n .sort((a, b) => a.packageName.localeCompare(b.packageName));\n}\n\ninterface ResolveExtraBuildDependenciesParams {\n commandRoot: string;\n platform: SupportedPlatform;\n}\n\n/** Resolves the extra build dependencies for the project, such as additional Maven repositories or CocoaPods pods. */\nexport async function resolveExtraBuildDependenciesAsync({\n commandRoot,\n platform,\n}: ResolveExtraBuildDependenciesParams): Promise {\n const platformLinking = getLinkingImplementationForPlatform(platform);\n const extraDependencies = await platformLinking.resolveExtraBuildDependenciesAsync(\n // NOTE: We assume we must be inside the native folder here\n // The `resolve` command either is invoked in the CWD of `./{android,ios}` or has a `--project-root`\n // that's in the native directory\n commandRoot\n );\n return extraDependencies ?? [];\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/concurrency.d.ts b/packages/expo-modules-autolinking/build/concurrency.d.ts new file mode 100644 index 00000000000000..a6dda83f309bd1 --- /dev/null +++ b/packages/expo-modules-autolinking/build/concurrency.d.ts @@ -0,0 +1,5 @@ +export interface Limiter { + (fn: (...args: Arguments) => PromiseLike | ReturnType, ...args: Arguments): Promise; +} +export declare const createLimiter: (limit: number) => Limiter; +export declare const taskAll: (inputs: T[], map: (input: T) => Promise) => Promise; diff --git a/packages/expo-modules-autolinking/build/concurrency.js b/packages/expo-modules-autolinking/build/concurrency.js new file mode 100644 index 00000000000000..159df667f230ba --- /dev/null +++ b/packages/expo-modules-autolinking/build/concurrency.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.taskAll = exports.createLimiter = void 0; +const createLimiter = (limit) => { + let running = 0; + let head = null; + let tail = null; + const enqueue = () => new Promise((resolve) => { + const item = { resolve, next: null }; + if (tail) { + tail.next = item; + tail = item; + } + else { + head = item; + tail = item; + } + }); + const dequeue = () => { + if (running < limit && head !== null) { + const { resolve, next } = head; + head.next = null; + head = next; + if (head === null) { + tail = null; + } + running++; + resolve(); + } + }; + return async (fn, ...args) => { + if (running < limit) { + running++; + } + else { + await enqueue(); + } + try { + return await fn(...args); + } + finally { + running--; + dequeue(); + } + }; +}; +exports.createLimiter = createLimiter; +const taskAll = (inputs, map) => { + // NOTE: This doesn't depend on CPU cores, but instead is hard-coded depending on + // number of concurrent IO-bound tasks. `taskAll` can be called concurrently, and + // we don't keep track of concurrent `taskAll` calls in expo-modules-autolinking. + // There's a fixed number of concurrent pending IO operations that Node.js handles + // nicely. It seems that expo-modules-autolinking behaves nicely when this number + // is around ~8, but this may be higher if disk + core speed is higher. + const limiter = (0, exports.createLimiter)(8); + return Promise.all(inputs.map((input) => limiter(map, input))); +}; +exports.taskAll = taskAll; +//# sourceMappingURL=concurrency.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/concurrency.js.map b/packages/expo-modules-autolinking/build/concurrency.js.map new file mode 100644 index 00000000000000..dbfbab3adbf92c --- /dev/null +++ b/packages/expo-modules-autolinking/build/concurrency.js.map @@ -0,0 +1 @@ +{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../src/concurrency.ts"],"names":[],"mappings":";;;AAYO,MAAM,aAAa,GAAG,CAAC,KAAa,EAAW,EAAE;IACtD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,IAAI,GAAqB,IAAI,CAAC;IAClC,IAAI,IAAI,GAAqB,IAAI,CAAC;IAElC,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAc,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAChD,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,IAAI,CAAC;YACZ,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACrC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,IAAI,GAAG,IAAI,CAAC;YACZ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,IAAI,GAAG,IAAI,CAAC;YACd,CAAC;YACD,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,KAAK,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE;QAC3B,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3B,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AA3CW,QAAA,aAAa,iBA2CxB;AAEK,MAAM,OAAO,GAAG,CAAO,MAAW,EAAE,GAA6B,EAAgB,EAAE;IACxF,iFAAiF;IACjF,iFAAiF;IACjF,iFAAiF;IACjF,kFAAkF;IAClF,iFAAiF;IACjF,uEAAuE;IACvE,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,CAAC,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC,CAAC;AATW,QAAA,OAAO,WASlB","sourcesContent":["export interface Limiter {\n (\n fn: (...args: Arguments) => PromiseLike | ReturnType,\n ...args: Arguments\n ): Promise;\n}\n\ninterface QueueItem {\n resolve(): void;\n next: QueueItem | null;\n}\n\nexport const createLimiter = (limit: number): Limiter => {\n let running = 0;\n let head: QueueItem | null = null;\n let tail: QueueItem | null = null;\n\n const enqueue = () =>\n new Promise((resolve) => {\n const item: QueueItem = { resolve, next: null };\n if (tail) {\n tail.next = item;\n tail = item;\n } else {\n head = item;\n tail = item;\n }\n });\n\n const dequeue = () => {\n if (running < limit && head !== null) {\n const { resolve, next } = head;\n head.next = null;\n head = next;\n if (head === null) {\n tail = null;\n }\n running++;\n resolve();\n }\n };\n\n return async (fn, ...args) => {\n if (running < limit) {\n running++;\n } else {\n await enqueue();\n }\n try {\n return await fn(...args);\n } finally {\n running--;\n dequeue();\n }\n };\n};\n\nexport const taskAll = (inputs: T[], map: (input: T) => Promise): Promise => {\n // NOTE: This doesn't depend on CPU cores, but instead is hard-coded depending on\n // number of concurrent IO-bound tasks. `taskAll` can be called concurrently, and\n // we don't keep track of concurrent `taskAll` calls in expo-modules-autolinking.\n // There's a fixed number of concurrent pending IO operations that Node.js handles\n // nicely. It seems that expo-modules-autolinking behaves nicely when this number\n // is around ~8, but this may be higher if disk + core speed is higher.\n const limiter = createLimiter(8);\n return Promise.all(inputs.map((input) => limiter(map, input)));\n};\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/resolution.js b/packages/expo-modules-autolinking/build/dependencies/resolution.js index f0892c8d0990d1..6394337e2b340f 100644 --- a/packages/expo-modules-autolinking/build/dependencies/resolution.js +++ b/packages/expo-modules-autolinking/build/dependencies/resolution.js @@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesRecursively = scanDependenciesRecursively; const node_module_1 = __importDefault(require("node:module")); const utils_1 = require("./utils"); +const concurrency_1 = require("../concurrency"); const utils_2 = require("../utils"); // NOTE(@kitten): There's no need to search very deep for modules // We don't expect native modules to be excessively nested in the dependency tree @@ -74,9 +75,7 @@ async function resolveDependencies(packageJson, nodeModulePaths, depth, shouldIn } return null; }; - const modules = await Promise.all(Object.keys(dependencies) - .filter((dependencyName) => shouldIncludeDependency(dependencyName)) - .map((dependencyName) => resolveDependency(dependencyName))); + const modules = await (0, concurrency_1.taskAll)(Object.keys(dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)), (dependencyName) => resolveDependency(dependencyName)); return modules.filter((resolution) => resolution != null); } async function scanDependenciesRecursively(rawPath, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency, limitDepth } = {}) { @@ -110,7 +109,7 @@ async function scanDependenciesRecursively(rawPath, { shouldIncludeDependency = searchResults[modules[idx].name] = modules[idx]; } if (depth + 1 < maxDepth) { - const childResults = await Promise.all(modules.map((resolution) => recurse(resolution, depth + 1))); + const childResults = await (0, concurrency_1.taskAll)(modules, (resolution) => recurse(resolution, depth + 1)); return (0, utils_1.mergeResolutionResults)(childResults, searchResults); } else { diff --git a/packages/expo-modules-autolinking/build/dependencies/resolution.js.map b/packages/expo-modules-autolinking/build/dependencies/resolution.js.map index f3eae67b2ed5f4..143e927d87fbd3 100644 --- a/packages/expo-modules-autolinking/build/dependencies/resolution.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/resolution.js.map @@ -1 +1 @@ -{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/dependencies/resolution.ts"],"names":[],"mappings":"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","sourcesContent":["import Module from 'node:module';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency, mergeResolutionResults } from './utils';\nimport { type PackageJson, loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\ndeclare module 'node:module' {\n export function _nodeModulePaths(base: string): readonly string[];\n}\n\n// NOTE(@kitten): There's no need to search very deep for modules\n// We don't expect native modules to be excessively nested in the dependency tree\nconst MAX_DEPTH = 8;\n\nconst createNodeModulePathsCreator = () => {\n const _nodeModulePathCache = new Map();\n return async function getNodeModulePaths(packagePath: string) {\n const outputPaths: string[] = [];\n const nodeModulePaths = Module._nodeModulePaths(packagePath);\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const nodeModulePath = nodeModulePaths[idx];\n let target = _nodeModulePathCache.get(nodeModulePath);\n if (target === undefined) {\n target = await maybeRealpath(nodeModulePath);\n if (idx !== 0) {\n _nodeModulePathCache.set(nodeModulePath, target);\n }\n }\n if (target != null) {\n outputPaths.push(target);\n }\n }\n return outputPaths;\n };\n};\n\nasync function resolveDependencies(\n packageJson: PackageJson,\n nodeModulePaths: readonly string[],\n depth: number,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n const dependencies: Record = Object.create(null);\n if (packageJson.dependencies != null && typeof packageJson.dependencies === 'object') {\n Object.assign(dependencies, packageJson.dependencies);\n }\n // NOTE(@kitten): Also traverse devDependencies for top-level package.json\n if (\n depth === 0 &&\n packageJson.devDependencies != null &&\n typeof packageJson.devDependencies === 'object'\n ) {\n Object.assign(dependencies, packageJson.devDependencies);\n }\n if (packageJson.peerDependencies != null && typeof packageJson.peerDependencies === 'object') {\n const peerDependenciesMeta =\n packageJson.peerDependenciesMeta != null &&\n typeof packageJson.peerDependenciesMeta === 'object'\n ? (packageJson.peerDependenciesMeta as Record)\n : undefined;\n for (const dependencyName in packageJson.peerDependencies) {\n // NOTE(@kitten): We only check peer dependencies because some package managers auto-install them\n // which would mean they'd have no reference in any dependencies. However, optional peer dependencies\n // don't auto-install and we can skip them\n if (!isOptionalPeerDependencyMeta(peerDependenciesMeta, dependencyName)) {\n dependencies[dependencyName] = '';\n }\n }\n }\n\n const resolveDependency = async (\n dependencyName: string\n ): Promise => {\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const originPath = fastJoin(nodeModulePaths[idx], dependencyName);\n const nodeModulePath = await maybeRealpath(originPath);\n if (nodeModulePath != null) {\n return {\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: dependencyName,\n version: '',\n path: nodeModulePath,\n originPath,\n duplicates: null,\n depth,\n };\n }\n }\n return null;\n };\n\n const modules = await Promise.all(\n Object.keys(dependencies)\n .filter((dependencyName) => shouldIncludeDependency(dependencyName))\n .map((dependencyName) => resolveDependency(dependencyName))\n );\n\n return modules.filter((resolution) => resolution != null);\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n limitDepth?: number;\n}\n\nexport async function scanDependenciesRecursively(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency, limitDepth }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n if (!rootPath) {\n return {};\n }\n\n const _visitedPackagePaths = new Set();\n const getNodeModulePaths = createNodeModulePathsCreator();\n const maxDepth = limitDepth != null ? limitDepth : MAX_DEPTH;\n\n const recurse = async (\n resolution: DependencyResolution,\n depth = 0\n ): Promise => {\n const searchResults: ResolutionResult = Object.create(null);\n if (_visitedPackagePaths.has(resolution.path)) {\n return searchResults;\n } else {\n _visitedPackagePaths.add(resolution.path);\n }\n const [nodeModulePaths, packageJson] = await Promise.all([\n getNodeModulePaths(resolution.path),\n loadPackageJson(fastJoin(resolution.path, 'package.json')),\n ]);\n if (!packageJson) {\n return searchResults;\n } else {\n resolution.version = packageJson.version || '';\n }\n\n const modules = await resolveDependencies(\n packageJson,\n nodeModulePaths,\n depth,\n shouldIncludeDependency\n );\n for (let idx = 0; idx < modules.length; idx++) {\n searchResults[modules[idx].name] = modules[idx];\n }\n\n if (depth + 1 < maxDepth) {\n const childResults = await Promise.all(\n modules.map((resolution) => recurse(resolution, depth + 1))\n );\n return mergeResolutionResults(childResults, searchResults);\n } else {\n return searchResults;\n }\n };\n\n const searchResults = await recurse({\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: '',\n version: '',\n path: rootPath,\n originPath: rawPath,\n duplicates: null,\n depth: -1,\n });\n\n return searchResults;\n}\n\nconst isOptionalPeerDependencyMeta = (\n peerDependenciesMeta: Record | undefined,\n packageName: string\n) => {\n return (\n peerDependenciesMeta &&\n peerDependenciesMeta[packageName] != null &&\n typeof peerDependenciesMeta[packageName] === 'object' &&\n 'optional' in peerDependenciesMeta[packageName] &&\n !!peerDependenciesMeta[packageName].optional\n );\n};\n"]} \ No newline at end of file +{"version":3,"file":"resolution.js","sourceRoot":"","sources":["../../src/dependencies/resolution.ts"],"names":[],"mappings":"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","sourcesContent":["import Module from 'node:module';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency, mergeResolutionResults } from './utils';\nimport { taskAll } from '../concurrency';\nimport { type PackageJson, loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\ndeclare module 'node:module' {\n export function _nodeModulePaths(base: string): readonly string[];\n}\n\n// NOTE(@kitten): There's no need to search very deep for modules\n// We don't expect native modules to be excessively nested in the dependency tree\nconst MAX_DEPTH = 8;\n\nconst createNodeModulePathsCreator = () => {\n const _nodeModulePathCache = new Map();\n return async function getNodeModulePaths(packagePath: string) {\n const outputPaths: string[] = [];\n const nodeModulePaths = Module._nodeModulePaths(packagePath);\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const nodeModulePath = nodeModulePaths[idx];\n let target = _nodeModulePathCache.get(nodeModulePath);\n if (target === undefined) {\n target = await maybeRealpath(nodeModulePath);\n if (idx !== 0) {\n _nodeModulePathCache.set(nodeModulePath, target);\n }\n }\n if (target != null) {\n outputPaths.push(target);\n }\n }\n return outputPaths;\n };\n};\n\nasync function resolveDependencies(\n packageJson: PackageJson,\n nodeModulePaths: readonly string[],\n depth: number,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n const dependencies: Record = Object.create(null);\n if (packageJson.dependencies != null && typeof packageJson.dependencies === 'object') {\n Object.assign(dependencies, packageJson.dependencies);\n }\n // NOTE(@kitten): Also traverse devDependencies for top-level package.json\n if (\n depth === 0 &&\n packageJson.devDependencies != null &&\n typeof packageJson.devDependencies === 'object'\n ) {\n Object.assign(dependencies, packageJson.devDependencies);\n }\n if (packageJson.peerDependencies != null && typeof packageJson.peerDependencies === 'object') {\n const peerDependenciesMeta =\n packageJson.peerDependenciesMeta != null &&\n typeof packageJson.peerDependenciesMeta === 'object'\n ? (packageJson.peerDependenciesMeta as Record)\n : undefined;\n for (const dependencyName in packageJson.peerDependencies) {\n // NOTE(@kitten): We only check peer dependencies because some package managers auto-install them\n // which would mean they'd have no reference in any dependencies. However, optional peer dependencies\n // don't auto-install and we can skip them\n if (!isOptionalPeerDependencyMeta(peerDependenciesMeta, dependencyName)) {\n dependencies[dependencyName] = '';\n }\n }\n }\n\n const resolveDependency = async (\n dependencyName: string\n ): Promise => {\n for (let idx = 0; idx < nodeModulePaths.length; idx++) {\n const originPath = fastJoin(nodeModulePaths[idx], dependencyName);\n const nodeModulePath = await maybeRealpath(originPath);\n if (nodeModulePath != null) {\n return {\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: dependencyName,\n version: '',\n path: nodeModulePath,\n originPath,\n duplicates: null,\n depth,\n };\n }\n }\n return null;\n };\n\n const modules = await taskAll(\n Object.keys(dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)),\n (dependencyName) => resolveDependency(dependencyName)\n );\n\n return modules.filter((resolution) => resolution != null);\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n limitDepth?: number;\n}\n\nexport async function scanDependenciesRecursively(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency, limitDepth }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n if (!rootPath) {\n return {};\n }\n\n const _visitedPackagePaths = new Set();\n const getNodeModulePaths = createNodeModulePathsCreator();\n const maxDepth = limitDepth != null ? limitDepth : MAX_DEPTH;\n\n const recurse = async (\n resolution: DependencyResolution,\n depth = 0\n ): Promise => {\n const searchResults: ResolutionResult = Object.create(null);\n if (_visitedPackagePaths.has(resolution.path)) {\n return searchResults;\n } else {\n _visitedPackagePaths.add(resolution.path);\n }\n const [nodeModulePaths, packageJson] = await Promise.all([\n getNodeModulePaths(resolution.path),\n loadPackageJson(fastJoin(resolution.path, 'package.json')),\n ]);\n if (!packageJson) {\n return searchResults;\n } else {\n resolution.version = packageJson.version || '';\n }\n\n const modules = await resolveDependencies(\n packageJson,\n nodeModulePaths,\n depth,\n shouldIncludeDependency\n );\n for (let idx = 0; idx < modules.length; idx++) {\n searchResults[modules[idx].name] = modules[idx];\n }\n\n if (depth + 1 < maxDepth) {\n const childResults = await taskAll(modules, (resolution) => recurse(resolution, depth + 1));\n return mergeResolutionResults(childResults, searchResults);\n } else {\n return searchResults;\n }\n };\n\n const searchResults = await recurse({\n source: DependencyResolutionSource.RECURSIVE_RESOLUTION,\n name: '',\n version: '',\n path: rootPath,\n originPath: rawPath,\n duplicates: null,\n depth: -1,\n });\n\n return searchResults;\n}\n\nconst isOptionalPeerDependencyMeta = (\n peerDependenciesMeta: Record | undefined,\n packageName: string\n) => {\n return (\n peerDependenciesMeta &&\n peerDependenciesMeta[packageName] != null &&\n typeof peerDependenciesMeta[packageName] === 'object' &&\n 'optional' in peerDependenciesMeta[packageName] &&\n !!peerDependenciesMeta[packageName].optional\n );\n};\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js index 9501f0d0e9f0da..15da7efacc4352 100644 --- a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js +++ b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js @@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesFromRNProjectConfig = scanDependenciesFromRNProjectConfig; const path_1 = __importDefault(require("path")); const utils_1 = require("./utils"); +const concurrency_1 = require("../concurrency"); const utils_2 = require("../utils"); async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { shouldIncludeDependency = utils_1.defaultShouldIncludeDependency } = {}) { const rootPath = await (0, utils_2.maybeRealpath)(rawPath); @@ -13,10 +14,7 @@ async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { sho if (!rootPath || !projectConfig || !projectConfig.dependencies) { return searchResults; } - for (const dependencyName in projectConfig.dependencies) { - if (!shouldIncludeDependency(dependencyName)) { - continue; - } + await (0, concurrency_1.taskAll)(Object.keys(projectConfig.dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)), async (dependencyName) => { const dependencyConfig = projectConfig.dependencies[dependencyName]; if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') { const originPath = path_1.default.resolve(rootPath, dependencyConfig.root); @@ -33,7 +31,7 @@ async function scanDependenciesFromRNProjectConfig(rawPath, projectConfig, { sho }; } } - } + }); return searchResults; } //# sourceMappingURL=rncliLocal.js.map \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map index 0f716e3f5b8bde..ebc0f51c029b08 100644 --- a/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/rncliLocal.js.map @@ -1 +1 @@ -{"version":3,"file":"rncliLocal.js","sourceRoot":"","sources":["../../src/dependencies/rncliLocal.ts"],"names":[],"mappings":";;;;;AAWA,kFAkCC;AA7CD,gDAAwB;AAGxB,mCAAyD;AAEzD,oCAAyC;AAMlC,KAAK,UAAU,mCAAmC,CACvD,OAAe,EACf,aAAsD,EACtD,EAAE,uBAAuB,GAAG,sCAA8B,KAAwB,EAAE;IAEpF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAC/D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,KAAK,MAAM,cAAc,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;QACxD,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QACpE,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,IAAI,OAAO,gBAAgB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3F,MAAM,UAAU,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,cAAc,CAAC,GAAG;oBAC9B,MAAM,iDAAyC;oBAC/C,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU;oBACV,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,CAAC;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import path from 'path';\n\nimport { DependencyResolutionSource, type ResolutionResult } from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { maybeRealpath } from '../utils';\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesFromRNProjectConfig(\n rawPath: string,\n projectConfig: RNConfigReactNativeProjectConfig | null,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath || !projectConfig || !projectConfig.dependencies) {\n return searchResults;\n }\n\n for (const dependencyName in projectConfig.dependencies) {\n if (!shouldIncludeDependency(dependencyName)) {\n continue;\n }\n const dependencyConfig = projectConfig.dependencies[dependencyName];\n if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {\n const originPath = path.resolve(rootPath, dependencyConfig.root);\n const realPath = await maybeRealpath(originPath);\n if (realPath) {\n searchResults[dependencyName] = {\n source: DependencyResolutionSource.RN_CLI_LOCAL,\n name: dependencyName,\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n }\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file +{"version":3,"file":"rncliLocal.js","sourceRoot":"","sources":["../../src/dependencies/rncliLocal.ts"],"names":[],"mappings":";;;;;AAYA,kFAoCC;AAhDD,gDAAwB;AAGxB,mCAAyD;AACzD,gDAAyC;AAEzC,oCAAyC;AAMlC,KAAK,UAAU,mCAAmC,CACvD,OAAe,EACf,aAAsD,EACtD,EAAE,uBAAuB,GAAG,sCAA8B,KAAwB,EAAE;IAEpF,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAC/D,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,IAAA,qBAAO,EACX,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE,EAAE,CAChE,uBAAuB,CAAC,cAAc,CAAC,CACxC,EACD,KAAK,EAAE,cAAc,EAAE,EAAE;QACvB,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAa,CAAC,cAAc,CAAC,CAAC;QACrE,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,IAAI,OAAO,gBAAgB,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3F,MAAM,UAAU,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,UAAU,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,cAAc,CAAC,GAAG;oBAC9B,MAAM,iDAAyC;oBAC/C,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU;oBACV,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,CAAC;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import path from 'path';\n\nimport { DependencyResolutionSource, type ResolutionResult } from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { taskAll } from '../concurrency';\nimport { RNConfigReactNativeProjectConfig } from '../reactNativeConfig';\nimport { maybeRealpath } from '../utils';\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesFromRNProjectConfig(\n rawPath: string,\n projectConfig: RNConfigReactNativeProjectConfig | null,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath || !projectConfig || !projectConfig.dependencies) {\n return searchResults;\n }\n\n await taskAll(\n Object.keys(projectConfig.dependencies).filter((dependencyName) =>\n shouldIncludeDependency(dependencyName)\n ),\n async (dependencyName) => {\n const dependencyConfig = projectConfig.dependencies![dependencyName];\n if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') {\n const originPath = path.resolve(rootPath, dependencyConfig.root);\n const realPath = await maybeRealpath(originPath);\n if (realPath) {\n searchResults[dependencyName] = {\n source: DependencyResolutionSource.RN_CLI_LOCAL,\n name: dependencyName,\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n }\n }\n }\n );\n\n return searchResults;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/scanning.js b/packages/expo-modules-autolinking/build/dependencies/scanning.js index 3c7624fc2d7340..0236515d1b0be5 100644 --- a/packages/expo-modules-autolinking/build/dependencies/scanning.js +++ b/packages/expo-modules-autolinking/build/dependencies/scanning.js @@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.scanDependenciesInSearchPath = scanDependenciesInSearchPath; const fs_1 = __importDefault(require("fs")); +const concurrency_1 = require("../concurrency"); const utils_1 = require("./utils"); const utils_2 = require("../utils"); async function resolveDependency(basePath, dependencyName, shouldIncludeDependency) { @@ -57,7 +58,7 @@ async function scanDependenciesInSearchPath(rawPath, { shouldIncludeDependency = } else { const dirents = await fs_1.default.promises.readdir(rootPath, { withFileTypes: true }); - await Promise.all(dirents.map(async (entry) => { + await (0, concurrency_1.taskAll)(dirents, async (entry) => { if (entry.isSymbolicLink()) { const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency); if (resolution) @@ -89,7 +90,7 @@ async function scanDependenciesInSearchPath(rawPath, { shouldIncludeDependency = resolvedDependencies.push(resolution); } } - })); + }); } for (let idx = 0; idx < resolvedDependencies.length; idx++) { const resolution = resolvedDependencies[idx]; diff --git a/packages/expo-modules-autolinking/build/dependencies/scanning.js.map b/packages/expo-modules-autolinking/build/dependencies/scanning.js.map index 4cbabac216a124..7e0f8f2a32fcad 100644 --- a/packages/expo-modules-autolinking/build/dependencies/scanning.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/scanning.js.map @@ -1 +1 @@ -{"version":3,"file":"scanning.js","sourceRoot":"","sources":["../../src/dependencies/scanning.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\nasync function resolveDependency(\n basePath: string,\n dependencyName: string | null,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n if (dependencyName && !shouldIncludeDependency(dependencyName)) {\n return null;\n }\n const originPath = dependencyName ? fastJoin(basePath, dependencyName) : basePath;\n const realPath = await maybeRealpath(originPath);\n const packageJson = await loadPackageJson(fastJoin(realPath || originPath, 'package.json'));\n if (packageJson) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: packageJson.name || '',\n version: packageJson.version || '',\n path: realPath || originPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else if (dependencyName && realPath) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: dependencyName.toLowerCase(),\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else {\n return null;\n }\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesInSearchPath(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath) {\n return searchResults;\n }\n\n const resolvedDependencies: DependencyResolution[] = [];\n\n const localModuleTarget = await maybeRealpath(fastJoin(rootPath, 'package.json'));\n if (localModuleTarget) {\n // If we have a `package.json` file in the search path, we're already dealing with a node module\n // and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../`\n const resolution = await resolveDependency(rootPath, null, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else {\n const dirents = await fs.promises.readdir(rootPath!, { withFileTypes: true });\n await Promise.all(\n dirents.map(async (entry) => {\n if (entry.isSymbolicLink()) {\n const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else if (entry.isDirectory()) {\n if (entry.name === 'node_modules') {\n // Ignore nested node_modules folder\n }\n if (entry.name[0] === '.') {\n // Ignore hidden folders\n } else if (entry.name[0] === '@') {\n // NOTE: We don't expect @-scope folders to be symlinks\n const entryPath = fastJoin(rootPath, entry.name);\n const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true });\n await Promise.all(\n childEntries.map(async (child) => {\n const dependencyName = `${entry.name}/${child.name}`;\n if (child.isDirectory() || child.isSymbolicLink()) {\n const resolution = await resolveDependency(\n rootPath,\n dependencyName,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n })\n );\n } else {\n const resolution = await resolveDependency(\n rootPath,\n entry.name,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n }\n })\n );\n }\n\n for (let idx = 0; idx < resolvedDependencies.length; idx++) {\n const resolution = resolvedDependencies[idx];\n const prevEntry = searchResults[resolution.name];\n if (prevEntry != null && resolution.path !== prevEntry.path) {\n (prevEntry.duplicates ?? (prevEntry.duplicates = [])).push({\n name: resolution.name,\n version: resolution.version,\n path: resolution.path,\n originPath: resolution.originPath,\n });\n } else if (prevEntry == null) {\n searchResults[resolution.name] = resolution;\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file +{"version":3,"file":"scanning.js","sourceRoot":"","sources":["../../src/dependencies/scanning.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\n\nimport {\n type ResolutionResult,\n type DependencyResolution,\n DependencyResolutionSource,\n} from './types';\nimport { taskAll } from '../concurrency';\nimport { defaultShouldIncludeDependency } from './utils';\nimport { loadPackageJson, maybeRealpath, fastJoin } from '../utils';\n\nasync function resolveDependency(\n basePath: string,\n dependencyName: string | null,\n shouldIncludeDependency: (dependencyName: string) => boolean\n): Promise {\n if (dependencyName && !shouldIncludeDependency(dependencyName)) {\n return null;\n }\n const originPath = dependencyName ? fastJoin(basePath, dependencyName) : basePath;\n const realPath = await maybeRealpath(originPath);\n const packageJson = await loadPackageJson(fastJoin(realPath || originPath, 'package.json'));\n if (packageJson) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: packageJson.name || '',\n version: packageJson.version || '',\n path: realPath || originPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else if (dependencyName && realPath) {\n return {\n source: DependencyResolutionSource.SEARCH_PATH,\n name: dependencyName.toLowerCase(),\n version: '',\n path: realPath,\n originPath,\n duplicates: null,\n depth: 0,\n };\n } else {\n return null;\n }\n}\n\ninterface ResolutionOptions {\n shouldIncludeDependency?(name: string): boolean;\n}\n\nexport async function scanDependenciesInSearchPath(\n rawPath: string,\n { shouldIncludeDependency = defaultShouldIncludeDependency }: ResolutionOptions = {}\n): Promise {\n const rootPath = await maybeRealpath(rawPath);\n const searchResults: ResolutionResult = Object.create(null);\n if (!rootPath) {\n return searchResults;\n }\n\n const resolvedDependencies: DependencyResolution[] = [];\n\n const localModuleTarget = await maybeRealpath(fastJoin(rootPath, 'package.json'));\n if (localModuleTarget) {\n // If we have a `package.json` file in the search path, we're already dealing with a node module\n // and can skip the rest. This is a special case created by create-expo-module's `nativeModulesDir: ../`\n const resolution = await resolveDependency(rootPath, null, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else {\n const dirents = await fs.promises.readdir(rootPath!, { withFileTypes: true });\n await taskAll(dirents, async (entry) => {\n if (entry.isSymbolicLink()) {\n const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n } else if (entry.isDirectory()) {\n if (entry.name === 'node_modules') {\n // Ignore nested node_modules folder\n }\n if (entry.name[0] === '.') {\n // Ignore hidden folders\n } else if (entry.name[0] === '@') {\n // NOTE: We don't expect @-scope folders to be symlinks\n const entryPath = fastJoin(rootPath, entry.name);\n const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true });\n await Promise.all(\n childEntries.map(async (child) => {\n const dependencyName = `${entry.name}/${child.name}`;\n if (child.isDirectory() || child.isSymbolicLink()) {\n const resolution = await resolveDependency(\n rootPath,\n dependencyName,\n shouldIncludeDependency\n );\n if (resolution) resolvedDependencies.push(resolution);\n }\n })\n );\n } else {\n const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency);\n if (resolution) resolvedDependencies.push(resolution);\n }\n }\n });\n }\n\n for (let idx = 0; idx < resolvedDependencies.length; idx++) {\n const resolution = resolvedDependencies[idx];\n const prevEntry = searchResults[resolution.name];\n if (prevEntry != null && resolution.path !== prevEntry.path) {\n (prevEntry.duplicates ?? (prevEntry.duplicates = [])).push({\n name: resolution.name,\n version: resolution.version,\n path: resolution.path,\n originPath: resolution.originPath,\n });\n } else if (prevEntry == null) {\n searchResults[resolution.name] = resolution;\n }\n }\n\n return searchResults;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/dependencies/utils.js b/packages/expo-modules-autolinking/build/dependencies/utils.js index 0123284d7bf556..74f31585afde14 100644 --- a/packages/expo-modules-autolinking/build/dependencies/utils.js +++ b/packages/expo-modules-autolinking/build/dependencies/utils.js @@ -8,6 +8,7 @@ exports.mergeWithDuplicate = mergeWithDuplicate; exports.filterMapResolutionResult = filterMapResolutionResult; exports.mergeResolutionResults = mergeResolutionResults; const path_1 = __importDefault(require("path")); +const concurrency_1 = require("../concurrency"); const NODE_MODULES_PATTERN = `${path_1.default.sep}node_modules${path_1.default.sep}`; // The default dependencies we exclude don't contain dependency chains leading to autolinked modules function defaultShouldIncludeDependency(dependencyName) { @@ -94,7 +95,7 @@ function mergeWithDuplicate(a, b) { return target; } async function filterMapResolutionResult(results, filterMap) { - const resolutions = await Promise.all(Object.keys(results).map(async (key) => { + const resolutions = await (0, concurrency_1.taskAll)(Object.keys(results), async (key) => { const resolution = results[key]; const result = resolution ? await filterMap(resolution) : null; // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates @@ -109,7 +110,7 @@ async function filterMapResolutionResult(results, filterMap) { } } return result; - })); + }); const output = Object.create(null); for (let idx = 0; idx < resolutions.length; idx++) { const resolution = resolutions[idx]; diff --git a/packages/expo-modules-autolinking/build/dependencies/utils.js.map b/packages/expo-modules-autolinking/build/dependencies/utils.js.map index 286b169cfad937..d574ea70bcb171 100644 --- a/packages/expo-modules-autolinking/build/dependencies/utils.js.map +++ b/packages/expo-modules-autolinking/build/dependencies/utils.js.map @@ -1 +1 @@ -{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { memoize } from '../memoize';\nimport {\n DependencyResolutionSource,\n type DependencyResolution,\n type ResolutionResult,\n} from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint' ||\n scopeName === 'testing-library' ||\n scopeName === 'aws-crypto' ||\n scopeName === 'aws-sdk'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/webpack-config':\n case '@expo/env':\n case '@react-native/codegen':\n case '@react-native/community-cli-plugin':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n case 'eslint-plugin-import':\n case 'jest-expo':\n case 'jest':\n case 'metro':\n case 'ts-node':\n case 'typescript':\n case 'webpack':\n return false;\n default:\n return true;\n }\n}\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n if (duplicates.every((parent) => parent.path !== duplicate.path)) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n } else if (!target.version && duplicate.version) {\n target.version = duplicate.version;\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise | T | null\n): Promise> {\n const resolutions = await Promise.all(\n Object.keys(results).map(async (key) => {\n const resolution = results[key];\n const result = resolution ? await filterMap(resolution) : null;\n // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates\n // to see if the `searchPaths` result is not a module but another is\n if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) {\n for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) {\n const duplicate = resolution.duplicates[idx];\n const duplicateResult = await filterMap({ ...resolution, ...duplicate });\n if (duplicateResult != null) {\n return duplicateResult;\n }\n }\n }\n return result;\n })\n );\n const output: Record = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(\n results: ResolutionResult[],\n base?: ResolutionResult\n): ResolutionResult {\n if (base == null && results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = base == null ? Object.create(null) : base;\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]} \ No newline at end of file +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/dependencies/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\n\nimport { taskAll } from '../concurrency';\nimport {\n DependencyResolutionSource,\n type DependencyResolution,\n type ResolutionResult,\n} from './types';\n\nconst NODE_MODULES_PATTERN = `${path.sep}node_modules${path.sep}`;\n\n// The default dependencies we exclude don't contain dependency chains leading to autolinked modules\nexport function defaultShouldIncludeDependency(dependencyName: string): boolean {\n const scopeName =\n dependencyName[0] === '@' ? dependencyName.slice(1, dependencyName.indexOf('/')) : null;\n if (\n scopeName === 'babel' ||\n scopeName === 'types' ||\n scopeName === 'eslint' ||\n scopeName === 'typescript-eslint' ||\n scopeName === 'testing-library' ||\n scopeName === 'aws-crypto' ||\n scopeName === 'aws-sdk'\n ) {\n return false;\n }\n switch (dependencyName) {\n case '@expo/cli':\n case '@expo/config':\n case '@expo/metro-config':\n case '@expo/package-manager':\n case '@expo/prebuild-config':\n case '@expo/webpack-config':\n case '@expo/env':\n case '@react-native/codegen':\n case '@react-native/community-cli-plugin':\n case 'eslint':\n case 'eslint-config-expo':\n case 'eslint-plugin-expo':\n case 'eslint-plugin-import':\n case 'jest-expo':\n case 'jest':\n case 'metro':\n case 'ts-node':\n case 'typescript':\n case 'webpack':\n return false;\n default:\n return true;\n }\n}\n\nexport function mergeWithDuplicate(\n a: DependencyResolution,\n b: DependencyResolution\n): DependencyResolution {\n let target: DependencyResolution;\n let duplicate: DependencyResolution;\n if (a.depth < b.depth) {\n target = a;\n duplicate = b;\n } else if (b.depth < a.depth) {\n target = b;\n duplicate = a;\n } else {\n // If both are equal, then the shallowest path wins\n const pathDepthA = a.originPath.split(NODE_MODULES_PATTERN).length;\n const pathDepthB = b.originPath.split(NODE_MODULES_PATTERN).length;\n if (pathDepthA < pathDepthB) {\n target = a;\n duplicate = b;\n } else if (pathDepthB < pathDepthA) {\n target = b;\n duplicate = a;\n } else {\n target = a;\n duplicate = b;\n }\n }\n const duplicates = target.duplicates || (target.duplicates = []);\n if (target.path !== duplicate.path) {\n if (duplicates.every((parent) => parent.path !== duplicate.path)) {\n duplicates.push({\n name: duplicate.name,\n version: duplicate.version,\n path: duplicate.path,\n originPath: duplicate.originPath,\n });\n }\n } else if (!target.version && duplicate.version) {\n target.version = duplicate.version;\n }\n if (duplicate.duplicates?.length) {\n duplicates.push(\n ...duplicate.duplicates.filter((child) =>\n duplicates.every((parent) => parent.path !== child.path)\n )\n );\n }\n return target;\n}\n\nexport async function filterMapResolutionResult(\n results: ResolutionResult,\n filterMap: (resolution: DependencyResolution) => Promise | T | null\n): Promise> {\n const resolutions = await taskAll(Object.keys(results), async (key) => {\n const resolution = results[key];\n const result = resolution ? await filterMap(resolution) : null;\n // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates\n // to see if the `searchPaths` result is not a module but another is\n if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) {\n for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) {\n const duplicate = resolution.duplicates[idx];\n const duplicateResult = await filterMap({ ...resolution, ...duplicate });\n if (duplicateResult != null) {\n return duplicateResult;\n }\n }\n }\n return result;\n });\n const output: Record = Object.create(null);\n for (let idx = 0; idx < resolutions.length; idx++) {\n const resolution = resolutions[idx];\n if (resolution != null) {\n output[resolution.name] = resolution;\n }\n }\n return output;\n}\n\nexport function mergeResolutionResults(\n results: ResolutionResult[],\n base?: ResolutionResult\n): ResolutionResult {\n if (base == null && results.length === 1) {\n return results[0];\n }\n const output: ResolutionResult = base == null ? Object.create(null) : base;\n for (let idx = 0; idx < results.length; idx++) {\n for (const key in results[idx]) {\n const resolution = results[idx][key]!;\n const prevResolution = output[key];\n if (prevResolution != null) {\n output[key] = mergeWithDuplicate(prevResolution, resolution);\n } else {\n output[key] = resolution;\n }\n }\n }\n return output;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/platforms/android/android.js b/packages/expo-modules-autolinking/build/platforms/android/android.js index 881f676308b45e..8efcbfae30b6a3 100644 --- a/packages/expo-modules-autolinking/build/platforms/android/android.js +++ b/packages/expo-modules-autolinking/build/platforms/android/android.js @@ -13,6 +13,7 @@ exports.convertPackageWithGradleToProjectName = convertPackageWithGradleToProjec exports.searchGradlePropertyFirst = searchGradlePropertyFirst; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); +const concurrency_1 = require("../../concurrency"); const utils_1 = require("../../utils"); const ANDROID_PROPERTIES_FILE = 'gradle.properties'; const ANDROID_EXTRA_BUILD_DEPS_KEY = 'android.extraMavenRepos'; @@ -51,7 +52,7 @@ async function resolveModuleAsync(packageName, revision) { plugins, }; } - const projects = await Promise.all(androidProjects.map(async (project) => { + const projects = await (0, concurrency_1.taskAll)(androidProjects, async (project) => { const projectPath = path_1.default.join(revision.path, project.path); const aarProjects = (project.gradleAarProjects ?? [])?.map((aarProject) => { const projectName = `${defaultProjectName}$${aarProject.name}`; @@ -92,7 +93,7 @@ async function resolveModuleAsync(packageName, revision) { ...(publication ? { publication } : {}), ...(aarProjects?.length > 0 ? { aarProjects } : {}), }; - })); + }); const coreFeatures = revision.config?.coreFeatures() ?? []; return { packageName, diff --git a/packages/expo-modules-autolinking/build/platforms/android/android.js.map b/packages/expo-modules-autolinking/build/platforms/android/android.js.map index 259ecd15a70e73..c27b58a5a05966 100644 --- a/packages/expo-modules-autolinking/build/platforms/android/android.js.map +++ b/packages/expo-modules-autolinking/build/platforms/android/android.js.map @@ -1 +1 @@ -{"version":3,"file":"android.js","sourceRoot":"","sources":["../../../src/platforms/android/android.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { AutolinkingOptions } from '../../commands/autolinkingOptions';\nimport type { ExtraDependencies, ModuleDescriptorAndroid, PackageRevision } from '../../types';\nimport { scanFilesRecursively } from '../../utils';\n\nconst ANDROID_PROPERTIES_FILE = 'gradle.properties';\nconst ANDROID_EXTRA_BUILD_DEPS_KEY = 'android.extraMavenRepos';\n\ninterface AndroidConfigurationOutput {\n buildFromSource: string[];\n}\n\nexport function getConfiguration(\n options: AutolinkingOptions\n): AndroidConfigurationOutput | undefined {\n return options.buildFromSource ? { buildFromSource: options.buildFromSource } : undefined;\n}\n\nexport function isAndroidProject(projectRoot: string): boolean {\n return (\n fs.existsSync(path.join(projectRoot, 'build.gradle')) ||\n fs.existsSync(path.join(projectRoot, 'build.gradle.kts'))\n );\n}\n\nexport async function resolveModuleAsync(\n packageName: string,\n revision: PackageRevision\n): Promise {\n // TODO: Relative source dir should be configurable through the module config.\n\n // Don't link itself... :D\n if (packageName === '@unimodules/react-native-adapter') {\n return null;\n }\n\n const plugins = (revision.config?.androidGradlePlugins() ?? []).map(\n ({ id, group, sourceDir, applyToRootProject }) => ({\n id,\n group,\n sourceDir: path.join(revision.path, sourceDir),\n applyToRootProject: applyToRootProject ?? true,\n })\n );\n\n const defaultProjectName = convertPackageToProjectName(packageName);\n\n const androidProjects = revision.config\n ?.androidProjects(defaultProjectName)\n ?.filter((project) => {\n return !project.isDefault || isAndroidProject(path.join(revision.path, project.path));\n });\n\n // Just in case where the module doesn't have its own `build.gradle`/`settings.gradle`.\n if (!androidProjects?.length) {\n if (!plugins.length) {\n return null;\n }\n\n return {\n packageName,\n plugins,\n };\n }\n\n const projects = await Promise.all(\n androidProjects.map(async (project) => {\n const projectPath = path.join(revision.path, project.path);\n\n const aarProjects = (project.gradleAarProjects ?? [])?.map((aarProject) => {\n const projectName = `${defaultProjectName}$${aarProject.name}`;\n const projectDir = path.join(projectPath, 'build', projectName);\n return {\n name: projectName,\n aarFilePath: path.join(revision.path, aarProject.aarFilePath),\n projectDir,\n };\n });\n\n const { publication } = project;\n const shouldUsePublicationScriptPath = project.shouldUsePublicationScriptPath\n ? path.join(revision.path, project.shouldUsePublicationScriptPath)\n : undefined;\n\n const packages = new Set();\n for await (const file of scanFilesRecursively(projectPath)) {\n if (!file.name.endsWith('Package.java') && !file.name.endsWith('Package.kt')) {\n continue;\n }\n const fileContent = await fs.promises.readFile(file.path, 'utf8');\n\n // Very naive check to skip non-expo packages\n if (\n !/\\bimport\\s+expo\\.modules\\.core\\.(interfaces\\.Package|BasePackage)\\b/.test(fileContent)\n ) {\n continue;\n }\n\n const classPathMatches = fileContent.match(/^package ([\\w.]+)\\b/m);\n\n if (classPathMatches) {\n const basename = path.basename(file.name, path.extname(file.name));\n packages.add(`${classPathMatches[1]}.${basename}`);\n }\n }\n\n return {\n name: project.name,\n sourceDir: projectPath,\n modules: project.modules ?? [],\n services: project.services ?? [],\n packages: [...packages].sort((a, b) => a.localeCompare(b)),\n ...(shouldUsePublicationScriptPath ? { shouldUsePublicationScriptPath } : {}),\n ...(publication ? { publication } : {}),\n ...(aarProjects?.length > 0 ? { aarProjects } : {}),\n };\n })\n );\n\n const coreFeatures = revision.config?.coreFeatures() ?? [];\n\n return {\n packageName,\n projects,\n ...(plugins?.length > 0 ? { plugins } : {}),\n ...(coreFeatures.length > 0 ? { coreFeatures } : {}),\n };\n}\n\nexport async function resolveExtraBuildDependenciesAsync(\n projectNativeRoot: string\n): Promise {\n const extraMavenReposString = await resolveGradlePropertyAsync(\n projectNativeRoot,\n ANDROID_EXTRA_BUILD_DEPS_KEY\n );\n if (extraMavenReposString) {\n try {\n return JSON.parse(extraMavenReposString);\n } catch {}\n }\n return null;\n}\n\nexport async function resolveGradlePropertyAsync(\n projectNativeRoot: string,\n propertyKey: string\n): Promise {\n const propsFile = path.join(projectNativeRoot, ANDROID_PROPERTIES_FILE);\n try {\n const contents = await fs.promises.readFile(propsFile, 'utf8');\n const propertyValue = searchGradlePropertyFirst(contents, propertyKey);\n if (propertyValue) {\n return propertyValue;\n }\n } catch {}\n return null;\n}\n\n/**\n * Converts the package name to Android's project name.\n * `/` path will transform as `-`\n *\n * Example: `@expo/example` + `android/build.gradle` → `expo-example`\n */\nexport function convertPackageToProjectName(packageName: string): string {\n return packageName.replace(/^@/g, '').replace(/\\W+/g, '-');\n}\n\n/**\n * Converts the package name and gradle file path to Android's project name.\n * `$` to indicate subprojects\n * `/` path will transform as `-`\n *\n * Example: `@expo/example` + `android/build.gradle` → `expo-example`\n *\n * Example: multiple projects\n * - `expo-test` + `android/build.gradle` → `react-native-third-party`\n * - `expo-test` + `subproject/build.gradle` → `react-native-third-party$subproject`\n */\nexport function convertPackageWithGradleToProjectName(\n packageName: string,\n buildGradleFile: string\n): string {\n const name = convertPackageToProjectName(packageName);\n const baseDir = path.dirname(buildGradleFile).replace(/\\//g, '-');\n return baseDir === 'android' ? name : `${name}$${baseDir}`;\n}\n\n/**\n * Given the contents of a `gradle.properties` file,\n * searches for a property with the given name.\n *\n * This function will return the first property found with the given name.\n * The implementation follows config-plugins and\n * tries to align the behavior with the `withGradleProperties` plugin.\n */\nexport function searchGradlePropertyFirst(contents: string, propertyName: string): string | null {\n const lines = contents.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line && !line.startsWith('#')) {\n const eok = line.indexOf('=');\n const key = line.slice(0, eok);\n if (key === propertyName) {\n const value = line.slice(eok + 1, line.length);\n return value;\n }\n }\n }\n return null;\n}\n"]} \ No newline at end of file +{"version":3,"file":"android.js","sourceRoot":"","sources":["../../../src/platforms/android/android.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { AutolinkingOptions } from '../../commands/autolinkingOptions';\nimport { taskAll } from '../../concurrency';\nimport type { ExtraDependencies, ModuleDescriptorAndroid, PackageRevision } from '../../types';\nimport { scanFilesRecursively } from '../../utils';\n\nconst ANDROID_PROPERTIES_FILE = 'gradle.properties';\nconst ANDROID_EXTRA_BUILD_DEPS_KEY = 'android.extraMavenRepos';\n\ninterface AndroidConfigurationOutput {\n buildFromSource: string[];\n}\n\nexport function getConfiguration(\n options: AutolinkingOptions\n): AndroidConfigurationOutput | undefined {\n return options.buildFromSource ? { buildFromSource: options.buildFromSource } : undefined;\n}\n\nexport function isAndroidProject(projectRoot: string): boolean {\n return (\n fs.existsSync(path.join(projectRoot, 'build.gradle')) ||\n fs.existsSync(path.join(projectRoot, 'build.gradle.kts'))\n );\n}\n\nexport async function resolveModuleAsync(\n packageName: string,\n revision: PackageRevision\n): Promise {\n // TODO: Relative source dir should be configurable through the module config.\n\n // Don't link itself... :D\n if (packageName === '@unimodules/react-native-adapter') {\n return null;\n }\n\n const plugins = (revision.config?.androidGradlePlugins() ?? []).map(\n ({ id, group, sourceDir, applyToRootProject }) => ({\n id,\n group,\n sourceDir: path.join(revision.path, sourceDir),\n applyToRootProject: applyToRootProject ?? true,\n })\n );\n\n const defaultProjectName = convertPackageToProjectName(packageName);\n\n const androidProjects = revision.config\n ?.androidProjects(defaultProjectName)\n ?.filter((project) => {\n return !project.isDefault || isAndroidProject(path.join(revision.path, project.path));\n });\n\n // Just in case where the module doesn't have its own `build.gradle`/`settings.gradle`.\n if (!androidProjects?.length) {\n if (!plugins.length) {\n return null;\n }\n\n return {\n packageName,\n plugins,\n };\n }\n\n const projects = await taskAll(androidProjects, async (project) => {\n const projectPath = path.join(revision.path, project.path);\n\n const aarProjects = (project.gradleAarProjects ?? [])?.map((aarProject) => {\n const projectName = `${defaultProjectName}$${aarProject.name}`;\n const projectDir = path.join(projectPath, 'build', projectName);\n return {\n name: projectName,\n aarFilePath: path.join(revision.path, aarProject.aarFilePath),\n projectDir,\n };\n });\n\n const { publication } = project;\n const shouldUsePublicationScriptPath = project.shouldUsePublicationScriptPath\n ? path.join(revision.path, project.shouldUsePublicationScriptPath)\n : undefined;\n\n const packages = new Set();\n for await (const file of scanFilesRecursively(projectPath)) {\n if (!file.name.endsWith('Package.java') && !file.name.endsWith('Package.kt')) {\n continue;\n }\n const fileContent = await fs.promises.readFile(file.path, 'utf8');\n\n // Very naive check to skip non-expo packages\n if (\n !/\\bimport\\s+expo\\.modules\\.core\\.(interfaces\\.Package|BasePackage)\\b/.test(fileContent)\n ) {\n continue;\n }\n\n const classPathMatches = fileContent.match(/^package ([\\w.]+)\\b/m);\n\n if (classPathMatches) {\n const basename = path.basename(file.name, path.extname(file.name));\n packages.add(`${classPathMatches[1]}.${basename}`);\n }\n }\n\n return {\n name: project.name,\n sourceDir: projectPath,\n modules: project.modules ?? [],\n services: project.services ?? [],\n packages: [...packages].sort((a, b) => a.localeCompare(b)),\n ...(shouldUsePublicationScriptPath ? { shouldUsePublicationScriptPath } : {}),\n ...(publication ? { publication } : {}),\n ...(aarProjects?.length > 0 ? { aarProjects } : {}),\n };\n });\n\n const coreFeatures = revision.config?.coreFeatures() ?? [];\n\n return {\n packageName,\n projects,\n ...(plugins?.length > 0 ? { plugins } : {}),\n ...(coreFeatures.length > 0 ? { coreFeatures } : {}),\n };\n}\n\nexport async function resolveExtraBuildDependenciesAsync(\n projectNativeRoot: string\n): Promise {\n const extraMavenReposString = await resolveGradlePropertyAsync(\n projectNativeRoot,\n ANDROID_EXTRA_BUILD_DEPS_KEY\n );\n if (extraMavenReposString) {\n try {\n return JSON.parse(extraMavenReposString);\n } catch {}\n }\n return null;\n}\n\nexport async function resolveGradlePropertyAsync(\n projectNativeRoot: string,\n propertyKey: string\n): Promise {\n const propsFile = path.join(projectNativeRoot, ANDROID_PROPERTIES_FILE);\n try {\n const contents = await fs.promises.readFile(propsFile, 'utf8');\n const propertyValue = searchGradlePropertyFirst(contents, propertyKey);\n if (propertyValue) {\n return propertyValue;\n }\n } catch {}\n return null;\n}\n\n/**\n * Converts the package name to Android's project name.\n * `/` path will transform as `-`\n *\n * Example: `@expo/example` + `android/build.gradle` → `expo-example`\n */\nexport function convertPackageToProjectName(packageName: string): string {\n return packageName.replace(/^@/g, '').replace(/\\W+/g, '-');\n}\n\n/**\n * Converts the package name and gradle file path to Android's project name.\n * `$` to indicate subprojects\n * `/` path will transform as `-`\n *\n * Example: `@expo/example` + `android/build.gradle` → `expo-example`\n *\n * Example: multiple projects\n * - `expo-test` + `android/build.gradle` → `react-native-third-party`\n * - `expo-test` + `subproject/build.gradle` → `react-native-third-party$subproject`\n */\nexport function convertPackageWithGradleToProjectName(\n packageName: string,\n buildGradleFile: string\n): string {\n const name = convertPackageToProjectName(packageName);\n const baseDir = path.dirname(buildGradleFile).replace(/\\//g, '-');\n return baseDir === 'android' ? name : `${name}$${baseDir}`;\n}\n\n/**\n * Given the contents of a `gradle.properties` file,\n * searches for a property with the given name.\n *\n * This function will return the first property found with the given name.\n * The implementation follows config-plugins and\n * tries to align the behavior with the `withGradleProperties` plugin.\n */\nexport function searchGradlePropertyFirst(contents: string, propertyName: string): string | null {\n const lines = contents.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line && !line.startsWith('#')) {\n const eok = line.indexOf('=');\n const key = line.slice(0, eok);\n if (key === propertyName) {\n const value = line.slice(eok + 1, line.length);\n return value;\n }\n }\n }\n return null;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js index 9171c5187efcc2..a46f4f0d00493c 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js @@ -12,6 +12,7 @@ exports.parseComponentDescriptorsAsync = parseComponentDescriptorsAsync; exports.findGradleAndManifestAsync = findGradleAndManifestAsync; const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); +const concurrency_1 = require("../concurrency"); const utils_1 = require("../utils"); async function resolveDependencyConfigImplAndroidAsync(packageRoot, reactNativeConfig, expoModuleConfig) { if (reactNativeConfig === null) { @@ -258,7 +259,7 @@ const findAndroidManifestsAsync = async (targetPath) => { return manifestPaths.sort((a, b) => a.localeCompare(b)); }; const getFileCandidatesAsync = async (targetPath, fileNames) => { - const gradlePaths = await Promise.all(fileNames.map((fileName) => (0, utils_1.fileExistsAsync)(path_1.default.join(targetPath, fileName)))); + const gradlePaths = await (0, concurrency_1.taskAll)(fileNames, (fileName) => (0, utils_1.fileExistsAsync)(path_1.default.join(targetPath, fileName))); return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b)); }; async function findGradleAndManifestAsync({ androidDir, isLibrary, }) { diff --git a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map index 270fe5538824c4..282411e008025d 100644 --- a/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map +++ b/packages/expo-modules-autolinking/build/reactNativeConfig/androidResolver.js.map @@ -1 +1 @@ -{"version":3,"file":"androidResolver.js","sourceRoot":"","sources":["../../src/reactNativeConfig/androidResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nimport type {\n RNConfigDependencyAndroid,\n RNConfigReactNativePlatformsConfigAndroid,\n} from './reactNativeConfig.types';\nimport type { ExpoModuleConfig } from '../ExpoModuleConfig';\nimport { scanFilesRecursively, fileExistsAsync, fastJoin, loadPackageJson } from '../utils';\n\nexport async function resolveDependencyConfigImplAndroidAsync(\n packageRoot: string,\n reactNativeConfig: RNConfigReactNativePlatformsConfigAndroid | null | undefined,\n expoModuleConfig?: ExpoModuleConfig | null\n): Promise {\n if (reactNativeConfig === null) {\n // Skip autolinking for this package.\n return null;\n }\n\n // NOTE(@kitten): We allow `reactNativeConfig === undefined` here. That indicates a missing config file\n // However, React Native modules with left out config files are explicitly supported and valid\n\n const sourceDir = reactNativeConfig?.sourceDir || 'android';\n const androidDir = path.join(packageRoot, sourceDir);\n const { gradle, manifest } = await findGradleAndManifestAsync({ androidDir, isLibrary: true });\n\n const isPureCxxDependency =\n reactNativeConfig?.cxxModuleCMakeListsModuleName != null &&\n reactNativeConfig?.cxxModuleCMakeListsPath != null &&\n reactNativeConfig?.cxxModuleHeaderName != null &&\n !manifest &&\n !gradle;\n\n if (!manifest && !gradle && !isPureCxxDependency) {\n return null;\n }\n\n if (reactNativeConfig === undefined && expoModuleConfig?.supportsPlatform('android')) {\n if (!!gradle && !expoModuleConfig?.rawConfig.android?.gradlePath) {\n // If the React Native module has a gradle file and the Expo module doesn't redirect it,\n // they will conflict and we can't link both at the same time\n return null;\n }\n }\n\n let packageInstance: string | null = null;\n let packageImportPath: string | null = null;\n if (!isPureCxxDependency) {\n const packageName =\n reactNativeConfig?.packageName || (await parsePackageNameAsync(manifest, gradle));\n if (!packageName) {\n return null;\n }\n const nativePackageClassName = await parseNativePackageClassNameAsync(packageRoot, androidDir);\n if (!nativePackageClassName) {\n return null;\n }\n packageImportPath =\n reactNativeConfig?.packageImportPath || `import ${packageName}.${nativePackageClassName};`;\n packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`;\n }\n\n const packageJson = await loadPackageJson(fastJoin(packageRoot, 'package.json'));\n const buildTypes = reactNativeConfig?.buildTypes || [];\n const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration;\n const libraryName =\n reactNativeConfig?.libraryName || (await parseLibraryNameAsync(androidDir, packageJson));\n const componentDescriptors =\n reactNativeConfig?.componentDescriptors ||\n (await parseComponentDescriptorsAsync(packageRoot, packageJson));\n let cmakeListsPath = reactNativeConfig?.cmakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cmakeListsPath)\n : path.join(androidDir, 'build/generated/source/codegen/jni/CMakeLists.txt');\n const cxxModuleCMakeListsModuleName = reactNativeConfig?.cxxModuleCMakeListsModuleName || null;\n const cxxModuleHeaderName = reactNativeConfig?.cxxModuleHeaderName || null;\n let cxxModuleCMakeListsPath = reactNativeConfig?.cxxModuleCMakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cxxModuleCMakeListsPath)\n : null;\n if (process.platform === 'win32') {\n cmakeListsPath = cmakeListsPath.replace(/\\\\/g, '/');\n if (cxxModuleCMakeListsPath) {\n cxxModuleCMakeListsPath = cxxModuleCMakeListsPath.replace(/\\\\/g, '/');\n }\n }\n\n const result: RNConfigDependencyAndroid = {\n sourceDir: androidDir,\n packageImportPath,\n packageInstance,\n dependencyConfiguration,\n buildTypes,\n libraryName,\n componentDescriptors,\n cmakeListsPath,\n cxxModuleCMakeListsModuleName,\n cxxModuleCMakeListsPath,\n cxxModuleHeaderName,\n isPureCxxDependency,\n };\n if (!result.libraryName) {\n delete result.libraryName;\n }\n if (!result.dependencyConfiguration) {\n delete result.dependencyConfiguration;\n }\n return result;\n}\n\n/**\n * Parse the `RNConfigDependencyAndroid.packageName`\n */\nexport async function parsePackageNameAsync(\n manifestPath: string | null,\n gradlePath: string | null\n): Promise {\n if (gradlePath) {\n const gradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = gradleContents.match(/namespace\\s*[=]*\\s*[\"'](.+?)[\"']/);\n if (match) {\n return match[1];\n }\n }\n if (manifestPath) {\n const manifestContents = await fs.readFile(manifestPath, 'utf8');\n const match = manifestContents.match(/package=\"(.+?)\"/);\n if (match) {\n return match[1];\n }\n }\n return null;\n}\n\n/**\n * Parse the Java or Kotlin class name to for `ReactPackage` or `(Base|Turbo)ReactPackage`.\n */\nexport async function parseNativePackageClassNameAsync(\n packageRoot: string,\n androidDir: string\n): Promise {\n // Search for **/*Package.{java,kt} files first\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('Package.java') || entry.name.endsWith('Package.kt')) {\n try {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n } catch {\n continue;\n }\n }\n }\n\n // Early return if the module is an Expo module\n if (await fileExistsAsync(path.join(packageRoot, 'expo-module.config.json'))) {\n return null;\n }\n\n // Search all **/*.{java,kt} files\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('.java') || entry.name.endsWith('.kt')) {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n }\n }\n return null;\n}\n\nlet lazyReactPackageRegex: RegExp | null = null;\nlet lazyTurboReactPackageRegex: RegExp | null = null;\nexport function matchNativePackageClassName(_filePath: string, contents: Buffer): string | null {\n const fileContents = contents.toString();\n\n // [0] Match ReactPackage\n if (!lazyReactPackageRegex) {\n lazyReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+implements\\s+|:)[\\s\\w():,]*[^{]*ReactPackage/;\n }\n const matchReactPackage = fileContents.match(lazyReactPackageRegex);\n if (matchReactPackage) {\n return matchReactPackage[1];\n }\n\n // [1] Match (Base|Turbo)ReactPackage\n if (!lazyTurboReactPackageRegex) {\n lazyTurboReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+extends\\s+|:)[\\s\\w():,]*[^{]*(Base|Turbo)ReactPackage/;\n }\n const matchTurboReactPackage = fileContents.match(lazyTurboReactPackageRegex);\n if (matchTurboReactPackage) {\n return matchTurboReactPackage[1];\n }\n\n return null;\n}\n\nexport async function parseLibraryNameAsync(\n androidDir: string,\n packageJson: any\n): Promise {\n // [0] `codegenConfig.name` from package.json\n if (packageJson.codegenConfig?.name) {\n return packageJson.codegenConfig.name;\n }\n\n const libraryNameRegExp = /libraryName = [\"'](.+)[\"']/;\n const gradlePath = path.join(androidDir, 'build.gradle');\n // [1] `libraryName` from build.gradle\n if (await fileExistsAsync(gradlePath)) {\n const buildGradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n // [2] `libraryName` from build.gradle.kts\n const gradleKtsPath = path.join(androidDir, 'build.gradle.kts');\n if (await fileExistsAsync(gradleKtsPath)) {\n const buildGradleContents = await fs.readFile(gradleKtsPath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n return null;\n}\n\nexport async function parseComponentDescriptorsAsync(\n packageRoot: string,\n packageJson: any\n): Promise {\n const jsRoot = packageJson?.codegenConfig?.jsSrcsDir\n ? path.join(packageRoot, packageJson.codegenConfig.jsSrcsDir)\n : packageRoot;\n const extRe = /\\.[tj]sx?$/;\n const results = new Set();\n for await (const entry of scanFilesRecursively(jsRoot)) {\n if (extRe.test(entry.name)) {\n const contents = await fs.readFile(entry.path, 'utf8');\n const matched = matchComponentDescriptors(entry.path, contents);\n if (matched) {\n results.add(matched);\n }\n }\n }\n return [...results].sort((a, b) => a.localeCompare(b));\n}\n\nlet lazyCodegenComponentRegex: RegExp | null = null;\nfunction matchComponentDescriptors(_filePath: string, contents: string): string | null {\n if (!lazyCodegenComponentRegex) {\n lazyCodegenComponentRegex =\n /codegenNativeComponent(<.*>)?\\s*\\(\\s*[\"'`](\\w+)[\"'`](,?[\\s\\S]+interfaceOnly:\\s*(\\w+))?/m;\n }\n const match = contents.match(lazyCodegenComponentRegex);\n if (!(match?.[4] === 'true') && match?.[2]) {\n return `${match[2]}ComponentDescriptor`;\n }\n return null;\n}\n\nconst findAndroidManifestsAsync = async (targetPath: string) => {\n const files = scanFilesRecursively(targetPath, (parentPath, name) => {\n switch (name) {\n case 'build':\n case 'debug':\n case 'Pods':\n return false;\n case 'Examples':\n case 'examples':\n // Only ignore top-level examples directories in `targetPath` but not nested ones\n return parentPath !== targetPath;\n case 'android':\n return !/[\\\\/]sdks[\\\\/]hermes$/.test(parentPath);\n case 'androidTest':\n case 'test':\n return !/[\\\\/]src$/.test(parentPath);\n default:\n return true;\n }\n });\n const manifestPaths: string[] = [];\n for await (const entry of files) {\n if (entry.name === 'AndroidManifest.xml') {\n manifestPaths.push(entry.path);\n }\n }\n return manifestPaths.sort((a, b) => a.localeCompare(b));\n};\n\nconst getFileCandidatesAsync = async (targetPath: string, fileNames: string[]) => {\n const gradlePaths = await Promise.all(\n fileNames.map((fileName) => fileExistsAsync(path.join(targetPath, fileName)))\n );\n return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b));\n};\n\nexport async function findGradleAndManifestAsync({\n androidDir,\n isLibrary,\n}: {\n androidDir: string;\n isLibrary: boolean;\n}): Promise<{ gradle: string | null; manifest: string | null }> {\n const [manifests, gradles] = await Promise.all([\n findAndroidManifestsAsync(androidDir),\n getFileCandidatesAsync(isLibrary ? androidDir : path.join(androidDir, 'app'), [\n 'build.gradle',\n 'build.gradle.kts',\n ]),\n ]);\n // TODO(@kitten): We can't optimise this because of the prior `includes()` pattern. Is this meant to be startsWith?\n const manifest =\n manifests.find((manifest) => manifest.includes('src/main/')) ??\n manifests.sort((a, b) => a.localeCompare(b))[0];\n const gradle = gradles.sort((a, b) => a.localeCompare(b))[0];\n return { gradle: gradle || null, manifest: manifest || null };\n}\n"]} \ No newline at end of file +{"version":3,"file":"androidResolver.js","sourceRoot":"","sources":["../../src/reactNativeConfig/androidResolver.ts"],"names":[],"mappings":";;;;;AAWA,0FAiGC;AAKD,sDAmBC;AAKD,4EAmCC;AAID,kEAwBC;AAED,sDA+BC;AAED,wEAmBC;AAmDD,gEAoBC;AArUD,2DAA6B;AAC7B,gDAAwB;AAOxB,gDAAyC;AACzC,oCAA4F;AAErF,KAAK,UAAU,uCAAuC,CAC3D,WAAmB,EACnB,iBAA+E,EAC/E,gBAA0C;IAE1C,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,qCAAqC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uGAAuG;IACvG,8FAA8F;IAE9F,MAAM,SAAS,GAAG,iBAAiB,EAAE,SAAS,IAAI,SAAS,CAAC;IAC5D,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,0BAA0B,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/F,MAAM,mBAAmB,GACvB,iBAAiB,EAAE,6BAA6B,IAAI,IAAI;QACxD,iBAAiB,EAAE,uBAAuB,IAAI,IAAI;QAClD,iBAAiB,EAAE,mBAAmB,IAAI,IAAI;QAC9C,CAAC,QAAQ;QACT,CAAC,MAAM,CAAC;IAEV,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,iBAAiB,KAAK,SAAS,IAAI,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;QACrF,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;YACjE,wFAAwF;YACxF,6DAA6D;YAC7D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,IAAI,iBAAiB,GAAkB,IAAI,CAAC;IAC5C,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,WAAW,GACf,iBAAiB,EAAE,WAAW,IAAI,CAAC,MAAM,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACpF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,sBAAsB,GAAG,MAAM,gCAAgC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC/F,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,iBAAiB;YACf,iBAAiB,EAAE,iBAAiB,IAAI,UAAU,WAAW,IAAI,sBAAsB,GAAG,CAAC;QAC7F,eAAe,GAAG,iBAAiB,EAAE,eAAe,IAAI,OAAO,sBAAsB,IAAI,CAAC;IAC5F,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,IAAA,uBAAe,EAAC,IAAA,gBAAQ,EAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;IACjF,MAAM,UAAU,GAAG,iBAAiB,EAAE,UAAU,IAAI,EAAE,CAAC;IACvD,MAAM,uBAAuB,GAAG,iBAAiB,EAAE,uBAAuB,CAAC;IAC3E,MAAM,WAAW,GACf,iBAAiB,EAAE,WAAW,IAAI,CAAC,MAAM,qBAAqB,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAC3F,MAAM,oBAAoB,GACxB,iBAAiB,EAAE,oBAAoB;QACvC,CAAC,MAAM,8BAA8B,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IACnE,IAAI,cAAc,GAAG,iBAAiB,EAAE,cAAc;QACpD,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,cAAc,CAAC;QAC1D,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,mDAAmD,CAAC,CAAC;IAC/E,MAAM,6BAA6B,GAAG,iBAAiB,EAAE,6BAA6B,IAAI,IAAI,CAAC;IAC/F,MAAM,mBAAmB,GAAG,iBAAiB,EAAE,mBAAmB,IAAI,IAAI,CAAC;IAC3E,IAAI,uBAAuB,GAAG,iBAAiB,EAAE,uBAAuB;QACtE,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,uBAAuB,CAAC;QACnE,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,uBAAuB,EAAE,CAAC;YAC5B,uBAAuB,GAAG,uBAAuB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA8B;QACxC,SAAS,EAAE,UAAU;QACrB,iBAAiB;QACjB,eAAe;QACf,uBAAuB;QACvB,UAAU;QACV,WAAW;QACX,oBAAoB;QACpB,cAAc;QACd,6BAA6B;QAC7B,uBAAuB;QACvB,mBAAmB;QACnB,mBAAmB;KACpB,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,uBAAuB,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,uBAAuB,CAAC;IACxC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,qBAAqB,CACzC,YAA2B,EAC3B,UAAyB;IAEzB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,cAAc,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACvE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,gBAAgB,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACjE,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,gCAAgC,CACpD,WAAmB,EACnB,UAAkB;IAElB,+CAA+C;IAC/C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAA,4BAAoB,EAAC,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5E,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7E,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC/C,MAAM,OAAO,GAAG,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBAClE,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,OAAO,CAAC;gBACjB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,IAAI,MAAM,IAAA,uBAAe,EAAC,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,yBAAyB,CAAC,CAAC,EAAE,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kCAAkC;IAClC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAA,4BAAoB,EAAC,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5E,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAClE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,IAAI,qBAAqB,GAAkB,IAAI,CAAC;AAChD,IAAI,0BAA0B,GAAkB,IAAI,CAAC;AACrD,SAAgB,2BAA2B,CAAC,SAAiB,EAAE,QAAgB;IAC7E,MAAM,YAAY,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAEzC,yBAAyB;IACzB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC3B,qBAAqB;YACnB,gFAAgF,CAAC;IACrF,CAAC;IACD,MAAM,iBAAiB,GAAG,YAAY,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACpE,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAChC,0BAA0B;YACxB,yFAAyF,CAAC;IAC9F,CAAC;IACD,MAAM,sBAAsB,GAAG,YAAY,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9E,IAAI,sBAAsB,EAAE,CAAC;QAC3B,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAEM,KAAK,UAAU,qBAAqB,CACzC,UAAkB,EAClB,WAAgB;IAEhB,6CAA6C;IAC7C,IAAI,WAAW,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;QACpC,OAAO,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC;IACxC,CAAC;IAED,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;IACvD,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACzD,sCAAsC;IACtC,IAAI,MAAM,IAAA,uBAAe,EAAC,UAAU,CAAC,EAAE,CAAC;QACtC,MAAM,mBAAmB,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3D,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAChE,IAAI,MAAM,IAAA,uBAAe,EAAC,aAAa,CAAC,EAAE,CAAC;QACzC,MAAM,mBAAmB,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3D,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAEM,KAAK,UAAU,8BAA8B,CAClD,WAAmB,EACnB,WAAgB;IAEhB,MAAM,MAAM,GAAG,WAAW,EAAE,aAAa,EAAE,SAAS;QAClD,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC;QAC7D,CAAC,CAAC,WAAW,CAAC;IAChB,MAAM,KAAK,GAAG,YAAY,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAA,4BAAoB,EAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACvD,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAChE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,yBAAyB,GAAkB,IAAI,CAAC;AACpD,SAAS,yBAAyB,CAAC,SAAiB,EAAE,QAAgB;IACpE,IAAI,CAAC,yBAAyB,EAAE,CAAC;QAC/B,yBAAyB;YACvB,yFAAyF,CAAC;IAC9F,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,yBAAyB,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;IAC7D,MAAM,KAAK,GAAG,IAAA,4BAAoB,EAAC,UAAU,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE;QAClE,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,OAAO,CAAC;YACb,KAAK,OAAO,CAAC;YACb,KAAK,MAAM;gBACT,OAAO,KAAK,CAAC;YACf,KAAK,UAAU,CAAC;YAChB,KAAK,UAAU;gBACb,iFAAiF;gBACjF,OAAO,UAAU,KAAK,UAAU,CAAC;YACnC,KAAK,SAAS;gBACZ,OAAO,CAAC,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnD,KAAK,aAAa,CAAC;YACnB,KAAK,MAAM;gBACT,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvC;gBACE,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACzC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,KAAK,EAAE,UAAkB,EAAE,SAAmB,EAAE,EAAE;IAC/E,MAAM,WAAW,GAAG,MAAM,IAAA,qBAAO,EAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxD,IAAA,uBAAe,EAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CACjD,CAAC;IACF,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC,CAAC;AAEK,KAAK,UAAU,0BAA0B,CAAC,EAC/C,UAAU,EACV,SAAS,GAIV;IACC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7C,yBAAyB,CAAC,UAAU,CAAC;QACrC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE;YAC5E,cAAc;YACd,kBAAkB;SACnB,CAAC;KACH,CAAC,CAAC;IACH,mHAAmH;IACnH,MAAM,QAAQ,GACZ,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5D,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAChE,CAAC","sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\n\nimport type {\n RNConfigDependencyAndroid,\n RNConfigReactNativePlatformsConfigAndroid,\n} from './reactNativeConfig.types';\nimport type { ExpoModuleConfig } from '../ExpoModuleConfig';\nimport { taskAll } from '../concurrency';\nimport { scanFilesRecursively, fileExistsAsync, fastJoin, loadPackageJson } from '../utils';\n\nexport async function resolveDependencyConfigImplAndroidAsync(\n packageRoot: string,\n reactNativeConfig: RNConfigReactNativePlatformsConfigAndroid | null | undefined,\n expoModuleConfig?: ExpoModuleConfig | null\n): Promise {\n if (reactNativeConfig === null) {\n // Skip autolinking for this package.\n return null;\n }\n\n // NOTE(@kitten): We allow `reactNativeConfig === undefined` here. That indicates a missing config file\n // However, React Native modules with left out config files are explicitly supported and valid\n\n const sourceDir = reactNativeConfig?.sourceDir || 'android';\n const androidDir = path.join(packageRoot, sourceDir);\n const { gradle, manifest } = await findGradleAndManifestAsync({ androidDir, isLibrary: true });\n\n const isPureCxxDependency =\n reactNativeConfig?.cxxModuleCMakeListsModuleName != null &&\n reactNativeConfig?.cxxModuleCMakeListsPath != null &&\n reactNativeConfig?.cxxModuleHeaderName != null &&\n !manifest &&\n !gradle;\n\n if (!manifest && !gradle && !isPureCxxDependency) {\n return null;\n }\n\n if (reactNativeConfig === undefined && expoModuleConfig?.supportsPlatform('android')) {\n if (!!gradle && !expoModuleConfig?.rawConfig.android?.gradlePath) {\n // If the React Native module has a gradle file and the Expo module doesn't redirect it,\n // they will conflict and we can't link both at the same time\n return null;\n }\n }\n\n let packageInstance: string | null = null;\n let packageImportPath: string | null = null;\n if (!isPureCxxDependency) {\n const packageName =\n reactNativeConfig?.packageName || (await parsePackageNameAsync(manifest, gradle));\n if (!packageName) {\n return null;\n }\n const nativePackageClassName = await parseNativePackageClassNameAsync(packageRoot, androidDir);\n if (!nativePackageClassName) {\n return null;\n }\n packageImportPath =\n reactNativeConfig?.packageImportPath || `import ${packageName}.${nativePackageClassName};`;\n packageInstance = reactNativeConfig?.packageInstance || `new ${nativePackageClassName}()`;\n }\n\n const packageJson = await loadPackageJson(fastJoin(packageRoot, 'package.json'));\n const buildTypes = reactNativeConfig?.buildTypes || [];\n const dependencyConfiguration = reactNativeConfig?.dependencyConfiguration;\n const libraryName =\n reactNativeConfig?.libraryName || (await parseLibraryNameAsync(androidDir, packageJson));\n const componentDescriptors =\n reactNativeConfig?.componentDescriptors ||\n (await parseComponentDescriptorsAsync(packageRoot, packageJson));\n let cmakeListsPath = reactNativeConfig?.cmakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cmakeListsPath)\n : path.join(androidDir, 'build/generated/source/codegen/jni/CMakeLists.txt');\n const cxxModuleCMakeListsModuleName = reactNativeConfig?.cxxModuleCMakeListsModuleName || null;\n const cxxModuleHeaderName = reactNativeConfig?.cxxModuleHeaderName || null;\n let cxxModuleCMakeListsPath = reactNativeConfig?.cxxModuleCMakeListsPath\n ? path.join(androidDir, reactNativeConfig?.cxxModuleCMakeListsPath)\n : null;\n if (process.platform === 'win32') {\n cmakeListsPath = cmakeListsPath.replace(/\\\\/g, '/');\n if (cxxModuleCMakeListsPath) {\n cxxModuleCMakeListsPath = cxxModuleCMakeListsPath.replace(/\\\\/g, '/');\n }\n }\n\n const result: RNConfigDependencyAndroid = {\n sourceDir: androidDir,\n packageImportPath,\n packageInstance,\n dependencyConfiguration,\n buildTypes,\n libraryName,\n componentDescriptors,\n cmakeListsPath,\n cxxModuleCMakeListsModuleName,\n cxxModuleCMakeListsPath,\n cxxModuleHeaderName,\n isPureCxxDependency,\n };\n if (!result.libraryName) {\n delete result.libraryName;\n }\n if (!result.dependencyConfiguration) {\n delete result.dependencyConfiguration;\n }\n return result;\n}\n\n/**\n * Parse the `RNConfigDependencyAndroid.packageName`\n */\nexport async function parsePackageNameAsync(\n manifestPath: string | null,\n gradlePath: string | null\n): Promise {\n if (gradlePath) {\n const gradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = gradleContents.match(/namespace\\s*[=]*\\s*[\"'](.+?)[\"']/);\n if (match) {\n return match[1];\n }\n }\n if (manifestPath) {\n const manifestContents = await fs.readFile(manifestPath, 'utf8');\n const match = manifestContents.match(/package=\"(.+?)\"/);\n if (match) {\n return match[1];\n }\n }\n return null;\n}\n\n/**\n * Parse the Java or Kotlin class name to for `ReactPackage` or `(Base|Turbo)ReactPackage`.\n */\nexport async function parseNativePackageClassNameAsync(\n packageRoot: string,\n androidDir: string\n): Promise {\n // Search for **/*Package.{java,kt} files first\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('Package.java') || entry.name.endsWith('Package.kt')) {\n try {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n } catch {\n continue;\n }\n }\n }\n\n // Early return if the module is an Expo module\n if (await fileExistsAsync(path.join(packageRoot, 'expo-module.config.json'))) {\n return null;\n }\n\n // Search all **/*.{java,kt} files\n for await (const entry of scanFilesRecursively(androidDir, undefined, true)) {\n if (entry.name.endsWith('.java') || entry.name.endsWith('.kt')) {\n const contents = await fs.readFile(entry.path);\n const matched = matchNativePackageClassName(entry.path, contents);\n if (matched) {\n return matched;\n }\n }\n }\n return null;\n}\n\nlet lazyReactPackageRegex: RegExp | null = null;\nlet lazyTurboReactPackageRegex: RegExp | null = null;\nexport function matchNativePackageClassName(_filePath: string, contents: Buffer): string | null {\n const fileContents = contents.toString();\n\n // [0] Match ReactPackage\n if (!lazyReactPackageRegex) {\n lazyReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+implements\\s+|:)[\\s\\w():,]*[^{]*ReactPackage/;\n }\n const matchReactPackage = fileContents.match(lazyReactPackageRegex);\n if (matchReactPackage) {\n return matchReactPackage[1];\n }\n\n // [1] Match (Base|Turbo)ReactPackage\n if (!lazyTurboReactPackageRegex) {\n lazyTurboReactPackageRegex =\n /class\\s+(\\w+[^(\\s]*)[\\s\\w():]*(\\s+extends\\s+|:)[\\s\\w():,]*[^{]*(Base|Turbo)ReactPackage/;\n }\n const matchTurboReactPackage = fileContents.match(lazyTurboReactPackageRegex);\n if (matchTurboReactPackage) {\n return matchTurboReactPackage[1];\n }\n\n return null;\n}\n\nexport async function parseLibraryNameAsync(\n androidDir: string,\n packageJson: any\n): Promise {\n // [0] `codegenConfig.name` from package.json\n if (packageJson.codegenConfig?.name) {\n return packageJson.codegenConfig.name;\n }\n\n const libraryNameRegExp = /libraryName = [\"'](.+)[\"']/;\n const gradlePath = path.join(androidDir, 'build.gradle');\n // [1] `libraryName` from build.gradle\n if (await fileExistsAsync(gradlePath)) {\n const buildGradleContents = await fs.readFile(gradlePath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n // [2] `libraryName` from build.gradle.kts\n const gradleKtsPath = path.join(androidDir, 'build.gradle.kts');\n if (await fileExistsAsync(gradleKtsPath)) {\n const buildGradleContents = await fs.readFile(gradleKtsPath, 'utf8');\n const match = buildGradleContents.match(libraryNameRegExp);\n if (match) {\n return match[1];\n }\n }\n\n return null;\n}\n\nexport async function parseComponentDescriptorsAsync(\n packageRoot: string,\n packageJson: any\n): Promise {\n const jsRoot = packageJson?.codegenConfig?.jsSrcsDir\n ? path.join(packageRoot, packageJson.codegenConfig.jsSrcsDir)\n : packageRoot;\n const extRe = /\\.[tj]sx?$/;\n const results = new Set();\n for await (const entry of scanFilesRecursively(jsRoot)) {\n if (extRe.test(entry.name)) {\n const contents = await fs.readFile(entry.path, 'utf8');\n const matched = matchComponentDescriptors(entry.path, contents);\n if (matched) {\n results.add(matched);\n }\n }\n }\n return [...results].sort((a, b) => a.localeCompare(b));\n}\n\nlet lazyCodegenComponentRegex: RegExp | null = null;\nfunction matchComponentDescriptors(_filePath: string, contents: string): string | null {\n if (!lazyCodegenComponentRegex) {\n lazyCodegenComponentRegex =\n /codegenNativeComponent(<.*>)?\\s*\\(\\s*[\"'`](\\w+)[\"'`](,?[\\s\\S]+interfaceOnly:\\s*(\\w+))?/m;\n }\n const match = contents.match(lazyCodegenComponentRegex);\n if (!(match?.[4] === 'true') && match?.[2]) {\n return `${match[2]}ComponentDescriptor`;\n }\n return null;\n}\n\nconst findAndroidManifestsAsync = async (targetPath: string) => {\n const files = scanFilesRecursively(targetPath, (parentPath, name) => {\n switch (name) {\n case 'build':\n case 'debug':\n case 'Pods':\n return false;\n case 'Examples':\n case 'examples':\n // Only ignore top-level examples directories in `targetPath` but not nested ones\n return parentPath !== targetPath;\n case 'android':\n return !/[\\\\/]sdks[\\\\/]hermes$/.test(parentPath);\n case 'androidTest':\n case 'test':\n return !/[\\\\/]src$/.test(parentPath);\n default:\n return true;\n }\n });\n const manifestPaths: string[] = [];\n for await (const entry of files) {\n if (entry.name === 'AndroidManifest.xml') {\n manifestPaths.push(entry.path);\n }\n }\n return manifestPaths.sort((a, b) => a.localeCompare(b));\n};\n\nconst getFileCandidatesAsync = async (targetPath: string, fileNames: string[]) => {\n const gradlePaths = await taskAll(fileNames, (fileName) =>\n fileExistsAsync(path.join(targetPath, fileName))\n );\n return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b));\n};\n\nexport async function findGradleAndManifestAsync({\n androidDir,\n isLibrary,\n}: {\n androidDir: string;\n isLibrary: boolean;\n}): Promise<{ gradle: string | null; manifest: string | null }> {\n const [manifests, gradles] = await Promise.all([\n findAndroidManifestsAsync(androidDir),\n getFileCandidatesAsync(isLibrary ? androidDir : path.join(androidDir, 'app'), [\n 'build.gradle',\n 'build.gradle.kts',\n ]),\n ]);\n // TODO(@kitten): We can't optimise this because of the prior `includes()` pattern. Is this meant to be startsWith?\n const manifest =\n manifests.find((manifest) => manifest.includes('src/main/')) ??\n manifests.sort((a, b) => a.localeCompare(b))[0];\n const gradle = gradles.sort((a, b) => a.localeCompare(b))[0];\n return { gradle: gradle || null, manifest: manifest || null };\n}\n"]} \ No newline at end of file diff --git a/packages/expo-modules-autolinking/src/__tests__/concurrency-test.ts b/packages/expo-modules-autolinking/src/__tests__/concurrency-test.ts new file mode 100644 index 00000000000000..b1500000c9ed63 --- /dev/null +++ b/packages/expo-modules-autolinking/src/__tests__/concurrency-test.ts @@ -0,0 +1,71 @@ +import { createLimiter } from '../concurrency'; + +const withResolvers = () => { + let resolve: (value: T) => void; + const promise = new Promise((_resolve) => { + resolve = _resolve; + }); + return { + promise, + resolve(value: T): Promise { + resolve(value); + return promise.then(() => Promise.resolve()); + }, + }; +}; + +describe(createLimiter, () => { + it('limits concurrent executions', async () => { + const a = withResolvers(); + const b = withResolvers(); + const c = withResolvers(); + const d = withResolvers(); + + const limit = createLimiter(2); + const started: string[] = []; + const stopped: string[] = []; + + limit(async () => { + started.push('a'); + await a.promise; + stopped.push('a'); + }); + limit(async () => { + started.push('b'); + await b.promise; + stopped.push('b'); + }); + limit(async () => { + started.push('c'); + await c.promise; + stopped.push('c'); + }); + limit(async () => { + started.push('d'); + await d.promise; + stopped.push('d'); + }); + + expect(started).toEqual(['a', 'b']); + expect(stopped).toEqual([]); + + await a.resolve(); + expect(stopped).toEqual(['a']); + + await c.resolve(); + expect(started).toEqual(['a', 'b', 'c', 'd']); + expect(stopped).toEqual(['a', 'c']); + + await b.resolve(); + expect(stopped).toEqual(['a', 'c', 'b']); + + await d.resolve(); + expect(stopped).toEqual(['a', 'c', 'b', 'd']); + + await limit(async () => { + stopped.push('e'); + }); + + expect(stopped).toEqual(['a', 'c', 'b', 'd', 'e']); + }); +}); diff --git a/packages/expo-modules-autolinking/src/autolinking/resolveModules.ts b/packages/expo-modules-autolinking/src/autolinking/resolveModules.ts index 5b05aafd9a43cc..88d9d090076a33 100644 --- a/packages/expo-modules-autolinking/src/autolinking/resolveModules.ts +++ b/packages/expo-modules-autolinking/src/autolinking/resolveModules.ts @@ -1,4 +1,5 @@ import { AutolinkingOptions } from '../commands/autolinkingOptions'; +import { taskAll } from '../concurrency'; import { getLinkingImplementationForPlatform } from '../platforms'; import type { ExtraDependencies, @@ -16,8 +17,9 @@ export async function resolveModulesAsync( // Additional output property for Cocoapods flags const extraOutput = { flags: autolinkingOptions.flags }; - const moduleDescriptorList = await Promise.all( - Object.entries(searchResults).map(async ([packageName, revision]) => { + const moduleDescriptorList = await taskAll( + Object.entries(searchResults), + async ([packageName, revision]) => { const resolvedModule = await platformLinking.resolveModuleAsync( packageName, revision, @@ -30,7 +32,7 @@ export async function resolveModulesAsync( packageName: resolvedModule.packageName ?? packageName, } : null; - }) + } ); return moduleDescriptorList diff --git a/packages/expo-modules-autolinking/src/concurrency.ts b/packages/expo-modules-autolinking/src/concurrency.ts new file mode 100644 index 00000000000000..1f9014f873e67d --- /dev/null +++ b/packages/expo-modules-autolinking/src/concurrency.ts @@ -0,0 +1,67 @@ +export interface Limiter { + ( + fn: (...args: Arguments) => PromiseLike | ReturnType, + ...args: Arguments + ): Promise; +} + +interface QueueItem { + resolve(): void; + next: QueueItem | null; +} + +export const createLimiter = (limit: number): Limiter => { + let running = 0; + let head: QueueItem | null = null; + let tail: QueueItem | null = null; + + const enqueue = () => + new Promise((resolve) => { + const item: QueueItem = { resolve, next: null }; + if (tail) { + tail.next = item; + tail = item; + } else { + head = item; + tail = item; + } + }); + + const dequeue = () => { + if (running < limit && head !== null) { + const { resolve, next } = head; + head.next = null; + head = next; + if (head === null) { + tail = null; + } + running++; + resolve(); + } + }; + + return async (fn, ...args) => { + if (running < limit) { + running++; + } else { + await enqueue(); + } + try { + return await fn(...args); + } finally { + running--; + dequeue(); + } + }; +}; + +export const taskAll = (inputs: T[], map: (input: T) => Promise): Promise => { + // NOTE: This doesn't depend on CPU cores, but instead is hard-coded depending on + // number of concurrent IO-bound tasks. `taskAll` can be called concurrently, and + // we don't keep track of concurrent `taskAll` calls in expo-modules-autolinking. + // There's a fixed number of concurrent pending IO operations that Node.js handles + // nicely. It seems that expo-modules-autolinking behaves nicely when this number + // is around ~8, but this may be higher if disk + core speed is higher. + const limiter = createLimiter(8); + return Promise.all(inputs.map((input) => limiter(map, input))); +}; diff --git a/packages/expo-modules-autolinking/src/dependencies/resolution.ts b/packages/expo-modules-autolinking/src/dependencies/resolution.ts index 7391b9cd68246e..451e92408498f7 100644 --- a/packages/expo-modules-autolinking/src/dependencies/resolution.ts +++ b/packages/expo-modules-autolinking/src/dependencies/resolution.ts @@ -6,6 +6,7 @@ import { DependencyResolutionSource, } from './types'; import { defaultShouldIncludeDependency, mergeResolutionResults } from './utils'; +import { taskAll } from '../concurrency'; import { type PackageJson, loadPackageJson, maybeRealpath, fastJoin } from '../utils'; declare module 'node:module' { @@ -93,10 +94,9 @@ async function resolveDependencies( return null; }; - const modules = await Promise.all( - Object.keys(dependencies) - .filter((dependencyName) => shouldIncludeDependency(dependencyName)) - .map((dependencyName) => resolveDependency(dependencyName)) + const modules = await taskAll( + Object.keys(dependencies).filter((dependencyName) => shouldIncludeDependency(dependencyName)), + (dependencyName) => resolveDependency(dependencyName) ); return modules.filter((resolution) => resolution != null); @@ -151,9 +151,7 @@ export async function scanDependenciesRecursively( } if (depth + 1 < maxDepth) { - const childResults = await Promise.all( - modules.map((resolution) => recurse(resolution, depth + 1)) - ); + const childResults = await taskAll(modules, (resolution) => recurse(resolution, depth + 1)); return mergeResolutionResults(childResults, searchResults); } else { return searchResults; diff --git a/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts b/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts index ff0dd7f58daf7d..fbd9345d5aa562 100644 --- a/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts +++ b/packages/expo-modules-autolinking/src/dependencies/rncliLocal.ts @@ -2,6 +2,7 @@ import path from 'path'; import { DependencyResolutionSource, type ResolutionResult } from './types'; import { defaultShouldIncludeDependency } from './utils'; +import { taskAll } from '../concurrency'; import { RNConfigReactNativeProjectConfig } from '../reactNativeConfig'; import { maybeRealpath } from '../utils'; @@ -20,27 +21,29 @@ export async function scanDependenciesFromRNProjectConfig( return searchResults; } - for (const dependencyName in projectConfig.dependencies) { - if (!shouldIncludeDependency(dependencyName)) { - continue; - } - const dependencyConfig = projectConfig.dependencies[dependencyName]; - if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') { - const originPath = path.resolve(rootPath, dependencyConfig.root); - const realPath = await maybeRealpath(originPath); - if (realPath) { - searchResults[dependencyName] = { - source: DependencyResolutionSource.RN_CLI_LOCAL, - name: dependencyName, - version: '', - path: realPath, - originPath, - duplicates: null, - depth: 0, - }; + await taskAll( + Object.keys(projectConfig.dependencies).filter((dependencyName) => + shouldIncludeDependency(dependencyName) + ), + async (dependencyName) => { + const dependencyConfig = projectConfig.dependencies![dependencyName]; + if (dependencyConfig && dependencyConfig.root && typeof dependencyConfig.root === 'string') { + const originPath = path.resolve(rootPath, dependencyConfig.root); + const realPath = await maybeRealpath(originPath); + if (realPath) { + searchResults[dependencyName] = { + source: DependencyResolutionSource.RN_CLI_LOCAL, + name: dependencyName, + version: '', + path: realPath, + originPath, + duplicates: null, + depth: 0, + }; + } } } - } + ); return searchResults; } diff --git a/packages/expo-modules-autolinking/src/dependencies/scanning.ts b/packages/expo-modules-autolinking/src/dependencies/scanning.ts index 9a8b9f914feae5..41cf8c279b8b8e 100644 --- a/packages/expo-modules-autolinking/src/dependencies/scanning.ts +++ b/packages/expo-modules-autolinking/src/dependencies/scanning.ts @@ -5,6 +5,7 @@ import { type DependencyResolution, DependencyResolutionSource, } from './types'; +import { taskAll } from '../concurrency'; import { defaultShouldIncludeDependency } from './utils'; import { loadPackageJson, maybeRealpath, fastJoin } from '../utils'; @@ -68,45 +69,39 @@ export async function scanDependenciesInSearchPath( if (resolution) resolvedDependencies.push(resolution); } else { const dirents = await fs.promises.readdir(rootPath!, { withFileTypes: true }); - await Promise.all( - dirents.map(async (entry) => { - if (entry.isSymbolicLink()) { + await taskAll(dirents, async (entry) => { + if (entry.isSymbolicLink()) { + const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency); + if (resolution) resolvedDependencies.push(resolution); + } else if (entry.isDirectory()) { + if (entry.name === 'node_modules') { + // Ignore nested node_modules folder + } + if (entry.name[0] === '.') { + // Ignore hidden folders + } else if (entry.name[0] === '@') { + // NOTE: We don't expect @-scope folders to be symlinks + const entryPath = fastJoin(rootPath, entry.name); + const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true }); + await Promise.all( + childEntries.map(async (child) => { + const dependencyName = `${entry.name}/${child.name}`; + if (child.isDirectory() || child.isSymbolicLink()) { + const resolution = await resolveDependency( + rootPath, + dependencyName, + shouldIncludeDependency + ); + if (resolution) resolvedDependencies.push(resolution); + } + }) + ); + } else { const resolution = await resolveDependency(rootPath, entry.name, shouldIncludeDependency); if (resolution) resolvedDependencies.push(resolution); - } else if (entry.isDirectory()) { - if (entry.name === 'node_modules') { - // Ignore nested node_modules folder - } - if (entry.name[0] === '.') { - // Ignore hidden folders - } else if (entry.name[0] === '@') { - // NOTE: We don't expect @-scope folders to be symlinks - const entryPath = fastJoin(rootPath, entry.name); - const childEntries = await fs.promises.readdir(entryPath, { withFileTypes: true }); - await Promise.all( - childEntries.map(async (child) => { - const dependencyName = `${entry.name}/${child.name}`; - if (child.isDirectory() || child.isSymbolicLink()) { - const resolution = await resolveDependency( - rootPath, - dependencyName, - shouldIncludeDependency - ); - if (resolution) resolvedDependencies.push(resolution); - } - }) - ); - } else { - const resolution = await resolveDependency( - rootPath, - entry.name, - shouldIncludeDependency - ); - if (resolution) resolvedDependencies.push(resolution); - } } - }) - ); + } + }); } for (let idx = 0; idx < resolvedDependencies.length; idx++) { diff --git a/packages/expo-modules-autolinking/src/dependencies/utils.ts b/packages/expo-modules-autolinking/src/dependencies/utils.ts index ca32ed61f6fb68..0f42f989dac742 100644 --- a/packages/expo-modules-autolinking/src/dependencies/utils.ts +++ b/packages/expo-modules-autolinking/src/dependencies/utils.ts @@ -1,7 +1,6 @@ -import fs from 'fs'; import path from 'path'; -import { memoize } from '../memoize'; +import { taskAll } from '../concurrency'; import { DependencyResolutionSource, type DependencyResolution, @@ -105,24 +104,22 @@ export async function filterMapResolutionResult( results: ResolutionResult, filterMap: (resolution: DependencyResolution) => Promise | T | null ): Promise> { - const resolutions = await Promise.all( - Object.keys(results).map(async (key) => { - const resolution = results[key]; - const result = resolution ? await filterMap(resolution) : null; - // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates - // to see if the `searchPaths` result is not a module but another is - if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) { - for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) { - const duplicate = resolution.duplicates[idx]; - const duplicateResult = await filterMap({ ...resolution, ...duplicate }); - if (duplicateResult != null) { - return duplicateResult; - } + const resolutions = await taskAll(Object.keys(results), async (key) => { + const resolution = results[key]; + const result = resolution ? await filterMap(resolution) : null; + // If we failed to find a matching resolution from `searchPaths`, also try the other duplicates + // to see if the `searchPaths` result is not a module but another is + if (resolution?.source === DependencyResolutionSource.SEARCH_PATH && !result) { + for (let idx = 0; resolution.duplicates && idx < resolution.duplicates.length; idx++) { + const duplicate = resolution.duplicates[idx]; + const duplicateResult = await filterMap({ ...resolution, ...duplicate }); + if (duplicateResult != null) { + return duplicateResult; } } - return result; - }) - ); + } + return result; + }); const output: Record = Object.create(null); for (let idx = 0; idx < resolutions.length; idx++) { const resolution = resolutions[idx]; diff --git a/packages/expo-modules-autolinking/src/platforms/android/android.ts b/packages/expo-modules-autolinking/src/platforms/android/android.ts index bc7caf2eb4a887..389d9fb89f9cef 100644 --- a/packages/expo-modules-autolinking/src/platforms/android/android.ts +++ b/packages/expo-modules-autolinking/src/platforms/android/android.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import path from 'path'; import { AutolinkingOptions } from '../../commands/autolinkingOptions'; +import { taskAll } from '../../concurrency'; import type { ExtraDependencies, ModuleDescriptorAndroid, PackageRevision } from '../../types'; import { scanFilesRecursively } from '../../utils'; @@ -65,59 +66,57 @@ export async function resolveModuleAsync( }; } - const projects = await Promise.all( - androidProjects.map(async (project) => { - const projectPath = path.join(revision.path, project.path); - - const aarProjects = (project.gradleAarProjects ?? [])?.map((aarProject) => { - const projectName = `${defaultProjectName}$${aarProject.name}`; - const projectDir = path.join(projectPath, 'build', projectName); - return { - name: projectName, - aarFilePath: path.join(revision.path, aarProject.aarFilePath), - projectDir, - }; - }); - - const { publication } = project; - const shouldUsePublicationScriptPath = project.shouldUsePublicationScriptPath - ? path.join(revision.path, project.shouldUsePublicationScriptPath) - : undefined; - - const packages = new Set(); - for await (const file of scanFilesRecursively(projectPath)) { - if (!file.name.endsWith('Package.java') && !file.name.endsWith('Package.kt')) { - continue; - } - const fileContent = await fs.promises.readFile(file.path, 'utf8'); - - // Very naive check to skip non-expo packages - if ( - !/\bimport\s+expo\.modules\.core\.(interfaces\.Package|BasePackage)\b/.test(fileContent) - ) { - continue; - } - - const classPathMatches = fileContent.match(/^package ([\w.]+)\b/m); - - if (classPathMatches) { - const basename = path.basename(file.name, path.extname(file.name)); - packages.add(`${classPathMatches[1]}.${basename}`); - } - } + const projects = await taskAll(androidProjects, async (project) => { + const projectPath = path.join(revision.path, project.path); + const aarProjects = (project.gradleAarProjects ?? [])?.map((aarProject) => { + const projectName = `${defaultProjectName}$${aarProject.name}`; + const projectDir = path.join(projectPath, 'build', projectName); return { - name: project.name, - sourceDir: projectPath, - modules: project.modules ?? [], - services: project.services ?? [], - packages: [...packages].sort((a, b) => a.localeCompare(b)), - ...(shouldUsePublicationScriptPath ? { shouldUsePublicationScriptPath } : {}), - ...(publication ? { publication } : {}), - ...(aarProjects?.length > 0 ? { aarProjects } : {}), + name: projectName, + aarFilePath: path.join(revision.path, aarProject.aarFilePath), + projectDir, }; - }) - ); + }); + + const { publication } = project; + const shouldUsePublicationScriptPath = project.shouldUsePublicationScriptPath + ? path.join(revision.path, project.shouldUsePublicationScriptPath) + : undefined; + + const packages = new Set(); + for await (const file of scanFilesRecursively(projectPath)) { + if (!file.name.endsWith('Package.java') && !file.name.endsWith('Package.kt')) { + continue; + } + const fileContent = await fs.promises.readFile(file.path, 'utf8'); + + // Very naive check to skip non-expo packages + if ( + !/\bimport\s+expo\.modules\.core\.(interfaces\.Package|BasePackage)\b/.test(fileContent) + ) { + continue; + } + + const classPathMatches = fileContent.match(/^package ([\w.]+)\b/m); + + if (classPathMatches) { + const basename = path.basename(file.name, path.extname(file.name)); + packages.add(`${classPathMatches[1]}.${basename}`); + } + } + + return { + name: project.name, + sourceDir: projectPath, + modules: project.modules ?? [], + services: project.services ?? [], + packages: [...packages].sort((a, b) => a.localeCompare(b)), + ...(shouldUsePublicationScriptPath ? { shouldUsePublicationScriptPath } : {}), + ...(publication ? { publication } : {}), + ...(aarProjects?.length > 0 ? { aarProjects } : {}), + }; + }); const coreFeatures = revision.config?.coreFeatures() ?? []; diff --git a/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts b/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts index 57b7da3e75a970..f164936cac009b 100644 --- a/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts +++ b/packages/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts @@ -6,6 +6,7 @@ import type { RNConfigReactNativePlatformsConfigAndroid, } from './reactNativeConfig.types'; import type { ExpoModuleConfig } from '../ExpoModuleConfig'; +import { taskAll } from '../concurrency'; import { scanFilesRecursively, fileExistsAsync, fastJoin, loadPackageJson } from '../utils'; export async function resolveDependencyConfigImplAndroidAsync( @@ -296,8 +297,8 @@ const findAndroidManifestsAsync = async (targetPath: string) => { }; const getFileCandidatesAsync = async (targetPath: string, fileNames: string[]) => { - const gradlePaths = await Promise.all( - fileNames.map((fileName) => fileExistsAsync(path.join(targetPath, fileName))) + const gradlePaths = await taskAll(fileNames, (fileName) => + fileExistsAsync(path.join(targetPath, fileName)) ); return gradlePaths.filter((file) => file != null).sort((a, b) => a.localeCompare(b)); };