@kopai/app 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Kopai</title>
7
+ <link
8
+ rel="icon"
9
+ type="image/svg+xml"
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
+ />
12
+ <script type="module" crossorigin src="/assets/index-oJZ3KchX.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-C5X3Abtu.css">
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,14 @@
1
+ {
2
+ "base": "/",
3
+ "root": "/home/runner/work/kopai-mono/kopai-mono/packages/app/src/client",
4
+ "build": {
5
+ "assetsDir": "assets",
6
+ "outDir": "/home/runner/work/kopai-mono/kopai-mono/packages/app/dist/client/client"
7
+ },
8
+ "fastify": {
9
+ "outDirs": {
10
+ "client": "/home/runner/work/kopai-mono/kopai-mono/packages/app/dist/client/client"
11
+ },
12
+ "entryPaths": {}
13
+ }
14
+ }
@@ -9,6 +9,9 @@ import { signalsRoutes } from "@kopai/api";
9
9
  import "@kopai/core";
10
10
  import { collectorRoutes } from "@kopai/collector";
11
11
  import { createOptimizedDatasource, initializeDatabase } from "@kopai/sqlite-datasource";
12
+ import { dirname, resolve } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import FastifyVite from "@fastify/vite";
12
15
 
13
16
  //#region src/routes/index.ts
14
17
  const apiRoutes = async function(fastify, opts) {
@@ -23,9 +26,11 @@ const otelCollectorRoutes = async function(fastify, opts) {
23
26
 
24
27
  //#endregion
25
28
  //#region src/server.ts
29
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
30
  const apiServer = fastify({ logger: true });
27
31
  apiServer.setValidatorCompiler(validatorCompiler);
28
32
  apiServer.setSerializerCompiler(serializerCompiler);
33
+ const uiRoutes = ["/", "/*"];
29
34
  apiServer.register(fastifySwagger, {
30
35
  openapi: {
31
36
  info: {
@@ -35,14 +40,24 @@ apiServer.register(fastifySwagger, {
35
40
  },
36
41
  servers: []
37
42
  },
38
- transform: jsonSchemaTransform,
43
+ transform: ({ schema, url, ...rest }) => {
44
+ if (uiRoutes.includes(url)) return {
45
+ schema: { hide: true },
46
+ url
47
+ };
48
+ return jsonSchemaTransform({
49
+ schema,
50
+ url,
51
+ ...rest
52
+ });
53
+ },
39
54
  transformObject: jsonSchemaTransformObject
40
55
  });
41
56
  apiServer.register(fastifySwaggerUI, {
42
57
  routePrefix: "/documentation",
43
58
  logo: {
44
59
  type: "image/svg+xml",
45
- content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0iU3BhY2UgR3JvdGVzaywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjI0IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5Lb3BhaTwvdGV4dD48L3N2Zz4K", "base64"),
60
+ content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPnwtLWsmZ3Q7IGtvcGFpPC90ZXh0Pjwvc3ZnPg==", "base64"),
46
61
  href: "/documentation",
47
62
  target: "_blank"
48
63
  },
@@ -51,13 +66,24 @@ apiServer.register(fastifySwaggerUI, {
51
66
  rel: "icon",
52
67
  sizes: "32x32",
53
68
  type: "image/svg+xml",
54
- content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjQiIHk9IjIzIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5LPC90ZXh0Pjwvc3ZnPgo=", "base64")
69
+ content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjMiIHk9IjIyIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPmsmZ3Q7PC90ZXh0Pjwvc3ZnPg==", "base64")
55
70
  }] }
56
71
  });
57
72
  const sqliteDatabase = initializeDatabase(env.SQLITE_DB_FILE_PATH);
58
73
  const telemetryDatasource = createOptimizedDatasource(sqliteDatabase);
59
74
  apiServer.after(() => {
60
75
  apiServer.register(apiRoutes, { readTelemetryDatasource: telemetryDatasource });
76
+ apiServer.register(async (fastify) => {
77
+ await fastify.register(FastifyVite, {
78
+ root: resolve(__dirname, ".."),
79
+ distDir: resolve(__dirname, "..", "dist", "client"),
80
+ dev: false,
81
+ spa: true
82
+ });
83
+ fastify.get("/", (_req, reply) => reply.html());
84
+ fastify.get("/*", (_req, reply) => reply.html());
85
+ await fastify.vite.ready();
86
+ });
61
87
  });
62
88
  const collectorServer = fastify({ logger: true });
63
89
  collectorServer.setValidatorCompiler(validatorCompiler);
@@ -66,7 +92,7 @@ collectorServer.after(() => {
66
92
  collectorServer.register(otelCollectorRoutes, { telemetryDatasource });
67
93
  });
68
94
  async function run() {
69
- console.log(`@kopai/app v${version}`);
95
+ console.log(`|--k> @kopai/app v${version}\n\n`);
70
96
  await apiServer.ready();
71
97
  const host = env.HOST || "localhost";
72
98
  const port = env.PORT;
@@ -114,4 +140,4 @@ closeWithGrace(async ({ signal, err }) => {
114
140
 
115
141
  //#endregion
116
142
  export { };
117
- //# sourceMappingURL=server-2JXtBWDI.mjs.map
143
+ //# sourceMappingURL=server-CTsaV_8O.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-CTsaV_8O.mjs","names":[],"sources":["../src/routes/index.ts","../src/collector/index.ts","../src/server.ts"],"sourcesContent":["import type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { signalsRoutes } from \"@kopai/api\";\nimport { type datasource } from \"@kopai/core\";\n\nexport const apiRoutes: FastifyPluginAsyncZod<{\n readTelemetryDatasource: datasource.ReadTelemetryDatasource;\n}> = async function (fastify, opts) {\n fastify.register(signalsRoutes, {\n readTelemetryDatasource: opts.readTelemetryDatasource,\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 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} from \"@kopai/sqlite-datasource\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport FastifyVite from \"@fastify/vite\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst apiServer = fastify({\n logger: true,\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: jsonSchemaTransformObject,\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);\n\napiServer.after(() => {\n apiServer.register(apiRoutes, {\n readTelemetryDatasource: telemetryDatasource,\n });\n apiServer.register(async (fastify) => {\n await fastify.register(FastifyVite, {\n root: resolve(__dirname, \"..\"),\n distDir: resolve(__dirname, \"..\", \"dist\", \"client\"),\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: true,\n});\n\ncollectorServer.setValidatorCompiler(validatorCompiler);\ncollectorServer.setSerializerCompiler(serializerCompiler);\n\ncollectorServer.after(() => {\n collectorServer.register(otelCollectorRoutes, {\n telemetryDatasource,\n });\n});\n\nasync function run() {\n console.log(`|--k> @kopai/app v${version}\\n\\n`);\n\n await apiServer.ready();\n\n const host = env.HOST || \"localhost\";\n const port = env.PORT;\n const STANDARD_OTEL_HTTP_COLLECTOR_PORT = 4318;\n\n apiServer.listen(\n {\n port,\n host,\n listenTextResolver(address) {\n return `API server listening at ${address}`;\n },\n },\n (err, address) => {\n if (err) {\n console.error(err);\n process.exit(1);\n }\n apiServer.log.info(\n `API server documentation available at ${address}/documentation`\n );\n }\n );\n\n await collectorServer.ready();\n\n collectorServer.listen(\n {\n port: STANDARD_OTEL_HTTP_COLLECTOR_PORT,\n host,\n listenTextResolver(address) {\n return `OTEL collector server listening at ${address}:${STANDARD_OTEL_HTTP_COLLECTOR_PORT}`;\n },\n },\n (err) => {\n if (err) {\n console.error(err);\n process.exit(1);\n }\n }\n );\n}\n\nrun();\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":";;;;;;;;;;;;;;;;AAIA,MAAa,YAER,eAAgB,SAAS,MAAM;AAClC,SAAQ,SAAS,eAAe,EAC9B,yBAAyB,KAAK,yBAC/B,CAAC;;;;;ACLJ,MAAa,sBAER,eAAgB,SAAS,MAAM;AAClC,SAAQ,SAAS,iBAAiB,KAAK;;;;;ACgBzC,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAEzD,MAAM,YAAY,QAAQ,EACxB,QAAQ,MACT,CAAC;AAGF,UAAU,qBAAqB,kBAAkB;AACjD,UAAU,sBAAsB,mBAAmB;AAEnD,MAAM,WAAW,CAAC,KAAK,KAAK;AAC5B,UAAU,SAAS,gBAAgB;CACjC,SAAS;EACP,MAAM;GACJ,OAAO;GACP,aAAa;GACb;GACD;EACD,SAAS,EAAE;EACZ;CACD,YAAY,EAAE,QAAQ,KAAK,GAAG,WAAW;AACvC,MAAI,SAAS,SAAS,IAAI,CAAE,QAAO;GAAE,QAAQ,EAAE,MAAM,MAAM;GAAE;GAAK;AAClE,SAAO,oBAAoB;GAAE;GAAQ;GAAK,GAAG;GAAM,CAAC;;CAEtD,iBAAiB;CAClB,CAAC;AAEF,UAAU,SAAS,kBAAkB;CACnC,aAAa;CACb,MAAM;EACJ,MAAM;EACN,SAAS,OAAO,KACd,wRACA,SACD;EACD,MAAM;EACN,QAAQ;EACT;CACD,OAAO,EACL,SAAS,CACP;EACE,UAAU;EACV,KAAK;EACL,OAAO;EACP,MAAM;EACN,SAAS,OAAO,KACd,gVACA,SACD;EACF,CACF,EACF;CACF,CAAC;AAEF,MAAM,iBAAiB,mBAAmB,IAAI,oBAAoB;AAClE,MAAM,sBAAsB,0BAA0B,eAAe;AAErE,UAAU,YAAY;AACpB,WAAU,SAAS,WAAW,EAC5B,yBAAyB,qBAC1B,CAAC;AACF,WAAU,SAAS,OAAO,YAAY;AACpC,QAAM,QAAQ,SAAS,aAAa;GAClC,MAAM,QAAQ,WAAW,KAAK;GAC9B,SAAS,QAAQ,WAAW,MAAM,QAAQ,SAAS;GACnD,KAAK;GACL,KAAK;GACN,CAAC;AACF,UAAQ,IAAI,MAAM,MAAM,UAAU,MAAM,MAAM,CAAC;AAC/C,UAAQ,IAAI,OAAO,MAAM,UAAU,MAAM,MAAM,CAAC;AAChD,QAAM,QAAQ,KAAK,OAAO;GAC1B;EACF;AAEF,MAAM,kBAAkB,QAAQ,EAC9B,QAAQ,MACT,CAAC;AAEF,gBAAgB,qBAAqB,kBAAkB;AACvD,gBAAgB,sBAAsB,mBAAmB;AAEzD,gBAAgB,YAAY;AAC1B,iBAAgB,SAAS,qBAAqB,EAC5C,qBACD,CAAC;EACF;AAEF,eAAe,MAAM;AACnB,SAAQ,IAAI,qBAAqB,QAAQ,MAAM;AAE/C,OAAM,UAAU,OAAO;CAEvB,MAAM,OAAO,IAAI,QAAQ;CACzB,MAAM,OAAO,IAAI;CACjB,MAAM,oCAAoC;AAE1C,WAAU,OACR;EACE;EACA;EACA,mBAAmB,SAAS;AAC1B,UAAO,2BAA2B;;EAErC,GACA,KAAK,YAAY;AAChB,MAAI,KAAK;AACP,WAAQ,MAAM,IAAI;AAClB,WAAQ,KAAK,EAAE;;AAEjB,YAAU,IAAI,KACZ,yCAAyC,QAAQ,gBAClD;GAEJ;AAED,OAAM,gBAAgB,OAAO;AAE7B,iBAAgB,OACd;EACE,MAAM;EACN;EACA,mBAAmB,SAAS;AAC1B,UAAO,sCAAsC,QAAQ,GAAG;;EAE3D,GACA,QAAQ;AACP,MAAI,KAAK;AACP,WAAQ,MAAM,IAAI;AAClB,WAAQ,KAAK,EAAE;;GAGpB;;AAGH,KAAK;AAEL,eAAe,OAAO,EAAE,QAAQ,UAAU;AACxC,KAAI,KAAK;AACP,kBAAgB,IAAI,MAClB,EAAE,KAAK,EACP,2CACD;AACD,YAAU,IAAI,MAAM,EAAE,KAAK,EAAE,gCAAgC;QACxD;AACL,kBAAgB,IAAI,KAClB,mBAAmB,OAAO,iCAC3B;AACD,YAAU,IAAI,KAAK,mBAAmB,OAAO,sBAAsB;;AAGrE,OAAM,gBAAgB,OAAO;AAC7B,iBAAgB,OAAO;AACvB,OAAM,UAAU,OAAO;EACvB"}
@@ -13,6 +13,10 @@ let _kopai_api = require("@kopai/api");
13
13
  require("@kopai/core");
14
14
  let _kopai_collector = require("@kopai/collector");
15
15
  let _kopai_sqlite_datasource = require("@kopai/sqlite-datasource");
16
+ let node_path = require("node:path");
17
+ let node_url = require("node:url");
18
+ let _fastify_vite = require("@fastify/vite");
19
+ _fastify_vite = require_config.__toESM(_fastify_vite);
16
20
 
17
21
  //#region src/routes/index.ts
18
22
  const apiRoutes = async function(fastify, opts) {
@@ -27,9 +31,11 @@ const otelCollectorRoutes = async function(fastify, opts) {
27
31
 
28
32
  //#endregion
29
33
  //#region src/server.ts
34
+ const __dirname$1 = (0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
30
35
  const apiServer = (0, fastify.default)({ logger: true });
31
36
  apiServer.setValidatorCompiler(fastify_type_provider_zod.validatorCompiler);
32
37
  apiServer.setSerializerCompiler(fastify_type_provider_zod.serializerCompiler);
38
+ const uiRoutes = ["/", "/*"];
33
39
  apiServer.register(_fastify_swagger.default, {
34
40
  openapi: {
35
41
  info: {
@@ -39,14 +45,24 @@ apiServer.register(_fastify_swagger.default, {
39
45
  },
40
46
  servers: []
41
47
  },
42
- transform: fastify_type_provider_zod.jsonSchemaTransform,
48
+ transform: ({ schema, url, ...rest }) => {
49
+ if (uiRoutes.includes(url)) return {
50
+ schema: { hide: true },
51
+ url
52
+ };
53
+ return (0, fastify_type_provider_zod.jsonSchemaTransform)({
54
+ schema,
55
+ url,
56
+ ...rest
57
+ });
58
+ },
43
59
  transformObject: fastify_type_provider_zod.jsonSchemaTransformObject
44
60
  });
45
61
  apiServer.register(_fastify_swagger_ui.default, {
46
62
  routePrefix: "/documentation",
47
63
  logo: {
48
64
  type: "image/svg+xml",
49
- content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0iU3BhY2UgR3JvdGVzaywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjI0IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5Lb3BhaTwvdGV4dD48L3N2Zz4K", "base64"),
65
+ content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMjAiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPnwtLWsmZ3Q7IGtvcGFpPC90ZXh0Pjwvc3ZnPg==", "base64"),
50
66
  href: "/documentation",
51
67
  target: "_blank"
52
68
  },
@@ -55,13 +71,24 @@ apiServer.register(_fastify_swagger_ui.default, {
55
71
  rel: "icon",
56
72
  sizes: "32x32",
57
73
  type: "image/svg+xml",
58
- content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjQiIHk9IjIzIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5LPC90ZXh0Pjwvc3ZnPgo=", "base64")
74
+ content: Buffer.from("PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSI+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjMiIHk9IjIyIiBmb250LWZhbWlseT0idWktbW9ub3NwYWNlLCBtb25vc3BhY2UiIGZvbnQtc2l6ZT0iMTYiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiNmYWZhZmEiPmsmZ3Q7PC90ZXh0Pjwvc3ZnPg==", "base64")
59
75
  }] }
60
76
  });
61
77
  const sqliteDatabase = (0, _kopai_sqlite_datasource.initializeDatabase)(require_config.env.SQLITE_DB_FILE_PATH);
62
78
  const telemetryDatasource = (0, _kopai_sqlite_datasource.createOptimizedDatasource)(sqliteDatabase);
63
79
  apiServer.after(() => {
64
80
  apiServer.register(apiRoutes, { readTelemetryDatasource: telemetryDatasource });
81
+ apiServer.register(async (fastify$2) => {
82
+ await fastify$2.register(_fastify_vite.default, {
83
+ root: (0, node_path.resolve)(__dirname$1, ".."),
84
+ distDir: (0, node_path.resolve)(__dirname$1, "..", "dist", "client"),
85
+ dev: false,
86
+ spa: true
87
+ });
88
+ fastify$2.get("/", (_req, reply) => reply.html());
89
+ fastify$2.get("/*", (_req, reply) => reply.html());
90
+ await fastify$2.vite.ready();
91
+ });
65
92
  });
66
93
  const collectorServer = (0, fastify.default)({ logger: true });
67
94
  collectorServer.setValidatorCompiler(fastify_type_provider_zod.validatorCompiler);
@@ -70,7 +97,7 @@ collectorServer.after(() => {
70
97
  collectorServer.register(otelCollectorRoutes, { telemetryDatasource });
71
98
  });
72
99
  async function run() {
73
- console.log(`@kopai/app v${require_cli.version}`);
100
+ console.log(`|--k> @kopai/app v${require_cli.version}\n\n`);
74
101
  await apiServer.ready();
75
102
  const host = require_config.env.HOST || "localhost";
76
103
  const port = require_config.env.PORT;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopai/app",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Local OpenTelemetry backend for testing instrumentation - no Docker, no config, just npx",
5
5
  "keywords": [
6
6
  "opentelemetry",
@@ -47,6 +47,7 @@
47
47
  "dist"
48
48
  ],
49
49
  "dependencies": {
50
+ "@fastify/vite": "^8.1.0",
50
51
  "@fastify/swagger": "^9.7.0",
51
52
  "@fastify/swagger-ui": "^5.2.5",
52
53
  "close-with-grace": "^2.4.0",
@@ -55,16 +56,27 @@
55
56
  "zod": "^4.3.6",
56
57
  "@kopai/api": "0.2.3",
57
58
  "@kopai/collector": "0.4.0",
58
- "@kopai/sqlite-datasource": "0.5.0",
59
- "@kopai/core": "0.5.0"
59
+ "@kopai/sqlite-datasource": "0.6.0",
60
+ "@kopai/core": "0.5.0",
61
+ "@kopai/ui": "0.1.0"
60
62
  },
61
63
  "devDependencies": {
64
+ "@types/react": "^19.2.10",
65
+ "@types/react-dom": "^19.1.0",
66
+ "@vitejs/plugin-react": "^4.5.2",
67
+ "autoprefixer": "^10.4.20",
68
+ "postcss": "^8.5.3",
69
+ "react": "^19.2.4",
70
+ "react-dom": "^19.2.4",
71
+ "tailwindcss": "^3.4.17",
62
72
  "tsdown": "^0.20.3",
63
73
  "typescript": "^5.9.3",
74
+ "vite": "^6.3.5",
64
75
  "@kopai/tsconfig": "0.2.0"
65
76
  },
66
77
  "scripts": {
67
- "build": "tsdown",
78
+ "build": "tsdown && vite build",
79
+ "build:client": "vite build",
68
80
  "dev": "node --env-file-if-exists=.env ./dist/cli.mjs start",
69
81
  "lint": "eslint src",
70
82
  "type-check": "tsc --noEmit",
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-2JXtBWDI.mjs","names":[],"sources":["../src/routes/index.ts","../src/collector/index.ts","../src/server.ts"],"sourcesContent":["import type { FastifyPluginAsyncZod } from \"fastify-type-provider-zod\";\nimport { signalsRoutes } from \"@kopai/api\";\nimport { type datasource } from \"@kopai/core\";\n\nexport const apiRoutes: FastifyPluginAsyncZod<{\n readTelemetryDatasource: datasource.ReadTelemetryDatasource;\n}> = async function (fastify, opts) {\n fastify.register(signalsRoutes, {\n readTelemetryDatasource: opts.readTelemetryDatasource,\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 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} from \"@kopai/sqlite-datasource\";\n\nconst apiServer = fastify({\n logger: true,\n});\n\n// Add schema validator and serializer\napiServer.setValidatorCompiler(validatorCompiler);\napiServer.setSerializerCompiler(serializerCompiler);\n\napiServer.register(fastifySwagger, {\n openapi: {\n info: {\n title: \"Kopai App\",\n description: \"Kopai App documentation\",\n version,\n },\n servers: [],\n },\n transform: jsonSchemaTransform,\n transformObject: jsonSchemaTransformObject,\n});\n\napiServer.register(fastifySwaggerUI, {\n routePrefix: \"/documentation\",\n logo: {\n type: \"image/svg+xml\",\n content: Buffer.from(\n \"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAgNDAiIGZpbGw9Im5vbmUiPjx0ZXh0IHg9IjAiIHk9IjI4IiBmb250LWZhbWlseT0iU3BhY2UgR3JvdGVzaywgc3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjI0IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5Lb3BhaTwvdGV4dD48L3N2Zz4K\",\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+PHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iNCIgZmlsbD0iIzBhMGEwYSIvPjx0ZXh0IHg9IjQiIHk9IjIzIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjE4IiBmb250LXdlaWdodD0iNzAwIiBmaWxsPSIjZmFmYWZhIj5LPC90ZXh0Pjwvc3ZnPgo=\",\n \"base64\"\n ),\n },\n ],\n },\n});\n\nconst sqliteDatabase = initializeDatabase(env.SQLITE_DB_FILE_PATH);\nconst telemetryDatasource = createOptimizedDatasource(sqliteDatabase);\n\napiServer.after(() => {\n apiServer.register(apiRoutes, {\n readTelemetryDatasource: telemetryDatasource,\n });\n});\n\nconst collectorServer = fastify({\n logger: true,\n});\n\ncollectorServer.setValidatorCompiler(validatorCompiler);\ncollectorServer.setSerializerCompiler(serializerCompiler);\n\ncollectorServer.after(() => {\n collectorServer.register(otelCollectorRoutes, {\n telemetryDatasource,\n });\n});\n\nasync function run() {\n console.log(`@kopai/app v${version}`);\n\n await apiServer.ready();\n\n const host = env.HOST || \"localhost\";\n const port = env.PORT;\n const STANDARD_OTEL_HTTP_COLLECTOR_PORT = 4318;\n\n apiServer.listen(\n {\n port,\n host,\n listenTextResolver(address) {\n return `API server listening at ${address}`;\n },\n },\n (err, address) => {\n if (err) {\n console.error(err);\n process.exit(1);\n }\n apiServer.log.info(\n `API server documentation available at ${address}/documentation`\n );\n }\n );\n\n await collectorServer.ready();\n\n collectorServer.listen(\n {\n port: STANDARD_OTEL_HTTP_COLLECTOR_PORT,\n host,\n listenTextResolver(address) {\n return `OTEL collector server listening at ${address}:${STANDARD_OTEL_HTTP_COLLECTOR_PORT}`;\n },\n },\n (err) => {\n if (err) {\n console.error(err);\n process.exit(1);\n }\n }\n );\n}\n\nrun();\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":";;;;;;;;;;;;;AAIA,MAAa,YAER,eAAgB,SAAS,MAAM;AAClC,SAAQ,SAAS,eAAe,EAC9B,yBAAyB,KAAK,yBAC/B,CAAC;;;;;ACLJ,MAAa,sBAER,eAAgB,SAAS,MAAM;AAClC,SAAQ,SAAS,iBAAiB,KAAK;;;;;ACazC,MAAM,YAAY,QAAQ,EACxB,QAAQ,MACT,CAAC;AAGF,UAAU,qBAAqB,kBAAkB;AACjD,UAAU,sBAAsB,mBAAmB;AAEnD,UAAU,SAAS,gBAAgB;CACjC,SAAS;EACP,MAAM;GACJ,OAAO;GACP,aAAa;GACb;GACD;EACD,SAAS,EAAE;EACZ;CACD,WAAW;CACX,iBAAiB;CAClB,CAAC;AAEF,UAAU,SAAS,kBAAkB;CACnC,aAAa;CACb,MAAM;EACJ,MAAM;EACN,SAAS,OAAO,KACd,4RACA,SACD;EACD,MAAM;EACN,QAAQ;EACT;CACD,OAAO,EACL,SAAS,CACP;EACE,UAAU;EACV,KAAK;EACL,OAAO;EACP,MAAM;EACN,SAAS,OAAO,KACd,wUACA,SACD;EACF,CACF,EACF;CACF,CAAC;AAEF,MAAM,iBAAiB,mBAAmB,IAAI,oBAAoB;AAClE,MAAM,sBAAsB,0BAA0B,eAAe;AAErE,UAAU,YAAY;AACpB,WAAU,SAAS,WAAW,EAC5B,yBAAyB,qBAC1B,CAAC;EACF;AAEF,MAAM,kBAAkB,QAAQ,EAC9B,QAAQ,MACT,CAAC;AAEF,gBAAgB,qBAAqB,kBAAkB;AACvD,gBAAgB,sBAAsB,mBAAmB;AAEzD,gBAAgB,YAAY;AAC1B,iBAAgB,SAAS,qBAAqB,EAC5C,qBACD,CAAC;EACF;AAEF,eAAe,MAAM;AACnB,SAAQ,IAAI,eAAe,UAAU;AAErC,OAAM,UAAU,OAAO;CAEvB,MAAM,OAAO,IAAI,QAAQ;CACzB,MAAM,OAAO,IAAI;CACjB,MAAM,oCAAoC;AAE1C,WAAU,OACR;EACE;EACA;EACA,mBAAmB,SAAS;AAC1B,UAAO,2BAA2B;;EAErC,GACA,KAAK,YAAY;AAChB,MAAI,KAAK;AACP,WAAQ,MAAM,IAAI;AAClB,WAAQ,KAAK,EAAE;;AAEjB,YAAU,IAAI,KACZ,yCAAyC,QAAQ,gBAClD;GAEJ;AAED,OAAM,gBAAgB,OAAO;AAE7B,iBAAgB,OACd;EACE,MAAM;EACN;EACA,mBAAmB,SAAS;AAC1B,UAAO,sCAAsC,QAAQ,GAAG;;EAE3D,GACA,QAAQ;AACP,MAAI,KAAK;AACP,WAAQ,MAAM,IAAI;AAClB,WAAQ,KAAK,EAAE;;GAGpB;;AAGH,KAAK;AAEL,eAAe,OAAO,EAAE,QAAQ,UAAU;AACxC,KAAI,KAAK;AACP,kBAAgB,IAAI,MAClB,EAAE,KAAK,EACP,2CACD;AACD,YAAU,IAAI,MAAM,EAAE,KAAK,EAAE,gCAAgC;QACxD;AACL,kBAAgB,IAAI,KAClB,mBAAmB,OAAO,iCAC3B;AACD,YAAU,IAAI,KAAK,mBAAmB,OAAO,sBAAsB;;AAGrE,OAAM,gBAAgB,OAAO;AAC7B,iBAAgB,OAAO;AACvB,OAAM,UAAU,OAAO;EACvB"}