Skip to content

Commit

Permalink
✨ useApiRoute composables #97
Browse files Browse the repository at this point in the history
  • Loading branch information
trydofor committed Nov 15, 2024
1 parent d6811d8 commit 26d842e
Show file tree
Hide file tree
Showing 11 changed files with 464 additions and 170 deletions.
6 changes: 6 additions & 0 deletions .changeset/great-toys-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@fessional/razor-common": patch
"@fessional/razor-mobile": patch
---

✨ useApiRoute composables #97
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nodejs 20.18.0
pnpm 9.13.0
pnpm 9.13.2
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"nuxi",
"nuxt",
"nuxtjs",
"ofetch",
"pinia",
"pnpmfile",
"revi",
Expand Down
7 changes: 7 additions & 0 deletions hoist-layer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -67,6 +68,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -109,6 +111,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -145,6 +148,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -181,6 +185,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -215,6 +220,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down Expand Up @@ -252,6 +258,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down
29 changes: 29 additions & 0 deletions layers/common/composables/UseApiRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* A helper for handling API fetch with apiRoute prefix.
*
* @returns {Object} The API helper.
* @returns {Function} `url(uri: string): string` - the url apiRoute prefix.
* @returns {Function} `get<Data>(uri: string): Promise<DataResult<Data>>` - GET request with apiRoute prefix
* @returns {Function} `post<Data>(uri: string): Promise<DataResult<Data>>` - POST request with apiRoute prefix
*/
export function useApiRoute() {
const prefix = useRuntimeConfig().public.apiRoute;
return {
url: (uri: string) => prefix + uri,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
get: <Data>(uri: string, query?: Record<string, any>) => $fetch<DataResult<Data>>(
prefix + uri,
{
method: 'get',
query,
}),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
post: <Data>(uri: string, body?: Record<string, any> | URLSearchParams | FormData, query?: Record<string, any>) => $fetch<DataResult<Data>>(
prefix + uri,
{
method: 'post',
query,
body,
}),
};
}
3 changes: 2 additions & 1 deletion layers/common/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fessional/razor-common",
"type": "module",
"version": "0.2.0",
"version": "0.2.1",
"description": "common layer for mobile and desktop",
"main": "./nuxt.config.ts",
"types": "./index.d.ts",
Expand All @@ -27,6 +27,7 @@
"@vue/test-utils": "catalog:commonDev",
"eslint": "catalog:commonDev",
"happy-dom": "catalog:commonDev",
"msw": "catalog:commonDev",
"nuxi": "catalog:commonDev",
"nuxt": "catalog:commonDev",
"typescript": "catalog:commonDev",
Expand Down
77 changes: 77 additions & 0 deletions layers/common/tests/UseApiRoute.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';
import { createFetch } from 'ofetch';
import { useApiRoute } from '../composables/UseApiRoute';

const server = setupServer(
http.get('/api/v1/test-get.json', ({ request }) => {
const contentType = request.headers.get('content-type');
return HttpResponse.json({
success: true,
data: contentType,
});
}),
http.post('/api/v1/test-post.json', ({ request }) => {
const contentType = request.headers.get('content-type');
return HttpResponse.json({
success: true,
data: contentType,
});
}),
);

beforeAll(() => {
server.listen({ onUnhandledRequest: 'error' });
// eslint-disable-next-line
// @ts-ignore https://github.com/nuxt/test-utils/issues/775
// 404 Cannot find any path matching /api/v1/test-get.json if comment
globalThis.$fetch = createFetch();
console.log('set env 24');
});

afterEach(() => {
server.resetHandlers();
});

afterAll(() => {
server.close();
});

describe('useApiRoute with real $fetch requests', () => {
it('should send GET request with correct Content-Type (no body)', async () => {
const { get } = useApiRoute();
const rs = await get('/test-get.json');
console.log('get', JSON.stringify(rs));
expect(rs.data).toBeNull();
});

it('should send POST request with JSON Content-Type', async () => {
const { post } = useApiRoute();
const jsonBody = { key: 'value' };
const rs = await post('/test-post.json', jsonBody);
console.log('post JSON', JSON.stringify(rs));
expect(rs.data).toBe('application/json');
});

it('should send POST request with FormData Content-Type', async () => {
const { post } = useApiRoute();
const formData = new FormData();
formData.append('key', 'value');

const rs = await post('/test-post.json', formData);
console.log('post FormData', JSON.stringify(rs));
// in nuxt dev, it auto set `multipart/form-data; boundary`, but test not !!
// expect(rs.data).toContain('multipart/form-data');
});

it('should send POST request with URLSearchParams Content-Type', async () => {
const { post } = useApiRoute();
const params = new URLSearchParams();
params.append('key', 'value');

const rs = await post('/test-post.json', params);
console.log('post SearchParams', JSON.stringify(rs));
expect(rs.data).toContain('application/x-www-form-urlencoded');
});
});
2 changes: 1 addition & 1 deletion layers/mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fessional/razor-mobile",
"type": "module",
"version": "0.2.0",
"version": "0.2.1",
"description": "mobile layer with ionic and capacitor",
"main": "./nuxt.config.ts",
"scripts": {
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@fessional/razor",
"type": "module",
"version": "0.2.0",
"version": "0.2.1",
"description": "Use front-end tech (Nuxt/Ts) to build multi-platform from one codebase, suitable for small team and app to write app once, apply almost anywhere.",
"packageManager": "[email protected].0",
"packageManager": "[email protected].2",
"engines": {
"node": "20.18.0",
"pnpm": "9.13.0"
"pnpm": "9.13.2"
},
"files": [
"hoist-layer.json",
Expand Down
Loading

0 comments on commit 26d842e

Please sign in to comment.