3.1.1 • Published 6 months ago

koajax v3.1.1

Weekly downloads
8
License
LGPL-3.0
Repository
github
Last release
6 months ago

KoAJAX

HTTP Client based on Koa-like middlewares

NPM Dependency CI & CD npm.io

NPM

Feature

Request Body

Automatic Serialized types:

  1. Pure text: string
  2. Form encoding: URLSearchParams, FormData
  3. DOM object: Node
  4. JSON object: Object
  5. Binary data: Blob, ArrayBuffer, TypedArray, DataView
  6. Stream object: ReadableStream

Response Body

Automatic Parsed type:

  1. HTML/XML: Document
  2. JSON: Object
  3. Binary data: ArrayBuffer

Usage

Browser

Installation

npm install koajax

index.html

<head>
    <script src="https://polyfill.web-cell.dev/feature/Regenerator.js"></script>
    <script src="https://polyfill.web-cell.dev/feature/ECMAScript.js"></script>
    <script src="https://polyfill.web-cell.dev/feature/TextEncoder.js"></script>
    <script src="https://polyfill.web-cell.dev/feature/AbortController.js"></script>
    <script src="https://polyfill.web-cell.dev/feature/Stream.js"></script>
</head>

Node.js

Installation

npm install koajax core-js jsdom

index.ts

import { polyfill } from 'koajax/source/polyfill';

import { HTTPClient } from 'koajax';

const origin = 'https://your-target-origin.com';

polyfill(origin).then(() => {
    const client = new HTTPClient({
        baseURI: `${origin}/api`,
        responseType: 'json'
    });
    const { body } = await client.get('test/interface');

    console.log(body);
});

Execution

npx tsx index.ts

Non-polyfillable runtimes

  1. https://github.com/idea2app/KoAJAX-Taro-adapter

Example

RESTful API with Token-based Authorization

import { HTTPClient } from 'koajax';

var token = '';

export const client = new HTTPClient().use(
    async ({ request: { method, path, headers }, response }, next) => {
        if (token) headers['Authorization'] = 'token ' + token;

        await next();

        if (method === 'POST' && path.startsWith('/session'))
            token = response.headers.Token;
    }
);

client.get('/path/to/your/API').then(console.log);

Up/Download files

Single HTTP request based on XMLHTTPRequest progress events

(based on Async Generator)

import { request } from 'koajax';

document.querySelector('input[type="file"]').onchange = async ({
    target: { files }
}) => {
    for (const file of files) {
        const { upload, download, response } = request({
            method: 'POST',
            path: '/files',
            body: file,
            responseType: 'json'
        });

        for await (const { loaded } of upload)
            console.log(`Upload ${file.name} : ${(loaded / file.size) * 100}%`);

        const { body } = await response;

        console.log(`Upload ${file.name} : ${body.url}`);
    }
};

Single HTTP request based on Fetch duplex streams

This experimental feature has some limitations.

-import { request } from 'koajax';
+import { requestFetch } from 'koajax';

document.querySelector('input[type="file"]').onchange = async ({
    target: { files }
}) => {
    for (const file of files) {
-        const { upload, download, response } = request({
+        const { upload, download, response } = requestFetch({
            method: 'POST',
            path: '/files',
+            headers: {
+                'Content-Type': file.type,
+                'Content-Length': file.size + ''
+            },
-            body: file,
+            body: file.stream(),
            responseType: 'json'
        });

        for await (const { loaded } of upload)
            console.log(`Upload ${file.name} : ${(loaded / file.size) * 100}%`);

        const { body } = await response;

        console.log(`Upload ${file.name} : ${body.url}`);
    }
};

Multiple HTTP requests based on Range header

npm i native-file-system-adapter  # Web standard API polyfill
import { showSaveFilePicker } from 'native-file-system-adapter';
import { HTTPClient } from 'koajax';

const bufferClient = new HTTPClient({ responseType: 'arraybuffer' });

document.querySelector('#download').onclick = async () => {
    const fileURL = 'https://your.server/with/Range/header/supported/file.zip';
    const suggestedName = new URL(fileURL).pathname.split('/').pop();

    const fileHandle = await showSaveFilePicker({ suggestedName });
    const writer = await fileHandle.createWritable(),
        stream = bufferClient.download(fileURL);

    try {
        for await (const { total, loaded, percent, buffer } of stream) {
            await writer.write(buffer);

            console.table({ total, loaded, percent });
        }
        window.alert(`File ${fileHandle.name} downloaded successfully!`);
    } finally {
        await writer.close();
    }
};

Global Error fallback

npm install browser-unhandled-rejection  # Web standard API polyfill
import { auto } from 'browser-unhandled-rejection';
import { HTTPError } from 'koajax';

auto();

window.addEventListener('unhandledrejection', ({ reason }) => {
    if (!(reason instanceof HTTPError)) return;

    const { message } = reason.response.body;

    if (message) window.alert(message);
});

Read Files

(based on Async Generator)

import { readAs } from 'koajax';

document.querySelector('input[type="file"]').onchange = async ({
    target: { files }
}) => {
    for (const file of files) {
        const { progress, result } = readAs(file, 'dataURL');

        for await (const { loaded } of progress)
            console.log(
                `Loading ${file.name} : ${(loaded / file.size) * 100}%`
            );

        const URI = await result;

        console.log(`Loaded ${file.name} : ${URI}`);
    }
};
3.1.1

6 months ago

3.1.0

6 months ago

3.1.0-rc.2

6 months ago

3.1.0-rc.0

7 months ago

3.1.0-rc.1

7 months ago

3.0.3

8 months ago

3.0.2

9 months ago

3.0.1

9 months ago

3.0.0

9 months ago

3.0.0-rc.2

10 months ago

3.0.0-rc.1

10 months ago

3.0.0-rc.0

10 months ago

3.0.0-rc.4

9 months ago

3.0.0-rc.3

9 months ago

2.1.0-rc.0

10 months ago

2.0.0

10 months ago

1.1.1

1 year ago

2.0.0-rc.0

10 months ago

2.0.0-rc.1

10 months ago

1.1.2

1 year ago

2.0.1-rc.0

10 months ago

2.0.1-rc.1

10 months ago

1.1.0

1 year ago

1.1.0-rc.1

1 year ago

1.1.0-rc.0

1 year ago

1.0.0

1 year ago

1.0.0-rc.3

1 year ago

1.0.0-rc.2

1 year ago

1.0.0-rc.1

1 year ago

1.0.0-rc.0

1 year ago

0.9.6

2 years ago

0.9.5

2 years ago

0.9.4

2 years ago

0.9.3

2 years ago

0.9.0

2 years ago

0.9.2

2 years ago

0.9.1

2 years ago

0.8.5

2 years ago

0.8.6

2 years ago

0.8.4

2 years ago

0.8.3

3 years ago

0.8.2

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago

0.8.0-rc.2

3 years ago

0.8.0-rc.3

3 years ago

0.8.0-rc.0

3 years ago

0.8.0-rc.1

3 years ago

0.7.2

3 years ago

0.7.1

4 years ago

0.7.0

4 years ago

0.7.0-alpha

4 years ago

0.6.5

4 years ago

0.6.4

5 years ago

0.6.3

5 years ago

0.6.2

5 years ago

0.6.1

5 years ago

0.6.0

5 years ago

0.5.3

5 years ago

0.5.2

5 years ago

0.5.1

6 years ago

0.5.0

6 years ago

0.4.0

6 years ago

0.3.3

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago