Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes.
<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes.
Please follow the template so that the reviewers can easily understand what the code changes affect -->

# 📝 Why & how
Expand All @@ -14,4 +14,4 @@ Please follow the template so that the reviewers can easily understand what the

<!-- If you added a feature or fixed a bug -->
- [ ] Documented in this PR how to use the feature or replicate the bug.
- [ ] Documented in this PR how you fixed or created the feature.
- [ ] Documented in this PR how you fixed an issue or created the feature.
17 changes: 7 additions & 10 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 14 additions & 12 deletions components/Library/MetaData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,20 @@ export function MetaData({ library, secondary }: Props) {
const data = generateSecondaryData(library, isDark).filter(Boolean);
return (
<>
{data.map(({ id, icon, content }, i) => (
<View
key={id}
style={[
styles.displayHorizontal,
i + 1 !== data.length ? styles.datumContainer : {},
styles.secondaryContainer,
]}>
<View style={[styles.iconContainer, styles.secondaryIconContainer]}>{icon}</View>
{content}
</View>
))}
{data
.filter(entry => !!entry)
.map(({ id, icon, content }, i) => (
<View
key={id}
style={[
styles.displayHorizontal,
i + 1 !== data.length ? styles.datumContainer : {},
styles.secondaryContainer,
]}>
<View style={[styles.iconContainer, styles.secondaryIconContainer]}>{icon}</View>
{content}
</View>
))}
</>
);
} else {
Expand Down
41 changes: 17 additions & 24 deletions next.config.js → next.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { withExpo } from '@expo/next-adapter';
import BundleAnalyzer from '@next/bundle-analyzer';
import type { NextConfig } from 'next';
import withPlugins from 'next-compose-plugins';
import withFonts from 'next-fonts';
import withImages from 'next-images';

const PACKAGES_TO_OPTIMIZE = [
'@expo/html-elements',
'@react-native-picker/picker',
'@sentry/*',
'node-emoji',
'react-native',
'react-native-safe-area-context',
'react-native-svg',
'react-native-web',
];

const withBundleAnalyzer = BundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
Expand All @@ -12,40 +24,21 @@ export default withPlugins([withExpo, withImages, withFonts, withBundleAnalyzer]
productionBrowserSourceMaps: true,
reactStrictMode: true,
poweredByHeader: false,
devIndicators: {
enabled: false,
},
devIndicators: false,
eslint: {
ignoreDuringBuilds: true,
},
images: {
disableStaticImages: true,
},
transpilePackages: [
'@expo/html-elements',
'@react-native-picker/picker',
'@sentry/react',
'react-native-safe-area-context',
'react-native-svg',
'react-native-web',
'react-native-web-hooks',
'react-native',
],
transpilePackages: PACKAGES_TO_OPTIMIZE,
experimental: {
forceSwcTransforms: true,
webpackBuildWorker: true,
browserDebugInfoInTerminal: true,
clientSegmentCache: true,
optimizePackageImports: [
'@expo/html-elements',
'@react-native-picker/picker',
'@sentry/react',
'react-native-safe-area-context',
'react-native-svg',
'react-native-web',
'react-native-web-hooks',
'react-native',
],
useLightningcss: true,
optimizePackageImports: PACKAGES_TO_OPTIMIZE,
},
async headers() {
return [
Expand All @@ -58,4 +51,4 @@ export default withPlugins([withExpo, withImages, withFonts, withBundleAnalyzer]
},
];
},
});
} satisfies NextConfig);
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
"@react-native-async-storage/async-storage": "^2.2.0",
"@react-native-picker/picker": "^2.11.2",
"@sentry/react": "^10.12.0",
"@vercel/blob": "^0.27.3",
"expo": "54.0.9",
"expo-font": "^14.0.8",
"lodash": "^4.17.21",
"es-toolkit": "^1.39.10",
"next": "^15.5.3",
"node-emoji": "^2.2.0",
"react": "19.1.1",
Expand All @@ -44,8 +43,8 @@
"@expo/next-adapter": "^6.0.0",
"@next/bundle-analyzer": "^15.5.3",
"@types/bun": "^1.2.22",
"@types/lodash": "^4.17.20",
"@types/react": "^19.1.13",
"@vercel/blob": "^0.27.3",
"ajv-cli": "^5.0.0",
"browserslist": "^4.26.2",
"cheerio": "^1.1.2",
Expand Down
15 changes: 12 additions & 3 deletions pages/api/libraries/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ import { type NextApiRequest, type NextApiResponse } from 'next';

import data from '~/assets/data.json';
import { type DataAssetType } from '~/types';
import { getNewArchSupportStatus } from '~/util/newArchStatus';
import { getNewArchSupportStatus, NewArchSupportStatus } from '~/util/newArchStatus';

type CheckResultsType = Record<
string,
{
unmaintained?: boolean;
newArchitecture: NewArchSupportStatus;
}
>;

// Copy data into an object that is keyed by npm package name for faster lookup
const dataByNpmPackage = {};
const dataByNpmPackage: CheckResultsType = {};

(data as DataAssetType).libraries.forEach(library => {
dataByNpmPackage[library.npmPkg] = {
unmaintained: library.unmaintained,
Expand All @@ -30,7 +39,7 @@ export default function handler(req: NextApiRequest, res: NextApiResponse) {
}

res.statusCode = 200;
const result = {};
const result: CheckResultsType = {};
packages.forEach(pkgName => {
result[pkgName] = dataByNpmPackage[pkgName];
});
Expand Down
7 changes: 3 additions & 4 deletions pages/api/libraries/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import drop from 'lodash/drop';
import take from 'lodash/take';
import { drop, take } from 'es-toolkit';
import { NextApiRequest, NextApiResponse } from 'next';

import data from '~/assets/data.json';
import { type LibraryType, QueryOrder } from '~/types';
import { type DataAssetType, QueryOrder } from '~/types';
import { NUM_PER_PAGE } from '~/util/Constants';
import { parseQueryParams } from '~/util/parseQueryParams';
import { handleFilterLibraries } from '~/util/search';
import * as Sorting from '~/util/sorting';

const originalData = [...data.libraries] as LibraryType[];
const originalData = [...(data as DataAssetType).libraries];
const getData = () => ({
updated: Sorting.updated([...originalData]),
added: [...originalData.reverse()],
Expand Down
2 changes: 1 addition & 1 deletion scripts/build-and-score-data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BlobAccessError, list, put } from '@vercel/blob';
import { fetch } from 'bun';
import chunk from 'lodash/chunk';
import { chunk } from 'es-toolkit';
import fs from 'node:fs';
import path from 'node:path';

Expand Down
7 changes: 3 additions & 4 deletions scripts/calculate-score.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ export function calculateDirectoryScore(data: LibraryType) {
};
}

function getCombinedPopularity(data: LibraryType) {
const { subscribers, forks, stars } = data.github.stats;
const { downloads } = data.npm;
return subscribers * 50 + forks * 25 + stars * 10 + downloads / 100;
function getCombinedPopularity({ github, npm }: LibraryType) {
const { subscribers, forks, stars } = github.stats;
return subscribers * 50 + forks * 25 + stars * 10 + (npm?.downloads ?? 0) / 100;
}

function getUpdatedDaysAgo(data: LibraryType) {
Expand Down
16 changes: 7 additions & 9 deletions scripts/cleanup-libraries-json.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import identity from 'lodash/identity';
import omit from 'lodash/omit';
import pickBy from 'lodash/pickBy';
import { identity, omit, pickBy } from 'es-toolkit';
import fs from 'node:fs';
import path from 'node:path';

Expand All @@ -11,15 +9,15 @@ const LIBRARIES_JSON_PATH = path.join('react-native-libraries.json');

const emptyPropertiesToKeep = ['newArchitecture'];

function removeEmptyArray(lib: LibraryDataEntryType, key: string) {
return lib[key] && !lib[key].length ? (omit(lib, key) as LibraryDataEntryType) : lib;
function removeEmptyArray(lib: LibraryDataEntryType, key: 'examples' | 'images') {
return lib[key] && !lib[key].length ? omit(lib, [key]) : lib;
}

const processedLibraries = (libraries as LibraryDataEntryType[])
const processedLibraries = libraries
// Remove redundant `npmPkg` for libraries with the correct GitHub repository name
.map(lib =>
.map((lib: LibraryDataEntryType) =>
lib.npmPkg && !lib.npmPkg.includes('/') && lib.githubUrl.endsWith(`/${lib.npmPkg}`)
? omit(lib, 'npmPkg')
? omit(lib, ['npmPkg'])
: lib
)
// Remove empty arrays
Expand All @@ -31,7 +29,7 @@ const processedLibraries = (libraries as LibraryDataEntryType[])
if (emptyPropertiesToKeep.includes(key)) {
return true;
} else {
return identity(value);
return !!identity(value);
}
})
);
Expand Down
4 changes: 2 additions & 2 deletions scripts/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ export function processTopics(topics?: string[]) {
}

function splitAndGetLastChunk(value: string, delimiter = '/') {
return value.split(delimiter).at(-1).toLowerCase();
return value.split(delimiter).at(-1)?.toLowerCase();
}

export function hasMismatchedPackageData(library: LibraryType) {
const desiredName = library.npmPkg ?? splitAndGetLastChunk(library.githubUrl);

if (library.github.registry && library.github.registry !== 'https://registry.npmjs.org/') {
const registryScope = splitAndGetLastChunk(library.github.registry);
if (registryScope.startsWith('@')) {
if (registryScope?.startsWith('@')) {
return library.github?.name.replace(`${registryScope}/`, '') !== desiredName;
}
}
Expand Down
3 changes: 1 addition & 2 deletions scripts/validate-new-entries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { fetch } from 'bun';
import differenceWith from 'lodash/differenceWith';
import isEqual from 'lodash/isEqual';
import { differenceWith, isEqual } from 'es-toolkit';

import { fetchGithubData } from './fetch-github-data';
import { fetchNpmDownloadData } from './fetch-npm-download-data';
Expand Down
3 changes: 3 additions & 0 deletions types/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module 'next-compose-plugins';
declare module 'next-fonts';
declare module 'next-images';
2 changes: 1 addition & 1 deletion types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export type LibraryDataEntryType = {
fireos?: boolean;
tvos?: boolean;
visionos?: boolean;
unmaintained?: boolean | string;
unmaintained?: boolean;
dev?: boolean;
template?: boolean;
newArchitecture?: boolean | 'new-arch-only';
Expand Down