gs-error-reporter 1.0.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 (41) hide show
  1. package/dist/cli/detectProject.d.ts +6 -0
  2. package/dist/cli/detectProject.d.ts.map +1 -0
  3. package/dist/cli/detectProject.js +36 -0
  4. package/dist/cli/fileInstaller.d.ts +2 -0
  5. package/dist/cli/fileInstaller.d.ts.map +1 -0
  6. package/dist/cli/fileInstaller.js +21 -0
  7. package/dist/cli/index.d.ts +3 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +60 -0
  10. package/dist/cli/installEnv.d.ts +2 -0
  11. package/dist/cli/installEnv.d.ts.map +1 -0
  12. package/dist/cli/installEnv.js +46 -0
  13. package/dist/core/client/clientRuntime.d.ts +2 -0
  14. package/dist/core/client/clientRuntime.d.ts.map +1 -0
  15. package/dist/core/client/clientRuntime.js +75 -0
  16. package/dist/core/server/index.d.ts +2 -0
  17. package/dist/core/server/index.d.ts.map +1 -0
  18. package/dist/core/server/index.js +17 -0
  19. package/dist/core/server/serverRuntime.d.ts +3 -0
  20. package/dist/core/server/serverRuntime.d.ts.map +1 -0
  21. package/dist/core/server/serverRuntime.js +60 -0
  22. package/dist/core/shared/buildPayout.d.ts +23 -0
  23. package/dist/core/shared/buildPayout.d.ts.map +1 -0
  24. package/dist/core/shared/buildPayout.js +64 -0
  25. package/dist/core/shared/reporter.d.ts +2 -0
  26. package/dist/core/shared/reporter.d.ts.map +1 -0
  27. package/dist/core/shared/reporter.js +23 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +5 -0
  31. package/dist/react/GSReporter.d.ts +3 -0
  32. package/dist/react/GSReporter.d.ts.map +1 -0
  33. package/dist/react/GSReporter.js +22 -0
  34. package/package.json +46 -0
  35. package/templates/.env.example +5 -0
  36. package/templates/js/gs-error-reporter.js +98 -0
  37. package/templates/js/instrumentation.js +1 -0
  38. package/templates/js/route.js +93 -0
  39. package/templates/ts/gs-error-reporter.ts +100 -0
  40. package/templates/ts/instrumentation.ts +1 -0
  41. package/templates/ts/route.ts +99 -0
@@ -0,0 +1,6 @@
1
+ export declare const hasTsconfig: boolean;
2
+ export declare const hasSrc: boolean;
3
+ export declare const baseDir: string;
4
+ export declare function hasAppRouter(rootPath: string): boolean;
5
+ export declare function hasPagesRouter(rootPath: string): boolean;
6
+ //# sourceMappingURL=detectProject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detectProject.d.ts","sourceRoot":"","sources":["../../src/cli/detectProject.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,SAAkD,CAAC;AAI3E,eAAO,MAAM,MAAM,SAAwC,CAAC;AAC5D,eAAO,MAAM,OAAO,QAAsB,CAAC;AAG3C,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,WAa5C;AAGD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,WAU9C"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.baseDir = exports.hasSrc = exports.hasTsconfig = void 0;
7
+ exports.hasAppRouter = hasAppRouter;
8
+ exports.hasPagesRouter = hasPagesRouter;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const root = process.cwd();
12
+ // Check for TypeScript
13
+ exports.hasTsconfig = fs_1.default.existsSync(path_1.default.join(root, "tsconfig.json"));
14
+ console.log("Typescript: ", exports.hasTsconfig);
15
+ // Check for "src" directory
16
+ exports.hasSrc = fs_1.default.existsSync(path_1.default.join(root, "src"));
17
+ exports.baseDir = exports.hasSrc ? "src" : "";
18
+ // Check for App Router
19
+ function hasAppRouter(rootPath) {
20
+ const base = fs_1.default.existsSync(path_1.default.join(rootPath, "src")) ? "src" : "";
21
+ const appPath = path_1.default.join(rootPath, base, "app");
22
+ return (fs_1.default.existsSync(appPath) &&
23
+ (fs_1.default.existsSync(path_1.default.join(appPath, "layout.tsx")) ||
24
+ fs_1.default.existsSync(path_1.default.join(appPath, "layout.jsx")) ||
25
+ fs_1.default.existsSync(path_1.default.join(appPath, "layout.js")) ||
26
+ fs_1.default.existsSync(path_1.default.join(appPath, "layout.ts"))));
27
+ }
28
+ // Check for Pages Router
29
+ function hasPagesRouter(rootPath) {
30
+ const base = fs_1.default.existsSync(path_1.default.join(rootPath, "src")) ? "src" : "";
31
+ const pagesPath = path_1.default.join(rootPath, base, "pages");
32
+ return (fs_1.default.existsSync(path_1.default.join(pagesPath, "_app.tsx")) ||
33
+ fs_1.default.existsSync(path_1.default.join(pagesPath, "_app.jsx")) ||
34
+ fs_1.default.existsSync(path_1.default.join(pagesPath, "_app.js")) ||
35
+ fs_1.default.existsSync(path_1.default.join(pagesPath, "_app.ts")));
36
+ }
@@ -0,0 +1,2 @@
1
+ export declare function copyTemplateFile(templatePath: string, targetPath: string): void;
2
+ //# sourceMappingURL=fileInstaller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileInstaller.d.ts","sourceRoot":"","sources":["../../src/cli/fileInstaller.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,QAenB"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.copyTemplateFile = copyTemplateFile;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const root = process.cwd();
10
+ function copyTemplateFile(templatePath, targetPath) {
11
+ // If file already exists → DO NOTHING
12
+ if (fs_1.default.existsSync(targetPath)) {
13
+ console.log(`⚠ Skipped (already exists): ${targetPath}`);
14
+ return;
15
+ }
16
+ // Ensure directory exists
17
+ fs_1.default.mkdirSync(path_1.default.dirname(targetPath), { recursive: true });
18
+ // Copy file
19
+ fs_1.default.copyFileSync(templatePath, targetPath);
20
+ console.log(`✔ Created: ${targetPath}`);
21
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const detectProject_1 = require("./detectProject");
12
+ const detectProject_2 = require("./detectProject");
13
+ const detectProject_3 = require("./detectProject");
14
+ const detectProject_4 = require("./detectProject");
15
+ const fileInstaller_1 = require("./fileInstaller");
16
+ const installEnv_1 = require("./installEnv");
17
+ console.log(chalk_1.default.cyanBright(`\n!!! Welcome to gs-error-reporter !!!`));
18
+ console.log(chalk_1.default.white(`gs-error-reporter is an error reporting system for Next.js (App Router & Pages Router) with email notifications and CLI setup. (1.0.0)`));
19
+ console.log(chalk_1.default.yellowBright(`\nThis is the CLI system that will generate important files for gs-error-reporter.`));
20
+ console.log(chalk_1.default.redBright(`\nIMPORTANT INFORMATION:`));
21
+ console.log(` * Provide all requested information carefully.`);
22
+ console.log(` * Version 1.0.0 supports Gmail only.\n`);
23
+ const rootPath = process.cwd();
24
+ const packageJsonPath = path_1.default.join(rootPath, "package.json");
25
+ if (!fs_1.default.existsSync(packageJsonPath)) {
26
+ console.error("❌ No package.json found. Run this inside a Next.js project.");
27
+ process.exit(1);
28
+ }
29
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, "utf8"));
30
+ if (!packageJson.dependencies?.next && !packageJson.devDependencies?.next) {
31
+ console.error("❌ This is not a Next.js project.");
32
+ process.exit(1);
33
+ }
34
+ (0, installEnv_1.setupEnv)(rootPath);
35
+ async function setup() {
36
+ const templatesDir = path_1.default.join(__dirname, "../../templates", detectProject_1.hasTsconfig ? "ts" : "js");
37
+ const instrumentationTarget = path_1.default.join(rootPath, detectProject_2.baseDir, "instrumentation." + (detectProject_1.hasTsconfig ? "ts" : "js"));
38
+ (0, fileInstaller_1.copyTemplateFile)(path_1.default.join(templatesDir, "instrumentation." + (detectProject_1.hasTsconfig ? "ts" : "js")), instrumentationTarget);
39
+ const AppRouter = (0, detectProject_3.hasAppRouter)(rootPath);
40
+ const PagesRouter = (0, detectProject_4.hasPagesRouter)(rootPath);
41
+ if (AppRouter && PagesRouter) {
42
+ const answers = await inquirer_1.default.prompt([
43
+ {
44
+ type: 'list',
45
+ name: 'router',
46
+ message: 'In What router you want to inmplement SendMail API',
47
+ choices: ['App Router', 'Pages Router']
48
+ }
49
+ ]);
50
+ }
51
+ else if (AppRouter && !PagesRouter) {
52
+ const SendMailTarget = path_1.default.join(rootPath, detectProject_2.baseDir, "app", "api", "gs-error-reporter", "route." + (detectProject_1.hasTsconfig ? "ts" : "js"));
53
+ (0, fileInstaller_1.copyTemplateFile)(path_1.default.join(templatesDir, "route." + (detectProject_1.hasTsconfig ? "ts" : "js")), SendMailTarget);
54
+ }
55
+ else if (!AppRouter && PagesRouter) {
56
+ const SendMailTarget = path_1.default.join(rootPath, detectProject_2.baseDir, "pages", "api", "gs-error-reporter." + (detectProject_1.hasTsconfig ? "ts" : "js"));
57
+ (0, fileInstaller_1.copyTemplateFile)(path_1.default.join(templatesDir, "gs-error-reporter." + (detectProject_1.hasTsconfig ? "ts" : "js")), SendMailTarget);
58
+ }
59
+ }
60
+ setup();
@@ -0,0 +1,2 @@
1
+ export declare function setupEnv(projectRoot: string): void;
2
+ //# sourceMappingURL=installEnv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installEnv.d.ts","sourceRoot":"","sources":["../../src/cli/installEnv.ts"],"names":[],"mappings":"AAWA,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,QAwC3C"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupEnv = setupEnv;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const REQUIRED_ENV_VARS = {
10
+ GS_REPORTER_EMAIL: "",
11
+ GS_REPORTER_APP_PASSWORD: "",
12
+ GS_REPORTER_RECEIVER: "",
13
+ BASE_URL: "",
14
+ PROJECT_NAME: ""
15
+ };
16
+ function setupEnv(projectRoot) {
17
+ const envPath = path_1.default.join(projectRoot, ".env");
18
+ // ------------------------------------
19
+ // CASE 1: .env does not exist
20
+ // ------------------------------------
21
+ if (!fs_1.default.existsSync(envPath)) {
22
+ const content = Object.entries(REQUIRED_ENV_VARS)
23
+ .map(([key, value]) => `${key}=${value}`)
24
+ .join("\n");
25
+ fs_1.default.writeFileSync(envPath, content + "\n");
26
+ console.log("✔ Created .env with gs-error-reporter variables");
27
+ return;
28
+ }
29
+ // ------------------------------------
30
+ // CASE 2: .env exists → append safely
31
+ // ------------------------------------
32
+ const existingContent = fs_1.default.readFileSync(envPath, "utf8");
33
+ const linesToAppend = [];
34
+ for (const key of Object.keys(REQUIRED_ENV_VARS)) {
35
+ const regex = new RegExp(`^${key}=`, "m");
36
+ if (!regex.test(existingContent)) {
37
+ linesToAppend.push(`${key}=`);
38
+ }
39
+ }
40
+ if (linesToAppend.length === 0) {
41
+ console.log("✔ .env already contains required variables");
42
+ return;
43
+ }
44
+ fs_1.default.appendFileSync(envPath, "\n# GS Error Reporter\n" + linesToAppend.join("\n") + "\n");
45
+ console.log("✔ Added missing gs-error-reporter variables to .env");
46
+ }
@@ -0,0 +1,2 @@
1
+ export declare function initClientRuntime(): void;
2
+ //# sourceMappingURL=clientRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientRuntime.d.ts","sourceRoot":"","sources":["../../../src/core/client/clientRuntime.ts"],"names":[],"mappings":"AA6EA,wBAAgB,iBAAiB,SAShC"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ /*
4
+ Browser Runtime Monitor
5
+ NOTE: Do NOT auto-run this file.
6
+ It must be started from a client React component.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.initClientRuntime = initClientRuntime;
10
+ const reporter_1 = require("../shared/reporter");
11
+ const buildPayout_1 = require("../shared/buildPayout");
12
+ let initialized = false;
13
+ let reporting = false;
14
+ async function safeReport(type, error, extra) {
15
+ if (reporting)
16
+ return;
17
+ reporting = true;
18
+ try {
19
+ // Build structured payload
20
+ const payload = (0, buildPayout_1.buildPayload)({
21
+ runtime: "client",
22
+ error,
23
+ extra: {
24
+ errorType: type,
25
+ ...extra,
26
+ },
27
+ });
28
+ await (0, reporter_1.reportError)(payload);
29
+ console.log("ERROR CATCHED!");
30
+ }
31
+ catch (err) {
32
+ // never break app
33
+ console.log("gs-error-reporter failed to send error report", err);
34
+ }
35
+ reporting = false;
36
+ }
37
+ /* ---------------- Runtime JS errors ---------------- */
38
+ function attachRuntimeErrorListener() {
39
+ window.addEventListener("error", (event) => {
40
+ safeReport("window.error", event.error || event.message, {
41
+ source: event.filename,
42
+ lineno: event.lineno,
43
+ colno: event.colno,
44
+ });
45
+ });
46
+ }
47
+ /* ---------------- Promise rejections ---------------- */
48
+ function attachUnhandledRejection() {
49
+ window.addEventListener("unhandledrejection", (event) => {
50
+ safeReport("unhandledrejection", event.reason);
51
+ });
52
+ }
53
+ /* ---------------- Console patch ---------------- */
54
+ function patchConsole() {
55
+ const originalError = console.error;
56
+ const originalWarn = console.warn;
57
+ console.error = (...args) => {
58
+ originalError(...args);
59
+ safeReport("console.error", args, { source: "client-console" });
60
+ };
61
+ console.warn = (...args) => {
62
+ originalWarn(...args);
63
+ safeReport("console.warn", args, { source: "client-console" });
64
+ };
65
+ }
66
+ /* ---------------- Public initializer ---------------- */
67
+ function initClientRuntime() {
68
+ if (initialized)
69
+ return;
70
+ initialized = true;
71
+ attachRuntimeErrorListener();
72
+ attachUnhandledRejection();
73
+ patchConsole();
74
+ console.log("gs-error-reporter client runtime initialized");
75
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/server/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const serverRuntime_1 = require("./serverRuntime");
4
+ const g = globalThis;
5
+ if (!g.__GS_ERROR_REPORTER_SERVER__) {
6
+ g.__GS_ERROR_REPORTER_SERVER__ = true;
7
+ console.log("gs-error-reporter: server monitoring initialized");
8
+ // Attach process listeners
9
+ process.on("uncaughtException", (error) => {
10
+ (0, serverRuntime_1.handleServerError)(error, "uncaughtException");
11
+ });
12
+ process.on("unhandledRejection", (reason) => {
13
+ (0, serverRuntime_1.handleServerError)(reason, "unhandledRejection");
14
+ });
15
+ // Patch console (optional but powerful)
16
+ (0, serverRuntime_1.patchServerConsole)();
17
+ }
@@ -0,0 +1,3 @@
1
+ export declare function handleServerError(error: any, source: string): Promise<void>;
2
+ export declare function patchServerConsole(): void;
3
+ //# sourceMappingURL=serverRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverRuntime.d.ts","sourceRoot":"","sources":["../../../src/core/server/serverRuntime.ts"],"names":[],"mappings":"AAmBA,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,iBAuBjE;AAQD,wBAAgB,kBAAkB,SAkBjC"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ /*
4
+ Server Error Handler (NOT a runtime starter anymore)
5
+ This file only processes errors sent by server/index.ts
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.handleServerError = handleServerError;
9
+ exports.patchServerConsole = patchServerConsole;
10
+ const reporter_1 = require("../shared/reporter");
11
+ const buildPayout_1 = require("../shared/buildPayout");
12
+ /* ---------------------------------------------------------- */
13
+ /* INTERNAL PROTECTION (ANTI-LOOP) */
14
+ /* ---------------------------------------------------------- */
15
+ let reporting = false;
16
+ /* ---------------------------------------------------------- */
17
+ /* MAIN SERVER ERROR HANDLER */
18
+ /* ---------------------------------------------------------- */
19
+ async function handleServerError(error, source) {
20
+ // Prevent recursive reporting
21
+ if (reporting)
22
+ return;
23
+ reporting = true;
24
+ try {
25
+ const payload = (0, buildPayout_1.buildPayload)({
26
+ runtime: "server",
27
+ error,
28
+ extra: {
29
+ errorType: source,
30
+ },
31
+ });
32
+ await (0, reporter_1.reportError)(payload);
33
+ console.log("gs-error-reporter captured server error:", source);
34
+ }
35
+ catch (err) {
36
+ // Never allow reporter itself to crash the server
37
+ console.warn("gs-error-reporter failed while reporting server error");
38
+ }
39
+ reporting = false;
40
+ }
41
+ /* ---------------------------------------------------------- */
42
+ /* OPTIONAL: SERVER CONSOLE MONITORING */
43
+ /* ---------------------------------------------------------- */
44
+ let consolePatched = false;
45
+ function patchServerConsole() {
46
+ if (consolePatched)
47
+ return;
48
+ consolePatched = true;
49
+ const originalError = console.error;
50
+ const originalWarn = console.warn;
51
+ console.error = (...args) => {
52
+ originalError(...args);
53
+ handleServerError(args, "console.error");
54
+ };
55
+ console.warn = (...args) => {
56
+ originalWarn(...args);
57
+ handleServerError(args, "console.warn");
58
+ };
59
+ console.log("gs-error-reporter server console patched");
60
+ }
@@ -0,0 +1,23 @@
1
+ type RuntimeType = "client" | "server";
2
+ interface BuildPayloadOptions {
3
+ runtime: RuntimeType;
4
+ error: any;
5
+ extra?: Record<string, any>;
6
+ }
7
+ export interface ErrorPayload {
8
+ type: RuntimeType;
9
+ message: string;
10
+ stack?: string;
11
+ timestamp: string;
12
+ url?: string;
13
+ method?: string;
14
+ userAgent?: string;
15
+ language?: string;
16
+ nodeVersion?: string;
17
+ platform?: string;
18
+ environment?: string;
19
+ extra?: Record<string, any>;
20
+ }
21
+ export declare function buildPayload(options: BuildPayloadOptions): ErrorPayload;
22
+ export {};
23
+ //# sourceMappingURL=buildPayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildPayout.d.ts","sourceRoot":"","sources":["../../../src/core/shared/buildPayout.ts"],"names":[],"mappings":"AAMA,KAAK,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvC,UAAU,mBAAmB;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAElB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC7B;AAwCD,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CA8BvE"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ /*
4
+ buildPayload.ts
5
+ Converts raw error data into a structured report
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.buildPayload = buildPayload;
9
+ /* -------------------------------------------------- */
10
+ /* Utility: normalize error */
11
+ /* -------------------------------------------------- */
12
+ function normalizeError(error) {
13
+ if (!error) {
14
+ return {
15
+ message: "Unknown error",
16
+ stack: undefined,
17
+ };
18
+ }
19
+ if (error instanceof Error) {
20
+ return {
21
+ message: error.message,
22
+ stack: error.stack,
23
+ };
24
+ }
25
+ // Sometimes promises reject with string/object
26
+ if (typeof error === "string") {
27
+ return {
28
+ message: error,
29
+ stack: undefined,
30
+ };
31
+ }
32
+ // fallback
33
+ return {
34
+ message: JSON.stringify(error),
35
+ stack: undefined,
36
+ };
37
+ }
38
+ /* -------------------------------------------------- */
39
+ /* Main Payload Builder */
40
+ /* -------------------------------------------------- */
41
+ function buildPayload(options) {
42
+ const { runtime, error, extra } = options;
43
+ const normalized = normalizeError(error);
44
+ const basePayload = {
45
+ type: runtime,
46
+ message: normalized.message,
47
+ stack: normalized.stack,
48
+ timestamp: new Date().toISOString(),
49
+ environment: process.env.NODE_ENV || "unknown",
50
+ extra,
51
+ };
52
+ /* ---------------- CLIENT DATA ---------------- */
53
+ if (runtime === "client" && typeof window !== "undefined") {
54
+ basePayload.url = window.location.href;
55
+ basePayload.userAgent = navigator.userAgent;
56
+ basePayload.language = navigator.language;
57
+ }
58
+ /* ---------------- SERVER DATA ---------------- */
59
+ if (runtime === "server" && typeof process !== "undefined") {
60
+ basePayload.nodeVersion = process.version;
61
+ basePayload.platform = process.platform;
62
+ }
63
+ return basePayload;
64
+ }
@@ -0,0 +1,2 @@
1
+ export declare function reportError(payload: any): Promise<void>;
2
+ //# sourceMappingURL=reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../../src/core/shared/reporter.ts"],"names":[],"mappings":"AAAA,wBAAsB,WAAW,CAAC,OAAO,EAAE,GAAG,iBAkB7C"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reportError = reportError;
4
+ async function reportError(payload) {
5
+ if (payload.type === "server") {
6
+ await fetch(`${process.env.BASE_URL}/api/gs-error-reporter`, {
7
+ method: "POST",
8
+ headers: { "Content-Type": "application/json" },
9
+ body: JSON.stringify({
10
+ payload
11
+ }),
12
+ });
13
+ }
14
+ else if (payload.type === "client") {
15
+ await fetch('/api/gs-error-reporter', {
16
+ method: "POST",
17
+ headers: { "Content-Type": "application/json" },
18
+ body: JSON.stringify({
19
+ payload
20
+ }),
21
+ });
22
+ }
23
+ }
@@ -0,0 +1,2 @@
1
+ export { GSReporter } from "./react/GSReporter";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GSReporter = void 0;
4
+ var GSReporter_1 = require("./react/GSReporter");
5
+ Object.defineProperty(exports, "GSReporter", { enumerable: true, get: function () { return GSReporter_1.GSReporter; } });
@@ -0,0 +1,3 @@
1
+ import "../core/server/serverRuntime";
2
+ export declare function GSReporter(): null;
3
+ //# sourceMappingURL=GSReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GSReporter.d.ts","sourceRoot":"","sources":["../../src/react/GSReporter.tsx"],"names":[],"mappings":"AAMA,OAAO,8BAA8B,CAAC;AAOtC,wBAAgB,UAAU,SAWzB"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ // @ts-nocheck
3
+ "use client";
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.GSReporter = GSReporter;
6
+ const react_1 = require("react");
7
+ // Import server runtime (runs automatically on server)
8
+ require("../core/server/serverRuntime");
9
+ // Import client initializer
10
+ const clientRuntime_1 = require("../core/client/clientRuntime");
11
+ let started = false;
12
+ function GSReporter() {
13
+ (0, react_1.useEffect)(() => {
14
+ // Prevent double init during Fast Refresh
15
+ if (started)
16
+ return;
17
+ started = true;
18
+ // Start browser monitoring
19
+ (0, clientRuntime_1.initClientRuntime)();
20
+ }, []);
21
+ return null;
22
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "gs-error-reporter",
3
+ "version": "1.0.0",
4
+ "description": "Runtime error monitoring and email reporting for Next.js",
5
+ "license": "ISC",
6
+ "author": "GS",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "type": "commonjs",
10
+ "sideEffects": true,
11
+ "bin": {
12
+ "gs-email-reporter": "./dist/cli/index.js"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "templates",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "prepare": "npm run build"
22
+ },
23
+ "peerDependencies": {
24
+ "next": ">=13",
25
+ "react": ">=18"
26
+ },
27
+ "devDependencies": {
28
+ "@types/nodemailer": "^7.0.9",
29
+ "typescript": "^5.9.3"
30
+ },
31
+ "exports": {
32
+ ".": {
33
+ "require": "./dist/index.js",
34
+ "default": "./dist/index.js"
35
+ },
36
+ "./server": {
37
+ "require": "./dist/core/server/index.js",
38
+ "default": "./dist/core/server/index.js"
39
+ }
40
+ },
41
+ "dependencies": {
42
+ "chalk": "^5.6.2",
43
+ "inquirer": "^13.2.4",
44
+ "nodemailer": "^8.0.1"
45
+ }
46
+ }
@@ -0,0 +1,5 @@
1
+ GS_REPORTER_EMAIL=Sender_Email
2
+ GS_REPORTER_APP_PASSWORD=Sender's_Gmail_App_Password
3
+ GS_REPORTER_RECEIVER=Receiver_Email
4
+ BASE_URL=Domain
5
+ PROJECT_NAME=my-next-app
@@ -0,0 +1,98 @@
1
+ import nodemailer from "nodemailer";
2
+
3
+ /* This route receives error reports from gs-error-reporter
4
+ and emails them to the developer.
5
+ */
6
+
7
+ export default async function handler(req, res) {
8
+ // Ensure we only process POST requests
9
+ if (req.method !== 'POST') {
10
+ return res.status(405).json({ message: 'Method Not Allowed' });
11
+ }
12
+
13
+ try {
14
+ // In Pages router, req.body is already parsed if content-type is application/json
15
+ const payload = req.body;
16
+
17
+ /* ---------- EMAIL SUBJECT ---------- */
18
+
19
+ const projectName = process.env.PROJECT_NAME;
20
+
21
+ const subject = `🚨 [${projectName}] [${payload.payload.type?.toUpperCase()}] ${payload.payload.message || "Unknown Error"}`;
22
+
23
+ /* ---------- HTML FORMATTER ---------- */
24
+
25
+ const html = `
26
+ <body style="font-family: Arial, sans-serif; background:#f4f4f7; padding:20px;">
27
+ <div style="max-width:650px; margin:auto; background:white; border-radius:12px; padding:24px; box-shadow:0 4px 12px rgba(0,0,0,0.08);">
28
+
29
+ <h2 style="color:#d32f2f; margin-top:0;">🚨 GS Error Reporter</h2>
30
+
31
+ <h3>🧠 Error Information</h3>
32
+ <p><strong>Runtime:</strong> ${payload.payload.type}</p>
33
+ <p><strong>Message:</strong> ${payload.payload.message}</p>
34
+ <p><strong>Environment:</strong> ${payload.payload.environment}</p>
35
+ <p><strong>Time:</strong> ${payload.payload.timestamp}</p>
36
+
37
+ <hr/>
38
+
39
+ <h3>🌍 Request Context</h3>
40
+ <p><strong>URL:</strong> ${payload.payload.url || "N/A"}</p>
41
+ <p><strong>Method:</strong> ${payload.payload.method || "N/A"}</p>
42
+
43
+ <hr/>
44
+
45
+ <h3>💻 System Information</h3>
46
+ <p><strong>User Agent:</strong> ${payload.payload.userAgent || "Server Runtime"}</p>
47
+ <p><strong>Language:</strong> ${payload.payload.language || "N/A"}</p>
48
+ <p><strong>Node Version:</strong> ${payload.payload.nodeVersion || "N/A"}</p>
49
+ <p><strong>Platform:</strong> ${payload.payload.platform || "N/A"}</p>
50
+
51
+ <hr/>
52
+
53
+ <h3>📄 Stack Trace</h3>
54
+ <pre style="background:#111; color:#0f0; padding:14px; border-radius:8px; font-size:12px; overflow-x:auto;">
55
+ ${payload.payload.stack || "No stack trace available"}
56
+ </pre>
57
+
58
+ ${payload.payload.extra
59
+ ? `
60
+ <hr/>
61
+ <h3>🧩 Extra Data</h3>
62
+ <pre style="background:#f7f7f7; padding:12px; border-radius:8px; font-size:12px;">
63
+ ${JSON.stringify(payload.payload.extra, null, 2)}
64
+ </pre>`
65
+ : ""
66
+ }
67
+
68
+ <p style="margin-top:30px; font-size:12px; color:#888; text-align:center;">
69
+ Sent automatically by <b>gs-error-reporter</b>
70
+ </p>
71
+
72
+ </div>
73
+ </body>
74
+ `;
75
+
76
+ /* ---------- NODEMAILER ---------- */
77
+
78
+ const transporter = nodemailer.createTransport({
79
+ service: "gmail",
80
+ auth: {
81
+ user: process.env.GS_REPORTER_EMAIL,
82
+ pass: process.env.GS_REPORTER_APP_PASSWORD,
83
+ },
84
+ });
85
+
86
+ await transporter.sendMail({
87
+ from: process.env.GS_REPORTER_EMAIL,
88
+ to: process.env.GS_REPORTER_RECEIVER,
89
+ subject,
90
+ html,
91
+ });
92
+
93
+ return res.status(200).json({ success: true });
94
+ } catch (err) {
95
+ console.error("gs-error-reporter mail route failed:", err);
96
+ return res.status(500).json({ success: false });
97
+ }
98
+ }
@@ -0,0 +1 @@
1
+ import "gs-error-reporter/server";
@@ -0,0 +1,93 @@
1
+ import nodemailer from "nodemailer";
2
+ import { NextResponse } from "next/server";
3
+
4
+ /* This route receives error reports from gs-error-reporter
5
+ and emails them to the developer.
6
+ */
7
+
8
+ export async function POST(req) {
9
+ try {
10
+ const payload = await req.json();
11
+
12
+ /* ---------- EMAIL SUBJECT ---------- */
13
+
14
+ const projectName = process.env.PROJECT_NAME;
15
+
16
+ const subject = `🚨 [${projectName}] [${payload.payload.type?.toUpperCase()}] ${payload.payload.message || "Unknown Error"}`;
17
+
18
+ /* ---------- HTML FORMATTER ---------- */
19
+
20
+ const html = `
21
+ <body style="font-family: Arial, sans-serif; background:#f4f4f7; padding:20px;">
22
+ <div style="max-width:650px; margin:auto; background:white; border-radius:12px; padding:24px; box-shadow:0 4px 12px rgba(0,0,0,0.08);">
23
+
24
+ <h2 style="color:#d32f2f; margin-top:0;">🚨 GS Error Reporter</h2>
25
+
26
+ <h3>🧠 Error Information</h3>
27
+ <p><strong>Runtime:</strong> ${payload.payload.type}</p>
28
+ <p><strong>Message:</strong> ${payload.payload.message}</p>
29
+ <p><strong>Environment:</strong> ${payload.payload.environment}</p>
30
+ <p><strong>Time:</strong> ${payload.payload.timestamp}</p>
31
+
32
+ <hr/>
33
+
34
+ <h3>🌍 Request Context</h3>
35
+ <p><strong>URL:</strong> ${payload.payload.url || "N/A"}</p>
36
+ <p><strong>Method:</strong> ${payload.payload.method || "N/A"}</p>
37
+
38
+ <hr/>
39
+
40
+ <h3>💻 System Information</h3>
41
+ <p><strong>User Agent:</strong> ${payload.payload.userAgent || "Server Runtime"}</p>
42
+ <p><strong>Language:</strong> ${payload.payload.language || "N/A"}</p>
43
+ <p><strong>Node Version:</strong> ${payload.payload.nodeVersion || "N/A"}</p>
44
+ <p><strong>Platform:</strong> ${payload.payload.platform || "N/A"}</p>
45
+
46
+ <hr/>
47
+
48
+ <h3>📄 Stack Trace</h3>
49
+ <pre style="background:#111; color:#0f0; padding:14px; border-radius:8px; font-size:12px; overflow-x:auto;">
50
+ ${payload.payload.stack || "No stack trace available"}
51
+ </pre>
52
+
53
+ ${payload.payload.extra
54
+ ? `
55
+ <hr/>
56
+ <h3>🧩 Extra Data</h3>
57
+ <pre style="background:#f7f7f7; padding:12px; border-radius:8px; font-size:12px;">
58
+ ${JSON.stringify(payload.payload.extra, null, 2)}
59
+ </pre>`
60
+ : ""
61
+ }
62
+
63
+ <p style="margin-top:30px; font-size:12px; color:#888; text-align:center;">
64
+ Sent automatically by <b>gs-error-reporter</b>
65
+ </p>
66
+
67
+ </div>
68
+ </body>
69
+ `;
70
+
71
+ /* ---------- NODEMAILER ---------- */
72
+
73
+ const transporter = nodemailer.createTransport({
74
+ service: "gmail",
75
+ auth: {
76
+ user: process.env.GS_REPORTER_EMAIL,
77
+ pass: process.env.GS_REPORTER_APP_PASSWORD,
78
+ },
79
+ });
80
+
81
+ await transporter.sendMail({
82
+ from: process.env.GS_REPORTER_EMAIL,
83
+ to: process.env.GS_REPORTER_RECEIVER,
84
+ subject,
85
+ html,
86
+ });
87
+
88
+ return NextResponse.json({ success: true });
89
+ } catch (err) {
90
+ console.error("gs-error-reporter mail route failed:", err);
91
+ return NextResponse.json({ success: false }, { status: 500 });
92
+ }
93
+ }
@@ -0,0 +1,100 @@
1
+ // @ts-nocheck
2
+ import nodemailer from "nodemailer";
3
+ import type { NextApiRequest, NextApiResponse } from 'next';
4
+
5
+ /* This route receives error reports from gs-error-reporter
6
+ and emails them to the developer.
7
+ */
8
+
9
+ export default async function handler(req: NextApiRequest, res: NextApiResponse) {
10
+ // Ensure we only process POST requests
11
+ if (req.method !== 'POST') {
12
+ return res.status(405).json({ message: 'Method Not Allowed' });
13
+ }
14
+
15
+ try {
16
+ // In Pages router, req.body is already parsed if content-type is application/json
17
+ const payload = req.body;
18
+
19
+ /* ---------- EMAIL SUBJECT ---------- */
20
+
21
+ const projectName = process.env.PROJECT_NAME;
22
+
23
+ const subject = `🚨 [${projectName}] [${payload.payload.type?.toUpperCase()}] ${payload.payload.message || "Unknown Error"}`;
24
+
25
+ /* ---------- HTML FORMATTER ---------- */
26
+
27
+ const html = `
28
+ <body style="font-family: Arial, sans-serif; background:#f4f4f7; padding:20px;">
29
+ <div style="max-width:650px; margin:auto; background:white; border-radius:12px; padding:24px; box-shadow:0 4px 12px rgba(0,0,0,0.08);">
30
+
31
+ <h2 style="color:#d32f2f; margin-top:0;">🚨 GS Error Reporter</h2>
32
+
33
+ <h3>🧠 Error Information</h3>
34
+ <p><strong>Runtime:</strong> ${payload.payload.type}</p>
35
+ <p><strong>Message:</strong> ${payload.payload.message}</p>
36
+ <p><strong>Environment:</strong> ${payload.payload.environment}</p>
37
+ <p><strong>Time:</strong> ${payload.payload.timestamp}</p>
38
+
39
+ <hr/>
40
+
41
+ <h3>🌍 Request Context</h3>
42
+ <p><strong>URL:</strong> ${payload.payload.url || "N/A"}</p>
43
+ <p><strong>Method:</strong> ${payload.payload.method || "N/A"}</p>
44
+
45
+ <hr/>
46
+
47
+ <h3>💻 System Information</h3>
48
+ <p><strong>User Agent:</strong> ${payload.payload.userAgent || "Server Runtime"}</p>
49
+ <p><strong>Language:</strong> ${payload.payload.language || "N/A"}</p>
50
+ <p><strong>Node Version:</strong> ${payload.payload.nodeVersion || "N/A"}</p>
51
+ <p><strong>Platform:</strong> ${payload.payload.platform || "N/A"}</p>
52
+
53
+ <hr/>
54
+
55
+ <h3>📄 Stack Trace</h3>
56
+ <pre style="background:#111; color:#0f0; padding:14px; border-radius:8px; font-size:12px; overflow-x:auto;">
57
+ ${payload.payload.stack || "No stack trace available"}
58
+ </pre>
59
+
60
+ ${payload.payload.extra
61
+ ? `
62
+ <hr/>
63
+ <h3>🧩 Extra Data</h3>
64
+ <pre style="background:#f7f7f7; padding:12px; border-radius:8px; font-size:12px;">
65
+ ${JSON.stringify(payload.payload.extra, null, 2)}
66
+ </pre>`
67
+ : ""
68
+ }
69
+
70
+ <p style="margin-top:30px; font-size:12px; color:#888; text-align:center;">
71
+ Sent automatically by <b>gs-error-reporter</b>
72
+ </p>
73
+
74
+ </div>
75
+ </body>
76
+ `;
77
+
78
+ /* ---------- NODEMAILER ---------- */
79
+
80
+ const transporter = nodemailer.createTransport({
81
+ service: "gmail",
82
+ auth: {
83
+ user: process.env.GS_REPORTER_EMAIL,
84
+ pass: process.env.GS_REPORTER_APP_PASSWORD,
85
+ },
86
+ });
87
+
88
+ await transporter.sendMail({
89
+ from: process.env.GS_REPORTER_EMAIL,
90
+ to: process.env.GS_REPORTER_RECEIVER,
91
+ subject,
92
+ html,
93
+ });
94
+
95
+ return res.status(200).json({ success: true });
96
+ } catch (err: any) {
97
+ console.error("gs-error-reporter mail route failed:", err);
98
+ return res.status(500).json({ success: false });
99
+ }
100
+ }
@@ -0,0 +1 @@
1
+ import "gs-error-reporter/server";
@@ -0,0 +1,99 @@
1
+ // @ts-nocheck
2
+
3
+ import nodemailer from "nodemailer";
4
+ import { NextRequest, NextResponse } from "next/server";
5
+
6
+ /*
7
+ This route receives error reports from gs-error-reporter
8
+ and emails them to the developer.
9
+ */
10
+
11
+ export async function POST(req: NextRequest) {
12
+ try {
13
+ const payload = await req.json();
14
+
15
+ /* ---------- EMAIL SUBJECT ---------- */
16
+
17
+ const projectName = process.env.PROJECT_NAME;
18
+
19
+ const subject = `🚨 [${projectName}] [${payload.payload.type?.toUpperCase()}] ${payload.payload.message || "Unknown Error"}`;
20
+
21
+ /* ---------- HTML FORMATTER ---------- */
22
+
23
+ const html = `
24
+ <body style="font-family: Arial, sans-serif; background:#f4f4f7; padding:20px;">
25
+ <div style="max-width:650px; margin:auto; background:white; border-radius:12px; padding:24px; box-shadow:0 4px 12px rgba(0,0,0,0.08);">
26
+
27
+ <h2 style="color:#d32f2f; margin-top:0;">🚨 GS Error Reporter</h2>
28
+
29
+ <h3>📦 Project</h3>
30
+ <p><strong>Name:</strong> ${projectName}</p>
31
+
32
+ <h3>🧠 Error Information</h3>
33
+ <p><strong>Runtime:</strong> ${payload.payload.type}</p>
34
+ <p><strong>Message:</strong> ${payload.payload.message}</p>
35
+ <p><strong>Environment:</strong> ${payload.payload.environment}</p>
36
+ <p><strong>Time:</strong> ${payload.payload.timestamp}</p>
37
+
38
+ <hr/>
39
+
40
+ <h3>🌍 Request Context</h3>
41
+ <p><strong>URL:</strong> ${payload.payload.url || "N/A"}</p>
42
+ <p><strong>Method:</strong> ${payload.payload.method || "N/A"}</p>
43
+
44
+ <hr/>
45
+
46
+ <h3>💻 System Information</h3>
47
+ <p><strong>User Agent:</strong> ${payload.payload.userAgent || "Server Runtime"}</p>
48
+ <p><strong>Language:</strong> ${payload.payload.language || "N/A"}</p>
49
+ <p><strong>Node Version:</strong> ${payload.payload.nodeVersion || "N/A"}</p>
50
+ <p><strong>Platform:</strong> ${payload.payload.platform || "N/A"}</p>
51
+
52
+ <hr/>
53
+
54
+ <h3>📄 Stack Trace</h3>
55
+ <pre style="background:#111; color:#0f0; padding:14px; border-radius:8px; font-size:12px; overflow-x:auto;">
56
+ ${payload.payload.stack || "No stack trace available"}
57
+ </pre>
58
+
59
+ ${payload.payload.extra
60
+ ? `
61
+ <hr/>
62
+ <h3>🧩 Extra Data</h3>
63
+ <pre style="background:#f7f7f7; padding:12px; border-radius:8px; font-size:12px;">
64
+ ${JSON.stringify(payload.payload.extra, null, 2)}
65
+ </pre>`
66
+ : ""
67
+ }
68
+
69
+ <p style="margin-top:30px; font-size:12px; color:#888; text-align:center;">
70
+ Sent automatically by <b>gs-error-reporter</b>
71
+ </p>
72
+
73
+ </div>
74
+ </body>
75
+ `;
76
+
77
+ /* ---------- NODEMAILER ---------- */
78
+
79
+ const transporter = nodemailer.createTransport({
80
+ service: "gmail",
81
+ auth: {
82
+ user: process.env.GS_REPORTER_EMAIL,
83
+ pass: process.env.GS_REPORTER_APP_PASSWORD,
84
+ },
85
+ });
86
+
87
+ await transporter.sendMail({
88
+ from: process.env.GS_REPORTER_EMAIL,
89
+ to: process.env.GS_REPORTER_RECEIVER,
90
+ subject,
91
+ html,
92
+ });
93
+
94
+ return NextResponse.json({ success: true });
95
+ } catch (err: any) {
96
+ console.error("gs-error-reporter mail route failed:", err);
97
+ return NextResponse.json({ success: false }, { status: 500 });
98
+ }
99
+ }