@oneminutelogs/nestjs 1.0.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/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # @oneminutelogs/nestjs
2
+
3
+ The official NestJS SDK for [OneMinuteLogs](https://oneminutelogs.com).
4
+
5
+ This package provides a seamless integration with NestJS, including a Global Module, Service for manual logging, and an Interceptor for automatic request logging.
6
+
7
+ **Official Documentation:** [oneminutestack.com/docs/nestjs](https://oneminutestack.com/docs/nestjs)
8
+
9
+ ## Features
10
+
11
+ - **Global Module**: Initialize once, use everywhere via dependency injection.
12
+ - **Interceptor**: Automatically logs every HTTP request with duration, status, and metadata.
13
+ - **Type-Safe Service**: injectable `OneMinuteLogsService` with all typed log methods (`info`, `error`, `audit`, etc.).
14
+ - **Async Configuration**: Support for `forRootAsync` to load config from `ConfigService`.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @oneminutelogs/nestjs
20
+ # or
21
+ yarn add @oneminutelogs/nestjs
22
+ # or
23
+ pnpm add @oneminutelogs/nestjs
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Import Module
29
+
30
+ Import `OneMinuteLogsModule` in your root `AppModule`.
31
+
32
+ ```typescript
33
+ import { Module } from "@nestjs/common";
34
+ import { OneMinuteLogsModule } from "@oneminutelogs/nestjs";
35
+
36
+ @Module({
37
+ imports: [
38
+ OneMinuteLogsModule.forRoot({
39
+ apiKey: process.env.OML_API_KEY!,
40
+ appName: "my-nestjs-service",
41
+ environment: process.env.NODE_ENV || "development"
42
+ }),
43
+ ],
44
+ })
45
+ export class AppModule {}
46
+ ```
47
+
48
+ ### 2. Automatic Request Logging
49
+
50
+ Bind the `OneMinuteLogsInterceptor` globally in your `main.ts` or as a global provider.
51
+
52
+ **Option A: In `main.ts`**
53
+ ```typescript
54
+ import { OneMinuteLogsInterceptor, OneMinuteLogsService } from "@oneminutelogs/nestjs";
55
+
56
+ async function bootstrap() {
57
+ const app = await NestFactory.create(AppModule);
58
+
59
+ const omlService = app.get(OneMinuteLogsService);
60
+ app.useGlobalInterceptors(new OneMinuteLogsInterceptor(omlService));
61
+
62
+ await app.listen(3000);
63
+ }
64
+ bootstrap();
65
+ ```
66
+
67
+ **Option B: As a Provider (Recommended)**
68
+ ```typescript
69
+ import { Module } from "@nestjs/common";
70
+ import { APP_INTERCEPTOR } from "@nestjs/core";
71
+ import { OneMinuteLogsModule, OneMinuteLogsInterceptor } from "@oneminutelogs/nestjs";
72
+
73
+ @Module({
74
+ imports: [
75
+ OneMinuteLogsModule.forRoot({ /* ... */ }),
76
+ ],
77
+ providers: [
78
+ {
79
+ provide: APP_INTERCEPTOR,
80
+ useClass: OneMinuteLogsInterceptor,
81
+ },
82
+ ],
83
+ })
84
+ export class AppModule {}
85
+ ```
86
+
87
+ ### 3. Manual Logging
88
+
89
+ Inject `OneMinuteLogsService` into any provider or controller.
90
+
91
+ ```typescript
92
+ import { Injectable } from "@nestjs/common";
93
+ import { OneMinuteLogsService } from "@oneminutelogs/nestjs";
94
+
95
+ @Injectable()
96
+ export class AuthService {
97
+ constructor(private readonly logger: OneMinuteLogsService) {}
98
+
99
+ async validateUser(username: string) {
100
+ // Info log
101
+ await this.logger.info({ message: `Validating user ${username}` });
102
+
103
+ // Security Audit
104
+ await this.logger.audit({
105
+ message: "Login attempt",
106
+ security: {
107
+ auth_status: "pending",
108
+ user_id: username
109
+ }
110
+ });
111
+ }
112
+ }
113
+ ```
114
+
115
+ ## Async Configuration
116
+
117
+ If you need to load configuration asynchronously (e.g., from `@nestjs/config`), use `forRootAsync`.
118
+
119
+ ```typescript
120
+ import { ConfigModule, ConfigService } from "@nestjs/config";
121
+
122
+ OneMinuteLogsModule.forRootAsync({
123
+ imports: [ConfigModule],
124
+ useFactory: async (configService: ConfigService) => ({
125
+ apiKey: configService.getOrThrow("OML_API_KEY"),
126
+ appName: configService.get("APP_NAME"),
127
+ }),
128
+ inject: [ConfigService],
129
+ });
130
+ ```
131
+
132
+ ## API Reference
133
+
134
+ ### OneMinuteLogsService
135
+
136
+ - `info(payload)`
137
+ - `error(payload)`
138
+ - `warning(payload)`
139
+ - `audit(payload)`
140
+ - `metric(payload)`
141
+ - `debug(payload)`
142
+ - `success(payload)`
143
+ - `send(payload)` (Generic)
144
+ - `get(filters)` (Query logs)
145
+ - `stream(filters)` (Stream logs)
146
+
147
+ ---
148
+
149
+ ## Support
150
+
151
+ If you have any questions or need assistance, please contact us at [contact@oneminutestack.com](mailto:contact@oneminutestack.com).
@@ -0,0 +1,9 @@
1
+ import { NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
2
+ import { Observable } from "rxjs";
3
+ import { OneMinuteLogsService } from "./OneMinuteLogsService.js";
4
+ export declare class OneMinuteLogsInterceptor implements NestInterceptor {
5
+ private readonly oml;
6
+ constructor(oml: OneMinuteLogsService);
7
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
8
+ private logRequest;
9
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.OneMinuteLogsInterceptor = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const operators_1 = require("rxjs/operators");
15
+ const OneMinuteLogsService_js_1 = require("./OneMinuteLogsService.js");
16
+ let OneMinuteLogsInterceptor = class OneMinuteLogsInterceptor {
17
+ constructor(oml) {
18
+ this.oml = oml;
19
+ }
20
+ intercept(context, next) {
21
+ const req = context.switchToHttp().getRequest();
22
+ const res = context.switchToHttp().getResponse();
23
+ // Safety check for HTTP context
24
+ if (!req || !res) {
25
+ return next.handle();
26
+ }
27
+ const start = Date.now();
28
+ const method = req.method;
29
+ const url = req.originalUrl || req.url;
30
+ const ip = req.ip || req.socket?.remoteAddress;
31
+ const userAgent = req.get ? req.get("user-agent") : req.headers["user-agent"];
32
+ return next.handle().pipe((0, operators_1.tap)({
33
+ next: () => {
34
+ this.logRequest(method, url, res.statusCode, Date.now() - start, ip, userAgent);
35
+ },
36
+ error: (err) => {
37
+ // NestJS exception filters usually handle the response status specific logic
38
+ // But here we can catch the error flow
39
+ const status = err.status || 500;
40
+ this.logRequest(method, url, status, Date.now() - start, ip, userAgent, err.message);
41
+ },
42
+ }));
43
+ }
44
+ logRequest(method, url, statusCode, duration, ip, userAgent, errorMessage) {
45
+ const isError = statusCode >= 400;
46
+ const logMethod = isError ? this.oml.error.bind(this.oml) : this.oml.info.bind(this.oml);
47
+ logMethod({
48
+ message: `${method} ${url} ${statusCode} - ${duration}ms${errorMessage ? ` [Error: ${errorMessage}]` : ""}`,
49
+ subsystem: "network",
50
+ metrics: {
51
+ duration,
52
+ statusCode,
53
+ method,
54
+ },
55
+ track: {
56
+ ip,
57
+ userAgent,
58
+ },
59
+ });
60
+ }
61
+ };
62
+ exports.OneMinuteLogsInterceptor = OneMinuteLogsInterceptor;
63
+ exports.OneMinuteLogsInterceptor = OneMinuteLogsInterceptor = __decorate([
64
+ (0, common_1.Injectable)(),
65
+ __metadata("design:paramtypes", [OneMinuteLogsService_js_1.OneMinuteLogsService])
66
+ ], OneMinuteLogsInterceptor);
@@ -0,0 +1,9 @@
1
+ import { DynamicModule } from "@nestjs/common";
2
+ import { LoggerConfig } from "./types/index.js";
3
+ export declare class OneMinuteLogsModule {
4
+ static forRoot(config: LoggerConfig): DynamicModule;
5
+ static forRootAsync(options: {
6
+ useFactory: (...args: any[]) => Promise<LoggerConfig> | LoggerConfig;
7
+ inject?: any[];
8
+ }): DynamicModule;
9
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var OneMinuteLogsModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.OneMinuteLogsModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const OneMinuteLogsService_js_1 = require("./OneMinuteLogsService.js");
13
+ let OneMinuteLogsModule = OneMinuteLogsModule_1 = class OneMinuteLogsModule {
14
+ static forRoot(config) {
15
+ return {
16
+ module: OneMinuteLogsModule_1,
17
+ providers: [
18
+ {
19
+ provide: OneMinuteLogsService_js_1.OML_CONFIG,
20
+ useValue: config,
21
+ },
22
+ OneMinuteLogsService_js_1.OneMinuteLogsService,
23
+ ],
24
+ exports: [OneMinuteLogsService_js_1.OneMinuteLogsService],
25
+ };
26
+ }
27
+ static forRootAsync(options) {
28
+ const providers = [
29
+ {
30
+ provide: OneMinuteLogsService_js_1.OML_CONFIG,
31
+ useFactory: options.useFactory,
32
+ inject: options.inject || [],
33
+ },
34
+ OneMinuteLogsService_js_1.OneMinuteLogsService,
35
+ ];
36
+ return {
37
+ module: OneMinuteLogsModule_1,
38
+ providers,
39
+ exports: [OneMinuteLogsService_js_1.OneMinuteLogsService],
40
+ };
41
+ }
42
+ };
43
+ exports.OneMinuteLogsModule = OneMinuteLogsModule;
44
+ exports.OneMinuteLogsModule = OneMinuteLogsModule = OneMinuteLogsModule_1 = __decorate([
45
+ (0, common_1.Global)(),
46
+ (0, common_1.Module)({})
47
+ ], OneMinuteLogsModule);
@@ -0,0 +1,28 @@
1
+ import { LoggerConfig, LogPayload } from "./types/index.js";
2
+ export declare const OML_CONFIG = "OML_CONFIG";
3
+ export declare class OneMinuteLogsService {
4
+ private config;
5
+ private logger;
6
+ constructor(config: LoggerConfig);
7
+ /**
8
+ * Send a generic log payload.
9
+ */
10
+ send(payload: LogPayload): Promise<void>;
11
+ info(payload: Omit<LogPayload, "type">): Promise<void>;
12
+ error(payload: Omit<LogPayload, "type">): Promise<void>;
13
+ warning(payload: Omit<LogPayload, "type">): Promise<void>;
14
+ audit(payload: Omit<LogPayload, "type">): Promise<void>;
15
+ metric(payload: Omit<LogPayload, "type">): Promise<void>;
16
+ debug(payload: Omit<LogPayload, "type">): Promise<void>;
17
+ success(payload: Omit<LogPayload, "type">): Promise<void>;
18
+ /**
19
+ * Get historical logs.
20
+ */
21
+ get(filters?: Record<string, any>): Promise<any>;
22
+ /**
23
+ * Stream live logs.
24
+ */
25
+ stream(filters: Record<string, any>): {
26
+ body: ReadableStream<Uint8Array> | null;
27
+ };
28
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.OneMinuteLogsService = exports.OML_CONFIG = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const createLogger_js_1 = require("./core/createLogger.js");
18
+ exports.OML_CONFIG = "OML_CONFIG";
19
+ let OneMinuteLogsService = class OneMinuteLogsService {
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.logger = (0, createLogger_js_1.createLogger)(config);
23
+ }
24
+ /**
25
+ * Send a generic log payload.
26
+ */
27
+ async send(payload) {
28
+ return this.logger.send(payload);
29
+ }
30
+ async info(payload) {
31
+ return this.logger.info(payload);
32
+ }
33
+ async error(payload) {
34
+ return this.logger.error(payload);
35
+ }
36
+ async warning(payload) {
37
+ return this.logger.warning(payload);
38
+ }
39
+ async audit(payload) {
40
+ return this.logger.audit(payload);
41
+ }
42
+ async metric(payload) {
43
+ return this.logger.metric(payload);
44
+ }
45
+ async debug(payload) {
46
+ return this.logger.debug(payload);
47
+ }
48
+ async success(payload) {
49
+ return this.logger.success(payload);
50
+ }
51
+ /**
52
+ * Get historical logs.
53
+ */
54
+ async get(filters) {
55
+ return this.logger.get(filters);
56
+ }
57
+ /**
58
+ * Stream live logs.
59
+ */
60
+ stream(filters) {
61
+ return this.logger.stream(filters);
62
+ }
63
+ };
64
+ exports.OneMinuteLogsService = OneMinuteLogsService;
65
+ exports.OneMinuteLogsService = OneMinuteLogsService = __decorate([
66
+ (0, common_1.Injectable)(),
67
+ __param(0, (0, common_1.Inject)(exports.OML_CONFIG)),
68
+ __metadata("design:paramtypes", [Object])
69
+ ], OneMinuteLogsService);
@@ -0,0 +1,4 @@
1
+ export interface EnvConfig {
2
+ baseUrl: string;
3
+ }
4
+ export declare const getEnvConfig: () => EnvConfig;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEnvConfig = void 0;
4
+ const getEnvConfig = () => {
5
+ return {
6
+ baseUrl: "https://api.oneminutelogs.com/v1/api",
7
+ };
8
+ };
9
+ exports.getEnvConfig = getEnvConfig;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * oneminutelogs – createLogger
3
+ *
4
+ * Summary:
5
+ * Factory that creates a typed logger backed by OMLTransport. Provides:
6
+ * - `send` for generic logging
7
+ * - type helpers: `info`, `error`, `metric`, `audit`, `warning`
8
+ * - passthrough `get` and `stream` to query historical logs and subscribe to live logs
9
+ *
10
+ * Package: @oneminutelogs/express
11
+ * Module: core/createLogger
12
+ */
13
+ import type { LoggerConfig, LogPayload } from "../types/index.js";
14
+ /**
15
+ * Creates a logger bound to an OML transport.
16
+ *
17
+ * Behavior:
18
+ * - Enriches payloads with `appName` and `environment` from config when not provided.
19
+ * - Defaults `type` to "info" when `send` is called without an explicit type.
20
+ *
21
+ * @param config Configuration with `apiKey` and optional `appName`, `environment`.
22
+ * @returns Logger API with `send`, type helpers, `get`, and `stream`.
23
+ */
24
+ export declare function createLogger(config: LoggerConfig): {
25
+ send: (payload: LogPayload) => Promise<void>;
26
+ info: (payload: Omit<LogPayload, "type">) => Promise<void>;
27
+ error: (payload: Omit<LogPayload, "type">) => Promise<void>;
28
+ metric: (payload: Omit<LogPayload, "type">) => Promise<void>;
29
+ audit: (payload: Omit<LogPayload, "type">) => Promise<void>;
30
+ warning: (payload: Omit<LogPayload, "type">) => Promise<void>;
31
+ debug: (payload: Omit<LogPayload, "type">) => Promise<void>;
32
+ success: (payload: Omit<LogPayload, "type">) => Promise<void>;
33
+ get: (filters?: Record<string, any>) => Promise<any>;
34
+ stream: (filters: Record<string, any>) => {
35
+ body: ReadableStream<Uint8Array> | null;
36
+ };
37
+ };
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * oneminutelogs – createLogger
4
+ *
5
+ * Summary:
6
+ * Factory that creates a typed logger backed by OMLTransport. Provides:
7
+ * - `send` for generic logging
8
+ * - type helpers: `info`, `error`, `metric`, `audit`, `warning`
9
+ * - passthrough `get` and `stream` to query historical logs and subscribe to live logs
10
+ *
11
+ * Package: @oneminutelogs/express
12
+ * Module: core/createLogger
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.createLogger = createLogger;
16
+ const transport_js_1 = require("../utils/transport.js");
17
+ /**
18
+ * Creates a logger bound to an OML transport.
19
+ *
20
+ * Behavior:
21
+ * - Enriches payloads with `appName` and `environment` from config when not provided.
22
+ * - Defaults `type` to "info" when `send` is called without an explicit type.
23
+ *
24
+ * @param config Configuration with `apiKey` and optional `appName`, `environment`.
25
+ * @returns Logger API with `send`, type helpers, `get`, and `stream`.
26
+ */
27
+ function createLogger(config) {
28
+ const transport = new transport_js_1.OMLTransport(config);
29
+ /**
30
+ * Sends a log payload.
31
+ *
32
+ * Merges defaults:
33
+ * - `type`: defaults to "info"
34
+ * - `appName`: `payload.appName || config.appName || "default"`
35
+ * - `environment`: `payload.environment || config.environment || process.env.NODE_ENV || "development"`
36
+ *
37
+ * @param payload Log payload to send.
38
+ * @returns Promise that resolves when the payload is enqueued/flushed.
39
+ */
40
+ const send = async (payload) => {
41
+ const { type = "info", message, importance, subsystem, operation, service, track, security, metrics, timestamps, appName, environment, } = payload;
42
+ const finalPayload = {
43
+ type,
44
+ message,
45
+ importance,
46
+ subsystem,
47
+ operation,
48
+ service,
49
+ track,
50
+ security,
51
+ metrics,
52
+ timestamps,
53
+ appName: appName || config.appName || "default",
54
+ environment: environment ||
55
+ config.environment ||
56
+ process.env.NODE_ENV ||
57
+ "development",
58
+ };
59
+ await transport.send(finalPayload);
60
+ };
61
+ // Helper factory to create type-specific methods dynamically
62
+ /**
63
+ * Factory for type-specific logging methods (e.g., `info`, `error`).
64
+ *
65
+ * @param type Log type to set on the outgoing payload.
66
+ * @returns Function that accepts a payload without `type` and sends it with the provided `type`.
67
+ */
68
+ const createTypeMethod = (type) => (payload) => send({ ...payload, type });
69
+ /**
70
+ * Returned API:
71
+ * - `send(payload)`: send a generic log (defaults `type` to "info").
72
+ * - `info(payload)`, `error(payload)`, `metric(payload)`, `audit(payload)`, `warning(payload)`: type-specific helpers.
73
+ * - `get(filters?)`: fetch historical logs via transport.
74
+ * - `stream(filters?)`: open SSE stream via transport.
75
+ */
76
+ return {
77
+ send,
78
+ info: createTypeMethod("info"),
79
+ error: createTypeMethod("error"),
80
+ metric: createTypeMethod("metric"),
81
+ audit: createTypeMethod("audit"),
82
+ warning: createTypeMethod("warning"),
83
+ debug: createTypeMethod("debug"),
84
+ success: createTypeMethod("success"),
85
+ get: (filters) => transport.get(filters),
86
+ stream: (filters) => transport.stream(filters),
87
+ };
88
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./types/index.js";
2
+ export * from "./OneMinuteLogsService.js";
3
+ export * from "./OneMinuteLogsModule.js";
4
+ export * from "./OneMinuteLogsInterceptor.js";
5
+ export { createLogger } from "./core/createLogger.js";
6
+ export { getLogs } from "./utils/getLogs.js";
7
+ export { getStream } from "./utils/getStream.js";
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
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
+ exports.getStream = exports.getLogs = exports.createLogger = void 0;
18
+ __exportStar(require("./types/index.js"), exports);
19
+ __exportStar(require("./OneMinuteLogsService.js"), exports);
20
+ __exportStar(require("./OneMinuteLogsModule.js"), exports);
21
+ __exportStar(require("./OneMinuteLogsInterceptor.js"), exports);
22
+ var createLogger_js_1 = require("./core/createLogger.js");
23
+ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return createLogger_js_1.createLogger; } });
24
+ var getLogs_js_1 = require("./utils/getLogs.js");
25
+ Object.defineProperty(exports, "getLogs", { enumerable: true, get: function () { return getLogs_js_1.getLogs; } });
26
+ var getStream_js_1 = require("./utils/getStream.js");
27
+ Object.defineProperty(exports, "getStream", { enumerable: true, get: function () { return getStream_js_1.getStream; } });
@@ -0,0 +1,30 @@
1
+ import { LogTimestamps } from "./log.js";
2
+ import { LogMetrics } from "./metrics.js";
3
+ import { LogSecurity } from "./security.js";
4
+ import { LogTrack } from "./track.js";
5
+ export type LogLevel = "info" | "warn" | "error";
6
+ export interface LoggerConfig {
7
+ apiKey: string;
8
+ appName?: string;
9
+ environment?: string;
10
+ }
11
+ export interface LogPayload {
12
+ type: LogType;
13
+ message: string;
14
+ importance?: Importance;
15
+ subsystem?: Subsystem;
16
+ operation?: string;
17
+ track?: LogTrack;
18
+ security?: LogSecurity;
19
+ metrics?: LogMetrics;
20
+ service?: string;
21
+ timestamps?: LogTimestamps;
22
+ ingested_at?: number;
23
+ appName?: string;
24
+ environment?: string;
25
+ }
26
+ export type LogType = "error" | "warning" | "info" | "audit" | "metric" | "debug" | "success";
27
+ export type Importance = "critical" | "high" | "medium" | "low";
28
+ export type Subsystem = "db" | "cache" | "queue" | "network";
29
+ export type UserRole = "super-admin" | "admin" | "user";
30
+ export type AuthStatus = "success" | "failed" | "expired";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export type LogTimestamps = Record<string, number | string>;
2
+ export type LogMetrics = Record<string, number | string>;
3
+ export type LogSecurity = Record<string, any>;
4
+ export type LogTrack = Record<string, any>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type LogMetrics = Record<string, number | string | Record<string, any>>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type LogSecurity = Record<string, any>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type LogTrack = Record<string, any>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,26 @@
1
+ /**
2
+ * oneminutelogs – getLogs utility
3
+ *
4
+ * Summary:
5
+ * A utility function to fetch logs from the OML server.
6
+ * Unlike the Next.js SDK, this is not a hook but a plain async function.
7
+ *
8
+ * Package: @oneminutelogs/express
9
+ * Module: utils/getLogs
10
+ */
11
+ import type { LoggerConfig } from "../types/index.js";
12
+ /**
13
+ * Result returned by `getLogs`.
14
+ * Wraps the server response.
15
+ */
16
+ export type GetLogsResult<T = any> = T[] | {
17
+ logs: T[];
18
+ };
19
+ /**
20
+ * Fetches logs from the OML server.
21
+ *
22
+ * @param config - Logger configuration (apiKey is required).
23
+ * @param filters - Optional filters (type, limit, search, etc.).
24
+ * @returns Promise resolving to the logs.
25
+ */
26
+ export declare function getLogs<T = any>(config: LoggerConfig, filters?: Record<string, any>): Promise<GetLogsResult<T>>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * oneminutelogs – getLogs utility
4
+ *
5
+ * Summary:
6
+ * A utility function to fetch logs from the OML server.
7
+ * Unlike the Next.js SDK, this is not a hook but a plain async function.
8
+ *
9
+ * Package: @oneminutelogs/express
10
+ * Module: utils/getLogs
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getLogs = getLogs;
14
+ const transport_js_1 = require("./transport.js");
15
+ /**
16
+ * Fetches logs from the OML server.
17
+ *
18
+ * @param config - Logger configuration (apiKey is required).
19
+ * @param filters - Optional filters (type, limit, search, etc.).
20
+ * @returns Promise resolving to the logs.
21
+ */
22
+ async function getLogs(config, filters) {
23
+ const transport = new transport_js_1.OMLTransport(config);
24
+ return transport.get(filters);
25
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * oneminutelogs – getStream utility
3
+ *
4
+ * Summary:
5
+ * A utility function to subscribe to the OML server SSE stream.
6
+ * Returns a ReadableStream of bytes.
7
+ *
8
+ * Package: @oneminutelogs/express
9
+ * Module: utils/getStream
10
+ */
11
+ import type { LoggerConfig } from "../types/index.js";
12
+ /**
13
+ * Subscribes to the OML SSE stream.
14
+ *
15
+ * @param config - Logger configuration (apiKey is required).
16
+ * @param filters - Optional filters (type, limit, search, etc.).
17
+ * @returns Object containing the body stream.
18
+ */
19
+ export declare function getStream(config: LoggerConfig, filters: Record<string, any>): {
20
+ body: ReadableStream<Uint8Array> | null;
21
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * oneminutelogs – getStream utility
4
+ *
5
+ * Summary:
6
+ * A utility function to subscribe to the OML server SSE stream.
7
+ * Returns a ReadableStream of bytes.
8
+ *
9
+ * Package: @oneminutelogs/express
10
+ * Module: utils/getStream
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getStream = getStream;
14
+ const transport_js_1 = require("./transport.js");
15
+ /**
16
+ * Subscribes to the OML SSE stream.
17
+ *
18
+ * @param config - Logger configuration (apiKey is required).
19
+ * @param filters - Optional filters (type, limit, search, etc.).
20
+ * @returns Object containing the body stream.
21
+ */
22
+ function getStream(config, filters) {
23
+ const transport = new transport_js_1.OMLTransport(config);
24
+ return transport.stream(filters);
25
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * oneminutelogs – OMLTransport
3
+ *
4
+ * Summary:
5
+ * A thin transport client used by oneminutelogs SDK to:
6
+ * - batch and send logs to the OML server (`/send`)
7
+ * - query historical logs (`/logs`)
8
+ * - subscribe to live logs stream via SSE (`/logs/stream`)
9
+ *
10
+ * Package: @oneminutelogs/express
11
+ * Module: utils/transport
12
+ */
13
+ import type { LoggerConfig, LogPayload } from "../types/index.js";
14
+ /**
15
+ * Transport for communicating with the OML server.
16
+ *
17
+ * Responsibilities:
18
+ * - Buffers logs client-side and flushes by interval or batch size.
19
+ * - Sends logs to `/send`.
20
+ * - Retrieves logs from `/logs` with optional filters.
21
+ * - Opens SSE stream from `/logs/stream`.
22
+ */
23
+ export declare class OMLTransport {
24
+ private config;
25
+ /** Base server URL (depends on env config). */
26
+ private baseUrl;
27
+ /** API key used for authentication (x-oml-api-key). */
28
+ private apiKey;
29
+ /** Optional app name used to tag requests (x-oml-app-name). */
30
+ private appName;
31
+ /** Optional environment used to tag requests (x-oml-env). */
32
+ private environment;
33
+ /** Default headers applied to outbound requests. */
34
+ private headers;
35
+ /** In-memory buffer of logs to batch-send. */
36
+ private buffer;
37
+ /** Scheduled timer for periodic flushes. */
38
+ private timer;
39
+ /** Flush interval in milliseconds for buffered logs. */
40
+ private flushInterval;
41
+ /** Indicates shutdown is in progress and new logs should be ignored. */
42
+ private shuttingDown;
43
+ /** Indicates whether a flush is currently in progress. */
44
+ private isFlushing;
45
+ /**
46
+ * Creates a new transport instance.
47
+ *
48
+ * @param config Logger configuration containing `apiKey`, and optionally `appName` and `environment`.
49
+ */
50
+ constructor(config: LoggerConfig);
51
+ /** Queues a single log payload for sending. */
52
+ send(payload: LogPayload): Promise<void>;
53
+ /** Flushes the in-memory buffer to the server as a single batch. */
54
+ private flush;
55
+ /** Registers process-level handlers (SIGINT, SIGTERM, beforeExit) */
56
+ private setupGracefulShutdown;
57
+ /** Retrieves historical logs from the server. */
58
+ get(filters?: Record<string, any>): Promise<any>;
59
+ /** Opens a Server-Sent Events (SSE) stream of live logs. */
60
+ stream(filters: Record<string, string>): {
61
+ body: ReadableStream<Uint8Array> | null;
62
+ };
63
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /**
3
+ * oneminutelogs – OMLTransport
4
+ *
5
+ * Summary:
6
+ * A thin transport client used by oneminutelogs SDK to:
7
+ * - batch and send logs to the OML server (`/send`)
8
+ * - query historical logs (`/logs`)
9
+ * - subscribe to live logs stream via SSE (`/logs/stream`)
10
+ *
11
+ * Package: @oneminutelogs/express
12
+ * Module: utils/transport
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.OMLTransport = void 0;
16
+ const index_js_1 = require("../configs/index.js");
17
+ /**
18
+ * Transport for communicating with the OML server.
19
+ *
20
+ * Responsibilities:
21
+ * - Buffers logs client-side and flushes by interval or batch size.
22
+ * - Sends logs to `/send`.
23
+ * - Retrieves logs from `/logs` with optional filters.
24
+ * - Opens SSE stream from `/logs/stream`.
25
+ */
26
+ class OMLTransport {
27
+ /**
28
+ * Creates a new transport instance.
29
+ *
30
+ * @param config Logger configuration containing `apiKey`, and optionally `appName` and `environment`.
31
+ */
32
+ constructor(config) {
33
+ this.config = config;
34
+ /** In-memory buffer of logs to batch-send. */
35
+ this.buffer = [];
36
+ /** Scheduled timer for periodic flushes. */
37
+ this.timer = null;
38
+ /** Flush interval in milliseconds for buffered logs. */
39
+ this.flushInterval = 2000;
40
+ /** Indicates shutdown is in progress and new logs should be ignored. */
41
+ this.shuttingDown = false;
42
+ /** Indicates whether a flush is currently in progress. */
43
+ this.isFlushing = false;
44
+ const envConfig = (0, index_js_1.getEnvConfig)();
45
+ this.baseUrl = envConfig.baseUrl;
46
+ this.apiKey = config.apiKey;
47
+ this.appName = config.appName;
48
+ this.environment = config.environment;
49
+ this.headers = {
50
+ "Content-Type": "application/json",
51
+ "x-oml-api-key": config.apiKey,
52
+ ...(config.appName ? { "x-oml-app-name": config.appName } : {}),
53
+ ...(config.environment ? { "x-oml-env": config.environment } : {}),
54
+ };
55
+ this.setupGracefulShutdown();
56
+ }
57
+ /** Queues a single log payload for sending. */
58
+ async send(payload) {
59
+ if (this.shuttingDown)
60
+ return; // ignore new logs during shutdown
61
+ this.buffer.push({
62
+ ...payload,
63
+ ingested_at: Date.now(),
64
+ });
65
+ // Rely on the 2s periodic flush
66
+ if (!this.timer) {
67
+ this.timer = setTimeout(() => this.flush(), this.flushInterval);
68
+ }
69
+ }
70
+ /** Flushes the in-memory buffer to the server as a single batch. */
71
+ async flush() {
72
+ // Prevent multiple flushes from running simultaneously.
73
+ if (this.isFlushing)
74
+ return;
75
+ this.isFlushing = true;
76
+ if (this.timer) {
77
+ clearTimeout(this.timer);
78
+ this.timer = null;
79
+ }
80
+ const batch = this.buffer.splice(0, this.buffer.length);
81
+ if (batch.length === 0) {
82
+ this.isFlushing = false;
83
+ return;
84
+ }
85
+ try {
86
+ await fetch(`${this.baseUrl}/send`, {
87
+ method: "POST",
88
+ headers: this.headers,
89
+ body: JSON.stringify({ logs: batch }),
90
+ // @ts-ignore: keepalive might not be in all fetch types, but supported in modern node
91
+ keepalive: true,
92
+ });
93
+ }
94
+ catch (err) {
95
+ console.error("OMLTransport flush failed:", err);
96
+ }
97
+ this.isFlushing = false;
98
+ }
99
+ /** Registers process-level handlers (SIGINT, SIGTERM, beforeExit) */
100
+ setupGracefulShutdown() {
101
+ const shutdownHandler = async (signal) => {
102
+ if (this.shuttingDown)
103
+ return;
104
+ this.shuttingDown = true;
105
+ try {
106
+ await this.flush();
107
+ }
108
+ catch (err) {
109
+ console.error("[OMLTransport] Flush during shutdown failed:", err);
110
+ }
111
+ finally {
112
+ process.exit(0);
113
+ }
114
+ };
115
+ process.on("beforeExit", () => shutdownHandler("beforeExit"));
116
+ process.on("SIGINT", () => shutdownHandler("SIGINT"));
117
+ process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
118
+ }
119
+ /** Retrieves historical logs from the server. */
120
+ async get(filters) {
121
+ const headers = {
122
+ "x-oml-api-key": this.apiKey,
123
+ ...(this.appName ? { "x-oml-app-name": this.appName } : {}),
124
+ ...(this.environment ? { "x-oml-env": this.environment } : {}),
125
+ };
126
+ const qs = filters && Object.keys(filters).length > 0
127
+ ? `?${new URLSearchParams(filters).toString()}`
128
+ : "";
129
+ const res = await fetch(`${this.baseUrl}/logs${qs}`, { headers });
130
+ if (!res.ok) {
131
+ const text = await res.text();
132
+ throw new Error(`OML get failed (${res.status}): ${text.slice(0, 200)}`);
133
+ }
134
+ return res.json();
135
+ }
136
+ /** Opens a Server-Sent Events (SSE) stream of live logs. */
137
+ stream(filters) {
138
+ const qs = new URLSearchParams(filters).toString();
139
+ const url = `${this.baseUrl}/logs/stream?${qs}`;
140
+ const headers = {
141
+ "x-oml-api-key": this.apiKey,
142
+ ...(this.appName ? { "x-oml-app-name": this.appName } : {}),
143
+ ...(this.environment ? { "x-oml-env": this.environment } : {}),
144
+ };
145
+ const abortController = new AbortController();
146
+ // In node-fetch or native fetch, response.body is a stream.
147
+ // We return a wrapped object to match similar API pattern or just return the fetch promise.
148
+ // However, to keep it sync-like wrapper (returning stream object immediately), we can't do await fetch.
149
+ // The original code was async inside ReadableStream start.
150
+ // For Node.js consumption, we probably want a simpler async method or return the promise of the stream.
151
+ // But adhering to the interface:
152
+ const readable = new ReadableStream({
153
+ start: async (controller) => {
154
+ try {
155
+ const res = await fetch(url, {
156
+ headers,
157
+ signal: abortController.signal,
158
+ });
159
+ if (!res.body) {
160
+ controller.error(new Error("Upstream stream unavailable"));
161
+ return;
162
+ }
163
+ // @ts-ignore
164
+ const reader = res.body.getReader();
165
+ while (true) {
166
+ const { done, value } = await reader.read();
167
+ if (done)
168
+ break;
169
+ if (value)
170
+ controller.enqueue(value);
171
+ }
172
+ controller.close();
173
+ }
174
+ catch (err) {
175
+ controller.error(err);
176
+ }
177
+ },
178
+ cancel() {
179
+ abortController.abort();
180
+ },
181
+ });
182
+ return { body: readable };
183
+ }
184
+ }
185
+ exports.OMLTransport = OMLTransport;
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@oneminutelogs/nestjs",
3
+ "version": "1.0.0",
4
+ "description": "NestJS SDK for OneMinuteLogs",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "clean": "rm -rf dist",
19
+ "prepublishOnly": "npm run clean && npm run build"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/One-Minute-Stack/oneminutelogs-nestjs.git"
24
+ },
25
+ "keywords": [
26
+ "logging",
27
+ "nestjs",
28
+ "oneminutelogs",
29
+ "logger",
30
+ "monitoring",
31
+ "observability"
32
+ ],
33
+ "author": "OneMinute Stack",
34
+ "license": "ISC",
35
+ "bugs": {
36
+ "url": "https://github.com/One-Minute-Stack/oneminutelogs-nestjs/issues"
37
+ },
38
+ "homepage": "https://oneminutelogs.com/docs/nestjs",
39
+ "peerDependencies": {
40
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
41
+ "@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0",
42
+ "rxjs": "^7.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@nestjs/common": "^10.0.0",
46
+ "@nestjs/core": "^10.0.0",
47
+ "@types/node": "^20.0.0",
48
+ "reflect-metadata": "^0.1.13",
49
+ "rxjs": "^7.8.1",
50
+ "typescript": "^5.0.0"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ }
55
+ }