Skip to content

Commit

Permalink
Merge pull request #860 from jderochervlk/package-search
Browse files Browse the repository at this point in the history
improve Package search sorting
  • Loading branch information
fhammerschmidt authored May 14, 2024
2 parents 19009b3 + 5e6722c commit 67ecba3
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 25 deletions.
115 changes: 91 additions & 24 deletions src/Packages.res
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,27 @@ type npmPackage = {
description: string,
repositoryHref: Js.Null.t<string>,
npmHref: string,
searchScore: float,
maintenanceScore: float,
}

// These are packages that we do not want to filter out when loading searching from NPM.
let packageAllowList: array<string> = []

module Resource = {
type t = Npm(npmPackage) | Url(urlResource)
type t = Npm(npmPackage) | Url(urlResource) | Outdated(npmPackage)

let getId = (res: t) => {
switch res {
| Npm({name})
| Outdated({name})
| Url({name}) => name
}
}

let shouldFilter = (res: t) => {
switch res {
| Npm(pkg) =>
| Npm(pkg) | Outdated(pkg) =>
if pkg.name->Js.String2.startsWith("@elm-react") {
true
} else if pkg.name->Js.String2.startsWith("bs-") {
Expand Down Expand Up @@ -71,7 +77,7 @@ module Resource = {

let isOfficial = (res: t) => {
switch res {
| Npm(pkg) =>
| Npm(pkg) | Outdated(pkg) =>
pkg.name === "rescript" ||
pkg.name->Js.String2.startsWith("@rescript/") ||
pkg.name === "gentype"
Expand All @@ -94,7 +100,9 @@ module Resource = {

let fuser = Fuse.make(packages, fuseOpts)

fuser->Fuse.search(pattern)
fuser
->Fuse.search(pattern)
->Js.Array2.sortInPlaceWith((a, b) => a["item"].searchScore > b["item"].searchScore ? -1 : 1)
}

let applyUrlResourceSearch = (urls: array<urlResource>, pattern: string): array<
Expand All @@ -116,35 +124,41 @@ module Resource = {
}

let applySearch = (resources: array<t>, pattern: string): array<t> => {
let (allNpms, allUrls) = Belt.Array.reduce(resources, ([], []), (acc, next) => {
let (npms, resources) = acc
let (allNpms, allUrls, allOutDated) = Belt.Array.reduce(resources, ([], [], []), (
acc,
next,
) => {
let (npms, resources, outdated) = acc

switch next {
| Npm(pkg) => Js.Array2.push(npms, pkg)->ignore
| Url(res) => Js.Array2.push(resources, res)->ignore
| Outdated(pkg) => Js.Array2.push(outdated, pkg)->ignore
}
(npms, resources)
(npms, resources, outdated)
})

let filteredNpm = applyNpmSearch(allNpms, pattern)->Belt.Array.map(m => Npm(m["item"]))
let filteredUrls = applyUrlResourceSearch(allUrls, pattern)->Belt.Array.map(m => Url(m["item"]))
let filteredOutdated =
applyNpmSearch(allOutDated, pattern)->Belt.Array.map(m => Outdated(m["item"]))

Belt.Array.concat(filteredNpm, filteredUrls)
Belt.Array.concatMany([filteredNpm, filteredUrls, filteredOutdated])
}
}

module Card = {
@react.component
let make = (~value: Resource.t, ~onKeywordSelect: option<string => unit>=?) => {
let icon = switch value {
| Npm(_) => <Icon.Npm className="w-8 opacity-50" />
| Npm(_) | Outdated(_) => <Icon.Npm className="w-8 opacity-50" />
| Url(_) =>
<span>
<Icon.Hyperlink className="w-8 opacity-50" />
</span>
}
let linkBox = switch value {
| Npm(pkg) =>
| Npm(pkg) | Outdated(pkg) =>
let repositoryHref = Js.Null.toOption(pkg.repositoryHref)
let repoEl = switch repositoryHref {
| Some(href) =>
Expand All @@ -169,12 +183,14 @@ module Card = {
}

let titleHref = switch value {
| Npm(pkg) => pkg.repositoryHref->Js.Null.toOption->Belt.Option.getWithDefault(pkg.npmHref)
| Npm(pkg) | Outdated(pkg) =>
pkg.repositoryHref->Js.Null.toOption->Belt.Option.getWithDefault(pkg.npmHref)
| Url(res) => res.urlHref
}

let (title, description, keywords) = switch value {
| Npm({name, description, keywords})
| Outdated({name, description, keywords})
| Url({name, description, keywords}) => (name, description, keywords)
}

Expand Down Expand Up @@ -238,6 +254,7 @@ module Filter = {
includeCommunity: bool,
includeNpm: bool,
includeUrlResource: bool,
includeOutdated: bool,
}
}

Expand All @@ -263,7 +280,7 @@ module InfoSidebar = {

<aside className=" border-l-2 p-4 py-12 border-fire-30 space-y-16">
<div>
<h2 className=h2> {React.string("Filter for")} </h2>
<h2 className=h2> {React.string("Include")} </h2>
<div className="space-y-2">
<Toggle
enabled={filter.includeOfficial}
Expand Down Expand Up @@ -301,6 +318,15 @@ module InfoSidebar = {
}}>
{React.string("URL resources")}
</Toggle>
<Toggle
enabled={filter.includeOutdated}
toggle={() => {
setFilter(prev => {
{...prev, Filter.includeOutdated: !filter.includeOutdated}
})
}}>
{React.string("Outdated")}
</Toggle>
</div>
</div>
<div>
Expand All @@ -320,7 +346,11 @@ module InfoSidebar = {
}
}

type props = {"packages": array<npmPackage>, "urlResources": array<urlResource>}
type props = {
"packages": array<npmPackage>,
"urlResources": array<urlResource>,
"unmaintained": array<npmPackage>,
}

type state =
| All
Expand All @@ -346,13 +376,14 @@ let default = (props: props) => {
includeCommunity: true,
includeNpm: true,
includeUrlResource: true,
includeOutdated: false,
})

let allResources = {
let npms = props["packages"]->Belt.Array.map(pkg => Resource.Npm(pkg))
let urls = props["urlResources"]->Belt.Array.map(res => Resource.Url(res))

Belt.Array.concat(npms, urls)
let outdated = props["unmaintained"]->Belt.Array.map(pkg => Resource.Outdated(pkg))
Belt.Array.concatMany([npms, urls, outdated])
}

let resources = switch state {
Expand Down Expand Up @@ -386,6 +417,7 @@ let default = (props: props) => {
let isResourceIncluded = switch next {
| Npm(_) => filter.includeNpm
| Url(_) => filter.includeUrlResource
| Outdated(_) => filter.includeOutdated && filter.includeNpm
}
if !isResourceIncluded {
()
Expand Down Expand Up @@ -435,7 +467,6 @@ let default = (props: props) => {

React.useEffect(() => {
firstRenderDone.current = true

None
}, [])

Expand Down Expand Up @@ -505,6 +536,11 @@ let default = (props: props) => {

type npmData = {
"objects": array<{
"searchScore": float,
"score": {
"final": float,
"detail": {"quality": float, "popularity": float, "maintenance": float},
},
"package": {
"name": string,
"keywords": array<string>,
Expand All @@ -522,14 +558,8 @@ module Response = {

@val external fetchNpmPackages: string => promise<Response.t> = "fetch"

let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx => {
let response = await fetchNpmPackages(
"https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250",
)

let data = await response->Response.json

let pkges = Belt.Array.map(data["objects"], item => {
let parsePkgs = data =>
Belt.Array.map(data["objects"], item => {
let pkg = item["package"]
{
name: pkg["name"],
Expand All @@ -538,9 +568,45 @@ let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx =>
description: Belt.Option.getWithDefault(pkg["description"], ""),
repositoryHref: Js.Null.fromOption(pkg["links"]["repository"]),
npmHref: pkg["links"]["npm"],
searchScore: item["searchScore"],
maintenanceScore: item["score"]["detail"]["maintenance"],
}
})

let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx => {
let baseUrl = "https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250&maintenance=1.0&popularity=0.5&quality=0.9"

let (one, two, three) = await Js.Promise2.all3((
fetchNpmPackages(baseUrl),
fetchNpmPackages(baseUrl ++ "&from=250"),
fetchNpmPackages(baseUrl ++ "&from=500"),
))

let (data1, data2, data3) = await Js.Promise2.all3((
one->Response.json,
two->Response.json,
three->Response.json,
))

let unmaintained = []

let pkges =
parsePkgs(data1)
->Js.Array2.concat(parsePkgs(data2))
->Js.Array2.concat(parsePkgs(data3))
->Js.Array2.filter(pkg => {
if packageAllowList->Js.Array2.includes(pkg.name) {
true
} else if pkg.name->Js.String2.includes("reason") {
false
} else if pkg.maintenanceScore < 0.3 {
let _ = unmaintained->Js.Array2.push(pkg)
false
} else {
true
}
})

let index_data_dir = Node.Path.join2(Node.Process.cwd(), "./data")
let urlResources =
Node.Path.join2(index_data_dir, "packages_url_resources.json")
Expand All @@ -549,6 +615,7 @@ let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx =>
->unsafeToUrlResource
let props: props = {
"packages": pkges,
"unmaintained": unmaintained,
"urlResources": urlResources,
}

Expand Down
8 changes: 7 additions & 1 deletion src/Packages.resi
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ type npmPackage = {
description: string,
repositoryHref: Js.Null.t<string>,
npmHref: string,
searchScore: float,
maintenanceScore: float,
}

type props = {"packages": array<npmPackage>, "urlResources": array<urlResource>}
type props = {
"packages": array<npmPackage>,
"urlResources": array<urlResource>,
"unmaintained": array<npmPackage>,
}

let default: props => React.element

Expand Down

0 comments on commit 67ecba3

Please sign in to comment.