aziosxjs 0.4.1 → 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 +1 -0
- package/dist/cache/memoryCache.js +7 -1
- package/dist/cache/memoryCache.js.map +1 -1
- package/dist/core/Azios.d.ts +33 -8
- package/dist/core/Azios.js +68 -2
- package/dist/core/Azios.js.map +1 -1
- package/dist/core/dispatchRequest.js +10 -75
- package/dist/core/dispatchRequest.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/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/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 +5 -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,143 @@
|
|
|
1
|
+
import type { AziosPlugin, PluginRegistry } from '../types/plugin'
|
|
2
|
+
import type { AziosInstance } from '../types/request'
|
|
3
|
+
import type { AziosRequestConfig } from '../types/config'
|
|
4
|
+
import type { AziosResponse } from '../types/response'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* PluginManager handles plugin lifecycle and hook execution
|
|
8
|
+
* Production-grade plugin system with error handling and validation
|
|
9
|
+
*/
|
|
10
|
+
export default class PluginManager {
|
|
11
|
+
private plugins: PluginRegistry = {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Install a plugin and trigger its onInstall hook
|
|
15
|
+
* @throws Error if plugin name is already registered
|
|
16
|
+
*/
|
|
17
|
+
async install(plugin: AziosPlugin, instance: AziosInstance): Promise<void> {
|
|
18
|
+
if (this.plugins[plugin.name]) {
|
|
19
|
+
throw new Error(`Plugin "${plugin.name}" is already installed`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.plugins[plugin.name] = plugin
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
if (plugin.hooks.onInstall) {
|
|
26
|
+
await plugin.hooks.onInstall(instance)
|
|
27
|
+
}
|
|
28
|
+
} catch (err) {
|
|
29
|
+
// Rollback on error
|
|
30
|
+
delete this.plugins[plugin.name]
|
|
31
|
+
throw err
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Uninstall a plugin and trigger its onUninstall hook
|
|
37
|
+
*/
|
|
38
|
+
async uninstall(pluginName: string, instance: AziosInstance): Promise<void> {
|
|
39
|
+
const plugin = this.plugins[pluginName]
|
|
40
|
+
|
|
41
|
+
if (!plugin) {
|
|
42
|
+
throw new Error(`Plugin "${pluginName}" is not installed`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
if (plugin.hooks.onUninstall) {
|
|
47
|
+
await plugin.hooks.onUninstall(instance)
|
|
48
|
+
}
|
|
49
|
+
} finally {
|
|
50
|
+
delete this.plugins[pluginName]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Execute beforeRequest hooks from all plugins
|
|
56
|
+
*/
|
|
57
|
+
async executeBeforeRequestHooks(
|
|
58
|
+
config: AziosRequestConfig
|
|
59
|
+
): Promise<AziosRequestConfig> {
|
|
60
|
+
let result = config
|
|
61
|
+
|
|
62
|
+
for (const plugin of Object.values(this.plugins)) {
|
|
63
|
+
if (plugin.hooks.beforeRequest) {
|
|
64
|
+
try {
|
|
65
|
+
result = await plugin.hooks.beforeRequest(result)
|
|
66
|
+
} catch (err) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`Plugin "${plugin.name}" beforeRequest hook failed: ${err instanceof Error ? err.message : String(err)}`
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return result
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Execute afterResponse hooks from all plugins
|
|
79
|
+
*/
|
|
80
|
+
async executeAfterResponseHooks(
|
|
81
|
+
response: AziosResponse
|
|
82
|
+
): Promise<AziosResponse> {
|
|
83
|
+
let result = response
|
|
84
|
+
|
|
85
|
+
for (const plugin of Object.values(this.plugins)) {
|
|
86
|
+
if (plugin.hooks.afterResponse) {
|
|
87
|
+
try {
|
|
88
|
+
result = await plugin.hooks.afterResponse(result)
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Plugin "${plugin.name}" afterResponse hook failed: ${err instanceof Error ? err.message : String(err)}`
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return result
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Execute onError hooks from all plugins
|
|
102
|
+
*/
|
|
103
|
+
async executeOnErrorHooks(error: Error): Promise<Error> {
|
|
104
|
+
let result = error
|
|
105
|
+
|
|
106
|
+
for (const plugin of Object.values(this.plugins)) {
|
|
107
|
+
if (plugin.hooks.onError) {
|
|
108
|
+
try {
|
|
109
|
+
result = await plugin.hooks.onError(result)
|
|
110
|
+
} catch (err) {
|
|
111
|
+
// Log but don't throw - error handlers should not crash
|
|
112
|
+
console.warn(
|
|
113
|
+
`Plugin "${plugin.name}" onError hook failed:`,
|
|
114
|
+
err instanceof Error ? err.message : String(err)
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return result
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get all currently installed plugins
|
|
125
|
+
*/
|
|
126
|
+
getInstalledPlugins(): AziosPlugin[] {
|
|
127
|
+
return Object.values(this.plugins)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Check if a plugin is installed
|
|
132
|
+
*/
|
|
133
|
+
isPluginInstalled(name: string): boolean {
|
|
134
|
+
return name in this.plugins
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Clear all plugins
|
|
139
|
+
*/
|
|
140
|
+
clear(): void {
|
|
141
|
+
this.plugins = {}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
let queue: Function[] = [];
|
|
2
|
+
let activeRequests = 0;
|
|
3
|
+
|
|
4
|
+
export function schedule(task: Function, limit: number) {
|
|
5
|
+
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
|
|
8
|
+
const run = async () => {
|
|
9
|
+
|
|
10
|
+
activeRequests++;
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const result = await task();
|
|
14
|
+
resolve(result);
|
|
15
|
+
} catch (err) {
|
|
16
|
+
reject(err);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
activeRequests--;
|
|
20
|
+
|
|
21
|
+
if (queue.length) {
|
|
22
|
+
const next = queue.shift();
|
|
23
|
+
next && next();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
if (activeRequests < limit) {
|
|
29
|
+
run();
|
|
30
|
+
} else {
|
|
31
|
+
queue.push(run);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { HttpAdapter } from './HttpAdapter'
|
|
2
|
+
import { currentRuntime, RuntimeType } from './detectRuntime'
|
|
3
|
+
import UniversalHttpAdapter from './UniversalHttpAdapter'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adapter factory for selecting the appropriate HTTP adapter
|
|
7
|
+
* Uses universal Fetch API when available with fallbacks for specific runtimes
|
|
8
|
+
*/
|
|
9
|
+
export class AdapterFactory {
|
|
10
|
+
private static adapters: Map<RuntimeType, HttpAdapter> = new Map()
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get or create adapter for current runtime
|
|
14
|
+
*/
|
|
15
|
+
static getAdapter(): HttpAdapter {
|
|
16
|
+
if (!this.adapters.has(currentRuntime)) {
|
|
17
|
+
this.adapters.set(currentRuntime, new UniversalHttpAdapter())
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const adapter = this.adapters.get(currentRuntime)!
|
|
21
|
+
|
|
22
|
+
if (!adapter.isSupported()) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`No supported HTTP adapter found for runtime: ${currentRuntime}`
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return adapter
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register custom adapter for specific runtime
|
|
33
|
+
*/
|
|
34
|
+
static registerAdapter(runtime: RuntimeType, adapter: HttpAdapter): void {
|
|
35
|
+
this.adapters.set(runtime, adapter)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Clear adapter cache
|
|
40
|
+
*/
|
|
41
|
+
static clearCache(): void {
|
|
42
|
+
this.adapters.clear()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default AdapterFactory
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AziosRequestConfig } from '../types/config'
|
|
2
|
+
import type { AziosResponse } from '../types/response'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Universal HTTP adapter interface
|
|
6
|
+
* Abstracts HTTP functionality across different runtimes
|
|
7
|
+
*/
|
|
8
|
+
export interface HttpAdapter {
|
|
9
|
+
/**
|
|
10
|
+
* Execute an HTTP request
|
|
11
|
+
*/
|
|
12
|
+
request(config: AziosRequestConfig): Promise<AziosResponse>
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Method to check if adapter supports the current runtime
|
|
16
|
+
*/
|
|
17
|
+
isSupported(): boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Base adapter class with common logic
|
|
22
|
+
*/
|
|
23
|
+
export abstract class BaseAdapter implements HttpAdapter {
|
|
24
|
+
abstract request(config: AziosRequestConfig): Promise<AziosResponse>
|
|
25
|
+
abstract isSupported(): boolean
|
|
26
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { AziosRequestConfig } from '../types/config'
|
|
2
|
+
import type { AziosResponse } from '../types/response'
|
|
3
|
+
import { BaseAdapter } from './HttpAdapter'
|
|
4
|
+
import AziosError from '../errors/AziosError'
|
|
5
|
+
import { isRuntime, RuntimeType } from './detectRuntime'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Unified HTTP adapter using Fetch API
|
|
9
|
+
* Works across Node 18+, browsers, Bun, Deno, and edge runtimes
|
|
10
|
+
* Falls back to runtime-specific implementations if needed
|
|
11
|
+
*/
|
|
12
|
+
export class UniversalHttpAdapter extends BaseAdapter {
|
|
13
|
+
/**
|
|
14
|
+
* Check if Fetch API is available
|
|
15
|
+
*/
|
|
16
|
+
isSupported(): boolean {
|
|
17
|
+
return typeof fetch !== 'undefined'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Execute HTTP request using Fetch API
|
|
22
|
+
*/
|
|
23
|
+
async request(config: AziosRequestConfig): Promise<AziosResponse> {
|
|
24
|
+
if (!this.isSupported()) {
|
|
25
|
+
throw new AziosError(
|
|
26
|
+
'Fetch API is not available in this runtime',
|
|
27
|
+
'UNSUPPORTED_RUNTIME',
|
|
28
|
+
config
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const { url, method = 'GET', headers, data, timeout, signal } = config
|
|
34
|
+
|
|
35
|
+
const baseURL = config.baseURL ? config.baseURL : ''
|
|
36
|
+
const fullURL = new URL(baseURL + url)
|
|
37
|
+
|
|
38
|
+
// Add query parameters
|
|
39
|
+
if (config.params) {
|
|
40
|
+
Object.entries(config.params).forEach(([key, value]) => {
|
|
41
|
+
if (value !== null && value !== undefined) {
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
value.forEach(v => fullURL.searchParams.append(key, String(v)))
|
|
44
|
+
} else {
|
|
45
|
+
fullURL.searchParams.set(key, String(value))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Prepare request body
|
|
52
|
+
let body: string | null = null
|
|
53
|
+
if (data) {
|
|
54
|
+
body = typeof data === 'string' ? data : JSON.stringify(data)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Set up timeout if specified (using AbortController)
|
|
58
|
+
let timeoutId: NodeJS.Timeout | undefined
|
|
59
|
+
const controller = new AbortController()
|
|
60
|
+
const finalSignal = signal || controller.signal
|
|
61
|
+
|
|
62
|
+
if (timeout) {
|
|
63
|
+
timeoutId = setTimeout(() => {
|
|
64
|
+
controller.abort()
|
|
65
|
+
}, timeout)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Execute fetch
|
|
69
|
+
const response = await fetch(fullURL.toString(), {
|
|
70
|
+
method,
|
|
71
|
+
headers: {
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
...headers
|
|
74
|
+
},
|
|
75
|
+
body,
|
|
76
|
+
signal: finalSignal as any
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
if (timeoutId) {
|
|
80
|
+
clearTimeout(timeoutId)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Parse response body
|
|
84
|
+
let responseData: any
|
|
85
|
+
|
|
86
|
+
if (response.status === 204) {
|
|
87
|
+
// No content
|
|
88
|
+
responseData = null
|
|
89
|
+
} else {
|
|
90
|
+
const contentType = response.headers.get('content-type')
|
|
91
|
+
|
|
92
|
+
if (contentType?.includes('application/json')) {
|
|
93
|
+
try {
|
|
94
|
+
responseData = await response.json()
|
|
95
|
+
} catch {
|
|
96
|
+
responseData = await response.text()
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
responseData = await response.text()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const aziosResponse: AziosResponse = {
|
|
104
|
+
data: responseData,
|
|
105
|
+
status: response.status,
|
|
106
|
+
statusText: response.statusText,
|
|
107
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
108
|
+
config
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return aziosResponse
|
|
112
|
+
} catch (err) {
|
|
113
|
+
if (err instanceof TypeError && err.message.includes('aborted')) {
|
|
114
|
+
throw new AziosError(
|
|
115
|
+
'Request aborted',
|
|
116
|
+
'ABORTED',
|
|
117
|
+
config
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (err instanceof AziosError) {
|
|
122
|
+
throw err
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
throw new AziosError(
|
|
126
|
+
err instanceof Error ? err.message : 'Network request failed',
|
|
127
|
+
'NETWORK_ERROR',
|
|
128
|
+
config,
|
|
129
|
+
undefined,
|
|
130
|
+
err instanceof Error ? err : new Error(String(err))
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default UniversalHttpAdapter
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime detection utilities
|
|
3
|
+
* Identifies the current JavaScript runtime environment
|
|
4
|
+
* Supports: Node.js, Browser, Bun, Deno, Cloudflare Workers/Edge
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export enum RuntimeType {
|
|
8
|
+
Node = 'node',
|
|
9
|
+
Browser = 'browser',
|
|
10
|
+
Bun = 'bun',
|
|
11
|
+
Deno = 'deno',
|
|
12
|
+
Edge = 'edge',
|
|
13
|
+
Unknown = 'unknown'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Detects the current runtime environment
|
|
18
|
+
* Production-grade detection with reliable environment checks
|
|
19
|
+
*/
|
|
20
|
+
export function detectRuntime(): RuntimeType {
|
|
21
|
+
// Check for Deno
|
|
22
|
+
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
23
|
+
return RuntimeType.Deno
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check for Bun
|
|
27
|
+
if (typeof (globalThis as any).Bun !== 'undefined') {
|
|
28
|
+
return RuntimeType.Bun
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check for Cloudflare Workers / Edge
|
|
32
|
+
if (
|
|
33
|
+
typeof (globalThis as any).caches !== 'undefined' &&
|
|
34
|
+
typeof (globalThis as any).ENVIRONMENT !== 'undefined'
|
|
35
|
+
) {
|
|
36
|
+
return RuntimeType.Edge
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Check for Node.js
|
|
40
|
+
if (
|
|
41
|
+
typeof process !== 'undefined' &&
|
|
42
|
+
process.versions &&
|
|
43
|
+
process.versions.node
|
|
44
|
+
) {
|
|
45
|
+
return RuntimeType.Node
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Check for Browser
|
|
49
|
+
if (typeof (globalThis as any).window !== 'undefined' && typeof (globalThis as any).document !== 'undefined') {
|
|
50
|
+
return RuntimeType.Browser
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return RuntimeType.Unknown
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get current runtime for use in adapters
|
|
58
|
+
*/
|
|
59
|
+
export const currentRuntime = detectRuntime()
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check if running in a specific runtime
|
|
63
|
+
*/
|
|
64
|
+
export function isRuntime(runtime: RuntimeType): boolean {
|
|
65
|
+
return currentRuntime === runtime
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if running in server-side runtime
|
|
70
|
+
*/
|
|
71
|
+
export function isServerRuntime(): boolean {
|
|
72
|
+
return (
|
|
73
|
+
currentRuntime === RuntimeType.Node ||
|
|
74
|
+
currentRuntime === RuntimeType.Bun ||
|
|
75
|
+
currentRuntime === RuntimeType.Deno ||
|
|
76
|
+
currentRuntime === RuntimeType.Edge
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Check if running in browser runtime
|
|
82
|
+
*/
|
|
83
|
+
export function isBrowserRuntime(): boolean {
|
|
84
|
+
return currentRuntime === RuntimeType.Browser
|
|
85
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface AziosRequestConfig {
|
|
2
|
+
|
|
3
|
+
url?: string
|
|
4
|
+
method?: string
|
|
5
|
+
|
|
6
|
+
baseURL?: string
|
|
7
|
+
|
|
8
|
+
headers?: Record<string, any>
|
|
9
|
+
|
|
10
|
+
params?: Record<string, any>
|
|
11
|
+
|
|
12
|
+
data?: any
|
|
13
|
+
|
|
14
|
+
timeout?: number
|
|
15
|
+
|
|
16
|
+
responseType?: string
|
|
17
|
+
|
|
18
|
+
signal?: AbortSignal
|
|
19
|
+
|
|
20
|
+
// Sprint 3
|
|
21
|
+
retry?: number
|
|
22
|
+
retryDelay?: number
|
|
23
|
+
|
|
24
|
+
// Sprint 4
|
|
25
|
+
cache?: boolean
|
|
26
|
+
cacheTTL?: number
|
|
27
|
+
|
|
28
|
+
rateLimit?: number
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AziosRequestConfig } from './config'
|
|
2
|
+
import { AziosResponse } from './response'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Middleware function type for request/response processing
|
|
6
|
+
* Koa-style middleware pattern that receives context and next function
|
|
7
|
+
*/
|
|
8
|
+
export type AziosMiddleware = (
|
|
9
|
+
config: AziosRequestConfig,
|
|
10
|
+
next: (cfg?: AziosRequestConfig) => Promise<AziosResponse>
|
|
11
|
+
) => Promise<AziosResponse>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Middleware context for tracking state across pipeline
|
|
15
|
+
*/
|
|
16
|
+
export interface MiddlewareContext {
|
|
17
|
+
startTime?: number
|
|
18
|
+
endTime?: number
|
|
19
|
+
config: AziosRequestConfig
|
|
20
|
+
metadata?: Record<string, any>
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AziosRequestConfig } from './config'
|
|
2
|
+
import { AziosResponse } from './response'
|
|
3
|
+
import type { AziosInstance } from './request'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Plugin lifecycle hooks
|
|
7
|
+
* Allows plugins to inject behavior at various stages of the request/response pipeline
|
|
8
|
+
*/
|
|
9
|
+
export interface PluginHooks {
|
|
10
|
+
/**
|
|
11
|
+
* Called when plugin is installed
|
|
12
|
+
*/
|
|
13
|
+
onInstall?(instance: AziosInstance): void | Promise<void>
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Called before request is sent
|
|
17
|
+
*/
|
|
18
|
+
beforeRequest?(config: AziosRequestConfig): AziosRequestConfig | Promise<AziosRequestConfig>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Called after response is received
|
|
22
|
+
*/
|
|
23
|
+
afterResponse?(response: AziosResponse): AziosResponse | Promise<AziosResponse>
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Called when an error occurs
|
|
27
|
+
*/
|
|
28
|
+
onError?(error: Error): Error | Promise<Error>
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Called when plugin is uninstalled
|
|
32
|
+
*/
|
|
33
|
+
onUninstall?(instance: AziosInstance): void | Promise<void>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Plugin definition with metadata
|
|
38
|
+
*/
|
|
39
|
+
export interface AziosPlugin {
|
|
40
|
+
name: string
|
|
41
|
+
version?: string
|
|
42
|
+
hooks: PluginHooks
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Plugin registry to track installed plugins
|
|
47
|
+
*/
|
|
48
|
+
export interface PluginRegistry {
|
|
49
|
+
[key: string]: AziosPlugin
|
|
50
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AziosRequestConfig } from "./config"
|
|
2
|
+
import { AziosResponse } from "./response"
|
|
3
|
+
import InterceptorManager from "../interceptors/InterceptorManager"
|
|
4
|
+
import type { AziosPlugin } from "./plugin"
|
|
5
|
+
import type { AziosMiddleware } from "./middleware"
|
|
6
|
+
|
|
7
|
+
export interface AziosInstance {
|
|
8
|
+
|
|
9
|
+
(config: AziosRequestConfig): Promise<AziosResponse>
|
|
10
|
+
|
|
11
|
+
request(config: AziosRequestConfig): Promise<AziosResponse>
|
|
12
|
+
|
|
13
|
+
get(url: string, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
14
|
+
|
|
15
|
+
post(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
16
|
+
|
|
17
|
+
put(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
18
|
+
|
|
19
|
+
patch(url: string, data?: any, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
20
|
+
|
|
21
|
+
delete(url: string, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
22
|
+
|
|
23
|
+
head(url: string, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
24
|
+
|
|
25
|
+
options(url: string, config?: AziosRequestConfig): Promise<AziosResponse>
|
|
26
|
+
|
|
27
|
+
interceptors: {
|
|
28
|
+
request: InterceptorManager<AziosRequestConfig>
|
|
29
|
+
response: InterceptorManager<AziosResponse>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Plugin system
|
|
33
|
+
installPlugin(plugin: AziosPlugin): Promise<void>
|
|
34
|
+
uninstallPlugin(name: string): Promise<void>
|
|
35
|
+
|
|
36
|
+
// Middleware system
|
|
37
|
+
use(middleware: AziosMiddleware): void
|
|
38
|
+
|
|
39
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AziosRequestConfig } from "./config"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Azios HTTP response object
|
|
5
|
+
* Returned by all request methods
|
|
6
|
+
*/
|
|
7
|
+
export interface AziosResponse<T = any> {
|
|
8
|
+
/**
|
|
9
|
+
* Response data (parsed if JSON)
|
|
10
|
+
*/
|
|
11
|
+
data: T
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* HTTP status code
|
|
15
|
+
*/
|
|
16
|
+
status: number
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* HTTP status text
|
|
20
|
+
*/
|
|
21
|
+
statusText: string
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Response headers
|
|
25
|
+
*/
|
|
26
|
+
headers: Record<string, any>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Original request config
|
|
30
|
+
*/
|
|
31
|
+
config: AziosRequestConfig
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Native request object (if available)
|
|
35
|
+
*/
|
|
36
|
+
request?: any
|
|
37
|
+
}
|