@scpxl/nodejs-framework 1.0.14 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/api-requester/api-requester.d.ts +27 -6
- package/dist/api-requester/api-requester.d.ts.map +1 -1
- package/dist/api-requester/api-requester.js +188 -26
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/api-requester/index.d.ts +1 -0
- package/dist/api-requester/index.d.ts.map +1 -1
- package/dist/api-requester/index.js.map +1 -1
- package/dist/application/base-application.d.ts +16 -20
- package/dist/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.js +152 -109
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/command-application.d.ts.map +1 -1
- package/dist/application/command-application.js +3 -4
- package/dist/application/command-application.js.map +2 -2
- package/dist/application/web-application.d.ts.map +1 -1
- package/dist/application/web-application.js +9 -2
- package/dist/application/web-application.js.map +2 -2
- package/dist/cache/manager.d.ts +87 -6
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +77 -30
- package/dist/cache/manager.js.map +2 -2
- package/dist/cluster/cluster-manager.d.ts.map +1 -1
- package/dist/cluster/cluster-manager.js +7 -9
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/config/env.d.ts +11 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +103 -0
- package/dist/config/env.js.map +7 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +7 -0
- package/dist/config/schema.d.ts +408 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +218 -0
- package/dist/config/schema.js.map +7 -0
- package/dist/database/dynamic-entity.d.ts.map +1 -1
- package/dist/database/dynamic-entity.js +6 -2
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/instance.d.ts.map +1 -1
- package/dist/database/instance.js +0 -8
- package/dist/database/instance.js.map +2 -2
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +71 -9
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.d.ts +96 -0
- package/dist/error/error-reporter.d.ts.map +1 -0
- package/dist/error/error-reporter.js +228 -0
- package/dist/error/error-reporter.js.map +7 -0
- package/dist/error/error.interface.d.ts +126 -0
- package/dist/error/error.interface.d.ts.map +1 -0
- package/dist/error/error.interface.js +45 -0
- package/dist/error/error.interface.js.map +7 -0
- package/dist/error/framework-errors.d.ts +113 -0
- package/dist/error/framework-errors.d.ts.map +1 -0
- package/dist/error/framework-errors.js +176 -0
- package/dist/error/framework-errors.js.map +7 -0
- package/dist/error/index.d.ts +6 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +34 -0
- package/dist/error/index.js.map +7 -0
- package/dist/event/manager.d.ts.map +1 -1
- package/dist/event/manager.js +2 -9
- package/dist/event/manager.js.map +2 -2
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +2 -2
- package/dist/lifecycle/exit.d.ts +11 -0
- package/dist/lifecycle/exit.d.ts.map +1 -0
- package/dist/lifecycle/exit.js +29 -0
- package/dist/lifecycle/exit.js.map +7 -0
- package/dist/lifecycle/index.d.ts +7 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +12 -0
- package/dist/lifecycle/index.js.map +7 -0
- package/dist/lifecycle/lifecycle-manager.d.ts +66 -0
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-manager.js +280 -0
- package/dist/lifecycle/lifecycle-manager.js.map +7 -0
- package/dist/lifecycle/shutdown-controller.d.ts +15 -0
- package/dist/lifecycle/shutdown-controller.d.ts.map +1 -0
- package/dist/lifecycle/shutdown-controller.js +38 -0
- package/dist/lifecycle/shutdown-controller.js.map +7 -0
- package/dist/lifecycle/types.d.ts +28 -0
- package/dist/lifecycle/types.d.ts.map +1 -0
- package/dist/lifecycle/types.js +13 -0
- package/dist/lifecycle/types.js.map +7 -0
- package/dist/logger/logger.d.ts +2 -1
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +35 -11
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/cache-performance.d.ts +6 -0
- package/dist/performance/cache-performance.d.ts.map +1 -1
- package/dist/performance/cache-performance.js +16 -0
- package/dist/performance/cache-performance.js.map +2 -2
- package/dist/performance/index.d.ts +1 -0
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +1 -0
- package/dist/performance/index.js.map +2 -2
- package/dist/performance/performance-monitor.d.ts.map +1 -1
- package/dist/performance/performance-monitor.js +47 -18
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/performance/performance-monitor.plugin.d.ts +24 -0
- package/dist/performance/performance-monitor.plugin.d.ts.map +1 -0
- package/dist/performance/performance-monitor.plugin.js +89 -0
- package/dist/performance/performance-monitor.plugin.js.map +7 -0
- package/dist/performance/webserver-performance.js +1 -1
- package/dist/performance/webserver-performance.js.map +2 -2
- package/dist/queue/manager.d.ts.map +1 -1
- package/dist/queue/manager.js +3 -10
- package/dist/queue/manager.js.map +2 -2
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/queue/worker.js +2 -2
- package/dist/queue/worker.js.map +2 -2
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +228 -33
- package/dist/redis/manager.js.map +2 -2
- package/dist/request-context/index.d.ts +3 -0
- package/dist/request-context/index.d.ts.map +1 -0
- package/dist/request-context/index.js +25 -0
- package/dist/request-context/index.js.map +7 -0
- package/dist/request-context/request-context.d.ts +108 -0
- package/dist/request-context/request-context.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.d.ts +46 -0
- package/dist/request-context/request-context.interface.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.js +1 -0
- package/dist/request-context/request-context.interface.js.map +7 -0
- package/dist/request-context/request-context.js +79 -0
- package/dist/request-context/request-context.js.map +7 -0
- package/dist/services/aws/s3.js +4 -6
- package/dist/services/aws/s3.js.map +2 -2
- package/dist/util/file.d.ts +13 -0
- package/dist/util/file.d.ts.map +1 -1
- package/dist/util/file.js +46 -9
- package/dist/util/file.js.map +2 -2
- package/dist/util/helper.d.ts +16 -1
- package/dist/util/helper.d.ts.map +1 -1
- package/dist/util/helper.js +19 -43
- package/dist/util/helper.js.map +2 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +18 -16
- package/dist/util/index.js.map +2 -2
- package/dist/util/loader.d.ts.map +1 -1
- package/dist/util/loader.js +13 -2
- package/dist/util/loader.js.map +2 -2
- package/dist/util/os.d.ts.map +1 -1
- package/dist/util/os.js +8 -14
- package/dist/util/os.js.map +2 -2
- package/dist/util/time.d.ts +8 -2
- package/dist/util/time.d.ts.map +1 -1
- package/dist/util/time.js +12 -7
- package/dist/util/time.js.map +2 -2
- package/dist/util/timing.d.ts +36 -0
- package/dist/util/timing.d.ts.map +1 -0
- package/dist/util/timing.interface.d.ts +47 -0
- package/dist/util/timing.interface.d.ts.map +1 -0
- package/dist/util/timing.interface.js +1 -0
- package/dist/util/timing.interface.js.map +7 -0
- package/dist/util/timing.js +98 -0
- package/dist/util/timing.js.map +7 -0
- package/dist/util/url.js +1 -1
- package/dist/util/url.js.map +2 -2
- package/dist/webserver/controller/base.d.ts +3 -1
- package/dist/webserver/controller/base.d.ts.map +1 -1
- package/dist/webserver/controller/base.interface.d.ts +2 -0
- package/dist/webserver/controller/base.interface.d.ts.map +1 -1
- package/dist/webserver/controller/base.js +4 -1
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/health.d.ts +8 -1
- package/dist/webserver/controller/health.d.ts.map +1 -1
- package/dist/webserver/controller/health.js +36 -22
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/webserver.d.ts +16 -2
- package/dist/webserver/webserver.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.d.ts +37 -0
- package/dist/webserver/webserver.interface.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.js.map +2 -2
- package/dist/webserver/webserver.js +117 -20
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/controllers/server/system.d.ts.map +1 -1
- package/dist/websocket/controllers/server/system.js.map +2 -2
- package/dist/websocket/websocket-base.d.ts.map +1 -1
- package/dist/websocket/websocket-base.js +2 -3
- package/dist/websocket/websocket-base.js.map +2 -2
- package/dist/websocket/websocket-server.d.ts +1 -1
- package/dist/websocket/websocket-server.d.ts.map +1 -1
- package/dist/websocket/websocket-server.js +7 -31
- package/dist/websocket/websocket-server.js.map +2 -2
- package/package.json +68 -25
package/README.md
CHANGED
|
@@ -100,6 +100,35 @@ class UserService {
|
|
|
100
100
|
}
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
+
## Examples
|
|
104
|
+
|
|
105
|
+
The `examples/` directory contains working examples demonstrating the framework:
|
|
106
|
+
|
|
107
|
+
### Hello World Example
|
|
108
|
+
|
|
109
|
+
A simple full-stack example with:
|
|
110
|
+
|
|
111
|
+
- Backend: PXL WebApplication with TypeScript
|
|
112
|
+
- Frontend: Vue 3 + TypeScript + Vite
|
|
113
|
+
|
|
114
|
+
**Run the example:**
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Install dependencies for the example (one-time setup)
|
|
118
|
+
npm run example:install
|
|
119
|
+
|
|
120
|
+
# Run backend + frontend together with hot-reload
|
|
121
|
+
npm run example:hello-world
|
|
122
|
+
|
|
123
|
+
# Or run individually
|
|
124
|
+
npm run example:hello-world:backend
|
|
125
|
+
npm run example:hello-world:frontend
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Then open http://localhost:5173 to see the app.
|
|
129
|
+
|
|
130
|
+
See [examples/README.md](examples/README.md) for more details.
|
|
131
|
+
|
|
103
132
|
## When Not to Use
|
|
104
133
|
|
|
105
134
|
If you only need a single HTTP server or minimal script, this framework may be heavier than needed.
|
|
@@ -1,11 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
export interface ApiRequestConfig extends Omit<RequestInit, 'method' | 'body' | 'headers'> {
|
|
2
|
+
headers?: Record<string, string | undefined>;
|
|
3
|
+
params?: Record<string, string | number | boolean | null | undefined>;
|
|
4
|
+
responseType?: 'json' | 'text';
|
|
5
|
+
}
|
|
6
|
+
export interface ApiResponse<T> {
|
|
7
|
+
data: T;
|
|
8
|
+
status: number;
|
|
9
|
+
statusText: string;
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
}
|
|
2
12
|
export default class ApiRequester {
|
|
3
|
-
private
|
|
13
|
+
private readonly baseURL;
|
|
14
|
+
private readonly defaultHeaders;
|
|
4
15
|
constructor(baseURL: string, headers?: Record<string, string>);
|
|
5
|
-
get<T>(url: string, config?:
|
|
6
|
-
post<T, R>(url: string, data: T, config?:
|
|
7
|
-
put<T, R>(url: string, data: T, config?:
|
|
8
|
-
delete<T>(url: string, config?:
|
|
16
|
+
get<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T> | undefined>;
|
|
17
|
+
post<T, R>(url: string, data: T, config?: ApiRequestConfig): Promise<ApiResponse<R> | undefined>;
|
|
18
|
+
put<T, R>(url: string, data: T, config?: ApiRequestConfig): Promise<ApiResponse<R> | undefined>;
|
|
19
|
+
delete<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T> | undefined>;
|
|
20
|
+
private request;
|
|
21
|
+
private mergeHeaders;
|
|
22
|
+
private prepareBody;
|
|
23
|
+
private shouldSerializeAsJson;
|
|
24
|
+
private headersToRecord;
|
|
25
|
+
private buildUrl;
|
|
26
|
+
private isAbsoluteUrl;
|
|
27
|
+
private combineWithBase;
|
|
28
|
+
private parseResponse;
|
|
29
|
+
private createHttpError;
|
|
9
30
|
private handleError;
|
|
10
31
|
}
|
|
11
32
|
//# sourceMappingURL=api-requester.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-requester.d.ts","sourceRoot":"","sources":["../../src/api-requester/api-requester.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"api-requester.d.ts","sourceRoot":"","sources":["../../src/api-requester/api-requester.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACtE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AA0BD,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;gBAE5C,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAKpD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAInF,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAIhG,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAI/F,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;YAIrF,OAAO;IAsCrB,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;YAUT,aAAa;YAkBb,eAAe;IAoC7B,OAAO,CAAC,WAAW;CAapB"}
|
|
@@ -1,52 +1,214 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
|
|
3
|
+
class ApiRequesterHttpError extends Error {
|
|
4
|
+
static {
|
|
5
|
+
__name(this, "ApiRequesterHttpError");
|
|
6
|
+
}
|
|
7
|
+
status;
|
|
8
|
+
statusText;
|
|
9
|
+
data;
|
|
10
|
+
headers;
|
|
11
|
+
constructor(message, options) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "ApiRequesterHttpError";
|
|
14
|
+
this.status = options.status;
|
|
15
|
+
this.statusText = options.statusText;
|
|
16
|
+
this.data = options.data;
|
|
17
|
+
this.headers = options.headers;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
4
20
|
class ApiRequester {
|
|
5
21
|
static {
|
|
6
22
|
__name(this, "ApiRequester");
|
|
7
23
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
});
|
|
24
|
+
baseURL;
|
|
25
|
+
defaultHeaders;
|
|
26
|
+
constructor(baseURL, headers = {}) {
|
|
27
|
+
this.baseURL = baseURL;
|
|
28
|
+
this.defaultHeaders = { ...headers };
|
|
14
29
|
}
|
|
15
30
|
async get(url, config) {
|
|
16
|
-
|
|
17
|
-
const response = await this.axiosInstance.get(url, config);
|
|
18
|
-
return response;
|
|
19
|
-
} catch (error) {
|
|
20
|
-
this.handleError(error);
|
|
21
|
-
}
|
|
31
|
+
return this.request("GET", url, void 0, config);
|
|
22
32
|
}
|
|
23
33
|
async post(url, data, config) {
|
|
34
|
+
return this.request("POST", url, data, config);
|
|
35
|
+
}
|
|
36
|
+
async put(url, data, config) {
|
|
37
|
+
return this.request("PUT", url, data, config);
|
|
38
|
+
}
|
|
39
|
+
async delete(url, config) {
|
|
40
|
+
return this.request("DELETE", url, void 0, config);
|
|
41
|
+
}
|
|
42
|
+
async request(method, url, data, config) {
|
|
24
43
|
try {
|
|
25
|
-
const
|
|
26
|
-
|
|
44
|
+
const { headers: configHeaders, params, responseType = "json", ...init } = config ?? {};
|
|
45
|
+
const finalUrl = this.buildUrl(url, params);
|
|
46
|
+
const headers = this.mergeHeaders(configHeaders, data);
|
|
47
|
+
const body = this.prepareBody(method, data);
|
|
48
|
+
const response = await fetch(finalUrl, {
|
|
49
|
+
...init,
|
|
50
|
+
method,
|
|
51
|
+
headers,
|
|
52
|
+
body
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
throw await this.createHttpError(response);
|
|
56
|
+
}
|
|
57
|
+
const parsed = await this.parseResponse(response, responseType);
|
|
58
|
+
return {
|
|
59
|
+
data: parsed,
|
|
60
|
+
status: response.status,
|
|
61
|
+
statusText: response.statusText,
|
|
62
|
+
headers: this.headersToRecord(response.headers)
|
|
63
|
+
};
|
|
27
64
|
} catch (error) {
|
|
28
65
|
this.handleError(error);
|
|
29
66
|
}
|
|
30
67
|
}
|
|
31
|
-
|
|
68
|
+
mergeHeaders(headers, body) {
|
|
69
|
+
const merged = new Headers();
|
|
70
|
+
for (const [key, value] of Object.entries(this.defaultHeaders)) {
|
|
71
|
+
if (value !== void 0) {
|
|
72
|
+
merged.set(key, value);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (headers) {
|
|
76
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
77
|
+
if (value !== void 0) {
|
|
78
|
+
merged.set(key, value);
|
|
79
|
+
} else {
|
|
80
|
+
merged.delete(key);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (body !== void 0 && this.shouldSerializeAsJson(body) && !merged.has("content-type")) {
|
|
85
|
+
merged.set("content-type", "application/json");
|
|
86
|
+
}
|
|
87
|
+
return merged;
|
|
88
|
+
}
|
|
89
|
+
prepareBody(method, data) {
|
|
90
|
+
if (method === "GET" || method === "HEAD" || data === void 0) {
|
|
91
|
+
return void 0;
|
|
92
|
+
}
|
|
93
|
+
if (typeof data === "string" || data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
|
94
|
+
return data;
|
|
95
|
+
}
|
|
96
|
+
if (typeof Blob !== "undefined" && data instanceof Blob) {
|
|
97
|
+
return data;
|
|
98
|
+
}
|
|
99
|
+
if (typeof FormData !== "undefined" && data instanceof FormData) {
|
|
100
|
+
return data;
|
|
101
|
+
}
|
|
102
|
+
if (typeof URLSearchParams !== "undefined" && data instanceof URLSearchParams) {
|
|
103
|
+
return data;
|
|
104
|
+
}
|
|
105
|
+
if (typeof ReadableStream !== "undefined" && data instanceof ReadableStream) {
|
|
106
|
+
return data;
|
|
107
|
+
}
|
|
108
|
+
return JSON.stringify(data);
|
|
109
|
+
}
|
|
110
|
+
shouldSerializeAsJson(data) {
|
|
111
|
+
if (data === null) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
if (Array.isArray(data)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
const primitiveTypes = ["string", "number", "boolean", "bigint"];
|
|
118
|
+
if (primitiveTypes.includes(typeof data)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (typeof data === "object") {
|
|
122
|
+
return !(data instanceof ArrayBuffer || ArrayBuffer.isView(data) || typeof Blob !== "undefined" && data instanceof Blob || typeof FormData !== "undefined" && data instanceof FormData || typeof URLSearchParams !== "undefined" && data instanceof URLSearchParams || typeof ReadableStream !== "undefined" && data instanceof ReadableStream || typeof Buffer !== "undefined" && Buffer.isBuffer(data));
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
headersToRecord(headers) {
|
|
127
|
+
const result = {};
|
|
128
|
+
headers.forEach((value, key) => {
|
|
129
|
+
result[key] = value;
|
|
130
|
+
});
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
buildUrl(path, params) {
|
|
134
|
+
const absolute = this.isAbsoluteUrl(path) ? path : this.combineWithBase(path);
|
|
135
|
+
if (!params) {
|
|
136
|
+
return absolute;
|
|
137
|
+
}
|
|
138
|
+
const url = new URL(absolute);
|
|
139
|
+
for (const [key, rawValue] of Object.entries(params)) {
|
|
140
|
+
if (rawValue === void 0 || rawValue === null) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
url.searchParams.set(key, String(rawValue));
|
|
144
|
+
}
|
|
145
|
+
return url.toString();
|
|
146
|
+
}
|
|
147
|
+
isAbsoluteUrl(url) {
|
|
148
|
+
return /^https?:\/\//i.test(url);
|
|
149
|
+
}
|
|
150
|
+
combineWithBase(path) {
|
|
151
|
+
if (!this.baseURL) {
|
|
152
|
+
return path;
|
|
153
|
+
}
|
|
154
|
+
const normalizedBase = this.baseURL.endsWith("/") ? this.baseURL.slice(0, -1) : this.baseURL;
|
|
155
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
156
|
+
return `${normalizedBase}${normalizedPath}`;
|
|
157
|
+
}
|
|
158
|
+
async parseResponse(response, responseType) {
|
|
159
|
+
if (responseType === "text") {
|
|
160
|
+
return await response.text();
|
|
161
|
+
}
|
|
162
|
+
const body = await response.text();
|
|
163
|
+
if (!body) {
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
32
166
|
try {
|
|
33
|
-
|
|
34
|
-
return response;
|
|
167
|
+
return JSON.parse(body);
|
|
35
168
|
} catch (error) {
|
|
36
|
-
|
|
169
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
170
|
+
throw new Error(`Failed to parse JSON response: ${reason}`);
|
|
37
171
|
}
|
|
38
172
|
}
|
|
39
|
-
async
|
|
173
|
+
async createHttpError(response) {
|
|
174
|
+
const headers = this.headersToRecord(response.headers);
|
|
175
|
+
let data = void 0;
|
|
176
|
+
let message = `Request failed with status ${response.status}`;
|
|
40
177
|
try {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
178
|
+
const text = await response.text();
|
|
179
|
+
if (text) {
|
|
180
|
+
const contentType = headers["content-type"] ?? "";
|
|
181
|
+
if (contentType.includes("application/json")) {
|
|
182
|
+
data = JSON.parse(text);
|
|
183
|
+
if (data && typeof data === "object" && "message" in data) {
|
|
184
|
+
const potentialMessage = data.message;
|
|
185
|
+
if (typeof potentialMessage === "string") {
|
|
186
|
+
message = potentialMessage;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
data = text;
|
|
191
|
+
message = text;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
} catch {
|
|
195
|
+
data = void 0;
|
|
196
|
+
message = `Request failed with status ${response.status}`;
|
|
45
197
|
}
|
|
198
|
+
return new ApiRequesterHttpError(message, {
|
|
199
|
+
status: response.status,
|
|
200
|
+
statusText: response.statusText,
|
|
201
|
+
data,
|
|
202
|
+
headers
|
|
203
|
+
});
|
|
46
204
|
}
|
|
47
205
|
handleError(error) {
|
|
48
|
-
if (
|
|
49
|
-
console.error("
|
|
206
|
+
if (error instanceof ApiRequesterHttpError) {
|
|
207
|
+
console.error("HTTP error:", {
|
|
208
|
+
status: error.status,
|
|
209
|
+
statusText: error.statusText,
|
|
210
|
+
data: error.data
|
|
211
|
+
});
|
|
50
212
|
} else {
|
|
51
213
|
console.error("Unexpected error:", error);
|
|
52
214
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/api-requester/api-requester.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";;AAAA,OAAO,
|
|
4
|
+
"sourcesContent": ["export interface ApiRequestConfig extends Omit<RequestInit, 'method' | 'body' | 'headers'> {\n headers?: Record<string, string | undefined>;\n params?: Record<string, string | number | boolean | null | undefined>;\n responseType?: 'json' | 'text';\n}\n\nexport interface ApiResponse<T> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n}\n\nclass ApiRequesterHttpError extends Error {\n public readonly status: number;\n public readonly statusText: string;\n public readonly data: unknown;\n public readonly headers: Record<string, string>;\n\n constructor(\n message: string,\n options: {\n status: number;\n statusText: string;\n data: unknown;\n headers: Record<string, string>;\n },\n ) {\n super(message);\n this.name = 'ApiRequesterHttpError';\n this.status = options.status;\n this.statusText = options.statusText;\n this.data = options.data;\n this.headers = options.headers;\n }\n}\n\nexport default class ApiRequester {\n private readonly baseURL: string;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(baseURL: string, headers: Record<string, string> = {}) {\n this.baseURL = baseURL;\n this.defaultHeaders = { ...headers };\n }\n\n public async get<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T> | undefined> {\n return this.request<T>('GET', url, undefined, config);\n }\n\n public async post<T, R>(url: string, data: T, config?: ApiRequestConfig): Promise<ApiResponse<R> | undefined> {\n return this.request<R>('POST', url, data, config);\n }\n\n public async put<T, R>(url: string, data: T, config?: ApiRequestConfig): Promise<ApiResponse<R> | undefined> {\n return this.request<R>('PUT', url, data, config);\n }\n\n public async delete<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T> | undefined> {\n return this.request<T>('DELETE', url, undefined, config);\n }\n\n private async request<T>(\n method: string,\n url: string,\n data?: unknown,\n config?: ApiRequestConfig,\n ): Promise<ApiResponse<T> | undefined> {\n try {\n const { headers: configHeaders, params, responseType = 'json', ...init } = config ?? {};\n const finalUrl = this.buildUrl(url, params);\n const headers = this.mergeHeaders(configHeaders, data);\n const body = this.prepareBody(method, data);\n\n // fetch is a global in Node.js 18+\n // eslint-disable-next-line no-undef\n const response = await fetch(finalUrl, {\n ...init,\n method,\n headers,\n body,\n });\n\n if (!response.ok) {\n throw await this.createHttpError(response);\n }\n\n const parsed = await this.parseResponse<T>(response, responseType);\n\n return {\n data: parsed,\n status: response.status,\n statusText: response.statusText,\n headers: this.headersToRecord(response.headers),\n };\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private mergeHeaders(headers?: Record<string, string | undefined>, body?: unknown): Headers {\n const merged = new Headers();\n\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n if (value !== undefined) {\n merged.set(key, value);\n }\n }\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) {\n merged.set(key, value);\n } else {\n merged.delete(key);\n }\n }\n }\n\n if (body !== undefined && this.shouldSerializeAsJson(body) && !merged.has('content-type')) {\n merged.set('content-type', 'application/json');\n }\n\n return merged;\n }\n\n private prepareBody(method: string, data?: unknown): BodyInit | null | undefined {\n if (method === 'GET' || method === 'HEAD' || data === undefined) {\n return undefined;\n }\n\n if (typeof data === 'string' || data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {\n return data as BodyInit;\n }\n\n if (typeof Blob !== 'undefined' && data instanceof Blob) {\n return data;\n }\n\n if (typeof FormData !== 'undefined' && data instanceof FormData) {\n return data;\n }\n\n if (typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams) {\n return data;\n }\n\n if (typeof ReadableStream !== 'undefined' && data instanceof ReadableStream) {\n return data;\n }\n\n return JSON.stringify(data);\n }\n\n private shouldSerializeAsJson(data: unknown): boolean {\n if (data === null) {\n return true;\n }\n\n if (Array.isArray(data)) {\n return true;\n }\n\n const primitiveTypes = ['string', 'number', 'boolean', 'bigint'];\n if (primitiveTypes.includes(typeof data)) {\n return false;\n }\n\n if (typeof data === 'object') {\n return !(\n data instanceof ArrayBuffer ||\n ArrayBuffer.isView(data) ||\n (typeof Blob !== 'undefined' && data instanceof Blob) ||\n (typeof FormData !== 'undefined' && data instanceof FormData) ||\n (typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams) ||\n (typeof ReadableStream !== 'undefined' && data instanceof ReadableStream) ||\n (typeof Buffer !== 'undefined' && Buffer.isBuffer(data))\n );\n }\n\n return false;\n }\n\n private headersToRecord(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n // Safe: key comes from Headers iterator, not user input\n // eslint-disable-next-line security/detect-object-injection\n result[key] = value;\n });\n return result;\n }\n\n private buildUrl(path: string, params?: Record<string, string | number | boolean | null | undefined>): string {\n const absolute = this.isAbsoluteUrl(path) ? path : this.combineWithBase(path);\n if (!params) {\n return absolute;\n }\n\n const url = new URL(absolute);\n for (const [key, rawValue] of Object.entries(params)) {\n if (rawValue === undefined || rawValue === null) {\n continue;\n }\n url.searchParams.set(key, String(rawValue));\n }\n return url.toString();\n }\n\n private isAbsoluteUrl(url: string): boolean {\n return /^https?:\\/\\//i.test(url);\n }\n\n private combineWithBase(path: string): string {\n if (!this.baseURL) {\n return path;\n }\n\n const normalizedBase = this.baseURL.endsWith('/') ? this.baseURL.slice(0, -1) : this.baseURL;\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n return `${normalizedBase}${normalizedPath}`;\n }\n\n private async parseResponse<T>(response: Response, responseType: 'json' | 'text'): Promise<T> {\n if (responseType === 'text') {\n return (await response.text()) as T;\n }\n\n const body = await response.text();\n if (!body) {\n return undefined as T;\n }\n\n try {\n return JSON.parse(body) as T;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse JSON response: ${reason}`);\n }\n }\n\n private async createHttpError(response: Response): Promise<ApiRequesterHttpError> {\n const headers = this.headersToRecord(response.headers);\n let data: unknown = undefined;\n let message = `Request failed with status ${response.status}`;\n\n try {\n const text = await response.text();\n if (text) {\n const contentType = headers['content-type'] ?? '';\n if (contentType.includes('application/json')) {\n data = JSON.parse(text);\n if (data && typeof data === 'object' && 'message' in (data as Record<string, unknown>)) {\n const potentialMessage = (data as Record<string, unknown>).message;\n if (typeof potentialMessage === 'string') {\n message = potentialMessage;\n }\n }\n } else {\n data = text;\n message = text;\n }\n }\n } catch {\n // If parsing fails, use defaults set above\n data = undefined;\n message = `Request failed with status ${response.status}`;\n }\n\n return new ApiRequesterHttpError(message, {\n status: response.status,\n statusText: response.statusText,\n data,\n headers,\n });\n }\n\n private handleError(error: unknown): never {\n if (error instanceof ApiRequesterHttpError) {\n console.error('HTTP error:', {\n status: error.status,\n statusText: error.statusText,\n data: error.data,\n });\n } else {\n console.error('Unexpected error:', error);\n }\n\n throw error;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-requester/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api-requester/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/api-requester/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { default as ApiRequester } from './api-requester.js';\n"],
|
|
4
|
+
"sourcesContent": ["export { default as ApiRequester } from './api-requester.js';\nexport type { ApiRequestConfig, ApiResponse } from './api-requester.js';\n"],
|
|
5
5
|
"mappings": "AAAA,SAAoB,WAAXA,gBAA+B;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import { type DatabaseInstance, DatabaseManager } from '../database/index.js';
|
|
2
2
|
import QueueManager from '../queue/manager.js';
|
|
3
3
|
import RedisManager from '../redis/manager.js';
|
|
4
|
-
import type { ApplicationConfig } from './base-application.interface.js';
|
|
4
|
+
import type { ApplicationConfig, ApplicationStopInstanceOptions } from './base-application.interface.js';
|
|
5
5
|
import type RedisInstance from '../redis/instance.js';
|
|
6
6
|
import CacheManager from '../cache/manager.js';
|
|
7
7
|
import EventManager from '../event/manager.js';
|
|
8
|
-
import { PerformanceMonitor } from '../performance/performance-monitor.js';
|
|
8
|
+
import type { PerformanceMonitor } from '../performance/performance-monitor.js';
|
|
9
|
+
import { LifecycleManager, ShutdownController } from '../lifecycle/index.js';
|
|
9
10
|
export type { ApplicationConfig } from './base-application.interface.js';
|
|
10
11
|
export default abstract class BaseApplication {
|
|
11
12
|
/** Unique instance ID */
|
|
12
13
|
uniqueInstanceId: string;
|
|
13
|
-
/** Shutdown signals */
|
|
14
|
-
protected shutdownSignals: NodeJS.Signals[];
|
|
15
14
|
/** Application start time */
|
|
16
|
-
protected startTime:
|
|
17
|
-
/** Whether application is stopping */
|
|
18
|
-
protected isStopping: boolean;
|
|
15
|
+
protected startTime: number;
|
|
19
16
|
/** Shutdown timeout (30 seconds) */
|
|
20
17
|
protected shutdownTimeout: number;
|
|
21
18
|
/** Cache for application version to avoid repeated imports */
|
|
@@ -38,6 +35,10 @@ export default abstract class BaseApplication {
|
|
|
38
35
|
eventManager?: EventManager;
|
|
39
36
|
/** Performance monitor */
|
|
40
37
|
performanceMonitor?: PerformanceMonitor;
|
|
38
|
+
/** Lifecycle manager */
|
|
39
|
+
lifecycle: LifecycleManager;
|
|
40
|
+
/** Shutdown controller */
|
|
41
|
+
shutdownController: ShutdownController;
|
|
41
42
|
get Name(): string;
|
|
42
43
|
/**
|
|
43
44
|
* Application constructor
|
|
@@ -67,10 +68,6 @@ export default abstract class BaseApplication {
|
|
|
67
68
|
protected onStopped({ runtime: _runtime }: {
|
|
68
69
|
runtime: number;
|
|
69
70
|
}): void;
|
|
70
|
-
/**
|
|
71
|
-
* Before application stop event
|
|
72
|
-
*/
|
|
73
|
-
private onBeforeStop;
|
|
74
71
|
/**
|
|
75
72
|
* Start application instance
|
|
76
73
|
*/
|
|
@@ -88,23 +85,22 @@ export default abstract class BaseApplication {
|
|
|
88
85
|
/**
|
|
89
86
|
* Initialize performance monitor
|
|
90
87
|
*/
|
|
91
|
-
private initializePerformanceMonitor;
|
|
92
88
|
private setupGlobalErrorHandlers;
|
|
89
|
+
/**
|
|
90
|
+
* Register shutdown hooks for proper cleanup
|
|
91
|
+
*/
|
|
92
|
+
private registerShutdownHooks;
|
|
93
93
|
/**
|
|
94
94
|
* Initiate graceful shutdown
|
|
95
95
|
*/
|
|
96
96
|
private initiateGracefulShutdown;
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Stop application using lifecycle manager
|
|
99
99
|
*/
|
|
100
|
-
|
|
101
|
-
onStopped?: ({ runtime }: {
|
|
102
|
-
runtime: number;
|
|
103
|
-
}) => void;
|
|
104
|
-
}): void;
|
|
100
|
+
stop({ onStopped }?: ApplicationStopInstanceOptions): Promise<void>;
|
|
105
101
|
/**
|
|
106
|
-
*
|
|
102
|
+
* Finalize exit: during tests, suppress actual process exit to avoid failing vitest runs.
|
|
107
103
|
*/
|
|
108
|
-
private
|
|
104
|
+
private finalizeExit;
|
|
109
105
|
}
|
|
110
106
|
//# sourceMappingURL=base-application.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-application.d.ts","sourceRoot":"","sources":["../../src/application/base-application.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAC/C,OAAO,YAAY,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EACV,iBAAiB,
|
|
1
|
+
{"version":3,"file":"base-application.d.ts","sourceRoot":"","sources":["../../src/application/base-application.ts"],"names":[],"mappings":"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"}
|