Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase tchack use fetch #5900

Merged
merged 4 commits into from
Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 3 additions & 32 deletions addon/adapters/json-api.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
/* global heimdall */
/**
@module ember-data
*/
import { dasherize } from '@ember/string';
import RESTAdapter from './rest';
import { instrument } from 'ember-data/-debug';
import { pluralize } from 'ember-inflector';

/**
Expand Down Expand Up @@ -155,36 +153,9 @@ const JSONAPIAdapter = RESTAdapter.extend({
@return {Object}
*/
ajaxOptions(url, type, options) {
let hash = this._super(...arguments);

if (hash.contentType) {
hash.contentType = 'application/vnd.api+json';
}

instrument(function() {
hash.converters = {
'text json': function(payload) {
let token = heimdall.start('json.parse');
let json;
try {
json = JSON.parse(payload);
} catch (e) {
json = payload;
}
heimdall.stop(token);
return json;
},
};
});

let beforeSend = hash.beforeSend;
hash.beforeSend = function(xhr) {
xhr.setRequestHeader('Accept', 'application/vnd.api+json');
if (beforeSend) {
beforeSend(xhr);
}
};

options.contentType = 'application/vnd.api+json';
let hash = this._super(url, type, options);
hash.headers['Accept'] = 'application/vnd.api+json';
return hash;
},

Expand Down
184 changes: 148 additions & 36 deletions addon/adapters/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
@module ember-data
*/

import $ from 'jquery';
import Ember from 'ember';
import fetch, { Response } from 'fetch';
import serializeQueryParams from 'ember-fetch/utils/serialize-query-params';
import determineBodyPromise from 'ember-fetch/utils/determine-body-promise';

import { Promise as EmberPromise } from 'rsvp';
import RSVP, { Promise as EmberPromise } from 'rsvp';
import { get, computed } from '@ember/object';
import { getOwner } from '@ember/application';
import { run } from '@ember/runloop';
import Adapter from '../adapter';
import { assign } from '@ember/polyfills';
import {
parseResponseHeaders,
BuildURLMixin,
Expand All @@ -24,7 +28,6 @@ import {
TimeoutError,
AbortError,
} from '../-private';
import { instrument } from 'ember-data/-debug';
import { warn } from '@ember/debug';
import { DEBUG } from '@glimmer/env';

Expand Down Expand Up @@ -298,6 +301,11 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, {
return getOwner(this).lookup('service:fastboot');
}),

useFetch: computed(function() {
let ENV = getOwner(this).resolveRegistration('config:environment');
return (ENV && ENV._JQUERY_INTEGRATION) === false || Ember.$ === undefined;
}),

/**
By default, the RESTAdapter will send the query params sorted alphabetically to the
server.
Expand Down Expand Up @@ -982,12 +990,35 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, {
};
let hash = adapter.ajaxOptions(url, type, options);

if (get(this, 'useFetch')) {
return this._fetchRequest(hash)
.catch(() => {
heimdall.stop(token);
})
.then(response => {
heimdall.stop(token);

return RSVP.hash({
response,
payload: determineBodyPromise(response, requestData),
});
})
.then(({ response, payload }) => {
if (response.ok) {
return fetchSuccessHandler(adapter, payload, response, requestData);
} else {
throw fetchErrorHandler(adapter, payload, response, null, requestData);
}
});
}

return new Promise(function(resolve, reject) {
hash.success = function(payload, textStatus, jqXHR) {
heimdall.stop(token);
let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData);
run.join(null, resolve, response);
};

hash.error = function(jqXHR, textStatus, errorThrown) {
heimdall.stop(token);
let error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData);
Expand All @@ -1004,7 +1035,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, {
@param {Object} options jQuery ajax options to be used for the ajax request
*/
_ajaxRequest(options) {
$.ajax(options);
Ember.$.ajax(options);
},

/**
Expand All @@ -1022,8 +1053,22 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, {
}
},

_fetchRequest(options) {
fetch(options.url, options)
.then(response => {
if (response.ok) {
options.success(response);
} else {
options.error(response);
}
})
.catch(error => options.error(new Response(), error));
},

_ajax(options) {
if (get(this, 'fastboot.isFastBoot')) {
if (get(this, 'useFetch')) {
this._fetchRequest(options);
} else if (get(this, 'fastboot.isFastBoot')) {
this._najaxRequest(options);
} else {
this._ajaxRequest(options);
Expand All @@ -1038,43 +1083,37 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, {
@param {Object} options
@return {Object}
*/
ajaxOptions(url, type, options) {
let hash = options || {};
hash.type = type;
hash.dataType = 'json';
hash.context = this;

instrument(function() {
hash.converters = {
'text json': function(payload) {
let token = heimdall.start('json.parse');
let json;
try {
json = JSON.parse(payload);
} catch (e) {
json = payload;
}
heimdall.stop(token);
return json;
},
};
});

if (hash.data && type !== 'GET') {
hash.contentType = 'application/json; charset=utf-8';
hash.data = JSON.stringify(hash.data);
}
ajaxOptions(url, method, options) {
options = assign(
{
url,
method,
type: method,
},
options
);

let headers = get(this, 'headers');
if (headers !== undefined) {
hash.beforeSend = function(xhr) {
Object.keys(headers).forEach(key => xhr.setRequestHeader(key, headers[key]));
};
options.headers = assign({}, options.headers, headers);
} else if (!options.headers) {
options.headers = {};
}

hash.url = this._ajaxURL(url);
if (options.data && options.type !== 'GET') {
let contentType = options.contentType || 'application/json; charset=utf-8';
options.headers['content-type'] = contentType;
}

return hash;
if (get(this, 'useFetch')) {
options = fetchOptions(options, this);
} else {
options = ajaxOptions(options, this);
}

options.url = this._ajaxURL(options.url);

return options;
},

_ajaxURL(url) {
Expand Down Expand Up @@ -1262,6 +1301,17 @@ function endsWith(string, suffix) {
}
}

function fetchSuccessHandler(adapter, payload, response, requestData) {
let responseData = fetchResponseData(response);
return ajaxSuccess(adapter, payload, requestData, responseData);
}

function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) {
let responseData = fetchResponseData(response);
responseData.errorThrown = errorThrown;
return ajaxError(adapter, payload, requestData, responseData);
}

function ajaxSuccessHandler(adapter, payload, jqXHR, requestData) {
let responseData = ajaxResponseData(jqXHR);
return ajaxSuccess(adapter, payload, requestData, responseData);
Expand All @@ -1274,6 +1324,14 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) {
return ajaxError(adapter, payload, requestData, responseData);
}

function fetchResponseData(response) {
return {
status: response.status,
textStatus: response.textStatus,
headers: headersToObject(response.headers),
};
}

function ajaxResponseData(jqXHR) {
return {
status: jqXHR.status,
Expand All @@ -1282,4 +1340,58 @@ function ajaxResponseData(jqXHR) {
};
}

function headersToObject(headers) {
let headersObject = {};

if (headers) {
headers.forEach((value, key) => (headersObject[key] = value));
}

return headersObject;
}

/**
* Helper function that translates the options passed to `jQuery.ajax` into a format that `fetch` expects.
* @param {Object} _options
* @param {DS.Adapter} adapter
* @returns {Object}
*/
export function fetchOptions(options, adapter) {
options.credentials = 'same-origin';

if (options.data) {
// GET and HEAD requests can't have a `body`
if (options.method === 'GET' || options.method === 'HEAD') {
// If no options are passed, Ember Data sets `data` to an empty object, which we test for.
if (Object.keys(options.data).length) {
// Test if there are already query params in the url (mimics jQuey.ajax).
const queryParamDelimiter = options.url.indexOf('?') > -1 ? '&' : '?';
options.url += `${queryParamDelimiter}${serializeQueryParams(options.data)}`;
}
} else {
// NOTE: a request's body cannot be an object, so we stringify it if it is.
// JSON.stringify removes keys with values of `undefined` (mimics jQuery.ajax).
options.body = JSON.stringify(options.data);
}
}

return options;
}

function ajaxOptions(options, adapter) {
options.dataType = 'json';
options.context = adapter;

if (options.data && options.type !== 'GET') {
options.data = JSON.stringify(options.data);
options.contentType = 'application/json; charset=utf-8';
}

options.beforeSend = function(xhr) {
Object.keys(options.headers).forEach(key => xhr.setRequestHeader(key, options.headers[key]));
};

return options;
}

export default RESTAdapter;
24 changes: 24 additions & 0 deletions config/ember-try.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ module.exports = function() {
bower: {},
npm: {},
},
{
name: 'ember-lts-2.18',
env: {
EMBER_OPTIONAL_FEATURES: JSON.stringify({ 'jquery-integration': true }),
},
npm: {
devDependencies: {
'@ember/jquery': '^0.5.1',
'ember-source': '~2.18.0',
},
},
},
{
name: 'ember-lts-2.18',
npm: {
Expand All @@ -24,6 +36,18 @@ module.exports = function() {
},
},
},
{
name: 'ember-lts-3.4',
env: {
EMBER_OPTIONAL_FEATURES: JSON.stringify({ 'jquery-integration': true }),
},
npm: {
devDependencies: {
'@ember/jquery': '^0.5.1',
'ember-source': '~3.4.0',
},
},
},
{
name: 'ember-lts-3.4',
npm: {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"ember-cli-test-info": "^1.0.0",
"ember-cli-typescript": "^2.0.0-beta.2",
"ember-cli-version-checker": "^3.1.2",
"ember-fetch": "^6.2.2",
"ember-inflector": "^3.0.0",
"git-repo-info": "^2.0.0",
"heimdalljs": "^0.3.0",
Expand Down Expand Up @@ -104,7 +105,7 @@
"ember-load-initializers": "^2.0.0",
"ember-maybe-import-regenerator": "^0.1.6",
"ember-qunit": "^4.4.1",
"ember-qunit-assert-helpers": "^0.2.1",
"ember-qunit-assert-helpers": "^0.2.2",
"ember-resolver": "^5.0.1",
"ember-source": "~3.8.0",
"ember-source-channel-url": "^1.1.0",
Expand Down
Loading