startx 0.0.1

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 (181) hide show
  1. package/.editorconfig +20 -0
  2. package/.prettierignore +24 -0
  3. package/.prettierrc.js +52 -0
  4. package/.vscode/settings.json +3 -0
  5. package/LICENSE +21 -0
  6. package/apps/core-server/.env.example +24 -0
  7. package/apps/core-server/Dockerfile +61 -0
  8. package/apps/core-server/eslint.config.mjs +47 -0
  9. package/apps/core-server/package.json +73 -0
  10. package/apps/core-server/src/config/custom-type.ts +54 -0
  11. package/apps/core-server/src/events/index.ts +37 -0
  12. package/apps/core-server/src/index.ts +19 -0
  13. package/apps/core-server/src/middlewares/auth-middleware.ts +50 -0
  14. package/apps/core-server/src/middlewares/cors-middleware.ts +6 -0
  15. package/apps/core-server/src/middlewares/error-middleware.ts +23 -0
  16. package/apps/core-server/src/middlewares/logger-middleware.ts +21 -0
  17. package/apps/core-server/src/middlewares/notfound-middleware.ts +14 -0
  18. package/apps/core-server/src/middlewares/serve-static.ts +24 -0
  19. package/apps/core-server/src/routes/files/router.ts +7 -0
  20. package/apps/core-server/src/routes/server.ts +36 -0
  21. package/apps/core-server/tsconfig.json +10 -0
  22. package/apps/core-server/tsdown.config.ts +14 -0
  23. package/biome.json +62 -0
  24. package/configs/eslint-config/package.json +60 -0
  25. package/configs/eslint-config/plugins.d.ts +1 -0
  26. package/configs/eslint-config/src/configs/base.ts +237 -0
  27. package/configs/eslint-config/src/configs/frontend.ts +62 -0
  28. package/configs/eslint-config/src/configs/node.ts +10 -0
  29. package/configs/eslint-config/src/plugin.ts +25 -0
  30. package/configs/eslint-config/src/rules/index.ts +30 -0
  31. package/configs/eslint-config/src/rules/no-argument-spread.test.ts +47 -0
  32. package/configs/eslint-config/src/rules/no-argument-spread.ts +96 -0
  33. package/configs/eslint-config/src/rules/no-dynamic-import-template.ts +32 -0
  34. package/configs/eslint-config/src/rules/no-internal-package-import.ts +40 -0
  35. package/configs/eslint-config/src/rules/no-interpolation-in-regular-string.ts +32 -0
  36. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.test.ts +34 -0
  37. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.ts +49 -0
  38. package/configs/eslint-config/src/rules/no-plain-errors.ts +50 -0
  39. package/configs/eslint-config/src/rules/no-skipped-tests.ts +61 -0
  40. package/configs/eslint-config/src/rules/no-top-level-relative-imports-in-backend-module.ts +27 -0
  41. package/configs/eslint-config/src/rules/no-type-unsafe-event-emitter.ts +33 -0
  42. package/configs/eslint-config/src/rules/no-uncaught-json-parse.test.ts +21 -0
  43. package/configs/eslint-config/src/rules/no-uncaught-json-parse.ts +45 -0
  44. package/configs/eslint-config/src/rules/no-untyped-config-class-field.ts +26 -0
  45. package/configs/eslint-config/src/rules/no-unused-param-catch-clause.ts +33 -0
  46. package/configs/eslint-config/src/rules/no-useless-catch-throw.test.ts +34 -0
  47. package/configs/eslint-config/src/rules/no-useless-catch-throw.ts +47 -0
  48. package/configs/eslint-config/src/utils/json.ts +21 -0
  49. package/configs/eslint-config/tsconfig.json +8 -0
  50. package/configs/eslint-config/tsdown.config.ts +11 -0
  51. package/configs/eslint-config/vitest.config.ts +3 -0
  52. package/configs/tsdown-config/package.json +14 -0
  53. package/configs/tsdown-config/src/config/tsdown.base.ts +13 -0
  54. package/configs/typescript-config/package.json +10 -0
  55. package/configs/typescript-config/tsconfig.common.json +32 -0
  56. package/configs/typescript-config/tsconfig.frontend.json +14 -0
  57. package/configs/typescript-config/tsconfig.node.json +9 -0
  58. package/configs/vitest-config/package.json +25 -0
  59. package/configs/vitest-config/src/base.ts +34 -0
  60. package/configs/vitest-config/src/frontend.ts +15 -0
  61. package/configs/vitest-config/src/node.ts +5 -0
  62. package/configs/vitest-config/tsconfig.json +7 -0
  63. package/package.json +47 -0
  64. package/packages/@repo/constants/eslint.config.mjs +21 -0
  65. package/packages/@repo/constants/package.json +19 -0
  66. package/packages/@repo/constants/src/api.ts +1 -0
  67. package/packages/@repo/constants/src/index.ts +8 -0
  68. package/packages/@repo/constants/src/time.ts +23 -0
  69. package/packages/@repo/constants/tsconfig.json +7 -0
  70. package/packages/@repo/db/eslint.config.mjs +21 -0
  71. package/packages/@repo/db/package.json +30 -0
  72. package/packages/@repo/db/src/functions.ts +122 -0
  73. package/packages/@repo/db/src/index.ts +20 -0
  74. package/packages/@repo/db/src/schema/common.ts +49 -0
  75. package/packages/@repo/db/src/schema/index.ts +1 -0
  76. package/packages/@repo/db/tsconfig.json +13 -0
  77. package/packages/@repo/lib/eslint.config.mjs +49 -0
  78. package/packages/@repo/lib/package.json +57 -0
  79. package/packages/@repo/lib/src/bucket-module/file-storage.ts +49 -0
  80. package/packages/@repo/lib/src/bucket-module/s3-storage.ts +114 -0
  81. package/packages/@repo/lib/src/bucket-module/utils.ts +11 -0
  82. package/packages/@repo/lib/src/command-module.ts +77 -0
  83. package/packages/@repo/lib/src/constants.ts +3 -0
  84. package/packages/@repo/lib/src/cookie-module.ts +42 -0
  85. package/packages/@repo/lib/src/custom-type.ts +54 -0
  86. package/packages/@repo/lib/src/env.ts +13 -0
  87. package/packages/@repo/lib/src/error-handlers-module/index.ts +11 -0
  88. package/packages/@repo/lib/src/file-system/index.ts +90 -0
  89. package/packages/@repo/lib/src/hashing-module.ts +9 -0
  90. package/packages/@repo/lib/src/index.ts +27 -0
  91. package/packages/@repo/lib/src/logger-module/log-config.ts +16 -0
  92. package/packages/@repo/lib/src/logger-module/logger.ts +78 -0
  93. package/packages/@repo/lib/src/logger-module/memory-profiler.ts +65 -0
  94. package/packages/@repo/lib/src/mail-module/api.ts +0 -0
  95. package/packages/@repo/lib/src/mail-module/mock.ts +8 -0
  96. package/packages/@repo/lib/src/mail-module/nodemailer.ts +45 -0
  97. package/packages/@repo/lib/src/notification-module/index.ts +172 -0
  98. package/packages/@repo/lib/src/notification-module/push-notification.ts +90 -0
  99. package/packages/@repo/lib/src/oauth2-client.ts +109 -0
  100. package/packages/@repo/lib/src/otp-module.ts +98 -0
  101. package/packages/@repo/lib/src/pagination-module.ts +49 -0
  102. package/packages/@repo/lib/src/token-module.ts +35 -0
  103. package/packages/@repo/lib/src/user-session.ts +117 -0
  104. package/packages/@repo/lib/src/utils.ts +42 -0
  105. package/packages/@repo/lib/src/validation-module.ts +187 -0
  106. package/packages/@repo/lib/tsconfig.json +7 -0
  107. package/packages/@repo/mail/package.json +29 -0
  108. package/packages/@repo/mail/src/emails/admin/OtpEmail.tsx +168 -0
  109. package/packages/@repo/mail/src/index.ts +13 -0
  110. package/packages/@repo/mail/tsconfig.build.json +14 -0
  111. package/packages/@repo/mail/tsconfig.json +13 -0
  112. package/packages/@repo/mail/tsdown.config.ts +9 -0
  113. package/packages/@repo/redis/eslint.config.mjs +8 -0
  114. package/packages/@repo/redis/package.json +31 -0
  115. package/packages/@repo/redis/src/index.ts +2 -0
  116. package/packages/@repo/redis/src/lib/redis-client.ts +23 -0
  117. package/packages/@repo/redis/src/lib/redis-module.ts +3 -0
  118. package/packages/@repo/redis/tsconfig.json +12 -0
  119. package/packages/ui/components.json +17 -0
  120. package/packages/ui/eslint.config.mjs +18 -0
  121. package/packages/ui/package.json +67 -0
  122. package/packages/ui/postcss.config.mjs +9 -0
  123. package/packages/ui/src/components/custom/form-wrapper.tsx +551 -0
  124. package/packages/ui/src/components/custom/grid-component.tsx +23 -0
  125. package/packages/ui/src/components/custom/hover-tool.tsx +38 -0
  126. package/packages/ui/src/components/custom/image-picker.tsx +109 -0
  127. package/packages/ui/src/components/custom/no-content.tsx +37 -0
  128. package/packages/ui/src/components/custom/page-container.tsx +24 -0
  129. package/packages/ui/src/components/custom/page-section.tsx +59 -0
  130. package/packages/ui/src/components/custom/simple-popover.tsx +29 -0
  131. package/packages/ui/src/components/custom/switch-component.tsx +20 -0
  132. package/packages/ui/src/components/custom/theme-provider.tsx +74 -0
  133. package/packages/ui/src/components/custom/typography.tsx +111 -0
  134. package/packages/ui/src/components/extensions/carousel.tsx +392 -0
  135. package/packages/ui/src/components/hooks/event/use-click.tsx +39 -0
  136. package/packages/ui/src/components/hooks/time/useDebounce.tsx +21 -0
  137. package/packages/ui/src/components/hooks/time/useInterval.tsx +35 -0
  138. package/packages/ui/src/components/hooks/time/useTimeout.tsx +19 -0
  139. package/packages/ui/src/components/hooks/time/useTimer.tsx +51 -0
  140. package/packages/ui/src/components/hooks/use-media-query.tsx +19 -0
  141. package/packages/ui/src/components/hooks/use-persistent-storage.tsx +52 -0
  142. package/packages/ui/src/components/hooks/use-update-effect.tsx +13 -0
  143. package/packages/ui/src/components/hooks/use-window-dimension.tsx +30 -0
  144. package/packages/ui/src/components/lib/utils.ts +242 -0
  145. package/packages/ui/src/components/lucide.tsx +3 -0
  146. package/packages/ui/src/components/sonner.tsx +1 -0
  147. package/packages/ui/src/components/ui/alert-dialog.tsx +116 -0
  148. package/packages/ui/src/components/ui/avatar.tsx +53 -0
  149. package/packages/ui/src/components/ui/badge.tsx +46 -0
  150. package/packages/ui/src/components/ui/breadcrumb.tsx +109 -0
  151. package/packages/ui/src/components/ui/button.tsx +96 -0
  152. package/packages/ui/src/components/ui/card.tsx +92 -0
  153. package/packages/ui/src/components/ui/carousel.tsx +243 -0
  154. package/packages/ui/src/components/ui/checkbox.tsx +32 -0
  155. package/packages/ui/src/components/ui/command.tsx +155 -0
  156. package/packages/ui/src/components/ui/dialog.tsx +127 -0
  157. package/packages/ui/src/components/ui/dropdown-menu.tsx +226 -0
  158. package/packages/ui/src/components/ui/form.tsx +165 -0
  159. package/packages/ui/src/components/ui/input-otp.tsx +76 -0
  160. package/packages/ui/src/components/ui/input.tsx +21 -0
  161. package/packages/ui/src/components/ui/label.tsx +24 -0
  162. package/packages/ui/src/components/ui/multiple-select.tsx +510 -0
  163. package/packages/ui/src/components/ui/popover.tsx +42 -0
  164. package/packages/ui/src/components/ui/select.tsx +170 -0
  165. package/packages/ui/src/components/ui/separator.tsx +28 -0
  166. package/packages/ui/src/components/ui/sheet.tsx +130 -0
  167. package/packages/ui/src/components/ui/skeleton.tsx +13 -0
  168. package/packages/ui/src/components/ui/spinner.tsx +16 -0
  169. package/packages/ui/src/components/ui/switch.tsx +28 -0
  170. package/packages/ui/src/components/ui/table.tsx +116 -0
  171. package/packages/ui/src/components/ui/tabs.tsx +54 -0
  172. package/packages/ui/src/components/ui/textarea.tsx +18 -0
  173. package/packages/ui/src/components/ui/timeline.tsx +118 -0
  174. package/packages/ui/src/components/ui/tooltip.tsx +30 -0
  175. package/packages/ui/src/components/util/n-formattor.ts +22 -0
  176. package/packages/ui/src/components/util/storage.ts +37 -0
  177. package/packages/ui/src/globals.css +87 -0
  178. package/packages/ui/tailwind.config.ts +94 -0
  179. package/packages/ui/tsconfig.json +12 -0
  180. package/pnpm-workspace.yaml +43 -0
  181. package/turbo.json +77 -0
@@ -0,0 +1,42 @@
1
+ import crypto from "crypto";
2
+ import path from "path";
3
+
4
+ export function __dirname() {
5
+ if (!process.env.NODE_ENV || process.env.NODE_ENV === "development") {
6
+ return path.resolve(process.cwd(), "../../");
7
+ }
8
+ return process.cwd();
9
+ }
10
+
11
+ /**
12
+ * @description Utility class for generating random strings and numbers
13
+ */
14
+ export class Random {
15
+ /**
16
+ * @description Generate a random UUID
17
+ */
18
+ static generateUUID() {
19
+ return crypto.randomUUID();
20
+ }
21
+
22
+ /**
23
+ * @description Generate a random string
24
+ * @param length
25
+ * @param encoding (default: 'hex')
26
+ */
27
+ static generateString(length: number, encoding: BufferEncoding = "hex") {
28
+ return crypto.randomBytes(length).toString(encoding);
29
+ }
30
+
31
+ /**
32
+ * @description Generate a random number
33
+ * @param digits (default: 6)
34
+ */
35
+ static generateNumber(digits: number = 6) {
36
+ return crypto.randomInt(10 ** (digits - 1), 10 ** digits);
37
+ }
38
+
39
+ static generateBoolean() {
40
+ return crypto.randomInt(0, 2) === 1;
41
+ }
42
+ }
@@ -0,0 +1,187 @@
1
+ import vine from "@vinejs/vine";
2
+ import type { Infer, SchemaTypes } from "@vinejs/vine/types";
3
+ import type { NextFunction, Request, Response } from "express";
4
+
5
+ import { logger } from "./logger-module/logger";
6
+
7
+ export async function validateBody<T extends SchemaTypes>(
8
+ schema: T,
9
+ validate: any,
10
+ ): Promise<{
11
+ data?: Infer<T>;
12
+ error: string[];
13
+ }> {
14
+ try {
15
+ const validator = vine.compile(schema as any);
16
+ const payload = (await validator.validate(validate)) as Infer<T>;
17
+ return { data: payload, error: [] };
18
+ } catch (error: any) {
19
+ return {
20
+ error: error.messages.map((e: any) => {
21
+ return e.message;
22
+ }) as string[],
23
+ };
24
+ }
25
+ }
26
+
27
+ export function bodyValidator<T extends SchemaTypes>(schema: T) {
28
+ return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
29
+ const originalMethod = descriptor.value;
30
+
31
+ descriptor.value = async function (
32
+ req: Request<unknown, unknown, Infer<T>>,
33
+ res: Response,
34
+ next: NextFunction,
35
+ ) {
36
+ const { error, data } = await validateBody(schema, req.body);
37
+ logger.info(`Body: ${JSON.stringify(req.body, null, 2)} `, {
38
+ logType: "requestBody",
39
+ });
40
+ if (!data || error.length > 0) {
41
+ logger.error(error.join("\n"), { logType: "validationErrors" });
42
+ return res.status(422).json({ message: error.join("\n") });
43
+ }
44
+
45
+ req.body = data; // Make req.body type-safe
46
+ return originalMethod.apply(this, [req, res, next]);
47
+ };
48
+
49
+ return descriptor;
50
+ };
51
+ }
52
+ export function paramsValidator(schema: SchemaTypes) {
53
+ return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
54
+ const originalMethod = descriptor.value;
55
+
56
+ descriptor.value = async function (req: Request, res: Response, next: NextFunction) {
57
+ const { error, data } = await validateBody(schema, req.params);
58
+ if (!data || error.length > 0) {
59
+ logger.error(error.join("\n"), { logType: "validationErrors" });
60
+ return res.status(422).json({ message: error.join("\n") });
61
+ }
62
+ req.params = data; // Make req.body type-safe
63
+ return originalMethod.apply(this, [req, res, next]);
64
+ };
65
+
66
+ return descriptor;
67
+ };
68
+ }
69
+
70
+ export function queryValidator(schema: SchemaTypes) {
71
+ return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
72
+ const originalMethod = descriptor.value;
73
+
74
+ descriptor.value = async function (req: Request, res: Response, next: NextFunction) {
75
+ const { error, data } = await validateBody(schema, req.query);
76
+ if (!data || error.length > 0) {
77
+ logger.error(error.join("\n"), { logType: "validationErrors" });
78
+ return res.status(422).json({ message: error.join("\n") });
79
+ }
80
+ req.query = data; // Make req.body type-safe
81
+ return originalMethod.apply(this, [req, res, next]);
82
+ };
83
+
84
+ return descriptor;
85
+ };
86
+ }
87
+
88
+ // export function authValidator({ optional = false }: { optional?: boolean } | undefined = {}) {
89
+ // return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
90
+ // const originalMethod = descriptor.value;
91
+ // descriptor.value = async function (req: Request, res: Response, next: NextFunction) {
92
+ // try {
93
+ // const accessToken = req.headers["authorization"]?.split(" ")[1];
94
+ // if (optional && (!accessToken || !TokenModule.verifyAccessToken(accessToken))) {
95
+ // return originalMethod.apply(this, [req, res, next]);
96
+ // }
97
+ // if (!accessToken) {
98
+ // res.status(401).json({ message: "access token missing" });
99
+ // return;
100
+ // }
101
+ // const payload = TokenModule.verifyAccessToken(accessToken);
102
+
103
+ // if (!payload) {
104
+ // res.status(401).json({ message: "invalid access token" });
105
+ // return;
106
+ // }
107
+ // req.user = {
108
+ // id: payload.userID,
109
+ // email: payload.email
110
+ // };
111
+ // return originalMethod.apply(this, [req, res, next]);
112
+ // } catch (error) {
113
+ // next(error);
114
+ // }
115
+ // };
116
+ // };
117
+ // }
118
+
119
+ export function mediaBodyValidator(schema: SchemaTypes, optional = false) {
120
+ return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
121
+ const originalMethod = descriptor.value;
122
+
123
+ descriptor.value = async function (req: Request, res: Response, next: NextFunction) {
124
+ const files = req.files;
125
+ if (!files && !optional) {
126
+ // throw new ErrorResponse("Add at least one file", 422);
127
+ logger.error("Add at least one file", { logType: "validationErrors" });
128
+ return res.status(422).json({ message: "Add at least one file" });
129
+ }
130
+
131
+ const isJSON = (str: any) => {
132
+ try {
133
+ const value = JSON.parse(str as string);
134
+
135
+ if (typeof value === "object" || value === null || typeof value === "boolean") {
136
+ return value;
137
+ }
138
+ return str;
139
+ } catch (e) {
140
+ console.log(e)
141
+ return str;
142
+ }
143
+ };
144
+
145
+ const parseData = Object.entries(req.body as object).map(([key, value]) => {
146
+ return [key, isJSON(value)];
147
+ });
148
+
149
+ const parsedData = Object.fromEntries(parseData);
150
+ logger.info(`Body: ${JSON.stringify(parsedData, null, 2)} `, {
151
+ logType: "requestBody",
152
+ });
153
+ const { error, data } = await validateBody(schema, parsedData);
154
+
155
+ if (!data || error.length > 0) {
156
+ logger.error(error.join("\n"), { logType: "validationErrors" });
157
+ return res.status(422).json({ message: error.join("\n") });
158
+ }
159
+ req.body = data;
160
+ req.files = files;
161
+ return originalMethod.apply(this, [req, res, next]);
162
+ };
163
+
164
+ return descriptor;
165
+ };
166
+ }
167
+
168
+ export const validateId = vine.object({
169
+ id: vine.string().uuid(),
170
+ });
171
+
172
+ export const paginationValidator = vine.object({
173
+ page: vine
174
+ .number()
175
+ .positive()
176
+ .parse((e: any) => (!e ? 1 : e))
177
+ .optional(),
178
+ limit: vine
179
+ .number()
180
+ .positive()
181
+ .parse((e: any) => (!e ? 10 : e))
182
+ .optional(),
183
+ query: vine
184
+ .string()
185
+ .parse((e: any) => (!e ? "" : e))
186
+ .optional(),
187
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "typescript-config/tsconfig.node.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "./src"
5
+ },
6
+ "include": ["src/**/*.ts"]
7
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@repo/email",
3
+ "type": "module",
4
+ "version": "1.0.0",
5
+ "description": "",
6
+ "scripts": {
7
+ "dev": "email dev --port 3014 --dir ./src"
8
+ },
9
+ "exports": "./src/index.ts",
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "devDependencies": {
14
+ "@react-email/preview-server": "catalog:",
15
+ "@types/react": "catalog:",
16
+ "@types/react-dom": "catalog:",
17
+ "react-email": "catalog:",
18
+ "tsdown-config": "workspace:*"
19
+ },
20
+ "dependencies": {
21
+ "@react-email/components": "catalog:",
22
+ "@react-email/render": "catalog:",
23
+ "@react-email/tailwind": "catalog:",
24
+ "eslint-config": "workspace:*",
25
+ "react": "catalog:",
26
+ "react-dom": "catalog:",
27
+ "typescript-config": "workspace:*"
28
+ }
29
+ }
@@ -0,0 +1,168 @@
1
+ import {
2
+ Body,
3
+ Container,
4
+ Font,
5
+ Head,
6
+ Heading,
7
+ Hr,
8
+ Html,
9
+ Img,
10
+ Link,
11
+ Preview,
12
+ Section,
13
+ Text,
14
+ } from "@react-email/components";
15
+
16
+ export default function VerifyEmailOtp({
17
+ verificationCode = "596853",
18
+ }: {
19
+ verificationCode: string;
20
+ }) {
21
+ return (
22
+ <Html>
23
+ <Head>
24
+ <Font
25
+ fontFamily="Public Sans"
26
+ fallbackFontFamily="Helvetica"
27
+ webFont={{
28
+ url: "https://fonts.googleapis.com/css2?family=Public+Sans:wght@400;500;600&display=swap",
29
+ format: "woff2",
30
+ }}
31
+ fontWeight={400}
32
+ fontStyle="normal"
33
+ />
34
+ </Head>{" "}
35
+ <Body style={main}>
36
+ <Preview>App verification</Preview>
37
+ <Container style={container}>
38
+ <Section style={coverSection}>
39
+ <Section style={{ paddingInline: "35px", paddingTop: "12px" }}>
40
+ <Img
41
+ src={`${"https://app.com"}/logo/app-logo.png`}
42
+ alt="App"
43
+ // width="64"
44
+ height="24px"
45
+ />
46
+ </Section>
47
+ <Section style={upperSection}>
48
+ <Heading style={h1}>Verify your email address</Heading>
49
+ <Text style={mainText}>Your One-Time Password (OTP) for logging into App is:</Text>
50
+ <Section style={verificationSection}>
51
+ <Text style={verifyText}>Verification code</Text>
52
+
53
+ <Text style={codeText}>{verificationCode}</Text>
54
+ </Section>
55
+ </Section>
56
+ <Hr />
57
+ <Section style={lowerSection}>
58
+ <Text style={cautionText}>
59
+ This OTP is valid for 10 minutes. Please do not share this code with anyone for
60
+ security reasons. If you did not request this, please ignore this email or contact
61
+ our support team immediately.
62
+ </Text>
63
+ </Section>
64
+ </Section>
65
+ <Text style={footerText}>
66
+ This message was produced and distributed by App, Ltd.{" "}
67
+ <Link href="https://app.com" target="_blank" style={link}>
68
+ App.com
69
+ </Link>
70
+ <br />
71
+ View our{" "}
72
+ <Link href="https://app.com/privacy-policy" target="_blank" style={link}>
73
+ privacy policy
74
+ </Link>
75
+ .
76
+ </Text>
77
+ </Container>
78
+ </Body>
79
+ </Html>
80
+ );
81
+ }
82
+
83
+ const main = {
84
+ backgroundColor: "#fff",
85
+ color: "#212121",
86
+ };
87
+
88
+ const container = {
89
+ padding: "20px",
90
+ margin: "0 auto",
91
+ backgroundColor: "#eee",
92
+ };
93
+
94
+ const h1 = {
95
+ color: "#333",
96
+ fontFamily:
97
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
98
+ fontSize: "20px",
99
+ fontWeight: "bold",
100
+ marginBottom: "15px",
101
+ };
102
+
103
+ const link = {
104
+ color: "#2754C5",
105
+ fontFamily:
106
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
107
+ fontSize: "14px",
108
+ textDecoration: "underline",
109
+ };
110
+
111
+ const text = {
112
+ color: "#333",
113
+ fontFamily:
114
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
115
+ fontSize: "14px",
116
+ margin: "24px 0",
117
+ };
118
+
119
+ const imageSection = {
120
+ backgroundColor: "#fff",
121
+ display: "flex",
122
+ padding: "20px 0",
123
+ alignItems: "center",
124
+ justifyContent: "center",
125
+ };
126
+
127
+ const coverSection = { backgroundColor: "#fff" };
128
+
129
+ const upperSection = { padding: "12px 35px" };
130
+
131
+ const lowerSection = { padding: "25px 35px" };
132
+
133
+ const footerText = {
134
+ ...text,
135
+ fontSize: "12px",
136
+ padding: "0 20px",
137
+ };
138
+
139
+ const verifyText = {
140
+ ...text,
141
+ margin: 0,
142
+ fontWeight: "bold",
143
+ textAlign: "center" as const,
144
+ };
145
+
146
+ const codeText = {
147
+ ...text,
148
+ fontWeight: "bold",
149
+ fontSize: "36px",
150
+ margin: "10px 0",
151
+ textAlign: "center" as const,
152
+ };
153
+
154
+ const validityText = {
155
+ ...text,
156
+ margin: "0px",
157
+ textAlign: "center" as const,
158
+ };
159
+
160
+ const verificationSection = {
161
+ display: "flex",
162
+ alignItems: "center",
163
+ justifyContent: "center",
164
+ };
165
+
166
+ const mainText = { ...text, marginBottom: "14px" };
167
+
168
+ const cautionText = { ...text, margin: "0px" };
@@ -0,0 +1,13 @@
1
+ import { render } from "@react-email/render";
2
+
3
+ import VerifyEmailOtp from "./emails/admin/OtpEmail.js";
4
+
5
+ export class AdminEmailTemplate {
6
+ static getOtpEmail = async (props: { otp: string }) => {
7
+ return await render(
8
+ VerifyEmailOtp({
9
+ verificationCode: props.otp,
10
+ }),
11
+ );
12
+ };
13
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": ["./tsconfig.json", "typescript-config/tsconfig.build.json"],
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "rootDir": ".",
6
+ "outDir": "dist",
7
+ "jsx": "react-jsx",
8
+ "tsBuildInfoFile": "dist/build.tsbuildinfo",
9
+ "declaration": true,
10
+ "preserveSymlinks": false
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["src/**/__tests__/**"]
14
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "typescript-config/tsconfig.common.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "types": ["node"],
6
+ "baseUrl": "src",
7
+ "jsx": "react-jsx",
8
+ "tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
9
+ "experimentalDecorators": true,
10
+ "emitDecoratorMetadata": true
11
+ },
12
+ "include": ["src/**/*.ts"]
13
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "tsdown";
2
+ import { baseConfig } from "tsdown-config";
3
+
4
+ export default defineConfig({
5
+ ...baseConfig,
6
+ entry: [
7
+ "./src/**/*.ts",
8
+ ],
9
+ });
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "eslint/config";
2
+ import { baseConfig } from "eslint-config/base";
3
+
4
+ export default defineConfig(baseConfig, {
5
+ rules: {
6
+ "unicorn/filename-case": ["error", { case: "kebabCase" }],
7
+ },
8
+ });
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@repo/redis",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "clean": "rimraf dist .turbo",
7
+ "watch:dev": "pnpm watch",
8
+ "typecheck": "tsc --noEmit",
9
+ "format": "biome format --write .",
10
+ "format:check": "biome ci .",
11
+ "lint": "eslint .",
12
+ "lint:fix": "eslint . --fix",
13
+ "watch": "tsc -p tsconfig.build.json --watch"
14
+ },
15
+ "exports": "./src/index.ts",
16
+ "devDependencies": {
17
+ "eslint-config": "workspace:*",
18
+ "typescript-config": "workspace:*",
19
+ "@types/eslint": "^8.56.5",
20
+ "@types/node": "^20.16.5",
21
+ "@types/pg": "^8.11.10",
22
+ "eslint": "catalog:",
23
+ "tsc-alias": "^1.8.10",
24
+ "typescript": "5.5.4"
25
+ },
26
+ "dependencies": {
27
+ "drizzle-orm": "^0.36.0",
28
+ "ioredis": "^5.4.1",
29
+ "pg": "^8.13.1"
30
+ }
31
+ }
@@ -0,0 +1,2 @@
1
+ export * from "ioredis";
2
+ export * from "./lib/redis-client.js";
@@ -0,0 +1,23 @@
1
+ import { Redis } from "ioredis";
2
+
3
+ export const redisClient = new Redis({
4
+ host: process.env.REDIS_HOST,
5
+ port: Number(process.env.REDIS_PORT),
6
+ username: process.env.REDIS_USERNAME,
7
+ password: process.env.REDIS_PASSWORD,
8
+ });
9
+
10
+ function setEventListeners() {
11
+ redisClient.on("error", (error: string) => {
12
+ console.log("Could not establish a connection with redis. " + error);
13
+ });
14
+ redisClient.on("connect", (error: string) => {
15
+ if (error) {
16
+ console.log("Could not establish a connection with redis. " + error);
17
+ }
18
+ console.log("Connected to redis successfully");
19
+ });
20
+ }
21
+
22
+ setEventListeners();
23
+
@@ -0,0 +1,3 @@
1
+ export class RedisModule {
2
+ //
3
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "typescript-config/tsconfig.common.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "types": ["node"],
6
+ "baseUrl": "src",
7
+ "tsBuildInfoFile": "dist/typecheck.tsbuildinfo",
8
+ "experimentalDecorators": true,
9
+ "emitDecoratorMetadata": true
10
+ },
11
+ "include": ["src/**/*.ts"]
12
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "default",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.ts",
8
+ "css": "src/globals.css",
9
+ "baseColor": "zinc",
10
+ "cssVariables": true
11
+ },
12
+ "aliases": {
13
+ "components": "@/components",
14
+
15
+ "utils": "@/lib/utils"
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from "eslint/config";
2
+ import { frontendConfig } from "eslint-config/frontend";
3
+
4
+ export default defineConfig(frontendConfig, {
5
+ rules: {
6
+ "no-empty": "warn",
7
+ "@typescript-eslint/require-await": "warn",
8
+ "@typescript-eslint/no-empty-object-type": "warn",
9
+ "@typescript-eslint/naming-convention": "warn",
10
+ "@typescript-eslint/no-unsafe-function-type": "warn",
11
+ "@typescript-eslint/no-unsafe-call": "warn",
12
+ "@typescript-eslint/no-unsafe-member-access": "warn",
13
+ "@typescript-eslint/no-unsafe-return": "warn",
14
+ "@typescript-eslint/no-unsafe-assignment": "warn",
15
+ "@typescript-eslint/no-unused-vars": "warn",
16
+ "import-x/default": "off",
17
+ },
18
+ });
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@repo/ui",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "clean": "rimraf dist .turbo",
7
+ "watch:dev": "pnpm watch",
8
+ "typecheck": "tsc --noEmit",
9
+ "format": "biome format --write .",
10
+ "format:check": "biome ci .",
11
+ "lint": "eslint .",
12
+ "lint:fix": "eslint . --fix",
13
+ "watch": "tsc -p tsconfig.build.json --watch"
14
+ },
15
+ "peerDependencies": {
16
+ "react": "^19.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "catalog:",
20
+ "@types/react": "catalog:",
21
+ "autoprefixer": "^10",
22
+ "eslint-config": "workspace:*",
23
+ "postcss": "^8.4.49",
24
+ "postcss-load-config": "^6",
25
+ "tailwindcss": "catalog:",
26
+ "typescript": "catalog:",
27
+ "typescript-config": "workspace:*",
28
+ "vite": "catalog:"
29
+ },
30
+ "dependencies": {
31
+ "@hookform/resolvers": "^3.9.1",
32
+ "@radix-ui/react-alert-dialog": "^1.1.15",
33
+ "@radix-ui/react-avatar": "^1.1.1",
34
+ "@radix-ui/react-checkbox": "^1.1.2",
35
+ "@radix-ui/react-dialog": "^1.1.15",
36
+ "@radix-ui/react-dropdown-menu": "^2.1.2",
37
+ "@radix-ui/react-label": "^2.1.0",
38
+ "@radix-ui/react-popover": "^1.1.2",
39
+ "@radix-ui/react-select": "^2.1.2",
40
+ "@radix-ui/react-separator": "^1.1.0",
41
+ "@radix-ui/react-slot": "^1.2.3",
42
+ "@radix-ui/react-switch": "^1.1.1",
43
+ "@radix-ui/react-tabs": "^1.1.1",
44
+ "@radix-ui/react-tooltip": "^1.1.3",
45
+ "@tailwindcss/postcss": "^4",
46
+ "class-variance-authority": "^0.7.0",
47
+ "clsx": "^2.1.1",
48
+ "cmdk": "^1.1.1",
49
+ "date-fns": "^4.1.0",
50
+ "embla-carousel": "^8.5.2",
51
+ "embla-carousel-react": "^8.5.2",
52
+ "input-otp": "^1.4.1",
53
+ "lucide-react": "catalog:",
54
+ "react-hook-form": "^7.53.1",
55
+ "react-icons": "^5.5.0",
56
+ "sonner": "^1.7.0",
57
+ "tailwind-merge": "^2.3.0",
58
+ "tailwindcss-animate": "^1.0.7",
59
+ "zod": "^3.23.8"
60
+ },
61
+ "exports": {
62
+ "./globals.css": "./src/globals.css",
63
+ "./postcss.config": "./postcss.config.mjs",
64
+ "./tailwind.config": "./tailwind.config.ts",
65
+ "./components/*": "./src/components/*"
66
+ }
67
+ }