@kopai/app 0.3.0 → 0.4.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.
package/dist/cli.cjs CHANGED
@@ -51,7 +51,7 @@ if (values.help || command === "help" || !command) {
51
51
  showHelp();
52
52
  process.exit(0);
53
53
  }
54
- if (command === "start") Promise.resolve().then(() => require("./server-Bci2-vxj.cjs"));
54
+ if (command === "start") Promise.resolve().then(() => require("./server-BueiBhZ-.cjs"));
55
55
  else {
56
56
  console.error(`Unknown command: ${command}`);
57
57
  showHelp();
package/dist/cli.mjs CHANGED
@@ -50,7 +50,7 @@ if (values.help || command === "help" || !command) {
50
50
  showHelp();
51
51
  process.exit(0);
52
52
  }
53
- if (command === "start") import("./server-DZHgJbDT.mjs");
53
+ if (command === "start") import("./server-2JXtBWDI.mjs");
54
54
  else {
55
55
  console.error(`Unknown command: ${command}`);
56
56
  showHelp();
@@ -8,7 +8,7 @@ import closeWithGrace from "close-with-grace";
8
8
  import { signalsRoutes } from "@kopai/api";
9
9
  import "@kopai/core";
10
10
  import { collectorRoutes } from "@kopai/collector";
11
- import { NodeSqliteTelemetryDatasource, initializeDatabase } from "@kopai/sqlite-datasource";
11
+ import { createOptimizedDatasource, initializeDatabase } from "@kopai/sqlite-datasource";
12
12
 
13
13
  //#region src/routes/index.ts
14
14
  const apiRoutes = async function(fastify, opts) {
@@ -55,15 +55,14 @@ apiServer.register(fastifySwaggerUI, {
55
55
  }] }
56
56
  });
57
57
  const sqliteDatabase = initializeDatabase(env.SQLITE_DB_FILE_PATH);
58
+ const telemetryDatasource = createOptimizedDatasource(sqliteDatabase);
58
59
  apiServer.after(() => {
59
- const telemetryDatasource = new NodeSqliteTelemetryDatasource(sqliteDatabase);
60
60
  apiServer.register(apiRoutes, { readTelemetryDatasource: telemetryDatasource });
61
61
  });
62
62
  const collectorServer = fastify({ logger: true });
63
63
  collectorServer.setValidatorCompiler(validatorCompiler);
64
64
  collectorServer.setSerializerCompiler(serializerCompiler);
65
- collectorServer.after(async () => {
66
- const telemetryDatasource = new NodeSqliteTelemetryDatasource(sqliteDatabase);
65
+ collectorServer.after(() => {
67
66
  collectorServer.register(otelCollectorRoutes, { telemetryDatasource });
68
67
  });
69
68
  async function run() {
@@ -115,4 +114,4 @@ closeWithGrace(async ({ signal, err }) => {
115
114
 
116
115
  //#endregion
117
116
  export { };
118
- //# sourceMappingURL=server-DZHgJbDT.mjs.map
117
+ //# sourceMappingURL=server-2JXtBWDI.mjs.map
@@ -0,0 +1 @@
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"}
@@ -59,15 +59,14 @@ apiServer.register(_fastify_swagger_ui.default, {
59
59
  }] }
60
60
  });
61
61
  const sqliteDatabase = (0, _kopai_sqlite_datasource.initializeDatabase)(require_config.env.SQLITE_DB_FILE_PATH);
62
+ const telemetryDatasource = (0, _kopai_sqlite_datasource.createOptimizedDatasource)(sqliteDatabase);
62
63
  apiServer.after(() => {
63
- const telemetryDatasource = new _kopai_sqlite_datasource.NodeSqliteTelemetryDatasource(sqliteDatabase);
64
64
  apiServer.register(apiRoutes, { readTelemetryDatasource: telemetryDatasource });
65
65
  });
66
66
  const collectorServer = (0, fastify.default)({ logger: true });
67
67
  collectorServer.setValidatorCompiler(fastify_type_provider_zod.validatorCompiler);
68
68
  collectorServer.setSerializerCompiler(fastify_type_provider_zod.serializerCompiler);
69
- collectorServer.after(async () => {
70
- const telemetryDatasource = new _kopai_sqlite_datasource.NodeSqliteTelemetryDatasource(sqliteDatabase);
69
+ collectorServer.after(() => {
71
70
  collectorServer.register(otelCollectorRoutes, { telemetryDatasource });
72
71
  });
73
72
  async function run() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopai/app",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Local OpenTelemetry backend for testing instrumentation - no Docker, no config, just npx",
5
5
  "keywords": [
6
6
  "opentelemetry",
@@ -48,15 +48,15 @@
48
48
  ],
49
49
  "dependencies": {
50
50
  "@fastify/swagger": "^9.6.1",
51
- "@fastify/swagger-ui": "^5.2.4",
51
+ "@fastify/swagger-ui": "^5.2.5",
52
52
  "close-with-grace": "^2.4.0",
53
53
  "fastify": "^5.7.2",
54
54
  "fastify-type-provider-zod": "^6.1.0",
55
55
  "zod": "^4.3.6",
56
- "@kopai/api": "0.2.2",
57
- "@kopai/collector": "0.3.0",
58
- "@kopai/core": "0.4.0",
59
- "@kopai/sqlite-datasource": "0.4.0"
56
+ "@kopai/api": "0.2.3",
57
+ "@kopai/collector": "0.3.1",
58
+ "@kopai/core": "0.5.0",
59
+ "@kopai/sqlite-datasource": "0.5.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "nodemon": "^3.1.11",
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-DZHgJbDT.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 NodeSqliteTelemetryDatasource,\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);\n\napiServer.after(() => {\n const telemetryDatasource = new NodeSqliteTelemetryDatasource(sqliteDatabase);\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(async () => {\n const telemetryDatasource = new NodeSqliteTelemetryDatasource(sqliteDatabase);\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;AAElE,UAAU,YAAY;CACpB,MAAM,sBAAsB,IAAI,8BAA8B,eAAe;AAC7E,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,MAAM,YAAY;CAChC,MAAM,sBAAsB,IAAI,8BAA8B,eAAe;AAC7E,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"}