@@ -23,21 +23,27 @@ type npmPackage = {
2323 description : string ,
2424 repositoryHref : Js .Null .t <string >,
2525 npmHref : string ,
26+ searchScore : float ,
27+ maintenanceScore : float ,
2628}
2729
30+ // These are packages that we do not want to filter out when loading searching from NPM.
31+ let packageAllowList : array <string > = []
32+
2833module Resource = {
29- type t = Npm (npmPackage ) | Url (urlResource )
34+ type t = Npm (npmPackage ) | Url (urlResource ) | Outdated ( npmPackage )
3035
3136 let getId = (res : t ) => {
3237 switch res {
3338 | Npm ({name })
39+ | Outdated ({name })
3440 | Url ({name }) => name
3541 }
3642 }
3743
3844 let shouldFilter = (res : t ) => {
3945 switch res {
40- | Npm (pkg ) =>
46+ | Npm (pkg ) | Outdated ( pkg ) =>
4147 if pkg .name -> Js .String2 .startsWith ("@elm-react" ) {
4248 true
4349 } else if pkg .name -> Js .String2 .startsWith ("bs-" ) {
@@ -71,7 +77,7 @@ module Resource = {
7177
7278 let isOfficial = (res : t ) => {
7379 switch res {
74- | Npm (pkg ) =>
80+ | Npm (pkg ) | Outdated ( pkg ) =>
7581 pkg .name === "rescript" ||
7682 pkg .name -> Js .String2 .startsWith ("@rescript/" ) ||
7783 pkg .name === "gentype"
@@ -94,7 +100,9 @@ module Resource = {
94100
95101 let fuser = Fuse .make (packages , fuseOpts )
96102
97- fuser -> Fuse .search (pattern )
103+ fuser
104+ -> Fuse .search (pattern )
105+ -> Js .Array2 .sortInPlaceWith ((a , b ) => a ["item" ].searchScore > b ["item" ].searchScore ? - 1 : 1 )
98106 }
99107
100108 let applyUrlResourceSearch = (urls : array <urlResource >, pattern : string ): array <
@@ -116,35 +124,41 @@ module Resource = {
116124 }
117125
118126 let applySearch = (resources : array <t >, pattern : string ): array <t > => {
119- let (allNpms , allUrls ) = Belt .Array .reduce (resources , ([], []), (acc , next ) => {
120- let (npms , resources ) = acc
127+ let (allNpms , allUrls , allOutDated ) = Belt .Array .reduce (resources , ([], [], []), (
128+ acc ,
129+ next ,
130+ ) => {
131+ let (npms , resources , outdated ) = acc
121132
122133 switch next {
123134 | Npm (pkg ) => Js .Array2 .push (npms , pkg )-> ignore
124135 | Url (res ) => Js .Array2 .push (resources , res )-> ignore
136+ | Outdated (pkg ) => Js .Array2 .push (outdated , pkg )-> ignore
125137 }
126- (npms , resources )
138+ (npms , resources , outdated )
127139 })
128140
129141 let filteredNpm = applyNpmSearch (allNpms , pattern )-> Belt .Array .map (m => Npm (m ["item" ]))
130142 let filteredUrls = applyUrlResourceSearch (allUrls , pattern )-> Belt .Array .map (m => Url (m ["item" ]))
143+ let filteredOutdated =
144+ applyNpmSearch (allOutDated , pattern )-> Belt .Array .map (m => Outdated (m ["item" ]))
131145
132- Belt .Array .concat ( filteredNpm , filteredUrls )
146+ Belt .Array .concatMany ([ filteredNpm , filteredUrls , filteredOutdated ] )
133147 }
134148}
135149
136150module Card = {
137151 @react.component
138152 let make = (~value : Resource .t , ~onKeywordSelect : option <string => unit >= ?) => {
139153 let icon = switch value {
140- | Npm (_ ) => <Icon .Npm className = "w-8 opacity-50" />
154+ | Npm (_ ) | Outdated ( _ ) => <Icon .Npm className = "w-8 opacity-50" />
141155 | Url (_ ) =>
142156 <span >
143157 <Icon .Hyperlink className = "w-8 opacity-50" />
144158 </span >
145159 }
146160 let linkBox = switch value {
147- | Npm (pkg ) =>
161+ | Npm (pkg ) | Outdated ( pkg ) =>
148162 let repositoryHref = Js .Null .toOption (pkg .repositoryHref )
149163 let repoEl = switch repositoryHref {
150164 | Some (href ) =>
@@ -169,12 +183,14 @@ module Card = {
169183 }
170184
171185 let titleHref = switch value {
172- | Npm (pkg ) => pkg .repositoryHref -> Js .Null .toOption -> Belt .Option .getWithDefault (pkg .npmHref )
186+ | Npm (pkg ) | Outdated (pkg ) =>
187+ pkg .repositoryHref -> Js .Null .toOption -> Belt .Option .getWithDefault (pkg .npmHref )
173188 | Url (res ) => res .urlHref
174189 }
175190
176191 let (title , description , keywords ) = switch value {
177192 | Npm ({name , description , keywords })
193+ | Outdated ({name , description , keywords })
178194 | Url ({name , description , keywords }) => (name , description , keywords )
179195 }
180196
@@ -238,6 +254,7 @@ module Filter = {
238254 includeCommunity : bool ,
239255 includeNpm : bool ,
240256 includeUrlResource : bool ,
257+ includeOutdated : bool ,
241258 }
242259}
243260
@@ -263,7 +280,7 @@ module InfoSidebar = {
263280
264281 <aside className = " border-l-2 p-4 py-12 border-fire-30 space-y-16" >
265282 <div >
266- <h2 className = h2 > {React .string ("Filter for " )} </h2 >
283+ <h2 className = h2 > {React .string ("Include " )} </h2 >
267284 <div className = "space-y-2" >
268285 <Toggle
269286 enabled = {filter .includeOfficial }
@@ -301,6 +318,15 @@ module InfoSidebar = {
301318 }}>
302319 {React .string ("URL resources" )}
303320 </Toggle >
321+ <Toggle
322+ enabled = {filter .includeOutdated }
323+ toggle = {() => {
324+ setFilter (prev => {
325+ {... prev , Filter .includeOutdated : ! filter .includeOutdated }
326+ })
327+ }}>
328+ {React .string ("Outdated" )}
329+ </Toggle >
304330 </div >
305331 </div >
306332 <div >
@@ -320,7 +346,11 @@ module InfoSidebar = {
320346 }
321347}
322348
323- type props = {"packages" : array <npmPackage >, "urlResources" : array <urlResource >}
349+ type props = {
350+ "packages" : array <npmPackage >,
351+ "urlResources" : array <urlResource >,
352+ "unmaintained" : array <npmPackage >,
353+ }
324354
325355type state =
326356 | All
@@ -346,13 +376,14 @@ let default = (props: props) => {
346376 includeCommunity : true ,
347377 includeNpm : true ,
348378 includeUrlResource : true ,
379+ includeOutdated : false ,
349380 })
350381
351382 let allResources = {
352383 let npms = props ["packages" ]-> Belt .Array .map (pkg => Resource .Npm (pkg ))
353384 let urls = props ["urlResources" ]-> Belt .Array .map (res => Resource .Url (res ))
354-
355- Belt .Array .concat ( npms , urls )
385+ let outdated = props [ "unmaintained" ] -> Belt . Array . map ( pkg => Resource . Outdated ( pkg ))
386+ Belt .Array .concatMany ([ npms , urls , outdated ] )
356387 }
357388
358389 let resources = switch state {
@@ -386,6 +417,7 @@ let default = (props: props) => {
386417 let isResourceIncluded = switch next {
387418 | Npm (_ ) => filter .includeNpm
388419 | Url (_ ) => filter .includeUrlResource
420+ | Outdated (_ ) => filter .includeOutdated && filter .includeNpm
389421 }
390422 if ! isResourceIncluded {
391423 ()
@@ -435,7 +467,6 @@ let default = (props: props) => {
435467
436468 React .useEffect (() => {
437469 firstRenderDone .current = true
438-
439470 None
440471 }, [])
441472
@@ -505,6 +536,11 @@ let default = (props: props) => {
505536
506537type npmData = {
507538 "objects" : array <{
539+ "searchScore" : float ,
540+ "score" : {
541+ "final" : float ,
542+ "detail" : {"quality" : float , "popularity" : float , "maintenance" : float },
543+ },
508544 "package" : {
509545 "name" : string ,
510546 "keywords" : array <string >,
@@ -522,14 +558,8 @@ module Response = {
522558
523559@val external fetchNpmPackages : string => promise <Response .t > = "fetch"
524560
525- let getStaticProps : Next .GetStaticProps .revalidate <props , unit > = async _ctx => {
526- let response = await fetchNpmPackages (
527- "https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250" ,
528- )
529-
530- let data = await response -> Response .json
531-
532- let pkges = Belt .Array .map (data ["objects" ], item => {
561+ let parsePkgs = data =>
562+ Belt .Array .map (data ["objects" ], item => {
533563 let pkg = item ["package" ]
534564 {
535565 name : pkg ["name" ],
@@ -538,9 +568,45 @@ let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx =>
538568 description : Belt .Option .getWithDefault (pkg ["description" ], "" ),
539569 repositoryHref : Js .Null .fromOption (pkg ["links" ]["repository" ]),
540570 npmHref : pkg ["links" ]["npm" ],
571+ searchScore : item ["searchScore" ],
572+ maintenanceScore : item ["score" ]["detail" ]["maintenance" ],
541573 }
542574 })
543575
576+ let getStaticProps : Next .GetStaticProps .revalidate <props , unit > = async _ctx => {
577+ let baseUrl = "https://registry.npmjs.org/-/v1/search?text=keywords:rescript&size=250&maintenance=1.0&popularity=0.5&quality=0.9"
578+
579+ let (one , two , three ) = await Js .Promise2 .all3 ((
580+ fetchNpmPackages (baseUrl ),
581+ fetchNpmPackages (baseUrl ++ "&from=250" ),
582+ fetchNpmPackages (baseUrl ++ "&from=500" ),
583+ ))
584+
585+ let (data1 , data2 , data3 ) = await Js .Promise2 .all3 ((
586+ one -> Response .json ,
587+ two -> Response .json ,
588+ three -> Response .json ,
589+ ))
590+
591+ let unmaintained = []
592+
593+ let pkges =
594+ parsePkgs (data1 )
595+ -> Js .Array2 .concat (parsePkgs (data2 ))
596+ -> Js .Array2 .concat (parsePkgs (data3 ))
597+ -> Js .Array2 .filter (pkg => {
598+ if packageAllowList -> Js .Array2 .includes (pkg .name ) {
599+ true
600+ } else if pkg .name -> Js .String2 .includes ("reason" ) {
601+ false
602+ } else if pkg .maintenanceScore < 0.3 {
603+ let _ = unmaintained -> Js .Array2 .push (pkg )
604+ false
605+ } else {
606+ true
607+ }
608+ })
609+
544610 let index_data_dir = Node .Path .join2 (Node .Process .cwd (), "./data" )
545611 let urlResources =
546612 Node .Path .join2 (index_data_dir , "packages_url_resources.json" )
@@ -549,6 +615,7 @@ let getStaticProps: Next.GetStaticProps.revalidate<props, unit> = async _ctx =>
549615 -> unsafeToUrlResource
550616 let props : props = {
551617 "packages" : pkges ,
618+ "unmaintained" : unmaintained ,
552619 "urlResources" : urlResources ,
553620 }
554621
0 commit comments