@blyp/core 0.1.2 → 0.1.22
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.
- package/README.md +273 -14
- package/STABILITY.md +56 -0
- package/dist/ai/anthropic/index.d.ts +3 -0
- package/dist/ai/anthropic/normalize.d.ts +9 -0
- package/dist/ai/anthropic/stream.d.ts +3 -0
- package/dist/ai/anthropic/wrap.d.ts +13 -0
- package/dist/ai/anthropic.js +701 -0
- package/dist/ai/anthropic.mjs +701 -0
- package/dist/ai/fetch.js +701 -0
- package/dist/ai/fetch.mjs +701 -0
- package/dist/ai/openai/index.d.ts +3 -0
- package/dist/ai/openai/normalize.d.ts +10 -0
- package/dist/ai/openai/stream.d.ts +3 -0
- package/dist/ai/openai/wrap.d.ts +24 -0
- package/dist/ai/openai.js +701 -0
- package/dist/ai/openai.mjs +701 -0
- package/dist/ai/shared/fetch.d.ts +5 -0
- package/dist/ai/shared/index.d.ts +2 -0
- package/dist/ai/shared/normalize.d.ts +17 -0
- package/dist/ai/shared/redaction.d.ts +6 -0
- package/dist/ai/shared/stream.d.ts +7 -0
- package/dist/ai/shared/trace.d.ts +116 -0
- package/dist/ai/shared/types.d.ts +161 -0
- package/dist/ai/shared.js +701 -0
- package/dist/ai/shared.mjs +701 -0
- package/dist/ai/vercel/index.d.ts +3 -0
- package/dist/ai/vercel/middleware.d.ts +3 -0
- package/dist/ai/vercel/model.d.ts +3 -0
- package/dist/ai/vercel.js +701 -0
- package/dist/ai/vercel.mjs +701 -0
- package/dist/astro.js +701 -0
- package/dist/astro.mjs +701 -0
- package/dist/client.js +1 -1132
- package/dist/client.mjs +1 -1125
- package/dist/connectors/betterstack.js +9 -1508
- package/dist/connectors/betterstack.mjs +9 -1483
- package/dist/connectors/databuddy/index.d.ts +7 -0
- package/dist/connectors/databuddy/sender.d.ts +5 -0
- package/dist/connectors/databuddy.js +9 -0
- package/dist/connectors/databuddy.mjs +9 -0
- package/dist/connectors/delivery/backoff.d.ts +2 -0
- package/dist/connectors/delivery/manager.d.ts +44 -0
- package/dist/connectors/delivery/queue-path.d.ts +1 -0
- package/dist/connectors/delivery/sqlite-adapter-bun.d.ts +1 -0
- package/dist/connectors/delivery/sqlite-adapter-node.d.ts +1 -0
- package/dist/connectors/delivery/sqlite-client.d.ts +37 -0
- package/dist/connectors/delivery/sqlite-worker.d.ts +1 -0
- package/dist/connectors/delivery/studio-queue.d.ts +12 -0
- package/dist/connectors/delivery/types.d.ts +98 -0
- package/dist/connectors/otlp/index.d.ts +1 -0
- package/dist/connectors/otlp.js +9 -1347
- package/dist/connectors/otlp.mjs +9 -1344
- package/dist/connectors/posthog/properties.d.ts +4 -0
- package/dist/connectors/posthog/sender.d.ts +0 -1
- package/dist/connectors/posthog.js +10 -1503
- package/dist/connectors/posthog.mjs +10 -1498
- package/dist/connectors/sentry.js +9 -1356
- package/dist/connectors/sentry.mjs +9 -1333
- package/dist/core/config.d.ts +7 -2
- package/dist/core/log-record.d.ts +5 -4
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/optional-module.d.ts +1 -0
- package/dist/core/pino-pretty-loader.d.ts +4 -0
- package/dist/database.js +1 -24
- package/dist/database.mjs +1 -21
- package/dist/elysia.js +621 -4100
- package/dist/elysia.mjs +622 -4073
- package/dist/expo.js +1 -719
- package/dist/expo.mjs +1 -717
- package/dist/express.js +616 -4085
- package/dist/express.mjs +616 -4056
- package/dist/fastify.js +618 -4104
- package/dist/fastify.mjs +618 -4075
- package/dist/frameworks/astro/index.d.ts +2 -0
- package/dist/frameworks/astro/logger.d.ts +3 -0
- package/dist/frameworks/elysia/index.d.ts +1 -1
- package/dist/frameworks/elysia/logger.d.ts +2 -35
- package/dist/frameworks/nestjs/helpers.d.ts +2 -0
- package/dist/frameworks/nitro/index.d.ts +2 -0
- package/dist/frameworks/nitro/logger.d.ts +6 -0
- package/dist/frameworks/nuxt/index.d.ts +2 -0
- package/dist/frameworks/nuxt/logger.d.ts +3 -0
- package/dist/frameworks/react-router/index.d.ts +2 -0
- package/dist/frameworks/react-router/logger.d.ts +3 -0
- package/dist/frameworks/shared/h3.d.ts +19 -0
- package/dist/frameworks/shared/http.d.ts +3 -2
- package/dist/frameworks/shared/index.d.ts +2 -1
- package/dist/frameworks/shared/logger.d.ts +2 -0
- package/dist/frameworks/shared/request-context.d.ts +2 -0
- package/dist/frameworks/shared/trace.d.ts +6 -0
- package/dist/hono.js +624 -4079
- package/dist/hono.mjs +626 -4053
- package/dist/index.d.ts +57 -17
- package/dist/index.js +616 -6494
- package/dist/index.mjs +619 -6410
- package/dist/nestjs.js +626 -4574
- package/dist/nestjs.mjs +622 -4542
- package/dist/nextjs.js +625 -4107
- package/dist/nextjs.mjs +627 -4081
- package/dist/nitro.js +701 -0
- package/dist/nitro.mjs +701 -0
- package/dist/nuxt.js +701 -0
- package/dist/nuxt.mjs +701 -0
- package/dist/react-router.js +701 -0
- package/dist/react-router.mjs +701 -0
- package/dist/shared/redaction.d.ts +17 -0
- package/dist/standalone.js +606 -3258
- package/dist/standalone.mjs +611 -3234
- package/dist/sveltekit.js +625 -4106
- package/dist/sveltekit.mjs +626 -4079
- package/dist/tanstack-start.js +624 -4105
- package/dist/tanstack-start.mjs +626 -4079
- package/dist/types/connectors/databuddy.d.ts +52 -0
- package/dist/types/core/config.d.ts +89 -0
- package/dist/types/core/logger.d.ts +5 -0
- package/dist/types/core/structured-log.d.ts +2 -0
- package/dist/types/database.d.ts +1 -0
- package/dist/types/frameworks/astro.d.ts +33 -0
- package/dist/types/frameworks/client.d.ts +2 -0
- package/dist/types/frameworks/elysia.d.ts +2 -0
- package/dist/types/frameworks/express.d.ts +1 -0
- package/dist/types/frameworks/fastify.d.ts +1 -0
- package/dist/types/frameworks/hono.d.ts +1 -0
- package/dist/types/frameworks/http.d.ts +1 -0
- package/dist/types/frameworks/nestjs.d.ts +2 -0
- package/dist/types/frameworks/nextjs.d.ts +1 -0
- package/dist/types/frameworks/nitro.d.ts +63 -0
- package/dist/types/frameworks/nuxt.d.ts +12 -0
- package/dist/types/frameworks/react-router.d.ts +35 -0
- package/dist/types/frameworks/request-context.d.ts +1 -0
- package/dist/types/frameworks/shared.d.ts +28 -1
- package/dist/types/frameworks/standalone.d.ts +3 -2
- package/dist/types/frameworks/sveltekit.d.ts +1 -0
- package/dist/types/frameworks/tanstack-start.d.ts +9 -3
- package/dist/types/frameworks/workers.d.ts +3 -0
- package/dist/types/shared/client-log.d.ts +2 -1
- package/dist/workers.js +2 -626
- package/dist/workers.mjs +2 -623
- package/package.json +273 -143
- package/dist/client.js.map +0 -1
- package/dist/client.mjs.map +0 -1
- package/dist/connectors/betterstack.js.map +0 -1
- package/dist/connectors/betterstack.mjs.map +0 -1
- package/dist/connectors/otlp.js.map +0 -1
- package/dist/connectors/otlp.mjs.map +0 -1
- package/dist/connectors/posthog.js.map +0 -1
- package/dist/connectors/posthog.mjs.map +0 -1
- package/dist/connectors/sentry.js.map +0 -1
- package/dist/connectors/sentry.mjs.map +0 -1
- package/dist/database.js.map +0 -1
- package/dist/database.mjs.map +0 -1
- package/dist/elysia.js.map +0 -1
- package/dist/elysia.mjs.map +0 -1
- package/dist/expo.js.map +0 -1
- package/dist/expo.mjs.map +0 -1
- package/dist/express.js.map +0 -1
- package/dist/express.mjs.map +0 -1
- package/dist/fastify.js.map +0 -1
- package/dist/fastify.mjs.map +0 -1
- package/dist/hono.js.map +0 -1
- package/dist/hono.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/nestjs.js.map +0 -1
- package/dist/nestjs.mjs.map +0 -1
- package/dist/nextjs.js.map +0 -1
- package/dist/nextjs.mjs.map +0 -1
- package/dist/standalone.js.map +0 -1
- package/dist/standalone.mjs.map +0 -1
- package/dist/sveltekit.js.map +0 -1
- package/dist/sveltekit.mjs.map +0 -1
- package/dist/tanstack-start.js.map +0 -1
- package/dist/tanstack-start.mjs.map +0 -1
- package/dist/workers.js.map +0 -1
- package/dist/workers.mjs.map +0 -1
- package/exports/client.js +0 -3
- package/exports/client.mjs +0 -3
- package/exports/connectors/betterstack.js +0 -1
- package/exports/connectors/betterstack.mjs +0 -1
- package/exports/connectors/otlp.js +0 -1
- package/exports/connectors/otlp.mjs +0 -1
- package/exports/connectors/posthog.js +0 -1
- package/exports/connectors/posthog.mjs +0 -1
- package/exports/connectors/sentry.js +0 -1
- package/exports/connectors/sentry.mjs +0 -1
- package/exports/database.js +0 -1
- package/exports/database.mjs +0 -1
- package/exports/expo.js +0 -1
- package/exports/expo.mjs +0 -1
- package/exports/frameworks/elysia.js +0 -1
- package/exports/frameworks/elysia.mjs +0 -1
- package/exports/frameworks/express.js +0 -1
- package/exports/frameworks/express.mjs +0 -1
- package/exports/frameworks/fastify.js +0 -1
- package/exports/frameworks/fastify.mjs +0 -1
- package/exports/frameworks/hono.js +0 -1
- package/exports/frameworks/hono.mjs +0 -1
- package/exports/frameworks/nestjs.js +0 -1
- package/exports/frameworks/nestjs.mjs +0 -1
- package/exports/frameworks/nextjs.js +0 -1
- package/exports/frameworks/nextjs.mjs +0 -1
- package/exports/frameworks/standalone.js +0 -1
- package/exports/frameworks/standalone.mjs +0 -1
- package/exports/frameworks/sveltekit.js +0 -1
- package/exports/frameworks/sveltekit.mjs +0 -1
- package/exports/frameworks/tanstack-start.js +0 -1
- package/exports/frameworks/tanstack-start.mjs +0 -1
- package/exports/workers.js +0 -1
- package/exports/workers.mjs +0 -1
- package/types/client.d.ts +0 -34
- package/types/connectors/betterstack.d.ts +0 -1
- package/types/connectors/otlp.d.ts +0 -1
- package/types/connectors/posthog.d.ts +0 -1
- package/types/connectors/sentry.d.ts +0 -1
- package/types/database.d.ts +0 -1
- package/types/expo.d.ts +0 -17
- package/types/frameworks/client.d.ts +0 -160
- package/types/frameworks/elysia.d.ts +0 -1
- package/types/frameworks/expo.d.ts +0 -50
- package/types/frameworks/express.d.ts +0 -1
- package/types/frameworks/fastify.d.ts +0 -1
- package/types/frameworks/hono.d.ts +0 -1
- package/types/frameworks/nestjs.d.ts +0 -1
- package/types/frameworks/nextjs.d.ts +0 -1
- package/types/frameworks/standalone.d.ts +0 -1
- package/types/frameworks/sveltekit.d.ts +0 -1
- package/types/frameworks/tanstack-start.d.ts +0 -1
- package/types/frameworks/workers.d.ts +0 -115
- package/types/index.d.ts +0 -1
- package/types/workers.d.ts +0 -13
package/dist/fastify.js
CHANGED
|
@@ -1,4187 +1,701 @@
|
|
|
1
|
-
'use strict';
|
|
1
|
+
'use strict';var Yo=require('fastify-plugin'),zod=require('zod'),S=require('fs'),jiti=require('jiti'),U=require('path'),tn=require('os'),fflate=require('fflate'),tr=require('pino'),module$1=require('module'),async_hooks=require('async_hooks'),crypto=require('crypto'),worker_threads=require('worker_threads');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Yo__default=/*#__PURE__*/_interopDefault(Yo);var S__default=/*#__PURE__*/_interopDefault(S);var U__default=/*#__PURE__*/_interopDefault(U);var tn__default=/*#__PURE__*/_interopDefault(tn);var tr__default=/*#__PURE__*/_interopDefault(tr);var Dr=Object.defineProperty;var kr=(e,t,r)=>t in e?Dr(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var l=(e,t,r)=>kr(e,typeof t!="symbol"?t+"":t,r);function re(e){return `${{GET:"\x1B[32m",POST:"\x1B[36m",PUT:"\x1B[33m",PATCH:"\x1B[34m",DELETE:"\x1B[31m"}[e.toUpperCase()]||""}${e}\x1B[0m`}function ne(e){let t="\x1B[0m";return e>=500?`\x1B[31m${e}${t}`:e>=400?`\x1B[33m${e}${t}`:e>=300?`\x1B[36m${e}${t}`:e>=200?`\x1B[32m${e}${t}`:`\x1B[37m${e}${t}`}function dt(e){return {GET:"\u2192",POST:"\u2191",PUT:"\u21D1",PATCH:"\u2197",DELETE:"\u2715"}[e.toUpperCase()]||"\u2022"}function oe(e){let t="\x1B[0m";return e<100?`\x1B[32m${e}ms${t}`:e<300?`\x1B[33m${e}ms${t}`:e<1e3?`\x1B[31m${e}ms${t}`:`\x1B[41m\x1B[37m${e}ms${t}`}function ie(e){let t={name:e.name,message:e.message};e.stack&&(t.stack=e.stack);let r=e;return r.cause!==void 0&&(t.cause=x(r.cause)),t}function x(e,t=new WeakSet){if(e instanceof Error)return ie(e);if(typeof e=="function")return `[Function: ${e.name||"anonymous"}]`;if(typeof e=="symbol")return e.toString();if(e==null)return e;if(Array.isArray(e))return e.map(r=>x(r,t));if(typeof e=="object"){if(t.has(e))return "[Circular]";t.add(e);let r={};for(let[n,o]of Object.entries(e))r[n]=x(o,t);return t.delete(e),r}return e}function ve(e){if(typeof e=="string")return e;if(e instanceof Error)return e.message||e.name;let t=x(e);if(typeof t=="string")return t;try{return JSON.stringify(t,null,2)??String(t)}catch{return String(t)}}var gt="[REDACTED]",_r=["password","passwd","pwd","secret","token","api_key","apikey","api_secret","authorization","auth","x-api-key","private_key","privatekey","access_token","refresh_token","client_secret","session","cookie","set-cookie","ssn","credit_card","card_number","cvv","cvc","otp","pin"],Pr=["authorization","cookie","set-cookie","x-api-key","x-auth-token"],Ar=[{type:"bearer",pattern:/\bBearer\s+(?:sk-[A-Za-z0-9]{20,}|pk_(?:live|test)_[A-Za-z0-9]{16,}|eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|[A-Za-z0-9._~+/-]{20,})\b/g},{type:"jwt",pattern:/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{type:"api_key",pattern:/\b(?:sk-[A-Za-z0-9]{20,}|pk_(?:live|test)_[A-Za-z0-9]{16,})\b/g}],Br=/\b(?:\d[ -]*?){16}\b/g;function lt(e){let t=new Set,r=[];for(let n of e)typeof n!="string"||n.length===0||t.has(n)||(t.add(n),r.push(n));return r}function Ir(e){let t=e.flags.includes("g")?e.flags:`${e.flags}g`;return new RegExp(e.source,t)}function Or(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Nr(e){return new Set(e.keys.map(t=>t.toLowerCase()))}function Fr(e){return new Set([...Pr,...e.keys.map(t=>t.toLowerCase())])}function Mr(e){return e.split(".").filter(Boolean)}function Te(e,t,r=0,n=0){if(r===e.length)return n===t.length;let o=e[r];if(o==="**"){if(r===e.length-1)return true;for(let i=n;i<=t.length;i+=1)if(Te(e,t,r+1,i))return true;return false}return n>=t.length||o!=="*"&&o!==t[n]?false:Te(e,t,r+1,n+1)}function zr(e,t){return e.length===0||t.paths.length===0?false:t.paths.some(r=>Te(Mr(r),e))}function jr(e){let t=e.replace(/\D/g,"");if(t.length!==16)return false;let r=0,n=false;for(let o=t.length-1;o>=0;o-=1){let i=Number(t[o]);n&&(i*=2,i>9&&(i-=9)),r+=i,n=!n;}return r%10===0}function se(e,t,r){if(r||t.disablePatternScanning)return e;let n=e;for(let{type:o,pattern:i}of Ar)n=n.replace(i,`[REDACTED:${o}]`);n=n.replace(Br,o=>jr(o)?"[REDACTED:card]":o);for(let o of t.patterns)n=n.replace(Ir(o),"[REDACTED:pattern]");return n}function ae(e,t,r,n){if(typeof e=="string")return se(e,t,!!n.skipPatternScanning);if(e==null||typeof e=="number"||typeof e=="boolean")return e;if(Array.isArray(e))return e.map((i,a)=>ae(i,t,r,{path:[...n.path,String(a)],skipPatternScanning:n.skipPatternScanning}));if(!Or(e))return e;let o={};for(let[i,a]of Object.entries(e)){let s=[...n.path,i];if(r.has(i.toLowerCase())||zr(s,t)){if(a==null||typeof a=="string"||typeof a=="number"||typeof a=="boolean"){o[i]=gt;continue}o[i]=ae(a,t,r,{path:s,skipPatternScanning:n.skipPatternScanning});continue}o[i]=ae(a,t,r,{path:s,skipPatternScanning:n.skipPatternScanning});}return o}function T(e,t){return {keys:lt([..._r,...e?.keys??[],...t?.keys??[]]),paths:lt([...e?.paths??[],...t?.paths??[]]),patterns:[...e?.patterns??[],...t?.patterns??[]].filter(r=>r instanceof RegExp),disablePatternScanning:t?.disablePatternScanning??e?.disablePatternScanning??false}}function C(e,t,r={path:[]}){let n=x(e);return ae(n,t,Nr(t),r)}function B(e,t){return typeof e=="string"?se(e,t,false):ve(C(e,t))}function $r(e){if(!e)return {};if(e instanceof Headers){let t={};return e.forEach((r,n)=>{t[n]=r;}),t}if(typeof e.entries=="function"){let t={};for(let[r,n]of e.entries())t[r]=n;return t}return typeof e.get=="function"?{}:{...e}}function pt(e,t){let r=$r(e),n=Fr(t),o={};for(let[i,a]of Object.entries(r)){if(n.has(i.toLowerCase())){o[i]=gt;continue}if(Array.isArray(a)){o[i]=a.map(s=>se(s,t,false));continue}o[i]=typeof a=="string"?se(a,t,false):a;}return o}function b(e,t){if(!e)return;if(e instanceof Headers||typeof e.get=="function")return e.get(t)??e.get(t.toLowerCase())??void 0;let r=e,n=r[t]??r[t.toLowerCase()];return Array.isArray(n)?n[0]:n}function qr(e){return e?e.split(",").map(t=>t.trim()).filter(Boolean).map(t=>t.match(/for="?(\[[^\]]+\]|[^;,\s"]+)/i)?.[1]?.replace(/^"|"$/g,"")??"").map(t=>t.replace(/^\[|\]$/g,"")).filter(Boolean):[]}function Ur(e){return e?e.split(",").map(t=>t.trim()).filter(Boolean):[]}function Hr(e){if(e.startsWith("[")){let t=e.indexOf("]");return t>=0?e.slice(1,t):e}return e.replace(/:\d+$/,"")}function Wr(e){return /edg\//i.test(e)?"Edge":/opr\//i.test(e)||/opera/i.test(e)?"Opera":/chrome\//i.test(e)&&!/edg\//i.test(e)?"Chrome":/firefox\//i.test(e)?"Firefox":/safari\//i.test(e)&&!/chrome\//i.test(e)?"Safari":/curl\//i.test(e)?"curl":/postmanruntime/i.test(e)?"Postman":"Unknown"}function Qr(e){return /windows/i.test(e)?"Windows":/android/i.test(e)?"Android":/iphone|ipad|ipod/i.test(e)?"iOS":/mac os x|macintosh/i.test(e)?"macOS":/linux/i.test(e)?"Linux":"Unknown"}function Jr(e){return e?/bot|crawler|spider|curl|wget|postmanruntime/i.test(e)?"bot":/ipad|tablet/i.test(e)?"tablet":/mobi|iphone|android/i.test(e)?"mobile":"desktop":"unknown"}function I(e,t="/"){if(!e)return t;if(e.startsWith("http://")||e.startsWith("https://"))try{return new URL(e).pathname||t}catch{return t}if(e.startsWith("/")){let r=e.indexOf("?");return r>=0?e.slice(0,r):e}try{return new URL(e,"http://localhost").pathname||t}catch{return t}}function ce(e,t,r){return {method:e,url:t,headers:r}}function xe(e,t,r=T()){let n=t??I(e.url),o=(()=>{try{return new URL(e.url)}catch{try{return new URL(n,"http://localhost")}catch{return null}}})(),i=b(e.headers,"x-forwarded-host")??b(e.headers,"host")??o?.host??void 0,a=i?Hr(i):o?.hostname,s=i?.match(/:(\d+)$/)?.[1]??(o?.port||void 0),d=Ur(b(e.headers,"x-forwarded-for")),u=qr(b(e.headers,"forwarded")),c=[b(e.headers,"cf-connecting-ip"),b(e.headers,"true-client-ip"),b(e.headers,"fly-client-ip"),b(e.headers,"x-real-ip"),b(e.headers,"x-client-ip"),d[0],u[0]].filter(w=>!!w),p=b(e.headers,"user-agent"),m=b(e.headers,"sec-ch-ua-platform")?.replace(/^"|"$/g,"")??void 0,R=Jr(p??"");return {hostname:a,ip:c[0],forwardedFor:[...d,...u].filter((w,f,g)=>g.indexOf(w)===f),protocol:b(e.headers,"x-forwarded-proto")??(o?.protocol?o.protocol.replace(/:$/,""):void 0),port:s,userAgent:p,origin:b(e.headers,"origin"),referer:b(e.headers,"referer"),acceptLanguage:b(e.headers,"accept-language"),headers:pt(e.headers,r),client:{ip:c[0],hostname:a,browser:p?Wr(p):void 0,os:p?Qr(p):void 0,deviceType:R,platform:m,isMobile:R==="mobile"}}}function ue(e,t,r,n,o,i={},a=T()){return {type:t,method:e.method,url:r,statusCode:n,responseTime:o,...xe(e,r,a),...i}}function de(e,t,r,n){let o=re(e),i=ne(t),a=oe(n),s=dt(e);return `${o} ${s} ${i} ${r} ${a}`}function Ee(e,t){if(e==null)return t===void 0?void 0:{statusCode:t,message:`HTTP ${t}`};if(e instanceof Error){let r=e;return {status:r.status,statusCode:r.statusCode??t,code:r.code,message:e.message,stack:e.stack,why:r.why,fix:r.fix,link:r.link,details:r.details,cause:r.cause}}if(typeof e=="object"){let r=e;return {status:typeof r.status=="number"?r.status:void 0,statusCode:typeof r.statusCode=="number"?r.statusCode:t,code:typeof r.code=="string"||typeof r.code=="number"?r.code:void 0,message:typeof r.message=="string"?r.message:`HTTP ${t??500}`,stack:typeof r.stack=="string"?r.stack:void 0,why:typeof r.why=="string"?r.why:void 0,fix:typeof r.fix=="string"?r.fix:void 0,link:typeof r.link=="string"?r.link:void 0,details:r.details!==null&&typeof r.details=="object"&&!Array.isArray(r.details)?r.details:void 0,cause:r.cause}}return {statusCode:t,message:typeof e=="string"?e:`HTTP ${t??500}`}}function De(e){return e>=400}var Gr=zod.z.string().url().refine(e=>{try{let t=new URL(e);return t.protocol==="http:"||t.protocol==="https:"}catch{return false}},{message:"Expected an absolute http(s) URL"}),G=zod.z.custom(e=>e!==null&&typeof e=="object"&&!Array.isArray(e),{message:"Expected a plain object"}),_e=zod.z.string().trim().min(1);function Pe(e){return Gr.safeParse(e).success}function z(e){return G.safeParse(e).success}function O(e){return _e.safeParse(e).success}var N="/inngest";var Kr=["debug","info","warning","error","critical","success","table"],Xr=zod.z.union([zod.z.literal("betterstack"),zod.z.literal("databuddy"),zod.z.literal("posthog"),zod.z.literal("sentry"),zod.z.undefined(),zod.z.object({type:zod.z.literal("otlp"),name:_e})]);function Vr(e){return typeof e=="string"&&Kr.includes(e)}function Yr(e){return Xr.safeParse(e).success}function Zr(e){try{return e()}catch{return}}function en(){return Math.random().toString(36).slice(2,10)}function le(){let e=Zr(()=>globalThis.crypto),t=e&&typeof e.randomUUID=="function"?e.randomUUID.bind(e):void 0;return t?t():`${Date.now().toString(36)}-${en()}`}function ft(e){if(!z(e)||e.type!=="client_log"||e.source!=="client"||!Vr(e.level)||typeof e.id!="string"||typeof e.message!="string"||typeof e.clientTimestamp!="string")return false;let t=G.safeParse(e.page),r=G.safeParse(e.browser),n=G.safeParse(e.session);return !t.success||!r.success||!n.success||!Yr(e.connector)?false:typeof n.data.pageId=="string"&&typeof n.data.sessionId=="string"}function Ae(e){return e?e.startsWith("/")?e:`/${e}`:N}function mt(){return U__default.default.join(tn__default.default.homedir(),".blyp","queue.db")}function nn(e,t=new Set){return (r,n,o)=>{if(t.has(r)||typeof console>"u")return;let i=console[e];if(typeof i=="function"){if(t.add(r),o===void 0){i.call(console,n);return}i.call(console,n,o);}}}function k(e){return nn("warn",e)}var cn="@blyp/core",un=".gitignore",Ct=["blyp.config.ts","blyp.config.mts","blyp.config.cts","blyp.config.js","blyp.config.mjs","blyp.config.cjs","blyp.config.json"],dn="blyp.config.json",ln="https://us.i.posthog.com",gn="blyp-app",pn=gn,fn=new Set,_=k(fn),wt={enabled:true,maxSizeBytes:10*1024*1024,maxArchives:5,compress:true},Rt={enabled:true,dir:"",archiveDir:"",format:"ndjson",rotation:wt},Be={enabled:true,path:N},Lt=T(),j={maxAttempts:8,initialBackoffMs:500,maxBackoffMs:3e4,multiplier:2,jitter:true},v={enabled:false,memoryBufferSize:500,durableQueuePath:mt(),durableSpillStrategy:"after-first-failure",memoryBatchSize:25,sqliteWriteBatchSize:100,sqliteReadBatchSize:50,dispatchConcurrency:4,pollIntervalMs:1e3,overflowStrategy:"drop-oldest",retry:j},St={maxRetries:1,backoffMs:100},mn={strategy:"immediate",batchSize:1,flushIntervalMs:250,maxQueueSize:1e3,overflowStrategy:"drop-oldest",flushTimeoutMs:5e3,retry:St},yt={pretty:true,level:"info",destination:"file",file:Rt,clientLogging:Be,redact:Lt,connectors:{delivery:v}},K=null;function yn(e){let t=e;for(;;){let r=U.resolve(t,"package.json");if(S.existsSync(r))try{let o=JSON.parse(S.readFileSync(r,"utf-8"));if(O(o.name))return o.name}catch{}let n=U.dirname(t);if(n===t)return;t=n;}}function Oe(e=process.cwd()){return yn(e)??pn}function hn(){return {pretty:true,level:"info",destination:"file",file:{enabled:true,format:"ndjson",rotation:{enabled:true,maxSizeBytes:10*1024*1024,maxArchives:5,compress:true}},clientLogging:{enabled:true,path:N},redact:Lt,connectors:{delivery:v}}}function bn(e){let t=U.resolve(e,"package.json");if(!S.existsSync(t))return true;try{return JSON.parse(S.readFileSync(t,"utf-8")).name!==cn}catch{return true}}function Cn(e){if(Ct.some(r=>S.existsSync(U.resolve(e,r))))return;let t=U.resolve(e,dn);if(!S.existsSync(t))try{S.writeFileSync(t,`${JSON.stringify(hn(),null,2)}
|
|
2
|
+
`);}catch(r){console.error("[Blyp] Warning: Failed to create blyp.config.json:",r);}}function wn(e){let t=U.resolve(e,un);if(!S.existsSync(t)){try{S.writeFileSync(t,`logs
|
|
3
|
+
.blyp
|
|
4
|
+
`);}catch(r){console.error("[Blyp] Warning: Failed to create .gitignore:",r);}return}try{let r=S.readFileSync(t,"utf-8"),n=["logs",".blyp"].filter(i=>{let a=i.replace(".","\\.");return !new RegExp(`^(?:/?${a}/?)\\s*$`,"m").test(r)});if(n.length===0)return;let o=r.endsWith(`
|
|
5
|
+
`)?"":`
|
|
6
|
+
`;S.appendFileSync(t,`${o}${n.join(`
|
|
7
|
+
`)}
|
|
8
|
+
`);}catch(r){console.error("[Blyp] Warning: Failed to update .gitignore:",r);}}function Rn(){let e=process.cwd();bn(e)&&(Cn(e),wn(e));}function Ln(){let e=process.cwd(),t=Ct.map(n=>U.resolve(e,n)).filter(n=>S.existsSync(n));if(t.length===0)return null;if(t.length>1){let n=t[0];_(`config-multiple:${n}`,`[Blyp] Warning: Multiple config files found. Using ${n} and ignoring ${t.slice(1).join(", ")}.`);}let r=t[0];return {path:r,type:r.endsWith(".json")?"json":"jiti"}}function vt(e,t){let r=e&&typeof e=="object"&&"default"in e&&e.default!==void 0?e.default:e;return !r||typeof r!="object"||Array.isArray(r)?(_(`config-invalid:${t}`,`[Blyp] Warning: Config file ${t} did not export an object. Falling back to defaults.`),{}):r}function Sn(e){try{let t=S.readFileSync(e,"utf-8");return vt(JSON.parse(t),e)}catch(t){return console.error("[Blyp] Warning: Failed to parse blyp.config.json:",t),{}}}function vn(e){try{let t=jiti.createJiti(process.cwd(),{interopDefault:!0,moduleCache:!1,fsCache:!1});return vt(t(e),e)}catch(t){return console.error(`[Blyp] Warning: Failed to load ${e}:`,t),{}}}function Tn(e){return e.type==="json"?Sn(e.path):vn(e.path)}function ht(e){return !!e&&typeof e=="object"&&e.type==="prisma"}function xn(e){return !!e&&typeof e=="object"&&e.type==="drizzle"}function En(e,t){return {...St,...e,...t}}function Dn(e,t){return {...mn,...e,...t,retry:En(e?.retry,t?.retry)}}function kn(e){let t=e.model??"blypLog",n=e.client?.[t];return !!n&&typeof n.create=="function"}function _n(e){let t=e.db;return !!t&&typeof t.insert=="function"&&e.table!==void 0}function Pn(e,t){if(!e)return;let r=e.adapter,n=false;t==="json"?_("database-json-config","[Blyp] Warning: Database logging requires an executable blyp config file. Database destination remains disabled until you move this config to blyp.config.ts/js."):e.dialect!=="postgres"&&e.dialect!=="mysql"?_(`database-dialect:${String(e.dialect)}`,`[Blyp] Warning: Unsupported database dialect "${String(e.dialect)}". Database logging is disabled.`):r?ht(r)?(n=kn({...r,model:r.model??"blypLog"}),n||_("database-prisma-missing",`[Blyp] Warning: Prisma database adapter is missing the "${r.model??"blypLog"}" delegate or its create method. Database logging is disabled.`)):xn(r)&&(n=_n(r),n||_("database-drizzle-missing","[Blyp] Warning: Drizzle database adapter is missing a db.insert function or table reference. Database logging is disabled.")):_("database-adapter-missing","[Blyp] Warning: Database logging is enabled without an adapter. Database logging is disabled.");let o=ht(r)?{...r,model:r.model??"blypLog"}:r;return {dialect:e.dialect,adapter:o,delivery:Dn(void 0,e.delivery),ready:n,status:n?"enabled":"missing"}}function An(e,t){return {...wt,...e,...t}}function Bn(e,t){return {...Rt,...e,...t,rotation:An(e?.rotation,t?.rotation)}}function In(e,t){return {...Be,...e,...t,path:t?.path??e?.path??Be.path}}function On(e,t){return T(e,t)}function Nn(e,t){return {maxAttempts:Math.max(1,Math.floor(t?.maxAttempts??e?.maxAttempts??j.maxAttempts)),initialBackoffMs:Math.max(0,Math.floor(t?.initialBackoffMs??e?.initialBackoffMs??j.initialBackoffMs)),maxBackoffMs:Math.max(0,Math.floor(t?.maxBackoffMs??e?.maxBackoffMs??j.maxBackoffMs)),multiplier:Math.max(1,t?.multiplier??e?.multiplier??j.multiplier),jitter:t?.jitter??e?.jitter??j.jitter}}function Fn(e,t){let r=t?.durableQueuePath??e?.durableQueuePath??v.durableQueuePath;return {enabled:t?.enabled??e?.enabled??v.enabled,memoryBufferSize:Math.max(1,Math.floor(t?.memoryBufferSize??e?.memoryBufferSize??v.memoryBufferSize)),durableQueuePath:O(r)?r:v.durableQueuePath,durableSpillStrategy:t?.durableSpillStrategy??e?.durableSpillStrategy??v.durableSpillStrategy,memoryBatchSize:Math.max(1,Math.floor(t?.memoryBatchSize??e?.memoryBatchSize??v.memoryBatchSize)),sqliteWriteBatchSize:Math.max(1,Math.floor(t?.sqliteWriteBatchSize??e?.sqliteWriteBatchSize??v.sqliteWriteBatchSize)),sqliteReadBatchSize:Math.max(1,Math.floor(t?.sqliteReadBatchSize??e?.sqliteReadBatchSize??v.sqliteReadBatchSize)),dispatchConcurrency:Math.max(1,Math.floor(t?.dispatchConcurrency??e?.dispatchConcurrency??v.dispatchConcurrency)),pollIntervalMs:Math.max(50,Math.floor(t?.pollIntervalMs??e?.pollIntervalMs??v.pollIntervalMs)),overflowStrategy:t?.overflowStrategy??e?.overflowStrategy??v.overflowStrategy,retry:Nn(e?.retry,t?.retry),durableReady:false}}function Mn(e,t,r){if(!(!e&&!t))return Pn({dialect:t?.dialect??e?.dialect,adapter:t?.adapter??e?.adapter,delivery:{...e?.delivery??{},...t?.delivery??{},retry:{...e?.delivery?.retry??{},...t?.delivery?.retry??{}}}},r)}function zn(e,t){let r=t?.enabled??e?.enabled??false,n=t?.projectKey??e?.projectKey,o=e?.enabled===true?e?.errorTracking:void 0,i=t?.errorTracking?.mode??o?.mode??"auto",a=t?.errorTracking?.enabled??o?.enabled??r,s=r&&a&&typeof n=="string"&&n.trim().length>0;return {enabled:r,mode:t?.mode??e?.mode??"auto",projectKey:n,host:t?.host??e?.host??ln,serviceName:t?.serviceName??e?.serviceName??Oe(),errorTracking:{enabled:a,mode:i,enableExceptionAutocapture:t?.errorTracking?.enableExceptionAutocapture??o?.enableExceptionAutocapture??i==="auto",ready:s,status:s?"enabled":"missing"}}}function jn(e,t){let r=t?.enabled??e?.enabled??false,n=t?.apiKey??e?.apiKey,o=t?.websiteId??e?.websiteId,i=r&&O(n)&&O(o);return {enabled:r,mode:t?.mode??e?.mode??"auto",apiKey:n,websiteId:o,namespace:t?.namespace??e?.namespace,source:t?.source??e?.source,apiUrl:t?.apiUrl??e?.apiUrl,debug:t?.debug??e?.debug??false,enableBatching:t?.enableBatching??e?.enableBatching??true,batchSize:t?.batchSize??e?.batchSize,batchTimeout:t?.batchTimeout??e?.batchTimeout,maxQueueSize:t?.maxQueueSize??e?.maxQueueSize,ready:i,status:i?"enabled":"missing"}}function $n(e,t){let r=t?.sourceToken??e?.sourceToken,n=t?.ingestingHost??e?.ingestingHost,o=t?.enabled??e?.enabled??false,i=e?.enabled===true?e?.errorTracking:void 0,a=qn(o,i,t?.errorTracking),s=o&&O(r)&&Pe(n);return {enabled:o,mode:t?.mode??e?.mode??"auto",sourceToken:r,ingestingHost:n,serviceName:t?.serviceName??e?.serviceName??Oe(),errorTracking:a,ready:s,status:s?"enabled":"missing"}}function qn(e,t,r){let n=r?.dsn??t?.dsn,o=r?.enabled??t?.enabled??e,i=o&&O(n);return {enabled:o,dsn:n,tracesSampleRate:r?.tracesSampleRate??t?.tracesSampleRate??1,environment:r?.environment??t?.environment,release:r?.release??t?.release,ready:i,status:i?"enabled":"missing"}}function Un(e,t){let r=t?.dsn??e?.dsn,n=t?.enabled??e?.enabled??false,o=n&&typeof r=="string"&&r.trim().length>0;return {enabled:n,mode:t?.mode??e?.mode??"auto",dsn:r,environment:t?.environment??e?.environment,release:t?.release??e?.release,ready:o,status:o?"enabled":"missing"}}function Hn(e,t){let r=t?.endpoint??e?.endpoint,n=t?.enabled??e?.enabled??false,o={...{},...t?.headers??{}},i=n&&Pe(r);return {name:t?.name??e?.name??"",enabled:n,mode:t?.mode??e?.mode??"auto",endpoint:r,headers:o,auth:t?.auth??e?.auth,serviceName:t?.serviceName??e?.serviceName??Oe(),ready:i,status:i?"enabled":"missing"}}function Wn(e,t){let r=t??e??[],n=new Map;for(let o of r)!o||typeof o.name!="string"||o.name.length===0||(n.has(o.name)&&_(`otlp-duplicate:${o.name}`,`[Blyp] Warning: Duplicate OTLP connector name "${o.name}" found. Using the last definition.`),n.set(o.name,Hn(void 0,o)));return Array.from(n.values())}function Qn(e,t){return {betterstack:$n(e?.betterstack,t?.betterstack),databuddy:jn(e?.databuddy,t?.databuddy),posthog:zn(e?.posthog,t?.posthog),sentry:Un(e?.sentry,t?.sentry),otlp:Wn(e?.otlp,t?.otlp),delivery:Fn(e?.delivery,t?.delivery)}}function Ie(e,t={},r={}){return {...e,...t,destination:t.destination??e.destination??"file",file:Bn(e.file,t.file),database:Mn(e.database,t.database,r.configFileType),clientLogging:In(e.clientLogging,t.clientLogging),redact:On(e.redact,t.redact),connectors:Qn(e.connectors,t.connectors)}}function Jn(){if(K!==null)return K;Rn();let e=Ln();if(e){let t=Tn(e);K=Ie(yt,t,{configFileType:e.type});}else K=Ie(yt);return K}function X(e={}){return Ie(Jn(),e)}function Gn(e){let t=e.indexOf("?"),r=t>=0?e.substring(0,t):e;return r.endsWith("/")&&r.length>1&&(r=r.slice(0,-1)),r.startsWith("/")||(r="/"+r),r}function Kn(e){let t=e.indexOf("?"),r=t>=0?e.substring(0,t):e;return r.endsWith("/")&&r.length>1&&(r=r.slice(0,-1)),r.startsWith("/")||(r="/"+r),r}function Ne(e,t){if(!t||t.length===0)return false;let r=Gn(e);return t.some(n=>{let o=Kn(n);if(o===r||o==="/**"||o==="**")return true;if(o==="/*")return r.split("/").filter(a=>a.length>0).length===1;if(o.endsWith("/*")&&!o.includes("**")){let i=o.slice(0,-1);return r.startsWith(i)?r.slice(i.length).split("/").filter(d=>d.length>0).length===1:false}if(o.includes("**")){if(o==="/**")return true;if(o.startsWith("/")&&o.endsWith("**")){let d=o.slice(0,-2);return d.endsWith("/")&&d.length>1&&(d=d.slice(0,-1)),d===r?true:r.startsWith(d+"/")}let i=o.indexOf("**"),a=o.substring(0,i),s=o.substring(i+2);return a.endsWith("/")&&a.length>1&&(a=a.slice(0,-1)),a===""&&s===""?true:a!==""&&s===""?r.startsWith(a+"/"):a===""&&s!==""?r.endsWith(s)||r.includes(s+"/"):a!==""&&s!==""?r.startsWith(a)&&(r.endsWith(s)||r.includes(s+"/")):false}if(o.includes("*")){let i=o.lastIndexOf("."),a=o.lastIndexOf("*");if(i>a&&a>0&&o[a-1]==="/"){let c=o.slice(a),p=r.slice(r.lastIndexOf("/")+1),m=p.lastIndexOf(".");if(m>0)return p.slice(m)===c}let s=o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*");return new RegExp("^"+s+"$").test(r)}return false})}function Vn(e){return Buffer.from(fflate.gzipSync(e))}function Yn(e,t){console.warn(`[Blyp] Warning: ${e}`,t);}function pe(e){S__default.default.mkdirSync(e,{recursive:true});}function Zn(e){try{return S__default.default.statSync(e).size}catch{return 0}}function eo(e){let t=e.getUTCFullYear(),r=String(e.getUTCMonth()+1).padStart(2,"0"),n=String(e.getUTCDate()).padStart(2,"0"),o=String(e.getUTCHours()).padStart(2,"0"),i=String(e.getUTCMinutes()).padStart(2,"0"),a=String(e.getUTCSeconds()).padStart(2,"0");return `${t}${r}${n}T${o}${i}${a}Z`}function to(e,t){let r=`${e}${t}`,n=1;for(;S__default.default.existsSync(r);)r=`${e}-${n}${t}`,n+=1;return r}function ro(e,t,r,n){let o=`${t}.`;try{let i=S__default.default.readdirSync(e).filter(s=>s.startsWith(o)&&(s.endsWith(".ndjson")||s.endsWith(".ndjson.gz"))).map(s=>U__default.default.join(e,s)).sort((s,d)=>S__default.default.statSync(s).mtimeMs-S__default.default.statSync(d).mtimeMs),a=Math.max(i.length-r,0);for(let s=0;s<a;s+=1)S__default.default.rmSync(i[s]);}catch(i){n(`Failed to prune archives for ${t}`,i);}}function no(){let e=new WeakSet;return (t,r)=>{if(typeof r=="function")return `[Function: ${r.name||"anonymous"}]`;if(r===void 0)return "[undefined]";if(typeof r=="symbol")return r.toString();if(r!==null&&typeof r=="object"){if(e.has(r))return "[Circular]";e.add(r);}return r}}function Me(e){return JSON.stringify(e,no())}function oo(e){let t=e.file,r=t?.dir||e.logDir||U__default.default.join(process.cwd(),"logs"),n=t?.archiveDir||U__default.default.join(r,"archive"),o=t?.rotation;return {enabled:t?.enabled??true,dir:r,archiveDir:n,rotationEnabled:o?.enabled??true,maxSizeBytes:o?.maxSizeBytes??10*1024*1024,maxArchives:o?.maxArchives??5,compress:o?.compress??true}}var Fe=class{constructor(t,r={}){l(this,"config");l(this,"gzip");l(this,"warn");l(this,"combined");l(this,"error");this.config=oo(t),this.gzip=r.gzip??Vn,this.warn=r.warn??Yn,this.combined={activePath:U__default.default.join(this.config.dir,"log.ndjson"),archivePrefix:"log",bytes:0,queue:[],processing:false},this.error={activePath:U__default.default.join(this.config.dir,"log.error.ndjson"),archivePrefix:"log.error",bytes:0,queue:[],processing:false},this.config.enabled&&(pe(this.config.dir),pe(this.config.archiveDir),this.seedStream(this.combined),this.seedStream(this.error));}write(t){if(!this.config.enabled)return;let r=`${Me(t)}
|
|
9
|
+
`;this.enqueue(this.combined,r),(t.level==="error"||t.level==="critical")&&this.enqueue(this.error,r);}enqueue(t,r){t.queue.push(r),this.processQueue(t);}processQueue(t){if(!t.processing){t.processing=true;try{for(;t.queue.length>0;){let r=t.queue.shift();if(r!==void 0)try{this.append(t,r);}catch(n){this.warn(`Failed writing log line for ${t.archivePrefix}`,n);}}}finally{t.processing=false;}}}seedStream(t){t.bytes=Zn(t.activePath),this.config.rotationEnabled&&t.bytes>this.config.maxSizeBytes&&t.bytes>0&&(this.rotate(t),S__default.default.closeSync(S__default.default.openSync(t.activePath,"a")),t.bytes=0);}append(t,r){pe(this.config.dir);let n=Buffer.byteLength(r,"utf8");this.config.rotationEnabled&&t.bytes>0&&t.bytes+n>this.config.maxSizeBytes&&this.rotate(t),S__default.default.appendFileSync(t.activePath,r,"utf8"),t.bytes+=n;}rotate(t){if(pe(this.config.archiveDir),!S__default.default.existsSync(t.activePath)||t.bytes===0){t.bytes=0;return}let r=eo(new Date),n=U__default.default.join(this.config.archiveDir,`${t.archivePrefix}.${r}`),o=to(n,".ndjson");if(S__default.default.renameSync(t.activePath,o),this.config.compress)try{let i=`${o}.gz`,a=this.gzip(S__default.default.readFileSync(o));S__default.default.writeFileSync(i,a),S__default.default.rmSync(o);}catch(i){this.warn(`Failed to gzip archive ${o}`,i);}t.bytes=0,ro(this.config.archiveDir,t.archivePrefix,this.config.maxArchives,this.warn);}};function Tt(e){return new Fe(e)}function ze(e){return z(e.data)?e.data:e}function P(e,t){if(t in e){let o=e[t];if(typeof o=="string"||typeof o=="number")return o}let n=ze(e)[t];if(typeof n=="string"||typeof n=="number")return n}function je(e,t){let r=ze(e),o=(z(r.page)?r.page:void 0)?.[t];return typeof o=="string"?o:void 0}function $e(e,t){let r=ze(e),o=(z(r.session)?r.session:void 0)?.[t];return typeof o=="string"?o:void 0}function fe(e){return P(e,"type")}function io(e,t){let r=fe(e),n=typeof e.caller=="string"?e.caller:void 0,o=P(e,"groupId"),i=P(e,"traceId"),a=P(e,"method"),s=P(e,"path"),d=P(e,"status"),u=P(e,"duration"),c=je(e,"pathname"),p=je(e,"url"),m=$e(e,"sessionId"),R=$e(e,"pageId"),w={"blyp.level":e.level,"blyp.source":t,"blyp.payload":Me(e)},f=[["blyp.type",r],["blyp.caller",n],["blyp.group_id",o],["blyp.trace_id",i],["http.method",a],["url.path",s],["client.page_path",c],["client.page_url",p],["client.session_id",m],["client.page_id",R]],g=[["http.status_code",d],["blyp.duration_ms",u]];for(let[y,L]of f)L&&(w[y]=L);for(let[y,L]of g)L!==void 0&&(w[y]=L);return w}function qe(e,t,r={}){return {...io(e,t),...r}}var so=jiti.createJiti(typeof __filename=="string"?__filename:(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('fastify.js', document.baseURI).href)),{interopDefault:false,moduleCache:true,fsCache:false}),xt=new Map;function co(e){if(!e||typeof e!="object")return false;let t="code"in e?e.code:void 0,r="message"in e?e.message:void 0;return t==="MODULE_NOT_FOUND"||t==="ERR_MODULE_NOT_FOUND"||typeof r=="string"&&(r.includes("Cannot find module")||r.includes("Cannot find package"))}function H(e,t,r=`@blyp/core/${e}`){let n=`@blyp/core/${e}`,o=`${n}::${r}`,i=xt.get(o);if(i)return i;try{let a=so(r);return xt.set(o,a),a}catch(a){if(!co(a))throw a;let s=t.map(u=>`"${u}"`).join(", "),d=t.join(" ");throw new Error(`[Blyp] Optional connector dependencies missing for "${n}". Install ${s} to use this API. Example: bun add ${d}. You can also import directly from "${n}".`,{cause:a instanceof Error?a:void 0})}}var lo=module$1.createRequire(typeof __filename=="string"?__filename:(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('fastify.js', document.baseURI).href))),Ue=null;function go(e){if(!e||typeof e!="object")return false;let t="code"in e?e.code:void 0,r="message"in e?e.message:void 0;return t==="MODULE_NOT_FOUND"||t==="ERR_MODULE_NOT_FOUND"||typeof r=="string"&&(r.includes("Cannot find module")||r.includes("Cannot find package"))}function po(e){if(typeof e=="function")return e;if(!e||typeof e!="object")return null;let t="default"in e?e.default:void 0;return typeof t=="function"?t:null}function Et(){if(Ue)return Ue;let e;try{e=lo("pino-pretty");}catch(r){throw go(r)?new Error('[Blyp] Failed to initialize the pretty logger transport because pretty: true requires "pino-pretty" to be installed.',{cause:r instanceof Error?r:void 0}):new Error('[Blyp] Failed to initialize the pretty logger transport with "pino-pretty".',{cause:r instanceof Error?r:void 0})}let t=po(e);if(!t)throw new Error('[Blyp] Failed to initialize the pretty logger transport because "pino-pretty" did not expose a callable factory.');return Ue=t,t}var Dt=new async_hooks.AsyncLocalStorage;function mo(){return {requestScopedLoggerActive:true,structuredCollectorActive:false,structuredLogEmitted:false,mixedLoggerWarningShown:false}}function He(){let e=mo();return Dt.enterWith(e),e}function F(){return Dt.getStore()}function We(e){let t=F();t&&(t.activeLogger=e);}function V(e){let t=F();t&&(t.traceId=e);}function A(){return F()?.traceId}function Qe(){let e=F();e&&(e.structuredCollectorActive=true);}function Je(){let e=F();e&&(e.structuredLogEmitted=true);}function me(){let e=F();return !e||!e.requestScopedLoggerActive||!e.structuredCollectorActive?false:(e.mixedLoggerWarningShown||(e.mixedLoggerWarningShown=true,console.warn("[Blyp] Warning: Mixed logger usage detected for this request. The root logger call was ignored because a request-scoped structured logger is active.")),true)}var kt={success:"success",critical:"critical",warning:"warning",info:"info",debug:"debug",error:"error",warn:"warning",table:"table"};function ye(e){return e.replace(/\\/g,"/")}function yo(e){let t=ye(e);return t.startsWith("node:")||t.includes("/node_modules/pino")||t.includes("/node_modules/pino-pretty")||t.includes("/node_modules/@blyp/core/")||t.includes("/blyp/src/core/")||t.includes("/blyp/src/frameworks/")||t.includes("/blyp/src/posthog/")||t.includes("/blyp/dist/")}function ho(e){let t=ye(e),r=ye(process.cwd());return t.startsWith(`${r}/`)?t.slice(r.length+1):t}function _t(){try{let e=new Error().stack;if(!e)return {file:null,line:null};let t=e.split(`
|
|
10
|
+
`),r=null;for(let n=2;n<t.length;n+=1){let o=t[n];if(!o)continue;let i=o.match(/\((.*):(\d+):\d+\)/)||o.match(/at\s+(.*):(\d+):(\d+)/);if(!i)continue;let a=i[1]||"",s=parseInt(i[2]||"0",10)||null;if(a&&!a.includes("node_modules")&&!yo(a)){let d=ho(a);if(!ye(d).startsWith("dist/"))return {file:d,line:s};r??(r={file:d,line:s});}}if(r)return r}catch{return {file:null,line:null}}return {file:null,line:null}}var Pt=B;function At(e){return e.replace(/\u001b\[[0-9;]*m/g,"")}function Bt(e,t,r,n,o=T()){let{file:i,line:a}=_t(),s=Pt(t,o),d={timestamp:new Date().toISOString(),level:kt[e],message:At(s)},u=A();return t instanceof Error&&(d.error=C(ie(t),o)),i&&(d.caller=a!==null?`${i}:${a}`:i),r.length===1?d.data=C(r[0],o):r.length>1&&(d.data=C(r,o)),Object.keys(n).length>0&&(d.bindings=C(n,o)),u&&(d.traceId=u),d}function It(e,t,r,n,o=T()){let{file:i,line:a}=_t(),s=C(r,o),d=A(),u={message:At(Pt(t,o)),...s};return i&&(u.caller=a!==null?`${i}:${a}`:i),Object.keys(n).length>0&&(u.bindings=C(n,o)),d&&u.traceId===void 0&&(u.traceId=d),u.level=typeof s.level=="string"&&s.level.length>0?s.level:kt[e],u.timestamp=typeof s.timestamp=="string"&&s.timestamp.length>0?s.timestamp:new Date().toISOString(),u}function Ot(e){switch(e){case "debug":return "debug";case "warning":return "warning";case "warn":return "warn";case "error":return "error";case "success":return "success";case "critical":return "critical";case "table":return "table";default:return "info"}}var Ge=class{constructor(t){this.logger=t;l(this,"isAsync",false);l(this,"isReady",true);}write(t){this.logger.write(t);}async flush(){}async shutdown(){}};function Nt(e){return new Ge(Tt(e))}function Ft(e){let t=e.db;if(typeof t?.insert!="function"||e.table===void 0)throw new Error("[Blyp] Drizzle database adapter is missing a db.insert function or table reference.");return {async insert(r){r.length!==0&&await t.insert(e.table).values(r);}}}function bo(e){let t=String(e??"");return t.includes("createMany")||t.includes("Unknown argument")||t.includes("not supported")||t.includes("is not a function")}function Mt(e){let t=e.client,r=e.model??"blypLog",n=t[r];if(!n||typeof n.create!="function")throw new Error(`[Blyp] Prisma database adapter is missing the "${r}" delegate or its create method.`);let o=n,i=typeof o.createMany=="function";async function a(s){if(typeof t.$transaction=="function"){await t.$transaction(s.map(d=>o.create({data:d})));return}for(let d of s)await o.create({data:d});}return {async insert(s){if(s.length!==0){if(s.length===1){await o.create({data:s[0]});return}if(!i||typeof o.createMany!="function"){await a(s);return}try{await o.createMany({data:s});}catch(d){if(!bo(d))throw d;i=false,await a(s);}}}}}function zt(e){return typeof e=="number"&&Number.isFinite(e)?e:null}function W(e){return typeof e=="string"&&e.length>0?e:null}function wo(e){if(typeof e=="string"){let t=new Date(e);if(!Number.isNaN(t.getTime()))return t}return new Date}function jt(e){let t=x(e);return {id:crypto.randomUUID(),timestamp:wo(e.timestamp),level:e.level,message:e.message,caller:W(e.caller),type:W(e.type),traceId:W(e.traceId),groupId:W(e.groupId),method:W(e.method),path:W(e.path),status:zt(e.status),duration:zt(e.duration),hasError:t.error!=null,data:t.data??null,bindings:t.bindings??null,error:t.error??null,events:t.events??null,record:t,createdAt:new Date}}function Ro(e){return !!e&&e.type==="prisma"}function Lo(e){return !!e&&e.type==="drizzle"}function $t(e){if(Ro(e.adapter))return Mt(e.adapter);if(Lo(e.adapter))return Ft(e.adapter);throw new Error("[Blyp] Unsupported database adapter configuration.")}function So(e){return new Promise(t=>{setTimeout(t,e);})}var he=class{constructor(t){this.config=t;l(this,"isAsync",true);l(this,"isReady",true);l(this,"warnOnce",k(new Set));l(this,"queue",[]);l(this,"writer");l(this,"timer",null);l(this,"processing",false);l(this,"closed",false);l(this,"terminalError",null);l(this,"activeDispatch",null);this.writer=$t(t);}write(t){this.closed||(this.enqueue(jt(t)),this.scheduleDispatch());}async flush(){this.timer&&(clearTimeout(this.timer),this.timer=null);let t=(async()=>{if(await this.drain(),this.terminalError)throw this.terminalError})(),r=null;try{await Promise.race([t,new Promise((n,o)=>{r=setTimeout(()=>{this.warnOnce("database-flush-timeout",`[Blyp] Warning: Timed out flushing database logs after ${this.config.delivery.flushTimeoutMs}ms.`),o(new Error("[Blyp] Timed out flushing database logs."));},this.config.delivery.flushTimeoutMs);})]);}finally{r&&clearTimeout(r);}}async shutdown(){this.closed=true,await this.flush();}enqueue(t){this.queue.push(t);let r=this.queue.length-this.config.delivery.maxQueueSize;if(!(r<=0)){if(this.warnOnce("database-overflow",`[Blyp] Warning: Database log queue exceeded ${this.config.delivery.maxQueueSize} entries. Applying ${this.config.delivery.overflowStrategy} overflow handling.`),this.config.delivery.overflowStrategy==="drop-new"){this.queue.splice(this.config.delivery.maxQueueSize);return}this.queue.splice(0,r);}}scheduleDispatch(){if(!this.processing){if(this.config.delivery.strategy==="immediate"){this.drain();return}if(this.queue.length>=this.config.delivery.batchSize){this.drain();return}this.timer||(this.timer=setTimeout(()=>{this.timer=null,this.drain();},this.config.delivery.flushIntervalMs));}}async drain(){if(this.processing){this.activeDispatch&&await this.activeDispatch;return}this.processing=true,this.activeDispatch=this.processQueue();try{await this.activeDispatch;}finally{this.processing=false,this.activeDispatch=null;}}async processQueue(){for(;this.queue.length>0;){let t=this.config.delivery.strategy==="batch"?Math.max(1,this.config.delivery.batchSize):1,r=this.queue.splice(0,t);try{await this.insertWithRetry(r);}catch(n){let o=n instanceof Error?n:new Error(String(n??"Unknown database logging failure"));throw this.terminalError=o,this.warnOnce("database-insert-failure",`[Blyp] Warning: Failed to persist logs to the ${this.config.dialect??"database"} database.`,o),o}}}async insertWithRetry(t){let r=Math.max(1,this.config.delivery.retry.maxRetries+1),n=0;for(;n<r;){n+=1;try{await this.writer.insert(t);return}catch(o){if(n>=r)throw o;await So(this.config.delivery.retry.backoffMs);}}}};var Ke=class{constructor(){l(this,"isAsync",false);l(this,"isReady",false);}write(t){}async flush(){}async shutdown(){}},vo=k(new Set);function qt(e){if(e.destination!=="database")return Nt(e);let t=e.database;return t?.ready?new he(t):(vo("database-sink-disabled","[Blyp] Warning: Database destination is configured but not ready. Falling back to a no-op primary sink."),new Ke)}function Ut(e,t){let r=Math.max(1,Math.floor(e)),n=Math.pow(t.multiplier,r-1),o=Math.min(Math.max(0,Math.floor(t.initialBackoffMs*n)),Math.max(0,t.maxBackoffMs));return t.jitter?Math.floor(Math.random()*(o+1)):o}var Ht="bun:sqlite";var Wt="node:sqlite";function Qt(){return `
|
|
11
|
+
const { parentPort } = require('node:worker_threads');
|
|
12
|
+
const fs = require('node:fs');
|
|
13
|
+
const path = require('node:path');
|
|
2
14
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var jiti = require('jiti');
|
|
7
|
-
var path = require('path');
|
|
8
|
-
var apiLogs = require('@opentelemetry/api-logs');
|
|
9
|
-
var exporterLogsOtlpHttp = require('@opentelemetry/exporter-logs-otlp-http');
|
|
10
|
-
var resources = require('@opentelemetry/resources');
|
|
11
|
-
var sdkLogs = require('@opentelemetry/sdk-logs');
|
|
12
|
-
var posthogNode = require('posthog-node');
|
|
13
|
-
var fflate = require('fflate');
|
|
14
|
-
var pino = require('pino');
|
|
15
|
-
var async_hooks = require('async_hooks');
|
|
16
|
-
var crypto = require('crypto');
|
|
17
|
-
var Sentry = require('@sentry/node');
|
|
18
|
-
var node = require('@logtail/node');
|
|
15
|
+
const NODE_SQLITE_MODULE = ${JSON.stringify(Wt)};
|
|
16
|
+
const BUN_SQLITE_MODULE = ${JSON.stringify(Ht)};
|
|
17
|
+
const CLAIM_LEASE_MS = 30000;
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
let db;
|
|
20
|
+
let runtime = 'unsupported';
|
|
21
21
|
|
|
22
|
-
function
|
|
23
|
-
if (e && e.__esModule) return e;
|
|
24
|
-
var n = Object.create(null);
|
|
25
|
-
if (e) {
|
|
26
|
-
Object.keys(e).forEach(function (k) {
|
|
27
|
-
if (k !== 'default') {
|
|
28
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
29
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
get: function () { return e[k]; }
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
n.default = e;
|
|
37
|
-
return Object.freeze(n);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
var fp__default = /*#__PURE__*/_interopDefault(fp);
|
|
41
|
-
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
42
|
-
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
43
|
-
var pino__default = /*#__PURE__*/_interopDefault(pino);
|
|
44
|
-
var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
|
|
45
|
-
|
|
46
|
-
var __defProp = Object.defineProperty;
|
|
47
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
48
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
49
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
50
|
-
}) : x)(function(x) {
|
|
51
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
52
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
53
|
-
});
|
|
54
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
55
|
-
|
|
56
|
-
// src/core/colors.ts
|
|
57
|
-
function getMethodColor(method) {
|
|
58
|
-
const colors = {
|
|
59
|
-
GET: "\x1B[32m",
|
|
60
|
-
POST: "\x1B[36m",
|
|
61
|
-
PUT: "\x1B[33m",
|
|
62
|
-
PATCH: "\x1B[34m",
|
|
63
|
-
DELETE: "\x1B[31m"
|
|
64
|
-
};
|
|
65
|
-
const reset = "\x1B[0m";
|
|
66
|
-
return `${colors[method.toUpperCase()] || ""}${method}${reset}`;
|
|
67
|
-
}
|
|
68
|
-
function getStatusColor(statusCode) {
|
|
69
|
-
const reset = "\x1B[0m";
|
|
70
|
-
if (statusCode >= 500) return `\x1B[31m${statusCode}${reset}`;
|
|
71
|
-
if (statusCode >= 400) return `\x1B[33m${statusCode}${reset}`;
|
|
72
|
-
if (statusCode >= 300) return `\x1B[36m${statusCode}${reset}`;
|
|
73
|
-
if (statusCode >= 200) return `\x1B[32m${statusCode}${reset}`;
|
|
74
|
-
return `\x1B[37m${statusCode}${reset}`;
|
|
75
|
-
}
|
|
76
|
-
function getArrowForMethod(method) {
|
|
77
|
-
const arrows = {
|
|
78
|
-
GET: "\u2192",
|
|
79
|
-
POST: "\u2191",
|
|
80
|
-
PUT: "\u21D1",
|
|
81
|
-
PATCH: "\u2197",
|
|
82
|
-
DELETE: "\u2715"
|
|
83
|
-
};
|
|
84
|
-
return arrows[method.toUpperCase()] || "\u2022";
|
|
85
|
-
}
|
|
86
|
-
function getResponseTimeColor(ms) {
|
|
87
|
-
const reset = "\x1B[0m";
|
|
88
|
-
if (ms < 100) return `\x1B[32m${ms}ms${reset}`;
|
|
89
|
-
if (ms < 300) return `\x1B[33m${ms}ms${reset}`;
|
|
90
|
-
if (ms < 1e3) return `\x1B[31m${ms}ms${reset}`;
|
|
91
|
-
return `\x1B[41m\x1B[37m${ms}ms${reset}`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/frameworks/shared/http.ts
|
|
95
|
-
function getHeaderValue(headers, name) {
|
|
96
|
-
if (!headers) {
|
|
97
|
-
return void 0;
|
|
98
|
-
}
|
|
99
|
-
if (headers instanceof Headers) {
|
|
100
|
-
return headers.get(name) ?? headers.get(name.toLowerCase()) ?? void 0;
|
|
101
|
-
}
|
|
102
|
-
if (typeof headers.get === "function") {
|
|
103
|
-
const direct2 = headers.get(name);
|
|
104
|
-
return direct2 ?? headers.get(name.toLowerCase()) ?? void 0;
|
|
105
|
-
}
|
|
106
|
-
const record = headers;
|
|
107
|
-
const direct = record[name] ?? record[name.toLowerCase()];
|
|
108
|
-
if (Array.isArray(direct)) {
|
|
109
|
-
return direct[0];
|
|
110
|
-
}
|
|
111
|
-
return direct;
|
|
112
|
-
}
|
|
113
|
-
function parseForwardedHeader(value) {
|
|
114
|
-
if (!value) {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
return value.split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
118
|
-
const match = entry.match(/for="?(\[[^\]]+\]|[^;,\s"]+)/i);
|
|
119
|
-
return match?.[1]?.replace(/^"|"$/g, "") ?? "";
|
|
120
|
-
}).map((entry) => entry.replace(/^\[|\]$/g, "")).filter(Boolean);
|
|
121
|
-
}
|
|
122
|
-
function parseForwardedFor(value) {
|
|
123
|
-
if (!value) {
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
127
|
-
}
|
|
128
|
-
function stripPort(host) {
|
|
129
|
-
if (host.startsWith("[")) {
|
|
130
|
-
const endIndex = host.indexOf("]");
|
|
131
|
-
return endIndex >= 0 ? host.slice(1, endIndex) : host;
|
|
132
|
-
}
|
|
133
|
-
return host.replace(/:\d+$/, "");
|
|
134
|
-
}
|
|
135
|
-
function detectBrowser(userAgent) {
|
|
136
|
-
if (/edg\//i.test(userAgent)) return "Edge";
|
|
137
|
-
if (/opr\//i.test(userAgent) || /opera/i.test(userAgent)) return "Opera";
|
|
138
|
-
if (/chrome\//i.test(userAgent) && !/edg\//i.test(userAgent)) return "Chrome";
|
|
139
|
-
if (/firefox\//i.test(userAgent)) return "Firefox";
|
|
140
|
-
if (/safari\//i.test(userAgent) && !/chrome\//i.test(userAgent)) return "Safari";
|
|
141
|
-
if (/curl\//i.test(userAgent)) return "curl";
|
|
142
|
-
if (/postmanruntime/i.test(userAgent)) return "Postman";
|
|
143
|
-
return "Unknown";
|
|
144
|
-
}
|
|
145
|
-
function detectOperatingSystem(userAgent) {
|
|
146
|
-
if (/windows/i.test(userAgent)) return "Windows";
|
|
147
|
-
if (/android/i.test(userAgent)) return "Android";
|
|
148
|
-
if (/iphone|ipad|ipod/i.test(userAgent)) return "iOS";
|
|
149
|
-
if (/mac os x|macintosh/i.test(userAgent)) return "macOS";
|
|
150
|
-
if (/linux/i.test(userAgent)) return "Linux";
|
|
151
|
-
return "Unknown";
|
|
152
|
-
}
|
|
153
|
-
function detectDeviceType(userAgent) {
|
|
154
|
-
if (!userAgent) return "unknown";
|
|
155
|
-
if (/bot|crawler|spider|curl|wget|postmanruntime/i.test(userAgent)) return "bot";
|
|
156
|
-
if (/ipad|tablet/i.test(userAgent)) return "tablet";
|
|
157
|
-
if (/mobi|iphone|android/i.test(userAgent)) return "mobile";
|
|
158
|
-
return "desktop";
|
|
159
|
-
}
|
|
160
|
-
function extractPathname(requestUrl, fallbackPath = "/") {
|
|
161
|
-
if (!requestUrl) {
|
|
162
|
-
return fallbackPath;
|
|
163
|
-
}
|
|
164
|
-
if (requestUrl.startsWith("http://") || requestUrl.startsWith("https://")) {
|
|
165
|
-
try {
|
|
166
|
-
return new URL(requestUrl).pathname || fallbackPath;
|
|
167
|
-
} catch {
|
|
168
|
-
return fallbackPath;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (requestUrl.startsWith("/")) {
|
|
172
|
-
const queryIndex = requestUrl.indexOf("?");
|
|
173
|
-
return queryIndex >= 0 ? requestUrl.slice(0, queryIndex) : requestUrl;
|
|
174
|
-
}
|
|
175
|
-
try {
|
|
176
|
-
return new URL(requestUrl, "http://localhost").pathname || fallbackPath;
|
|
177
|
-
} catch {
|
|
178
|
-
return fallbackPath;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
function createRequestLike(method, url, headers) {
|
|
182
|
-
return { method, url, headers };
|
|
183
|
-
}
|
|
184
|
-
function buildClientDetails(request, fallbackPath) {
|
|
185
|
-
const pathname = fallbackPath ?? extractPathname(request.url);
|
|
186
|
-
const urlObject = (() => {
|
|
187
|
-
try {
|
|
188
|
-
return new URL(request.url);
|
|
189
|
-
} catch {
|
|
190
|
-
try {
|
|
191
|
-
return new URL(pathname, "http://localhost");
|
|
192
|
-
} catch {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
})();
|
|
197
|
-
const hostHeader = getHeaderValue(request.headers, "x-forwarded-host") ?? getHeaderValue(request.headers, "host") ?? urlObject?.host ?? void 0;
|
|
198
|
-
const hostname = hostHeader ? stripPort(hostHeader) : urlObject?.hostname;
|
|
199
|
-
const port = hostHeader?.match(/:(\d+)$/)?.[1] ?? (urlObject?.port || void 0);
|
|
200
|
-
const xForwardedFor = parseForwardedFor(getHeaderValue(request.headers, "x-forwarded-for"));
|
|
201
|
-
const forwardedFor = parseForwardedHeader(getHeaderValue(request.headers, "forwarded"));
|
|
202
|
-
const ipCandidates = [
|
|
203
|
-
getHeaderValue(request.headers, "cf-connecting-ip"),
|
|
204
|
-
getHeaderValue(request.headers, "true-client-ip"),
|
|
205
|
-
getHeaderValue(request.headers, "fly-client-ip"),
|
|
206
|
-
getHeaderValue(request.headers, "x-real-ip"),
|
|
207
|
-
getHeaderValue(request.headers, "x-client-ip"),
|
|
208
|
-
xForwardedFor[0],
|
|
209
|
-
forwardedFor[0]
|
|
210
|
-
].filter((value) => Boolean(value));
|
|
211
|
-
const userAgent = getHeaderValue(request.headers, "user-agent");
|
|
212
|
-
const platform = getHeaderValue(request.headers, "sec-ch-ua-platform")?.replace(/^"|"$/g, "") ?? void 0;
|
|
213
|
-
const deviceType = detectDeviceType(userAgent ?? "");
|
|
214
|
-
return {
|
|
215
|
-
hostname,
|
|
216
|
-
ip: ipCandidates[0],
|
|
217
|
-
forwardedFor: [...xForwardedFor, ...forwardedFor].filter((value, index, values) => {
|
|
218
|
-
return values.indexOf(value) === index;
|
|
219
|
-
}),
|
|
220
|
-
protocol: getHeaderValue(request.headers, "x-forwarded-proto") ?? (urlObject?.protocol ? urlObject.protocol.replace(/:$/, "") : void 0),
|
|
221
|
-
port,
|
|
222
|
-
userAgent,
|
|
223
|
-
origin: getHeaderValue(request.headers, "origin"),
|
|
224
|
-
referer: getHeaderValue(request.headers, "referer"),
|
|
225
|
-
acceptLanguage: getHeaderValue(request.headers, "accept-language"),
|
|
226
|
-
client: {
|
|
227
|
-
ip: ipCandidates[0],
|
|
228
|
-
hostname,
|
|
229
|
-
browser: userAgent ? detectBrowser(userAgent) : void 0,
|
|
230
|
-
os: userAgent ? detectOperatingSystem(userAgent) : void 0,
|
|
231
|
-
deviceType,
|
|
232
|
-
platform,
|
|
233
|
-
isMobile: deviceType === "mobile"
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
function buildRequestLogData(request, type, path3, statusCode, responseTime, extra = {}) {
|
|
238
|
-
return {
|
|
239
|
-
type,
|
|
240
|
-
method: request.method,
|
|
241
|
-
url: path3,
|
|
242
|
-
statusCode,
|
|
243
|
-
responseTime,
|
|
244
|
-
...buildClientDetails(request, path3),
|
|
245
|
-
...extra
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
function buildInfoLogMessage(method, statusCode, url, responseTime) {
|
|
249
|
-
const methodColor = getMethodColor(method);
|
|
250
|
-
const statusColor = getStatusColor(statusCode);
|
|
251
|
-
const timeColor = getResponseTimeColor(responseTime);
|
|
252
|
-
const arrow = getArrowForMethod(method);
|
|
253
|
-
return `${methodColor} ${arrow} ${statusColor} ${url} ${timeColor}`;
|
|
254
|
-
}
|
|
255
|
-
function toErrorLike(error, fallbackStatusCode) {
|
|
256
|
-
if (error === void 0 || error === null) {
|
|
257
|
-
return fallbackStatusCode === void 0 ? void 0 : { statusCode: fallbackStatusCode, message: `HTTP ${fallbackStatusCode}` };
|
|
258
|
-
}
|
|
259
|
-
if (error instanceof Error) {
|
|
260
|
-
const errorWithStatus = error;
|
|
261
|
-
return {
|
|
262
|
-
status: errorWithStatus.status,
|
|
263
|
-
statusCode: errorWithStatus.statusCode ?? fallbackStatusCode,
|
|
264
|
-
code: errorWithStatus.code,
|
|
265
|
-
message: error.message,
|
|
266
|
-
stack: error.stack,
|
|
267
|
-
why: errorWithStatus.why,
|
|
268
|
-
fix: errorWithStatus.fix,
|
|
269
|
-
link: errorWithStatus.link,
|
|
270
|
-
details: errorWithStatus.details,
|
|
271
|
-
cause: errorWithStatus.cause
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
if (typeof error === "object") {
|
|
275
|
-
const record = error;
|
|
276
|
-
return {
|
|
277
|
-
status: typeof record.status === "number" ? record.status : void 0,
|
|
278
|
-
statusCode: typeof record.statusCode === "number" ? record.statusCode : fallbackStatusCode,
|
|
279
|
-
code: typeof record.code === "string" || typeof record.code === "number" ? record.code : void 0,
|
|
280
|
-
message: typeof record.message === "string" ? record.message : `HTTP ${fallbackStatusCode ?? 500}`,
|
|
281
|
-
stack: typeof record.stack === "string" ? record.stack : void 0,
|
|
282
|
-
why: typeof record.why === "string" ? record.why : void 0,
|
|
283
|
-
fix: typeof record.fix === "string" ? record.fix : void 0,
|
|
284
|
-
link: typeof record.link === "string" ? record.link : void 0,
|
|
285
|
-
details: record.details !== null && typeof record.details === "object" && !Array.isArray(record.details) ? record.details : void 0,
|
|
286
|
-
cause: record.cause
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
return {
|
|
290
|
-
statusCode: fallbackStatusCode,
|
|
291
|
-
message: typeof error === "string" ? error : `HTTP ${fallbackStatusCode ?? 500}`
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
function isErrorStatus(statusCode) {
|
|
295
|
-
return statusCode >= 400;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// src/shared/log-value.ts
|
|
299
|
-
function normalizeError(error) {
|
|
300
|
-
const normalized = {
|
|
301
|
-
name: error.name,
|
|
302
|
-
message: error.message
|
|
303
|
-
};
|
|
304
|
-
if (error.stack) {
|
|
305
|
-
normalized.stack = error.stack;
|
|
306
|
-
}
|
|
307
|
-
const errorWithCause = error;
|
|
308
|
-
if (errorWithCause.cause !== void 0) {
|
|
309
|
-
normalized.cause = normalizeLogValue(errorWithCause.cause);
|
|
310
|
-
}
|
|
311
|
-
return normalized;
|
|
312
|
-
}
|
|
313
|
-
function normalizeLogValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
314
|
-
if (value instanceof Error) {
|
|
315
|
-
return normalizeError(value);
|
|
316
|
-
}
|
|
317
|
-
if (typeof value === "function") {
|
|
318
|
-
return `[Function: ${value.name || "anonymous"}]`;
|
|
319
|
-
}
|
|
320
|
-
if (typeof value === "symbol") {
|
|
321
|
-
return value.toString();
|
|
322
|
-
}
|
|
323
|
-
if (value === void 0 || value === null) {
|
|
324
|
-
return value;
|
|
325
|
-
}
|
|
326
|
-
if (Array.isArray(value)) {
|
|
327
|
-
return value.map((entry) => normalizeLogValue(entry, seen));
|
|
328
|
-
}
|
|
329
|
-
if (typeof value === "object") {
|
|
330
|
-
if (seen.has(value)) {
|
|
331
|
-
return "[Circular]";
|
|
332
|
-
}
|
|
333
|
-
seen.add(value);
|
|
334
|
-
const normalized = {};
|
|
335
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
336
|
-
normalized[key] = normalizeLogValue(entry, seen);
|
|
337
|
-
}
|
|
338
|
-
seen.delete(value);
|
|
339
|
-
return normalized;
|
|
340
|
-
}
|
|
341
|
-
return value;
|
|
342
|
-
}
|
|
343
|
-
function serializeLogMessage(message) {
|
|
344
|
-
if (typeof message === "string") {
|
|
345
|
-
return message;
|
|
346
|
-
}
|
|
347
|
-
if (message instanceof Error) {
|
|
348
|
-
return message.message || message.name;
|
|
349
|
-
}
|
|
350
|
-
const normalized = normalizeLogValue(message);
|
|
351
|
-
if (typeof normalized === "string") {
|
|
352
|
-
return normalized;
|
|
353
|
-
}
|
|
354
|
-
try {
|
|
355
|
-
const serialized = JSON.stringify(normalized, null, 2);
|
|
356
|
-
return serialized ?? String(normalized);
|
|
357
|
-
} catch {
|
|
358
|
-
return String(normalized);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
var absoluteHttpUrlSchema = zod.z.string().url().refine((value) => {
|
|
362
|
-
try {
|
|
363
|
-
const url = new URL(value);
|
|
364
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
365
|
-
} catch {
|
|
366
|
-
return false;
|
|
367
|
-
}
|
|
368
|
-
}, {
|
|
369
|
-
message: "Expected an absolute http(s) URL"
|
|
370
|
-
});
|
|
371
|
-
var plainObjectSchema = zod.z.custom(
|
|
372
|
-
(value) => {
|
|
373
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
374
|
-
},
|
|
375
|
-
{
|
|
376
|
-
message: "Expected a plain object"
|
|
377
|
-
}
|
|
378
|
-
);
|
|
379
|
-
var nonEmptyStringSchema = zod.z.string().trim().min(1);
|
|
380
|
-
function isAbsoluteHttpUrl(value) {
|
|
381
|
-
return absoluteHttpUrlSchema.safeParse(value).success;
|
|
382
|
-
}
|
|
383
|
-
function isPlainObject(value) {
|
|
384
|
-
return plainObjectSchema.safeParse(value).success;
|
|
385
|
-
}
|
|
386
|
-
function hasNonEmptyString(value) {
|
|
387
|
-
return nonEmptyStringSchema.safeParse(value).success;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// src/shared/client-log.ts
|
|
391
|
-
var DEFAULT_CLIENT_LOG_ENDPOINT = "/inngest";
|
|
392
|
-
var CLIENT_LOG_LEVELS = [
|
|
393
|
-
"debug",
|
|
394
|
-
"info",
|
|
395
|
-
"warning",
|
|
396
|
-
"error",
|
|
397
|
-
"critical",
|
|
398
|
-
"success",
|
|
399
|
-
"table"
|
|
400
|
-
];
|
|
401
|
-
var clientConnectorRequestSchema = zod.z.union([
|
|
402
|
-
zod.z.literal("betterstack"),
|
|
403
|
-
zod.z.literal("posthog"),
|
|
404
|
-
zod.z.literal("sentry"),
|
|
405
|
-
zod.z.undefined(),
|
|
406
|
-
zod.z.object({
|
|
407
|
-
type: zod.z.literal("otlp"),
|
|
408
|
-
name: nonEmptyStringSchema
|
|
409
|
-
})
|
|
410
|
-
]);
|
|
411
|
-
function isClientLogLevel(value) {
|
|
412
|
-
return typeof value === "string" && CLIENT_LOG_LEVELS.includes(value);
|
|
413
|
-
}
|
|
414
|
-
function isClientConnectorRequest(value) {
|
|
415
|
-
return clientConnectorRequestSchema.safeParse(value).success;
|
|
416
|
-
}
|
|
417
|
-
function isClientLogEvent(payload) {
|
|
418
|
-
if (!isPlainObject(payload)) {
|
|
419
|
-
return false;
|
|
420
|
-
}
|
|
421
|
-
if (payload.type !== "client_log" || payload.source !== "client" || !isClientLogLevel(payload.level) || typeof payload.id !== "string" || typeof payload.message !== "string" || typeof payload.clientTimestamp !== "string") {
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
const pageResult = plainObjectSchema.safeParse(payload.page);
|
|
425
|
-
const browserResult = plainObjectSchema.safeParse(payload.browser);
|
|
426
|
-
const sessionResult = plainObjectSchema.safeParse(payload.session);
|
|
427
|
-
if (!pageResult.success || !browserResult.success || !sessionResult.success) {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
if (!isClientConnectorRequest(payload.connector)) {
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
return typeof sessionResult.data.pageId === "string" && typeof sessionResult.data.sessionId === "string";
|
|
434
|
-
}
|
|
435
|
-
function normalizeEndpointPath(path3) {
|
|
436
|
-
if (!path3) {
|
|
437
|
-
return DEFAULT_CLIENT_LOG_ENDPOINT;
|
|
438
|
-
}
|
|
439
|
-
return path3.startsWith("/") ? path3 : `/${path3}`;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// src/shared/once.ts
|
|
443
|
-
function createConsoleOnceLogger(method, warnedKeys6 = /* @__PURE__ */ new Set()) {
|
|
444
|
-
return (key, message, error) => {
|
|
445
|
-
if (warnedKeys6.has(key) || typeof console === "undefined") {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
const writer = console[method];
|
|
449
|
-
if (typeof writer !== "function") {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
warnedKeys6.add(key);
|
|
453
|
-
if (error === void 0) {
|
|
454
|
-
writer.call(console, message);
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
writer.call(console, message, error);
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
function createWarnOnceLogger(warnedKeys6) {
|
|
461
|
-
return createConsoleOnceLogger("warn", warnedKeys6);
|
|
462
|
-
}
|
|
463
|
-
function createErrorOnceLogger(warnedKeys6) {
|
|
464
|
-
return createConsoleOnceLogger("error", warnedKeys6);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// src/core/config.ts
|
|
468
|
-
var PACKAGE_NAME = "@blyp/core";
|
|
469
|
-
var GITIGNORE_FILE_NAME = ".gitignore";
|
|
470
|
-
var CONFIG_FILE_NAMES = [
|
|
471
|
-
"blyp.config.ts",
|
|
472
|
-
"blyp.config.mts",
|
|
473
|
-
"blyp.config.cts",
|
|
474
|
-
"blyp.config.js",
|
|
475
|
-
"blyp.config.mjs",
|
|
476
|
-
"blyp.config.cjs",
|
|
477
|
-
"blyp.config.json"
|
|
478
|
-
];
|
|
479
|
-
var CONFIG_FILE_NAME = "blyp.config.json";
|
|
480
|
-
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
481
|
-
var DEFAULT_CONNECTOR_SERVICE_NAME = "blyp-app";
|
|
482
|
-
var DEFAULT_POSTHOG_SERVICE_NAME = DEFAULT_CONNECTOR_SERVICE_NAME;
|
|
483
|
-
var warnedKeys = /* @__PURE__ */ new Set();
|
|
484
|
-
var warnOnce = createWarnOnceLogger(warnedKeys);
|
|
485
|
-
var DEFAULT_ROTATION_CONFIG = {
|
|
486
|
-
enabled: true,
|
|
487
|
-
maxSizeBytes: 10 * 1024 * 1024,
|
|
488
|
-
maxArchives: 5,
|
|
489
|
-
compress: true
|
|
490
|
-
};
|
|
491
|
-
var DEFAULT_FILE_CONFIG = {
|
|
492
|
-
enabled: true,
|
|
493
|
-
dir: "",
|
|
494
|
-
archiveDir: "",
|
|
495
|
-
format: "ndjson",
|
|
496
|
-
rotation: DEFAULT_ROTATION_CONFIG
|
|
497
|
-
};
|
|
498
|
-
var DEFAULT_CLIENT_LOGGING_CONFIG = {
|
|
499
|
-
enabled: true,
|
|
500
|
-
path: DEFAULT_CLIENT_LOG_ENDPOINT
|
|
501
|
-
};
|
|
502
|
-
var DEFAULT_DATABASE_RETRY_CONFIG = {
|
|
503
|
-
maxRetries: 1,
|
|
504
|
-
backoffMs: 100
|
|
505
|
-
};
|
|
506
|
-
var DEFAULT_DATABASE_DELIVERY_CONFIG = {
|
|
507
|
-
strategy: "immediate",
|
|
508
|
-
batchSize: 1,
|
|
509
|
-
flushIntervalMs: 250,
|
|
510
|
-
maxQueueSize: 1e3,
|
|
511
|
-
overflowStrategy: "drop-oldest",
|
|
512
|
-
flushTimeoutMs: 5e3,
|
|
513
|
-
retry: DEFAULT_DATABASE_RETRY_CONFIG
|
|
514
|
-
};
|
|
515
|
-
var DEFAULT_CONFIG = {
|
|
516
|
-
pretty: true,
|
|
517
|
-
level: "info",
|
|
518
|
-
destination: "file",
|
|
519
|
-
file: DEFAULT_FILE_CONFIG,
|
|
520
|
-
clientLogging: DEFAULT_CLIENT_LOGGING_CONFIG,
|
|
521
|
-
connectors: {}
|
|
522
|
-
};
|
|
523
|
-
var cachedConfig = null;
|
|
524
|
-
function findNearestPackageName(startDir) {
|
|
525
|
-
let currentDir = startDir;
|
|
526
|
-
while (true) {
|
|
527
|
-
const packageJsonPath = path.resolve(currentDir, "package.json");
|
|
528
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
529
|
-
try {
|
|
530
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
531
|
-
if (hasNonEmptyString(packageJson.name)) {
|
|
532
|
-
return packageJson.name;
|
|
533
|
-
}
|
|
534
|
-
} catch {
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
const parentDir = path.dirname(currentDir);
|
|
538
|
-
if (parentDir === currentDir) {
|
|
539
|
-
return void 0;
|
|
540
|
-
}
|
|
541
|
-
currentDir = parentDir;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
function resolveDefaultConnectorServiceName(cwd = process.cwd()) {
|
|
545
|
-
return findNearestPackageName(cwd) ?? DEFAULT_POSTHOG_SERVICE_NAME;
|
|
546
|
-
}
|
|
547
|
-
function getBootstrapConfig() {
|
|
548
|
-
return {
|
|
549
|
-
pretty: true,
|
|
550
|
-
level: "info",
|
|
551
|
-
destination: "file",
|
|
552
|
-
file: {
|
|
553
|
-
enabled: true,
|
|
554
|
-
format: "ndjson",
|
|
555
|
-
rotation: {
|
|
556
|
-
enabled: true,
|
|
557
|
-
maxSizeBytes: 10 * 1024 * 1024,
|
|
558
|
-
maxArchives: 5,
|
|
559
|
-
compress: true
|
|
560
|
-
}
|
|
561
|
-
},
|
|
562
|
-
clientLogging: {
|
|
563
|
-
enabled: true,
|
|
564
|
-
path: DEFAULT_CLIENT_LOG_ENDPOINT
|
|
565
|
-
},
|
|
566
|
-
connectors: {}
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
function shouldBootstrapProjectFiles(cwd) {
|
|
570
|
-
const packageJsonPath = path.resolve(cwd, "package.json");
|
|
571
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
572
|
-
return true;
|
|
573
|
-
}
|
|
574
|
-
try {
|
|
575
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
576
|
-
return packageJson.name !== PACKAGE_NAME;
|
|
577
|
-
} catch {
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
function ensureConfigFile(cwd) {
|
|
582
|
-
if (CONFIG_FILE_NAMES.some((fileName) => fs.existsSync(path.resolve(cwd, fileName)))) {
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
const configPath = path.resolve(cwd, CONFIG_FILE_NAME);
|
|
586
|
-
if (fs.existsSync(configPath)) {
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
try {
|
|
590
|
-
fs.writeFileSync(configPath, `${JSON.stringify(getBootstrapConfig(), null, 2)}
|
|
591
|
-
`);
|
|
592
|
-
} catch (error) {
|
|
593
|
-
console.error("[Blyp] Warning: Failed to create blyp.config.json:", error);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
function ensureLogsIgnored(cwd) {
|
|
597
|
-
const gitignorePath = path.resolve(cwd, GITIGNORE_FILE_NAME);
|
|
598
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
599
|
-
try {
|
|
600
|
-
fs.writeFileSync(gitignorePath, "logs\n");
|
|
601
|
-
} catch (error) {
|
|
602
|
-
console.error("[Blyp] Warning: Failed to create .gitignore:", error);
|
|
603
|
-
}
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
try {
|
|
607
|
-
const currentContent = fs.readFileSync(gitignorePath, "utf-8");
|
|
608
|
-
if (/^(?:\/?logs\/?)\s*$/m.test(currentContent)) {
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
const separator = currentContent.endsWith("\n") ? "" : "\n";
|
|
612
|
-
fs.appendFileSync(gitignorePath, `${separator}logs
|
|
613
|
-
`);
|
|
614
|
-
} catch (error) {
|
|
615
|
-
console.error("[Blyp] Warning: Failed to update .gitignore:", error);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
function bootstrapProjectFiles() {
|
|
619
|
-
const cwd = process.cwd();
|
|
620
|
-
if (!shouldBootstrapProjectFiles(cwd)) {
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
ensureConfigFile(cwd);
|
|
624
|
-
ensureLogsIgnored(cwd);
|
|
625
|
-
}
|
|
626
|
-
function findConfigFile() {
|
|
627
|
-
const cwd = process.cwd();
|
|
628
|
-
const matches = CONFIG_FILE_NAMES.map((fileName) => path.resolve(cwd, fileName)).filter((filePath) => fs.existsSync(filePath));
|
|
629
|
-
if (matches.length === 0) {
|
|
630
|
-
return null;
|
|
631
|
-
}
|
|
632
|
-
if (matches.length > 1) {
|
|
633
|
-
const preferred = matches[0];
|
|
634
|
-
warnOnce(
|
|
635
|
-
`config-multiple:${preferred}`,
|
|
636
|
-
`[Blyp] Warning: Multiple config files found. Using ${preferred} and ignoring ${matches.slice(1).join(", ")}.`
|
|
637
|
-
);
|
|
638
|
-
}
|
|
639
|
-
const selectedPath = matches[0];
|
|
640
|
-
return {
|
|
641
|
-
path: selectedPath,
|
|
642
|
-
type: selectedPath.endsWith(".json") ? "json" : "jiti"
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
function normalizeLoadedConfig(value, configPath) {
|
|
646
|
-
const normalized = value && typeof value === "object" && "default" in value && value.default !== void 0 ? value.default : value;
|
|
647
|
-
if (!normalized || typeof normalized !== "object" || Array.isArray(normalized)) {
|
|
648
|
-
warnOnce(
|
|
649
|
-
`config-invalid:${configPath}`,
|
|
650
|
-
`[Blyp] Warning: Config file ${configPath} did not export an object. Falling back to defaults.`
|
|
651
|
-
);
|
|
652
|
-
return {};
|
|
653
|
-
}
|
|
654
|
-
return normalized;
|
|
655
|
-
}
|
|
656
|
-
function parseJsonConfigFile(configPath) {
|
|
657
|
-
try {
|
|
658
|
-
const content = fs.readFileSync(configPath, "utf-8");
|
|
659
|
-
return normalizeLoadedConfig(JSON.parse(content), configPath);
|
|
660
|
-
} catch (error) {
|
|
661
|
-
console.error("[Blyp] Warning: Failed to parse blyp.config.json:", error);
|
|
662
|
-
return {};
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
function parseExecutableConfigFile(configPath) {
|
|
666
|
-
try {
|
|
667
|
-
const jiti$1 = jiti.createJiti(process.cwd(), {
|
|
668
|
-
interopDefault: true,
|
|
669
|
-
moduleCache: false,
|
|
670
|
-
fsCache: false
|
|
671
|
-
});
|
|
672
|
-
return normalizeLoadedConfig(jiti$1(configPath), configPath);
|
|
673
|
-
} catch (error) {
|
|
674
|
-
console.error(`[Blyp] Warning: Failed to load ${configPath}:`, error);
|
|
675
|
-
return {};
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
function parseConfigFile(config) {
|
|
679
|
-
return config.type === "json" ? parseJsonConfigFile(config.path) : parseExecutableConfigFile(config.path);
|
|
680
|
-
}
|
|
681
|
-
function isPrismaAdapter(value) {
|
|
682
|
-
return !!value && typeof value === "object" && value.type === "prisma";
|
|
683
|
-
}
|
|
684
|
-
function isDrizzleAdapter(value) {
|
|
685
|
-
return !!value && typeof value === "object" && value.type === "drizzle";
|
|
686
|
-
}
|
|
687
|
-
function mergeDatabaseRetryConfig(base, override) {
|
|
688
|
-
return {
|
|
689
|
-
...DEFAULT_DATABASE_RETRY_CONFIG,
|
|
690
|
-
...base,
|
|
691
|
-
...override
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
function mergeDatabaseDeliveryConfig(base, override) {
|
|
695
|
-
return {
|
|
696
|
-
...DEFAULT_DATABASE_DELIVERY_CONFIG,
|
|
697
|
-
...base,
|
|
698
|
-
...override,
|
|
699
|
-
retry: mergeDatabaseRetryConfig(base?.retry, override?.retry)
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
function hasPrismaDelegate(adapter) {
|
|
703
|
-
const model = adapter.model ?? "blypLog";
|
|
704
|
-
const client = adapter.client;
|
|
705
|
-
const delegate = client?.[model];
|
|
706
|
-
return !!delegate && typeof delegate.create === "function";
|
|
707
|
-
}
|
|
708
|
-
function hasDrizzleAdapterShape(adapter) {
|
|
709
|
-
const db = adapter.db;
|
|
710
|
-
return !!db && typeof db.insert === "function" && adapter.table !== void 0;
|
|
711
|
-
}
|
|
712
|
-
function resolveDatabaseLoggerConfig(config, sourceType) {
|
|
713
|
-
if (!config) {
|
|
714
|
-
return void 0;
|
|
715
|
-
}
|
|
716
|
-
const adapter = config.adapter;
|
|
717
|
-
let ready = false;
|
|
718
|
-
if (sourceType === "json") {
|
|
719
|
-
warnOnce(
|
|
720
|
-
"database-json-config",
|
|
721
|
-
"[Blyp] Warning: Database logging requires an executable blyp config file. Database destination remains disabled until you move this config to blyp.config.ts/js."
|
|
722
|
-
);
|
|
723
|
-
} else if (config.dialect !== "postgres" && config.dialect !== "mysql") {
|
|
724
|
-
warnOnce(
|
|
725
|
-
`database-dialect:${String(config.dialect)}`,
|
|
726
|
-
`[Blyp] Warning: Unsupported database dialect "${String(config.dialect)}". Database logging is disabled.`
|
|
727
|
-
);
|
|
728
|
-
} else if (!adapter) {
|
|
729
|
-
warnOnce(
|
|
730
|
-
"database-adapter-missing",
|
|
731
|
-
"[Blyp] Warning: Database logging is enabled without an adapter. Database logging is disabled."
|
|
732
|
-
);
|
|
733
|
-
} else if (isPrismaAdapter(adapter)) {
|
|
734
|
-
ready = hasPrismaDelegate({
|
|
735
|
-
...adapter,
|
|
736
|
-
model: adapter.model ?? "blypLog"
|
|
737
|
-
});
|
|
738
|
-
if (!ready) {
|
|
739
|
-
warnOnce(
|
|
740
|
-
"database-prisma-missing",
|
|
741
|
-
`[Blyp] Warning: Prisma database adapter is missing the "${adapter.model ?? "blypLog"}" delegate or its create method. Database logging is disabled.`
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
} else if (isDrizzleAdapter(adapter)) {
|
|
745
|
-
ready = hasDrizzleAdapterShape(adapter);
|
|
746
|
-
if (!ready) {
|
|
747
|
-
warnOnce(
|
|
748
|
-
"database-drizzle-missing",
|
|
749
|
-
"[Blyp] Warning: Drizzle database adapter is missing a db.insert function or table reference. Database logging is disabled."
|
|
750
|
-
);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
const normalizedAdapter = isPrismaAdapter(adapter) ? {
|
|
754
|
-
...adapter,
|
|
755
|
-
model: adapter.model ?? "blypLog"
|
|
756
|
-
} : adapter;
|
|
757
|
-
return {
|
|
758
|
-
dialect: config.dialect,
|
|
759
|
-
adapter: normalizedAdapter,
|
|
760
|
-
delivery: mergeDatabaseDeliveryConfig(void 0, config.delivery),
|
|
761
|
-
ready,
|
|
762
|
-
status: ready ? "enabled" : "missing"
|
|
763
|
-
};
|
|
764
|
-
}
|
|
765
|
-
function mergeRotationConfig(base, override) {
|
|
766
|
-
return {
|
|
767
|
-
...DEFAULT_ROTATION_CONFIG,
|
|
768
|
-
...base,
|
|
769
|
-
...override
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
function mergeFileConfig(base, override) {
|
|
773
|
-
return {
|
|
774
|
-
...DEFAULT_FILE_CONFIG,
|
|
775
|
-
...base,
|
|
776
|
-
...override,
|
|
777
|
-
rotation: mergeRotationConfig(base?.rotation, override?.rotation)
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
function mergeClientLoggingConfig(base, override) {
|
|
781
|
-
return {
|
|
782
|
-
...DEFAULT_CLIENT_LOGGING_CONFIG,
|
|
783
|
-
...base,
|
|
784
|
-
...override,
|
|
785
|
-
path: override?.path ?? base?.path ?? DEFAULT_CLIENT_LOGGING_CONFIG.path
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
function mergeDatabaseLoggerConfig(base, override, sourceType) {
|
|
789
|
-
if (!base && !override) {
|
|
790
|
-
return void 0;
|
|
791
|
-
}
|
|
792
|
-
return resolveDatabaseLoggerConfig(
|
|
793
|
-
{
|
|
794
|
-
dialect: override?.dialect ?? base?.dialect,
|
|
795
|
-
adapter: override?.adapter ?? base?.adapter,
|
|
796
|
-
delivery: {
|
|
797
|
-
...base?.delivery ?? {},
|
|
798
|
-
...override?.delivery ?? {},
|
|
799
|
-
retry: {
|
|
800
|
-
...base?.delivery?.retry ?? {},
|
|
801
|
-
...override?.delivery?.retry ?? {}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
},
|
|
805
|
-
sourceType
|
|
806
|
-
);
|
|
807
|
-
}
|
|
808
|
-
function mergePostHogConnectorConfig(base, override) {
|
|
809
|
-
const enabled = override?.enabled ?? base?.enabled ?? false;
|
|
810
|
-
const projectKey = override?.projectKey ?? base?.projectKey;
|
|
811
|
-
const baseErrorTracking = base?.enabled === true ? base?.errorTracking : void 0;
|
|
812
|
-
const errorTrackingMode = override?.errorTracking?.mode ?? baseErrorTracking?.mode ?? "auto";
|
|
813
|
-
const errorTrackingEnabled = override?.errorTracking?.enabled ?? baseErrorTracking?.enabled ?? enabled;
|
|
814
|
-
const errorTrackingReady = enabled && errorTrackingEnabled && typeof projectKey === "string" && projectKey.trim().length > 0;
|
|
815
|
-
return {
|
|
816
|
-
enabled,
|
|
817
|
-
mode: override?.mode ?? base?.mode ?? "auto",
|
|
818
|
-
projectKey,
|
|
819
|
-
host: override?.host ?? base?.host ?? DEFAULT_POSTHOG_HOST,
|
|
820
|
-
serviceName: override?.serviceName ?? base?.serviceName ?? resolveDefaultConnectorServiceName(),
|
|
821
|
-
errorTracking: {
|
|
822
|
-
enabled: errorTrackingEnabled,
|
|
823
|
-
mode: errorTrackingMode,
|
|
824
|
-
enableExceptionAutocapture: override?.errorTracking?.enableExceptionAutocapture ?? baseErrorTracking?.enableExceptionAutocapture ?? errorTrackingMode === "auto",
|
|
825
|
-
ready: errorTrackingReady,
|
|
826
|
-
status: errorTrackingReady ? "enabled" : "missing"
|
|
827
|
-
}
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
function mergeBetterStackConnectorConfig(base, override) {
|
|
831
|
-
const sourceToken = override?.sourceToken ?? base?.sourceToken;
|
|
832
|
-
const ingestingHost = override?.ingestingHost ?? base?.ingestingHost;
|
|
833
|
-
const enabled = override?.enabled ?? base?.enabled ?? false;
|
|
834
|
-
const baseErrorTracking = base?.enabled === true ? base?.errorTracking : void 0;
|
|
835
|
-
const errorTracking = mergeBetterStackErrorTrackingConfig(
|
|
836
|
-
enabled,
|
|
837
|
-
baseErrorTracking,
|
|
838
|
-
override?.errorTracking
|
|
839
|
-
);
|
|
840
|
-
const ready = enabled && hasNonEmptyString(sourceToken) && isAbsoluteHttpUrl(ingestingHost);
|
|
841
|
-
return {
|
|
842
|
-
enabled,
|
|
843
|
-
mode: override?.mode ?? base?.mode ?? "auto",
|
|
844
|
-
sourceToken,
|
|
845
|
-
ingestingHost,
|
|
846
|
-
serviceName: override?.serviceName ?? base?.serviceName ?? resolveDefaultConnectorServiceName(),
|
|
847
|
-
errorTracking,
|
|
848
|
-
ready,
|
|
849
|
-
status: ready ? "enabled" : "missing"
|
|
850
|
-
};
|
|
851
|
-
}
|
|
852
|
-
function mergeBetterStackErrorTrackingConfig(connectorEnabled, base, override) {
|
|
853
|
-
const dsn = override?.dsn ?? base?.dsn;
|
|
854
|
-
const enabled = override?.enabled ?? base?.enabled ?? connectorEnabled;
|
|
855
|
-
const ready = enabled && hasNonEmptyString(dsn);
|
|
856
|
-
return {
|
|
857
|
-
enabled,
|
|
858
|
-
dsn,
|
|
859
|
-
tracesSampleRate: override?.tracesSampleRate ?? base?.tracesSampleRate ?? 1,
|
|
860
|
-
environment: override?.environment ?? base?.environment,
|
|
861
|
-
release: override?.release ?? base?.release,
|
|
862
|
-
ready,
|
|
863
|
-
status: ready ? "enabled" : "missing"
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
function mergeSentryConnectorConfig(base, override) {
|
|
867
|
-
const dsn = override?.dsn ?? base?.dsn;
|
|
868
|
-
const enabled = override?.enabled ?? base?.enabled ?? false;
|
|
869
|
-
const ready = enabled && typeof dsn === "string" && dsn.trim().length > 0;
|
|
870
|
-
return {
|
|
871
|
-
enabled,
|
|
872
|
-
mode: override?.mode ?? base?.mode ?? "auto",
|
|
873
|
-
dsn,
|
|
874
|
-
environment: override?.environment ?? base?.environment,
|
|
875
|
-
release: override?.release ?? base?.release,
|
|
876
|
-
ready,
|
|
877
|
-
status: ready ? "enabled" : "missing"
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
function mergeOTLPConnectorConfig(base, override) {
|
|
881
|
-
const endpoint = override?.endpoint ?? base?.endpoint;
|
|
882
|
-
const enabled = override?.enabled ?? base?.enabled ?? false;
|
|
883
|
-
const resolvedHeaders = {
|
|
884
|
-
...{},
|
|
885
|
-
...override?.headers ?? {}
|
|
886
|
-
};
|
|
887
|
-
const ready = enabled && isAbsoluteHttpUrl(endpoint);
|
|
888
|
-
return {
|
|
889
|
-
name: override?.name ?? base?.name ?? "",
|
|
890
|
-
enabled,
|
|
891
|
-
mode: override?.mode ?? base?.mode ?? "auto",
|
|
892
|
-
endpoint,
|
|
893
|
-
headers: resolvedHeaders,
|
|
894
|
-
auth: override?.auth ?? base?.auth,
|
|
895
|
-
serviceName: override?.serviceName ?? base?.serviceName ?? resolveDefaultConnectorServiceName(),
|
|
896
|
-
ready,
|
|
897
|
-
status: ready ? "enabled" : "missing"
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
function mergeOTLPConnectorsConfig(base, override) {
|
|
901
|
-
const source = override ?? base ?? [];
|
|
902
|
-
const deduped = /* @__PURE__ */ new Map();
|
|
903
|
-
for (const connector of source) {
|
|
904
|
-
if (!connector || typeof connector.name !== "string" || connector.name.length === 0) {
|
|
905
|
-
continue;
|
|
906
|
-
}
|
|
907
|
-
if (deduped.has(connector.name)) {
|
|
908
|
-
warnOnce(
|
|
909
|
-
`otlp-duplicate:${connector.name}`,
|
|
910
|
-
`[Blyp] Warning: Duplicate OTLP connector name "${connector.name}" found. Using the last definition.`
|
|
911
|
-
);
|
|
912
|
-
}
|
|
913
|
-
deduped.set(connector.name, mergeOTLPConnectorConfig(void 0, connector));
|
|
914
|
-
}
|
|
915
|
-
return Array.from(deduped.values());
|
|
916
|
-
}
|
|
917
|
-
function mergeConnectorsConfig(base, override) {
|
|
918
|
-
return {
|
|
919
|
-
betterstack: mergeBetterStackConnectorConfig(base?.betterstack, override?.betterstack),
|
|
920
|
-
posthog: mergePostHogConnectorConfig(base?.posthog, override?.posthog),
|
|
921
|
-
sentry: mergeSentryConnectorConfig(base?.sentry, override?.sentry),
|
|
922
|
-
otlp: mergeOTLPConnectorsConfig(base?.otlp, override?.otlp)
|
|
923
|
-
};
|
|
924
|
-
}
|
|
925
|
-
function mergeBlypConfig(base, override = {}, options = {}) {
|
|
926
|
-
return {
|
|
927
|
-
...base,
|
|
928
|
-
...override,
|
|
929
|
-
destination: override.destination ?? base.destination ?? "file",
|
|
930
|
-
file: mergeFileConfig(base.file, override.file),
|
|
931
|
-
database: mergeDatabaseLoggerConfig(base.database, override.database, options.configFileType),
|
|
932
|
-
clientLogging: mergeClientLoggingConfig(base.clientLogging, override.clientLogging),
|
|
933
|
-
connectors: mergeConnectorsConfig(base.connectors, override.connectors)
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
|
-
function loadConfig() {
|
|
937
|
-
if (cachedConfig !== null) {
|
|
938
|
-
return cachedConfig;
|
|
939
|
-
}
|
|
940
|
-
bootstrapProjectFiles();
|
|
941
|
-
const configFile = findConfigFile();
|
|
942
|
-
if (configFile) {
|
|
943
|
-
const userConfig = parseConfigFile(configFile);
|
|
944
|
-
cachedConfig = mergeBlypConfig(DEFAULT_CONFIG, userConfig, {
|
|
945
|
-
configFileType: configFile.type
|
|
946
|
-
});
|
|
947
|
-
} else {
|
|
948
|
-
cachedConfig = mergeBlypConfig(DEFAULT_CONFIG);
|
|
949
|
-
}
|
|
950
|
-
return cachedConfig;
|
|
951
|
-
}
|
|
952
|
-
function resolveConfig(overrides = {}) {
|
|
953
|
-
return mergeBlypConfig(loadConfig(), overrides);
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
// src/core/helpers.ts
|
|
957
|
-
function normalizePath(path3) {
|
|
958
|
-
const queryIndex = path3.indexOf("?");
|
|
959
|
-
let withoutQuery = queryIndex >= 0 ? path3.substring(0, queryIndex) : path3;
|
|
960
|
-
if (withoutQuery.endsWith("/") && withoutQuery.length > 1) {
|
|
961
|
-
withoutQuery = withoutQuery.slice(0, -1);
|
|
962
|
-
}
|
|
963
|
-
if (!withoutQuery.startsWith("/")) {
|
|
964
|
-
withoutQuery = "/" + withoutQuery;
|
|
965
|
-
}
|
|
966
|
-
return withoutQuery;
|
|
967
|
-
}
|
|
968
|
-
function normalizePattern(pattern) {
|
|
969
|
-
const queryIndex = pattern.indexOf("?");
|
|
970
|
-
let withoutQuery = queryIndex >= 0 ? pattern.substring(0, queryIndex) : pattern;
|
|
971
|
-
if (withoutQuery.endsWith("/") && withoutQuery.length > 1) {
|
|
972
|
-
withoutQuery = withoutQuery.slice(0, -1);
|
|
973
|
-
}
|
|
974
|
-
if (!withoutQuery.startsWith("/")) {
|
|
975
|
-
withoutQuery = "/" + withoutQuery;
|
|
976
|
-
}
|
|
977
|
-
return withoutQuery;
|
|
978
|
-
}
|
|
979
|
-
function shouldIgnorePath(path3, ignorePaths) {
|
|
980
|
-
if (!ignorePaths || ignorePaths.length === 0) {
|
|
981
|
-
return false;
|
|
982
|
-
}
|
|
983
|
-
const normalizedPath = normalizePath(path3);
|
|
984
|
-
return ignorePaths.some((ignoredPattern) => {
|
|
985
|
-
const normalizedPattern = normalizePattern(ignoredPattern);
|
|
986
|
-
if (normalizedPattern === normalizedPath) {
|
|
987
|
-
return true;
|
|
988
|
-
}
|
|
989
|
-
if (normalizedPattern === "/**" || normalizedPattern === "**") {
|
|
990
|
-
return true;
|
|
991
|
-
}
|
|
992
|
-
if (normalizedPattern === "/*") {
|
|
993
|
-
const segments = normalizedPath.split("/").filter((s) => s.length > 0);
|
|
994
|
-
return segments.length === 1;
|
|
995
|
-
}
|
|
996
|
-
if (normalizedPattern.endsWith("/*") && !normalizedPattern.includes("**")) {
|
|
997
|
-
const prefix = normalizedPattern.slice(0, -1);
|
|
998
|
-
if (normalizedPath.startsWith(prefix)) {
|
|
999
|
-
const rest = normalizedPath.slice(prefix.length);
|
|
1000
|
-
const restSegments = rest.split("/").filter((s) => s.length > 0);
|
|
1001
|
-
return restSegments.length === 1;
|
|
1002
|
-
}
|
|
1003
|
-
return false;
|
|
1004
|
-
}
|
|
1005
|
-
if (normalizedPattern.includes("**")) {
|
|
1006
|
-
if (normalizedPattern === "/**") {
|
|
1007
|
-
return true;
|
|
1008
|
-
}
|
|
1009
|
-
if (normalizedPattern.startsWith("/") && normalizedPattern.endsWith("**")) {
|
|
1010
|
-
let prefix2 = normalizedPattern.slice(0, -2);
|
|
1011
|
-
if (prefix2.endsWith("/") && prefix2.length > 1) {
|
|
1012
|
-
prefix2 = prefix2.slice(0, -1);
|
|
1013
|
-
}
|
|
1014
|
-
if (prefix2 === normalizedPath) {
|
|
1015
|
-
return true;
|
|
1016
|
-
}
|
|
1017
|
-
return normalizedPath.startsWith(prefix2 + "/");
|
|
1018
|
-
}
|
|
1019
|
-
const starIndex = normalizedPattern.indexOf("**");
|
|
1020
|
-
let prefix = normalizedPattern.substring(0, starIndex);
|
|
1021
|
-
const suffix = normalizedPattern.substring(starIndex + 2);
|
|
1022
|
-
if (prefix.endsWith("/") && prefix.length > 1) {
|
|
1023
|
-
prefix = prefix.slice(0, -1);
|
|
1024
|
-
}
|
|
1025
|
-
if (prefix === "" && suffix === "") {
|
|
1026
|
-
return true;
|
|
1027
|
-
}
|
|
1028
|
-
if (prefix !== "" && suffix === "") {
|
|
1029
|
-
return normalizedPath.startsWith(prefix + "/");
|
|
1030
|
-
}
|
|
1031
|
-
if (prefix === "" && suffix !== "") {
|
|
1032
|
-
return normalizedPath.endsWith(suffix) || normalizedPath.includes(suffix + "/");
|
|
1033
|
-
}
|
|
1034
|
-
if (prefix !== "" && suffix !== "") {
|
|
1035
|
-
return normalizedPath.startsWith(prefix) && (normalizedPath.endsWith(suffix) || normalizedPath.includes(suffix + "/"));
|
|
1036
|
-
}
|
|
1037
|
-
return false;
|
|
1038
|
-
}
|
|
1039
|
-
if (normalizedPattern.includes("*")) {
|
|
1040
|
-
const lastDotIndex = normalizedPattern.lastIndexOf(".");
|
|
1041
|
-
const lastStarIndex = normalizedPattern.lastIndexOf("*");
|
|
1042
|
-
if (lastDotIndex > lastStarIndex && lastStarIndex > 0) {
|
|
1043
|
-
const charBeforeStar = normalizedPattern[lastStarIndex - 1];
|
|
1044
|
-
if (charBeforeStar === "/") {
|
|
1045
|
-
const extPattern = normalizedPattern.slice(lastStarIndex);
|
|
1046
|
-
const filePart = normalizedPath.slice(normalizedPath.lastIndexOf("/") + 1);
|
|
1047
|
-
const extIndex = filePart.lastIndexOf(".");
|
|
1048
|
-
if (extIndex > 0) {
|
|
1049
|
-
const actualExt = filePart.slice(extIndex);
|
|
1050
|
-
return actualExt === extPattern;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
const regexPattern = normalizedPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*");
|
|
1055
|
-
const regex = new RegExp("^" + regexPattern + "$");
|
|
1056
|
-
return regex.test(normalizedPath);
|
|
1057
|
-
}
|
|
1058
|
-
return false;
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
|
-
function gzipBuffer(buf) {
|
|
1062
|
-
return Buffer.from(fflate.gzipSync(buf));
|
|
1063
|
-
}
|
|
1064
|
-
function warnWithConsole(message, error) {
|
|
1065
|
-
console.warn(`[Blyp] Warning: ${message}`, error);
|
|
1066
|
-
}
|
|
1067
|
-
function ensureDirectory(dirPath) {
|
|
1068
|
-
fs__default.default.mkdirSync(dirPath, { recursive: true });
|
|
1069
|
-
}
|
|
1070
|
-
function getFileSize(filePath) {
|
|
1071
|
-
try {
|
|
1072
|
-
return fs__default.default.statSync(filePath).size;
|
|
1073
|
-
} catch {
|
|
1074
|
-
return 0;
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
function formatArchiveTimestamp(timestamp) {
|
|
1078
|
-
const year = timestamp.getUTCFullYear();
|
|
1079
|
-
const month = String(timestamp.getUTCMonth() + 1).padStart(2, "0");
|
|
1080
|
-
const day = String(timestamp.getUTCDate()).padStart(2, "0");
|
|
1081
|
-
const hours = String(timestamp.getUTCHours()).padStart(2, "0");
|
|
1082
|
-
const minutes = String(timestamp.getUTCMinutes()).padStart(2, "0");
|
|
1083
|
-
const seconds = String(timestamp.getUTCSeconds()).padStart(2, "0");
|
|
1084
|
-
return `${year}${month}${day}T${hours}${minutes}${seconds}Z`;
|
|
1085
|
-
}
|
|
1086
|
-
function getUniqueArchivePath(basePath, extension) {
|
|
1087
|
-
let candidate = `${basePath}${extension}`;
|
|
1088
|
-
let suffix = 1;
|
|
1089
|
-
while (fs__default.default.existsSync(candidate)) {
|
|
1090
|
-
candidate = `${basePath}-${suffix}${extension}`;
|
|
1091
|
-
suffix += 1;
|
|
1092
|
-
}
|
|
1093
|
-
return candidate;
|
|
1094
|
-
}
|
|
1095
|
-
function pruneArchives(archiveDir, archivePrefix, maxArchives, warn) {
|
|
1096
|
-
const prefix = `${archivePrefix}.`;
|
|
1097
|
-
try {
|
|
1098
|
-
const archivePaths = fs__default.default.readdirSync(archiveDir).filter(
|
|
1099
|
-
(name) => name.startsWith(prefix) && (name.endsWith(".ndjson") || name.endsWith(".ndjson.gz"))
|
|
1100
|
-
).map((name) => path__default.default.join(archiveDir, name)).sort((left, right) => {
|
|
1101
|
-
return fs__default.default.statSync(left).mtimeMs - fs__default.default.statSync(right).mtimeMs;
|
|
1102
|
-
});
|
|
1103
|
-
const deleteCount = Math.max(archivePaths.length - maxArchives, 0);
|
|
1104
|
-
for (let index = 0; index < deleteCount; index += 1) {
|
|
1105
|
-
fs__default.default.rmSync(archivePaths[index]);
|
|
1106
|
-
}
|
|
1107
|
-
} catch (error) {
|
|
1108
|
-
warn(`Failed to prune archives for ${archivePrefix}`, error);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
function createSafeReplacer() {
|
|
1112
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
1113
|
-
return (_key, value) => {
|
|
1114
|
-
if (typeof value === "function") {
|
|
1115
|
-
return `[Function: ${value.name || "anonymous"}]`;
|
|
1116
|
-
}
|
|
1117
|
-
if (value === void 0) {
|
|
1118
|
-
return "[undefined]";
|
|
1119
|
-
}
|
|
1120
|
-
if (typeof value === "symbol") {
|
|
1121
|
-
return value.toString();
|
|
1122
|
-
}
|
|
1123
|
-
if (value !== null && typeof value === "object") {
|
|
1124
|
-
if (seen.has(value)) {
|
|
1125
|
-
return "[Circular]";
|
|
1126
|
-
}
|
|
1127
|
-
seen.add(value);
|
|
1128
|
-
}
|
|
1129
|
-
return value;
|
|
1130
|
-
};
|
|
1131
|
-
}
|
|
1132
|
-
function serializeLogRecord(record) {
|
|
1133
|
-
return JSON.stringify(record, createSafeReplacer());
|
|
1134
|
-
}
|
|
1135
|
-
function resolveFileLoggerConfig(config) {
|
|
1136
|
-
const fileConfig = config.file;
|
|
1137
|
-
const dir = fileConfig?.dir || config.logDir || path__default.default.join(process.cwd(), "logs");
|
|
1138
|
-
const archiveDir = fileConfig?.archiveDir || path__default.default.join(dir, "archive");
|
|
1139
|
-
const rotation = fileConfig?.rotation;
|
|
1140
|
-
return {
|
|
1141
|
-
enabled: fileConfig?.enabled ?? true,
|
|
1142
|
-
dir,
|
|
1143
|
-
archiveDir,
|
|
1144
|
-
rotationEnabled: rotation?.enabled ?? true,
|
|
1145
|
-
maxSizeBytes: rotation?.maxSizeBytes ?? 10 * 1024 * 1024,
|
|
1146
|
-
maxArchives: rotation?.maxArchives ?? 5,
|
|
1147
|
-
compress: rotation?.compress ?? true
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
var RotatingFileLogger = class {
|
|
1151
|
-
constructor(config, dependencies = {}) {
|
|
1152
|
-
__publicField(this, "config");
|
|
1153
|
-
__publicField(this, "gzip");
|
|
1154
|
-
__publicField(this, "warn");
|
|
1155
|
-
__publicField(this, "combined");
|
|
1156
|
-
__publicField(this, "error");
|
|
1157
|
-
this.config = resolveFileLoggerConfig(config);
|
|
1158
|
-
this.gzip = dependencies.gzip ?? gzipBuffer;
|
|
1159
|
-
this.warn = dependencies.warn ?? warnWithConsole;
|
|
1160
|
-
this.combined = {
|
|
1161
|
-
activePath: path__default.default.join(this.config.dir, "log.ndjson"),
|
|
1162
|
-
archivePrefix: "log",
|
|
1163
|
-
bytes: 0,
|
|
1164
|
-
queue: [],
|
|
1165
|
-
processing: false
|
|
1166
|
-
};
|
|
1167
|
-
this.error = {
|
|
1168
|
-
activePath: path__default.default.join(this.config.dir, "log.error.ndjson"),
|
|
1169
|
-
archivePrefix: "log.error",
|
|
1170
|
-
bytes: 0,
|
|
1171
|
-
queue: [],
|
|
1172
|
-
processing: false
|
|
1173
|
-
};
|
|
1174
|
-
if (!this.config.enabled) {
|
|
1175
|
-
return;
|
|
1176
|
-
}
|
|
1177
|
-
ensureDirectory(this.config.dir);
|
|
1178
|
-
ensureDirectory(this.config.archiveDir);
|
|
1179
|
-
this.seedStream(this.combined);
|
|
1180
|
-
this.seedStream(this.error);
|
|
1181
|
-
}
|
|
1182
|
-
write(record) {
|
|
1183
|
-
if (!this.config.enabled) {
|
|
1184
|
-
return;
|
|
1185
|
-
}
|
|
1186
|
-
const line = `${serializeLogRecord(record)}
|
|
1187
|
-
`;
|
|
1188
|
-
this.enqueue(this.combined, line);
|
|
1189
|
-
if (record.level === "error" || record.level === "critical") {
|
|
1190
|
-
this.enqueue(this.error, line);
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
enqueue(stream, line) {
|
|
1194
|
-
stream.queue.push(line);
|
|
1195
|
-
this.processQueue(stream);
|
|
1196
|
-
}
|
|
1197
|
-
processQueue(stream) {
|
|
1198
|
-
if (stream.processing) {
|
|
1199
|
-
return;
|
|
1200
|
-
}
|
|
1201
|
-
stream.processing = true;
|
|
1202
|
-
try {
|
|
1203
|
-
while (stream.queue.length > 0) {
|
|
1204
|
-
const queuedLine = stream.queue.shift();
|
|
1205
|
-
if (queuedLine === void 0) {
|
|
1206
|
-
continue;
|
|
1207
|
-
}
|
|
1208
|
-
try {
|
|
1209
|
-
this.append(stream, queuedLine);
|
|
1210
|
-
} catch (error) {
|
|
1211
|
-
this.warn(`Failed writing log line for ${stream.archivePrefix}`, error);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
} finally {
|
|
1215
|
-
stream.processing = false;
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
seedStream(stream) {
|
|
1219
|
-
stream.bytes = getFileSize(stream.activePath);
|
|
1220
|
-
if (this.config.rotationEnabled && stream.bytes > this.config.maxSizeBytes && stream.bytes > 0) {
|
|
1221
|
-
this.rotate(stream);
|
|
1222
|
-
fs__default.default.closeSync(fs__default.default.openSync(stream.activePath, "a"));
|
|
1223
|
-
stream.bytes = 0;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
append(stream, line) {
|
|
1227
|
-
ensureDirectory(this.config.dir);
|
|
1228
|
-
const lineBytes = Buffer.byteLength(line, "utf8");
|
|
1229
|
-
if (this.config.rotationEnabled && stream.bytes > 0 && stream.bytes + lineBytes > this.config.maxSizeBytes) {
|
|
1230
|
-
this.rotate(stream);
|
|
1231
|
-
}
|
|
1232
|
-
fs__default.default.appendFileSync(stream.activePath, line, "utf8");
|
|
1233
|
-
stream.bytes += lineBytes;
|
|
1234
|
-
}
|
|
1235
|
-
rotate(stream) {
|
|
1236
|
-
ensureDirectory(this.config.archiveDir);
|
|
1237
|
-
if (!fs__default.default.existsSync(stream.activePath) || stream.bytes === 0) {
|
|
1238
|
-
stream.bytes = 0;
|
|
1239
|
-
return;
|
|
1240
|
-
}
|
|
1241
|
-
const archiveTimestamp = formatArchiveTimestamp(/* @__PURE__ */ new Date());
|
|
1242
|
-
const archiveBasePath = path__default.default.join(
|
|
1243
|
-
this.config.archiveDir,
|
|
1244
|
-
`${stream.archivePrefix}.${archiveTimestamp}`
|
|
1245
|
-
);
|
|
1246
|
-
const archivePath = getUniqueArchivePath(archiveBasePath, ".ndjson");
|
|
1247
|
-
fs__default.default.renameSync(stream.activePath, archivePath);
|
|
1248
|
-
if (this.config.compress) {
|
|
1249
|
-
try {
|
|
1250
|
-
const compressedPath = `${archivePath}.gz`;
|
|
1251
|
-
const gzipped = this.gzip(fs__default.default.readFileSync(archivePath));
|
|
1252
|
-
fs__default.default.writeFileSync(compressedPath, gzipped);
|
|
1253
|
-
fs__default.default.rmSync(archivePath);
|
|
1254
|
-
} catch (error) {
|
|
1255
|
-
this.warn(`Failed to gzip archive ${archivePath}`, error);
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
stream.bytes = 0;
|
|
1259
|
-
pruneArchives(this.config.archiveDir, stream.archivePrefix, this.config.maxArchives, this.warn);
|
|
1260
|
-
}
|
|
1261
|
-
};
|
|
1262
|
-
function createFileLogger(config) {
|
|
1263
|
-
return new RotatingFileLogger(config);
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
// src/connectors/shared.ts
|
|
1267
|
-
function isBlypConfig(config) {
|
|
1268
|
-
return isPlainObject(config) && ("connectors" in config || "pretty" in config || "level" in config);
|
|
1269
|
-
}
|
|
1270
|
-
function getPrimaryPayload(record) {
|
|
1271
|
-
return isPlainObject(record.data) ? record.data : record;
|
|
1272
|
-
}
|
|
1273
|
-
function getField(record, key) {
|
|
1274
|
-
if (key in record) {
|
|
1275
|
-
const direct = record[key];
|
|
1276
|
-
if (typeof direct === "string" || typeof direct === "number") {
|
|
1277
|
-
return direct;
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
const payload = getPrimaryPayload(record);
|
|
1281
|
-
const nested = payload[key];
|
|
1282
|
-
if (typeof nested === "string" || typeof nested === "number") {
|
|
1283
|
-
return nested;
|
|
1284
|
-
}
|
|
1285
|
-
return void 0;
|
|
1286
|
-
}
|
|
1287
|
-
function getClientPageField(record, key) {
|
|
1288
|
-
const payload = getPrimaryPayload(record);
|
|
1289
|
-
const page = isPlainObject(payload.page) ? payload.page : void 0;
|
|
1290
|
-
const value = page?.[key];
|
|
1291
|
-
return typeof value === "string" ? value : void 0;
|
|
1292
|
-
}
|
|
1293
|
-
function getClientSessionField(record, key) {
|
|
1294
|
-
const payload = getPrimaryPayload(record);
|
|
1295
|
-
const session = isPlainObject(payload.session) ? payload.session : void 0;
|
|
1296
|
-
const value = session?.[key];
|
|
1297
|
-
return typeof value === "string" ? value : void 0;
|
|
1298
|
-
}
|
|
1299
|
-
function getRecordType(record) {
|
|
1300
|
-
return getField(record, "type");
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
// src/connectors/posthog/sender.ts
|
|
1304
|
-
var PREVIOUSLY_CAPTURED_ERROR_KEY = "__posthog_previously_captured_error";
|
|
1305
|
-
var warnedKeys2 = /* @__PURE__ */ new Set();
|
|
1306
|
-
var testHooks = {};
|
|
1307
|
-
var warnOnce2 = createErrorOnceLogger(warnedKeys2);
|
|
1308
|
-
function normalizeHost(host) {
|
|
1309
|
-
const trimmed = (host || "https://us.i.posthog.com").trim();
|
|
1310
|
-
return trimmed.replace(/\/+$/, "");
|
|
1311
|
-
}
|
|
1312
|
-
function buildRecordAttributes(record, source) {
|
|
1313
|
-
const recordType = getRecordType(record);
|
|
1314
|
-
const caller = typeof record.caller === "string" ? record.caller : void 0;
|
|
1315
|
-
const groupId = getField(record, "groupId");
|
|
1316
|
-
const method = getField(record, "method");
|
|
1317
|
-
const path3 = getField(record, "path");
|
|
1318
|
-
const status = getField(record, "status");
|
|
1319
|
-
const duration = getField(record, "duration");
|
|
1320
|
-
const pagePath = getClientPageField(record, "pathname");
|
|
1321
|
-
const pageUrl = getClientPageField(record, "url");
|
|
1322
|
-
const sessionId = getClientSessionField(record, "sessionId");
|
|
1323
|
-
const pageId = getClientSessionField(record, "pageId");
|
|
1324
|
-
const attributes = {
|
|
1325
|
-
"blyp.level": record.level,
|
|
1326
|
-
"blyp.source": source,
|
|
1327
|
-
"blyp.payload": serializeLogRecord(record)
|
|
1328
|
-
};
|
|
1329
|
-
const ifTruthy = [
|
|
1330
|
-
["blyp.type", recordType],
|
|
1331
|
-
["blyp.caller", caller],
|
|
1332
|
-
["blyp.group_id", groupId],
|
|
1333
|
-
["http.method", method],
|
|
1334
|
-
["url.path", path3],
|
|
1335
|
-
["client.page_path", pagePath],
|
|
1336
|
-
["client.page_url", pageUrl],
|
|
1337
|
-
["client.session_id", sessionId],
|
|
1338
|
-
["client.page_id", pageId]
|
|
1339
|
-
];
|
|
1340
|
-
const ifDefined = [
|
|
1341
|
-
["http.status_code", status],
|
|
1342
|
-
["blyp.duration_ms", duration]
|
|
1343
|
-
];
|
|
1344
|
-
for (const [k, v] of ifTruthy) if (v) attributes[k] = v;
|
|
1345
|
-
for (const [k, v] of ifDefined) if (v !== void 0) attributes[k] = v;
|
|
1346
|
-
return attributes;
|
|
1347
|
-
}
|
|
1348
|
-
function normalizeExceptionProperties(value) {
|
|
1349
|
-
if (!isPlainObject(value)) {
|
|
1350
|
-
return {};
|
|
1351
|
-
}
|
|
1352
|
-
return normalizeLogValue(value);
|
|
1353
|
-
}
|
|
1354
|
-
function assignExceptionField(target, key, value) {
|
|
1355
|
-
if (value === void 0) {
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
try {
|
|
1359
|
-
target[key] = value;
|
|
1360
|
-
} catch {
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
function createSyntheticError(message, source) {
|
|
1364
|
-
const error = new Error(message);
|
|
1365
|
-
const name = hasNonEmptyString(source.name) ? source.name : "Error";
|
|
1366
|
-
error.name = name;
|
|
1367
|
-
if (hasNonEmptyString(source.stack)) {
|
|
1368
|
-
error.stack = source.stack;
|
|
1369
|
-
}
|
|
1370
|
-
assignExceptionField(error, "cause", source.cause);
|
|
1371
|
-
assignExceptionField(error, "status", source.status);
|
|
1372
|
-
assignExceptionField(error, "statusCode", source.statusCode);
|
|
1373
|
-
assignExceptionField(error, "code", source.code);
|
|
1374
|
-
assignExceptionField(error, "why", source.why);
|
|
1375
|
-
assignExceptionField(error, "fix", source.fix);
|
|
1376
|
-
assignExceptionField(error, "link", source.link);
|
|
1377
|
-
assignExceptionField(error, "details", source.details);
|
|
1378
|
-
return error;
|
|
1379
|
-
}
|
|
1380
|
-
function normalizeExceptionInput(input, fallbackMessage = "Unknown error") {
|
|
1381
|
-
if (input instanceof Error) {
|
|
1382
|
-
return {
|
|
1383
|
-
error: input,
|
|
1384
|
-
properties: normalizeExceptionProperties(input)
|
|
1385
|
-
};
|
|
1386
|
-
}
|
|
1387
|
-
if (isPlainObject(input)) {
|
|
1388
|
-
const message = hasNonEmptyString(input.message) ? input.message : hasNonEmptyString(input.error) ? input.error : fallbackMessage;
|
|
1389
|
-
return {
|
|
1390
|
-
error: createSyntheticError(message, input),
|
|
1391
|
-
properties: normalizeExceptionProperties(input)
|
|
1392
|
-
};
|
|
1393
|
-
}
|
|
1394
|
-
if (typeof input === "string") {
|
|
1395
|
-
return {
|
|
1396
|
-
error: new Error(input),
|
|
1397
|
-
properties: {
|
|
1398
|
-
message: input
|
|
1399
|
-
}
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
return {
|
|
1403
|
-
error: new Error(fallbackMessage),
|
|
1404
|
-
properties: {
|
|
1405
|
-
value: normalizeLogValue(input)
|
|
1406
|
-
}
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
function createExceptionPropertiesFromRecord(record, source) {
|
|
1410
|
-
return buildRecordAttributes(record, source);
|
|
1411
|
-
}
|
|
1412
|
-
function isPreviouslyCapturedPostHogError(value) {
|
|
1413
|
-
return isPlainObject(value) && value[PREVIOUSLY_CAPTURED_ERROR_KEY] === true;
|
|
1414
|
-
}
|
|
1415
|
-
function markPostHogCapturedError(value) {
|
|
1416
|
-
if (!isPlainObject(value) || isPreviouslyCapturedPostHogError(value)) {
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
try {
|
|
1420
|
-
Object.defineProperty(value, PREVIOUSLY_CAPTURED_ERROR_KEY, {
|
|
1421
|
-
value: true,
|
|
1422
|
-
enumerable: false,
|
|
1423
|
-
configurable: true,
|
|
1424
|
-
writable: true
|
|
1425
|
-
});
|
|
1426
|
-
} catch {
|
|
1427
|
-
try {
|
|
1428
|
-
value[PREVIOUSLY_CAPTURED_ERROR_KEY] = true;
|
|
1429
|
-
} catch {
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
function isClientLogRecord(record) {
|
|
1434
|
-
return getRecordType(record) === "client_log";
|
|
1435
|
-
}
|
|
1436
|
-
function normalizePostHogRecord(record, connector, source = "server") {
|
|
1437
|
-
const severity = resolveSeverity(record.level);
|
|
1438
|
-
const body = typeof record.message === "string" ? record.message : String(record.message);
|
|
1439
|
-
return {
|
|
1440
|
-
body,
|
|
1441
|
-
severityText: severity.text,
|
|
1442
|
-
severityNumber: severity.number,
|
|
1443
|
-
attributes: buildRecordAttributes(record, source),
|
|
1444
|
-
resourceAttributes: {
|
|
1445
|
-
"service.name": connector.serviceName
|
|
1446
|
-
}
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
|
-
function resolveSeverity(level) {
|
|
1450
|
-
switch (level) {
|
|
1451
|
-
case "debug":
|
|
1452
|
-
return { text: "debug", number: apiLogs.SeverityNumber.DEBUG };
|
|
1453
|
-
case "warning":
|
|
1454
|
-
case "warn":
|
|
1455
|
-
return { text: "warn", number: apiLogs.SeverityNumber.WARN };
|
|
1456
|
-
case "error":
|
|
1457
|
-
return { text: "error", number: apiLogs.SeverityNumber.ERROR };
|
|
1458
|
-
case "critical":
|
|
1459
|
-
return { text: "fatal", number: apiLogs.SeverityNumber.FATAL };
|
|
1460
|
-
case "success":
|
|
1461
|
-
case "table":
|
|
1462
|
-
case "info":
|
|
1463
|
-
default:
|
|
1464
|
-
return { text: "info", number: apiLogs.SeverityNumber.INFO };
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
function registerShutdownHooks(key, shutdown) {
|
|
1468
|
-
const handlers = ["beforeExit", "SIGINT", "SIGTERM"];
|
|
1469
|
-
for (const event of handlers) {
|
|
1470
|
-
process.once(event, () => {
|
|
1471
|
-
void shutdown().catch((error) => {
|
|
1472
|
-
warnOnce2(
|
|
1473
|
-
`${key}:shutdown`,
|
|
1474
|
-
"[Blyp] Failed to flush PostHog telemetry during shutdown.",
|
|
1475
|
-
error
|
|
1476
|
-
);
|
|
1477
|
-
});
|
|
1478
|
-
});
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
function createDefaultTransport(connector) {
|
|
1482
|
-
const exporter = new exporterLogsOtlpHttp.OTLPLogExporter({
|
|
1483
|
-
url: `${normalizeHost(connector.host)}/i/v1/logs`,
|
|
1484
|
-
headers: {
|
|
1485
|
-
Authorization: `Bearer ${connector.projectKey}`
|
|
1486
|
-
}
|
|
1487
|
-
});
|
|
1488
|
-
const provider = new sdkLogs.LoggerProvider({
|
|
1489
|
-
resource: resources.resourceFromAttributes({
|
|
1490
|
-
"service.name": connector.serviceName
|
|
1491
|
-
}),
|
|
1492
|
-
processors: [new sdkLogs.BatchLogRecordProcessor(exporter)]
|
|
1493
|
-
});
|
|
1494
|
-
const logger2 = provider.getLogger("blyp-posthog");
|
|
1495
|
-
return {
|
|
1496
|
-
emit(payload) {
|
|
1497
|
-
logger2.emit({
|
|
1498
|
-
body: payload.body,
|
|
1499
|
-
severityText: payload.severityText,
|
|
1500
|
-
severityNumber: payload.severityNumber,
|
|
1501
|
-
attributes: payload.attributes
|
|
1502
|
-
});
|
|
1503
|
-
},
|
|
1504
|
-
flush() {
|
|
1505
|
-
return provider.forceFlush();
|
|
1506
|
-
},
|
|
1507
|
-
shutdown() {
|
|
1508
|
-
return provider.shutdown();
|
|
1509
|
-
}
|
|
1510
|
-
};
|
|
1511
|
-
}
|
|
1512
|
-
function createDefaultExceptionClient(connector) {
|
|
1513
|
-
const client = new posthogNode.PostHog(connector.projectKey ?? "", {
|
|
1514
|
-
host: connector.host,
|
|
1515
|
-
enableExceptionAutocapture: connector.errorTracking.enableExceptionAutocapture
|
|
1516
|
-
});
|
|
1517
|
-
return {
|
|
1518
|
-
captureException(error, distinctId, additionalProperties) {
|
|
1519
|
-
return client.captureExceptionImmediate(error, distinctId, additionalProperties);
|
|
1520
|
-
},
|
|
1521
|
-
shutdown() {
|
|
1522
|
-
return client._shutdown();
|
|
1523
|
-
}
|
|
1524
|
-
};
|
|
1525
|
-
}
|
|
1526
|
-
function resolveConnectorConfig(config) {
|
|
1527
|
-
const connector = isBlypConfig(config) ? config.connectors?.posthog : config;
|
|
1528
|
-
const enabled = connector?.enabled ?? false;
|
|
1529
|
-
const projectKey = connector?.projectKey;
|
|
1530
|
-
const errorTrackingEnabled = connector?.errorTracking?.enabled ?? enabled;
|
|
1531
|
-
const errorTrackingMode = connector?.errorTracking?.mode ?? "auto";
|
|
1532
|
-
const errorTrackingReady = enabled && errorTrackingEnabled && hasNonEmptyString(projectKey);
|
|
1533
|
-
return {
|
|
1534
|
-
enabled,
|
|
1535
|
-
mode: connector?.mode ?? "auto",
|
|
1536
|
-
projectKey,
|
|
1537
|
-
host: normalizeHost(connector?.host),
|
|
1538
|
-
serviceName: connector?.serviceName ?? "blyp-app",
|
|
1539
|
-
errorTracking: {
|
|
1540
|
-
enabled: errorTrackingEnabled,
|
|
1541
|
-
mode: errorTrackingMode,
|
|
1542
|
-
enableExceptionAutocapture: connector?.errorTracking?.enableExceptionAutocapture ?? errorTrackingMode === "auto",
|
|
1543
|
-
ready: errorTrackingReady,
|
|
1544
|
-
status: errorTrackingReady ? "enabled" : "missing"
|
|
1545
|
-
}
|
|
1546
|
-
};
|
|
1547
|
-
}
|
|
1548
|
-
function createPostHogSender(config) {
|
|
1549
|
-
const connector = resolveConnectorConfig(config);
|
|
1550
|
-
const key = `${connector.serviceName}:${connector.host}:${connector.mode}`;
|
|
1551
|
-
const ready = connector.enabled === true && hasNonEmptyString(connector.projectKey);
|
|
1552
|
-
const transport = ready ? testHooks.createTransport?.(connector) ?? createDefaultTransport(connector) : void 0;
|
|
1553
|
-
const exceptionClient = connector.errorTracking.ready ? testHooks.createExceptionClient?.(connector) ?? createDefaultExceptionClient(connector) : void 0;
|
|
1554
|
-
const shutdown = async () => {
|
|
1555
|
-
if (transport?.shutdown) {
|
|
1556
|
-
await transport.shutdown();
|
|
1557
|
-
} else if (transport?.flush) {
|
|
1558
|
-
await transport.flush();
|
|
1559
|
-
}
|
|
1560
|
-
if (exceptionClient?.shutdown) {
|
|
1561
|
-
await exceptionClient.shutdown();
|
|
1562
|
-
}
|
|
1563
|
-
};
|
|
1564
|
-
if (transport || exceptionClient) {
|
|
1565
|
-
registerShutdownHooks(key, shutdown);
|
|
1566
|
-
}
|
|
1567
|
-
const emitUnavailableWarning = () => {
|
|
1568
|
-
warnOnce2(
|
|
1569
|
-
`posthog-unavailable:${key}`,
|
|
1570
|
-
"[Blyp] PostHog connector is not configured. Skipping PostHog delivery."
|
|
1571
|
-
);
|
|
1572
|
-
};
|
|
1573
|
-
const emitExceptionUnavailableWarning = () => {
|
|
1574
|
-
warnOnce2(
|
|
1575
|
-
`posthog-exception-unavailable:${key}`,
|
|
1576
|
-
"[Blyp] PostHog error tracking is not configured. Skipping PostHog exception capture."
|
|
1577
|
-
);
|
|
1578
|
-
};
|
|
1579
|
-
return {
|
|
1580
|
-
enabled: connector.enabled,
|
|
1581
|
-
ready,
|
|
1582
|
-
mode: connector.mode,
|
|
1583
|
-
serviceName: connector.serviceName,
|
|
1584
|
-
host: connector.host,
|
|
1585
|
-
status: ready ? "enabled" : "missing",
|
|
1586
|
-
errorTracking: {
|
|
1587
|
-
enabled: connector.errorTracking.enabled,
|
|
1588
|
-
ready: connector.errorTracking.ready,
|
|
1589
|
-
mode: connector.errorTracking.mode,
|
|
1590
|
-
status: connector.errorTracking.status,
|
|
1591
|
-
enableExceptionAutocapture: connector.errorTracking.enableExceptionAutocapture
|
|
1592
|
-
},
|
|
1593
|
-
shouldAutoForwardServerLogs() {
|
|
1594
|
-
return ready && connector.mode === "auto";
|
|
1595
|
-
},
|
|
1596
|
-
shouldAutoCaptureExceptions() {
|
|
1597
|
-
return connector.errorTracking.ready && connector.errorTracking.mode === "auto";
|
|
1598
|
-
},
|
|
1599
|
-
send(record, options = {}) {
|
|
1600
|
-
const source = options.source ?? "server";
|
|
1601
|
-
if (!ready || !transport) {
|
|
1602
|
-
if (options.warnIfUnavailable) {
|
|
1603
|
-
emitUnavailableWarning();
|
|
1604
|
-
}
|
|
1605
|
-
return;
|
|
1606
|
-
}
|
|
1607
|
-
const normalized = normalizePostHogRecord(record, connector, source);
|
|
1608
|
-
try {
|
|
1609
|
-
const result = transport.emit(normalized);
|
|
1610
|
-
if (result && typeof result.catch === "function") {
|
|
1611
|
-
void result.catch((error) => {
|
|
1612
|
-
warnOnce2(
|
|
1613
|
-
`posthog-emit:${key}`,
|
|
1614
|
-
"[Blyp] Failed to deliver log to PostHog.",
|
|
1615
|
-
error
|
|
1616
|
-
);
|
|
1617
|
-
});
|
|
1618
|
-
}
|
|
1619
|
-
} catch (error) {
|
|
1620
|
-
warnOnce2(
|
|
1621
|
-
`posthog-emit:${key}`,
|
|
1622
|
-
"[Blyp] Failed to deliver log to PostHog.",
|
|
1623
|
-
error
|
|
1624
|
-
);
|
|
1625
|
-
}
|
|
1626
|
-
},
|
|
1627
|
-
captureException(error, options = {}) {
|
|
1628
|
-
if (!connector.errorTracking.ready || !exceptionClient) {
|
|
1629
|
-
if (options.warnIfUnavailable) {
|
|
1630
|
-
emitExceptionUnavailableWarning();
|
|
1631
|
-
}
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
if (isPreviouslyCapturedPostHogError(error)) {
|
|
1635
|
-
return;
|
|
1636
|
-
}
|
|
1637
|
-
const normalized = normalizeExceptionInput(
|
|
1638
|
-
error,
|
|
1639
|
-
options.source === "client" ? "Client error" : "Server error"
|
|
1640
|
-
);
|
|
1641
|
-
const properties = {
|
|
1642
|
-
...normalized.properties,
|
|
1643
|
-
...options.properties ?? {},
|
|
1644
|
-
"blyp.source": options.source ?? "server"
|
|
1645
|
-
};
|
|
1646
|
-
try {
|
|
1647
|
-
const result = exceptionClient.captureException(
|
|
1648
|
-
normalized.error,
|
|
1649
|
-
options.distinctId,
|
|
1650
|
-
properties
|
|
1651
|
-
);
|
|
1652
|
-
markPostHogCapturedError(error);
|
|
1653
|
-
markPostHogCapturedError(normalized.error);
|
|
1654
|
-
if (result && typeof result.catch === "function") {
|
|
1655
|
-
void result.catch((captureError) => {
|
|
1656
|
-
warnOnce2(
|
|
1657
|
-
`posthog-capture:${key}`,
|
|
1658
|
-
"[Blyp] Failed to capture exception in PostHog.",
|
|
1659
|
-
captureError
|
|
1660
|
-
);
|
|
1661
|
-
});
|
|
1662
|
-
}
|
|
1663
|
-
} catch (captureError) {
|
|
1664
|
-
warnOnce2(
|
|
1665
|
-
`posthog-capture:${key}`,
|
|
1666
|
-
"[Blyp] Failed to capture exception in PostHog.",
|
|
1667
|
-
captureError
|
|
1668
|
-
);
|
|
1669
|
-
}
|
|
1670
|
-
},
|
|
1671
|
-
async flush() {
|
|
1672
|
-
try {
|
|
1673
|
-
if (transport?.flush) {
|
|
1674
|
-
await transport.flush();
|
|
1675
|
-
}
|
|
1676
|
-
} catch (error) {
|
|
1677
|
-
warnOnce2(
|
|
1678
|
-
`posthog-flush:${key}`,
|
|
1679
|
-
"[Blyp] Failed to flush PostHog telemetry.",
|
|
1680
|
-
error
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
function buildPostHogExceptionProperties(record, source, properties = {}) {
|
|
1687
|
-
return {
|
|
1688
|
-
...createExceptionPropertiesFromRecord(record, source),
|
|
1689
|
-
...properties
|
|
1690
|
-
};
|
|
1691
|
-
}
|
|
1692
|
-
var requestContextStorage = new async_hooks.AsyncLocalStorage();
|
|
1693
|
-
function createStore() {
|
|
1694
|
-
return {
|
|
1695
|
-
requestScopedLoggerActive: true,
|
|
1696
|
-
structuredCollectorActive: false,
|
|
1697
|
-
structuredLogEmitted: false,
|
|
1698
|
-
mixedLoggerWarningShown: false
|
|
1699
|
-
};
|
|
1700
|
-
}
|
|
1701
|
-
function enterRequestContext() {
|
|
1702
|
-
const store = createStore();
|
|
1703
|
-
requestContextStorage.enterWith(store);
|
|
1704
|
-
return store;
|
|
1705
|
-
}
|
|
1706
|
-
function getRequestContextStore() {
|
|
1707
|
-
return requestContextStorage.getStore();
|
|
1708
|
-
}
|
|
1709
|
-
function setActiveRequestLogger(logger2) {
|
|
1710
|
-
const store = getRequestContextStore();
|
|
1711
|
-
if (store) {
|
|
1712
|
-
store.activeLogger = logger2;
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
function markStructuredCollectorActive() {
|
|
1716
|
-
const store = getRequestContextStore();
|
|
1717
|
-
if (store) {
|
|
1718
|
-
store.structuredCollectorActive = true;
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
|
-
function markStructuredLogEmitted() {
|
|
1722
|
-
const store = getRequestContextStore();
|
|
1723
|
-
if (store) {
|
|
1724
|
-
store.structuredLogEmitted = true;
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
function shouldDropRootLogWrite() {
|
|
1728
|
-
const store = getRequestContextStore();
|
|
1729
|
-
if (!store || !store.requestScopedLoggerActive || !store.structuredCollectorActive) {
|
|
1730
|
-
return false;
|
|
1731
|
-
}
|
|
1732
|
-
if (!store.mixedLoggerWarningShown) {
|
|
1733
|
-
store.mixedLoggerWarningShown = true;
|
|
1734
|
-
console.warn(
|
|
1735
|
-
"[Blyp] Warning: Mixed logger usage detected for this request. The root logger call was ignored because a request-scoped structured logger is active."
|
|
1736
|
-
);
|
|
1737
|
-
}
|
|
1738
|
-
return true;
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
// src/core/log-record.ts
|
|
1742
|
-
var RECORD_LEVELS = {
|
|
1743
|
-
success: "success",
|
|
1744
|
-
critical: "critical",
|
|
1745
|
-
warning: "warning",
|
|
1746
|
-
info: "info",
|
|
1747
|
-
debug: "debug",
|
|
1748
|
-
error: "error",
|
|
1749
|
-
warn: "warning",
|
|
1750
|
-
table: "table"
|
|
1751
|
-
};
|
|
1752
|
-
function normalizePath2(filePath) {
|
|
1753
|
-
return filePath.replace(/\\/g, "/");
|
|
1754
|
-
}
|
|
1755
|
-
function isInternalLoggerFrame(filePath) {
|
|
1756
|
-
const normalizedPath = normalizePath2(filePath);
|
|
1757
|
-
return normalizedPath.startsWith("node:") || normalizedPath.includes("/node_modules/pino") || normalizedPath.includes("/node_modules/pino-pretty") || normalizedPath.includes("/node_modules/@blyp/core/") || normalizedPath.includes("/blyp/src/core/") || normalizedPath.includes("/blyp/src/frameworks/") || normalizedPath.includes("/blyp/src/posthog/") || normalizedPath.includes("/blyp/dist/");
|
|
1758
|
-
}
|
|
1759
|
-
function formatCallerPath(filePath) {
|
|
1760
|
-
const normalizedPath = normalizePath2(filePath);
|
|
1761
|
-
const normalizedCwd = normalizePath2(process.cwd());
|
|
1762
|
-
return normalizedPath.startsWith(`${normalizedCwd}/`) ? normalizedPath.slice(normalizedCwd.length + 1) : normalizedPath;
|
|
1763
|
-
}
|
|
1764
|
-
function getCallerLocation() {
|
|
1765
|
-
try {
|
|
1766
|
-
const stack = new Error().stack;
|
|
1767
|
-
if (!stack) {
|
|
1768
|
-
return { file: null, line: null };
|
|
1769
|
-
}
|
|
1770
|
-
const lines = stack.split("\n");
|
|
1771
|
-
let fallback = null;
|
|
1772
|
-
for (let index = 2; index < lines.length; index += 1) {
|
|
1773
|
-
const line = lines[index];
|
|
1774
|
-
if (!line) {
|
|
1775
|
-
continue;
|
|
1776
|
-
}
|
|
1777
|
-
const match = line.match(/\((.*):(\d+):\d+\)/) || line.match(/at\s+(.*):(\d+):(\d+)/);
|
|
1778
|
-
if (!match) {
|
|
1779
|
-
continue;
|
|
1780
|
-
}
|
|
1781
|
-
const fileName = match[1] || "";
|
|
1782
|
-
const lineNumber = parseInt(match[2] || "0", 10) || null;
|
|
1783
|
-
if (fileName && !fileName.includes("node_modules") && !isInternalLoggerFrame(fileName)) {
|
|
1784
|
-
const formattedPath = formatCallerPath(fileName);
|
|
1785
|
-
const normalizedFormattedPath = normalizePath2(formattedPath);
|
|
1786
|
-
if (!normalizedFormattedPath.startsWith("dist/")) {
|
|
1787
|
-
return { file: formattedPath, line: lineNumber };
|
|
1788
|
-
}
|
|
1789
|
-
fallback ?? (fallback = { file: formattedPath, line: lineNumber });
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
if (fallback) {
|
|
1793
|
-
return fallback;
|
|
1794
|
-
}
|
|
1795
|
-
} catch {
|
|
1796
|
-
return { file: null, line: null };
|
|
1797
|
-
}
|
|
1798
|
-
return { file: null, line: null };
|
|
1799
|
-
}
|
|
1800
|
-
var serializeMessage = serializeLogMessage;
|
|
1801
|
-
function stripAnsi(value) {
|
|
1802
|
-
return value.replace(/\u001b\[[0-9;]*m/g, "");
|
|
1803
|
-
}
|
|
1804
|
-
function buildRecord(level, message, args, bindings) {
|
|
1805
|
-
const { file, line } = getCallerLocation();
|
|
1806
|
-
const serializedMessage = serializeMessage(message);
|
|
1807
|
-
const record = {
|
|
1808
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1809
|
-
level: RECORD_LEVELS[level],
|
|
1810
|
-
message: stripAnsi(serializedMessage)
|
|
1811
|
-
};
|
|
1812
|
-
if (message instanceof Error) {
|
|
1813
|
-
record.error = normalizeError(message);
|
|
1814
|
-
}
|
|
1815
|
-
if (file) {
|
|
1816
|
-
record.caller = line !== null ? `${file}:${line}` : file;
|
|
1817
|
-
}
|
|
1818
|
-
if (args.length === 1) {
|
|
1819
|
-
record.data = normalizeLogValue(args[0]);
|
|
1820
|
-
} else if (args.length > 1) {
|
|
1821
|
-
record.data = normalizeLogValue(args);
|
|
1822
|
-
}
|
|
1823
|
-
if (Object.keys(bindings).length > 0) {
|
|
1824
|
-
record.bindings = normalizeLogValue(bindings);
|
|
1825
|
-
}
|
|
1826
|
-
return record;
|
|
1827
|
-
}
|
|
1828
|
-
function buildStructuredRecord(level, message, payload, bindings) {
|
|
1829
|
-
const { file, line } = getCallerLocation();
|
|
1830
|
-
const normalizedPayload = normalizeLogValue(payload);
|
|
1831
|
-
const record = {
|
|
1832
|
-
message: stripAnsi(message),
|
|
1833
|
-
...normalizedPayload
|
|
1834
|
-
};
|
|
1835
|
-
if (file) {
|
|
1836
|
-
record.caller = line !== null ? `${file}:${line}` : file;
|
|
1837
|
-
}
|
|
1838
|
-
if (Object.keys(bindings).length > 0) {
|
|
1839
|
-
record.bindings = normalizeLogValue(bindings);
|
|
1840
|
-
}
|
|
1841
|
-
record.level = typeof normalizedPayload.level === "string" && normalizedPayload.level.length > 0 ? normalizedPayload.level : RECORD_LEVELS[level];
|
|
1842
|
-
record.timestamp = typeof normalizedPayload.timestamp === "string" && normalizedPayload.timestamp.length > 0 ? normalizedPayload.timestamp : (/* @__PURE__ */ new Date()).toISOString();
|
|
1843
|
-
return record;
|
|
1844
|
-
}
|
|
1845
|
-
function resolveStructuredWriteLevel(level) {
|
|
1846
|
-
switch (level) {
|
|
1847
|
-
case "debug":
|
|
1848
|
-
return "debug";
|
|
1849
|
-
case "warning":
|
|
1850
|
-
return "warning";
|
|
1851
|
-
case "warn":
|
|
1852
|
-
return "warn";
|
|
1853
|
-
case "error":
|
|
1854
|
-
return "error";
|
|
1855
|
-
case "success":
|
|
1856
|
-
return "success";
|
|
1857
|
-
case "critical":
|
|
1858
|
-
return "critical";
|
|
1859
|
-
case "table":
|
|
1860
|
-
return "table";
|
|
1861
|
-
case "info":
|
|
1862
|
-
default:
|
|
1863
|
-
return "info";
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
// src/core/sinks/file-primary-sink.ts
|
|
1868
|
-
var FilePrimarySink = class {
|
|
1869
|
-
constructor(logger2) {
|
|
1870
|
-
this.logger = logger2;
|
|
1871
|
-
__publicField(this, "isAsync", false);
|
|
1872
|
-
__publicField(this, "isReady", true);
|
|
1873
|
-
}
|
|
1874
|
-
write(record) {
|
|
1875
|
-
this.logger.write(record);
|
|
1876
|
-
}
|
|
1877
|
-
async flush() {
|
|
1878
|
-
}
|
|
1879
|
-
async shutdown() {
|
|
1880
|
-
}
|
|
1881
|
-
};
|
|
1882
|
-
function createFilePrimarySink(config) {
|
|
1883
|
-
return new FilePrimarySink(createFileLogger(config));
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
|
-
// src/database/adapters/drizzle.ts
|
|
1887
|
-
function createDrizzleRowWriter(adapter) {
|
|
1888
|
-
const db = adapter.db;
|
|
1889
|
-
if (typeof db?.insert !== "function" || adapter.table === void 0) {
|
|
1890
|
-
throw new Error(
|
|
1891
|
-
"[Blyp] Drizzle database adapter is missing a db.insert function or table reference."
|
|
1892
|
-
);
|
|
1893
|
-
}
|
|
1894
|
-
return {
|
|
1895
|
-
async insert(rows) {
|
|
1896
|
-
if (rows.length === 0) {
|
|
1897
|
-
return;
|
|
1898
|
-
}
|
|
1899
|
-
await db.insert(adapter.table).values(rows);
|
|
1900
|
-
}
|
|
1901
|
-
};
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
// src/database/adapters/prisma.ts
|
|
1905
|
-
function shouldFallbackFromCreateMany(error) {
|
|
1906
|
-
const message = String(error ?? "");
|
|
1907
|
-
return message.includes("createMany") || message.includes("Unknown argument") || message.includes("not supported") || message.includes("is not a function");
|
|
1908
|
-
}
|
|
1909
|
-
function createPrismaRowWriter(adapter) {
|
|
1910
|
-
const client = adapter.client;
|
|
1911
|
-
const model = adapter.model ?? "blypLog";
|
|
1912
|
-
const delegateCandidate = client[model];
|
|
1913
|
-
if (!delegateCandidate || typeof delegateCandidate.create !== "function") {
|
|
1914
|
-
throw new Error(
|
|
1915
|
-
`[Blyp] Prisma database adapter is missing the "${model}" delegate or its create method.`
|
|
1916
|
-
);
|
|
1917
|
-
}
|
|
1918
|
-
const delegate = delegateCandidate;
|
|
1919
|
-
let useCreateMany = typeof delegate.createMany === "function";
|
|
1920
|
-
async function fallbackInsert(rows) {
|
|
1921
|
-
if (typeof client.$transaction === "function") {
|
|
1922
|
-
await client.$transaction(
|
|
1923
|
-
rows.map((row) => delegate.create({ data: row }))
|
|
1924
|
-
);
|
|
1925
|
-
return;
|
|
1926
|
-
}
|
|
1927
|
-
for (const row of rows) {
|
|
1928
|
-
await delegate.create({ data: row });
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
return {
|
|
1932
|
-
async insert(rows) {
|
|
1933
|
-
if (rows.length === 0) {
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
if (rows.length === 1) {
|
|
1937
|
-
await delegate.create({ data: rows[0] });
|
|
1938
|
-
return;
|
|
1939
|
-
}
|
|
1940
|
-
if (!useCreateMany || typeof delegate.createMany !== "function") {
|
|
1941
|
-
await fallbackInsert(rows);
|
|
1942
|
-
return;
|
|
1943
|
-
}
|
|
1944
|
-
try {
|
|
1945
|
-
await delegate.createMany({ data: rows });
|
|
1946
|
-
} catch (error) {
|
|
1947
|
-
if (!shouldFallbackFromCreateMany(error)) {
|
|
1948
|
-
throw error;
|
|
1949
|
-
}
|
|
1950
|
-
useCreateMany = false;
|
|
1951
|
-
await fallbackInsert(rows);
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
};
|
|
1955
|
-
}
|
|
1956
|
-
|
|
1957
|
-
// src/database/helpers.ts
|
|
1958
|
-
function normalizeNullableNumber(value) {
|
|
1959
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1960
|
-
}
|
|
1961
|
-
function normalizeNullableString(value) {
|
|
1962
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1963
|
-
}
|
|
1964
|
-
function parseTimestamp(value) {
|
|
1965
|
-
if (typeof value === "string") {
|
|
1966
|
-
const timestamp = new Date(value);
|
|
1967
|
-
if (!Number.isNaN(timestamp.getTime())) {
|
|
1968
|
-
return timestamp;
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
return /* @__PURE__ */ new Date();
|
|
1972
|
-
}
|
|
1973
|
-
function toDatabaseLogRow(record) {
|
|
1974
|
-
const normalizedRecord = normalizeLogValue(record);
|
|
1975
|
-
return {
|
|
1976
|
-
id: crypto.randomUUID(),
|
|
1977
|
-
timestamp: parseTimestamp(record.timestamp),
|
|
1978
|
-
level: record.level,
|
|
1979
|
-
message: record.message,
|
|
1980
|
-
caller: normalizeNullableString(record.caller),
|
|
1981
|
-
type: normalizeNullableString(record.type),
|
|
1982
|
-
groupId: normalizeNullableString(record.groupId),
|
|
1983
|
-
method: normalizeNullableString(record.method),
|
|
1984
|
-
path: normalizeNullableString(record.path),
|
|
1985
|
-
status: normalizeNullableNumber(record.status),
|
|
1986
|
-
duration: normalizeNullableNumber(record.duration),
|
|
1987
|
-
hasError: normalizedRecord.error != null,
|
|
1988
|
-
data: normalizedRecord.data ?? null,
|
|
1989
|
-
bindings: normalizedRecord.bindings ?? null,
|
|
1990
|
-
error: normalizedRecord.error ?? null,
|
|
1991
|
-
events: normalizedRecord.events ?? null,
|
|
1992
|
-
record: normalizedRecord,
|
|
1993
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
1994
|
-
};
|
|
1995
|
-
}
|
|
1996
|
-
function isPrismaAdapter2(adapter) {
|
|
1997
|
-
return !!adapter && adapter.type === "prisma";
|
|
1998
|
-
}
|
|
1999
|
-
function isDrizzleAdapter2(adapter) {
|
|
2000
|
-
return !!adapter && adapter.type === "drizzle";
|
|
2001
|
-
}
|
|
2002
|
-
function createDatabaseRowWriter(config) {
|
|
2003
|
-
if (isPrismaAdapter2(config.adapter)) {
|
|
2004
|
-
return createPrismaRowWriter(config.adapter);
|
|
2005
|
-
}
|
|
2006
|
-
if (isDrizzleAdapter2(config.adapter)) {
|
|
2007
|
-
return createDrizzleRowWriter(config.adapter);
|
|
2008
|
-
}
|
|
2009
|
-
throw new Error("[Blyp] Unsupported database adapter configuration.");
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
// src/core/sinks/database-primary-sink.ts
|
|
2013
|
-
function delay(ms) {
|
|
2014
|
-
return new Promise((resolve2) => {
|
|
2015
|
-
setTimeout(resolve2, ms);
|
|
2016
|
-
});
|
|
2017
|
-
}
|
|
2018
|
-
var DatabasePrimarySink = class {
|
|
2019
|
-
constructor(config) {
|
|
2020
|
-
this.config = config;
|
|
2021
|
-
__publicField(this, "isAsync", true);
|
|
2022
|
-
__publicField(this, "isReady", true);
|
|
2023
|
-
__publicField(this, "warnOnce", createWarnOnceLogger(/* @__PURE__ */ new Set()));
|
|
2024
|
-
__publicField(this, "queue", []);
|
|
2025
|
-
__publicField(this, "writer");
|
|
2026
|
-
__publicField(this, "timer", null);
|
|
2027
|
-
__publicField(this, "processing", false);
|
|
2028
|
-
__publicField(this, "closed", false);
|
|
2029
|
-
__publicField(this, "terminalError", null);
|
|
2030
|
-
__publicField(this, "activeDispatch", null);
|
|
2031
|
-
this.writer = createDatabaseRowWriter(config);
|
|
2032
|
-
}
|
|
2033
|
-
write(record) {
|
|
2034
|
-
if (this.closed) {
|
|
2035
|
-
return;
|
|
2036
|
-
}
|
|
2037
|
-
this.enqueue(toDatabaseLogRow(record));
|
|
2038
|
-
this.scheduleDispatch();
|
|
2039
|
-
}
|
|
2040
|
-
async flush() {
|
|
2041
|
-
if (this.timer) {
|
|
2042
|
-
clearTimeout(this.timer);
|
|
2043
|
-
this.timer = null;
|
|
2044
|
-
}
|
|
2045
|
-
const flushPromise = (async () => {
|
|
2046
|
-
await this.drain();
|
|
2047
|
-
if (this.terminalError) {
|
|
2048
|
-
throw this.terminalError;
|
|
2049
|
-
}
|
|
2050
|
-
})();
|
|
2051
|
-
let timeoutHandle = null;
|
|
2052
|
-
try {
|
|
2053
|
-
await Promise.race([
|
|
2054
|
-
flushPromise,
|
|
2055
|
-
new Promise((_, reject) => {
|
|
2056
|
-
timeoutHandle = setTimeout(() => {
|
|
2057
|
-
this.warnOnce(
|
|
2058
|
-
"database-flush-timeout",
|
|
2059
|
-
`[Blyp] Warning: Timed out flushing database logs after ${this.config.delivery.flushTimeoutMs}ms.`
|
|
2060
|
-
);
|
|
2061
|
-
reject(new Error("[Blyp] Timed out flushing database logs."));
|
|
2062
|
-
}, this.config.delivery.flushTimeoutMs);
|
|
2063
|
-
})
|
|
2064
|
-
]);
|
|
2065
|
-
} finally {
|
|
2066
|
-
if (timeoutHandle) {
|
|
2067
|
-
clearTimeout(timeoutHandle);
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
async shutdown() {
|
|
2072
|
-
this.closed = true;
|
|
2073
|
-
await this.flush();
|
|
2074
|
-
}
|
|
2075
|
-
enqueue(row) {
|
|
2076
|
-
this.queue.push(row);
|
|
2077
|
-
const overflow = this.queue.length - this.config.delivery.maxQueueSize;
|
|
2078
|
-
if (overflow <= 0) {
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
this.warnOnce(
|
|
2082
|
-
"database-overflow",
|
|
2083
|
-
`[Blyp] Warning: Database log queue exceeded ${this.config.delivery.maxQueueSize} entries. Applying ${this.config.delivery.overflowStrategy} overflow handling.`
|
|
2084
|
-
);
|
|
2085
|
-
if (this.config.delivery.overflowStrategy === "drop-new") {
|
|
2086
|
-
this.queue.splice(this.config.delivery.maxQueueSize);
|
|
2087
|
-
return;
|
|
2088
|
-
}
|
|
2089
|
-
this.queue.splice(0, overflow);
|
|
2090
|
-
}
|
|
2091
|
-
scheduleDispatch() {
|
|
2092
|
-
if (this.processing) {
|
|
2093
|
-
return;
|
|
2094
|
-
}
|
|
2095
|
-
if (this.config.delivery.strategy === "immediate") {
|
|
2096
|
-
void this.drain();
|
|
2097
|
-
return;
|
|
2098
|
-
}
|
|
2099
|
-
if (this.queue.length >= this.config.delivery.batchSize) {
|
|
2100
|
-
void this.drain();
|
|
2101
|
-
return;
|
|
2102
|
-
}
|
|
2103
|
-
if (this.timer) {
|
|
2104
|
-
return;
|
|
2105
|
-
}
|
|
2106
|
-
this.timer = setTimeout(() => {
|
|
2107
|
-
this.timer = null;
|
|
2108
|
-
void this.drain();
|
|
2109
|
-
}, this.config.delivery.flushIntervalMs);
|
|
2110
|
-
}
|
|
2111
|
-
async drain() {
|
|
2112
|
-
if (this.processing) {
|
|
2113
|
-
if (this.activeDispatch) {
|
|
2114
|
-
await this.activeDispatch;
|
|
2115
|
-
}
|
|
2116
|
-
return;
|
|
2117
|
-
}
|
|
2118
|
-
this.processing = true;
|
|
2119
|
-
this.activeDispatch = this.processQueue();
|
|
2120
|
-
try {
|
|
2121
|
-
await this.activeDispatch;
|
|
2122
|
-
} finally {
|
|
2123
|
-
this.processing = false;
|
|
2124
|
-
this.activeDispatch = null;
|
|
2125
|
-
}
|
|
2126
|
-
}
|
|
2127
|
-
async processQueue() {
|
|
2128
|
-
while (this.queue.length > 0) {
|
|
2129
|
-
const batchSize = this.config.delivery.strategy === "batch" ? Math.max(1, this.config.delivery.batchSize) : 1;
|
|
2130
|
-
const batch = this.queue.splice(0, batchSize);
|
|
2131
|
-
try {
|
|
2132
|
-
await this.insertWithRetry(batch);
|
|
2133
|
-
} catch (error) {
|
|
2134
|
-
const failure = error instanceof Error ? error : new Error(String(error ?? "Unknown database logging failure"));
|
|
2135
|
-
this.terminalError = failure;
|
|
2136
|
-
this.warnOnce(
|
|
2137
|
-
"database-insert-failure",
|
|
2138
|
-
`[Blyp] Warning: Failed to persist logs to the ${this.config.dialect ?? "database"} database.`,
|
|
2139
|
-
failure
|
|
2140
|
-
);
|
|
2141
|
-
throw failure;
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
async insertWithRetry(batch) {
|
|
2146
|
-
const maxAttempts = Math.max(1, this.config.delivery.retry.maxRetries + 1);
|
|
2147
|
-
let attempt = 0;
|
|
2148
|
-
while (attempt < maxAttempts) {
|
|
2149
|
-
attempt += 1;
|
|
2150
|
-
try {
|
|
2151
|
-
await this.writer.insert(batch);
|
|
2152
|
-
return;
|
|
2153
|
-
} catch (error) {
|
|
2154
|
-
if (attempt >= maxAttempts) {
|
|
2155
|
-
throw error;
|
|
2156
|
-
}
|
|
2157
|
-
await delay(this.config.delivery.retry.backoffMs);
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
};
|
|
2162
|
-
|
|
2163
|
-
// src/core/primary-sink.ts
|
|
2164
|
-
var NoopPrimarySink = class {
|
|
2165
|
-
constructor() {
|
|
2166
|
-
__publicField(this, "isAsync", false);
|
|
2167
|
-
__publicField(this, "isReady", false);
|
|
2168
|
-
}
|
|
2169
|
-
write(_record) {
|
|
2170
|
-
}
|
|
2171
|
-
async flush() {
|
|
2172
|
-
}
|
|
2173
|
-
async shutdown() {
|
|
2174
|
-
}
|
|
2175
|
-
};
|
|
2176
|
-
var warnOnce3 = createWarnOnceLogger(/* @__PURE__ */ new Set());
|
|
2177
|
-
function createPrimarySink(config) {
|
|
2178
|
-
if (config.destination !== "database") {
|
|
2179
|
-
return createFilePrimarySink(config);
|
|
2180
|
-
}
|
|
2181
|
-
const databaseConfig = config.database;
|
|
2182
|
-
if (!databaseConfig?.ready) {
|
|
2183
|
-
warnOnce3(
|
|
2184
|
-
"database-sink-disabled",
|
|
2185
|
-
"[Blyp] Warning: Database destination is configured but not ready. Falling back to a no-op primary sink."
|
|
2186
|
-
);
|
|
2187
|
-
return new NoopPrimarySink();
|
|
2188
|
-
}
|
|
2189
|
-
return new DatabasePrimarySink(databaseConfig);
|
|
2190
|
-
}
|
|
2191
|
-
var PREVIOUSLY_CAPTURED_ERROR_KEY2 = "__betterstack_previously_captured_error";
|
|
2192
|
-
var warnedKeys3 = /* @__PURE__ */ new Set();
|
|
2193
|
-
var testHooks2 = {};
|
|
2194
|
-
var warnOnce4 = createErrorOnceLogger(warnedKeys3);
|
|
2195
|
-
function getSentryModule() {
|
|
2196
|
-
return testHooks2.module ?? Sentry__namespace;
|
|
2197
|
-
}
|
|
2198
|
-
function resolveConnectorConfig2(config) {
|
|
2199
|
-
const connector = isBlypConfig(config) ? config.connectors?.betterstack : config;
|
|
2200
|
-
const enabled = connector?.enabled ?? false;
|
|
2201
|
-
const sourceToken = connector?.sourceToken;
|
|
2202
|
-
const ingestingHost = connector?.ingestingHost;
|
|
2203
|
-
const errorTrackingEnabled = connector?.errorTracking?.enabled ?? enabled;
|
|
2204
|
-
const errorTrackingDsn = connector?.errorTracking?.dsn;
|
|
2205
|
-
const errorTrackingReady = enabled && errorTrackingEnabled && hasNonEmptyString(errorTrackingDsn);
|
|
2206
|
-
const ready = enabled && hasNonEmptyString(sourceToken) && isAbsoluteHttpUrl(ingestingHost);
|
|
2207
|
-
return {
|
|
2208
|
-
enabled,
|
|
2209
|
-
mode: connector?.mode ?? "auto",
|
|
2210
|
-
sourceToken,
|
|
2211
|
-
ingestingHost,
|
|
2212
|
-
serviceName: connector?.serviceName ?? "blyp-app",
|
|
2213
|
-
errorTracking: {
|
|
2214
|
-
enabled: errorTrackingEnabled,
|
|
2215
|
-
dsn: errorTrackingDsn,
|
|
2216
|
-
tracesSampleRate: connector?.errorTracking?.tracesSampleRate ?? 1,
|
|
2217
|
-
environment: connector?.errorTracking?.environment,
|
|
2218
|
-
release: connector?.errorTracking?.release,
|
|
2219
|
-
ready: errorTrackingReady,
|
|
2220
|
-
status: errorTrackingReady ? "enabled" : "missing"
|
|
2221
|
-
},
|
|
2222
|
-
ready,
|
|
2223
|
-
status: ready ? "enabled" : "missing"
|
|
2224
|
-
};
|
|
2225
|
-
}
|
|
2226
|
-
function resolveBetterStackLevel(level) {
|
|
2227
|
-
switch (level) {
|
|
2228
|
-
case "debug":
|
|
2229
|
-
return "debug";
|
|
2230
|
-
case "warning":
|
|
2231
|
-
case "warn":
|
|
2232
|
-
return "warn";
|
|
2233
|
-
case "error":
|
|
2234
|
-
return "error";
|
|
2235
|
-
case "critical":
|
|
2236
|
-
return "fatal";
|
|
2237
|
-
case "success":
|
|
2238
|
-
case "table":
|
|
2239
|
-
case "info":
|
|
2240
|
-
default:
|
|
2241
|
-
return "info";
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
function parseCaller(caller) {
|
|
2245
|
-
if (typeof caller !== "string" || caller.trim().length === 0) {
|
|
2246
|
-
return {};
|
|
2247
|
-
}
|
|
2248
|
-
const match = caller.match(/^(.*):(\d+)$/);
|
|
2249
|
-
if (!match) {
|
|
2250
|
-
return {};
|
|
2251
|
-
}
|
|
2252
|
-
const file = match[1]?.trim();
|
|
2253
|
-
const line = Number.parseInt(match[2] ?? "", 10);
|
|
2254
|
-
return {
|
|
2255
|
-
...file ? { file } : {},
|
|
2256
|
-
...Number.isFinite(line) ? { line } : {}
|
|
2257
|
-
};
|
|
2258
|
-
}
|
|
2259
|
-
function buildContext(record, connector, source) {
|
|
2260
|
-
const recordType = getRecordType(record);
|
|
2261
|
-
const groupId = getField(record, "groupId");
|
|
2262
|
-
const method = getField(record, "method");
|
|
2263
|
-
const path3 = getField(record, "path");
|
|
2264
|
-
const status = getField(record, "status");
|
|
2265
|
-
const duration = getField(record, "duration");
|
|
2266
|
-
const pagePath = getClientPageField(record, "pathname");
|
|
2267
|
-
const pageUrl = getClientPageField(record, "url");
|
|
2268
|
-
const sessionId = getClientSessionField(record, "sessionId");
|
|
2269
|
-
const pageId = getClientSessionField(record, "pageId");
|
|
2270
|
-
const runtime2 = parseCaller(record.caller);
|
|
2271
|
-
return {
|
|
2272
|
-
service: connector.serviceName,
|
|
2273
|
-
context: {
|
|
2274
|
-
blyp: {
|
|
2275
|
-
level: record.level,
|
|
2276
|
-
source,
|
|
2277
|
-
...recordType ? { type: recordType } : {},
|
|
2278
|
-
...groupId ? { group_id: groupId } : {},
|
|
2279
|
-
...record.caller ? { caller: record.caller } : {},
|
|
2280
|
-
...duration !== void 0 ? { duration_ms: duration } : {},
|
|
2281
|
-
...record.bindings ? { bindings: record.bindings } : {},
|
|
2282
|
-
payload: serializeLogRecord(record)
|
|
2283
|
-
},
|
|
2284
|
-
...method || path3 || status !== void 0 ? {
|
|
2285
|
-
http: {
|
|
2286
|
-
...method ? { method } : {},
|
|
2287
|
-
...path3 ? { path: path3 } : {},
|
|
2288
|
-
...status !== void 0 ? { status_code: status } : {}
|
|
2289
|
-
}
|
|
2290
|
-
} : {},
|
|
2291
|
-
...pagePath || pageUrl || sessionId || pageId ? {
|
|
2292
|
-
client: {
|
|
2293
|
-
...pagePath ? { page_path: pagePath } : {},
|
|
2294
|
-
...pageUrl ? { page_url: pageUrl } : {},
|
|
2295
|
-
...sessionId ? { session_id: sessionId } : {},
|
|
2296
|
-
...pageId ? { page_id: pageId } : {}
|
|
2297
|
-
}
|
|
2298
|
-
} : {},
|
|
2299
|
-
...Object.keys(runtime2).length > 0 ? { runtime: runtime2 } : {},
|
|
2300
|
-
...record.data !== void 0 ? { data: record.data } : {},
|
|
2301
|
-
...record.error !== void 0 ? { error: record.error } : {}
|
|
2302
|
-
}
|
|
2303
|
-
};
|
|
2304
|
-
}
|
|
2305
|
-
function toExceptionCandidate(value) {
|
|
2306
|
-
if (!isPlainObject(value)) {
|
|
2307
|
-
return void 0;
|
|
2308
|
-
}
|
|
2309
|
-
const message = typeof value.message === "string" ? value.message : void 0;
|
|
2310
|
-
const name = typeof value.name === "string" ? value.name : void 0;
|
|
2311
|
-
const stack = typeof value.stack === "string" ? value.stack : void 0;
|
|
2312
|
-
if (!message && !name && !stack) {
|
|
2313
|
-
return void 0;
|
|
2314
|
-
}
|
|
2315
|
-
const error = new Error(message ?? name ?? "Unknown error");
|
|
2316
|
-
error.name = name ?? "Error";
|
|
2317
|
-
if (stack) {
|
|
2318
|
-
error.stack = stack;
|
|
2319
|
-
}
|
|
2320
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
2321
|
-
if (key === "message" || key === "name" || key === "stack") {
|
|
2322
|
-
continue;
|
|
2323
|
-
}
|
|
2324
|
-
error[key] = entry;
|
|
2325
|
-
}
|
|
2326
|
-
return error;
|
|
2327
|
-
}
|
|
2328
|
-
function normalizeScopeLevel(level) {
|
|
2329
|
-
switch (level) {
|
|
2330
|
-
case "debug":
|
|
2331
|
-
return "debug";
|
|
2332
|
-
case "warning":
|
|
2333
|
-
case "warn":
|
|
2334
|
-
return "warning";
|
|
2335
|
-
case "critical":
|
|
2336
|
-
return "fatal";
|
|
2337
|
-
case "error":
|
|
2338
|
-
return "error";
|
|
2339
|
-
case "success":
|
|
2340
|
-
case "table":
|
|
2341
|
-
case "info":
|
|
2342
|
-
default:
|
|
2343
|
-
return "info";
|
|
2344
|
-
}
|
|
2345
|
-
}
|
|
2346
|
-
function normalizeExceptionInput2(input) {
|
|
2347
|
-
if (input instanceof Error) {
|
|
2348
|
-
return input;
|
|
2349
|
-
}
|
|
2350
|
-
const direct = toExceptionCandidate(input);
|
|
2351
|
-
if (direct) {
|
|
2352
|
-
return direct;
|
|
2353
|
-
}
|
|
2354
|
-
if (typeof input === "string") {
|
|
2355
|
-
return new Error(input);
|
|
2356
|
-
}
|
|
2357
|
-
return new Error("Unknown Better Stack exception");
|
|
2358
|
-
}
|
|
2359
|
-
function isPreviouslyCapturedError(value) {
|
|
2360
|
-
return isPlainObject(value) && value[PREVIOUSLY_CAPTURED_ERROR_KEY2] === true;
|
|
2361
|
-
}
|
|
2362
|
-
function markCapturedError(value) {
|
|
2363
|
-
if (!isPlainObject(value) || isPreviouslyCapturedError(value)) {
|
|
2364
|
-
return;
|
|
2365
|
-
}
|
|
22
|
+
async function loadDatabase() {
|
|
2366
23
|
try {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
configurable: true,
|
|
2371
|
-
writable: true
|
|
2372
|
-
});
|
|
2373
|
-
} catch {
|
|
2374
|
-
try {
|
|
2375
|
-
value[PREVIOUSLY_CAPTURED_ERROR_KEY2] = true;
|
|
2376
|
-
} catch {
|
|
2377
|
-
}
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
function createDefaultClient(connector) {
|
|
2381
|
-
return new node.Logtail(connector.sourceToken ?? "", {
|
|
2382
|
-
endpoint: connector.ingestingHost,
|
|
2383
|
-
captureStackContext: false
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
|
-
function getClientOptions(client) {
|
|
2387
|
-
return client?.getOptions?.() ?? {};
|
|
2388
|
-
}
|
|
2389
|
-
function registerShutdownHooks2(key, flush) {
|
|
2390
|
-
const handlers = ["beforeExit", "SIGINT", "SIGTERM"];
|
|
2391
|
-
for (const event of handlers) {
|
|
2392
|
-
process.once(event, () => {
|
|
2393
|
-
void flush().catch((error) => {
|
|
2394
|
-
warnOnce4(
|
|
2395
|
-
`${key}:shutdown`,
|
|
2396
|
-
"[Blyp] Failed to flush Better Stack logs during shutdown.",
|
|
2397
|
-
error
|
|
2398
|
-
);
|
|
2399
|
-
});
|
|
2400
|
-
});
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
function createBetterStackSender(config) {
|
|
2404
|
-
const connector = resolveConnectorConfig2(config);
|
|
2405
|
-
const key = `${connector.serviceName}:${connector.ingestingHost ?? "missing"}:${connector.mode}`;
|
|
2406
|
-
const sentryModule = getSentryModule();
|
|
2407
|
-
const client = connector.ready ? testHooks2.createClient?.(connector) ?? createDefaultClient(connector) : void 0;
|
|
2408
|
-
let sentryClient = connector.errorTracking.enabled ? sentryModule?.getClient?.() : void 0;
|
|
2409
|
-
if (sentryClient) {
|
|
2410
|
-
const options = getClientOptions(sentryClient);
|
|
2411
|
-
if (hasNonEmptyString(connector.errorTracking.dsn) && connector.errorTracking.dsn !== options.dsn || hasNonEmptyString(connector.errorTracking.environment) && connector.errorTracking.environment !== options.environment || hasNonEmptyString(connector.errorTracking.release) && connector.errorTracking.release !== options.release) {
|
|
2412
|
-
warnOnce4(
|
|
2413
|
-
`betterstack-error-mismatch:${key}`,
|
|
2414
|
-
"[Blyp] Sentry is already initialized with different options. Reusing the existing Sentry client for Better Stack error tracking."
|
|
2415
|
-
);
|
|
2416
|
-
}
|
|
2417
|
-
}
|
|
2418
|
-
if (!sentryClient && connector.errorTracking.enabled && hasNonEmptyString(connector.errorTracking.dsn) && sentryModule) {
|
|
2419
|
-
try {
|
|
2420
|
-
sentryModule.init({
|
|
2421
|
-
dsn: connector.errorTracking.dsn,
|
|
2422
|
-
tracesSampleRate: connector.errorTracking.tracesSampleRate,
|
|
2423
|
-
environment: connector.errorTracking.environment,
|
|
2424
|
-
release: connector.errorTracking.release
|
|
2425
|
-
});
|
|
2426
|
-
sentryClient = sentryModule.getClient();
|
|
2427
|
-
} catch (error) {
|
|
2428
|
-
warnOnce4(
|
|
2429
|
-
`betterstack-error-init:${key}`,
|
|
2430
|
-
"[Blyp] Failed to initialize Better Stack error tracking.",
|
|
2431
|
-
error
|
|
2432
|
-
);
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
const errorTrackingReady = connector.errorTracking.enabled && sentryClient !== void 0;
|
|
2436
|
-
if (client || errorTrackingReady) {
|
|
2437
|
-
registerShutdownHooks2(key, async () => {
|
|
2438
|
-
if (client) {
|
|
2439
|
-
await client.flush();
|
|
2440
|
-
}
|
|
2441
|
-
if (errorTrackingReady) {
|
|
2442
|
-
await sentryModule.flush(2e3);
|
|
2443
|
-
}
|
|
2444
|
-
});
|
|
2445
|
-
}
|
|
2446
|
-
const emitUnavailableWarning = () => {
|
|
2447
|
-
warnOnce4(
|
|
2448
|
-
`betterstack-unavailable:${key}`,
|
|
2449
|
-
"[Blyp] Better Stack connector is not configured or not ready. Skipping Better Stack delivery."
|
|
2450
|
-
);
|
|
2451
|
-
};
|
|
2452
|
-
const emitExceptionUnavailableWarning = () => {
|
|
2453
|
-
warnOnce4(
|
|
2454
|
-
`betterstack-exception-unavailable:${key}`,
|
|
2455
|
-
"[Blyp] Better Stack error tracking is not configured. Skipping Better Stack exception capture."
|
|
2456
|
-
);
|
|
2457
|
-
};
|
|
2458
|
-
return {
|
|
2459
|
-
enabled: connector.enabled,
|
|
2460
|
-
ready: connector.ready,
|
|
2461
|
-
mode: connector.mode,
|
|
2462
|
-
serviceName: connector.serviceName,
|
|
2463
|
-
ingestingHost: connector.ingestingHost,
|
|
2464
|
-
status: connector.status,
|
|
2465
|
-
errorTracking: {
|
|
2466
|
-
enabled: connector.errorTracking.enabled,
|
|
2467
|
-
ready: errorTrackingReady,
|
|
2468
|
-
status: errorTrackingReady ? "enabled" : "missing",
|
|
2469
|
-
dsn: connector.errorTracking.dsn,
|
|
2470
|
-
tracesSampleRate: connector.errorTracking.tracesSampleRate,
|
|
2471
|
-
environment: connector.errorTracking.environment,
|
|
2472
|
-
release: connector.errorTracking.release
|
|
2473
|
-
},
|
|
2474
|
-
shouldAutoForwardServerLogs() {
|
|
2475
|
-
return connector.ready && connector.mode === "auto";
|
|
2476
|
-
},
|
|
2477
|
-
shouldAutoCaptureExceptions() {
|
|
2478
|
-
return errorTrackingReady;
|
|
2479
|
-
},
|
|
2480
|
-
send(record, options = {}) {
|
|
2481
|
-
if (!connector.ready || !client) {
|
|
2482
|
-
if (options.warnIfUnavailable) {
|
|
2483
|
-
emitUnavailableWarning();
|
|
2484
|
-
}
|
|
2485
|
-
return;
|
|
2486
|
-
}
|
|
2487
|
-
const source = options.source ?? "server";
|
|
2488
|
-
void client.log(
|
|
2489
|
-
record.message,
|
|
2490
|
-
resolveBetterStackLevel(record.level),
|
|
2491
|
-
buildContext(record, connector, source)
|
|
2492
|
-
).catch((error) => {
|
|
2493
|
-
warnOnce4(
|
|
2494
|
-
`betterstack-send:${key}`,
|
|
2495
|
-
"[Blyp] Failed to deliver log to Better Stack.",
|
|
2496
|
-
error
|
|
2497
|
-
);
|
|
2498
|
-
});
|
|
2499
|
-
},
|
|
2500
|
-
captureException(error, options = {}) {
|
|
2501
|
-
if (!errorTrackingReady || !sentryModule) {
|
|
2502
|
-
if (options.warnIfUnavailable) {
|
|
2503
|
-
emitExceptionUnavailableWarning();
|
|
2504
|
-
}
|
|
2505
|
-
return;
|
|
2506
|
-
}
|
|
2507
|
-
if (isPreviouslyCapturedError(error)) {
|
|
2508
|
-
return;
|
|
2509
|
-
}
|
|
2510
|
-
try {
|
|
2511
|
-
const exception = normalizeExceptionInput2(error);
|
|
2512
|
-
sentryModule.withScope((scope) => {
|
|
2513
|
-
scope.setLevel(
|
|
2514
|
-
normalizeScopeLevel(
|
|
2515
|
-
options.source === "client" ? "error" : "error"
|
|
2516
|
-
)
|
|
2517
|
-
);
|
|
2518
|
-
scope.setContext("blyp", {
|
|
2519
|
-
source: options.source ?? "server",
|
|
2520
|
-
...options.context ? { context: options.context } : {}
|
|
2521
|
-
});
|
|
2522
|
-
sentryModule.captureException(exception);
|
|
2523
|
-
});
|
|
2524
|
-
markCapturedError(error);
|
|
2525
|
-
markCapturedError(exception);
|
|
2526
|
-
} catch (captureError) {
|
|
2527
|
-
warnOnce4(
|
|
2528
|
-
`betterstack-manual-capture:${key}`,
|
|
2529
|
-
"[Blyp] Failed to capture exception in Better Stack error tracking.",
|
|
2530
|
-
captureError
|
|
2531
|
-
);
|
|
2532
|
-
}
|
|
2533
|
-
},
|
|
2534
|
-
async flush() {
|
|
2535
|
-
if (!client) {
|
|
2536
|
-
if (!errorTrackingReady || !sentryModule) {
|
|
2537
|
-
return;
|
|
2538
|
-
}
|
|
2539
|
-
}
|
|
2540
|
-
try {
|
|
2541
|
-
if (client) {
|
|
2542
|
-
await client.flush();
|
|
2543
|
-
}
|
|
2544
|
-
if (errorTrackingReady && sentryModule) {
|
|
2545
|
-
await sentryModule.flush(2e3);
|
|
2546
|
-
}
|
|
2547
|
-
} catch (error) {
|
|
2548
|
-
warnOnce4(
|
|
2549
|
-
`betterstack-flush:${key}`,
|
|
2550
|
-
"[Blyp] Failed to flush Better Stack logs.",
|
|
2551
|
-
error
|
|
2552
|
-
);
|
|
2553
|
-
}
|
|
2554
|
-
}
|
|
2555
|
-
};
|
|
2556
|
-
}
|
|
2557
|
-
var warnedKeys4 = /* @__PURE__ */ new Set();
|
|
2558
|
-
var testHooks3 = {};
|
|
2559
|
-
var warnOnce5 = createErrorOnceLogger(warnedKeys4);
|
|
2560
|
-
function getSentryModule2() {
|
|
2561
|
-
return testHooks3.module ?? Sentry__namespace;
|
|
2562
|
-
}
|
|
2563
|
-
function resolveConnectorConfig3(config) {
|
|
2564
|
-
const connector = isBlypConfig(config) ? config.connectors?.sentry : config;
|
|
2565
|
-
const enabled = connector?.enabled ?? false;
|
|
2566
|
-
const dsn = connector?.dsn;
|
|
2567
|
-
const ready = enabled && hasNonEmptyString(dsn);
|
|
2568
|
-
return {
|
|
2569
|
-
enabled,
|
|
2570
|
-
mode: connector?.mode ?? "auto",
|
|
2571
|
-
dsn,
|
|
2572
|
-
environment: connector?.environment,
|
|
2573
|
-
release: connector?.release,
|
|
2574
|
-
ready,
|
|
2575
|
-
status: ready ? "enabled" : "missing"
|
|
2576
|
-
};
|
|
2577
|
-
}
|
|
2578
|
-
function normalizeAttributes(record, source) {
|
|
2579
|
-
const attributes = {
|
|
2580
|
-
"blyp.level": record.level,
|
|
2581
|
-
"blyp.source": source,
|
|
2582
|
-
"blyp.payload": serializeLogRecord(record)
|
|
2583
|
-
};
|
|
2584
|
-
const recordType = getRecordType(record);
|
|
2585
|
-
const caller = typeof record.caller === "string" ? record.caller : void 0;
|
|
2586
|
-
const groupId = getField(record, "groupId");
|
|
2587
|
-
const method = getField(record, "method");
|
|
2588
|
-
const path3 = getField(record, "path");
|
|
2589
|
-
const status = getField(record, "status");
|
|
2590
|
-
const duration = getField(record, "duration");
|
|
2591
|
-
const pagePath = getClientPageField(record, "pathname");
|
|
2592
|
-
const pageUrl = getClientPageField(record, "url");
|
|
2593
|
-
const sessionId = getClientSessionField(record, "sessionId");
|
|
2594
|
-
const pageId = getClientSessionField(record, "pageId");
|
|
2595
|
-
const ifTruthy = [
|
|
2596
|
-
["blyp.type", recordType],
|
|
2597
|
-
["blyp.caller", caller],
|
|
2598
|
-
["blyp.group_id", groupId],
|
|
2599
|
-
["http.method", method],
|
|
2600
|
-
["url.path", path3],
|
|
2601
|
-
["client.page_path", pagePath],
|
|
2602
|
-
["client.page_url", pageUrl],
|
|
2603
|
-
["client.session_id", sessionId],
|
|
2604
|
-
["client.page_id", pageId]
|
|
2605
|
-
];
|
|
2606
|
-
const ifDefined = [
|
|
2607
|
-
["http.status_code", status],
|
|
2608
|
-
["blyp.duration_ms", duration]
|
|
2609
|
-
];
|
|
2610
|
-
for (const [k, v] of ifTruthy) if (v) attributes[k] = v;
|
|
2611
|
-
for (const [k, v] of ifDefined) if (v !== void 0) attributes[k] = v;
|
|
2612
|
-
return attributes;
|
|
2613
|
-
}
|
|
2614
|
-
function resolveLogMethod(module, level) {
|
|
2615
|
-
switch (level) {
|
|
2616
|
-
case "debug":
|
|
2617
|
-
return module.logger.debug;
|
|
2618
|
-
case "warning":
|
|
2619
|
-
case "warn":
|
|
2620
|
-
return module.logger.warn;
|
|
2621
|
-
case "error":
|
|
2622
|
-
return module.logger.error;
|
|
2623
|
-
case "critical":
|
|
2624
|
-
return module.logger.fatal;
|
|
2625
|
-
case "success":
|
|
2626
|
-
case "table":
|
|
2627
|
-
case "info":
|
|
2628
|
-
default:
|
|
2629
|
-
return module.logger.info;
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2632
|
-
function normalizeScopeLevel2(level) {
|
|
2633
|
-
switch (level) {
|
|
2634
|
-
case "debug":
|
|
2635
|
-
return "debug";
|
|
2636
|
-
case "warning":
|
|
2637
|
-
case "warn":
|
|
2638
|
-
return "warning";
|
|
2639
|
-
case "critical":
|
|
2640
|
-
return "fatal";
|
|
2641
|
-
case "error":
|
|
2642
|
-
return "error";
|
|
2643
|
-
case "success":
|
|
2644
|
-
case "table":
|
|
2645
|
-
case "info":
|
|
2646
|
-
default:
|
|
2647
|
-
return "info";
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
2650
|
-
function toExceptionCandidate2(value) {
|
|
2651
|
-
if (!isPlainObject(value)) {
|
|
2652
|
-
return void 0;
|
|
2653
|
-
}
|
|
2654
|
-
const message = typeof value.message === "string" ? value.message : void 0;
|
|
2655
|
-
const name = typeof value.name === "string" ? value.name : void 0;
|
|
2656
|
-
const stack = typeof value.stack === "string" ? value.stack : void 0;
|
|
2657
|
-
if (!message && !name && !stack) {
|
|
2658
|
-
return void 0;
|
|
2659
|
-
}
|
|
2660
|
-
const error = new Error(message ?? name ?? "Unknown error");
|
|
2661
|
-
error.name = name ?? "Error";
|
|
2662
|
-
if (stack) {
|
|
2663
|
-
error.stack = stack;
|
|
2664
|
-
}
|
|
2665
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
2666
|
-
if (key === "message" || key === "name" || key === "stack") {
|
|
2667
|
-
continue;
|
|
2668
|
-
}
|
|
2669
|
-
error[key] = entry;
|
|
2670
|
-
}
|
|
2671
|
-
return error;
|
|
2672
|
-
}
|
|
2673
|
-
function extractExceptionCandidate(record) {
|
|
2674
|
-
if (record.level !== "error" && record.level !== "critical") {
|
|
2675
|
-
return void 0;
|
|
2676
|
-
}
|
|
2677
|
-
const direct = toExceptionCandidate2(record.error);
|
|
2678
|
-
if (direct) {
|
|
2679
|
-
return direct;
|
|
2680
|
-
}
|
|
2681
|
-
if (isPlainObject(record.data)) {
|
|
2682
|
-
const directData = toExceptionCandidate2(record.data);
|
|
2683
|
-
if (directData) {
|
|
2684
|
-
return directData;
|
|
2685
|
-
}
|
|
2686
|
-
const nested = toExceptionCandidate2(record.data.error);
|
|
2687
|
-
if (nested) {
|
|
2688
|
-
return nested;
|
|
2689
|
-
}
|
|
2690
|
-
}
|
|
2691
|
-
const payload = getPrimaryPayload(record);
|
|
2692
|
-
if (isPlainObject(payload)) {
|
|
2693
|
-
const nested = toExceptionCandidate2(payload.error);
|
|
2694
|
-
if (nested) {
|
|
2695
|
-
return nested;
|
|
2696
|
-
}
|
|
2697
|
-
}
|
|
2698
|
-
return void 0;
|
|
2699
|
-
}
|
|
2700
|
-
function getClientOptions2(client) {
|
|
2701
|
-
return client?.getOptions?.() ?? {};
|
|
2702
|
-
}
|
|
2703
|
-
function hasConfigMismatch(connector, client) {
|
|
2704
|
-
const options = getClientOptions2(client);
|
|
2705
|
-
return hasNonEmptyString(connector.dsn) && connector.dsn !== options.dsn || hasNonEmptyString(connector.environment) && connector.environment !== options.environment || hasNonEmptyString(connector.release) && connector.release !== options.release;
|
|
2706
|
-
}
|
|
2707
|
-
function createSentrySender(config) {
|
|
2708
|
-
const connector = resolveConnectorConfig3(config);
|
|
2709
|
-
const key = `${connector.mode}:${connector.dsn ?? "missing"}`;
|
|
2710
|
-
const module = getSentryModule2();
|
|
2711
|
-
let client = connector.enabled ? module.getClient() : void 0;
|
|
2712
|
-
if (!client && connector.enabled && hasNonEmptyString(connector.dsn)) {
|
|
2713
|
-
try {
|
|
2714
|
-
module.init({
|
|
2715
|
-
dsn: connector.dsn,
|
|
2716
|
-
environment: connector.environment,
|
|
2717
|
-
release: connector.release,
|
|
2718
|
-
enableLogs: true
|
|
2719
|
-
});
|
|
2720
|
-
client = module.getClient();
|
|
2721
|
-
} catch (error) {
|
|
2722
|
-
warnOnce5(
|
|
2723
|
-
`sentry-init:${key}`,
|
|
2724
|
-
"[Blyp] Failed to initialize Sentry. Skipping Sentry delivery.",
|
|
2725
|
-
error
|
|
2726
|
-
);
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
if (client && hasConfigMismatch(connector, client)) {
|
|
2730
|
-
warnOnce5(
|
|
2731
|
-
`sentry-mismatch:${key}`,
|
|
2732
|
-
"[Blyp] Sentry is already initialized with different options. Reusing the existing Sentry client."
|
|
2733
|
-
);
|
|
2734
|
-
}
|
|
2735
|
-
const ready = connector.enabled && client !== void 0;
|
|
2736
|
-
const emitUnavailableWarning = () => {
|
|
2737
|
-
warnOnce5(
|
|
2738
|
-
`sentry-unavailable:${key}`,
|
|
2739
|
-
"[Blyp] Sentry connector is not configured. Skipping Sentry delivery."
|
|
2740
|
-
);
|
|
2741
|
-
};
|
|
2742
|
-
return {
|
|
2743
|
-
enabled: connector.enabled,
|
|
2744
|
-
ready,
|
|
2745
|
-
mode: connector.mode,
|
|
2746
|
-
status: ready ? "enabled" : "missing",
|
|
2747
|
-
shouldAutoForwardServerLogs() {
|
|
2748
|
-
return ready && connector.mode === "auto";
|
|
2749
|
-
},
|
|
2750
|
-
send(record, options = {}) {
|
|
2751
|
-
if (!ready) {
|
|
2752
|
-
if (options.warnIfUnavailable) {
|
|
2753
|
-
emitUnavailableWarning();
|
|
2754
|
-
}
|
|
2755
|
-
return;
|
|
2756
|
-
}
|
|
2757
|
-
const source = options.source ?? "server";
|
|
2758
|
-
const attributes = normalizeAttributes(record, source);
|
|
2759
|
-
const logMethod = resolveLogMethod(module, record.level);
|
|
2760
|
-
try {
|
|
2761
|
-
logMethod(record.message, attributes);
|
|
2762
|
-
} catch (error) {
|
|
2763
|
-
warnOnce5(
|
|
2764
|
-
`sentry-log:${key}`,
|
|
2765
|
-
"[Blyp] Failed to deliver log to Sentry.",
|
|
2766
|
-
error
|
|
2767
|
-
);
|
|
2768
|
-
}
|
|
2769
|
-
const exception = extractExceptionCandidate(record);
|
|
2770
|
-
if (!exception) {
|
|
2771
|
-
return;
|
|
2772
|
-
}
|
|
2773
|
-
try {
|
|
2774
|
-
module.withScope((scope) => {
|
|
2775
|
-
scope.setLevel(normalizeScopeLevel2(record.level));
|
|
2776
|
-
scope.setContext("blyp", attributes);
|
|
2777
|
-
scope.setExtra("blyp.payload", serializeLogRecord(record));
|
|
2778
|
-
module.captureException(exception);
|
|
2779
|
-
});
|
|
2780
|
-
} catch (error) {
|
|
2781
|
-
warnOnce5(
|
|
2782
|
-
`sentry-exception:${key}`,
|
|
2783
|
-
"[Blyp] Failed to capture exception in Sentry.",
|
|
2784
|
-
error
|
|
2785
|
-
);
|
|
2786
|
-
}
|
|
2787
|
-
},
|
|
2788
|
-
async flush() {
|
|
2789
|
-
try {
|
|
2790
|
-
await module.flush(2e3);
|
|
2791
|
-
} catch (error) {
|
|
2792
|
-
warnOnce5(
|
|
2793
|
-
`sentry-flush:${key}`,
|
|
2794
|
-
"[Blyp] Failed to flush Sentry logs.",
|
|
2795
|
-
error
|
|
2796
|
-
);
|
|
2797
|
-
}
|
|
2798
|
-
}
|
|
2799
|
-
};
|
|
2800
|
-
}
|
|
2801
|
-
var warnedKeys5 = /* @__PURE__ */ new Set();
|
|
2802
|
-
var testHooks4 = {};
|
|
2803
|
-
var warnOnce6 = createErrorOnceLogger(warnedKeys5);
|
|
2804
|
-
function normalizeOTLPRecord(record, connector, source = "server") {
|
|
2805
|
-
const severity = resolveSeverity2(record.level);
|
|
2806
|
-
const body = typeof record.message === "string" ? record.message : String(record.message);
|
|
2807
|
-
const recordType = getRecordType(record);
|
|
2808
|
-
const caller = typeof record.caller === "string" ? record.caller : void 0;
|
|
2809
|
-
const groupId = getField(record, "groupId");
|
|
2810
|
-
const method = getField(record, "method");
|
|
2811
|
-
const path3 = getField(record, "path");
|
|
2812
|
-
const status = getField(record, "status");
|
|
2813
|
-
const duration = getField(record, "duration");
|
|
2814
|
-
const pagePath = getClientPageField(record, "pathname");
|
|
2815
|
-
const pageUrl = getClientPageField(record, "url");
|
|
2816
|
-
const sessionId = getClientSessionField(record, "sessionId");
|
|
2817
|
-
const pageId = getClientSessionField(record, "pageId");
|
|
2818
|
-
const attributes = {
|
|
2819
|
-
"blyp.level": record.level,
|
|
2820
|
-
"blyp.source": source,
|
|
2821
|
-
"blyp.payload": serializeLogRecord(record)
|
|
2822
|
-
};
|
|
2823
|
-
const ifTruthy = [
|
|
2824
|
-
["blyp.type", recordType],
|
|
2825
|
-
["blyp.caller", caller],
|
|
2826
|
-
["blyp.group_id", groupId],
|
|
2827
|
-
["http.method", method],
|
|
2828
|
-
["url.path", path3],
|
|
2829
|
-
["client.page_path", pagePath],
|
|
2830
|
-
["client.page_url", pageUrl],
|
|
2831
|
-
["client.session_id", sessionId],
|
|
2832
|
-
["client.page_id", pageId]
|
|
2833
|
-
];
|
|
2834
|
-
const ifDefined = [
|
|
2835
|
-
["http.status_code", status],
|
|
2836
|
-
["blyp.duration_ms", duration]
|
|
2837
|
-
];
|
|
2838
|
-
for (const [k, v] of ifTruthy) if (v) attributes[k] = v;
|
|
2839
|
-
for (const [k, v] of ifDefined) if (v !== void 0) attributes[k] = v;
|
|
2840
|
-
return {
|
|
2841
|
-
body,
|
|
2842
|
-
severityText: severity.text,
|
|
2843
|
-
severityNumber: severity.number,
|
|
2844
|
-
attributes,
|
|
2845
|
-
resourceAttributes: {
|
|
2846
|
-
"service.name": connector.serviceName
|
|
2847
|
-
}
|
|
2848
|
-
};
|
|
2849
|
-
}
|
|
2850
|
-
function resolveSeverity2(level) {
|
|
2851
|
-
switch (level) {
|
|
2852
|
-
case "debug":
|
|
2853
|
-
return { text: "debug", number: apiLogs.SeverityNumber.DEBUG };
|
|
2854
|
-
case "warning":
|
|
2855
|
-
case "warn":
|
|
2856
|
-
return { text: "warn", number: apiLogs.SeverityNumber.WARN };
|
|
2857
|
-
case "error":
|
|
2858
|
-
return { text: "error", number: apiLogs.SeverityNumber.ERROR };
|
|
2859
|
-
case "critical":
|
|
2860
|
-
return { text: "fatal", number: apiLogs.SeverityNumber.FATAL };
|
|
2861
|
-
case "success":
|
|
2862
|
-
case "table":
|
|
2863
|
-
case "info":
|
|
2864
|
-
default:
|
|
2865
|
-
return { text: "info", number: apiLogs.SeverityNumber.INFO };
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
function registerShutdownHooks3(key, shutdown) {
|
|
2869
|
-
const handlers = ["beforeExit", "SIGINT", "SIGTERM"];
|
|
2870
|
-
for (const event of handlers) {
|
|
2871
|
-
process.once(event, async () => {
|
|
2872
|
-
try {
|
|
2873
|
-
await shutdown();
|
|
2874
|
-
} catch (error) {
|
|
2875
|
-
warnOnce6(
|
|
2876
|
-
`${key}:shutdown`,
|
|
2877
|
-
"[Blyp] Failed to flush OTLP logs during shutdown.",
|
|
2878
|
-
error
|
|
2879
|
-
);
|
|
2880
|
-
}
|
|
2881
|
-
if (event !== "beforeExit") {
|
|
2882
|
-
process.exit(0);
|
|
2883
|
-
}
|
|
2884
|
-
});
|
|
2885
|
-
}
|
|
2886
|
-
}
|
|
2887
|
-
function resolveTransportHeaders(connector) {
|
|
2888
|
-
const headers = {
|
|
2889
|
-
...connector.headers ?? {}
|
|
2890
|
-
};
|
|
2891
|
-
if (headers.Authorization === void 0 && connector.auth) {
|
|
2892
|
-
headers.Authorization = connector.auth;
|
|
2893
|
-
}
|
|
2894
|
-
return headers;
|
|
2895
|
-
}
|
|
2896
|
-
function createDefaultTransport2(connector) {
|
|
2897
|
-
const exporter = new exporterLogsOtlpHttp.OTLPLogExporter({
|
|
2898
|
-
url: connector.endpoint,
|
|
2899
|
-
headers: resolveTransportHeaders(connector)
|
|
2900
|
-
});
|
|
2901
|
-
const provider = new sdkLogs.LoggerProvider({
|
|
2902
|
-
resource: resources.resourceFromAttributes({
|
|
2903
|
-
"service.name": connector.serviceName
|
|
2904
|
-
}),
|
|
2905
|
-
processors: [new sdkLogs.BatchLogRecordProcessor(exporter)]
|
|
2906
|
-
});
|
|
2907
|
-
const logger2 = provider.getLogger(`blyp-otlp:${connector.name}`);
|
|
2908
|
-
return {
|
|
2909
|
-
emit(payload) {
|
|
2910
|
-
logger2.emit({
|
|
2911
|
-
body: payload.body,
|
|
2912
|
-
severityText: payload.severityText,
|
|
2913
|
-
severityNumber: payload.severityNumber,
|
|
2914
|
-
attributes: payload.attributes
|
|
2915
|
-
});
|
|
2916
|
-
},
|
|
2917
|
-
flush() {
|
|
2918
|
-
return provider.forceFlush();
|
|
2919
|
-
},
|
|
2920
|
-
shutdown() {
|
|
2921
|
-
return provider.shutdown();
|
|
2922
|
-
}
|
|
2923
|
-
};
|
|
2924
|
-
}
|
|
2925
|
-
function resolveConnectors(config) {
|
|
2926
|
-
const connectors = isBlypConfig(config) ? config.connectors?.otlp ?? [] : config;
|
|
2927
|
-
return connectors.map((connector) => {
|
|
2928
|
-
const headers = {
|
|
2929
|
-
...connector.headers ?? {}
|
|
2930
|
-
};
|
|
2931
|
-
const enabled = connector.enabled ?? false;
|
|
2932
|
-
const endpoint = connector.endpoint;
|
|
2933
|
-
const explicitReady = "ready" in connector && typeof connector.ready === "boolean" ? connector.ready : void 0;
|
|
2934
|
-
const ready = (explicitReady ?? (enabled && isAbsoluteHttpUrl(endpoint))) && isAbsoluteHttpUrl(endpoint);
|
|
24
|
+
const mod = await import(BUN_SQLITE_MODULE);
|
|
25
|
+
const Database = mod.default;
|
|
26
|
+
runtime = 'bun';
|
|
2935
27
|
return {
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
28
|
+
create(filePath) {
|
|
29
|
+
return new Database(filePath);
|
|
30
|
+
},
|
|
31
|
+
exec(instance, sql) {
|
|
32
|
+
instance.exec(sql);
|
|
33
|
+
},
|
|
34
|
+
prepare(instance, sql) {
|
|
35
|
+
return instance.prepare(sql);
|
|
36
|
+
},
|
|
37
|
+
close(instance) {
|
|
38
|
+
instance.close();
|
|
39
|
+
},
|
|
40
|
+
run(statement, params) {
|
|
41
|
+
statement.run(...params);
|
|
42
|
+
},
|
|
43
|
+
all(statement, params) {
|
|
44
|
+
return statement.all(...params);
|
|
45
|
+
},
|
|
2945
46
|
};
|
|
2946
|
-
}
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
`[Blyp] OTLP target "${senderName}" is not configured or not ready. Skipping OTLP delivery.`
|
|
2955
|
-
);
|
|
2956
|
-
};
|
|
2957
|
-
return {
|
|
2958
|
-
name: senderName,
|
|
2959
|
-
enabled: connector?.enabled ?? false,
|
|
2960
|
-
ready: false,
|
|
2961
|
-
mode: connector?.mode ?? "auto",
|
|
2962
|
-
serviceName: connector?.serviceName ?? "blyp-app",
|
|
2963
|
-
endpoint: connector?.endpoint,
|
|
2964
|
-
status: "missing",
|
|
2965
|
-
send(_record, options = {}) {
|
|
2966
|
-
if (options.warnIfUnavailable) {
|
|
2967
|
-
emitUnavailableWarning();
|
|
2968
|
-
}
|
|
2969
|
-
},
|
|
2970
|
-
async flush() {
|
|
2971
|
-
}
|
|
2972
|
-
};
|
|
2973
|
-
}
|
|
2974
|
-
function createSender(connector) {
|
|
2975
|
-
if (!connector.ready || !connector.endpoint) {
|
|
2976
|
-
return createUnavailableSender(connector.name, connector);
|
|
2977
|
-
}
|
|
2978
|
-
const key = `${connector.name}:${connector.serviceName}:${connector.endpoint}:${connector.mode}`;
|
|
2979
|
-
const transportConnector = {
|
|
2980
|
-
...connector,
|
|
2981
|
-
headers: resolveTransportHeaders(connector)
|
|
2982
|
-
};
|
|
2983
|
-
const transport = testHooks4.createTransport?.(transportConnector) ?? createDefaultTransport2(transportConnector);
|
|
2984
|
-
return {
|
|
2985
|
-
name: connector.name,
|
|
2986
|
-
enabled: connector.enabled,
|
|
2987
|
-
ready: connector.ready,
|
|
2988
|
-
mode: connector.mode,
|
|
2989
|
-
serviceName: connector.serviceName,
|
|
2990
|
-
endpoint: connector.endpoint,
|
|
2991
|
-
status: connector.status,
|
|
2992
|
-
send(record, options = {}) {
|
|
2993
|
-
const source = options.source ?? "server";
|
|
2994
|
-
const normalized = normalizeOTLPRecord(record, connector, source);
|
|
2995
|
-
try {
|
|
2996
|
-
const result = transport.emit(normalized);
|
|
2997
|
-
if (result && typeof result.catch === "function") {
|
|
2998
|
-
void result.catch((error) => {
|
|
2999
|
-
warnOnce6(
|
|
3000
|
-
`otlp-emit:${key}`,
|
|
3001
|
-
`[Blyp] Failed to deliver log to OTLP target "${connector.name}".`,
|
|
3002
|
-
error
|
|
3003
|
-
);
|
|
3004
|
-
});
|
|
3005
|
-
}
|
|
3006
|
-
} catch (error) {
|
|
3007
|
-
warnOnce6(
|
|
3008
|
-
`otlp-emit:${key}`,
|
|
3009
|
-
`[Blyp] Failed to deliver log to OTLP target "${connector.name}".`,
|
|
3010
|
-
error
|
|
3011
|
-
);
|
|
3012
|
-
}
|
|
3013
|
-
},
|
|
3014
|
-
async flush() {
|
|
3015
|
-
try {
|
|
3016
|
-
if (transport.flush) {
|
|
3017
|
-
await transport.flush();
|
|
3018
|
-
}
|
|
3019
|
-
} catch (error) {
|
|
3020
|
-
warnOnce6(
|
|
3021
|
-
`otlp-flush:${key}`,
|
|
3022
|
-
`[Blyp] Failed to flush OTLP logs for target "${connector.name}".`,
|
|
3023
|
-
error
|
|
3024
|
-
);
|
|
3025
|
-
}
|
|
3026
|
-
}
|
|
3027
|
-
};
|
|
3028
|
-
}
|
|
3029
|
-
function createOTLPRegistry(config) {
|
|
3030
|
-
const senders = /* @__PURE__ */ new Map();
|
|
3031
|
-
for (const connector of resolveConnectors(config)) {
|
|
3032
|
-
senders.set(connector.name, createSender(connector));
|
|
3033
|
-
}
|
|
3034
|
-
const registry = {
|
|
3035
|
-
get(name) {
|
|
3036
|
-
return senders.get(name) ?? createUnavailableSender(name);
|
|
3037
|
-
},
|
|
3038
|
-
getAutoForwardTargets() {
|
|
3039
|
-
return Array.from(senders.values()).filter((sender) => sender.ready && sender.mode === "auto");
|
|
3040
|
-
},
|
|
3041
|
-
send(name, record, options = {}) {
|
|
3042
|
-
const sender = senders.get(name) ?? createUnavailableSender(name);
|
|
3043
|
-
sender.send(record, options);
|
|
3044
|
-
},
|
|
3045
|
-
async flush() {
|
|
3046
|
-
await Promise.all(Array.from(senders.values()).map((sender) => sender.flush()));
|
|
3047
|
-
}
|
|
3048
|
-
};
|
|
3049
|
-
registerShutdownHooks3("otlp-registry", () => registry.flush());
|
|
3050
|
-
return registry;
|
|
3051
|
-
}
|
|
3052
|
-
var _RuntimeDetector = class _RuntimeDetector {
|
|
3053
|
-
constructor() {
|
|
3054
|
-
__publicField(this, "_type", null);
|
|
3055
|
-
}
|
|
3056
|
-
static getInstance() {
|
|
3057
|
-
if (!_RuntimeDetector.instance) {
|
|
3058
|
-
_RuntimeDetector.instance = new _RuntimeDetector();
|
|
3059
|
-
}
|
|
3060
|
-
return _RuntimeDetector.instance;
|
|
3061
|
-
}
|
|
3062
|
-
get type() {
|
|
3063
|
-
if (this._type === null) {
|
|
3064
|
-
this._type = this.detectRuntime();
|
|
3065
|
-
}
|
|
3066
|
-
return this._type;
|
|
3067
|
-
}
|
|
3068
|
-
get isBun() {
|
|
3069
|
-
return this.type === "bun";
|
|
3070
|
-
}
|
|
3071
|
-
get isNode() {
|
|
3072
|
-
return this.type === "node";
|
|
3073
|
-
}
|
|
3074
|
-
detectRuntime() {
|
|
3075
|
-
if (typeof Bun !== "undefined" && typeof Bun.file === "function") {
|
|
3076
|
-
return "bun";
|
|
3077
|
-
}
|
|
3078
|
-
return "node";
|
|
3079
|
-
}
|
|
3080
|
-
};
|
|
3081
|
-
__publicField(_RuntimeDetector, "instance");
|
|
3082
|
-
var RuntimeDetector = _RuntimeDetector;
|
|
3083
|
-
var BunAdapter = class {
|
|
3084
|
-
constructor() {
|
|
3085
|
-
__publicField(this, "type", "bun");
|
|
3086
|
-
__publicField(this, "isBun", true);
|
|
3087
|
-
__publicField(this, "isNode", false);
|
|
3088
|
-
__publicField(this, "file", {
|
|
3089
|
-
existsSync: (filePath) => {
|
|
3090
|
-
try {
|
|
3091
|
-
const file = Bun.file(filePath);
|
|
3092
|
-
return file.size > 0 || file.name !== "";
|
|
3093
|
-
} catch {
|
|
3094
|
-
return false;
|
|
3095
|
-
}
|
|
47
|
+
} catch {}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const mod = await import(NODE_SQLITE_MODULE);
|
|
51
|
+
runtime = 'node';
|
|
52
|
+
return {
|
|
53
|
+
create(filePath) {
|
|
54
|
+
return new mod.DatabaseSync(filePath);
|
|
3096
55
|
},
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
fs__default.default.mkdirSync(filePath, options);
|
|
3100
|
-
} catch {
|
|
3101
|
-
}
|
|
56
|
+
exec(instance, sql) {
|
|
57
|
+
instance.exec(sql);
|
|
3102
58
|
},
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
}
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
join: (...paths) => {
|
|
3109
|
-
return path__default.default.join(...paths);
|
|
3110
|
-
}
|
|
3111
|
-
});
|
|
3112
|
-
__publicField(this, "env", {
|
|
3113
|
-
get: (key) => Bun.env[key]
|
|
3114
|
-
});
|
|
3115
|
-
__publicField(this, "cwd", () => {
|
|
3116
|
-
return process.cwd();
|
|
3117
|
-
});
|
|
3118
|
-
}
|
|
3119
|
-
};
|
|
3120
|
-
var NodeAdapter = class {
|
|
3121
|
-
constructor() {
|
|
3122
|
-
__publicField(this, "type", "node");
|
|
3123
|
-
__publicField(this, "isBun", false);
|
|
3124
|
-
__publicField(this, "isNode", true);
|
|
3125
|
-
__publicField(this, "file", {
|
|
3126
|
-
existsSync: (filePath) => fs__default.default.existsSync(filePath),
|
|
3127
|
-
mkdirSync: (filePath, options) => {
|
|
3128
|
-
fs__default.default.mkdirSync(filePath, options);
|
|
59
|
+
prepare(instance, sql) {
|
|
60
|
+
return instance.prepare(sql);
|
|
61
|
+
},
|
|
62
|
+
close(instance) {
|
|
63
|
+
instance.close();
|
|
3129
64
|
},
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
}
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
get: (key) => process.env[key]
|
|
3139
|
-
});
|
|
3140
|
-
__publicField(this, "cwd", () => process.cwd());
|
|
3141
|
-
}
|
|
3142
|
-
};
|
|
3143
|
-
function createRuntimeAdapter() {
|
|
3144
|
-
const detector = RuntimeDetector.getInstance();
|
|
3145
|
-
if (detector.isBun) {
|
|
3146
|
-
return new BunAdapter();
|
|
3147
|
-
}
|
|
3148
|
-
return new NodeAdapter();
|
|
3149
|
-
}
|
|
3150
|
-
var runtime = createRuntimeAdapter();
|
|
65
|
+
run(statement, params) {
|
|
66
|
+
statement.run(...params);
|
|
67
|
+
},
|
|
68
|
+
all(statement, params) {
|
|
69
|
+
return statement.all(...params);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
} catch {}
|
|
3151
73
|
|
|
3152
|
-
|
|
3153
|
-
function serializeMessage2(message) {
|
|
3154
|
-
if (typeof message === "string") {
|
|
3155
|
-
return message;
|
|
3156
|
-
}
|
|
3157
|
-
if (message !== null && typeof message === "object") {
|
|
3158
|
-
try {
|
|
3159
|
-
return JSON.stringify(
|
|
3160
|
-
message,
|
|
3161
|
-
(_key, value) => {
|
|
3162
|
-
if (typeof value === "function") {
|
|
3163
|
-
return `[Function: ${value.name || "anonymous"}]`;
|
|
3164
|
-
}
|
|
3165
|
-
if (value === void 0) {
|
|
3166
|
-
return "[undefined]";
|
|
3167
|
-
}
|
|
3168
|
-
if (typeof value === "symbol") {
|
|
3169
|
-
return value.toString();
|
|
3170
|
-
}
|
|
3171
|
-
return value;
|
|
3172
|
-
},
|
|
3173
|
-
2
|
|
3174
|
-
);
|
|
3175
|
-
} catch {
|
|
3176
|
-
return "[Object]";
|
|
3177
|
-
}
|
|
3178
|
-
}
|
|
3179
|
-
return String(message);
|
|
74
|
+
throw new Error('No built-in SQLite runtime is available in this worker.');
|
|
3180
75
|
}
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
76
|
+
|
|
77
|
+
let adapter;
|
|
78
|
+
|
|
79
|
+
function ensureReady() {
|
|
80
|
+
if (!db || !adapter) {
|
|
81
|
+
throw new Error('SQLite durable queue is not initialized.');
|
|
3187
82
|
}
|
|
3188
|
-
const values = [message, ...args];
|
|
3189
|
-
return values.length === 1 ? values[0] : values;
|
|
3190
83
|
}
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
}
|
|
3195
|
-
return value;
|
|
84
|
+
|
|
85
|
+
function normalizeConnectorTarget(value) {
|
|
86
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
3196
87
|
}
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
message: `HTTP ${fallbackStatus}`,
|
|
3201
|
-
code: fallbackStatus,
|
|
3202
|
-
type: "HttpError"
|
|
3203
|
-
};
|
|
3204
|
-
}
|
|
3205
|
-
if (error instanceof Error) {
|
|
3206
|
-
const errorLike = error;
|
|
3207
|
-
return {
|
|
3208
|
-
message: error.message,
|
|
3209
|
-
code: errorLike.code,
|
|
3210
|
-
type: errorLike.type ?? error.name ?? error.constructor?.name,
|
|
3211
|
-
stack: error.stack,
|
|
3212
|
-
why: errorLike.why,
|
|
3213
|
-
fix: errorLike.fix,
|
|
3214
|
-
link: errorLike.link,
|
|
3215
|
-
details: normalizeDetails(errorLike.details),
|
|
3216
|
-
cause: errorLike.cause
|
|
3217
|
-
};
|
|
3218
|
-
}
|
|
3219
|
-
if (typeof error === "object") {
|
|
3220
|
-
const record = error;
|
|
3221
|
-
const statusCode = typeof record.statusCode === "number" ? record.statusCode : typeof record.status === "number" ? record.status : fallbackStatus;
|
|
3222
|
-
return {
|
|
3223
|
-
message: typeof record.message === "string" ? record.message : `HTTP ${statusCode ?? 500}`,
|
|
3224
|
-
code: typeof record.code === "string" || typeof record.code === "number" ? record.code : statusCode,
|
|
3225
|
-
type: typeof record.type === "string" ? record.type : typeof record.name === "string" ? record.name : "Error",
|
|
3226
|
-
stack: typeof record.stack === "string" ? record.stack : void 0,
|
|
3227
|
-
why: typeof record.why === "string" ? record.why : void 0,
|
|
3228
|
-
fix: typeof record.fix === "string" ? record.fix : void 0,
|
|
3229
|
-
link: typeof record.link === "string" ? record.link : void 0,
|
|
3230
|
-
details: normalizeDetails(record.details),
|
|
3231
|
-
cause: record.cause
|
|
3232
|
-
};
|
|
3233
|
-
}
|
|
3234
|
-
return {
|
|
3235
|
-
message: String(error),
|
|
3236
|
-
code: fallbackStatus,
|
|
3237
|
-
type: typeof error
|
|
3238
|
-
};
|
|
88
|
+
|
|
89
|
+
function createConnectorCondition() {
|
|
90
|
+
return '(connector_type = ? AND ((connector_target IS NULL AND ? IS NULL) OR connector_target = ?))';
|
|
3239
91
|
}
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
92
|
+
|
|
93
|
+
function updateConnectorDeliveryStatus(item, success) {
|
|
94
|
+
const connectorTarget = normalizeConnectorTarget(item.connectorTarget);
|
|
95
|
+
const select = adapter.prepare(
|
|
96
|
+
db,
|
|
97
|
+
'SELECT rowid FROM connector_delivery_status WHERE ' + createConnectorCondition() + ' LIMIT 1'
|
|
98
|
+
);
|
|
99
|
+
const existing = adapter.all(select, [item.connectorType, connectorTarget, connectorTarget])[0];
|
|
100
|
+
|
|
101
|
+
if (existing) {
|
|
102
|
+
const update = adapter.prepare(
|
|
103
|
+
db,
|
|
104
|
+
success
|
|
105
|
+
? 'UPDATE connector_delivery_status SET last_success_at = ?, last_error = NULL, updated_at = ? WHERE rowid = ?'
|
|
106
|
+
: 'UPDATE connector_delivery_status SET last_failure_at = ?, last_error = ?, updated_at = ? WHERE rowid = ?'
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
adapter.run(
|
|
110
|
+
update,
|
|
111
|
+
success
|
|
112
|
+
? [item.timestamp, item.timestamp, existing.rowid]
|
|
113
|
+
: [item.timestamp, item.lastError ?? null, item.timestamp, existing.rowid]
|
|
114
|
+
);
|
|
115
|
+
return;
|
|
3252
116
|
}
|
|
3253
|
-
|
|
117
|
+
|
|
118
|
+
const insert = adapter.prepare(
|
|
119
|
+
db,
|
|
120
|
+
'INSERT INTO connector_delivery_status (connector_type, connector_target, last_success_at, last_failure_at, last_error, updated_at) VALUES (?, ?, ?, ?, ?, ?)'
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
adapter.run(insert, [
|
|
124
|
+
item.connectorType,
|
|
125
|
+
connectorTarget,
|
|
126
|
+
success ? item.timestamp : null,
|
|
127
|
+
success ? null : item.timestamp,
|
|
128
|
+
success ? null : item.lastError ?? null,
|
|
129
|
+
item.timestamp,
|
|
130
|
+
]);
|
|
3254
131
|
}
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
const error = normalizeError2(emitOptions.error, status);
|
|
3306
|
-
const level = emitOptions.level ?? (error ? "error" : "info");
|
|
3307
|
-
const payload = {
|
|
3308
|
-
...defaultFields,
|
|
3309
|
-
...fields,
|
|
3310
|
-
groupId,
|
|
3311
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3312
|
-
level,
|
|
3313
|
-
duration: Math.round(performance.now() - startedAt),
|
|
3314
|
-
...typeof status === "number" ? { status } : {},
|
|
3315
|
-
...events.length > 0 ? { events: [...events] } : {},
|
|
3316
|
-
...error ? { error } : {}
|
|
3317
|
-
};
|
|
3318
|
-
options.write(payload, emitOptions.message ?? "structured_log");
|
|
3319
|
-
emittedPayload = payload;
|
|
3320
|
-
options.onEmit?.(payload);
|
|
3321
|
-
return payload;
|
|
3322
|
-
}
|
|
3323
|
-
};
|
|
3324
|
-
return structuredLog;
|
|
132
|
+
|
|
133
|
+
function initializeSchema() {
|
|
134
|
+
ensureReady();
|
|
135
|
+
adapter.exec(db, [
|
|
136
|
+
'PRAGMA journal_mode = WAL;',
|
|
137
|
+
'PRAGMA busy_timeout = 5000;',
|
|
138
|
+
'CREATE TABLE IF NOT EXISTS connector_queue_meta (schema_version INTEGER NOT NULL);',
|
|
139
|
+
'DELETE FROM connector_queue_meta;',
|
|
140
|
+
'INSERT INTO connector_queue_meta (schema_version) VALUES (2);',
|
|
141
|
+
'CREATE TABLE IF NOT EXISTS connector_jobs (',
|
|
142
|
+
' id TEXT PRIMARY KEY,',
|
|
143
|
+
' connector_type TEXT NOT NULL,',
|
|
144
|
+
' connector_target TEXT NULL,',
|
|
145
|
+
' operation TEXT NOT NULL,',
|
|
146
|
+
' payload_json TEXT NOT NULL,',
|
|
147
|
+
' attempt_count INTEGER NOT NULL,',
|
|
148
|
+
' max_attempts INTEGER NOT NULL,',
|
|
149
|
+
' next_attempt_at INTEGER NOT NULL,',
|
|
150
|
+
' state TEXT NOT NULL,',
|
|
151
|
+
' last_error TEXT NULL,',
|
|
152
|
+
' created_at INTEGER NOT NULL,',
|
|
153
|
+
' updated_at INTEGER NOT NULL,',
|
|
154
|
+
' claimed_at INTEGER NULL',
|
|
155
|
+
');',
|
|
156
|
+
'CREATE TABLE IF NOT EXISTS connector_dead_letters (',
|
|
157
|
+
' id TEXT PRIMARY KEY,',
|
|
158
|
+
' connector_type TEXT NOT NULL,',
|
|
159
|
+
' connector_target TEXT NULL,',
|
|
160
|
+
' operation TEXT NOT NULL,',
|
|
161
|
+
' payload_json TEXT NOT NULL,',
|
|
162
|
+
' attempt_count INTEGER NOT NULL,',
|
|
163
|
+
' max_attempts INTEGER NOT NULL,',
|
|
164
|
+
' last_error TEXT NULL,',
|
|
165
|
+
' first_enqueued_at INTEGER NOT NULL,',
|
|
166
|
+
' dead_lettered_at INTEGER NOT NULL,',
|
|
167
|
+
' last_attempt_at INTEGER NOT NULL',
|
|
168
|
+
');',
|
|
169
|
+
'CREATE TABLE IF NOT EXISTS connector_delivery_status (',
|
|
170
|
+
' connector_type TEXT NOT NULL,',
|
|
171
|
+
' connector_target TEXT NULL,',
|
|
172
|
+
' last_success_at INTEGER NULL,',
|
|
173
|
+
' last_failure_at INTEGER NULL,',
|
|
174
|
+
' last_error TEXT NULL,',
|
|
175
|
+
' updated_at INTEGER NOT NULL',
|
|
176
|
+
');',
|
|
177
|
+
'CREATE INDEX IF NOT EXISTS idx_connector_jobs_state_due ON connector_jobs(state, next_attempt_at);',
|
|
178
|
+
'CREATE INDEX IF NOT EXISTS idx_connector_jobs_connector_state_due ON connector_jobs(connector_type, connector_target, state, next_attempt_at);',
|
|
179
|
+
'CREATE INDEX IF NOT EXISTS idx_connector_dead_letters_connector_dead_lettered ON connector_dead_letters(connector_type, connector_target, dead_lettered_at);',
|
|
180
|
+
'CREATE INDEX IF NOT EXISTS idx_connector_delivery_status_connector ON connector_delivery_status(connector_type, connector_target);'
|
|
181
|
+
].join('\\n'));
|
|
3325
182
|
}
|
|
3326
183
|
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
warning: 40,
|
|
3335
|
-
error: 50,
|
|
3336
|
-
critical: 60
|
|
3337
|
-
};
|
|
3338
|
-
var CONSOLE_LEVELS = {
|
|
3339
|
-
success: "success",
|
|
3340
|
-
critical: "critical",
|
|
3341
|
-
warning: "warning",
|
|
3342
|
-
info: "info",
|
|
3343
|
-
debug: "debug",
|
|
3344
|
-
error: "error",
|
|
3345
|
-
warn: "warn",
|
|
3346
|
-
table: "debug"
|
|
3347
|
-
};
|
|
3348
|
-
var MAGENTA = "\x1B[35m";
|
|
3349
|
-
var RESET = "\x1B[0m";
|
|
3350
|
-
function summarizeClientConsoleData(data) {
|
|
3351
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
3352
|
-
return null;
|
|
3353
|
-
}
|
|
3354
|
-
const record = data;
|
|
3355
|
-
const summary = {};
|
|
3356
|
-
if (record.data !== void 0) {
|
|
3357
|
-
summary.data = record.data;
|
|
3358
|
-
}
|
|
3359
|
-
const pathname = typeof record.page?.pathname === "string" ? record.page.pathname : void 0;
|
|
3360
|
-
const url = typeof record.page?.url === "string" ? record.page.url : void 0;
|
|
3361
|
-
if (pathname || url) {
|
|
3362
|
-
summary.page = pathname ?? url;
|
|
3363
|
-
}
|
|
3364
|
-
if (record.metadata !== void 0) {
|
|
3365
|
-
summary.metadata = record.metadata;
|
|
3366
|
-
}
|
|
3367
|
-
return Object.keys(summary).length > 0 ? summary : null;
|
|
184
|
+
function reclaimExpired(now) {
|
|
185
|
+
ensureReady();
|
|
186
|
+
const statement = adapter.prepare(
|
|
187
|
+
db,
|
|
188
|
+
'UPDATE connector_jobs SET state = ?, claimed_at = NULL, updated_at = ? WHERE state = ? AND claimed_at IS NOT NULL AND claimed_at <= ?'
|
|
189
|
+
);
|
|
190
|
+
adapter.run(statement, ['pending', now, 'claimed', now - CLAIM_LEASE_MS]);
|
|
3368
191
|
}
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
if (record.type === "http_request" || record.type === "http_error") {
|
|
3375
|
-
return { hidden: true };
|
|
3376
|
-
}
|
|
3377
|
-
if (record.type === "client_log") {
|
|
3378
|
-
const summary = summarizeClientConsoleData(data);
|
|
3379
|
-
if (!summary) {
|
|
3380
|
-
return { hidden: true };
|
|
3381
|
-
}
|
|
3382
|
-
return {
|
|
3383
|
-
hidden: false,
|
|
3384
|
-
value: summary
|
|
3385
|
-
};
|
|
192
|
+
|
|
193
|
+
function insertJobs(jobs) {
|
|
194
|
+
ensureReady();
|
|
195
|
+
if (!Array.isArray(jobs) || jobs.length === 0) {
|
|
196
|
+
return;
|
|
3386
197
|
}
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
colorize: true,
|
|
3394
|
-
translateTime: "SYS:HH:MM:ss",
|
|
3395
|
-
ignore: "pid,hostname,caller",
|
|
3396
|
-
customColors: {
|
|
3397
|
-
success: "green",
|
|
3398
|
-
critical: "red bold",
|
|
3399
|
-
info: "blue",
|
|
3400
|
-
warning: "yellow",
|
|
3401
|
-
error: "red",
|
|
3402
|
-
debug: "cyan",
|
|
3403
|
-
table: "cyan"
|
|
3404
|
-
},
|
|
3405
|
-
messageFormat: (log, messageKey) => {
|
|
3406
|
-
const message = String(log[messageKey] ?? "");
|
|
3407
|
-
const caller = typeof log.caller === "string" ? log.caller.trim() : "";
|
|
3408
|
-
if (!caller) {
|
|
3409
|
-
return message;
|
|
3410
|
-
}
|
|
3411
|
-
return `${message} ${MAGENTA}${caller}${RESET}`;
|
|
3412
|
-
}
|
|
3413
|
-
});
|
|
3414
|
-
return pino__default.default(
|
|
3415
|
-
{
|
|
3416
|
-
level: config.level,
|
|
3417
|
-
customLevels: CUSTOM_LEVELS
|
|
3418
|
-
},
|
|
3419
|
-
pretty
|
|
198
|
+
|
|
199
|
+
adapter.exec(db, 'BEGIN');
|
|
200
|
+
try {
|
|
201
|
+
const statement = adapter.prepare(
|
|
202
|
+
db,
|
|
203
|
+
'INSERT OR REPLACE INTO connector_jobs (id, connector_type, connector_target, operation, payload_json, attempt_count, max_attempts, next_attempt_at, state, last_error, created_at, updated_at, claimed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
3420
204
|
);
|
|
205
|
+
|
|
206
|
+
for (const job of jobs) {
|
|
207
|
+
adapter.run(statement, [
|
|
208
|
+
job.id,
|
|
209
|
+
job.connectorType,
|
|
210
|
+
normalizeConnectorTarget(job.connectorTarget),
|
|
211
|
+
job.operation,
|
|
212
|
+
job.payloadJson,
|
|
213
|
+
job.attemptCount,
|
|
214
|
+
job.maxAttempts,
|
|
215
|
+
job.nextAttemptAt,
|
|
216
|
+
job.state,
|
|
217
|
+
job.lastError ?? null,
|
|
218
|
+
job.createdAt,
|
|
219
|
+
job.updatedAt,
|
|
220
|
+
job.claimedAt ?? null,
|
|
221
|
+
]);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
adapter.exec(db, 'COMMIT');
|
|
225
|
+
} catch (error) {
|
|
226
|
+
adapter.exec(db, 'ROLLBACK');
|
|
227
|
+
throw error;
|
|
3421
228
|
}
|
|
3422
|
-
return pino__default.default({
|
|
3423
|
-
level: config.level,
|
|
3424
|
-
customLevels: CUSTOM_LEVELS
|
|
3425
|
-
});
|
|
3426
229
|
}
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
230
|
+
|
|
231
|
+
function claimDue(limit, now) {
|
|
232
|
+
ensureReady();
|
|
233
|
+
reclaimExpired(now);
|
|
234
|
+
|
|
235
|
+
const select = adapter.prepare(
|
|
236
|
+
db,
|
|
237
|
+
'SELECT * FROM connector_jobs WHERE state = ? AND next_attempt_at <= ? ORDER BY next_attempt_at ASC LIMIT ?'
|
|
238
|
+
);
|
|
239
|
+
const rows = adapter.all(select, ['pending', now, limit]);
|
|
240
|
+
|
|
241
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
242
|
+
return [];
|
|
3431
243
|
}
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
function getPostHogSender(logger2) {
|
|
3435
|
-
return getLoggerFactory(logger2).posthog;
|
|
3436
|
-
}
|
|
3437
|
-
function getBetterStackSender(logger2) {
|
|
3438
|
-
return getLoggerFactory(logger2).betterstack;
|
|
3439
|
-
}
|
|
3440
|
-
function tryGetPostHogSender(logger2) {
|
|
244
|
+
|
|
245
|
+
adapter.exec(db, 'BEGIN');
|
|
3441
246
|
try {
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
247
|
+
const update = adapter.prepare(
|
|
248
|
+
db,
|
|
249
|
+
'UPDATE connector_jobs SET state = ?, claimed_at = ?, updated_at = ? WHERE id = ?'
|
|
250
|
+
);
|
|
251
|
+
for (const row of rows) {
|
|
252
|
+
adapter.run(update, ['claimed', now, now, row.id]);
|
|
253
|
+
row.state = 'claimed';
|
|
254
|
+
row.claimed_at = now;
|
|
255
|
+
row.updated_at = now;
|
|
256
|
+
}
|
|
257
|
+
adapter.exec(db, 'COMMIT');
|
|
258
|
+
} catch (error) {
|
|
259
|
+
adapter.exec(db, 'ROLLBACK');
|
|
260
|
+
throw error;
|
|
3445
261
|
}
|
|
262
|
+
|
|
263
|
+
return rows.map((row) => ({
|
|
264
|
+
id: row.id,
|
|
265
|
+
connectorType: row.connector_type,
|
|
266
|
+
connectorTarget: row.connector_target ?? undefined,
|
|
267
|
+
operation: row.operation,
|
|
268
|
+
payloadJson: row.payload_json,
|
|
269
|
+
attemptCount: row.attempt_count,
|
|
270
|
+
maxAttempts: row.max_attempts,
|
|
271
|
+
nextAttemptAt: row.next_attempt_at,
|
|
272
|
+
state: row.state,
|
|
273
|
+
lastError: row.last_error ?? undefined,
|
|
274
|
+
createdAt: row.created_at,
|
|
275
|
+
updatedAt: row.updated_at,
|
|
276
|
+
claimedAt: row.claimed_at ?? undefined,
|
|
277
|
+
}));
|
|
3446
278
|
}
|
|
3447
|
-
|
|
279
|
+
|
|
280
|
+
function ack(ids) {
|
|
281
|
+
ensureReady();
|
|
282
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
adapter.exec(db, 'BEGIN');
|
|
3448
287
|
try {
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
288
|
+
const statement = adapter.prepare(db, 'DELETE FROM connector_jobs WHERE id = ?');
|
|
289
|
+
for (const id of ids) {
|
|
290
|
+
adapter.run(statement, [id]);
|
|
291
|
+
}
|
|
292
|
+
adapter.exec(db, 'COMMIT');
|
|
293
|
+
} catch (error) {
|
|
294
|
+
adapter.exec(db, 'ROLLBACK');
|
|
295
|
+
throw error;
|
|
3452
296
|
}
|
|
3453
297
|
}
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
return getLoggerFactory(logger2).otlp;
|
|
3459
|
-
}
|
|
3460
|
-
function attachLoggerInternals(target, source) {
|
|
3461
|
-
const factory = getLoggerFactory(source);
|
|
3462
|
-
Object.defineProperty(target, LOGGER_FACTORY, {
|
|
3463
|
-
value: factory,
|
|
3464
|
-
enumerable: false,
|
|
3465
|
-
configurable: false,
|
|
3466
|
-
writable: false
|
|
3467
|
-
});
|
|
3468
|
-
return target;
|
|
3469
|
-
}
|
|
3470
|
-
function createLoggerWithSource(logger2, source) {
|
|
3471
|
-
const factory = getLoggerFactory(logger2);
|
|
3472
|
-
return factory.create(source, factory.bindings);
|
|
3473
|
-
}
|
|
3474
|
-
function createStructuredLogForLogger(logger2, groupId, options = {}) {
|
|
3475
|
-
const factory = getLoggerFactory(logger2);
|
|
3476
|
-
return createStructuredLog(groupId, {
|
|
3477
|
-
initialFields: options.initialFields,
|
|
3478
|
-
resolveDefaultFields: () => ({
|
|
3479
|
-
...factory.bindings,
|
|
3480
|
-
...options.resolveDefaultFields?.() ?? {}
|
|
3481
|
-
}),
|
|
3482
|
-
write: (payload, message) => {
|
|
3483
|
-
factory.writeStructured(payload, message, "structured-flush");
|
|
3484
|
-
},
|
|
3485
|
-
onCreate: options.onCreate,
|
|
3486
|
-
onEmit: options.onEmit
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
|
-
function maybeSendToPostHog(posthog, record) {
|
|
3490
|
-
if (isClientLogRecord(record)) {
|
|
298
|
+
|
|
299
|
+
function reschedule(items, now) {
|
|
300
|
+
ensureReady();
|
|
301
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3491
302
|
return;
|
|
3492
303
|
}
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
304
|
+
|
|
305
|
+
adapter.exec(db, 'BEGIN');
|
|
306
|
+
try {
|
|
307
|
+
const statement = adapter.prepare(
|
|
308
|
+
db,
|
|
309
|
+
'UPDATE connector_jobs SET state = ?, attempt_count = ?, next_attempt_at = ?, last_error = ?, claimed_at = NULL, updated_at = ? WHERE id = ?'
|
|
310
|
+
);
|
|
311
|
+
for (const item of items) {
|
|
312
|
+
adapter.run(statement, [
|
|
313
|
+
'pending',
|
|
314
|
+
item.attemptCount,
|
|
315
|
+
item.nextAttemptAt,
|
|
316
|
+
item.lastError ?? null,
|
|
317
|
+
now,
|
|
318
|
+
item.id,
|
|
319
|
+
]);
|
|
3496
320
|
}
|
|
3497
|
-
|
|
321
|
+
adapter.exec(db, 'COMMIT');
|
|
322
|
+
} catch (error) {
|
|
323
|
+
adapter.exec(db, 'ROLLBACK');
|
|
324
|
+
throw error;
|
|
3498
325
|
}
|
|
3499
|
-
posthog.send(record, { source: "server", warnIfUnavailable: true });
|
|
3500
326
|
}
|
|
3501
|
-
|
|
3502
|
-
|
|
327
|
+
|
|
328
|
+
function deadLetter(items) {
|
|
329
|
+
ensureReady();
|
|
330
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3503
331
|
return;
|
|
3504
332
|
}
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
333
|
+
|
|
334
|
+
adapter.exec(db, 'BEGIN');
|
|
335
|
+
try {
|
|
336
|
+
const insert = adapter.prepare(
|
|
337
|
+
db,
|
|
338
|
+
'INSERT OR REPLACE INTO connector_dead_letters (id, connector_type, connector_target, operation, payload_json, attempt_count, max_attempts, last_error, first_enqueued_at, dead_lettered_at, last_attempt_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
339
|
+
);
|
|
340
|
+
const remove = adapter.prepare(db, 'DELETE FROM connector_jobs WHERE id = ?');
|
|
341
|
+
|
|
342
|
+
for (const item of items) {
|
|
343
|
+
adapter.run(insert, [
|
|
344
|
+
item.id,
|
|
345
|
+
item.connectorType,
|
|
346
|
+
normalizeConnectorTarget(item.connectorTarget),
|
|
347
|
+
item.operation,
|
|
348
|
+
item.payloadJson,
|
|
349
|
+
item.attemptCount,
|
|
350
|
+
item.maxAttempts,
|
|
351
|
+
item.lastError ?? null,
|
|
352
|
+
item.firstEnqueuedAt,
|
|
353
|
+
item.deadLetteredAt,
|
|
354
|
+
item.lastAttemptAt,
|
|
355
|
+
]);
|
|
356
|
+
adapter.run(remove, [item.id]);
|
|
3508
357
|
}
|
|
3509
|
-
|
|
358
|
+
|
|
359
|
+
adapter.exec(db, 'COMMIT');
|
|
360
|
+
} catch (error) {
|
|
361
|
+
adapter.exec(db, 'ROLLBACK');
|
|
362
|
+
throw error;
|
|
3510
363
|
}
|
|
3511
|
-
betterstack.send(record, { source: "server", warnIfUnavailable: true });
|
|
3512
364
|
}
|
|
3513
|
-
|
|
3514
|
-
|
|
365
|
+
|
|
366
|
+
function markSuccess(items) {
|
|
367
|
+
ensureReady();
|
|
368
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3515
369
|
return;
|
|
3516
370
|
}
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
371
|
+
|
|
372
|
+
adapter.exec(db, 'BEGIN');
|
|
373
|
+
try {
|
|
374
|
+
for (const item of items) {
|
|
375
|
+
updateConnectorDeliveryStatus(item, true);
|
|
3520
376
|
}
|
|
3521
|
-
|
|
377
|
+
adapter.exec(db, 'COMMIT');
|
|
378
|
+
} catch (error) {
|
|
379
|
+
adapter.exec(db, 'ROLLBACK');
|
|
380
|
+
throw error;
|
|
3522
381
|
}
|
|
3523
|
-
sentry.send(record, { source: "server", warnIfUnavailable: true });
|
|
3524
382
|
}
|
|
3525
|
-
|
|
3526
|
-
|
|
383
|
+
|
|
384
|
+
function markFailure(items) {
|
|
385
|
+
ensureReady();
|
|
386
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
3527
387
|
return;
|
|
3528
388
|
}
|
|
3529
|
-
|
|
3530
|
-
|
|
389
|
+
|
|
390
|
+
adapter.exec(db, 'BEGIN');
|
|
391
|
+
try {
|
|
392
|
+
for (const item of items) {
|
|
393
|
+
updateConnectorDeliveryStatus(item, false);
|
|
394
|
+
}
|
|
395
|
+
adapter.exec(db, 'COMMIT');
|
|
396
|
+
} catch (error) {
|
|
397
|
+
adapter.exec(db, 'ROLLBACK');
|
|
398
|
+
throw error;
|
|
3531
399
|
}
|
|
3532
400
|
}
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
401
|
+
|
|
402
|
+
function getStatusSummary() {
|
|
403
|
+
ensureReady();
|
|
404
|
+
const rows = [];
|
|
405
|
+
const byKey = new Map();
|
|
406
|
+
|
|
407
|
+
const statusRows = adapter.all(
|
|
408
|
+
adapter.prepare(
|
|
409
|
+
db,
|
|
410
|
+
'SELECT connector_type, connector_target, last_success_at, last_failure_at, last_error, updated_at FROM connector_delivery_status'
|
|
411
|
+
),
|
|
412
|
+
[]
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
for (const row of statusRows) {
|
|
416
|
+
const key = row.connector_type + ':' + (row.connector_target ?? '');
|
|
417
|
+
const item = {
|
|
418
|
+
connectorType: row.connector_type,
|
|
419
|
+
connectorTarget: row.connector_target ?? undefined,
|
|
420
|
+
pendingCount: 0,
|
|
421
|
+
deadLetterCount: 0,
|
|
422
|
+
lastSuccessAt: row.last_success_at ?? undefined,
|
|
423
|
+
lastFailureAt: row.last_failure_at ?? undefined,
|
|
424
|
+
lastError: row.last_error ?? undefined,
|
|
425
|
+
updatedAt: row.updated_at ?? undefined,
|
|
3543
426
|
};
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
payload.data = consoleData.value;
|
|
3547
|
-
}
|
|
3548
|
-
const consoleMethod = CONSOLE_LEVELS[level];
|
|
3549
|
-
const boundLogger = rawLogger;
|
|
3550
|
-
const logMethod = boundLogger[consoleMethod] ?? boundLogger.info ?? ((_payload, _message) => {
|
|
3551
|
-
});
|
|
3552
|
-
logMethod.call(
|
|
3553
|
-
rawLogger,
|
|
3554
|
-
payload,
|
|
3555
|
-
consoleMessage
|
|
3556
|
-
);
|
|
3557
|
-
sink.write(record);
|
|
3558
|
-
maybeSendToBetterStack(betterstack, record);
|
|
3559
|
-
maybeSendToPostHog(posthog, record);
|
|
3560
|
-
maybeSendToSentry(sentry, record);
|
|
3561
|
-
maybeSendToOTLP(otlp, record);
|
|
3562
|
-
};
|
|
3563
|
-
const writeStructuredRecord = (payload, message, writeSource = "structured-flush") => {
|
|
3564
|
-
const level = resolveStructuredWriteLevel(payload.level);
|
|
3565
|
-
const record = buildStructuredRecord(level, message, payload, bindings);
|
|
3566
|
-
const consoleMethod = CONSOLE_LEVELS[level];
|
|
3567
|
-
const boundLogger = rawLogger;
|
|
3568
|
-
const logMethod = boundLogger[consoleMethod] ?? boundLogger.info ?? ((_payload, _message) => {
|
|
3569
|
-
});
|
|
3570
|
-
logMethod.call(
|
|
3571
|
-
rawLogger,
|
|
3572
|
-
{
|
|
3573
|
-
caller: record.caller,
|
|
3574
|
-
...payload
|
|
3575
|
-
},
|
|
3576
|
-
message
|
|
3577
|
-
);
|
|
3578
|
-
if (writeSource !== "root" || !shouldDropRootLogWrite()) {
|
|
3579
|
-
sink.write(record);
|
|
3580
|
-
}
|
|
3581
|
-
maybeSendToBetterStack(betterstack, record);
|
|
3582
|
-
maybeSendToPostHog(posthog, record);
|
|
3583
|
-
maybeSendToSentry(sentry, record);
|
|
3584
|
-
maybeSendToOTLP(otlp, record);
|
|
3585
|
-
};
|
|
3586
|
-
const logger2 = {
|
|
3587
|
-
success: (message, ...args) => {
|
|
3588
|
-
writeRecord("success", message, args);
|
|
3589
|
-
},
|
|
3590
|
-
critical: (message, ...args) => {
|
|
3591
|
-
writeRecord("critical", message, args);
|
|
3592
|
-
},
|
|
3593
|
-
warning: (message, ...args) => {
|
|
3594
|
-
writeRecord("warning", message, args);
|
|
3595
|
-
},
|
|
3596
|
-
info: (message, ...args) => {
|
|
3597
|
-
writeRecord("info", message, args);
|
|
3598
|
-
},
|
|
3599
|
-
debug: (message, ...args) => {
|
|
3600
|
-
writeRecord("debug", message, args);
|
|
3601
|
-
},
|
|
3602
|
-
error: (message, ...args) => {
|
|
3603
|
-
writeRecord("error", message, args);
|
|
3604
|
-
},
|
|
3605
|
-
warn: (message, ...args) => {
|
|
3606
|
-
writeRecord("warn", message, args);
|
|
3607
|
-
},
|
|
3608
|
-
table: (message, data) => {
|
|
3609
|
-
if (data && typeof data === "object" && runtime.env.get("NODE_ENV") !== "production") {
|
|
3610
|
-
console.log("TABLE:", message);
|
|
3611
|
-
console.table(data);
|
|
3612
|
-
}
|
|
3613
|
-
writeRecord("table", message, data === void 0 ? [] : [data]);
|
|
3614
|
-
},
|
|
3615
|
-
flush: () => sink.flush(),
|
|
3616
|
-
shutdown: () => sink.shutdown(),
|
|
3617
|
-
createStructuredLog: (groupId, initial) => {
|
|
3618
|
-
return createStructuredLogForLogger(logger2, groupId, {
|
|
3619
|
-
initialFields: initial
|
|
3620
|
-
});
|
|
3621
|
-
},
|
|
3622
|
-
child: (childBindings) => {
|
|
3623
|
-
const mergedBindings = { ...bindings, ...childBindings };
|
|
3624
|
-
return createLoggerInstance(
|
|
3625
|
-
rootRawLogger,
|
|
3626
|
-
sink,
|
|
3627
|
-
betterstack,
|
|
3628
|
-
posthog,
|
|
3629
|
-
sentry,
|
|
3630
|
-
otlp,
|
|
3631
|
-
mergedBindings,
|
|
3632
|
-
source
|
|
3633
|
-
);
|
|
3634
|
-
},
|
|
3635
|
-
[LOGGER_FACTORY]: {
|
|
3636
|
-
bindings,
|
|
3637
|
-
betterstack,
|
|
3638
|
-
posthog,
|
|
3639
|
-
sentry,
|
|
3640
|
-
otlp,
|
|
3641
|
-
sink,
|
|
3642
|
-
create: (nextSource, nextBindings = bindings) => {
|
|
3643
|
-
return createLoggerInstance(
|
|
3644
|
-
rootRawLogger,
|
|
3645
|
-
sink,
|
|
3646
|
-
betterstack,
|
|
3647
|
-
posthog,
|
|
3648
|
-
sentry,
|
|
3649
|
-
otlp,
|
|
3650
|
-
nextBindings,
|
|
3651
|
-
nextSource
|
|
3652
|
-
);
|
|
3653
|
-
},
|
|
3654
|
-
writeStructured: (payload, message, nextSource = "structured-flush") => {
|
|
3655
|
-
writeStructuredRecord(payload, message, nextSource);
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
};
|
|
3659
|
-
return logger2;
|
|
3660
|
-
}
|
|
3661
|
-
var loggerInstance = null;
|
|
3662
|
-
function createBaseLogger(config) {
|
|
3663
|
-
if (config === void 0 && loggerInstance) {
|
|
3664
|
-
return loggerInstance;
|
|
427
|
+
byKey.set(key, item);
|
|
428
|
+
rows.push(item);
|
|
3665
429
|
}
|
|
3666
|
-
|
|
3667
|
-
const
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
const instance = createLoggerInstance(
|
|
3674
|
-
rawLogger,
|
|
3675
|
-
sink,
|
|
3676
|
-
betterstack,
|
|
3677
|
-
posthog,
|
|
3678
|
-
sentry,
|
|
3679
|
-
otlp
|
|
430
|
+
|
|
431
|
+
const pendingRows = adapter.all(
|
|
432
|
+
adapter.prepare(
|
|
433
|
+
db,
|
|
434
|
+
'SELECT connector_type, connector_target, COUNT(*) AS count FROM connector_jobs WHERE state = ? GROUP BY connector_type, connector_target'
|
|
435
|
+
),
|
|
436
|
+
['pending']
|
|
3680
437
|
);
|
|
3681
|
-
|
|
3682
|
-
|
|
438
|
+
|
|
439
|
+
for (const row of pendingRows) {
|
|
440
|
+
const key = row.connector_type + ':' + (row.connector_target ?? '');
|
|
441
|
+
const item = byKey.get(key) ?? {
|
|
442
|
+
connectorType: row.connector_type,
|
|
443
|
+
connectorTarget: row.connector_target ?? undefined,
|
|
444
|
+
pendingCount: 0,
|
|
445
|
+
deadLetterCount: 0,
|
|
446
|
+
};
|
|
447
|
+
item.pendingCount = Number(row.count ?? 0);
|
|
448
|
+
if (!byKey.has(key)) {
|
|
449
|
+
byKey.set(key, item);
|
|
450
|
+
rows.push(item);
|
|
451
|
+
}
|
|
3683
452
|
}
|
|
3684
|
-
return instance;
|
|
3685
|
-
}
|
|
3686
|
-
createBaseLogger();
|
|
3687
453
|
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
}
|
|
3695
|
-
function resolveClientLoggingConfig(clientLogging, defaultClientLogging) {
|
|
3696
|
-
const defaultPath = normalizeEndpointPath(
|
|
3697
|
-
defaultClientLogging?.path ?? DEFAULT_CLIENT_LOG_ENDPOINT
|
|
454
|
+
const deadLetterRows = adapter.all(
|
|
455
|
+
adapter.prepare(
|
|
456
|
+
db,
|
|
457
|
+
'SELECT connector_type, connector_target, COUNT(*) AS count FROM connector_dead_letters GROUP BY connector_type, connector_target'
|
|
458
|
+
),
|
|
459
|
+
[]
|
|
3698
460
|
);
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
return {
|
|
3708
|
-
path: defaultPath
|
|
461
|
+
|
|
462
|
+
for (const row of deadLetterRows) {
|
|
463
|
+
const key = row.connector_type + ':' + (row.connector_target ?? '');
|
|
464
|
+
const item = byKey.get(key) ?? {
|
|
465
|
+
connectorType: row.connector_type,
|
|
466
|
+
connectorTarget: row.connector_target ?? undefined,
|
|
467
|
+
pendingCount: 0,
|
|
468
|
+
deadLetterCount: 0,
|
|
3709
469
|
};
|
|
470
|
+
item.deadLetterCount = Number(row.count ?? 0);
|
|
471
|
+
if (!byKey.has(key)) {
|
|
472
|
+
byKey.set(key, item);
|
|
473
|
+
rows.push(item);
|
|
474
|
+
}
|
|
3710
475
|
}
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
}
|
|
3717
|
-
function resolveServerLogger(config = {}, loggerOverride) {
|
|
3718
|
-
const resolvedConfig = resolveConfig({
|
|
3719
|
-
...config.level !== void 0 ? { level: config.level } : {},
|
|
3720
|
-
...config.pretty !== void 0 ? { pretty: config.pretty } : {},
|
|
3721
|
-
...config.destination !== void 0 ? { destination: config.destination } : {},
|
|
3722
|
-
...config.logDir !== void 0 ? { logDir: config.logDir } : {},
|
|
3723
|
-
...config.file !== void 0 ? { file: config.file } : {},
|
|
3724
|
-
...config.database !== void 0 ? { database: config.database } : {},
|
|
3725
|
-
...config.connectors !== void 0 ? { connectors: config.connectors } : {}
|
|
3726
|
-
});
|
|
3727
|
-
const {
|
|
3728
|
-
level = resolvedConfig.level,
|
|
3729
|
-
pretty = resolvedConfig.pretty,
|
|
3730
|
-
destination = resolvedConfig.destination,
|
|
3731
|
-
logDir = resolvedConfig.logDir,
|
|
3732
|
-
file = resolvedConfig.file,
|
|
3733
|
-
database = resolvedConfig.database,
|
|
3734
|
-
autoLogging = true,
|
|
3735
|
-
customProps,
|
|
3736
|
-
logErrors = true,
|
|
3737
|
-
ignorePaths,
|
|
3738
|
-
clientLogging,
|
|
3739
|
-
connectors
|
|
3740
|
-
} = config;
|
|
3741
|
-
const logger2 = createBaseLogger({
|
|
3742
|
-
level,
|
|
3743
|
-
pretty,
|
|
3744
|
-
destination,
|
|
3745
|
-
logDir,
|
|
3746
|
-
file,
|
|
3747
|
-
database,
|
|
3748
|
-
connectors
|
|
476
|
+
|
|
477
|
+
return rows.sort((left, right) => {
|
|
478
|
+
const leftKey = left.connectorType + ':' + (left.connectorTarget ?? '');
|
|
479
|
+
const rightKey = right.connectorType + ':' + (right.connectorTarget ?? '');
|
|
480
|
+
return leftKey.localeCompare(rightKey);
|
|
3749
481
|
});
|
|
3750
|
-
const resolvedClientLogging = resolveClientLoggingConfig(
|
|
3751
|
-
clientLogging,
|
|
3752
|
-
resolvedConfig.clientLogging
|
|
3753
|
-
);
|
|
3754
|
-
const ingestionPath = resolvedClientLogging?.path ?? DEFAULT_CLIENT_LOG_ENDPOINT;
|
|
3755
|
-
const resolvedIgnorePaths = resolvedClientLogging ? Array.from(/* @__PURE__ */ new Set([...ignorePaths ?? [], ingestionPath])) : ignorePaths;
|
|
3756
|
-
return {
|
|
3757
|
-
logger: logger2,
|
|
3758
|
-
betterstack: getBetterStackSender(logger2),
|
|
3759
|
-
posthog: getPostHogSender(logger2),
|
|
3760
|
-
sentry: getSentrySender(logger2),
|
|
3761
|
-
otlp: getOtlpRegistry(logger2),
|
|
3762
|
-
resolvedConfig,
|
|
3763
|
-
level,
|
|
3764
|
-
pretty,
|
|
3765
|
-
logDir,
|
|
3766
|
-
file,
|
|
3767
|
-
autoLogging,
|
|
3768
|
-
customProps,
|
|
3769
|
-
logErrors,
|
|
3770
|
-
resolvedIgnorePaths,
|
|
3771
|
-
resolvedClientLogging,
|
|
3772
|
-
ingestionPath
|
|
3773
|
-
};
|
|
3774
|
-
}
|
|
3775
|
-
function shouldSkipAutoLogging(config, ctx, path3) {
|
|
3776
|
-
if (config.autoLogging === false) {
|
|
3777
|
-
return true;
|
|
3778
|
-
}
|
|
3779
|
-
if (typeof config.autoLogging === "object" && config.autoLogging.ignore?.(ctx)) {
|
|
3780
|
-
return true;
|
|
3781
|
-
}
|
|
3782
|
-
return shouldIgnorePath(path3, config.resolvedIgnorePaths);
|
|
3783
482
|
}
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
483
|
+
|
|
484
|
+
function listDeadLetters(limit, offset, connectorType, connectorTarget) {
|
|
485
|
+
ensureReady();
|
|
486
|
+
const clauses = [];
|
|
487
|
+
const params = [];
|
|
488
|
+
|
|
489
|
+
if (typeof connectorType === 'string' && connectorType.length > 0) {
|
|
490
|
+
clauses.push('connector_type = ?');
|
|
491
|
+
params.push(connectorType);
|
|
3787
492
|
}
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
}
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
request,
|
|
3796
|
-
"http_request",
|
|
3797
|
-
path3,
|
|
3798
|
-
statusCode,
|
|
3799
|
-
responseTime,
|
|
3800
|
-
additionalProps
|
|
3801
|
-
);
|
|
3802
|
-
if (level === "info") {
|
|
3803
|
-
logger2.info(
|
|
3804
|
-
buildInfoLogMessage(request.method, statusCode, path3, responseTime),
|
|
3805
|
-
requestLogData
|
|
3806
|
-
);
|
|
3807
|
-
} else {
|
|
3808
|
-
logger2.info(
|
|
3809
|
-
buildVerboseLogMessage(request.method, statusCode, path3, responseTime),
|
|
3810
|
-
requestLogData
|
|
3811
|
-
);
|
|
3812
|
-
if (Object.keys(additionalProps).length > 0) {
|
|
3813
|
-
logger2.debug("Request context", additionalProps);
|
|
493
|
+
|
|
494
|
+
if (connectorTarget !== undefined) {
|
|
495
|
+
if (connectorTarget === null || connectorTarget === '') {
|
|
496
|
+
clauses.push('connector_target IS NULL');
|
|
497
|
+
} else {
|
|
498
|
+
clauses.push('connector_target = ?');
|
|
499
|
+
params.push(connectorTarget);
|
|
3814
500
|
}
|
|
3815
501
|
}
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
code: error?.code,
|
|
3829
|
-
why: error?.why,
|
|
3830
|
-
fix: error?.fix,
|
|
3831
|
-
link: error?.link,
|
|
3832
|
-
details: error?.details,
|
|
3833
|
-
...additionalProps
|
|
3834
|
-
}
|
|
502
|
+
|
|
503
|
+
const whereSql = clauses.length > 0 ? ' WHERE ' + clauses.join(' AND ') : '';
|
|
504
|
+
const countRow = adapter.all(
|
|
505
|
+
adapter.prepare(db, 'SELECT COUNT(*) AS count FROM connector_dead_letters' + whereSql),
|
|
506
|
+
params
|
|
507
|
+
)[0];
|
|
508
|
+
const rows = adapter.all(
|
|
509
|
+
adapter.prepare(
|
|
510
|
+
db,
|
|
511
|
+
'SELECT * FROM connector_dead_letters' + whereSql + ' ORDER BY dead_lettered_at DESC LIMIT ? OFFSET ?'
|
|
512
|
+
),
|
|
513
|
+
[...params, limit, offset]
|
|
3835
514
|
);
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
}
|
|
3860
|
-
)
|
|
3861
|
-
});
|
|
515
|
+
|
|
516
|
+
return {
|
|
517
|
+
items: rows.map((row) => ({
|
|
518
|
+
id: row.id,
|
|
519
|
+
connectorType: row.connector_type,
|
|
520
|
+
connectorTarget: row.connector_target ?? undefined,
|
|
521
|
+
operation: row.operation,
|
|
522
|
+
payloadJson: row.payload_json,
|
|
523
|
+
attemptCount: row.attempt_count,
|
|
524
|
+
maxAttempts: row.max_attempts,
|
|
525
|
+
lastError: row.last_error ?? undefined,
|
|
526
|
+
firstEnqueuedAt: row.first_enqueued_at,
|
|
527
|
+
deadLetteredAt: row.dead_lettered_at,
|
|
528
|
+
lastAttemptAt: row.last_attempt_at,
|
|
529
|
+
})),
|
|
530
|
+
total: Number(countRow?.count ?? 0),
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function retryDeadLetters(ids, now) {
|
|
535
|
+
ensureReady();
|
|
536
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
537
|
+
return 0;
|
|
3862
538
|
}
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
539
|
+
|
|
540
|
+
adapter.exec(db, 'BEGIN');
|
|
541
|
+
try {
|
|
542
|
+
const select = adapter.prepare(db, 'SELECT * FROM connector_dead_letters WHERE id = ?');
|
|
543
|
+
const insert = adapter.prepare(
|
|
544
|
+
db,
|
|
545
|
+
'INSERT OR REPLACE INTO connector_jobs (id, connector_type, connector_target, operation, payload_json, attempt_count, max_attempts, next_attempt_at, state, last_error, created_at, updated_at, claimed_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
|
546
|
+
);
|
|
547
|
+
const remove = adapter.prepare(db, 'DELETE FROM connector_dead_letters WHERE id = ?');
|
|
548
|
+
let count = 0;
|
|
549
|
+
|
|
550
|
+
for (const id of ids) {
|
|
551
|
+
const row = adapter.all(select, [id])[0];
|
|
552
|
+
if (!row) {
|
|
553
|
+
continue;
|
|
3875
554
|
}
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
555
|
+
|
|
556
|
+
adapter.run(insert, [
|
|
557
|
+
row.id,
|
|
558
|
+
row.connector_type,
|
|
559
|
+
row.connector_target ?? null,
|
|
560
|
+
row.operation,
|
|
561
|
+
row.payload_json,
|
|
562
|
+
0,
|
|
563
|
+
row.max_attempts,
|
|
564
|
+
now,
|
|
565
|
+
'pending',
|
|
566
|
+
null,
|
|
567
|
+
row.first_enqueued_at,
|
|
568
|
+
now,
|
|
569
|
+
null,
|
|
570
|
+
]);
|
|
571
|
+
adapter.run(remove, [id]);
|
|
572
|
+
count += 1;
|
|
3884
573
|
}
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
}
|
|
3892
|
-
function getClientLogMethod(logger2, level) {
|
|
3893
|
-
switch (level) {
|
|
3894
|
-
case "debug":
|
|
3895
|
-
return logger2.debug;
|
|
3896
|
-
case "info":
|
|
3897
|
-
return logger2.info;
|
|
3898
|
-
case "warning":
|
|
3899
|
-
return logger2.warning;
|
|
3900
|
-
case "error":
|
|
3901
|
-
return logger2.error;
|
|
3902
|
-
case "critical":
|
|
3903
|
-
return logger2.critical;
|
|
3904
|
-
case "success":
|
|
3905
|
-
return logger2.success;
|
|
574
|
+
|
|
575
|
+
adapter.exec(db, 'COMMIT');
|
|
576
|
+
return count;
|
|
577
|
+
} catch (error) {
|
|
578
|
+
adapter.exec(db, 'ROLLBACK');
|
|
579
|
+
throw error;
|
|
3906
580
|
}
|
|
3907
581
|
}
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
582
|
+
|
|
583
|
+
function clearDeadLetters(ids) {
|
|
584
|
+
ensureReady();
|
|
585
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
586
|
+
return 0;
|
|
3912
587
|
}
|
|
3913
|
-
|
|
588
|
+
|
|
589
|
+
adapter.exec(db, 'BEGIN');
|
|
3914
590
|
try {
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
const isAllowed = config.resolvedClientLogging.validate ? await config.resolvedClientLogging.validate(ctx, payload) : true;
|
|
3923
|
-
if (!isAllowed) {
|
|
3924
|
-
return { status: 403 };
|
|
3925
|
-
}
|
|
3926
|
-
const serverContext = config.resolvedClientLogging.enrich ? await config.resolvedClientLogging.enrich(ctx, payload) : void 0;
|
|
3927
|
-
const structuredPayload = {
|
|
3928
|
-
...payload,
|
|
3929
|
-
receivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3930
|
-
delivery: buildClientDetails(request, deliveryPath ?? extractPathname(request.url))
|
|
3931
|
-
};
|
|
3932
|
-
if (serverContext !== void 0) {
|
|
3933
|
-
structuredPayload.serverContext = serverContext;
|
|
3934
|
-
}
|
|
3935
|
-
if (payload.level === "table") {
|
|
3936
|
-
config.logger.table(`[client] ${payload.message}`, structuredPayload);
|
|
3937
|
-
} else {
|
|
3938
|
-
const logMethod = getClientLogMethod(config.logger, payload.level);
|
|
3939
|
-
logMethod(`[client] ${payload.message}`, structuredPayload);
|
|
3940
|
-
}
|
|
3941
|
-
const headers = {};
|
|
3942
|
-
if (payload.connector === "betterstack") {
|
|
3943
|
-
headers["x-blyp-betterstack-status"] = config.betterstack.ready ? "enabled" : "missing";
|
|
3944
|
-
if (config.betterstack.ready) {
|
|
3945
|
-
const forwardedRecord = {
|
|
3946
|
-
timestamp: structuredPayload.receivedAt,
|
|
3947
|
-
level: payload.level,
|
|
3948
|
-
message: `[client] ${payload.message}`,
|
|
3949
|
-
data: structuredPayload
|
|
3950
|
-
};
|
|
3951
|
-
config.betterstack.send(forwardedRecord, {
|
|
3952
|
-
source: "client"
|
|
3953
|
-
});
|
|
3954
|
-
if ((payload.level === "error" || payload.level === "critical") && config.betterstack.shouldAutoCaptureExceptions()) {
|
|
3955
|
-
const clientErrorCandidate = payload.data && typeof payload.data === "object" && !Array.isArray(payload.data) && typeof payload.data.message === "string" ? payload.data : payload.message;
|
|
3956
|
-
config.betterstack.captureException(clientErrorCandidate, {
|
|
3957
|
-
source: "client",
|
|
3958
|
-
warnIfUnavailable: true,
|
|
3959
|
-
context: {
|
|
3960
|
-
sessionId: payload.session.sessionId,
|
|
3961
|
-
pageUrl: payload.page.url,
|
|
3962
|
-
pagePath: payload.page.pathname,
|
|
3963
|
-
metadata: payload.metadata,
|
|
3964
|
-
payload: structuredPayload
|
|
3965
|
-
}
|
|
3966
|
-
});
|
|
3967
|
-
}
|
|
3968
|
-
}
|
|
3969
|
-
} else if (payload.connector === "posthog") {
|
|
3970
|
-
headers["x-blyp-posthog-status"] = config.posthog.ready ? "enabled" : "missing";
|
|
3971
|
-
if (config.posthog.ready) {
|
|
3972
|
-
const forwardedRecord = {
|
|
3973
|
-
timestamp: structuredPayload.receivedAt,
|
|
3974
|
-
level: payload.level,
|
|
3975
|
-
message: `[client] ${payload.message}`,
|
|
3976
|
-
data: structuredPayload
|
|
3977
|
-
};
|
|
3978
|
-
config.posthog.send(forwardedRecord, {
|
|
3979
|
-
source: "client"
|
|
3980
|
-
});
|
|
3981
|
-
if ((payload.level === "error" || payload.level === "critical") && config.posthog.shouldAutoCaptureExceptions()) {
|
|
3982
|
-
const metadata = structuredPayload.metadata;
|
|
3983
|
-
const posthogDistinctId = metadata && typeof metadata === "object" && !Array.isArray(metadata) && typeof metadata.posthogDistinctId === "string" && metadata.posthogDistinctId ? String(metadata.posthogDistinctId) : void 0;
|
|
3984
|
-
const clientErrorCandidate = payload.data && typeof payload.data === "object" && !Array.isArray(payload.data) && typeof payload.data.message === "string" ? payload.data : payload.message;
|
|
3985
|
-
config.posthog.captureException(clientErrorCandidate, {
|
|
3986
|
-
source: "client",
|
|
3987
|
-
warnIfUnavailable: true,
|
|
3988
|
-
distinctId: posthogDistinctId,
|
|
3989
|
-
properties: buildPostHogExceptionProperties(forwardedRecord, "client", {
|
|
3990
|
-
$session_id: payload.session.sessionId,
|
|
3991
|
-
$current_url: payload.page.url,
|
|
3992
|
-
$request_path: payload.page.pathname,
|
|
3993
|
-
"client.runtime": payload.device?.runtime,
|
|
3994
|
-
"client.metadata": payload.metadata
|
|
3995
|
-
})
|
|
3996
|
-
});
|
|
591
|
+
const select = adapter.prepare(db, 'SELECT id FROM connector_dead_letters WHERE id = ?');
|
|
592
|
+
const remove = adapter.prepare(db, 'DELETE FROM connector_dead_letters WHERE id = ?');
|
|
593
|
+
let count = 0;
|
|
594
|
+
for (const id of ids) {
|
|
595
|
+
const row = adapter.all(select, [id])[0];
|
|
596
|
+
if (!row) {
|
|
597
|
+
continue;
|
|
3997
598
|
}
|
|
599
|
+
adapter.run(remove, [id]);
|
|
600
|
+
count += 1;
|
|
3998
601
|
}
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
level: payload.level,
|
|
4005
|
-
message: `[client] ${payload.message}`,
|
|
4006
|
-
data: structuredPayload
|
|
4007
|
-
}, {
|
|
4008
|
-
source: "client"
|
|
4009
|
-
});
|
|
4010
|
-
}
|
|
4011
|
-
} else if (payload.connector?.type === "otlp") {
|
|
4012
|
-
const sender = config.otlp.get(payload.connector.name);
|
|
4013
|
-
headers["x-blyp-otlp-status"] = sender.ready ? "enabled" : "missing";
|
|
4014
|
-
if (sender.ready) {
|
|
4015
|
-
sender.send({
|
|
4016
|
-
timestamp: structuredPayload.receivedAt,
|
|
4017
|
-
level: payload.level,
|
|
4018
|
-
message: `[client] ${payload.message}`,
|
|
4019
|
-
data: structuredPayload
|
|
4020
|
-
}, {
|
|
4021
|
-
source: "client"
|
|
4022
|
-
});
|
|
4023
|
-
}
|
|
4024
|
-
}
|
|
4025
|
-
return Object.keys(headers).length > 0 ? { status: 204, headers } : { status: 204 };
|
|
4026
|
-
}
|
|
4027
|
-
function buildAbsoluteUrl(path3, headers) {
|
|
4028
|
-
if (path3.startsWith("http://") || path3.startsWith("https://")) {
|
|
4029
|
-
return path3;
|
|
602
|
+
adapter.exec(db, 'COMMIT');
|
|
603
|
+
return count;
|
|
604
|
+
} catch (error) {
|
|
605
|
+
adapter.exec(db, 'ROLLBACK');
|
|
606
|
+
throw error;
|
|
4030
607
|
}
|
|
4031
|
-
const protocol = getHeaderValue(headers, "x-forwarded-proto") ?? "http";
|
|
4032
|
-
const host = getHeaderValue(headers, "host") ?? "localhost";
|
|
4033
|
-
return `${protocol}://${host}${path3.startsWith("/") ? path3 : `/${path3}`}`;
|
|
4034
608
|
}
|
|
4035
609
|
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
const
|
|
4039
|
-
const
|
|
4040
|
-
|
|
4041
|
-
createStructuredLog: (groupId, initial) => {
|
|
4042
|
-
return createStructuredLogForLogger(requestScopedLogger, groupId, {
|
|
4043
|
-
initialFields: initial,
|
|
4044
|
-
resolveDefaultFields: options.resolveStructuredFields,
|
|
4045
|
-
onCreate: () => {
|
|
4046
|
-
markStructuredCollectorActive();
|
|
4047
|
-
},
|
|
4048
|
-
onEmit: () => {
|
|
4049
|
-
markStructuredLogEmitted();
|
|
4050
|
-
options.onStructuredEmit?.();
|
|
4051
|
-
}
|
|
4052
|
-
});
|
|
4053
|
-
},
|
|
4054
|
-
child(bindings) {
|
|
4055
|
-
return createRequestScopedLogger(scopedLogger.child(bindings), options);
|
|
4056
|
-
}
|
|
4057
|
-
}, scopedLogger);
|
|
4058
|
-
setActiveRequestLogger(requestScopedLogger);
|
|
4059
|
-
return requestScopedLogger;
|
|
610
|
+
function count() {
|
|
611
|
+
ensureReady();
|
|
612
|
+
const statement = adapter.prepare(db, 'SELECT COUNT(*) as count FROM connector_jobs');
|
|
613
|
+
const rows = adapter.all(statement, []);
|
|
614
|
+
return Number(rows[0]?.count ?? 0);
|
|
4060
615
|
}
|
|
4061
616
|
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
});
|
|
4075
|
-
fastify.decorateRequest("blypStartTime", void 0);
|
|
4076
|
-
fastify.decorateRequest("blypError", void 0);
|
|
4077
|
-
fastify.decorateRequest("blypStructuredLogEmitted", void 0);
|
|
4078
|
-
fastify.addHook("onRequest", async (request) => {
|
|
4079
|
-
enterRequestContext();
|
|
4080
|
-
request.blypStartTime = performance.now();
|
|
4081
|
-
request.blypError = void 0;
|
|
4082
|
-
request.blypStructuredLogEmitted = false;
|
|
4083
|
-
});
|
|
4084
|
-
fastify.addHook("preHandler", async (request) => {
|
|
4085
|
-
request.blypLog = createRequestScopedLogger(shared.logger, {
|
|
4086
|
-
resolveStructuredFields: () => ({
|
|
4087
|
-
method: request.method,
|
|
4088
|
-
path: extractPathname(request.url),
|
|
4089
|
-
...resolveAdditionalProps(shared, {
|
|
4090
|
-
request,
|
|
4091
|
-
reply: {},
|
|
4092
|
-
error: request.blypError
|
|
4093
|
-
})
|
|
4094
|
-
}),
|
|
4095
|
-
onStructuredEmit: () => {
|
|
4096
|
-
request.blypStructuredLogEmitted = true;
|
|
4097
|
-
}
|
|
4098
|
-
});
|
|
4099
|
-
});
|
|
4100
|
-
fastify.addHook("onError", async (request, _reply, error) => {
|
|
4101
|
-
request.blypError = error;
|
|
4102
|
-
});
|
|
4103
|
-
fastify.addHook("onResponse", async (request, reply) => {
|
|
4104
|
-
const path3 = extractPathname(request.url);
|
|
4105
|
-
const requestLike = createRequestLike(
|
|
4106
|
-
request.method,
|
|
4107
|
-
buildAbsoluteUrl(request.url, request.headers),
|
|
4108
|
-
request.headers
|
|
4109
|
-
);
|
|
4110
|
-
const responseTime = Math.round(
|
|
4111
|
-
performance.now() - (request.blypStartTime ?? performance.now())
|
|
4112
|
-
);
|
|
4113
|
-
const context = {
|
|
4114
|
-
request,
|
|
4115
|
-
reply,
|
|
4116
|
-
error: request.blypError
|
|
4117
|
-
};
|
|
4118
|
-
if (request.blypStructuredLogEmitted) {
|
|
617
|
+
parentPort.on('message', async (message) => {
|
|
618
|
+
const { id, type, payload } = message;
|
|
619
|
+
try {
|
|
620
|
+
switch (type) {
|
|
621
|
+
case 'init': {
|
|
622
|
+
adapter = await loadDatabase();
|
|
623
|
+
const filePath = payload.path;
|
|
624
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
625
|
+
db = adapter.create(filePath);
|
|
626
|
+
initializeSchema();
|
|
627
|
+
reclaimExpired(Date.now());
|
|
628
|
+
parentPort.postMessage({ id, ok: true, result: { runtime } });
|
|
4119
629
|
return;
|
|
4120
630
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
shared.logger,
|
|
4125
|
-
shared.level,
|
|
4126
|
-
requestLike,
|
|
4127
|
-
path3,
|
|
4128
|
-
reply.statusCode,
|
|
4129
|
-
responseTime,
|
|
4130
|
-
toErrorLike(request.blypError, reply.statusCode),
|
|
4131
|
-
resolveAdditionalProps(shared, context),
|
|
4132
|
-
{
|
|
4133
|
-
error: request.blypError
|
|
4134
|
-
}
|
|
4135
|
-
);
|
|
4136
|
-
}
|
|
631
|
+
case 'insert':
|
|
632
|
+
insertJobs(payload.jobs);
|
|
633
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
4137
634
|
return;
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
635
|
+
case 'claimDue':
|
|
636
|
+
parentPort.postMessage({ id, ok: true, result: claimDue(payload.limit, payload.now) });
|
|
637
|
+
return;
|
|
638
|
+
case 'ack':
|
|
639
|
+
ack(payload.ids);
|
|
640
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
641
|
+
return;
|
|
642
|
+
case 'reschedule':
|
|
643
|
+
reschedule(payload.items, payload.now);
|
|
644
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
645
|
+
return;
|
|
646
|
+
case 'deadLetter':
|
|
647
|
+
deadLetter(payload.items);
|
|
648
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
649
|
+
return;
|
|
650
|
+
case 'markSuccess':
|
|
651
|
+
markSuccess(payload.items);
|
|
652
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
653
|
+
return;
|
|
654
|
+
case 'markFailure':
|
|
655
|
+
markFailure(payload.items);
|
|
656
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
657
|
+
return;
|
|
658
|
+
case 'getStatusSummary':
|
|
659
|
+
parentPort.postMessage({ id, ok: true, result: getStatusSummary() });
|
|
660
|
+
return;
|
|
661
|
+
case 'listDeadLetters':
|
|
662
|
+
parentPort.postMessage({
|
|
663
|
+
id,
|
|
664
|
+
ok: true,
|
|
665
|
+
result: listDeadLetters(
|
|
666
|
+
payload.limit,
|
|
667
|
+
payload.offset,
|
|
668
|
+
payload.connectorType,
|
|
669
|
+
payload.connectorTarget
|
|
670
|
+
),
|
|
671
|
+
});
|
|
672
|
+
return;
|
|
673
|
+
case 'retryDeadLetters':
|
|
674
|
+
parentPort.postMessage({ id, ok: true, result: retryDeadLetters(payload.ids, payload.now) });
|
|
675
|
+
return;
|
|
676
|
+
case 'clearDeadLetters':
|
|
677
|
+
parentPort.postMessage({ id, ok: true, result: clearDeadLetters(payload.ids) });
|
|
678
|
+
return;
|
|
679
|
+
case 'count':
|
|
680
|
+
parentPort.postMessage({ id, ok: true, result: count() });
|
|
681
|
+
return;
|
|
682
|
+
case 'shutdown':
|
|
683
|
+
if (db && adapter) {
|
|
684
|
+
adapter.close(db);
|
|
685
|
+
db = undefined;
|
|
4177
686
|
}
|
|
4178
|
-
|
|
687
|
+
parentPort.postMessage({ id, ok: true, result: true });
|
|
688
|
+
return;
|
|
689
|
+
default:
|
|
690
|
+
throw new Error('Unknown SQLite worker command: ' + type);
|
|
4179
691
|
}
|
|
4180
|
-
})
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
692
|
+
} catch (error) {
|
|
693
|
+
parentPort.postMessage({
|
|
694
|
+
id,
|
|
695
|
+
ok: false,
|
|
696
|
+
error: error instanceof Error ? error.message : String(error),
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
`}var be=class{constructor(t){this.path=t;l(this,"worker");l(this,"pending",new Map);l(this,"nextId",1);this.worker=new worker_threads.Worker(Qt(),{eval:true}),this.worker.on("message",r=>{let n=this.pending.get(r.id);if(n){if(this.pending.delete(r.id),r.ok){n.resolve(r.result);return}n.reject(new Error(r.error??"SQLite worker request failed."));}}),this.worker.on("error",r=>{for(let n of this.pending.values())n.reject(r instanceof Error?r:new Error(String(r)));this.pending.clear();});}request(t,r={}){let n=this.nextId++;return new Promise((o,i)=>{this.pending.set(n,{resolve:o,reject:i}),this.worker.postMessage({id:n,type:t,payload:r});})}async init(){await this.request("init",{path:this.path});}async insert(t){await this.request("insert",{jobs:t});}async claimDue(t,r){return this.request("claimDue",{limit:t,now:r})}async ack(t){await this.request("ack",{ids:t});}async reschedule(t,r){await this.request("reschedule",{items:t,now:r});}async deadLetter(t){await this.request("deadLetter",{items:t});}async markSuccess(t){await this.request("markSuccess",{items:t});}async markFailure(t){await this.request("markFailure",{items:t});}async getStatusSummary(){return this.request("getStatusSummary")}async listDeadLetters(t){return this.request("listDeadLetters",t)}async retryDeadLetters(t,r){return this.request("retryDeadLetters",{ids:t,now:r})}async clearDeadLetters(t){return this.request("clearDeadLetters",{ids:t})}async count(){return this.request("count")}async shutdown(){try{await this.request("shutdown");}finally{await this.worker.terminate();}}};var Jt=Symbol("blyp.connector.batch-dispatch"),Y=Symbol("blyp.connector.delivery-binder");function Z(e){return new Promise(t=>{setTimeout(t,e);})}function xo(e){return e.data===void 0||typeof e.data!="object"||e.data===null||e.data.type!=="client_log"}function Gt(e){return JSON.stringify(e)}function Eo(e){try{let t=JSON.parse(e);return !t||typeof t!="object"||typeof t.jobId!="string"?null:t}catch{return null}}function Kt(e){let t=new Map;for(let r of e){let n=`${r.connectorType}:${r.connectorTarget??""}`;t.has(n)||t.set(n,{connectorType:r.connectorType,connectorTarget:r.connectorTarget});}return [...t.values()]}var Ce=class{constructor(t){this.config=t;l(this,"warnOnce",k(new Set));l(this,"memoryQueue",[]);l(this,"durableStaging",[]);l(this,"dispatchers",new Map);l(this,"activeDispatches",0);l(this,"flushPromise",null);l(this,"durableFlushPromise",null);l(this,"pollTimer",null);l(this,"durablePollRunning",false);l(this,"closed",false);l(this,"durableClient",null);l(this,"durableReady",false);l(this,"durableInitPromise",null);t.enabled&&(this.durableInitPromise=this.initializeDurableQueue());}bindTarget(t){typeof t[Y]=="function"&&t[Y](this);let r=t[Jt];r&&this.dispatchers.set(r.dispatchKey,r);}unbindTarget(t){typeof t[Y]=="function"&&t[Y](null);}enqueue(t,r,n,o){this.closed||!xo(r)||(this.dispatchers.set(n.dispatchKey,n),this.memoryQueue.push({id:le(),connectorType:t,connectorTarget:o,source:"server",record:r,attemptCount:0,maxAttempts:this.config.retry.maxAttempts,nextAttemptAt:Date.now(),createdAt:Date.now(),dispatchKey:n.dispatchKey,dispatcher:n}),this.enforceMemoryCapacity(),this.scheduleDispatch());}async flush(){await this.durableInitPromise?.catch(()=>{}),await this.processUntilIdle(),await this.flushDurableStaging(),await this.drainDurableQueueForFlush(),await this.flushDurableStaging(),await this.processUntilIdle();}async shutdown(){if(this.closed=true,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),await this.durableInitPromise?.catch(()=>{}),this.durableReady){let t=this.memoryQueue.splice(0,this.memoryQueue.length);for(let r of t)this.stageDurableJob(r,r.attemptCount,Math.max(r.nextAttemptAt,Date.now()));await this.flushDurableStaging();}await this.processUntilIdle(),this.durableClient&&(await this.durableClient.shutdown().catch(()=>{}),this.durableClient=null);}async getDurableCountForTests(){return await this.durableInitPromise?.catch(()=>{}),!this.durableReady||!this.durableClient?0:this.durableClient.count()}async getStatusSummaryForTests(){return await this.durableInitPromise?.catch(()=>{}),!this.durableReady||!this.durableClient?[]:this.durableClient.getStatusSummary()}async listDeadLettersForTests(){return await this.durableInitPromise?.catch(()=>{}),!this.durableReady||!this.durableClient?[]:(await this.durableClient.listDeadLetters({limit:1e3,offset:0})).items}async initializeDurableQueue(){try{let t=new be(this.config.durableQueuePath);await t.init(),this.durableClient=t,this.durableReady=!0,this.scheduleDurablePoll();}catch(t){this.durableReady=false,this.durableClient=null,this.warnOnce("connector-durable-disabled",`[Blyp] Warning: Failed to initialize the connector SQLite queue at ${this.config.durableQueuePath}. Falling back to in-memory retries.`,t);}}scheduleDispatch(){this.flushPromise||(this.flushPromise=(async()=>{try{await this.pumpMemoryQueue();}finally{this.flushPromise=null,!this.closed&&this.hasReadyMemoryJobs()&&this.scheduleDispatch();}})());}async pumpMemoryQueue(){for(;!this.closed;){for(;this.activeDispatches<this.config.dispatchConcurrency;){let t=this.takeNextMemoryBatch();if(t.length===0)break;this.activeDispatches+=1,this.dispatchMemoryBatch(t).finally(()=>{this.activeDispatches-=1,this.closed||this.scheduleDispatch();});}if(this.activeDispatches===0||!this.hasReadyMemoryJobs())break;await Z(10);}}takeNextMemoryBatch(){let t=Date.now(),r=this.memoryQueue.findIndex(i=>i.nextAttemptAt<=t);if(r===-1)return [];let n=this.memoryQueue[r],o=[n];this.memoryQueue.splice(r,1);for(let i=this.memoryQueue.length-1;i>=0;i-=1){let a=this.memoryQueue[i];a.dispatchKey===n.dispatchKey&&a.connectorTarget===n.connectorTarget&&a.nextAttemptAt<=t&&o.length<this.config.memoryBatchSize&&(o.push(a),this.memoryQueue.splice(i,1));}return o}async dispatchMemoryBatch(t){let r=t[0].dispatcher,n=Date.now(),o=await r.dispatch(t.map(i=>i.record),{source:"server",target:t[0].connectorTarget}).catch(i=>({ok:false,retryable:true,error:i instanceof Error?i.message:String(i)}));if(o.ok){await this.recordSuccessfulDispatch(t,n);return}await this.handleRetryableFailure(t,o,false,n);}async handleRetryableFailure(t,r,n,o){n||await this.durableInitPromise?.catch(()=>{});let i=[],a=[];await this.recordFailedDispatch(t,r,o);for(let s of t){let d=s.attemptCount+1;if(!r.retryable||d>=s.maxAttempts){a.push({id:s.id,connectorType:s.connectorType,connectorTarget:s.connectorTarget,operation:"send",payloadJson:Gt({jobId:s.id,connectorType:s.connectorType,connectorTarget:s.connectorTarget,source:s.source,record:s.record,createdAt:s.createdAt}),attemptCount:d,maxAttempts:s.maxAttempts,lastError:r.error,firstEnqueuedAt:s.createdAt,deadLetteredAt:o,lastAttemptAt:o}),this.warnOnce(`connector-drop:${s.connectorType}:${s.connectorTarget??"default"}:${s.id}`,n&&this.durableReady?`[Blyp] Warning: Dead-lettered ${s.connectorType} connector job after ${d} failed attempt(s). ${r.error??"Connector delivery failed."}`:`[Blyp] Warning: Dropped ${s.connectorType} connector job after ${d} failed attempt(s). ${r.error??"Connector delivery failed."}`);continue}let u=o+Ut(d,this.config.retry);if(n){i.push({id:s.id,attemptCount:d,nextAttemptAt:u,lastError:r.error});continue}if(this.durableReady&&this.config.durableSpillStrategy==="after-first-failure"){this.stageDurableJob(s,d,u,r.error);continue}this.memoryQueue.push({...s,attemptCount:d,nextAttemptAt:u});}a.length>0&&await this.durableClient?.deadLetter(a).catch(s=>{this.warnOnce("connector-dead-letter-failure","[Blyp] Warning: Failed to persist dead-lettered connector queue jobs.",s);}),i.length>0&&await this.durableClient?.reschedule(i,o).catch(s=>{this.warnOnce("connector-reschedule-failure","[Blyp] Warning: Failed to reschedule durable connector queue jobs.",s);});}async recordSuccessfulDispatch(t,r){if(!this.durableReady||!this.durableClient||t.length===0)return;let n=Kt(t).map(o=>({connectorType:o.connectorType,connectorTarget:o.connectorTarget,timestamp:r}));await this.durableClient.markSuccess(n).catch(o=>{this.warnOnce("connector-status-success-failure","[Blyp] Warning: Failed to record connector delivery success state.",o);});}async recordFailedDispatch(t,r,n){if(!this.durableReady||!this.durableClient||t.length===0)return;let o=Kt(t).map(i=>({connectorType:i.connectorType,connectorTarget:i.connectorTarget,timestamp:n,lastError:r.error}));await this.durableClient.markFailure(o).catch(i=>{this.warnOnce("connector-status-failure-failure","[Blyp] Warning: Failed to record connector delivery failure state.",i);});}stageDurableJob(t,r,n,o){let i=Gt({jobId:t.id,connectorType:t.connectorType,connectorTarget:t.connectorTarget,source:t.source,record:t.record,createdAt:t.createdAt});this.durableStaging.push({id:t.id,connectorType:t.connectorType,connectorTarget:t.connectorTarget,operation:"send",payloadJson:i,attemptCount:r,maxAttempts:t.maxAttempts,nextAttemptAt:n,state:"pending",lastError:o,createdAt:t.createdAt,updatedAt:Date.now()}),this.flushDurableStaging();}async flushDurableStaging(){if(!(!this.durableReady||!this.durableClient||this.durableStaging.length===0)){if(this.durableFlushPromise){await this.durableFlushPromise;return}this.durableFlushPromise=(async()=>{for(;this.durableStaging.length>0;){let t=this.durableStaging.splice(0,this.config.sqliteWriteBatchSize);try{await this.durableClient.insert(t);}catch(r){this.warnOnce("connector-durable-insert-failure","[Blyp] Warning: Failed to persist connector jobs into the durable SQLite queue.",r),this.durableStaging.unshift(...t);break}}})();try{await this.durableFlushPromise;}finally{this.durableFlushPromise=null;}}}async processDurableQueueOnce(){if(!(!this.durableReady||!this.durableClient||this.durablePollRunning)){this.durablePollRunning=true;try{for(;!this.closed;){let t=await this.durableClient.claimDue(this.config.sqliteReadBatchSize,Date.now());if(t.length===0)break;let r=new Map,n=[];for(let o of t){let i=Eo(o.payloadJson);if(!i){n.push(o.id);continue}let a=o.connectorType==="otlp"?`otlp:${o.connectorTarget??""}`:o.connectorType,s=this.dispatchers.get(a);if(!s){n.push(o.id);continue}let d={id:o.id,connectorType:o.connectorType,connectorTarget:o.connectorTarget,source:i.source,record:i.record,attemptCount:o.attemptCount,maxAttempts:o.maxAttempts,nextAttemptAt:o.nextAttemptAt,createdAt:o.createdAt,dispatchKey:a,dispatcher:s},u=r.get(a)??[];u.push(d),r.set(a,u);}n.length>0&&await this.durableClient.ack(n);for(let o of r.values()){let a=await o[0].dispatcher.dispatch(o.map(s=>s.record),{source:"server",target:o[0].connectorTarget}).catch(s=>({ok:!1,retryable:!0,error:s instanceof Error?s.message:String(s)}));if(a.ok){await this.recordSuccessfulDispatch(o,Date.now()),await this.durableClient.ack(o.map(s=>s.id));continue}await this.handleRetryableFailure(o,a,!0,Date.now());}}}finally{this.durablePollRunning=false;}}}async drainDurableQueueForFlush(){if(!(!this.durableReady||!this.durableClient)){this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null);try{for(;!this.closed;){for(;this.durablePollRunning;)await Z(10);if(await this.processDurableQueueOnce(),await this.flushDurableStaging(),await this.durableClient.count().catch(()=>0)===0&&!this.durablePollRunning&&this.durableStaging.length===0)break;await Z(10);}}finally{this.closed||this.scheduleDurablePoll();}}}scheduleDurablePoll(){this.closed||!this.durableReady||this.pollTimer||(this.pollTimer=setTimeout(async()=>{this.pollTimer=null,await this.flushDurableStaging(),await this.processDurableQueueOnce(),this.scheduleDurablePoll();},this.config.pollIntervalMs));}enforceMemoryCapacity(){for(;this.memoryQueue.length>this.config.memoryBufferSize;){let t=this.config.overflowStrategy==="drop-new"?this.memoryQueue.length-1:0,[r]=this.memoryQueue.splice(t,1);if(!r)break;if(this.durableReady){this.stageDurableJob(r,r.attemptCount,Math.max(Date.now(),r.nextAttemptAt),"spilled from in-memory buffer");continue}this.warnOnce(`connector-overflow:${r.connectorType}:${r.connectorTarget??"default"}:${t}`,`[Blyp] Warning: Connector queue overflow reached ${this.config.memoryBufferSize}. Dropping queued ${r.connectorType} job.`);}}hasReadyMemoryJobs(){let t=Date.now();return this.memoryQueue.some(r=>r.nextAttemptAt<=t)}async processUntilIdle(){for(;this.activeDispatches>0||this.memoryQueue.length>0||this.durableStaging.length>0||this.flushPromise!==null||this.durableFlushPromise!==null;){if(this.scheduleDispatch(),await this.flushPromise?.catch(()=>{}),await this.flushDurableStaging(),this.memoryQueue.some(t=>t.nextAttemptAt>Date.now())||await this.processDurableQueueOnce(),this.activeDispatches===0&&this.memoryQueue.length>0&&!this.hasReadyMemoryJobs()){let t=Math.min(...this.memoryQueue.map(r=>r.nextAttemptAt));await Z(Math.max(t-Date.now(),0));}else await Z(10);if(this.activeDispatches===0&&this.memoryQueue.length===0&&this.durableStaging.length===0)break}}};var M=class M{constructor(){l(this,"_type",null);}static getInstance(){return M.instance||(M.instance=new M),M.instance}get type(){return this._type===null&&(this._type=this.detectRuntime()),this._type}get isBun(){return this.type==="bun"}get isNode(){return this.type==="node"}detectRuntime(){return typeof Bun<"u"&&typeof Bun.file=="function"?"bun":"node"}};l(M,"instance");var Xe=M,Ve=class{constructor(){l(this,"type","bun");l(this,"isBun",true);l(this,"isNode",false);l(this,"file",{existsSync:t=>{try{let r=Bun.file(t);return r.size>0||r.name!==""}catch{return false}},mkdirSync:(t,r)=>{try{S__default.default.mkdirSync(t,r);}catch{}},writeFileSync:(t,r)=>{Bun.write(t,r);}});l(this,"path",{join:(...t)=>U__default.default.join(...t)});l(this,"env",{get:t=>Bun.env[t]});l(this,"cwd",()=>process.cwd());}},Ye=class{constructor(){l(this,"type","node");l(this,"isBun",false);l(this,"isNode",true);l(this,"file",{existsSync:t=>S__default.default.existsSync(t),mkdirSync:(t,r)=>{S__default.default.mkdirSync(t,r);},writeFileSync:(t,r)=>{S__default.default.writeFileSync(t,r);}});l(this,"path",{join:(...t)=>U__default.default.join(...t)});l(this,"env",{get:t=>process.env[t]});l(this,"cwd",()=>process.cwd());}};function Do(){return Xe.getInstance().isBun?new Ve:new Ye}var Vt=Do();function Yt(e,t){if(typeof e=="string")return t.length===0?void 0:t.length===1?t[0]:t;let r=[e,...t];return r.length===1?r[0]:r}function Zt(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function ko(e,t){if(e==null)return t===void 0||t<400?void 0:{message:`HTTP ${t}`,code:t,type:"HttpError"};if(e instanceof Error){let r=e;return {message:e.message,code:r.code,type:r.type??e.name??e.constructor?.name,stack:e.stack,why:r.why,fix:r.fix,link:r.link,details:Zt(r.details),cause:r.cause}}if(typeof e=="object"){let r=e,n=typeof r.statusCode=="number"?r.statusCode:typeof r.status=="number"?r.status:t;return {message:typeof r.message=="string"?r.message:`HTTP ${n??500}`,code:typeof r.code=="string"||typeof r.code=="number"?r.code:n,type:typeof r.type=="string"?r.type:typeof r.name=="string"?r.name:"Error",stack:typeof r.stack=="string"?r.stack:void 0,why:typeof r.why=="string"?r.why:void 0,fix:typeof r.fix=="string"?r.fix:void 0,link:typeof r.link=="string"?r.link:void 0,details:Zt(r.details),cause:r.cause}}return {message:String(e),code:t,type:typeof e}}function _o(e){return e.response&&typeof e.response.status=="number"?e.response.status:typeof e.status=="number"?e.status:e.error&&typeof e.error=="object"&&e.error!==null&&typeof e.error.statusCode=="number"?e.error.statusCode:e.error&&typeof e.error=="object"&&e.error!==null&&typeof e.error.status=="number"?e.error.status:e.error?500:void 0}function er(e,t){let r=t.redact??T(),n=performance.now(),o=C(t.initialFields??{},r),i=[],a;t.onCreate?.();let s=(u,c,p)=>(i.push({level:u,message:B(c,r),timestamp:new Date().toISOString(),...Yt(c,p)===void 0?{}:{data:C(Yt(c,p),r)}}),d),d={set(u){return Object.assign(o,C(u,r)),d},debug(u,...c){return s("debug",u,c)},info(u,...c){return s("info",u,c)},warn(u,...c){return s("warn",u,c)},warning(u,...c){return s("warning",u,c)},error(u,...c){return s("error",u,c)},success(u,...c){return s("success",u,c)},critical(u,...c){return s("critical",u,c)},table(u,c){return s("table",u,c===void 0?[]:[c])},emit(u={}){if(a)return a;let c=C(t.resolveDefaultFields?.()??{},r),p=_o(u),m=C(ko(u.error,p),r),R=u.level??(m?"error":"info"),w=C({...c,...o,groupId:e,timestamp:new Date().toISOString(),level:R,duration:Math.round(performance.now()-n),...typeof p=="number"?{status:p}:{},...i.length>0?{events:[...i]}:{},...m?{error:m}:{}},r);return t.write(w,B(u.message??"structured_log",r)),a=w,t.onEmit?.(w),w}};return d}var tt=Symbol("blyp.logger.factory"),rr={success:25,info:30,debug:35,table:37,warning:40,error:50,critical:60},nr={success:"success",critical:"critical",warning:"warning",info:"info",debug:"debug",error:"error",warn:"warn",table:"debug"},Po="\x1B[35m",Ao="\x1B[0m";function ee(e){return fe(e)==="client_log"}function Bo(){return {enabled:false,ready:false,mode:"auto",serviceName:"blyp-app",ingestingHost:void 0,status:"missing",errorTracking:{enabled:false,ready:false,status:"missing",dsn:void 0,tracesSampleRate:1,environment:void 0,release:void 0},shouldAutoForwardServerLogs:()=>false,shouldAutoCaptureExceptions:()=>false,send:()=>{},captureException:()=>{},flush:async()=>{}}}function Io(){return {enabled:false,ready:false,mode:"auto",status:"missing",shouldAutoForwardServerLogs:()=>false,shouldAutoCaptureExceptions:()=>false,send:()=>{},captureException:()=>{},flush:async()=>{}}}function Oo(){return {enabled:false,ready:false,mode:"auto",serviceName:"blyp-app",host:"https://us.i.posthog.com",status:"missing",errorTracking:{enabled:false,ready:false,mode:"auto",status:"missing",enableExceptionAutocapture:false},shouldAutoForwardServerLogs:()=>false,shouldAutoCaptureExceptions:()=>false,send:()=>{},captureException:()=>{},flush:async()=>{}}}function No(){return {enabled:false,ready:false,mode:"auto",status:"missing",shouldAutoForwardServerLogs:()=>false,send:()=>{},flush:async()=>{}}}function Fo(e){return {name:e,enabled:false,ready:false,mode:"auto",serviceName:"blyp-app",endpoint:void 0,status:"missing",send:()=>{},flush:async()=>{}}}function Mo(){return {get:e=>Fo(e),getAutoForwardTargets:()=>[],send:()=>{},flush:async()=>{}}}function zo(e){return e.connectors?.betterstack?.enabled?H("betterstack",["@logtail/node","@sentry/node"],"../connectors/betterstack/sender").createBetterStackSender(e):Bo()}function jo(e){return e.connectors?.databuddy?.enabled?H("databuddy",["@databuddy/sdk"],"../connectors/databuddy/sender").createDatabuddySender(e):Io()}function $o(e){return e.connectors?.posthog?.enabled?H("posthog",["posthog-node","@opentelemetry/api-logs","@opentelemetry/exporter-logs-otlp-http","@opentelemetry/resources","@opentelemetry/sdk-logs"],"../connectors/posthog/sender").createPostHogSender(e):Oo()}function qo(e){return e.connectors?.sentry?.enabled?H("sentry",["@sentry/node"],"../connectors/sentry/sender").createSentrySender(e):No()}function Uo(e){return e.connectors?.otlp?.some(t=>t.enabled)?H("otlp",["@opentelemetry/api-logs","@opentelemetry/exporter-logs-otlp-http","@opentelemetry/resources","@opentelemetry/sdk-logs"],"../connectors/otlp/sender").createOTLPRegistry(e):Mo()}function Ho(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e,r={};t.data!==void 0&&(r.data=t.data);let n=typeof t.page?.pathname=="string"?t.page.pathname:void 0,o=typeof t.page?.url=="string"?t.page.url:void 0;return (n||o)&&(r.page=n??o),t.metadata!==void 0&&(r.metadata=t.metadata),Object.keys(r).length>0?r:null}function Wo(e){if(!e||typeof e!="object"||Array.isArray(e))return {hidden:false,value:e};let t=e;if(t.type==="http_request"||t.type==="http_error")return {hidden:true};if(t.type==="client_log"){let r=Ho(e);return r?{hidden:false,value:r}:{hidden:true}}return {hidden:false,value:e}}function Qo(e){if(e.pretty){let r=Et()({colorize:true,translateTime:"SYS:HH:MM:ss",ignore:"pid,hostname,caller",customColors:{success:"green",critical:"red bold",info:"blue",warning:"yellow",error:"red",debug:"cyan",table:"cyan"},messageFormat:(n,o)=>{let i=String(n[o]??""),a=typeof n.caller=="string"?n.caller.trim():"";return a?`${i} ${Po}${a}${Ao}`:i}});return tr__default.default({level:e.level,customLevels:rr},r)}return tr__default.default({level:e.level,customLevels:rr})}function E(e){let t=e[tt];if(!t)throw new Error("Unsupported Blyp logger instance");return t}function rt(e){return E(e).posthog}function nt(e){return E(e).betterstack}function ot(e){return E(e).databuddy}function ur(e){try{return rt(e)}catch{return null}}function dr(e){try{return nt(e)}catch{return null}}function lr(e){try{return ot(e)}catch{return null}}function gr(e){return E(e).sentry}function pr(e){return E(e).otlp}function Re(e){try{return E(e).redact}catch{return X().redact}}function fr(e,t){let r=E(t);return Object.defineProperty(e,tt,{value:r,enumerable:false,configurable:false,writable:false}),e}function mr(e,t){let r=E(e);return r.create(t,r.bindings)}function it(e,t,r={}){let n=E(e);return er(t,{initialFields:r.initialFields,resolveDefaultFields:()=>({...n.bindings,...r.resolveDefaultFields?.()??{}}),write:(o,i)=>{n.writeStructured(o,i,"structured-flush");},onCreate:r.onCreate,onEmit:r.onEmit,redact:r.redact??n.redact})}function or(e,t){if(!ee(t)){if(!e.shouldAutoForwardServerLogs()){e.enabled&&!e.ready&&e.send(t,{source:"server",warnIfUnavailable:true});return}e.send(t,{source:"server",warnIfUnavailable:true});}}function ir(e,t){if(!ee(t)){if(!e.shouldAutoForwardServerLogs()){e.enabled&&!e.ready&&e.send(t,{source:"server",warnIfUnavailable:true});return}e.send(t,{source:"server",warnIfUnavailable:true});}}function ar(e,t){if(!ee(t)){if(!e.shouldAutoForwardServerLogs()){e.enabled&&!e.ready&&e.send(t,{source:"server",warnIfUnavailable:true});return}e.send(t,{source:"server",warnIfUnavailable:true});}}function sr(e,t){if(!ee(t)){if(!e.shouldAutoForwardServerLogs()){e.enabled&&!e.ready&&e.send(t,{source:"server",warnIfUnavailable:true});return}e.send(t,{source:"server",warnIfUnavailable:true});}}function cr(e,t){if(!ee(t))for(let r of e.getAutoForwardTargets())r.send(t,{source:"server",warnIfUnavailable:true});}function et(e,t,r,n,o,i,a,s,d,u={},c="root"){let p=Object.keys(u).length>0?e.child(u):e,m=(f,g,y,L=c)=>{if(L==="root"&&me())return;let h=Bt(f,g,y,u,d),Q=h.message,J={caller:h.caller},te=Wo(h.data);!te.hidden&&te.value!==void 0&&(J.data=te.value);let ut=nr[f],Se=p;(Se[ut]??Se.info??((ti,ri)=>{})).call(p,J,Q),t.write(h),ir(n,h),ar(o,h),or(i,h),sr(a,h),cr(s,h);},R=(f,g,y="structured-flush")=>{let L=Ot(f.level),h=It(L,g,f,u,d),Q=nr[L],J=p;(J[Q]??J.info??((ut,Se)=>{})).call(p,{caller:h.caller,...h},h.message),(y!=="root"||!me())&&t.write(h),ir(n,h),ar(o,h),or(i,h),sr(a,h),cr(s,h);},w={success:(f,...g)=>{m("success",f,g);},critical:(f,...g)=>{m("critical",f,g);},warning:(f,...g)=>{m("warning",f,g);},info:(f,...g)=>{m("info",f,g);},debug:(f,...g)=>{m("debug",f,g);},error:(f,...g)=>{m("error",f,g);},warn:(f,...g)=>{m("warn",f,g);},table:(f,g)=>{g&&typeof g=="object"&&Vt.env.get("NODE_ENV")!=="production"&&(console.log("TABLE:",f),console.table(C(g,d))),m("table",f,g===void 0?[]:[g]);},flush:async()=>{await t.flush(),r&&await r.flush(),await Promise.allSettled([n.flush(),o.flush(),i.flush(),a.flush(),s.flush()]);},shutdown:async()=>{await t.shutdown(),r&&await r.shutdown(),await Promise.allSettled([n.flush(),o.flush(),i.flush(),a.flush(),s.flush()]);},createStructuredLog:(f,g)=>it(w,f,{initialFields:g}),child:f=>{let g={...u,...f};return et(e,t,r,n,o,i,a,s,d,g,c)},[tt]:{bindings:u,betterstack:n,databuddy:o,posthog:i,sentry:a,otlp:s,redact:d,sink:t,create:(f,g=u)=>et(e,t,r,n,o,i,a,s,d,g,f),writeStructured:(f,g,y="structured-flush")=>{R(f,g,y);}}};return w}var Ze=null;function at(e){if(e===void 0&&Ze)return Ze;let t=X(e),r=Qo(t),n=qt(t),o=zo(t),i=jo(t),a=$o(t),s=qo(t),d=Uo(t),u=t.connectors.delivery.enabled?new Ce(t.connectors.delivery):null;if(u){u.bindTarget(o),u.bindTarget(i),u.bindTarget(a),u.bindTarget(s);for(let p of d.getAutoForwardTargets())u.bindTarget(p);}let c=et(r,n,u,o,i,a,s,d,t.redact);return e===void 0&&(Ze=c),c}at();function yr(e,t,r,n){let o=re(e),i=ne(t),a=oe(n);return `${o} ${r} ${i} ${a}`}function Jo(e,t){let r=Ae(t?.path??N),n=t?.enabled===false?null:{path:r};return e===false?null:e===void 0?n:e===true?{path:r}:{...n,...e,path:Ae(e.path??r)}}function hr(e={},t){let r=X({...e.level!==void 0?{level:e.level}:{},...e.pretty!==void 0?{pretty:e.pretty}:{},...e.destination!==void 0?{destination:e.destination}:{},...e.logDir!==void 0?{logDir:e.logDir}:{},...e.file!==void 0?{file:e.file}:{},...e.database!==void 0?{database:e.database}:{},...e.redact!==void 0?{redact:e.redact}:{},...e.connectors!==void 0?{connectors:e.connectors}:{}}),{level:n=r.level,pretty:o=r.pretty,destination:i=r.destination,logDir:a=r.logDir,file:s=r.file,database:d=r.database,autoLogging:u=true,customProps:c,logErrors:p=true,includePaths:m,ignorePaths:R,clientLogging:w,connectors:f}=e,g=at({level:n,pretty:o,destination:i,logDir:a,file:s,database:d,connectors:f}),y=Jo(w,r.clientLogging),L=y?.path??N,h=m,Q=y?Array.from(new Set([...R??[],L])):R;return {logger:g,betterstack:nt(g),databuddy:ot(g),posthog:rt(g),sentry:gr(g),otlp:pr(g),resolvedConfig:r,level:n,pretty:o,logDir:a,file:s,autoLogging:u,customProps:c,logErrors:p,resolvedIncludePaths:h,resolvedIgnorePaths:Q,resolvedClientLogging:y,ingestionPath:L}}function Go(e,t){return !t||t.length===0?true:Ne(e,t)}function br(e,t,r){return Go(e,t)?Ne(e,r):true}function Cr(e,t,r){return e.autoLogging===false||typeof e.autoLogging=="object"&&e.autoLogging.ignore?.(t)?true:br(r,e.resolvedIncludePaths,e.resolvedIgnorePaths)}function wr(e,t){return e.logErrors?br(t,e.resolvedIncludePaths,e.resolvedIgnorePaths):true}function Le(e,t){return e.customProps?e.customProps(t):{}}function Rr(e,t,r,n,o,i,a={}){let s=ue(r,"http_request",n,o,i,a,Re(e));return t==="info"?e.info(de(r.method,o,n,i),s):(e.info(yr(r.method,o,n,i),s),Object.keys(a).length>0&&e.debug("Request context",a)),s}function Lr(e,t,r,n,o,i,a,s={},d={}){let u=ue(r,"http_error",n,o,i,{error:a?.message??`HTTP ${o}`,stack:a?.stack,code:a?.code,why:a?.why,fix:a?.fix,link:a?.link,details:a?.details,...s},Re(e)),c=t==="info"?de(r.method,o,n,i):yr(r.method,o,n,i);e.error(c,u);let p=ur(e);p?.shouldAutoCaptureExceptions()&&p.captureException(d.error??a??c,{source:"server",warnIfUnavailable:true,distinctId:d.distinctId??b(r.headers,"x-posthog-distinct-id"),properties:qe({timestamp:new Date().toISOString(),level:"error",message:c,data:u},"server",{$request_method:r.method,$request_path:n,$current_url:r.url,$response_status_code:o,...b(r.headers,"user-agent")?{$user_agent:b(r.headers,"user-agent")}:{},...u.ip?{$ip:u.ip}:{}})});let m=dr(e);m?.shouldAutoCaptureExceptions()&&m.captureException(d.error??a??c,{source:"server",warnIfUnavailable:true,context:{timestamp:new Date().toISOString(),level:"error",message:c,status:o,path:n,data:u}});let R=lr(e);return R?.shouldAutoCaptureExceptions()&&R.captureException(d.error??a??c,{source:"server",warnIfUnavailable:true,properties:{method:r.method,path:n,status_code:o,...r.url?{current_url:r.url}:{},...b(r.headers,"user-agent")?{user_agent:b(r.headers,"user-agent")}:{},...u.ip?{ip:u.ip}:{},payload:u}}),u}async function Ko(e,t){if(t!==void 0)return typeof t=="string"?JSON.parse(t):t;if(typeof e.json=="function")return await e.json();throw new Error("Unable to parse client log payload")}function Xo(e,t){switch(t){case "debug":return e.debug;case "info":return e.info;case "warning":return e.warning;case "error":return e.error;case "critical":return e.critical;case "success":return e.success}}async function Sr(e){let{config:t,ctx:r,request:n,body:o,deliveryPath:i}=e;if(!t.resolvedClientLogging)return {status:404};let a;try{a=await Ko(n,o);}catch{return {status:400}}if(!ft(a))return {status:400};if(!(t.resolvedClientLogging.validate?await t.resolvedClientLogging.validate(r,a):true))return {status:403};let d=t.resolvedClientLogging.enrich?await t.resolvedClientLogging.enrich(r,a):void 0,u=Re(t.logger),c=C(a,u),p=C({...c,receivedAt:new Date().toISOString(),delivery:xe(n,i??I(n.url),u)},u);d!==void 0&&(p.serverContext=C(d,u));let m=B(`[client] ${c.message}`,u),R=A(),w=typeof c.traceId=="string"&&c.traceId.length>0?c.traceId:R;try{w&&V(w),c.level==="table"?t.logger.table(m,p):Xo(t.logger,c.level)(m,p);}finally{V(R);}let f={};if(c.connector==="betterstack"){if(f["x-blyp-betterstack-status"]=t.betterstack.ready?"enabled":"missing",t.betterstack.ready){let g={timestamp:p.receivedAt,level:c.level,message:m,data:p};if(t.betterstack.send(g,{source:"client"}),(c.level==="error"||c.level==="critical")&&t.betterstack.shouldAutoCaptureExceptions()){let y=c.data&&typeof c.data=="object"&&!Array.isArray(c.data)&&typeof c.data.message=="string"?c.data:c.message;t.betterstack.captureException(y,{source:"client",warnIfUnavailable:true,context:{sessionId:c.session.sessionId,pageUrl:c.page.url,pagePath:c.page.pathname,metadata:c.metadata,payload:p}});}}}else if(c.connector==="databuddy"){if(f["x-blyp-databuddy-status"]=t.databuddy.ready?"enabled":"missing",t.databuddy.ready){let g={timestamp:p.receivedAt,level:c.level,message:m,data:p};if(t.databuddy.send(g,{source:"client"}),(c.level==="error"||c.level==="critical")&&t.databuddy.shouldAutoCaptureExceptions()){let y=c.data&&typeof c.data=="object"&&!Array.isArray(c.data)&&typeof c.data.message=="string"?c.data:c.message;t.databuddy.captureException(y,{source:"client",warnIfUnavailable:true,sessionId:c.session.sessionId,properties:{page_url:c.page.url,page_path:c.page.pathname,client_runtime:c.device?.runtime,metadata:c.metadata,payload:p}});}}}else if(c.connector==="posthog"){if(f["x-blyp-posthog-status"]=t.posthog.ready?"enabled":"missing",t.posthog.ready){let g={timestamp:p.receivedAt,level:c.level,message:m,data:p};if(t.posthog.send(g,{source:"client"}),(c.level==="error"||c.level==="critical")&&t.posthog.shouldAutoCaptureExceptions()){let y=p.metadata,L=y&&typeof y=="object"&&!Array.isArray(y)&&typeof y.posthogDistinctId=="string"&&y.posthogDistinctId?String(y.posthogDistinctId):void 0,h=c.data&&typeof c.data=="object"&&!Array.isArray(c.data)&&typeof c.data.message=="string"?c.data:c.message;t.posthog.captureException(h,{source:"client",warnIfUnavailable:true,distinctId:L,properties:qe(g,"client",{$session_id:c.session.sessionId,$current_url:c.page.url,$request_path:c.page.pathname,"client.runtime":c.device?.runtime,"client.metadata":c.metadata})});}}}else if(c.connector==="sentry")f["x-blyp-sentry-status"]=t.sentry.ready?"enabled":"missing",t.sentry.ready&&t.sentry.send({timestamp:p.receivedAt,level:c.level,message:m,data:p},{source:"client"});else if(c.connector?.type==="otlp"){let g=t.otlp.get(c.connector.name);f["x-blyp-otlp-status"]=g.ready?"enabled":"missing",g.ready&&g.send({timestamp:p.receivedAt,level:c.level,message:m,data:p},{source:"client"});}return Object.keys(f).length>0?{status:204,headers:f}:{status:204}}function st(e,t){if(e.startsWith("http://")||e.startsWith("https://"))return e;let r=b(t,"x-forwarded-proto")??"http",n=b(t,"host")??"localhost";return `${r}://${n}${e.startsWith("/")?e:`/${e}`}`}function ct(e,t={}){let r=mr(e,"request-scoped"),n=fr({...r,createStructuredLog:(o,i)=>it(n,o,{initialFields:i,resolveDefaultFields:()=>{let a=A();return {...t.resolveStructuredFields?.()??{},...a?{traceId:a}:{}}},onCreate:()=>{Qe();},onEmit:()=>{Je(),t.onStructuredEmit?.();}}),child(o){return ct(r.child(o),t)}},r);return We(n),n}var vr="x-blyp-trace-id",Vo="trace_";function Tr(){return `${Vo}${le().replace(/[^a-z0-9]/gi,"").toLowerCase().slice(0,12)}`}function xr(e){V(e);}function Er(e={}){let t=hr(e);return Yo__default.default(async r=>{r.decorateRequest("blypLogHolder"),r.decorateRequest("blypLog",{getter(){return this.blypLogHolder},setter(n){this.blypLogHolder=n;}}),r.decorateRequest("blypStartTime",void 0),r.decorateRequest("blypTraceId",void 0),r.decorateRequest("blypError",void 0),r.decorateRequest("blypStructuredLogEmitted",void 0),r.addHook("onRequest",async(n,o)=>{He();let i=Tr();xr(i),n.blypStartTime=performance.now(),n.blypTraceId=i,o.header(vr,i),n.blypError=void 0,n.blypStructuredLogEmitted=false;}),r.addHook("preHandler",async n=>{n.blypLog=ct(t.logger,{resolveStructuredFields:()=>({method:n.method,path:I(n.url),...Le(t,{request:n,reply:{},error:n.blypError})}),onStructuredEmit:()=>{n.blypStructuredLogEmitted=true;}});}),r.addHook("onError",async(n,o,i)=>{n.blypError=i;}),r.addHook("onResponse",async(n,o)=>{let i=I(n.url),a=ce(n.method,st(n.url,n.headers),n.headers),s=Math.round(performance.now()-(n.blypStartTime??performance.now())),d={request:n,reply:o,error:n.blypError};if(!n.blypStructuredLogEmitted){if(n.blypError||De(o.statusCode)){wr(t,i)||Lr(t.logger,t.level,a,i,o.statusCode,s,Ee(n.blypError,o.statusCode),Le(t,d),{error:n.blypError});return}Cr(t,d,i)||Rr(t.logger,t.level,a,i,o.statusCode,s,Le(t,d));}}),t.resolvedClientLogging&&r.route({method:"POST",url:t.ingestionPath,handler:async(n,o)=>{let i=await Sr({config:t,ctx:{request:n,reply:o},request:ce(n.method,st(n.url,n.headers),n.headers),body:n.body,deliveryPath:t.ingestionPath});if(o.code(i.status),i.headers)for(let[a,s]of Object.entries(i.headers))o.header(a,s);return null}});})}var Zo=Er;
|
|
701
|
+
exports.createFastifyLogger=Er;exports.createLogger=Zo;
|