aziosxjs 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +92 -267
- package/dist/cache/memoryCache.d.ts +4 -0
- package/dist/cache/memoryCache.js +32 -0
- package/dist/cache/memoryCache.js.map +1 -0
- package/dist/core/Azios.d.ts +33 -3
- package/dist/core/Azios.js +119 -2
- package/dist/core/Azios.js.map +1 -1
- package/dist/core/createInstance.js +3 -0
- package/dist/core/createInstance.js.map +1 -1
- package/dist/core/dispatchRequest.d.ts +1 -2
- package/dist/core/dispatchRequest.js +68 -42
- package/dist/core/dispatchRequest.js.map +1 -1
- package/dist/core/requestStore.d.ts +3 -0
- package/dist/core/requestStore.js +16 -0
- package/dist/core/requestStore.js.map +1 -0
- package/dist/errors/AziosError.d.ts +2 -2
- package/dist/errors/AziosError.js +6 -3
- package/dist/errors/AziosError.js.map +1 -1
- package/dist/helpers/buildURL.d.ts +1 -0
- package/dist/helpers/buildURL.js +27 -0
- package/dist/helpers/buildURL.js.map +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/MiddlewarePipeline.d.ts +54 -0
- package/dist/middleware/MiddlewarePipeline.js +122 -0
- package/dist/middleware/MiddlewarePipeline.js.map +1 -0
- package/dist/middleware/compose.d.ts +1 -0
- package/dist/middleware/compose.js +25 -0
- package/dist/middleware/compose.js.map +1 -0
- package/dist/middleware/middlewareManager.d.ts +4 -0
- package/dist/middleware/middlewareManager.js +12 -0
- package/dist/middleware/middlewareManager.js.map +1 -0
- package/dist/plugins/pluginManager.d.ts +44 -0
- package/dist/plugins/pluginManager.js +120 -0
- package/dist/plugins/pluginManager.js.map +1 -0
- package/dist/rateLimiter/rateLimiter.d.ts +1 -0
- package/dist/rateLimiter/rateLimiter.js +31 -0
- package/dist/rateLimiter/rateLimiter.js.map +1 -0
- package/dist/runtimes/AdapterFactory.d.ts +22 -0
- package/dist/runtimes/AdapterFactory.js +43 -0
- package/dist/runtimes/AdapterFactory.js.map +1 -0
- package/dist/runtimes/HttpAdapter.d.ts +23 -0
- package/dist/runtimes/HttpAdapter.js +10 -0
- package/dist/runtimes/HttpAdapter.js.map +1 -0
- package/dist/runtimes/UniversalHttpAdapter.d.ts +19 -0
- package/dist/runtimes/UniversalHttpAdapter.js +114 -0
- package/dist/runtimes/UniversalHttpAdapter.js.map +1 -0
- package/dist/runtimes/detectRuntime.d.ts +34 -0
- package/dist/runtimes/detectRuntime.js +77 -0
- package/dist/runtimes/detectRuntime.js.map +1 -0
- package/dist/types/config.d.ts +8 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +22 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/middleware.d.ts +16 -0
- package/dist/types/middleware.js +3 -0
- package/dist/types/middleware.js.map +1 -0
- package/dist/types/plugin.d.ts +43 -0
- package/dist/types/plugin.js +3 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/types/request.d.ts +15 -0
- package/dist/types/response.d.ts +23 -1
- package/package.json +24 -5
- package/src/adapters/httpAdapter.ts +0 -0
- package/src/adapters/index.ts +0 -0
- package/src/adapters/xhrAdapter.ts +0 -0
- package/src/cache/memoryCache.ts +45 -0
- package/src/config/mergeConfig.ts +0 -0
- package/src/core/Azios.ts +184 -0
- package/src/core/createInstance.ts +23 -0
- package/src/core/dispatchRequest.ts +111 -0
- package/src/core/requestMethods.ts +0 -0
- package/src/core/requestStore.ts +13 -0
- package/src/errors/AziosError.ts +26 -0
- package/src/helpers/buildURL.ts +44 -0
- package/src/helpers/normalizeHeaders.ts +0 -0
- package/src/helpers/parseHeaders.ts +0 -0
- package/src/index.ts +64 -0
- package/src/interceptors/InterceptorManager.ts +30 -0
- package/src/middleware/MiddlewarePipeline.ts +155 -0
- package/src/middleware/compose.ts +33 -0
- package/src/middleware/middlewareManager.ts +9 -0
- package/src/plugins/pluginManager.ts +143 -0
- package/src/rateLimiter/rateLimiter.ts +36 -0
- package/src/runtimes/AdapterFactory.ts +46 -0
- package/src/runtimes/HttpAdapter.ts +26 -0
- package/src/runtimes/UniversalHttpAdapter.ts +136 -0
- package/src/runtimes/detectRuntime.ts +85 -0
- package/src/types/config.ts +30 -0
- package/src/types/index.ts +5 -0
- package/src/types/middleware.ts +21 -0
- package/src/types/plugin.ts +50 -0
- package/src/types/request.ts +39 -0
- package/src/types/response.ts +37 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AziosRequestConfig } from './config';
|
|
2
|
+
import { AziosResponse } from './response';
|
|
3
|
+
import type { AziosInstance } from './request';
|
|
4
|
+
/**
|
|
5
|
+
* Plugin lifecycle hooks
|
|
6
|
+
* Allows plugins to inject behavior at various stages of the request/response pipeline
|
|
7
|
+
*/
|
|
8
|
+
export interface PluginHooks {
|
|
9
|
+
/**
|
|
10
|
+
* Called when plugin is installed
|
|
11
|
+
*/
|
|
12
|
+
onInstall?(instance: AziosInstance): void | Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Called before request is sent
|
|
15
|
+
*/
|
|
16
|
+
beforeRequest?(config: AziosRequestConfig): AziosRequestConfig | Promise<AziosRequestConfig>;
|
|
17
|
+
/**
|
|
18
|
+
* Called after response is received
|
|
19
|
+
*/
|
|
20
|
+
afterResponse?(response: AziosResponse): AziosResponse | Promise<AziosResponse>;
|
|
21
|
+
/**
|
|
22
|
+
* Called when an error occurs
|
|
23
|
+
*/
|
|
24
|
+
onError?(error: Error): Error | Promise<Error>;
|
|
25
|
+
/**
|
|
26
|
+
* Called when plugin is uninstalled
|
|
27
|
+
*/
|
|
28
|
+
onUninstall?(instance: AziosInstance): void | Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Plugin definition with metadata
|
|
32
|
+
*/
|
|
33
|
+
export interface AziosPlugin {
|
|
34
|
+
name: string;
|
|
35
|
+
version?: string;
|
|
36
|
+
hooks: PluginHooks;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Plugin registry to track installed plugins
|
|
40
|
+
*/
|
|
41
|
+
export interface PluginRegistry {
|
|
42
|
+
[key: string]: AziosPlugin;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/types/plugin.ts"],"names":[],"mappings":""}
|
package/dist/types/request.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { AziosRequestConfig } from "./config";
|
|
2
2
|
import { AziosResponse } from "./response";
|
|
3
|
+
import InterceptorManager from "../interceptors/InterceptorManager";
|
|
4
|
+
import type { AziosPlugin } from "./plugin";
|
|
5
|
+
import type { AziosMiddleware } from "./middleware";
|
|
3
6
|
export interface AziosInstance {
|
|
4
7
|
(config: AziosRequestConfig): Promise<AziosResponse>;
|
|
5
8
|
request(config: AziosRequestConfig): Promise<AziosResponse>;
|
|
6
9
|
get(url: string, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
7
10
|
post(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
11
|
+
put(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
12
|
+
patch(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
13
|
+
delete(url: string, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
14
|
+
head(url: string, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
15
|
+
options(url: string, config?: AziosRequestConfig): Promise<AziosResponse>;
|
|
16
|
+
interceptors: {
|
|
17
|
+
request: InterceptorManager<AziosRequestConfig>;
|
|
18
|
+
response: InterceptorManager<AziosResponse>;
|
|
19
|
+
};
|
|
20
|
+
installPlugin(plugin: AziosPlugin): Promise<void>;
|
|
21
|
+
uninstallPlugin(name: string): Promise<void>;
|
|
22
|
+
use(middleware: AziosMiddleware): void;
|
|
8
23
|
}
|
package/dist/types/response.d.ts
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
1
|
import { AziosRequestConfig } from "./config";
|
|
2
|
+
/**
|
|
3
|
+
* Azios HTTP response object
|
|
4
|
+
* Returned by all request methods
|
|
5
|
+
*/
|
|
2
6
|
export interface AziosResponse<T = any> {
|
|
7
|
+
/**
|
|
8
|
+
* Response data (parsed if JSON)
|
|
9
|
+
*/
|
|
3
10
|
data: T;
|
|
11
|
+
/**
|
|
12
|
+
* HTTP status code
|
|
13
|
+
*/
|
|
4
14
|
status: number;
|
|
15
|
+
/**
|
|
16
|
+
* HTTP status text
|
|
17
|
+
*/
|
|
5
18
|
statusText: string;
|
|
6
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Response headers
|
|
21
|
+
*/
|
|
22
|
+
headers: Record<string, any>;
|
|
23
|
+
/**
|
|
24
|
+
* Original request config
|
|
25
|
+
*/
|
|
7
26
|
config: AziosRequestConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Native request object (if available)
|
|
29
|
+
*/
|
|
8
30
|
request?: any;
|
|
9
31
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aziosxjs",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Lightweight HTTP client
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Lightweight, predictable HTTP client with plugins, middleware, and universal runtime support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"build": "tsc"
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "ts-node tests/all.test.ts",
|
|
10
|
+
"test:sprint1": "ts-node examples/sprint2.ts",
|
|
11
|
+
"test:sprint2": "ts-node examples/sprint2.ts",
|
|
12
|
+
"test:sprint3": "ts-node examples/sprint3.ts",
|
|
13
|
+
"test:sprint4": "ts-node examples/sprint4.ts",
|
|
14
|
+
"test:sprint5:plugins": "ts-node examples/sprint5-plugins.ts",
|
|
15
|
+
"test:sprint5:middleware": "ts-node examples/sprint5-middleware.ts",
|
|
16
|
+
"test:sprint7": "ts-node examples/sprint7-universal.ts",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
9
18
|
},
|
|
10
19
|
"files": [
|
|
11
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
12
22
|
],
|
|
13
23
|
"keywords": [
|
|
14
24
|
"http",
|
|
15
25
|
"client",
|
|
16
26
|
"axios",
|
|
17
27
|
"request",
|
|
18
|
-
"nodejs"
|
|
28
|
+
"nodejs",
|
|
29
|
+
"browser",
|
|
30
|
+
"universal",
|
|
31
|
+
"plugin",
|
|
32
|
+
"middleware",
|
|
33
|
+
"lightweight",
|
|
34
|
+
"typescript"
|
|
19
35
|
],
|
|
20
36
|
"author": "Azeem Ali",
|
|
21
37
|
"license": "MIT",
|
|
@@ -26,5 +42,8 @@
|
|
|
26
42
|
"homepage": "https://github.com/azeemali2001/azios",
|
|
27
43
|
"bugs": {
|
|
28
44
|
"url": "https://github.com/azeemali2001/azios/issues"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"typescript": "^5.0.0"
|
|
29
48
|
}
|
|
30
49
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
type CacheEntry = {
|
|
2
|
+
data: any
|
|
3
|
+
expiry: number
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const cache = new Map<string, CacheEntry>()
|
|
7
|
+
|
|
8
|
+
export function getCache(key: string) {
|
|
9
|
+
|
|
10
|
+
const entry = cache.get(key)
|
|
11
|
+
|
|
12
|
+
if (!entry) return null
|
|
13
|
+
|
|
14
|
+
// remove expired cache
|
|
15
|
+
if (Date.now() > entry.expiry) {
|
|
16
|
+
cache.delete(key)
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return entry.data
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function setCache(
|
|
25
|
+
key: string,
|
|
26
|
+
value: any,
|
|
27
|
+
ttl: number = 5000
|
|
28
|
+
) {
|
|
29
|
+
|
|
30
|
+
const expiry = Date.now() + ttl
|
|
31
|
+
|
|
32
|
+
cache.set(key, {
|
|
33
|
+
data: value,
|
|
34
|
+
expiry
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function clearCache(key: string) {
|
|
40
|
+
cache.delete(key)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function clearAllCache() {
|
|
44
|
+
cache.clear()
|
|
45
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import dispatchRequest from "./dispatchRequest"
|
|
2
|
+
import { AziosRequestConfig } from "../types/config"
|
|
3
|
+
import type { AziosInstance } from "../types/request"
|
|
4
|
+
import type { AziosPlugin } from "../types/plugin"
|
|
5
|
+
import InterceptorManager from "../interceptors/InterceptorManager"
|
|
6
|
+
import PluginManager from "../plugins/pluginManager"
|
|
7
|
+
import MiddlewareManager from "../middleware/middlewareManager"
|
|
8
|
+
import { compose } from "../middleware/compose"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Core Azios HTTP client class
|
|
12
|
+
* Production-grade implementation with plugin system, middleware, and interceptors
|
|
13
|
+
*/
|
|
14
|
+
export default class Azios {
|
|
15
|
+
defaults: AziosRequestConfig
|
|
16
|
+
|
|
17
|
+
interceptors: {
|
|
18
|
+
request: InterceptorManager<AziosRequestConfig>
|
|
19
|
+
response: InterceptorManager<any>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
middlewares: MiddlewareManager
|
|
23
|
+
plugins: PluginManager
|
|
24
|
+
|
|
25
|
+
constructor(config: AziosRequestConfig) {
|
|
26
|
+
this.defaults = config
|
|
27
|
+
|
|
28
|
+
this.interceptors = {
|
|
29
|
+
request: new InterceptorManager(),
|
|
30
|
+
response: new InterceptorManager()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.middlewares = new MiddlewareManager()
|
|
34
|
+
this.plugins = new PluginManager()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Register middleware using Koa-style middleware pattern
|
|
39
|
+
*/
|
|
40
|
+
use(fn: any) {
|
|
41
|
+
this.middlewares.use(fn)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Install a plugin into this instance
|
|
46
|
+
* @throws Error if plugin is already installed or installation fails
|
|
47
|
+
*/
|
|
48
|
+
async installPlugin(plugin: AziosPlugin): Promise<void> {
|
|
49
|
+
await this.plugins.install(plugin, this as any as AziosInstance)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Uninstall a plugin by name
|
|
54
|
+
*/
|
|
55
|
+
async uninstallPlugin(pluginName: string): Promise<void> {
|
|
56
|
+
await this.plugins.uninstall(pluginName, this as any as AziosInstance)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Core request method - central request pipeline
|
|
61
|
+
*/
|
|
62
|
+
async request(config: AziosRequestConfig): Promise<any> {
|
|
63
|
+
config = { ...this.defaults, ...config }
|
|
64
|
+
|
|
65
|
+
// -------------------------
|
|
66
|
+
// PLUGIN: PRE-REQUEST HOOKS
|
|
67
|
+
// -------------------------
|
|
68
|
+
config = await this.plugins.executeBeforeRequestHooks(config)
|
|
69
|
+
|
|
70
|
+
// -------------------------
|
|
71
|
+
// MIDDLEWARE PIPELINE
|
|
72
|
+
// -------------------------
|
|
73
|
+
const context = { config }
|
|
74
|
+
const fn = compose(this.middlewares.middlewares)
|
|
75
|
+
await fn(context)
|
|
76
|
+
config = context.config
|
|
77
|
+
|
|
78
|
+
// -------------------------
|
|
79
|
+
// INTERCEPTOR PIPELINE
|
|
80
|
+
// -------------------------
|
|
81
|
+
const chain: any[] = []
|
|
82
|
+
|
|
83
|
+
// Request interceptors (reverse order)
|
|
84
|
+
this.interceptors.request.forEach(interceptor => {
|
|
85
|
+
chain.unshift(interceptor.fulfilled, interceptor.rejected)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Main dispatch
|
|
89
|
+
chain.push(dispatchRequest, undefined)
|
|
90
|
+
|
|
91
|
+
// Response interceptors (normal order)
|
|
92
|
+
this.interceptors.response.forEach(interceptor => {
|
|
93
|
+
chain.push(interceptor.fulfilled, interceptor.rejected)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
let promise = Promise.resolve(config)
|
|
97
|
+
|
|
98
|
+
while (chain.length) {
|
|
99
|
+
const fulfilled = chain.shift()
|
|
100
|
+
const rejected = chain.shift()
|
|
101
|
+
promise = promise.then(fulfilled, rejected)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const response = await promise as any
|
|
106
|
+
|
|
107
|
+
// -------------------------
|
|
108
|
+
// PLUGIN: POST-RESPONSE HOOKS
|
|
109
|
+
// -------------------------
|
|
110
|
+
return await this.plugins.executeAfterResponseHooks(response)
|
|
111
|
+
} catch (error) {
|
|
112
|
+
// -------------------------
|
|
113
|
+
// PLUGIN: ERROR HOOKS
|
|
114
|
+
// -------------------------
|
|
115
|
+
if (error instanceof Error) {
|
|
116
|
+
throw await this.plugins.executeOnErrorHooks(error)
|
|
117
|
+
}
|
|
118
|
+
throw error
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// =========================================
|
|
123
|
+
// HTTP METHODS
|
|
124
|
+
// =========================================
|
|
125
|
+
|
|
126
|
+
get(url: string, config?: AziosRequestConfig) {
|
|
127
|
+
return this.request({
|
|
128
|
+
...config,
|
|
129
|
+
method: "GET",
|
|
130
|
+
url
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
post(url: string, data?: any, config?: AziosRequestConfig) {
|
|
135
|
+
return this.request({
|
|
136
|
+
...config,
|
|
137
|
+
method: "POST",
|
|
138
|
+
url,
|
|
139
|
+
data
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
put(url: string, data?: any, config?: AziosRequestConfig) {
|
|
144
|
+
return this.request({
|
|
145
|
+
...config,
|
|
146
|
+
method: "PUT",
|
|
147
|
+
url,
|
|
148
|
+
data
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
patch(url: string, data?: any, config?: AziosRequestConfig) {
|
|
153
|
+
return this.request({
|
|
154
|
+
...config,
|
|
155
|
+
method: "PATCH",
|
|
156
|
+
url,
|
|
157
|
+
data
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
delete(url: string, config?: AziosRequestConfig) {
|
|
162
|
+
return this.request({
|
|
163
|
+
...config,
|
|
164
|
+
method: "DELETE",
|
|
165
|
+
url
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
head(url: string, config?: AziosRequestConfig) {
|
|
170
|
+
return this.request({
|
|
171
|
+
...config,
|
|
172
|
+
method: "HEAD",
|
|
173
|
+
url
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
options(url: string, config?: AziosRequestConfig) {
|
|
178
|
+
return this.request({
|
|
179
|
+
...config,
|
|
180
|
+
method: "OPTIONS",
|
|
181
|
+
url
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Azios from "./Azios"
|
|
2
|
+
import { AziosRequestConfig } from "../types/config"
|
|
3
|
+
import { AziosInstance } from "../types/request"
|
|
4
|
+
|
|
5
|
+
export function createInstance(config: AziosRequestConfig): AziosInstance {
|
|
6
|
+
|
|
7
|
+
const context = new Azios(config)
|
|
8
|
+
|
|
9
|
+
const instance = Azios.prototype.request.bind(context) as AziosInstance
|
|
10
|
+
|
|
11
|
+
Object.getOwnPropertyNames(Azios.prototype).forEach(method => {
|
|
12
|
+
|
|
13
|
+
if (method !== "constructor") {
|
|
14
|
+
;(instance as any)[method] = (Azios.prototype as any)[method].bind(context)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// attach interceptors
|
|
20
|
+
instance.interceptors = context.interceptors
|
|
21
|
+
|
|
22
|
+
return instance
|
|
23
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { AziosRequestConfig } from "../types/config"
|
|
2
|
+
import { AziosResponse } from "../types/response"
|
|
3
|
+
import buildURL from "../helpers/buildURL"
|
|
4
|
+
import AziosError from "../errors/AziosError"
|
|
5
|
+
import AdapterFactory from "../runtimes/AdapterFactory"
|
|
6
|
+
|
|
7
|
+
import { getPending, setPending, removePending } from "./requestStore"
|
|
8
|
+
import { getCache, setCache } from "../cache/memoryCache"
|
|
9
|
+
import { schedule } from "../rateLimiter/rateLimiter"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sleep utility for retry delays
|
|
13
|
+
*/
|
|
14
|
+
function delay(ms: number): Promise<void> {
|
|
15
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Make a single HTTP request using the universal adapter
|
|
20
|
+
* This ensures cross-runtime compatibility
|
|
21
|
+
*/
|
|
22
|
+
async function makeRequest(config: AziosRequestConfig): Promise<AziosResponse> {
|
|
23
|
+
const adapter = AdapterFactory.getAdapter()
|
|
24
|
+
return adapter.request(config)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default async function dispatchRequest(config: AziosRequestConfig) {
|
|
28
|
+
|
|
29
|
+
const requestKey =
|
|
30
|
+
`${config.method}-${config.url}-${JSON.stringify(config.params)}`
|
|
31
|
+
|
|
32
|
+
// -------------------------
|
|
33
|
+
// CACHE CHECK (Sprint 4)
|
|
34
|
+
// -------------------------
|
|
35
|
+
|
|
36
|
+
if (config.cache) {
|
|
37
|
+
|
|
38
|
+
const cached = getCache(requestKey)
|
|
39
|
+
|
|
40
|
+
if (cached) {
|
|
41
|
+
return cached
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// -------------------------
|
|
47
|
+
// DEDUPLICATION (Sprint 3)
|
|
48
|
+
// -------------------------
|
|
49
|
+
|
|
50
|
+
const existing = getPending(requestKey)
|
|
51
|
+
|
|
52
|
+
if (existing) {
|
|
53
|
+
return existing
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const retries = config.retry || 0
|
|
57
|
+
const retryDelay = config.retryDelay || 300
|
|
58
|
+
|
|
59
|
+
let attempt = 0
|
|
60
|
+
|
|
61
|
+
const promise = (async () => {
|
|
62
|
+
|
|
63
|
+
while (true) {
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
|
|
67
|
+
const task = () => makeRequest(config)
|
|
68
|
+
|
|
69
|
+
const response = config.rateLimit
|
|
70
|
+
? await schedule(task, config.rateLimit)
|
|
71
|
+
: await task()
|
|
72
|
+
|
|
73
|
+
// -------------------------
|
|
74
|
+
// CACHE STORE
|
|
75
|
+
// -------------------------
|
|
76
|
+
|
|
77
|
+
if (config.cache) {
|
|
78
|
+
setCache(requestKey, response, config.cacheTTL ?? 5000)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
removePending(requestKey)
|
|
82
|
+
|
|
83
|
+
return response
|
|
84
|
+
|
|
85
|
+
} catch (err) {
|
|
86
|
+
|
|
87
|
+
if (attempt >= retries) {
|
|
88
|
+
|
|
89
|
+
removePending(requestKey)
|
|
90
|
+
|
|
91
|
+
throw err
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
attempt++
|
|
96
|
+
|
|
97
|
+
const backoff = retryDelay * Math.pow(2, attempt)
|
|
98
|
+
|
|
99
|
+
await delay(backoff)
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
})()
|
|
106
|
+
|
|
107
|
+
setPending(requestKey, promise)
|
|
108
|
+
|
|
109
|
+
return promise
|
|
110
|
+
|
|
111
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const pendingRequests = new Map()
|
|
2
|
+
|
|
3
|
+
export function getPending(key: string) {
|
|
4
|
+
return pendingRequests.get(key)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function setPending(key: string, promise: Promise<any>) {
|
|
8
|
+
pendingRequests.set(key, promise)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function removePending(key: string) {
|
|
12
|
+
pendingRequests.delete(key)
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default class AziosError extends Error {
|
|
2
|
+
|
|
3
|
+
config: any
|
|
4
|
+
code?: string
|
|
5
|
+
request?: any
|
|
6
|
+
response?: any
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
message: string,
|
|
10
|
+
code?: string,
|
|
11
|
+
config?: any,
|
|
12
|
+
request?: any,
|
|
13
|
+
response?: any
|
|
14
|
+
) {
|
|
15
|
+
|
|
16
|
+
super(message)
|
|
17
|
+
|
|
18
|
+
this.name = "AziosError"
|
|
19
|
+
this.code = code
|
|
20
|
+
this.config = config
|
|
21
|
+
this.request = request
|
|
22
|
+
this.response = response
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export default function buildURL(
|
|
2
|
+
url: string,
|
|
3
|
+
params?: Record<string, any>
|
|
4
|
+
) {
|
|
5
|
+
|
|
6
|
+
if (!params) return url
|
|
7
|
+
|
|
8
|
+
const parts: string[] = []
|
|
9
|
+
|
|
10
|
+
Object.keys(params).forEach(key => {
|
|
11
|
+
|
|
12
|
+
const val = params[key]
|
|
13
|
+
|
|
14
|
+
if (val === null || typeof val === "undefined") {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (Array.isArray(val)) {
|
|
19
|
+
|
|
20
|
+
val.forEach(v => {
|
|
21
|
+
parts.push(
|
|
22
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(v)}`
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
} else {
|
|
27
|
+
|
|
28
|
+
parts.push(
|
|
29
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(val)}`
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
if (parts.length === 0) return url
|
|
37
|
+
|
|
38
|
+
const serialized = parts.join("&")
|
|
39
|
+
|
|
40
|
+
return url.includes("?")
|
|
41
|
+
? `${url}&${serialized}`
|
|
42
|
+
: `${url}?${serialized}`
|
|
43
|
+
|
|
44
|
+
}
|
|
File without changes
|
|
File without changes
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createInstance } from "./core/createInstance"
|
|
2
|
+
|
|
3
|
+
// Export main instance
|
|
4
|
+
const azios = createInstance({
|
|
5
|
+
url: ""
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
// ============================================
|
|
9
|
+
// Type Exports
|
|
10
|
+
// ============================================
|
|
11
|
+
|
|
12
|
+
export type { AziosRequestConfig } from "./types/config"
|
|
13
|
+
export type { AziosResponse } from "./types/response"
|
|
14
|
+
export type { AziosInstance } from "./types/request"
|
|
15
|
+
export type { AziosPlugin, PluginHooks } from "./types/plugin"
|
|
16
|
+
|
|
17
|
+
// ============================================
|
|
18
|
+
// Class Exports
|
|
19
|
+
// ============================================
|
|
20
|
+
|
|
21
|
+
export { default as AziosError } from "./errors/AziosError"
|
|
22
|
+
export { default as InterceptorManager } from "./interceptors/InterceptorManager"
|
|
23
|
+
export { default as Azios } from "./core/Azios"
|
|
24
|
+
export { createInstance } from "./core/createInstance"
|
|
25
|
+
|
|
26
|
+
// ============================================
|
|
27
|
+
// Plugin System Exports
|
|
28
|
+
// ============================================
|
|
29
|
+
|
|
30
|
+
export { default as PluginManager } from "./plugins/pluginManager"
|
|
31
|
+
|
|
32
|
+
// ============================================
|
|
33
|
+
// Middleware System Exports
|
|
34
|
+
// ============================================
|
|
35
|
+
|
|
36
|
+
export { default as MiddlewarePipeline } from "./middleware/MiddlewarePipeline"
|
|
37
|
+
export type { RequestMiddleware, ResponseMiddleware } from "./middleware/MiddlewarePipeline"
|
|
38
|
+
|
|
39
|
+
// ============================================
|
|
40
|
+
// Runtime Support Exports
|
|
41
|
+
// ============================================
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
detectRuntime,
|
|
45
|
+
currentRuntime,
|
|
46
|
+
isRuntime,
|
|
47
|
+
isServerRuntime,
|
|
48
|
+
isBrowserRuntime,
|
|
49
|
+
RuntimeType
|
|
50
|
+
} from "./runtimes/detectRuntime"
|
|
51
|
+
export { default as AdapterFactory } from "./runtimes/AdapterFactory"
|
|
52
|
+
|
|
53
|
+
// ============================================
|
|
54
|
+
// Cache & Rate Limit Exports
|
|
55
|
+
// ============================================
|
|
56
|
+
|
|
57
|
+
export { getCache, setCache, clearCache } from "./cache/memoryCache"
|
|
58
|
+
export { schedule } from "./rateLimiter/rateLimiter"
|
|
59
|
+
|
|
60
|
+
// ============================================
|
|
61
|
+
// Default Export
|
|
62
|
+
// ============================================
|
|
63
|
+
|
|
64
|
+
export default azios
|