@conduitplatform/module-tools 0.17.0-alpha.7 → 0.17.0-alpha.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/README.mdx +13 -0
- package/dist/index.cjs +678 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +185 -4
- package/dist/index.d.ts +185 -4
- package/dist/index.esm.js +639 -96
- package/dist/index.esm.js.map +1 -1
- package/package.json +9 -8
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AUTHENTICATION_CONFIG_UPDATE_CHANNEL: () => AUTHENTICATION_CONFIG_UPDATE_CHANNEL,
|
|
34
|
+
AccessTokenVerifier: () => AccessTokenVerifier,
|
|
33
35
|
ConduitActiveSchema: () => ConduitActiveSchema,
|
|
34
36
|
ConduitBoolean: () => ConduitBoolean,
|
|
35
37
|
ConduitDate: () => ConduitDate,
|
|
@@ -40,6 +42,7 @@ __export(index_exports, {
|
|
|
40
42
|
ConduitServiceModule: () => ConduitServiceModule,
|
|
41
43
|
ConduitString: () => ConduitString,
|
|
42
44
|
ConfigController: () => ConfigController,
|
|
45
|
+
DEFAULT_LEEWAY_SECONDS: () => DEFAULT_LEEWAY_SECONDS,
|
|
43
46
|
DEFAULT_STRIP_FIELDS: () => DEFAULT_STRIP_FIELDS,
|
|
44
47
|
GrpcServer: () => GrpcServer,
|
|
45
48
|
ManagedModule: () => ManagedModule,
|
|
@@ -52,20 +55,27 @@ __export(index_exports, {
|
|
|
52
55
|
convictConfigParser: () => convictConfigParser,
|
|
53
56
|
createParsedRouterRequest: () => createParsedRouterRequest,
|
|
54
57
|
createServer: () => createServer,
|
|
58
|
+
createUserHydrator: () => createUserHydrator,
|
|
55
59
|
exportModel: () => exportModel,
|
|
60
|
+
getAuthMiddlewareKind: () => getAuthMiddlewareKind,
|
|
61
|
+
hydrateContextUser: () => hydrateContextUser,
|
|
56
62
|
importModel: () => importModel,
|
|
57
63
|
initializeSdk: () => initializeSdk,
|
|
58
64
|
linearBackoffTimeout: () => linearBackoffTimeout,
|
|
59
65
|
linearBackoffTimeoutAsync: () => linearBackoffTimeoutAsync,
|
|
66
|
+
mapHydrationErrorCode: () => mapHydrationErrorCode,
|
|
60
67
|
merge: () => merge,
|
|
61
68
|
readConduitPeersManifest: () => readConduitPeersManifest,
|
|
62
69
|
reconcileStoredModuleConfig: () => reconcileStoredModuleConfig,
|
|
63
70
|
redactSensitiveConfig: () => redactSensitiveConfig,
|
|
64
71
|
restoreRedactedSecrets: () => restoreRedactedSecrets,
|
|
65
72
|
sanitizeDocumentsForExport: () => sanitizeDocumentsForExport,
|
|
73
|
+
selectVerificationKey: () => selectVerificationKey,
|
|
74
|
+
shouldHydrateUser: () => shouldHydrateUser,
|
|
66
75
|
stableConfigJson: () => stableConfigJson,
|
|
67
76
|
storedConfigsEquivalent: () => storedConfigsEquivalent,
|
|
68
77
|
stripInternalFields: () => stripInternalFields,
|
|
78
|
+
verifyAccessToken: () => verifyAccessToken,
|
|
69
79
|
wrapFunctionsAsync: () => wrapFunctionsAsync,
|
|
70
80
|
wrapGrpcFunctions: () => wrapGrpcFunctions,
|
|
71
81
|
wrapRouterGrpcFunction: () => wrapRouterGrpcFunction
|
|
@@ -461,8 +471,8 @@ var GrpcServer = class {
|
|
|
461
471
|
var import_path = __toESM(require("path"), 1);
|
|
462
472
|
var import_events = require("events");
|
|
463
473
|
var import_lodash_es2 = require("lodash-es");
|
|
464
|
-
var
|
|
465
|
-
var
|
|
474
|
+
var import_grpc_js6 = require("@grpc/grpc-js");
|
|
475
|
+
var import_grpc_sdk9 = require("@conduitplatform/grpc-sdk");
|
|
466
476
|
|
|
467
477
|
// src/routing/RouteBuilder.ts
|
|
468
478
|
var import_grpc_sdk5 = require("@conduitplatform/grpc-sdk");
|
|
@@ -540,6 +550,16 @@ var RouteBuilder = class {
|
|
|
540
550
|
this._options.captureRawHeaders = capture;
|
|
541
551
|
return this;
|
|
542
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Whether module-tools hydrates `context.user` from `context.userId` on routes with
|
|
555
|
+
* `authMiddleware` / `authMiddleware?` (default true).
|
|
556
|
+
* @deprecated The default flips to false in the next major; call
|
|
557
|
+
* `grpcSdk.authentication.getUser(userId)` explicitly instead.
|
|
558
|
+
*/
|
|
559
|
+
hydrateUser(hydrate) {
|
|
560
|
+
this._options.hydrateUser = hydrate;
|
|
561
|
+
return this;
|
|
562
|
+
}
|
|
543
563
|
return(name, fields) {
|
|
544
564
|
this._returns = new import_grpc_sdk5.ConduitRouteReturnDefinition(name, fields);
|
|
545
565
|
return this;
|
|
@@ -572,44 +592,104 @@ var RouteBuilder = class {
|
|
|
572
592
|
};
|
|
573
593
|
|
|
574
594
|
// src/routing/wrapRouterFunctions.ts
|
|
595
|
+
var import_grpc_sdk7 = require("@conduitplatform/grpc-sdk");
|
|
596
|
+
var import_grpc_js4 = require("@grpc/grpc-js");
|
|
597
|
+
|
|
598
|
+
// src/routing/hydrateUser.ts
|
|
575
599
|
var import_grpc_sdk6 = require("@conduitplatform/grpc-sdk");
|
|
576
600
|
var import_grpc_js3 = require("@grpc/grpc-js");
|
|
601
|
+
function middlewareList(routeOptions) {
|
|
602
|
+
const m = routeOptions?.middlewares;
|
|
603
|
+
if (Array.isArray(m)) return m.filter((x) => typeof x === "string");
|
|
604
|
+
if (typeof m === "string") return [m];
|
|
605
|
+
return [];
|
|
606
|
+
}
|
|
607
|
+
function getAuthMiddlewareKind(routeOptions) {
|
|
608
|
+
const list = middlewareList(routeOptions);
|
|
609
|
+
if (list.includes("authMiddleware")) return "required";
|
|
610
|
+
if (list.includes("authMiddleware?")) return "optional";
|
|
611
|
+
return void 0;
|
|
612
|
+
}
|
|
613
|
+
function shouldHydrateUser(routeOptions, context) {
|
|
614
|
+
if (!routeOptions || !context) return false;
|
|
615
|
+
if (routeOptions.hydrateUser === false) return false;
|
|
616
|
+
if (!getAuthMiddlewareKind(routeOptions)) return false;
|
|
617
|
+
return typeof context.userId === "string" && !!context.userId && !context.user;
|
|
618
|
+
}
|
|
619
|
+
function createUserHydrator(routeOptions, resolve) {
|
|
620
|
+
if (!routeOptions) return void 0;
|
|
621
|
+
const kind = getAuthMiddlewareKind(routeOptions);
|
|
622
|
+
if (!kind || routeOptions.hydrateUser === false) return void 0;
|
|
623
|
+
return {
|
|
624
|
+
optional: kind === "optional",
|
|
625
|
+
getUser: async (userId) => {
|
|
626
|
+
const resolver = resolve();
|
|
627
|
+
if (!resolver) throw new import_grpc_sdk6.GrpcError(import_grpc_js3.status.UNAVAILABLE, "User lookup unavailable");
|
|
628
|
+
return resolver(userId);
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function mapHydrationErrorCode(error) {
|
|
633
|
+
const code = error?.code;
|
|
634
|
+
if (typeof code !== "number" || code === import_grpc_js3.status.OK) return import_grpc_js3.status.INTERNAL;
|
|
635
|
+
if (code === import_grpc_js3.status.NOT_FOUND) return import_grpc_js3.status.UNAUTHENTICATED;
|
|
636
|
+
return code;
|
|
637
|
+
}
|
|
638
|
+
async function hydrateContextUser(routeOptions, context, hydrator) {
|
|
639
|
+
if (!shouldHydrateUser(routeOptions, context)) return;
|
|
640
|
+
try {
|
|
641
|
+
context.user = await hydrator.getUser(context.userId);
|
|
642
|
+
} catch (e) {
|
|
643
|
+
import_grpc_sdk6.ConduitGrpcSdk.Logger.warn(
|
|
644
|
+
`User hydration failed: ${e?.message ?? String(e)}`
|
|
645
|
+
);
|
|
646
|
+
if (!hydrator.optional) {
|
|
647
|
+
const code = mapHydrationErrorCode(e);
|
|
648
|
+
throw new import_grpc_sdk6.GrpcError(
|
|
649
|
+
code,
|
|
650
|
+
code === import_grpc_js3.status.UNAUTHENTICATED ? "Unauthorized" : "User lookup failed"
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/routing/wrapRouterFunctions.ts
|
|
577
657
|
var mapGrpcStatusToHttp = (code) => {
|
|
578
658
|
if (!code) return "200 (OK)";
|
|
579
659
|
switch (code) {
|
|
580
|
-
case
|
|
660
|
+
case import_grpc_js4.status.OK:
|
|
581
661
|
return `200 (OK)`;
|
|
582
|
-
case
|
|
662
|
+
case import_grpc_js4.status.CANCELLED:
|
|
583
663
|
return `499 (Cancelled)`;
|
|
584
|
-
case
|
|
664
|
+
case import_grpc_js4.status.INVALID_ARGUMENT:
|
|
585
665
|
return `400 (Invalid Argument)`;
|
|
586
|
-
case
|
|
666
|
+
case import_grpc_js4.status.DEADLINE_EXCEEDED:
|
|
587
667
|
return `504 (Deadline Exceeded)`;
|
|
588
|
-
case
|
|
668
|
+
case import_grpc_js4.status.NOT_FOUND:
|
|
589
669
|
return `404 (Not Found)`;
|
|
590
|
-
case
|
|
670
|
+
case import_grpc_js4.status.ALREADY_EXISTS:
|
|
591
671
|
return `409 (Already Exists)`;
|
|
592
|
-
case
|
|
672
|
+
case import_grpc_js4.status.PERMISSION_DENIED:
|
|
593
673
|
return `403 (Permission Denied)`;
|
|
594
|
-
case
|
|
674
|
+
case import_grpc_js4.status.UNAUTHENTICATED:
|
|
595
675
|
return `401 (Unauthenticated)`;
|
|
596
|
-
case
|
|
676
|
+
case import_grpc_js4.status.OUT_OF_RANGE:
|
|
597
677
|
return `416 (Out of Range)`;
|
|
598
|
-
case
|
|
678
|
+
case import_grpc_js4.status.FAILED_PRECONDITION:
|
|
599
679
|
return `412 (Failed Precondition)`;
|
|
600
|
-
case
|
|
680
|
+
case import_grpc_js4.status.ABORTED:
|
|
601
681
|
return `409 (Aborted)`;
|
|
602
|
-
case
|
|
682
|
+
case import_grpc_js4.status.INTERNAL:
|
|
603
683
|
return `416 (Internal)`;
|
|
604
|
-
case
|
|
684
|
+
case import_grpc_js4.status.UNAVAILABLE:
|
|
605
685
|
return `503 (Service Unavailable)`;
|
|
606
|
-
case
|
|
686
|
+
case import_grpc_js4.status.DATA_LOSS:
|
|
607
687
|
return `500 (Data Loss)`;
|
|
608
688
|
default:
|
|
609
689
|
return `500 (Unknown)`;
|
|
610
690
|
}
|
|
611
691
|
};
|
|
612
|
-
function generateLog(routerType, routerRequest, requestReceive, call,
|
|
692
|
+
function generateLog(routerType, routerRequest, requestReceive, call, status10) {
|
|
613
693
|
let log = "";
|
|
614
694
|
const latency = Date.now() - requestReceive;
|
|
615
695
|
if (routerRequest) {
|
|
@@ -619,15 +699,15 @@ function generateLog(routerType, routerRequest, requestReceive, call, status6) {
|
|
|
619
699
|
const socketLabel = socketReq.socketId ?? socketReq.socket;
|
|
620
700
|
log += `(${routerType}) Socket: ${socketReq.event} socket: ${socketLabel}`;
|
|
621
701
|
}
|
|
622
|
-
log += ` ${mapGrpcStatusToHttp(
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
702
|
+
log += ` ${mapGrpcStatusToHttp(status10) ?? "200"} ${latency}ms`;
|
|
703
|
+
import_grpc_sdk7.ConduitGrpcSdk.Logger.log(log);
|
|
704
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.set("grpc_request_latency_seconds", latency / 1e3);
|
|
705
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.set(
|
|
626
706
|
`${routerType}_grpc_request_latency_seconds`,
|
|
627
707
|
latency / 1e3
|
|
628
708
|
);
|
|
629
|
-
const successStatus = !
|
|
630
|
-
|
|
709
|
+
const successStatus = !status10 || status10.toString().startsWith("2");
|
|
710
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.increment(`${routerType}_grpc_response_statuses_total`, 1, {
|
|
631
711
|
success: successStatus ? "true" : "false"
|
|
632
712
|
});
|
|
633
713
|
}
|
|
@@ -643,7 +723,7 @@ function parseResponseData(r, routerRequest, requestReceive, call, callback, res
|
|
|
643
723
|
responded.did = true;
|
|
644
724
|
if (!r) {
|
|
645
725
|
callback({
|
|
646
|
-
code:
|
|
726
|
+
code: import_grpc_js4.status.INTERNAL,
|
|
647
727
|
message: "Handler did not return a response"
|
|
648
728
|
});
|
|
649
729
|
}
|
|
@@ -674,11 +754,11 @@ function parseResponseData(r, routerRequest, requestReceive, call, callback, res
|
|
|
674
754
|
}
|
|
675
755
|
generateLog(routerType, routerRequest, requestReceive, call, void 0);
|
|
676
756
|
}
|
|
677
|
-
function wrapRouterGrpcFunction(fun, routerType) {
|
|
757
|
+
function wrapRouterGrpcFunction(fun, routerType, hydration) {
|
|
678
758
|
return (call, callback) => {
|
|
679
759
|
const requestReceive = Date.now();
|
|
680
760
|
let routerRequest = true;
|
|
681
|
-
|
|
761
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.increment(`${routerType}_grpc_requests_total`);
|
|
682
762
|
try {
|
|
683
763
|
call.request.context = parseRequestData(call.request.context);
|
|
684
764
|
call.request.params = parseRequestData(call.request.params);
|
|
@@ -697,16 +777,16 @@ function wrapRouterGrpcFunction(fun, routerType) {
|
|
|
697
777
|
}
|
|
698
778
|
}
|
|
699
779
|
} catch (e) {
|
|
700
|
-
|
|
701
|
-
generateLog(routerType, routerRequest, requestReceive, call,
|
|
702
|
-
|
|
780
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.increment(`${routerType}_grpc_errors_total`);
|
|
781
|
+
generateLog(routerType, routerRequest, requestReceive, call, import_grpc_js4.status.INTERNAL);
|
|
782
|
+
import_grpc_sdk7.ConduitGrpcSdk.Logger.error(e.message ?? "Something went wrong");
|
|
703
783
|
return callback({
|
|
704
|
-
code:
|
|
784
|
+
code: import_grpc_js4.status.INTERNAL,
|
|
705
785
|
message: e.message ?? "Something went wrong"
|
|
706
786
|
});
|
|
707
787
|
}
|
|
708
788
|
const responded = { did: false };
|
|
709
|
-
fun(call, (r) => {
|
|
789
|
+
const invoke = () => fun(call, (r) => {
|
|
710
790
|
parseResponseData(
|
|
711
791
|
r,
|
|
712
792
|
routerRequest,
|
|
@@ -716,7 +796,13 @@ function wrapRouterGrpcFunction(fun, routerType) {
|
|
|
716
796
|
responded,
|
|
717
797
|
routerType
|
|
718
798
|
);
|
|
719
|
-
})
|
|
799
|
+
});
|
|
800
|
+
const needsHydration = hydration && shouldHydrateUser(hydration.options, call.request.context);
|
|
801
|
+
(needsHydration ? hydrateContextUser(
|
|
802
|
+
hydration.options,
|
|
803
|
+
call.request.context,
|
|
804
|
+
hydration.hydrator
|
|
805
|
+
).then(invoke) : invoke()).then(
|
|
720
806
|
(r) => parseResponseData(
|
|
721
807
|
r,
|
|
722
808
|
routerRequest,
|
|
@@ -727,19 +813,19 @@ function wrapRouterGrpcFunction(fun, routerType) {
|
|
|
727
813
|
routerType
|
|
728
814
|
)
|
|
729
815
|
).catch((error) => {
|
|
730
|
-
|
|
816
|
+
import_grpc_sdk7.ConduitGrpcSdk.Metrics?.increment(`${routerType}_grpc_errors_total`);
|
|
731
817
|
generateLog(
|
|
732
818
|
routerType,
|
|
733
819
|
routerRequest,
|
|
734
820
|
requestReceive,
|
|
735
821
|
call,
|
|
736
|
-
error.code ??
|
|
822
|
+
error.code ?? import_grpc_js4.status.INTERNAL
|
|
737
823
|
);
|
|
738
|
-
|
|
824
|
+
import_grpc_sdk7.ConduitGrpcSdk.Logger.error(
|
|
739
825
|
error.debugLogInfo ?? error.message ?? "Something went wrong"
|
|
740
826
|
);
|
|
741
827
|
callback({
|
|
742
|
-
code: error.code ??
|
|
828
|
+
code: error.code ?? import_grpc_js4.status.INTERNAL,
|
|
743
829
|
message: error.details ?? error.message ?? "Something went wrong"
|
|
744
830
|
});
|
|
745
831
|
});
|
|
@@ -747,21 +833,26 @@ function wrapRouterGrpcFunction(fun, routerType) {
|
|
|
747
833
|
}
|
|
748
834
|
|
|
749
835
|
// src/routing/RoutingUtilities.ts
|
|
750
|
-
function wrapFunctionsAsync(functions, routerType) {
|
|
836
|
+
function wrapFunctionsAsync(functions, routerType, hydrations = {}) {
|
|
751
837
|
const modifiedFunctions = {};
|
|
752
838
|
Object.keys(functions).forEach((key) => {
|
|
753
|
-
modifiedFunctions[key] = wrapRouterGrpcFunction(
|
|
839
|
+
modifiedFunctions[key] = wrapRouterGrpcFunction(
|
|
840
|
+
functions[key],
|
|
841
|
+
routerType,
|
|
842
|
+
hydrations[key]
|
|
843
|
+
);
|
|
754
844
|
});
|
|
755
845
|
return modifiedFunctions;
|
|
756
846
|
}
|
|
757
847
|
|
|
758
848
|
// src/routing/RoutingManager.ts
|
|
759
|
-
var
|
|
849
|
+
var import_grpc_sdk8 = require("@conduitplatform/grpc-sdk");
|
|
850
|
+
var import_grpc_js5 = require("@grpc/grpc-js");
|
|
760
851
|
var RoutingManager = class _RoutingManager {
|
|
761
852
|
constructor(_router, _server) {
|
|
762
853
|
this._router = _router;
|
|
763
854
|
this._server = _server;
|
|
764
|
-
if (_router instanceof
|
|
855
|
+
if (_router instanceof import_grpc_sdk8.Admin) {
|
|
765
856
|
this.isAdmin = true;
|
|
766
857
|
}
|
|
767
858
|
}
|
|
@@ -770,22 +861,46 @@ var RoutingManager = class _RoutingManager {
|
|
|
770
861
|
_moduleRoutes = {};
|
|
771
862
|
static ClientController;
|
|
772
863
|
static AdminController;
|
|
864
|
+
/** Set by ManagedModule; used to hydrate context.user on client routes. */
|
|
865
|
+
static grpcSdk;
|
|
866
|
+
static userResolver;
|
|
867
|
+
static warnedNoResolver = false;
|
|
868
|
+
/**
|
|
869
|
+
* Overrides how users are fetched for hydration (default: grpcSdk.authentication.getUser).
|
|
870
|
+
* Intended for the module that owns the users: the authentication module has no gRPC
|
|
871
|
+
* client to itself and will register a local resolver here.
|
|
872
|
+
*/
|
|
873
|
+
static setUserResolver(resolver) {
|
|
874
|
+
_RoutingManager.userResolver = resolver;
|
|
875
|
+
}
|
|
876
|
+
static resolveUser() {
|
|
877
|
+
if (_RoutingManager.userResolver) return _RoutingManager.userResolver;
|
|
878
|
+
const sdk = _RoutingManager.grpcSdk;
|
|
879
|
+
if (!sdk) return void 0;
|
|
880
|
+
return async (userId) => {
|
|
881
|
+
const auth = sdk.authentication;
|
|
882
|
+
if (!auth) {
|
|
883
|
+
throw new import_grpc_sdk8.GrpcError(import_grpc_js5.status.UNAVAILABLE, "authentication module unavailable");
|
|
884
|
+
}
|
|
885
|
+
return auth.getUser(userId);
|
|
886
|
+
};
|
|
887
|
+
}
|
|
773
888
|
_routeHandlers = {};
|
|
774
889
|
isAdmin = false;
|
|
775
890
|
get(path4) {
|
|
776
|
-
return new RouteBuilder(this).method(
|
|
891
|
+
return new RouteBuilder(this).method(import_grpc_sdk8.ConduitRouteActions.GET).path(path4);
|
|
777
892
|
}
|
|
778
893
|
post(path4) {
|
|
779
|
-
return new RouteBuilder(this).method(
|
|
894
|
+
return new RouteBuilder(this).method(import_grpc_sdk8.ConduitRouteActions.POST).path(path4);
|
|
780
895
|
}
|
|
781
896
|
delete(path4) {
|
|
782
|
-
return new RouteBuilder(this).method(
|
|
897
|
+
return new RouteBuilder(this).method(import_grpc_sdk8.ConduitRouteActions.DELETE).path(path4);
|
|
783
898
|
}
|
|
784
899
|
update(path4) {
|
|
785
|
-
return new RouteBuilder(this).method(
|
|
900
|
+
return new RouteBuilder(this).method(import_grpc_sdk8.ConduitRouteActions.UPDATE).path(path4);
|
|
786
901
|
}
|
|
787
902
|
patch(path4) {
|
|
788
|
-
return new RouteBuilder(this).method(
|
|
903
|
+
return new RouteBuilder(this).method(import_grpc_sdk8.ConduitRouteActions.PATCH).path(path4);
|
|
789
904
|
}
|
|
790
905
|
clear() {
|
|
791
906
|
this._moduleRoutes = {};
|
|
@@ -836,7 +951,27 @@ var RoutingManager = class _RoutingManager {
|
|
|
836
951
|
}
|
|
837
952
|
async registerRoutes() {
|
|
838
953
|
if (Object.keys(this._routeHandlers).length === 0) return;
|
|
839
|
-
const
|
|
954
|
+
const hydrations = {};
|
|
955
|
+
if (!this.isAdmin) {
|
|
956
|
+
for (const [name, route] of Object.entries(this._moduleRoutes)) {
|
|
957
|
+
const options = route.options;
|
|
958
|
+
const hydrator = createUserHydrator(options, _RoutingManager.resolveUser);
|
|
959
|
+
if (!hydrator) continue;
|
|
960
|
+
const names = "events" in route ? Object.keys(JSON.parse(route.events || "{}")) : [name];
|
|
961
|
+
for (const n of names) hydrations[n] = { options, hydrator };
|
|
962
|
+
if (!_RoutingManager.grpcSdk && !_RoutingManager.userResolver && !_RoutingManager.warnedNoResolver) {
|
|
963
|
+
_RoutingManager.warnedNoResolver = true;
|
|
964
|
+
import_grpc_sdk8.ConduitGrpcSdk.Logger.warn(
|
|
965
|
+
"User hydration is needed but RoutingManager.grpcSdk is not set; hydration will fail"
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
const modifiedFunctions = wrapFunctionsAsync(
|
|
971
|
+
this._routeHandlers,
|
|
972
|
+
this.isAdmin ? "admin" : "client",
|
|
973
|
+
hydrations
|
|
974
|
+
);
|
|
840
975
|
if (this.isAdmin) {
|
|
841
976
|
_RoutingManager.AdminController.setRoutes(modifiedFunctions);
|
|
842
977
|
} else {
|
|
@@ -882,7 +1017,7 @@ var ConduitServiceModule = class {
|
|
|
882
1017
|
// external address:port of service (LoadBalancer)
|
|
883
1018
|
grpcServer;
|
|
884
1019
|
events = new import_events.EventEmitter();
|
|
885
|
-
_serviceHealthState =
|
|
1020
|
+
_serviceHealthState = import_grpc_sdk9.HealthCheckStatus.SERVING;
|
|
886
1021
|
// default for health-agnostic modules
|
|
887
1022
|
constructor(moduleName) {
|
|
888
1023
|
this._moduleName = (0, import_lodash_es2.camelCase)(moduleName);
|
|
@@ -909,15 +1044,15 @@ var ConduitServiceModule = class {
|
|
|
909
1044
|
return this._serviceHealthState;
|
|
910
1045
|
}
|
|
911
1046
|
updateHealth(state, init = false) {
|
|
912
|
-
if (state ===
|
|
1047
|
+
if (state === import_grpc_sdk9.HealthCheckStatus.UNKNOWN && !init || state === import_grpc_sdk9.HealthCheckStatus.SERVICE_UNKNOWN) {
|
|
913
1048
|
throw new Error(
|
|
914
|
-
`Cannot explicitly set gRPC health state to ${
|
|
1049
|
+
`Cannot explicitly set gRPC health state to ${import_grpc_sdk9.HealthCheckStatus[state]}`
|
|
915
1050
|
);
|
|
916
1051
|
}
|
|
917
1052
|
if (!init) {
|
|
918
|
-
|
|
1053
|
+
import_grpc_sdk9.ConduitGrpcSdk.Metrics?.set(
|
|
919
1054
|
"module_health_state",
|
|
920
|
-
state ===
|
|
1055
|
+
state === import_grpc_sdk9.HealthCheckStatus.SERVING ? 1 : 0
|
|
921
1056
|
);
|
|
922
1057
|
}
|
|
923
1058
|
if (init) {
|
|
@@ -936,12 +1071,12 @@ var ConduitServiceModule = class {
|
|
|
936
1071
|
const service = call.request.service.substring(call.request.service.indexOf(".") + 1);
|
|
937
1072
|
if (service && service !== this._serviceName) {
|
|
938
1073
|
callback(null, {
|
|
939
|
-
status:
|
|
1074
|
+
status: import_grpc_sdk9.HealthCheckStatus.SERVICE_UNKNOWN
|
|
940
1075
|
});
|
|
941
1076
|
} else {
|
|
942
1077
|
if (!this._registered) {
|
|
943
1078
|
return callback(null, {
|
|
944
|
-
status:
|
|
1079
|
+
status: import_grpc_sdk9.HealthCheckResponse_ServingStatus.UNKNOWN
|
|
945
1080
|
});
|
|
946
1081
|
}
|
|
947
1082
|
callback(null, {
|
|
@@ -953,14 +1088,14 @@ var ConduitServiceModule = class {
|
|
|
953
1088
|
const service = call.request.service.substring(call.request.service.indexOf(".") + 1);
|
|
954
1089
|
if (service && service !== this._serviceName) {
|
|
955
1090
|
call.write({
|
|
956
|
-
status:
|
|
1091
|
+
status: import_grpc_sdk9.HealthCheckStatus.SERVICE_UNKNOWN
|
|
957
1092
|
});
|
|
958
1093
|
} else {
|
|
959
1094
|
this.events.on(
|
|
960
1095
|
`grpc-health-change:${this._serviceName}`,
|
|
961
|
-
(
|
|
1096
|
+
(status10) => {
|
|
962
1097
|
call.write({
|
|
963
|
-
status:
|
|
1098
|
+
status: status10
|
|
964
1099
|
});
|
|
965
1100
|
}
|
|
966
1101
|
);
|
|
@@ -983,7 +1118,7 @@ var ConduitServiceModule = class {
|
|
|
983
1118
|
const resources = this.getExportableResources();
|
|
984
1119
|
callback(null, { resources: JSON.stringify(resources) });
|
|
985
1120
|
} catch (e) {
|
|
986
|
-
callback({ code:
|
|
1121
|
+
callback({ code: import_grpc_js6.status.INTERNAL, message: e.message });
|
|
987
1122
|
}
|
|
988
1123
|
}
|
|
989
1124
|
async exportResourcesHandler(call, callback) {
|
|
@@ -992,7 +1127,7 @@ var ConduitServiceModule = class {
|
|
|
992
1127
|
const data = await this.exportResources(resourceTypes);
|
|
993
1128
|
callback(null, { data: JSON.stringify(data) });
|
|
994
1129
|
} catch (e) {
|
|
995
|
-
callback({ code:
|
|
1130
|
+
callback({ code: import_grpc_js6.status.INTERNAL, message: e.message });
|
|
996
1131
|
}
|
|
997
1132
|
}
|
|
998
1133
|
async importResourcesHandler(call, callback) {
|
|
@@ -1004,11 +1139,11 @@ var ConduitServiceModule = class {
|
|
|
1004
1139
|
const err = e;
|
|
1005
1140
|
if (err instanceof SyntaxError) {
|
|
1006
1141
|
callback({
|
|
1007
|
-
code:
|
|
1142
|
+
code: import_grpc_js6.status.INVALID_ARGUMENT,
|
|
1008
1143
|
message: "Invalid JSON in import data"
|
|
1009
1144
|
});
|
|
1010
1145
|
} else {
|
|
1011
|
-
callback({ code:
|
|
1146
|
+
callback({ code: import_grpc_js6.status.INTERNAL, message: err.message });
|
|
1012
1147
|
}
|
|
1013
1148
|
}
|
|
1014
1149
|
}
|
|
@@ -1081,7 +1216,7 @@ var ConfigController = class _ConfigController {
|
|
|
1081
1216
|
|
|
1082
1217
|
// src/ManagedModule.ts
|
|
1083
1218
|
var import_lodash_es6 = require("lodash-es");
|
|
1084
|
-
var
|
|
1219
|
+
var import_grpc_js10 = require("@grpc/grpc-js");
|
|
1085
1220
|
var import_convict = __toESM(require("convict"), 1);
|
|
1086
1221
|
|
|
1087
1222
|
// src/interfaces/ModuleLifecycleStage.ts
|
|
@@ -1095,13 +1230,13 @@ var ModuleLifecycleStage = /* @__PURE__ */ ((ModuleLifecycleStage2) => {
|
|
|
1095
1230
|
})(ModuleLifecycleStage || {});
|
|
1096
1231
|
|
|
1097
1232
|
// src/ManagedModule.ts
|
|
1098
|
-
var
|
|
1233
|
+
var import_grpc_sdk17 = require("@conduitplatform/grpc-sdk");
|
|
1099
1234
|
|
|
1100
1235
|
// src/utilities/initializeSdk.ts
|
|
1101
|
-
var
|
|
1236
|
+
var import_grpc_sdk14 = require("@conduitplatform/grpc-sdk");
|
|
1102
1237
|
|
|
1103
1238
|
// src/logging/index.ts
|
|
1104
|
-
var
|
|
1239
|
+
var import_grpc_sdk10 = require("@conduitplatform/grpc-sdk");
|
|
1105
1240
|
var import_winston = __toESM(require("winston"), 1);
|
|
1106
1241
|
var import_lodash_es3 = require("lodash-es");
|
|
1107
1242
|
var import_http = require("http");
|
|
@@ -1258,7 +1393,7 @@ async function setupLoki(module2, instance) {
|
|
|
1258
1393
|
if (lokiUrl.endsWith("/")) lokiUrl = lokiUrl.slice(0, -1);
|
|
1259
1394
|
const onTry = async () => {
|
|
1260
1395
|
return await lokiReadyCheck(lokiUrl).then(() => {
|
|
1261
|
-
|
|
1396
|
+
import_grpc_sdk10.ConduitGrpcSdk.Logger.addTransport(
|
|
1262
1397
|
new import_winston_loki.default({
|
|
1263
1398
|
level: "debug",
|
|
1264
1399
|
host: lokiUrl,
|
|
@@ -1277,15 +1412,90 @@ async function setupLoki(module2, instance) {
|
|
|
1277
1412
|
}).catch(() => true);
|
|
1278
1413
|
};
|
|
1279
1414
|
const onFailure = () => {
|
|
1280
|
-
|
|
1415
|
+
import_grpc_sdk10.ConduitGrpcSdk.Logger.error(`Failed to connect to Loki on '${lokiUrl}'`);
|
|
1281
1416
|
};
|
|
1282
1417
|
await linearBackoffTimeoutAsync(onTry, 250, 15, onFailure, true);
|
|
1283
1418
|
}
|
|
1284
1419
|
}
|
|
1285
1420
|
|
|
1286
|
-
// src/
|
|
1287
|
-
var
|
|
1421
|
+
// src/logging/fileTransports.ts
|
|
1422
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
1423
|
+
var import_os = __toESM(require("os"), 1);
|
|
1288
1424
|
var import_path2 = __toESM(require("path"), 1);
|
|
1425
|
+
var import_winston2 = __toESM(require("winston"), 1);
|
|
1426
|
+
var import_winston_daily_rotate_file = __toESM(require("winston-daily-rotate-file"), 1);
|
|
1427
|
+
var DEFAULT_RETENTION_DAYS = 3;
|
|
1428
|
+
var DEFAULT_MAX_SIZE = "20m";
|
|
1429
|
+
var SIZE_STRING = /^(?:0\.)?\d+[kmg]$/i;
|
|
1430
|
+
function positiveIntFromEnv(raw, fallback) {
|
|
1431
|
+
if (raw === void 0) return fallback;
|
|
1432
|
+
const trimmed = raw.trim();
|
|
1433
|
+
if (!/^[0-9]+$/.test(trimmed)) return fallback;
|
|
1434
|
+
const value = Number(trimmed);
|
|
1435
|
+
if (!Number.isSafeInteger(value) || value <= 0) return fallback;
|
|
1436
|
+
return value;
|
|
1437
|
+
}
|
|
1438
|
+
function logFileMaxSize() {
|
|
1439
|
+
const raw = process.env.LOG_FILE_MAX_SIZE?.trim();
|
|
1440
|
+
if (!raw) return DEFAULT_MAX_SIZE;
|
|
1441
|
+
if (SIZE_STRING.test(raw)) return raw.toLowerCase();
|
|
1442
|
+
if (/^[0-9]+$/.test(raw)) {
|
|
1443
|
+
const bytes = Number(raw);
|
|
1444
|
+
if (Number.isSafeInteger(bytes) && bytes > 0) return bytes;
|
|
1445
|
+
}
|
|
1446
|
+
return DEFAULT_MAX_SIZE;
|
|
1447
|
+
}
|
|
1448
|
+
function formatMeta(meta) {
|
|
1449
|
+
if (Array.isArray(meta)) {
|
|
1450
|
+
if (meta.length === 0) return "";
|
|
1451
|
+
return meta.map((item) => JSON.stringify(item)).join(" ");
|
|
1452
|
+
}
|
|
1453
|
+
if (meta !== null && typeof meta === "object") {
|
|
1454
|
+
if (Object.keys(meta).length === 0) return "";
|
|
1455
|
+
return JSON.stringify(meta);
|
|
1456
|
+
}
|
|
1457
|
+
return "";
|
|
1458
|
+
}
|
|
1459
|
+
function createFileFormat() {
|
|
1460
|
+
return import_winston2.default.format.combine(
|
|
1461
|
+
import_winston2.default.format.errors({ stack: true }),
|
|
1462
|
+
import_winston2.default.format.timestamp({
|
|
1463
|
+
format: "YYYY-MM-DD HH:mm:ss"
|
|
1464
|
+
}),
|
|
1465
|
+
import_winston2.default.format.printf((info) => {
|
|
1466
|
+
const metaText = formatMeta(info.meta);
|
|
1467
|
+
const line = `[${info.timestamp}] [${info.level.toUpperCase()}]: ${info.message}`;
|
|
1468
|
+
if (info.stack) {
|
|
1469
|
+
return `${line} ${info.stack}`;
|
|
1470
|
+
}
|
|
1471
|
+
return metaText ? `${line} ${metaText}` : line;
|
|
1472
|
+
})
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
function rotateTransport(logDir, name, level) {
|
|
1476
|
+
return new import_winston_daily_rotate_file.default({
|
|
1477
|
+
dirname: logDir,
|
|
1478
|
+
filename: `${name}-%DATE%.log`,
|
|
1479
|
+
datePattern: "YYYY-MM-DD",
|
|
1480
|
+
level,
|
|
1481
|
+
maxFiles: `${positiveIntFromEnv(process.env.LOG_RETENTION_DAYS, DEFAULT_RETENTION_DAYS)}d`,
|
|
1482
|
+
maxSize: logFileMaxSize(),
|
|
1483
|
+
zippedArchive: false,
|
|
1484
|
+
auditFile: import_path2.default.join(logDir, `.${name}-audit.json`),
|
|
1485
|
+
format: createFileFormat()
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
function createFileLogTransports() {
|
|
1489
|
+
if (process.env.LOG_TO_FILE?.trim() === "false") {
|
|
1490
|
+
return [];
|
|
1491
|
+
}
|
|
1492
|
+
const logDir = process.env.LOG_FILE_DIR?.trim() || import_path2.default.join(import_os.default.tmpdir(), "conduit-logs");
|
|
1493
|
+
import_fs.default.mkdirSync(logDir, { recursive: true });
|
|
1494
|
+
return [
|
|
1495
|
+
rotateTransport(logDir, "combined", "info"),
|
|
1496
|
+
rotateTransport(logDir, "errors", "error")
|
|
1497
|
+
];
|
|
1498
|
+
}
|
|
1289
1499
|
|
|
1290
1500
|
// src/metrics/index.ts
|
|
1291
1501
|
var import_prom_client = require("prom-client");
|
|
@@ -1293,7 +1503,7 @@ var import_prom_client = require("prom-client");
|
|
|
1293
1503
|
// src/metrics/MetricsServer.ts
|
|
1294
1504
|
var import_http2 = require("http");
|
|
1295
1505
|
var import_lodash_es4 = require("lodash-es");
|
|
1296
|
-
var
|
|
1506
|
+
var import_grpc_sdk11 = require("@conduitplatform/grpc-sdk");
|
|
1297
1507
|
var MetricsServer = class {
|
|
1298
1508
|
moduleName;
|
|
1299
1509
|
instance;
|
|
@@ -1308,7 +1518,7 @@ var MetricsServer = class {
|
|
|
1308
1518
|
const url = "0.0.0.0:" + port.toString();
|
|
1309
1519
|
const server = (0, import_http2.createServer)(this.requestHandler.bind(this));
|
|
1310
1520
|
server.listen(port, () => {
|
|
1311
|
-
|
|
1521
|
+
import_grpc_sdk11.ConduitGrpcSdk.Logger.info(`Metrics server listening on: ${url}`);
|
|
1312
1522
|
});
|
|
1313
1523
|
return server;
|
|
1314
1524
|
}
|
|
@@ -1330,12 +1540,12 @@ var MetricsServer = class {
|
|
|
1330
1540
|
getHttpPort() {
|
|
1331
1541
|
const value = process.env["METRICS_PORT"];
|
|
1332
1542
|
if (!value) {
|
|
1333
|
-
|
|
1543
|
+
import_grpc_sdk11.ConduitGrpcSdk.Logger.error(`Metrics HTTP port not set`);
|
|
1334
1544
|
process.exit(-1);
|
|
1335
1545
|
}
|
|
1336
1546
|
const port = parseInt(value, 10);
|
|
1337
1547
|
if ((0, import_lodash_es4.isNaN)(port) || port < 1 || port > 65535) {
|
|
1338
|
-
|
|
1548
|
+
import_grpc_sdk11.ConduitGrpcSdk.Logger.error(`Invalid HTTP port value: ${port}`);
|
|
1339
1549
|
process.exit(-1);
|
|
1340
1550
|
}
|
|
1341
1551
|
return port;
|
|
@@ -1343,73 +1553,73 @@ var MetricsServer = class {
|
|
|
1343
1553
|
};
|
|
1344
1554
|
|
|
1345
1555
|
// src/metrics/config/defaults.ts
|
|
1346
|
-
var
|
|
1556
|
+
var import_grpc_sdk12 = require("@conduitplatform/grpc-sdk");
|
|
1347
1557
|
var defaults_default = {
|
|
1348
1558
|
internalGrpcRequests: {
|
|
1349
|
-
type:
|
|
1559
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1350
1560
|
config: {
|
|
1351
1561
|
name: "internal_grpc_requests_total",
|
|
1352
1562
|
help: "Tracks the total number of Conduit's internal gRPC requests"
|
|
1353
1563
|
}
|
|
1354
1564
|
},
|
|
1355
1565
|
clientGrpcRequests: {
|
|
1356
|
-
type:
|
|
1566
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1357
1567
|
config: {
|
|
1358
1568
|
name: "client_grpc_requests_total",
|
|
1359
1569
|
help: "Tracks the total number of the client gRPC requests"
|
|
1360
1570
|
}
|
|
1361
1571
|
},
|
|
1362
1572
|
adminGrpcRequests: {
|
|
1363
|
-
type:
|
|
1573
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1364
1574
|
config: {
|
|
1365
1575
|
name: "admin_grpc_requests_total",
|
|
1366
1576
|
help: "Tracks the total number of the admin gRPC requests"
|
|
1367
1577
|
}
|
|
1368
1578
|
},
|
|
1369
1579
|
clientGrpcErrors: {
|
|
1370
|
-
type:
|
|
1580
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1371
1581
|
config: {
|
|
1372
1582
|
name: "client_grpc_errors_total",
|
|
1373
1583
|
help: "Tracks the total number of client grpc errors"
|
|
1374
1584
|
}
|
|
1375
1585
|
},
|
|
1376
1586
|
adminGrpcErrors: {
|
|
1377
|
-
type:
|
|
1587
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1378
1588
|
config: {
|
|
1379
1589
|
name: "admin_grpc_errors_total",
|
|
1380
1590
|
help: "Tracks the total number of admin grpc errors"
|
|
1381
1591
|
}
|
|
1382
1592
|
},
|
|
1383
1593
|
moduleHealthState: {
|
|
1384
|
-
type:
|
|
1594
|
+
type: import_grpc_sdk12.MetricType.Gauge,
|
|
1385
1595
|
config: {
|
|
1386
1596
|
name: "module_health_state",
|
|
1387
1597
|
help: "Tracks the health state of the module"
|
|
1388
1598
|
}
|
|
1389
1599
|
},
|
|
1390
1600
|
grpcRequestLatency: {
|
|
1391
|
-
type:
|
|
1601
|
+
type: import_grpc_sdk12.MetricType.Gauge,
|
|
1392
1602
|
config: {
|
|
1393
1603
|
name: "grpc_request_latency_seconds",
|
|
1394
1604
|
help: "Tracks the latency of grpc requests in seconds"
|
|
1395
1605
|
}
|
|
1396
1606
|
},
|
|
1397
1607
|
adminGrpcRequestLatency: {
|
|
1398
|
-
type:
|
|
1608
|
+
type: import_grpc_sdk12.MetricType.Gauge,
|
|
1399
1609
|
config: {
|
|
1400
1610
|
name: "admin_grpc_request_latency_seconds",
|
|
1401
1611
|
help: "Tracks the latency of admin grpc requests in seconds"
|
|
1402
1612
|
}
|
|
1403
1613
|
},
|
|
1404
1614
|
clientGrpcRequestLatency: {
|
|
1405
|
-
type:
|
|
1615
|
+
type: import_grpc_sdk12.MetricType.Gauge,
|
|
1406
1616
|
config: {
|
|
1407
1617
|
name: "client_grpc_request_latency_seconds",
|
|
1408
1618
|
help: "Tracks the latency of client grpc requests in seconds"
|
|
1409
1619
|
}
|
|
1410
1620
|
},
|
|
1411
1621
|
grpcResponseStatuses: {
|
|
1412
|
-
type:
|
|
1622
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1413
1623
|
config: {
|
|
1414
1624
|
name: "grpc_response_statuses_total",
|
|
1415
1625
|
help: "Tracks the total number of grpc response codes",
|
|
@@ -1417,7 +1627,7 @@ var defaults_default = {
|
|
|
1417
1627
|
}
|
|
1418
1628
|
},
|
|
1419
1629
|
adminGrpcResponseStatuses: {
|
|
1420
|
-
type:
|
|
1630
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1421
1631
|
config: {
|
|
1422
1632
|
name: "admin_grpc_response_statuses_total",
|
|
1423
1633
|
help: "Tracks the total number of admin grpc response codes",
|
|
@@ -1425,7 +1635,7 @@ var defaults_default = {
|
|
|
1425
1635
|
}
|
|
1426
1636
|
},
|
|
1427
1637
|
clientGrpcResponseStatuses: {
|
|
1428
|
-
type:
|
|
1638
|
+
type: import_grpc_sdk12.MetricType.Counter,
|
|
1429
1639
|
config: {
|
|
1430
1640
|
name: "client_grpc_response_statuses_total",
|
|
1431
1641
|
help: "Tracks the total number of client grpc response codes",
|
|
@@ -1435,7 +1645,7 @@ var defaults_default = {
|
|
|
1435
1645
|
};
|
|
1436
1646
|
|
|
1437
1647
|
// src/metrics/index.ts
|
|
1438
|
-
var
|
|
1648
|
+
var import_grpc_sdk13 = require("@conduitplatform/grpc-sdk");
|
|
1439
1649
|
var METRICS_PREFIX = "cnd_";
|
|
1440
1650
|
var ConduitMetrics = class {
|
|
1441
1651
|
moduleName;
|
|
@@ -1467,16 +1677,16 @@ var ConduitMetrics = class {
|
|
|
1467
1677
|
const metricConfig = JSON.parse(JSON.stringify(config));
|
|
1468
1678
|
metricConfig.name = this.addPrefix(config.name);
|
|
1469
1679
|
switch (type) {
|
|
1470
|
-
case
|
|
1680
|
+
case import_grpc_sdk13.MetricType.Counter:
|
|
1471
1681
|
this.createCounter(metricConfig);
|
|
1472
1682
|
break;
|
|
1473
|
-
case
|
|
1683
|
+
case import_grpc_sdk13.MetricType.Gauge:
|
|
1474
1684
|
this.createGauge(metricConfig);
|
|
1475
1685
|
break;
|
|
1476
|
-
case
|
|
1686
|
+
case import_grpc_sdk13.MetricType.Histogram:
|
|
1477
1687
|
this.createHistogram(metricConfig);
|
|
1478
1688
|
break;
|
|
1479
|
-
case
|
|
1689
|
+
case import_grpc_sdk13.MetricType.Summary:
|
|
1480
1690
|
this.createSummary(metricConfig);
|
|
1481
1691
|
break;
|
|
1482
1692
|
}
|
|
@@ -1624,7 +1834,7 @@ function clientMiddleware() {
|
|
|
1624
1834
|
clientStartedMetric.inc(labels);
|
|
1625
1835
|
const stopTimer = clientHandlingSecondsMetric.startTimer(labels);
|
|
1626
1836
|
let settled = false;
|
|
1627
|
-
let
|
|
1837
|
+
let status10 = import_nice_grpc_common.Status.OK;
|
|
1628
1838
|
try {
|
|
1629
1839
|
let request;
|
|
1630
1840
|
if (!call.requestStream) {
|
|
@@ -1650,44 +1860,36 @@ function clientMiddleware() {
|
|
|
1650
1860
|
} catch (err) {
|
|
1651
1861
|
settled = true;
|
|
1652
1862
|
if (err instanceof import_nice_grpc_common.ClientError) {
|
|
1653
|
-
|
|
1863
|
+
status10 = err.code;
|
|
1654
1864
|
} else if ((0, import_abort_controller_x.isAbortError)(err)) {
|
|
1655
|
-
|
|
1865
|
+
status10 = import_nice_grpc_common.Status.ABORTED;
|
|
1656
1866
|
} else {
|
|
1657
|
-
|
|
1867
|
+
status10 = import_nice_grpc_common.Status.UNKNOWN;
|
|
1658
1868
|
}
|
|
1659
1869
|
throw err;
|
|
1660
1870
|
} finally {
|
|
1661
1871
|
if (!settled) {
|
|
1662
|
-
|
|
1872
|
+
status10 = import_nice_grpc_common.Status.CANCELLED;
|
|
1663
1873
|
}
|
|
1664
|
-
stopTimer({ [codeLabel]: import_nice_grpc_common.Status[
|
|
1874
|
+
stopTimer({ [codeLabel]: import_nice_grpc_common.Status[status10] });
|
|
1665
1875
|
clientHandledMetric.inc({
|
|
1666
1876
|
...labels,
|
|
1667
|
-
[codeLabel]: import_nice_grpc_common.Status[
|
|
1877
|
+
[codeLabel]: import_nice_grpc_common.Status[status10]
|
|
1668
1878
|
});
|
|
1669
1879
|
}
|
|
1670
1880
|
};
|
|
1671
1881
|
}
|
|
1672
1882
|
|
|
1673
1883
|
// src/utilities/initializeSdk.ts
|
|
1674
|
-
var initializeSdk = (coreUrl, moduleName, watchModules = true, serviceHealthStatusGetter = () =>
|
|
1884
|
+
var initializeSdk = (coreUrl, moduleName, watchModules = true, serviceHealthStatusGetter = () => import_grpc_sdk14.HealthCheckStatus.SERVING) => {
|
|
1675
1885
|
let logger;
|
|
1676
1886
|
try {
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
level: "info"
|
|
1681
|
-
}),
|
|
1682
|
-
new import_winston2.default.transports.File({
|
|
1683
|
-
filename: import_path2.default.join(__dirname, ".logs/errors.log"),
|
|
1684
|
-
level: "error"
|
|
1685
|
-
})
|
|
1686
|
-
]);
|
|
1687
|
-
} catch (e) {
|
|
1887
|
+
const fileTransports = createFileLogTransports();
|
|
1888
|
+
logger = fileTransports.length > 0 ? new ConduitLogger(fileTransports) : new ConduitLogger();
|
|
1889
|
+
} catch {
|
|
1688
1890
|
logger = new ConduitLogger();
|
|
1689
1891
|
}
|
|
1690
|
-
const grpcSdk = new
|
|
1892
|
+
const grpcSdk = new import_grpc_sdk14.ConduitGrpcSdk(
|
|
1691
1893
|
coreUrl,
|
|
1692
1894
|
moduleName,
|
|
1693
1895
|
watchModules,
|
|
@@ -1696,7 +1898,7 @@ var initializeSdk = (coreUrl, moduleName, watchModules = true, serviceHealthStat
|
|
|
1696
1898
|
);
|
|
1697
1899
|
setupLoki(grpcSdk.name, grpcSdk.instance).then();
|
|
1698
1900
|
if (process.env.METRICS_PORT) {
|
|
1699
|
-
|
|
1901
|
+
import_grpc_sdk14.ConduitGrpcSdk.Metrics = new ConduitMetrics(grpcSdk.name, grpcSdk.instance);
|
|
1700
1902
|
grpcSdk.addMiddleware(clientMiddleware());
|
|
1701
1903
|
}
|
|
1702
1904
|
return grpcSdk;
|
|
@@ -1894,8 +2096,346 @@ async function reconcileStoredModuleConfig(args) {
|
|
|
1894
2096
|
return { config: persisted, persisted: true };
|
|
1895
2097
|
}
|
|
1896
2098
|
|
|
2099
|
+
// src/utilities/accessTokenVerifier.ts
|
|
2100
|
+
var import_grpc_sdk16 = require("@conduitplatform/grpc-sdk");
|
|
2101
|
+
var import_grpc_js8 = require("@grpc/grpc-js");
|
|
2102
|
+
var import_node_crypto = require("crypto");
|
|
2103
|
+
|
|
2104
|
+
// src/utilities/accessTokenVerifier.logic.ts
|
|
2105
|
+
var import_fast_jwt2 = require("fast-jwt");
|
|
2106
|
+
var import_grpc_js7 = require("@grpc/grpc-js");
|
|
2107
|
+
var import_grpc_sdk15 = require("@conduitplatform/grpc-sdk");
|
|
2108
|
+
var DEFAULT_LEEWAY_SECONDS = 5;
|
|
2109
|
+
var verifiers = /* @__PURE__ */ new Map();
|
|
2110
|
+
var decode = (0, import_fast_jwt2.createDecoder)({ complete: true });
|
|
2111
|
+
function fail(reason) {
|
|
2112
|
+
throw new import_grpc_sdk15.GrpcError(import_grpc_js7.status.UNAUTHENTICATED, reason);
|
|
2113
|
+
}
|
|
2114
|
+
function getVerifier(publicKey) {
|
|
2115
|
+
let verifier = verifiers.get(publicKey);
|
|
2116
|
+
if (!verifier) {
|
|
2117
|
+
verifier = (0, import_fast_jwt2.createVerifier)({
|
|
2118
|
+
key: publicKey,
|
|
2119
|
+
algorithms: ["EdDSA"],
|
|
2120
|
+
ignoreExpiration: true,
|
|
2121
|
+
ignoreNotBefore: true,
|
|
2122
|
+
cache: false
|
|
2123
|
+
});
|
|
2124
|
+
verifiers.set(publicKey, verifier);
|
|
2125
|
+
}
|
|
2126
|
+
return verifier;
|
|
2127
|
+
}
|
|
2128
|
+
function selectVerificationKey(kid, signing, now) {
|
|
2129
|
+
if (!kid) return void 0;
|
|
2130
|
+
if (signing.publicKey && kid === signing.kid) return signing.publicKey;
|
|
2131
|
+
if (signing.previousKid && signing.previousPublicKey && kid === signing.previousKid && (signing.previousRetiredAt ?? 0) > now) {
|
|
2132
|
+
return signing.previousPublicKey;
|
|
2133
|
+
}
|
|
2134
|
+
return void 0;
|
|
2135
|
+
}
|
|
2136
|
+
function verifyAccessToken(token, state, options = {}) {
|
|
2137
|
+
const now = options.now ?? Date.now();
|
|
2138
|
+
const leeway = options.leewaySeconds ?? DEFAULT_LEEWAY_SECONDS;
|
|
2139
|
+
if (typeof token !== "string" || token.length === 0) fail("malformed token");
|
|
2140
|
+
let kid;
|
|
2141
|
+
try {
|
|
2142
|
+
const decoded = decode(token);
|
|
2143
|
+
if (decoded.header.alg !== "EdDSA") fail("unsupported algorithm");
|
|
2144
|
+
kid = decoded.header.kid;
|
|
2145
|
+
} catch (e) {
|
|
2146
|
+
if (e instanceof import_grpc_sdk15.GrpcError) throw e;
|
|
2147
|
+
fail("malformed token");
|
|
2148
|
+
}
|
|
2149
|
+
const key = selectVerificationKey(kid, state.signing, now);
|
|
2150
|
+
if (!key) fail("unknown kid");
|
|
2151
|
+
let claims;
|
|
2152
|
+
try {
|
|
2153
|
+
claims = getVerifier(key)(token);
|
|
2154
|
+
} catch {
|
|
2155
|
+
fail("bad signature");
|
|
2156
|
+
}
|
|
2157
|
+
if (typeof claims.sub !== "string" || typeof claims.sid !== "string" || typeof claims.exp !== "number") {
|
|
2158
|
+
fail("malformed token");
|
|
2159
|
+
}
|
|
2160
|
+
if (now / 1e3 >= claims.exp + leeway) fail("expired");
|
|
2161
|
+
if (claims.tv !== state.tokenVersion) fail("version mismatch");
|
|
2162
|
+
if (options.clientId !== void 0 && claims.cid !== options.clientId) {
|
|
2163
|
+
fail("client mismatch");
|
|
2164
|
+
}
|
|
2165
|
+
return claims;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
// src/utilities/accessTokenVerifier.ts
|
|
2169
|
+
var AUTHENTICATION_CONFIG_UPDATE_CHANNEL = "authentication:config:update";
|
|
2170
|
+
var INITIAL_RETRY_MS = 1e3;
|
|
2171
|
+
var MAX_RETRY_MS = 3e4;
|
|
2172
|
+
var REFRESH_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2173
|
+
var UNKNOWN_KID_REFETCH_MIN_MS = 10 * 1e3;
|
|
2174
|
+
var SUBSCRIBER_ID = "access-token-verifier";
|
|
2175
|
+
function isConfigWithAccessTokens(config) {
|
|
2176
|
+
return typeof config === "object" && config !== null && typeof config.accessTokens === "object" && config.accessTokens !== null;
|
|
2177
|
+
}
|
|
2178
|
+
var AccessTokenVerifier = class _AccessTokenVerifier {
|
|
2179
|
+
constructor(grpcSdk) {
|
|
2180
|
+
this.grpcSdk = grpcSdk;
|
|
2181
|
+
}
|
|
2182
|
+
grpcSdk;
|
|
2183
|
+
static instance;
|
|
2184
|
+
_mode = "session";
|
|
2185
|
+
_strictRevocation = false;
|
|
2186
|
+
_tokenVersion = 0;
|
|
2187
|
+
_signing;
|
|
2188
|
+
_loaded = false;
|
|
2189
|
+
_subscribed = false;
|
|
2190
|
+
_generation = 0;
|
|
2191
|
+
_running = false;
|
|
2192
|
+
_retryTimer;
|
|
2193
|
+
_refreshTimer;
|
|
2194
|
+
_lastRefetch = 0;
|
|
2195
|
+
_refetching = false;
|
|
2196
|
+
_warned = /* @__PURE__ */ new Set();
|
|
2197
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
2198
|
+
static getInstance(grpcSdk) {
|
|
2199
|
+
if (!_AccessTokenVerifier.instance) {
|
|
2200
|
+
_AccessTokenVerifier.instance = new _AccessTokenVerifier(grpcSdk);
|
|
2201
|
+
}
|
|
2202
|
+
return _AccessTokenVerifier.instance;
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Internal, for tests only: stops the verifier, clears all state and drops the singleton.
|
|
2206
|
+
*/
|
|
2207
|
+
static resetForTests() {
|
|
2208
|
+
_AccessTokenVerifier.instance?.stop();
|
|
2209
|
+
_AccessTokenVerifier.instance?.resetState();
|
|
2210
|
+
_AccessTokenVerifier.instance = void 0;
|
|
2211
|
+
}
|
|
2212
|
+
resetState() {
|
|
2213
|
+
this._mode = "session";
|
|
2214
|
+
this._strictRevocation = false;
|
|
2215
|
+
this._tokenVersion = 0;
|
|
2216
|
+
this._signing = void 0;
|
|
2217
|
+
this._loaded = false;
|
|
2218
|
+
this._lastRefetch = 0;
|
|
2219
|
+
this._warned.clear();
|
|
2220
|
+
this._listeners.clear();
|
|
2221
|
+
}
|
|
2222
|
+
/** Snapshot of the verifier's observable state. */
|
|
2223
|
+
get state() {
|
|
2224
|
+
return {
|
|
2225
|
+
mode: this._mode,
|
|
2226
|
+
strictRevocation: this._strictRevocation,
|
|
2227
|
+
ready: this.ready,
|
|
2228
|
+
tokenVersion: this._tokenVersion,
|
|
2229
|
+
kid: this._signing?.kid
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Registers a listener fired synchronously at the end of every applyConfig that changed
|
|
2234
|
+
* anything (including the first successful load). Returns an unsubscribe function.
|
|
2235
|
+
*/
|
|
2236
|
+
onChange(listener) {
|
|
2237
|
+
this._listeners.add(listener);
|
|
2238
|
+
return () => {
|
|
2239
|
+
this._listeners.delete(listener);
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
fingerprint() {
|
|
2243
|
+
return JSON.stringify([this._loaded, this._signing, this.state]);
|
|
2244
|
+
}
|
|
2245
|
+
get mode() {
|
|
2246
|
+
return this._mode;
|
|
2247
|
+
}
|
|
2248
|
+
get strictRevocation() {
|
|
2249
|
+
return this._strictRevocation;
|
|
2250
|
+
}
|
|
2251
|
+
/** True once signing keys have been loaded. */
|
|
2252
|
+
get ready() {
|
|
2253
|
+
return !!this._signing?.publicKey;
|
|
2254
|
+
}
|
|
2255
|
+
get tokenVersion() {
|
|
2256
|
+
return this._tokenVersion;
|
|
2257
|
+
}
|
|
2258
|
+
/**
|
|
2259
|
+
* Loads the authentication config, subscribes to its updates and starts a slow periodic
|
|
2260
|
+
* refresh. The first attempt is awaited; if it fails, retries continue in the background
|
|
2261
|
+
* with capped backoff until the config is loaded and the subscription is acknowledged.
|
|
2262
|
+
* Idempotent while running; never throws.
|
|
2263
|
+
*/
|
|
2264
|
+
async start() {
|
|
2265
|
+
if (this._running) return;
|
|
2266
|
+
this._running = true;
|
|
2267
|
+
const generation = ++this._generation;
|
|
2268
|
+
await this.attempt(generation, INITIAL_RETRY_MS);
|
|
2269
|
+
if (generation !== this._generation) return;
|
|
2270
|
+
this._refreshTimer = setInterval(() => void this.refetch(true), REFRESH_INTERVAL_MS);
|
|
2271
|
+
this._refreshTimer.unref?.();
|
|
2272
|
+
}
|
|
2273
|
+
stop() {
|
|
2274
|
+
this._running = false;
|
|
2275
|
+
this._generation++;
|
|
2276
|
+
if (this._retryTimer) clearTimeout(this._retryTimer);
|
|
2277
|
+
if (this._refreshTimer) clearInterval(this._refreshTimer);
|
|
2278
|
+
this._retryTimer = void 0;
|
|
2279
|
+
this._refreshTimer = void 0;
|
|
2280
|
+
if (this._subscribed) {
|
|
2281
|
+
try {
|
|
2282
|
+
this.grpcSdk.bus?.unsubscribe(SUBSCRIBER_ID);
|
|
2283
|
+
} catch {
|
|
2284
|
+
}
|
|
2285
|
+
this._subscribed = false;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
async attempt(generation, delay) {
|
|
2289
|
+
if (generation !== this._generation) return;
|
|
2290
|
+
try {
|
|
2291
|
+
await this.subscribe(generation);
|
|
2292
|
+
if (!this._loaded) {
|
|
2293
|
+
this.applyConfig(await this.grpcSdk.config.get("authentication"));
|
|
2294
|
+
}
|
|
2295
|
+
} catch {
|
|
2296
|
+
}
|
|
2297
|
+
if (generation !== this._generation) return;
|
|
2298
|
+
if (this._subscribed && this._loaded) return;
|
|
2299
|
+
this._retryTimer = setTimeout(
|
|
2300
|
+
() => void this.attempt(generation, Math.min(delay * 2, MAX_RETRY_MS)),
|
|
2301
|
+
delay
|
|
2302
|
+
);
|
|
2303
|
+
this._retryTimer.unref?.();
|
|
2304
|
+
}
|
|
2305
|
+
async subscribe(generation) {
|
|
2306
|
+
if (this._subscribed) return;
|
|
2307
|
+
const bus = this.grpcSdk.bus;
|
|
2308
|
+
if (!bus) return;
|
|
2309
|
+
await bus.subscribeAck(
|
|
2310
|
+
AUTHENTICATION_CONFIG_UPDATE_CHANNEL,
|
|
2311
|
+
(message) => {
|
|
2312
|
+
try {
|
|
2313
|
+
this.applyConfig(JSON.parse(message));
|
|
2314
|
+
} catch {
|
|
2315
|
+
}
|
|
2316
|
+
},
|
|
2317
|
+
SUBSCRIBER_ID
|
|
2318
|
+
);
|
|
2319
|
+
if (generation !== this._generation) {
|
|
2320
|
+
bus.unsubscribe(SUBSCRIBER_ID);
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
this._subscribed = true;
|
|
2324
|
+
}
|
|
2325
|
+
/** Refetches the config from the authentication module; failures keep the previous state. */
|
|
2326
|
+
async refetch(force = false) {
|
|
2327
|
+
const now = Date.now();
|
|
2328
|
+
if (this._refetching) return;
|
|
2329
|
+
if (!force && now - this._lastRefetch < UNKNOWN_KID_REFETCH_MIN_MS) return;
|
|
2330
|
+
this._lastRefetch = now;
|
|
2331
|
+
this._refetching = true;
|
|
2332
|
+
try {
|
|
2333
|
+
this.applyConfig(await this.grpcSdk.config.get("authentication"));
|
|
2334
|
+
} catch {
|
|
2335
|
+
} finally {
|
|
2336
|
+
this._refetching = false;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
warnOnce(key, message) {
|
|
2340
|
+
if (this._warned.has(key)) return;
|
|
2341
|
+
this._warned.add(key);
|
|
2342
|
+
import_grpc_sdk16.ConduitGrpcSdk.Logger.warn(`AccessTokenVerifier: ${message}`);
|
|
2343
|
+
}
|
|
2344
|
+
static validPem(pem) {
|
|
2345
|
+
if (typeof pem !== "string" || !pem) return false;
|
|
2346
|
+
try {
|
|
2347
|
+
(0, import_node_crypto.createPublicKey)(pem);
|
|
2348
|
+
return true;
|
|
2349
|
+
} catch {
|
|
2350
|
+
return false;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
/**
|
|
2354
|
+
* Validates and normalizes the signing keys. Returns undefined when no signing block is
|
|
2355
|
+
* configured, null when the public key is invalid (the caller keeps the previous state).
|
|
2356
|
+
*/
|
|
2357
|
+
normalizeSigning(s) {
|
|
2358
|
+
if (!(s && typeof s.kid === "string" && s.kid && s.publicKey)) return void 0;
|
|
2359
|
+
if (!_AccessTokenVerifier.validPem(s.publicKey)) {
|
|
2360
|
+
this.warnOnce("publicKey", "invalid signing public key, keeping previous state");
|
|
2361
|
+
return null;
|
|
2362
|
+
}
|
|
2363
|
+
const previousPublicKey = this.validPreviousKey(s.previousPublicKey);
|
|
2364
|
+
return {
|
|
2365
|
+
kid: s.kid,
|
|
2366
|
+
publicKey: s.publicKey,
|
|
2367
|
+
previousKid: previousPublicKey ? s.previousKid || void 0 : void 0,
|
|
2368
|
+
previousPublicKey,
|
|
2369
|
+
previousRetiredAt: Number(s.previousRetiredAt ?? 0)
|
|
2370
|
+
};
|
|
2371
|
+
}
|
|
2372
|
+
validPreviousKey(pem) {
|
|
2373
|
+
if (!pem) return void 0;
|
|
2374
|
+
if (_AccessTokenVerifier.validPem(pem)) return pem;
|
|
2375
|
+
this.warnOnce("previousPublicKey", "invalid previous public key, ignoring it");
|
|
2376
|
+
return void 0;
|
|
2377
|
+
}
|
|
2378
|
+
parseTokenVersion(raw) {
|
|
2379
|
+
const version = Number(raw ?? 0);
|
|
2380
|
+
if (Number.isNaN(version)) {
|
|
2381
|
+
this.warnOnce("tokenVersion", "invalid tokenVersion, all tokens will be rejected");
|
|
2382
|
+
}
|
|
2383
|
+
return version;
|
|
2384
|
+
}
|
|
2385
|
+
notifyListeners() {
|
|
2386
|
+
const state = this.state;
|
|
2387
|
+
for (const listener of [...this._listeners]) {
|
|
2388
|
+
try {
|
|
2389
|
+
listener(state);
|
|
2390
|
+
} catch (e) {
|
|
2391
|
+
import_grpc_sdk16.ConduitGrpcSdk.Logger.warn(
|
|
2392
|
+
`AccessTokenVerifier: change listener failed: ${e?.message}`
|
|
2393
|
+
);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Applies an authentication module config object (full config). Invalid input is ignored
|
|
2399
|
+
* and the previous state is kept; invalid keys are logged once.
|
|
2400
|
+
*/
|
|
2401
|
+
applyConfig(config) {
|
|
2402
|
+
if (!isConfigWithAccessTokens(config)) return;
|
|
2403
|
+
const tokens = config.accessTokens;
|
|
2404
|
+
const before = this.fingerprint();
|
|
2405
|
+
const signing = this.normalizeSigning(tokens.signing);
|
|
2406
|
+
if (signing === null) return;
|
|
2407
|
+
const version = this.parseTokenVersion(tokens.tokenVersion);
|
|
2408
|
+
this._mode = tokens.mode === "jwt" ? "jwt" : "session";
|
|
2409
|
+
this._tokenVersion = version;
|
|
2410
|
+
this._strictRevocation = tokens.strictRevocation === true;
|
|
2411
|
+
this._signing = signing;
|
|
2412
|
+
this._loaded = true;
|
|
2413
|
+
if (this.fingerprint() !== before) this.notifyListeners();
|
|
2414
|
+
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Verifies an access token, throwing GrpcError(UNAUTHENTICATED) with a short reason on failure.
|
|
2417
|
+
* `options.now` is epoch milliseconds. An `unknown kid` triggers a throttled (at most once
|
|
2418
|
+
* per 10 s) background refetch of the config, to pick up a rotation sooner.
|
|
2419
|
+
*/
|
|
2420
|
+
verify(token, options) {
|
|
2421
|
+
if (!this._signing) {
|
|
2422
|
+
throw new import_grpc_sdk16.GrpcError(import_grpc_js8.status.UNAUTHENTICATED, "verifier not ready");
|
|
2423
|
+
}
|
|
2424
|
+
try {
|
|
2425
|
+
return verifyAccessToken(
|
|
2426
|
+
token,
|
|
2427
|
+
{ tokenVersion: this._tokenVersion, signing: this._signing },
|
|
2428
|
+
options
|
|
2429
|
+
);
|
|
2430
|
+
} catch (e) {
|
|
2431
|
+
if (e.message === "unknown kid") void this.refetch();
|
|
2432
|
+
throw e;
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
};
|
|
2436
|
+
|
|
1897
2437
|
// src/routing/RoutingController.ts
|
|
1898
|
-
var
|
|
2438
|
+
var import_grpc_js9 = require("@grpc/grpc-js");
|
|
1899
2439
|
var RoutingController = class {
|
|
1900
2440
|
_routeHandlers = {};
|
|
1901
2441
|
handleRequest(call, callback) {
|
|
@@ -1903,7 +2443,7 @@ var RoutingController = class {
|
|
|
1903
2443
|
this._routeHandlers[call.request.functionName](call, callback);
|
|
1904
2444
|
} else {
|
|
1905
2445
|
callback({
|
|
1906
|
-
code:
|
|
2446
|
+
code: import_grpc_js9.status.NOT_FOUND,
|
|
1907
2447
|
message: "Not found"
|
|
1908
2448
|
});
|
|
1909
2449
|
}
|
|
@@ -1962,13 +2502,13 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
1962
2502
|
await this.preRegisterLifecycle();
|
|
1963
2503
|
await this.grpcSdk.config.registerModule(this.name, this.address, this.healthState);
|
|
1964
2504
|
} catch (err) {
|
|
1965
|
-
|
|
1966
|
-
|
|
2505
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.error("Failed to initialize server");
|
|
2506
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.error(err);
|
|
1967
2507
|
process.exit(-1);
|
|
1968
2508
|
}
|
|
1969
2509
|
await this.postRegisterLifecycle().catch((err) => {
|
|
1970
|
-
|
|
1971
|
-
|
|
2510
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.error("Failed to activate module");
|
|
2511
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.error(err);
|
|
1972
2512
|
process.exit(-1);
|
|
1973
2513
|
});
|
|
1974
2514
|
}
|
|
@@ -2035,11 +2575,11 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2035
2575
|
* Registers common and module-specific metric types.
|
|
2036
2576
|
*/
|
|
2037
2577
|
async registerMetrics() {
|
|
2038
|
-
if (
|
|
2039
|
-
|
|
2578
|
+
if (import_grpc_sdk17.ConduitGrpcSdk.Metrics) {
|
|
2579
|
+
import_grpc_sdk17.ConduitGrpcSdk.Metrics.initializeDefaultMetrics();
|
|
2040
2580
|
if (this.metricsSchema) {
|
|
2041
2581
|
Object.values(this.metricsSchema).forEach((metric) => {
|
|
2042
|
-
|
|
2582
|
+
import_grpc_sdk17.ConduitGrpcSdk.Metrics.registerMetric(metric.type, metric.config);
|
|
2043
2583
|
});
|
|
2044
2584
|
}
|
|
2045
2585
|
}
|
|
@@ -2063,7 +2603,7 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2063
2603
|
const known = new Set(this.grpcSdk.getKnownModuleNames());
|
|
2064
2604
|
for (const n of names) {
|
|
2065
2605
|
if (!known.has(n)) {
|
|
2066
|
-
|
|
2606
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.warn(
|
|
2067
2607
|
`Declared Conduit peer "${n}" is not a known built-in module (see ConduitGrpcSdk.getKnownModuleNames).`
|
|
2068
2608
|
);
|
|
2069
2609
|
}
|
|
@@ -2124,18 +2664,19 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2124
2664
|
this.service.functions
|
|
2125
2665
|
);
|
|
2126
2666
|
}
|
|
2667
|
+
RoutingManager.grpcSdk = this.grpcSdk;
|
|
2127
2668
|
RoutingManager.ClientController = new RoutingController();
|
|
2128
2669
|
RoutingManager.AdminController = new RoutingController();
|
|
2129
2670
|
await this.addHealthCheckService();
|
|
2130
2671
|
await this.addModuleService();
|
|
2131
2672
|
await this.grpcServer.start();
|
|
2132
|
-
|
|
2673
|
+
import_grpc_sdk17.ConduitGrpcSdk.Logger.log("gRPC server listening on " + this._port);
|
|
2133
2674
|
}
|
|
2134
2675
|
async setConfig(call, callback) {
|
|
2135
2676
|
try {
|
|
2136
2677
|
if (!this.config) {
|
|
2137
2678
|
return callback({
|
|
2138
|
-
code:
|
|
2679
|
+
code: import_grpc_js10.status.INVALID_ARGUMENT,
|
|
2139
2680
|
message: "Module is not configurable"
|
|
2140
2681
|
});
|
|
2141
2682
|
}
|
|
@@ -2154,7 +2695,7 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2154
2695
|
this.config = (0, import_convict.default)(this.configSchema);
|
|
2155
2696
|
this.config.load(previousConfig);
|
|
2156
2697
|
return callback({
|
|
2157
|
-
code:
|
|
2698
|
+
code: import_grpc_js10.status.INVALID_ARGUMENT,
|
|
2158
2699
|
message: "Invalid configuration values: " + e.message
|
|
2159
2700
|
});
|
|
2160
2701
|
}
|
|
@@ -2163,7 +2704,7 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2163
2704
|
await this._drainConfigQueue();
|
|
2164
2705
|
this.grpcSdk.bus?.publish((0, import_lodash_es6.kebabCase)(this.name) + ":config:update", configJson);
|
|
2165
2706
|
} catch (e) {
|
|
2166
|
-
return callback({ code:
|
|
2707
|
+
return callback({ code: import_grpc_js10.status.INTERNAL, message: e.message });
|
|
2167
2708
|
}
|
|
2168
2709
|
}
|
|
2169
2710
|
/** Used to update the module's configuration on initial Redis/DB reconciliation. */
|
|
@@ -2243,8 +2784,8 @@ var ManagedModule = class extends ConduitServiceModule {
|
|
|
2243
2784
|
};
|
|
2244
2785
|
|
|
2245
2786
|
// src/classes/ModuleError.ts
|
|
2246
|
-
var
|
|
2247
|
-
var ModuleError = class extends
|
|
2787
|
+
var import_grpc_sdk18 = require("@conduitplatform/grpc-sdk");
|
|
2788
|
+
var ModuleError = class extends import_grpc_sdk18.GrpcError {
|
|
2248
2789
|
debugLogInfo;
|
|
2249
2790
|
constructor(errorDefinition, debugLogInfo) {
|
|
2250
2791
|
const { grpcCode, conduitCode, message } = errorDefinition;
|
|
@@ -2260,6 +2801,8 @@ var ModuleError = class extends import_grpc_sdk15.GrpcError {
|
|
|
2260
2801
|
};
|
|
2261
2802
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2262
2803
|
0 && (module.exports = {
|
|
2804
|
+
AUTHENTICATION_CONFIG_UPDATE_CHANNEL,
|
|
2805
|
+
AccessTokenVerifier,
|
|
2263
2806
|
ConduitActiveSchema,
|
|
2264
2807
|
ConduitBoolean,
|
|
2265
2808
|
ConduitDate,
|
|
@@ -2270,6 +2813,7 @@ var ModuleError = class extends import_grpc_sdk15.GrpcError {
|
|
|
2270
2813
|
ConduitServiceModule,
|
|
2271
2814
|
ConduitString,
|
|
2272
2815
|
ConfigController,
|
|
2816
|
+
DEFAULT_LEEWAY_SECONDS,
|
|
2273
2817
|
DEFAULT_STRIP_FIELDS,
|
|
2274
2818
|
GrpcServer,
|
|
2275
2819
|
ManagedModule,
|
|
@@ -2282,20 +2826,27 @@ var ModuleError = class extends import_grpc_sdk15.GrpcError {
|
|
|
2282
2826
|
convictConfigParser,
|
|
2283
2827
|
createParsedRouterRequest,
|
|
2284
2828
|
createServer,
|
|
2829
|
+
createUserHydrator,
|
|
2285
2830
|
exportModel,
|
|
2831
|
+
getAuthMiddlewareKind,
|
|
2832
|
+
hydrateContextUser,
|
|
2286
2833
|
importModel,
|
|
2287
2834
|
initializeSdk,
|
|
2288
2835
|
linearBackoffTimeout,
|
|
2289
2836
|
linearBackoffTimeoutAsync,
|
|
2837
|
+
mapHydrationErrorCode,
|
|
2290
2838
|
merge,
|
|
2291
2839
|
readConduitPeersManifest,
|
|
2292
2840
|
reconcileStoredModuleConfig,
|
|
2293
2841
|
redactSensitiveConfig,
|
|
2294
2842
|
restoreRedactedSecrets,
|
|
2295
2843
|
sanitizeDocumentsForExport,
|
|
2844
|
+
selectVerificationKey,
|
|
2845
|
+
shouldHydrateUser,
|
|
2296
2846
|
stableConfigJson,
|
|
2297
2847
|
storedConfigsEquivalent,
|
|
2298
2848
|
stripInternalFields,
|
|
2849
|
+
verifyAccessToken,
|
|
2299
2850
|
wrapFunctionsAsync,
|
|
2300
2851
|
wrapGrpcFunctions,
|
|
2301
2852
|
wrapRouterGrpcFunction
|