logixia 1.3.0 → 1.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/README.md +848 -7
- package/dist/.tsbuildinfo +1 -0
- package/dist/{index-iDTW2-eY.d.mts → index-Ium497V3.d.mts} +180 -2
- package/dist/index-Ium497V3.d.mts.map +1 -0
- package/dist/{index-CHIsdA9n.d.ts → index-t-ActikQ.d.ts} +180 -2
- package/dist/index-t-ActikQ.d.ts.map +1 -0
- package/dist/index.d.mts +458 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +458 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +436 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +416 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{logitron-logger.module-C0G8JGVf.d.ts → logitron-logger.module-9vOhKWDG.d.ts} +120 -6
- package/dist/logitron-logger.module-9vOhKWDG.d.ts.map +1 -0
- package/dist/{logitron-logger.module-2AzkadqZ.mjs → logitron-logger.module-C939PIEV.mjs} +331 -10
- package/dist/logitron-logger.module-C939PIEV.mjs.map +1 -0
- package/dist/{logitron-logger.module-BqNKp0Fs.js → logitron-logger.module-CCnX7GwK.js} +383 -8
- package/dist/logitron-logger.module-CCnX7GwK.js.map +1 -0
- package/dist/{logitron-logger.module-DQKaZTJL.d.mts → logitron-logger.module-SArymP6b.d.mts} +120 -6
- package/dist/logitron-logger.module-SArymP6b.d.mts.map +1 -0
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/nest.d.mts +2 -2
- package/dist/nest.d.ts +2 -2
- package/dist/nest.js +2 -2
- package/dist/nest.mjs +2 -2
- package/dist/{promise-DaiZ2BaH.js → promise-BI-3eI4n.js} +285 -128
- package/dist/promise-BI-3eI4n.js.map +1 -0
- package/dist/{promise-C4pQPcK4.mjs → promise-BrZcjavs.mjs} +285 -128
- package/dist/promise-BrZcjavs.mjs.map +1 -0
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +7 -1
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +7 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/{transport.manager-5VVdqS3o.mjs → transport.manager-DR7TLXQT.mjs} +82 -4
- package/dist/transport.manager-DR7TLXQT.mjs.map +1 -0
- package/dist/{transport.manager-DCOm4uIQ.js → transport.manager-DVTM978M.js} +82 -4
- package/dist/transport.manager-DVTM978M.js.map +1 -0
- package/dist/transports.d.mts +61 -168
- package/dist/transports.d.mts.map +1 -1
- package/dist/transports.d.ts +61 -168
- package/dist/transports.d.ts.map +1 -1
- package/dist/transports.js +1 -1
- package/dist/transports.mjs +1 -1
- package/package.json +72 -9
- package/dist/index-CHIsdA9n.d.ts.map +0 -1
- package/dist/index-iDTW2-eY.d.mts.map +0 -1
- package/dist/logitron-logger.module-2AzkadqZ.mjs.map +0 -1
- package/dist/logitron-logger.module-BqNKp0Fs.js.map +0 -1
- package/dist/logitron-logger.module-C0G8JGVf.d.ts.map +0 -1
- package/dist/logitron-logger.module-DQKaZTJL.d.mts.map +0 -1
- package/dist/promise-C4pQPcK4.mjs.map +0 -1
- package/dist/promise-DaiZ2BaH.js.map +0 -1
- package/dist/transport.manager-5VVdqS3o.mjs.map +0 -1
- package/dist/transport.manager-DCOm4uIQ.js.map +0 -1
package/dist/testing.d.mts
CHANGED
package/dist/testing.d.ts
CHANGED
package/dist/testing.js
CHANGED
|
@@ -121,7 +121,13 @@ function createMockLogger(options = {}) {
|
|
|
121
121
|
context: ctx
|
|
122
122
|
}).logger;
|
|
123
123
|
},
|
|
124
|
-
async close() {}
|
|
124
|
+
async close() {},
|
|
125
|
+
use(_plugin) {
|
|
126
|
+
return this;
|
|
127
|
+
},
|
|
128
|
+
unuse(_pluginName) {
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
125
131
|
};
|
|
126
132
|
const instance = {
|
|
127
133
|
get logger() {
|
package/dist/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","names":["_calls: MockLogCall[]","logger: IBaseLogger","instance: MockLoggerInstance"],"sources":["../src/testing/mock-logger.ts"],"sourcesContent":["/**\n * logixia/testing — Zero-dependency mock logger for Vitest & Jest.\n *\n * @example\n * ```ts\n * import { createMockLogger } from 'logixia/testing';\n *\n * const mock = createMockLogger();\n * await myService.doSomething(mock.logger);\n *\n * mock.expectLog('info', { message: 'order created' });\n * mock.expectLog('error', { message: /failed/ });\n * mock.reset();\n * ```\n */\n\nimport type { IBaseLogger, LogEntry } from '../types';\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MockLogCall {\n level: string;\n message: string;\n data?: Record<string, unknown>;\n /** Full LogEntry shape for assertions that inspect the complete record. */\n entry: Pick<LogEntry, 'level' | 'message' | 'context'> & { data?: Record<string, unknown> };\n}\n\nexport type LogMatcher =\n | string\n | RegExp\n | ((call: MockLogCall) => boolean)\n | Partial<Record<'message' | 'level' | string, unknown>>;\n\nexport interface MockLoggerInstance {\n /** The logger itself — pass this where an IBaseLogger is expected. */\n readonly logger: IBaseLogger;\n /** Every call recorded across all levels, in insertion order. */\n readonly calls: MockLogCall[];\n /**\n * Get all calls for a specific level (case-insensitive). If `level` is\n * omitted, returns all calls across every level.\n */\n getCalls(level?: string): MockLogCall[];\n /** Return the most recent call, optionally filtered by level. */\n getLastCall(level?: string): MockLogCall | undefined;\n /**\n * Assert that at least one recorded call matches `matcher`.\n *\n * - string → exact message match\n * - RegExp → message test\n * - function → receives the full MockLogCall\n * - object → every key/value must match (supports RegExp values)\n *\n * Throws an Error with a descriptive message if the assertion fails (works\n * with both Vitest `expect` and Jest matchers via `.toThrow()`, or you can\n * let it propagate directly).\n */\n expectLog(level: string, matcher?: LogMatcher): void;\n /**\n * Assert that NO recorded call matches `matcher` at the given level.\n */\n expectNoLog(level: string, matcher?: LogMatcher): void;\n /** Clear all recorded calls. Call between tests. */\n reset(): void;\n /**\n * Silence — when true, the mock suppresses all console output from the\n * logger. Default: true.\n */\n silent: boolean;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveCallField(call: MockLogCall, key: string): unknown {\n if (key === 'message') return call.message;\n if (key === 'level') return call.level;\n return call.data?.[key] ?? (call.entry as Record<string, unknown>)[key];\n}\n\nfunction formatMatcherDescription(matcher: LogMatcher | undefined): string {\n if (matcher === undefined) return '(any)';\n if (matcher instanceof RegExp) return matcher.toString();\n return JSON.stringify(matcher);\n}\n\nfunction matchesCall(call: MockLogCall, matcher?: LogMatcher): boolean {\n if (matcher === undefined) return true;\n if (typeof matcher === 'string') return call.message === matcher;\n if (matcher instanceof RegExp) return matcher.test(call.message);\n if (typeof matcher === 'function') return matcher(call);\n // Object shape: every key/value must match\n for (const [key, expected] of Object.entries(matcher)) {\n const actual = resolveCallField(call, key);\n if (expected instanceof RegExp) {\n if (!expected.test(String(actual ?? ''))) return false;\n } else {\n if (actual !== expected) return false;\n }\n }\n return true;\n}\n\nfunction formatCalls(calls: MockLogCall[]): string {\n if (calls.length === 0) return ' (no calls recorded)';\n return calls\n .map((c) => ` [${c.level}] \"${c.message}\" ${c.data ? JSON.stringify(c.data) : ''}`)\n .join('\\n');\n}\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\n/**\n * Create a mock logger for use in tests.\n *\n * The returned object implements `IBaseLogger` and additionally exposes `.calls`,\n * `.getCalls()`, `.getLastCall()`, `.expectLog()`, `.expectNoLog()`, and `.reset()`.\n *\n * @param options.silent Suppress console output (default: true)\n * @param options.context Optional context label written into every `entry.context`\n */\nexport function createMockLogger(\n options: { silent?: boolean; context?: string } = {}\n): MockLoggerInstance {\n const { silent = true, context } = options;\n const _calls: MockLogCall[] = [];\n\n function record(\n level: string,\n messageOrError: string | Error,\n data?: Record<string, unknown>\n ): void {\n const message = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n const extraData =\n messageOrError instanceof Error\n ? { ...data, error: { message: messageOrError.message, stack: messageOrError.stack } }\n : data;\n\n _calls.push({\n level,\n message,\n ...(extraData !== undefined ? { data: extraData } : {}),\n entry: {\n level,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(extraData !== undefined ? { data: extraData } : {}),\n },\n });\n }\n\n const logger: IBaseLogger = {\n async error(messageOrError, data) {\n record('error', messageOrError as string | Error, data);\n },\n async warn(message, data) {\n record('warn', message, data);\n },\n async info(message, data) {\n record('info', message, data);\n },\n async debug(message, data) {\n record('debug', message, data);\n },\n async trace(message, data) {\n record('trace', message, data);\n },\n async verbose(message, data) {\n record('verbose', message, data);\n },\n async logLevel(level, message, data) {\n record(level, message, data);\n },\n\n time(_label) {\n /* no-op in tests */\n },\n async timeEnd(_label) {\n return 0;\n },\n async timeAsync(_label, fn) {\n return fn();\n },\n\n setLevel(_level) {\n /* no-op */\n },\n getLevel() {\n return 'info';\n },\n setContext(_ctx) {\n /* no-op */\n },\n getContext() {\n return context;\n },\n\n enableField(_f) {\n /* no-op */\n },\n disableField(_f) {\n /* no-op */\n },\n isFieldEnabled(_f) {\n return true;\n },\n getFieldState() {\n return {};\n },\n resetFieldState() {\n /* no-op */\n },\n\n enableTransportLevelPrompting() {\n /* no-op */\n },\n disableTransportLevelPrompting() {\n /* no-op */\n },\n setTransportLevels(_id, _levels) {\n /* no-op */\n },\n getTransportLevels(_id): string[] | undefined {\n return undefined;\n },\n clearTransportLevelPreferences() {\n /* no-op */\n },\n getAvailableTransports() {\n return [];\n },\n\n child(ctx, _data) {\n return createMockLogger({ silent, context: ctx }).logger;\n },\n async close() {\n /* no-op */\n },\n };\n\n const instance: MockLoggerInstance = {\n get logger() {\n return logger;\n },\n get calls() {\n return _calls;\n },\n\n getCalls(level?: string): MockLogCall[] {\n if (!level) return [..._calls];\n const l = level.toLowerCase();\n return _calls.filter((c) => c.level.toLowerCase() === l);\n },\n\n getLastCall(level?: string): MockLogCall | undefined {\n const filtered = level\n ? _calls.filter((c) => c.level.toLowerCase() === level.toLowerCase())\n : _calls;\n return filtered[filtered.length - 1];\n },\n\n expectLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (!matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected at least one [${level}] log matching ${matcherDesc}.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n expectNoLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected NO [${level}] log matching ${matcherDesc}, but one was found.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n reset(): void {\n _calls.length = 0;\n },\n\n silent,\n };\n\n return instance;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"testing.js","names":["_calls: MockLogCall[]","logger: IBaseLogger","instance: MockLoggerInstance"],"sources":["../src/testing/mock-logger.ts"],"sourcesContent":["/**\n * logixia/testing — Zero-dependency mock logger for Vitest & Jest.\n *\n * @example\n * ```ts\n * import { createMockLogger } from 'logixia/testing';\n *\n * const mock = createMockLogger();\n * await myService.doSomething(mock.logger);\n *\n * mock.expectLog('info', { message: 'order created' });\n * mock.expectLog('error', { message: /failed/ });\n * mock.reset();\n * ```\n */\n\nimport type { IBaseLogger, LogEntry } from '../types';\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MockLogCall {\n level: string;\n message: string;\n data?: Record<string, unknown>;\n /** Full LogEntry shape for assertions that inspect the complete record. */\n entry: Pick<LogEntry, 'level' | 'message' | 'context'> & { data?: Record<string, unknown> };\n}\n\nexport type LogMatcher =\n | string\n | RegExp\n | ((call: MockLogCall) => boolean)\n | Partial<Record<'message' | 'level' | string, unknown>>;\n\nexport interface MockLoggerInstance {\n /** The logger itself — pass this where an IBaseLogger is expected. */\n readonly logger: IBaseLogger;\n /** Every call recorded across all levels, in insertion order. */\n readonly calls: MockLogCall[];\n /**\n * Get all calls for a specific level (case-insensitive). If `level` is\n * omitted, returns all calls across every level.\n */\n getCalls(level?: string): MockLogCall[];\n /** Return the most recent call, optionally filtered by level. */\n getLastCall(level?: string): MockLogCall | undefined;\n /**\n * Assert that at least one recorded call matches `matcher`.\n *\n * - string → exact message match\n * - RegExp → message test\n * - function → receives the full MockLogCall\n * - object → every key/value must match (supports RegExp values)\n *\n * Throws an Error with a descriptive message if the assertion fails (works\n * with both Vitest `expect` and Jest matchers via `.toThrow()`, or you can\n * let it propagate directly).\n */\n expectLog(level: string, matcher?: LogMatcher): void;\n /**\n * Assert that NO recorded call matches `matcher` at the given level.\n */\n expectNoLog(level: string, matcher?: LogMatcher): void;\n /** Clear all recorded calls. Call between tests. */\n reset(): void;\n /**\n * Silence — when true, the mock suppresses all console output from the\n * logger. Default: true.\n */\n silent: boolean;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveCallField(call: MockLogCall, key: string): unknown {\n if (key === 'message') return call.message;\n if (key === 'level') return call.level;\n return call.data?.[key] ?? (call.entry as Record<string, unknown>)[key];\n}\n\nfunction formatMatcherDescription(matcher: LogMatcher | undefined): string {\n if (matcher === undefined) return '(any)';\n if (matcher instanceof RegExp) return matcher.toString();\n return JSON.stringify(matcher);\n}\n\nfunction matchesCall(call: MockLogCall, matcher?: LogMatcher): boolean {\n if (matcher === undefined) return true;\n if (typeof matcher === 'string') return call.message === matcher;\n if (matcher instanceof RegExp) return matcher.test(call.message);\n if (typeof matcher === 'function') return matcher(call);\n // Object shape: every key/value must match\n for (const [key, expected] of Object.entries(matcher)) {\n const actual = resolveCallField(call, key);\n if (expected instanceof RegExp) {\n if (!expected.test(String(actual ?? ''))) return false;\n } else {\n if (actual !== expected) return false;\n }\n }\n return true;\n}\n\nfunction formatCalls(calls: MockLogCall[]): string {\n if (calls.length === 0) return ' (no calls recorded)';\n return calls\n .map((c) => ` [${c.level}] \"${c.message}\" ${c.data ? JSON.stringify(c.data) : ''}`)\n .join('\\n');\n}\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\n/**\n * Create a mock logger for use in tests.\n *\n * The returned object implements `IBaseLogger` and additionally exposes `.calls`,\n * `.getCalls()`, `.getLastCall()`, `.expectLog()`, `.expectNoLog()`, and `.reset()`.\n *\n * @param options.silent Suppress console output (default: true)\n * @param options.context Optional context label written into every `entry.context`\n */\nexport function createMockLogger(\n options: { silent?: boolean; context?: string } = {}\n): MockLoggerInstance {\n const { silent = true, context } = options;\n const _calls: MockLogCall[] = [];\n\n function record(\n level: string,\n messageOrError: string | Error,\n data?: Record<string, unknown>\n ): void {\n const message = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n const extraData =\n messageOrError instanceof Error\n ? { ...data, error: { message: messageOrError.message, stack: messageOrError.stack } }\n : data;\n\n _calls.push({\n level,\n message,\n ...(extraData !== undefined ? { data: extraData } : {}),\n entry: {\n level,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(extraData !== undefined ? { data: extraData } : {}),\n },\n });\n }\n\n const logger: IBaseLogger = {\n async error(messageOrError, data) {\n record('error', messageOrError as string | Error, data);\n },\n async warn(message, data) {\n record('warn', message, data);\n },\n async info(message, data) {\n record('info', message, data);\n },\n async debug(message, data) {\n record('debug', message, data);\n },\n async trace(message, data) {\n record('trace', message, data);\n },\n async verbose(message, data) {\n record('verbose', message, data);\n },\n async logLevel(level, message, data) {\n record(level, message, data);\n },\n\n time(_label) {\n /* no-op in tests */\n },\n async timeEnd(_label) {\n return 0;\n },\n async timeAsync(_label, fn) {\n return fn();\n },\n\n setLevel(_level) {\n /* no-op */\n },\n getLevel() {\n return 'info';\n },\n setContext(_ctx) {\n /* no-op */\n },\n getContext() {\n return context;\n },\n\n enableField(_f) {\n /* no-op */\n },\n disableField(_f) {\n /* no-op */\n },\n isFieldEnabled(_f) {\n return true;\n },\n getFieldState() {\n return {};\n },\n resetFieldState() {\n /* no-op */\n },\n\n enableTransportLevelPrompting() {\n /* no-op */\n },\n disableTransportLevelPrompting() {\n /* no-op */\n },\n setTransportLevels(_id, _levels) {\n /* no-op */\n },\n getTransportLevels(_id): string[] | undefined {\n return undefined;\n },\n clearTransportLevelPreferences() {\n /* no-op */\n },\n getAvailableTransports() {\n return [];\n },\n\n child(ctx, _data) {\n return createMockLogger({ silent, context: ctx }).logger;\n },\n async close() {\n /* no-op */\n },\n\n // Plugin API stubs — mock logger does not run plugins\n use(_plugin) {\n return this;\n },\n unuse(_pluginName) {\n return this;\n },\n };\n\n const instance: MockLoggerInstance = {\n get logger() {\n return logger;\n },\n get calls() {\n return _calls;\n },\n\n getCalls(level?: string): MockLogCall[] {\n if (!level) return [..._calls];\n const l = level.toLowerCase();\n return _calls.filter((c) => c.level.toLowerCase() === l);\n },\n\n getLastCall(level?: string): MockLogCall | undefined {\n const filtered = level\n ? _calls.filter((c) => c.level.toLowerCase() === level.toLowerCase())\n : _calls;\n return filtered[filtered.length - 1];\n },\n\n expectLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (!matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected at least one [${level}] log matching ${matcherDesc}.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n expectNoLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected NO [${level}] log matching ${matcherDesc}, but one was found.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n reset(): void {\n _calls.length = 0;\n },\n\n silent,\n };\n\n return instance;\n}\n"],"mappings":"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"}
|
package/dist/testing.mjs
CHANGED
|
@@ -120,7 +120,13 @@ function createMockLogger(options = {}) {
|
|
|
120
120
|
context: ctx
|
|
121
121
|
}).logger;
|
|
122
122
|
},
|
|
123
|
-
async close() {}
|
|
123
|
+
async close() {},
|
|
124
|
+
use(_plugin) {
|
|
125
|
+
return this;
|
|
126
|
+
},
|
|
127
|
+
unuse(_pluginName) {
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
124
130
|
};
|
|
125
131
|
const instance = {
|
|
126
132
|
get logger() {
|
package/dist/testing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.mjs","names":["_calls: MockLogCall[]","logger: IBaseLogger","instance: MockLoggerInstance"],"sources":["../src/testing/mock-logger.ts"],"sourcesContent":["/**\n * logixia/testing — Zero-dependency mock logger for Vitest & Jest.\n *\n * @example\n * ```ts\n * import { createMockLogger } from 'logixia/testing';\n *\n * const mock = createMockLogger();\n * await myService.doSomething(mock.logger);\n *\n * mock.expectLog('info', { message: 'order created' });\n * mock.expectLog('error', { message: /failed/ });\n * mock.reset();\n * ```\n */\n\nimport type { IBaseLogger, LogEntry } from '../types';\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MockLogCall {\n level: string;\n message: string;\n data?: Record<string, unknown>;\n /** Full LogEntry shape for assertions that inspect the complete record. */\n entry: Pick<LogEntry, 'level' | 'message' | 'context'> & { data?: Record<string, unknown> };\n}\n\nexport type LogMatcher =\n | string\n | RegExp\n | ((call: MockLogCall) => boolean)\n | Partial<Record<'message' | 'level' | string, unknown>>;\n\nexport interface MockLoggerInstance {\n /** The logger itself — pass this where an IBaseLogger is expected. */\n readonly logger: IBaseLogger;\n /** Every call recorded across all levels, in insertion order. */\n readonly calls: MockLogCall[];\n /**\n * Get all calls for a specific level (case-insensitive). If `level` is\n * omitted, returns all calls across every level.\n */\n getCalls(level?: string): MockLogCall[];\n /** Return the most recent call, optionally filtered by level. */\n getLastCall(level?: string): MockLogCall | undefined;\n /**\n * Assert that at least one recorded call matches `matcher`.\n *\n * - string → exact message match\n * - RegExp → message test\n * - function → receives the full MockLogCall\n * - object → every key/value must match (supports RegExp values)\n *\n * Throws an Error with a descriptive message if the assertion fails (works\n * with both Vitest `expect` and Jest matchers via `.toThrow()`, or you can\n * let it propagate directly).\n */\n expectLog(level: string, matcher?: LogMatcher): void;\n /**\n * Assert that NO recorded call matches `matcher` at the given level.\n */\n expectNoLog(level: string, matcher?: LogMatcher): void;\n /** Clear all recorded calls. Call between tests. */\n reset(): void;\n /**\n * Silence — when true, the mock suppresses all console output from the\n * logger. Default: true.\n */\n silent: boolean;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveCallField(call: MockLogCall, key: string): unknown {\n if (key === 'message') return call.message;\n if (key === 'level') return call.level;\n return call.data?.[key] ?? (call.entry as Record<string, unknown>)[key];\n}\n\nfunction formatMatcherDescription(matcher: LogMatcher | undefined): string {\n if (matcher === undefined) return '(any)';\n if (matcher instanceof RegExp) return matcher.toString();\n return JSON.stringify(matcher);\n}\n\nfunction matchesCall(call: MockLogCall, matcher?: LogMatcher): boolean {\n if (matcher === undefined) return true;\n if (typeof matcher === 'string') return call.message === matcher;\n if (matcher instanceof RegExp) return matcher.test(call.message);\n if (typeof matcher === 'function') return matcher(call);\n // Object shape: every key/value must match\n for (const [key, expected] of Object.entries(matcher)) {\n const actual = resolveCallField(call, key);\n if (expected instanceof RegExp) {\n if (!expected.test(String(actual ?? ''))) return false;\n } else {\n if (actual !== expected) return false;\n }\n }\n return true;\n}\n\nfunction formatCalls(calls: MockLogCall[]): string {\n if (calls.length === 0) return ' (no calls recorded)';\n return calls\n .map((c) => ` [${c.level}] \"${c.message}\" ${c.data ? JSON.stringify(c.data) : ''}`)\n .join('\\n');\n}\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\n/**\n * Create a mock logger for use in tests.\n *\n * The returned object implements `IBaseLogger` and additionally exposes `.calls`,\n * `.getCalls()`, `.getLastCall()`, `.expectLog()`, `.expectNoLog()`, and `.reset()`.\n *\n * @param options.silent Suppress console output (default: true)\n * @param options.context Optional context label written into every `entry.context`\n */\nexport function createMockLogger(\n options: { silent?: boolean; context?: string } = {}\n): MockLoggerInstance {\n const { silent = true, context } = options;\n const _calls: MockLogCall[] = [];\n\n function record(\n level: string,\n messageOrError: string | Error,\n data?: Record<string, unknown>\n ): void {\n const message = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n const extraData =\n messageOrError instanceof Error\n ? { ...data, error: { message: messageOrError.message, stack: messageOrError.stack } }\n : data;\n\n _calls.push({\n level,\n message,\n ...(extraData !== undefined ? { data: extraData } : {}),\n entry: {\n level,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(extraData !== undefined ? { data: extraData } : {}),\n },\n });\n }\n\n const logger: IBaseLogger = {\n async error(messageOrError, data) {\n record('error', messageOrError as string | Error, data);\n },\n async warn(message, data) {\n record('warn', message, data);\n },\n async info(message, data) {\n record('info', message, data);\n },\n async debug(message, data) {\n record('debug', message, data);\n },\n async trace(message, data) {\n record('trace', message, data);\n },\n async verbose(message, data) {\n record('verbose', message, data);\n },\n async logLevel(level, message, data) {\n record(level, message, data);\n },\n\n time(_label) {\n /* no-op in tests */\n },\n async timeEnd(_label) {\n return 0;\n },\n async timeAsync(_label, fn) {\n return fn();\n },\n\n setLevel(_level) {\n /* no-op */\n },\n getLevel() {\n return 'info';\n },\n setContext(_ctx) {\n /* no-op */\n },\n getContext() {\n return context;\n },\n\n enableField(_f) {\n /* no-op */\n },\n disableField(_f) {\n /* no-op */\n },\n isFieldEnabled(_f) {\n return true;\n },\n getFieldState() {\n return {};\n },\n resetFieldState() {\n /* no-op */\n },\n\n enableTransportLevelPrompting() {\n /* no-op */\n },\n disableTransportLevelPrompting() {\n /* no-op */\n },\n setTransportLevels(_id, _levels) {\n /* no-op */\n },\n getTransportLevels(_id): string[] | undefined {\n return undefined;\n },\n clearTransportLevelPreferences() {\n /* no-op */\n },\n getAvailableTransports() {\n return [];\n },\n\n child(ctx, _data) {\n return createMockLogger({ silent, context: ctx }).logger;\n },\n async close() {\n /* no-op */\n },\n };\n\n const instance: MockLoggerInstance = {\n get logger() {\n return logger;\n },\n get calls() {\n return _calls;\n },\n\n getCalls(level?: string): MockLogCall[] {\n if (!level) return [..._calls];\n const l = level.toLowerCase();\n return _calls.filter((c) => c.level.toLowerCase() === l);\n },\n\n getLastCall(level?: string): MockLogCall | undefined {\n const filtered = level\n ? _calls.filter((c) => c.level.toLowerCase() === level.toLowerCase())\n : _calls;\n return filtered[filtered.length - 1];\n },\n\n expectLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (!matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected at least one [${level}] log matching ${matcherDesc}.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n expectNoLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected NO [${level}] log matching ${matcherDesc}, but one was found.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n reset(): void {\n _calls.length = 0;\n },\n\n silent,\n };\n\n return instance;\n}\n"],"mappings":";AA0EA,SAAS,iBAAiB,MAAmB,KAAsB;;AACjE,KAAI,QAAQ,UAAW,QAAO,KAAK;AACnC,KAAI,QAAQ,QAAS,QAAO,KAAK;AACjC,uBAAO,KAAK,8DAAO,SAAS,KAAK,MAAkC;;AAGrE,SAAS,yBAAyB,SAAyC;AACzE,KAAI,YAAY,OAAW,QAAO;AAClC,KAAI,mBAAmB,OAAQ,QAAO,QAAQ,UAAU;AACxD,QAAO,KAAK,UAAU,QAAQ;;AAGhC,SAAS,YAAY,MAAmB,SAA+B;AACrE,KAAI,YAAY,OAAW,QAAO;AAClC,KAAI,OAAO,YAAY,SAAU,QAAO,KAAK,YAAY;AACzD,KAAI,mBAAmB,OAAQ,QAAO,QAAQ,KAAK,KAAK,QAAQ;AAChE,KAAI,OAAO,YAAY,WAAY,QAAO,QAAQ,KAAK;AAEvD,MAAK,MAAM,CAAC,KAAK,aAAa,OAAO,QAAQ,QAAQ,EAAE;EACrD,MAAM,SAAS,iBAAiB,MAAM,IAAI;AAC1C,MAAI,oBAAoB,QACtB;OAAI,CAAC,SAAS,KAAK,OAAO,UAAU,GAAG,CAAC,CAAE,QAAO;aAE7C,WAAW,SAAU,QAAO;;AAGpC,QAAO;;AAGT,SAAS,YAAY,OAA8B;AACjD,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAO,MACJ,KAAK,MAAM,MAAM,EAAE,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,OAAO,KAAK,UAAU,EAAE,KAAK,GAAG,KAAK,CACnF,KAAK,KAAK;;;;;;;;;;;AAcf,SAAgB,iBACd,UAAkD,EAAE,EAChC;CACpB,MAAM,EAAE,SAAS,MAAM,YAAY;CACnC,MAAMA,SAAwB,EAAE;CAEhC,SAAS,OACP,OACA,gBACA,MACM;EACN,MAAM,UAAU,0BAA0B,QAAQ,eAAe,UAAU;EAC3E,MAAM,YACJ,0BAA0B,QACtB;GAAE,GAAG;GAAM,OAAO;IAAE,SAAS,eAAe;IAAS,OAAO,eAAe;IAAO;GAAE,GACpF;AAEN,SAAO,KAAK;GACV;GACA;GACA,GAAI,cAAc,SAAY,EAAE,MAAM,WAAW,GAAG,EAAE;GACtD,OAAO;IACL;IACA;IACA,GAAI,YAAY,SAAY,EAAE,SAAS,GAAG,EAAE;IAC5C,GAAI,cAAc,SAAY,EAAE,MAAM,WAAW,GAAG,EAAE;IACvD;GACF,CAAC;;CAGJ,MAAMC,SAAsB;EAC1B,MAAM,MAAM,gBAAgB,MAAM;AAChC,UAAO,SAAS,gBAAkC,KAAK;;EAEzD,MAAM,KAAK,SAAS,MAAM;AACxB,UAAO,QAAQ,SAAS,KAAK;;EAE/B,MAAM,KAAK,SAAS,MAAM;AACxB,UAAO,QAAQ,SAAS,KAAK;;EAE/B,MAAM,MAAM,SAAS,MAAM;AACzB,UAAO,SAAS,SAAS,KAAK;;EAEhC,MAAM,MAAM,SAAS,MAAM;AACzB,UAAO,SAAS,SAAS,KAAK;;EAEhC,MAAM,QAAQ,SAAS,MAAM;AAC3B,UAAO,WAAW,SAAS,KAAK;;EAElC,MAAM,SAAS,OAAO,SAAS,MAAM;AACnC,UAAO,OAAO,SAAS,KAAK;;EAG9B,KAAK,QAAQ;EAGb,MAAM,QAAQ,QAAQ;AACpB,UAAO;;EAET,MAAM,UAAU,QAAQ,IAAI;AAC1B,UAAO,IAAI;;EAGb,SAAS,QAAQ;EAGjB,WAAW;AACT,UAAO;;EAET,WAAW,MAAM;EAGjB,aAAa;AACX,UAAO;;EAGT,YAAY,IAAI;EAGhB,aAAa,IAAI;EAGjB,eAAe,IAAI;AACjB,UAAO;;EAET,gBAAgB;AACd,UAAO,EAAE;;EAEX,kBAAkB;EAIlB,gCAAgC;EAGhC,iCAAiC;EAGjC,mBAAmB,KAAK,SAAS;EAGjC,mBAAmB,KAA2B;EAG9C,iCAAiC;EAGjC,yBAAyB;AACvB,UAAO,EAAE;;EAGX,MAAM,KAAK,OAAO;AAChB,UAAO,iBAAiB;IAAE;IAAQ,SAAS;IAAK,CAAC,CAAC;;EAEpD,MAAM,QAAQ;EAGf;CAED,MAAMC,WAA+B;EACnC,IAAI,SAAS;AACX,UAAO;;EAET,IAAI,QAAQ;AACV,UAAO;;EAGT,SAAS,OAA+B;AACtC,OAAI,CAAC,MAAO,QAAO,CAAC,GAAG,OAAO;GAC9B,MAAM,IAAI,MAAM,aAAa;AAC7B,UAAO,OAAO,QAAQ,MAAM,EAAE,MAAM,aAAa,KAAK,EAAE;;EAG1D,YAAY,OAAyC;GACnD,MAAM,WAAW,QACb,OAAO,QAAQ,MAAM,EAAE,MAAM,aAAa,KAAK,MAAM,aAAa,CAAC,GACnE;AACJ,UAAO,SAAS,SAAS,SAAS;;EAGpC,UAAU,OAAe,SAA4B;AAGnD,OAAI,CAFe,SAAS,SAAS,MAAM,CAChB,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,EACjD;IACZ,MAAM,cAAc,yBAAyB,QAAQ;AACrD,UAAM,IAAI,MACR,0BAA0B,MAAM,iBAAiB,YAAY,sBACvC,YAAY,OAAO,GAC1C;;;EAIL,YAAY,OAAe,SAA4B;AAGrD,OAFmB,SAAS,SAAS,MAAM,CAChB,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,EAClD;IACX,MAAM,cAAc,yBAAyB,QAAQ;AACrD,UAAM,IAAI,MACR,gBAAgB,MAAM,iBAAiB,YAAY,yCAC7B,YAAY,OAAO,GAC1C;;;EAIL,QAAc;AACZ,UAAO,SAAS;;EAGlB;EACD;AAED,QAAO"}
|
|
1
|
+
{"version":3,"file":"testing.mjs","names":["_calls: MockLogCall[]","logger: IBaseLogger","instance: MockLoggerInstance"],"sources":["../src/testing/mock-logger.ts"],"sourcesContent":["/**\n * logixia/testing — Zero-dependency mock logger for Vitest & Jest.\n *\n * @example\n * ```ts\n * import { createMockLogger } from 'logixia/testing';\n *\n * const mock = createMockLogger();\n * await myService.doSomething(mock.logger);\n *\n * mock.expectLog('info', { message: 'order created' });\n * mock.expectLog('error', { message: /failed/ });\n * mock.reset();\n * ```\n */\n\nimport type { IBaseLogger, LogEntry } from '../types';\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MockLogCall {\n level: string;\n message: string;\n data?: Record<string, unknown>;\n /** Full LogEntry shape for assertions that inspect the complete record. */\n entry: Pick<LogEntry, 'level' | 'message' | 'context'> & { data?: Record<string, unknown> };\n}\n\nexport type LogMatcher =\n | string\n | RegExp\n | ((call: MockLogCall) => boolean)\n | Partial<Record<'message' | 'level' | string, unknown>>;\n\nexport interface MockLoggerInstance {\n /** The logger itself — pass this where an IBaseLogger is expected. */\n readonly logger: IBaseLogger;\n /** Every call recorded across all levels, in insertion order. */\n readonly calls: MockLogCall[];\n /**\n * Get all calls for a specific level (case-insensitive). If `level` is\n * omitted, returns all calls across every level.\n */\n getCalls(level?: string): MockLogCall[];\n /** Return the most recent call, optionally filtered by level. */\n getLastCall(level?: string): MockLogCall | undefined;\n /**\n * Assert that at least one recorded call matches `matcher`.\n *\n * - string → exact message match\n * - RegExp → message test\n * - function → receives the full MockLogCall\n * - object → every key/value must match (supports RegExp values)\n *\n * Throws an Error with a descriptive message if the assertion fails (works\n * with both Vitest `expect` and Jest matchers via `.toThrow()`, or you can\n * let it propagate directly).\n */\n expectLog(level: string, matcher?: LogMatcher): void;\n /**\n * Assert that NO recorded call matches `matcher` at the given level.\n */\n expectNoLog(level: string, matcher?: LogMatcher): void;\n /** Clear all recorded calls. Call between tests. */\n reset(): void;\n /**\n * Silence — when true, the mock suppresses all console output from the\n * logger. Default: true.\n */\n silent: boolean;\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction resolveCallField(call: MockLogCall, key: string): unknown {\n if (key === 'message') return call.message;\n if (key === 'level') return call.level;\n return call.data?.[key] ?? (call.entry as Record<string, unknown>)[key];\n}\n\nfunction formatMatcherDescription(matcher: LogMatcher | undefined): string {\n if (matcher === undefined) return '(any)';\n if (matcher instanceof RegExp) return matcher.toString();\n return JSON.stringify(matcher);\n}\n\nfunction matchesCall(call: MockLogCall, matcher?: LogMatcher): boolean {\n if (matcher === undefined) return true;\n if (typeof matcher === 'string') return call.message === matcher;\n if (matcher instanceof RegExp) return matcher.test(call.message);\n if (typeof matcher === 'function') return matcher(call);\n // Object shape: every key/value must match\n for (const [key, expected] of Object.entries(matcher)) {\n const actual = resolveCallField(call, key);\n if (expected instanceof RegExp) {\n if (!expected.test(String(actual ?? ''))) return false;\n } else {\n if (actual !== expected) return false;\n }\n }\n return true;\n}\n\nfunction formatCalls(calls: MockLogCall[]): string {\n if (calls.length === 0) return ' (no calls recorded)';\n return calls\n .map((c) => ` [${c.level}] \"${c.message}\" ${c.data ? JSON.stringify(c.data) : ''}`)\n .join('\\n');\n}\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\n/**\n * Create a mock logger for use in tests.\n *\n * The returned object implements `IBaseLogger` and additionally exposes `.calls`,\n * `.getCalls()`, `.getLastCall()`, `.expectLog()`, `.expectNoLog()`, and `.reset()`.\n *\n * @param options.silent Suppress console output (default: true)\n * @param options.context Optional context label written into every `entry.context`\n */\nexport function createMockLogger(\n options: { silent?: boolean; context?: string } = {}\n): MockLoggerInstance {\n const { silent = true, context } = options;\n const _calls: MockLogCall[] = [];\n\n function record(\n level: string,\n messageOrError: string | Error,\n data?: Record<string, unknown>\n ): void {\n const message = messageOrError instanceof Error ? messageOrError.message : messageOrError;\n const extraData =\n messageOrError instanceof Error\n ? { ...data, error: { message: messageOrError.message, stack: messageOrError.stack } }\n : data;\n\n _calls.push({\n level,\n message,\n ...(extraData !== undefined ? { data: extraData } : {}),\n entry: {\n level,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(extraData !== undefined ? { data: extraData } : {}),\n },\n });\n }\n\n const logger: IBaseLogger = {\n async error(messageOrError, data) {\n record('error', messageOrError as string | Error, data);\n },\n async warn(message, data) {\n record('warn', message, data);\n },\n async info(message, data) {\n record('info', message, data);\n },\n async debug(message, data) {\n record('debug', message, data);\n },\n async trace(message, data) {\n record('trace', message, data);\n },\n async verbose(message, data) {\n record('verbose', message, data);\n },\n async logLevel(level, message, data) {\n record(level, message, data);\n },\n\n time(_label) {\n /* no-op in tests */\n },\n async timeEnd(_label) {\n return 0;\n },\n async timeAsync(_label, fn) {\n return fn();\n },\n\n setLevel(_level) {\n /* no-op */\n },\n getLevel() {\n return 'info';\n },\n setContext(_ctx) {\n /* no-op */\n },\n getContext() {\n return context;\n },\n\n enableField(_f) {\n /* no-op */\n },\n disableField(_f) {\n /* no-op */\n },\n isFieldEnabled(_f) {\n return true;\n },\n getFieldState() {\n return {};\n },\n resetFieldState() {\n /* no-op */\n },\n\n enableTransportLevelPrompting() {\n /* no-op */\n },\n disableTransportLevelPrompting() {\n /* no-op */\n },\n setTransportLevels(_id, _levels) {\n /* no-op */\n },\n getTransportLevels(_id): string[] | undefined {\n return undefined;\n },\n clearTransportLevelPreferences() {\n /* no-op */\n },\n getAvailableTransports() {\n return [];\n },\n\n child(ctx, _data) {\n return createMockLogger({ silent, context: ctx }).logger;\n },\n async close() {\n /* no-op */\n },\n\n // Plugin API stubs — mock logger does not run plugins\n use(_plugin) {\n return this;\n },\n unuse(_pluginName) {\n return this;\n },\n };\n\n const instance: MockLoggerInstance = {\n get logger() {\n return logger;\n },\n get calls() {\n return _calls;\n },\n\n getCalls(level?: string): MockLogCall[] {\n if (!level) return [..._calls];\n const l = level.toLowerCase();\n return _calls.filter((c) => c.level.toLowerCase() === l);\n },\n\n getLastCall(level?: string): MockLogCall | undefined {\n const filtered = level\n ? _calls.filter((c) => c.level.toLowerCase() === level.toLowerCase())\n : _calls;\n return filtered[filtered.length - 1];\n },\n\n expectLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (!matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected at least one [${level}] log matching ${matcherDesc}.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n expectNoLog(level: string, matcher?: LogMatcher): void {\n const levelCalls = instance.getCalls(level);\n const matched = levelCalls.some((c) => matchesCall(c, matcher));\n if (matched) {\n const matcherDesc = formatMatcherDescription(matcher);\n throw new Error(\n `Expected NO [${level}] log matching ${matcherDesc}, but one was found.\\n` +\n `Recorded calls:\\n${formatCalls(_calls)}`\n );\n }\n },\n\n reset(): void {\n _calls.length = 0;\n },\n\n silent,\n };\n\n return instance;\n}\n"],"mappings":"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"}
|
|
@@ -48,6 +48,14 @@ function internalError(message, error) {
|
|
|
48
48
|
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/transports/console.transport.ts
|
|
51
|
+
/**
|
|
52
|
+
* Writes log entries to stdout (info/debug/verbose) and stderr (error/warn).
|
|
53
|
+
*
|
|
54
|
+
* Supports pretty-printed colorized output and compact JSON mode.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* transports: { console: { format: 'json' } }
|
|
58
|
+
*/
|
|
51
59
|
var ConsoleTransport = class ConsoleTransport {
|
|
52
60
|
static #_ = this.COLORS = new Map([
|
|
53
61
|
["red", "\x1B[31m"],
|
|
@@ -126,14 +134,35 @@ var ConsoleTransport = class ConsoleTransport {
|
|
|
126
134
|
|
|
127
135
|
//#endregion
|
|
128
136
|
//#region src/transports/database.transport.ts
|
|
137
|
+
/**
|
|
138
|
+
* Validates that a SQL identifier (table/index name) contains only safe characters.
|
|
139
|
+
* Prevents SQL injection via user-supplied table names.
|
|
140
|
+
*/
|
|
141
|
+
function validateSqlIdentifier(name, label = "table") {
|
|
142
|
+
if (!/^[a-zA-Z_]\w*$/.test(name)) throw new Error(`Invalid ${label} name "${name}". Only letters, digits, and underscores are allowed, and the name must start with a letter or underscore.`);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Persists log entries to a database in batches.
|
|
146
|
+
*
|
|
147
|
+
* Supports MongoDB, PostgreSQL, MySQL, and SQLite. Entries are buffered and
|
|
148
|
+
* flushed on a configurable interval or batch size threshold to minimize
|
|
149
|
+
* round-trips.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* transports: {
|
|
153
|
+
* database: { type: 'postgresql', host: 'localhost', database: 'appdb', table: 'logs' }
|
|
154
|
+
* }
|
|
155
|
+
*/
|
|
129
156
|
var DatabaseTransport = class {
|
|
130
157
|
constructor(config) {
|
|
131
158
|
this.config = config;
|
|
132
159
|
this.name = "database";
|
|
133
160
|
this.batch = [];
|
|
161
|
+
this.isFlushing = false;
|
|
134
162
|
this.isConnected = false;
|
|
135
163
|
this.batchSize = config.batchSize || 100;
|
|
136
164
|
this.flushInterval = config.flushInterval || 5e3;
|
|
165
|
+
if (config.table) validateSqlIdentifier(config.table, "table");
|
|
137
166
|
this.setupFlushTimer();
|
|
138
167
|
}
|
|
139
168
|
async write(entry) {
|
|
@@ -146,6 +175,8 @@ var DatabaseTransport = class {
|
|
|
146
175
|
}
|
|
147
176
|
async flush() {
|
|
148
177
|
if (this.batch.length === 0) return;
|
|
178
|
+
if (this.isFlushing) return;
|
|
179
|
+
this.isFlushing = true;
|
|
149
180
|
const entriesToFlush = [...this.batch];
|
|
150
181
|
this.batch = [];
|
|
151
182
|
try {
|
|
@@ -168,6 +199,8 @@ var DatabaseTransport = class {
|
|
|
168
199
|
internalError("Database flush error", error);
|
|
169
200
|
this.batch.unshift(...entriesToFlush);
|
|
170
201
|
throw error;
|
|
202
|
+
} finally {
|
|
203
|
+
this.isFlushing = false;
|
|
171
204
|
}
|
|
172
205
|
}
|
|
173
206
|
async isReady() {
|
|
@@ -240,7 +273,7 @@ var DatabaseTransport = class {
|
|
|
240
273
|
}
|
|
241
274
|
async connectMySQL() {
|
|
242
275
|
try {
|
|
243
|
-
const mysql = await import("./promise-
|
|
276
|
+
const mysql = await import("./promise-BrZcjavs.mjs").then(__toDynamicImportESM()).catch(() => {
|
|
244
277
|
throw new Error("MySQL driver not installed. Run: npm install mysql2");
|
|
245
278
|
});
|
|
246
279
|
const config = {
|
|
@@ -534,6 +567,14 @@ var AnalyticsTransport = class {
|
|
|
534
567
|
|
|
535
568
|
//#endregion
|
|
536
569
|
//#region src/transports/datadog.transport.ts
|
|
570
|
+
/**
|
|
571
|
+
* Sends log entries and metrics to Datadog via the Logs and Metrics HTTP APIs.
|
|
572
|
+
*
|
|
573
|
+
* The API key is transmitted via the `DD-API-KEY` request header — never in the URL.
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* transports: { datadog: { apiKey: process.env.DD_API_KEY, service: 'api', env: 'production' } }
|
|
577
|
+
*/
|
|
537
578
|
var DataDogTransport = class extends AnalyticsTransport {
|
|
538
579
|
constructor(config) {
|
|
539
580
|
super("datadog", config);
|
|
@@ -576,7 +617,7 @@ var DataDogTransport = class extends AnalyticsTransport {
|
|
|
576
617
|
}
|
|
577
618
|
async sendLogBatch(entries) {
|
|
578
619
|
const payload = { logs: entries.map((entry) => this.transformToDataDogLog(entry)) };
|
|
579
|
-
await this.makeLogsRequest("/v1/input
|
|
620
|
+
await this.makeLogsRequest("/v1/input", payload);
|
|
580
621
|
}
|
|
581
622
|
async sendMetric(entry) {
|
|
582
623
|
await this.sendMetricBatch([entry]);
|
|
@@ -759,11 +800,21 @@ const mkdir = promisify(fs.mkdir);
|
|
|
759
800
|
const unlink = promisify(fs.unlink);
|
|
760
801
|
const readdir = promisify(fs.readdir);
|
|
761
802
|
const stat = promisify(fs.stat);
|
|
803
|
+
/**
|
|
804
|
+
* Appends log entries to a local file with automatic rotation.
|
|
805
|
+
*
|
|
806
|
+
* Supports batched writes, size-based and date-based rotation, and optional
|
|
807
|
+
* gzip compression of rotated files.
|
|
808
|
+
*
|
|
809
|
+
* @example
|
|
810
|
+
* transports: { file: { filename: 'app.log', dirname: './logs', maxSize: '50MB' } }
|
|
811
|
+
*/
|
|
762
812
|
var FileTransport = class {
|
|
763
813
|
constructor(config) {
|
|
764
814
|
this.name = "file";
|
|
765
815
|
this.batch = [];
|
|
766
816
|
this.lastRotation = /* @__PURE__ */ new Date();
|
|
817
|
+
this.isRotating = false;
|
|
767
818
|
this.config = {
|
|
768
819
|
format: "json",
|
|
769
820
|
batchSize: 100,
|
|
@@ -778,7 +829,14 @@ var FileTransport = class {
|
|
|
778
829
|
}
|
|
779
830
|
async write(entry) {
|
|
780
831
|
try {
|
|
781
|
-
if (this.shouldRotateNow()
|
|
832
|
+
if (this.shouldRotateNow() && !this.isRotating) {
|
|
833
|
+
this.isRotating = true;
|
|
834
|
+
try {
|
|
835
|
+
await this.rotate();
|
|
836
|
+
} finally {
|
|
837
|
+
this.isRotating = false;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
782
840
|
if (this.config.batchSize && this.config.batchSize > 1) this.addToBatch(entry);
|
|
783
841
|
else await this.writeBatch([entry]);
|
|
784
842
|
} catch (error) {
|
|
@@ -910,6 +968,14 @@ var FileTransport = class {
|
|
|
910
968
|
|
|
911
969
|
//#endregion
|
|
912
970
|
//#region src/transports/google-analytics.transport.ts
|
|
971
|
+
/**
|
|
972
|
+
* Sends log entries as Google Analytics 4 Measurement Protocol events.
|
|
973
|
+
*
|
|
974
|
+
* @example
|
|
975
|
+
* transports: {
|
|
976
|
+
* googleAnalytics: { measurementId: 'G-XXXXXXX', apiSecret: process.env.GA_API_SECRET }
|
|
977
|
+
* }
|
|
978
|
+
*/
|
|
913
979
|
var GoogleAnalyticsTransport = class extends AnalyticsTransport {
|
|
914
980
|
constructor(config) {
|
|
915
981
|
super("google-analytics", config);
|
|
@@ -1133,6 +1199,12 @@ var GoogleAnalyticsTransport = class extends AnalyticsTransport {
|
|
|
1133
1199
|
|
|
1134
1200
|
//#endregion
|
|
1135
1201
|
//#region src/transports/mixpanel.transport.ts
|
|
1202
|
+
/**
|
|
1203
|
+
* Sends log entries as Mixpanel events via the Track and Engage HTTP APIs.
|
|
1204
|
+
*
|
|
1205
|
+
* @example
|
|
1206
|
+
* transports: { mixpanel: { token: process.env.MIXPANEL_TOKEN } }
|
|
1207
|
+
*/
|
|
1136
1208
|
var MixpanelTransport = class extends AnalyticsTransport {
|
|
1137
1209
|
constructor(config) {
|
|
1138
1210
|
super("mixpanel", config);
|
|
@@ -1270,6 +1342,12 @@ var MixpanelTransport = class extends AnalyticsTransport {
|
|
|
1270
1342
|
|
|
1271
1343
|
//#endregion
|
|
1272
1344
|
//#region src/transports/segment.transport.ts
|
|
1345
|
+
/**
|
|
1346
|
+
* Sends log entries as Segment track/identify events via the HTTP Tracking API.
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* transports: { segment: { writeKey: process.env.SEGMENT_WRITE_KEY } }
|
|
1350
|
+
*/
|
|
1273
1351
|
var SegmentTransport = class extends AnalyticsTransport {
|
|
1274
1352
|
constructor(config) {
|
|
1275
1353
|
super("segment", config);
|
|
@@ -1895,4 +1973,4 @@ var TransportManager = class extends EventEmitter {
|
|
|
1895
1973
|
|
|
1896
1974
|
//#endregion
|
|
1897
1975
|
export { FileTransport as a, DatabaseTransport as c, internalLog as d, internalWarn as f, GoogleAnalyticsTransport as i, ConsoleTransport as l, SegmentTransport as n, DataDogTransport as o, MixpanelTransport as r, AnalyticsTransport as s, TransportManager as t, internalError as u };
|
|
1898
|
-
//# sourceMappingURL=transport.manager-
|
|
1976
|
+
//# sourceMappingURL=transport.manager-DR7TLXQT.mjs.map
|