Skip to content

Commit cbfc01e

Browse files
lino-levanautofix-ci[bot]43081jdanielroe
authored
feat: add module-replacements support first class (#268)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: James Garbutt <43081j@users.noreply.github.com> Co-authored-by: Daniel Roe <daniel@roe.dev>
1 parent 88509be commit cbfc01e

8 files changed

Lines changed: 120 additions & 2 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<script setup lang="ts">
2+
import type { ModuleReplacement } from 'module-replacements'
3+
4+
const props = defineProps<{
5+
replacement: ModuleReplacement
6+
}>()
7+
8+
const { t } = useI18n()
9+
10+
const message = computed(() => {
11+
switch (props.replacement.type) {
12+
case 'native':
13+
return t('package.replacement.native', {
14+
replacement: props.replacement.replacement,
15+
nodeVersion: props.replacement.nodeVersion,
16+
})
17+
case 'simple':
18+
return t('package.replacement.simple', {
19+
replacement: props.replacement.replacement,
20+
})
21+
case 'documented':
22+
return t('package.replacement.documented')
23+
case 'none':
24+
return t('package.replacement.none')
25+
}
26+
})
27+
28+
const mdnUrl = computed(() => {
29+
if (props.replacement.type !== 'native' || !props.replacement.mdnPath) return null
30+
return `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/${props.replacement.mdnPath}`
31+
})
32+
33+
const docPath = computed(() => {
34+
if (props.replacement.type !== 'documented' || !props.replacement.docPath) return null
35+
return `https://github.com/es-tooling/module-replacements/blob/main/docs/modules/${props.replacement.docPath}.md`
36+
})
37+
</script>
38+
39+
<template>
40+
<div
41+
class="border border-amber-600/40 bg-amber-500/10 rounded-lg px-3 py-2 text-base text-amber-700 dark:text-amber-400"
42+
>
43+
<h2 class="font-medium mb-1 flex items-center gap-2">
44+
<span class="i-carbon-idea w-4 h-4" aria-hidden="true" />
45+
{{ $t('package.replacement.title') }}
46+
</h2>
47+
<p class="text-sm m-0">
48+
{{ message }}
49+
<a
50+
v-if="mdnUrl"
51+
:href="mdnUrl"
52+
target="_blank"
53+
rel="noopener noreferrer"
54+
class="inline-flex items-center gap-1 ml-1 underline underline-offset-4 decoration-amber-600/60 dark:decoration-amber-400/50 hover:decoration-fg transition-colors"
55+
>
56+
{{ $t('package.replacement.mdn') }}
57+
<span class="i-carbon-launch w-3 h-3" aria-hidden="true" />
58+
</a>
59+
<a
60+
v-if="docPath"
61+
:href="docPath"
62+
target="_blank"
63+
rel="noopener noreferrer"
64+
class="inline-flex items-center gap-1 ml-1 underline underline-offset-4 decoration-amber-600/60 dark:decoration-amber-400/50 hover:decoration-fg transition-colors"
65+
>
66+
{{ $t('package.replacement.learn_more') }}
67+
<span class="i-carbon-launch w-3 h-3" aria-hidden="true" />
68+
</a>
69+
</p>
70+
</div>
71+
</template>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { ModuleReplacement } from 'module-replacements'
2+
3+
/** @public */
4+
export function useModuleReplacement(packageName: MaybeRefOrGetter<string>) {
5+
return useLazyFetch<ModuleReplacement | null>(() => `/api/replacements/${toValue(packageName)}`)
6+
}

app/pages/[...package].vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ const {
6666
onMounted(() => fetchInstallSize())
6767
6868
const { data: packageAnalysis } = usePackageAnalysis(packageName, requestedVersion)
69+
const { data: moduleReplacement } = useModuleReplacement(packageName)
6970
7071
const { data: pkg, status, error } = await usePackage(packageName, requestedVersion)
7172
const resolvedVersion = computed(() => pkg.value?.resolvedVersion ?? null)
@@ -1201,8 +1202,10 @@ function handleClick(event: MouseEvent) {
12011202
</div>
12021203
</section>
12031204

1204-
<!-- Vulnerability scan - full width -->
1205-
<div class="area-vulns">
1205+
<div class="area-vulns space-y-6">
1206+
<!-- Bad package warning -->
1207+
<PackageReplacement v-if="moduleReplacement" :replacement="moduleReplacement" />
1208+
<!-- Vulnerability scan -->
12061209
<ClientOnly>
12071210
<PackageVulnerabilityTree
12081211
v-if="displayVersion"

i18n/locales/en.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@
116116
"version": "This version has been deprecated.",
117117
"no_reason": "No reason provided"
118118
},
119+
"replacement": {
120+
"title": "You might not need this dependency.",
121+
"native": "This can be replaced with {replacement}, available since Node {nodeVersion}.",
122+
"simple": "The community has flagged this package as redundant, with the advice: {replacement}.",
123+
"documented": "The community has flagged this package as having more performant alternatives.",
124+
"none": "This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.",
125+
"learn_more": "Learn more",
126+
"mdn": "MDN"
127+
},
119128
"stats": {
120129
"license": "License",
121130
"deps": "Deps",

lunaria/files/en-US.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@
116116
"version": "This version has been deprecated.",
117117
"no_reason": "No reason provided"
118118
},
119+
"replacement": {
120+
"title": "You might not need this dependency.",
121+
"native": "This can be replaced with {replacement}, available since Node {nodeVersion}.",
122+
"simple": "The community has flagged this package as redundant, with the advice: {replacement}.",
123+
"documented": "The community has flagged this package as having more performant alternatives.",
124+
"none": "This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.",
125+
"learn_more": "Learn more",
126+
"mdn": "MDN"
127+
},
119128
"stats": {
120129
"license": "License",
121130
"deps": "Deps",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@shikijs/themes": "^3.21.0",
5050
"@vueuse/core": "^14.1.0",
5151
"@vueuse/nuxt": "14.1.0",
52+
"module-replacements": "^2.11.0",
5253
"nuxt": "^4.3.0",
5354
"nuxt-og-image": "^5.1.13",
5455
"ohash": "^2.0.11",

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { all, type ModuleReplacement } from 'module-replacements'
2+
3+
const replacementMap = new Map<string, ModuleReplacement>(
4+
all.moduleReplacements.map(r => [r.moduleName, r]),
5+
)
6+
7+
export default defineEventHandler((event): ModuleReplacement | null => {
8+
const pkg = getRouterParam(event, 'pkg')
9+
if (!pkg) return null
10+
return replacementMap.get(pkg) ?? null
11+
})

0 commit comments

Comments
 (0)