@geekmidas/telescope 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +521 -0
  2. package/dist/Telescope-B3Wd82yk.cjs +602 -0
  3. package/dist/Telescope-B3Wd82yk.cjs.map +1 -0
  4. package/dist/Telescope-C5dyDYYB.d.cts +133 -0
  5. package/dist/Telescope-D-uoZB6b.mjs +596 -0
  6. package/dist/Telescope-D-uoZB6b.mjs.map +1 -0
  7. package/dist/Telescope-DyIWgh9-.d.mts +133 -0
  8. package/dist/Telescope.cjs +3 -0
  9. package/dist/Telescope.d.cts +3 -0
  10. package/dist/Telescope.d.mts +3 -0
  11. package/dist/Telescope.mjs +3 -0
  12. package/dist/chunk-CUT6urMc.cjs +30 -0
  13. package/dist/index.cjs +5 -0
  14. package/dist/index.d.cts +4 -0
  15. package/dist/index.d.mts +4 -0
  16. package/dist/index.mjs +4 -0
  17. package/dist/logger/console.cjs +161 -0
  18. package/dist/logger/console.cjs.map +1 -0
  19. package/dist/logger/console.d.cts +109 -0
  20. package/dist/logger/console.d.mts +109 -0
  21. package/dist/logger/console.mjs +159 -0
  22. package/dist/logger/console.mjs.map +1 -0
  23. package/dist/logger/pino.cjs +118 -0
  24. package/dist/logger/pino.cjs.map +1 -0
  25. package/dist/logger/pino.d.cts +89 -0
  26. package/dist/logger/pino.d.mts +89 -0
  27. package/dist/logger/pino.mjs +116 -0
  28. package/dist/logger/pino.mjs.map +1 -0
  29. package/dist/memory-9-B9WACq.cjs +110 -0
  30. package/dist/memory-9-B9WACq.cjs.map +1 -0
  31. package/dist/memory-Cm0eevCS.d.mts +38 -0
  32. package/dist/memory-DiP1a-pp.d.cts +38 -0
  33. package/dist/memory-SdN5vtG9.mjs +104 -0
  34. package/dist/memory-SdN5vtG9.mjs.map +1 -0
  35. package/dist/server/hono.cjs +180 -0
  36. package/dist/server/hono.cjs.map +1 -0
  37. package/dist/server/hono.d.cts +26 -0
  38. package/dist/server/hono.d.mts +26 -0
  39. package/dist/server/hono.mjs +176 -0
  40. package/dist/server/hono.mjs.map +1 -0
  41. package/dist/storage/kysely.cjs +336 -0
  42. package/dist/storage/kysely.cjs.map +1 -0
  43. package/dist/storage/kysely.d.cts +161 -0
  44. package/dist/storage/kysely.d.mts +161 -0
  45. package/dist/storage/kysely.mjs +334 -0
  46. package/dist/storage/kysely.mjs.map +1 -0
  47. package/dist/storage/memory.cjs +3 -0
  48. package/dist/storage/memory.d.cts +3 -0
  49. package/dist/storage/memory.d.mts +3 -0
  50. package/dist/storage/memory.mjs +3 -0
  51. package/dist/types-BGDhFv4R.d.cts +170 -0
  52. package/dist/types-CZbzz8kx.d.mts +170 -0
  53. package/dist/types.cjs +0 -0
  54. package/dist/types.d.cts +2 -0
  55. package/dist/types.d.mts +2 -0
  56. package/dist/types.mjs +0 -0
  57. package/dist/ui-assets-D6-8TAr_.mjs +30 -0
  58. package/dist/ui-assets-D6-8TAr_.mjs.map +1 -0
  59. package/dist/ui-assets-ulevVble.cjs +48 -0
  60. package/dist/ui-assets-ulevVble.cjs.map +1 -0
  61. package/dist/ui-assets.cjs +5 -0
  62. package/dist/ui-assets.d.cts +12 -0
  63. package/dist/ui-assets.d.mts +12 -0
  64. package/dist/ui-assets.mjs +3 -0
  65. package/package.json +83 -0
  66. package/scripts/embed-ui.ts +90 -0
  67. package/src/Telescope.ts +714 -0
  68. package/src/__tests__/Telescope.spec.ts +356 -0
  69. package/src/index.ts +23 -0
  70. package/src/logger/__tests__/console.spec.ts +266 -0
  71. package/src/logger/__tests__/pino.spec.ts +217 -0
  72. package/src/logger/console.ts +230 -0
  73. package/src/logger/pino.ts +191 -0
  74. package/src/server/__tests__/hono.spec.ts +340 -0
  75. package/src/server/hono.ts +247 -0
  76. package/src/storage/__tests__/kysely.spec.ts +715 -0
  77. package/src/storage/__tests__/memory.spec.ts +411 -0
  78. package/src/storage/kysely.ts +572 -0
  79. package/src/storage/memory.ts +168 -0
  80. package/src/types.ts +188 -0
  81. package/src/ui-assets.ts +40 -0
  82. package/ui/index.html +12 -0
  83. package/ui/node_modules/.bin/browserslist +21 -0
  84. package/ui/node_modules/.bin/jiti +21 -0
  85. package/ui/node_modules/.bin/terser +21 -0
  86. package/ui/node_modules/.bin/tsc +21 -0
  87. package/ui/node_modules/.bin/tsserver +21 -0
  88. package/ui/node_modules/.bin/tsx +21 -0
  89. package/ui/node_modules/.bin/vite +21 -0
  90. package/ui/package.json +24 -0
  91. package/ui/src/App.tsx +342 -0
  92. package/ui/src/api.ts +75 -0
  93. package/ui/src/components/ExceptionDetail.tsx +100 -0
  94. package/ui/src/components/LogDetail.tsx +91 -0
  95. package/ui/src/components/RequestDetail.tsx +143 -0
  96. package/ui/src/main.tsx +10 -0
  97. package/ui/src/styles.css +10 -0
  98. package/ui/src/types.ts +63 -0
  99. package/ui/src/vite-env.d.ts +1 -0
  100. package/ui/src/vite-plugin-gkm-config.ts +54 -0
  101. package/ui/tsconfig.json +20 -0
  102. package/ui/tsconfig.tsbuildinfo +14 -0
  103. package/ui/vite.config.ts +13 -0
@@ -0,0 +1,159 @@
1
+ //#region src/logger/console.ts
2
+ /**
3
+ * A logger that sends logs to both Telescope and an optional underlying logger.
4
+ * Implements the Logger interface from @geekmidas/logger.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
9
+ * import { TelescopeLogger } from '@geekmidas/telescope/logger/console';
10
+ * import { ConsoleLogger } from '@geekmidas/logger/console';
11
+ *
12
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
13
+ *
14
+ * // With underlying logger (logs to both console and Telescope)
15
+ * const logger = new TelescopeLogger({
16
+ * telescope,
17
+ * logger: new ConsoleLogger({ app: 'myApp' }),
18
+ * });
19
+ *
20
+ * // Without underlying logger (logs only to Telescope)
21
+ * const telescopeOnly = new TelescopeLogger({ telescope });
22
+ *
23
+ * // Usage
24
+ * logger.info({ userId: '123' }, 'User logged in');
25
+ * logger.error({ error: 'Something failed' }, 'Operation failed');
26
+ * ```
27
+ */
28
+ var TelescopeLogger = class TelescopeLogger {
29
+ telescope;
30
+ logger;
31
+ requestId;
32
+ context;
33
+ constructor(options) {
34
+ this.telescope = options.telescope;
35
+ this.logger = options.logger;
36
+ this.requestId = options.requestId;
37
+ this.context = options.context ?? {};
38
+ }
39
+ createLogFn(level) {
40
+ const fn = (objOrMsg, msg, ...args) => {
41
+ let context;
42
+ let message;
43
+ if (typeof objOrMsg === "string") {
44
+ context = { ...this.context };
45
+ message = objOrMsg;
46
+ } else {
47
+ context = {
48
+ ...this.context,
49
+ ...objOrMsg
50
+ };
51
+ message = msg ?? "";
52
+ }
53
+ if (this.logger) if (typeof objOrMsg === "string") this.logger[level](objOrMsg);
54
+ else this.logger[level](objOrMsg, msg, ...args);
55
+ this.telescope[level](message, context, this.requestId).catch(() => {});
56
+ };
57
+ return fn;
58
+ }
59
+ debug = this.createLogFn("debug");
60
+ info = this.createLogFn("info");
61
+ warn = this.createLogFn("warn");
62
+ error = this.createLogFn("error");
63
+ fatal = (objOrMsg, msg, ...args) => {
64
+ if (this.logger) if (typeof objOrMsg === "string") this.logger.fatal(objOrMsg);
65
+ else this.logger.fatal(objOrMsg, msg, ...args);
66
+ let context;
67
+ let message;
68
+ if (typeof objOrMsg === "string") {
69
+ context = {
70
+ ...this.context,
71
+ level: "fatal"
72
+ };
73
+ message = objOrMsg;
74
+ } else {
75
+ context = {
76
+ ...this.context,
77
+ ...objOrMsg,
78
+ level: "fatal"
79
+ };
80
+ message = msg ?? "";
81
+ }
82
+ this.telescope.error(message, context, this.requestId).catch(() => {});
83
+ };
84
+ trace = (objOrMsg, msg, ...args) => {
85
+ if (this.logger) if (typeof objOrMsg === "string") this.logger.trace(objOrMsg);
86
+ else this.logger.trace(objOrMsg, msg, ...args);
87
+ let context;
88
+ let message;
89
+ if (typeof objOrMsg === "string") {
90
+ context = {
91
+ ...this.context,
92
+ level: "trace"
93
+ };
94
+ message = objOrMsg;
95
+ } else {
96
+ context = {
97
+ ...this.context,
98
+ ...objOrMsg,
99
+ level: "trace"
100
+ };
101
+ message = msg ?? "";
102
+ }
103
+ this.telescope.debug(message, context, this.requestId).catch(() => {});
104
+ };
105
+ /**
106
+ * Creates a child logger with additional context.
107
+ * The child logger inherits all context from the parent.
108
+ */
109
+ child(obj) {
110
+ return new TelescopeLogger({
111
+ telescope: this.telescope,
112
+ logger: this.logger?.child(obj),
113
+ requestId: this.requestId,
114
+ context: {
115
+ ...this.context,
116
+ ...obj
117
+ }
118
+ });
119
+ }
120
+ /**
121
+ * Create a child logger bound to a specific request ID.
122
+ * Useful for correlating logs with HTTP requests.
123
+ */
124
+ withRequestId(requestId) {
125
+ return new TelescopeLogger({
126
+ telescope: this.telescope,
127
+ logger: this.logger,
128
+ requestId,
129
+ context: this.context
130
+ });
131
+ }
132
+ };
133
+ /**
134
+ * Create a logger that sends logs to Telescope.
135
+ * Convenience function for creating a TelescopeLogger.
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * import { createTelescopeLogger } from '@geekmidas/telescope/logger/console';
140
+ * import { ConsoleLogger } from '@geekmidas/logger/console';
141
+ *
142
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
143
+ * const baseLogger = new ConsoleLogger({ app: 'myApp' });
144
+ *
145
+ * const logger = createTelescopeLogger(telescope, baseLogger);
146
+ * logger.info({ action: 'startup' }, 'Application started');
147
+ * ```
148
+ */
149
+ function createTelescopeLogger(telescope, logger, context) {
150
+ return new TelescopeLogger({
151
+ telescope,
152
+ logger,
153
+ context
154
+ });
155
+ }
156
+
157
+ //#endregion
158
+ export { TelescopeLogger, createTelescopeLogger };
159
+ //# sourceMappingURL=console.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.mjs","names":["options: TelescopeLoggerOptions","level: LogLevel","objOrMsg: T | string","msg?: string","context: Record<string, unknown>","message: string","objOrMsg: object | string","obj: object","requestId: string","telescope: Telescope","logger?: Logger","context?: Record<string, unknown>"],"sources":["../../src/logger/console.ts"],"sourcesContent":["import type { Telescope } from '../Telescope';\n\n/**\n * Logger interface matching @geekmidas/logger\n */\nexport interface Logger {\n debug: LogFn;\n info: LogFn;\n warn: LogFn;\n error: LogFn;\n fatal: LogFn;\n trace: LogFn;\n child: (obj: object) => Logger;\n}\n\nexport type LogFn = {\n <T extends object>(obj: T, msg?: string, ...args: any[]): void;\n (msg: string): void;\n};\n\nexport interface TelescopeLoggerOptions {\n /**\n * The Telescope instance to send logs to\n */\n telescope: Telescope;\n /**\n * Optional underlying logger to also forward logs to.\n * If not provided, logs will only go to Telescope.\n */\n logger?: Logger;\n /**\n * Request ID to associate logs with a specific request.\n */\n requestId?: string;\n /**\n * Initial context data to include in all log messages\n */\n context?: Record<string, unknown>;\n}\n\ntype LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/**\n * A logger that sends logs to both Telescope and an optional underlying logger.\n * Implements the Logger interface from @geekmidas/logger.\n *\n * @example\n * ```typescript\n * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';\n * import { TelescopeLogger } from '@geekmidas/telescope/logger/console';\n * import { ConsoleLogger } from '@geekmidas/logger/console';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n *\n * // With underlying logger (logs to both console and Telescope)\n * const logger = new TelescopeLogger({\n * telescope,\n * logger: new ConsoleLogger({ app: 'myApp' }),\n * });\n *\n * // Without underlying logger (logs only to Telescope)\n * const telescopeOnly = new TelescopeLogger({ telescope });\n *\n * // Usage\n * logger.info({ userId: '123' }, 'User logged in');\n * logger.error({ error: 'Something failed' }, 'Operation failed');\n * ```\n */\nexport class TelescopeLogger implements Logger {\n private telescope: Telescope;\n private logger?: Logger;\n private requestId?: string;\n private context: Record<string, unknown>;\n\n constructor(options: TelescopeLoggerOptions) {\n this.telescope = options.telescope;\n this.logger = options.logger;\n this.requestId = options.requestId;\n this.context = options.context ?? {};\n }\n\n private createLogFn(level: LogLevel): LogFn {\n const fn = <T extends object>(\n objOrMsg: T | string,\n msg?: string,\n ...args: any[]\n ): void => {\n let context: Record<string, unknown>;\n let message: string;\n\n if (typeof objOrMsg === 'string') {\n context = { ...this.context };\n message = objOrMsg;\n } else {\n context = { ...this.context, ...objOrMsg };\n message = msg ?? '';\n }\n\n // Forward to underlying logger if present\n if (this.logger) {\n if (typeof objOrMsg === 'string') {\n this.logger[level](objOrMsg);\n } else {\n this.logger[level](objOrMsg as any, msg, ...args);\n }\n }\n\n // Send to Telescope (fire and forget)\n this.telescope[level](message, context, this.requestId).catch(() => {});\n };\n\n return fn as LogFn;\n }\n\n debug: LogFn = this.createLogFn('debug');\n info: LogFn = this.createLogFn('info');\n warn: LogFn = this.createLogFn('warn');\n error: LogFn = this.createLogFn('error');\n\n // Map fatal and trace to error and debug for Telescope\n fatal: LogFn = ((\n objOrMsg: object | string,\n msg?: string,\n ...args: any[]\n ): void => {\n // Forward to underlying logger if present\n if (this.logger) {\n if (typeof objOrMsg === 'string') {\n this.logger.fatal(objOrMsg);\n } else {\n this.logger.fatal(objOrMsg as any, msg, ...args);\n }\n }\n\n // Send to Telescope as error level\n let context: Record<string, unknown>;\n let message: string;\n\n if (typeof objOrMsg === 'string') {\n context = { ...this.context, level: 'fatal' };\n message = objOrMsg;\n } else {\n context = { ...this.context, ...objOrMsg, level: 'fatal' };\n message = msg ?? '';\n }\n\n this.telescope.error(message, context, this.requestId).catch(() => {});\n }) as LogFn;\n\n trace: LogFn = ((\n objOrMsg: object | string,\n msg?: string,\n ...args: any[]\n ): void => {\n // Forward to underlying logger if present\n if (this.logger) {\n if (typeof objOrMsg === 'string') {\n this.logger.trace(objOrMsg);\n } else {\n this.logger.trace(objOrMsg as any, msg, ...args);\n }\n }\n\n // Send to Telescope as debug level\n let context: Record<string, unknown>;\n let message: string;\n\n if (typeof objOrMsg === 'string') {\n context = { ...this.context, level: 'trace' };\n message = objOrMsg;\n } else {\n context = { ...this.context, ...objOrMsg, level: 'trace' };\n message = msg ?? '';\n }\n\n this.telescope.debug(message, context, this.requestId).catch(() => {});\n }) as LogFn;\n\n /**\n * Creates a child logger with additional context.\n * The child logger inherits all context from the parent.\n */\n child(obj: object): Logger {\n return new TelescopeLogger({\n telescope: this.telescope,\n logger: this.logger?.child(obj),\n requestId: this.requestId,\n context: { ...this.context, ...obj },\n });\n }\n\n /**\n * Create a child logger bound to a specific request ID.\n * Useful for correlating logs with HTTP requests.\n */\n withRequestId(requestId: string): TelescopeLogger {\n return new TelescopeLogger({\n telescope: this.telescope,\n logger: this.logger,\n requestId,\n context: this.context,\n });\n }\n}\n\n/**\n * Create a logger that sends logs to Telescope.\n * Convenience function for creating a TelescopeLogger.\n *\n * @example\n * ```typescript\n * import { createTelescopeLogger } from '@geekmidas/telescope/logger/console';\n * import { ConsoleLogger } from '@geekmidas/logger/console';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n * const baseLogger = new ConsoleLogger({ app: 'myApp' });\n *\n * const logger = createTelescopeLogger(telescope, baseLogger);\n * logger.info({ action: 'startup' }, 'Application started');\n * ```\n */\nexport function createTelescopeLogger(\n telescope: Telescope,\n logger?: Logger,\n context?: Record<string, unknown>,\n): TelescopeLogger {\n return new TelescopeLogger({ telescope, logger, context });\n}\n\nexport type { Telescope };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,IAAa,kBAAb,MAAa,gBAAkC;CAC7C,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAYA,SAAiC;AAC3C,OAAK,YAAY,QAAQ;AACzB,OAAK,SAAS,QAAQ;AACtB,OAAK,YAAY,QAAQ;AACzB,OAAK,UAAU,QAAQ,WAAW,CAAE;CACrC;CAED,AAAQ,YAAYC,OAAwB;EAC1C,MAAM,KAAK,CACTC,UACAC,KACA,GAAG,SACM;GACT,IAAIC;GACJ,IAAIC;AAEJ,cAAW,aAAa,UAAU;AAChC,cAAU,EAAE,GAAG,KAAK,QAAS;AAC7B,cAAU;GACX,OAAM;AACL,cAAU;KAAE,GAAG,KAAK;KAAS,GAAG;IAAU;AAC1C,cAAU,OAAO;GAClB;AAGD,OAAI,KAAK,OACP,YAAW,aAAa,SACtB,MAAK,OAAO,OAAO,SAAS;OAE5B,MAAK,OAAO,OAAO,UAAiB,KAAK,GAAG,KAAK;AAKrD,QAAK,UAAU,OAAO,SAAS,SAAS,KAAK,UAAU,CAAC,MAAM,MAAM,CAAE,EAAC;EACxE;AAED,SAAO;CACR;CAED,QAAe,KAAK,YAAY,QAAQ;CACxC,OAAc,KAAK,YAAY,OAAO;CACtC,OAAc,KAAK,YAAY,OAAO;CACtC,QAAe,KAAK,YAAY,QAAQ;CAGxC,QAAgB,CACdC,UACAH,KACA,GAAG,SACM;AAET,MAAI,KAAK,OACP,YAAW,aAAa,SACtB,MAAK,OAAO,MAAM,SAAS;MAE3B,MAAK,OAAO,MAAM,UAAiB,KAAK,GAAG,KAAK;EAKpD,IAAIC;EACJ,IAAIC;AAEJ,aAAW,aAAa,UAAU;AAChC,aAAU;IAAE,GAAG,KAAK;IAAS,OAAO;GAAS;AAC7C,aAAU;EACX,OAAM;AACL,aAAU;IAAE,GAAG,KAAK;IAAS,GAAG;IAAU,OAAO;GAAS;AAC1D,aAAU,OAAO;EAClB;AAED,OAAK,UAAU,MAAM,SAAS,SAAS,KAAK,UAAU,CAAC,MAAM,MAAM,CAAE,EAAC;CACvE;CAED,QAAgB,CACdC,UACAH,KACA,GAAG,SACM;AAET,MAAI,KAAK,OACP,YAAW,aAAa,SACtB,MAAK,OAAO,MAAM,SAAS;MAE3B,MAAK,OAAO,MAAM,UAAiB,KAAK,GAAG,KAAK;EAKpD,IAAIC;EACJ,IAAIC;AAEJ,aAAW,aAAa,UAAU;AAChC,aAAU;IAAE,GAAG,KAAK;IAAS,OAAO;GAAS;AAC7C,aAAU;EACX,OAAM;AACL,aAAU;IAAE,GAAG,KAAK;IAAS,GAAG;IAAU,OAAO;GAAS;AAC1D,aAAU,OAAO;EAClB;AAED,OAAK,UAAU,MAAM,SAAS,SAAS,KAAK,UAAU,CAAC,MAAM,MAAM,CAAE,EAAC;CACvE;;;;;CAMD,MAAME,KAAqB;AACzB,SAAO,IAAI,gBAAgB;GACzB,WAAW,KAAK;GAChB,QAAQ,KAAK,QAAQ,MAAM,IAAI;GAC/B,WAAW,KAAK;GAChB,SAAS;IAAE,GAAG,KAAK;IAAS,GAAG;GAAK;EACrC;CACF;;;;;CAMD,cAAcC,WAAoC;AAChD,SAAO,IAAI,gBAAgB;GACzB,WAAW,KAAK;GAChB,QAAQ,KAAK;GACb;GACA,SAAS,KAAK;EACf;CACF;AACF;;;;;;;;;;;;;;;;;AAkBD,SAAgB,sBACdC,WACAC,QACAC,SACiB;AACjB,QAAO,IAAI,gBAAgB;EAAE;EAAW;EAAQ;CAAS;AAC1D"}
@@ -0,0 +1,118 @@
1
+ const require_chunk = require('../chunk-CUT6urMc.cjs');
2
+ const pino_abstract_transport = require_chunk.__toESM(require("pino-abstract-transport"));
3
+
4
+ //#region src/logger/pino.ts
5
+ /**
6
+ * Map Pino numeric levels to Telescope log levels
7
+ */
8
+ function mapPinoLevel(level) {
9
+ if (level <= 20) return "debug";
10
+ if (level <= 30) return "info";
11
+ if (level <= 40) return "warn";
12
+ return "error";
13
+ }
14
+ /**
15
+ * Create a Pino transport that sends logs to Telescope.
16
+ *
17
+ * Uses pino-abstract-transport for proper async iteration and backpressure handling.
18
+ * Logs are batched for performance and flushed either when the batch is full
19
+ * or after the flush interval.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import pino from 'pino';
24
+ * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
25
+ * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';
26
+ *
27
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
28
+ *
29
+ * // Use with pino.multistream to log to both stdout and Telescope
30
+ * const logger = pino(
31
+ * { level: 'debug' },
32
+ * pino.multistream([
33
+ * { stream: process.stdout },
34
+ * { stream: createPinoTransport({ telescope }) }
35
+ * ])
36
+ * );
37
+ *
38
+ * logger.info({ userId: '123' }, 'User logged in');
39
+ * ```
40
+ */
41
+ function createPinoTransport(options) {
42
+ const { telescope, requestId, batchSize = 100, flushIntervalMs = 1e3 } = options;
43
+ const batch = [];
44
+ let flushTimer = null;
45
+ async function flush() {
46
+ if (batch.length === 0) return;
47
+ const toFlush = batch.splice(0, batch.length);
48
+ try {
49
+ await telescope.log(toFlush);
50
+ } catch {}
51
+ }
52
+ function scheduleFlush() {
53
+ if (flushTimer === null) flushTimer = setTimeout(() => {
54
+ flushTimer = null;
55
+ flush().catch(() => {});
56
+ }, flushIntervalMs);
57
+ }
58
+ function clearFlushTimer() {
59
+ if (flushTimer !== null) {
60
+ clearTimeout(flushTimer);
61
+ flushTimer = null;
62
+ }
63
+ }
64
+ return (0, pino_abstract_transport.default)(async (source) => {
65
+ for await (const obj of source) {
66
+ const data = obj;
67
+ const { level, msg, time, pid, hostname,...context } = data;
68
+ const telescopeLevel = mapPinoLevel(level);
69
+ let reqId;
70
+ if (typeof requestId === "function") reqId = requestId(data);
71
+ else if (typeof requestId === "string") reqId = requestId;
72
+ else if (typeof context.requestId === "string") {
73
+ reqId = context.requestId;
74
+ delete context.requestId;
75
+ }
76
+ batch.push({
77
+ level: telescopeLevel,
78
+ message: msg || "",
79
+ context,
80
+ requestId: reqId
81
+ });
82
+ if (batch.length >= batchSize) {
83
+ clearFlushTimer();
84
+ await flush();
85
+ } else scheduleFlush();
86
+ }
87
+ }, { async close() {
88
+ clearFlushTimer();
89
+ await flush();
90
+ } });
91
+ }
92
+ /**
93
+ * Create a Pino destination that sends logs to Telescope.
94
+ * Alias for createPinoTransport for API compatibility.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * import pino from 'pino';
99
+ * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';
100
+ *
101
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
102
+ *
103
+ * // Use with pino.multistream to log to both stdout and Telescope
104
+ * const logger = pino(
105
+ * { level: 'debug' },
106
+ * pino.multistream([
107
+ * { stream: process.stdout },
108
+ * { stream: createPinoDestination({ telescope }) }
109
+ * ])
110
+ * );
111
+ * ```
112
+ */
113
+ const createPinoDestination = createPinoTransport;
114
+
115
+ //#endregion
116
+ exports.createPinoDestination = createPinoDestination;
117
+ exports.createPinoTransport = createPinoTransport;
118
+ //# sourceMappingURL=pino.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino.cjs","names":["level: number","options: TelescopePinoTransportOptions","batch: LogBatch[]","flushTimer: ReturnType<typeof setTimeout> | null","reqId: string | undefined"],"sources":["../../src/logger/pino.ts"],"sourcesContent":["import build from 'pino-abstract-transport';\nimport type { Telescope } from '../Telescope';\n\n/**\n * Pino log object structure after parsing\n */\nexport interface PinoLogObject {\n level: number;\n time: number;\n pid?: number;\n hostname?: string;\n msg?: string;\n [key: string]: unknown;\n}\n\nexport interface TelescopePinoTransportOptions {\n /**\n * The Telescope instance to send logs to\n */\n telescope: Telescope;\n /**\n * Request ID to associate logs with a specific request.\n * Can be a static string or a function that extracts the ID from log data.\n */\n requestId?: string | ((data: PinoLogObject) => string | undefined);\n /**\n * Batch size before flushing to Telescope (default: 100)\n */\n batchSize?: number;\n /**\n * Flush interval in milliseconds (default: 1000ms)\n */\n flushIntervalMs?: number;\n}\n\ntype TelescopeLogLevel = 'debug' | 'info' | 'warn' | 'error';\n\ninterface LogBatch {\n level: TelescopeLogLevel;\n message: string;\n context: Record<string, unknown>;\n requestId?: string;\n}\n\n/**\n * Map Pino numeric levels to Telescope log levels\n */\nfunction mapPinoLevel(level: number): TelescopeLogLevel {\n // Pino levels: trace=10, debug=20, info=30, warn=40, error=50, fatal=60\n if (level <= 20) return 'debug'; // trace, debug\n if (level <= 30) return 'info';\n if (level <= 40) return 'warn';\n return 'error'; // error, fatal\n}\n\n/**\n * Create a Pino transport that sends logs to Telescope.\n *\n * Uses pino-abstract-transport for proper async iteration and backpressure handling.\n * Logs are batched for performance and flushed either when the batch is full\n * or after the flush interval.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';\n * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n *\n * // Use with pino.multistream to log to both stdout and Telescope\n * const logger = pino(\n * { level: 'debug' },\n * pino.multistream([\n * { stream: process.stdout },\n * { stream: createPinoTransport({ telescope }) }\n * ])\n * );\n *\n * logger.info({ userId: '123' }, 'User logged in');\n * ```\n */\nexport function createPinoTransport(options: TelescopePinoTransportOptions) {\n const {\n telescope,\n requestId,\n batchSize = 100,\n flushIntervalMs = 1000,\n } = options;\n\n const batch: LogBatch[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n async function flush(): Promise<void> {\n if (batch.length === 0) return;\n\n const toFlush = batch.splice(0, batch.length);\n\n // Use batch insert for better performance\n try {\n await telescope.log(toFlush);\n } catch {\n // Silently ignore errors to not break logging\n }\n }\n\n function scheduleFlush(): void {\n if (flushTimer === null) {\n flushTimer = setTimeout(() => {\n flushTimer = null;\n flush().catch(() => {\n // Silently ignore flush errors\n });\n }, flushIntervalMs);\n }\n }\n\n function clearFlushTimer(): void {\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n }\n\n return build(\n async (source) => {\n for await (const obj of source) {\n const data = obj as PinoLogObject;\n const { level, msg, time, pid, hostname, ...context } = data;\n\n const telescopeLevel = mapPinoLevel(level);\n\n // Extract request ID\n let reqId: string | undefined;\n if (typeof requestId === 'function') {\n reqId = requestId(data);\n } else if (typeof requestId === 'string') {\n reqId = requestId;\n } else if (typeof context.requestId === 'string') {\n reqId = context.requestId;\n delete context.requestId;\n }\n\n batch.push({\n level: telescopeLevel,\n message: msg || '',\n context,\n requestId: reqId,\n });\n\n if (batch.length >= batchSize) {\n clearFlushTimer();\n await flush();\n } else {\n scheduleFlush();\n }\n }\n },\n {\n async close() {\n clearFlushTimer();\n await flush();\n },\n },\n );\n}\n\n/**\n * Create a Pino destination that sends logs to Telescope.\n * Alias for createPinoTransport for API compatibility.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n *\n * // Use with pino.multistream to log to both stdout and Telescope\n * const logger = pino(\n * { level: 'debug' },\n * pino.multistream([\n * { stream: process.stdout },\n * { stream: createPinoDestination({ telescope }) }\n * ])\n * );\n * ```\n */\nexport const createPinoDestination = createPinoTransport;\n\nexport type { Telescope };\n"],"mappings":";;;;;;;AA+CA,SAAS,aAAaA,OAAkC;AAEtD,KAAI,SAAS,GAAI,QAAO;AACxB,KAAI,SAAS,GAAI,QAAO;AACxB,KAAI,SAAS,GAAI,QAAO;AACxB,QAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BD,SAAgB,oBAAoBC,SAAwC;CAC1E,MAAM,EACJ,WACA,WACA,YAAY,KACZ,kBAAkB,KACnB,GAAG;CAEJ,MAAMC,QAAoB,CAAE;CAC5B,IAAIC,aAAmD;CAEvD,eAAe,QAAuB;AACpC,MAAI,MAAM,WAAW,EAAG;EAExB,MAAM,UAAU,MAAM,OAAO,GAAG,MAAM,OAAO;AAG7C,MAAI;AACF,SAAM,UAAU,IAAI,QAAQ;EAC7B,QAAO,CAEP;CACF;CAED,SAAS,gBAAsB;AAC7B,MAAI,eAAe,KACjB,cAAa,WAAW,MAAM;AAC5B,gBAAa;AACb,UAAO,CAAC,MAAM,MAAM,CAEnB,EAAC;EACH,GAAE,gBAAgB;CAEtB;CAED,SAAS,kBAAwB;AAC/B,MAAI,eAAe,MAAM;AACvB,gBAAa,WAAW;AACxB,gBAAa;EACd;CACF;AAED,QAAO,qCACL,OAAO,WAAW;AAChB,aAAW,MAAM,OAAO,QAAQ;GAC9B,MAAM,OAAO;GACb,MAAM,EAAE,OAAO,KAAK,MAAM,KAAK,SAAU,GAAG,SAAS,GAAG;GAExD,MAAM,iBAAiB,aAAa,MAAM;GAG1C,IAAIC;AACJ,cAAW,cAAc,WACvB,SAAQ,UAAU,KAAK;mBACP,cAAc,SAC9B,SAAQ;mBACQ,QAAQ,cAAc,UAAU;AAChD,YAAQ,QAAQ;AAChB,WAAO,QAAQ;GAChB;AAED,SAAM,KAAK;IACT,OAAO;IACP,SAAS,OAAO;IAChB;IACA,WAAW;GACZ,EAAC;AAEF,OAAI,MAAM,UAAU,WAAW;AAC7B,qBAAiB;AACjB,UAAM,OAAO;GACd,MACC,gBAAe;EAElB;CACF,GACD,EACE,MAAM,QAAQ;AACZ,mBAAiB;AACjB,QAAM,OAAO;CACd,EACF,EACF;AACF;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAa,wBAAwB"}
@@ -0,0 +1,89 @@
1
+ import "../types-BGDhFv4R.cjs";
2
+ import { Telescope } from "../Telescope-C5dyDYYB.cjs";
3
+ import * as stream0 from "stream";
4
+ import build from "pino-abstract-transport";
5
+
6
+ //#region src/logger/pino.d.ts
7
+ /**
8
+ * Pino log object structure after parsing
9
+ */
10
+ interface PinoLogObject {
11
+ level: number;
12
+ time: number;
13
+ pid?: number;
14
+ hostname?: string;
15
+ msg?: string;
16
+ [key: string]: unknown;
17
+ }
18
+ interface TelescopePinoTransportOptions {
19
+ /**
20
+ * The Telescope instance to send logs to
21
+ */
22
+ telescope: Telescope;
23
+ /**
24
+ * Request ID to associate logs with a specific request.
25
+ * Can be a static string or a function that extracts the ID from log data.
26
+ */
27
+ requestId?: string | ((data: PinoLogObject) => string | undefined);
28
+ /**
29
+ * Batch size before flushing to Telescope (default: 100)
30
+ */
31
+ batchSize?: number;
32
+ /**
33
+ * Flush interval in milliseconds (default: 1000ms)
34
+ */
35
+ flushIntervalMs?: number;
36
+ }
37
+ /**
38
+ * Create a Pino transport that sends logs to Telescope.
39
+ *
40
+ * Uses pino-abstract-transport for proper async iteration and backpressure handling.
41
+ * Logs are batched for performance and flushed either when the batch is full
42
+ * or after the flush interval.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import pino from 'pino';
47
+ * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
48
+ * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';
49
+ *
50
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
51
+ *
52
+ * // Use with pino.multistream to log to both stdout and Telescope
53
+ * const logger = pino(
54
+ * { level: 'debug' },
55
+ * pino.multistream([
56
+ * { stream: process.stdout },
57
+ * { stream: createPinoTransport({ telescope }) }
58
+ * ])
59
+ * );
60
+ *
61
+ * logger.info({ userId: '123' }, 'User logged in');
62
+ * ```
63
+ */
64
+ declare function createPinoTransport(options: TelescopePinoTransportOptions): stream0.Transform & build.OnUnknown;
65
+ /**
66
+ * Create a Pino destination that sends logs to Telescope.
67
+ * Alias for createPinoTransport for API compatibility.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * import pino from 'pino';
72
+ * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';
73
+ *
74
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
75
+ *
76
+ * // Use with pino.multistream to log to both stdout and Telescope
77
+ * const logger = pino(
78
+ * { level: 'debug' },
79
+ * pino.multistream([
80
+ * { stream: process.stdout },
81
+ * { stream: createPinoDestination({ telescope }) }
82
+ * ])
83
+ * );
84
+ * ```
85
+ */
86
+ declare const createPinoDestination: typeof createPinoTransport;
87
+ //#endregion
88
+ export { PinoLogObject, Telescope, TelescopePinoTransportOptions, createPinoDestination, createPinoTransport };
89
+ //# sourceMappingURL=pino.d.cts.map
@@ -0,0 +1,89 @@
1
+ import "../types-CZbzz8kx.mjs";
2
+ import { Telescope } from "../Telescope-DyIWgh9-.mjs";
3
+ import build from "pino-abstract-transport";
4
+ import * as stream0 from "stream";
5
+
6
+ //#region src/logger/pino.d.ts
7
+ /**
8
+ * Pino log object structure after parsing
9
+ */
10
+ interface PinoLogObject {
11
+ level: number;
12
+ time: number;
13
+ pid?: number;
14
+ hostname?: string;
15
+ msg?: string;
16
+ [key: string]: unknown;
17
+ }
18
+ interface TelescopePinoTransportOptions {
19
+ /**
20
+ * The Telescope instance to send logs to
21
+ */
22
+ telescope: Telescope;
23
+ /**
24
+ * Request ID to associate logs with a specific request.
25
+ * Can be a static string or a function that extracts the ID from log data.
26
+ */
27
+ requestId?: string | ((data: PinoLogObject) => string | undefined);
28
+ /**
29
+ * Batch size before flushing to Telescope (default: 100)
30
+ */
31
+ batchSize?: number;
32
+ /**
33
+ * Flush interval in milliseconds (default: 1000ms)
34
+ */
35
+ flushIntervalMs?: number;
36
+ }
37
+ /**
38
+ * Create a Pino transport that sends logs to Telescope.
39
+ *
40
+ * Uses pino-abstract-transport for proper async iteration and backpressure handling.
41
+ * Logs are batched for performance and flushed either when the batch is full
42
+ * or after the flush interval.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import pino from 'pino';
47
+ * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
48
+ * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';
49
+ *
50
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
51
+ *
52
+ * // Use with pino.multistream to log to both stdout and Telescope
53
+ * const logger = pino(
54
+ * { level: 'debug' },
55
+ * pino.multistream([
56
+ * { stream: process.stdout },
57
+ * { stream: createPinoTransport({ telescope }) }
58
+ * ])
59
+ * );
60
+ *
61
+ * logger.info({ userId: '123' }, 'User logged in');
62
+ * ```
63
+ */
64
+ declare function createPinoTransport(options: TelescopePinoTransportOptions): stream0.Transform & build.OnUnknown;
65
+ /**
66
+ * Create a Pino destination that sends logs to Telescope.
67
+ * Alias for createPinoTransport for API compatibility.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * import pino from 'pino';
72
+ * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';
73
+ *
74
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
75
+ *
76
+ * // Use with pino.multistream to log to both stdout and Telescope
77
+ * const logger = pino(
78
+ * { level: 'debug' },
79
+ * pino.multistream([
80
+ * { stream: process.stdout },
81
+ * { stream: createPinoDestination({ telescope }) }
82
+ * ])
83
+ * );
84
+ * ```
85
+ */
86
+ declare const createPinoDestination: typeof createPinoTransport;
87
+ //#endregion
88
+ export { PinoLogObject, Telescope, TelescopePinoTransportOptions, createPinoDestination, createPinoTransport };
89
+ //# sourceMappingURL=pino.d.mts.map
@@ -0,0 +1,116 @@
1
+ import build from "pino-abstract-transport";
2
+
3
+ //#region src/logger/pino.ts
4
+ /**
5
+ * Map Pino numeric levels to Telescope log levels
6
+ */
7
+ function mapPinoLevel(level) {
8
+ if (level <= 20) return "debug";
9
+ if (level <= 30) return "info";
10
+ if (level <= 40) return "warn";
11
+ return "error";
12
+ }
13
+ /**
14
+ * Create a Pino transport that sends logs to Telescope.
15
+ *
16
+ * Uses pino-abstract-transport for proper async iteration and backpressure handling.
17
+ * Logs are batched for performance and flushed either when the batch is full
18
+ * or after the flush interval.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import pino from 'pino';
23
+ * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
24
+ * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';
25
+ *
26
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
27
+ *
28
+ * // Use with pino.multistream to log to both stdout and Telescope
29
+ * const logger = pino(
30
+ * { level: 'debug' },
31
+ * pino.multistream([
32
+ * { stream: process.stdout },
33
+ * { stream: createPinoTransport({ telescope }) }
34
+ * ])
35
+ * );
36
+ *
37
+ * logger.info({ userId: '123' }, 'User logged in');
38
+ * ```
39
+ */
40
+ function createPinoTransport(options) {
41
+ const { telescope, requestId, batchSize = 100, flushIntervalMs = 1e3 } = options;
42
+ const batch = [];
43
+ let flushTimer = null;
44
+ async function flush() {
45
+ if (batch.length === 0) return;
46
+ const toFlush = batch.splice(0, batch.length);
47
+ try {
48
+ await telescope.log(toFlush);
49
+ } catch {}
50
+ }
51
+ function scheduleFlush() {
52
+ if (flushTimer === null) flushTimer = setTimeout(() => {
53
+ flushTimer = null;
54
+ flush().catch(() => {});
55
+ }, flushIntervalMs);
56
+ }
57
+ function clearFlushTimer() {
58
+ if (flushTimer !== null) {
59
+ clearTimeout(flushTimer);
60
+ flushTimer = null;
61
+ }
62
+ }
63
+ return build(async (source) => {
64
+ for await (const obj of source) {
65
+ const data = obj;
66
+ const { level, msg, time, pid, hostname,...context } = data;
67
+ const telescopeLevel = mapPinoLevel(level);
68
+ let reqId;
69
+ if (typeof requestId === "function") reqId = requestId(data);
70
+ else if (typeof requestId === "string") reqId = requestId;
71
+ else if (typeof context.requestId === "string") {
72
+ reqId = context.requestId;
73
+ delete context.requestId;
74
+ }
75
+ batch.push({
76
+ level: telescopeLevel,
77
+ message: msg || "",
78
+ context,
79
+ requestId: reqId
80
+ });
81
+ if (batch.length >= batchSize) {
82
+ clearFlushTimer();
83
+ await flush();
84
+ } else scheduleFlush();
85
+ }
86
+ }, { async close() {
87
+ clearFlushTimer();
88
+ await flush();
89
+ } });
90
+ }
91
+ /**
92
+ * Create a Pino destination that sends logs to Telescope.
93
+ * Alias for createPinoTransport for API compatibility.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * import pino from 'pino';
98
+ * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';
99
+ *
100
+ * const telescope = new Telescope({ storage: new InMemoryStorage() });
101
+ *
102
+ * // Use with pino.multistream to log to both stdout and Telescope
103
+ * const logger = pino(
104
+ * { level: 'debug' },
105
+ * pino.multistream([
106
+ * { stream: process.stdout },
107
+ * { stream: createPinoDestination({ telescope }) }
108
+ * ])
109
+ * );
110
+ * ```
111
+ */
112
+ const createPinoDestination = createPinoTransport;
113
+
114
+ //#endregion
115
+ export { createPinoDestination, createPinoTransport };
116
+ //# sourceMappingURL=pino.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino.mjs","names":["level: number","options: TelescopePinoTransportOptions","batch: LogBatch[]","flushTimer: ReturnType<typeof setTimeout> | null","reqId: string | undefined"],"sources":["../../src/logger/pino.ts"],"sourcesContent":["import build from 'pino-abstract-transport';\nimport type { Telescope } from '../Telescope';\n\n/**\n * Pino log object structure after parsing\n */\nexport interface PinoLogObject {\n level: number;\n time: number;\n pid?: number;\n hostname?: string;\n msg?: string;\n [key: string]: unknown;\n}\n\nexport interface TelescopePinoTransportOptions {\n /**\n * The Telescope instance to send logs to\n */\n telescope: Telescope;\n /**\n * Request ID to associate logs with a specific request.\n * Can be a static string or a function that extracts the ID from log data.\n */\n requestId?: string | ((data: PinoLogObject) => string | undefined);\n /**\n * Batch size before flushing to Telescope (default: 100)\n */\n batchSize?: number;\n /**\n * Flush interval in milliseconds (default: 1000ms)\n */\n flushIntervalMs?: number;\n}\n\ntype TelescopeLogLevel = 'debug' | 'info' | 'warn' | 'error';\n\ninterface LogBatch {\n level: TelescopeLogLevel;\n message: string;\n context: Record<string, unknown>;\n requestId?: string;\n}\n\n/**\n * Map Pino numeric levels to Telescope log levels\n */\nfunction mapPinoLevel(level: number): TelescopeLogLevel {\n // Pino levels: trace=10, debug=20, info=30, warn=40, error=50, fatal=60\n if (level <= 20) return 'debug'; // trace, debug\n if (level <= 30) return 'info';\n if (level <= 40) return 'warn';\n return 'error'; // error, fatal\n}\n\n/**\n * Create a Pino transport that sends logs to Telescope.\n *\n * Uses pino-abstract-transport for proper async iteration and backpressure handling.\n * Logs are batched for performance and flushed either when the batch is full\n * or after the flush interval.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n * import { Telescope, InMemoryStorage } from '@geekmidas/telescope';\n * import { createPinoTransport } from '@geekmidas/telescope/logger/pino';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n *\n * // Use with pino.multistream to log to both stdout and Telescope\n * const logger = pino(\n * { level: 'debug' },\n * pino.multistream([\n * { stream: process.stdout },\n * { stream: createPinoTransport({ telescope }) }\n * ])\n * );\n *\n * logger.info({ userId: '123' }, 'User logged in');\n * ```\n */\nexport function createPinoTransport(options: TelescopePinoTransportOptions) {\n const {\n telescope,\n requestId,\n batchSize = 100,\n flushIntervalMs = 1000,\n } = options;\n\n const batch: LogBatch[] = [];\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n async function flush(): Promise<void> {\n if (batch.length === 0) return;\n\n const toFlush = batch.splice(0, batch.length);\n\n // Use batch insert for better performance\n try {\n await telescope.log(toFlush);\n } catch {\n // Silently ignore errors to not break logging\n }\n }\n\n function scheduleFlush(): void {\n if (flushTimer === null) {\n flushTimer = setTimeout(() => {\n flushTimer = null;\n flush().catch(() => {\n // Silently ignore flush errors\n });\n }, flushIntervalMs);\n }\n }\n\n function clearFlushTimer(): void {\n if (flushTimer !== null) {\n clearTimeout(flushTimer);\n flushTimer = null;\n }\n }\n\n return build(\n async (source) => {\n for await (const obj of source) {\n const data = obj as PinoLogObject;\n const { level, msg, time, pid, hostname, ...context } = data;\n\n const telescopeLevel = mapPinoLevel(level);\n\n // Extract request ID\n let reqId: string | undefined;\n if (typeof requestId === 'function') {\n reqId = requestId(data);\n } else if (typeof requestId === 'string') {\n reqId = requestId;\n } else if (typeof context.requestId === 'string') {\n reqId = context.requestId;\n delete context.requestId;\n }\n\n batch.push({\n level: telescopeLevel,\n message: msg || '',\n context,\n requestId: reqId,\n });\n\n if (batch.length >= batchSize) {\n clearFlushTimer();\n await flush();\n } else {\n scheduleFlush();\n }\n }\n },\n {\n async close() {\n clearFlushTimer();\n await flush();\n },\n },\n );\n}\n\n/**\n * Create a Pino destination that sends logs to Telescope.\n * Alias for createPinoTransport for API compatibility.\n *\n * @example\n * ```typescript\n * import pino from 'pino';\n * import { createPinoDestination } from '@geekmidas/telescope/logger/pino';\n *\n * const telescope = new Telescope({ storage: new InMemoryStorage() });\n *\n * // Use with pino.multistream to log to both stdout and Telescope\n * const logger = pino(\n * { level: 'debug' },\n * pino.multistream([\n * { stream: process.stdout },\n * { stream: createPinoDestination({ telescope }) }\n * ])\n * );\n * ```\n */\nexport const createPinoDestination = createPinoTransport;\n\nexport type { Telescope };\n"],"mappings":";;;;;;AA+CA,SAAS,aAAaA,OAAkC;AAEtD,KAAI,SAAS,GAAI,QAAO;AACxB,KAAI,SAAS,GAAI,QAAO;AACxB,KAAI,SAAS,GAAI,QAAO;AACxB,QAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BD,SAAgB,oBAAoBC,SAAwC;CAC1E,MAAM,EACJ,WACA,WACA,YAAY,KACZ,kBAAkB,KACnB,GAAG;CAEJ,MAAMC,QAAoB,CAAE;CAC5B,IAAIC,aAAmD;CAEvD,eAAe,QAAuB;AACpC,MAAI,MAAM,WAAW,EAAG;EAExB,MAAM,UAAU,MAAM,OAAO,GAAG,MAAM,OAAO;AAG7C,MAAI;AACF,SAAM,UAAU,IAAI,QAAQ;EAC7B,QAAO,CAEP;CACF;CAED,SAAS,gBAAsB;AAC7B,MAAI,eAAe,KACjB,cAAa,WAAW,MAAM;AAC5B,gBAAa;AACb,UAAO,CAAC,MAAM,MAAM,CAEnB,EAAC;EACH,GAAE,gBAAgB;CAEtB;CAED,SAAS,kBAAwB;AAC/B,MAAI,eAAe,MAAM;AACvB,gBAAa,WAAW;AACxB,gBAAa;EACd;CACF;AAED,QAAO,MACL,OAAO,WAAW;AAChB,aAAW,MAAM,OAAO,QAAQ;GAC9B,MAAM,OAAO;GACb,MAAM,EAAE,OAAO,KAAK,MAAM,KAAK,SAAU,GAAG,SAAS,GAAG;GAExD,MAAM,iBAAiB,aAAa,MAAM;GAG1C,IAAIC;AACJ,cAAW,cAAc,WACvB,SAAQ,UAAU,KAAK;mBACP,cAAc,SAC9B,SAAQ;mBACQ,QAAQ,cAAc,UAAU;AAChD,YAAQ,QAAQ;AAChB,WAAO,QAAQ;GAChB;AAED,SAAM,KAAK;IACT,OAAO;IACP,SAAS,OAAO;IAChB;IACA,WAAW;GACZ,EAAC;AAEF,OAAI,MAAM,UAAU,WAAW;AAC7B,qBAAiB;AACjB,UAAM,OAAO;GACd,MACC,gBAAe;EAElB;CACF,GACD,EACE,MAAM,QAAQ;AACZ,mBAAiB;AACjB,QAAM,OAAO;CACd,EACF,EACF;AACF;;;;;;;;;;;;;;;;;;;;;;AAuBD,MAAa,wBAAwB"}