# Base classes used by `nitweb`.
module api_base
-import model::model_views
-import model::model_json
-import doc_down
import popcorn
import popcorn::pop_config
import popcorn::pop_repos
import popcorn::pop_json
+import commands::commands_http
+import commands::commands_json
+import commands::commands_html
+
# Nitweb config file.
class NitwebConfig
super AppConfig
# Modelbuilder used to access sources.
var modelbuilder: ModelBuilder
- # ModelView used to access model.
- var view: ModelView
+ # The JSON API does not filter anything by default.
+ var filter: nullable ModelFilter
+
+ # Catalog to pass to handlers.
+ var catalog: Catalog
end
# Specific handler for the nitweb API.
var config: NitwebConfig
# Find the MEntity ` with `full_name`.
- fun find_mentity(model: ModelView, full_name: nullable String): nullable MEntity do
+ fun find_mentity(full_name: nullable String): nullable MEntity do
if full_name == null then return null
- var mentity = model.mentity_by_full_name(full_name.from_percent_encoding)
+ var mentity = config.model.mentity_by_full_name(full_name.from_percent_encoding, config.filter)
if mentity == null then return null
- if config.view.accept_mentity(mentity) then return mentity
+
+ var filter = config.filter
+ if filter == null or filter.accept_mentity(mentity) then return mentity
return null
end
res.api_error(400, "Expected mentity full name")
return null
end
- var mentity = find_mentity(config.view, id)
+ var mentity = find_mentity(id)
if mentity == null then
res.api_error(404, "MEntity `{id}` not found")
end
fun api_json(req: HttpRequest, serializable: nullable Serializable, status: nullable Int, plain, pretty: nullable Bool) do
json(serializable, status, plain, req.bool_arg("pretty"))
end
-
- # Return the full version of `serializable` as a json string
- #
- # Uses `req` to define serializable options.
- fun api_full_json(req: HttpRequest, serializable: nullable MEntity, status: nullable Int, plain, pretty: nullable Bool) do
- if serializable == null then
- json(null, status)
- else
- raw_json(serializable.serialize_to_full_json(
- plain or else true, req.bool_arg("pretty") or else false), status)
- end
- end
- # Write data as JSON and set the right content type header.
- fun raw_json(json: nullable String, status: nullable Int) do
- header["Content-Type"] = media_types["json"].as(not null)
- if json == null then
- send(null, status)
- else
- send(json, status)
- end
- end
end
# An error returned by the API.
var message: String
end
-# Fullname representation that can be used to build decorated links
-#
-# * MPackage: `mpackage_name`
-# * MGroup: `(mpackage_name::)mgroup_name`
-class Namespace
- super Array[nullable NSEntity]
- super NSEntity
- serialize
-
- redef fun to_s do return self.join("")
- redef fun serialize_to(v) do to_a.serialize_to(v)
-end
-
-# Something that goes in a Namespace
-#
-# Can be either:
-# * a `NSToken` for tokens like `::`, `>` and `$`
-# * a `MSRef` for references to mentities
-interface NSEntity
- super Serializable
-end
-
-# A reference to a MEntity that can be rendered as a link.
-#
-# We do not reuse `MEntityRef` ref since NSRef can be found in a ref and create
-# an infinite loop.
-class NSRef
- super NSEntity
- serialize
-
- # The mentity to link to/
- var mentity: MEntity
-
- redef fun core_serialize_to(v) do
- v.serialize_attribute("web_url", mentity.web_url)
- v.serialize_attribute("api_url", mentity.api_url)
- v.serialize_attribute("name", mentity.name)
- end
-end
-
-# A namespace token representation
-#
-# Used for namespace tokens like `::`, `>` and `$`
-redef class String
- super NSEntity
-end
-
redef class MEntity
# URL to `self` within the web interface.
# URL to `self` within the JSON api.
fun api_url: String do return "/api/entity/" / full_name
+ redef fun html_url do return web_url
+
redef fun core_serialize_to(v) do
super
- v.serialize_attribute("namespace", namespace)
v.serialize_attribute("web_url", web_url)
v.serialize_attribute("api_url", api_url)
end
-
- # Return `self.full_name` as an object that can be serialized to json.
- fun namespace: nullable Namespace do return null
-
- # Return a new NSRef to `self`.
- fun to_ns_ref: NSRef do return new NSRef(self)
end
redef class MEntityRef
redef fun core_serialize_to(v) do
super
- v.serialize_attribute("namespace", mentity.namespace)
v.serialize_attribute("web_url", mentity.web_url)
v.serialize_attribute("api_url", mentity.api_url)
- v.serialize_attribute("name", mentity.name)
- v.serialize_attribute("mdoc", mentity.mdoc_or_fallback)
- v.serialize_attribute("visibility", mentity.visibility.to_s)
- v.serialize_attribute("modifiers", mentity.collect_modifiers)
- v.serialize_attribute("class_name", mentity.class_name)
- var mentity = self.mentity
- if mentity isa MMethod then
- v.serialize_attribute("msignature", mentity.intro.msignature)
- else if mentity isa MMethodDef then
- v.serialize_attribute("msignature", mentity.msignature)
- else if mentity isa MVirtualTypeProp then
- v.serialize_attribute("bound", to_mentity_ref(mentity.intro.bound))
- else if mentity isa MVirtualTypeDef then
- v.serialize_attribute("bound", to_mentity_ref(mentity.bound))
- end
- v.serialize_attribute("location", mentity.location)
- end
-end
-
-redef class MDoc
-
- # Add doc down processing
- redef fun core_serialize_to(v) do
- v.serialize_attribute("html_synopsis", html_synopsis.write_to_string)
- end
-end
-
-redef class MPackage
- redef fun namespace do return new Namespace.from([to_ns_ref])
-end
-
-redef class MGroup
- redef fun namespace do
- var p = parent
- if p == null then
- return new Namespace.from([to_ns_ref, ">": nullable NSEntity])
- end
- return new Namespace.from([p.namespace, to_ns_ref, ">": nullable NSEntity])
- end
-end
-
-redef class MModule
- redef fun namespace do
- var mgroup = self.mgroup
- if mgroup == null then
- return new Namespace.from([to_ns_ref])
- end
- return new Namespace.from([mgroup.mpackage.to_ns_ref, "::", to_ns_ref: nullable NSEntity])
- end
-
- private fun ns_for(visibility: MVisibility): nullable Namespace do
- if visibility <= private_visibility then return namespace
- var mgroup = self.mgroup
- if mgroup == null then return namespace
- return mgroup.mpackage.namespace
- end
-end
-
-redef class MClass
- redef fun namespace do
- return new Namespace.from([intro_mmodule.ns_for(visibility), "::", to_ns_ref: nullable NSEntity])
end
end
redef class MClassDef
- redef fun namespace do
- if is_intro then
- return new Namespace.from([mmodule.ns_for(mclass.visibility), "$", to_ns_ref: nullable NSEntity])
- else if mclass.intro_mmodule.mpackage != mmodule.mpackage then
- return new Namespace.from([mmodule.namespace, "$", mclass.namespace: nullable NSEntity])
- else if mclass.visibility > private_visibility then
- return new Namespace.from([mmodule.namespace, "$", mclass.to_ns_ref: nullable NSEntity])
- end
- return new Namespace.from([mmodule.full_name, "$::", mclass.intro_mmodule.to_ns_ref: nullable NSEntity])
- end
-
redef fun web_url do return "{mclass.web_url}/lin#{full_name}"
end
-redef class MProperty
- redef fun namespace do
- if intro_mclassdef.is_intro then
- return new Namespace.from([intro_mclassdef.mmodule.ns_for(visibility), "::", intro_mclassdef.mclass.to_ns_ref, "::", to_ns_ref: nullable NSEntity])
- else
- return new Namespace.from([intro_mclassdef.mmodule.namespace, "::", intro_mclassdef.mclass.to_ns_ref, "::", to_ns_ref: nullable NSEntity])
- end
- end
+redef class MPropDef
+ redef fun web_url do return "{mproperty.web_url}/lin#{full_name}"
end
-redef class MPropDef
- redef fun namespace do
- var res = new Namespace
- res.add mclassdef.namespace
- res.add "$"
-
- if mclassdef.mclass == mproperty.intro_mclassdef.mclass then
- res.add to_ns_ref
- else
- if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then
- res.add mproperty.intro_mclassdef.mmodule.ns_for(mproperty.visibility)
- res.add "::"
- else if mproperty.visibility <= private_visibility then
- if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then
- res.add "::"
- res.add mproperty.intro_mclassdef.mmodule.to_ns_ref
- res.add "::"
- end
- end
- if mclassdef.mclass != mproperty.intro_mclassdef.mclass then
- res.add mproperty.intro_mclassdef.to_ns_ref
- res.add "::"
- end
- res.add to_ns_ref
- end
- return res
+redef class MType
+ redef fun core_serialize_to(v) do
+ super
+ v.serialize_attribute("web_url", web_url)
+ v.serialize_attribute("api_url", api_url)
end
-
- redef fun web_url do return "{mproperty.web_url}/lin#{full_name}"
end
redef class MClassType
redef var web_url = mclass.web_url is lazy
+ redef var api_url = mclass.api_url is lazy
end
redef class MNullableType
redef var web_url = mtype.web_url is lazy
+ redef var api_url = mtype.api_url is lazy
end
redef class MParameterType
redef var web_url = mclass.web_url is lazy
+ redef var api_url = mclass.api_url is lazy
end
redef class MVirtualType
redef var web_url = mproperty.web_url is lazy
+ redef var api_url = mproperty.api_url is lazy
end
-redef class POSetElement[E]
- super Serializable
+redef class CmdLicenseFile
+ redef var file_url is lazy do
+ var mentity = self.mentity
+ if mentity == null then return super
+ return "{mentity.web_url}/license"
+ end
+end
- redef fun core_serialize_to(v) do
- assert self isa POSetElement[MEntity]
- v.serialize_attribute("direct_greaters", to_mentity_refs(direct_greaters))
- v.serialize_attribute("direct_smallers", to_mentity_refs(direct_smallers))
+redef class CmdContribFile
+ redef var file_url is lazy do
+ var mentity = self.mentity
+ if mentity == null then return super
+ return "{mentity.web_url}/contrib"
end
end