logixia 2.0.11 → 2.2.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 (203) hide show
  1. package/README.md +4 -3
  2. package/dist/{async-context-BGUCdYAa.mjs → async-context-1YMPGgJZ.mjs} +3 -3
  3. package/dist/{async-context-BGUCdYAa.mjs.map → async-context-1YMPGgJZ.mjs.map} +1 -1
  4. package/dist/{async-context-D8um9I5V.js → async-context-CoPhbRG0.js} +4 -4
  5. package/dist/{async-context-D8um9I5V.js.map → async-context-CoPhbRG0.js.map} +1 -1
  6. package/dist/{azure-monitor.transport-CTnfwA0F.mjs → azure-monitor.transport-B_dqSV_o.mjs} +4 -4
  7. package/dist/{azure-monitor.transport-CTnfwA0F.mjs.map → azure-monitor.transport-B_dqSV_o.mjs.map} +1 -1
  8. package/dist/{azure-monitor.transport-C8KdmsSw.js → azure-monitor.transport-Bl3xVvpN.js} +4 -4
  9. package/dist/{azure-monitor.transport-C8KdmsSw.js.map → azure-monitor.transport-Bl3xVvpN.js.map} +1 -1
  10. package/dist/{azure-monitor.transport-CbSHOnNX.d.mts → azure-monitor.transport-C5VjvREZ.d.mts} +2 -2
  11. package/dist/{azure-monitor.transport-CbSHOnNX.d.mts.map → azure-monitor.transport-C5VjvREZ.d.mts.map} +1 -1
  12. package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts → azure-monitor.transport-CyHDjHS-.d.ts} +2 -2
  13. package/dist/{azure-monitor.transport-Bvf7Xegt.d.ts.map → azure-monitor.transport-CyHDjHS-.d.ts.map} +1 -1
  14. package/dist/azure.d.mts +1 -1
  15. package/dist/azure.d.ts +1 -1
  16. package/dist/azure.js +1 -1
  17. package/dist/azure.mjs +1 -1
  18. package/dist/{batch-buffer-BJqzpfpT.mjs → batch-buffer-BnmVCCwI.mjs} +2 -2
  19. package/dist/{batch-buffer-BJqzpfpT.mjs.map → batch-buffer-BnmVCCwI.mjs.map} +1 -1
  20. package/dist/{batch-buffer-BTQdAXwC.js → batch-buffer-C-ETEX3Y.js} +2 -2
  21. package/dist/{batch-buffer-BTQdAXwC.js.map → batch-buffer-C-ETEX3Y.js.map} +1 -1
  22. package/dist/browser.d.mts +2 -0
  23. package/dist/browser.d.mts.map +1 -1
  24. package/dist/browser.d.ts +2 -0
  25. package/dist/browser.d.ts.map +1 -1
  26. package/dist/browser.js +33 -15
  27. package/dist/browser.js.map +1 -1
  28. package/dist/browser.mjs +33 -15
  29. package/dist/browser.mjs.map +1 -1
  30. package/dist/{builder-C6kKEVrU.mjs → builder-CbttbixM.mjs} +158 -279
  31. package/dist/builder-CbttbixM.mjs.map +1 -0
  32. package/dist/{builder-Up4YxX7l.js → builder-Ck1tsC5d.js} +160 -305
  33. package/dist/builder-Ck1tsC5d.js.map +1 -0
  34. package/dist/cloudwatch.d.mts +1 -1
  35. package/dist/cloudwatch.d.ts +1 -1
  36. package/dist/cloudwatch.js +1 -1
  37. package/dist/cloudwatch.mjs +1 -1
  38. package/dist/{cloudwatch.transport-Bl1qzdBx.mjs → cloudwatch.transport-Brh5fmRN.mjs} +5 -5
  39. package/dist/{cloudwatch.transport-Bl1qzdBx.mjs.map → cloudwatch.transport-Brh5fmRN.mjs.map} +1 -1
  40. package/dist/{cloudwatch.transport-BoCyxNKO.js → cloudwatch.transport-DO9e__Z-.js} +5 -5
  41. package/dist/{cloudwatch.transport-BoCyxNKO.js.map → cloudwatch.transport-DO9e__Z-.js.map} +1 -1
  42. package/dist/{cloudwatch.transport-CQyT6U91.d.ts → cloudwatch.transport-DdSjUWvu.d.ts} +2 -2
  43. package/dist/{cloudwatch.transport-CQyT6U91.d.ts.map → cloudwatch.transport-DdSjUWvu.d.ts.map} +1 -1
  44. package/dist/{cloudwatch.transport-CjVrI6S4.d.mts → cloudwatch.transport-_hS7Mcc5.d.mts} +2 -2
  45. package/dist/{cloudwatch.transport-CjVrI6S4.d.mts.map → cloudwatch.transport-_hS7Mcc5.d.mts.map} +1 -1
  46. package/dist/correlation.js +3 -3
  47. package/dist/correlation.mjs +3 -3
  48. package/dist/{entry-fields-CJbeaoBs.js → entry-fields-BSLkzw18.js} +3 -3
  49. package/dist/{entry-fields-CJbeaoBs.js.map → entry-fields-BSLkzw18.js.map} +1 -1
  50. package/dist/{entry-fields-D_aNnjg0.mjs → entry-fields-J1OBi24o.mjs} +2 -2
  51. package/dist/{entry-fields-D_aNnjg0.mjs.map → entry-fields-J1OBi24o.mjs.map} +1 -1
  52. package/dist/error.utils-B8_CwESF.mjs +189 -0
  53. package/dist/error.utils-B8_CwESF.mjs.map +1 -0
  54. package/dist/error.utils-fZkRExam.js +212 -0
  55. package/dist/error.utils-fZkRExam.js.map +1 -0
  56. package/dist/fastify.d.mts +89 -0
  57. package/dist/fastify.d.mts.map +1 -0
  58. package/dist/fastify.d.ts +89 -0
  59. package/dist/fastify.d.ts.map +1 -0
  60. package/dist/fastify.js +265 -0
  61. package/dist/fastify.js.map +1 -0
  62. package/dist/fastify.mjs +263 -0
  63. package/dist/fastify.mjs.map +1 -0
  64. package/dist/gcp.d.mts +1 -1
  65. package/dist/gcp.d.ts +1 -1
  66. package/dist/gcp.js +1 -1
  67. package/dist/gcp.mjs +1 -1
  68. package/dist/{gcp.transport-DOH4bpWM.mjs → gcp.transport-BY1Z3cS0.mjs} +5 -5
  69. package/dist/{gcp.transport-DOH4bpWM.mjs.map → gcp.transport-BY1Z3cS0.mjs.map} +1 -1
  70. package/dist/{gcp.transport-D9SdLPwP.d.mts → gcp.transport-C8VJiEM7.d.mts} +2 -2
  71. package/dist/{gcp.transport-D9SdLPwP.d.mts.map → gcp.transport-C8VJiEM7.d.mts.map} +1 -1
  72. package/dist/{gcp.transport-BCIvdFV-.d.ts → gcp.transport-Ct0BtKFo.d.ts} +2 -2
  73. package/dist/{gcp.transport-BCIvdFV-.d.ts.map → gcp.transport-Ct0BtKFo.d.ts.map} +1 -1
  74. package/dist/{gcp.transport-D_NHVZrw.js → gcp.transport-V9R4dwdT.js} +5 -5
  75. package/dist/{gcp.transport-D_NHVZrw.js.map → gcp.transport-V9R4dwdT.js.map} +1 -1
  76. package/dist/hono.d.mts +66 -0
  77. package/dist/hono.d.mts.map +1 -0
  78. package/dist/hono.d.ts +66 -0
  79. package/dist/hono.d.ts.map +1 -0
  80. package/dist/hono.js +512 -0
  81. package/dist/hono.js.map +1 -0
  82. package/dist/hono.mjs +511 -0
  83. package/dist/hono.mjs.map +1 -0
  84. package/dist/{index-BAkPHp5D.d.mts → index-B3ajtXJd.d.mts} +2 -2
  85. package/dist/{index-BAkPHp5D.d.mts.map → index-B3ajtXJd.d.mts.map} +1 -1
  86. package/dist/{index-e7LowmAu.d.ts → index-oqD3WNxf.d.ts} +2 -2
  87. package/dist/{index-e7LowmAu.d.ts.map → index-oqD3WNxf.d.ts.map} +1 -1
  88. package/dist/index.d.mts +8 -7
  89. package/dist/index.d.mts.map +1 -1
  90. package/dist/index.d.ts +8 -7
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +23 -20
  93. package/dist/index.js.map +1 -1
  94. package/dist/index.mjs +11 -9
  95. package/dist/index.mjs.map +1 -1
  96. package/dist/{logitron-logger-DVUdgmBY.d.ts → logitron-logger-Csn3e6Qu.d.ts} +2 -2
  97. package/dist/{logitron-logger-DVUdgmBY.d.ts.map → logitron-logger-Csn3e6Qu.d.ts.map} +1 -1
  98. package/dist/{logitron-logger-DoWmMjYB.d.mts → logitron-logger-fMOkXr8H.d.mts} +2 -2
  99. package/dist/{logitron-logger-DoWmMjYB.d.mts.map → logitron-logger-fMOkXr8H.d.mts.map} +1 -1
  100. package/dist/middleware.d.mts +1 -1
  101. package/dist/middleware.d.ts +1 -1
  102. package/dist/middleware.js +6 -5
  103. package/dist/middleware.js.map +1 -1
  104. package/dist/middleware.mjs +4 -3
  105. package/dist/middleware.mjs.map +1 -1
  106. package/dist/nest.d.mts +47 -15
  107. package/dist/nest.d.mts.map +1 -1
  108. package/dist/nest.d.ts +47 -15
  109. package/dist/nest.d.ts.map +1 -1
  110. package/dist/nest.js +172 -50
  111. package/dist/nest.js.map +1 -1
  112. package/dist/nest.mjs +168 -46
  113. package/dist/nest.mjs.map +1 -1
  114. package/dist/{otel-DH6-G6DR.js → otel-BrgvxLDW.js} +319 -66
  115. package/dist/otel-BrgvxLDW.js.map +1 -0
  116. package/dist/{otel-DAVxpArV.mjs → otel-C5jBV_l_.mjs} +319 -66
  117. package/dist/otel-C5jBV_l_.mjs.map +1 -0
  118. package/dist/own-property-BWkibepN.js +40 -0
  119. package/dist/own-property-BWkibepN.js.map +1 -0
  120. package/dist/own-property-CjFw9qwZ.mjs +29 -0
  121. package/dist/own-property-CjFw9qwZ.mjs.map +1 -0
  122. package/dist/{request-trace-C7kXMjx5.js → request-trace-6NBSw5lt.js} +14 -3
  123. package/dist/{request-trace-C7kXMjx5.js.map → request-trace-6NBSw5lt.js.map} +1 -1
  124. package/dist/{request-trace-Dekcnenb.mjs → request-trace-txUhyyre.mjs} +9 -4
  125. package/dist/{request-trace-Dekcnenb.mjs.map → request-trace-txUhyyre.mjs.map} +1 -1
  126. package/dist/{safe-stringify-pZOnzGRJ.mjs → safe-stringify-B5p5ktFe.mjs} +2 -2
  127. package/dist/{safe-stringify-pZOnzGRJ.mjs.map → safe-stringify-B5p5ktFe.mjs.map} +1 -1
  128. package/dist/{safe-stringify-CJisLyZ3.js → safe-stringify-J3sh-7YM.js} +5 -5
  129. package/dist/{safe-stringify-CJisLyZ3.js.map → safe-stringify-J3sh-7YM.js.map} +1 -1
  130. package/dist/{search-Crf2IEoA.d.mts → search-B-hJe2N-.d.mts} +7 -3
  131. package/dist/{search-Crf2IEoA.d.mts.map → search-B-hJe2N-.d.mts.map} +1 -1
  132. package/dist/{search-B4eEzrhM.d.ts → search-BlKBLm5D.d.ts} +7 -3
  133. package/dist/{search-B4eEzrhM.d.ts.map → search-BlKBLm5D.d.ts.map} +1 -1
  134. package/dist/{search-CjYl-mo5.mjs → search-CTR4XNHq.mjs} +52 -14
  135. package/dist/search-CTR4XNHq.mjs.map +1 -0
  136. package/dist/{search-CJw_xoQl.js → search-_qx4YzRP.js} +52 -14
  137. package/dist/search-_qx4YzRP.js.map +1 -0
  138. package/dist/search.d.mts +1 -1
  139. package/dist/search.d.ts +1 -1
  140. package/dist/search.js +1 -1
  141. package/dist/search.mjs +1 -1
  142. package/dist/{secret-config-D1F4MW69.mjs → secret-config-Cng7XPLx.mjs} +18 -13
  143. package/dist/secret-config-Cng7XPLx.mjs.map +1 -0
  144. package/dist/{secret-config-6hdODxBb.js → secret-config-OqmIPmpV.js} +21 -16
  145. package/dist/secret-config-OqmIPmpV.js.map +1 -0
  146. package/dist/{sensitive-names-wv27qBQC.mjs → sensitive-names-BiBM6R1X.mjs} +2 -28
  147. package/dist/sensitive-names-BiBM6R1X.mjs.map +1 -0
  148. package/dist/{sensitive-names-CNgHaqv9.js → sensitive-names-NiKIRhp5.js} +1 -39
  149. package/dist/sensitive-names-NiKIRhp5.js.map +1 -0
  150. package/dist/{slack.transport-C6E0l4kw.d.ts → slack.transport-5OPL7H3u.d.mts} +76 -3
  151. package/dist/slack.transport-5OPL7H3u.d.mts.map +1 -0
  152. package/dist/{slack.transport-BDyENuR0.d.mts → slack.transport-BFpBD_Ri.d.ts} +76 -3
  153. package/dist/slack.transport-BFpBD_Ri.d.ts.map +1 -0
  154. package/dist/{slack.transport-YvaLJxNv.mjs → slack.transport-C6dzPJHX.mjs} +226 -9
  155. package/dist/slack.transport-C6dzPJHX.mjs.map +1 -0
  156. package/dist/{slack.transport-CEYBVzUj.js → slack.transport-Ci0swStG.js} +231 -8
  157. package/dist/slack.transport-Ci0swStG.js.map +1 -0
  158. package/dist/testing.d.mts +1 -1
  159. package/dist/testing.d.ts +1 -1
  160. package/dist/{transport.types-CzJq4IrF.d.ts → transport.types-B1ejJJP6.d.mts} +6 -1
  161. package/dist/transport.types-B1ejJJP6.d.mts.map +1 -0
  162. package/dist/{transport.types-CzJq4IrF.d.mts → transport.types-B1ejJJP6.d.ts} +6 -1
  163. package/dist/transport.types-B1ejJJP6.d.ts.map +1 -0
  164. package/dist/transports.d.mts +61 -11
  165. package/dist/transports.d.mts.map +1 -1
  166. package/dist/transports.d.ts +61 -11
  167. package/dist/transports.d.ts.map +1 -1
  168. package/dist/transports.js +7 -6
  169. package/dist/transports.mjs +7 -7
  170. package/dist/worker-entry.js +106 -22
  171. package/dist/worker.d.mts +1 -1
  172. package/dist/worker.d.ts +1 -1
  173. package/dist/worker.js +1 -1
  174. package/dist/worker.mjs +1 -1
  175. package/dist/{worker.transport-B9mCQSM1.d.ts → worker.transport-B7olL1Uh.d.ts} +12 -2
  176. package/dist/worker.transport-B7olL1Uh.d.ts.map +1 -0
  177. package/dist/{worker.transport-CwNpH98o.js → worker.transport-CZOutlxC.js} +40 -2
  178. package/dist/worker.transport-CZOutlxC.js.map +1 -0
  179. package/dist/{worker.transport-DgK_ZXlB.mjs → worker.transport-CxFD8mvS.mjs} +40 -2
  180. package/dist/worker.transport-CxFD8mvS.mjs.map +1 -0
  181. package/dist/{worker.transport-Bl8lFRck.d.mts → worker.transport-DnU0_9Bd.d.mts} +12 -2
  182. package/dist/worker.transport-DnU0_9Bd.d.mts.map +1 -0
  183. package/package.json +37 -2
  184. package/dist/builder-C6kKEVrU.mjs.map +0 -1
  185. package/dist/builder-Up4YxX7l.js.map +0 -1
  186. package/dist/otel-DAVxpArV.mjs.map +0 -1
  187. package/dist/otel-DH6-G6DR.js.map +0 -1
  188. package/dist/search-CJw_xoQl.js.map +0 -1
  189. package/dist/search-CjYl-mo5.mjs.map +0 -1
  190. package/dist/secret-config-6hdODxBb.js.map +0 -1
  191. package/dist/secret-config-D1F4MW69.mjs.map +0 -1
  192. package/dist/sensitive-names-CNgHaqv9.js.map +0 -1
  193. package/dist/sensitive-names-wv27qBQC.mjs.map +0 -1
  194. package/dist/slack.transport-BDyENuR0.d.mts.map +0 -1
  195. package/dist/slack.transport-C6E0l4kw.d.ts.map +0 -1
  196. package/dist/slack.transport-CEYBVzUj.js.map +0 -1
  197. package/dist/slack.transport-YvaLJxNv.mjs.map +0 -1
  198. package/dist/transport.types-CzJq4IrF.d.mts.map +0 -1
  199. package/dist/transport.types-CzJq4IrF.d.ts.map +0 -1
  200. package/dist/worker.transport-B9mCQSM1.d.ts.map +0 -1
  201. package/dist/worker.transport-Bl8lFRck.d.mts.map +0 -1
  202. package/dist/worker.transport-CwNpH98o.js.map +0 -1
  203. package/dist/worker.transport-DgK_ZXlB.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive-names-BiBM6R1X.mjs","names":[],"sources":["../src/utils/sensitive-names.ts"],"sourcesContent":["/**\n * The one list of sensitive names. Log redaction (redact.utils), the HTTP logger\n * middleware and transport secret handling (transports/secret-config) all read it,\n * so the lists cannot drift. No imports: safe from any module, including browser code.\n */\n\n/** Field names redacted by name, wherever they appear in logged data. */\nexport const SENSITIVE_KEY_NAMES: readonly string[] = [\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'apiKey',\n 'api_key',\n 'accessToken',\n 'access_token',\n 'refreshToken',\n 'refresh_token',\n 'authorization',\n 'credentials',\n 'privateKey',\n 'private_key',\n 'clientSecret',\n 'client_secret',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'session',\n 'proxy-authorization',\n 'x-auth-token',\n 'x-access-token',\n 'aws_secret_access_key',\n 'awsSecretAccessKey',\n 'secretAccessKey',\n];\n\n/**\n * Extra names that only mean \"secret\" inside transport configuration, where\n * short words like `key` or `signature` are credentials, not log fields.\n */\nexport const TRANSPORT_CONFIG_SECRET_NAMES: readonly string[] = [\n 'writeKey',\n 'apiSecret',\n 'connectionString',\n 'sessionToken',\n 'passphrase',\n 'signature',\n 'pwd',\n 'pfx',\n 'cert',\n 'key',\n 'auth',\n];\n\n/** Request headers whose values are never logged. */\nexport const DEFAULT_REDACT_HEADERS: readonly string[] = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'proxy-authorization',\n 'x-auth-token',\n 'x-access-token',\n 'x-csrf-token',\n 'x-amz-security-token',\n];\n\n/** Query-string parameters whose values are never logged. */\nexport const DEFAULT_REDACT_QUERY_PARAMS: readonly string[] = [\n 'token',\n 'access_token',\n 'refresh_token',\n 'code',\n 'password',\n 'secret',\n 'api_key',\n 'apikey',\n 'key',\n 'signature',\n 'sig',\n 'auth',\n 'accesstoken',\n 'refreshtoken',\n 'id_token',\n 'idtoken',\n 'client_secret',\n 'clientsecret',\n 'session',\n 'sessionid',\n 'session_id',\n 'jwt',\n 'auth_token',\n 'authtoken',\n 'api-key',\n 'x-api-key',\n 'x-amz-signature',\n 'x-amz-credential',\n 'x-amz-security-token',\n 'x-goog-signature',\n 'x-goog-credential',\n 'access-token',\n 'x-access-token',\n 'x-auth-token',\n 'apitoken',\n 'api_token',\n];\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, ' '));\n } catch {\n return value;\n }\n}\n\n/** Replace the values of sensitive query parameters, leaving the rest verbatim. */\nexport function redactUrlQuery(url: string, redactParams: ReadonlySet<string>): string {\n const q = url.indexOf('?');\n if (q === -1) return url;\n const hashAt = url.indexOf('#', q);\n const query = url.slice(q + 1, hashAt === -1 ? undefined : hashAt);\n const hash = hashAt === -1 ? '' : url.slice(hashAt);\n const cleaned = query\n .split('&')\n .map((pair) => {\n const eq = pair.indexOf('=');\n const rawKey = eq === -1 ? pair : pair.slice(0, eq);\n const decoded = safeDecode(rawKey);\n const bracket = decoded.indexOf('[');\n const name = (bracket === -1 ? decoded : decoded.slice(0, bracket)).toLowerCase();\n return redactParams.has(name) && eq !== -1 ? `${rawKey}=[REDACTED]` : pair;\n })\n .join('&');\n return `${url.slice(0, q)}?${cleaned}${hash}`;\n}\n\n/** Lower-cased lookup set of the default names plus any extras. */\nexport function buildNameSet(\n defaults: readonly string[],\n extra: readonly string[] | undefined\n): Set<string> {\n return new Set([...defaults, ...(extra ?? [])].map((n) => n.toLowerCase()));\n}\n\nconst REDACTED = '[REDACTED]';\nconst MIN_SCRUB_LENGTH = 3;\n\nfunction queryNameOf(rawKey: string): string {\n const decoded = safeDecode(rawKey);\n const bracket = decoded.indexOf('[');\n return (bracket === -1 ? decoded : decoded.slice(0, bracket)).toLowerCase();\n}\n\n/**\n * Raw and decoded values of sensitive query parameters present in this URL.\n * Values shorter than 3 characters or already `[REDACTED]` are ignored.\n */\nexport function sensitiveQueryValues(url: string, names: ReadonlySet<string>): string[] {\n const q = url.indexOf('?');\n if (q === -1) return [];\n const hashAt = url.indexOf('#', q);\n const query = url.slice(q + 1, hashAt === -1 ? undefined : hashAt);\n const found = new Set<string>();\n for (const pair of query.split('&')) {\n const eq = pair.indexOf('=');\n if (eq === -1 || !names.has(queryNameOf(pair.slice(0, eq)))) continue;\n const raw = pair.slice(eq + 1);\n for (const value of [raw, safeDecode(raw)]) {\n if (value.length >= MIN_SCRUB_LENGTH && value !== REDACTED) found.add(value);\n }\n }\n return [...found];\n}\n\n/** Replace every literal occurrence of `values` in `text` with `[REDACTED]`. */\nexport function scrubValues(text: string, values: readonly string[]): string {\n if (values.length === 0 || text.length === 0) return text;\n let out = text;\n for (const value of [...values].sort((a, b) => b.length - a.length)) {\n if (value.length > 0 && out.includes(value)) out = out.split(value).join(REDACTED);\n }\n return out;\n}\n\nfunction isUrlTerminator(ch: string): boolean {\n return (\n ch === ' ' ||\n ch === '\\n' ||\n ch === '\\r' ||\n ch === '\\t' ||\n ch === '\"' ||\n ch === \"'\" ||\n ch === '`'\n );\n}\n\n/**\n * Redact sensitive query values in every `?query` found inside free text (an\n * error message, a stack line). Scans for `?` and cuts at whitespace or a quote.\n */\nexport function redactUrlsInText(text: string, names: ReadonlySet<string>): string {\n let q = text.indexOf('?');\n if (q === -1) return text;\n let out = '';\n let cursor = 0;\n while (q !== -1) {\n let end = q + 1;\n while (end < text.length && !isUrlTerminator(text.charAt(end))) end++;\n out += text.slice(cursor, q) + redactUrlQuery(text.slice(q, end), names);\n cursor = end;\n q = text.indexOf('?', end);\n }\n return out + text.slice(cursor);\n}\n\n/** Shape-preserving URL redaction plus literal scrubbing of this request's secret values. */\nexport function sanitizeText(\n text: string,\n names: ReadonlySet<string>,\n values: readonly string[]\n): string {\n return scrubValues(redactUrlsInText(text, names), values);\n}\n"],"mappings":"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"}
@@ -1,29 +1,3 @@
1
- // src/utils/own-property.ts
2
- /**
3
- * True for the one key that must never be assigned with `target[key] = value`.
4
- *
5
- * Assigning `constructor` or `prototype` on a fresh plain object only creates an
6
- * own property, which is harmless. Only `__proto__` invokes the prototype setter.
7
- */
8
- function isProtoKey(key) {
9
- return key === "__proto__";
10
- }
11
- /**
12
- * Copy `value` onto `target[key]` as an own, enumerable data property.
13
- *
14
- * Normal keys use a plain assignment, which is the fast path. `__proto__` goes
15
- * through `Object.defineProperty` so that a key taken from logged or parsed data
16
- * becomes an own property instead of replacing the object's prototype.
17
- */
18
- function assignOwn(target, key, value) {
19
- if (key === "__proto__") Object.defineProperty(target, key, {
20
- value,
21
- enumerable: true,
22
- writable: true,
23
- configurable: true
24
- });
25
- else target[key] = value;
26
- }
27
1
  // src/utils/sensitive-names.ts
28
2
  /**
29
3
  * The one list of sensitive names. Log redaction (redact.utils), the HTTP logger
@@ -236,24 +210,12 @@ Object.defineProperty(exports, "TRANSPORT_CONFIG_SECRET_NAMES", {
236
210
  return TRANSPORT_CONFIG_SECRET_NAMES;
237
211
  }
238
212
  });
239
- Object.defineProperty(exports, "assignOwn", {
240
- enumerable: true,
241
- get: function() {
242
- return assignOwn;
243
- }
244
- });
245
213
  Object.defineProperty(exports, "buildNameSet", {
246
214
  enumerable: true,
247
215
  get: function() {
248
216
  return buildNameSet;
249
217
  }
250
218
  });
251
- Object.defineProperty(exports, "isProtoKey", {
252
- enumerable: true,
253
- get: function() {
254
- return isProtoKey;
255
- }
256
- });
257
219
  Object.defineProperty(exports, "redactUrlQuery", {
258
220
  enumerable: true,
259
221
  get: function() {
@@ -279,4 +241,4 @@ Object.defineProperty(exports, "sensitiveQueryValues", {
279
241
  }
280
242
  });
281
243
 
282
- //# sourceMappingURL=sensitive-names-CNgHaqv9.js.map
244
+ //# sourceMappingURL=sensitive-names-NiKIRhp5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive-names-NiKIRhp5.js","names":[],"sources":["../src/utils/sensitive-names.ts"],"sourcesContent":["/**\n * The one list of sensitive names. Log redaction (redact.utils), the HTTP logger\n * middleware and transport secret handling (transports/secret-config) all read it,\n * so the lists cannot drift. No imports: safe from any module, including browser code.\n */\n\n/** Field names redacted by name, wherever they appear in logged data. */\nexport const SENSITIVE_KEY_NAMES: readonly string[] = [\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'apiKey',\n 'api_key',\n 'accessToken',\n 'access_token',\n 'refreshToken',\n 'refresh_token',\n 'authorization',\n 'credentials',\n 'privateKey',\n 'private_key',\n 'clientSecret',\n 'client_secret',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'session',\n 'proxy-authorization',\n 'x-auth-token',\n 'x-access-token',\n 'aws_secret_access_key',\n 'awsSecretAccessKey',\n 'secretAccessKey',\n];\n\n/**\n * Extra names that only mean \"secret\" inside transport configuration, where\n * short words like `key` or `signature` are credentials, not log fields.\n */\nexport const TRANSPORT_CONFIG_SECRET_NAMES: readonly string[] = [\n 'writeKey',\n 'apiSecret',\n 'connectionString',\n 'sessionToken',\n 'passphrase',\n 'signature',\n 'pwd',\n 'pfx',\n 'cert',\n 'key',\n 'auth',\n];\n\n/** Request headers whose values are never logged. */\nexport const DEFAULT_REDACT_HEADERS: readonly string[] = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'proxy-authorization',\n 'x-auth-token',\n 'x-access-token',\n 'x-csrf-token',\n 'x-amz-security-token',\n];\n\n/** Query-string parameters whose values are never logged. */\nexport const DEFAULT_REDACT_QUERY_PARAMS: readonly string[] = [\n 'token',\n 'access_token',\n 'refresh_token',\n 'code',\n 'password',\n 'secret',\n 'api_key',\n 'apikey',\n 'key',\n 'signature',\n 'sig',\n 'auth',\n 'accesstoken',\n 'refreshtoken',\n 'id_token',\n 'idtoken',\n 'client_secret',\n 'clientsecret',\n 'session',\n 'sessionid',\n 'session_id',\n 'jwt',\n 'auth_token',\n 'authtoken',\n 'api-key',\n 'x-api-key',\n 'x-amz-signature',\n 'x-amz-credential',\n 'x-amz-security-token',\n 'x-goog-signature',\n 'x-goog-credential',\n 'access-token',\n 'x-access-token',\n 'x-auth-token',\n 'apitoken',\n 'api_token',\n];\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, ' '));\n } catch {\n return value;\n }\n}\n\n/** Replace the values of sensitive query parameters, leaving the rest verbatim. */\nexport function redactUrlQuery(url: string, redactParams: ReadonlySet<string>): string {\n const q = url.indexOf('?');\n if (q === -1) return url;\n const hashAt = url.indexOf('#', q);\n const query = url.slice(q + 1, hashAt === -1 ? undefined : hashAt);\n const hash = hashAt === -1 ? '' : url.slice(hashAt);\n const cleaned = query\n .split('&')\n .map((pair) => {\n const eq = pair.indexOf('=');\n const rawKey = eq === -1 ? pair : pair.slice(0, eq);\n const decoded = safeDecode(rawKey);\n const bracket = decoded.indexOf('[');\n const name = (bracket === -1 ? decoded : decoded.slice(0, bracket)).toLowerCase();\n return redactParams.has(name) && eq !== -1 ? `${rawKey}=[REDACTED]` : pair;\n })\n .join('&');\n return `${url.slice(0, q)}?${cleaned}${hash}`;\n}\n\n/** Lower-cased lookup set of the default names plus any extras. */\nexport function buildNameSet(\n defaults: readonly string[],\n extra: readonly string[] | undefined\n): Set<string> {\n return new Set([...defaults, ...(extra ?? [])].map((n) => n.toLowerCase()));\n}\n\nconst REDACTED = '[REDACTED]';\nconst MIN_SCRUB_LENGTH = 3;\n\nfunction queryNameOf(rawKey: string): string {\n const decoded = safeDecode(rawKey);\n const bracket = decoded.indexOf('[');\n return (bracket === -1 ? decoded : decoded.slice(0, bracket)).toLowerCase();\n}\n\n/**\n * Raw and decoded values of sensitive query parameters present in this URL.\n * Values shorter than 3 characters or already `[REDACTED]` are ignored.\n */\nexport function sensitiveQueryValues(url: string, names: ReadonlySet<string>): string[] {\n const q = url.indexOf('?');\n if (q === -1) return [];\n const hashAt = url.indexOf('#', q);\n const query = url.slice(q + 1, hashAt === -1 ? undefined : hashAt);\n const found = new Set<string>();\n for (const pair of query.split('&')) {\n const eq = pair.indexOf('=');\n if (eq === -1 || !names.has(queryNameOf(pair.slice(0, eq)))) continue;\n const raw = pair.slice(eq + 1);\n for (const value of [raw, safeDecode(raw)]) {\n if (value.length >= MIN_SCRUB_LENGTH && value !== REDACTED) found.add(value);\n }\n }\n return [...found];\n}\n\n/** Replace every literal occurrence of `values` in `text` with `[REDACTED]`. */\nexport function scrubValues(text: string, values: readonly string[]): string {\n if (values.length === 0 || text.length === 0) return text;\n let out = text;\n for (const value of [...values].sort((a, b) => b.length - a.length)) {\n if (value.length > 0 && out.includes(value)) out = out.split(value).join(REDACTED);\n }\n return out;\n}\n\nfunction isUrlTerminator(ch: string): boolean {\n return (\n ch === ' ' ||\n ch === '\\n' ||\n ch === '\\r' ||\n ch === '\\t' ||\n ch === '\"' ||\n ch === \"'\" ||\n ch === '`'\n );\n}\n\n/**\n * Redact sensitive query values in every `?query` found inside free text (an\n * error message, a stack line). Scans for `?` and cuts at whitespace or a quote.\n */\nexport function redactUrlsInText(text: string, names: ReadonlySet<string>): string {\n let q = text.indexOf('?');\n if (q === -1) return text;\n let out = '';\n let cursor = 0;\n while (q !== -1) {\n let end = q + 1;\n while (end < text.length && !isUrlTerminator(text.charAt(end))) end++;\n out += text.slice(cursor, q) + redactUrlQuery(text.slice(q, end), names);\n cursor = end;\n q = text.indexOf('?', end);\n }\n return out + text.slice(cursor);\n}\n\n/** Shape-preserving URL redaction plus literal scrubbing of this request's secret values. */\nexport function sanitizeText(\n text: string,\n names: ReadonlySet<string>,\n values: readonly string[]\n): string {\n return scrubValues(redactUrlsInText(text, names), values);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { _ as TransportLogEntry, l as IAsyncTransport } from "./transport.types-CzJq4IrF.js";
1
+ import { _ as TransportLogEntry, l as IAsyncTransport } from "./transport.types-B1ejJJP6.mjs";
2
2
  interface OtlpLogTransportConfig {
3
3
  /** OTLP/HTTP logs endpoint, e.g. `http://localhost:4318/v1/logs`. */
4
4
  url: string;
@@ -18,6 +18,11 @@ interface OtlpLogTransportConfig {
18
18
  flushIntervalMs?: number;
19
19
  /** Abort a request that has not finished after this many ms. Default: 10000. */
20
20
  requestTimeoutMs?: number;
21
+ /**
22
+ * Request timeout (ms) while closing, so a hung collector cannot outlast the
23
+ * shutdown budget (5 s by default); also caps a request already in flight when close() starts, and close() tries twice. Default: 1500.
24
+ */
25
+ closeTimeoutMs?: number;
21
26
  /** Max buffered entries; the oldest are dropped past this. Default: 10000. */
22
27
  maxBufferSize?: number;
23
28
  level?: string;
@@ -39,6 +44,9 @@ declare class OtlpLogTransport implements IAsyncTransport {
39
44
  private readonly batchSize;
40
45
  private readonly flushIntervalMs;
41
46
  private readonly requestTimeoutMs;
47
+ private readonly closeTimeoutMs;
48
+ private closing;
49
+ private readonly inFlight;
42
50
  private readonly resourceAttrs;
43
51
  private readonly buffer;
44
52
  private flushTimer;
@@ -108,6 +116,71 @@ declare class DiscordTransport implements IAsyncTransport {
108
116
  private fitToBudget;
109
117
  private draftFor;
110
118
  }
119
+ type SentrySeverity = 'fatal' | 'error' | 'warning' | 'log' | 'info' | 'debug';
120
+ type SentryLogMethod = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
121
+ /** The part of a Sentry scope the transport uses. `withScope` hands one to its callback. */
122
+ interface SentryScopeLike {
123
+ setLevel(level: SentrySeverity): unknown;
124
+ setTag(key: string, value: string): unknown;
125
+ setExtras(extras: Record<string, unknown>): unknown;
126
+ setContext(name: string, context: Record<string, unknown> | null): unknown;
127
+ }
128
+ /** The part of the Sentry Logs API (`Sentry.logger`, SDK 9.41+) the transport uses. */
129
+ type SentryLoggerLike = Partial<Record<SentryLogMethod, (message: string, attributes?: Record<string, unknown>) => unknown>>;
130
+ /**
131
+ * The part of the Sentry JS namespace the transport calls (`import * as Sentry from
132
+ * '@sentry/node'` satisfies it). Only the two capture functions are required.
133
+ */
134
+ interface SentryLike {
135
+ captureException(exception: unknown, hint?: unknown): unknown;
136
+ captureMessage(message: string, hint?: unknown): unknown;
137
+ addBreadcrumb?(breadcrumb: Record<string, unknown>): unknown;
138
+ withScope?(callback: (scope: SentryScopeLike) => void): unknown;
139
+ logger?: SentryLoggerLike;
140
+ flush?(timeout?: number): PromiseLike<unknown>;
141
+ }
142
+ interface SentryTransportConfig {
143
+ /** Your initialised Sentry namespace, e.g. `import * as Sentry from '@sentry/node'`. */
144
+ sentry: SentryLike;
145
+ /**
146
+ * Lowest level sent as a Sentry event. Lower levels become breadcrumbs or logs.
147
+ * A logixia level name; compared by its Sentry severity. Default: 'error'.
148
+ */
149
+ minLevel?: string;
150
+ /**
151
+ * Send levels below `minLevel` to the Sentry Logs API (`sentry.logger`) instead of
152
+ * breadcrumbs. Needs SDK 9.41+ with `enableLogs: true` in `Sentry.init` (on by default
153
+ * from 10.71). Default: false. Without `sentry.logger` it falls back to breadcrumbs.
154
+ */
155
+ logs?: boolean;
156
+ /** Record levels below `minLevel` as breadcrumbs (when not sent as logs). Default: true. */
157
+ breadcrumbs?: boolean;
158
+ /** Extra or overriding level -> Sentry severity mappings, e.g. for custom levels. */
159
+ levelMap?: Record<string, SentrySeverity>;
160
+ /** Max ms `flush()` and `close()` wait for `sentry.flush`. Default: 2000. */
161
+ flushTimeoutMs?: number;
162
+ filter?: (entry: TransportLogEntry) => boolean;
163
+ }
164
+ declare class SentryTransport implements IAsyncTransport {
165
+ readonly name = "sentry";
166
+ filter?: (entry: TransportLogEntry) => boolean;
167
+ private readonly sentry;
168
+ private readonly minRank;
169
+ private readonly useLogs;
170
+ private readonly useBreadcrumbs;
171
+ private readonly levelMap;
172
+ private readonly flushTimeoutMs;
173
+ private warnedNoLogger;
174
+ constructor(config: SentryTransportConfig);
175
+ write(entry: TransportLogEntry): void;
176
+ flush(): Promise<void>;
177
+ /** Flushes pending events; the Sentry client itself stays open for the application. */
178
+ close(): Promise<void>;
179
+ private severityOf;
180
+ private captureEvent;
181
+ private sendLog;
182
+ private addBreadcrumb;
183
+ }
111
184
  /** A Slack message body as returned by a custom `formatter`. */
112
185
  interface SlackMessage {
113
186
  text?: string;
@@ -155,5 +228,5 @@ declare class SlackTransport implements IAsyncTransport {
155
228
  private buildPayload;
156
229
  private messageFor;
157
230
  }
158
- export { DiscordTransport as a, OtlpLogTransportConfig as c, DiscordEmbed as i, toOtelSeverity as l, SlackTransport as n, DiscordTransportConfig as o, SlackTransportConfig as r, OtlpLogTransport as s, SlackMessage as t };
159
- //# sourceMappingURL=slack.transport-C6E0l4kw.d.ts.map
231
+ export { SentryLoggerLike as a, SentryTransport as c, DiscordTransport as d, DiscordTransportConfig as f, toOtelSeverity as h, SentryLike as i, SentryTransportConfig as l, OtlpLogTransportConfig as m, SlackTransport as n, SentryScopeLike as o, OtlpLogTransport as p, SlackTransportConfig as r, SentrySeverity as s, SlackMessage as t, DiscordEmbed as u };
232
+ //# sourceMappingURL=slack.transport-5OPL7H3u.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.transport-5OPL7H3u.d.mts","names":[],"sources":["../src/transports/otlp.transport.ts","../src/transports/discord.transport.ts","../src/transports/sentry.transport.ts","../src/transports/slack.transport.ts"],"mappings":";UAuCiB;;EAEf;;EAEA,UAAU;;EAEV;;EAEA;;EAEA;;EAEA,qBAAqB;;EAErB;;EAEA;;EAEA;;;;;EAKA;;EAEA;EACA;;;;;;;iBA4Bc,eAAe;EAAkB;EAAgB;;cA4GpD,4BAA4B;WACvB;WACA;mBAEC;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;mBACS;mBACA;mBAEA;UACT;EAEI,YAAA,QAAQ;EAgCpB,MAAM,OAAO;;UAML;UA+BA;EAgBR,SAAS;UAID;UAIM;EAiCR,SAAS;;UC1SA;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA,SAAS;GACR;;UAGc;;EAEf;;EAEA;EACA;;EAEA;;EAEA;;;;;EAKA,aAAa,OAAO,sBAAsB;EAC1C,UAAU,OAAO;;EAEjB;;EAEA;;EAEA;EACA;;cA0FW,4BAA4B;WACvB;WACA;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EAiCpB,MAAM,OAAO;EAMb,SAAS;EAIT,SAAS;;EAKT,UAAU;UASF;;UAoBA;UAgBA;;KC9PE;KACP;;UAGY;EACf,SAAS,OAAO;EAChB,OAAO,aAAa;EACpB,UAAU,QAAQ;EAClB,WAAW,cAAc,SAAS;;;KAIxB,mBAAmB,QAC7B,OAAO,kBAAkB,iBAAiB,aAAa;;;;;UAOxC;EACf,iBAAiB,oBAAoB;EACrC,eAAe,iBAAiB;EAChC,eAAe,YAAY;EAC3B,WAAW,WAAW,OAAO;EAC7B,SAAS;EACT,OAAO,mBAAmB;;UAGX;;EAEf,QAAQ;;;;;EAKR;;;;;;EAMA;;EAEA;;EAEA,WAAW,eAAe;;EAE1B;EACA,UAAU,OAAO;;cAiDN,2BAA2B;WACtB;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;EAEI,YAAA,QAAQ;EAyBpB,MAAM,OAAO;EAeP,SAAS;;EAkBf,SAAS;UAID;UAIA;UAiCA;UAuBA;;;UCxNO;EACf;EACA;GACC;;UAGc;;EAEf;;EAEA;EACA;EACA;;EAEA;;;;;;EAMA,aAAa,OAAO,sBAAsB;EAC1C,UAAU,OAAO;;EAEjB;;EAEA;;EAEA;EACA;;cAgBW,0BAA0B;WACrB;WACA;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EA4BpB,MAAM,OAAO;EAMb,SAAS;EAIT,SAAS;;EAKT,UAAU;UASF;UAiBA"}
@@ -1,4 +1,4 @@
1
- import { _ as TransportLogEntry, l as IAsyncTransport } from "./transport.types-CzJq4IrF.mjs";
1
+ import { _ as TransportLogEntry, l as IAsyncTransport } from "./transport.types-B1ejJJP6.js";
2
2
  interface OtlpLogTransportConfig {
3
3
  /** OTLP/HTTP logs endpoint, e.g. `http://localhost:4318/v1/logs`. */
4
4
  url: string;
@@ -18,6 +18,11 @@ interface OtlpLogTransportConfig {
18
18
  flushIntervalMs?: number;
19
19
  /** Abort a request that has not finished after this many ms. Default: 10000. */
20
20
  requestTimeoutMs?: number;
21
+ /**
22
+ * Request timeout (ms) while closing, so a hung collector cannot outlast the
23
+ * shutdown budget (5 s by default); also caps a request already in flight when close() starts, and close() tries twice. Default: 1500.
24
+ */
25
+ closeTimeoutMs?: number;
21
26
  /** Max buffered entries; the oldest are dropped past this. Default: 10000. */
22
27
  maxBufferSize?: number;
23
28
  level?: string;
@@ -39,6 +44,9 @@ declare class OtlpLogTransport implements IAsyncTransport {
39
44
  private readonly batchSize;
40
45
  private readonly flushIntervalMs;
41
46
  private readonly requestTimeoutMs;
47
+ private readonly closeTimeoutMs;
48
+ private closing;
49
+ private readonly inFlight;
42
50
  private readonly resourceAttrs;
43
51
  private readonly buffer;
44
52
  private flushTimer;
@@ -108,6 +116,71 @@ declare class DiscordTransport implements IAsyncTransport {
108
116
  private fitToBudget;
109
117
  private draftFor;
110
118
  }
119
+ type SentrySeverity = 'fatal' | 'error' | 'warning' | 'log' | 'info' | 'debug';
120
+ type SentryLogMethod = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
121
+ /** The part of a Sentry scope the transport uses. `withScope` hands one to its callback. */
122
+ interface SentryScopeLike {
123
+ setLevel(level: SentrySeverity): unknown;
124
+ setTag(key: string, value: string): unknown;
125
+ setExtras(extras: Record<string, unknown>): unknown;
126
+ setContext(name: string, context: Record<string, unknown> | null): unknown;
127
+ }
128
+ /** The part of the Sentry Logs API (`Sentry.logger`, SDK 9.41+) the transport uses. */
129
+ type SentryLoggerLike = Partial<Record<SentryLogMethod, (message: string, attributes?: Record<string, unknown>) => unknown>>;
130
+ /**
131
+ * The part of the Sentry JS namespace the transport calls (`import * as Sentry from
132
+ * '@sentry/node'` satisfies it). Only the two capture functions are required.
133
+ */
134
+ interface SentryLike {
135
+ captureException(exception: unknown, hint?: unknown): unknown;
136
+ captureMessage(message: string, hint?: unknown): unknown;
137
+ addBreadcrumb?(breadcrumb: Record<string, unknown>): unknown;
138
+ withScope?(callback: (scope: SentryScopeLike) => void): unknown;
139
+ logger?: SentryLoggerLike;
140
+ flush?(timeout?: number): PromiseLike<unknown>;
141
+ }
142
+ interface SentryTransportConfig {
143
+ /** Your initialised Sentry namespace, e.g. `import * as Sentry from '@sentry/node'`. */
144
+ sentry: SentryLike;
145
+ /**
146
+ * Lowest level sent as a Sentry event. Lower levels become breadcrumbs or logs.
147
+ * A logixia level name; compared by its Sentry severity. Default: 'error'.
148
+ */
149
+ minLevel?: string;
150
+ /**
151
+ * Send levels below `minLevel` to the Sentry Logs API (`sentry.logger`) instead of
152
+ * breadcrumbs. Needs SDK 9.41+ with `enableLogs: true` in `Sentry.init` (on by default
153
+ * from 10.71). Default: false. Without `sentry.logger` it falls back to breadcrumbs.
154
+ */
155
+ logs?: boolean;
156
+ /** Record levels below `minLevel` as breadcrumbs (when not sent as logs). Default: true. */
157
+ breadcrumbs?: boolean;
158
+ /** Extra or overriding level -> Sentry severity mappings, e.g. for custom levels. */
159
+ levelMap?: Record<string, SentrySeverity>;
160
+ /** Max ms `flush()` and `close()` wait for `sentry.flush`. Default: 2000. */
161
+ flushTimeoutMs?: number;
162
+ filter?: (entry: TransportLogEntry) => boolean;
163
+ }
164
+ declare class SentryTransport implements IAsyncTransport {
165
+ readonly name = "sentry";
166
+ filter?: (entry: TransportLogEntry) => boolean;
167
+ private readonly sentry;
168
+ private readonly minRank;
169
+ private readonly useLogs;
170
+ private readonly useBreadcrumbs;
171
+ private readonly levelMap;
172
+ private readonly flushTimeoutMs;
173
+ private warnedNoLogger;
174
+ constructor(config: SentryTransportConfig);
175
+ write(entry: TransportLogEntry): void;
176
+ flush(): Promise<void>;
177
+ /** Flushes pending events; the Sentry client itself stays open for the application. */
178
+ close(): Promise<void>;
179
+ private severityOf;
180
+ private captureEvent;
181
+ private sendLog;
182
+ private addBreadcrumb;
183
+ }
111
184
  /** A Slack message body as returned by a custom `formatter`. */
112
185
  interface SlackMessage {
113
186
  text?: string;
@@ -155,5 +228,5 @@ declare class SlackTransport implements IAsyncTransport {
155
228
  private buildPayload;
156
229
  private messageFor;
157
230
  }
158
- export { DiscordTransport as a, OtlpLogTransportConfig as c, DiscordEmbed as i, toOtelSeverity as l, SlackTransport as n, DiscordTransportConfig as o, SlackTransportConfig as r, OtlpLogTransport as s, SlackMessage as t };
159
- //# sourceMappingURL=slack.transport-BDyENuR0.d.mts.map
231
+ export { SentryLoggerLike as a, SentryTransport as c, DiscordTransport as d, DiscordTransportConfig as f, toOtelSeverity as h, SentryLike as i, SentryTransportConfig as l, OtlpLogTransportConfig as m, SlackTransport as n, SentryScopeLike as o, OtlpLogTransport as p, SlackTransportConfig as r, SentrySeverity as s, SlackMessage as t, DiscordEmbed as u };
232
+ //# sourceMappingURL=slack.transport-BFpBD_Ri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.transport-BFpBD_Ri.d.ts","names":[],"sources":["../src/transports/otlp.transport.ts","../src/transports/discord.transport.ts","../src/transports/sentry.transport.ts","../src/transports/slack.transport.ts"],"mappings":";UAuCiB;;EAEf;;EAEA,UAAU;;EAEV;;EAEA;;EAEA;;EAEA,qBAAqB;;EAErB;;EAEA;;EAEA;;;;;EAKA;;EAEA;EACA;;;;;;;iBA4Bc,eAAe;EAAkB;EAAgB;;cA4GpD,4BAA4B;WACvB;WACA;mBAEC;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;mBACS;mBACA;mBAEA;UACT;EAEI,YAAA,QAAQ;EAgCpB,MAAM,OAAO;;UAML;UA+BA;EAgBR,SAAS;UAID;UAIM;EAiCR,SAAS;;UC1SA;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA,SAAS;GACR;;UAGc;;EAEf;;EAEA;EACA;;EAEA;;EAEA;;;;;EAKA,aAAa,OAAO,sBAAsB;EAC1C,UAAU,OAAO;;EAEjB;;EAEA;;EAEA;EACA;;cA0FW,4BAA4B;WACvB;WACA;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EAiCpB,MAAM,OAAO;EAMb,SAAS;EAIT,SAAS;;EAKT,UAAU;UASF;;UAoBA;UAgBA;;KC9PE;KACP;;UAGY;EACf,SAAS,OAAO;EAChB,OAAO,aAAa;EACpB,UAAU,QAAQ;EAClB,WAAW,cAAc,SAAS;;;KAIxB,mBAAmB,QAC7B,OAAO,kBAAkB,iBAAiB,aAAa;;;;;UAOxC;EACf,iBAAiB,oBAAoB;EACrC,eAAe,iBAAiB;EAChC,eAAe,YAAY;EAC3B,WAAW,WAAW,OAAO;EAC7B,SAAS;EACT,OAAO,mBAAmB;;UAGX;;EAEf,QAAQ;;;;;EAKR;;;;;;EAMA;;EAEA;;EAEA,WAAW,eAAe;;EAE1B;EACA,UAAU,OAAO;;cAiDN,2BAA2B;WACtB;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;EAEI,YAAA,QAAQ;EAyBpB,MAAM,OAAO;EAeP,SAAS;;EAkBf,SAAS;UAID;UAIA;UAiCA;UAuBA;;;UCxNO;EACf;EACA;GACC;;UAGc;;EAEf;;EAEA;EACA;EACA;;EAEA;;;;;;EAMA,aAAa,OAAO,sBAAsB;EAC1C,UAAU,OAAO;;EAEjB;;EAEA;;EAEA;EACA;;cAgBW,0BAA0B;WACrB;WACA;EACT,UAAU,OAAO;mBAEP;mBACA;mBACA;mBACA;EAEL,YAAA,QAAQ;EA4BpB,MAAM,OAAO;EAMb,SAAS;EAIT,SAAS;;EAKT,UAAU;UASF;UAiBA"}
@@ -1,9 +1,10 @@
1
- import { n as protectSecrets, r as scrubError, t as collectSecrets } from "./secret-config-D1F4MW69.mjs";
1
+ import { n as protectSecrets, r as scrubError, t as collectSecrets } from "./secret-config-Cng7XPLx.mjs";
2
2
  import { r as internalWarn, t as internalError } from "./internal-log-Cy5nF1ZL.mjs";
3
- import { i as stringifyForLog } from "./safe-stringify-pZOnzGRJ.mjs";
4
- import { g as BufferCap, t as _getOtelBridgeFieldNames } from "./otel-DAVxpArV.mjs";
5
- import { i as HttpError, o as isPermanentHttpError, t as BatchBuffer } from "./batch-buffer-BJqzpfpT.mjs";
3
+ import { i as stringifyForLog } from "./safe-stringify-B5p5ktFe.mjs";
4
+ import { g as BufferCap, t as _getOtelBridgeFieldNames } from "./otel-C5jBV_l_.mjs";
5
+ import { i as HttpError, o as isPermanentHttpError, t as BatchBuffer } from "./batch-buffer-BnmVCCwI.mjs";
6
6
  // src/transports/otlp.transport.ts
7
+ const DEFAULT_CLOSE_TIMEOUT_MS = 1500;
7
8
  const HEX_32 = /^[0-9a-f]{32}$/;
8
9
  const HEX_16 = /^[0-9a-f]{16}$/;
9
10
  /** OTLP JSON wants a 16-char lowercase hex span id; anything else (or all zeros) returns undefined. */
@@ -135,6 +136,9 @@ var OtlpLogTransport = class {
135
136
  batchSize;
136
137
  flushIntervalMs;
137
138
  requestTimeoutMs;
139
+ closeTimeoutMs;
140
+ closing = false;
141
+ inFlight = /* @__PURE__ */ new Set();
138
142
  resourceAttrs;
139
143
  buffer;
140
144
  flushTimer = null;
@@ -144,6 +148,7 @@ var OtlpLogTransport = class {
144
148
  this.batchSize = config.batchSize ?? 100;
145
149
  this.flushIntervalMs = config.flushIntervalMs ?? 5e3;
146
150
  this.requestTimeoutMs = config.requestTimeoutMs ?? 1e4;
151
+ this.closeTimeoutMs = config.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS;
147
152
  this.level = config.level;
148
153
  this.buffer = new BatchBuffer({
149
154
  name: "OtlpLogTransport",
@@ -218,7 +223,9 @@ var OtlpLogTransport = class {
218
223
  return;
219
224
  }
220
225
  const controller = new AbortController();
221
- const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
226
+ this.inFlight.add(controller);
227
+ const timeoutMs = this.closing ? Math.min(this.requestTimeoutMs, this.closeTimeoutMs) : this.requestTimeoutMs;
228
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
222
229
  try {
223
230
  const res = await fetch(this.url, {
224
231
  method: "POST",
@@ -232,10 +239,11 @@ var OtlpLogTransport = class {
232
239
  if (!res.ok) throw new HttpError(res.status, "", "OTLP export");
233
240
  } catch (err) {
234
241
  scrubError(err, this.secretValues());
235
- if (controller.signal.aborted) throw new Error(`OTLP export timed out after ${this.requestTimeoutMs}ms`, { cause: err });
242
+ if (controller.signal.aborted) throw new Error(`OTLP export timed out after ${timeoutMs}ms`, { cause: err });
236
243
  throw err;
237
244
  } finally {
238
245
  clearTimeout(timer);
246
+ this.inFlight.delete(controller);
239
247
  }
240
248
  }
241
249
  async close() {
@@ -243,7 +251,12 @@ var OtlpLogTransport = class {
243
251
  clearInterval(this.flushTimer);
244
252
  this.flushTimer = null;
245
253
  }
246
- await this.buffer.close();
254
+ this.closing = true;
255
+ for (const controller of this.inFlight) {
256
+ var _setTimeout$unref, _setTimeout;
257
+ (_setTimeout$unref = (_setTimeout = setTimeout(() => controller.abort(), this.closeTimeoutMs)).unref) === null || _setTimeout$unref === void 0 || _setTimeout$unref.call(_setTimeout);
258
+ }
259
+ await this.buffer.close(2);
247
260
  }
248
261
  };
249
262
  // src/transports/webhook-queue.ts
@@ -756,6 +769,210 @@ async function readRetryAfter(res) {
756
769
  } catch {}
757
770
  return retryAfterHeaderMs(res);
758
771
  }
772
+ // src/transports/sentry.transport.ts
773
+ const DEFAULT_FLUSH_TIMEOUT_MS = 2e3;
774
+ const MAX_CAUSE_DEPTH = 5;
775
+ const MAX_TAG_LENGTH = 200;
776
+ const SEVERITY_RANK = {
777
+ debug: 0,
778
+ log: 1,
779
+ info: 2,
780
+ warning: 3,
781
+ error: 4,
782
+ fatal: 5
783
+ };
784
+ const BUILTIN_SEVERITY = {
785
+ fatal: "fatal",
786
+ error: "error",
787
+ warn: "warning",
788
+ warning: "warning",
789
+ info: "info",
790
+ log: "log",
791
+ debug: "debug",
792
+ verbose: "debug",
793
+ trace: "debug"
794
+ };
795
+ const LOG_METHOD_BY_LEVEL = {
796
+ trace: "trace",
797
+ verbose: "trace",
798
+ debug: "debug",
799
+ info: "info",
800
+ log: "info",
801
+ warn: "warn",
802
+ warning: "warn",
803
+ error: "error",
804
+ fatal: "fatal"
805
+ };
806
+ const LOG_METHOD_BY_SEVERITY = {
807
+ debug: "debug",
808
+ log: "info",
809
+ info: "info",
810
+ warning: "warn",
811
+ error: "error",
812
+ fatal: "fatal"
813
+ };
814
+ var SentryTransport = class {
815
+ name = "sentry";
816
+ filter;
817
+ sentry;
818
+ minRank;
819
+ useLogs;
820
+ useBreadcrumbs;
821
+ levelMap;
822
+ flushTimeoutMs;
823
+ warnedNoLogger = false;
824
+ constructor(config) {
825
+ const sentry = config === null || config === void 0 ? void 0 : config.sentry;
826
+ if (!sentry || typeof sentry.captureException !== "function" || typeof sentry.captureMessage !== "function") throw new TypeError("SentryTransport: `sentry` must provide captureException and captureMessage (pass `import * as Sentry from \"@sentry/node\"`)");
827
+ this.sentry = sentry;
828
+ this.levelMap = normalizeLevelMap(config.levelMap);
829
+ const minLevel = (config.minLevel ?? "error").toLowerCase();
830
+ const minSeverity = this.levelMap[minLevel];
831
+ if (!minSeverity) throw new TypeError(`SentryTransport: unknown minLevel "${minLevel.slice(0, 40)}"`);
832
+ this.minRank = SEVERITY_RANK[minSeverity];
833
+ this.useLogs = config.logs === true;
834
+ this.useBreadcrumbs = config.breadcrumbs !== false;
835
+ this.flushTimeoutMs = Math.max(0, config.flushTimeoutMs ?? DEFAULT_FLUSH_TIMEOUT_MS);
836
+ if (config.filter) this.filter = config.filter;
837
+ }
838
+ write(entry) {
839
+ try {
840
+ const severity = this.severityOf(entry.level);
841
+ if (SEVERITY_RANK[severity] >= this.minRank) this.captureEvent(entry, severity);
842
+ else if (this.useLogs && this.sendLog(entry, severity)) {} else if (this.useBreadcrumbs) this.addBreadcrumb(entry, severity);
843
+ } catch (error) {
844
+ internalError("SentryTransport: failed to send entry", error);
845
+ }
846
+ }
847
+ async flush() {
848
+ const { flush } = this.sentry;
849
+ if (typeof flush !== "function") return;
850
+ let timer;
851
+ try {
852
+ const timeout = new Promise((resolve) => {
853
+ var _timer$unref;
854
+ timer = setTimeout(resolve, this.flushTimeoutMs + 50);
855
+ (_timer$unref = timer.unref) === null || _timer$unref === void 0 || _timer$unref.call(timer);
856
+ });
857
+ await Promise.race([Promise.resolve(flush.call(this.sentry, this.flushTimeoutMs)), timeout]);
858
+ } catch (error) {
859
+ internalError("SentryTransport: flush failed", error);
860
+ } finally {
861
+ if (timer) clearTimeout(timer);
862
+ }
863
+ }
864
+ /** Flushes pending events; the Sentry client itself stays open for the application. */
865
+ close() {
866
+ return this.flush();
867
+ }
868
+ severityOf(level) {
869
+ return this.levelMap[level.toLowerCase()] ?? "info";
870
+ }
871
+ captureEvent(entry, severity) {
872
+ const { error, rest } = splitError(entry.data);
873
+ const tags = { logixia_level: truncate(entry.level) };
874
+ if (entry.traceId) tags["trace_id"] = truncate(entry.traceId);
875
+ if (entry.context) tags["context"] = truncate(entry.context);
876
+ const extra = { ...rest };
877
+ if (error && error.message !== entry.message) extra["logMessage"] = entry.message;
878
+ const logixia = { level: entry.level };
879
+ if (entry.traceId) logixia["traceId"] = entry.traceId;
880
+ if (entry.context) logixia["context"] = entry.context;
881
+ if (entry.appName) logixia["appName"] = entry.appName;
882
+ if (entry.environment) logixia["environment"] = entry.environment;
883
+ const capture = (hint) => {
884
+ if (error) this.sentry.captureException(error, hint);
885
+ else this.sentry.captureMessage(entry.message, hint ?? severity);
886
+ };
887
+ if (typeof this.sentry.withScope === "function") this.sentry.withScope((scope) => {
888
+ scope.setLevel(severity);
889
+ for (const [key, value] of Object.entries(tags)) scope.setTag(key, value);
890
+ scope.setExtras(extra);
891
+ scope.setContext("logixia", logixia);
892
+ capture();
893
+ });
894
+ else capture({
895
+ level: severity,
896
+ tags,
897
+ extra,
898
+ contexts: { logixia }
899
+ });
900
+ }
901
+ sendLog(entry, severity) {
902
+ const logger = this.sentry.logger;
903
+ const method = logger ? LOG_METHOD_BY_LEVEL[entry.level.toLowerCase()] ?? LOG_METHOD_BY_SEVERITY[severity] : void 0;
904
+ const fn = method ? logger === null || logger === void 0 ? void 0 : logger[method] : void 0;
905
+ if (!fn) {
906
+ if (!this.warnedNoLogger) {
907
+ this.warnedNoLogger = true;
908
+ internalWarn("SentryTransport: logs: true but sentry.logger is unavailable (needs SDK 9.41+); using breadcrumbs");
909
+ }
910
+ return false;
911
+ }
912
+ const attributes = {};
913
+ for (const [key, value] of Object.entries(entry.data ?? {})) attributes[key] = attr(value);
914
+ if (entry.traceId) attributes["trace_id"] = entry.traceId;
915
+ if (entry.context) attributes["context"] = entry.context;
916
+ fn.call(logger, entry.message, attributes);
917
+ return true;
918
+ }
919
+ addBreadcrumb(entry, severity) {
920
+ if (typeof this.sentry.addBreadcrumb !== "function") return;
921
+ const data = { ...entry.data };
922
+ if (entry.traceId) data["traceId"] = entry.traceId;
923
+ this.sentry.addBreadcrumb({
924
+ category: entry.context ?? "logixia",
925
+ message: entry.message,
926
+ level: severity,
927
+ timestamp: entry.timestamp.getTime() / 1e3,
928
+ ...Object.keys(data).length > 0 ? { data } : {}
929
+ });
930
+ }
931
+ };
932
+ function normalizeLevelMap(custom) {
933
+ const map = { ...BUILTIN_SEVERITY };
934
+ for (const [level, severity] of Object.entries(custom ?? {})) if (severity in SEVERITY_RANK) map[level.toLowerCase()] = severity;
935
+ return map;
936
+ }
937
+ function truncate(value) {
938
+ return value.length > MAX_TAG_LENGTH ? value.slice(0, MAX_TAG_LENGTH) : value;
939
+ }
940
+ /** Sentry log attributes are primitives; anything else is sent as JSON text. */
941
+ function attr(value) {
942
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
943
+ return stringifyForLog(value);
944
+ }
945
+ function splitError(data) {
946
+ if (!data) return {
947
+ error: void 0,
948
+ rest: {}
949
+ };
950
+ const { error: raw, ...rest } = data;
951
+ const error = toError(raw, 0);
952
+ return error ? {
953
+ error,
954
+ rest
955
+ } : {
956
+ error: void 0,
957
+ rest: data
958
+ };
959
+ }
960
+ /** Rebuilds an Error from `serializeError` output (or passes a real Error through). */
961
+ function toError(value, depth) {
962
+ if (value instanceof Error) return value;
963
+ if (!value || typeof value !== "object") return void 0;
964
+ const { name, message, stack, cause } = value;
965
+ if (typeof message !== "string") return void 0;
966
+ const error = new Error(message);
967
+ const errorName = typeof name === "string" && name ? name : "Error";
968
+ error.name = errorName;
969
+ error.stack = typeof stack === "string" && stack ? stack : `${errorName}: ${message}`;
970
+ if (cause !== void 0 && depth < MAX_CAUSE_DEPTH) {
971
+ const nested = toError(cause, depth + 1);
972
+ if (nested) error.cause = nested;
973
+ }
974
+ return error;
975
+ }
759
976
  const SLACK_DATA_MAX = 2500;
760
977
  const SLACK_FIELD_MAX = 300;
761
978
  const SLACK_TEXT_MAX = 1e3;
@@ -898,6 +1115,6 @@ function defaultMessage(entry) {
898
1115
  blocks
899
1116
  };
900
1117
  }
901
- export { toOtelSeverity as i, DiscordTransport as n, OtlpLogTransport as r, SlackTransport as t };
1118
+ export { toOtelSeverity as a, OtlpLogTransport as i, SentryTransport as n, DiscordTransport as r, SlackTransport as t };
902
1119
 
903
- //# sourceMappingURL=slack.transport-YvaLJxNv.mjs.map
1120
+ //# sourceMappingURL=slack.transport-C6dzPJHX.mjs.map