@pikku/fetch 0.6.1
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/CHANGELOG.md +61 -0
- package/README.md +3 -0
- package/dist/cjs/abstract-pikku-fetch.d.ts +99 -0
- package/dist/cjs/abstract-pikku-fetch.js +178 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.js +15 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/pikku-fetch.d.ts +10 -0
- package/dist/cjs/pikku-fetch.js +45 -0
- package/dist/cjs/transform-date.d.ts +10 -0
- package/dist/cjs/transform-date.js +30 -0
- package/dist/esm/abstract-pikku-fetch.d.ts +99 -0
- package/dist/esm/abstract-pikku-fetch.js +158 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/pikku-fetch.d.ts +10 -0
- package/dist/esm/pikku-fetch.js +35 -0
- package/dist/esm/transform-date.d.ts +10 -0
- package/dist/esm/transform-date.js +26 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +32 -0
- package/run-tests.sh +53 -0
- package/src/abstract-pikku-fetch.ts +200 -0
- package/src/index.ts +15 -0
- package/src/pikku-fetch.ts +41 -0
- package/src/transform-date.ts +26 -0
- package/tsconfig.cjs.json +11 -0
- package/tsconfig.json +14 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @pikku/fetch
|
|
2
|
+
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2bc64fd: feat: adding methods to fetch wrapper (and small fixes)
|
|
8
|
+
- a40a508: fix: Fixing some generation bugs and other minors
|
|
9
|
+
|
|
10
|
+
## 0.6
|
|
11
|
+
|
|
12
|
+
Marking a major release to include channels and scheduled tasks
|
|
13
|
+
|
|
14
|
+
## 0.5.8
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 886a2fb: refactor: moving singletons (like routes and channels) to global to avoid nodemodule overrides
|
|
19
|
+
|
|
20
|
+
## 0.5.7
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 0f96787: refactor: dropping cjs support
|
|
25
|
+
- c23524a: refactor: bump to versions to ensure correct package usage
|
|
26
|
+
|
|
27
|
+
## 0.5.6
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- bba25cc: chore: updating all packages to reflect major changes
|
|
32
|
+
|
|
33
|
+
## 0.5.5
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- 35d1a49: fix: server url shouldn't with a /, bug with //
|
|
38
|
+
|
|
39
|
+
## 0.5.4
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- 78a17e8: fix: avoid // when concatenating serverUrl and uri
|
|
44
|
+
|
|
45
|
+
## 0.5.3
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- effbb4c: doc: adding readme to all packages
|
|
50
|
+
|
|
51
|
+
## 0.5.2
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- 725723d: docs: adding typedocs
|
|
56
|
+
|
|
57
|
+
## 0.5.1
|
|
58
|
+
|
|
59
|
+
### Patch Changes
|
|
60
|
+
|
|
61
|
+
- b237ace: fix: fixing bugs in fetch
|
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
type AuthHeaders = {
|
|
2
|
+
jwt?: string;
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
};
|
|
5
|
+
export type HTTPMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'HEAD' | 'PUT';
|
|
6
|
+
/**
|
|
7
|
+
* Options for configuring the `CorePikkuFetch` utility.
|
|
8
|
+
*
|
|
9
|
+
* @typedef {Object} CorePikkuFetchOptions
|
|
10
|
+
* @property {boolean} [transformDate] - Whether to transform date-like strings in the response to `Date` objects.
|
|
11
|
+
* @property {string} [serverUrl] - The base server URL for requests.
|
|
12
|
+
* @property {AuthHeaders} [authHeaders] - Authorization headers, including JWT or API key.
|
|
13
|
+
* @property {RequestInit['cache']} [cache] - The cache mode for the request.
|
|
14
|
+
* @property {RequestInit['credentials']} [credentials] - The credentials mode for the request.
|
|
15
|
+
* @property {RequestInit['mode']} [mode] - The mode for the request.
|
|
16
|
+
*/
|
|
17
|
+
export type CorePikkuFetchOptions = {
|
|
18
|
+
transformDate?: boolean;
|
|
19
|
+
serverUrl?: string;
|
|
20
|
+
authHeaders?: AuthHeaders;
|
|
21
|
+
} & Pick<RequestInit, 'cache' | 'credentials' | 'mode'>;
|
|
22
|
+
/**
|
|
23
|
+
* The `CorePikkuFetch` class provides a utility for making HTTP requests, including handling authorization,
|
|
24
|
+
* transforming dates in responses, and managing server URLs. This class is designed to simplify API interactions
|
|
25
|
+
* with configurable options and support for JWT and API key-based authentication.
|
|
26
|
+
*/
|
|
27
|
+
export declare class CorePikkuFetch {
|
|
28
|
+
private options;
|
|
29
|
+
private authHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* Constructs a new instance of the `CorePikkuFetch` class.
|
|
32
|
+
*
|
|
33
|
+
* @param {CorePikkuFetchOptions} options - Optional configuration for the fetch utility.
|
|
34
|
+
*/
|
|
35
|
+
constructor(options?: CorePikkuFetchOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Generates the headers for the request, including authorization headers if set.
|
|
38
|
+
*
|
|
39
|
+
* @returns {Record<string, string>} - The headers for the request.
|
|
40
|
+
*/
|
|
41
|
+
private getHeaders;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the server URL for subsequent requests.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} serverUrl - The server URL to be set.
|
|
46
|
+
*/
|
|
47
|
+
setServerUrl(serverUrl: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Sets the JWT for authorization.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} jwt - The JWT to be used for authorization.
|
|
52
|
+
*/
|
|
53
|
+
setAuthorizationJWT(jwt: string | null): void;
|
|
54
|
+
/**
|
|
55
|
+
* Sets the API key for authorization.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} [apiKey] - The API key to be used for authorization.
|
|
58
|
+
*/
|
|
59
|
+
setAPIKey(apiKey: string | null): void;
|
|
60
|
+
post(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
61
|
+
get(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
62
|
+
patch(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
63
|
+
head(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* Makes an API request with the specified URI, method, and data, and optionally transforms dates in the response.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
68
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
69
|
+
* @param {any} data - The data to be sent with the request.
|
|
70
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
71
|
+
* @returns {Promise<any>} - A promise that resolves to the response data.
|
|
72
|
+
* @throws {Response} - Throws the response if the status code is greater than 400.
|
|
73
|
+
*/
|
|
74
|
+
api(uri: string, method: HTTPMethod, data: any, options?: RequestInit): Promise<any>;
|
|
75
|
+
/**
|
|
76
|
+
* Makes a raw fetch request with the specified URI, method, and data.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
79
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
80
|
+
* @param {any} data - The data to be sent with the request.
|
|
81
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
82
|
+
* @returns {Promise<Response>} - A promise that resolves to the fetch response.
|
|
83
|
+
*/
|
|
84
|
+
fetch(uri: string, method: HTTPMethod, data: any, options?: RequestInit): Promise<Response>;
|
|
85
|
+
/**
|
|
86
|
+
* Verifies that the server URL is set before making a request.
|
|
87
|
+
*
|
|
88
|
+
* @throws {Error} - Throws an error if the server URL is not set.
|
|
89
|
+
*/
|
|
90
|
+
private verifyServerUrlSet;
|
|
91
|
+
/**
|
|
92
|
+
* Transforms date-like strings in the response data into `Date` objects if the `transformDate` option is set.
|
|
93
|
+
*
|
|
94
|
+
* @param {any} data - The data to transform.
|
|
95
|
+
* @returns {any} - The transformed data.
|
|
96
|
+
*/
|
|
97
|
+
private transformDates;
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CorePikkuFetch = void 0;
|
|
13
|
+
const transform_date_js_1 = require("./transform-date.js");
|
|
14
|
+
const pikku_fetch_js_1 = require("./pikku-fetch.js");
|
|
15
|
+
/**
|
|
16
|
+
* The `CorePikkuFetch` class provides a utility for making HTTP requests, including handling authorization,
|
|
17
|
+
* transforming dates in responses, and managing server URLs. This class is designed to simplify API interactions
|
|
18
|
+
* with configurable options and support for JWT and API key-based authentication.
|
|
19
|
+
*/
|
|
20
|
+
class CorePikkuFetch {
|
|
21
|
+
/**
|
|
22
|
+
* Constructs a new instance of the `CorePikkuFetch` class.
|
|
23
|
+
*
|
|
24
|
+
* @param {CorePikkuFetchOptions} options - Optional configuration for the fetch utility.
|
|
25
|
+
*/
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.authHeaders = {};
|
|
29
|
+
this.authHeaders = options.authHeaders || {};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generates the headers for the request, including authorization headers if set.
|
|
33
|
+
*
|
|
34
|
+
* @returns {Record<string, string>} - The headers for the request.
|
|
35
|
+
*/
|
|
36
|
+
getHeaders() {
|
|
37
|
+
const headers = {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
};
|
|
40
|
+
if (this.authHeaders.jwt) {
|
|
41
|
+
headers.Authorization = `Bearer ${this.authHeaders.jwt}`;
|
|
42
|
+
}
|
|
43
|
+
else if (this.authHeaders.apiKey) {
|
|
44
|
+
headers['X-API-KEY'] = this.authHeaders.apiKey;
|
|
45
|
+
}
|
|
46
|
+
return headers;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sets the server URL for subsequent requests.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} serverUrl - The server URL to be set.
|
|
52
|
+
*/
|
|
53
|
+
setServerUrl(serverUrl) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
if (serverUrl.endsWith('/')) {
|
|
56
|
+
console.warn('Server URL should not end with a slash, removing.');
|
|
57
|
+
serverUrl = serverUrl.slice(0, -1);
|
|
58
|
+
}
|
|
59
|
+
this.options.serverUrl = serverUrl;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets the JWT for authorization.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} jwt - The JWT to be used for authorization.
|
|
66
|
+
*/
|
|
67
|
+
setAuthorizationJWT(jwt) {
|
|
68
|
+
if (jwt) {
|
|
69
|
+
this.authHeaders.jwt = jwt;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
delete this.authHeaders.jwt;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sets the API key for authorization.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} [apiKey] - The API key to be used for authorization.
|
|
79
|
+
*/
|
|
80
|
+
setAPIKey(apiKey) {
|
|
81
|
+
if (apiKey) {
|
|
82
|
+
this.authHeaders.apiKey = apiKey;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
delete this.authHeaders.apiKey;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
post(uri, data, options) {
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
return yield this.api(uri, 'POST', data, options);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
get(uri, data, options) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
+
return yield this.api(uri, 'GET', data, options);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
patch(uri, data, options) {
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
return yield this.api(uri, 'PATCH', data, options);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
head(uri, data, options) {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
return yield this.api(uri, 'HEAD', data, options);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Makes an API request with the specified URI, method, and data, and optionally transforms dates in the response.
|
|
110
|
+
*
|
|
111
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
112
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
113
|
+
* @param {any} data - The data to be sent with the request.
|
|
114
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
115
|
+
* @returns {Promise<any>} - A promise that resolves to the response data.
|
|
116
|
+
* @throws {Response} - Throws the response if the status code is greater than 400.
|
|
117
|
+
*/
|
|
118
|
+
api(uri, method, data, options) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const response = yield this.fetch(uri, method, data, options);
|
|
121
|
+
if (response.status >= 400) {
|
|
122
|
+
throw response;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const result = yield response.json();
|
|
126
|
+
return this.transformDates(result);
|
|
127
|
+
}
|
|
128
|
+
catch (_a) {
|
|
129
|
+
// TODO: If it doesn't return anything..
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Makes a raw fetch request with the specified URI, method, and data.
|
|
136
|
+
*
|
|
137
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
138
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
139
|
+
* @param {any} data - The data to be sent with the request.
|
|
140
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
141
|
+
* @returns {Promise<Response>} - A promise that resolves to the fetch response.
|
|
142
|
+
*/
|
|
143
|
+
fetch(uri, method, data, options) {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
this.verifyServerUrlSet();
|
|
146
|
+
if (uri.startsWith('/')) {
|
|
147
|
+
uri = `${this.options.serverUrl}${uri}`;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
uri = `${this.options.serverUrl}/${uri}`;
|
|
151
|
+
}
|
|
152
|
+
return yield (0, pikku_fetch_js_1.corePikkuFetch)(uri, data, Object.assign(Object.assign({}, options), { method, mode: this.options.mode, credentials: this.options.credentials, headers: Object.assign(Object.assign({}, this.getHeaders()), options === null || options === void 0 ? void 0 : options.headers) }));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Verifies that the server URL is set before making a request.
|
|
157
|
+
*
|
|
158
|
+
* @throws {Error} - Throws an error if the server URL is not set.
|
|
159
|
+
*/
|
|
160
|
+
verifyServerUrlSet() {
|
|
161
|
+
if (!this.options.serverUrl) {
|
|
162
|
+
throw new Error('Server url is not set');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Transforms date-like strings in the response data into `Date` objects if the `transformDate` option is set.
|
|
167
|
+
*
|
|
168
|
+
* @param {any} data - The data to transform.
|
|
169
|
+
* @returns {any} - The transformed data.
|
|
170
|
+
*/
|
|
171
|
+
transformDates(data) {
|
|
172
|
+
if (!this.options.transformDate) {
|
|
173
|
+
return data;
|
|
174
|
+
}
|
|
175
|
+
return (0, transform_date_js_1.transformDates)(data);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.CorePikkuFetch = CorePikkuFetch;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides a wrapper around the Fetch API that integrates with the Pikku framework.
|
|
3
|
+
* It includes utilities for making HTTP requests, such as options for authorization, server URL management,
|
|
4
|
+
* and transforming dates in responses, while ensuring requests are validated against Pikku routes.
|
|
5
|
+
* The module exports the `CorePikkuFetch` class, as well as other supporting types and functions.
|
|
6
|
+
*
|
|
7
|
+
* @module @pikku/fetch
|
|
8
|
+
*/
|
|
9
|
+
export { CorePikkuFetch, CorePikkuFetchOptions, HTTPMethod, } from './abstract-pikku-fetch.js';
|
|
10
|
+
export { corePikkuFetch } from './pikku-fetch.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* This module provides a wrapper around the Fetch API that integrates with the Pikku framework.
|
|
4
|
+
* It includes utilities for making HTTP requests, such as options for authorization, server URL management,
|
|
5
|
+
* and transforming dates in responses, while ensuring requests are validated against Pikku routes.
|
|
6
|
+
* The module exports the `CorePikkuFetch` class, as well as other supporting types and functions.
|
|
7
|
+
*
|
|
8
|
+
* @module @pikku/fetch
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.corePikkuFetch = exports.CorePikkuFetch = void 0;
|
|
12
|
+
var abstract_pikku_fetch_js_1 = require("./abstract-pikku-fetch.js");
|
|
13
|
+
Object.defineProperty(exports, "CorePikkuFetch", { enumerable: true, get: function () { return abstract_pikku_fetch_js_1.CorePikkuFetch; } });
|
|
14
|
+
var pikku_fetch_js_1 = require("./pikku-fetch.js");
|
|
15
|
+
Object.defineProperty(exports, "corePikkuFetch", { enumerable: true, get: function () { return pikku_fetch_js_1.corePikkuFetch; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `corePikkuFetch` function is a utility for making HTTP requests with dynamic URI and data handling.
|
|
3
|
+
* It can automatically replace URI parameters, append query strings for GET requests, and set the request body for POST, PATCH, or PUT requests.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} uri - The endpoint URI for the request. URI parameters can be specified using `:param` syntax.
|
|
6
|
+
* @param {any} data - The data to be included in the request, either as query parameters or as the request body.
|
|
7
|
+
* @param {Omit<RequestInit, 'body'>} [options] - Optional configuration options for the fetch request, excluding the body.
|
|
8
|
+
* @returns {Promise<Response>} - A promise that resolves to the response of the fetch request.
|
|
9
|
+
*/
|
|
10
|
+
export declare const corePikkuFetch: (uri: string, data: any, options?: Omit<RequestInit, "body">) => Promise<Response>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.corePikkuFetch = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* The `corePikkuFetch` function is a utility for making HTTP requests with dynamic URI and data handling.
|
|
15
|
+
* It can automatically replace URI parameters, append query strings for GET requests, and set the request body for POST, PATCH, or PUT requests.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} uri - The endpoint URI for the request. URI parameters can be specified using `:param` syntax.
|
|
18
|
+
* @param {any} data - The data to be included in the request, either as query parameters or as the request body.
|
|
19
|
+
* @param {Omit<RequestInit, 'body'>} [options] - Optional configuration options for the fetch request, excluding the body.
|
|
20
|
+
* @returns {Promise<Response>} - A promise that resolves to the response of the fetch request.
|
|
21
|
+
*/
|
|
22
|
+
const corePikkuFetch = (uri, data, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
var _a;
|
|
24
|
+
const method = ((_a = options === null || options === void 0 ? void 0 : options.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'GET';
|
|
25
|
+
let body;
|
|
26
|
+
if (data) {
|
|
27
|
+
data = JSON.parse(JSON.stringify(data));
|
|
28
|
+
const keys = Object.keys(data);
|
|
29
|
+
for (const key of keys) {
|
|
30
|
+
if (uri.includes(`:${key}`)) {
|
|
31
|
+
uri = uri.replace(`:${key}`, data[key]);
|
|
32
|
+
delete data[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (method === 'POST' || method === 'PATCH' || method === 'PUT') {
|
|
36
|
+
body = data;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const queryString = new URLSearchParams(JSON.parse(JSON.stringify(data)));
|
|
40
|
+
uri = `${uri}?${queryString}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return yield fetch(uri, Object.assign(Object.assign({ method: method.toUpperCase() }, options), { body: body ? JSON.stringify(body) : undefined }));
|
|
44
|
+
});
|
|
45
|
+
exports.corePikkuFetch = corePikkuFetch;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformDates` function recursively traverses an object or array and converts any date-like strings
|
|
3
|
+
* into JavaScript `Date` objects. This helps in ensuring that date fields are properly handled as `Date` instances
|
|
4
|
+
* rather than strings.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @param {any} data - The input data that may contain date strings. It can be an object, array, or primitive value.
|
|
8
|
+
* @returns {any} - The transformed data with date strings converted to `Date` objects.
|
|
9
|
+
*/
|
|
10
|
+
export declare const transformDates: (data: any) => any;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformDates = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The `transformDates` function recursively traverses an object or array and converts any date-like strings
|
|
6
|
+
* into JavaScript `Date` objects. This helps in ensuring that date fields are properly handled as `Date` instances
|
|
7
|
+
* rather than strings.
|
|
8
|
+
*
|
|
9
|
+
* @private
|
|
10
|
+
* @param {any} data - The input data that may contain date strings. It can be an object, array, or primitive value.
|
|
11
|
+
* @returns {any} - The transformed data with date strings converted to `Date` objects.
|
|
12
|
+
*/
|
|
13
|
+
const transformDates = (data) => {
|
|
14
|
+
if (data === null)
|
|
15
|
+
return null;
|
|
16
|
+
if (Array.isArray(data))
|
|
17
|
+
return data.map(exports.transformDates.bind(this));
|
|
18
|
+
if (typeof data === 'object') {
|
|
19
|
+
return Object.entries(data).reduce((result, [key, value]) => {
|
|
20
|
+
result[key] = (0, exports.transformDates)(value);
|
|
21
|
+
return result;
|
|
22
|
+
}, {});
|
|
23
|
+
}
|
|
24
|
+
if (typeof data === 'string' &&
|
|
25
|
+
/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}\.\d{3}Z?)?/.test(data)) {
|
|
26
|
+
return new Date(data);
|
|
27
|
+
}
|
|
28
|
+
return data;
|
|
29
|
+
};
|
|
30
|
+
exports.transformDates = transformDates;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
type AuthHeaders = {
|
|
2
|
+
jwt?: string;
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
};
|
|
5
|
+
export type HTTPMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'HEAD' | 'PUT';
|
|
6
|
+
/**
|
|
7
|
+
* Options for configuring the `CorePikkuFetch` utility.
|
|
8
|
+
*
|
|
9
|
+
* @typedef {Object} CorePikkuFetchOptions
|
|
10
|
+
* @property {boolean} [transformDate] - Whether to transform date-like strings in the response to `Date` objects.
|
|
11
|
+
* @property {string} [serverUrl] - The base server URL for requests.
|
|
12
|
+
* @property {AuthHeaders} [authHeaders] - Authorization headers, including JWT or API key.
|
|
13
|
+
* @property {RequestInit['cache']} [cache] - The cache mode for the request.
|
|
14
|
+
* @property {RequestInit['credentials']} [credentials] - The credentials mode for the request.
|
|
15
|
+
* @property {RequestInit['mode']} [mode] - The mode for the request.
|
|
16
|
+
*/
|
|
17
|
+
export type CorePikkuFetchOptions = {
|
|
18
|
+
transformDate?: boolean;
|
|
19
|
+
serverUrl?: string;
|
|
20
|
+
authHeaders?: AuthHeaders;
|
|
21
|
+
} & Pick<RequestInit, 'cache' | 'credentials' | 'mode'>;
|
|
22
|
+
/**
|
|
23
|
+
* The `CorePikkuFetch` class provides a utility for making HTTP requests, including handling authorization,
|
|
24
|
+
* transforming dates in responses, and managing server URLs. This class is designed to simplify API interactions
|
|
25
|
+
* with configurable options and support for JWT and API key-based authentication.
|
|
26
|
+
*/
|
|
27
|
+
export declare class CorePikkuFetch {
|
|
28
|
+
private options;
|
|
29
|
+
private authHeaders;
|
|
30
|
+
/**
|
|
31
|
+
* Constructs a new instance of the `CorePikkuFetch` class.
|
|
32
|
+
*
|
|
33
|
+
* @param {CorePikkuFetchOptions} options - Optional configuration for the fetch utility.
|
|
34
|
+
*/
|
|
35
|
+
constructor(options?: CorePikkuFetchOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Generates the headers for the request, including authorization headers if set.
|
|
38
|
+
*
|
|
39
|
+
* @returns {Record<string, string>} - The headers for the request.
|
|
40
|
+
*/
|
|
41
|
+
private getHeaders;
|
|
42
|
+
/**
|
|
43
|
+
* Sets the server URL for subsequent requests.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} serverUrl - The server URL to be set.
|
|
46
|
+
*/
|
|
47
|
+
setServerUrl(serverUrl: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Sets the JWT for authorization.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} jwt - The JWT to be used for authorization.
|
|
52
|
+
*/
|
|
53
|
+
setAuthorizationJWT(jwt: string | null): void;
|
|
54
|
+
/**
|
|
55
|
+
* Sets the API key for authorization.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} [apiKey] - The API key to be used for authorization.
|
|
58
|
+
*/
|
|
59
|
+
setAPIKey(apiKey: string | null): void;
|
|
60
|
+
post(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
61
|
+
get(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
62
|
+
patch(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
63
|
+
head(uri: string, data: any, options?: RequestInit): Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* Makes an API request with the specified URI, method, and data, and optionally transforms dates in the response.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
68
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
69
|
+
* @param {any} data - The data to be sent with the request.
|
|
70
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
71
|
+
* @returns {Promise<any>} - A promise that resolves to the response data.
|
|
72
|
+
* @throws {Response} - Throws the response if the status code is greater than 400.
|
|
73
|
+
*/
|
|
74
|
+
api(uri: string, method: HTTPMethod, data: any, options?: RequestInit): Promise<any>;
|
|
75
|
+
/**
|
|
76
|
+
* Makes a raw fetch request with the specified URI, method, and data.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
79
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
80
|
+
* @param {any} data - The data to be sent with the request.
|
|
81
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
82
|
+
* @returns {Promise<Response>} - A promise that resolves to the fetch response.
|
|
83
|
+
*/
|
|
84
|
+
fetch(uri: string, method: HTTPMethod, data: any, options?: RequestInit): Promise<Response>;
|
|
85
|
+
/**
|
|
86
|
+
* Verifies that the server URL is set before making a request.
|
|
87
|
+
*
|
|
88
|
+
* @throws {Error} - Throws an error if the server URL is not set.
|
|
89
|
+
*/
|
|
90
|
+
private verifyServerUrlSet;
|
|
91
|
+
/**
|
|
92
|
+
* Transforms date-like strings in the response data into `Date` objects if the `transformDate` option is set.
|
|
93
|
+
*
|
|
94
|
+
* @param {any} data - The data to transform.
|
|
95
|
+
* @returns {any} - The transformed data.
|
|
96
|
+
*/
|
|
97
|
+
private transformDates;
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { transformDates } from './transform-date.js';
|
|
2
|
+
import { corePikkuFetch } from './pikku-fetch.js';
|
|
3
|
+
/**
|
|
4
|
+
* The `CorePikkuFetch` class provides a utility for making HTTP requests, including handling authorization,
|
|
5
|
+
* transforming dates in responses, and managing server URLs. This class is designed to simplify API interactions
|
|
6
|
+
* with configurable options and support for JWT and API key-based authentication.
|
|
7
|
+
*/
|
|
8
|
+
export class CorePikkuFetch {
|
|
9
|
+
options;
|
|
10
|
+
authHeaders = {};
|
|
11
|
+
/**
|
|
12
|
+
* Constructs a new instance of the `CorePikkuFetch` class.
|
|
13
|
+
*
|
|
14
|
+
* @param {CorePikkuFetchOptions} options - Optional configuration for the fetch utility.
|
|
15
|
+
*/
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.authHeaders = options.authHeaders || {};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generates the headers for the request, including authorization headers if set.
|
|
22
|
+
*
|
|
23
|
+
* @returns {Record<string, string>} - The headers for the request.
|
|
24
|
+
*/
|
|
25
|
+
getHeaders() {
|
|
26
|
+
const headers = {
|
|
27
|
+
'Content-Type': 'application/json',
|
|
28
|
+
};
|
|
29
|
+
if (this.authHeaders.jwt) {
|
|
30
|
+
headers.Authorization = `Bearer ${this.authHeaders.jwt}`;
|
|
31
|
+
}
|
|
32
|
+
else if (this.authHeaders.apiKey) {
|
|
33
|
+
headers['X-API-KEY'] = this.authHeaders.apiKey;
|
|
34
|
+
}
|
|
35
|
+
return headers;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sets the server URL for subsequent requests.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} serverUrl - The server URL to be set.
|
|
41
|
+
*/
|
|
42
|
+
async setServerUrl(serverUrl) {
|
|
43
|
+
if (serverUrl.endsWith('/')) {
|
|
44
|
+
console.warn('Server URL should not end with a slash, removing.');
|
|
45
|
+
serverUrl = serverUrl.slice(0, -1);
|
|
46
|
+
}
|
|
47
|
+
this.options.serverUrl = serverUrl;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sets the JWT for authorization.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} jwt - The JWT to be used for authorization.
|
|
53
|
+
*/
|
|
54
|
+
setAuthorizationJWT(jwt) {
|
|
55
|
+
if (jwt) {
|
|
56
|
+
this.authHeaders.jwt = jwt;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
delete this.authHeaders.jwt;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets the API key for authorization.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} [apiKey] - The API key to be used for authorization.
|
|
66
|
+
*/
|
|
67
|
+
setAPIKey(apiKey) {
|
|
68
|
+
if (apiKey) {
|
|
69
|
+
this.authHeaders.apiKey = apiKey;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
delete this.authHeaders.apiKey;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async post(uri, data, options) {
|
|
76
|
+
return await this.api(uri, 'POST', data, options);
|
|
77
|
+
}
|
|
78
|
+
async get(uri, data, options) {
|
|
79
|
+
return await this.api(uri, 'GET', data, options);
|
|
80
|
+
}
|
|
81
|
+
async patch(uri, data, options) {
|
|
82
|
+
return await this.api(uri, 'PATCH', data, options);
|
|
83
|
+
}
|
|
84
|
+
async head(uri, data, options) {
|
|
85
|
+
return await this.api(uri, 'HEAD', data, options);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Makes an API request with the specified URI, method, and data, and optionally transforms dates in the response.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
91
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
92
|
+
* @param {any} data - The data to be sent with the request.
|
|
93
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
94
|
+
* @returns {Promise<any>} - A promise that resolves to the response data.
|
|
95
|
+
* @throws {Response} - Throws the response if the status code is greater than 400.
|
|
96
|
+
*/
|
|
97
|
+
async api(uri, method, data, options) {
|
|
98
|
+
const response = await this.fetch(uri, method, data, options);
|
|
99
|
+
if (response.status >= 400) {
|
|
100
|
+
throw response;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const result = await response.json();
|
|
104
|
+
return this.transformDates(result);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// TODO: If it doesn't return anything..
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Makes a raw fetch request with the specified URI, method, and data.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
115
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
116
|
+
* @param {any} data - The data to be sent with the request.
|
|
117
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
118
|
+
* @returns {Promise<Response>} - A promise that resolves to the fetch response.
|
|
119
|
+
*/
|
|
120
|
+
async fetch(uri, method, data, options) {
|
|
121
|
+
this.verifyServerUrlSet();
|
|
122
|
+
if (uri.startsWith('/')) {
|
|
123
|
+
uri = `${this.options.serverUrl}${uri}`;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
uri = `${this.options.serverUrl}/${uri}`;
|
|
127
|
+
}
|
|
128
|
+
return await corePikkuFetch(uri, data, {
|
|
129
|
+
...options,
|
|
130
|
+
method,
|
|
131
|
+
mode: this.options.mode,
|
|
132
|
+
credentials: this.options.credentials,
|
|
133
|
+
headers: { ...this.getHeaders(), ...options?.headers },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Verifies that the server URL is set before making a request.
|
|
138
|
+
*
|
|
139
|
+
* @throws {Error} - Throws an error if the server URL is not set.
|
|
140
|
+
*/
|
|
141
|
+
verifyServerUrlSet() {
|
|
142
|
+
if (!this.options.serverUrl) {
|
|
143
|
+
throw new Error('Server url is not set');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Transforms date-like strings in the response data into `Date` objects if the `transformDate` option is set.
|
|
148
|
+
*
|
|
149
|
+
* @param {any} data - The data to transform.
|
|
150
|
+
* @returns {any} - The transformed data.
|
|
151
|
+
*/
|
|
152
|
+
transformDates(data) {
|
|
153
|
+
if (!this.options.transformDate) {
|
|
154
|
+
return data;
|
|
155
|
+
}
|
|
156
|
+
return transformDates(data);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides a wrapper around the Fetch API that integrates with the Pikku framework.
|
|
3
|
+
* It includes utilities for making HTTP requests, such as options for authorization, server URL management,
|
|
4
|
+
* and transforming dates in responses, while ensuring requests are validated against Pikku routes.
|
|
5
|
+
* The module exports the `CorePikkuFetch` class, as well as other supporting types and functions.
|
|
6
|
+
*
|
|
7
|
+
* @module @pikku/fetch
|
|
8
|
+
*/
|
|
9
|
+
export { CorePikkuFetch, CorePikkuFetchOptions, HTTPMethod, } from './abstract-pikku-fetch.js';
|
|
10
|
+
export { corePikkuFetch } from './pikku-fetch.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides a wrapper around the Fetch API that integrates with the Pikku framework.
|
|
3
|
+
* It includes utilities for making HTTP requests, such as options for authorization, server URL management,
|
|
4
|
+
* and transforming dates in responses, while ensuring requests are validated against Pikku routes.
|
|
5
|
+
* The module exports the `CorePikkuFetch` class, as well as other supporting types and functions.
|
|
6
|
+
*
|
|
7
|
+
* @module @pikku/fetch
|
|
8
|
+
*/
|
|
9
|
+
export { CorePikkuFetch, } from './abstract-pikku-fetch.js';
|
|
10
|
+
export { corePikkuFetch } from './pikku-fetch.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `corePikkuFetch` function is a utility for making HTTP requests with dynamic URI and data handling.
|
|
3
|
+
* It can automatically replace URI parameters, append query strings for GET requests, and set the request body for POST, PATCH, or PUT requests.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} uri - The endpoint URI for the request. URI parameters can be specified using `:param` syntax.
|
|
6
|
+
* @param {any} data - The data to be included in the request, either as query parameters or as the request body.
|
|
7
|
+
* @param {Omit<RequestInit, 'body'>} [options] - Optional configuration options for the fetch request, excluding the body.
|
|
8
|
+
* @returns {Promise<Response>} - A promise that resolves to the response of the fetch request.
|
|
9
|
+
*/
|
|
10
|
+
export declare const corePikkuFetch: (uri: string, data: any, options?: Omit<RequestInit, "body">) => Promise<Response>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `corePikkuFetch` function is a utility for making HTTP requests with dynamic URI and data handling.
|
|
3
|
+
* It can automatically replace URI parameters, append query strings for GET requests, and set the request body for POST, PATCH, or PUT requests.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} uri - The endpoint URI for the request. URI parameters can be specified using `:param` syntax.
|
|
6
|
+
* @param {any} data - The data to be included in the request, either as query parameters or as the request body.
|
|
7
|
+
* @param {Omit<RequestInit, 'body'>} [options] - Optional configuration options for the fetch request, excluding the body.
|
|
8
|
+
* @returns {Promise<Response>} - A promise that resolves to the response of the fetch request.
|
|
9
|
+
*/
|
|
10
|
+
export const corePikkuFetch = async (uri, data, options) => {
|
|
11
|
+
const method = options?.method?.toUpperCase() || 'GET';
|
|
12
|
+
let body;
|
|
13
|
+
if (data) {
|
|
14
|
+
data = JSON.parse(JSON.stringify(data));
|
|
15
|
+
const keys = Object.keys(data);
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
if (uri.includes(`:${key}`)) {
|
|
18
|
+
uri = uri.replace(`:${key}`, data[key]);
|
|
19
|
+
delete data[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (method === 'POST' || method === 'PATCH' || method === 'PUT') {
|
|
23
|
+
body = data;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const queryString = new URLSearchParams(JSON.parse(JSON.stringify(data)));
|
|
27
|
+
uri = `${uri}?${queryString}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return await fetch(uri, {
|
|
31
|
+
method: method.toUpperCase(),
|
|
32
|
+
...options,
|
|
33
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
34
|
+
});
|
|
35
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformDates` function recursively traverses an object or array and converts any date-like strings
|
|
3
|
+
* into JavaScript `Date` objects. This helps in ensuring that date fields are properly handled as `Date` instances
|
|
4
|
+
* rather than strings.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @param {any} data - The input data that may contain date strings. It can be an object, array, or primitive value.
|
|
8
|
+
* @returns {any} - The transformed data with date strings converted to `Date` objects.
|
|
9
|
+
*/
|
|
10
|
+
export declare const transformDates: (data: any) => any;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformDates` function recursively traverses an object or array and converts any date-like strings
|
|
3
|
+
* into JavaScript `Date` objects. This helps in ensuring that date fields are properly handled as `Date` instances
|
|
4
|
+
* rather than strings.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @param {any} data - The input data that may contain date strings. It can be an object, array, or primitive value.
|
|
8
|
+
* @returns {any} - The transformed data with date strings converted to `Date` objects.
|
|
9
|
+
*/
|
|
10
|
+
export const transformDates = (data) => {
|
|
11
|
+
if (data === null)
|
|
12
|
+
return null;
|
|
13
|
+
if (Array.isArray(data))
|
|
14
|
+
return data.map(transformDates.bind(this));
|
|
15
|
+
if (typeof data === 'object') {
|
|
16
|
+
return Object.entries(data).reduce((result, [key, value]) => {
|
|
17
|
+
result[key] = transformDates(value);
|
|
18
|
+
return result;
|
|
19
|
+
}, {});
|
|
20
|
+
}
|
|
21
|
+
if (typeof data === 'string' &&
|
|
22
|
+
/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}\.\d{3}Z?)?/.test(data)) {
|
|
23
|
+
return new Date(data);
|
|
24
|
+
}
|
|
25
|
+
return data;
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/abstract-pikku-fetch.ts","../src/index.ts","../src/pikku-fetch.ts","../src/transform-date.ts"],"version":"5.7.3"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/abstract-pikku-fetch.ts","../src/index.ts","../src/pikku-fetch.ts","../src/transform-date.ts"],"version":"5.7.3"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pikku/fetch",
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"author": "yasser.fadl@gmail.com",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/cjs/index.js",
|
|
8
|
+
"module": "dist/esm/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/esm/index.js",
|
|
12
|
+
"require": "./dist/cjs/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"tsc": "tsc",
|
|
17
|
+
"build:esm": "tsc -b && echo '{\"type\": \"module\"}' > dist/esm/package.json",
|
|
18
|
+
"build:cjs": "tsc -b tsconfig.cjs.json && echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
|
|
19
|
+
"build": "yarn build:esm && yarn build:cjs",
|
|
20
|
+
"ncu": "ncu -x '/.*glob.*/'",
|
|
21
|
+
"release": "yarn build && npm test",
|
|
22
|
+
"test": "bash run-tests.sh",
|
|
23
|
+
"test:watch": "bash run-tests.sh --watch",
|
|
24
|
+
"test:coverage": "bash run-tests.sh --coverage"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.6"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/run-tests.sh
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Enable nullglob to handle cases where no files match the pattern
|
|
4
|
+
shopt -s nullglob
|
|
5
|
+
|
|
6
|
+
# Initialize variables for options
|
|
7
|
+
watch_mode=false
|
|
8
|
+
coverage_mode=false
|
|
9
|
+
|
|
10
|
+
# Parse command-line options
|
|
11
|
+
while [[ $# -gt 0 ]]; do
|
|
12
|
+
case $1 in
|
|
13
|
+
--watch)
|
|
14
|
+
watch_mode=true
|
|
15
|
+
shift
|
|
16
|
+
;;
|
|
17
|
+
--coverage)
|
|
18
|
+
coverage_mode=true
|
|
19
|
+
shift
|
|
20
|
+
;;
|
|
21
|
+
*)
|
|
22
|
+
echo "Unknown option: $1"
|
|
23
|
+
exit 1
|
|
24
|
+
;;
|
|
25
|
+
esac
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
# Define the pattern to match your test files
|
|
29
|
+
pattern="src/*.test.ts"
|
|
30
|
+
|
|
31
|
+
# Expand the pattern into an array of files
|
|
32
|
+
files=($(find src -type f -name "*.test.ts"))
|
|
33
|
+
|
|
34
|
+
# Check if any files matched the pattern
|
|
35
|
+
if [ ${#files[@]} -eq 0 ]; then
|
|
36
|
+
echo "No test files found matching pattern: $pattern"
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Construct the node command
|
|
41
|
+
node_cmd="node --import tsx --test"
|
|
42
|
+
|
|
43
|
+
# Append options based on flags
|
|
44
|
+
if [ "$watch_mode" = true ]; then
|
|
45
|
+
node_cmd="$node_cmd --watch"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if [ "$coverage_mode" = true ]; then
|
|
49
|
+
node_cmd="$node_cmd --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Execute the node command with the expanded list of files
|
|
53
|
+
$node_cmd "${files[@]}"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { transformDates } from './transform-date.js'
|
|
2
|
+
import { corePikkuFetch } from './pikku-fetch.js'
|
|
3
|
+
|
|
4
|
+
type AuthHeaders = {
|
|
5
|
+
jwt?: string
|
|
6
|
+
apiKey?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type HTTPMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'HEAD' | 'PUT'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Options for configuring the `CorePikkuFetch` utility.
|
|
13
|
+
*
|
|
14
|
+
* @typedef {Object} CorePikkuFetchOptions
|
|
15
|
+
* @property {boolean} [transformDate] - Whether to transform date-like strings in the response to `Date` objects.
|
|
16
|
+
* @property {string} [serverUrl] - The base server URL for requests.
|
|
17
|
+
* @property {AuthHeaders} [authHeaders] - Authorization headers, including JWT or API key.
|
|
18
|
+
* @property {RequestInit['cache']} [cache] - The cache mode for the request.
|
|
19
|
+
* @property {RequestInit['credentials']} [credentials] - The credentials mode for the request.
|
|
20
|
+
* @property {RequestInit['mode']} [mode] - The mode for the request.
|
|
21
|
+
*/
|
|
22
|
+
export type CorePikkuFetchOptions = {
|
|
23
|
+
transformDate?: boolean
|
|
24
|
+
serverUrl?: string
|
|
25
|
+
authHeaders?: AuthHeaders
|
|
26
|
+
} & Pick<RequestInit, 'cache' | 'credentials' | 'mode'>
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The `CorePikkuFetch` class provides a utility for making HTTP requests, including handling authorization,
|
|
30
|
+
* transforming dates in responses, and managing server URLs. This class is designed to simplify API interactions
|
|
31
|
+
* with configurable options and support for JWT and API key-based authentication.
|
|
32
|
+
*/
|
|
33
|
+
export class CorePikkuFetch {
|
|
34
|
+
private authHeaders: AuthHeaders = {}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Constructs a new instance of the `CorePikkuFetch` class.
|
|
38
|
+
*
|
|
39
|
+
* @param {CorePikkuFetchOptions} options - Optional configuration for the fetch utility.
|
|
40
|
+
*/
|
|
41
|
+
constructor(private options: CorePikkuFetchOptions = {}) {
|
|
42
|
+
this.authHeaders = options.authHeaders || {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generates the headers for the request, including authorization headers if set.
|
|
47
|
+
*
|
|
48
|
+
* @returns {Record<string, string>} - The headers for the request.
|
|
49
|
+
*/
|
|
50
|
+
private getHeaders(): Record<string, string> {
|
|
51
|
+
const headers: Record<string, string> = {
|
|
52
|
+
'Content-Type': 'application/json',
|
|
53
|
+
}
|
|
54
|
+
if (this.authHeaders.jwt) {
|
|
55
|
+
headers.Authorization = `Bearer ${this.authHeaders.jwt}`
|
|
56
|
+
} else if (this.authHeaders.apiKey) {
|
|
57
|
+
headers['X-API-KEY'] = this.authHeaders.apiKey
|
|
58
|
+
}
|
|
59
|
+
return headers
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sets the server URL for subsequent requests.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} serverUrl - The server URL to be set.
|
|
66
|
+
*/
|
|
67
|
+
public async setServerUrl(serverUrl: string): Promise<void> {
|
|
68
|
+
if (serverUrl.endsWith('/')) {
|
|
69
|
+
console.warn('Server URL should not end with a slash, removing.')
|
|
70
|
+
serverUrl = serverUrl.slice(0, -1)
|
|
71
|
+
}
|
|
72
|
+
this.options.serverUrl = serverUrl
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Sets the JWT for authorization.
|
|
77
|
+
*
|
|
78
|
+
* @param {string} jwt - The JWT to be used for authorization.
|
|
79
|
+
*/
|
|
80
|
+
public setAuthorizationJWT(jwt: string | null): void {
|
|
81
|
+
if (jwt) {
|
|
82
|
+
this.authHeaders.jwt = jwt
|
|
83
|
+
} else {
|
|
84
|
+
delete this.authHeaders.jwt
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Sets the API key for authorization.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} [apiKey] - The API key to be used for authorization.
|
|
92
|
+
*/
|
|
93
|
+
public setAPIKey(apiKey: string | null): void {
|
|
94
|
+
if (apiKey) {
|
|
95
|
+
this.authHeaders.apiKey = apiKey
|
|
96
|
+
} else {
|
|
97
|
+
delete this.authHeaders.apiKey
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public async post(uri: string, data: any, options?: RequestInit) {
|
|
102
|
+
return await this.api(uri, 'POST', data, options)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public async get(uri: string, data: any, options?: RequestInit) {
|
|
106
|
+
return await this.api(uri, 'GET', data, options)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public async patch(uri: string, data: any, options?: RequestInit) {
|
|
110
|
+
return await this.api(uri, 'PATCH', data, options)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public async head(uri: string, data: any, options?: RequestInit) {
|
|
114
|
+
return await this.api(uri, 'HEAD', data, options)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Makes an API request with the specified URI, method, and data, and optionally transforms dates in the response.
|
|
119
|
+
*
|
|
120
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
121
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
122
|
+
* @param {any} data - The data to be sent with the request.
|
|
123
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
124
|
+
* @returns {Promise<any>} - A promise that resolves to the response data.
|
|
125
|
+
* @throws {Response} - Throws the response if the status code is greater than 400.
|
|
126
|
+
*/
|
|
127
|
+
public async api(
|
|
128
|
+
uri: string,
|
|
129
|
+
method: HTTPMethod,
|
|
130
|
+
data: any,
|
|
131
|
+
options?: RequestInit
|
|
132
|
+
) {
|
|
133
|
+
const response = await this.fetch(uri, method, data, options)
|
|
134
|
+
if (response.status >= 400) {
|
|
135
|
+
throw response
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const result = await response.json()
|
|
139
|
+
return this.transformDates(result)
|
|
140
|
+
} catch {
|
|
141
|
+
// TODO: If it doesn't return anything..
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Makes a raw fetch request with the specified URI, method, and data.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} uri - The endpoint URI for the request.
|
|
150
|
+
* @param {HTTPMethod} method - The HTTP method for the request.
|
|
151
|
+
* @param {any} data - The data to be sent with the request.
|
|
152
|
+
* @param {RequestInit} [options] - Additional options for the request.
|
|
153
|
+
* @returns {Promise<Response>} - A promise that resolves to the fetch response.
|
|
154
|
+
*/
|
|
155
|
+
public async fetch(
|
|
156
|
+
uri: string,
|
|
157
|
+
method: HTTPMethod,
|
|
158
|
+
data: any,
|
|
159
|
+
options?: RequestInit
|
|
160
|
+
) {
|
|
161
|
+
this.verifyServerUrlSet()
|
|
162
|
+
if (uri.startsWith('/')) {
|
|
163
|
+
uri = `${this.options.serverUrl}${uri}`
|
|
164
|
+
} else {
|
|
165
|
+
uri = `${this.options.serverUrl}/${uri}`
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return await corePikkuFetch(uri, data, {
|
|
169
|
+
...options,
|
|
170
|
+
method,
|
|
171
|
+
mode: this.options.mode,
|
|
172
|
+
credentials: this.options.credentials,
|
|
173
|
+
headers: { ...this.getHeaders(), ...options?.headers },
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Verifies that the server URL is set before making a request.
|
|
179
|
+
*
|
|
180
|
+
* @throws {Error} - Throws an error if the server URL is not set.
|
|
181
|
+
*/
|
|
182
|
+
private verifyServerUrlSet() {
|
|
183
|
+
if (!this.options.serverUrl) {
|
|
184
|
+
throw new Error('Server url is not set')
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Transforms date-like strings in the response data into `Date` objects if the `transformDate` option is set.
|
|
190
|
+
*
|
|
191
|
+
* @param {any} data - The data to transform.
|
|
192
|
+
* @returns {any} - The transformed data.
|
|
193
|
+
*/
|
|
194
|
+
private transformDates(data: any): any {
|
|
195
|
+
if (!this.options.transformDate) {
|
|
196
|
+
return data
|
|
197
|
+
}
|
|
198
|
+
return transformDates(data)
|
|
199
|
+
}
|
|
200
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides a wrapper around the Fetch API that integrates with the Pikku framework.
|
|
3
|
+
* It includes utilities for making HTTP requests, such as options for authorization, server URL management,
|
|
4
|
+
* and transforming dates in responses, while ensuring requests are validated against Pikku routes.
|
|
5
|
+
* The module exports the `CorePikkuFetch` class, as well as other supporting types and functions.
|
|
6
|
+
*
|
|
7
|
+
* @module @pikku/fetch
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
CorePikkuFetch,
|
|
12
|
+
CorePikkuFetchOptions,
|
|
13
|
+
HTTPMethod,
|
|
14
|
+
} from './abstract-pikku-fetch.js'
|
|
15
|
+
export { corePikkuFetch } from './pikku-fetch.js'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `corePikkuFetch` function is a utility for making HTTP requests with dynamic URI and data handling.
|
|
3
|
+
* It can automatically replace URI parameters, append query strings for GET requests, and set the request body for POST, PATCH, or PUT requests.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} uri - The endpoint URI for the request. URI parameters can be specified using `:param` syntax.
|
|
6
|
+
* @param {any} data - The data to be included in the request, either as query parameters or as the request body.
|
|
7
|
+
* @param {Omit<RequestInit, 'body'>} [options] - Optional configuration options for the fetch request, excluding the body.
|
|
8
|
+
* @returns {Promise<Response>} - A promise that resolves to the response of the fetch request.
|
|
9
|
+
*/
|
|
10
|
+
export const corePikkuFetch = async (
|
|
11
|
+
uri: string,
|
|
12
|
+
data: any,
|
|
13
|
+
options?: Omit<RequestInit, 'body'>
|
|
14
|
+
) => {
|
|
15
|
+
const method = options?.method?.toUpperCase() || 'GET'
|
|
16
|
+
let body: any | undefined
|
|
17
|
+
|
|
18
|
+
if (data) {
|
|
19
|
+
data = JSON.parse(JSON.stringify(data))
|
|
20
|
+
|
|
21
|
+
const keys = Object.keys(data)
|
|
22
|
+
for (const key of keys) {
|
|
23
|
+
if (uri.includes(`:${key}`)) {
|
|
24
|
+
uri = uri.replace(`:${key}`, data[key])
|
|
25
|
+
delete data[key]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (method === 'POST' || method === 'PATCH' || method === 'PUT') {
|
|
29
|
+
body = data
|
|
30
|
+
} else {
|
|
31
|
+
const queryString = new URLSearchParams(JSON.parse(JSON.stringify(data)))
|
|
32
|
+
uri = `${uri}?${queryString}`
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return await fetch(uri, {
|
|
37
|
+
method: method.toUpperCase(),
|
|
38
|
+
...options,
|
|
39
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
40
|
+
})
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `transformDates` function recursively traverses an object or array and converts any date-like strings
|
|
3
|
+
* into JavaScript `Date` objects. This helps in ensuring that date fields are properly handled as `Date` instances
|
|
4
|
+
* rather than strings.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
* @param {any} data - The input data that may contain date strings. It can be an object, array, or primitive value.
|
|
8
|
+
* @returns {any} - The transformed data with date strings converted to `Date` objects.
|
|
9
|
+
*/
|
|
10
|
+
export const transformDates = (data: any) => {
|
|
11
|
+
if (data === null) return null
|
|
12
|
+
if (Array.isArray(data)) return data.map(transformDates.bind(this))
|
|
13
|
+
if (typeof data === 'object') {
|
|
14
|
+
return Object.entries(data).reduce((result, [key, value]) => {
|
|
15
|
+
result[key] = transformDates(value)
|
|
16
|
+
return result
|
|
17
|
+
}, {} as any)
|
|
18
|
+
}
|
|
19
|
+
if (
|
|
20
|
+
typeof data === 'string' &&
|
|
21
|
+
/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}\.\d{3}Z?)?/.test(data)
|
|
22
|
+
) {
|
|
23
|
+
return new Date(data)
|
|
24
|
+
}
|
|
25
|
+
return data
|
|
26
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "./src",
|
|
5
|
+
"module": "Node16",
|
|
6
|
+
"outDir": "dist/esm",
|
|
7
|
+
"target": "esnext",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"resolveJsonModule": true,
|
|
10
|
+
"lib": ["DOM"]
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/*.ts"],
|
|
13
|
+
"exclude": ["**/*.test.ts", "node_modules"]
|
|
14
|
+
}
|