@kivia/sdk 0.1.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.
@@ -0,0 +1,28 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ id-token: write
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: "22"
19
+ registry-url: "https://registry.npmjs.org"
20
+ - run: npm ci
21
+ - run: npm run build
22
+ - run: npm publish --provenance --access public
23
+ env:
24
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
25
+ - name: Create GitHub Release
26
+ uses: softprops/action-gh-release@v2
27
+ with:
28
+ generate_release_notes: true
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Kivia TypeScript SDK
2
+
3
+ The Kivia TypeScript SDK is the official Node.js client for the Kivia observability platform. It allows Node.js developers using Express or Fastify to instantly track API request metrics, response times, and paths.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @kivia/sdk
9
+ ```
10
+
11
+ ## Quick Start (with Express)
12
+
13
+ ```typescript
14
+ import express from 'express';
15
+ import { KiviaClient } from '@kivia/sdk';
16
+
17
+ const app = express();
18
+
19
+ const kiviaClient = new KiviaClient({
20
+ apiKey: 'YOUR_KIVIA_API_KEY',
21
+ });
22
+
23
+ // Let Kivia track all your network traffic by setting this global middleware
24
+ app.use(kiviaClient.logMiddleware());
25
+
26
+ app.get('/hello', (req, res) => {
27
+ res.send('Hello from Kivia TS SDK!');
28
+ });
29
+
30
+ app.listen(3000, () => console.log('Server running on port 3000'));
31
+ ```
32
+
33
+ ## Quick Start (with NestJS)
34
+
35
+ Because NestJS runs on Express (or Fastify) under the hood, you can simply inject the SDK as a global middleware right in your `main.ts` bootstrap function!
36
+
37
+ ```typescript
38
+ // main.ts
39
+ import { NestFactory } from '@nestjs/core';
40
+ import { AppModule } from './app.module';
41
+ import { KiviaClient } from '@kivia/sdk';
42
+
43
+ async function bootstrap() {
44
+ const app = await NestFactory.create(AppModule);
45
+
46
+ const kiviaClient = new KiviaClient({
47
+ apiKey: 'YOUR_KIVIA_API_KEY'
48
+ });
49
+
50
+ // Just apply it as global middleware!
51
+ app.use(kiviaClient.logMiddleware());
52
+
53
+ await app.listen(3000);
54
+ }
55
+ bootstrap();
56
+ ```
57
+
58
+ ## Quick Start (with Fastify Plugin)
59
+
60
+ We export a native Fastify plugin so you can easily encapsulate options and registration.
61
+
62
+ ```typescript
63
+ import Fastify from 'fastify';
64
+ import { kiviaFastifyPlugin } from '@kivia/sdk';
65
+
66
+ const fastify = Fastify({ logger: false });
67
+
68
+ // Register as a native Fastify plugin
69
+ fastify.register(kiviaFastifyPlugin, {
70
+ apiKey: 'YOUR_KIVIA_API_KEY'
71
+ });
72
+
73
+ fastify.get('/hello', async (request, reply) => {
74
+ return { message: 'Hello from Kivia TS SDK using Fastify Plugin!' };
75
+ });
76
+
77
+ fastify.listen({ port: 3000 });
78
+ ```
@@ -0,0 +1,17 @@
1
+ import { DynoClientOptions } from './types';
2
+ export declare class DynoClient {
3
+ private apiKey;
4
+ private baseUrl;
5
+ constructor(options: DynoClientOptions);
6
+ /**
7
+ * Express/Connect middleware for automatically logging requests.
8
+ */
9
+ logMiddleware(): (req: any, res: any, next: any) => void;
10
+ /**
11
+ * Fastify hook variant to be used with the 'onResponse' lifecycle hook.
12
+ * Usage: fastify.addHook('onResponse', dynoClient.logFastifyOnResponse());
13
+ */
14
+ logFastifyOnResponse(): (request: any, reply: any) => Promise<void>;
15
+ private sendLog;
16
+ }
17
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAO,MAAM,SAAS,CAAC;AAEjD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACI,aAAa,KACV,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG;IAsBvC;;;OAGG;IACI,oBAAoB,KACX,SAAS,GAAG,EAAE,OAAO,GAAG;YAgB1B,OAAO;CAmBtB"}
package/dist/client.js ADDED
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynoClient = void 0;
4
+ class DynoClient {
5
+ constructor(options) {
6
+ this.apiKey = options.apiKey;
7
+ this.baseUrl = options.baseUrl || 'https://nginx-production-a9aa.up.railway.app/api/v1';
8
+ }
9
+ /**
10
+ * Express/Connect middleware for automatically logging requests.
11
+ */
12
+ logMiddleware() {
13
+ return (req, res, next) => {
14
+ const start = Date.now();
15
+ // Listen for the response to finish
16
+ res.on('finish', () => {
17
+ var _a;
18
+ const latency = Date.now() - start;
19
+ const logEntry = {
20
+ path: req.originalUrl || req.url,
21
+ status: res.statusCode,
22
+ ip_address: req.ip || ((_a = req.connection) === null || _a === void 0 ? void 0 : _a.remoteAddress),
23
+ timestamp: new Date().toISOString(),
24
+ latency,
25
+ };
26
+ this.sendLog(logEntry);
27
+ });
28
+ next();
29
+ };
30
+ }
31
+ /**
32
+ * Fastify hook variant to be used with the 'onResponse' lifecycle hook.
33
+ * Usage: fastify.addHook('onResponse', dynoClient.logFastifyOnResponse());
34
+ */
35
+ logFastifyOnResponse() {
36
+ return async (request, reply) => {
37
+ var _a, _b, _c, _d;
38
+ // reply.getResponseTime() is available in Fastify to get latency in ms
39
+ const latency = reply.getResponseTime ? reply.getResponseTime() : 0;
40
+ const logEntry = {
41
+ path: request.url || ((_a = request.raw) === null || _a === void 0 ? void 0 : _a.url),
42
+ status: reply.statusCode || ((_b = reply.raw) === null || _b === void 0 ? void 0 : _b.statusCode),
43
+ ip_address: request.ip || ((_d = (_c = request.raw) === null || _c === void 0 ? void 0 : _c.connection) === null || _d === void 0 ? void 0 : _d.remoteAddress),
44
+ timestamp: new Date().toISOString(),
45
+ latency: Math.round(latency),
46
+ };
47
+ this.sendLog(logEntry);
48
+ };
49
+ }
50
+ async sendLog(logEntry) {
51
+ try {
52
+ const response = await fetch(`${this.baseUrl}/logs/create`, {
53
+ method: 'POST',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ 'X-dyno-api-key': this.apiKey,
57
+ },
58
+ body: JSON.stringify(logEntry),
59
+ });
60
+ if (!response.ok) {
61
+ const errBody = await response.text();
62
+ console.error(`dynosdk: log rejected (${response.status}): ${errBody}`);
63
+ }
64
+ }
65
+ catch (error) {
66
+ console.error('dynosdk: failed to send log:', error);
67
+ }
68
+ }
69
+ }
70
+ exports.DynoClient = DynoClient;
71
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAEA,MAAa,UAAU;IAIrB,YAAY,OAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,qDAAqD,CAAC;IAC1F,CAAC;IAED;;OAEG;IACI,aAAa;QAClB,OAAO,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAEzB,oCAAoC;YACpC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;;gBACpB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBAEnC,MAAM,QAAQ,GAAQ;oBACpB,IAAI,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG;oBAChC,MAAM,EAAE,GAAG,CAAC,UAAU;oBACtB,UAAU,EAAE,GAAG,CAAC,EAAE,KAAI,MAAA,GAAG,CAAC,UAAU,0CAAE,aAAa,CAAA;oBACnD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,OAAO;iBACR,CAAC;gBAEF,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;YAEH,IAAI,EAAE,CAAC;QACT,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,oBAAoB;QACzB,OAAO,KAAK,EAAE,OAAY,EAAE,KAAU,EAAE,EAAE;;YACxC,uEAAuE;YACvE,MAAM,OAAO,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAEpE,MAAM,QAAQ,GAAQ;gBACpB,IAAI,EAAE,OAAO,CAAC,GAAG,KAAI,MAAA,OAAO,CAAC,GAAG,0CAAE,GAAG,CAAA;gBACrC,MAAM,EAAE,KAAK,CAAC,UAAU,KAAI,MAAA,KAAK,CAAC,GAAG,0CAAE,UAAU,CAAA;gBACjD,UAAU,EAAE,OAAO,CAAC,EAAE,KAAI,MAAA,MAAA,OAAO,CAAC,GAAG,0CAAE,UAAU,0CAAE,aAAa,CAAA;gBAChE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;aAC7B,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,QAAa;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,cAAc,EAAE;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,gBAAgB,EAAE,IAAI,CAAC,MAAM;iBAC9B;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACtC,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF;AA3ED,gCA2EC"}
@@ -0,0 +1,7 @@
1
+ import { DynoClientOptions } from './types';
2
+ /**
3
+ * Fastify plugin for Dyno observability.
4
+ * Usage: fastify.register(dynoFastifyPlugin, { apiKey: '...' })
5
+ */
6
+ export declare function dynoFastifyPlugin(fastify: any, options: DynoClientOptions): Promise<void>;
7
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,iBAAiB,iBAG/E"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dynoFastifyPlugin = dynoFastifyPlugin;
4
+ const client_1 = require("./client");
5
+ /**
6
+ * Fastify plugin for Dyno observability.
7
+ * Usage: fastify.register(dynoFastifyPlugin, { apiKey: '...' })
8
+ */
9
+ async function dynoFastifyPlugin(fastify, options) {
10
+ const client = new client_1.DynoClient(options);
11
+ fastify.addHook('onResponse', client.logFastifyOnResponse());
12
+ }
13
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.js","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":";;AAOA,8CAGC;AAVD,qCAAsC;AAGtC;;;GAGG;AACI,KAAK,UAAU,iBAAiB,CAAC,OAAY,EAAE,OAA0B;IAC9E,MAAM,MAAM,GAAG,IAAI,mBAAU,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './types';
2
+ export * from './client';
3
+ export * from './fastify';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./client"), exports);
19
+ __exportStar(require("./fastify"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,2CAAyB;AACzB,4CAA0B"}
@@ -0,0 +1,16 @@
1
+ export interface Log {
2
+ id?: string;
3
+ path: string;
4
+ status: number;
5
+ ip_address?: string;
6
+ timestamp: string;
7
+ latency: number;
8
+ }
9
+ export interface DynoClientOptions {
10
+ apiKey: string;
11
+ /**
12
+ * Override the default production base URL.
13
+ */
14
+ baseUrl?: string;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@kivia/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for the Kivia API observability platform",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch"
10
+ },
11
+ "keywords": [
12
+ "kivia",
13
+ "observability",
14
+ "logging",
15
+ "sdk"
16
+ ],
17
+ "author": "winnerx0",
18
+ "license": "MIT",
19
+ "devDependencies": {
20
+ "@types/node": "^25.5.2",
21
+ "typescript": "^5.4.0"
22
+ }
23
+ }
package/src/client.ts ADDED
@@ -0,0 +1,78 @@
1
+ import { KiviaClientOptions, Log } from './types';
2
+
3
+ export class KiviaClient {
4
+ private apiKey: string;
5
+ private baseUrl: string;
6
+
7
+ constructor(options: KiviaClientOptions) {
8
+ this.apiKey = options.apiKey;
9
+ this.baseUrl = options.baseUrl || 'https://nginx-production-a9aa.up.railway.app/api/v1';
10
+ }
11
+
12
+ /**
13
+ * Express/Connect middleware for automatically logging requests.
14
+ */
15
+ public logMiddleware() {
16
+ return (req: any, res: any, next: any) => {
17
+ const start = Date.now();
18
+
19
+ // Listen for the response to finish
20
+ res.on('finish', () => {
21
+ const latency = Date.now() - start;
22
+
23
+ const logEntry: Log = {
24
+ path: req.originalUrl || req.url,
25
+ status: res.statusCode,
26
+ ip_address: req.ip || req.connection?.remoteAddress,
27
+ timestamp: new Date().toISOString(),
28
+ latency,
29
+ };
30
+
31
+ this.sendLog(logEntry);
32
+ });
33
+
34
+ next();
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Fastify hook variant to be used with the 'onResponse' lifecycle hook.
40
+ * Usage: fastify.addHook('onResponse', kiviaClient.logFastifyOnResponse());
41
+ */
42
+ public logFastifyOnResponse() {
43
+ return async (request: any, reply: any) => {
44
+ // reply.getResponseTime() is available in Fastify to get latency in ms
45
+ const latency = reply.getResponseTime ? reply.getResponseTime() : 0;
46
+
47
+ const logEntry: Log = {
48
+ path: request.url || request.raw?.url,
49
+ status: reply.statusCode || reply.raw?.statusCode,
50
+ ip_address: request.ip || request.raw?.connection?.remoteAddress,
51
+ timestamp: new Date().toISOString(),
52
+ latency: Math.round(latency),
53
+ };
54
+
55
+ this.sendLog(logEntry);
56
+ };
57
+ }
58
+
59
+ private async sendLog(logEntry: Log): Promise<void> {
60
+ try {
61
+ const response = await fetch(`${this.baseUrl}/logs/create`, {
62
+ method: 'POST',
63
+ headers: {
64
+ 'Content-Type': 'application/json',
65
+ 'X-kivia-api-key': this.apiKey,
66
+ },
67
+ body: JSON.stringify(logEntry),
68
+ });
69
+
70
+ if (!response.ok) {
71
+ const errBody = await response.text();
72
+ console.error(`kiviasdk: log rejected (${response.status}): ${errBody}`);
73
+ }
74
+ } catch (error) {
75
+ console.error('kiviasdk: failed to send log:', error);
76
+ }
77
+ }
78
+ }
package/src/fastify.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { KiviaClient } from './client';
2
+ import { KiviaClientOptions } from './types';
3
+
4
+ /**
5
+ * Fastify plugin for Kivia observability.
6
+ * Usage: fastify.register(kiviaFastifyPlugin, { apiKey: '...' })
7
+ */
8
+ export async function kiviaFastifyPlugin(fastify: any, options: KiviaClientOptions) {
9
+ const client = new KiviaClient(options);
10
+ fastify.addHook('onResponse', client.logFastifyOnResponse());
11
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './client';
3
+ export * from './fastify';
package/src/types.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface Log {
2
+ id?: string;
3
+ path: string;
4
+ status: number;
5
+ ip_address?: string;
6
+ timestamp: string; // ISO 8601
7
+ latency: number; // milliseconds
8
+ }
9
+
10
+ export interface KiviaClientOptions {
11
+ apiKey: string;
12
+ /**
13
+ * Override the default production base URL.
14
+ */
15
+ baseUrl?: string;
16
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2018",
4
+ "module": "commonjs",
5
+ "lib": ["ES2022", "DOM"],
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }