From 02ef2d716ce93dab43cdb93df1c6d9efbb351707 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 23 Oct 2020 12:08:28 -0700 Subject: [PATCH 01/56] [Chore]: ts adapters --- packages/adapter/addon/{index.js => index.ts} | 14 +- .../addon/{json-api.js => json-api.ts} | 10 +- packages/adapter/addon/{rest.js => rest.ts} | 124 ++++++++++-------- 3 files changed, 85 insertions(+), 63 deletions(-) rename packages/adapter/addon/{index.js => index.ts} (97%) rename packages/adapter/addon/{json-api.js => json-api.ts} (92%) rename packages/adapter/addon/{rest.js => rest.ts} (90%) diff --git a/packages/adapter/addon/index.js b/packages/adapter/addon/index.ts similarity index 97% rename from packages/adapter/addon/index.js rename to packages/adapter/addon/index.ts index 8ac492e4779..7576e38592a 100644 --- a/packages/adapter/addon/index.js +++ b/packages/adapter/addon/index.ts @@ -1,5 +1,9 @@ import EmberObject from '@ember/object'; +type Store = import('@ember-data/store/-private/system/core-store').default; +type Snapshot = import('ember-data/-private').Snapshot; +type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; + /** An adapter is an object that receives requests from a store and translates them into the appropriate action to take against your @@ -475,7 +479,7 @@ export default class Adapter extends EmberObject { @return {Array} an array of arrays of records, each of which is to be loaded separately by `findMany`. */ - groupRecordsForFindMany(store, snapshots) { + groupRecordsForFindMany(store: Store, snapshots: Snapshot[]) { return [snapshots]; } @@ -525,7 +529,7 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Boolean} */ - shouldReloadRecord(store, snapshot) { + shouldReloadRecord(store: Store, snapshot: Snapshot) { return false; } @@ -580,7 +584,7 @@ export default class Adapter extends EmberObject { @param {SnapshotRecordArray} snapshotRecordArray @return {Boolean} */ - shouldReloadAll(store, snapshotRecordArray) { + shouldReloadAll(store: Store, snapshotRecordArray) { return !snapshotRecordArray.length; } @@ -616,7 +620,7 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Boolean} */ - shouldBackgroundReloadRecord(store, snapshot) { + shouldBackgroundReloadRecord(store: Store, Snapshot) { return true; } @@ -652,7 +656,7 @@ export default class Adapter extends EmberObject { @param {SnapshotRecordArray} snapshotRecordArray @return {Boolean} */ - shouldBackgroundReloadAll(store, snapshotRecordArray) { + shouldBackgroundReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray) { return true; } } diff --git a/packages/adapter/addon/json-api.js b/packages/adapter/addon/json-api.ts similarity index 92% rename from packages/adapter/addon/json-api.js rename to packages/adapter/addon/json-api.ts index 425884831ad..645a512d348 100644 --- a/packages/adapter/addon/json-api.js +++ b/packages/adapter/addon/json-api.ts @@ -8,6 +8,10 @@ import { pluralize } from 'ember-inflector'; import { serializeIntoHash } from './-private'; import RESTAdapter from './rest'; +type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; +type Store = import('@ember-data/store/-private/system/core-store').default; +type Snapshot = import('@ember-data/store/-private/system/snapshot').default; + /** The `JSONAPIAdapter` is the default adapter used by Ember Data. It is responsible for transforming the store's requests into HTTP @@ -156,7 +160,7 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url, type, options = {}) { + ajaxOptions(url: string, type: string, options = {}) { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; @@ -221,7 +225,7 @@ class JSONAPIAdapter extends RESTAdapter { */ coalesceFindRequests = false; - findMany(store, type, ids, snapshots) { + findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } }); } @@ -231,7 +235,7 @@ class JSONAPIAdapter extends RESTAdapter { return pluralize(dasherized); } - updateRecord(store, type, snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { const data = serializeIntoHash(store, type, snapshot); let url = this.buildURL(type.modelName, snapshot.id, snapshot, 'updateRecord'); diff --git a/packages/adapter/addon/rest.js b/packages/adapter/addon/rest.ts similarity index 90% rename from packages/adapter/addon/rest.js rename to packages/adapter/addon/rest.ts index 7f5b7a6018f..2a98c0f0f6b 100644 --- a/packages/adapter/addon/rest.js +++ b/packages/adapter/addon/rest.ts @@ -1,4 +1,4 @@ -/* globals najax jQuery */ +/* globals jQuery */ /** @module @ember-data/adapter @@ -33,6 +33,14 @@ import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, s const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; +declare var najax: Function; +type IAdapter = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; +type Payload = Record | string | undefined; +type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; +type Store = import('@ember-data/store/-private/system/core-store').default; +type Snapshot = import('@ember-data/store/-private/system/snapshot').default; +type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; + /** The REST adapter allows your store to communicate with an HTTP server by transmitting JSON via XHR. Most Ember.js apps that consume a JSON API @@ -293,7 +301,7 @@ const hasJQuery = typeof jQuery !== 'undefined'; @extends Adapter @uses BuildURLMixin */ -class RESTAdapter extends Adapter.extend(BuildURLMixin) { +class RESTAdapter extends Adapter.extend(BuildURLMixin) implements IAdapter { defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; @@ -309,7 +317,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } set fastboot(value) { - return (this._fastboot = value); + this._fastboot = value; } /** @@ -501,7 +509,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - findRecord(store, type, id, snapshot) { + findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { let url = this.buildURL(type.modelName, id, snapshot, 'findRecord'); let query = this.buildQuery(snapshot); @@ -522,9 +530,9 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ - findAll(store, type, sinceToken, snapshotRecordArray) { - let query = this.buildQuery(snapshotRecordArray); - let url = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); + findAll(store: Store, type: ShimModelClass, sinceToken, snapshotRecordArray: SnapshotRecordArray) { + let query: Record = this.buildQuery(snapshotRecordArray); + let url: string = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); if (sinceToken) { query.since = sinceToken; @@ -550,7 +558,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - query(store, type, query) { + query(store: Store, type: ShimModelClass, query) { let url = this.buildURL(type.modelName, null, null, 'query', query); if (this.sortQueryParams) { @@ -578,7 +586,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - queryRecord(store, type, query) { + queryRecord(store: Store, type: ShimModelClass, query) { let url = this.buildURL(type.modelName, null, null, 'queryRecord', query); if (this.sortQueryParams) { @@ -621,7 +629,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Array} snapshots @return {Promise} promise */ - findMany(store, type, ids, snapshots) { + findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { ids: ids } }); } @@ -662,7 +670,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findHasMany(store, snapshot, url, relationship) { + findHasMany(store: Store, snapshot: Snapshot, url: string, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -707,7 +715,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findBelongsTo(store, snapshot, url, relationship) { + findBelongsTo(store: Store, snapshot: Snapshot, url: string, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -731,7 +739,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - createRecord(store, type, snapshot) { + createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); const data = serializeIntoHash(store, type, snapshot); @@ -755,7 +763,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - updateRecord(store, type, snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { const data = serializeIntoHash(store, type, snapshot, {}); let id = snapshot.id; @@ -775,26 +783,26 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - deleteRecord(store, type, snapshot) { + deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { let id = snapshot.id; return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), 'DELETE'); } - _stripIDFromURL(store, snapshot) { - let url = this.buildURL(snapshot.modelName, snapshot.id, snapshot); + _stripIDFromURL(store: Store, snapshot: Snapshot) { + let url: string = this.buildURL(snapshot.modelName, snapshot.id, snapshot); - let expandedURL = url.split('/'); + let expandedURL: string[] = url.split('/'); // Case when the url is of the format ...something/:id // We are decodeURIComponent-ing the lastSegment because if it represents // the id, it has been encodeURIComponent-ified within `buildURL`. If we // don't do this, then records with id having special characters are not // coalesced correctly (see GH #4190 for the reported bug) - let lastSegment = expandedURL[expandedURL.length - 1]; + let lastSegment: string = expandedURL[expandedURL.length - 1]; let id = snapshot.id; if (decodeURIComponent(lastSegment) === id) { expandedURL[expandedURL.length - 1] = ''; - } else if (endsWith(lastSegment, '?id=' + id)) { + } else if (id && endsWith(lastSegment, '?id=' + id)) { //Case when the url is of the format ...something?id=:id expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1); } @@ -827,13 +835,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @return {Array} an array of arrays of records, each of which is to be loaded separately by `findMany`. */ - groupRecordsForFindMany(store, snapshots) { + groupRecordsForFindMany(store: Store, snapshots: Snapshot[]): Snapshot[][] { let groups = new Map(); let adapter = this; let maxURLLength = this.maxURLLength; snapshots.forEach(snapshot => { - let baseUrl = adapter._stripIDFromURL(store, snapshot); + let baseUrl: string = adapter._stripIDFromURL(store, snapshot); if (!groups.has(baseUrl)) { groups.set(baseUrl, []); } @@ -843,11 +851,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { function splitGroupToFitInUrl(group, maxURLLength, paramNameLength) { let idsSize = 0; - let baseUrl = adapter._stripIDFromURL(store, group[0]); - let splitGroups = [[]]; + let baseUrl: string = adapter._stripIDFromURL(store, group[0]); + let splitGroups: Snapshot[][] = [[]]; group.forEach(snapshot => { - let additionalLength = encodeURIComponent(snapshot.id).length + paramNameLength; + let additionalLength: number = encodeURIComponent(snapshot.id).length + paramNameLength; if (baseUrl.length + idsSize + additionalLength >= maxURLLength) { idsSize = 0; splitGroups.push([]); @@ -862,7 +870,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return splitGroups; } - let groupsArray = []; + let groupsArray: Snapshot[][] = []; groups.forEach((group, key) => { let paramNameLength = '&ids%5B%5D='.length; let splitGroups = splitGroupToFitInUrl(group, maxURLLength, paramNameLength); @@ -902,11 +910,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData - the original request information @return {Object | AdapterError} response */ - handleResponse(status, headers, payload, requestData) { + handleResponse(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings) { if (this.isSuccess(status, headers, payload)) { return payload; - } else if (this.isInvalid(status, headers, payload)) { - return new InvalidError(payload.errors); + } else if (payload && this.isInvalid(status, headers, payload)) { + return new InvalidError((payload as Record).errors); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -941,7 +949,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isSuccess(status, headers, payload) { + isSuccess(status: number, headers, payload): boolean { return (status >= 200 && status < 300) || status === 304; } @@ -956,7 +964,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isInvalid(status, headers, payload) { + isInvalid(status: number, headers, payload): boolean { return status === 422; } @@ -984,10 +992,10 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url, type, options) { + ajax(url: string, type: string, options = {}) { let adapter = this; - let requestData = { + let requestData: Record = { url: url, method: type, }; @@ -1029,7 +1037,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options) { + _ajaxRequest(options): void { jQuery.ajax(options); } @@ -1045,7 +1053,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options) { + _ajax(options): void { if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && get(this, 'fastboot.isFastBoot')) { @@ -1063,7 +1071,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url, method, options) { + ajaxOptions(url: string, method: string, options) { options = assign( { url, @@ -1103,7 +1111,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return options; } - _ajaxURL(url) { + _ajaxURL(url: string): string | void { if (get(this, 'fastboot.isFastBoot')) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; @@ -1133,7 +1141,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {String} responseText @return {Object} */ - parseErrorResponse(responseText) { + parseErrorResponse(responseText: string) { let json = responseText; try { @@ -1153,7 +1161,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Array} errors payload */ - normalizeErrorResponse(status, headers, payload) { + normalizeErrorResponse(status: number, headers, payload) { if (payload && typeof payload === 'object' && payload.errors) { return payload.errors; } else { @@ -1179,11 +1187,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData @return {String} detailed error message */ - generatedDetailedMessage(status, headers, payload, requestData) { + generatedDetailedMessage(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings): string { let shortenedPayload; let payloadContentType = headers['content-type'] || 'Empty Content-Type'; - if (payloadContentType === 'text/html' && payload.length > 250) { + if (payloadContentType === 'text/html' && (payload as string).length > 250) { shortenedPayload = '[Omitted Lengthy HTML]'; } else { shortenedPayload = payload; @@ -1203,11 +1211,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @method buildQuery @since 2.5.0 @public - @param {Snapshot} snapshot + @param {Snapshot | SnapshotRecordArray} snapshot @return {Object} */ - buildQuery(snapshot) { - let query = {}; + buildQuery(snapshot: Snapshot | SnapshotRecordArray): object { + let query: Record = {}; if (snapshot) { let { include } = snapshot; @@ -1221,7 +1229,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } -function ajaxSuccess(adapter, payload, requestData, responseData) { +function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { let response; try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); @@ -1236,7 +1244,7 @@ function ajaxSuccess(adapter, payload, requestData, responseData) { } } -function ajaxError(adapter, payload, requestData, responseData) { +function ajaxError(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1262,7 +1270,7 @@ function ajaxError(adapter, payload, requestData, responseData) { } // Adapter abort error to include any relevent info, e.g. request/response: -function handleAbort(requestData, responseData) { +function handleAbort(requestData, responseData): AbortError { let { method, url, errorThrown } = requestData; let { status } = responseData; let msg = `Request failed: ${method} ${url} ${errorThrown || ''}`; @@ -1271,7 +1279,7 @@ function handleAbort(requestData, responseData) { } //From http://stackoverflow.com/questions/280634/endswith-in-javascript -function endsWith(string, suffix) { +function endsWith(string, suffix): boolean { if (typeof String.prototype.endsWith !== 'function') { return string.indexOf(suffix, string.length - suffix.length) !== -1; } else { @@ -1279,12 +1287,18 @@ function endsWith(string, suffix) { } } -function fetchSuccessHandler(adapter, payload, response, requestData) { +function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: Record) { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); } -function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) { +function fetchErrorHandler( + adapter, + payload: Payload, + response: Response, + errorThrown, + requestData: Record +) { let responseData = fetchResponseData(response); if (responseData.status === 200 && payload instanceof Error) { @@ -1297,7 +1311,7 @@ function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) return ajaxError(adapter, payload, requestData, responseData); } -function ajaxSuccessHandler(adapter, payload, jqXHR, requestData) { +function ajaxSuccessHandler(adapter, payload: Payload, jqXHR, requestData: Record) { let responseData = ajaxResponseData(jqXHR); return ajaxSuccess(adapter, payload, requestData, responseData); } @@ -1318,15 +1332,15 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { return ajaxError(adapter, payload, requestData, responseData); } -function fetchResponseData(response) { +function fetchResponseData(response: Response): Record { return { status: response.status, - textStatus: response.textStatus, + textStatus: (response).textStatus, headers: headersToObject(response.headers), }; } -function ajaxResponseData(jqXHR) { +function ajaxResponseData(jqXHR): Record { return { status: jqXHR.status, textStatus: jqXHR.statusText, @@ -1334,7 +1348,7 @@ function ajaxResponseData(jqXHR) { }; } -function headersToObject(headers) { +function headersToObject(headers): Record { let headersObject = {}; if (headers) { From 99747b772220e8e61895c669a82df60c71188564 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 23 Oct 2020 14:22:22 -0700 Subject: [PATCH 02/56] interface should be on base class --- packages/adapter/addon/index.ts | 56 ++++++++++++++++++++++++++++++++- packages/adapter/addon/rest.ts | 3 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index 7576e38592a..a4861fe9c07 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -1,5 +1,10 @@ +import { warn } from '@ember/debug'; import EmberObject from '@ember/object'; +import { Promise } from 'rsvp'; + +type IAdapter = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; +type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('ember-data/-private').Snapshot; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; @@ -59,7 +64,7 @@ type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-re @class Adapter @extends EmberObject */ -export default class Adapter extends EmberObject { +export default class Adapter extends EmberObject implements IAdapter { /** If you would like your adapter to use a custom serializer you can set the `defaultSerializer` property to be the name of the custom @@ -117,6 +122,13 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Promise} promise */ + findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { + warn('You subclassed the Adapter class but missing a findRecord override', false, { + id: 'adapter.missing-find-record', + }); + + return Promise.resolve(); + } /** The `findAll()` method is used to retrieve all records for a given type. @@ -148,6 +160,13 @@ export default class Adapter extends EmberObject { @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ + findAll(store: Store, type: ShimModelClass, neverSet, snapshotRecordArray: SnapshotRecordArray) { + warn('You subclassed the Adapter class but missing a findAll override', false, { + id: 'adapter.missing-find-all', + }); + + return Promise.resolve(); + } /** This method is called when you call `query` on the store. @@ -180,6 +199,13 @@ export default class Adapter extends EmberObject { @param {Object} adapterOptions @return {Promise} promise */ + query(store: Store, type: ShimModelClass, query) { + warn('You subclassed the Adapter class but missing a query override', false, { + id: 'adapter.missing-query', + }); + + return Promise.resolve(); + } /** The `queryRecord()` method is invoked when the store is asked for a single @@ -218,6 +244,13 @@ export default class Adapter extends EmberObject { @param {Object} adapterOptions @return {Promise} promise */ + queryRecord(store: Store, type: ShimModelClass, query, adapterOptions) { + warn('You subclassed the Adapter class but missing a queryRecord override', false, { + id: 'adapter.missing-query-record', + }); + + return Promise.resolve(); + } /** If the globally unique IDs for your records should be generated on the client, @@ -320,6 +353,13 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Promise} promise */ + createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + warn('You subclassed the Adapter class but missing a createRecord override', false, { + id: 'adapter.missing-create-record', + }); + + return Promise.resolve(); + } /** Implement this method in a subclass to handle the updating of @@ -371,6 +411,13 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Promise} promise */ + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + warn('You subclassed the Adapter class but missing a updateRecord override', false, { + id: 'adapter.missing-update-record', + }); + + return Promise.resolve(); + } /** Implement this method in a subclass to handle the deletion of @@ -414,6 +461,13 @@ export default class Adapter extends EmberObject { @param {Snapshot} snapshot @return {Promise} promise */ + deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + warn('You subclassed the Adapter class but missing a deleteRecord override', false, { + id: 'adapter.missing-delete-record', + }); + + return Promise.resolve(); + } /** By default the store will try to coalesce all `fetchRecord` calls within the same runloop diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 2a98c0f0f6b..77728581e0d 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -34,7 +34,6 @@ const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; declare var najax: Function; -type IAdapter = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; type Payload = Record | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; @@ -301,7 +300,7 @@ type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-re @extends Adapter @uses BuildURLMixin */ -class RESTAdapter extends Adapter.extend(BuildURLMixin) implements IAdapter { +class RESTAdapter extends Adapter { defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; From 60496a28d41416413ff3941abca9e63ceecff5de Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 30 Oct 2020 13:04:16 -0700 Subject: [PATCH 03/56] add back extend --- packages/adapter/addon/index.ts | 4 ++-- packages/adapter/addon/rest.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index a4861fe9c07..0ae876b2fce 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -3,7 +3,7 @@ import EmberObject from '@ember/object'; import { Promise } from 'rsvp'; -type IAdapter = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; +type MinimumAdapterInterface = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('ember-data/-private').Snapshot; @@ -64,7 +64,7 @@ type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-re @class Adapter @extends EmberObject */ -export default class Adapter extends EmberObject implements IAdapter { +export default class Adapter extends EmberObject implements MinimumAdapterInterface { /** If you would like your adapter to use a custom serializer you can set the `defaultSerializer` property to be the name of the custom diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 77728581e0d..528c1c8a3a3 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -300,7 +300,7 @@ type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-re @extends Adapter @uses BuildURLMixin */ -class RESTAdapter extends Adapter { +class RESTAdapter extends Adapter.extend(BuildURLMixin) { defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; From 411510854212f6bfaf490d54ec42bcd650aca3c3 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 30 Oct 2020 13:06:06 -0700 Subject: [PATCH 04/56] mixin to ts --- .../addon/-private/{build-url-mixin.js => build-url-mixin.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/adapter/addon/-private/{build-url-mixin.js => build-url-mixin.ts} (100%) diff --git a/packages/adapter/addon/-private/build-url-mixin.js b/packages/adapter/addon/-private/build-url-mixin.ts similarity index 100% rename from packages/adapter/addon/-private/build-url-mixin.js rename to packages/adapter/addon/-private/build-url-mixin.ts From fe3e1e4461934c818ce2d5161430f5f7dbc1c0c4 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 30 Oct 2020 22:18:29 -0700 Subject: [PATCH 05/56] finish up ts conversion --- .../integration/identifiers/scenarios-test.ts | 14 ++++-- .../adapter/addon/-private/build-url-mixin.ts | 47 +++++++++++-------- .../addon/-private/fastboot-interface.ts | 24 ++++++++++ packages/adapter/addon/index.ts | 2 +- packages/adapter/addon/rest.ts | 30 +++++++----- 5 files changed, 81 insertions(+), 36 deletions(-) create mode 100644 packages/adapter/addon/-private/fastboot-interface.ts diff --git a/packages/-ember-data/tests/integration/identifiers/scenarios-test.ts b/packages/-ember-data/tests/integration/identifiers/scenarios-test.ts index bc67004462e..089495ebf82 100644 --- a/packages/-ember-data/tests/integration/identifiers/scenarios-test.ts +++ b/packages/-ember-data/tests/integration/identifiers/scenarios-test.ts @@ -31,6 +31,7 @@ module('Integration | Identifiers - scenarios', function(hooks) { module('Secondary Cache based on an attribute', function(hooks) { let store; let calls; + let isQuery = false; let secondaryCache: { id: ConfidentDict; username: ConfidentDict; @@ -44,10 +45,11 @@ module('Integration | Identifiers - scenarios', function(hooks) { shouldBackgroundReloadRecord() { return false; } - findRecord(isQuery = false) { + findRecord() { if (isQuery !== true) { calls.findRecord++; } + isQuery = false; return resolve({ data: { id: '1', @@ -62,7 +64,8 @@ module('Integration | Identifiers - scenarios', function(hooks) { } queryRecord() { calls.queryRecord++; - return this.findRecord(true); + isQuery = true; + return this.findRecord(); } } @@ -234,6 +237,7 @@ module('Integration | Identifiers - scenarios', function(hooks) { module('Secondary Cache using an attribute as an alternate id', function(hooks) { let store; let calls; + let isQuery = false; let secondaryCache: ConfidentDict; class TestSerializer extends Serializer { normalizeResponse(_, __, payload) { @@ -244,10 +248,11 @@ module('Integration | Identifiers - scenarios', function(hooks) { shouldBackgroundReloadRecord() { return false; } - findRecord(isQuery = false) { + findRecord() { if (isQuery !== true) { calls.findRecord++; } + isQuery = false; return resolve({ data: { id: '1', @@ -262,7 +267,8 @@ module('Integration | Identifiers - scenarios', function(hooks) { } queryRecord() { calls.queryRecord++; - return this.findRecord(true); + isQuery = true; + return this.findRecord(); } } diff --git a/packages/adapter/addon/-private/build-url-mixin.ts b/packages/adapter/addon/-private/build-url-mixin.ts index 2d7cb39d42a..56f6558d55a 100644 --- a/packages/adapter/addon/-private/build-url-mixin.ts +++ b/packages/adapter/addon/-private/build-url-mixin.ts @@ -4,6 +4,9 @@ import { camelize } from '@ember/string'; import { pluralize } from 'ember-inflector'; +type Snapshot = import('@ember-data/store/-private/system/snapshot').default; +type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; + /** @module @ember-data/adapter */ @@ -55,7 +58,13 @@ export default Mixin.create({ @param {Object} query object of query parameters to send for query requests. @return {String} url */ - buildURL(modelName, id, snapshot, requestType, query) { + buildURL( + modelName: string, + id: string | string[] | Record | null, + snapshot: Snapshot | Snapshot[] | SnapshotRecordArray | null, + requestType: string = '', + query = {} + ) { switch (requestType) { case 'findRecord': return this.urlForFindRecord(id, modelName, snapshot); @@ -89,9 +98,9 @@ export default Mixin.create({ @param {String} id @return {String} url */ - _buildURL(modelName, id) { + _buildURL(modelName: string, id: string): string { let path; - let url = []; + let url: string[] = []; let host = get(this, 'host'); let prefix = this.urlPrefix(); @@ -109,12 +118,12 @@ export default Mixin.create({ url.unshift(prefix); } - url = url.join('/'); - if (!host && url && url.charAt(0) !== '/') { - url = '/' + url; + let urlString = url.join('/'); + if (!host && urlString && urlString.charAt(0) !== '/') { + urlString = '/' + urlString; } - return url; + return urlString; }, /** @@ -140,7 +149,7 @@ export default Mixin.create({ @return {String} url */ - urlForFindRecord(id, modelName, snapshot) { + urlForFindRecord(id: string, modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName, id); }, @@ -165,7 +174,7 @@ export default Mixin.create({ @param {SnapshotRecordArray} snapshot @return {String} url */ - urlForFindAll(modelName, snapshot) { + urlForFindAll(modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName); }, @@ -195,7 +204,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQuery(query, modelName) { + urlForQuery(query: Record, modelName: string): string { return this._buildURL(modelName); }, @@ -220,7 +229,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQueryRecord(query, modelName) { + urlForQueryRecord(query: Record, modelName: string): string { return this._buildURL(modelName); }, @@ -248,7 +257,7 @@ export default Mixin.create({ @param {Array} snapshots @return {String} url */ - urlForFindMany(ids, modelName, snapshots) { + urlForFindMany(ids: string[], modelName: string, snapshots: Snapshot[]) { return this._buildURL(modelName); }, @@ -275,7 +284,7 @@ export default Mixin.create({ @param {Snapshot} snapshot @return {String} url */ - urlForFindHasMany(id, modelName, snapshot) { + urlForFindHasMany(id: string, modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName, id); }, @@ -302,7 +311,7 @@ export default Mixin.create({ @param {Snapshot} snapshot @return {String} url */ - urlForFindBelongsTo(id, modelName, snapshot) { + urlForFindBelongsTo(id: string, modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName, id); }, @@ -352,7 +361,7 @@ export default Mixin.create({ @param {Snapshot} snapshot @return {String} url */ - urlForUpdateRecord(id, modelName, snapshot) { + urlForUpdateRecord(id: string, modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName, id); }, @@ -377,7 +386,7 @@ export default Mixin.create({ @param {Snapshot} snapshot @return {String} url */ - urlForDeleteRecord(id, modelName, snapshot) { + urlForDeleteRecord(id: string, modelName: string, snapshot: Snapshot): string { return this._buildURL(modelName, id); }, @@ -388,7 +397,7 @@ export default Mixin.create({ @param {String} parentURL @return {String} urlPrefix */ - urlPrefix(path, parentURL) { + urlPrefix(path: string, parentURL: string): string { let host = get(this, 'host'); let namespace = get(this, 'namespace'); @@ -412,7 +421,7 @@ export default Mixin.create({ } // No path provided - let url = []; + let url: string[] = []; if (host) { url.push(host); } @@ -450,7 +459,7 @@ export default Mixin.create({ @param {String} modelName @return {String} path **/ - pathForType(modelName) { + pathForType(modelName: string): string { let camelized = camelize(modelName); return pluralize(camelized); }, diff --git a/packages/adapter/addon/-private/fastboot-interface.ts b/packages/adapter/addon/-private/fastboot-interface.ts new file mode 100644 index 00000000000..ded3c74ecab --- /dev/null +++ b/packages/adapter/addon/-private/fastboot-interface.ts @@ -0,0 +1,24 @@ +export interface Request { + method: string; + body: unknown; + cookies: unknown; + headers: unknown; + queryParams: unknown; + path: string; + protocol: string; + host: string; +} + +interface Shoebox { + put(key: string, value: unknown): void; + retrieve(key: string): undefined | JSON; +} + +export interface Fastboot { + isFastBoot: boolean; + request: Request; + shoebox: Shoebox; + response: unknown; // need types + metadata: unknown; // need types + deferRendering(promise: Promise): unknown; +} diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index 0ae876b2fce..05e3364ef12 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -199,7 +199,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Object} adapterOptions @return {Promise} promise */ - query(store: Store, type: ShimModelClass, query) { + query(store: Store, type: ShimModelClass, query): Promise { warn('You subclassed the Adapter class but missing a query override', false, { id: 'adapter.missing-query', }); diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 528c1c8a3a3..1025321c108 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -6,7 +6,7 @@ import { getOwner } from '@ember/application'; import { deprecate, warn } from '@ember/debug'; -import { computed, get } from '@ember/object'; +import { get } from '@ember/object'; import { assign } from '@ember/polyfills'; import { run } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; @@ -39,6 +39,7 @@ type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; +type Fastboot = import('./-private/fastboot-interface').Fastboot; /** The REST adapter allows your store to communicate with an HTTP server by @@ -301,11 +302,14 @@ type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-re @uses BuildURLMixin */ class RESTAdapter extends Adapter.extend(BuildURLMixin) { + _fastboot: FastBoot | undefined; + _najaxRequest: Function; + useFetch: Boolean; + defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; - @computed get fastboot() { // Avoid computed property override deprecation in fastboot as suggested by: // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override @@ -490,6 +494,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @property headers @type {Object} */ + headers: unknown; /** Called by the store in order to fetch the JSON for a given @@ -991,7 +996,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url: string, type: string, options = {}) { + ajax(url: string, type: string, options = {}): Promise { let adapter = this; let requestData: Record = { @@ -1040,11 +1045,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { jQuery.ajax(options); } - _fetchRequest(options) { + _fetchRequest(options): Promise { let fetchFunction = fetch(); if (fetchFunction) { - return fetchFunction(options.url, options); + return fetchFunction(options.url, options) as Promise; } else { throw new Error( 'cannot find the `fetch` module or the `fetch` global. Did you mean to install the `ember-fetch` addon?' @@ -1055,7 +1060,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { _ajax(options): void { if (this.useFetch) { this._fetchRequest(options); - } else if (DEPRECATE_NAJAX && get(this, 'fastboot.isFastBoot')) { + } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { this._najaxRequest(options); } else { this._ajaxRequest(options); @@ -1080,9 +1085,9 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { options ); - let headers = get(this, 'headers'); + let headers = this.headers; if (headers !== undefined) { - options.headers = assign({}, headers, options.headers); + options.headers = assign({}, headers as object, options.headers); } else if (!options.headers) { options.headers = {}; } @@ -1111,11 +1116,12 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } _ajaxURL(url: string): string | void { - if (get(this, 'fastboot.isFastBoot')) { + let fastboot: Fastboot | undefined = this.fastboot; + if (fastboot && fastboot.isFastBoot) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; - let protocol = get(this, 'fastboot.request.protocol'); - let host = get(this, 'fastboot.request.host'); + let protocol = get(fastboot, 'request.protocol' as keyof Fastboot); + let host = get(fastboot, 'fastboot.request.host' as keyof Fastboot); if (protocolRelativeRegex.test(url)) { return `${protocol}${url}`; @@ -1418,7 +1424,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options) { + RESTAdapter.prototype._najaxRequest = function(options): void { if (typeof najax !== 'undefined') { najax(options); } else { From 74a140958593301b6fa4e07f8019660a3e8a7d24 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 30 Oct 2020 22:33:06 -0700 Subject: [PATCH 06/56] Revert "types/ember update" This reverts commit 40a7b16722fd52d0286e31223227579f73be4c8e. --- yarn.lock | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/yarn.lock b/yarn.lock index df461f11f87..32479c781ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2966,31 +2966,6 @@ "@types/jquery" "*" "@types/rsvp" "*" -"@types/ember@^3.16.2": - version "3.16.2" - resolved "https://registry.npmjs.org/@types/ember/-/ember-3.16.2.tgz#95d58f42de8d8eb043496fca2aaef3cf62832a13" - integrity sha512-00Rh+wDTua6H57wegaU7OWRf6tUNkDOCuxLqdqRDUQTag9W64G1Qgeo6jpT7PiZfoB0T559lziFVgHoKnyBQfQ== - dependencies: - "@types/ember__application" "*" - "@types/ember__array" "*" - "@types/ember__component" "*" - "@types/ember__controller" "*" - "@types/ember__debug" "*" - "@types/ember__engine" "*" - "@types/ember__error" "*" - "@types/ember__object" "*" - "@types/ember__polyfills" "*" - "@types/ember__routing" "*" - "@types/ember__runloop" "*" - "@types/ember__service" "*" - "@types/ember__string" "*" - "@types/ember__template" "*" - "@types/ember__test" "*" - "@types/ember__utils" "*" - "@types/htmlbars-inline-precompile" "*" - "@types/jquery" "*" - "@types/rsvp" "*" - "@types/ember__application@*": version "3.16.0" resolved "https://registry.npmjs.org/@types/ember__application/-/ember__application-3.16.0.tgz#2765a9db639173d0d9abd72f3a76ca61b0c09b38" From 04ee267e42cb7a411585e1d580708fe5f481f858 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 1 Nov 2020 18:32:19 -0800 Subject: [PATCH 07/56] some more casting --- packages/adapter/addon/rest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 1025321c108..dca50fa0ecd 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1075,7 +1075,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options) { + ajaxOptions(url: string, method: string, options: Record) { options = assign( { url, @@ -1087,7 +1087,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { let headers = this.headers; if (headers !== undefined) { - options.headers = assign({}, headers as object, options.headers); + options.headers = assign({}, headers as Record, options.headers); } else if (!options.headers) { options.headers = {}; } From b1f0cfd2404458b4e448467fd41e4ce42e8dceec Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 1 Nov 2020 19:49:41 -0800 Subject: [PATCH 08/56] whoops writable --- packages/adapter/addon/rest.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index dca50fa0ecd..ccf9070b929 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -304,7 +304,6 @@ type Fastboot = import('./-private/fastboot-interface').Fastboot; class RESTAdapter extends Adapter.extend(BuildURLMixin) { _fastboot: FastBoot | undefined; _najaxRequest: Function; - useFetch: Boolean; defaultSerializer = '-rest'; @@ -328,6 +327,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @type {Boolean} @public */ + useFetch: Boolean = false; /** By default, the RESTAdapter will send the query params sorted alphabetically to the @@ -1488,10 +1488,8 @@ if (DEPRECATE_NAJAX) { }); } else { Object.defineProperty(RESTAdapter.prototype, 'useFetch', { - value() { - return true; - }, - configurable: true, + writable: true, + value: true, }); } From 9618dc8513f0ab614b7d68e9eee457b7314a5635 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 1 Nov 2020 20:56:54 -0800 Subject: [PATCH 09/56] fix jquery in typescript globals is not allowed --- packages/adapter/addon/rest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index ccf9070b929..392b55c1224 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1,5 +1,3 @@ -/* globals jQuery */ - /** @module @ember-data/adapter */ @@ -31,8 +29,10 @@ import { addSymbol, symbol } from '@ember-data/store/-private'; import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; const UseFetch = symbol('useFetch'); + const hasJQuery = typeof jQuery !== 'undefined'; +declare var jQuery: any; declare var najax: Function; type Payload = Record | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; @@ -327,7 +327,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @type {Boolean} @public */ - useFetch: Boolean = false; + useFetch: boolean; /** By default, the RESTAdapter will send the query params sorted alphabetically to the From 551330c9236edf8d9988a635f384f40c53341492 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 1 Nov 2020 21:27:33 -0800 Subject: [PATCH 10/56] just set useFetch instead of non ie11 compat version --- packages/adapter/addon/rest.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 392b55c1224..61a26a0b715 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1487,10 +1487,7 @@ if (DEPRECATE_NAJAX) { }, }); } else { - Object.defineProperty(RESTAdapter.prototype, 'useFetch', { - writable: true, - value: true, - }); + RESTAdapter.prototype.useFetch = true; } export default RESTAdapter; From 67a83272cd5679fa23c3607b1ea120de94349508 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 1 Nov 2020 21:40:21 -0800 Subject: [PATCH 11/56] textStatus(jquery) => statusText(Response) --- packages/adapter/addon/rest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 61a26a0b715..348aa0f6934 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1340,7 +1340,7 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { function fetchResponseData(response: Response): Record { return { status: response.status, - textStatus: (response).textStatus, + textStatus: response.statusText, headers: headersToObject(response.headers), }; } From aa61154f120c39dfb4da6f8625544970c6294fca Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 2 Nov 2020 20:11:28 -0800 Subject: [PATCH 12/56] create js util for jquery --- packages/adapter/addon/-private/index.ts | 1 + packages/adapter/addon/-private/jquery.js | 8 ++++++++ packages/adapter/addon/rest.ts | 10 ++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 packages/adapter/addon/-private/jquery.js diff --git a/packages/adapter/addon/-private/index.ts b/packages/adapter/addon/-private/index.ts index 4d1d18fb8df..c2f0a748a8a 100644 --- a/packages/adapter/addon/-private/index.ts +++ b/packages/adapter/addon/-private/index.ts @@ -8,3 +8,4 @@ export { serializeQueryParams } from './utils/serialize-query-params'; export { default as fetch } from './utils/fetch'; export { default as BuildURLMixin } from './build-url-mixin'; export { default as serializeIntoHash } from './utils/serialize-into-hash'; +export { default as jQuery } from './jquery'; diff --git a/packages/adapter/addon/-private/jquery.js b/packages/adapter/addon/-private/jquery.js new file mode 100644 index 00000000000..bb9d1de7439 --- /dev/null +++ b/packages/adapter/addon/-private/jquery.js @@ -0,0 +1,8 @@ +/* globals jQuery */ + +let jquery; +if (typeof jQuery !== 'undefined') { + jquery = jQuery; +} + +export default jquery; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 348aa0f6934..201484f7f99 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -26,13 +26,19 @@ import AdapterError, { import { DEPRECATE_NAJAX } from '@ember-data/private-build-infra/deprecations'; import { addSymbol, symbol } from '@ember-data/store/-private'; -import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; +import { + determineBodyPromise, + fetch, + jQuery, + parseResponseHeaders, + serializeIntoHash, + serializeQueryParams, +} from './-private'; const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; -declare var jQuery: any; declare var najax: Function; type Payload = Record | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; From 76a54832851a04c2eada6f75bfa64844dd5d1dc4 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 4 Nov 2020 19:14:16 -0800 Subject: [PATCH 13/56] Add global definition jQuery --- packages/adapter/addon/-private/index.ts | 1 - packages/adapter/addon/-private/jquery.d.ts | 7 +++++++ packages/adapter/addon/-private/jquery.js | 8 -------- packages/adapter/addon/rest.ts | 9 +-------- 4 files changed, 8 insertions(+), 17 deletions(-) create mode 100644 packages/adapter/addon/-private/jquery.d.ts delete mode 100644 packages/adapter/addon/-private/jquery.js diff --git a/packages/adapter/addon/-private/index.ts b/packages/adapter/addon/-private/index.ts index c2f0a748a8a..4d1d18fb8df 100644 --- a/packages/adapter/addon/-private/index.ts +++ b/packages/adapter/addon/-private/index.ts @@ -8,4 +8,3 @@ export { serializeQueryParams } from './utils/serialize-query-params'; export { default as fetch } from './utils/fetch'; export { default as BuildURLMixin } from './build-url-mixin'; export { default as serializeIntoHash } from './utils/serialize-into-hash'; -export { default as jQuery } from './jquery'; diff --git a/packages/adapter/addon/-private/jquery.d.ts b/packages/adapter/addon/-private/jquery.d.ts new file mode 100644 index 00000000000..3475e863d47 --- /dev/null +++ b/packages/adapter/addon/-private/jquery.d.ts @@ -0,0 +1,7 @@ +import jQuery from '@types/jquery'; + +declare global { + interface Window { + jQuery?: typeof jQuery; + } +} diff --git a/packages/adapter/addon/-private/jquery.js b/packages/adapter/addon/-private/jquery.js deleted file mode 100644 index bb9d1de7439..00000000000 --- a/packages/adapter/addon/-private/jquery.js +++ /dev/null @@ -1,8 +0,0 @@ -/* globals jQuery */ - -let jquery; -if (typeof jQuery !== 'undefined') { - jquery = jQuery; -} - -export default jquery; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 201484f7f99..cebf7c57c65 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -26,14 +26,7 @@ import AdapterError, { import { DEPRECATE_NAJAX } from '@ember-data/private-build-infra/deprecations'; import { addSymbol, symbol } from '@ember-data/store/-private'; -import { - determineBodyPromise, - fetch, - jQuery, - parseResponseHeaders, - serializeIntoHash, - serializeQueryParams, -} from './-private'; +import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; const UseFetch = symbol('useFetch'); From 1973a25a15dfc6a3df4235d5dcce55e2e08607a9 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 4 Nov 2020 19:26:32 -0800 Subject: [PATCH 14/56] add globals for jQuery. I thought this didnt work --- packages/adapter/addon/rest.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index cebf7c57c65..70eea843445 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1,3 +1,5 @@ +/* globals jQuery */ + /** @module @ember-data/adapter */ From 1e9d4d788d2a7dca9a0bf7a213fb651ffaa3dff4 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 4 Nov 2020 20:28:38 -0800 Subject: [PATCH 15/56] v0.0.0 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 028dac6ab64..9059f2574d8 100644 --- a/package.json +++ b/package.json @@ -146,5 +146,6 @@ "volta": { "node": "12.16.2", "yarn": "1.22.4" - } + }, + "version": "0.0.0" } From d9d74bd050ffa0c313c4e5508295b428f6ede52b Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 8 Nov 2020 21:01:50 -0800 Subject: [PATCH 16/56] get off window --- packages/adapter/addon/rest.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 70eea843445..1c14d5b764c 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1,5 +1,3 @@ -/* globals jQuery */ - /** @module @ember-data/adapter */ @@ -1043,7 +1041,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options jQuery ajax options to be used for the ajax request */ _ajaxRequest(options): void { - jQuery.ajax(options); + let jQuery: Window['jQuery'] = window.jQuery; + jQuery!.ajax(options); } _fetchRequest(options): Promise { From 6d2d1e8c442f6222fd2bf2c0ba6d7f2a5d246470 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 8 Nov 2020 21:49:40 -0800 Subject: [PATCH 17/56] improvements --- package.json | 3 +-- packages/private-build-infra/addon/current-deprecations.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9059f2574d8..028dac6ab64 100644 --- a/package.json +++ b/package.json @@ -146,6 +146,5 @@ "volta": { "node": "12.16.2", "yarn": "1.22.4" - }, - "version": "0.0.0" + } } diff --git a/packages/private-build-infra/addon/current-deprecations.ts b/packages/private-build-infra/addon/current-deprecations.ts index 4e8f2de5358..dec3da9a66b 100644 --- a/packages/private-build-infra/addon/current-deprecations.ts +++ b/packages/private-build-infra/addon/current-deprecations.ts @@ -15,7 +15,7 @@ * An app can use a different version than what it specifies as it's compatibility * version. For instance, an App could be using `3.16` while specifying compatibility * with `3.12`. This would remove any deprecations that were present in or before `3.12` - * but keep support for anything deprecated in or abvoe `3.13`. + * but keep support for anything deprecated in or above `3.13`. * * ### Configuring Compatibility * From 870f16c465c03702c9c65f86aab65f308e3bc3f6 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Sun, 8 Nov 2020 21:50:08 -0800 Subject: [PATCH 18/56] Lets try simplest route with ts first --- .../addon/-private/fastboot-interface.ts | 2 +- packages/adapter/addon/rest.ts | 137 +++++++++--------- 2 files changed, 66 insertions(+), 73 deletions(-) diff --git a/packages/adapter/addon/-private/fastboot-interface.ts b/packages/adapter/addon/-private/fastboot-interface.ts index ded3c74ecab..d51b0fa0a1b 100644 --- a/packages/adapter/addon/-private/fastboot-interface.ts +++ b/packages/adapter/addon/-private/fastboot-interface.ts @@ -14,7 +14,7 @@ interface Shoebox { retrieve(key: string): undefined | JSON; } -export interface Fastboot { +export interface FastBoot { isFastBoot: boolean; request: Request; shoebox: Shoebox; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 1c14d5b764c..98c290511b3 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1,10 +1,11 @@ +/* globals jQuery */ + /** @module @ember-data/adapter */ import { getOwner } from '@ember/application'; import { deprecate, warn } from '@ember/debug'; -import { get } from '@ember/object'; import { assign } from '@ember/polyfills'; import { run } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; @@ -29,16 +30,11 @@ import { addSymbol, symbol } from '@ember-data/store/-private'; import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; const UseFetch = symbol('useFetch'); - const hasJQuery = typeof jQuery !== 'undefined'; declare var najax: Function; -type Payload = Record | string | undefined; -type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; -type Store = import('@ember-data/store/-private/system/core-store').default; +type FastBoot = import('./-private/fastboot-interface').FastBoot; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; -type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; -type Fastboot = import('./-private/fastboot-interface').Fastboot; /** The REST adapter allows your store to communicate with an HTTP server by @@ -512,7 +508,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { + findRecord(store, type, id, snapshot) { let url = this.buildURL(type.modelName, id, snapshot, 'findRecord'); let query = this.buildQuery(snapshot); @@ -533,9 +529,9 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ - findAll(store: Store, type: ShimModelClass, sinceToken, snapshotRecordArray: SnapshotRecordArray) { + findAll(store, type, sinceToken, snapshotRecordArray) { let query: Record = this.buildQuery(snapshotRecordArray); - let url: string = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); + let url = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); if (sinceToken) { query.since = sinceToken; @@ -561,7 +557,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - query(store: Store, type: ShimModelClass, query) { + query(store, type, query) { let url = this.buildURL(type.modelName, null, null, 'query', query); if (this.sortQueryParams) { @@ -589,7 +585,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - queryRecord(store: Store, type: ShimModelClass, query) { + queryRecord(store, type, query) { let url = this.buildURL(type.modelName, null, null, 'queryRecord', query); if (this.sortQueryParams) { @@ -632,7 +628,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Array} snapshots @return {Promise} promise */ - findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { + findMany(store, type, ids, snapshots) { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { ids: ids } }); } @@ -673,7 +669,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findHasMany(store: Store, snapshot: Snapshot, url: string, relationship) { + findHasMany(store, snapshot, url, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -718,7 +714,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findBelongsTo(store: Store, snapshot: Snapshot, url: string, relationship) { + findBelongsTo(store, snapshot, url, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -742,7 +738,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + createRecord(store, type, snapshot) { let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); const data = serializeIntoHash(store, type, snapshot); @@ -766,7 +762,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + updateRecord(store, type, snapshot) { const data = serializeIntoHash(store, type, snapshot, {}); let id = snapshot.id; @@ -786,26 +782,26 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + deleteRecord(store, type, snapshot) { let id = snapshot.id; return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), 'DELETE'); } - _stripIDFromURL(store: Store, snapshot: Snapshot) { - let url: string = this.buildURL(snapshot.modelName, snapshot.id, snapshot); + _stripIDFromURL(store, snapshot) { + let url = this.buildURL(snapshot.modelName, snapshot.id, snapshot); - let expandedURL: string[] = url.split('/'); + let expandedURL = url.split('/'); // Case when the url is of the format ...something/:id // We are decodeURIComponent-ing the lastSegment because if it represents // the id, it has been encodeURIComponent-ified within `buildURL`. If we // don't do this, then records with id having special characters are not // coalesced correctly (see GH #4190 for the reported bug) - let lastSegment: string = expandedURL[expandedURL.length - 1]; + let lastSegment = expandedURL[expandedURL.length - 1]; let id = snapshot.id; if (decodeURIComponent(lastSegment) === id) { expandedURL[expandedURL.length - 1] = ''; - } else if (id && endsWith(lastSegment, '?id=' + id)) { + } else if (endsWith(lastSegment, '?id=' + id)) { //Case when the url is of the format ...something?id=:id expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1); } @@ -838,13 +834,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @return {Array} an array of arrays of records, each of which is to be loaded separately by `findMany`. */ - groupRecordsForFindMany(store: Store, snapshots: Snapshot[]): Snapshot[][] { + groupRecordsForFindMany(store, snapshots) { let groups = new Map(); let adapter = this; let maxURLLength = this.maxURLLength; snapshots.forEach(snapshot => { - let baseUrl: string = adapter._stripIDFromURL(store, snapshot); + let baseUrl = adapter._stripIDFromURL(store, snapshot); if (!groups.has(baseUrl)) { groups.set(baseUrl, []); } @@ -854,11 +850,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { function splitGroupToFitInUrl(group, maxURLLength, paramNameLength) { let idsSize = 0; - let baseUrl: string = adapter._stripIDFromURL(store, group[0]); + let baseUrl = adapter._stripIDFromURL(store, group[0]); let splitGroups: Snapshot[][] = [[]]; group.forEach(snapshot => { - let additionalLength: number = encodeURIComponent(snapshot.id).length + paramNameLength; + let additionalLength = encodeURIComponent(snapshot.id).length + paramNameLength; if (baseUrl.length + idsSize + additionalLength >= maxURLLength) { idsSize = 0; splitGroups.push([]); @@ -913,11 +909,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData - the original request information @return {Object | AdapterError} response */ - handleResponse(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings) { + handleResponse(status, headers, payload, requestData) { if (this.isSuccess(status, headers, payload)) { return payload; - } else if (payload && this.isInvalid(status, headers, payload)) { - return new InvalidError((payload as Record).errors); + } else if (this.isInvalid(status, headers, payload)) { + return new InvalidError(payload.errors); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -952,7 +948,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isSuccess(status: number, headers, payload): boolean { + isSuccess(status, headers, payload) { return (status >= 200 && status < 300) || status === 304; } @@ -967,7 +963,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isInvalid(status: number, headers, payload): boolean { + isInvalid(status, headers, payload) { return status === 422; } @@ -995,10 +991,10 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url: string, type: string, options = {}): Promise { + ajax(url, type, options = {}): Promise { let adapter = this; - let requestData: Record = { + let requestData = { url: url, method: type, }; @@ -1040,12 +1036,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options): void { - let jQuery: Window['jQuery'] = window.jQuery; - jQuery!.ajax(options); + _ajaxRequest(options) { + jQuery.ajax(options); } - _fetchRequest(options): Promise { + _fetchRequest(options) { let fetchFunction = fetch(); if (fetchFunction) { @@ -1057,7 +1052,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options): void { + _ajax(options) { if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { @@ -1075,7 +1070,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: Record) { + ajaxOptions(url, method, options) { options = assign( { url, @@ -1085,9 +1080,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { options ); - let headers = this.headers; - if (headers !== undefined) { - options.headers = assign({}, headers as Record, options.headers); + if (this.headers !== undefined) { + options.headers = assign({}, this.headers as Record, options.headers); } else if (!options.headers) { options.headers = {}; } @@ -1115,13 +1109,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return options; } - _ajaxURL(url: string): string | void { - let fastboot: Fastboot | undefined = this.fastboot; - if (fastboot && fastboot.isFastBoot) { + _ajaxURL(url) { + let fastboot: FastBoot = this.fastboot; + if (fastboot.isFastBoot) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; - let protocol = get(fastboot, 'request.protocol' as keyof Fastboot); - let host = get(fastboot, 'fastboot.request.host' as keyof Fastboot); + let protocol = fastboot.request.protocol; + let host = fastboot.request.host; if (protocolRelativeRegex.test(url)) { return `${protocol}${url}`; @@ -1146,7 +1140,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {String} responseText @return {Object} */ - parseErrorResponse(responseText: string) { + parseErrorResponse(responseText) { let json = responseText; try { @@ -1166,7 +1160,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Array} errors payload */ - normalizeErrorResponse(status: number, headers, payload) { + normalizeErrorResponse(status, headers, payload) { if (payload && typeof payload === 'object' && payload.errors) { return payload.errors; } else { @@ -1192,11 +1186,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData @return {String} detailed error message */ - generatedDetailedMessage(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings): string { + generatedDetailedMessage(status, headers, payload, requestData) { let shortenedPayload; let payloadContentType = headers['content-type'] || 'Empty Content-Type'; - if (payloadContentType === 'text/html' && (payload as string).length > 250) { + if (payloadContentType === 'text/html' && payload.length > 250) { shortenedPayload = '[Omitted Lengthy HTML]'; } else { shortenedPayload = payload; @@ -1216,10 +1210,10 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @method buildQuery @since 2.5.0 @public - @param {Snapshot | SnapshotRecordArray} snapshot + @param {Snapshot} snapshot @return {Object} */ - buildQuery(snapshot: Snapshot | SnapshotRecordArray): object { + buildQuery(snapshot) { let query: Record = {}; if (snapshot) { @@ -1234,7 +1228,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } -function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { +function ajaxSuccess(adapter, payload, requestData, responseData) { let response; try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); @@ -1249,7 +1243,7 @@ function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, } } -function ajaxError(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { +function ajaxError(adapter, payload, requestData, responseData) { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1275,7 +1269,7 @@ function ajaxError(adapter, payload: Payload, requestData: JQueryAjaxSettings, r } // Adapter abort error to include any relevent info, e.g. request/response: -function handleAbort(requestData, responseData): AbortError { +function handleAbort(requestData, responseData) { let { method, url, errorThrown } = requestData; let { status } = responseData; let msg = `Request failed: ${method} ${url} ${errorThrown || ''}`; @@ -1284,7 +1278,7 @@ function handleAbort(requestData, responseData): AbortError { } //From http://stackoverflow.com/questions/280634/endswith-in-javascript -function endsWith(string, suffix): boolean { +function endsWith(string, suffix) { if (typeof String.prototype.endsWith !== 'function') { return string.indexOf(suffix, string.length - suffix.length) !== -1; } else { @@ -1292,18 +1286,12 @@ function endsWith(string, suffix): boolean { } } -function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: Record) { +function fetchSuccessHandler(adapter, payload, response, requestData) { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); } -function fetchErrorHandler( - adapter, - payload: Payload, - response: Response, - errorThrown, - requestData: Record -) { +function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) { let responseData = fetchResponseData(response); if (responseData.status === 200 && payload instanceof Error) { @@ -1316,7 +1304,7 @@ function fetchErrorHandler( return ajaxError(adapter, payload, requestData, responseData); } -function ajaxSuccessHandler(adapter, payload: Payload, jqXHR, requestData: Record) { +function ajaxSuccessHandler(adapter, payload, jqXHR, requestData) { let responseData = ajaxResponseData(jqXHR); return ajaxSuccess(adapter, payload, requestData, responseData); } @@ -1337,10 +1325,10 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { return ajaxError(adapter, payload, requestData, responseData); } -function fetchResponseData(response: Response): Record { +function fetchResponseData(response): Record { return { status: response.status, - textStatus: response.statusText, + textStatus: response.textStatus, headers: headersToObject(response.headers), }; } @@ -1353,7 +1341,7 @@ function ajaxResponseData(jqXHR): Record { }; } -function headersToObject(headers): Record { +function headersToObject(headers) { let headersObject = {}; if (headers) { @@ -1424,7 +1412,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options): void { + RESTAdapter.prototype._najaxRequest = function(options) { if (typeof najax !== 'undefined') { najax(options); } else { @@ -1487,7 +1475,12 @@ if (DEPRECATE_NAJAX) { }, }); } else { - RESTAdapter.prototype.useFetch = true; + Object.defineProperty(RESTAdapter.prototype, 'useFetch', { + value() { + return true; + }, + configurable: true, + }); } export default RESTAdapter; From 8f88b804008ba47c1cf0d2449a6828ff3ee2e5cb Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 9 Nov 2020 20:34:25 -0800 Subject: [PATCH 19/56] fix test error --- packages/adapter/addon/rest.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 98c290511b3..44fafa9291f 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1110,12 +1110,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } _ajaxURL(url) { - let fastboot: FastBoot = this.fastboot; - if (fastboot.isFastBoot) { + if (this.fastboot?.isFastBoot) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; - let protocol = fastboot.request.protocol; - let host = fastboot.request.host; + let protocol = this.fastboot.request.protocol; + let host = this.fastboot.request.host; if (protocolRelativeRegex.test(url)) { return `${protocol}${url}`; From d4be51eed366cdb2e52235106a8b366e4b15b43e Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 9 Nov 2020 20:59:48 -0800 Subject: [PATCH 20/56] do not assign useFetch in constructor body --- packages/adapter/addon/rest.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 44fafa9291f..c4c7897a440 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -318,11 +318,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } /** + We do not define the type so that Typescipt does not assign in body of constructor to undefined @property useFetch @type {Boolean} @public */ - useFetch: boolean; /** By default, the RESTAdapter will send the query params sorted alphabetically to the @@ -1000,7 +1000,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { }; let hash = adapter.ajaxOptions(url, type, options); - if (this.useFetch) { + if ((this as any).useFetch) { let _response; return this._fetchRequest(hash) .then(response => { @@ -1053,7 +1053,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } _ajax(options) { - if (this.useFetch) { + if ((this as any).useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { this._najaxRequest(options); @@ -1088,7 +1088,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { let contentType = options.contentType || this._defaultContentType; - if (this.useFetch) { + if ((this as any).useFetch) { if (options.data && options.type !== 'GET') { if (!options.headers['Content-Type'] && !options.headers['content-type']) { options.headers['content-type'] = contentType; From 55960a6dd788af2f4c7344ac3dd5c303fc22ed09 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 9 Nov 2020 21:11:28 -0800 Subject: [PATCH 21/56] more as any to prevent assigning in body of constructor --- packages/adapter/addon/rest.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index c4c7897a440..2dc8c875c5e 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -298,7 +298,6 @@ type Snapshot = import('@ember-data/store/-private/system/snapshot').default; */ class RESTAdapter extends Adapter.extend(BuildURLMixin) { _fastboot: FastBoot | undefined; - _najaxRequest: Function; defaultSerializer = '-rest'; @@ -313,7 +312,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return (this._fastboot = getOwner(this).lookup('service:fastboot')); } - set fastboot(value) { + set fastboot(value: FastBoot) { this._fastboot = value; } @@ -1056,7 +1055,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if ((this as any).useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { - this._najaxRequest(options); + (this as any)._najaxRequest(options); } else { this._ajaxRequest(options); } @@ -1411,7 +1410,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options) { + (RESTAdapter.prototype as any)._najaxRequest = function(options) { if (typeof najax !== 'undefined') { najax(options); } else { From 52eab28c4a3ab6c9e1f727de18269e2ceb56605f Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 9 Nov 2020 21:49:12 -0800 Subject: [PATCH 22/56] moar types --- packages/adapter/addon/rest.ts | 76 +++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 2dc8c875c5e..af73c27aa49 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -34,7 +34,11 @@ const hasJQuery = typeof jQuery !== 'undefined'; declare var najax: Function; type FastBoot = import('./-private/fastboot-interface').FastBoot; +type Payload = Record | string | undefined; +type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; +type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; +type Store = import('@ember-data/store/-private/system/core-store').default; /** The REST adapter allows your store to communicate with an HTTP server by @@ -507,7 +511,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - findRecord(store, type, id, snapshot) { + findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { let url = this.buildURL(type.modelName, id, snapshot, 'findRecord'); let query = this.buildQuery(snapshot); @@ -528,7 +532,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ - findAll(store, type, sinceToken, snapshotRecordArray) { + findAll(store: Store, type: ShimModelClass, sinceToken, snapshotRecordArray: SnapshotRecordArray) { let query: Record = this.buildQuery(snapshotRecordArray); let url = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); @@ -556,7 +560,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - query(store, type, query) { + query(store: Store, type: ShimModelClass, query) { let url = this.buildURL(type.modelName, null, null, 'query', query); if (this.sortQueryParams) { @@ -584,7 +588,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - queryRecord(store, type, query) { + queryRecord(store: Store, type: ShimModelClass, query) { let url = this.buildURL(type.modelName, null, null, 'queryRecord', query); if (this.sortQueryParams) { @@ -627,7 +631,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Array} snapshots @return {Promise} promise */ - findMany(store, type, ids, snapshots) { + findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { ids: ids } }); } @@ -668,7 +672,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findHasMany(store, snapshot, url, relationship) { + findHasMany(store: Store, snapshot: Snapshot, url: string, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -713,7 +717,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findBelongsTo(store, snapshot, url, relationship) { + findBelongsTo(store: Store, snapshot: Snapshot, url: string, relationship) { let id = snapshot.id; let type = snapshot.modelName; @@ -737,7 +741,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - createRecord(store, type, snapshot) { + createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); const data = serializeIntoHash(store, type, snapshot); @@ -761,7 +765,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - updateRecord(store, type, snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { const data = serializeIntoHash(store, type, snapshot, {}); let id = snapshot.id; @@ -781,26 +785,26 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - deleteRecord(store, type, snapshot) { + deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { let id = snapshot.id; return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), 'DELETE'); } - _stripIDFromURL(store, snapshot) { + _stripIDFromURL(store: Store, snapshot: Snapshot): string { let url = this.buildURL(snapshot.modelName, snapshot.id, snapshot); - let expandedURL = url.split('/'); + let expandedURL: string[] = url.split('/'); // Case when the url is of the format ...something/:id // We are decodeURIComponent-ing the lastSegment because if it represents // the id, it has been encodeURIComponent-ified within `buildURL`. If we // don't do this, then records with id having special characters are not // coalesced correctly (see GH #4190 for the reported bug) - let lastSegment = expandedURL[expandedURL.length - 1]; + let lastSegment: string = expandedURL[expandedURL.length - 1]; let id = snapshot.id; if (decodeURIComponent(lastSegment) === id) { expandedURL[expandedURL.length - 1] = ''; - } else if (endsWith(lastSegment, '?id=' + id)) { + } else if (id && endsWith(lastSegment, '?id=' + id)) { //Case when the url is of the format ...something?id=:id expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1); } @@ -833,7 +837,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @return {Array} an array of arrays of records, each of which is to be loaded separately by `findMany`. */ - groupRecordsForFindMany(store, snapshots) { + groupRecordsForFindMany(store: Store, snapshots: Snapshot[]): Snapshot[][] { let groups = new Map(); let adapter = this; let maxURLLength = this.maxURLLength; @@ -908,11 +912,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData - the original request information @return {Object | AdapterError} response */ - handleResponse(status, headers, payload, requestData) { + handleResponse(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings) { if (this.isSuccess(status, headers, payload)) { return payload; } else if (this.isInvalid(status, headers, payload)) { - return new InvalidError(payload.errors); + return new InvalidError((payload as Record).errors); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -1035,7 +1039,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options) { + _ajaxRequest(options): void { jQuery.ajax(options); } @@ -1051,7 +1055,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options) { + _ajax(options): void { if ((this as any).useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { @@ -1069,7 +1073,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url, method, options) { + ajaxOptions(url: string, method: string, options: Record) { options = assign( { url, @@ -1108,7 +1112,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return options; } - _ajaxURL(url) { + _ajaxURL(url: string): string | void { if (this.fastboot?.isFastBoot) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; @@ -1184,11 +1188,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData @return {String} detailed error message */ - generatedDetailedMessage(status, headers, payload, requestData) { + generatedDetailedMessage(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings): string { let shortenedPayload; let payloadContentType = headers['content-type'] || 'Empty Content-Type'; - if (payloadContentType === 'text/html' && payload.length > 250) { + if (payloadContentType === 'text/html' && (payload as string).length > 250) { shortenedPayload = '[Omitted Lengthy HTML]'; } else { shortenedPayload = payload; @@ -1211,7 +1215,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Object} */ - buildQuery(snapshot) { + buildQuery(snapshot: Snapshot | SnapshotRecordArray): object { let query: Record = {}; if (snapshot) { @@ -1226,7 +1230,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } -function ajaxSuccess(adapter, payload, requestData, responseData) { +function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { let response; try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); @@ -1241,7 +1245,7 @@ function ajaxSuccess(adapter, payload, requestData, responseData) { } } -function ajaxError(adapter, payload, requestData, responseData) { +function ajaxError(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1267,7 +1271,7 @@ function ajaxError(adapter, payload, requestData, responseData) { } // Adapter abort error to include any relevent info, e.g. request/response: -function handleAbort(requestData, responseData) { +function handleAbort(requestData, responseData): AbortError { let { method, url, errorThrown } = requestData; let { status } = responseData; let msg = `Request failed: ${method} ${url} ${errorThrown || ''}`; @@ -1276,7 +1280,7 @@ function handleAbort(requestData, responseData) { } //From http://stackoverflow.com/questions/280634/endswith-in-javascript -function endsWith(string, suffix) { +function endsWith(string, suffix): boolean { if (typeof String.prototype.endsWith !== 'function') { return string.indexOf(suffix, string.length - suffix.length) !== -1; } else { @@ -1284,12 +1288,18 @@ function endsWith(string, suffix) { } } -function fetchSuccessHandler(adapter, payload, response, requestData) { +function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: Record) { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); } -function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) { +function fetchErrorHandler( + adapter, + payload: Payload, + response: Response, + errorThrown, + requestData: Record +) { let responseData = fetchResponseData(response); if (responseData.status === 200 && payload instanceof Error) { @@ -1323,10 +1333,10 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { return ajaxError(adapter, payload, requestData, responseData); } -function fetchResponseData(response): Record { +function fetchResponseData(response: Response): Record { return { status: response.status, - textStatus: response.textStatus, + textStatus: response.statusText, headers: headersToObject(response.headers), }; } @@ -1410,7 +1420,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - (RESTAdapter.prototype as any)._najaxRequest = function(options) { + (RESTAdapter.prototype as any)._najaxRequest = function(options): void { if (typeof najax !== 'undefined') { najax(options); } else { From 499308906010bf31084d3f0e943bea88192b95a0 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 9 Nov 2020 22:06:41 -0800 Subject: [PATCH 23/56] another constructor body issue --- packages/adapter/addon/rest.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index af73c27aa49..6c307253ec5 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -492,7 +492,6 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @property headers @type {Object} */ - headers: unknown; /** Called by the store in order to fetch the JSON for a given @@ -1083,8 +1082,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { options ); - if (this.headers !== undefined) { - options.headers = assign({}, this.headers as Record, options.headers); + if ((this as any).headers !== undefined) { + options.headers = assign({}, (this as any).headers as Record, options.headers); } else if (!options.headers) { options.headers = {}; } From 454b5155bcc335f4a69526c09976319c0cb8c9aa Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Tue, 10 Nov 2020 18:20:23 -0800 Subject: [PATCH 24/56] remove fastboot off of constructor --- packages/adapter/addon/rest.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 6c307253ec5..f5a528da32a 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -301,8 +301,6 @@ type Store = import('@ember-data/store/-private/system/core-store').default; @uses BuildURLMixin */ class RESTAdapter extends Adapter.extend(BuildURLMixin) { - _fastboot: FastBoot | undefined; - defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; @@ -310,14 +308,15 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { get fastboot() { // Avoid computed property override deprecation in fastboot as suggested by: // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override - if (this._fastboot) { - return this._fastboot; + let fastboot = (this as any)._fastboot; + if (fastboot) { + return fastboot; } - return (this._fastboot = getOwner(this).lookup('service:fastboot')); + return ((this as any)._fastboot = getOwner(this).lookup('service:fastboot')); } set fastboot(value: FastBoot) { - this._fastboot = value; + (this as any)._fastboot = value; } /** From 5d222952309d2005692fd893088442994c81829e Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Tue, 10 Nov 2020 20:25:02 -0800 Subject: [PATCH 25/56] add computed --- packages/adapter/addon/rest.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index f5a528da32a..364159d6394 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -6,6 +6,7 @@ import { getOwner } from '@ember/application'; import { deprecate, warn } from '@ember/debug'; +import { computed } from '@ember/object'; import { assign } from '@ember/polyfills'; import { run } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; @@ -305,6 +306,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { _defaultContentType = 'application/json; charset=utf-8'; + @computed('_fastboot') get fastboot() { // Avoid computed property override deprecation in fastboot as suggested by: // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override From 945f0970bc97ec7e504db3605398aba004e0e82c Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Mon, 23 Nov 2020 21:10:22 -0800 Subject: [PATCH 26/56] Address feedback --- .../adapter/addon/-private/build-url-mixin.ts | 15 +-- packages/adapter/addon/index.ts | 46 ++++----- packages/adapter/addon/json-api.ts | 3 +- packages/adapter/addon/rest.ts | 98 +++++++++++-------- 4 files changed, 90 insertions(+), 72 deletions(-) diff --git a/packages/adapter/addon/-private/build-url-mixin.ts b/packages/adapter/addon/-private/build-url-mixin.ts index 56f6558d55a..0126739e2c3 100644 --- a/packages/adapter/addon/-private/build-url-mixin.ts +++ b/packages/adapter/addon/-private/build-url-mixin.ts @@ -4,6 +4,7 @@ import { camelize } from '@ember/string'; import { pluralize } from 'ember-inflector'; +type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; @@ -60,11 +61,11 @@ export default Mixin.create({ */ buildURL( modelName: string, - id: string | string[] | Record | null, + id: string | string[] | Dict | null, snapshot: Snapshot | Snapshot[] | SnapshotRecordArray | null, requestType: string = '', query = {} - ) { + ): string { switch (requestType) { case 'findRecord': return this.urlForFindRecord(id, modelName, snapshot); @@ -98,7 +99,7 @@ export default Mixin.create({ @param {String} id @return {String} url */ - _buildURL(modelName: string, id: string): string { + _buildURL(modelName: string | null | undefined, id: string | null | undefined): string { let path; let url: string[] = []; let host = get(this, 'host'); @@ -204,7 +205,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQuery(query: Record, modelName: string): string { + urlForQuery(query: Dict, modelName: string): string { return this._buildURL(modelName); }, @@ -229,7 +230,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQueryRecord(query: Record, modelName: string): string { + urlForQueryRecord(query: Dict, modelName: string): string { return this._buildURL(modelName); }, @@ -336,7 +337,7 @@ export default Mixin.create({ @param {Snapshot} snapshot @return {String} url */ - urlForCreateRecord(modelName, snapshot) { + urlForCreateRecord(modelName: string, snapshot: Snapshot) { return this._buildURL(modelName); }, @@ -397,7 +398,7 @@ export default Mixin.create({ @param {String} parentURL @return {String} urlPrefix */ - urlPrefix(path: string, parentURL: string): string { + urlPrefix(path: string | null | undefined, parentURL: string): string { let host = get(this, 'host'); let namespace = get(this, 'namespace'); diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index 05e3364ef12..f37cf959ce8 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -1,5 +1,5 @@ -import { warn } from '@ember/debug'; import EmberObject from '@ember/object'; +import { DEBUG } from '@glimmer/env'; import { Promise } from 'rsvp'; @@ -123,9 +123,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { - warn('You subclassed the Adapter class but missing a findRecord override', false, { - id: 'adapter.missing-find-record', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a findRecord override'); + } return Promise.resolve(); } @@ -161,9 +161,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ findAll(store: Store, type: ShimModelClass, neverSet, snapshotRecordArray: SnapshotRecordArray) { - warn('You subclassed the Adapter class but missing a findAll override', false, { - id: 'adapter.missing-find-all', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a findAll override'); + } return Promise.resolve(); } @@ -200,9 +200,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ query(store: Store, type: ShimModelClass, query): Promise { - warn('You subclassed the Adapter class but missing a query override', false, { - id: 'adapter.missing-query', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a query override'); + } return Promise.resolve(); } @@ -245,9 +245,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ queryRecord(store: Store, type: ShimModelClass, query, adapterOptions) { - warn('You subclassed the Adapter class but missing a queryRecord override', false, { - id: 'adapter.missing-query-record', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a queryRecord override'); + } return Promise.resolve(); } @@ -354,9 +354,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { - warn('You subclassed the Adapter class but missing a createRecord override', false, { - id: 'adapter.missing-create-record', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a createRecord override'); + } return Promise.resolve(); } @@ -412,9 +412,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { - warn('You subclassed the Adapter class but missing a updateRecord override', false, { - id: 'adapter.missing-update-record', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a updateRecord override'); + } return Promise.resolve(); } @@ -462,9 +462,9 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Promise} promise */ deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { - warn('You subclassed the Adapter class but missing a deleteRecord override', false, { - id: 'adapter.missing-delete-record', - }); + if (DEBUG) { + throw new Error('You subclassed the Adapter class but missing a deleteRecord override'); + } return Promise.resolve(); } @@ -638,7 +638,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {SnapshotRecordArray} snapshotRecordArray @return {Boolean} */ - shouldReloadAll(store: Store, snapshotRecordArray) { + shouldReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray) { return !snapshotRecordArray.length; } diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index 645a512d348..a9299d7f34d 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -8,6 +8,7 @@ import { pluralize } from 'ember-inflector'; import { serializeIntoHash } from './-private'; import RESTAdapter from './rest'; +type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; @@ -160,7 +161,7 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url: string, type: string, options = {}) { + ajaxOptions(url: string, type: string, options: Dict = {}) { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 364159d6394..ff23e127c0f 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -34,13 +34,35 @@ const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; declare var najax: Function; +type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; +type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type FastBoot = import('./-private/fastboot-interface').FastBoot; -type Payload = Record | string | undefined; +type Payload = Dict | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; type Store = import('@ember-data/store/-private/system/core-store').default; +type QueryState = { + include?: unknown; + since?: unknown; +}; + +type FetchRequestData = { + url?: number; + method?: string; + string: any; +}; + +type RequestData = JQueryAjaxSettings | FetchRequestData; + +type ResponseData = { + status: number; + textStatus: string; + headers: {}; + errorThrown?: any; +}; + /** The REST adapter allows your store to communicate with an HTTP server by transmitting JSON via XHR. Most Ember.js apps that consume a JSON API @@ -306,7 +328,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { _defaultContentType = 'application/json; charset=utf-8'; - @computed('_fastboot') + @computed() get fastboot() { // Avoid computed property override deprecation in fastboot as suggested by: // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override @@ -511,9 +533,9 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { + findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot): Promise { let url = this.buildURL(type.modelName, id, snapshot, 'findRecord'); - let query = this.buildQuery(snapshot); + let query: QueryState = this.buildQuery(snapshot); return this.ajax(url, 'GET', { data: query }); } @@ -532,8 +554,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ - findAll(store: Store, type: ShimModelClass, sinceToken, snapshotRecordArray: SnapshotRecordArray) { - let query: Record = this.buildQuery(snapshotRecordArray); + findAll(store: Store, type: ShimModelClass, sinceToken, snapshotRecordArray: SnapshotRecordArray): Promise { + let query: QueryState = this.buildQuery(snapshotRecordArray); let url = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll'); if (sinceToken) { @@ -560,7 +582,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - query(store: Store, type: ShimModelClass, query) { + query(store: Store, type: ShimModelClass, query): Promise { let url = this.buildURL(type.modelName, null, null, 'query', query); if (this.sortQueryParams) { @@ -588,7 +610,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} query @return {Promise} promise */ - queryRecord(store: Store, type: ShimModelClass, query) { + queryRecord(store: Store, type: ShimModelClass, query: Dict): Promise { let url = this.buildURL(type.modelName, null, null, 'queryRecord', query); if (this.sortQueryParams) { @@ -631,7 +653,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Array} snapshots @return {Promise} promise */ - findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { + findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]): Promise { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { ids: ids } }); } @@ -672,7 +694,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findHasMany(store: Store, snapshot: Snapshot, url: string, relationship) { + findHasMany(store: Store, snapshot: Snapshot, url: string, relationship: Dict): Promise { let id = snapshot.id; let type = snapshot.modelName; @@ -717,7 +739,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} relationship meta object describing the relationship @return {Promise} promise */ - findBelongsTo(store: Store, snapshot: Snapshot, url: string, relationship) { + findBelongsTo(store: Store, snapshot: Snapshot, url: string, relationship): Promise { let id = snapshot.id; let type = snapshot.modelName; @@ -741,7 +763,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { let url = this.buildURL(type.modelName, null, snapshot, 'createRecord'); const data = serializeIntoHash(store, type, snapshot); @@ -765,7 +787,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { const data = serializeIntoHash(store, type, snapshot, {}); let id = snapshot.id; @@ -785,7 +807,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Promise} promise */ - deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { let id = snapshot.id; return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), 'DELETE'); @@ -794,7 +816,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { _stripIDFromURL(store: Store, snapshot: Snapshot): string { let url = this.buildURL(snapshot.modelName, snapshot.id, snapshot); - let expandedURL: string[] = url.split('/'); + let expandedURL = url.split('/'); // Case when the url is of the format ...something/:id // We are decodeURIComponent-ing the lastSegment because if it represents // the id, it has been encodeURIComponent-ified within `buildURL`. If we @@ -912,11 +934,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData - the original request information @return {Object | AdapterError} response */ - handleResponse(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings) { + handleResponse(status: number, headers, payload: Payload, requestData: RequestData) { if (this.isSuccess(status, headers, payload)) { return payload; } else if (this.isInvalid(status, headers, payload)) { - return new InvalidError((payload as Record).errors); + return new InvalidError((payload as Dict).errors); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -994,10 +1016,10 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url, type, options = {}): Promise { + ajax(url: string, type: string, options: JQueryAjaxSettings = {}): Promise { let adapter = this; - let requestData = { + let requestData: RequestData = { url: url, method: type, }; @@ -1008,13 +1030,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { return this._fetchRequest(hash) .then(response => { _response = response; - return determineBodyPromise(response, requestData); + return determineBodyPromise(response, requestData as JQueryAjaxSettings); }) - .then(payload => { + .then((payload: Payload) => { if (_response.ok && !(payload instanceof Error)) { - return fetchSuccessHandler(adapter, payload, _response, requestData); + return fetchSuccessHandler(adapter, payload, _response, requestData as FetchRequestData); } else { - throw fetchErrorHandler(adapter, payload, _response, null, requestData); + throw fetchErrorHandler(adapter, payload, _response, null, requestData as FetchRequestData); } }); } @@ -1073,7 +1095,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: Record) { + ajaxOptions(url: string, method: string, options: ConfidentDict) { options = assign( { url, @@ -1084,7 +1106,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { ); if ((this as any).headers !== undefined) { - options.headers = assign({}, (this as any).headers as Record, options.headers); + options.headers = assign({}, (this as any).headers as Dict, options.headers); } else if (!options.headers) { options.headers = {}; } @@ -1188,7 +1210,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData @return {String} detailed error message */ - generatedDetailedMessage(status: number, headers, payload: Payload, requestData: JQueryAjaxSettings): string { + generatedDetailedMessage(status: number, headers, payload: Payload, requestData: RequestData): string { let shortenedPayload; let payloadContentType = headers['content-type'] || 'Empty Content-Type'; @@ -1215,8 +1237,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Snapshot} snapshot @return {Object} */ - buildQuery(snapshot: Snapshot | SnapshotRecordArray): object { - let query: Record = {}; + buildQuery(snapshot: Snapshot | SnapshotRecordArray): QueryState { + let query: QueryState = {}; if (snapshot) { let { include } = snapshot; @@ -1230,7 +1252,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } -function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { +function ajaxSuccess(adapter, payload: Payload, requestData: RequestData, responseData: ResponseData) { let response; try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); @@ -1245,7 +1267,7 @@ function ajaxSuccess(adapter, payload: Payload, requestData: JQueryAjaxSettings, } } -function ajaxError(adapter, payload: Payload, requestData: JQueryAjaxSettings, responseData: Record) { +function ajaxError(adapter, payload: Payload, requestData: RequestData, responseData: ResponseData) { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1288,18 +1310,12 @@ function endsWith(string, suffix): boolean { } } -function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: Record) { +function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: FetchRequestData) { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); } -function fetchErrorHandler( - adapter, - payload: Payload, - response: Response, - errorThrown, - requestData: Record -) { +function fetchErrorHandler(adapter, payload: Payload, response: Response, errorThrown, requestData: FetchRequestData) { let responseData = fetchResponseData(response); if (responseData.status === 200 && payload instanceof Error) { @@ -1333,7 +1349,7 @@ function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { return ajaxError(adapter, payload, requestData, responseData); } -function fetchResponseData(response: Response): Record { +function fetchResponseData(response: Response): ResponseData { return { status: response.status, textStatus: response.statusText, @@ -1341,7 +1357,7 @@ function fetchResponseData(response: Response): Record { }; } -function ajaxResponseData(jqXHR): Record { +function ajaxResponseData(jqXHR): ResponseData { return { status: jqXHR.status, textStatus: jqXHR.statusText, @@ -1399,7 +1415,7 @@ export function fetchOptions(options, adapter) { return options; } -function ajaxOptions(options, adapter) { +function ajaxOptions(options: ConfidentDict, adapter): ConfidentDict { options.dataType = 'json'; options.context = adapter; From 2a0ac82e71ccd048946d3a8407bdaf75cc891777 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 16:49:29 -0800 Subject: [PATCH 27/56] revert --- yarn.lock | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/yarn.lock b/yarn.lock index 32479c781ed..df461f11f87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2966,6 +2966,31 @@ "@types/jquery" "*" "@types/rsvp" "*" +"@types/ember@^3.16.2": + version "3.16.2" + resolved "https://registry.npmjs.org/@types/ember/-/ember-3.16.2.tgz#95d58f42de8d8eb043496fca2aaef3cf62832a13" + integrity sha512-00Rh+wDTua6H57wegaU7OWRf6tUNkDOCuxLqdqRDUQTag9W64G1Qgeo6jpT7PiZfoB0T559lziFVgHoKnyBQfQ== + dependencies: + "@types/ember__application" "*" + "@types/ember__array" "*" + "@types/ember__component" "*" + "@types/ember__controller" "*" + "@types/ember__debug" "*" + "@types/ember__engine" "*" + "@types/ember__error" "*" + "@types/ember__object" "*" + "@types/ember__polyfills" "*" + "@types/ember__routing" "*" + "@types/ember__runloop" "*" + "@types/ember__service" "*" + "@types/ember__string" "*" + "@types/ember__template" "*" + "@types/ember__test" "*" + "@types/ember__utils" "*" + "@types/htmlbars-inline-precompile" "*" + "@types/jquery" "*" + "@types/rsvp" "*" + "@types/ember__application@*": version "3.16.0" resolved "https://registry.npmjs.org/@types/ember__application/-/ember__application-3.16.0.tgz#2765a9db639173d0d9abd72f3a76ca61b0c09b38" From 255dad75c6837966ece6cfe984d19f684d10acd4 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 17:06:31 -0800 Subject: [PATCH 28/56] declare useFetch --- packages/adapter/addon/rest.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index ff23e127c0f..f8c81ca2216 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -324,6 +324,13 @@ type ResponseData = { @uses BuildURLMixin */ class RESTAdapter extends Adapter.extend(BuildURLMixin) { + /** + @property useFetch + @type {Boolean} + @public + */ + declare useFetch: boolean; + defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; @@ -343,13 +350,6 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { (this as any)._fastboot = value; } - /** - We do not define the type so that Typescipt does not assign in body of constructor to undefined - @property useFetch - @type {Boolean} - @public - */ - /** By default, the RESTAdapter will send the query params sorted alphabetically to the server. @@ -1025,7 +1025,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { }; let hash = adapter.ajaxOptions(url, type, options); - if ((this as any).useFetch) { + if (this.useFetch) { let _response; return this._fetchRequest(hash) .then(response => { @@ -1078,7 +1078,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } _ajax(options): void { - if ((this as any).useFetch) { + if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { (this as any)._najaxRequest(options); @@ -1113,7 +1113,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { let contentType = options.contentType || this._defaultContentType; - if ((this as any).useFetch) { + if (this.useFetch) { if (options.data && options.type !== 'GET') { if (!options.headers['Content-Type'] && !options.headers['content-type']) { options.headers['content-type'] = contentType; From 4041fb433c348d38140b69343672492c3d1e5848 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 17:06:45 -0800 Subject: [PATCH 29/56] declare _fastboot --- packages/adapter/addon/rest.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index f8c81ca2216..279eb37bc8c 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -331,6 +331,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { */ declare useFetch: boolean; + declare _fastboot: FastBoot; + defaultSerializer = '-rest'; _defaultContentType = 'application/json; charset=utf-8'; @@ -339,15 +341,15 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { get fastboot() { // Avoid computed property override deprecation in fastboot as suggested by: // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override - let fastboot = (this as any)._fastboot; + let fastboot = this._fastboot; if (fastboot) { return fastboot; } - return ((this as any)._fastboot = getOwner(this).lookup('service:fastboot')); + return (this._fastboot = getOwner(this).lookup('service:fastboot')); } set fastboot(value: FastBoot) { - (this as any)._fastboot = value; + this._fastboot = value; } /** From fcee91a15a00701e63911ce3273faf28e58d4a70 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 17:07:30 -0800 Subject: [PATCH 30/56] declare _najaxRequest --- packages/adapter/addon/rest.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 279eb37bc8c..09c39c57eb6 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -332,6 +332,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { declare useFetch: boolean; declare _fastboot: FastBoot; + declare _najaxRequest: any; defaultSerializer = '-rest'; @@ -1083,7 +1084,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { - (this as any)._najaxRequest(options); + this._najaxRequest(options); } else { this._ajaxRequest(options); } @@ -1438,7 +1439,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - (RESTAdapter.prototype as any)._najaxRequest = function(options): void { + RESTAdapter.prototype._najaxRequest = function(options): void { if (typeof najax !== 'undefined') { najax(options); } else { From b857533b2be99520f4e6f7d3136a1accf3306b65 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 17:09:52 -0800 Subject: [PATCH 31/56] declare headers --- packages/adapter/addon/rest.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 09c39c57eb6..842c250ada3 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -518,6 +518,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @property headers @type {Object} */ + declare headers: unknown; /** Called by the store in order to fetch the JSON for a given @@ -1108,8 +1109,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { options ); - if ((this as any).headers !== undefined) { - options.headers = assign({}, (this as any).headers as Dict, options.headers); + if (this.headers !== undefined) { + options.headers = assign({}, this.headers as Dict, options.headers); } else if (!options.headers) { options.headers = {}; } From 60576f17c413dd9c23bd7d8136a5443cb8c78796 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 20:22:42 -0800 Subject: [PATCH 32/56] _najaxRequest is a Function --- packages/adapter/addon/rest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 842c250ada3..e6ffc732206 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -332,7 +332,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { declare useFetch: boolean; declare _fastboot: FastBoot; - declare _najaxRequest: any; + declare _najaxRequest: Function; defaultSerializer = '-rest'; From 16e6684ad9e6b2546fc21a2dccc079a2f994e2d8 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 20:31:32 -0800 Subject: [PATCH 33/56] Perhaps we dont need these --- packages/adapter/addon/-private/jquery.d.ts | 7 ------- packages/adapter/addon/rest.ts | 2 -- 2 files changed, 9 deletions(-) delete mode 100644 packages/adapter/addon/-private/jquery.d.ts diff --git a/packages/adapter/addon/-private/jquery.d.ts b/packages/adapter/addon/-private/jquery.d.ts deleted file mode 100644 index 3475e863d47..00000000000 --- a/packages/adapter/addon/-private/jquery.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import jQuery from '@types/jquery'; - -declare global { - interface Window { - jQuery?: typeof jQuery; - } -} diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index e6ffc732206..75adf3d8565 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1,5 +1,3 @@ -/* globals jQuery */ - /** @module @ember-data/adapter */ From c1dc782dc470d390984baaca403ea5c63710a981 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 2 Dec 2020 20:39:39 -0800 Subject: [PATCH 34/56] Minor refactors to najax and jQuery --- packages/adapter/addon/rest.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 75adf3d8565..6265841cecc 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -28,10 +28,6 @@ import { addSymbol, symbol } from '@ember-data/store/-private'; import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; -const UseFetch = symbol('useFetch'); -const hasJQuery = typeof jQuery !== 'undefined'; - -declare var najax: Function; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type FastBoot = import('./-private/fastboot-interface').FastBoot; @@ -61,6 +57,12 @@ type ResponseData = { errorThrown?: any; }; +declare const najax: Function | undefined; +declare const jQuery: ConfidentDict | undefined; + +const UseFetch = symbol('useFetch'); +const hasJQuery = typeof jQuery !== 'undefined'; + /** The REST adapter allows your store to communicate with an HTTP server by transmitting JSON via XHR. Most Ember.js apps that consume a JSON API @@ -1064,7 +1066,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options jQuery ajax options to be used for the ajax request */ _ajaxRequest(options): void { - jQuery.ajax(options); + typeof jQuery !== 'undefined' && jQuery.ajax(options); } _fetchRequest(options) { From ba8facdc6d3ff98dd5a46349395aa04133622702 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 4 Dec 2020 16:19:27 -0800 Subject: [PATCH 35/56] Slim down fastboot interface to only used known properties --- .../adapter/addon/-private/fastboot-interface.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/adapter/addon/-private/fastboot-interface.ts b/packages/adapter/addon/-private/fastboot-interface.ts index d51b0fa0a1b..a9277fb0556 100644 --- a/packages/adapter/addon/-private/fastboot-interface.ts +++ b/packages/adapter/addon/-private/fastboot-interface.ts @@ -1,24 +1,9 @@ export interface Request { - method: string; - body: unknown; - cookies: unknown; - headers: unknown; - queryParams: unknown; - path: string; protocol: string; host: string; } -interface Shoebox { - put(key: string, value: unknown): void; - retrieve(key: string): undefined | JSON; -} - export interface FastBoot { isFastBoot: boolean; request: Request; - shoebox: Shoebox; - response: unknown; // need types - metadata: unknown; // need types - deferRendering(promise: Promise): unknown; } From 858fa3ee52d4d6003af7410a4434408e8d8bb4cf Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 9 Dec 2020 20:57:09 -0800 Subject: [PATCH 36/56] address feedback --- .../-private/utils/determine-body-promise.ts | 11 +- packages/adapter/addon/index.ts | 25 +-- packages/adapter/addon/json-api.ts | 7 +- packages/adapter/addon/rest.ts | 150 +++++++++++------- 4 files changed, 124 insertions(+), 69 deletions(-) diff --git a/packages/adapter/addon/-private/utils/determine-body-promise.ts b/packages/adapter/addon/-private/utils/determine-body-promise.ts index 07b8309ce9a..88937a67215 100644 --- a/packages/adapter/addon/-private/utils/determine-body-promise.ts +++ b/packages/adapter/addon/-private/utils/determine-body-promise.ts @@ -3,6 +3,12 @@ import { DEBUG } from '@glimmer/env'; import continueOnReject from './continue-on-reject'; +type FetchRequestData = { + url?: string; + method?: string; + [key: string]: any; +}; + type Payload = object | string | undefined; interface CustomSyntaxError extends SyntaxError { @@ -62,7 +68,10 @@ function _determineContent(response: Response, requestData: JQueryAjaxSettings, return ret; } -export function determineBodyPromise(response: Response, requestData: JQueryAjaxSettings): Promise { +export function determineBodyPromise( + response: Response, + requestData: JQueryAjaxSettings | FetchRequestData +): Promise { // response.text() may resolve or reject // it is a native promise, may not have finally return continueOnReject(response.text()).then(payload => _determineContent(response, requestData, payload)); diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index f37cf959ce8..e9986944941 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -3,6 +3,7 @@ import { DEBUG } from '@glimmer/env'; import { Promise } from 'rsvp'; +type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type MinimumAdapterInterface = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; @@ -122,7 +123,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Promise} promise */ - findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot) { + findRecord(store: Store, type: ShimModelClass, id: string, snapshot: Snapshot): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a findRecord override'); } @@ -160,7 +161,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {SnapshotRecordArray} snapshotRecordArray @return {Promise} promise */ - findAll(store: Store, type: ShimModelClass, neverSet, snapshotRecordArray: SnapshotRecordArray) { + findAll(store: Store, type: ShimModelClass, neverSet, snapshotRecordArray: SnapshotRecordArray): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a findAll override'); } @@ -244,7 +245,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Object} adapterOptions @return {Promise} promise */ - queryRecord(store: Store, type: ShimModelClass, query, adapterOptions) { + queryRecord(store: Store, type: ShimModelClass, query, adapterOptions): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a queryRecord override'); } @@ -308,7 +309,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Object} options @return {Object} serialized snapshot */ - serialize(snapshot, options) { + serialize(snapshot, options): Dict { return snapshot.serialize(options); } @@ -353,7 +354,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Promise} promise */ - createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + createRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a createRecord override'); } @@ -411,7 +412,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Promise} promise */ - updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a updateRecord override'); } @@ -461,7 +462,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Promise} promise */ - deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + deleteRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { if (DEBUG) { throw new Error('You subclassed the Adapter class but missing a deleteRecord override'); } @@ -533,7 +534,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @return {Array} an array of arrays of records, each of which is to be loaded separately by `findMany`. */ - groupRecordsForFindMany(store: Store, snapshots: Snapshot[]) { + groupRecordsForFindMany(store: Store, snapshots: Snapshot[]): Snapshot[][] { return [snapshots]; } @@ -583,7 +584,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Boolean} */ - shouldReloadRecord(store: Store, snapshot: Snapshot) { + shouldReloadRecord(store: Store, snapshot: Snapshot): boolean { return false; } @@ -638,7 +639,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {SnapshotRecordArray} snapshotRecordArray @return {Boolean} */ - shouldReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray) { + shouldReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray): boolean { return !snapshotRecordArray.length; } @@ -674,7 +675,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {Snapshot} snapshot @return {Boolean} */ - shouldBackgroundReloadRecord(store: Store, Snapshot) { + shouldBackgroundReloadRecord(store: Store, Snapshot): boolean { return true; } @@ -710,7 +711,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf @param {SnapshotRecordArray} snapshotRecordArray @return {Boolean} */ - shouldBackgroundReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray) { + shouldBackgroundReloadAll(store: Store, snapshotRecordArray: SnapshotRecordArray): boolean { return true; } } diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index a9299d7f34d..e52b214e062 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -9,6 +9,7 @@ import { serializeIntoHash } from './-private'; import RESTAdapter from './rest'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; +type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; @@ -161,7 +162,7 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url: string, type: string, options: Dict = {}) { + ajaxOptions(url: string, type: string, options: Dict = {}): ConfidentDict { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; @@ -224,14 +225,14 @@ class JSONAPIAdapter extends RESTAdapter { @property coalesceFindRequests @type {boolean} */ - coalesceFindRequests = false; + coalesceFindRequests: boolean = false; findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } }); } - pathForType(modelName) { + pathForType(modelName): string { let dasherized = dasherize(modelName); return pluralize(dasherized); } diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 6265841cecc..f662e4d3755 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -29,9 +29,9 @@ import { addSymbol, symbol } from '@ember-data/store/-private'; import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; -type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; +type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict; type FastBoot = import('./-private/fastboot-interface').FastBoot; -type Payload = Dict | string | undefined; +type Payload = Dict | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; @@ -43,17 +43,21 @@ type QueryState = { }; type FetchRequestData = { - url?: number; + url?: string; method?: string; - string: any; + [key: string]: any; }; -type RequestData = JQueryAjaxSettings | FetchRequestData; +interface JQueryFetchData extends JQueryAjaxSettings { + errorThrown: Dict; +} + +type RequestData = JQueryFetchData | FetchRequestData; type ResponseData = { status: number; textStatus: string; - headers: {}; + headers: Dict; errorThrown?: any; }; @@ -395,7 +399,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} obj @return {Object} */ - sortQueryParams(obj) { + sortQueryParams(obj): Dict { let keys = Object.keys(obj); let len = keys.length; if (len < 2) { @@ -457,7 +461,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @property coalesceFindRequests @type {boolean} */ - coalesceFindRequests = false; + coalesceFindRequests: boolean = false; /** Endpoint paths can be prefixed with a `namespace` by setting the namespace @@ -938,7 +942,12 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} requestData - the original request information @return {Object | AdapterError} response */ - handleResponse(status: number, headers, payload: Payload, requestData: RequestData) { + handleResponse( + status: number, + headers: Dict, + payload: Payload, + requestData: RequestData + ): Payload | AdapterError { if (this.isSuccess(status, headers, payload)) { return payload; } else if (this.isInvalid(status, headers, payload)) { @@ -977,7 +986,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isSuccess(status, headers, payload) { + isSuccess(status: number, _headers: Dict, _payload: Payload): boolean { return (status >= 200 && status < 300) || status === 304; } @@ -992,7 +1001,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isInvalid(status, headers, payload) { + isInvalid(status: number, _headers: Dict, _payload: Payload): boolean { return status === 422; } @@ -1023,41 +1032,45 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { ajax(url: string, type: string, options: JQueryAjaxSettings = {}): Promise { let adapter = this; - let requestData: RequestData = { - url: url, - method: type, - }; let hash = adapter.ajaxOptions(url, type, options); if (this.useFetch) { + let requestData: FetchRequestData = { + url: url, + method: type, + }; let _response; - return this._fetchRequest(hash) - .then(response => { + return (this._fetchRequest(hash) as Promise) + .then((response: Response) => { _response = response; - return determineBodyPromise(response, requestData as JQueryAjaxSettings); + return determineBodyPromise(response, requestData); }) .then((payload: Payload) => { if (_response.ok && !(payload instanceof Error)) { - return fetchSuccessHandler(adapter, payload, _response, requestData as FetchRequestData); + return fetchSuccessHandler(adapter, payload, _response, requestData); } else { - throw fetchErrorHandler(adapter, payload, _response, null, requestData as FetchRequestData); + throw fetchErrorHandler(adapter, payload, _response, null, requestData); } }); - } - - return new Promise(function(resolve, reject) { - hash.success = function(payload, textStatus, jqXHR) { - let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); - run.join(null, resolve, response); + } else { + let requestData: JQueryAjaxSettings = { + url: url, + method: type, }; + return new Promise(function(resolve, reject) { + hash.success = function(payload, textStatus, jqXHR) { + let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); + run.join(null, resolve, response); + }; - hash.error = function(jqXHR, textStatus, errorThrown) { - let error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData); - run.join(null, reject, error); - }; + hash.error = function(jqXHR, textStatus, errorThrown) { + let error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData); + run.join(null, reject, error); + }; - adapter._ajax(hash); - }, 'DS: RESTAdapter#ajax ' + type + ' to ' + url); + adapter._ajax(hash); + }, 'DS: RESTAdapter#ajax ' + type + ' to ' + url); + } } /** @@ -1065,11 +1078,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options): void { + _ajaxRequest(options: ConfidentDict): void { typeof jQuery !== 'undefined' && jQuery.ajax(options); } - _fetchRequest(options) { + _fetchRequest(options): Promise | Error { let fetchFunction = fetch(); if (fetchFunction) { @@ -1081,7 +1094,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options): void { + _ajax(options: ConfidentDict): void { if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { @@ -1099,7 +1112,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: ConfidentDict) { + ajaxOptions(url: string, method: string, options: Dict): ConfidentDict { options = assign( { url, @@ -1168,8 +1181,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {String} responseText @return {Object} */ - parseErrorResponse(responseText) { - let json = responseText; + parseErrorResponse(responseText: string): Dict | string { + let json: string | Dict = responseText; try { json = JSON.parse(responseText); @@ -1177,7 +1190,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { // ignored } - return json; + return json as Dict; } /** @@ -1188,7 +1201,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Array} errors payload */ - normalizeErrorResponse(status, headers, payload) { + normalizeErrorResponse(status: number, _headers: Dict, payload: Payload): Dict[] { if (payload && typeof payload === 'object' && payload.errors) { return payload.errors; } else { @@ -1256,7 +1269,12 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } -function ajaxSuccess(adapter, payload: Payload, requestData: RequestData, responseData: ResponseData) { +function ajaxSuccess( + adapter: RESTAdapter, + payload: Payload, + requestData: RequestData, + responseData: ResponseData +): Promise { let response; try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); @@ -1271,7 +1289,12 @@ function ajaxSuccess(adapter, payload: Payload, requestData: RequestData, respon } } -function ajaxError(adapter, payload: Payload, requestData: RequestData, responseData: ResponseData) { +function ajaxError( + adapter: RESTAdapter, + payload: Payload, + requestData: RequestData, + responseData: ResponseData +): Error | TimeoutError | AbortError | ConfidentDict { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1297,7 +1320,7 @@ function ajaxError(adapter, payload: Payload, requestData: RequestData, response } // Adapter abort error to include any relevent info, e.g. request/response: -function handleAbort(requestData, responseData): AbortError { +function handleAbort(requestData: RequestData, responseData: ResponseData): AbortError { let { method, url, errorThrown } = requestData; let { status } = responseData; let msg = `Request failed: ${method} ${url} ${errorThrown || ''}`; @@ -1306,7 +1329,7 @@ function handleAbort(requestData, responseData): AbortError { } //From http://stackoverflow.com/questions/280634/endswith-in-javascript -function endsWith(string, suffix): boolean { +function endsWith(string: string, suffix: string): boolean { if (typeof String.prototype.endsWith !== 'function') { return string.indexOf(suffix, string.length - suffix.length) !== -1; } else { @@ -1314,12 +1337,23 @@ function endsWith(string, suffix): boolean { } } -function fetchSuccessHandler(adapter, payload: Payload, response: Response, requestData: FetchRequestData) { +function fetchSuccessHandler( + adapter: RESTAdapter, + payload: Payload, + response: Response, + requestData: FetchRequestData +): Promise { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); } -function fetchErrorHandler(adapter, payload: Payload, response: Response, errorThrown, requestData: FetchRequestData) { +function fetchErrorHandler( + adapter: RESTAdapter, + payload: Payload, + response: Response, + errorThrown, + requestData: FetchRequestData +) { let responseData = fetchResponseData(response); if (responseData.status === 200 && payload instanceof Error) { @@ -1327,17 +1361,27 @@ function fetchErrorHandler(adapter, payload: Payload, response: Response, errorT payload = responseData.errorThrown.payload; } else { responseData.errorThrown = errorThrown; - payload = adapter.parseErrorResponse(payload); + payload = adapter.parseErrorResponse(payload as string); } return ajaxError(adapter, payload, requestData, responseData); } -function ajaxSuccessHandler(adapter, payload, jqXHR, requestData) { +function ajaxSuccessHandler( + adapter: RESTAdapter, + payload: Payload, + jqXHR: JQuery.jqXHR, + requestData: JQueryAjaxSettings +): Promise { let responseData = ajaxResponseData(jqXHR); return ajaxSuccess(adapter, payload, requestData, responseData); } -function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) { +function ajaxErrorHandler( + adapter: RESTAdapter, + jqXHR: JQuery.jqXHR, + errorThrown: Dict, + requestData: JQueryAjaxSettings +) { let responseData = ajaxResponseData(jqXHR); responseData.errorThrown = errorThrown; let payload = adapter.parseErrorResponse(jqXHR.responseText); @@ -1361,7 +1405,7 @@ function fetchResponseData(response: Response): ResponseData { }; } -function ajaxResponseData(jqXHR): ResponseData { +function ajaxResponseData(jqXHR: JQuery.jqXHR): ResponseData { return { status: jqXHR.status, textStatus: jqXHR.statusText, @@ -1369,7 +1413,7 @@ function ajaxResponseData(jqXHR): ResponseData { }; } -function headersToObject(headers) { +function headersToObject(headers: Headers): Dict { let headersObject = {}; if (headers) { @@ -1385,7 +1429,7 @@ function headersToObject(headers) { * @param {Adapter} adapter * @returns {Object} */ -export function fetchOptions(options, adapter) { +export function fetchOptions(options: ConfidentDict, adapter: RESTAdapter): ConfidentDict { options.credentials = options.credentials || 'same-origin'; if (options.data) { @@ -1440,7 +1484,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options): void { + RESTAdapter.prototype._najaxRequest = function(options: ConfidentDict): void { if (typeof najax !== 'undefined') { najax(options); } else { From 0c313c372d81e2f714738fe5531c9658e04e8598 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 9 Dec 2020 21:53:37 -0800 Subject: [PATCH 37/56] typo fix --- packages/model/addon/-private/errors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/model/addon/-private/errors.js b/packages/model/addon/-private/errors.js index 5185962ed76..61d59c9b148 100644 --- a/packages/model/addon/-private/errors.js +++ b/packages/model/addon/-private/errors.js @@ -222,7 +222,7 @@ export default ArrayProxy.extend(DeprecatedEvented, { // add a single error errors.add('username', 'This field is required'); - errors.errorsFor('password'); + errors.errorsFor('username'); // => // [ // { attribute: 'username', message: 'This field is required' }, From db04a0bc3eeadbc673168d420c55889220c7517d Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Thu, 10 Dec 2020 12:36:15 -0800 Subject: [PATCH 38/56] alias rsvp promise as RSVPPromise --- packages/adapter/addon/index.ts | 16 ++++++++-------- packages/adapter/addon/json-api.ts | 4 ++-- packages/adapter/addon/rest.ts | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/adapter/addon/index.ts b/packages/adapter/addon/index.ts index e9986944941..b24c34a3804 100644 --- a/packages/adapter/addon/index.ts +++ b/packages/adapter/addon/index.ts @@ -1,7 +1,7 @@ import EmberObject from '@ember/object'; import { DEBUG } from '@glimmer/env'; -import { Promise } from 'rsvp'; +import { Promise as RSVPPromise } from 'rsvp'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type MinimumAdapterInterface = import('@ember-data/store/-private/ts-interfaces/minimum-adapter-interface').default; @@ -128,7 +128,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a findRecord override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -166,7 +166,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a findAll override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -205,7 +205,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a query override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -250,7 +250,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a queryRecord override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -359,7 +359,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a createRecord override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -417,7 +417,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a updateRecord override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** @@ -467,7 +467,7 @@ export default class Adapter extends EmberObject implements MinimumAdapterInterf throw new Error('You subclassed the Adapter class but missing a deleteRecord override'); } - return Promise.resolve(); + return RSVPPromise.resolve(); } /** diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index e52b214e062..8219255429a 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -227,7 +227,7 @@ class JSONAPIAdapter extends RESTAdapter { */ coalesceFindRequests: boolean = false; - findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]) { + findMany(store: Store, type: ShimModelClass, ids: string[], snapshots: Snapshot[]): Promise { let url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } }); } @@ -237,7 +237,7 @@ class JSONAPIAdapter extends RESTAdapter { return pluralize(dasherized); } - updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot) { + updateRecord(store: Store, type: ShimModelClass, snapshot: Snapshot): Promise { const data = serializeIntoHash(store, type, snapshot); let url = this.buildURL(type.modelName, snapshot.id, snapshot, 'updateRecord'); diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index f662e4d3755..6b18ebb4052 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -10,7 +10,7 @@ import { run } from '@ember/runloop'; import { DEBUG } from '@glimmer/env'; import { has } from 'require'; -import { Promise } from 'rsvp'; +import { Promise as RSVPPromise } from 'rsvp'; import Adapter, { BuildURLMixin } from '@ember-data/adapter'; import AdapterError, { @@ -1057,7 +1057,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { url: url, method: type, }; - return new Promise(function(resolve, reject) { + return new RSVPPromise(function(resolve, reject) { hash.success = function(payload, textStatus, jqXHR) { let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); run.join(null, resolve, response); @@ -1279,11 +1279,11 @@ function ajaxSuccess( try { response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData); } catch (error) { - return Promise.reject(error); + return RSVPPromise.reject(error); } if (response && response.isAdapterError) { - return Promise.reject(response); + return RSVPPromise.reject(response); } else { return response; } From dec529677171463078582b6f4b7dd832fe4e585a Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Thu, 10 Dec 2020 21:12:13 -0800 Subject: [PATCH 39/56] ConfidentDict => Dict --- packages/adapter/addon/json-api.ts | 3 +-- packages/adapter/addon/rest.ts | 35 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index 8219255429a..af985284cb5 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -9,7 +9,6 @@ import { serializeIntoHash } from './-private'; import RESTAdapter from './rest'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; -type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Store = import('@ember-data/store/-private/system/core-store').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; @@ -162,7 +161,7 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url: string, type: string, options: Dict = {}): ConfidentDict { + ajaxOptions(url: string, type: string, options: Dict = {}): Dict { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 6b18ebb4052..8a892cf7423 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -29,7 +29,6 @@ import { addSymbol, symbol } from '@ember-data/store/-private'; import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, serializeQueryParams } from './-private'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; -type ConfidentDict = import('@ember-data/store/-private/ts-interfaces/utils').ConfidentDict; type FastBoot = import('./-private/fastboot-interface').FastBoot; type Payload = Dict | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; @@ -62,7 +61,7 @@ type ResponseData = { }; declare const najax: Function | undefined; -declare const jQuery: ConfidentDict | undefined; +declare const jQuery: Dict | undefined; const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; @@ -522,7 +521,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @property headers @type {Object} */ - declare headers: unknown; + declare headers: Dict | undefined; /** Called by the store in order to fetch the JSON for a given @@ -944,7 +943,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { */ handleResponse( status: number, - headers: Dict, + headers: Dict, payload: Payload, requestData: RequestData ): Payload | AdapterError { @@ -986,7 +985,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isSuccess(status: number, _headers: Dict, _payload: Payload): boolean { + isSuccess(status: number, _headers: Dict, _payload: Payload): boolean { return (status >= 200 && status < 300) || status === 304; } @@ -1001,7 +1000,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Boolean} */ - isInvalid(status: number, _headers: Dict, _payload: Payload): boolean { + isInvalid(status: number, _headers: Dict, _payload: Payload): boolean { return status === 422; } @@ -1078,7 +1077,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options: ConfidentDict): void { + _ajaxRequest(options: Dict): void { typeof jQuery !== 'undefined' && jQuery.ajax(options); } @@ -1094,7 +1093,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options: ConfidentDict): void { + _ajax(options: Dict): void { if (this.useFetch) { this._fetchRequest(options); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { @@ -1112,7 +1111,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: Dict): ConfidentDict { + ajaxOptions(url: string, method: string, options: JQueryAjaxSettings): Dict { options = assign( { url, @@ -1123,7 +1122,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { ); if (this.headers !== undefined) { - options.headers = assign({}, this.headers as Dict, options.headers); + options.headers = assign({}, this.headers, options.headers); } else if (!options.headers) { options.headers = {}; } @@ -1131,7 +1130,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { let contentType = options.contentType || this._defaultContentType; if (this.useFetch) { - if (options.data && options.type !== 'GET') { + if (options.data && options.type !== 'GET' && options.headers) { if (!options.headers['Content-Type'] && !options.headers['content-type']) { options.headers['content-type'] = contentType; } @@ -1146,12 +1145,14 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { options = ajaxOptions(options, this); } - options.url = this._ajaxURL(options.url); + if (options.url) { + options.url = this._ajaxURL(options.url); + } return options; } - _ajaxURL(url: string): string | void { + _ajaxURL(url: string): string { if (this.fastboot?.isFastBoot) { let httpRegex = /^https?:\/\//; let protocolRelativeRegex = /^\/\//; @@ -1294,7 +1295,7 @@ function ajaxError( payload: Payload, requestData: RequestData, responseData: ResponseData -): Error | TimeoutError | AbortError | ConfidentDict { +): Error | TimeoutError | AbortError | Dict { let error; if (responseData.errorThrown instanceof Error && payload !== '') { @@ -1429,7 +1430,7 @@ function headersToObject(headers: Headers): Dict { * @param {Adapter} adapter * @returns {Object} */ -export function fetchOptions(options: ConfidentDict, adapter: RESTAdapter): ConfidentDict { +export function fetchOptions(options: Dict, adapter: RESTAdapter): Dict { options.credentials = options.credentials || 'same-origin'; if (options.data) { @@ -1463,7 +1464,7 @@ export function fetchOptions(options: ConfidentDict, adapter: RESTAdapter): return options; } -function ajaxOptions(options: ConfidentDict, adapter): ConfidentDict { +function ajaxOptions(options: JQueryAjaxSettings, adapter: RESTAdapter): JQueryAjaxSettings { options.dataType = 'json'; options.context = adapter; @@ -1484,7 +1485,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options: ConfidentDict): void { + RESTAdapter.prototype._najaxRequest = function(options: Dict): void { if (typeof najax !== 'undefined') { najax(options); } else { From 9ea712e5c103638bdf96c1eeb5c21042e4674973 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Thu, 10 Dec 2020 21:33:31 -0800 Subject: [PATCH 40/56] Add FetchRequestInit interface --- packages/adapter/addon/rest.ts | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 8a892cf7423..19a2791dc6c 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -47,6 +47,13 @@ type FetchRequestData = { [key: string]: any; }; +interface FetchRequestInit extends RequestInit { + contentType?: string; + data?: unknown; + type?: string; + url?: string; +} + interface JQueryFetchData extends JQueryAjaxSettings { errorThrown: Dict; } @@ -1028,7 +1035,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url: string, type: string, options: JQueryAjaxSettings = {}): Promise { + ajax(url: string, type: string, options: JQueryAjaxSettings | FetchRequestInit = {}): Promise { let adapter = this; let hash = adapter.ajaxOptions(url, type, options); @@ -1081,11 +1088,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { typeof jQuery !== 'undefined' && jQuery.ajax(options); } - _fetchRequest(options): Promise | Error { + _fetchRequest(options): Promise { let fetchFunction = fetch(); if (fetchFunction) { - return fetchFunction(options.url, options) as Promise; + return fetchFunction(options.url, options); } else { throw new Error( 'cannot find the `fetch` module or the `fetch` global. Did you mean to install the `ember-fetch` addon?' @@ -1111,7 +1118,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: JQueryAjaxSettings): Dict { + ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | FetchRequestInit): Dict { options = assign( { url, @@ -1142,7 +1149,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if (options.data && options.type !== 'GET') { options = assign(options, { contentType }); } - options = ajaxOptions(options, this); + options = ajaxOptions(options as JQueryAjaxSettings, this); } if (options.url) { @@ -1232,7 +1239,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { let shortenedPayload; let payloadContentType = headers['content-type'] || 'Empty Content-Type'; - if (payloadContentType === 'text/html' && (payload as string).length > 250) { + if (payloadContentType === 'text/html' && typeof payload === 'string' && payload.length > 250) { shortenedPayload = '[Omitted Lengthy HTML]'; } else { shortenedPayload = payload; @@ -1473,7 +1480,15 @@ function ajaxOptions(options: JQueryAjaxSettings, adapter: RESTAdapter): JQueryA } options.beforeSend = function(xhr) { - Object.keys(options.headers).forEach(key => xhr.setRequestHeader(key, options.headers[key])); + if (options.headers) { + Object.keys(options.headers).forEach(key => { + let headerValue = options.headers && options.headers[key]; + const isString = (value: unknown): value is string => typeof value === 'string'; + if (isString(headerValue)) { + xhr.setRequestHeader(key, headerValue); + } + }); + } }; return options; From 7ca81e38cc91a9621967aa43d4c1c315f320ddc8 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 11 Dec 2020 06:59:02 -0800 Subject: [PATCH 41/56] no cast for Promise. error returns back to calleer --- packages/adapter/addon/rest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 19a2791dc6c..4faa8c1f6e5 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1046,7 +1046,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { method: type, }; let _response; - return (this._fetchRequest(hash) as Promise) + return this._fetchRequest(hash) .then((response: Response) => { _response = response; return determineBodyPromise(response, requestData); From 76315d5e0b5247760cf761efa2642ebedeaa894c Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 11 Dec 2020 07:24:23 -0800 Subject: [PATCH 42/56] remove cast for payload and just add an if check. we do not want to JSON.parse undefined or emtpy string --- packages/adapter/addon/rest.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 4faa8c1f6e5..c6da9869ad7 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1190,7 +1190,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @return {Object} */ parseErrorResponse(responseText: string): Dict | string { - let json: string | Dict = responseText; + let json: string = responseText; try { json = JSON.parse(responseText); @@ -1198,7 +1198,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { // ignored } - return json as Dict; + return json; } /** @@ -1369,7 +1369,9 @@ function fetchErrorHandler( payload = responseData.errorThrown.payload; } else { responseData.errorThrown = errorThrown; - payload = adapter.parseErrorResponse(payload as string); + if (typeof payload === 'string') { + payload = adapter.parseErrorResponse(payload); + } } return ajaxError(adapter, payload, requestData, responseData); } From 4028ba7d95143a19c1e630f73739cf3223e763a9 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Fri, 11 Dec 2020 15:26:40 -0800 Subject: [PATCH 43/56] Clearer typing delineation between fetch and ajax paths --- packages/adapter/addon/rest.ts | 85 ++++++++++++++++------------------ 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index c6da9869ad7..f42946210c8 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -41,24 +41,26 @@ type QueryState = { since?: unknown; }; -type FetchRequestData = { - url?: string; - method?: string; - [key: string]: any; -}; - interface FetchRequestInit extends RequestInit { + url: string; + method: string; + type: string; contentType?: string; - data?: unknown; - type?: string; - url?: string; + body?: any; + data?: any; } -interface JQueryFetchData extends JQueryAjaxSettings { - errorThrown: Dict; +interface JQueryRequestInit extends JQueryAjaxSettings { + url: string; + method: string; + type: string; } -type RequestData = JQueryFetchData | FetchRequestData; +type RequestData = { + url: string; + method: string; + [key: string]: any; +}; type ResponseData = { status: number; @@ -1035,16 +1037,17 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Promise} promise */ - ajax(url: string, type: string, options: JQueryAjaxSettings | FetchRequestInit = {}): Promise { + ajax(url: string, type: string, options: JQueryAjaxSettings | RequestInit = {}): Promise { let adapter = this; let hash = adapter.ajaxOptions(url, type, options); + let requestData: RequestData = { + url: url, + method: type, + }; + if (this.useFetch) { - let requestData: FetchRequestData = { - url: url, - method: type, - }; let _response; return this._fetchRequest(hash) .then((response: Response) => { @@ -1059,10 +1062,6 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } }); } else { - let requestData: JQueryAjaxSettings = { - url: url, - method: type, - }; return new RSVPPromise(function(resolve, reject) { hash.success = function(payload, textStatus, jqXHR) { let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); @@ -1118,8 +1117,8 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | FetchRequestInit): Dict { - options = assign( + ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | RequestInit): Dict { + let reqOptions: JQueryRequestInit | FetchRequestInit = assign( { url, method, @@ -1129,34 +1128,32 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { ); if (this.headers !== undefined) { - options.headers = assign({}, this.headers, options.headers); + reqOptions.headers = assign({}, this.headers, reqOptions.headers); } else if (!options.headers) { - options.headers = {}; + reqOptions.headers = {}; } - let contentType = options.contentType || this._defaultContentType; + let contentType = reqOptions.contentType || this._defaultContentType; if (this.useFetch) { - if (options.data && options.type !== 'GET' && options.headers) { - if (!options.headers['Content-Type'] && !options.headers['content-type']) { - options.headers['content-type'] = contentType; + if (reqOptions.data && reqOptions.type !== 'GET' && reqOptions.headers) { + if (!reqOptions.headers['Content-Type'] && !reqOptions.headers['content-type']) { + reqOptions.headers['content-type'] = contentType; } } - options = fetchOptions(options, this); + reqOptions = fetchOptions(reqOptions as FetchRequestInit, this); } else { // GET requests without a body should not have a content-type header // and may be unexpected by a server - if (options.data && options.type !== 'GET') { - options = assign(options, { contentType }); + if (reqOptions.data && reqOptions.type !== 'GET') { + reqOptions = assign(reqOptions, { contentType }); } - options = ajaxOptions(options as JQueryAjaxSettings, this); + reqOptions = ajaxOptions(reqOptions as JQueryRequestInit, this); } - if (options.url) { - options.url = this._ajaxURL(options.url); - } + reqOptions.url = this._ajaxURL(reqOptions.url); - return options; + return reqOptions; } _ajaxURL(url: string): string { @@ -1349,7 +1346,7 @@ function fetchSuccessHandler( adapter: RESTAdapter, payload: Payload, response: Response, - requestData: FetchRequestData + requestData: RequestData ): Promise { let responseData = fetchResponseData(response); return ajaxSuccess(adapter, payload, requestData, responseData); @@ -1360,7 +1357,7 @@ function fetchErrorHandler( payload: Payload, response: Response, errorThrown, - requestData: FetchRequestData + requestData: RequestData ) { let responseData = fetchResponseData(response); @@ -1380,7 +1377,7 @@ function ajaxSuccessHandler( adapter: RESTAdapter, payload: Payload, jqXHR: JQuery.jqXHR, - requestData: JQueryAjaxSettings + requestData: RequestData ): Promise { let responseData = ajaxResponseData(jqXHR); return ajaxSuccess(adapter, payload, requestData, responseData); @@ -1390,7 +1387,7 @@ function ajaxErrorHandler( adapter: RESTAdapter, jqXHR: JQuery.jqXHR, errorThrown: Dict, - requestData: JQueryAjaxSettings + requestData: RequestData ) { let responseData = ajaxResponseData(jqXHR); responseData.errorThrown = errorThrown; @@ -1439,14 +1436,14 @@ function headersToObject(headers: Headers): Dict { * @param {Adapter} adapter * @returns {Object} */ -export function fetchOptions(options: Dict, adapter: RESTAdapter): Dict { +export function fetchOptions(options: FetchRequestInit, adapter: RESTAdapter): FetchRequestInit { options.credentials = 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) { + if (Object.keys(options.data).length && options.url) { // 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)}`; @@ -1473,7 +1470,7 @@ export function fetchOptions(options: Dict, adapter: RESTAdapter): Dict Date: Wed, 20 Jan 2021 10:16:41 -0800 Subject: [PATCH 44/56] Cleanup of payload --- packages/adapter/addon/rest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index f42946210c8..24269b91e0e 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -30,7 +30,7 @@ import { determineBodyPromise, fetch, parseResponseHeaders, serializeIntoHash, s type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type FastBoot = import('./-private/fastboot-interface').FastBoot; -type Payload = Dict | string | undefined; +type Payload = Dict | string | undefined; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; type Snapshot = import('@ember-data/store/-private/system/snapshot').default; type SnapshotRecordArray = import('@ember-data/store/-private/system/snapshot-record-array').default; @@ -959,7 +959,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if (this.isSuccess(status, headers, payload)) { return payload; } else if (this.isInvalid(status, headers, payload)) { - return new InvalidError((payload as Dict).errors); + return new InvalidError(typeof payload === 'object' ? payload.errors: undefined); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -1207,7 +1207,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @return {Array} errors payload */ normalizeErrorResponse(status: number, _headers: Dict, payload: Payload): Dict[] { - if (payload && typeof payload === 'object' && payload.errors) { + if (payload && typeof payload === 'object' && payload.errors instanceof Array) { return payload.errors; } else { return [ From c6e151590d48412e67e6e27681c0a51e740f3eff Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Wed, 20 Jan 2021 10:30:46 -0800 Subject: [PATCH 45/56] request types but with cache problem --- packages/adapter/addon/rest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 24269b91e0e..a90868b3ba9 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1141,14 +1141,14 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { reqOptions.headers['content-type'] = contentType; } } - reqOptions = fetchOptions(reqOptions as FetchRequestInit, this); + reqOptions = fetchOptions(reqOptions, this); } else { // GET requests without a body should not have a content-type header // and may be unexpected by a server if (reqOptions.data && reqOptions.type !== 'GET') { reqOptions = assign(reqOptions, { contentType }); } - reqOptions = ajaxOptions(reqOptions as JQueryRequestInit, this); + reqOptions = ajaxOptions(reqOptions, this); } reqOptions.url = this._ajaxURL(reqOptions.url); @@ -1436,7 +1436,7 @@ function headersToObject(headers: Headers): Dict { * @param {Adapter} adapter * @returns {Object} */ -export function fetchOptions(options: FetchRequestInit, adapter: RESTAdapter): FetchRequestInit { +export function fetchOptions(options: JQueryRequestInit & Partial, adapter: RESTAdapter): FetchRequestInit { options.credentials = options.credentials || 'same-origin'; if (options.data) { From d6c1496865aa82cfac759fa63b295e87340f23bc Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Wed, 20 Jan 2021 10:33:54 -0800 Subject: [PATCH 46/56] cleanup fetchRequest by setting it to any --- packages/adapter/addon/rest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index a90868b3ba9..074c2e1a17a 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -45,9 +45,11 @@ interface FetchRequestInit extends RequestInit { url: string; method: string; type: string; - contentType?: string; + contentType?: any; body?: any; data?: any; + cache?: any; + headers?: any; } interface JQueryRequestInit extends JQueryAjaxSettings { From 4036fb7f86f65245cb06e4f1b33ebc57eebed506 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 20 Jan 2021 16:07:38 -0600 Subject: [PATCH 47/56] Fix lint --- packages/adapter/addon/rest.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 074c2e1a17a..8a4ea5b8332 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -961,7 +961,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if (this.isSuccess(status, headers, payload)) { return payload; } else if (this.isInvalid(status, headers, payload)) { - return new InvalidError(typeof payload === 'object' ? payload.errors: undefined); + return new InvalidError(typeof payload === 'object' ? payload.errors : undefined); } let errors = this.normalizeErrorResponse(status, headers, payload); @@ -1438,7 +1438,10 @@ function headersToObject(headers: Headers): Dict { * @param {Adapter} adapter * @returns {Object} */ -export function fetchOptions(options: JQueryRequestInit & Partial, adapter: RESTAdapter): FetchRequestInit { +export function fetchOptions( + options: JQueryRequestInit & Partial, + adapter: RESTAdapter +): FetchRequestInit { options.credentials = options.credentials || 'same-origin'; if (options.data) { From 7d8fbc7aba16e54a6ecf207cd89087470df07246 Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Wed, 20 Jan 2021 23:01:56 -0800 Subject: [PATCH 48/56] cleanup anys in build-url-mixin --- packages/adapter/addon/-private/build-url-mixin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/-private/build-url-mixin.ts b/packages/adapter/addon/-private/build-url-mixin.ts index 0126739e2c3..04f645b586f 100644 --- a/packages/adapter/addon/-private/build-url-mixin.ts +++ b/packages/adapter/addon/-private/build-url-mixin.ts @@ -205,7 +205,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQuery(query: Dict, modelName: string): string { + urlForQuery(query: Dict, modelName: string): string { return this._buildURL(modelName); }, @@ -230,7 +230,7 @@ export default Mixin.create({ @param {String} modelName @return {String} url */ - urlForQueryRecord(query: Dict, modelName: string): string { + urlForQueryRecord(query: Dict, modelName: string): string { return this._buildURL(modelName); }, From ecbc13a4033f259907181f27689a69016b98be9a Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Wed, 20 Jan 2021 23:18:56 -0800 Subject: [PATCH 49/56] ajax options temp cleanup --- packages/adapter/addon/json-api.ts | 4 ++-- packages/adapter/addon/rest.ts | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index af985284cb5..6c80822a61b 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -6,7 +6,7 @@ import { dasherize } from '@ember/string'; import { pluralize } from 'ember-inflector'; import { serializeIntoHash } from './-private'; -import RESTAdapter from './rest'; +import RESTAdapter, {FetchRequestInit, JQueryRequestInit} from './rest'; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; @@ -161,7 +161,7 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url: string, type: string, options: Dict = {}): Dict { + ajaxOptions(url: string, type: string, options: JQueryAjaxSettings | RequestInit = {}): JQueryRequestInit | FetchRequestInit { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 8a4ea5b8332..e7513e6b4ac 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -41,7 +41,7 @@ type QueryState = { since?: unknown; }; -interface FetchRequestInit extends RequestInit { +export interface FetchRequestInit extends RequestInit { url: string; method: string; type: string; @@ -52,7 +52,7 @@ interface FetchRequestInit extends RequestInit { headers?: any; } -interface JQueryRequestInit extends JQueryAjaxSettings { +export interface JQueryRequestInit extends JQueryAjaxSettings { url: string; method: string; type: string; @@ -1065,12 +1065,12 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { }); } else { return new RSVPPromise(function(resolve, reject) { - hash.success = function(payload, textStatus, jqXHR) { + (hash as JQueryAjaxSettings).success = function(payload, textStatus, jqXHR) { let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); run.join(null, resolve, response); }; - hash.error = function(jqXHR, textStatus, errorThrown) { + (hash as JQueryAjaxSettings).error = function(jqXHR, textStatus, errorThrown) { let error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData); run.join(null, reject, error); }; @@ -1085,11 +1085,12 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options: Dict): void { + _ajaxRequest(options: JQueryAjaxSettings): void { + // TODO add assertion that jquery is there rather then equality check typeof jQuery !== 'undefined' && jQuery.ajax(options); } - _fetchRequest(options): Promise { + _fetchRequest(options: FetchRequestInit): Promise { let fetchFunction = fetch(); if (fetchFunction) { @@ -1101,13 +1102,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options: Dict): void { + _ajax(options: FetchRequestInit | JQueryAjaxSettings): void { if (this.useFetch) { - this._fetchRequest(options); + this._fetchRequest(options as FetchRequestInit); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { this._najaxRequest(options); } else { - this._ajaxRequest(options); + this._ajaxRequest(options as JQueryAjaxSettings); } } @@ -1119,7 +1120,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | RequestInit): Dict { + ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | RequestInit): JQueryRequestInit | FetchRequestInit { let reqOptions: JQueryRequestInit | FetchRequestInit = assign( { url, @@ -1388,7 +1389,7 @@ function ajaxSuccessHandler( function ajaxErrorHandler( adapter: RESTAdapter, jqXHR: JQuery.jqXHR, - errorThrown: Dict, + errorThrown: string, requestData: RequestData ) { let responseData = ajaxResponseData(jqXHR); From ad3b199290bfe7a0d11279932d2f5a70ce266002 Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Thu, 28 Jan 2021 14:51:50 -0800 Subject: [PATCH 50/56] cleanup ajax types --- packages/adapter/addon/rest.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index e7513e6b4ac..14ecfcda3a5 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1042,8 +1042,6 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { ajax(url: string, type: string, options: JQueryAjaxSettings | RequestInit = {}): Promise { let adapter = this; - let hash = adapter.ajaxOptions(url, type, options); - let requestData: RequestData = { url: url, method: type, @@ -1051,6 +1049,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { if (this.useFetch) { let _response; + let hash: FetchRequestInit = adapter.ajaxOptions(url, type, options); return this._fetchRequest(hash) .then((response: Response) => { _response = response; @@ -1064,13 +1063,15 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } }); } else { + let hash: JQueryRequestInit = adapter.ajaxOptions(url, type, options); + return new RSVPPromise(function(resolve, reject) { - (hash as JQueryAjaxSettings).success = function(payload, textStatus, jqXHR) { + hash.success = function(payload, textStatus, jqXHR) { let response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData); run.join(null, resolve, response); }; - (hash as JQueryAjaxSettings).error = function(jqXHR, textStatus, errorThrown) { + hash.error = function(jqXHR, textStatus, errorThrown) { let error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData); run.join(null, reject, error); }; From 1c61991b209999edc4f16c16a7f8b9176fc08c23 Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Thu, 28 Jan 2021 15:00:56 -0800 Subject: [PATCH 51/56] any clenaup --- packages/adapter/addon/rest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 14ecfcda3a5..caf73ea46a3 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1210,7 +1210,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} payload @return {Array} errors payload */ - normalizeErrorResponse(status: number, _headers: Dict, payload: Payload): Dict[] { + normalizeErrorResponse(status: number, _headers: Dict, payload: Payload): Dict[] { if (payload && typeof payload === 'object' && payload.errors instanceof Array) { return payload.errors; } else { @@ -1506,7 +1506,7 @@ if (DEPRECATE_NAJAX) { @private @param {Object} options jQuery ajax options to be used for the najax request */ - RESTAdapter.prototype._najaxRequest = function(options: Dict): void { + RESTAdapter.prototype._najaxRequest = function(options: JQueryAjaxSettings): void { if (typeof najax !== 'undefined') { najax(options); } else { From 3343cefb91a93ac580b58df34656302f864e9750 Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Thu, 28 Jan 2021 15:07:44 -0800 Subject: [PATCH 52/56] jquery type --- packages/adapter/addon/rest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index caf73ea46a3..2ba0448768e 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -72,7 +72,7 @@ type ResponseData = { }; declare const najax: Function | undefined; -declare const jQuery: Dict | undefined; +declare const jQuery: JQueryStatic | undefined; const UseFetch = symbol('useFetch'); const hasJQuery = typeof jQuery !== 'undefined'; From 64f6959f45e54c5287c65832175050a2e6d53e5a Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Thu, 28 Jan 2021 15:11:58 -0800 Subject: [PATCH 53/56] lint --- packages/adapter/addon/json-api.ts | 11 +++++++++-- packages/adapter/addon/rest.ts | 13 ++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/adapter/addon/json-api.ts b/packages/adapter/addon/json-api.ts index 6c80822a61b..87a6e7b1a1e 100644 --- a/packages/adapter/addon/json-api.ts +++ b/packages/adapter/addon/json-api.ts @@ -6,7 +6,10 @@ import { dasherize } from '@ember/string'; import { pluralize } from 'ember-inflector'; import { serializeIntoHash } from './-private'; -import RESTAdapter, {FetchRequestInit, JQueryRequestInit} from './rest'; +import RESTAdapter from './rest'; + +type FetchRequestInit = import('./rest').FetchRequestInit; +type JQueryRequestInit = import('./rest').JQueryRequestInit; type Dict = import('@ember-data/store/-private/ts-interfaces/utils').Dict; type ShimModelClass = import('@ember-data/store/-private/system/model/shim-model-class').default; @@ -161,7 +164,11 @@ class JSONAPIAdapter extends RESTAdapter { @param {Object} options @return {Object} */ - ajaxOptions(url: string, type: string, options: JQueryAjaxSettings | RequestInit = {}): JQueryRequestInit | FetchRequestInit { + ajaxOptions( + url: string, + type: string, + options: JQueryAjaxSettings | RequestInit = {} + ): JQueryRequestInit | FetchRequestInit { let hash = super.ajaxOptions(url, type, options); hash.headers['Accept'] = hash.headers['Accept'] || 'application/vnd.api+json'; diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 2ba0448768e..e0193133506 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1121,7 +1121,11 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @param {Object} options @return {Object} */ - ajaxOptions(url: string, method: string, options: JQueryAjaxSettings | RequestInit): JQueryRequestInit | FetchRequestInit { + ajaxOptions( + url: string, + method: string, + options: JQueryAjaxSettings | RequestInit + ): JQueryRequestInit | FetchRequestInit { let reqOptions: JQueryRequestInit | FetchRequestInit = assign( { url, @@ -1387,12 +1391,7 @@ function ajaxSuccessHandler( return ajaxSuccess(adapter, payload, requestData, responseData); } -function ajaxErrorHandler( - adapter: RESTAdapter, - jqXHR: JQuery.jqXHR, - errorThrown: string, - requestData: RequestData -) { +function ajaxErrorHandler(adapter: RESTAdapter, jqXHR: JQuery.jqXHR, errorThrown: string, requestData: RequestData) { let responseData = ajaxResponseData(jqXHR); responseData.errorThrown = errorThrown; let payload = adapter.parseErrorResponse(jqXHR.responseText); From 8a2e21d3ed4d9bb452898af88db0c5aea42617ce Mon Sep 17 00:00:00 2001 From: Igor Terzic Date: Wed, 3 Feb 2021 12:29:36 -1000 Subject: [PATCH 54/56] fix jquery type --- packages/adapter/addon/rest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index e0193133506..50b8a239579 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1103,13 +1103,13 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { } } - _ajax(options: FetchRequestInit | JQueryAjaxSettings): void { + _ajax(options: FetchRequestInit | JQueryRequestInit): void { if (this.useFetch) { this._fetchRequest(options as FetchRequestInit); } else if (DEPRECATE_NAJAX && this.fastboot && this.fastboot.isFastBoot) { this._najaxRequest(options); } else { - this._ajaxRequest(options as JQueryAjaxSettings); + this._ajaxRequest(options as JQueryRequestInit); } } From 759c470de504de86e5f7553beb611a542619b361 Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 3 Feb 2021 20:35:47 -0600 Subject: [PATCH 55/56] fix FetchRequestData type for determineBodyPromise --- .../addon/-private/utils/determine-body-promise.ts | 12 ++---------- packages/adapter/addon/rest.ts | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/adapter/addon/-private/utils/determine-body-promise.ts b/packages/adapter/addon/-private/utils/determine-body-promise.ts index 88937a67215..a97f583b75e 100644 --- a/packages/adapter/addon/-private/utils/determine-body-promise.ts +++ b/packages/adapter/addon/-private/utils/determine-body-promise.ts @@ -3,12 +3,7 @@ import { DEBUG } from '@glimmer/env'; import continueOnReject from './continue-on-reject'; -type FetchRequestData = { - url?: string; - method?: string; - [key: string]: any; -}; - +type RequestData = import('../../rest').RequestData; type Payload = object | string | undefined; interface CustomSyntaxError extends SyntaxError { @@ -68,10 +63,7 @@ function _determineContent(response: Response, requestData: JQueryAjaxSettings, return ret; } -export function determineBodyPromise( - response: Response, - requestData: JQueryAjaxSettings | FetchRequestData -): Promise { +export function determineBodyPromise(response: Response, requestData: RequestData): Promise { // response.text() may resolve or reject // it is a native promise, may not have finally return continueOnReject(response.text()).then(payload => _determineContent(response, requestData, payload)); diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index 50b8a239579..ffbbadc0068 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -58,7 +58,7 @@ export interface JQueryRequestInit extends JQueryAjaxSettings { type: string; } -type RequestData = { +export type RequestData = { url: string; method: string; [key: string]: any; From 98784c512fc6656591ab2af439b624d06f25359c Mon Sep 17 00:00:00 2001 From: Scott Newcomer Date: Wed, 3 Feb 2021 20:50:14 -0600 Subject: [PATCH 56/56] ajax settings => jquery request init --- packages/adapter/addon/rest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter/addon/rest.ts b/packages/adapter/addon/rest.ts index ffbbadc0068..f58e3493139 100644 --- a/packages/adapter/addon/rest.ts +++ b/packages/adapter/addon/rest.ts @@ -1086,7 +1086,7 @@ class RESTAdapter extends Adapter.extend(BuildURLMixin) { @private @param {Object} options jQuery ajax options to be used for the ajax request */ - _ajaxRequest(options: JQueryAjaxSettings): void { + _ajaxRequest(options: JQueryRequestInit): void { // TODO add assertion that jquery is there rather then equality check typeof jQuery !== 'undefined' && jQuery.ajax(options); }