@xenterprises/fastify-xconfig 0.0.10 → 1.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 (99) hide show
  1. package/.github/workflows/ci.yml +19 -0
  2. package/.taprc +3 -0
  3. package/README.md +18 -134
  4. package/index.d.ts +13 -0
  5. package/index.js +9 -0
  6. package/package.json +33 -39
  7. package/test/index.test-d.ts +13 -0
  8. package/test/index.test.js +14 -0
  9. package/test/xConfig.js +115 -0
  10. package/tsconfig.json +9 -0
  11. package/dist/integrations/cloudinary.d.ts +0 -1
  12. package/dist/integrations/cloudinary.js +0 -25
  13. package/dist/integrations/cloudinary.js.map +0 -1
  14. package/dist/integrations/prisma.d.ts +0 -1
  15. package/dist/integrations/prisma.js +0 -13
  16. package/dist/integrations/prisma.js.map +0 -1
  17. package/dist/integrations/sendgrid.d.ts +0 -1
  18. package/dist/integrations/sendgrid.js +0 -22
  19. package/dist/integrations/sendgrid.js.map +0 -1
  20. package/dist/integrations/stripe.d.ts +0 -1
  21. package/dist/integrations/stripe.js +0 -15
  22. package/dist/integrations/stripe.js.map +0 -1
  23. package/dist/integrations/twilio.d.ts +0 -1
  24. package/dist/integrations/twilio.js +0 -17
  25. package/dist/integrations/twilio.js.map +0 -1
  26. package/dist/middleware/bugsnag.d.ts +0 -2
  27. package/dist/middleware/bugsnag.js +0 -9
  28. package/dist/middleware/bugsnag.js.map +0 -1
  29. package/dist/middleware/cors.d.ts +0 -2
  30. package/dist/middleware/cors.js +0 -11
  31. package/dist/middleware/cors.js.map +0 -1
  32. package/dist/middleware/errorHandler.d.ts +0 -2
  33. package/dist/middleware/errorHandler.js +0 -19
  34. package/dist/middleware/errorHandler.js.map +0 -1
  35. package/dist/middleware/multipart.d.ts +0 -2
  36. package/dist/middleware/multipart.js +0 -7
  37. package/dist/middleware/multipart.js.map +0 -1
  38. package/dist/middleware/rateLimit.d.ts +0 -2
  39. package/dist/middleware/rateLimit.js +0 -7
  40. package/dist/middleware/rateLimit.js.map +0 -1
  41. package/dist/middleware/underPressure.d.ts +0 -2
  42. package/dist/middleware/underPressure.js +0 -7
  43. package/dist/middleware/underPressure.js.map +0 -1
  44. package/dist/utils/colorize.d.ts +0 -4
  45. package/dist/utils/colorize.js +0 -33
  46. package/dist/utils/colorize.js.map +0 -1
  47. package/dist/utils/formatBytes.d.ts +0 -1
  48. package/dist/utils/formatBytes.js +0 -10
  49. package/dist/utils/formatBytes.js.map +0 -1
  50. package/dist/utils/randomUUID.d.ts +0 -1
  51. package/dist/utils/randomUUID.js +0 -3
  52. package/dist/utils/randomUUID.js.map +0 -1
  53. package/dist/utils/statAsync.d.ts +0 -2
  54. package/dist/utils/statAsync.js +0 -4
  55. package/dist/utils/statAsync.js.map +0 -1
  56. package/dist/xConfig.d.ts +0 -3
  57. package/dist/xConfig.js +0 -9
  58. package/dist/xConfig.js.map +0 -1
  59. package/server/app.js +0 -92
  60. package/src/auth/admin.js +0 -241
  61. package/src/auth/portal.js +0 -286
  62. package/src/integrations/cloudinary.js +0 -98
  63. package/src/integrations/geocode.js +0 -43
  64. package/src/integrations/prisma.js +0 -30
  65. package/src/integrations/sendgrid.js +0 -58
  66. package/src/integrations/twilio.js +0 -146
  67. package/src/lifecycle/xFastifyAfter.js +0 -27
  68. package/src/middleware/bugsnag.js +0 -10
  69. package/src/middleware/cors.js +0 -10
  70. package/src/middleware/fancyErrors.js +0 -26
  71. package/src/middleware/multipart.js +0 -6
  72. package/src/middleware/rateLimit.js +0 -6
  73. package/src/middleware/underPressure.js +0 -6
  74. package/src/utils/colorize.js +0 -37
  75. package/src/utils/cookie.js +0 -5
  76. package/src/utils/formatBytes.js +0 -16
  77. package/src/utils/health.js +0 -126
  78. package/src/utils/xEcho.js +0 -12
  79. package/src/utils/xSlugify.js +0 -20
  80. package/src/utils/xUUID.js +0 -14
  81. package/src/xConfig.js +0 -117
  82. package/test/index.js +0 -17
  83. package/ts-reference/integrations/cloudinary.ts +0 -26
  84. package/ts-reference/integrations/prisma.ts +0 -13
  85. package/ts-reference/integrations/sendgrid.ts +0 -27
  86. package/ts-reference/integrations/stripe.ts +0 -15
  87. package/ts-reference/integrations/twilio.ts +0 -20
  88. package/ts-reference/middleware/bugsnag.ts +0 -10
  89. package/ts-reference/middleware/cors.ts +0 -13
  90. package/ts-reference/middleware/errorHandler.ts +0 -24
  91. package/ts-reference/middleware/multipart.ts +0 -8
  92. package/ts-reference/middleware/rateLimit.ts +0 -8
  93. package/ts-reference/middleware/underPressure.ts +0 -11
  94. package/ts-reference/utils/colorize.ts +0 -45
  95. package/ts-reference/utils/formatBytes.ts +0 -8
  96. package/ts-reference/utils/randomUUID.ts +0 -3
  97. package/ts-reference/utils/statAsync.ts +0 -4
  98. package/xConfigReference.js +0 -1495
  99. package/xConfigWorkingList.js +0 -720
@@ -1 +0,0 @@
1
- {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAwB,EACxB,WAAoB;IAEpB,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAChD,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;YAC3C,MAAM,QAAQ,GAAG;gBACf,MAAM,EAAE,UAAU;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,uBAAuB;gBACjD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;aACxE,CAAC;YAEF,mCAAmC;YACnC,IAAI,OAAO,CAAC,OAAO;gBAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC5B,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- import { FastifyInstance } from "fastify";
2
- export declare function setupMultipart(fastify: FastifyInstance, options: any): Promise<void>;
@@ -1,7 +0,0 @@
1
- export async function setupMultipart(fastify, options) {
2
- if (options.active !== false) {
3
- await fastify.register(import("@fastify/multipart"), options);
4
- console.info(" ✅ Multipart Enabled");
5
- }
6
- }
7
- //# sourceMappingURL=multipart.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../src/middleware/multipart.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB,EAAE,OAAY;IACzE,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- import { FastifyInstance } from "fastify";
2
- export declare function setupRateLimit(fastify: FastifyInstance, options: any): Promise<void>;
@@ -1,7 +0,0 @@
1
- export async function setupRateLimit(fastify, options) {
2
- if (options.active !== false) {
3
- await fastify.register(import("@fastify/rate-limit"), options);
4
- console.info(" ✅ Rate Limiting Enabled");
5
- }
6
- }
7
- //# sourceMappingURL=rateLimit.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../src/middleware/rateLimit.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB,EAAE,OAAY;IACzE,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- import { FastifyInstance } from "fastify";
2
- export declare function setupUnderPressure(fastify: FastifyInstance, options: any): Promise<void>;
@@ -1,7 +0,0 @@
1
- export async function setupUnderPressure(fastify, options) {
2
- if (options.active !== false) {
3
- await fastify.register(import("@fastify/under-pressure"), options);
4
- console.info(" ✅ Under Pressure Enabled");
5
- }
6
- }
7
- //# sourceMappingURL=underPressure.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"underPressure.js","sourceRoot":"","sources":["../../src/middleware/underPressure.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAwB,EACxB,OAAY;IAEZ,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
@@ -1,4 +0,0 @@
1
- import type { FastifyInstance, RouteOptions } from "fastify";
2
- export declare function colorize(method: string, text: string): string;
3
- export declare function printRoutes(routes: RouteOptions[], colors?: boolean): void;
4
- export declare function captureRoutes(fastify: FastifyInstance): RouteOptions[];
@@ -1,33 +0,0 @@
1
- const COLORS = {
2
- POST: 33,
3
- GET: 32,
4
- PUT: 34,
5
- DELETE: 31,
6
- PATCH: 90,
7
- clear: 39,
8
- };
9
- // Function to colorize method and path names
10
- export function colorize(method, text) {
11
- const colorCode = COLORS[method] || COLORS.clear;
12
- return `\u001b[${colorCode}m${text}\u001b[${COLORS.clear}m`;
13
- }
14
- // Function to print the collected routes
15
- export function printRoutes(routes, colors = true) {
16
- routes
17
- .sort((a, b) => a.url.localeCompare(b.url))
18
- .forEach(({ method, url }) => {
19
- const methodsArray = Array.isArray(method) ? method : [method];
20
- methodsArray
21
- .filter((m) => m !== "HEAD")
22
- .forEach((m) => console.info(`${colors ? colorize(m, m) : m}\t${colors ? colorize(m, url) : url}`));
23
- });
24
- }
25
- // Helper function to capture all registered routes
26
- export function captureRoutes(fastify) {
27
- const routes = [];
28
- fastify.addHook("onRoute", (routeOptions) => {
29
- routes.push(routeOptions);
30
- });
31
- return routes;
32
- }
33
- //# sourceMappingURL=colorize.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"colorize.js","sourceRoot":"","sources":["../../src/utils/colorize.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,GAA+B;IACzC,IAAI,EAAE,EAAE;IACR,GAAG,EAAE,EAAE;IACP,GAAG,EAAE,EAAE;IACP,MAAM,EAAE,EAAE;IACV,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,6CAA6C;AAC7C,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAY;IACnD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAoB,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC;IAC/D,OAAO,UAAU,SAAS,IAAI,IAAI,UAAU,MAAM,CAAC,KAAK,GAAG,CAAC;AAC9D,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,MAAsB,EAAE,MAAM,GAAG,IAAI;IAC/D,MAAM;SACH,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SAC1C,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;QAC3B,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/D,YAAY;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC;aAC3B,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,OAAO,CAAC,IAAI,CACV,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CACrE,CACF,CAAC;IACN,CAAC,CAAC,CAAC;AACP,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,aAAa,CAAC,OAAwB;IACpD,MAAM,MAAM,GAAmB,EAAE,CAAC;IAElC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,YAAY,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +0,0 @@
1
- export declare function formatBytes(bytes: number, decimals?: number): string;
@@ -1,10 +0,0 @@
1
- export function formatBytes(bytes, decimals = 2) {
2
- if (bytes === 0)
3
- return "0 Bytes";
4
- const k = 1024;
5
- const dm = decimals < 0 ? 0 : decimals;
6
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
7
- const i = Math.floor(Math.log(bytes) / Math.log(k));
8
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
9
- }
10
- //# sourceMappingURL=formatBytes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatBytes.js","sourceRoot":"","sources":["../../src/utils/formatBytes.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,QAAQ,GAAG,CAAC;IACrD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC;IACf,MAAM,EAAE,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,OAAO,GAAG,UAAU,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3E,CAAC"}
@@ -1 +0,0 @@
1
- export declare const generateUUID: any;
@@ -1,3 +0,0 @@
1
- import { randomUUID } from "uncrypto";
2
- export const generateUUID = randomUUID;
3
- //# sourceMappingURL=randomUUID.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"randomUUID.js","sourceRoot":"","sources":["../../src/utils/randomUUID.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC"}
@@ -1,2 +0,0 @@
1
- import fs from "fs";
2
- export declare const statAsync: typeof fs.stat.__promisify__;
@@ -1,4 +0,0 @@
1
- import fs from "fs";
2
- import util from "util";
3
- export const statAsync = util.promisify(fs.stat);
4
- //# sourceMappingURL=statAsync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"statAsync.js","sourceRoot":"","sources":["../../src/utils/statAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC"}
package/dist/xConfig.d.ts DELETED
@@ -1,3 +0,0 @@
1
- declare function xConfig(fastify: any, options: any): Promise<void>;
2
- declare const _default: typeof xConfig;
3
- export default _default;
package/dist/xConfig.js DELETED
@@ -1,9 +0,0 @@
1
- //src/xConfig.js
2
- import fp from "fastify-plugin";
3
- async function xConfig(fastify, options) {
4
- fastify.decorate("xEcho", () => "Hello from X Enterprises!");
5
- }
6
- export default fp(xConfig, {
7
- name: "xConfig",
8
- });
9
- //# sourceMappingURL=xConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"xConfig.js","sourceRoot":"","sources":["../src/xConfig.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEhC,KAAK,UAAU,OAAO,CAAC,OAAO,EAAE,OAAO;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,2BAA2B,CAAC,CAAC;AAC/D,CAAC;AAED,eAAe,EAAE,CAAC,OAAO,EAAE;IACzB,IAAI,EAAE,SAAS;CAChB,CAAC,CAAC"}
package/server/app.js DELETED
@@ -1,92 +0,0 @@
1
- // server/app.js
2
- import Fastify from 'fastify';
3
- import xConfig from '../src/xConfig.js'; // Import your plugin correctly
4
-
5
- const fastify = Fastify();
6
-
7
-
8
- export default async function (fastify, opts) {
9
- fastify.register(xConfig, {
10
- professional: false,
11
- fancyErrors: true,
12
- prisma: {
13
- active: false,
14
- },
15
- bugsnag: {
16
- apiKey: process.env.BUGSNAG_API_KEY
17
- },
18
- rateLimit: {
19
- max: process.env.RATE_LIMIT_MAX || 100,
20
- timeWindow: process.env.RATE_LIMIT_TIME_WINDOW || '1 minute'
21
- },
22
- stripe: {
23
- active: false,
24
- apiKey: process.env.STRIPE_API_KEY
25
- },
26
- sendGrid: {
27
- active: true,
28
- apiKey: process.env.SENDGRID_API_KEY,
29
- apiKeyEmailValidation: process.env.SENDGRID_API_EMAIL_VALIDATION_KEY,
30
- fromEmail: process.env.SENDGRID_FROM_EMAIL || 'ops@getx.io',
31
- },
32
- twilio: {
33
- active: true,
34
- accountSid: process.env.TWILIO_ACCOUNT_SID,
35
- authToken: process.env.TWILIO_AUTH_TOKEN,
36
- phoneNumber: process.env.TWILIO_PHONE_NUMBER
37
- },
38
- cloudinary: {
39
- active: false,
40
- cloudName: process.env.CLOUDINARY_CLOUD_NAME,
41
- apiKey: process.env.CLOUDINARY_API_KEY,
42
- apiSecret: process.env.CLOUDINARY_API_SECRET,
43
- basePath: process.env.CLOUDINARY_BASE_PATH || 'basepath'
44
- },
45
- cors: {
46
- active: true,
47
- origin: process.env.CORS_ORIGIN || ['http://localhost:3000', 'https://app.bandmate.io'],
48
- credentials: true
49
- },
50
- auth: {
51
- excludedPaths: ['/public', '/portal/auth/register'],
52
- admin: {
53
- active: true,
54
- secret: process.env.ADMIN_JWT_SECRET,
55
- expiresIn: '1h',
56
- cookieOptions: {
57
- name: 'adminToken',
58
- httpOnly: true,
59
- secure: true, // Set to false if not using HTTPS
60
- sameSite: 'strict', // Can be 'lax', 'strict', or 'none'
61
- }
62
- },
63
- user: {
64
- active: true,
65
- secret: process.env.USER_JWT_SECRET,
66
- expiresIn: '1h',
67
- cookieOptions: {
68
- name: 'userToken',
69
- httpOnly: true,
70
- secure: true,
71
- sameSite: 'strict',
72
- },
73
- me: {
74
- isOnboarded: true
75
- },
76
- registerEmail: {
77
- subject: 'Welcome to Bandmate!',
78
- templateId: ''
79
- }
80
- },
81
- },
82
- geocode: {
83
- active: true,
84
- apiKey: process.env.GEOCODIO_API_KEY
85
- }
86
- }); // Register the default export, which should be a function
87
- fastify.get('/', async (request, reply) => {
88
- console.log(fastify.xEcho())
89
- return { status: fastify.xEcho() }
90
- })
91
-
92
- };
package/src/auth/admin.js DELETED
@@ -1,241 +0,0 @@
1
- import jwt from "@fastify/jwt";
2
- import bcrypt from "bcrypt";
3
- const isProduction = process.env.NODE_ENV === 'production';
4
- export async function setupAdminAuth(fastify, options) {
5
- if (options.admin?.active !== false) {
6
-
7
- // Ensure the admin JWT secret is provided
8
- if (!options.admin.secret) {
9
- throw new Error("Admin JWT secret must be provided.");
10
- }
11
-
12
- const adminAuthOptions = options.admin;
13
- const adminCookieName =
14
- adminAuthOptions.cookieOptions?.name || "adminToken";
15
- const adminRefreshCookieName =
16
- adminAuthOptions.cookieOptions?.refreshTokenName || "adminRefreshToken";
17
- const adminCookieOptions = {
18
- httpOnly: true, // Ensures the cookie is not accessible via JavaScript
19
- secure: isProduction, // true in production (HTTPS), false in development (HTTP)
20
- sameSite: isProduction ? 'None' : 'Lax', // 'None' for cross-origin, 'Lax' for development
21
- path: '/', // Ensure cookies are valid for the entire site
22
- };
23
- const adminExcludedPaths = adminAuthOptions.excludedPaths || [
24
- "/admin/auth/login",
25
- "/admin/auth/logout",
26
- ];
27
-
28
- // Decorator to hash admin passwords
29
- async function hashAdminPassword(password) {
30
- const saltRounds = 10; // Number of salt rounds for bcrypt (10 is generally a good default)
31
- try {
32
- const hashedPassword = await bcrypt.hash(password, saltRounds);
33
- return hashedPassword;
34
- } catch (error) {
35
- throw new Error("Failed to hash password: " + error.message);
36
- }
37
- }
38
-
39
- fastify.decorate("hashAdminPassword", hashAdminPassword);
40
-
41
- // Register JWT for admin
42
- await fastify.register(jwt, {
43
- secret: adminAuthOptions.secret,
44
- sign: { algorithm: 'HS256', expiresIn: adminAuthOptions.expiresIn || "15m" },
45
- cookie: {
46
- cookieName: adminCookieName,
47
- signed: false,
48
- },
49
- namespace: "adminJwt",
50
- jwtVerify: "adminJwtVerify",
51
- jwtSign: "adminJwtSign",
52
- });
53
-
54
- // Common function to set tokens as cookies
55
- const setAdminAuthCookies = (reply, accessToken, refreshToken) => {
56
- reply.setCookie(adminCookieName, accessToken, adminCookieOptions);
57
- reply.setCookie(adminRefreshCookieName, refreshToken, {
58
- // ...adminCookieOptions,
59
- httpOnly: true, // Ensures the cookie is not accessible via JavaScript
60
- secure: isProduction, // true in production (HTTPS), false in development (HTTP)
61
- sameSite: isProduction ? 'None' : 'Lax', // 'None' for cross-origin, 'Lax' for development
62
- path: '/', // Ensure cookies are valid for the entire site
63
- });
64
- };
65
-
66
- // Admin authentication hook
67
- fastify.addHook("onRequest", async (request, reply) => {
68
- const url = request.url;
69
-
70
- // Skip authentication for excluded paths
71
- if (adminExcludedPaths.some((path) => url.startsWith(path))) {
72
- return;
73
- }
74
-
75
- if (url.startsWith("/admin")) {
76
- try {
77
- // Extract token from cookie or Authorization header
78
- const authHeader = request.headers.authorization;
79
- const authToken =
80
- authHeader && authHeader.startsWith("Bearer ")
81
- ? authHeader.slice(7)
82
- : null;
83
- const token = request.cookies[adminCookieName] || authToken;
84
-
85
- if (!token) {
86
- throw fastify.httpErrors.unauthorized(
87
- "Admin access token not provided"
88
- );
89
- }
90
-
91
- // Verify access token
92
- const decoded = await request.adminJwtVerify(token);
93
- request.adminAuth = decoded; // Attach admin auth context
94
- } catch (err) {
95
- // Use built-in HTTP error handling
96
- reply.send(
97
- fastify.httpErrors.unauthorized("Invalid or expired access token")
98
- );
99
- }
100
- }
101
- });
102
-
103
- // Admin login route
104
- fastify.post("/admin/auth/login", async (req, reply) => {
105
- try {
106
- const { email, password } = req.body;
107
-
108
- // Validate input
109
- if (!email || !password) {
110
- throw fastify.httpErrors.badRequest(
111
- "Email and password are required"
112
- );
113
- }
114
-
115
- // Fetch admin from the database
116
- const admin = await fastify.prisma.admins.findUnique({
117
- where: { email },
118
- });
119
- if (!admin) {
120
- throw fastify.httpErrors.unauthorized("Invalid credentials");
121
- }
122
-
123
- // Compare passwords using bcrypt
124
- const isValidPassword = await bcrypt.compare(password, admin.password);
125
- if (!isValidPassword) {
126
- throw fastify.httpErrors.unauthorized("Invalid credentials");
127
- }
128
-
129
- // Issue access token
130
- const accessToken = await reply.adminJwtSign({ id: admin.id });
131
-
132
- // Generate refresh token
133
- const refreshToken = await fastify.randomUUID();
134
- const hashedRefreshToken = await bcrypt.hash(refreshToken, 10);
135
-
136
- // Store hashed refresh token in the database
137
- await fastify.prisma.admins.update({
138
- where: { id: admin.id },
139
- data: { refreshToken: hashedRefreshToken },
140
- });
141
-
142
- // Set tokens as cookies
143
- setAdminAuthCookies(reply, accessToken, refreshToken);
144
-
145
- reply.send({ accessToken });
146
- } catch (err) {
147
- reply.send(err);
148
- }
149
- });
150
-
151
- // Admin refresh token route
152
- fastify.post("/admin/auth/refresh", async (req, reply) => {
153
- try {
154
- const adminAuth = req.adminAuth;
155
- const refreshToken = req.cookies[adminRefreshCookieName];
156
- if (!refreshToken) {
157
- throw fastify.httpErrors.unauthorized("Refresh token not provided");
158
- }
159
-
160
- // Fetch admin from the database using the refresh token
161
- const admin = await fastify.prisma.admins.findFirst({
162
- where: { id: adminAuth.id, refreshToken: { not: null } },
163
- });
164
- if (!admin) {
165
- throw fastify.httpErrors.unauthorized("Invalid refresh token");
166
- }
167
-
168
- // Verify the refresh token
169
- const isValid = await bcrypt.compare(refreshToken, admin.refreshToken);
170
- if (!isValid) {
171
- throw fastify.httpErrors.unauthorized("Invalid refresh token");
172
- }
173
-
174
- // Issue new access token
175
- const accessToken = await reply.adminJwtSign({ id: admin.id });
176
-
177
- // Generate new refresh token
178
- const newRefreshToken = await fastify.randomUUID();
179
- const hashedNewRefreshToken = await bcrypt.hash(newRefreshToken, 10);
180
-
181
- // Update refresh token in the database
182
- await fastify.prisma.admins.update({
183
- where: { id: admin.id },
184
- data: { refreshToken: hashedNewRefreshToken },
185
- });
186
-
187
- // Set new tokens as cookies
188
- setAdminAuthCookies(reply, accessToken, newRefreshToken);
189
-
190
- reply.send({ accessToken });
191
- } catch (err) {
192
- reply.send(err);
193
- }
194
- });
195
-
196
- // Admin logout route
197
- fastify.post("/admin/auth/logout", async (req, reply) => {
198
- try {
199
- const adminAuth = req.adminAuth;
200
- if (adminAuth) {
201
- // Delete refresh token from the database
202
- await fastify.prisma.admins.update({
203
- where: { id: adminAuth.id },
204
- data: { refreshToken: null },
205
- });
206
- }
207
-
208
- // Clear cookies
209
- reply.clearCookie(adminCookieName, { path: "/" });
210
- reply.clearCookie(adminRefreshCookieName, { path: "/" });
211
-
212
- reply.send({ message: "Logged out successfully" });
213
- } catch (err) {
214
- reply.send(err);
215
- }
216
- });
217
-
218
- // Admin authentication status route
219
- fastify.get("/admin/auth/me", async (req, reply) => {
220
- try {
221
- const adminAuth = req.adminAuth;
222
-
223
- // Fetch admin details from database
224
- const admin = await fastify.prisma.admins.findUnique({
225
- where: { id: adminAuth.id },
226
- select: { id: true, firstName: true, lastName: true, email: true },
227
- });
228
-
229
- if (!admin) {
230
- throw fastify.httpErrors.notFound("Admin not found");
231
- }
232
-
233
- reply.send(admin);
234
- } catch (err) {
235
- reply.send(err);
236
- }
237
- });
238
-
239
- console.info(" ✅ Auth Admin Enabled");
240
- }
241
- }