@leancodepl/axios-cqrs-client 8.5.0 → 8.6.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/README.md +111 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +194 -0
- package/index.cjs.mjs +2 -0
- package/index.d.ts +1 -0
- package/index.esm.js +191 -0
- package/package.json +3 -8
- package/src/index.d.ts +2 -0
- package/src/lib/mkCqrsClient.d.ts +45 -0
- package/src/lib/mkUncapitalizedCqrsClient.d.ts +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @leancodepl/axios-cqrs-client
|
|
2
|
+
|
|
3
|
+
CQRS client with Axios for HTTP communication and command/query handling.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @leancodepl/axios-cqrs-client
|
|
9
|
+
# or
|
|
10
|
+
yarn add @leancodepl/axios-cqrs-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## API
|
|
14
|
+
|
|
15
|
+
### `mkCqrsClient(cqrsEndpoint, tokenProvider, axiosOptions, tokenHeader)`
|
|
16
|
+
|
|
17
|
+
Creates CQRS client with Axios for HTTP communication and command/query handling.
|
|
18
|
+
|
|
19
|
+
**Parameters:**
|
|
20
|
+
|
|
21
|
+
- `cqrsEndpoint: string` - Base URL for CQRS API endpoints
|
|
22
|
+
- `tokenProvider?: TokenProvider` - Optional token provider for authentication
|
|
23
|
+
- `axiosOptions?: CreateAxiosDefaults` - Optional Axios configuration options
|
|
24
|
+
- `tokenHeader?: string` - Header name for authentication token (default: "Authorization")
|
|
25
|
+
|
|
26
|
+
**Returns:** Object with `createQuery`, `createOperation`, and `createCommand` methods
|
|
27
|
+
|
|
28
|
+
### `mkUncapitalizedCqrsClient(params)`
|
|
29
|
+
|
|
30
|
+
Creates CQRS client with automatic response key uncapitalization using "@leancodepl/utils".
|
|
31
|
+
|
|
32
|
+
**Parameters:**
|
|
33
|
+
|
|
34
|
+
- `params: MkCqrsClientParameters` - Configuration object for CQRS client
|
|
35
|
+
- `params.cqrsEndpoint: string` - Base URL for CQRS API endpoints
|
|
36
|
+
- `params.tokenProvider?: TokenProvider` - Optional token provider for authentication
|
|
37
|
+
- `params.axiosOptions?: CreateAxiosDefaults` - Optional Axios configuration options
|
|
38
|
+
- `params.tokenHeader?: string` - Header name for authentication token (default: "Authorization")
|
|
39
|
+
|
|
40
|
+
**Returns:** CQRS client with response key transformation
|
|
41
|
+
|
|
42
|
+
## Usage Examples
|
|
43
|
+
|
|
44
|
+
### Basic Setup
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { mkCqrsClient } from "@leancodepl/axios-cqrs-client"
|
|
48
|
+
|
|
49
|
+
const client = mkCqrsClient({
|
|
50
|
+
cqrsEndpoint: "https://api.example.com",
|
|
51
|
+
tokenProvider: {
|
|
52
|
+
getToken: () => Promise.resolve(localStorage.getItem("token")),
|
|
53
|
+
invalidateToken: () => Promise.resolve(true),
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Query Operations
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
interface GetUserQuery {
|
|
62
|
+
userId: string
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface UserResult {
|
|
66
|
+
id: string
|
|
67
|
+
name: string
|
|
68
|
+
email: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const getUser = client.createQuery<GetUserQuery, UserResult>("GetUser")
|
|
72
|
+
|
|
73
|
+
const response = await getUser({ userId: "123" })
|
|
74
|
+
|
|
75
|
+
if (response.isSuccess) {
|
|
76
|
+
console.log("User:", response.result)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Command Operations
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface CreateUserCommand {
|
|
84
|
+
name: string
|
|
85
|
+
email: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const errorCodes = { EmailExists: 1, InvalidEmail: 2 } as const
|
|
89
|
+
const createUser = client.createCommand<CreateUserCommand, typeof errorCodes>("CreateUser", errorCodes)
|
|
90
|
+
|
|
91
|
+
const response = await createUser({ name: "John", email: "john@example.com" })
|
|
92
|
+
|
|
93
|
+
createUser
|
|
94
|
+
.handle({ name: "John", email: "john@example.com" })
|
|
95
|
+
.handle("success", () => console.log("User created"))
|
|
96
|
+
.handle("EmailExists", () => console.log("Email already exists"))
|
|
97
|
+
.check()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Uncapitalized Client
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { mkUncapitalizedCqrsClient } from "@leancodepl/axios-cqrs-client"
|
|
104
|
+
|
|
105
|
+
const client = mkUncapitalizedCqrsClient({
|
|
106
|
+
cqrsEndpoint: "https://api.example.com",
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
// Automatically transforms { UserId: '123' } to { userId: '123' }
|
|
110
|
+
const response = await client.createQuery("GetUser")({ userId: "123" })
|
|
111
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
exports._default = require('./index.cjs.js').default;
|
package/index.cjs.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var axios = require('axios');
|
|
4
|
+
var validation = require('@leancodepl/validation');
|
|
5
|
+
var utils = require('@leancodepl/utils');
|
|
6
|
+
|
|
7
|
+
function _extends() {
|
|
8
|
+
_extends = Object.assign || function assign(target) {
|
|
9
|
+
for(var i = 1; i < arguments.length; i++){
|
|
10
|
+
var source = arguments[i];
|
|
11
|
+
for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
|
|
12
|
+
}
|
|
13
|
+
return target;
|
|
14
|
+
};
|
|
15
|
+
return _extends.apply(this, arguments);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createSuccess(result) {
|
|
19
|
+
return {
|
|
20
|
+
isSuccess: true,
|
|
21
|
+
result
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createError(error, options) {
|
|
25
|
+
return {
|
|
26
|
+
isSuccess: false,
|
|
27
|
+
isAborted: !!(options == null ? void 0 : options.isAborted),
|
|
28
|
+
error
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates CQRS client with Axios for HTTP communication and command/query handling.
|
|
33
|
+
*
|
|
34
|
+
* Provides type-safe methods for creating queries, operations, and commands with automatic
|
|
35
|
+
* token management, retry logic, and response handling. Supports validation error handling
|
|
36
|
+
* and HTTP status code management.
|
|
37
|
+
*
|
|
38
|
+
* @param cqrsEndpoint - Base URL for CQRS API endpoints
|
|
39
|
+
* @param tokenProvider - Optional token provider for authentication
|
|
40
|
+
* @param axiosOptions - Optional Axios configuration options
|
|
41
|
+
* @param tokenHeader - Header name for authentication token (default: "Authorization")
|
|
42
|
+
* @returns Object with `createQuery`, `createOperation`, and `createCommand` methods
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const client = mkCqrsClient({
|
|
46
|
+
* cqrsEndpoint: 'https://api.example.com',
|
|
47
|
+
* tokenProvider: { getToken: () => Promise.resolve('token') }
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/ function mkCqrsClient({ cqrsEndpoint, tokenProvider, axiosOptions, tokenHeader = "Authorization" }) {
|
|
51
|
+
const apiAxios = axios.create(_extends({
|
|
52
|
+
baseURL: cqrsEndpoint
|
|
53
|
+
}, axiosOptions));
|
|
54
|
+
apiAxios.interceptors.request.use(async (config)=>{
|
|
55
|
+
const token = await (tokenProvider == null ? void 0 : tokenProvider.getToken());
|
|
56
|
+
if (token) {
|
|
57
|
+
var _config_headers;
|
|
58
|
+
(_config_headers = config.headers) == null ? void 0 : _config_headers.set(tokenHeader, `Bearer ${token}`);
|
|
59
|
+
}
|
|
60
|
+
return config;
|
|
61
|
+
});
|
|
62
|
+
apiAxios.interceptors.response.use((response)=>{
|
|
63
|
+
response.data = createSuccess(response.data);
|
|
64
|
+
return response;
|
|
65
|
+
}, async (error)=>{
|
|
66
|
+
if (!(error instanceof axios.AxiosError)) {
|
|
67
|
+
return {
|
|
68
|
+
data: createError(`Unknown error ${error}`)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (error.code === "ERR_CANCELED") {
|
|
72
|
+
return {
|
|
73
|
+
data: createError(error, {
|
|
74
|
+
isAborted: true
|
|
75
|
+
})
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (!error.response) {
|
|
79
|
+
return {
|
|
80
|
+
data: createError(error)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const response = error.response;
|
|
84
|
+
switch(error.response.status){
|
|
85
|
+
case 401:
|
|
86
|
+
{
|
|
87
|
+
var _config_params;
|
|
88
|
+
var _config;
|
|
89
|
+
let config = error.config;
|
|
90
|
+
if (config == null ? void 0 : (_config_params = config.params) == null ? void 0 : _config_params.isRetry) {
|
|
91
|
+
response.data = createError("The request has not been authorized and token refresh did not help");
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (!(tokenProvider == null ? void 0 : tokenProvider.invalidateToken)) {
|
|
95
|
+
response.data = createError("User needs to be authenticated to execute the command/query/operation");
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (!await tokenProvider.invalidateToken()) {
|
|
99
|
+
response.data = createError("Cannot refresh access token after the server returned 401 Unauthorized");
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
config != null ? config : config = {
|
|
103
|
+
headers: new axios.AxiosHeaders()
|
|
104
|
+
};
|
|
105
|
+
var _params;
|
|
106
|
+
(_params = (_config = config).params) != null ? _params : _config.params = {};
|
|
107
|
+
config.params.isRetry = true;
|
|
108
|
+
return await apiAxios.request(config);
|
|
109
|
+
}
|
|
110
|
+
case 400:
|
|
111
|
+
response.data = createError("The request was malformed");
|
|
112
|
+
break;
|
|
113
|
+
case 403:
|
|
114
|
+
response.data = createError("User is not authorized to execute the command/query/operation");
|
|
115
|
+
break;
|
|
116
|
+
case 404:
|
|
117
|
+
response.data = createError("Command/query/operation not found");
|
|
118
|
+
break;
|
|
119
|
+
case 422:
|
|
120
|
+
response.data = createSuccess(error.response.data);
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
response.data = createError(`Cannot execute command/query/operation, server returned a ${error.response.status} code`);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
return response;
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
createQuery (type) {
|
|
130
|
+
return (dto)=>{
|
|
131
|
+
const abortController = new AbortController();
|
|
132
|
+
const promise = apiAxios.post("query/" + type, dto, {
|
|
133
|
+
signal: abortController.signal
|
|
134
|
+
}).then((r)=>r.data);
|
|
135
|
+
promise.abort = abortController.abort.bind(abortController);
|
|
136
|
+
return promise;
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
createOperation (type) {
|
|
140
|
+
return (dto)=>apiAxios.post("operation/" + type, dto).then((r)=>r.data);
|
|
141
|
+
},
|
|
142
|
+
createCommand (type, errorCodesMap) {
|
|
143
|
+
async function call(dto) {
|
|
144
|
+
const response = await apiAxios.post("command/" + type, dto);
|
|
145
|
+
return response.data;
|
|
146
|
+
}
|
|
147
|
+
call.handle = (dto)=>call(dto).then((response)=>validation.handleResponse(response, errorCodesMap));
|
|
148
|
+
return call;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function uncapitalizeResponse(response) {
|
|
154
|
+
if (!response.isSuccess) {
|
|
155
|
+
return response;
|
|
156
|
+
}
|
|
157
|
+
return _extends({}, response, {
|
|
158
|
+
result: utils.uncapitalizeDeep(response.result)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Creates CQRS client with automatic response key uncapitalization using "@leancodepl/utils".
|
|
163
|
+
*
|
|
164
|
+
* Extends the base CQRS client to automatically transform response object keys from
|
|
165
|
+
* PascalCase to camelCase using deep transformation.
|
|
166
|
+
*
|
|
167
|
+
* @param params - Configuration object for CQRS client
|
|
168
|
+
* @param params.cqrsEndpoint - Base URL for CQRS API endpoints
|
|
169
|
+
* @param params.tokenProvider - Optional token provider for authentication
|
|
170
|
+
* @param params.axiosOptions - Optional Axios configuration options
|
|
171
|
+
* @param params.tokenHeader - Header name for authentication token (default: "Authorization")
|
|
172
|
+
* @returns CQRS client with response key transformation
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const client = mkUncapitalizedCqrsClient({
|
|
176
|
+
* cqrsEndpoint: 'https://api.example.com'
|
|
177
|
+
* });
|
|
178
|
+
* ```
|
|
179
|
+
*/ function mkUncapitalizedCqrsClient(params) {
|
|
180
|
+
const baseClient = mkCqrsClient(params);
|
|
181
|
+
return _extends({}, baseClient, {
|
|
182
|
+
createQuery (type) {
|
|
183
|
+
const query = baseClient.createQuery(type);
|
|
184
|
+
return (dto)=>query(dto).then(uncapitalizeResponse);
|
|
185
|
+
},
|
|
186
|
+
createOperation (type) {
|
|
187
|
+
const operation = baseClient.createOperation(type);
|
|
188
|
+
return (dto)=>operation(dto).then(uncapitalizeResponse);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
exports.mkCqrsClient = mkCqrsClient;
|
|
194
|
+
exports.mkUncapitalizedCqrsClient = mkUncapitalizedCqrsClient;
|
package/index.cjs.mjs
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src/index";
|
package/index.esm.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import axios, { AxiosError, AxiosHeaders } from 'axios';
|
|
2
|
+
import { handleResponse } from '@leancodepl/validation';
|
|
3
|
+
import { uncapitalizeDeep } from '@leancodepl/utils';
|
|
4
|
+
|
|
5
|
+
function _extends() {
|
|
6
|
+
_extends = Object.assign || function assign(target) {
|
|
7
|
+
for(var i = 1; i < arguments.length; i++){
|
|
8
|
+
var source = arguments[i];
|
|
9
|
+
for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
|
|
10
|
+
}
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
return _extends.apply(this, arguments);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createSuccess(result) {
|
|
17
|
+
return {
|
|
18
|
+
isSuccess: true,
|
|
19
|
+
result
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function createError(error, options) {
|
|
23
|
+
return {
|
|
24
|
+
isSuccess: false,
|
|
25
|
+
isAborted: !!(options == null ? void 0 : options.isAborted),
|
|
26
|
+
error
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates CQRS client with Axios for HTTP communication and command/query handling.
|
|
31
|
+
*
|
|
32
|
+
* Provides type-safe methods for creating queries, operations, and commands with automatic
|
|
33
|
+
* token management, retry logic, and response handling. Supports validation error handling
|
|
34
|
+
* and HTTP status code management.
|
|
35
|
+
*
|
|
36
|
+
* @param cqrsEndpoint - Base URL for CQRS API endpoints
|
|
37
|
+
* @param tokenProvider - Optional token provider for authentication
|
|
38
|
+
* @param axiosOptions - Optional Axios configuration options
|
|
39
|
+
* @param tokenHeader - Header name for authentication token (default: "Authorization")
|
|
40
|
+
* @returns Object with `createQuery`, `createOperation`, and `createCommand` methods
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const client = mkCqrsClient({
|
|
44
|
+
* cqrsEndpoint: 'https://api.example.com',
|
|
45
|
+
* tokenProvider: { getToken: () => Promise.resolve('token') }
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/ function mkCqrsClient({ cqrsEndpoint, tokenProvider, axiosOptions, tokenHeader = "Authorization" }) {
|
|
49
|
+
const apiAxios = axios.create(_extends({
|
|
50
|
+
baseURL: cqrsEndpoint
|
|
51
|
+
}, axiosOptions));
|
|
52
|
+
apiAxios.interceptors.request.use(async (config)=>{
|
|
53
|
+
const token = await (tokenProvider == null ? void 0 : tokenProvider.getToken());
|
|
54
|
+
if (token) {
|
|
55
|
+
var _config_headers;
|
|
56
|
+
(_config_headers = config.headers) == null ? void 0 : _config_headers.set(tokenHeader, `Bearer ${token}`);
|
|
57
|
+
}
|
|
58
|
+
return config;
|
|
59
|
+
});
|
|
60
|
+
apiAxios.interceptors.response.use((response)=>{
|
|
61
|
+
response.data = createSuccess(response.data);
|
|
62
|
+
return response;
|
|
63
|
+
}, async (error)=>{
|
|
64
|
+
if (!(error instanceof AxiosError)) {
|
|
65
|
+
return {
|
|
66
|
+
data: createError(`Unknown error ${error}`)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (error.code === "ERR_CANCELED") {
|
|
70
|
+
return {
|
|
71
|
+
data: createError(error, {
|
|
72
|
+
isAborted: true
|
|
73
|
+
})
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (!error.response) {
|
|
77
|
+
return {
|
|
78
|
+
data: createError(error)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const response = error.response;
|
|
82
|
+
switch(error.response.status){
|
|
83
|
+
case 401:
|
|
84
|
+
{
|
|
85
|
+
var _config_params;
|
|
86
|
+
var _config;
|
|
87
|
+
let config = error.config;
|
|
88
|
+
if (config == null ? void 0 : (_config_params = config.params) == null ? void 0 : _config_params.isRetry) {
|
|
89
|
+
response.data = createError("The request has not been authorized and token refresh did not help");
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (!(tokenProvider == null ? void 0 : tokenProvider.invalidateToken)) {
|
|
93
|
+
response.data = createError("User needs to be authenticated to execute the command/query/operation");
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (!await tokenProvider.invalidateToken()) {
|
|
97
|
+
response.data = createError("Cannot refresh access token after the server returned 401 Unauthorized");
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
config != null ? config : config = {
|
|
101
|
+
headers: new AxiosHeaders()
|
|
102
|
+
};
|
|
103
|
+
var _params;
|
|
104
|
+
(_params = (_config = config).params) != null ? _params : _config.params = {};
|
|
105
|
+
config.params.isRetry = true;
|
|
106
|
+
return await apiAxios.request(config);
|
|
107
|
+
}
|
|
108
|
+
case 400:
|
|
109
|
+
response.data = createError("The request was malformed");
|
|
110
|
+
break;
|
|
111
|
+
case 403:
|
|
112
|
+
response.data = createError("User is not authorized to execute the command/query/operation");
|
|
113
|
+
break;
|
|
114
|
+
case 404:
|
|
115
|
+
response.data = createError("Command/query/operation not found");
|
|
116
|
+
break;
|
|
117
|
+
case 422:
|
|
118
|
+
response.data = createSuccess(error.response.data);
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
response.data = createError(`Cannot execute command/query/operation, server returned a ${error.response.status} code`);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
return response;
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
createQuery (type) {
|
|
128
|
+
return (dto)=>{
|
|
129
|
+
const abortController = new AbortController();
|
|
130
|
+
const promise = apiAxios.post("query/" + type, dto, {
|
|
131
|
+
signal: abortController.signal
|
|
132
|
+
}).then((r)=>r.data);
|
|
133
|
+
promise.abort = abortController.abort.bind(abortController);
|
|
134
|
+
return promise;
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
createOperation (type) {
|
|
138
|
+
return (dto)=>apiAxios.post("operation/" + type, dto).then((r)=>r.data);
|
|
139
|
+
},
|
|
140
|
+
createCommand (type, errorCodesMap) {
|
|
141
|
+
async function call(dto) {
|
|
142
|
+
const response = await apiAxios.post("command/" + type, dto);
|
|
143
|
+
return response.data;
|
|
144
|
+
}
|
|
145
|
+
call.handle = (dto)=>call(dto).then((response)=>handleResponse(response, errorCodesMap));
|
|
146
|
+
return call;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function uncapitalizeResponse(response) {
|
|
152
|
+
if (!response.isSuccess) {
|
|
153
|
+
return response;
|
|
154
|
+
}
|
|
155
|
+
return _extends({}, response, {
|
|
156
|
+
result: uncapitalizeDeep(response.result)
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Creates CQRS client with automatic response key uncapitalization using "@leancodepl/utils".
|
|
161
|
+
*
|
|
162
|
+
* Extends the base CQRS client to automatically transform response object keys from
|
|
163
|
+
* PascalCase to camelCase using deep transformation.
|
|
164
|
+
*
|
|
165
|
+
* @param params - Configuration object for CQRS client
|
|
166
|
+
* @param params.cqrsEndpoint - Base URL for CQRS API endpoints
|
|
167
|
+
* @param params.tokenProvider - Optional token provider for authentication
|
|
168
|
+
* @param params.axiosOptions - Optional Axios configuration options
|
|
169
|
+
* @param params.tokenHeader - Header name for authentication token (default: "Authorization")
|
|
170
|
+
* @returns CQRS client with response key transformation
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* const client = mkUncapitalizedCqrsClient({
|
|
174
|
+
* cqrsEndpoint: 'https://api.example.com'
|
|
175
|
+
* });
|
|
176
|
+
* ```
|
|
177
|
+
*/ function mkUncapitalizedCqrsClient(params) {
|
|
178
|
+
const baseClient = mkCqrsClient(params);
|
|
179
|
+
return _extends({}, baseClient, {
|
|
180
|
+
createQuery (type) {
|
|
181
|
+
const query = baseClient.createQuery(type);
|
|
182
|
+
return (dto)=>query(dto).then(uncapitalizeResponse);
|
|
183
|
+
},
|
|
184
|
+
createOperation (type) {
|
|
185
|
+
const operation = baseClient.createOperation(type);
|
|
186
|
+
return (dto)=>operation(dto).then(uncapitalizeResponse);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export { mkCqrsClient, mkUncapitalizedCqrsClient };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leancodepl/axios-cqrs-client",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.6.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"node": ">=18.0.0"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@leancodepl/cqrs-client-base": "8.
|
|
14
|
-
"@leancodepl/validation": "8.
|
|
13
|
+
"@leancodepl/cqrs-client-base": "8.6.0",
|
|
14
|
+
"@leancodepl/validation": "8.6.0",
|
|
15
15
|
"axios": ">=1.6.0"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
@@ -39,11 +39,6 @@
|
|
|
39
39
|
"name": "LeanCode",
|
|
40
40
|
"url": "https://leancode.co"
|
|
41
41
|
},
|
|
42
|
-
"files": [
|
|
43
|
-
"dist",
|
|
44
|
-
"README.md",
|
|
45
|
-
"CHANGELOG.md"
|
|
46
|
-
],
|
|
47
42
|
"sideEffects": false,
|
|
48
43
|
"exports": {
|
|
49
44
|
"./package.json": "./package.json",
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CreateAxiosDefaults } from "axios";
|
|
2
|
+
import { ApiError, ApiResponse, ApiSuccess, CommandResult, TokenProvider } from "@leancodepl/cqrs-client-base";
|
|
3
|
+
export type MkCqrsClientParameters = {
|
|
4
|
+
cqrsEndpoint: string;
|
|
5
|
+
tokenProvider?: TokenProvider;
|
|
6
|
+
axiosOptions?: CreateAxiosDefaults;
|
|
7
|
+
tokenHeader?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Creates CQRS client with Axios for HTTP communication and command/query handling.
|
|
11
|
+
*
|
|
12
|
+
* Provides type-safe methods for creating queries, operations, and commands with automatic
|
|
13
|
+
* token management, retry logic, and response handling. Supports validation error handling
|
|
14
|
+
* and HTTP status code management.
|
|
15
|
+
*
|
|
16
|
+
* @param cqrsEndpoint - Base URL for CQRS API endpoints
|
|
17
|
+
* @param tokenProvider - Optional token provider for authentication
|
|
18
|
+
* @param axiosOptions - Optional Axios configuration options
|
|
19
|
+
* @param tokenHeader - Header name for authentication token (default: "Authorization")
|
|
20
|
+
* @returns Object with `createQuery`, `createOperation`, and `createCommand` methods
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const client = mkCqrsClient({
|
|
24
|
+
* cqrsEndpoint: 'https://api.example.com',
|
|
25
|
+
* tokenProvider: { getToken: () => Promise.resolve('token') }
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function mkCqrsClient({ cqrsEndpoint, tokenProvider, axiosOptions, tokenHeader, }: MkCqrsClientParameters): {
|
|
30
|
+
createQuery<TQuery, TResult>(type: string): (dto: TQuery) => QueryPromise<TResult>;
|
|
31
|
+
createOperation<TOperation, TResult>(type: string): (dto: TOperation) => Promise<ApiError | ApiSuccess<TResult>>;
|
|
32
|
+
createCommand<TCommand, TErrorCodes extends {
|
|
33
|
+
[name: string]: number;
|
|
34
|
+
}>(type: string, errorCodesMap: TErrorCodes): {
|
|
35
|
+
(dto: TCommand): Promise<ApiResponse<CommandResult<TErrorCodes>>>;
|
|
36
|
+
handle(dto: TCommand): Promise<import("@leancodepl/validation").ValidationErrorsHandler<TErrorCodes & {
|
|
37
|
+
readonly success: -1;
|
|
38
|
+
readonly failure: -2;
|
|
39
|
+
}, never>>;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export type QueryAbort = {
|
|
43
|
+
abort: AbortController["abort"];
|
|
44
|
+
};
|
|
45
|
+
export type QueryPromise<TResult> = Promise<ApiResponse<TResult>> & QueryAbort;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ApiResponse } from "@leancodepl/cqrs-client-base";
|
|
2
|
+
import { type MkCqrsClientParameters } from "./mkCqrsClient";
|
|
3
|
+
/**
|
|
4
|
+
* Creates CQRS client with automatic response key uncapitalization using "@leancodepl/utils".
|
|
5
|
+
*
|
|
6
|
+
* Extends the base CQRS client to automatically transform response object keys from
|
|
7
|
+
* PascalCase to camelCase using deep transformation.
|
|
8
|
+
*
|
|
9
|
+
* @param params - Configuration object for CQRS client
|
|
10
|
+
* @param params.cqrsEndpoint - Base URL for CQRS API endpoints
|
|
11
|
+
* @param params.tokenProvider - Optional token provider for authentication
|
|
12
|
+
* @param params.axiosOptions - Optional Axios configuration options
|
|
13
|
+
* @param params.tokenHeader - Header name for authentication token (default: "Authorization")
|
|
14
|
+
* @returns CQRS client with response key transformation
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const client = mkUncapitalizedCqrsClient({
|
|
18
|
+
* cqrsEndpoint: 'https://api.example.com'
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function mkUncapitalizedCqrsClient(params: MkCqrsClientParameters): {
|
|
23
|
+
createQuery<TQuery, TResult>(type: string): (dto: TQuery) => Promise<import("@leancodepl/cqrs-client-base").ApiError | {
|
|
24
|
+
result: import("@leancodepl/utils").TransformDeep<TResult, "uncapitalize">;
|
|
25
|
+
isSuccess: true;
|
|
26
|
+
}>;
|
|
27
|
+
createOperation<TOperation, TResult>(type: string): (dto: TOperation) => Promise<import("@leancodepl/cqrs-client-base").ApiError | {
|
|
28
|
+
result: import("@leancodepl/utils").TransformDeep<TResult, "uncapitalize">;
|
|
29
|
+
isSuccess: true;
|
|
30
|
+
}>;
|
|
31
|
+
createCommand<TCommand, TErrorCodes extends {
|
|
32
|
+
[name: string]: number;
|
|
33
|
+
}>(type: string, errorCodesMap: TErrorCodes): {
|
|
34
|
+
(dto: TCommand): Promise<ApiResponse<import("@leancodepl/cqrs-client-base").CommandResult<TErrorCodes>>>;
|
|
35
|
+
handle(dto: TCommand): Promise<import("@leancodepl/validation").ValidationErrorsHandler<TErrorCodes & {
|
|
36
|
+
readonly success: -1;
|
|
37
|
+
readonly failure: -2;
|
|
38
|
+
}, never>>;
|
|
39
|
+
};
|
|
40
|
+
};
|