@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 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,3 @@
1
+ # @pikku/fetch
2
+
3
+ This package is part of @pikku/mono and is responsible making HTTP calls that are correctly typed and pikku compatible.
@@ -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
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "module": "commonjs",
6
+ "outDir": "dist/cjs",
7
+ "target": "es2015",
8
+ "moduleResolution": "node"
9
+ },
10
+ "exclude": ["**/*.test.ts", "node_modules", "dist"]
11
+ }
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
+ }