Skip to content

Commit

Permalink
fix: show errors from the API, add better examples
Browse files Browse the repository at this point in the history
  • Loading branch information
jrea committed May 19, 2022
1 parent d26c9b3 commit fec034f
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 26 deletions.
28 changes: 28 additions & 0 deletions lib/nile/templates/apis.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,35 @@ export class {{classname}} extends runtime.BaseAPI {
{{#summary}}
* {{&summary}}
{{/summary}}
* @example
*```typescript
* import {{moduleName}} from '{{{projectName}}}';
*
* const nile = new {{{moduleName}}}({ apiUrl: 'http://localhost:8080' });
*
{{#hasParams}}
* const body = {
{{#allParams}}
* // {{{dataType}}}{{#description}} | {{{description}}}{{/description}}{{^required}} (optional){{/required}}
* {{paramName}}: {{#example}}{{{example}}}{{/example}}{{^example}}{}{{/example}},
{{/allParams}}
* };
* {{/hasParams}}
{{^hasParams}}
* let body:any = {};
{{/hasParams}}
*
* nile.{{{operationId}}}(body).then(({{#returnType}}data{{/returnType}}) => {
{{#returnType}}
* console.log('API called successfully. Returned data: ' + data);
{{/returnType}}
{{^returnType}}
* console.log('API called successfully.');
{{/returnType}}
* }).catch((error:any) => console.error(error));
```
*/
async {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}Request, {{/allParams.0}}initOverrides?: RequestInit): Promise<{{#returnType}}void | {{/returnType}}{{{returnType}}}{{^returnType}}void{{/returnType}}> {
{{#allParams}}
Expand Down
12 changes: 12 additions & 0 deletions lib/nile/templates/runtime.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ export class BaseAPI {
if (response.status >= 200 && response.status < 300) {
return response;
}

let res;
try {
res = await response.json();
} catch (e) {
/* do the default */
}
if ('message' in res) {
const { message } = res;
throw new ResponseError(response, message);
}

throw new ResponseError(response, 'Response returned an error code');
}

Expand Down
32 changes: 32 additions & 0 deletions packages/examples/components/UserTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { useNile } from '@theniledev/react';
import { User } from '@theniledev/js';
import { useQuery } from 'react-query';

export function UserTable() {
const nile = useNile();

const {
isLoading,
isError,
error,
data: users = [],
} = useQuery<unknown, unknown, User[]>('nileUsers', () => nile.listUsers({}));

if (isLoading) {
return <div>Loading...</div>;
}

if (isError && error instanceof Error) {
return <div>{error.message}</div>;
}

return (
<>
<h2>Users</h2>
{users.map((user) => {
return <div key={user.id}>{user.email}</div>;
})}
</>
);
}
18 changes: 8 additions & 10 deletions packages/examples/pages/users.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React, { useCallback, useState } from 'react';
import { useRouter } from 'next/router';
import { Invite, User } from '@theniledev/js';
import { Invite } from '@theniledev/js';
import { useNile } from '@theniledev/react';
import { useQueries } from 'react-query';
import { useQuery } from 'react-query';

import { UserTable } from '../components/UserTable';

function SignIn() {
const nile = useNile();
const [joinCode, setJoinCode] = useState<string>('');
const router = useRouter();

const [{ data: users = [] }, { data: invites = [] }] = useQueries([
{ queryKey: 'users', queryFn: () => nile.listUsers({}) },
{ queryKey: 'invites', queryFn: () => nile.listInvites({}) },
]);
const { data: invites = [] } = useQuery('invites', () =>
nile.listInvites({})
);

const handleLogout = useCallback(() => {
nile.authToken = '';
Expand All @@ -32,10 +33,7 @@ function SignIn() {
<>
<h1>🤩 InstaExpense 🤩</h1>
<h2>Sign in</h2>
{users &&
users.map((user: User) => {
return <pre key={user.id}>{JSON.stringify(user, null, 2)}</pre>;
})}
<UserTable />
<button onClick={handleLogout}>Logout</button>
<input
type="text"
Expand Down
3 changes: 3 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,8 @@
"tsdx": "^0.14.1",
"tslib": "^2.3.1",
"typescript": "^4.6.3"
},
"dependencies": {
"react-query": "^3.39.0"
}
}
51 changes: 35 additions & 16 deletions packages/react/src/components/SignUpForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React from 'react';
import { useEffect } from 'react';
import { useMutation } from 'react-query';

import { useNile } from '../../context';
import Button from '../_Button';
Expand All @@ -14,32 +16,49 @@ export default function SignUpForm(props: Props) {
passwordLabel,
passwordInput,
handleSuccess,
handleFailure,
} = props;
const nile = useNile();

const mutation = useMutation(
(createUserRequest: { email: string; password: string }) =>
nile.createUser({ createUserRequest })
);

const mutate = mutation.mutate;

const wrapSuccess = React.useCallback(
(payload) => handleSuccess && handleSuccess(payload),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);

const getEmailAndPassword = React.useCallback(() => {
const email = document.querySelector('#signup #email') as HTMLInputElement;
const password = document.querySelector(
'#signup #password'
) as HTMLInputElement;
return [email.value, password.value];
}, []);

const handleSubmit = React.useCallback(
async function () {
const email = document.querySelector(
'#signup #email'
) as HTMLInputElement;
const password = document.querySelector(
'#signup #password'
) as HTMLInputElement;

const [email, password] = getEmailAndPassword();
const createUserRequest = {
email: email.value,
password: password.value,
email,
password,
};

await nile.createUser({ createUserRequest }).catch((e: Error) => {
handleFailure && handleFailure(e);
});
handleSuccess && handleSuccess(createUserRequest);
mutate(createUserRequest);
},
[handleFailure, handleSuccess, nile]
[getEmailAndPassword, mutate]
);

useEffect(() => {
if (mutation.isSuccess) {
const [email, password] = getEmailAndPassword();
wrapSuccess({ email, password });
}
}, [getEmailAndPassword, wrapSuccess, mutation.isSuccess]);

return (
<form id="signup">
<Label node={emailLabel} htmlFor="email" text="Email" />
Expand Down

0 comments on commit fec034f

Please sign in to comment.