Skip to content

Commit 899eeb1

Browse files
authored
mirage: Respect include query params in GET /api/v1/crates/:id (#10276)
1 parent 68064d3 commit 899eeb1

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

mirage/route-handlers/crates.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,15 @@ export function register(server) {
5858
let { name } = request.params;
5959
let crate = schema.crates.findBy({ name });
6060
if (!crate) return notFound();
61-
61+
let serialized = this.serialize(crate);
6262
return {
63-
...this.serialize(crate),
64-
...this.serialize(crate.categories),
65-
...this.serialize(crate.keywords),
66-
...this.serialize(crate.versions.sort((a, b) => Number(b.id) - Number(a.id))),
63+
categories: null,
64+
keywords: null,
65+
versions: null,
66+
...serialized,
67+
...(serialized.crate.categories && this.serialize(crate.categories)),
68+
...(serialized.crate.keywords && this.serialize(crate.keywords)),
69+
...(serialized.crate.versions && this.serialize(crate.versions.sort((a, b) => Number(b.id) - Number(a.id)))),
6770
};
6871
});
6972

mirage/serializers/crate.js

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@ import semverSort from 'semver/functions/rsort';
66
import { compareIsoDates } from '../route-handlers/-utils';
77
import BaseSerializer from './application';
88

9+
const VALID_INCLUDE_MODEL = new Set(['versions', 'keywords', 'categories' /*, 'badges', 'downloads' */]);
10+
911
export default BaseSerializer.extend({
12+
include(request) {
13+
let include = request.queryParams.include;
14+
return include == null || include === 'full'
15+
? VALID_INCLUDE_MODEL.values()
16+
: include.split(',').filter(it => VALID_INCLUDE_MODEL.has(it));
17+
},
1018
attrs: [
1119
'badges',
1220
'categories',
@@ -38,19 +46,20 @@ export default BaseSerializer.extend({
3846

3947
getHashForResource() {
4048
let [hash, addToIncludes] = BaseSerializer.prototype.getHashForResource.apply(this, arguments);
49+
let includes = [...this.include(this.request)];
4150

4251
if (Array.isArray(hash)) {
4352
for (let resource of hash) {
44-
this._adjust(resource);
53+
this._adjust(resource, includes);
4554
}
4655
} else {
47-
this._adjust(hash);
56+
this._adjust(hash, includes);
4857
}
4958

5059
return [hash, addToIncludes];
5160
},
5261

53-
_adjust(hash) {
62+
_adjust(hash, includes) {
5463
let versions = this.schema.versions.where({ crateId: hash.id });
5564
assert(`crate \`${hash.name}\` has no associated versions`, versions.length !== 0);
5665

@@ -63,25 +72,32 @@ export default BaseSerializer.extend({
6372
versionNums[0];
6473
hash.yanked = versionsByNum[hash.default_version]?.yanked ?? false;
6574

66-
versions = versions.filter(it => !it.yanked);
67-
versionNums = versionNums.filter(it => !versionsByNum[it].yanked);
68-
hash.max_version = versionNums[0] ?? '0.0.0';
69-
hash.max_stable_version = versionNums.find(it => !prerelease(it, { loose: true })) ?? null;
75+
if (includes.includes('versions')) {
76+
versions = versions.filter(it => !it.yanked);
77+
versionNums = versionNums.filter(it => !versionsByNum[it].yanked);
78+
hash.max_version = versionNums[0] ?? '0.0.0';
79+
hash.max_stable_version = versionNums.find(it => !prerelease(it, { loose: true })) ?? null;
7080

71-
let newestVersions = versions.models.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at));
72-
hash.newest_version = newestVersions[0]?.num ?? '0.0.0';
81+
let newestVersions = versions.models.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at));
82+
hash.newest_version = newestVersions[0]?.num ?? '0.0.0';
83+
84+
hash.versions = hash.version_ids;
85+
} else {
86+
hash.max_version = '0.0.0';
87+
hash.newest_version = '0.0.0';
88+
hash.max_stable_version = null;
89+
hash.versions = null;
90+
}
91+
delete hash.version_ids;
7392

7493
hash.id = hash.name;
7594

76-
hash.categories = hash.category_ids;
95+
hash.categories = includes.includes('categories') ? hash.category_ids : null;
7796
delete hash.category_ids;
7897

79-
hash.keywords = hash.keyword_ids;
98+
hash.keywords = includes.includes('keywords') ? hash.keyword_ids : null;
8099
delete hash.keyword_ids;
81100

82-
hash.versions = hash.version_ids;
83-
delete hash.version_ids;
84-
85101
delete hash.team_owner_ids;
86102
delete hash.user_owner_ids;
87103
},

tests/mirage/crates/get-by-id-test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,34 @@ module('Mirage | GET /api/v1/crates/:id', function (hooks) {
193193
},
194194
]);
195195
});
196+
197+
test('without versions included', async function (assert) {
198+
this.server.create('category', { category: 'no-std' });
199+
this.server.create('category', { category: 'cli' });
200+
this.server.create('keyword', { keyword: 'no-std' });
201+
this.server.create('keyword', { keyword: 'cli' });
202+
let crate = this.server.create('crate', { name: 'rand', categoryIds: ['no-std'], keywordIds: ['no-std'] });
203+
this.server.create('version', { crate, num: '1.0.0' });
204+
this.server.create('version', { crate, num: '1.1.0' });
205+
this.server.create('version', { crate, num: '1.2.0' });
206+
207+
let req = await fetch('/api/v1/crates/rand');
208+
let expected = await req.json();
209+
210+
let response = await fetch('/api/v1/crates/rand?include=keywords,categories');
211+
assert.strictEqual(response.status, 200);
212+
213+
let responsePayload = await response.json();
214+
assert.deepEqual(responsePayload, {
215+
...expected,
216+
crate: {
217+
...expected.crate,
218+
max_version: '0.0.0',
219+
newest_version: '0.0.0',
220+
max_stable_version: null,
221+
versions: null,
222+
},
223+
versions: null,
224+
});
225+
});
196226
});

0 commit comments

Comments
 (0)