|
1 |
| -import summaryFixture from '../mirage/fixtures/summary'; |
2 |
| -import searchFixture from '../mirage/fixtures/search'; |
3 |
| -import categoriesFixture from '../mirage/fixtures/categories'; |
4 |
| -import crateFixture from '../mirage/fixtures/crate'; |
5 |
| -import crateVersionsFixture from '../mirage/fixtures/crate_versions'; |
6 |
| -import crateAuthorsFixture from '../mirage/fixtures/crate_authors'; |
7 |
| -import crateOwnersFixture from '../mirage/fixtures/crate_owners'; |
8 |
| -import crateTeamsFixture from '../mirage/fixtures/crate_teams'; |
9 |
| -import crateReverseDependenciesFixture from '../mirage/fixtures/crate_reverse_dependencies'; |
10 |
| -import crateDependenciesFixture from '../mirage/fixtures/crate_dependencies'; |
11 |
| -import crateDownloadsFixture from '../mirage/fixtures/crate_downloads'; |
12 |
| -import keywordFixture from '../mirage/fixtures/keyword'; |
13 |
| -import teamFixture from '../mirage/fixtures/team'; |
14 |
| -import userFixture from '../mirage/fixtures/user'; |
| 1 | +import Response from 'ember-cli-mirage/response'; |
15 | 2 |
|
16 | 3 | export default function() {
|
17 |
| - this.get('/summary', () => summaryFixture); |
| 4 | + this.get('/summary', function(schema) { |
| 5 | + let crates = schema.crates.all(); |
18 | 6 |
|
19 |
| - this.get('/api/v1/crates', (db, request) => { |
20 |
| - const { start, end } = pageParams(request); |
21 |
| - const payload = { |
22 |
| - crates: searchFixture.crates.slice(start, end), |
23 |
| - meta: searchFixture.meta, |
| 7 | + let just_updated = crates.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at)).slice(0, 10); |
| 8 | + let most_downloaded = crates.sort((a, b) => b.downloads - a.downloads).slice(0, 10); |
| 9 | + let new_crates = crates.sort((a, b) => compareIsoDates(b.created_at, a.created_at)).slice(0, 10); |
| 10 | + |
| 11 | + let num_crates = crates.length; |
| 12 | + let num_downloads = crates.models.reduce((sum, crate) => sum + crate.downloads, 0); |
| 13 | + |
| 14 | + let popular_categories = schema.categories.all().sort((a, b) => b.crates_cnt - a.crates_cnt).slice(0, 10); |
| 15 | + let popular_keywords = schema.keywords.all().sort((a, b) => b.crates_cnt - a.crates_cnt).slice(0, 10); |
| 16 | + |
| 17 | + return { |
| 18 | + just_updated: this.serialize(just_updated).crates |
| 19 | + .map(it => ({ ...it, versions: null })), |
| 20 | + most_downloaded: this.serialize(most_downloaded).crates |
| 21 | + .map(it => ({ ...it, versions: null })), |
| 22 | + new_crates: this.serialize(new_crates).crates |
| 23 | + .map(it => ({ ...it, versions: null })), |
| 24 | + num_crates, |
| 25 | + num_downloads, |
| 26 | + popular_categories: this.serialize(popular_categories).categories, |
| 27 | + popular_keywords: this.serialize(popular_keywords).keywords, |
24 | 28 | };
|
| 29 | + }); |
| 30 | + |
| 31 | + this.namespace = '/api/v1'; |
| 32 | + |
| 33 | + this.get('/crates', function(schema, request) { |
| 34 | + const { start, end } = pageParams(request); |
| 35 | + |
| 36 | + let crates = schema.crates.all(); |
| 37 | + |
| 38 | + if (request.queryParams.letter) { |
| 39 | + let letter = request.queryParams.letter.toLowerCase(); |
| 40 | + crates = crates.filter(crate => crate.id[0].toLowerCase() === letter); |
| 41 | + } |
| 42 | + |
| 43 | + if (request.queryParams.q) { |
| 44 | + let q = request.queryParams.q.toLowerCase(); |
| 45 | + crates = crates.filter(crate => crate.id.toLowerCase().indexOf(q) !== -1); |
| 46 | + } |
| 47 | + |
| 48 | + if (request.queryParams.user_id) { |
| 49 | + let userId = parseInt(request.queryParams.user_id, 10); |
| 50 | + crates = crates.filter(crate => (crate._owner_users || []).indexOf(userId) !== -1); |
| 51 | + } |
25 | 52 |
|
26 | 53 | if (request.queryParams.team_id) {
|
27 |
| - payload.team = teamFixture.team; |
28 |
| - } else if (request.queryParams.user_id) { |
29 |
| - payload.user = userFixture.user; |
| 54 | + let teamId = parseInt(request.queryParams.team_id, 10); |
| 55 | + crates = crates.filter(crate => (crate._owner_teams || []).indexOf(teamId) !== -1); |
| 56 | + } |
| 57 | + |
| 58 | + if (request.queryParams.sort === 'alpha') { |
| 59 | + crates = crates.sort((a, b) => compareStrings(a.id.toLowerCase(), b.id.toLowerCase())); |
30 | 60 | }
|
31 | 61 |
|
32 |
| - return payload; |
| 62 | + return withMeta(this.serialize(crates.slice(start, end)), { total: crates.length }); |
33 | 63 | });
|
34 | 64 |
|
35 |
| - this.get('/api/v1/categories', () => categoriesFixture); |
| 65 | + this.get('/crates/:crate_id', function(schema, request) { |
| 66 | + let crateId = request.params.crate_id; |
| 67 | + let crate = schema.crates.find(crateId); |
| 68 | + let categories = schema.categories.all() |
| 69 | + .filter(category => (crate.categories || []).indexOf(category.id) !== -1); |
| 70 | + let keywords = schema.keywords.all() |
| 71 | + .filter(keyword => (crate.keywords || []).indexOf(keyword.id) !== -1); |
| 72 | + let versions = schema.versions.all() |
| 73 | + .filter(version => (crate.versions || []).indexOf(parseInt(version.id, 10)) !== -1); |
| 74 | + |
| 75 | + return { |
| 76 | + ...this.serialize(crate), |
| 77 | + ...this.serialize(categories), |
| 78 | + ...this.serialize(keywords), |
| 79 | + ...this.serialize(versions), |
| 80 | + }; |
| 81 | + }); |
| 82 | + |
| 83 | + this.get('/crates/:crate_id/versions', (schema, request) => { |
| 84 | + let crate = request.params.crate_id; |
| 85 | + return schema.versions.where({ crate }).sort((a, b) => compareIsoDates(b.created_at, a.created_at)); |
| 86 | + }); |
| 87 | + |
| 88 | + this.get('/crates/:crate_id/:version_num/authors', (schema, request) => { |
| 89 | + let crate = request.params.crate_id; |
| 90 | + let num = request.params.version_num; |
| 91 | + let version = schema.versions.findBy({ crate, num }); |
| 92 | + return { meta: { names: version._authors }, users: [] }; |
| 93 | + }); |
| 94 | + |
| 95 | + this.get('/crates/:crate_id/:version_num/dependencies', (schema, request) => { |
| 96 | + let crate = request.params.crate_id; |
| 97 | + let num = request.params.version_num; |
| 98 | + let version_id = schema.versions.findBy({ crate, num }).id; |
| 99 | + return schema.dependencies.where({ version_id }); |
| 100 | + }); |
| 101 | + |
| 102 | + this.get('/crates/:crate_id/:version_num/downloads', function(schema, request) { |
| 103 | + let crateId = request.params.crate_id; |
| 104 | + let versionNum = request.params.version_num; |
| 105 | + let versionId = schema.versions.findBy({ crate: crateId, num: versionNum }).id; |
| 106 | + return schema.versionDownloads.where({ version: versionId }); |
| 107 | + }); |
| 108 | + |
| 109 | + this.get('/crates/:crate_id/owner_user', function(schema, request) { |
| 110 | + let crateId = request.params.crate_id; |
| 111 | + let crate = schema.crates.find(crateId); |
| 112 | + let users = schema.users.find(crate._owner_users); |
| 113 | + |
| 114 | + let response = this.serialize(users); |
| 115 | + |
| 116 | + response.users.forEach(user => { |
| 117 | + user.kind = 'user'; |
| 118 | + }); |
| 119 | + |
| 120 | + return response; |
| 121 | + }); |
| 122 | + |
| 123 | + this.get('/crates/:crate_id/owner_team', function(schema, request) { |
| 124 | + let crateId = request.params.crate_id; |
| 125 | + let crate = schema.crates.find(crateId); |
| 126 | + let teams = schema.teams.find(crate._owner_teams); |
| 127 | + |
| 128 | + let response = this.serialize(teams); |
36 | 129 |
|
37 |
| - this.get('/api/v1/crates/nanomsg', () => crateFixture); |
38 |
| - this.get('/api/v1/crates/nanomsg/versions', () => crateVersionsFixture); |
39 |
| - this.get('/api/v1/crates/nanomsg/:version_num/authors', () => crateAuthorsFixture); |
40 |
| - this.get('/api/v1/crates/nanomsg/owner_user', () => crateOwnersFixture); |
41 |
| - this.get('/api/v1/crates/nanomsg/owner_team', () => crateTeamsFixture); |
42 |
| - this.get('/api/v1/crates/nanomsg/reverse_dependencies', () => crateReverseDependenciesFixture); |
43 |
| - this.get('/api/v1/crates/nanomsg/:version_num/dependencies', () => crateDependenciesFixture); |
44 |
| - this.get('/api/v1/crates/nanomsg/downloads', () => crateDownloadsFixture); |
45 |
| - this.get('/api/v1/crates/nanomsg/:version_num/downloads', () => crateDownloadsFixture); |
46 |
| - this.get('/api/v1/keywords/network', () => keywordFixture); |
47 |
| - this.get('/api/v1/teams/:team_id', () => teamFixture); |
48 |
| - this.get('/api/v1/users/:user_id', () => userFixture); |
| 130 | + response.teams.forEach(team => { |
| 131 | + team.kind = 'team'; |
| 132 | + }); |
| 133 | + |
| 134 | + return response; |
| 135 | + }); |
| 136 | + |
| 137 | + this.get('/crates/:crate_id/reverse_dependencies', function(schema, request) { |
| 138 | + let { start, end } = pageParams(request); |
| 139 | + |
| 140 | + let crate = request.params.crate_id; |
| 141 | + let allDependencies = schema.dependencies.where({ crate_id: crate }); |
| 142 | + let dependencies = allDependencies.slice(start, end); |
| 143 | + let total = allDependencies.length; |
| 144 | + |
| 145 | + let serialized = this.serialize(dependencies); |
| 146 | + |
| 147 | + // TODO https://github.com/rust-lang/crates.io/pull/810 |
| 148 | + serialized.dependencies.forEach(dep => { |
| 149 | + let version = schema.versions.find(dep.version_id); |
| 150 | + dep.crate_id = version.crate; |
| 151 | + }); |
| 152 | + |
| 153 | + return withMeta(serialized, { total }); |
| 154 | + }); |
| 155 | + |
| 156 | + this.get('/crates/:crate_id/downloads', function(schema, request) { |
| 157 | + let crateId = request.params.crate_id; |
| 158 | + let crate = schema.crates.find(crateId); |
| 159 | + let versionDownloads = schema.versionDownloads.all() |
| 160 | + .filter(it => crate.versions.indexOf(parseInt(it.version, 10)) !== -1); |
| 161 | + |
| 162 | + return withMeta(this.serialize(versionDownloads), { extra_downloads: crate._extra_downloads }); |
| 163 | + }); |
| 164 | + |
| 165 | + this.get('/categories', function(schema, request) { |
| 166 | + let { start, end } = pageParams(request); |
| 167 | + |
| 168 | + let allCategories = schema.categories.all().sort((a, b) => compareStrings(a.category, b.category)); |
| 169 | + let categories = allCategories.slice(start, end); |
| 170 | + let total = allCategories.length; |
| 171 | + |
| 172 | + return withMeta(this.serialize(categories), { total }); |
| 173 | + }); |
| 174 | + |
| 175 | + this.get('/keywords', function(schema, request) { |
| 176 | + let { start, end } = pageParams(request); |
| 177 | + |
| 178 | + let allKeywords = schema.keywords.all().sort((a, b) => a.crates_cnt - b.crates_cnt); |
| 179 | + let keywords = allKeywords.slice(start, end); |
| 180 | + let total = allKeywords.length; |
| 181 | + |
| 182 | + return withMeta(this.serialize(keywords), { total }); |
| 183 | + }); |
| 184 | + |
| 185 | + this.get('/keywords/:keyword_id', (schema, request) => { |
| 186 | + let keywordId = request.params.keyword_id; |
| 187 | + let keyword = schema.keywords.find(keywordId); |
| 188 | + return keyword ? keyword : notFound(); |
| 189 | + }); |
| 190 | + |
| 191 | + this.get('/teams/:team_id', (schema, request) => { |
| 192 | + let login = request.params.team_id; |
| 193 | + let team = schema.teams.findBy({ login }); |
| 194 | + return team ? team : notFound(); |
| 195 | + }); |
| 196 | + |
| 197 | + this.get('/users/:user_id', (schema, request) => { |
| 198 | + let login = request.params.user_id; |
| 199 | + let user = schema.users.findBy({ login }); |
| 200 | + return user ? user : notFound(); |
| 201 | + }); |
| 202 | +} |
| 203 | + |
| 204 | +function notFound() { |
| 205 | + return new Response(404, { 'Content-Type': 'application/json' }, { |
| 206 | + 'errors': [{ 'detail': 'Not Found' }] |
| 207 | + }); |
49 | 208 | }
|
50 | 209 |
|
51 | 210 | function pageParams(request) {
|
52 | 211 | const { queryParams } = request;
|
53 | 212 |
|
54 |
| - const page = parseInt(queryParams.page); |
55 |
| - const perPage = parseInt(queryParams.per_page); |
| 213 | + const page = parseInt(queryParams.page || '1'); |
| 214 | + const perPage = parseInt(queryParams.per_page || '10'); |
56 | 215 |
|
57 | 216 | const start = (page - 1) * perPage;
|
58 | 217 | const end = start + perPage;
|
59 | 218 |
|
60 | 219 | return { page, perPage, start, end };
|
61 | 220 | }
|
| 221 | + |
| 222 | +function withMeta(response, meta) { |
| 223 | + response.meta = meta; |
| 224 | + return response; |
| 225 | +} |
| 226 | + |
| 227 | +function compareStrings(a, b) { |
| 228 | + return (a < b) ? -1 : (a > b) ? 1 : 0; |
| 229 | +} |
| 230 | + |
| 231 | +function compareIsoDates(a, b) { |
| 232 | + let aDate = new Date(a); |
| 233 | + let bDate = new Date(b); |
| 234 | + return (aDate < bDate) ? -1 : (aDate > bDate) ? 1 : 0; |
| 235 | +} |
0 commit comments