Skip to content

Commit c64bb4c

Browse files
committed
More type changes
- simplify readme type instruction - drop redundant async in ajax.ts - add credentials to FetchOptions type - add FetchAdapter interface for our object literal and better support Mixin.create typing
1 parent 1b328e3 commit c64bb4c

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,19 @@ import fetch, { Headers, Request, Response, AbortController } from 'fetch';
3636
```
3737

3838
### Use with TypeScript
39-
To use `ember-fetch` with TypeScript or enable editor's type support, add `"fetch": "ember-cli/ember-fetch"` to your app's `devDependencies`.
40-
This will get the current state of `ember-fetch` from this GitHub repo as a dependency.
41-
42-
You can also add `"fetch": ["node_modules/ember-fetch"]` to your `tsconfig.json`.
39+
To use `ember-fetch` with TypeScript or enable editor's type support, You can add `"fetch": ["node_modules/ember-fetch"]` to your `tsconfig.json`.
40+
41+
```json
42+
{
43+
"compilerOptions": {
44+
"paths": {
45+
"fetch": [
46+
"node_modules/ember-fetch"
47+
]
48+
}
49+
}
50+
}
51+
```
4352

4453
### Use with Ember Data
4554
To have Ember Data utilize `fetch` instead of jQuery.ajax to make calls to your backend, extend your project's `application` adapter with the `adapter-fetch` mixin.
@@ -112,7 +121,8 @@ The way you do import remains same.
112121

113122
## Q & A
114123
### Does it work with pretender?
115-
Yes, [pretender v2.1](https://github.com/pretenderjs/pretender/tree/v2.1.0) comes with `fetch` support.
124+
125+
* Yes, [pretender v2.1](https://github.com/pretenderjs/pretender/tree/v2.1.0) comes with `fetch` support.
116126

117127
### Does this replace ic-ajax?
118128

addon/ajax.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
import fetch from 'fetch';
33

4-
export default async function ajax(
4+
export default function ajax(
55
input: RequestInfo,
66
init?: RequestInit
77
): Promise<Response> {

addon/mixins/adapter-fetch.ts

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ import {
1515
Nullable,
1616
AjaxOptions
1717
} from 'ember-fetch/types';
18+
import { Fix } from '@ember/object/-private/types';
1819

1920
/**
2021
* Helper function to create a plain object from the response's Headers.
2122
* Consumed by the adapter's `handleResponse`.
2223
*/
23-
export function headersToObject(headers: Headers): PlainObject {
24-
let headersObject: PlainObject = {};
24+
export function headersToObject(headers: Headers) {
25+
let headersObject: PlainObject<string> = {};
2526

2627
if (headers) {
2728
headers.forEach((value, key) => (headersObject[key] = value));
@@ -30,8 +31,35 @@ export function headersToObject(headers: Headers): PlainObject {
3031
return headersObject;
3132
}
3233

33-
export default Mixin.create({
34-
headers: undefined as undefined | PlainHeaders,
34+
export interface FetchAdapter {
35+
headers: undefined | PlainHeaders;
36+
ajaxOptions(url: string, type: Method, options: object): FetchOptions;
37+
ajax(url: string, type: Method, options: object): RSVP.Promise<void>;
38+
_ajaxRequest(
39+
options: Mix<RequestInit, { url: string }>
40+
): RSVP.Promise<Response>;
41+
_fetchRequest(url: string, options: RequestInit): RSVP.Promise<Response>;
42+
ajaxSuccess(
43+
adapter: DS.RESTAdapter,
44+
response: Response,
45+
payload: Nullable<string | object>,
46+
requestData: { url: string; method: string }
47+
): object | DS.AdapterError | RSVP.Promise<void>;
48+
parseFetchResponseForError(
49+
response: Response,
50+
payload: Nullable<object | string>
51+
): object | string;
52+
ajaxError(
53+
adapter: any,
54+
response: Response,
55+
payload: Nullable<string | object>,
56+
requestData: object,
57+
error?: Error
58+
): Error | object | DS.AdapterError;
59+
}
60+
61+
export default Mixin.create<FetchAdapter, DS.RESTAdapter>({
62+
headers: undefined,
3563
/**
3664
* @override
3765
*/
@@ -129,18 +157,22 @@ export default Mixin.create({
129157
* @override
130158
*/
131159
ajaxSuccess(
132-
adapter: any,
160+
adapter: DS.RESTAdapter,
133161
response: Response,
134162
payload: Nullable<string | object>,
135163
requestData: { url: string; method: string }
136-
): object | DS.AdapterError | RSVP.Promise<never> {
164+
): object | DS.AdapterError | RSVP.Promise<void> {
137165
const returnResponse = adapter.handleResponse(
138166
response.status,
139167
headersToObject(response.headers),
168+
// TODO: DS.RESTAdapter annotates payload: {}
169+
// @ts-ignore
140170
payload,
141171
requestData
142172
);
143173

174+
// TODO: DS.RESTAdapter annotates response: {}
175+
// @ts-ignore
144176
if (returnResponse && returnResponse.isAdapterError) {
145177
return reject(returnResponse);
146178
} else {
@@ -154,7 +186,7 @@ export default Mixin.create({
154186
*/
155187
parseFetchResponseForError(
156188
response: Response,
157-
payload: object | string
189+
payload: Nullable<object | string>
158190
): object | string {
159191
return payload || response.statusText;
160192
},
@@ -163,7 +195,7 @@ export default Mixin.create({
163195
* @override
164196
*/
165197
ajaxError(
166-
adapter: any,
198+
adapter: Fix<FetchAdapter & DS.RESTAdapter>,
167199
response: Response,
168200
payload: Nullable<string | object>,
169201
requestData: object,
@@ -179,6 +211,8 @@ export default Mixin.create({
179211
return adapter.handleResponse(
180212
response.status,
181213
headersToObject(response.headers),
214+
// TODO: parseErrorResponse is DS.RESTAdapter private API
215+
// @ts-ignore
182216
adapter.parseErrorResponse(parsedResponse) || payload,
183217
requestData
184218
);

addon/types.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import Mix from '@ember/polyfills/types';
22

33
export type Nullable<T> = T | null | undefined;
44

5-
export interface PlainObject {
6-
[key: string]: string | PlainObject | PlainObject[];
5+
export type PlainObject<T = string | number | boolean> = {
6+
[key: string]: T | PlainObject<T> | PlainObject<T>[];
77
}
88

9-
export interface PlainHeaders {
10-
[key: string]: string | undefined | null;
9+
export type PlainHeaders = {
10+
[key: string]: string;
1111
}
1212

1313
export type Method =
@@ -22,13 +22,15 @@ export type Method =
2222
export type AjaxOptions = {
2323
url: string;
2424
type: Method;
25-
data?: PlainObject | BodyInit;
25+
data?: PlainObject<string> | BodyInit;
2626
headers?: PlainHeaders;
2727
};
2828

29+
export type Credentials = 'omit' | 'same-origin' | 'include';
30+
2931
export type FetchOptions = Mix<
3032
AjaxOptions,
31-
{ body?: BodyInit | null; method?: Method }
33+
{ body?: BodyInit | null; method?: Method, credentials: Credentials }
3234
>;
3335

3436
export function isPlainObject(obj: any): obj is PlainObject {

types/dummy/index.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-

0 commit comments

Comments
 (0)