Skip to content

Commit

Permalink
Merge pull request #6 from yapplabs/improvement/url-generation
Browse files Browse the repository at this point in the history
appendToQueryParam
  • Loading branch information
lukemelia committed Aug 3, 2020
2 parents f5b5a1e + 36b9244 commit 041a866
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 14 deletions.
40 changes: 26 additions & 14 deletions addon/adapters/ember-data-utils-json-api.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import DS from 'ember-data';
import { camelize } from '@ember/string';
import { isEmpty } from '@ember/utils';
import { appendToQueryParam } from 'ember-data-utils/utils/url';
import { getOwner } from '@ember/application';

/**
Class to set as your ApplicationAdapter. Extend it for each model
you want to configure explicit filter and include params.
Class to set as your ApplicationAdapter. Extend it for each model
you want to configure explicit filter and include params.
```js
// app/adapters/application.js
import { EmberDataUtilsJSONAPIAdapter } from 'ember-data-utils';
Expand All @@ -26,20 +28,20 @@ import { isEmpty } from '@ember/utils';
*/
export default DS.JSONAPIAdapter.extend({
/**
List of query param keys that your resource supports filtering on.
Extend your base class for specific models to declare.
List of query param keys that your resource supports filtering on.
Extend your base class for specific models to declare.
@field {Array} supportedFilters
*/
supportedFilters: [], // eslint-disable-line ember/avoid-leaking-state-in-ember-objects

/**
Array of includes to always include when querying a particular model.
Extend your base class for specific models to declare.
Extend your base class for specific models to declare.
@field {Array} include
*/
include: [], // eslint-disable-line ember/avoid-leaking-state-in-ember-objects

/**
* @public
* @method query
Expand All @@ -60,9 +62,9 @@ export default DS.JSONAPIAdapter.extend({
* queryRecord and findRecord use buildQuery to add includes to
* api calls. This override adds an adapters configured set of
* default includes
*
*
* @method buildQuery
* @param {object} snapshot
* @param {object} snapshot
* @return {object} Mutated query object
*/
buildQuery(snapshot) {
Expand All @@ -77,20 +79,30 @@ export default DS.JSONAPIAdapter.extend({
let combinedUniqueIncludes = [...new Set(existingIncludes.concat(include))];

query.include = combinedUniqueIncludes.join(',');

return query;
},

findHasMany(store, snapshot, url, relationship) {
let adapter = this._adapterForRelationship(relationship.type);
let updatedUrl = appendToQueryParam(url, 'include', adapter.include)
return this._super(store, snapshot, updatedUrl, relationship);
},

_adapterForRelationship(type) {
return getOwner(this).lookup(`adapter:${type}`);
},

/**
* Mutate the `jsonApiQueryParams` object with pagination related keys from `rawQueryParams` object
*
*
* Pagination related keys are `limit`, `since`, and `until`
*
*
* @private
* @method _applyPagination
* @param {Object} jsonApiQueryParams Object of JSONAPI formated query params
* @param {Object} rawQueryParams Original, unformated Object of query params
* @return {Object} Mutated jsonApiQueryParams object with pagination params applied
* @return {Object} Mutated jsonApiQueryParams object with pagination params applied
*/
_applyPagination(jsonApiQueryParams, rawQueryParams) {
['limit', 'since', 'until'].forEach(key => {
Expand Down
25 changes: 25 additions & 0 deletions addon/utils/url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { isArray } from '@ember/array';
import { isEmpty } from '@ember/utils';

/**
* @function appendToQueryParam
* @export named
* @param {string} url
*/
export function appendToQueryParam(urlString, param, newValue) {
let url = new URL(urlString);
if (isEmpty(newValue)) {
return url.href;
}

let existingParamValue = url.searchParams.get(param);
let existingValues = existingParamValue ? existingParamValue.split(',') : [];
newValue = isArray(newValue) ? newValue : newValue.split(',');
// Merge the two arrays, filtering out empty values
existingValues = existingValues.concat(newValue).filter(Boolean);
// Remove duplicate content
existingValues = [...new Set(existingValues)]
url.searchParams.set(param, existingValues.join(','));

return url.href;
}
98 changes: 98 additions & 0 deletions tests/unit/utils/url-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { module, test } from 'qunit';
import { appendToQueryParam } from 'ember-data-utils/utils/url';

module('Unit | Utility | url', function() {

test('appendToQueryParam()', function(assert) {
assert.equal(
appendToQueryParam(
'https://www.test.com',
'include',
'profile'
),
'https://www.test.com/?include=profile',
'it adds a new query param'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=person',
'include',
'profile'
),
'https://www.test.com/?include=person%2Cprofile',
'it adds to an existing param'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?query=person',
'include',
'profile'
),
'https://www.test.com/?query=person&include=profile',
'it adds a new query param while leaving existing params alone'
);
assert.equal(
appendToQueryParam(
'https://www.test.com',
'include',
['profile', 'pizza']
),
'https://www.test.com/?include=profile%2Cpizza',
'new params can be an array'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
['profile', 'pizza']
),
'https://www.test.com/?include=party%2Cprofile%2Cpizza',
'array params are concatted with existing param values'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
'profile,pizza'
),
'https://www.test.com/?include=party%2Cprofile%2Cpizza',
'params that are strings are added'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
null
),
'https://www.test.com/?include=party',
'null params are ignored'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
[]
),
'https://www.test.com/?include=party',
'empty arrays are ignored'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
['party']
),
'https://www.test.com/?include=party',
'param values are not duplicated'
);
assert.equal(
appendToQueryParam(
'https://www.test.com?include=party',
'include',
'party,pizza'
),
'https://www.test.com/?include=party%2Cpizza',
'param values are not duplicated even if a string'
);
});
});

0 comments on commit 041a866

Please sign in to comment.