@terreno/api 0.11.4-beta.6 → 0.11.5
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/dist/expressServer.test.js +273 -0
- package/dist/notifiers/googleChatNotifier.d.ts +2 -2
- package/dist/notifiers/googleChatNotifier.js +34 -4
- package/dist/notifiers/zoomNotifier.d.ts +2 -2
- package/dist/notifiers/zoomNotifier.js +73 -75
- package/dist/openApiBuilder.d.ts +7 -7
- package/dist/openApiBuilder.js +4 -4
- package/package.json +2 -2
- package/src/expressServer.test.ts +188 -1
- package/src/notifiers/googleChatNotifier.ts +3 -3
- package/src/notifiers/zoomNotifier.ts +3 -6
- package/src/openApiBuilder.ts +9 -9
|
@@ -71,6 +71,17 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
71
71
|
}
|
|
72
72
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
73
|
};
|
|
74
|
+
var __values = (this && this.__values) || function(o) {
|
|
75
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
76
|
+
if (m) return m.call(o);
|
|
77
|
+
if (o && typeof o.length === "number") return {
|
|
78
|
+
next: function () {
|
|
79
|
+
if (o && i >= o.length) o = void 0;
|
|
80
|
+
return { value: o && o[i++], done: !o };
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
84
|
+
};
|
|
74
85
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
75
86
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
76
87
|
};
|
|
@@ -662,5 +673,267 @@ var tests_1 = require("./tests");
|
|
|
662
673
|
}
|
|
663
674
|
});
|
|
664
675
|
}); });
|
|
676
|
+
(0, bun_test_1.it)("re-throws when addRoutes throws during route initialization", function () {
|
|
677
|
+
var addRoutes = function () {
|
|
678
|
+
throw new Error("Route init boom");
|
|
679
|
+
};
|
|
680
|
+
(0, bun_test_1.expect)(function () {
|
|
681
|
+
return (0, expressServer_1.setupServer)({
|
|
682
|
+
addRoutes: addRoutes,
|
|
683
|
+
skipListen: true,
|
|
684
|
+
userModel: tests_1.UserModel,
|
|
685
|
+
});
|
|
686
|
+
}).toThrow("Route init boom");
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
(0, bun_test_1.describe)("wrapScript", function () {
|
|
690
|
+
var originalExit = process.exit;
|
|
691
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
692
|
+
process.env = __assign(__assign({}, process.env), { REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_EXPIRES_IN: "1h", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
|
|
693
|
+
// Prevent process.exit from killing the test runner
|
|
694
|
+
process.exit = (0, bun_test_1.mock)(function () {
|
|
695
|
+
throw new Error("__EXIT__");
|
|
696
|
+
});
|
|
697
|
+
});
|
|
698
|
+
(0, bun_test_1.afterEach)(function () {
|
|
699
|
+
process.exit = originalExit;
|
|
700
|
+
});
|
|
701
|
+
(0, bun_test_1.it)("calls process.exit(0) on success", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
702
|
+
var func;
|
|
703
|
+
return __generator(this, function (_a) {
|
|
704
|
+
switch (_a.label) {
|
|
705
|
+
case 0:
|
|
706
|
+
func = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
707
|
+
return [2 /*return*/, "done"];
|
|
708
|
+
}); }); };
|
|
709
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 0 })).rejects.toThrow("__EXIT__")];
|
|
710
|
+
case 1:
|
|
711
|
+
_a.sent();
|
|
712
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(0);
|
|
713
|
+
return [2 /*return*/];
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
}); });
|
|
717
|
+
(0, bun_test_1.it)("calls process.exit(1) on error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
718
|
+
var func;
|
|
719
|
+
return __generator(this, function (_a) {
|
|
720
|
+
switch (_a.label) {
|
|
721
|
+
case 0:
|
|
722
|
+
func = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
723
|
+
return __generator(this, function (_a) {
|
|
724
|
+
throw new Error("script failed");
|
|
725
|
+
});
|
|
726
|
+
}); };
|
|
727
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 0 })).rejects.toThrow("__EXIT__")];
|
|
728
|
+
case 1:
|
|
729
|
+
_a.sent();
|
|
730
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(1);
|
|
731
|
+
return [2 /*return*/];
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}); });
|
|
735
|
+
(0, bun_test_1.it)("calls onFinish with the result", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
736
|
+
var finishResult, func, onFinish;
|
|
737
|
+
return __generator(this, function (_a) {
|
|
738
|
+
switch (_a.label) {
|
|
739
|
+
case 0:
|
|
740
|
+
func = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
741
|
+
return [2 /*return*/, "result-value"];
|
|
742
|
+
}); }); };
|
|
743
|
+
onFinish = function (r) { return __awaiter(void 0, void 0, void 0, function () {
|
|
744
|
+
return __generator(this, function (_a) {
|
|
745
|
+
finishResult = r;
|
|
746
|
+
return [2 /*return*/];
|
|
747
|
+
});
|
|
748
|
+
}); };
|
|
749
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { onFinish: onFinish, terminateTimeout: 0 })).rejects.toThrow("__EXIT__")];
|
|
750
|
+
case 1:
|
|
751
|
+
_a.sent();
|
|
752
|
+
(0, bun_test_1.expect)(finishResult).toBe("result-value");
|
|
753
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(0);
|
|
754
|
+
return [2 /*return*/];
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
}); });
|
|
758
|
+
(0, bun_test_1.it)("sets up warn and terminate timeouts when terminateTimeout is not 0", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
759
|
+
var func;
|
|
760
|
+
return __generator(this, function (_a) {
|
|
761
|
+
switch (_a.label) {
|
|
762
|
+
case 0:
|
|
763
|
+
func = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
764
|
+
return [2 /*return*/, "ok"];
|
|
765
|
+
}); }); };
|
|
766
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 600 })).rejects.toThrow("__EXIT__")];
|
|
767
|
+
case 1:
|
|
768
|
+
_a.sent();
|
|
769
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(0);
|
|
770
|
+
return [2 /*return*/];
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}); });
|
|
774
|
+
(0, bun_test_1.it)("passes slackChannel option through", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
775
|
+
var func;
|
|
776
|
+
return __generator(this, function (_a) {
|
|
777
|
+
switch (_a.label) {
|
|
778
|
+
case 0:
|
|
779
|
+
func = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
780
|
+
return [2 /*return*/, "ok"];
|
|
781
|
+
}); }); };
|
|
782
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { slackChannel: "test-channel", terminateTimeout: 0 })).rejects.toThrow("__EXIT__")];
|
|
783
|
+
case 1:
|
|
784
|
+
_a.sent();
|
|
785
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(0);
|
|
786
|
+
return [2 /*return*/];
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
}); });
|
|
790
|
+
});
|
|
791
|
+
(0, bun_test_1.describe)("wrapScript", function () {
|
|
792
|
+
var originalExit = process.exit;
|
|
793
|
+
var originalSetTimeout = globalThis.setTimeout;
|
|
794
|
+
var timerIds = [];
|
|
795
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
796
|
+
// biome-ignore lint/suspicious/noExplicitAny: Mock requires type override for process.exit.
|
|
797
|
+
process.exit = (0, bun_test_1.mock)(function () {
|
|
798
|
+
throw new Error("process.exit called");
|
|
799
|
+
});
|
|
800
|
+
// Capture timer handles so we can clear them after each test
|
|
801
|
+
globalThis.setTimeout = (function () {
|
|
802
|
+
var args = [];
|
|
803
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
804
|
+
args[_i] = arguments[_i];
|
|
805
|
+
}
|
|
806
|
+
var id = originalSetTimeout.apply(void 0, __spreadArray([], __read(args), false));
|
|
807
|
+
timerIds.push(id);
|
|
808
|
+
return id;
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
(0, bun_test_1.afterEach)(function () {
|
|
812
|
+
var e_1, _a;
|
|
813
|
+
try {
|
|
814
|
+
for (var timerIds_1 = __values(timerIds), timerIds_1_1 = timerIds_1.next(); !timerIds_1_1.done; timerIds_1_1 = timerIds_1.next()) {
|
|
815
|
+
var id = timerIds_1_1.value;
|
|
816
|
+
clearTimeout(id);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
820
|
+
finally {
|
|
821
|
+
try {
|
|
822
|
+
if (timerIds_1_1 && !timerIds_1_1.done && (_a = timerIds_1.return)) _a.call(timerIds_1);
|
|
823
|
+
}
|
|
824
|
+
finally { if (e_1) throw e_1.error; }
|
|
825
|
+
}
|
|
826
|
+
timerIds.length = 0;
|
|
827
|
+
globalThis.setTimeout = originalSetTimeout;
|
|
828
|
+
process.exit = originalExit;
|
|
829
|
+
});
|
|
830
|
+
(0, bun_test_1.it)("runs a successful script and calls process.exit(0)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
831
|
+
var func;
|
|
832
|
+
return __generator(this, function (_a) {
|
|
833
|
+
switch (_a.label) {
|
|
834
|
+
case 0:
|
|
835
|
+
func = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
836
|
+
return [2 /*return*/, "done"];
|
|
837
|
+
}); }); });
|
|
838
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 0 })).rejects.toThrow("process.exit called")];
|
|
839
|
+
case 1:
|
|
840
|
+
_a.sent();
|
|
841
|
+
(0, bun_test_1.expect)(func).toHaveBeenCalled();
|
|
842
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(0);
|
|
843
|
+
return [2 /*return*/];
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
}); });
|
|
847
|
+
(0, bun_test_1.it)("calls onFinish callback on success", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
848
|
+
var onFinish, func;
|
|
849
|
+
return __generator(this, function (_a) {
|
|
850
|
+
switch (_a.label) {
|
|
851
|
+
case 0:
|
|
852
|
+
onFinish = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
853
|
+
return [2 /*return*/];
|
|
854
|
+
}); }); });
|
|
855
|
+
func = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
856
|
+
return [2 /*return*/, "result"];
|
|
857
|
+
}); }); });
|
|
858
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { onFinish: onFinish, terminateTimeout: 0 })).rejects.toThrow("process.exit called")];
|
|
859
|
+
case 1:
|
|
860
|
+
_a.sent();
|
|
861
|
+
(0, bun_test_1.expect)(onFinish).toHaveBeenCalledWith("result");
|
|
862
|
+
return [2 /*return*/];
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
}); });
|
|
866
|
+
(0, bun_test_1.it)("calls process.exit(1) when script throws", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
867
|
+
var func;
|
|
868
|
+
return __generator(this, function (_a) {
|
|
869
|
+
switch (_a.label) {
|
|
870
|
+
case 0:
|
|
871
|
+
func = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
872
|
+
return __generator(this, function (_a) {
|
|
873
|
+
throw new Error("script failure");
|
|
874
|
+
});
|
|
875
|
+
}); });
|
|
876
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 0 })).rejects.toThrow("process.exit called")];
|
|
877
|
+
case 1:
|
|
878
|
+
_a.sent();
|
|
879
|
+
(0, bun_test_1.expect)(process.exit).toHaveBeenCalledWith(1);
|
|
880
|
+
return [2 /*return*/];
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
}); });
|
|
884
|
+
(0, bun_test_1.it)("sets up timeout warnings when terminateTimeout is not 0", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
885
|
+
var func;
|
|
886
|
+
return __generator(this, function (_a) {
|
|
887
|
+
switch (_a.label) {
|
|
888
|
+
case 0:
|
|
889
|
+
func = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
890
|
+
return [2 /*return*/, "done"];
|
|
891
|
+
}); }); });
|
|
892
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func, { terminateTimeout: 600 })).rejects.toThrow("process.exit called")];
|
|
893
|
+
case 1:
|
|
894
|
+
_a.sent();
|
|
895
|
+
(0, bun_test_1.expect)(func).toHaveBeenCalled();
|
|
896
|
+
return [2 /*return*/];
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
}); });
|
|
900
|
+
(0, bun_test_1.it)("uses default terminateTimeout when not specified", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
901
|
+
var func;
|
|
902
|
+
return __generator(this, function (_a) {
|
|
903
|
+
switch (_a.label) {
|
|
904
|
+
case 0:
|
|
905
|
+
func = (0, bun_test_1.mock)(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
906
|
+
return [2 /*return*/, "done"];
|
|
907
|
+
}); }); });
|
|
908
|
+
return [4 /*yield*/, (0, bun_test_1.expect)((0, expressServer_1.wrapScript)(func)).rejects.toThrow("process.exit called")];
|
|
909
|
+
case 1:
|
|
910
|
+
_a.sent();
|
|
911
|
+
(0, bun_test_1.expect)(func).toHaveBeenCalled();
|
|
912
|
+
return [2 /*return*/];
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
}); });
|
|
916
|
+
});
|
|
917
|
+
(0, bun_test_1.describe)("setupServer error handling", function () {
|
|
918
|
+
var originalEnv = process.env;
|
|
919
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
920
|
+
process.env = __assign(__assign({}, originalEnv), { REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_EXPIRES_IN: "1h", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
|
|
921
|
+
});
|
|
922
|
+
(0, bun_test_1.afterEach)(function () {
|
|
923
|
+
process.env = originalEnv;
|
|
924
|
+
});
|
|
925
|
+
(0, bun_test_1.it)("catches and rethrows errors from initializeRoutes", function () {
|
|
926
|
+
var addRoutes = function () {
|
|
927
|
+
throw new Error("route initialization failed");
|
|
928
|
+
};
|
|
929
|
+
(0, bun_test_1.expect)(function () {
|
|
930
|
+
return (0, expressServer_1.setupServer)({
|
|
931
|
+
addRoutes: addRoutes,
|
|
932
|
+
skipListen: true,
|
|
933
|
+
// biome-ignore lint/suspicious/noExplicitAny: Test mock for UserModel.
|
|
934
|
+
userModel: tests_1.UserModel,
|
|
935
|
+
});
|
|
936
|
+
}).toThrow("route initialization failed");
|
|
937
|
+
});
|
|
665
938
|
});
|
|
666
939
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const sendToGoogleChat: (messageText: string, { channel, shouldThrow, env }?: {
|
|
2
2
|
channel?: string;
|
|
3
3
|
shouldThrow?: boolean;
|
|
4
4
|
env?: string;
|
|
5
|
-
})
|
|
5
|
+
}) => Promise<void>;
|
|
@@ -68,17 +68,46 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
68
68
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
72
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
73
|
+
if (!m) return o;
|
|
74
|
+
var i = m.call(o), r, ar = [], e;
|
|
75
|
+
try {
|
|
76
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
77
|
+
}
|
|
78
|
+
catch (error) { e = { error: error }; }
|
|
79
|
+
finally {
|
|
80
|
+
try {
|
|
81
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
82
|
+
}
|
|
83
|
+
finally { if (e) throw e.error; }
|
|
84
|
+
}
|
|
85
|
+
return ar;
|
|
86
|
+
};
|
|
87
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
88
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
89
|
+
if (ar || !(i in from)) {
|
|
90
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
91
|
+
ar[i] = from[i];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
95
|
+
};
|
|
71
96
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
72
97
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
73
98
|
};
|
|
74
99
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
75
|
-
exports.sendToGoogleChat =
|
|
100
|
+
exports.sendToGoogleChat = void 0;
|
|
76
101
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
77
102
|
var axios_1 = __importDefault(require("axios"));
|
|
78
103
|
var errors_1 = require("../errors");
|
|
79
104
|
var logger_1 = require("../logger");
|
|
80
|
-
function
|
|
81
|
-
|
|
105
|
+
var sendToGoogleChat = function (messageText_1) {
|
|
106
|
+
var args_1 = [];
|
|
107
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
108
|
+
args_1[_i - 1] = arguments[_i];
|
|
109
|
+
}
|
|
110
|
+
return __awaiter(void 0, __spreadArray([messageText_1], __read(args_1), false), void 0, function (messageText, _a) {
|
|
82
111
|
var chatWebhooksString, msg, chatWebhooks, chatChannel, chatWebhookUrl, msg, formattedMessageText, error_1;
|
|
83
112
|
var _b, _c, _d;
|
|
84
113
|
var _e = _a === void 0 ? {} : _a, channel = _e.channel, _f = _e.shouldThrow, shouldThrow = _f === void 0 ? false : _f, env = _e.env;
|
|
@@ -127,4 +156,5 @@ function sendToGoogleChat(messageText_1) {
|
|
|
127
156
|
}
|
|
128
157
|
});
|
|
129
158
|
});
|
|
130
|
-
}
|
|
159
|
+
};
|
|
160
|
+
exports.sendToGoogleChat = sendToGoogleChat;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* Logs errors to Sentry and logger when webhook is missing or request fails.
|
|
24
24
|
* Uses Zoom's rich message format (format=full) with structured header and body.
|
|
25
25
|
*/
|
|
26
|
-
export declare
|
|
26
|
+
export declare const sendToZoom: ({ header, body, subheader }: {
|
|
27
27
|
header: string;
|
|
28
28
|
body: string;
|
|
29
29
|
subheader?: string;
|
|
@@ -31,4 +31,4 @@ export declare function sendToZoom({ header, body, subheader }: {
|
|
|
31
31
|
channel: string;
|
|
32
32
|
shouldThrow?: boolean;
|
|
33
33
|
env?: string;
|
|
34
|
-
})
|
|
34
|
+
}) => Promise<void>;
|
|
@@ -72,7 +72,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
72
72
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
73
73
|
};
|
|
74
74
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
75
|
-
exports.sendToZoom =
|
|
75
|
+
exports.sendToZoom = void 0;
|
|
76
76
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
77
77
|
var axios_1 = __importDefault(require("axios"));
|
|
78
78
|
var errors_1 = require("../errors");
|
|
@@ -102,80 +102,78 @@ var logger_1 = require("../logger");
|
|
|
102
102
|
* Logs errors to Sentry and logger when webhook is missing or request fails.
|
|
103
103
|
* Uses Zoom's rich message format (format=full) with structured header and body.
|
|
104
104
|
*/
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
type: "message",
|
|
142
|
-
},
|
|
143
|
-
],
|
|
144
|
-
head: {
|
|
145
|
-
text: env ? "[".concat(env.toUpperCase(), "] ").concat(header) : header,
|
|
105
|
+
var sendToZoom = function (_a, _b) { return __awaiter(void 0, [_a, _b], void 0, function (_c, _d) {
|
|
106
|
+
var zoomWebhooksString, msg, zoomWebhooks, zoomChannel, zoomWebhookUrl, msg, zoomToken, msg, messageBody, error_1;
|
|
107
|
+
var _e, _f, _g, _h, _j, _k, _l, _m;
|
|
108
|
+
var header = _c.header, body = _c.body, subheader = _c.subheader;
|
|
109
|
+
var channel = _d.channel, _o = _d.shouldThrow, shouldThrow = _o === void 0 ? false : _o, env = _d.env;
|
|
110
|
+
return __generator(this, function (_p) {
|
|
111
|
+
switch (_p.label) {
|
|
112
|
+
case 0:
|
|
113
|
+
zoomWebhooksString = process.env.ZOOM_CHAT_WEBHOOKS;
|
|
114
|
+
if (!zoomWebhooksString) {
|
|
115
|
+
msg = "ZOOM_CHAT_WEBHOOKS not set. Zoom message not sent";
|
|
116
|
+
Sentry.captureException(new Error(msg));
|
|
117
|
+
logger_1.logger.error(msg);
|
|
118
|
+
return [2 /*return*/];
|
|
119
|
+
}
|
|
120
|
+
zoomWebhooks = JSON.parse(zoomWebhooksString !== null && zoomWebhooksString !== void 0 ? zoomWebhooksString : "{}");
|
|
121
|
+
zoomChannel = channel !== null && channel !== void 0 ? channel : "default";
|
|
122
|
+
zoomWebhookUrl = (_f = (_e = zoomWebhooks[zoomChannel]) === null || _e === void 0 ? void 0 : _e.channel) !== null && _f !== void 0 ? _f : (_g = zoomWebhooks.default) === null || _g === void 0 ? void 0 : _g.channel;
|
|
123
|
+
if (!zoomWebhookUrl) {
|
|
124
|
+
msg = "No webhook url set in env for ".concat(zoomChannel, ". Zoom message not sent");
|
|
125
|
+
Sentry.captureException(new Error(msg));
|
|
126
|
+
logger_1.logger.error(msg);
|
|
127
|
+
return [2 /*return*/];
|
|
128
|
+
}
|
|
129
|
+
zoomToken = (_j = (_h = zoomWebhooks[zoomChannel]) === null || _h === void 0 ? void 0 : _h.verificationToken) !== null && _j !== void 0 ? _j : (_k = zoomWebhooks.default) === null || _k === void 0 ? void 0 : _k.verificationToken;
|
|
130
|
+
if (!zoomToken) {
|
|
131
|
+
msg = "No verification token set in env for ".concat(zoomChannel, ". Zoom message not sent");
|
|
132
|
+
Sentry.captureException(new Error(msg));
|
|
133
|
+
logger_1.logger.error(msg);
|
|
134
|
+
return [2 /*return*/];
|
|
135
|
+
}
|
|
136
|
+
messageBody = {
|
|
137
|
+
body: [
|
|
138
|
+
{
|
|
139
|
+
text: body,
|
|
140
|
+
type: "message",
|
|
146
141
|
},
|
|
142
|
+
],
|
|
143
|
+
head: {
|
|
144
|
+
text: env ? "[".concat(env.toUpperCase(), "] ").concat(header) : header,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
if (subheader) {
|
|
148
|
+
messageBody.head.sub_head = {
|
|
149
|
+
text: subheader,
|
|
147
150
|
};
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
return [3 /*break*/, 4];
|
|
177
|
-
case 4: return [2 /*return*/];
|
|
178
|
-
}
|
|
179
|
-
});
|
|
151
|
+
}
|
|
152
|
+
_p.label = 1;
|
|
153
|
+
case 1:
|
|
154
|
+
_p.trys.push([1, 3, , 4]);
|
|
155
|
+
return [4 /*yield*/, axios_1.default.post("".concat(zoomWebhookUrl, "?format=full"), { content: messageBody }, {
|
|
156
|
+
headers: {
|
|
157
|
+
Authorization: zoomToken,
|
|
158
|
+
"Content-Type": "application/json",
|
|
159
|
+
},
|
|
160
|
+
})];
|
|
161
|
+
case 2:
|
|
162
|
+
_p.sent();
|
|
163
|
+
return [3 /*break*/, 4];
|
|
164
|
+
case 3:
|
|
165
|
+
error_1 = _p.sent();
|
|
166
|
+
logger_1.logger.error("Error posting to Zoom: ".concat((_l = error_1.text) !== null && _l !== void 0 ? _l : error_1.message));
|
|
167
|
+
Sentry.captureException(error_1);
|
|
168
|
+
if (shouldThrow) {
|
|
169
|
+
throw new errors_1.APIError({
|
|
170
|
+
status: 500,
|
|
171
|
+
title: "Error posting to Zoom: ".concat((_m = error_1.text) !== null && _m !== void 0 ? _m : error_1.message),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return [3 /*break*/, 4];
|
|
175
|
+
case 4: return [2 /*return*/];
|
|
176
|
+
}
|
|
180
177
|
});
|
|
181
|
-
}
|
|
178
|
+
}); };
|
|
179
|
+
exports.sendToZoom = sendToZoom;
|
package/dist/openApiBuilder.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ import type { ModelRouterOptions } from "./api";
|
|
|
33
33
|
* };
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export
|
|
36
|
+
export interface OpenApiSchemaProperty {
|
|
37
37
|
/** The JSON Schema type (e.g., "string", "number", "boolean", "object", "array") */
|
|
38
38
|
type: string;
|
|
39
39
|
/** Human-readable description of the property */
|
|
@@ -48,7 +48,7 @@ export type OpenApiSchemaProperty = {
|
|
|
48
48
|
additionalProperties?: OpenApiSchemaProperty | boolean;
|
|
49
49
|
/** Whether this property is required in the parent object */
|
|
50
50
|
required?: boolean;
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
/**
|
|
53
53
|
* Defines the top-level schema for request bodies and responses.
|
|
54
54
|
*
|
|
@@ -107,7 +107,7 @@ export type OpenApiSchema = {
|
|
|
107
107
|
* };
|
|
108
108
|
* ```
|
|
109
109
|
*/
|
|
110
|
-
export
|
|
110
|
+
export interface OpenApiParameter {
|
|
111
111
|
/** Location of the parameter */
|
|
112
112
|
in: "query" | "path" | "header";
|
|
113
113
|
/** Name of the parameter */
|
|
@@ -118,7 +118,7 @@ export type OpenApiParameter = {
|
|
|
118
118
|
schema: OpenApiSchemaProperty;
|
|
119
119
|
/** Human-readable description of the parameter */
|
|
120
120
|
description?: string;
|
|
121
|
-
}
|
|
121
|
+
}
|
|
122
122
|
/**
|
|
123
123
|
* Defines a response in an OpenAPI operation.
|
|
124
124
|
*
|
|
@@ -143,7 +143,7 @@ export type OpenApiParameter = {
|
|
|
143
143
|
* };
|
|
144
144
|
* ```
|
|
145
145
|
*/
|
|
146
|
-
export
|
|
146
|
+
export interface OpenApiResponse {
|
|
147
147
|
/** Human-readable description of the response */
|
|
148
148
|
description: string;
|
|
149
149
|
/** Content definitions keyed by media type */
|
|
@@ -152,7 +152,7 @@ export type OpenApiResponse = {
|
|
|
152
152
|
schema: OpenApiSchema;
|
|
153
153
|
};
|
|
154
154
|
};
|
|
155
|
-
}
|
|
155
|
+
}
|
|
156
156
|
/**
|
|
157
157
|
* Result from building OpenAPI middleware with schemas exposed.
|
|
158
158
|
* Useful when you want to use the schemas with asyncHandler's validation.
|
|
@@ -485,4 +485,4 @@ export declare class OpenApiMiddlewareBuilder {
|
|
|
485
485
|
* router.get("/analytics/stats", statsMiddleware, getStatsHandler);
|
|
486
486
|
* ```
|
|
487
487
|
*/
|
|
488
|
-
export declare
|
|
488
|
+
export declare const createOpenApiBuilder: (options: Partial<ModelRouterOptions<unknown>>) => OpenApiMiddlewareBuilder;
|
package/dist/openApiBuilder.js
CHANGED
|
@@ -30,8 +30,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
30
30
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
31
|
};
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
-
exports.OpenApiMiddlewareBuilder = void 0;
|
|
34
|
-
exports.createOpenApiBuilder = createOpenApiBuilder;
|
|
33
|
+
exports.createOpenApiBuilder = exports.OpenApiMiddlewareBuilder = void 0;
|
|
35
34
|
/**
|
|
36
35
|
* OpenAPI Middleware Builder
|
|
37
36
|
*
|
|
@@ -534,6 +533,7 @@ exports.OpenApiMiddlewareBuilder = OpenApiMiddlewareBuilder;
|
|
|
534
533
|
* router.get("/analytics/stats", statsMiddleware, getStatsHandler);
|
|
535
534
|
* ```
|
|
536
535
|
*/
|
|
537
|
-
function
|
|
536
|
+
var createOpenApiBuilder = function (options) {
|
|
538
537
|
return new OpenApiMiddlewareBuilder(options);
|
|
539
|
-
}
|
|
538
|
+
};
|
|
539
|
+
exports.createOpenApiBuilder = createOpenApiBuilder;
|
package/package.json
CHANGED
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"jsonwebtoken": "^9.0.2",
|
|
28
28
|
"lodash": "^4.17.23",
|
|
29
29
|
"luxon": "^3.7.2",
|
|
30
|
-
"mongoose": "8.23.0",
|
|
31
30
|
"mongoose-to-swagger": "^1.4.0",
|
|
32
31
|
"ms": "^2.1.3",
|
|
33
32
|
"on-finished": "^2.3.0",
|
|
@@ -62,6 +61,7 @@
|
|
|
62
61
|
"@types/sinon": "^21.0.0",
|
|
63
62
|
"@types/supertest": "^6.0.2",
|
|
64
63
|
"mongodb-memory-server": "^11.0.1",
|
|
64
|
+
"mongoose": "8.23.0",
|
|
65
65
|
"sinon": "^21.0.1",
|
|
66
66
|
"supertest": "^7.0.0",
|
|
67
67
|
"typedoc": "~0.28.17",
|
|
@@ -104,5 +104,5 @@
|
|
|
104
104
|
"updateSnapshot": "bun test --update-snapshots"
|
|
105
105
|
},
|
|
106
106
|
"types": "dist/index.d.ts",
|
|
107
|
-
"version": "0.11.
|
|
107
|
+
"version": "0.11.5"
|
|
108
108
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {afterEach, beforeEach, describe, expect, it} from "bun:test";
|
|
1
|
+
import {afterEach, beforeEach, describe, expect, it, mock} from "bun:test";
|
|
2
2
|
import express from "express";
|
|
3
3
|
import supertest from "supertest";
|
|
4
4
|
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
logRequests,
|
|
10
10
|
setupEnvironment,
|
|
11
11
|
setupServer,
|
|
12
|
+
wrapScript,
|
|
12
13
|
} from "./expressServer";
|
|
13
14
|
import {UserModel} from "./tests";
|
|
14
15
|
|
|
@@ -568,5 +569,191 @@ describe("expressServer", () => {
|
|
|
568
569
|
|
|
569
570
|
await supertest(app).get("/test").expect(200);
|
|
570
571
|
});
|
|
572
|
+
|
|
573
|
+
it("re-throws when addRoutes throws during route initialization", () => {
|
|
574
|
+
const addRoutes = () => {
|
|
575
|
+
throw new Error("Route init boom");
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
expect(() =>
|
|
579
|
+
setupServer({
|
|
580
|
+
addRoutes,
|
|
581
|
+
skipListen: true,
|
|
582
|
+
userModel: UserModel as any,
|
|
583
|
+
})
|
|
584
|
+
).toThrow("Route init boom");
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
describe("wrapScript", () => {
|
|
589
|
+
const originalExit = process.exit;
|
|
590
|
+
|
|
591
|
+
beforeEach(() => {
|
|
592
|
+
process.env = {
|
|
593
|
+
...process.env,
|
|
594
|
+
REFRESH_TOKEN_SECRET: "test-refresh-secret",
|
|
595
|
+
SESSION_SECRET: "test-session-secret",
|
|
596
|
+
TOKEN_EXPIRES_IN: "1h",
|
|
597
|
+
TOKEN_ISSUER: "test-issuer",
|
|
598
|
+
TOKEN_SECRET: "test-secret",
|
|
599
|
+
};
|
|
600
|
+
// Prevent process.exit from killing the test runner
|
|
601
|
+
process.exit = mock(() => {
|
|
602
|
+
throw new Error("__EXIT__");
|
|
603
|
+
}) as unknown as typeof process.exit;
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
afterEach(() => {
|
|
607
|
+
process.exit = originalExit;
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it("calls process.exit(0) on success", async () => {
|
|
611
|
+
const func = async () => "done";
|
|
612
|
+
await expect(wrapScript(func, {terminateTimeout: 0})).rejects.toThrow("__EXIT__");
|
|
613
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it("calls process.exit(1) on error", async () => {
|
|
617
|
+
const func = async () => {
|
|
618
|
+
throw new Error("script failed");
|
|
619
|
+
};
|
|
620
|
+
await expect(wrapScript(func, {terminateTimeout: 0})).rejects.toThrow("__EXIT__");
|
|
621
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it("calls onFinish with the result", async () => {
|
|
625
|
+
let finishResult: unknown;
|
|
626
|
+
const func = async () => "result-value";
|
|
627
|
+
const onFinish = async (r: unknown) => {
|
|
628
|
+
finishResult = r;
|
|
629
|
+
};
|
|
630
|
+
await expect(wrapScript(func, {onFinish, terminateTimeout: 0})).rejects.toThrow("__EXIT__");
|
|
631
|
+
expect(finishResult).toBe("result-value");
|
|
632
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it("sets up warn and terminate timeouts when terminateTimeout is not 0", async () => {
|
|
636
|
+
const func = async () => "ok";
|
|
637
|
+
await expect(wrapScript(func, {terminateTimeout: 600})).rejects.toThrow("__EXIT__");
|
|
638
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it("passes slackChannel option through", async () => {
|
|
642
|
+
const func = async () => "ok";
|
|
643
|
+
await expect(
|
|
644
|
+
wrapScript(func, {slackChannel: "test-channel", terminateTimeout: 0})
|
|
645
|
+
).rejects.toThrow("__EXIT__");
|
|
646
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
describe("wrapScript", () => {
|
|
651
|
+
const originalExit = process.exit;
|
|
652
|
+
const originalSetTimeout = globalThis.setTimeout;
|
|
653
|
+
const timerIds: ReturnType<typeof setTimeout>[] = [];
|
|
654
|
+
|
|
655
|
+
beforeEach(() => {
|
|
656
|
+
// biome-ignore lint/suspicious/noExplicitAny: Mock requires type override for process.exit.
|
|
657
|
+
process.exit = mock(() => {
|
|
658
|
+
throw new Error("process.exit called");
|
|
659
|
+
}) as unknown as typeof process.exit;
|
|
660
|
+
// Capture timer handles so we can clear them after each test
|
|
661
|
+
globalThis.setTimeout = ((...args: Parameters<typeof setTimeout>) => {
|
|
662
|
+
const id = originalSetTimeout(...args);
|
|
663
|
+
timerIds.push(id);
|
|
664
|
+
return id;
|
|
665
|
+
}) as typeof setTimeout;
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
afterEach(() => {
|
|
669
|
+
for (const id of timerIds) {
|
|
670
|
+
clearTimeout(id);
|
|
671
|
+
}
|
|
672
|
+
timerIds.length = 0;
|
|
673
|
+
globalThis.setTimeout = originalSetTimeout;
|
|
674
|
+
process.exit = originalExit;
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
it("runs a successful script and calls process.exit(0)", async () => {
|
|
678
|
+
const func = mock(async () => "done");
|
|
679
|
+
|
|
680
|
+
await expect(wrapScript(func, {terminateTimeout: 0})).rejects.toThrow("process.exit called");
|
|
681
|
+
|
|
682
|
+
expect(func).toHaveBeenCalled();
|
|
683
|
+
expect(process.exit).toHaveBeenCalledWith(0);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
it("calls onFinish callback on success", async () => {
|
|
687
|
+
const onFinish = mock(async () => {});
|
|
688
|
+
const func = mock(async () => "result");
|
|
689
|
+
|
|
690
|
+
await expect(wrapScript(func, {onFinish, terminateTimeout: 0})).rejects.toThrow(
|
|
691
|
+
"process.exit called"
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
expect(onFinish).toHaveBeenCalledWith("result");
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
it("calls process.exit(1) when script throws", async () => {
|
|
698
|
+
const func = mock(async () => {
|
|
699
|
+
throw new Error("script failure");
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
await expect(wrapScript(func, {terminateTimeout: 0})).rejects.toThrow("process.exit called");
|
|
703
|
+
|
|
704
|
+
expect(process.exit).toHaveBeenCalledWith(1);
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
it("sets up timeout warnings when terminateTimeout is not 0", async () => {
|
|
708
|
+
const func = mock(async () => "done");
|
|
709
|
+
|
|
710
|
+
await expect(wrapScript(func, {terminateTimeout: 600})).rejects.toThrow(
|
|
711
|
+
"process.exit called"
|
|
712
|
+
);
|
|
713
|
+
|
|
714
|
+
expect(func).toHaveBeenCalled();
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it("uses default terminateTimeout when not specified", async () => {
|
|
718
|
+
const func = mock(async () => "done");
|
|
719
|
+
|
|
720
|
+
await expect(wrapScript(func)).rejects.toThrow("process.exit called");
|
|
721
|
+
|
|
722
|
+
expect(func).toHaveBeenCalled();
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
describe("setupServer error handling", () => {
|
|
727
|
+
const originalEnv = process.env;
|
|
728
|
+
|
|
729
|
+
beforeEach(() => {
|
|
730
|
+
process.env = {
|
|
731
|
+
...originalEnv,
|
|
732
|
+
REFRESH_TOKEN_SECRET: "test-refresh-secret",
|
|
733
|
+
SESSION_SECRET: "test-session-secret",
|
|
734
|
+
TOKEN_EXPIRES_IN: "1h",
|
|
735
|
+
TOKEN_ISSUER: "test-issuer",
|
|
736
|
+
TOKEN_SECRET: "test-secret",
|
|
737
|
+
};
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
afterEach(() => {
|
|
741
|
+
process.env = originalEnv;
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it("catches and rethrows errors from initializeRoutes", () => {
|
|
745
|
+
const addRoutes = () => {
|
|
746
|
+
throw new Error("route initialization failed");
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
expect(() =>
|
|
750
|
+
setupServer({
|
|
751
|
+
addRoutes,
|
|
752
|
+
skipListen: true,
|
|
753
|
+
// biome-ignore lint/suspicious/noExplicitAny: Test mock for UserModel.
|
|
754
|
+
userModel: UserModel as any,
|
|
755
|
+
})
|
|
756
|
+
).toThrow("route initialization failed");
|
|
757
|
+
});
|
|
571
758
|
});
|
|
572
759
|
});
|
|
@@ -4,10 +4,10 @@ import axios from "axios";
|
|
|
4
4
|
import {APIError} from "../errors";
|
|
5
5
|
import {logger} from "../logger";
|
|
6
6
|
|
|
7
|
-
export async
|
|
7
|
+
export const sendToGoogleChat = async (
|
|
8
8
|
messageText: string,
|
|
9
9
|
{channel, shouldThrow = false, env}: {channel?: string; shouldThrow?: boolean; env?: string} = {}
|
|
10
|
-
) {
|
|
10
|
+
) => {
|
|
11
11
|
const chatWebhooksString = process.env.GOOGLE_CHAT_WEBHOOKS;
|
|
12
12
|
if (!chatWebhooksString) {
|
|
13
13
|
const msg = "GOOGLE_CHAT_WEBHOOKS not set. Google Chat message not sent";
|
|
@@ -44,4 +44,4 @@ export async function sendToGoogleChat(
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
}
|
|
47
|
+
};
|
|
@@ -29,10 +29,10 @@ import {logger} from "../logger";
|
|
|
29
29
|
* Logs errors to Sentry and logger when webhook is missing or request fails.
|
|
30
30
|
* Uses Zoom's rich message format (format=full) with structured header and body.
|
|
31
31
|
*/
|
|
32
|
-
export async
|
|
32
|
+
export const sendToZoom = async (
|
|
33
33
|
{header, body, subheader}: {header: string; body: string; subheader?: string},
|
|
34
34
|
{channel, shouldThrow = false, env}: {channel: string; shouldThrow?: boolean; env?: string}
|
|
35
|
-
) {
|
|
35
|
+
) => {
|
|
36
36
|
const zoomWebhooksString = process.env.ZOOM_CHAT_WEBHOOKS;
|
|
37
37
|
if (!zoomWebhooksString) {
|
|
38
38
|
const msg = "ZOOM_CHAT_WEBHOOKS not set. Zoom message not sent";
|
|
@@ -45,7 +45,6 @@ export async function sendToZoom(
|
|
|
45
45
|
);
|
|
46
46
|
|
|
47
47
|
const zoomChannel = channel ?? "default";
|
|
48
|
-
// Use format full
|
|
49
48
|
const zoomWebhookUrl = zoomWebhooks[zoomChannel]?.channel ?? zoomWebhooks.default?.channel;
|
|
50
49
|
|
|
51
50
|
if (!zoomWebhookUrl) {
|
|
@@ -64,7 +63,6 @@ export async function sendToZoom(
|
|
|
64
63
|
return;
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
// Build the message structure
|
|
68
66
|
const messageBody: {
|
|
69
67
|
head: {text: string; sub_head?: {text: string}};
|
|
70
68
|
body: Array<{type: string; text: string}>;
|
|
@@ -80,7 +78,6 @@ export async function sendToZoom(
|
|
|
80
78
|
},
|
|
81
79
|
};
|
|
82
80
|
|
|
83
|
-
// Add subheader if provided
|
|
84
81
|
if (subheader) {
|
|
85
82
|
messageBody.head.sub_head = {
|
|
86
83
|
text: subheader,
|
|
@@ -108,4 +105,4 @@ export async function sendToZoom(
|
|
|
108
105
|
});
|
|
109
106
|
}
|
|
110
107
|
}
|
|
111
|
-
}
|
|
108
|
+
};
|
package/src/openApiBuilder.ts
CHANGED
|
@@ -75,7 +75,7 @@ import {
|
|
|
75
75
|
* };
|
|
76
76
|
* ```
|
|
77
77
|
*/
|
|
78
|
-
export
|
|
78
|
+
export interface OpenApiSchemaProperty {
|
|
79
79
|
/** The JSON Schema type (e.g., "string", "number", "boolean", "object", "array") */
|
|
80
80
|
type: string;
|
|
81
81
|
/** Human-readable description of the property */
|
|
@@ -90,7 +90,7 @@ export type OpenApiSchemaProperty = {
|
|
|
90
90
|
additionalProperties?: OpenApiSchemaProperty | boolean;
|
|
91
91
|
/** Whether this property is required in the parent object */
|
|
92
92
|
required?: boolean;
|
|
93
|
-
}
|
|
93
|
+
}
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Defines the top-level schema for request bodies and responses.
|
|
@@ -151,7 +151,7 @@ export type OpenApiSchema = {
|
|
|
151
151
|
* };
|
|
152
152
|
* ```
|
|
153
153
|
*/
|
|
154
|
-
export
|
|
154
|
+
export interface OpenApiParameter {
|
|
155
155
|
/** Location of the parameter */
|
|
156
156
|
in: "query" | "path" | "header";
|
|
157
157
|
/** Name of the parameter */
|
|
@@ -162,7 +162,7 @@ export type OpenApiParameter = {
|
|
|
162
162
|
schema: OpenApiSchemaProperty;
|
|
163
163
|
/** Human-readable description of the parameter */
|
|
164
164
|
description?: string;
|
|
165
|
-
}
|
|
165
|
+
}
|
|
166
166
|
|
|
167
167
|
/**
|
|
168
168
|
* Defines a response in an OpenAPI operation.
|
|
@@ -188,7 +188,7 @@ export type OpenApiParameter = {
|
|
|
188
188
|
* };
|
|
189
189
|
* ```
|
|
190
190
|
*/
|
|
191
|
-
export
|
|
191
|
+
export interface OpenApiResponse {
|
|
192
192
|
/** Human-readable description of the response */
|
|
193
193
|
description: string;
|
|
194
194
|
/** Content definitions keyed by media type */
|
|
@@ -197,7 +197,7 @@ export type OpenApiResponse = {
|
|
|
197
197
|
schema: OpenApiSchema;
|
|
198
198
|
};
|
|
199
199
|
};
|
|
200
|
-
}
|
|
200
|
+
}
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
203
|
* Internal configuration object for the OpenAPI middleware builder.
|
|
@@ -817,8 +817,8 @@ export class OpenApiMiddlewareBuilder {
|
|
|
817
817
|
* router.get("/analytics/stats", statsMiddleware, getStatsHandler);
|
|
818
818
|
* ```
|
|
819
819
|
*/
|
|
820
|
-
export
|
|
820
|
+
export const createOpenApiBuilder = (
|
|
821
821
|
options: Partial<ModelRouterOptions<unknown>>
|
|
822
|
-
): OpenApiMiddlewareBuilder {
|
|
822
|
+
): OpenApiMiddlewareBuilder => {
|
|
823
823
|
return new OpenApiMiddlewareBuilder(options);
|
|
824
|
-
}
|
|
824
|
+
};
|