@goatlab/node-backend 0.0.15 → 0.1.0

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.
Files changed (126) hide show
  1. package/README.md +54 -38
  2. package/dist/container/Container.d.ts +441 -0
  3. package/dist/container/Container.js +895 -0
  4. package/dist/container/Container.js.map +1 -0
  5. package/dist/container/DistributedCacheInvalidator.d.ts +84 -0
  6. package/dist/container/DistributedCacheInvalidator.js +213 -0
  7. package/dist/container/DistributedCacheInvalidator.js.map +1 -0
  8. package/dist/container/LruCache.d.ts +14 -0
  9. package/dist/container/LruCache.js +23 -0
  10. package/dist/container/LruCache.js.map +1 -0
  11. package/dist/container/types.d.ts +128 -0
  12. package/dist/container/types.js +6 -0
  13. package/dist/container/types.js.map +1 -0
  14. package/dist/index.d.ts +31 -0
  15. package/dist/index.js +53 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/server/bootstraps/getExpressTrpcApp.d.ts +17 -0
  18. package/dist/server/bootstraps/getExpressTrpcApp.js +98 -0
  19. package/dist/server/bootstraps/getExpressTrpcApp.js.map +1 -0
  20. package/dist/server/consts.d.ts +35 -0
  21. package/dist/server/consts.js +33 -0
  22. package/dist/server/consts.js.map +1 -0
  23. package/dist/server/context/context.model.d.ts +13 -0
  24. package/dist/server/context/context.model.js +3 -0
  25. package/dist/server/context/context.model.js.map +1 -0
  26. package/dist/server/context/request.context.d.ts +40 -0
  27. package/dist/server/context/request.context.js +65 -0
  28. package/dist/server/context/request.context.js.map +1 -0
  29. package/dist/server/context/trpc.context.d.ts +11 -0
  30. package/dist/server/context/trpc.context.js +67 -0
  31. package/dist/server/context/trpc.context.js.map +1 -0
  32. package/dist/server/initOpenApiDocs.d.ts +9 -0
  33. package/dist/server/initOpenApiDocs.js +18 -0
  34. package/dist/server/initOpenApiDocs.js.map +1 -0
  35. package/dist/server/middleware/cloudTaskDecrypt.middleware.d.ts +6 -0
  36. package/dist/server/middleware/cloudTaskDecrypt.middleware.js +44 -0
  37. package/dist/server/middleware/cloudTaskDecrypt.middleware.js.map +1 -0
  38. package/dist/server/middleware/error.middleware.d.ts +17 -0
  39. package/dist/server/middleware/error.middleware.js +66 -0
  40. package/dist/server/middleware/error.middleware.js.map +1 -0
  41. package/dist/server/middleware/handleRequest.middleware.d.ts +7 -0
  42. package/dist/server/middleware/handleRequest.middleware.js +40 -0
  43. package/dist/server/middleware/handleRequest.middleware.js.map +1 -0
  44. package/dist/server/middleware/logger/cloudRun.logger.d.ts +27 -0
  45. package/dist/server/middleware/logger/cloudRun.logger.js +87 -0
  46. package/dist/server/middleware/logger/cloudRun.logger.js.map +1 -0
  47. package/dist/server/middleware/logger/logger.service.d.ts +6 -0
  48. package/dist/server/middleware/logger/logger.service.js +17 -0
  49. package/dist/server/middleware/logger/logger.service.js.map +1 -0
  50. package/dist/server/middleware/logs.middleware.d.ts +7 -0
  51. package/dist/server/middleware/logs.middleware.js +130 -0
  52. package/dist/server/middleware/logs.middleware.js.map +1 -0
  53. package/dist/server/middleware/requireAuthenticated.d.ts +2 -0
  54. package/dist/server/middleware/requireAuthenticated.js +13 -0
  55. package/dist/server/middleware/requireAuthenticated.js.map +1 -0
  56. package/dist/server/middleware/trpcError.middleware.d.ts +4 -0
  57. package/dist/server/middleware/trpcError.middleware.js +38 -0
  58. package/dist/server/middleware/trpcError.middleware.js.map +1 -0
  59. package/dist/server/schemas/user.schema.d.ts +109 -0
  60. package/dist/server/schemas/user.schema.js +28 -0
  61. package/dist/server/schemas/user.schema.js.map +1 -0
  62. package/dist/server/sentry/getSentry.d.ts +6 -0
  63. package/dist/server/sentry/getSentry.js +45 -0
  64. package/dist/server/sentry/getSentry.js.map +1 -0
  65. package/dist/server/sentry/sentry.service.d.ts +34 -0
  66. package/dist/server/sentry/sentry.service.js +110 -0
  67. package/dist/server/sentry/sentry.service.js.map +1 -0
  68. package/dist/server/services/email/email.model.d.ts +84 -0
  69. package/dist/server/services/email/email.model.js +62 -0
  70. package/dist/server/services/email/email.model.js.map +1 -0
  71. package/dist/server/services/email/email.service.d.ts +23 -0
  72. package/dist/server/services/email/email.service.js +139 -0
  73. package/dist/server/services/email/email.service.js.map +1 -0
  74. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.d.ts +15 -0
  75. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.js +9 -0
  76. package/dist/server/services/gcp/getGcpServiceAccountFromBase64.js.map +1 -0
  77. package/dist/server/services/secrets/secret.service.d.ts +31 -0
  78. package/dist/server/services/secrets/secret.service.js +172 -0
  79. package/dist/server/services/secrets/secret.service.js.map +1 -0
  80. package/dist/server/services/sendgrid/sendgrid.model.d.ts +118 -0
  81. package/dist/server/services/sendgrid/sendgrid.model.js +3 -0
  82. package/dist/server/services/sendgrid/sendgrid.model.js.map +1 -0
  83. package/dist/server/services/sendgrid/sendgridApi.service.d.ts +13 -0
  84. package/dist/server/services/sendgrid/sendgridApi.service.js +79 -0
  85. package/dist/server/services/sendgrid/sendgridApi.service.js.map +1 -0
  86. package/dist/server/services/sendgrid/sendgridHooks.model.d.ts +27 -0
  87. package/dist/server/services/sendgrid/sendgridHooks.model.js +19 -0
  88. package/dist/server/services/sendgrid/sendgridHooks.model.js.map +1 -0
  89. package/dist/server/services/translations/template.util.d.ts +7 -0
  90. package/dist/server/services/translations/template.util.js +11 -0
  91. package/dist/server/services/translations/template.util.js.map +1 -0
  92. package/dist/server/services/translations/translation.model.d.ts +4 -0
  93. package/dist/server/services/translations/translation.model.js +6 -0
  94. package/dist/server/services/translations/translation.model.js.map +1 -0
  95. package/dist/server/services/translations/translation.service.d.ts +25 -0
  96. package/dist/server/services/translations/translation.service.js +97 -0
  97. package/dist/server/services/translations/translation.service.js.map +1 -0
  98. package/dist/server/services/util/benchmarker.d.ts +13 -0
  99. package/dist/server/services/util/benchmarker.js +34 -0
  100. package/dist/server/services/util/benchmarker.js.map +1 -0
  101. package/dist/server/services/util/pagination.d.ts +50 -0
  102. package/dist/server/services/util/pagination.js +57 -0
  103. package/dist/server/services/util/pagination.js.map +1 -0
  104. package/dist/server/services/util/url.service.d.ts +75 -0
  105. package/dist/server/services/util/url.service.js +139 -0
  106. package/dist/server/services/util/url.service.js.map +1 -0
  107. package/dist/server/test/express.mock.d.ts +6 -0
  108. package/dist/server/test/express.mock.js +49 -0
  109. package/dist/server/test/express.mock.js.map +1 -0
  110. package/dist/server/test/firebase.mock.d.ts +4 -0
  111. package/dist/server/test/firebase.mock.js +30 -0
  112. package/dist/server/test/firebase.mock.js.map +1 -0
  113. package/dist/server/test/mock.model.d.ts +5 -0
  114. package/dist/server/test/mock.model.js +3 -0
  115. package/dist/server/test/mock.model.js.map +1 -0
  116. package/dist/server/test/trpc.mock.d.ts +6 -0
  117. package/dist/server/test/trpc.mock.js +14 -0
  118. package/dist/server/test/trpc.mock.js.map +1 -0
  119. package/dist/server/trpc.d.ts +364 -0
  120. package/dist/server/trpc.js +87 -0
  121. package/dist/server/trpc.js.map +1 -0
  122. package/dist/server/types/Envinronment.d.ts +1 -0
  123. package/dist/server/types/Envinronment.js +3 -0
  124. package/dist/server/types/Envinronment.js.map +1 -0
  125. package/dist/tsconfig.tsbuildinfo +1 -1
  126. package/package.json +33 -3
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SentryService = void 0;
4
+ const js_utils_1 = require("@goatlab/js-utils");
5
+ const sentrySeverityMap = {
6
+ debug: 'log',
7
+ info: 'log',
8
+ log: 'log',
9
+ warning: 'warn',
10
+ error: 'error',
11
+ fatal: 'error',
12
+ };
13
+ class SentryService {
14
+ config;
15
+ constructor(config) {
16
+ this.config = config;
17
+ }
18
+ //@Memo.syncMethod()
19
+ sentry() {
20
+ // Lazy-loading `@sentry/node`
21
+ const sentry = require('@sentry/node');
22
+ if (!this.config.dsn) {
23
+ return sentry;
24
+ }
25
+ console.log('SentryService init...');
26
+ sentry.init({
27
+ maxValueLength: 2000, // Default is 250 characters
28
+ ...this.config,
29
+ });
30
+ return sentry;
31
+ }
32
+ init() {
33
+ this.sentry();
34
+ }
35
+ /**
36
+ * For GDPR reasons we never send more information than just User ID.
37
+ */
38
+ setUserId(id) {
39
+ this.sentry().getCurrentScope().setUser({
40
+ id,
41
+ });
42
+ }
43
+ /**
44
+ * Does console.error(err)
45
+ * Returns "eventId" or undefined (if error was not reported).
46
+ */
47
+ captureException(error, logError = true) {
48
+ // Console.error(err)
49
+ // Using request-aware logger here
50
+ if (logError) {
51
+ this.config.logger?.error('captureException:', error);
52
+ }
53
+ if (error?.data?.report === false) {
54
+ // Skip reporting the error
55
+ return;
56
+ }
57
+ // This is to avoid Sentry cutting err.message to 253 characters
58
+ // It will log additional "breadcrumb object" before the error
59
+ // It's a Breadcrumb, not a console.log, because console.log are NOT automatically attached as Breadcrumbs in cron-job environments (outside of Express)
60
+ this.sentry().addBreadcrumb({
61
+ message: js_utils_1.Inspect.any(error, {
62
+ includeErrorData: true,
63
+ colors: false,
64
+ }),
65
+ // Data: (err as AppError).data, // included in message
66
+ });
67
+ return this.sentry().captureException(js_utils_1.Errors.anyToError(error, Error, {
68
+ stringifyFn: js_utils_1.Inspect.anyStringifyFn,
69
+ }));
70
+ }
71
+ /**
72
+ * Returns "eventId"
73
+ */
74
+ captureMessage(message, level) {
75
+ this.config.logger?.[sentrySeverityMap[level || 'error'] || 'log']('captureMessage:', message);
76
+ return this.sentry().captureMessage(message, level);
77
+ }
78
+ addBreadcrumb(breadcrumb) {
79
+ this.sentry().addBreadcrumb(breadcrumb);
80
+ }
81
+ /**
82
+ * Currently it will only use `logger.error` ("error" level) and ignore `log` and `warn`.
83
+ *
84
+ * For each `logger.error` - it'll do a captureException.
85
+ *
86
+ * @experimental
87
+ */
88
+ getCommonLogger() {
89
+ return {
90
+ log() { }, // Noop
91
+ warn() { }, // Noop
92
+ error: (...args) => {
93
+ const message = args
94
+ .map((arg) => js_utils_1.Inspect.any(arg, {
95
+ includeErrorData: true,
96
+ colors: false,
97
+ }))
98
+ .join(' ');
99
+ this.sentry().addBreadcrumb({
100
+ message,
101
+ });
102
+ this.sentry().captureException(js_utils_1.Errors.anyToError(args.length === 1 ? args[0] : args, Error, {
103
+ stringifyFn: js_utils_1.Inspect.anyStringifyFn,
104
+ }));
105
+ },
106
+ };
107
+ }
108
+ }
109
+ exports.SentryService = SentryService;
110
+ //# sourceMappingURL=sentry.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentry.service.js","sourceRoot":"","sources":["../../../src/server/sentry/sentry.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { z } from 'zod';
2
+ export declare enum EmailCategory {
3
+ SIMPLE = "SIMPLE",
4
+ TEST_EMAIL = "TEST_EMAIL",
5
+ EMAIL_VERIFICATION = "EMAIL_VERIFICATION",
6
+ SEND_ONCE = "SEND_ONCE",
7
+ OTP = "OTP",
8
+ MEETING = "MEETING",
9
+ ORGANIZATION_INVITATION = "ORGANIZATION_INVITATION",
10
+ PDF_EXAM = "PDF_EXAM"
11
+ }
12
+ export interface EmailAddress {
13
+ email: string;
14
+ name?: string;
15
+ }
16
+ export interface EmailTest {
17
+ to: string;
18
+ subject: string;
19
+ mjml: string;
20
+ }
21
+ export declare const testEmailTemplate: z.ZodObject<{
22
+ to: z.ZodString;
23
+ subject: z.ZodString;
24
+ mjml: z.ZodString;
25
+ }, "strip", z.ZodTypeAny, {
26
+ to?: string;
27
+ subject?: string;
28
+ mjml?: string;
29
+ }, {
30
+ to?: string;
31
+ subject?: string;
32
+ mjml?: string;
33
+ }>;
34
+ export interface EmailAttachment {
35
+ Content: string;
36
+ Type: string;
37
+ FileName: string;
38
+ }
39
+ export declare enum Layout {
40
+ default = "layouts/default.ejs"
41
+ }
42
+ export declare enum Content {
43
+ simple = "simple/simple.ejs",
44
+ doubleAction = "doubleAction/doubleAction.ejs"
45
+ }
46
+ export type Theme = {
47
+ logo: string;
48
+ logoLink: string;
49
+ primaryColor: string;
50
+ buttonTextColor: string;
51
+ privacyPolicyLink: string;
52
+ unsubscribeLink: string;
53
+ facebook: string;
54
+ instagram: string;
55
+ twitter: string;
56
+ appName: string;
57
+ };
58
+ export interface EmailVerificationResp {
59
+ res?: boolean;
60
+ suggestion?: string;
61
+ }
62
+ interface SimpleTemplate {
63
+ layout: Layout.default;
64
+ content: Content.simple;
65
+ categories: [EmailCategory.SIMPLE | EmailCategory.OTP | EmailCategory.MEETING];
66
+ theme?: Theme;
67
+ placeholders: {
68
+ title?: string;
69
+ imgSrc?: string;
70
+ imgAlt?: string;
71
+ greeting: string;
72
+ body: string;
73
+ footer: string;
74
+ };
75
+ }
76
+ export type EmailTemplates = SimpleTemplate;
77
+ export interface SendEmailFromTemplateParams {
78
+ template: EmailTemplates;
79
+ to: string;
80
+ subject: string;
81
+ attachments?: EmailAttachment[];
82
+ archive?: boolean;
83
+ }
84
+ export {};
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Content = exports.Layout = exports.testEmailTemplate = exports.EmailCategory = void 0;
4
+ const zod_1 = require("zod");
5
+ // export const themeVariables = {
6
+ // [Theme.Gealium]: {
7
+ // logo: `https://www.${env.BASE_DOMAIN}/assets/images/logo-wide-black.png`,
8
+ // logoLink: `https://www.${env.BASE_DOMAIN}/`,
9
+ // primaryColor: '#4db7a3',
10
+ // buttonTextColor: '#ffffff',
11
+ // privacyPolicyLink: 'https://www.gealium.com/about/privacy',
12
+ // unsubscribeLink: 'https://www.gealium.com',
13
+ // facebook: 'Gealium',
14
+ // instagram: 'gealium_com',
15
+ // twitter: 'https://www.gealium.com',
16
+ // appName: 'Gealium',
17
+ // },
18
+ // [Theme.Agrosocial]: {
19
+ // logo: `https://storage.googleapis.com/public-agrosocial-prod/assets/AGSemailcode.png`,
20
+ // logoLink: `https://www.${env.BASE_DOMAIN}/`,
21
+ // primaryColor: '#4db7a3',
22
+ // buttonTextColor: '#ffffff',
23
+ // privacyPolicyLink: 'https://www.agrosocial.com/termsandprivacy',
24
+ // unsubscribeLink: 'https://www.agrosocial.com',
25
+ // facebook: 'agrosocial',
26
+ // instagram: 'agrosocial',
27
+ // twitter: 'https://www.agrosocial.com',
28
+ // appName: 'AgroSocial',
29
+ // },
30
+ // }
31
+ // export const getThemeFromEnv = (): Theme => {
32
+ // if (env.APP_NAME.toLowerCase() === 'agrosocial') {
33
+ // return Theme.Agrosocial
34
+ // }
35
+ // return Theme.Gealium
36
+ // }
37
+ var EmailCategory;
38
+ (function (EmailCategory) {
39
+ EmailCategory["SIMPLE"] = "SIMPLE";
40
+ EmailCategory["TEST_EMAIL"] = "TEST_EMAIL";
41
+ EmailCategory["EMAIL_VERIFICATION"] = "EMAIL_VERIFICATION";
42
+ EmailCategory["SEND_ONCE"] = "SEND_ONCE";
43
+ EmailCategory["OTP"] = "OTP";
44
+ EmailCategory["MEETING"] = "MEETING";
45
+ EmailCategory["ORGANIZATION_INVITATION"] = "ORGANIZATION_INVITATION";
46
+ EmailCategory["PDF_EXAM"] = "PDF_EXAM";
47
+ })(EmailCategory || (exports.EmailCategory = EmailCategory = {}));
48
+ exports.testEmailTemplate = zod_1.z.object({
49
+ to: zod_1.z.string(),
50
+ subject: zod_1.z.string(),
51
+ mjml: zod_1.z.string(),
52
+ });
53
+ var Layout;
54
+ (function (Layout) {
55
+ Layout["default"] = "layouts/default.ejs";
56
+ })(Layout || (exports.Layout = Layout = {}));
57
+ var Content;
58
+ (function (Content) {
59
+ Content["simple"] = "simple/simple.ejs";
60
+ Content["doubleAction"] = "doubleAction/doubleAction.ejs";
61
+ })(Content || (exports.Content = Content = {}));
62
+ //# sourceMappingURL=email.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.model.js","sourceRoot":"","sources":["../../../../src/server/services/email/email.model.ts"],"names":[],"mappings":";;;AAAA,6BAAuB;AAEvB,kCAAkC;AAClC,uBAAuB;AACvB,gFAAgF;AAChF,mDAAmD;AACnD,+BAA+B;AAC/B,kCAAkC;AAClC,kEAAkE;AAClE,kDAAkD;AAClD,2BAA2B;AAC3B,gCAAgC;AAChC,0CAA0C;AAC1C,0BAA0B;AAC1B,OAAO;AACP,0BAA0B;AAC1B,6FAA6F;AAC7F,mDAAmD;AACnD,+BAA+B;AAC/B,kCAAkC;AAClC,uEAAuE;AACvE,qDAAqD;AACrD,8BAA8B;AAC9B,+BAA+B;AAC/B,6CAA6C;AAC7C,6BAA6B;AAC7B,OAAO;AACP,IAAI;AAEJ,gDAAgD;AAChD,uDAAuD;AACvD,8BAA8B;AAC9B,MAAM;AAEN,yBAAyB;AACzB,IAAI;AAEJ,IAAY,aASX;AATD,WAAY,aAAa;IACvB,kCAAiB,CAAA;IACjB,0CAAyB,CAAA;IACzB,0DAAyC,CAAA;IACzC,wCAAuB,CAAA;IACvB,4BAAW,CAAA;IACX,oCAAmB,CAAA;IACnB,oEAAmD,CAAA;IACnD,sCAAqB,CAAA;AACvB,CAAC,EATW,aAAa,6BAAb,aAAa,QASxB;AAaY,QAAA,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACxC,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAA;AAWF,IAAY,MAEX;AAFD,WAAY,MAAM;IAChB,yCAA+B,CAAA;AACjC,CAAC,EAFW,MAAM,sBAAN,MAAM,QAEjB;AAED,IAAY,OAGX;AAHD,WAAY,OAAO;IACjB,uCAA4B,CAAA;IAC5B,yDAA8C,CAAA;AAChD,CAAC,EAHW,OAAO,uBAAP,OAAO,QAGlB"}
@@ -0,0 +1,23 @@
1
+ import type { SendGridEmailResponse } from '../sendgrid/sendgrid.model';
2
+ import type { EmailTest, SendEmailFromTemplateParams, Theme } from './email.model';
3
+ import { SendgridService } from '../sendgrid/sendgridApi.service';
4
+ export declare class EmailService {
5
+ private shouldSendEmail;
6
+ private baseDomain;
7
+ private fromName;
8
+ private emailTransport;
9
+ private emailArchive;
10
+ private theme;
11
+ constructor({ fromName, shouldSendEmail, baseDomain, emailTransport, emailArchive, theme, }: {
12
+ fromName: string;
13
+ shouldSendEmail: boolean;
14
+ baseDomain?: string;
15
+ emailTransport: SendgridService;
16
+ emailArchive?: string;
17
+ theme: Theme;
18
+ });
19
+ private compileTemplate;
20
+ private compileMjml;
21
+ sendEmailFromTemplate({ template, to, subject, attachments, archive, }: SendEmailFromTemplateParams): Promise<SendGridEmailResponse>;
22
+ sendEmailTemplateTest(email: EmailTest): Promise<SendGridEmailResponse>;
23
+ }
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EmailService = void 0;
4
+ const js_utils_1 = require("@goatlab/js-utils");
5
+ const ejs_1 = require("ejs");
6
+ const mjml_1 = require("mjml");
7
+ const consts_1 = require("../../consts");
8
+ const email_model_1 = require("./email.model");
9
+ class EmailService {
10
+ shouldSendEmail = true;
11
+ baseDomain = '@goatlab.com';
12
+ fromName = '';
13
+ emailTransport;
14
+ emailArchive;
15
+ theme;
16
+ constructor({ fromName, shouldSendEmail, baseDomain, emailTransport, emailArchive, theme, }) {
17
+ this.shouldSendEmail = shouldSendEmail;
18
+ this.fromName = fromName;
19
+ if (baseDomain) {
20
+ this.baseDomain = baseDomain;
21
+ }
22
+ this.emailTransport = emailTransport;
23
+ if (emailArchive?.length) {
24
+ this.emailArchive = emailArchive;
25
+ }
26
+ if (theme) {
27
+ this.theme = theme;
28
+ }
29
+ }
30
+ async compileTemplate(template) {
31
+ const innerContent = await (0, ejs_1.renderFile)(`${consts_1.config.templateDir}/${template.content}`, {
32
+ ...template.placeholders,
33
+ theme: this.theme,
34
+ });
35
+ const html = await (0, ejs_1.renderFile)(`${consts_1.config.templateDir}/${template.layout}`, {
36
+ ...template.placeholders,
37
+ theme: this.theme,
38
+ content: innerContent,
39
+ });
40
+ return html;
41
+ }
42
+ compileMjml(mjml) {
43
+ const compiledMjMl = (0, mjml_1.default)(mjml, {
44
+ keepComments: false,
45
+ });
46
+ if (compiledMjMl.errors.length) {
47
+ console.log(compiledMjMl.errors);
48
+ throw new Error('Template could not compile');
49
+ }
50
+ return compiledMjMl.html;
51
+ }
52
+ async sendEmailFromTemplate({ template, to, subject, attachments, archive, }) {
53
+ if (!this.shouldSendEmail) {
54
+ return {
55
+ isSuccess: true,
56
+ statusCode: 1,
57
+ body: 'Email not sent. No emails are sent in test mode',
58
+ headers: {},
59
+ };
60
+ }
61
+ const mjml = await this.compileTemplate(template);
62
+ const html = this.compileMjml(mjml);
63
+ const bcc = [];
64
+ if (archive && this.emailArchive?.length) {
65
+ bcc.push({
66
+ email: this.emailArchive,
67
+ });
68
+ }
69
+ // This will not work if we are running in other environments (AWS/AZURE) check before using any other env
70
+ const isRunningInGCP =
71
+ // Linux container
72
+ !!(process.platform === 'linux' &&
73
+ // Cloud run
74
+ (process.env.K_SERVICE ??
75
+ // Cloud run job
76
+ process.env.CLOUD_RUN_JOB));
77
+ // Avoid sending emails to real users in dev, test and local prod
78
+ // Prod emails will only go out from linux and (GCP or CIRCLECI)
79
+ const shouldSendEmailToRealUser = to.endsWith(`@${this.baseDomain}`) ||
80
+ (this.shouldSendEmail && isRunningInGCP);
81
+ // Exit if we are testing emails and TEST_EMAIL_ADDRESS is not set
82
+ if (!process.env.TEST_EMAIL_ADDRESS && !shouldSendEmailToRealUser) {
83
+ console.log('Email not sent. TEST_EMAIL_ADDRESS env variable is missing');
84
+ return {
85
+ isSuccess: false,
86
+ statusCode: 1,
87
+ body: 'Email not sent. TEST_EMAIL_ADDRESS env variable is missing',
88
+ headers: {},
89
+ };
90
+ }
91
+ const recipient = shouldSendEmailToRealUser
92
+ ? {
93
+ email: to,
94
+ }
95
+ : {
96
+ email: process.env.TEST_EMAIL_ADDRESS || '',
97
+ };
98
+ if (!this.emailTransport) {
99
+ throw new Error('No email transport (Sendgrid) defined');
100
+ }
101
+ return await this.emailTransport?.sendFinalizedEmail({
102
+ html,
103
+ fromEmail: `info@${this.baseDomain}`,
104
+ fromName: js_utils_1.Strings.capitalize(this.fromName),
105
+ subject,
106
+ replyTo: `no_reply@${this.baseDomain}`,
107
+ recipients: [recipient],
108
+ attachments,
109
+ categories: template.categories,
110
+ bcc,
111
+ });
112
+ }
113
+ async sendEmailTemplateTest(email) {
114
+ const html = this.compileMjml(email.mjml);
115
+ const [username, domain] = email.to.split('@');
116
+ // Emails will only go out to domain accounts
117
+ if (domain && domain !== this.baseDomain) {
118
+ throw new Error(`Cannot send emails to ${domain} accounts`);
119
+ }
120
+ if (!this.emailTransport) {
121
+ throw new Error('No email transport (Sendgrid) defined');
122
+ }
123
+ return await this.emailTransport?.sendFinalizedEmail({
124
+ html,
125
+ fromEmail: `info@${this.baseDomain}`,
126
+ fromName: js_utils_1.Strings.capitalize(this.fromName),
127
+ subject: email.subject,
128
+ replyTo: `no_reply@${this.baseDomain}`,
129
+ recipients: [
130
+ {
131
+ email: `${username}@${this.baseDomain}`,
132
+ },
133
+ ],
134
+ categories: [email_model_1.EmailCategory.TEST_EMAIL],
135
+ });
136
+ }
137
+ }
138
+ exports.EmailService = EmailService;
139
+ //# sourceMappingURL=email.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.service.js","sourceRoot":"","sources":["../../../../src/server/services/email/email.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface GCPServiceAccount {
2
+ [k: string]: any;
3
+ keyFilename: string;
4
+ project_id: string;
5
+ client_id: string;
6
+ client_email: string;
7
+ private_key: string;
8
+ private_key_id: string;
9
+ auth_uri: string;
10
+ type: string;
11
+ token_uri: string;
12
+ auth_provider_x509_cert_url: string;
13
+ client_x509_cert_url: string;
14
+ }
15
+ export declare function getGcpServiceAccountFromBase64(base64: string): undefined | GCPServiceAccount;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getGcpServiceAccountFromBase64 = getGcpServiceAccountFromBase64;
4
+ function getGcpServiceAccountFromBase64(base64) {
5
+ // Create Google credentials from Secret
6
+ const serviceAccount = JSON.parse(Buffer.from(base64, 'base64').toString('utf8'));
7
+ return serviceAccount;
8
+ }
9
+ //# sourceMappingURL=getGcpServiceAccountFromBase64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getGcpServiceAccountFromBase64.js","sourceRoot":"","sources":["../../../../src/server/services/gcp/getGcpServiceAccountFromBase64.ts"],"names":[],"mappings":";;AAeA,wEASC;AATD,SAAgB,8BAA8B,CAC5C,MAAc;IAEd,wCAAwC;IACxC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC/C,CAAA;IAED,OAAO,cAAmC,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,31 @@
1
+ export type SecretProvider = 'GCP' | 'FILE' | 'VAULT';
2
+ interface VaultConfig {
3
+ endpoint: string;
4
+ token?: string;
5
+ mount?: string;
6
+ namespace?: string;
7
+ }
8
+ export declare class SecretService<SecretType> {
9
+ provider: SecretProvider;
10
+ location: string;
11
+ encryptionKey: string;
12
+ vaultConfig?: VaultConfig;
13
+ constructor({ provider, location, encryptionKey, vaultConfig, }: {
14
+ provider: SecretProvider;
15
+ location: string;
16
+ encryptionKey: string;
17
+ vaultConfig?: VaultConfig;
18
+ });
19
+ loadSecretsFromFile(): SecretType;
20
+ loadSecretsFromGCP(): SecretType;
21
+ loadEncryptionKeyFromGCP(): string;
22
+ loadSecretsFromVault(): Promise<SecretType>;
23
+ storeSecretsToVault(secrets: Partial<SecretType>): Promise<void>;
24
+ loadSecrets(): SecretType | Promise<SecretType>;
25
+ loadEncryptionKey(): string;
26
+ getSecret(secretName: keyof SecretType): Promise<string>;
27
+ getSecretJson<T = any>(secretName: keyof SecretType): Promise<T>;
28
+ getSecretSync(secretName: keyof SecretType): string;
29
+ getSecretJsonSync<T = any>(secretName: keyof SecretType): T;
30
+ }
31
+ export {};
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SecretService = void 0;
4
+ const fs = require("fs");
5
+ const undici_1 = require("undici");
6
+ const node_utils_1 = require("@goatlab/node-utils");
7
+ const colors_1 = require("kleur/colors");
8
+ const memoryCache = {};
9
+ class SecretService {
10
+ provider;
11
+ location;
12
+ encryptionKey;
13
+ vaultConfig;
14
+ constructor({ provider, location, encryptionKey, vaultConfig, }) {
15
+ this.provider = provider;
16
+ this.location = location;
17
+ this.encryptionKey = encryptionKey;
18
+ this.vaultConfig = vaultConfig;
19
+ }
20
+ // We should cache this call
21
+ loadSecretsFromFile() {
22
+ if (memoryCache[this.location]) {
23
+ return memoryCache[this.location];
24
+ }
25
+ if (!fs.existsSync(this.location)) {
26
+ throw new Error(`Secret file "${this.location}" does not exist`);
27
+ }
28
+ const start = process.hrtime.bigint();
29
+ const fileContents = fs.readFileSync(this.location, 'utf-8');
30
+ const secretEncryptedObject = JSON.parse(fileContents);
31
+ console.log(`🔐 Secrets loaded: ${(0, colors_1.magenta)(this.location.split('/').slice(-2).join('/'))}`);
32
+ try {
33
+ const decripted = node_utils_1.Security.decryptObject(secretEncryptedObject, this.encryptionKey);
34
+ memoryCache[this.location] = decripted;
35
+ const durationMs = Number(process.hrtime.bigint() - start) / 1_000_000;
36
+ console.log(`⏱️ loadSecrets(${this.location}) took ${durationMs.toFixed(3)}ms`);
37
+ return memoryCache[this.location];
38
+ }
39
+ catch (err) {
40
+ console.error(err);
41
+ throw new Error(`loadSecrets failed to decrypt: ${this.location}`);
42
+ }
43
+ }
44
+ loadSecretsFromGCP() {
45
+ return {};
46
+ }
47
+ loadEncryptionKeyFromGCP() {
48
+ return '';
49
+ }
50
+ async loadSecretsFromVault() {
51
+ if (!this.vaultConfig) {
52
+ throw new Error('Vault configuration is required for VAULT provider');
53
+ }
54
+ const cacheKey = `vault_${this.vaultConfig.endpoint}_${this.location}`;
55
+ if (memoryCache[cacheKey]) {
56
+ return memoryCache[cacheKey];
57
+ }
58
+ const start = process.hrtime.bigint();
59
+ try {
60
+ const vaultUrl = `${this.vaultConfig.endpoint}/v1/${this.vaultConfig.mount || 'secret'}/data/${this.location}`;
61
+ const headers = {
62
+ 'Content-Type': 'application/json',
63
+ };
64
+ // Add token authentication
65
+ if (this.vaultConfig.token) {
66
+ headers['X-Vault-Token'] = this.vaultConfig.token;
67
+ }
68
+ // Add namespace if specified
69
+ if (this.vaultConfig.namespace) {
70
+ headers['X-Vault-Namespace'] = this.vaultConfig.namespace;
71
+ }
72
+ const response = await (0, undici_1.fetch)(vaultUrl, {
73
+ method: 'GET',
74
+ headers,
75
+ });
76
+ if (!response.ok) {
77
+ throw new Error(`Vault request failed: ${response.status} ${response.statusText}`);
78
+ }
79
+ const data = await response.json();
80
+ // Vault KV v2 stores data in data.data
81
+ const secrets = data.data?.data || data.data || {};
82
+ memoryCache[cacheKey] = secrets;
83
+ const durationMs = Number(process.hrtime.bigint() - start) / 1_000_000;
84
+ console.log(`🔐 Secrets loaded from Vault: ${(0, colors_1.magenta)(this.location)} (${durationMs.toFixed(3)}ms)`);
85
+ return secrets;
86
+ }
87
+ catch (error) {
88
+ console.error('Failed to load secrets from Vault:', error.message);
89
+ throw new Error(`loadSecretsFromVault failed: ${error.message}`);
90
+ }
91
+ }
92
+ async storeSecretsToVault(secrets) {
93
+ if (!this.vaultConfig) {
94
+ throw new Error('Vault configuration is required for VAULT provider');
95
+ }
96
+ try {
97
+ const vaultUrl = `${this.vaultConfig.endpoint}/v1/${this.vaultConfig.mount || 'secret'}/data/${this.location}`;
98
+ const headers = {
99
+ 'Content-Type': 'application/json',
100
+ };
101
+ // Add token authentication
102
+ if (this.vaultConfig.token) {
103
+ headers['X-Vault-Token'] = this.vaultConfig.token;
104
+ }
105
+ // Add namespace if specified
106
+ if (this.vaultConfig.namespace) {
107
+ headers['X-Vault-Namespace'] = this.vaultConfig.namespace;
108
+ }
109
+ // For Vault KV v2, data needs to be wrapped in a data object
110
+ const payload = {
111
+ data: secrets,
112
+ };
113
+ const response = await (0, undici_1.fetch)(vaultUrl, {
114
+ method: 'POST',
115
+ headers,
116
+ body: JSON.stringify(payload),
117
+ });
118
+ if (!response.ok) {
119
+ throw new Error(`Vault store request failed: ${response.status} ${response.statusText}`);
120
+ }
121
+ // Clear cache to force reload on next access
122
+ const cacheKey = `vault_${this.vaultConfig.endpoint}_${this.location}`;
123
+ delete memoryCache[cacheKey];
124
+ console.log(`🔐 Secrets stored to Vault: ${(0, colors_1.magenta)(this.location)}`);
125
+ }
126
+ catch (error) {
127
+ console.error('Failed to store secrets to Vault:', error.message);
128
+ throw new Error(`storeSecretsToVault failed: ${error.message}`);
129
+ }
130
+ }
131
+ loadSecrets() {
132
+ if (this.provider === 'GCP') {
133
+ return this.loadSecretsFromGCP();
134
+ }
135
+ if (this.provider === 'VAULT') {
136
+ return this.loadSecretsFromVault();
137
+ }
138
+ return this.loadSecretsFromFile();
139
+ }
140
+ loadEncryptionKey() {
141
+ return this.encryptionKey;
142
+ }
143
+ async getSecret(secretName) {
144
+ const secrets = await this.loadSecrets();
145
+ const secret = secrets[secretName];
146
+ if (!secret) {
147
+ throw new Error(`Secret ${secretName.toString()} does not exist in ${this.location} env`);
148
+ }
149
+ return secret;
150
+ }
151
+ async getSecretJson(secretName) {
152
+ const secretValue = await this.getSecret(secretName);
153
+ return JSON.parse(secretValue);
154
+ }
155
+ // Synchronous versions for backward compatibility (FILE provider only)
156
+ getSecretSync(secretName) {
157
+ if (this.provider === 'VAULT') {
158
+ throw new Error('Use async getSecret() method for Vault provider');
159
+ }
160
+ const secrets = this.loadSecrets();
161
+ const secret = secrets[secretName];
162
+ if (!secret) {
163
+ throw new Error(`Secret ${secretName.toString()} does not exist in ${this.location} env`);
164
+ }
165
+ return secret;
166
+ }
167
+ getSecretJsonSync(secretName) {
168
+ return JSON.parse(this.getSecretSync(secretName));
169
+ }
170
+ }
171
+ exports.SecretService = SecretService;
172
+ //# sourceMappingURL=secret.service.js.map