-
Notifications
You must be signed in to change notification settings - Fork 785
feat: scraping expo/react-native version from package.json #838
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
giautm
wants to merge
9
commits into
react-native-community:main
from
giautm:giautm/public-versioned-api
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
d6e51ea
feat: scraping expo/react-native version from npm
giautm ffaf666
feat: added versions API
giautm a9a62f5
fix: change the method to GET
giautm ea6683a
fix: fixed undefined error for BabylonJS/BabylonReactNative
giautm a7db733
fix: update script to ignore non-existing packages
giautm 10a0dd5
fix: update skip logic
giautm 0f6e0ea
fix: revert lastCommitAt change, update BabylonJS URL
giautm cb916ee
fix: fixed lint
giautm 49bbbfa
Merge branch 'main' into giautm/public-versioned-api
giautm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| { | ||
| "expoSdkVersions": [ | ||
| "46.0.0", | ||
| "45.0.0", | ||
| "44.0.0", | ||
| "43.0.0" | ||
| ], | ||
| "reactNativeVersions": [ | ||
| "0.70.1", | ||
| "0.70.0", | ||
| "0.69.5", | ||
| "0.69.4", | ||
| "0.69.3", | ||
| "0.69.2", | ||
| "0.69.1", | ||
| "0.69.0", | ||
| "0.68.4", | ||
| "0.68.3", | ||
| "0.68.2", | ||
| "0.68.1", | ||
| "0.68.0", | ||
| "0.67.4", | ||
| "0.67.3", | ||
| "0.67.2", | ||
| "0.67.1", | ||
| "0.67.0", | ||
| "0.66.4", | ||
| "0.66.3", | ||
| "0.64.3", | ||
| "0.66.2", | ||
| "0.66.1", | ||
| "0.66.0", | ||
| "0.65.1", | ||
| "0.65.0", | ||
| "0.64.2", | ||
| "0.64.1", | ||
| "0.62.3", | ||
| "0.64.0", | ||
| "0.63.4", | ||
| "0.63.3", | ||
| "0.63.2", | ||
| "0.63.1", | ||
| "0.63.0", | ||
| "0.62.2", | ||
| "0.62.1", | ||
| "0.62.0" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| import { NextApiRequest, NextApiResponse } from 'next'; | ||
|
|
||
| import data from '../../../assets/data.json'; | ||
|
|
||
| type RequestQuery = { | ||
| reactNativeVersion: string; | ||
| expoSdkVersion: string; | ||
| packages: string[]; | ||
| }; | ||
|
|
||
| type PackageInfo = { | ||
| npmPackage: string; | ||
| sdkVersion?: string; | ||
| versionRange: string | null; | ||
| }; | ||
| type ExpoVersionsData = { | ||
| sdkVersions: { | ||
| [keyof: string]: { | ||
| facebookReactNativeVersion: string; | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| const EXPO_API_V2 = 'https://exp.host'; | ||
|
|
||
| async function fetchExpoVersionsAsync(): Promise<{ data: ExpoVersionsData }> { | ||
| const url = new URL('/--/api/v2/versions/latest', EXPO_API_V2); | ||
| const req = await fetch(url); | ||
| return req.json(); | ||
| } | ||
|
|
||
| async function fetchNativeModulesAsync(sdkVersion: string): Promise<{ data: PackageInfo[] }> { | ||
| const url = new URL(`/--/api/v2/sdks/${sdkVersion}/native-modules`, EXPO_API_V2); | ||
| const req = await fetch(url); | ||
| return req.json(); | ||
| } | ||
|
|
||
| function lookupPackageForReactNative(rnVersion: string, packages: string[]) { | ||
| return data.libraries | ||
| .filter(lib => packages.includes(lib.npmPkg) && lib.rnVersions?.[rnVersion]) | ||
| .map(lib => ({ | ||
| npmPackage: lib.npmPkg, | ||
| versionRange: lib.rnVersions[rnVersion], | ||
| })); | ||
| } | ||
|
|
||
| async function processRequestAsync(data: RequestQuery): Promise<PackageInfo[]> { | ||
| const { expoSdkVersion, reactNativeVersion, packages } = data; | ||
| if (expoSdkVersion) { | ||
| const { data } = await fetchNativeModulesAsync(expoSdkVersion); | ||
| const resolvedPackage = new Set(); | ||
| const result = data.filter(({ npmPackage }) => { | ||
| if (packages.includes(npmPackage)) { | ||
| resolvedPackage.add(npmPackage); | ||
| return true; | ||
| } | ||
| return false; | ||
| }); | ||
|
|
||
| const missingPackages = packages.filter(pkg => !resolvedPackage.has(pkg)); | ||
| if (missingPackages.length === 0) { | ||
| // All packages are resolved by Expo Native Modules. | ||
| return result; | ||
| } | ||
|
|
||
| // Continue looking for missing package based on RN version. | ||
| let rnVersion = reactNativeVersion; | ||
| if (!rnVersion) { | ||
| const { data: versionsData } = await fetchExpoVersionsAsync(); | ||
| if (!versionsData.sdkVersions[expoSdkVersion]) { | ||
| throw new Error(`invalid expoSdkVersion: ${expoSdkVersion}`); | ||
| } | ||
|
|
||
| ({ facebookReactNativeVersion: rnVersion } = versionsData.sdkVersions[expoSdkVersion]); | ||
| } | ||
| return result.concat(lookupPackageForReactNative(rnVersion, missingPackages)); | ||
| } else if (reactNativeVersion) { | ||
| return lookupPackageForReactNative(reactNativeVersion, packages); | ||
| } | ||
|
|
||
| return []; | ||
| } | ||
|
|
||
| export const config = { | ||
| api: {}, | ||
| }; | ||
|
|
||
| export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
| const body = req.query as RequestQuery; | ||
| try { | ||
| const packages = await processRequestAsync(body); | ||
|
|
||
| res.statusCode = 200; | ||
| res.setHeader('Content-Type', 'application/json'); | ||
| res.json({ | ||
| ...body, | ||
| packages: packages.map(({ npmPackage, sdkVersion, versionRange }) => ({ | ||
| npmPackage, | ||
| sdkVersion, | ||
| versionRange, | ||
| })), | ||
| }); | ||
| } catch { | ||
| res.statusCode = 500; | ||
| res.setHeader('Content-Type', 'application/json'); | ||
| res.json({ error: 'Internal server error' }); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import npmFetch from 'npm-registry-fetch'; | ||
| import path from 'path'; | ||
| import semver from 'semver'; | ||
|
|
||
| const DEPS_IN_ORDER = ['devDependencies', 'peerDependencies', 'dependencies']; | ||
| const REGEXP_VERSION = /^\d+\.\d+\.\d+$/; | ||
|
|
||
| function isStableVersion(ver) { | ||
| return REGEXP_VERSION.exec(ver) !== null; | ||
| } | ||
|
|
||
| function fillSupportVersions(packageManifest, dependencies) { | ||
| if (!packageManifest) { | ||
| return () => false; | ||
| } | ||
|
|
||
| const versionOfDeps = dependencies.reduce((acc, dep) => { | ||
| DEPS_IN_ORDER.forEach(depType => { | ||
| const version = packageManifest[depType]?.[dep]; | ||
| if (version) { | ||
| acc[dep] = version; | ||
| } | ||
| }); | ||
| return acc; | ||
| }, {}); | ||
|
|
||
| return depData => { | ||
| const requiredVersion = versionOfDeps?.[depData.name]; | ||
| if (requiredVersion && depData.unsupported.length > 0) { | ||
| depData.unsupported = depData.unsupported.filter(version => { | ||
| if (semver.satisfies(version, requiredVersion)) { | ||
| if (!depData.supports) { | ||
| depData.supports = {}; | ||
| } | ||
| depData.supports[version] = packageManifest.version; | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| }); | ||
| } | ||
|
|
||
| return depData.unsupported.length === 0; | ||
| }; | ||
| } | ||
|
|
||
| export const fetchVersionsData = async (npmPackage, packages) => { | ||
| const deps = packages.map(({ name }) => name); | ||
| const data = packages.map(({ name, versions: unsupported }) => ({ | ||
| name, | ||
| unsupported, | ||
| })); | ||
|
|
||
| const manifest = await npmFetch.json('/' + path.join(npmPackage, 'latest')); | ||
| if (!data.every(fillSupportVersions(manifest, deps))) { | ||
| // Fetch manifest for all versions processing. | ||
| const metadata = await npmFetch.json(npmPackage); | ||
|
|
||
| const versions = Object.keys(metadata.versions).filter(isStableVersion).reverse(); | ||
| for (const version of versions) { | ||
| if (data.every(fillSupportVersions(metadata.versions[version], deps))) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return data | ||
| .filter(({ supports }) => !!supports) | ||
| .map(({ name, supports }) => ({ name, supports })); | ||
| }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.