@xenterprises/fastify-xconfig 1.0.0 → 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 -171
  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 -85
  60. package/src/auth/admin.js +0 -181
  61. package/src/auth/portal.js +0 -177
  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 -1526
  99. package/xConfigWorkingList.js +0 -720
@@ -1,11 +0,0 @@
1
- export async function setupCors(fastify, options) {
2
- if (options.active !== false) {
3
- await fastify.register(import("@fastify/cors"), {
4
- origin: options.origin || ["https://getx.io", "http://localhost:3000"],
5
- credentials: options.credentials !== undefined ? options.credentials : true,
6
- methods: options.methods || ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
7
- });
8
- console.info(" ✅ CORS Enabled");
9
- }
10
- }
11
- //# sourceMappingURL=cors.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAwB,EAAE,OAAY;IACpE,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE;YAC9C,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;YACtE,WAAW,EACT,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;YAChE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;SACxE,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- import { FastifyInstance } from "fastify";
2
- export declare function setupErrorHandler(fastify: FastifyInstance, fancyErrors: boolean): Promise<void>;
@@ -1,19 +0,0 @@
1
- export async function setupErrorHandler(fastify, fancyErrors) {
2
- if (fancyErrors !== false) {
3
- fastify.setErrorHandler((error, request, reply) => {
4
- const statusCode = error.statusCode || 500;
5
- const response = {
6
- status: statusCode,
7
- message: error.message || "Internal Server Error",
8
- stack: process.env.NODE_ENV === "development" ? error.stack : undefined,
9
- };
10
- // Optional Bugsnag error reporting
11
- if (fastify.bugsnag)
12
- fastify.bugsnag.notify(error);
13
- fastify.log.error(response);
14
- reply.status(statusCode).send(response);
15
- });
16
- console.info(" ✅ Fancy Errors Enabled");
17
- }
18
- }
19
- //# sourceMappingURL=errorHandler.js.map
@@ -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,85 +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
- portalStackProjectId: process.env.STACK_PROJECT_ID,
66
- me: {
67
- isOnboarded: true
68
- },
69
- registerEmail: {
70
- subject: 'Welcome to Bandmate!',
71
- templateId: ''
72
- }
73
- },
74
- },
75
- geocode: {
76
- active: true,
77
- apiKey: process.env.GEOCODIO_API_KEY
78
- }
79
- }); // Register the default export, which should be a function
80
- fastify.get('/', async (request, reply) => {
81
- console.log(fastify.xEcho())
82
- return { status: fastify.xEcho() }
83
- })
84
-
85
- };
package/src/auth/admin.js DELETED
@@ -1,181 +0,0 @@
1
- import * as jose from "jose";
2
- const isProduction = process.env.NODE_ENV === 'production';
3
-
4
- export async function setupAdminAuth(fastify, options) {
5
- if (options.admin?.active !== false) {
6
- // Get configuration
7
- const projectId = options.admin.stackProjectId || process.env.ADMIN_STACK_PROJECT_ID;
8
- const publishableKey = options.admin.publishableKey || process.env.ADMIN_STACK_PUBLISHABLE_CLIENT_KEY;
9
- const secretKey = options.admin.secretKey || process.env.ADMIN_STACK_SECRET_SERVER_KEY;
10
-
11
- if (!projectId) {
12
- throw new Error("Stack Auth admin project ID is required");
13
- }
14
-
15
- if (!publishableKey || !secretKey) {
16
- throw new Error("Stack Auth admin publishable and secret keys are required");
17
- }
18
-
19
- const adminExcludedPaths = options.admin.excludedPaths || [
20
- "/admin/auth/login",
21
- "/admin/auth/logout",
22
- ];
23
-
24
- // Base URL for Stack Auth API
25
- const stackAuthBaseUrl = `https://api.stack-auth.com/api/v1`;
26
- const jwksUrl = `${stackAuthBaseUrl}/projects/${projectId}/.well-known/jwks.json`;
27
-
28
- // Create JWKS for token verification
29
- const jwks = jose.createRemoteJWKSet(new URL(jwksUrl));
30
-
31
- // Helper for Stack Auth API headers
32
- fastify.decorate('getAdminStackAuthHeaders', function (accessType = "server") {
33
- const headers = {
34
- 'Content-Type': 'application/json',
35
- 'Accept': 'application/json',
36
- 'X-Stack-Access-Type': accessType,
37
- 'X-Stack-Project-Id': projectId,
38
- };
39
-
40
- if (accessType === "client") {
41
- headers['X-Stack-Publishable-Client-Key'] = publishableKey;
42
- } else if (accessType === "server") {
43
- headers['X-Stack-Secret-Server-Key'] = secretKey;
44
- }
45
-
46
- return headers;
47
- });
48
-
49
- // JWT verification helper
50
- fastify.decorate('verifyAdminStackJWT', async function (accessToken) {
51
- try {
52
- // Add validation to ensure accessToken is a valid string
53
- if (!accessToken || typeof accessToken !== 'string') {
54
- fastify.log.error('Invalid admin token format: token must be a non-empty string');
55
- return null;
56
- }
57
-
58
- const { payload } = await jose.jwtVerify(accessToken, jwks);
59
-
60
- // Verify the payload has expected properties
61
- if (!payload || !payload.sub) {
62
- fastify.log.error('Invalid admin token payload: missing required claims');
63
- return null;
64
- }
65
-
66
- return payload;
67
- } catch (error) {
68
- fastify.log.error(error);
69
- return null;
70
- }
71
- });
72
-
73
- // Admin authentication hook
74
- fastify.addHook("onRequest", async (request, reply) => {
75
- const url = request.url;
76
-
77
- // Skip authentication for excluded paths
78
- if (adminExcludedPaths.some((path) => url.startsWith(path))) {
79
- return;
80
- }
81
-
82
- if (url.startsWith("/admin")) {
83
- try {
84
- // Get token from header
85
- const authHeader = request.headers.authorization;
86
- if (!authHeader || !authHeader.startsWith("Bearer ")) {
87
- return reply.code(401).send({ error: "Admin access token required" });
88
- }
89
-
90
- // Verify token
91
- const token = authHeader.slice(7);
92
- const payload = await fastify.verifyAdminStackJWT(token);
93
-
94
- if (!payload) {
95
- return reply.code(401).send({ error: "Invalid admin token" });
96
- }
97
-
98
- // Set admin info on request
99
- request.admin = payload;
100
- request.adminAuth = { id: payload.sub };
101
- } catch (err) {
102
- return reply.code(401).send({ error: "Admin authentication failed" });
103
- }
104
- }
105
- });
106
-
107
- // Admin login endpoint
108
- fastify.post("/admin/auth/login", async (req, reply) => {
109
- try {
110
- const { email, password } = req.body;
111
-
112
- if (!email || !password) {
113
- return reply.code(400).send({ error: "Email and password required" });
114
- }
115
-
116
- // Call Stack Auth API for password sign-in
117
- const response = await fetch(
118
- `${stackAuthBaseUrl}/auth/password/sign-in`,
119
- {
120
- method: 'POST',
121
- headers: fastify.getAdminStackAuthHeaders("server"),
122
- body: JSON.stringify({ email, password })
123
- }
124
- );
125
-
126
- const data = await response.json().catch(() => ({}));
127
-
128
- if (!response.ok) {
129
- return reply.code(response.status || 400).send({
130
- error: data.message || "Authentication failed"
131
- });
132
- }
133
-
134
- // Check if we have the expected response properties
135
- if (!data.access_token || !data.refresh_token || !data.user_id) {
136
- return reply.code(500).send({ error: "Invalid response from authentication service" });
137
- }
138
-
139
- // Verify token
140
- const payload = await fastify.verifyAdminStackJWT(data.access_token);
141
- if (!payload) {
142
- return reply.code(401).send({ error: "Invalid token received" });
143
- }
144
-
145
- reply.send({
146
- accessToken: data.access_token,
147
- refreshToken: data.refresh_token,
148
- admin: payload,
149
- adminId: data.user_id
150
- });
151
- } catch (err) {
152
- fastify.log.error(err);
153
- reply.code(500).send({ error: "Internal server error" });
154
- }
155
- });
156
-
157
- // Admin info endpoint
158
- fastify.get("/admin/auth/me", async (req, reply) => {
159
- reply.send(req.admin || { authenticated: false });
160
- });
161
-
162
- // Token verification endpoint
163
- fastify.post("/admin/auth/verify", async (req, reply) => {
164
- const { token } = req.body;
165
-
166
- if (!token) {
167
- return reply.code(400).send({ error: "Token required" });
168
- }
169
-
170
- const payload = await fastify.verifyAdminStackJWT(token);
171
-
172
- if (!payload) {
173
- return reply.code(401).send({ valid: false });
174
- }
175
-
176
- reply.send({ valid: true, admin: payload });
177
- });
178
-
179
- console.info(" ✅ Auth Admin Enabled");
180
- }
181
- }
@@ -1,177 +0,0 @@
1
- import * as jose from "jose";
2
- import fetch from "node-fetch";
3
-
4
- export async function setupAuth(fastify, options) {
5
- if (options.user?.active !== false) {
6
- // Get configuration
7
- const projectId = options.user.portalStackProjectId || process.env.STACK_PROJECT_ID;
8
- const publishableKey = options.user.publishableKey || process.env.STACK_PUBLISHABLE_CLIENT_KEY;
9
- const secretKey = options.user.secretKey || process.env.STACK_SECRET_SERVER_KEY;
10
-
11
- if (!projectId) {
12
- throw new Error("Stack Auth project ID is required");
13
- }
14
-
15
- if (!publishableKey || !secretKey) {
16
- throw new Error("Stack Auth publishable and secret keys are required");
17
- }
18
-
19
- const userExcludedPaths = options.user.excludedPaths || [
20
- "/portal/auth/login",
21
- "/portal/auth/logout",
22
- "/portal/auth/register",
23
- "/portal/auth/forgot-password",
24
- "/portal/auth/reset-password"
25
- ];
26
-
27
- // Base URL for Stack Auth API
28
- const stackAuthBaseUrl = `https://api.stack-auth.com/api/v1`;
29
- const jwksUrl = `${stackAuthBaseUrl}/projects/${projectId}/.well-known/jwks.json`;
30
-
31
- // Create JWKS for token verification
32
- const jwks = jose.createRemoteJWKSet(new URL(jwksUrl));
33
-
34
- // Helper for Stack Auth API headers
35
- fastify.decorate('getStackAuthHeaders', function (accessType = "server") {
36
- const headers = {
37
- 'Content-Type': 'application/json',
38
- 'Accept': 'application/json',
39
- 'X-Stack-Access-Type': accessType,
40
- 'X-Stack-Project-Id': projectId,
41
- };
42
-
43
- if (accessType === "client") {
44
- headers['X-Stack-Publishable-Client-Key'] = publishableKey;
45
- } else if (accessType === "server") {
46
- headers['X-Stack-Secret-Server-Key'] = secretKey;
47
- }
48
-
49
- return headers;
50
- });
51
-
52
- // JWT verification helper
53
- fastify.decorate('verifyStackJWT', async function (accessToken) {
54
- try {
55
- const { payload } = await jose.jwtVerify(accessToken, jwks);
56
- return payload;
57
- } catch (error) {
58
- fastify.log.error(error);
59
- return null;
60
- }
61
- });
62
-
63
- // API URL helper
64
- fastify.decorate('getStackAuthApiUrl', function () {
65
- return stackAuthBaseUrl;
66
- });
67
-
68
- // Authentication middleware
69
- fastify.addHook("onRequest", async (request, reply) => {
70
- const url = request.url;
71
-
72
- // Skip excluded paths
73
- if (userExcludedPaths.some(path => url.startsWith(path))) {
74
- return;
75
- }
76
-
77
- if (url.startsWith("/portal")) {
78
- try {
79
- // Get token from header
80
- const authHeader = request.headers.authorization;
81
- if (!authHeader || !authHeader.startsWith("Bearer ")) {
82
- return reply.code(401).send({ error: "Access token required" });
83
- }
84
-
85
- // Verify token
86
- const token = authHeader.slice(7);
87
- const payload = await fastify.verifyStackJWT(token);
88
-
89
- if (!payload) {
90
- return reply.code(401).send({ error: "Invalid token" });
91
- }
92
-
93
- // Set user info on request
94
- request.user = payload;
95
- request.userAuth = { id: payload.sub };
96
- } catch (err) {
97
- return reply.code(401).send({ error: "Authentication failed" });
98
- }
99
- }
100
- });
101
-
102
- // Login endpoint
103
- fastify.post("/portal/auth/login", async (req, reply) => {
104
- try {
105
- const { email, password } = req.body;
106
-
107
- if (!email || !password) {
108
- return reply.code(400).send({ error: "Email and password required" });
109
- }
110
-
111
- // Call Stack Auth API for password sign-in
112
- const response = await fetch(
113
- `${stackAuthBaseUrl}/auth/password/sign-in`,
114
- {
115
- method: 'POST',
116
- headers: fastify.getStackAuthHeaders("server"),
117
- body: JSON.stringify({ email, password })
118
- }
119
- );
120
-
121
- const data = await response.json().catch(() => ({}));
122
-
123
- if (!response.ok) {
124
- return reply.code(response.status || 400).send({
125
- error: data.message || "Authentication failed"
126
- });
127
- }
128
-
129
- // Check if we have the expected response properties
130
- if (!data.access_token || !data.refresh_token || !data.user_id) {
131
- return reply.code(500).send({ error: "Invalid response from authentication service" });
132
- }
133
-
134
- // Verify token
135
- const payload = await fastify.verifyStackJWT(data.access_token);
136
- if (!payload) {
137
- return reply.code(401).send({ error: "Invalid token received" });
138
- }
139
-
140
- reply.send({
141
- accessToken: data.access_token,
142
- refreshToken: data.refresh_token,
143
- user: payload,
144
- userId: data.user_id
145
- });
146
- } catch (err) {
147
- fastify.log.error(err);
148
- reply.code(500).send({ error: "Internal server error" });
149
- }
150
- });
151
-
152
-
153
- // User info endpoint
154
- fastify.get("/portal/auth/me", async (req, reply) => {
155
- reply.send(req.user || { authenticated: false });
156
- });
157
-
158
- // Token verification endpoint
159
- fastify.post("/portal/auth/verify", async (req, reply) => {
160
- const { token } = req.body;
161
-
162
- if (!token) {
163
- return reply.code(400).send({ error: "Token required" });
164
- }
165
-
166
- const payload = await fastify.verifyStackJWT(token);
167
-
168
- if (!payload) {
169
- return reply.code(401).send({ valid: false });
170
- }
171
-
172
- reply.send({ valid: true, user: payload });
173
- });
174
-
175
- console.info(" ✅ Auth User Enabled");
176
- }
177
- }