Skip to content

Commit

Permalink
Merge pull request #16 from AElfProject/release/v0.1.6
Browse files Browse the repository at this point in the history
feat: 🎸 request all in one
  • Loading branch information
hzz780 authored Jul 15, 2024
2 parents 110fb5f + 2f8b3db commit 0a2e4ef
Show file tree
Hide file tree
Showing 12 changed files with 511 additions and 7 deletions.
5 changes: 4 additions & 1 deletion lib/generator/templates/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "next/core-web-vitals"
"extends": [
"next/core-web-vitals",
"plugin:@tanstack/eslint-plugin-query/recommended"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ApolloClient, InMemoryCache, gql } from "@apollo/client";
import {IBaseRequestOptions} from '@/app/demos/api-all-in-one/fetch-data';

export interface IApolloRequestOptions extends IBaseRequestOptions {
apolloConfig?: any;
query?: any;
}

interface IApolloClientOptions {
uri: any;
cache: any;
}
export const createApolloClient = (options: IApolloClientOptions) => {
return new ApolloClient({
// uri: "https://countries.trevorblades.com",
// cache: new InMemoryCache(),
uri: options.uri || "https://countries.trevorblades.com",
cache: options.cache || new InMemoryCache(),
});
};

export const queryCountries = gql`
query Countries {
countries {
code
name
emoji
}
}
`;
85 changes: 85 additions & 0 deletions lib/generator/templates/src/app/demos/api-all-in-one/fetch-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {createApolloClient, IApolloRequestOptions} from '@/app/demos/api-all-in-one/apollo-client';
import {fetchData} from '@/app/demos/api-all-in-one/fetch';
import { ApolloClient, gql } from "@apollo/client";
import { io, Socket } from 'socket.io-client';
import {ISocketRequestOptions} from '@/app/demos/api-all-in-one/socket-io';

export interface IBaseRequestOptions {
method?: string;
headers?: Record<string, string>;
body?: Record<string, any>;
}

export interface IRequestOptions extends ISocketRequestOptions, IApolloRequestOptions {}

export const defaultHeaders = {
'Content-Type': 'application/json',
};

export class RequestAllInOne {
private readonly headers: Record<string, string>;
private readonly apolloConfig: any;
private readonly apolloClient: ApolloClient<any> | undefined; // TCacheShape
private readonly socketClient: Socket | undefined;
private options: Partial<IRequestOptions>;
constructor(options: Partial<IRequestOptions>) {
this.options = options || {};
this.headers = options.headers || defaultHeaders;

if (options.socketPath) {
this.socketClient = io({
path: options.socketPath
});
}
if (options.apolloConfig) {
this.apolloConfig = options.apolloConfig;
this.apolloClient = createApolloClient(this.apolloConfig);
}
}

async get(url: string) {
return fetchData(url, { headers: this.headers });
}

async post(url: string, options: IBaseRequestOptions = {}) {
return fetchData(url, {
method: 'POST',
headers: {
...this.headers,
...options.headers,
},
body: options.body
});
}

async gql(url: string, options: IApolloRequestOptions = {}) {
if (!this.apolloClient) {
throw Error('No apollo client found')
}
const { data } = await this.apolloClient.query({
query: gql`${options.query}`,
});

return data;
}

socket(url: string, options: ISocketRequestOptions) {
let socketClient = this.socketClient;
if (this.options.socketPath !== url || !socketClient) {
socketClient = io({
path: options.socketPath
});
}
if (options.type === 'on') {
socketClient.on(options.event, (response: any) => {
console.log(options.event, response);
options.callback && options.callback(response);
});
} else {
socketClient.emit(options.event, options.value, (response: any) => {
console.log(response);
options.callback && options.callback(response);
});
}
}
}
23 changes: 23 additions & 0 deletions lib/generator/templates/src/app/demos/api-all-in-one/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IBaseRequestOptions } from '@/app/demos/api-all-in-one/fetch-data';

export const fetchData = async (url: string, options: IBaseRequestOptions = {}) => {

const { method = 'GET', headers = {}, body } = options;

const fetchOptions: any = {
method,
headers,
};

if (body) {
fetchOptions.body = JSON.stringify(body);
}

const response = await fetch(url, fetchOptions);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

return response.json();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'use client';
import {RequestAllInOne} from '@/app/demos/api-all-in-one/fetch-data';
import {useEffect, useState} from 'react';

const client = new RequestAllInOne({});

export default function Fetch() {
const [data, setData] = useState<any>();

useEffect(() => {
const fetchData = async () => {
const response = await client.get('https://api.github.com/repos/TanStack/query');
setData(response);
};
fetchData();
}, []);

if (!data) {
return <>No data</>;
}

return <>
<div>
<div> Fetch Only </div>
<h1>{data.full_name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{' '}
<strong>{data.stargazers_count}</strong>{' '}
<strong>🍴 {data.forks_count}</strong>
{/*<div>{isFetching ? 'Updating...' : ''}</div>*/}
</div>
</>;
}

// function Example() {
// const { isPending, error, data, isFetching } = useQuery({
// queryKey: ['repoData'],
// queryFn: async () => {
// const response = await fetch(
// 'https://api.github.com/repos/TanStack/query',
// )
// return await response.json()
// },
// })
//
// if (isPending) return 'Loading...'
//
// if (error) return 'An error has occurred: ' + error.message
//
// return (
// <div>
// <h1>{data.full_name}</h1>
// <p>{data.description}</p>
// <strong>👀 {data.subscribers_count}</strong>{' '}
// <strong>✨ {data.stargazers_count}</strong>{' '}
// <strong>🍴 {data.forks_count}</strong>
// <div>{isFetching ? 'Updating...' : ''}</div>
// </div>
// )
// }

//
// function Todos() {
// // Access the client
// const queryClient = useQueryClient()
//
// // Queries
// const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })
//
// // Mutations
// const mutation = useMutation({
// mutationFn: postTodo,
// onSuccess: () => {
// // Invalidate and refetch
// queryClient.invalidateQueries({ queryKey: ['todos'] })
// },
// })
//
// return (
// <div>
// <ul>{query.data?.map((todo) => <li key={todo.id}>{todo.title}</li>)}</ul>
//
// <button
// onClick={() => {
// mutation.mutate({
// id: Date.now(),
// title: 'Do Laundry',
// })
// }}
// >
// Add Todo
// </button>
// </div>
// )
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client';
import {RequestAllInOne} from '@/app/demos/api-all-in-one/fetch-data';
import {useEffect, useState} from 'react';
import {queryCountries} from '@/app/demos/graphql/apollo-client';
import {InMemoryCache} from '@apollo/client';

const client = new RequestAllInOne({ apolloConfig: {
uri: "https://countries.trevorblades.com",
cache: new InMemoryCache(),
}});

export default function Fetch() {
const [data, setData] = useState<any>();

useEffect(() => {
const fetchData = async () => {
const response = await client.gql('https://countries.trevorblades.com', {
query: queryCountries
});
const countries = response.countries.slice(0, 4);
setData(countries);
};
fetchData();
}, []);

if (!data) {
return <>No data</>;
}

return <div>
{data.map((country: any) => (
<div key={country.code}>
<h3>{country.name}</h3>
<p>
{country.code} - {country.emoji}
</p>
</div>
))}
</div>
}
21 changes: 21 additions & 0 deletions lib/generator/templates/src/app/demos/api-all-in-one/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Menu } from 'antd';
import Link from 'next/link';
import type { MenuProps } from 'antd';

type MenuItem = Required<MenuProps>['items'][number];

const items: MenuItem[] = [
{ key: '1', label: <Link href="/demos/api-all-in-one/fetch">Fetch</Link> },
{ key: '2', label: <Link href="/demos/api-all-in-one/graphql">Graphql</Link> },
{ key: '3', label: <Link href="/demos/api-all-in-one/socket">Socket</Link> },
];
export default function APIAllInOneLayout({
children, // will be a page or nested layout
}: {
children: React.ReactNode
}) {
return <>
<Menu mode="horizontal" items={items} />
<div>{children}</div>
</>;
}
83 changes: 83 additions & 0 deletions lib/generator/templates/src/app/demos/api-all-in-one/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
'use client';
// useQuery use client only
// Todo: server side integration.
import {
useQuery,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query';

// Create a client
const queryClient = new QueryClient()

export default function APIAllInOne() {
return <>
<QueryClientProvider client={queryClient}>
<p>api all in one.</p>
{/*<Todos />*/}
<Example />
</QueryClientProvider>
</>;
}

function Example() {
const { isPending, error, data, isFetching } = useQuery({
queryKey: ['repoData'],
queryFn: async () => {
const response = await fetch(
'https://api.github.com/repos/TanStack/query',
)
return await response.json()
},
})

if (isPending) return 'Loading...'

if (error) return 'An error has occurred: ' + error.message

return (
<div>
<h1>{data.full_name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{' '}
<strong>{data.stargazers_count}</strong>{' '}
<strong>🍴 {data.forks_count}</strong>
<div>{isFetching ? 'Updating...' : ''}</div>
</div>
)
}

//
// function Todos() {
// // Access the client
// const queryClient = useQueryClient()
//
// // Queries
// const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })
//
// // Mutations
// const mutation = useMutation({
// mutationFn: postTodo,
// onSuccess: () => {
// // Invalidate and refetch
// queryClient.invalidateQueries({ queryKey: ['todos'] })
// },
// })
//
// return (
// <div>
// <ul>{query.data?.map((todo) => <li key={todo.id}>{todo.title}</li>)}</ul>
//
// <button
// onClick={() => {
// mutation.mutate({
// id: Date.now(),
// title: 'Do Laundry',
// })
// }}
// >
// Add Todo
// </button>
// </div>
// )
// }
Loading

0 comments on commit 0a2e4ef

Please sign in to comment.