@kopai/app 0.13.3 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@
9
9
  type="image/svg+xml"
10
10
  href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Crect width='32' height='32' rx='4' fill='%230a0a0a'/%3E%3Ctext x='3' y='22' font-family='ui-monospace,monospace' font-size='16' font-weight='400' fill='%23fafafa'%3Ek%3E%3C/text%3E%3C/svg%3E"
11
11
  />
12
- <script type="module" crossorigin src="/assets/index-D7kd8gMB.js"></script>
12
+ <script type="module" crossorigin src="/assets/index-DxpYPShU.js"></script>
13
13
  <link rel="stylesheet" crossorigin href="/assets/index-CAx44wZh.css">
14
14
  </head>
15
15
  <body>
@@ -32,7 +32,10 @@ const apiRoutes = async function(fastify, opts) {
32
32
  //#endregion
33
33
  //#region src/collector/index.ts
34
34
  const otelCollectorRoutes = async function(fastify, opts) {
35
- fastify.register(_kopai_collector.collectorRoutes, opts);
35
+ fastify.register(_kopai_collector.collectorRoutes, {
36
+ ...opts,
37
+ ingestionMetricsDatasource: opts.telemetryDatasource
38
+ });
36
39
  };
37
40
  //#endregion
38
41
  //#region src/startup-banner.ts
@@ -27,7 +27,10 @@ const apiRoutes = async function(fastify, opts) {
27
27
  //#endregion
28
28
  //#region src/collector/index.ts
29
29
  const otelCollectorRoutes = async function(fastify, opts) {
30
- fastify.register(collectorRoutes, opts);
30
+ fastify.register(collectorRoutes, {
31
+ ...opts,
32
+ ingestionMetricsDatasource: opts.telemetryDatasource
33
+ });
31
34
  };
32
35
  //#endregion
33
36
  //#region src/startup-banner.ts
@@ -216,4 +219,4 @@ closeWithGrace(async ({ signal, err }) => {
216
219
  //#endregion
217
220
  export {};
218
221
 
219
- //# sourceMappingURL=server-CLJTp1Ca.mjs.map
222
+ //# sourceMappingURL=server-K-NclWLG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-K-NclWLG.mjs","names":[],"sources":["../src/routes/index.ts","../src/collector/index.ts","../src/startup-banner.ts","../src/server.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { signalsRoutes, dashboardsRoutes } from \"@kopai/api\";\nimport { type datasource, type dashboardDatasource } from \"@kopai/core\";\nimport { generatePromptInstructions, observabilityCatalog } from \"@kopai/ui\";\n\nconst require = createRequire(import.meta.url);\nconst uiPkg = require(\"@kopai/ui/package.json\");\n\nconst promptInstructions = generatePromptInstructions(\n observabilityCatalog,\n uiPkg.version\n);\n\nexport const apiRoutes: FastifyPluginAsyncZod<{\n readTelemetryDatasource: datasource.ReadTelemetryDatasource;\n dynamicDashboardDatasource: dashboardDatasource.DynamicDashboardDatasource;\n}> = async function (fastify, opts) {\n fastify.register(signalsRoutes, {\n readTelemetryDatasource: opts.readTelemetryDatasource,\n });\n fastify.register(dashboardsRoutes, {\n dynamicDashboardDatasource: opts.dynamicDashboardDatasource,\n promptInstructions,\n });\n};\n","import type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { collectorRoutes } from \"@kopai/collector\";\nimport type { datasource } from \"@kopai/core\";\n\nexport const otelCollectorRoutes: FastifyPluginAsyncZod<{\n telemetryDatasource: datasource.WriteTelemetryDatasource;\n}> = async function (fastify, opts) {\n fastify.register(collectorRoutes, {\n ...opts,\n ingestionMetricsDatasource: opts.telemetryDatasource,\n });\n};\n","import { networkInterfaces } from \"node:os\";\n\nconst isTTY = process.stdout.isTTY;\nconst bold = isTTY ? \"\\x1b[1m\" : \"\";\nconst dim = isTTY ? \"\\x1b[2m\" : \"\";\nconst green = isTTY ? \"\\x1b[32m\" : \"\";\nconst cyan = isTTY ? \"\\x1b[36m\" : \"\";\nconst reset = isTTY ? \"\\x1b[0m\" : \"\";\n\nfunction getNetworkAddress(): string | undefined {\n const nets = networkInterfaces();\n for (const interfaces of Object.values(nets)) {\n if (!interfaces) continue;\n for (const net of interfaces) {\n if (net.family === \"IPv4\" && !net.internal) {\n return net.address;\n }\n }\n }\n return undefined;\n}\n\nexport function printStartupBanner({\n host,\n port,\n collectorPort,\n version,\n}: {\n host: string;\n port: number;\n collectorPort: number;\n version: string;\n}) {\n const localHost = host === \"0.0.0.0\" || host === \"::\" ? \"localhost\" : host;\n const networkAddress = getNetworkAddress();\n\n const lines: string[] = [\n \"\",\n ` ${bold}${green}|--k> @kopai/app${reset} ${dim}v${version}${reset}`,\n \"\",\n ];\n\n const rows: [string, string, string][] = [\n [\"Dashboard\", `http://${localHost}:${port}`, \"\"],\n [\"API Docs\", `http://${localHost}:${port}/documentation`, \"/documentation\"],\n [\"Collector\", `http://${localHost}:${collectorPort}`, \"\"],\n ];\n\n const maxLocalLen = Math.max(...rows.map(([, url]) => url.length));\n\n for (const [label, localUrl, path] of rows) {\n const padded = localUrl.padEnd(maxLocalLen);\n let line = ` ${green}▸${reset} ${bold}${label.padEnd(16)}${reset}${cyan}${padded}${reset}`;\n if (networkAddress) {\n const netPort = label === \"Collector\" ? collectorPort : port;\n const netUrl = `http://${networkAddress}:${netPort}${path}`;\n line += ` ${dim}${cyan}${netUrl}${reset}`;\n }\n lines.push(line);\n }\n\n lines.push(\"\");\n console.log(lines.join(\"\\n\"));\n}\n","import fastify from \"fastify\";\nimport {\n jsonSchemaTransformObject,\n jsonSchemaTransform,\n serializerCompiler,\n validatorCompiler,\n} from \"fastify-type-provider-zod\";\nimport fastifySwagger from \"@fastify/swagger\";\nimport fastifySwaggerUI from \"@fastify/swagger-ui\";\nimport closeWithGrace from \"close-with-grace\";\n\nimport { env } from \"./config.js\";\nimport { version } from \"./version.js\";\nimport { apiRoutes } from \"./routes/index.js\";\nimport { otelCollectorRoutes } from \"./collector/index.js\";\nimport {\n initializeDatabase,\n createOptimizedDatasource,\n DashboardDbDatasource,\n} from \"@kopai/sqlite-datasource\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport FastifyVite from \"@fastify/vite\";\nimport { printStartupBanner } from \"./startup-banner.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction hasComponentSchemas(\n doc: unknown\n): doc is { components: { schemas: Record<string, object> } } {\n return (\n typeof doc === \"object\" &&\n doc !== null &&\n \"components\" in doc &&\n typeof doc.components === \"object\" &&\n doc.components !== null &&\n \"schemas\" in doc.components &&\n typeof doc.components.schemas === \"object\" &&\n doc.components.schemas !== null\n );\n}\n\nconst apiServer = fastify({\n logger: { level: \"warn\" },\n});\n\n// Add schema validator and serializer\napiServer.setValidatorCompiler(validatorCompiler);\napiServer.setSerializerCompiler(serializerCompiler);\n\nconst uiRoutes = [\"/\", \"/*\"];\napiServer.register(fastifySwagger, {\n openapi: {\n info: {\n title: \"Kopai App\",\n description: \"Kopai App documentation\",\n version,\n },\n servers: [],\n },\n transform: ({ schema, url, ...rest }) => {\n if (uiRoutes.includes(url)) return { schema: { hide: true }, url };\n return jsonSchemaTransform({ schema, url, ...rest });\n },\n transformObject: (input) => {\n const result = jsonSchemaTransformObject(input);\n // Fix: z.lazy() recursive schemas generate $ref to schema0\n // but fastify-type-provider-zod doesn't define it in components.\n // Inject the missing schema definition and rename schema0 → AttributeValue.\n const raw = JSON.stringify(result);\n const renamed = raw.replaceAll(\n \"#/components/schemas/schema0\",\n \"#/components/schemas/AttributeValue\"\n );\n const patched: unknown = JSON.parse(renamed);\n if (\n hasComponentSchemas(patched) &&\n !patched.components.schemas.AttributeValue\n ) {\n patched.components.schemas.AttributeValue = {\n anyOf: [\n { type: \"string\" },\n { type: \"number\" },\n { type: \"boolean\" },\n {\n type: \"array\",\n items: { $ref: \"#/components/schemas/AttributeValue\" },\n },\n {\n type: \"object\",\n additionalProperties: {\n $ref: \"#/components/schemas/AttributeValue\",\n },\n },\n ],\n };\n }\n return patched as ReturnType<typeof jsonSchemaTransformObject>;\n },\n});\n\napiServer.register(fastifySwaggerUI, {\n routePrefix: \"/documentation\",\n logo: {\n type: \"image/svg+xml\",\n content: Buffer.from(\n \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPnwtLWsmZ3Q7IGtvcGFpPC90ZXh0Pjwvc3ZnPg==\",\n \"base64\"\n ),\n href: \"/documentation\",\n target: \"_blank\",\n },\n theme: {\n favicon: [\n {\n filename: \"favicon.svg\",\n rel: \"icon\",\n sizes: \"32x32\",\n type: \"image/svg+xml\",\n content: Buffer.from(\n \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjMiIHk9IjIyIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPmsmZ3Q7PC90ZXh0Pjwvc3ZnPg==\",\n \"base64\"\n ),\n },\n ],\n },\n});\n\nconst sqliteDatabase = initializeDatabase(env.SQLITE_DB_FILE_PATH);\nconst telemetryDatasource = createOptimizedDatasource(sqliteDatabase);\nconst dashboardDatasource = new DashboardDbDatasource(sqliteDatabase);\n\napiServer.after(() => {\n apiServer.register(apiRoutes, {\n readTelemetryDatasource: telemetryDatasource,\n dynamicDashboardDatasource: dashboardDatasource,\n });\n apiServer.register(async (fastify) => {\n await fastify.register(FastifyVite, {\n root: resolve(__dirname, \"..\"),\n distDir: \"dist\",\n dev: false,\n spa: true,\n });\n fastify.get(\"/\", (_req, reply) => reply.html());\n fastify.get(\"/*\", (_req, reply) => reply.html());\n await fastify.vite.ready();\n });\n});\n\nconst collectorServer = fastify({\n logger: { level: \"warn\" },\n});\n\ncollectorServer.setValidatorCompiler(validatorCompiler);\ncollectorServer.setSerializerCompiler(serializerCompiler);\n\ncollectorServer.after(() => {\n collectorServer.register(otelCollectorRoutes, {\n telemetryDatasource,\n });\n});\n\nasync function run() {\n await apiServer.ready();\n await collectorServer.ready();\n\n const host = env.HOST || \"localhost\";\n const port = env.PORT;\n const collectorPort = 4318;\n\n await apiServer.listen({ port, host });\n await collectorServer.listen({ port: collectorPort, host });\n\n printStartupBanner({ host, port, collectorPort, version });\n\n apiServer.log.level = \"info\";\n collectorServer.log.level = \"info\";\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n\ncloseWithGrace(async ({ signal, err }) => {\n if (err) {\n collectorServer.log.fatal(\n { err },\n \"Closing OTEL collector server with error\"\n );\n apiServer.log.fatal({ err }, \"Closing API server with error\");\n } else {\n collectorServer.log.info(\n `Received signal ${signal}, closing OTEL collector server`\n );\n apiServer.log.info(`Received signal ${signal}, closing API server`);\n }\n\n await collectorServer.close();\n sqliteDatabase?.close();\n await apiServer.close();\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopai/app",
3
- "version": "0.13.3",
3
+ "version": "0.14.0",
4
4
  "description": "Local OpenTelemetry backend for testing instrumentation - no Docker, no config, just npx",
5
5
  "keywords": [
6
6
  "opentelemetry",
@@ -54,11 +54,11 @@
54
54
  "fastify": "^5.8.2",
55
55
  "fastify-type-provider-zod": "^6.1.0",
56
56
  "zod": "^4.3.6",
57
- "@kopai/api": "0.5.0",
58
- "@kopai/collector": "0.6.2",
59
- "@kopai/core": "0.8.0",
60
- "@kopai/sqlite-datasource": "0.10.0",
61
- "@kopai/ui": "0.9.0"
57
+ "@kopai/api": "0.6.0",
58
+ "@kopai/collector": "0.7.0",
59
+ "@kopai/core": "0.9.0",
60
+ "@kopai/sqlite-datasource": "0.11.0",
61
+ "@kopai/ui": "0.10.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/react": "^19.2.14",
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-CLJTp1Ca.mjs","names":[],"sources":["../src/routes/index.ts","../src/collector/index.ts","../src/startup-banner.ts","../src/server.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { signalsRoutes, dashboardsRoutes } from \"@kopai/api\";\nimport { type datasource, type dashboardDatasource } from \"@kopai/core\";\nimport { generatePromptInstructions, observabilityCatalog } from \"@kopai/ui\";\n\nconst require = createRequire(import.meta.url);\nconst uiPkg = require(\"@kopai/ui/package.json\");\n\nconst promptInstructions = generatePromptInstructions(\n observabilityCatalog,\n uiPkg.version\n);\n\nexport const apiRoutes: FastifyPluginAsyncZod<{\n readTelemetryDatasource: datasource.ReadTelemetryDatasource;\n dynamicDashboardDatasource: dashboardDatasource.DynamicDashboardDatasource;\n}> = async function (fastify, opts) {\n fastify.register(signalsRoutes, {\n readTelemetryDatasource: opts.readTelemetryDatasource,\n });\n fastify.register(dashboardsRoutes, {\n dynamicDashboardDatasource: opts.dynamicDashboardDatasource,\n promptInstructions,\n });\n};\n","import type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { collectorRoutes } from \"@kopai/collector\";\nimport type { datasource } from \"@kopai/core\";\n\nexport const otelCollectorRoutes: FastifyPluginAsyncZod<{\n telemetryDatasource: datasource.WriteTelemetryDatasource;\n}> = async function (fastify, opts) {\n fastify.register(collectorRoutes, opts);\n};\n","import { networkInterfaces } from \"node:os\";\n\nconst isTTY = process.stdout.isTTY;\nconst bold = isTTY ? \"\\x1b[1m\" : \"\";\nconst dim = isTTY ? \"\\x1b[2m\" : \"\";\nconst green = isTTY ? \"\\x1b[32m\" : \"\";\nconst cyan = isTTY ? \"\\x1b[36m\" : \"\";\nconst reset = isTTY ? \"\\x1b[0m\" : \"\";\n\nfunction getNetworkAddress(): string | undefined {\n const nets = networkInterfaces();\n for (const interfaces of Object.values(nets)) {\n if (!interfaces) continue;\n for (const net of interfaces) {\n if (net.family === \"IPv4\" && !net.internal) {\n return net.address;\n }\n }\n }\n return undefined;\n}\n\nexport function printStartupBanner({\n host,\n port,\n collectorPort,\n version,\n}: {\n host: string;\n port: number;\n collectorPort: number;\n version: string;\n}) {\n const localHost = host === \"0.0.0.0\" || host === \"::\" ? \"localhost\" : host;\n const networkAddress = getNetworkAddress();\n\n const lines: string[] = [\n \"\",\n ` ${bold}${green}|--k> @kopai/app${reset} ${dim}v${version}${reset}`,\n \"\",\n ];\n\n const rows: [string, string, string][] = [\n [\"Dashboard\", `http://${localHost}:${port}`, \"\"],\n [\"API Docs\", `http://${localHost}:${port}/documentation`, \"/documentation\"],\n [\"Collector\", `http://${localHost}:${collectorPort}`, \"\"],\n ];\n\n const maxLocalLen = Math.max(...rows.map(([, url]) => url.length));\n\n for (const [label, localUrl, path] of rows) {\n const padded = localUrl.padEnd(maxLocalLen);\n let line = ` ${green}▸${reset} ${bold}${label.padEnd(16)}${reset}${cyan}${padded}${reset}`;\n if (networkAddress) {\n const netPort = label === \"Collector\" ? collectorPort : port;\n const netUrl = `http://${networkAddress}:${netPort}${path}`;\n line += ` ${dim}${cyan}${netUrl}${reset}`;\n }\n lines.push(line);\n }\n\n lines.push(\"\");\n console.log(lines.join(\"\\n\"));\n}\n","import fastify from \"fastify\";\nimport {\n jsonSchemaTransformObject,\n jsonSchemaTransform,\n serializerCompiler,\n validatorCompiler,\n} from \"fastify-type-provider-zod\";\nimport fastifySwagger from \"@fastify/swagger\";\nimport fastifySwaggerUI from \"@fastify/swagger-ui\";\nimport closeWithGrace from \"close-with-grace\";\n\nimport { env } from \"./config.js\";\nimport { version } from \"./version.js\";\nimport { apiRoutes } from \"./routes/index.js\";\nimport { otelCollectorRoutes } from \"./collector/index.js\";\nimport {\n initializeDatabase,\n createOptimizedDatasource,\n DashboardDbDatasource,\n} from \"@kopai/sqlite-datasource\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport FastifyVite from \"@fastify/vite\";\nimport { printStartupBanner } from \"./startup-banner.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction hasComponentSchemas(\n doc: unknown\n): doc is { components: { schemas: Record<string, object> } } {\n return (\n typeof doc === \"object\" &&\n doc !== null &&\n \"components\" in doc &&\n typeof doc.components === \"object\" &&\n doc.components !== null &&\n \"schemas\" in doc.components &&\n typeof doc.components.schemas === \"object\" &&\n doc.components.schemas !== null\n );\n}\n\nconst apiServer = fastify({\n logger: { level: \"warn\" },\n});\n\n// Add schema validator and serializer\napiServer.setValidatorCompiler(validatorCompiler);\napiServer.setSerializerCompiler(serializerCompiler);\n\nconst uiRoutes = [\"/\", \"/*\"];\napiServer.register(fastifySwagger, {\n openapi: {\n info: {\n title: \"Kopai App\",\n description: \"Kopai App documentation\",\n version,\n },\n servers: [],\n },\n transform: ({ schema, url, ...rest }) => {\n if (uiRoutes.includes(url)) return { schema: { hide: true }, url };\n return jsonSchemaTransform({ schema, url, ...rest });\n },\n transformObject: (input) => {\n const result = jsonSchemaTransformObject(input);\n // Fix: z.lazy() recursive schemas generate $ref to schema0\n // but fastify-type-provider-zod doesn't define it in components.\n // Inject the missing schema definition and rename schema0 → AttributeValue.\n const raw = JSON.stringify(result);\n const renamed = raw.replaceAll(\n \"#/components/schemas/schema0\",\n \"#/components/schemas/AttributeValue\"\n );\n const patched: unknown = JSON.parse(renamed);\n if (\n hasComponentSchemas(patched) &&\n !patched.components.schemas.AttributeValue\n ) {\n patched.components.schemas.AttributeValue = {\n anyOf: [\n { type: \"string\" },\n { type: \"number\" },\n { type: \"boolean\" },\n {\n type: \"array\",\n items: { $ref: \"#/components/schemas/AttributeValue\" },\n },\n {\n type: \"object\",\n additionalProperties: {\n $ref: \"#/components/schemas/AttributeValue\",\n },\n },\n ],\n };\n }\n return patched as ReturnType<typeof jsonSchemaTransformObject>;\n },\n});\n\napiServer.register(fastifySwaggerUI, {\n routePrefix: \"/documentation\",\n logo: {\n type: \"image/svg+xml\",\n content: Buffer.from(\n \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPnwtLWsmZ3Q7IGtvcGFpPC90ZXh0Pjwvc3ZnPg==\",\n \"base64\"\n ),\n href: \"/documentation\",\n target: \"_blank\",\n },\n theme: {\n favicon: [\n {\n filename: \"favicon.svg\",\n rel: \"icon\",\n sizes: \"32x32\",\n type: \"image/svg+xml\",\n content: Buffer.from(\n \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjMiIHk9IjIyIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPmsmZ3Q7PC90ZXh0Pjwvc3ZnPg==\",\n \"base64\"\n ),\n },\n ],\n },\n});\n\nconst sqliteDatabase = initializeDatabase(env.SQLITE_DB_FILE_PATH);\nconst telemetryDatasource = createOptimizedDatasource(sqliteDatabase);\nconst dashboardDatasource = new DashboardDbDatasource(sqliteDatabase);\n\napiServer.after(() => {\n apiServer.register(apiRoutes, {\n readTelemetryDatasource: telemetryDatasource,\n dynamicDashboardDatasource: dashboardDatasource,\n });\n apiServer.register(async (fastify) => {\n await fastify.register(FastifyVite, {\n root: resolve(__dirname, \"..\"),\n distDir: \"dist\",\n dev: false,\n spa: true,\n });\n fastify.get(\"/\", (_req, reply) => reply.html());\n fastify.get(\"/*\", (_req, reply) => reply.html());\n await fastify.vite.ready();\n });\n});\n\nconst collectorServer = fastify({\n logger: { level: \"warn\" },\n});\n\ncollectorServer.setValidatorCompiler(validatorCompiler);\ncollectorServer.setSerializerCompiler(serializerCompiler);\n\ncollectorServer.after(() => {\n collectorServer.register(otelCollectorRoutes, {\n telemetryDatasource,\n });\n});\n\nasync function run() {\n await apiServer.ready();\n await collectorServer.ready();\n\n const host = env.HOST || \"localhost\";\n const port = env.PORT;\n const collectorPort = 4318;\n\n await apiServer.listen({ port, host });\n await collectorServer.listen({ port: collectorPort, host });\n\n printStartupBanner({ host, port, collectorPort, version });\n\n apiServer.log.level = \"info\";\n collectorServer.log.level = \"info\";\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n\ncloseWithGrace(async ({ signal, err }) => {\n if (err) {\n collectorServer.log.fatal(\n { err },\n \"Closing OTEL collector server with error\"\n );\n apiServer.log.fatal({ err }, \"Closing API server with error\");\n } else {\n collectorServer.log.info(\n `Received signal ${signal}, closing OTEL collector server`\n );\n apiServer.log.info(`Received signal ${signal}, closing API server`);\n }\n\n await collectorServer.close();\n sqliteDatabase?.close();\n await apiServer.close();\n});\n"],"mappings":"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"}