Skip to content
Merged
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
61 changes: 28 additions & 33 deletions src/slugs/deps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import React from 'react';
import SizeContainer from '@/components/SizeContainer';
import Link from 'next/link';
import { PageProps } from '@/pages/package/[...slug]';
import { useFileContent } from '@/hooks/useFile';

const columns: TableColumnsType<object> = [
interface DepRecord {
package: string;
spec: string;
}

const columns: TableColumnsType<DepRecord> = [
{
title: '名称',
dataIndex: 'package',
render: (pkg: string) => {
render: (pkg: string, record: DepRecord) => {
return (
<Link href={`/package/${pkg}`} target="_blank">
<Link href={`/package/${pkg}?version=${encodeURIComponent(record.spec)}`} target="_blank">
{pkg}
</Link>
);
Expand All @@ -25,39 +29,33 @@ const columns: TableColumnsType<object> = [
},
];

export default function Deps({ manifest: pkg, version }: PageProps) {
const { data: versionManifest, isLoading } = useFileContent(
{ fullname: pkg.name, spec: version },
'/package.json',
);
export default function Deps({ manifest, version }: PageProps) {
const depsInfo = React.useMemo(() => {
if (isLoading) return undefined;
const targetVersion = JSON.parse(versionManifest || '{}');
const deps = ['dependencies', 'devDependencies'] as const;
const res: Record<string, { package: string; spec: string }[]> = {
dependencies: [],
devDependencies: [],
};
deps.forEach((k) => {
if (targetVersion?.[k]) {
res[k] = Object.keys(targetVersion[k] || {}).map((pkg) => ({
package: pkg,
spec: targetVersion[k][pkg],
}));
}
});
return res;
}, [versionManifest, isLoading]);
const versionData = manifest.versions?.[version!];
if (!versionData) return { dependencies: [], devDependencies: [] };

const deps = versionData.dependencies || {};
const devDeps = versionData.devDependencies || {};

const loading = depsInfo === undefined;
return {
dependencies: Object.entries(deps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
devDependencies: Object.entries(devDeps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
};
}, [manifest, version]);
Comment on lines 33 to +50
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This useMemo block can be made more robust and concise.

  1. Avoid Non-Null Assertion: Using the non-null assertion operator (!) on version can be risky if the version prop is not guaranteed to be defined. It's safer to add a guard clause to handle cases where version might be null or undefined.
  2. Reduce Duplication: The logic to transform the dependencies and devDependencies objects into arrays is identical. This can be extracted into a small helper function within the hook to adhere to the DRY (Don't Repeat Yourself) principle.

Here's a suggested refactoring that addresses both points.

Suggested change
const depsInfo = React.useMemo(() => {
if (isLoading) return undefined;
const targetVersion = JSON.parse(versionManifest || '{}');
const deps = ['dependencies', 'devDependencies'] as const;
const res: Record<string, { package: string; spec: string }[]> = {
dependencies: [],
devDependencies: [],
};
deps.forEach((k) => {
if (targetVersion?.[k]) {
res[k] = Object.keys(targetVersion[k] || {}).map((pkg) => ({
package: pkg,
spec: targetVersion[k][pkg],
}));
}
});
return res;
}, [versionManifest, isLoading]);
const versionData = manifest.versions?.[version!];
if (!versionData) return { dependencies: [], devDependencies: [] };
const deps = versionData.dependencies || {};
const devDeps = versionData.devDependencies || {};
const loading = depsInfo === undefined;
return {
dependencies: Object.entries(deps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
devDependencies: Object.entries(devDeps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
};
}, [manifest, version]);
const depsInfo = React.useMemo(() => {
if (!version) {
return { dependencies: [], devDependencies: [] };
}
const versionData = manifest.versions?.[version];
if (!versionData) {
return { dependencies: [], devDependencies: [] };
}
const transformDeps = (deps: Record<string, string> = {}) =>
Object.entries(deps).map(([pkg, spec]) => ({
package: pkg,
spec,
}));
return {
dependencies: transformDeps(versionData.dependencies),
devDependencies: transformDeps(versionData.devDependencies),
};
}, [manifest, version]);

Comment on lines +32 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove unsafe non-null assertion on optional parameter.

Line 34 uses a non-null assertion (version!) on an optional parameter. While the fallback on line 35 handles missing versionData, the non-null assertion is unsafe and could mask issues.

Apply this diff to handle the optional version safely:

   const depsInfo = React.useMemo(() => {
-    const versionData = manifest.versions?.[version!];
+    if (!version) return { dependencies: [], devDependencies: [] };
+    const versionData = manifest.versions?.[version];
     if (!versionData) return { dependencies: [], devDependencies: [] };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default function Deps({ manifest, version }: PageProps) {
const depsInfo = React.useMemo(() => {
if (isLoading) return undefined;
const targetVersion = JSON.parse(versionManifest || '{}');
const deps = ['dependencies', 'devDependencies'] as const;
const res: Record<string, { package: string; spec: string }[]> = {
dependencies: [],
devDependencies: [],
};
deps.forEach((k) => {
if (targetVersion?.[k]) {
res[k] = Object.keys(targetVersion[k] || {}).map((pkg) => ({
package: pkg,
spec: targetVersion[k][pkg],
}));
}
});
return res;
}, [versionManifest, isLoading]);
const versionData = manifest.versions?.[version!];
if (!versionData) return { dependencies: [], devDependencies: [] };
const deps = versionData.dependencies || {};
const devDeps = versionData.devDependencies || {};
const loading = depsInfo === undefined;
return {
dependencies: Object.entries(deps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
devDependencies: Object.entries(devDeps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
};
}, [manifest, version]);
export default function Deps({ manifest, version }: PageProps) {
const depsInfo = React.useMemo(() => {
if (!version) return { dependencies: [], devDependencies: [] };
const versionData = manifest.versions?.[version];
if (!versionData) return { dependencies: [], devDependencies: [] };
const deps = versionData.dependencies || {};
const devDeps = versionData.devDependencies || {};
return {
dependencies: Object.entries(deps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
devDependencies: Object.entries(devDeps).map(([pkg, spec]) => ({
package: pkg,
spec,
})),
};
}, [manifest, version]);
🤖 Prompt for AI Agents
In src/slugs/deps/index.tsx around lines 32 to 50, remove the unsafe non-null
assertion on the optional parameter by replacing manifest.versions?.[version!]
with a safe access manifest.versions?.[version] (no '!') and handle the
undefined case already covered by the existing early return; ensure TypeScript
types permit indexing with string | undefined (or narrow version into a const
versionKey = version ?? undefined before indexing) so no non-null assertions are
used.


const { dependencies = [], devDependencies = [] } = depsInfo || {};
const { dependencies, devDependencies } = depsInfo;

return (
<SizeContainer maxWidth="90%">
<Row gutter={[8, 8]}>
<Col span={12}>
<Card title={`Dependencies (${loading ? '-' : dependencies.length})`} loading={loading}>
<Card title={`Dependencies (${dependencies.length})`}>
<Table
dataSource={dependencies}
rowKey={'package'}
Expand All @@ -67,10 +65,7 @@ export default function Deps({ manifest: pkg, version }: PageProps) {
</Card>
</Col>
<Col span={12}>
<Card
title={`DevDependencies (${loading ? '-' : devDependencies.length})`}
loading={loading}
>
<Card title={`DevDependencies (${devDependencies.length})`}>
<Table
dataSource={devDependencies}
columns={columns}
Expand Down