1 /**
2 	Copyright: © 2013 rejectedsoftware e.K.
3 	License: Subject to the terms of the GNU GPLv3 license, as written in the included LICENSE.txt file.
4 	Authors: Colden Cullen
5 */
6 module dubregistry.api;
7 
8 import dubregistry.dbcontroller;
9 import dubregistry.registry;
10 
11 import vibe.d;
12 
13 void registerDubRegistryWebApi(URLRouter router, DubRegistry registry)
14 {
15 	auto pkgs = new Packages(registry);
16 	router.registerRestInterface(pkgs, "/api/packages");
17 }
18 
19 struct SearchResult { string name, description, version_; }
20 
21 interface IPackages {
22 	@method(HTTPMethod.GET)
23 	SearchResult[] search(string q);
24 
25 	@path(":name/latest")
26 	string getLatestVersion(string _name);
27 
28 	@path(":name/stats")
29 	Json getStats(string _name);
30 
31 	@path(":name/:version/stats")
32 	Json getStats(string _name, string _version);
33 
34 	@path(":name/info")
35 	Json getInfo(string _name);
36 
37 	@path(":name/:version/info")
38 	Json getInfo(string _name, string _version);
39 }
40 
41 class Packages : IPackages {
42 	private {
43 		DubRegistry m_registry;
44 	}
45 
46 	this(DubRegistry registry)
47 	{
48 		m_registry = registry;
49 	}
50 
51 override {
52 	@method(HTTPMethod.GET)
53 	SearchResult[] search(string q) {
54 		return m_registry.searchPackages(q)
55 			.map!(p => SearchResult(p.name, p.info["description"].opt!string, p.version_))
56 			.array;
57 	}
58 
59 	string getLatestVersion(string name) {
60 		return m_registry.getLatestVersion(rootOf(name))
61 			.check!(r => r.length)(HTTPStatus.notFound, "Package not found");
62 	}
63 
64 	Json getStats(string name) {
65 		return m_registry.getPackageStats(rootOf(name))
66 			.check!(r => r.type != Json.Type.null_)(HTTPStatus.notFound, "Package not found");
67 	}
68 
69 	Json getStats(string name, string ver) {
70 		return m_registry.getPackageStats(rootOf(name), ver)
71 			.check!(r => r.type != Json.Type.null_)(HTTPStatus.notFound, "Package/Version not found");
72 	}
73 
74 	Json getInfo(string name) {
75 		return m_registry.getPackageInfo(rootOf(name))
76 			.check!(r => r.type != Json.Type.null_)(HTTPStatus.notFound, "Package/Version not found");
77 	}
78 
79 	Json getInfo(string name, string ver) {
80 		return m_registry.getPackageVersionInfo(rootOf(name), ver)
81 			.check!(r => r.type != Json.Type.null_)(HTTPStatus.notFound, "Package/Version not found");
82 	}
83 }
84 
85 private:
86 	string rootOf(string pkg) {
87 		import std.algorithm: findSplitBefore;
88 		return pkg.urlDecode().findSplitBefore(":")[0];
89 	}
90 }
91 
92 
93 private	auto ref T check(alias cond, T)(auto ref T t, HTTPStatus status, string msg)
94 {
95 	enforce(cond(t), new HTTPStatusException(status, msg));
96 	return t;
97 }