Skip to content

Commit

Permalink
mirage: Respect include query params in GET /api/v1/crates/:id (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
eth3lbert authored Dec 30, 2024
1 parent 68064d3 commit 899eeb1
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 19 deletions.
13 changes: 8 additions & 5 deletions mirage/route-handlers/crates.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,15 @@ export function register(server) {
let { name } = request.params;
let crate = schema.crates.findBy({ name });
if (!crate) return notFound();

let serialized = this.serialize(crate);
return {
...this.serialize(crate),
...this.serialize(crate.categories),
...this.serialize(crate.keywords),
...this.serialize(crate.versions.sort((a, b) => Number(b.id) - Number(a.id))),
categories: null,
keywords: null,
versions: null,
...serialized,
...(serialized.crate.categories && this.serialize(crate.categories)),
...(serialized.crate.keywords && this.serialize(crate.keywords)),
...(serialized.crate.versions && this.serialize(crate.versions.sort((a, b) => Number(b.id) - Number(a.id)))),
};
});

Expand Down
44 changes: 30 additions & 14 deletions mirage/serializers/crate.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ import semverSort from 'semver/functions/rsort';
import { compareIsoDates } from '../route-handlers/-utils';
import BaseSerializer from './application';

const VALID_INCLUDE_MODEL = new Set(['versions', 'keywords', 'categories' /*, 'badges', 'downloads' */]);

export default BaseSerializer.extend({
include(request) {
let include = request.queryParams.include;
return include == null || include === 'full'
? VALID_INCLUDE_MODEL.values()
: include.split(',').filter(it => VALID_INCLUDE_MODEL.has(it));
},
attrs: [
'badges',
'categories',
Expand Down Expand Up @@ -38,19 +46,20 @@ export default BaseSerializer.extend({

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

if (Array.isArray(hash)) {
for (let resource of hash) {
this._adjust(resource);
this._adjust(resource, includes);
}
} else {
this._adjust(hash);
this._adjust(hash, includes);
}

return [hash, addToIncludes];
},

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

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

versions = versions.filter(it => !it.yanked);
versionNums = versionNums.filter(it => !versionsByNum[it].yanked);
hash.max_version = versionNums[0] ?? '0.0.0';
hash.max_stable_version = versionNums.find(it => !prerelease(it, { loose: true })) ?? null;
if (includes.includes('versions')) {
versions = versions.filter(it => !it.yanked);
versionNums = versionNums.filter(it => !versionsByNum[it].yanked);
hash.max_version = versionNums[0] ?? '0.0.0';
hash.max_stable_version = versionNums.find(it => !prerelease(it, { loose: true })) ?? null;

let newestVersions = versions.models.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at));
hash.newest_version = newestVersions[0]?.num ?? '0.0.0';
let newestVersions = versions.models.sort((a, b) => compareIsoDates(b.updated_at, a.updated_at));
hash.newest_version = newestVersions[0]?.num ?? '0.0.0';

hash.versions = hash.version_ids;
} else {
hash.max_version = '0.0.0';
hash.newest_version = '0.0.0';
hash.max_stable_version = null;
hash.versions = null;
}
delete hash.version_ids;

hash.id = hash.name;

hash.categories = hash.category_ids;
hash.categories = includes.includes('categories') ? hash.category_ids : null;
delete hash.category_ids;

hash.keywords = hash.keyword_ids;
hash.keywords = includes.includes('keywords') ? hash.keyword_ids : null;
delete hash.keyword_ids;

hash.versions = hash.version_ids;
delete hash.version_ids;

delete hash.team_owner_ids;
delete hash.user_owner_ids;
},
Expand Down
30 changes: 30 additions & 0 deletions tests/mirage/crates/get-by-id-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,34 @@ module('Mirage | GET /api/v1/crates/:id', function (hooks) {
},
]);
});

test('without versions included', async function (assert) {
this.server.create('category', { category: 'no-std' });
this.server.create('category', { category: 'cli' });
this.server.create('keyword', { keyword: 'no-std' });
this.server.create('keyword', { keyword: 'cli' });
let crate = this.server.create('crate', { name: 'rand', categoryIds: ['no-std'], keywordIds: ['no-std'] });
this.server.create('version', { crate, num: '1.0.0' });
this.server.create('version', { crate, num: '1.1.0' });
this.server.create('version', { crate, num: '1.2.0' });

let req = await fetch('/api/v1/crates/rand');
let expected = await req.json();

let response = await fetch('/api/v1/crates/rand?include=keywords,categories');
assert.strictEqual(response.status, 200);

let responsePayload = await response.json();
assert.deepEqual(responsePayload, {
...expected,
crate: {
...expected.crate,
max_version: '0.0.0',
newest_version: '0.0.0',
max_stable_version: null,
versions: null,
},
versions: null,
});
});
});

0 comments on commit 899eeb1

Please sign in to comment.