@forklaunch/core 0.8.7 → 0.8.9
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/lib/src/http/index.d.mts +13 -1
- package/lib/src/http/index.d.ts +13 -1
- package/lib/src/http/index.js +55 -37
- package/lib/src/http/index.js.map +1 -1
- package/lib/src/http/index.mjs +41 -25
- package/lib/src/http/index.mjs.map +1 -1
- package/lib/src/services/index.d.mts +2 -2
- package/lib/src/services/index.d.ts +2 -2
- package/lib/src/services/index.js +6 -6
- package/lib/src/services/index.js.map +1 -1
- package/lib/src/services/index.mjs +6 -6
- package/lib/src/services/index.mjs.map +1 -1
- package/package.json +19 -19
- package/lib/src/persistence/index.d.mts +0 -120
- package/lib/src/persistence/index.d.ts +0 -120
- package/lib/src/persistence/index.js +0 -152
- package/lib/src/persistence/index.js.map +0 -1
- package/lib/src/persistence/index.mjs +0 -127
- package/lib/src/persistence/index.mjs.map +0 -1
package/lib/src/http/index.d.mts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { AnySchemaValidator, UnboxedObjectSchema, IdiomaticSchema, Schema } from '@forklaunch/validator';
|
2
|
+
import { CorsOptions } from 'cors';
|
2
3
|
import { Counter, Gauge, Histogram, UpDownCounter, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Span } from '@opentelemetry/api';
|
3
4
|
import { LevelWithSilentOrString, LevelWithSilent, Logger } from 'pino';
|
4
5
|
import { UnionToIntersection, MimeType, Prettify, ExclusiveRecord, RemoveTrailingSlash, MakePropertyOptionalIfChildrenOptional } from '@forklaunch/common';
|
@@ -491,6 +492,12 @@ interface ForklaunchResponse<BaseResponse, ResBodyMap extends Record<number, unk
|
|
491
492
|
* @returns {Omit<ResHeaders, keyof ForklaunchResHeaders> & ForklaunchResHeaders} - The headers of the response.
|
492
493
|
*/
|
493
494
|
getHeaders: () => Omit<ResHeaders, keyof ForklaunchResHeaders> & ForklaunchResHeaders;
|
495
|
+
/**
|
496
|
+
* Gets a header for the response.
|
497
|
+
* @param {string} key - The header key.
|
498
|
+
* @returns {string | string[] | undefined} The header value.
|
499
|
+
*/
|
500
|
+
getHeader: (key: string) => string | string[] | undefined;
|
494
501
|
/**
|
495
502
|
* Sets a header for the response.
|
496
503
|
* @param {string} key - The header key.
|
@@ -946,12 +953,17 @@ declare abstract class ForklaunchExpressLikeApplication<SV extends AnySchemaVali
|
|
946
953
|
readonly internal: Server;
|
947
954
|
readonly postEnrichMiddleware: RouterHandler[];
|
948
955
|
readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>;
|
956
|
+
readonly appOptions?: {
|
957
|
+
cors?: CorsOptions;
|
958
|
+
} | undefined;
|
949
959
|
/**
|
950
960
|
* Creates an instance of the Application class.
|
951
961
|
*
|
952
962
|
* @param {SV} schemaValidator - The schema validator.
|
953
963
|
*/
|
954
|
-
constructor(schemaValidator: SV, internal: Server, postEnrichMiddleware: RouterHandler[], openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition
|
964
|
+
constructor(schemaValidator: SV, internal: Server, postEnrichMiddleware: RouterHandler[], openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>, appOptions?: {
|
965
|
+
cors?: CorsOptions;
|
966
|
+
} | undefined);
|
955
967
|
abstract listen(...args: unknown[]): void;
|
956
968
|
}
|
957
969
|
|
package/lib/src/http/index.d.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { AnySchemaValidator, UnboxedObjectSchema, IdiomaticSchema, Schema } from '@forklaunch/validator';
|
2
|
+
import { CorsOptions } from 'cors';
|
2
3
|
import { Counter, Gauge, Histogram, UpDownCounter, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Span } from '@opentelemetry/api';
|
3
4
|
import { LevelWithSilentOrString, LevelWithSilent, Logger } from 'pino';
|
4
5
|
import { UnionToIntersection, MimeType, Prettify, ExclusiveRecord, RemoveTrailingSlash, MakePropertyOptionalIfChildrenOptional } from '@forklaunch/common';
|
@@ -491,6 +492,12 @@ interface ForklaunchResponse<BaseResponse, ResBodyMap extends Record<number, unk
|
|
491
492
|
* @returns {Omit<ResHeaders, keyof ForklaunchResHeaders> & ForklaunchResHeaders} - The headers of the response.
|
492
493
|
*/
|
493
494
|
getHeaders: () => Omit<ResHeaders, keyof ForklaunchResHeaders> & ForklaunchResHeaders;
|
495
|
+
/**
|
496
|
+
* Gets a header for the response.
|
497
|
+
* @param {string} key - The header key.
|
498
|
+
* @returns {string | string[] | undefined} The header value.
|
499
|
+
*/
|
500
|
+
getHeader: (key: string) => string | string[] | undefined;
|
494
501
|
/**
|
495
502
|
* Sets a header for the response.
|
496
503
|
* @param {string} key - The header key.
|
@@ -946,12 +953,17 @@ declare abstract class ForklaunchExpressLikeApplication<SV extends AnySchemaVali
|
|
946
953
|
readonly internal: Server;
|
947
954
|
readonly postEnrichMiddleware: RouterHandler[];
|
948
955
|
readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>;
|
956
|
+
readonly appOptions?: {
|
957
|
+
cors?: CorsOptions;
|
958
|
+
} | undefined;
|
949
959
|
/**
|
950
960
|
* Creates an instance of the Application class.
|
951
961
|
*
|
952
962
|
* @param {SV} schemaValidator - The schema validator.
|
953
963
|
*/
|
954
|
-
constructor(schemaValidator: SV, internal: Server, postEnrichMiddleware: RouterHandler[], openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition
|
964
|
+
constructor(schemaValidator: SV, internal: Server, postEnrichMiddleware: RouterHandler[], openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>, appOptions?: {
|
965
|
+
cors?: CorsOptions;
|
966
|
+
} | undefined);
|
955
967
|
abstract listen(...args: unknown[]): void;
|
956
968
|
}
|
957
969
|
|
package/lib/src/http/index.js
CHANGED
@@ -75,12 +75,19 @@ module.exports = __toCommonJS(http_exports);
|
|
75
75
|
|
76
76
|
// src/http/middleware/request/cors.middleware.ts
|
77
77
|
var import_cors = __toESM(require("cors"));
|
78
|
-
function cors(
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
function cors(corsOptions) {
|
79
|
+
return (req, res, next) => {
|
80
|
+
if (req.method === "OPTIONS") {
|
81
|
+
res.cors = true;
|
82
|
+
}
|
83
|
+
if (!res.getHeader) {
|
84
|
+
res.getHeader = (key) => {
|
85
|
+
return res.getHeaders()[key];
|
86
|
+
};
|
87
|
+
}
|
88
|
+
(0, import_cors.default)(corsOptions)(req, res, next ?? (() => {
|
89
|
+
}));
|
90
|
+
};
|
84
91
|
}
|
85
92
|
|
86
93
|
// src/http/middleware/request/createContext.middleware.ts
|
@@ -288,13 +295,11 @@ async function parseRequestAuth(req, res, next) {
|
|
288
295
|
next?.();
|
289
296
|
}
|
290
297
|
|
291
|
-
// src/
|
292
|
-
|
293
|
-
const value = process.env[name];
|
294
|
-
return value;
|
295
|
-
}
|
298
|
+
// src/http/middleware/request/enrichDetails.middleware.ts
|
299
|
+
var import_common4 = require("@forklaunch/common");
|
296
300
|
|
297
301
|
// src/http/telemetry/openTelemetryCollector.ts
|
302
|
+
var import_common3 = require("@forklaunch/common");
|
298
303
|
var import_opentelemetry_instrumentation_hyper_express = require("@forklaunch/opentelemetry-instrumentation-hyper-express");
|
299
304
|
var import_api3 = require("@opentelemetry/api");
|
300
305
|
var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
|
@@ -488,24 +493,24 @@ var OpenTelemetryCollector = class {
|
|
488
493
|
return this.metrics[metricId];
|
489
494
|
}
|
490
495
|
};
|
491
|
-
import_dotenv.default.config({ path: getEnvVar("ENV_FILE_PATH") });
|
496
|
+
import_dotenv.default.config({ path: (0, import_common3.getEnvVar)("ENV_FILE_PATH") });
|
492
497
|
new import_sdk_node.NodeSDK({
|
493
498
|
resource: (0, import_resources.resourceFromAttributes)({
|
494
|
-
[import_semantic_conventions2.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME")
|
499
|
+
[import_semantic_conventions2.ATTR_SERVICE_NAME]: (0, import_common3.getEnvVar)("OTEL_SERVICE_NAME")
|
495
500
|
}),
|
496
501
|
traceExporter: new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
497
|
-
url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
|
502
|
+
url: `${(0, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
|
498
503
|
}),
|
499
504
|
metricReader: new import_sdk_metrics.PeriodicExportingMetricReader({
|
500
505
|
exporter: new import_exporter_metrics_otlp_http.OTLPMetricExporter({
|
501
|
-
url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
|
506
|
+
url: `${(0, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
|
502
507
|
}),
|
503
508
|
exportIntervalMillis: 5e3
|
504
509
|
}),
|
505
510
|
logRecordProcessors: [
|
506
511
|
new import_sdk_logs.BatchLogRecordProcessor(
|
507
512
|
new import_exporter_logs_otlp_http.OTLPLogExporter({
|
508
|
-
url: `${getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
|
513
|
+
url: `${(0, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
|
509
514
|
})
|
510
515
|
)
|
511
516
|
],
|
@@ -514,7 +519,7 @@ new import_sdk_node.NodeSDK({
|
|
514
519
|
applyCustomAttributesOnSpan: (span, request) => {
|
515
520
|
span.setAttribute(
|
516
521
|
"service.name",
|
517
|
-
getEnvVar("OTEL_SERVICE_NAME") ?? "unknown"
|
522
|
+
(0, import_common3.getEnvVar)("OTEL_SERVICE_NAME") ?? "unknown"
|
518
523
|
);
|
519
524
|
if (isForklaunchRequest(request)) {
|
520
525
|
span.setAttribute("api.name", request.contractDetails?.name);
|
@@ -525,10 +530,10 @@ new import_sdk_node.NodeSDK({
|
|
525
530
|
new import_opentelemetry_instrumentation_hyper_express.HyperExpressInstrumentation()
|
526
531
|
]
|
527
532
|
}).start();
|
528
|
-
var httpRequestsTotalCounter = import_api3.metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
|
533
|
+
var httpRequestsTotalCounter = import_api3.metrics.getMeter((0, import_common3.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
|
529
534
|
description: "Number of HTTP requests"
|
530
535
|
});
|
531
|
-
var httpServerDurationHistogram = import_api3.metrics.getMeter(getEnvVar("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
|
536
|
+
var httpServerDurationHistogram = import_api3.metrics.getMeter((0, import_common3.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
|
532
537
|
description: "Duration of HTTP server requests",
|
533
538
|
unit: "s"
|
534
539
|
});
|
@@ -547,7 +552,7 @@ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, op
|
|
547
552
|
const [seconds, nanoseconds] = process.hrtime(startTime);
|
548
553
|
const durationMs = seconds + nanoseconds / 1e9;
|
549
554
|
httpServerDurationHistogram.record(durationMs, {
|
550
|
-
[import_semantic_conventions.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME") || "unknown",
|
555
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: (0, import_common4.getEnvVar)("OTEL_SERVICE_NAME") || "unknown",
|
551
556
|
[ATTR_API_NAME]: req.contractDetails?.name || "unknown",
|
552
557
|
[import_semantic_conventions.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
553
558
|
[import_semantic_conventions.ATTR_HTTP_ROUTE]: req.originalPath || "unknown",
|
@@ -1365,7 +1370,7 @@ var ForklaunchExpressLikeApplication = class extends ForklaunchExpressLikeRouter
|
|
1365
1370
|
*
|
1366
1371
|
* @param {SV} schemaValidator - The schema validator.
|
1367
1372
|
*/
|
1368
|
-
constructor(schemaValidator, internal, postEnrichMiddleware, openTelemetryCollector) {
|
1373
|
+
constructor(schemaValidator, internal, postEnrichMiddleware, openTelemetryCollector, appOptions) {
|
1369
1374
|
super(
|
1370
1375
|
"/",
|
1371
1376
|
schemaValidator,
|
@@ -1377,8 +1382,26 @@ var ForklaunchExpressLikeApplication = class extends ForklaunchExpressLikeRouter
|
|
1377
1382
|
this.internal = internal;
|
1378
1383
|
this.postEnrichMiddleware = postEnrichMiddleware;
|
1379
1384
|
this.openTelemetryCollector = openTelemetryCollector;
|
1385
|
+
this.appOptions = appOptions;
|
1386
|
+
process.on("uncaughtException", (err) => {
|
1387
|
+
this.openTelemetryCollector.log("error", "Uncaught exception", { err });
|
1388
|
+
process.exit(1);
|
1389
|
+
});
|
1390
|
+
process.on("unhandledRejection", (reason) => {
|
1391
|
+
this.openTelemetryCollector.log("error", "Unhandled rejection", {
|
1392
|
+
reason
|
1393
|
+
});
|
1394
|
+
process.exit(1);
|
1395
|
+
});
|
1396
|
+
process.on("exit", () => {
|
1397
|
+
this.openTelemetryCollector.log("info", "Shutting down application");
|
1398
|
+
});
|
1399
|
+
process.on("SIGINT", () => {
|
1400
|
+
this.openTelemetryCollector.log("info", "Shutting down application");
|
1401
|
+
process.exit(0);
|
1402
|
+
});
|
1380
1403
|
this.internal.use(createContext(this.schemaValidator));
|
1381
|
-
this.internal.use(cors);
|
1404
|
+
this.internal.use(cors(this.appOptions?.cors ?? {}));
|
1382
1405
|
}
|
1383
1406
|
};
|
1384
1407
|
|
@@ -2504,23 +2527,18 @@ ${parseErrors.join("\n\n")}`
|
|
2504
2527
|
}
|
2505
2528
|
|
2506
2529
|
// src/http/middleware/response/enrichExpressLikeSend.middleware.ts
|
2507
|
-
var
|
2530
|
+
var import_common6 = require("@forklaunch/common");
|
2508
2531
|
var import_stream = require("stream");
|
2509
2532
|
|
2510
2533
|
// src/http/telemetry/recordMetric.ts
|
2534
|
+
var import_common5 = require("@forklaunch/common");
|
2511
2535
|
var import_semantic_conventions3 = require("@opentelemetry/semantic-conventions");
|
2512
|
-
|
2513
|
-
// src/services/configInjector.ts
|
2514
|
-
var import_common3 = require("@forklaunch/common");
|
2515
|
-
var import_validator3 = require("@forklaunch/validator");
|
2516
|
-
|
2517
|
-
// src/http/telemetry/recordMetric.ts
|
2518
2536
|
function recordMetric(req, res) {
|
2519
2537
|
if (res.metricRecorded) {
|
2520
2538
|
return;
|
2521
2539
|
}
|
2522
2540
|
httpRequestsTotalCounter.add(1, {
|
2523
|
-
[import_semantic_conventions3.ATTR_SERVICE_NAME]: getEnvVar("OTEL_SERVICE_NAME"),
|
2541
|
+
[import_semantic_conventions3.ATTR_SERVICE_NAME]: (0, import_common5.getEnvVar)("OTEL_SERVICE_NAME"),
|
2524
2542
|
[ATTR_API_NAME]: req.contractDetails?.name,
|
2525
2543
|
[ATTR_CORRELATION_ID]: req.context.correlationId,
|
2526
2544
|
[import_semantic_conventions3.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
@@ -2558,8 +2576,8 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2558
2576
|
`attachment; filename="${data.name}"`
|
2559
2577
|
);
|
2560
2578
|
}
|
2561
|
-
if ((0,
|
2562
|
-
import_stream.Readable.from((0,
|
2579
|
+
if ((0, import_common6.isNodeJsWriteableStream)(res)) {
|
2580
|
+
import_stream.Readable.from((0, import_common6.readableStreamToAsyncIterable)(data.stream())).pipe(
|
2563
2581
|
res
|
2564
2582
|
);
|
2565
2583
|
} else {
|
@@ -2568,7 +2586,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2568
2586
|
originalSend.call(instance, "Not a NodeJS WritableStream");
|
2569
2587
|
errorSent = true;
|
2570
2588
|
}
|
2571
|
-
} else if ((0,
|
2589
|
+
} else if ((0, import_common6.isAsyncGenerator)(data)) {
|
2572
2590
|
let firstPass = true;
|
2573
2591
|
const transformer = new import_stream.Transform({
|
2574
2592
|
objectMode: true,
|
@@ -2596,7 +2614,7 @@ ${res.locals.errorMessage}`;
|
|
2596
2614
|
if (!errorSent) {
|
2597
2615
|
let data2 = "";
|
2598
2616
|
for (const [key, value] of Object.entries(chunk)) {
|
2599
|
-
data2 += `${key}: ${typeof value === "string" ? value : (0,
|
2617
|
+
data2 += `${key}: ${typeof value === "string" ? value : (0, import_common6.safeStringify)(value)}
|
2600
2618
|
`;
|
2601
2619
|
}
|
2602
2620
|
data2 += "\n";
|
@@ -2604,7 +2622,7 @@ ${res.locals.errorMessage}`;
|
|
2604
2622
|
}
|
2605
2623
|
}
|
2606
2624
|
});
|
2607
|
-
if ((0,
|
2625
|
+
if ((0, import_common6.isNodeJsWriteableStream)(res)) {
|
2608
2626
|
import_stream.Readable.from(data).pipe(transformer).pipe(res);
|
2609
2627
|
} else {
|
2610
2628
|
res.type("text/plain");
|
@@ -2615,7 +2633,7 @@ ${res.locals.errorMessage}`;
|
|
2615
2633
|
} else {
|
2616
2634
|
const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;
|
2617
2635
|
res.bodyData = data;
|
2618
|
-
if ((0,
|
2636
|
+
if ((0, import_common6.isRecord)(data)) {
|
2619
2637
|
switch (parserType) {
|
2620
2638
|
case "json":
|
2621
2639
|
res.bodyData = "json" in data ? data.json : data;
|
@@ -2636,7 +2654,7 @@ ${res.locals.errorMessage}`;
|
|
2636
2654
|
res.bodyData = data;
|
2637
2655
|
break;
|
2638
2656
|
default:
|
2639
|
-
(0,
|
2657
|
+
(0, import_common6.isNever)(parserType);
|
2640
2658
|
res.bodyData = data;
|
2641
2659
|
break;
|
2642
2660
|
}
|