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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +92 -267
  3. package/dist/cache/memoryCache.d.ts +1 -0
  4. package/dist/cache/memoryCache.js +7 -1
  5. package/dist/cache/memoryCache.js.map +1 -1
  6. package/dist/core/Azios.d.ts +33 -8
  7. package/dist/core/Azios.js +68 -2
  8. package/dist/core/Azios.js.map +1 -1
  9. package/dist/core/dispatchRequest.js +10 -75
  10. package/dist/core/dispatchRequest.js.map +1 -1
  11. package/dist/index.d.ts +15 -0
  12. package/dist/index.js +50 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/middleware/MiddlewarePipeline.d.ts +54 -0
  15. package/dist/middleware/MiddlewarePipeline.js +122 -0
  16. package/dist/middleware/MiddlewarePipeline.js.map +1 -0
  17. package/dist/middleware/compose.d.ts +1 -0
  18. package/dist/middleware/compose.js +25 -0
  19. package/dist/middleware/compose.js.map +1 -0
  20. package/dist/middleware/middlewareManager.d.ts +4 -0
  21. package/dist/middleware/middlewareManager.js +12 -0
  22. package/dist/middleware/middlewareManager.js.map +1 -0
  23. package/dist/plugins/pluginManager.d.ts +44 -0
  24. package/dist/plugins/pluginManager.js +120 -0
  25. package/dist/plugins/pluginManager.js.map +1 -0
  26. package/dist/runtimes/AdapterFactory.d.ts +22 -0
  27. package/dist/runtimes/AdapterFactory.js +43 -0
  28. package/dist/runtimes/AdapterFactory.js.map +1 -0
  29. package/dist/runtimes/HttpAdapter.d.ts +23 -0
  30. package/dist/runtimes/HttpAdapter.js +10 -0
  31. package/dist/runtimes/HttpAdapter.js.map +1 -0
  32. package/dist/runtimes/UniversalHttpAdapter.d.ts +19 -0
  33. package/dist/runtimes/UniversalHttpAdapter.js +114 -0
  34. package/dist/runtimes/UniversalHttpAdapter.js.map +1 -0
  35. package/dist/runtimes/detectRuntime.d.ts +34 -0
  36. package/dist/runtimes/detectRuntime.js +77 -0
  37. package/dist/runtimes/detectRuntime.js.map +1 -0
  38. package/dist/types/index.d.ts +5 -0
  39. package/dist/types/index.js +22 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/dist/types/middleware.d.ts +16 -0
  42. package/dist/types/middleware.js +3 -0
  43. package/dist/types/middleware.js.map +1 -0
  44. package/dist/types/plugin.d.ts +43 -0
  45. package/dist/types/plugin.js +3 -0
  46. package/dist/types/plugin.js.map +1 -0
  47. package/dist/types/request.d.ts +5 -0
  48. package/dist/types/response.d.ts +23 -1
  49. package/package.json +24 -5
  50. package/src/adapters/httpAdapter.ts +0 -0
  51. package/src/adapters/index.ts +0 -0
  52. package/src/adapters/xhrAdapter.ts +0 -0
  53. package/src/cache/memoryCache.ts +45 -0
  54. package/src/config/mergeConfig.ts +0 -0
  55. package/src/core/Azios.ts +184 -0
  56. package/src/core/createInstance.ts +23 -0
  57. package/src/core/dispatchRequest.ts +111 -0
  58. package/src/core/requestMethods.ts +0 -0
  59. package/src/core/requestStore.ts +13 -0
  60. package/src/errors/AziosError.ts +26 -0
  61. package/src/helpers/buildURL.ts +44 -0
  62. package/src/helpers/normalizeHeaders.ts +0 -0
  63. package/src/helpers/parseHeaders.ts +0 -0
  64. package/src/index.ts +64 -0
  65. package/src/interceptors/InterceptorManager.ts +30 -0
  66. package/src/middleware/MiddlewarePipeline.ts +155 -0
  67. package/src/middleware/compose.ts +33 -0
  68. package/src/middleware/middlewareManager.ts +9 -0
  69. package/src/plugins/pluginManager.ts +143 -0
  70. package/src/rateLimiter/rateLimiter.ts +36 -0
  71. package/src/runtimes/AdapterFactory.ts +46 -0
  72. package/src/runtimes/HttpAdapter.ts +26 -0
  73. package/src/runtimes/UniversalHttpAdapter.ts +136 -0
  74. package/src/runtimes/detectRuntime.ts +85 -0
  75. package/src/types/config.ts +30 -0
  76. package/src/types/index.ts +5 -0
  77. package/src/types/middleware.ts +21 -0
  78. package/src/types/plugin.ts +50 -0
  79. package/src/types/request.ts +39 -0
  80. package/src/types/response.ts +37 -0
@@ -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
@@ -0,0 +1,30 @@
1
+ type FulfilledFn<T> = (val: T) => T | Promise<T>
2
+ type RejectedFn = (error: any) => any
3
+
4
+ interface Interceptor<T> {
5
+ fulfilled: FulfilledFn<T>
6
+ rejected?: RejectedFn
7
+ }
8
+
9
+ export default class InterceptorManager<T> {
10
+
11
+ private handlers: Array<Interceptor<T> | null> = []
12
+
13
+ use(fulfilled: FulfilledFn<T>, rejected?: RejectedFn) {
14
+ this.handlers.push({
15
+ fulfilled,
16
+ rejected
17
+ })
18
+
19
+ return this.handlers.length - 1
20
+ }
21
+
22
+ forEach(fn: (interceptor: Interceptor<T>) => void) {
23
+ this.handlers.forEach(h => {
24
+ if (h !== null) {
25
+ fn(h)
26
+ }
27
+ })
28
+ }
29
+
30
+ }
@@ -0,0 +1,155 @@
1
+ import type { AziosRequestConfig } from '../types/config'
2
+ import type { AziosResponse } from '../types/response'
3
+
4
+ /**
5
+ * Middleware handler types
6
+ * Supports async middleware in the style of Koa
7
+ */
8
+ export type RequestMiddleware = (
9
+ config: AziosRequestConfig,
10
+ next: () => Promise<AziosResponse>
11
+ ) => Promise<AziosResponse>
12
+
13
+ export type ResponseMiddleware = (
14
+ response: AziosResponse,
15
+ next: () => Promise<AziosResponse>
16
+ ) => Promise<AziosResponse>
17
+
18
+ /**
19
+ * Composition utility for middleware chaining
20
+ * Implements Koa-style middleware flow control
21
+ */
22
+ export class MiddlewarePipeline {
23
+ private requestMiddleware: RequestMiddleware[] = []
24
+ private responseMiddleware: ResponseMiddleware[] = []
25
+
26
+ /**
27
+ * Add request middleware
28
+ * Middleware will execute in registration order
29
+ */
30
+ useRequest(middleware: RequestMiddleware): this {
31
+ this.requestMiddleware.push(middleware)
32
+ return this
33
+ }
34
+
35
+ /**
36
+ * Add response middleware
37
+ * Middleware will execute in registration order
38
+ */
39
+ useResponse(middleware: ResponseMiddleware): this {
40
+ this.responseMiddleware.push(middleware)
41
+ return this
42
+ }
43
+
44
+ /**
45
+ * Compose request middleware with proper async error handling
46
+ */
47
+ private composeRequest(): RequestMiddleware {
48
+ const middleware = this.requestMiddleware
49
+
50
+ return async (config: AziosRequestConfig, next: () => Promise<AziosResponse>) => {
51
+ let index = -1
52
+
53
+ const dispatch = async (i: number): Promise<AziosResponse> => {
54
+ if (i <= index) {
55
+ throw new Error('next() called multiple times in middleware')
56
+ }
57
+
58
+ index = i
59
+
60
+ try {
61
+ if (i < middleware.length) {
62
+ return await middleware[i](config, () => dispatch(i + 1))
63
+ } else {
64
+ return await next()
65
+ }
66
+ } catch (err) {
67
+ throw err
68
+ }
69
+ }
70
+
71
+ return dispatch(0)
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Compose response middleware with proper async error handling
77
+ */
78
+ private composeResponse(): ResponseMiddleware {
79
+ const middleware = this.responseMiddleware
80
+
81
+ return async (response: AziosResponse, next: () => Promise<AziosResponse>) => {
82
+ let index = -1
83
+
84
+ const dispatch = async (i: number): Promise<AziosResponse> => {
85
+ if (i <= index) {
86
+ throw new Error('next() called multiple times in middleware')
87
+ }
88
+
89
+ index = i
90
+
91
+ try {
92
+ if (i < middleware.length) {
93
+ return await middleware[i](response, () => dispatch(i + 1))
94
+ } else {
95
+ return await next()
96
+ }
97
+ } catch (err) {
98
+ throw err
99
+ }
100
+ }
101
+
102
+ return dispatch(0)
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Execute request middleware pipeline
108
+ */
109
+ async executeRequestMiddleware(
110
+ config: AziosRequestConfig,
111
+ next: () => Promise<AziosResponse>
112
+ ): Promise<AziosResponse> {
113
+ if (this.requestMiddleware.length === 0) {
114
+ return next()
115
+ }
116
+
117
+ const composed = this.composeRequest()
118
+ return composed(config, next)
119
+ }
120
+
121
+ /**
122
+ * Execute response middleware pipeline
123
+ */
124
+ async executeResponseMiddleware(
125
+ response: AziosResponse,
126
+ next: () => Promise<AziosResponse>
127
+ ): Promise<AziosResponse> {
128
+ if (this.responseMiddleware.length === 0) {
129
+ return next()
130
+ }
131
+
132
+ const composed = this.composeResponse()
133
+ return composed(response, next)
134
+ }
135
+
136
+ /**
137
+ * Clear all middleware
138
+ */
139
+ clear(): void {
140
+ this.requestMiddleware = []
141
+ this.responseMiddleware = []
142
+ }
143
+
144
+ /**
145
+ * Get registered middleware count
146
+ */
147
+ getMiddlewareCount(): { request: number; response: number } {
148
+ return {
149
+ request: this.requestMiddleware.length,
150
+ response: this.responseMiddleware.length
151
+ }
152
+ }
153
+ }
154
+
155
+ export default MiddlewarePipeline
@@ -0,0 +1,33 @@
1
+ export function compose(middleware: any[]) {
2
+
3
+ return function (context: any) {
4
+
5
+ let index = -1
6
+
7
+ function dispatch(i: number): Promise<any> {
8
+
9
+ if (i <= index) {
10
+ return Promise.reject(new Error("next() called multiple times"))
11
+ }
12
+
13
+ index = i
14
+
15
+ const fn = middleware[i]
16
+
17
+ if (!fn) return Promise.resolve()
18
+
19
+ try {
20
+ return Promise.resolve(
21
+ fn(context, () => dispatch(i + 1))
22
+ )
23
+ } catch (err) {
24
+ return Promise.reject(err)
25
+ }
26
+
27
+ }
28
+
29
+ return dispatch(0)
30
+
31
+ }
32
+
33
+ }
@@ -0,0 +1,9 @@
1
+ export default class MiddlewareManager {
2
+
3
+ middlewares: any[] = []
4
+
5
+ use(fn: any) {
6
+ this.middlewares.push(fn)
7
+ }
8
+
9
+ }