redef class APIRouter
redef init do
super
+ use("/catalog/packages/", new APICatalogPackages(config))
+
use("/catalog/highlighted", new APICatalogHighLighted(config))
use("/catalog/required", new APICatalogMostRequired(config))
use("/catalog/bytags", new APICatalogByTags(config))
use("/catalog/contributors", new APICatalogContributors(config))
use("/catalog/stats", new APICatalogStats(config))
+
+ use("/catalog/tags", new APICatalogTags(config))
+ use("/catalog/tag/:tid", new APICatalogTag(config))
end
end
abstract class APICatalogHandler
super APIHandler
+ # Sorter used to sort packages
+ #
+ # Sorting is based on mpackage score.
+ var mpackages_sorter = new CatalogScoreSorter(config.catalog) is lazy
+
# List the 10 best packages from `cpt`
fun list_best(cpt: Counter[MPackage]): JsonArray do
var res = new JsonArray
end
end
-class APICatalogStats
+# Get all the packages from the catalog using pagination
+#
+# `GET /packages?p=1&n=10`: get the list of catalog by page
+class APICatalogPackages
super APICatalogHandler
redef fun get(req, res) do
- var obj = new JsonObject
- obj["packages"] = config.model.mpackages.length
- obj["maintainers"] = config.catalog.maint2proj.length
- obj["contributors"] = config.catalog.contrib2proj.length
- obj["modules"] = config.catalog.mmodules.sum
- obj["classes"] = config.catalog.mclasses.sum
- obj["methods"] = config.catalog.mmethods.sum
- obj["loc"] = config.catalog.loc.sum
- res.json obj
+ var page = req.int_arg("p")
+ var limit = req.int_arg("n")
+ var mpackages = config.catalog.mpackages.values.to_a
+ mpackages_sorter.sort(mpackages)
+ var response = new JsonArray.from(mpackages)
+ res.json paginate(response, response.length, page, limit)
end
end
end
end
+# Get the catalog statistics
+#
+# `GET /stats`: return the catalog statistics
+class APICatalogStats
+ super APICatalogHandler
+
+ redef fun get(req, res) do
+ res.json config.catalog.catalog_stats
+ end
+end
+
+# Get all the tags from the catalog
+#
+# `GET /tags`: the list of tags associated with their number of packages
+class APICatalogTags
+ super APICatalogHandler
+
+ # Sorter to sort tags alphabetically
+ var tags_sorter = new CatalogTagsSorter
+
+ redef fun get(req, res) do
+ var obj = new JsonObject
+
+ var tags = config.catalog.tag2proj.keys.to_a
+ tags_sorter.sort(tags)
+
+ for tag in tags do
+ if not config.catalog.tag2proj.has_key(tag) then continue
+ obj[tag] = config.catalog.tag2proj[tag].length
+ end
+ res.json obj
+ end
+end
+
+# Get the packages related to a tag
+#
+# `GET /tag/:tid?p=1&n=10`: return a paginated list of packages
+class APICatalogTag
+ super APICatalogHandler
+
+ redef fun get(req, res) do
+ var page = req.int_arg("p")
+ var limit = req.int_arg("n")
+ var id = req.param("tid")
+ if id == null then
+ res.api_error(400, "Missing tag")
+ return
+ end
+ id = id.from_percent_encoding
+ if not config.catalog.tag2proj.has_key(id) then
+ res.api_error(404, "Tag not found")
+ return
+ end
+ var obj = new JsonObject
+ obj["tag"] = id
+ var mpackages = config.catalog.tag2proj[id]
+ mpackages_sorter.sort(mpackages)
+ var response = new JsonArray.from(mpackages)
+ obj["packages"] = paginate(response, response.length, page, limit)
+ res.json obj
+ end
+end
redef class Catalog
# Build the catalog from `mpackages`
v.serialize_attribute("gravatar", gravatar)
end
end
+
+redef class MPackage
+ # Serialize the full catalog version of `self` to JSON
+ #
+ # See: `FullCatalogSerializer`
+ fun to_full_catalog_json(catalog: Catalog, plain, pretty: nullable Bool): String do
+ var stream = new StringWriter
+ var serializer = new FullCatalogSerializer(stream, catalog)
+ serializer.plain_json = plain or else false
+ serializer.pretty_json = pretty or else false
+ serializer.serialize self
+ stream.close
+ return stream.to_s
+ end
+
+ redef fun core_serialize_to(v) do
+ super
+ v.serialize_attribute("metadata", metadata)
+ if v isa FullCatalogSerializer then
+ v.serialize_attribute("stats", v.catalog.mpackages_stats[self])
+
+ var parents = v.catalog.deps[self].direct_greaters.to_a
+ v.serialize_attribute("dependencies", v.deps_to_json(parents))
+ var children = v.catalog.deps[self].direct_smallers.to_a
+ v.serialize_attribute("clients", v.deps_to_json(children))
+ end
+ end
+end
+
+# CatalogSerializer decorate the Package JSON with full catalog metadata
+#
+# See MEntity::to_full_catalog_json.
+class FullCatalogSerializer
+ super FullJsonSerializer
+
+ # Catalog used to decorate the MPackages
+ var catalog: Catalog
+
+ private fun deps_to_json(mpackages: Array[MPackage]): JsonArray do
+ var res = new JsonArray
+ for mpackage in mpackages do
+ res.add dep_to_json(mpackage)
+ end
+ return res
+ end
+
+ private fun dep_to_json(mpackage: MPackage): JsonObject do
+ var obj = new JsonObject
+ obj["name"] = mpackage.name
+ var mdoc = mpackage.mdoc_or_fallback
+ if mdoc != null then
+ obj["synopsis"] = mdoc.synopsis.write_to_string
+ end
+ return obj
+ end
+end