-
-
Notifications
You must be signed in to change notification settings - Fork 251
improve Package search sorting #860
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
Changes from 5 commits
650d1b3
95f269a
e6a3808
9623985
789bc14
c96fbaf
e2bd413
5e6722c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,21 +23,25 @@ type npmPackage = { | |
description: string, | ||
repositoryHref: Js.Null.t<string>, | ||
npmHref: string, | ||
searchScore: float, | ||
maintenanceScore: float, | ||
score: {"final": float, "detail": {"quality": float, "popularity": float, "maintenance": float}}, | ||
} | ||
|
||
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-") { | ||
|
@@ -71,7 +75,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" | ||
|
@@ -94,7 +98,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< | ||
|
@@ -116,35 +122,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.concat(filteredNpm, filteredUrls)->Belt.Array.concat(filteredOutdated) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is also Belt.Array.concatMany([]) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
} | ||
} | ||
|
||
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) => | ||
|
@@ -169,12 +181,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) | ||
} | ||
|
||
|
@@ -238,6 +252,7 @@ module Filter = { | |
includeCommunity: bool, | ||
includeNpm: bool, | ||
includeUrlResource: bool, | ||
includeOutdated: bool, | ||
} | ||
} | ||
|
||
|
@@ -263,7 +278,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} | ||
|
@@ -301,6 +316,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> | ||
|
@@ -320,7 +344,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 | ||
|
@@ -346,13 +374,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.concat(npms, urls)->Belt.Array.concat(outdated) | ||
} | ||
|
||
let resources = switch state { | ||
|
@@ -386,6 +415,7 @@ let default = (props: props) => { | |
let isResourceIncluded = switch next { | ||
| Npm(_) => filter.includeNpm | ||
| Url(_) => filter.includeUrlResource | ||
| Outdated(_) => filter.includeOutdated && filter.includeNpm | ||
} | ||
if !isResourceIncluded { | ||
() | ||
|
@@ -435,7 +465,6 @@ let default = (props: props) => { | |
|
||
React.useEffect(() => { | ||
firstRenderDone.current = true | ||
|
||
None | ||
}, []) | ||
|
||
|
@@ -505,6 +534,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>, | ||
|
@@ -522,14 +556,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"], | ||
|
@@ -538,9 +566,46 @@ 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"], | ||
score: item["score"], | ||
} | ||
}) | ||
|
||
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 [/* Allow list of names */]->Js.Array2.includes(pkg.name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could do a let allowList = [] somehwere at the beginning of the file already then you don't need the comment here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
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") | ||
|
@@ -549,6 +614,7 @@ let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx => | |
->unsafeToUrlResource | ||
let props: props = { | ||
"packages": pkges, | ||
"unmaintained": unmaintained, | ||
"urlResources": urlResources, | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.