Skip to content

Commit

Permalink
More type changes
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
xg-wang committed Feb 7, 2019
1 parent 1b328e3 commit ecfbcdb
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 16 deletions.
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@ import fetch, { Headers, Request, Response, AbortController } from 'fetch';
```

### Use with TypeScript
To use `ember-fetch` with TypeScript or enable editor's type support, add `"fetch": "ember-cli/ember-fetch"` to your app's `devDependencies`.
This will get the current state of `ember-fetch` from this GitHub repo as a dependency.

You can also add `"fetch": ["node_modules/ember-fetch"]` to your `tsconfig.json`.
To use `ember-fetch` with TypeScript or enable editor's type support, You can add `"fetch": ["node_modules/ember-fetch"]` to your `tsconfig.json`.

```json
{
"compilerOptions": {
"paths": {
"fetch": [
"node_modules/ember-fetch"
]
}
}
}
```

### Use with Ember Data
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.
Expand Down Expand Up @@ -112,7 +121,8 @@ The way you do import remains same.

## Q & A
### Does it work with pretender?
Yes, [pretender v2.1](https://github.com/pretenderjs/pretender/tree/v2.1.0) comes with `fetch` support.

* Yes, [pretender v2.1](https://github.com/pretenderjs/pretender/tree/v2.1.0) comes with `fetch` support.

### Does this replace ic-ajax?

Expand Down
2 changes: 1 addition & 1 deletion addon/ajax.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

import fetch from 'fetch';

export default async function ajax(
export default function ajax(
input: RequestInfo,
init?: RequestInit
): Promise<Response> {
Expand Down
44 changes: 39 additions & 5 deletions addon/mixins/adapter-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Nullable,
AjaxOptions
} from 'ember-fetch/types';
import { Fix } from '@ember/object/-private/types';

/**
* Helper function to create a plain object from the response's Headers.
Expand All @@ -30,8 +31,35 @@ export function headersToObject(headers: Headers): PlainObject {
return headersObject;
}

export default Mixin.create({
headers: undefined as undefined | PlainHeaders,
export interface FetchAdapter {
headers: undefined | PlainHeaders;
ajaxOptions(url: string, type: Method, options: object): FetchOptions;
ajax(url: string, type: Method, options: object): RSVP.Promise<never>;
_ajaxRequest(
options: Mix<RequestInit, { url: string }>
): RSVP.Promise<Response>;
_fetchRequest(url: string, options: RequestInit): RSVP.Promise<Response>;
ajaxSuccess(
adapter: DS.RESTAdapter,
response: Response,
payload: Nullable<string | object>,
requestData: { url: string; method: string }
): object | DS.AdapterError | RSVP.Promise<never>;
parseFetchResponseForError(
response: Response,
payload: Nullable<object | string>
): object | string;
ajaxError(
adapter: any,
response: Response,
payload: Nullable<string | object>,
requestData: object,
error?: Error
): Error | object | DS.AdapterError;
}

export default Mixin.create<FetchAdapter, DS.RESTAdapter>({
headers: undefined,
/**
* @override
*/
Expand Down Expand Up @@ -129,18 +157,22 @@ export default Mixin.create({
* @override
*/
ajaxSuccess(
adapter: any,
adapter: DS.RESTAdapter,
response: Response,
payload: Nullable<string | object>,
requestData: { url: string; method: string }
): object | DS.AdapterError | RSVP.Promise<never> {
const returnResponse = adapter.handleResponse(
response.status,
headersToObject(response.headers),
// TODO: DS.RESTAdapter annotates payload: {}
// @ts-ignore
payload,
requestData
);

// TODO: DS.RESTAdapter annotates response: {}
// @ts-ignore
if (returnResponse && returnResponse.isAdapterError) {
return reject(returnResponse);
} else {
Expand All @@ -154,7 +186,7 @@ export default Mixin.create({
*/
parseFetchResponseForError(
response: Response,
payload: object | string
payload: Nullable<object | string>
): object | string {
return payload || response.statusText;
},
Expand All @@ -163,7 +195,7 @@ export default Mixin.create({
* @override
*/
ajaxError(
adapter: any,
adapter: Fix<FetchAdapter & DS.RESTAdapter>,
response: Response,
payload: Nullable<string | object>,
requestData: object,
Expand All @@ -179,6 +211,8 @@ export default Mixin.create({
return adapter.handleResponse(
response.status,
headersToObject(response.headers),
// TODO: parseErrorResponse is DS.RESTAdapter private API
// @ts-ignore
adapter.parseErrorResponse(parsedResponse) || payload,
requestData
);
Expand Down
10 changes: 6 additions & 4 deletions addon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import Mix from '@ember/polyfills/types';

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

export interface PlainObject {
export type PlainObject = {
[key: string]: string | PlainObject | PlainObject[];
}

export interface PlainHeaders {
[key: string]: string | undefined | null;
export type PlainHeaders = {
[key: string]: string;
}

export type Method =
Expand All @@ -26,9 +26,11 @@ export type AjaxOptions = {
headers?: PlainHeaders;
};

export type Credentials = 'omit' | 'same-origin' | 'include';

export type FetchOptions = Mix<
AjaxOptions,
{ body?: BodyInit | null; method?: Method }
{ body?: BodyInit | null; method?: Method, credentials: Credentials }
>;

export function isPlainObject(obj: any): obj is PlainObject {
Expand Down
1 change: 0 additions & 1 deletion types/dummy/index.d.ts
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

0 comments on commit ecfbcdb

Please sign in to comment.