@logtape/windows-eventlog 1.0.0-dev.225

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.
Files changed (48) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +129 -0
  3. package/dist/_virtual/rolldown_runtime.cjs +30 -0
  4. package/dist/ffi.bun.cjs +102 -0
  5. package/dist/ffi.bun.js +102 -0
  6. package/dist/ffi.bun.js.map +1 -0
  7. package/dist/ffi.deno.cjs +116 -0
  8. package/dist/ffi.deno.js +113 -0
  9. package/dist/ffi.deno.js.map +1 -0
  10. package/dist/ffi.node.cjs +78 -0
  11. package/dist/ffi.node.js +78 -0
  12. package/dist/ffi.node.js.map +1 -0
  13. package/dist/mod.cjs +12 -0
  14. package/dist/mod.d.cts +3 -0
  15. package/dist/mod.d.ts +3 -0
  16. package/dist/mod.js +4 -0
  17. package/dist/platform.cjs +30 -0
  18. package/dist/platform.js +30 -0
  19. package/dist/platform.js.map +1 -0
  20. package/dist/sink.bun.cjs +102 -0
  21. package/dist/sink.bun.d.cts +34 -0
  22. package/dist/sink.bun.d.cts.map +1 -0
  23. package/dist/sink.bun.d.ts +34 -0
  24. package/dist/sink.bun.d.ts.map +1 -0
  25. package/dist/sink.bun.js +102 -0
  26. package/dist/sink.bun.js.map +1 -0
  27. package/dist/sink.deno.cjs +116 -0
  28. package/dist/sink.deno.d.cts +34 -0
  29. package/dist/sink.deno.d.cts.map +1 -0
  30. package/dist/sink.deno.d.ts +34 -0
  31. package/dist/sink.deno.d.ts.map +1 -0
  32. package/dist/sink.deno.js +116 -0
  33. package/dist/sink.deno.js.map +1 -0
  34. package/dist/sink.node.cjs +112 -0
  35. package/dist/sink.node.d.cts +33 -0
  36. package/dist/sink.node.d.cts.map +1 -0
  37. package/dist/sink.node.d.ts +33 -0
  38. package/dist/sink.node.d.ts.map +1 -0
  39. package/dist/sink.node.js +112 -0
  40. package/dist/sink.node.js.map +1 -0
  41. package/dist/types.cjs +55 -0
  42. package/dist/types.d.cts +79 -0
  43. package/dist/types.d.cts.map +1 -0
  44. package/dist/types.d.ts +79 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +52 -0
  47. package/dist/types.js.map +1 -0
  48. package/package.json +73 -0
@@ -0,0 +1,116 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_types = require('./types.cjs');
3
+ const require_platform = require('./platform.cjs');
4
+ const require_ffi_deno = require('./ffi.deno.cjs');
5
+ const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
6
+
7
+ //#region sink.deno.ts
8
+ /**
9
+ * Formats a log record message into a string suitable for Windows Event Log.
10
+ * Combines the template and arguments into a readable message.
11
+ */
12
+ function formatMessage(record) {
13
+ let message = "";
14
+ for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
15
+ else {
16
+ const arg = record.message[i];
17
+ if (typeof arg === "string") message += arg;
18
+ else message += JSON.stringify(arg);
19
+ }
20
+ return message;
21
+ }
22
+ /**
23
+ * Formats additional context information for the log entry.
24
+ * Includes category, properties, and other metadata.
25
+ */
26
+ function formatContext(record) {
27
+ const context = [];
28
+ if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
29
+ if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
30
+ context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
31
+ return context.length > 0 ? `\n\n${context.join("\n")}` : "";
32
+ }
33
+ /**
34
+ * Maps LogTape log levels to Windows Event Log types.
35
+ */
36
+ function getEventType(level) {
37
+ switch (level) {
38
+ case "fatal":
39
+ case "error": return require_ffi_deno.EVENTLOG_ERROR_TYPE;
40
+ case "warning": return require_ffi_deno.EVENTLOG_WARNING_TYPE;
41
+ case "info":
42
+ case "debug":
43
+ case "trace":
44
+ default: return require_ffi_deno.EVENTLOG_INFORMATION_TYPE;
45
+ }
46
+ }
47
+ /**
48
+ * Creates a Windows Event Log sink for Deno environments using FFI.
49
+ *
50
+ * This implementation uses Deno's Foreign Function Interface to directly
51
+ * call Windows Event Log APIs, providing reliable Event Log integration
52
+ * without depending on external packages.
53
+ *
54
+ * @param options Configuration options for the sink
55
+ * @returns A LogTape sink that writes to Windows Event Log
56
+ * @throws {WindowsPlatformError} If not running on Windows
57
+ * @throws {WindowsEventLogError} If Event Log operations fail
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
62
+ *
63
+ * const sink = getWindowsEventLogSink({
64
+ * sourceName: "MyApp",
65
+ * logName: "Application"
66
+ * });
67
+ * ```
68
+ *
69
+ * @since 1.0.0
70
+ */
71
+ function getWindowsEventLogSink(options) {
72
+ require_platform.validateWindowsPlatform();
73
+ const { sourceName, logName: _logName = "Application", eventIdMapping = {} } = options;
74
+ const eventIds = {
75
+ ...require_types.DEFAULT_EVENT_ID_MAPPING,
76
+ ...eventIdMapping
77
+ };
78
+ let ffi = null;
79
+ const metaLogger = (0, __logtape_logtape.getLogger)([
80
+ "logtape",
81
+ "meta",
82
+ "windows-eventlog"
83
+ ]);
84
+ const sink = (record) => {
85
+ if (!ffi) try {
86
+ ffi = new require_ffi_deno.WindowsEventLogFFI(sourceName);
87
+ ffi.initialize();
88
+ } catch (error) {
89
+ metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
90
+ return;
91
+ }
92
+ const message = formatMessage(record);
93
+ const context = formatContext(record);
94
+ const fullMessage = message + context;
95
+ const eventType = getEventType(record.level);
96
+ const eventId = eventIds[record.level];
97
+ try {
98
+ ffi.writeEvent(eventType, eventId, fullMessage);
99
+ } catch (error) {
100
+ metaLogger.error("Failed to write {level} message to Windows Event Log: {error}", {
101
+ level: record.level,
102
+ error
103
+ });
104
+ }
105
+ };
106
+ sink[Symbol.dispose] = () => {
107
+ if (ffi) {
108
+ ffi.dispose();
109
+ ffi = null;
110
+ }
111
+ };
112
+ return sink;
113
+ }
114
+
115
+ //#endregion
116
+ exports.getWindowsEventLogSink = getWindowsEventLogSink;
@@ -0,0 +1,34 @@
1
+ import { WindowsEventLogSinkOptions } from "./types.cjs";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region sink.deno.d.ts
5
+
6
+ /**
7
+ * Creates a Windows Event Log sink for Deno environments using FFI.
8
+ *
9
+ * This implementation uses Deno's Foreign Function Interface to directly
10
+ * call Windows Event Log APIs, providing reliable Event Log integration
11
+ * without depending on external packages.
12
+ *
13
+ * @param options Configuration options for the sink
14
+ * @returns A LogTape sink that writes to Windows Event Log
15
+ * @throws {WindowsPlatformError} If not running on Windows
16
+ * @throws {WindowsEventLogError} If Event Log operations fail
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
21
+ *
22
+ * const sink = getWindowsEventLogSink({
23
+ * sourceName: "MyApp",
24
+ * logName: "Application"
25
+ * });
26
+ * ```
27
+ *
28
+ * @since 1.0.0
29
+ */
30
+ declare function getWindowsEventLogSink(options: WindowsEventLogSinkOptions): Sink & Disposable;
31
+ //# sourceMappingURL=sink.deno.d.ts.map
32
+ //#endregion
33
+ export { getWindowsEventLogSink };
34
+ //# sourceMappingURL=sink.deno.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.deno.d.cts","names":[],"sources":["../sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;AAuGA;;;;;AAEoB;;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
@@ -0,0 +1,34 @@
1
+ import { WindowsEventLogSinkOptions } from "./types.js";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region sink.deno.d.ts
5
+
6
+ /**
7
+ * Creates a Windows Event Log sink for Deno environments using FFI.
8
+ *
9
+ * This implementation uses Deno's Foreign Function Interface to directly
10
+ * call Windows Event Log APIs, providing reliable Event Log integration
11
+ * without depending on external packages.
12
+ *
13
+ * @param options Configuration options for the sink
14
+ * @returns A LogTape sink that writes to Windows Event Log
15
+ * @throws {WindowsPlatformError} If not running on Windows
16
+ * @throws {WindowsEventLogError} If Event Log operations fail
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
21
+ *
22
+ * const sink = getWindowsEventLogSink({
23
+ * sourceName: "MyApp",
24
+ * logName: "Application"
25
+ * });
26
+ * ```
27
+ *
28
+ * @since 1.0.0
29
+ */
30
+ declare function getWindowsEventLogSink(options: WindowsEventLogSinkOptions): Sink & Disposable;
31
+ //# sourceMappingURL=sink.deno.d.ts.map
32
+ //#endregion
33
+ export { getWindowsEventLogSink };
34
+ //# sourceMappingURL=sink.deno.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.deno.d.ts","names":[],"sources":["../sink.deno.ts"],"sourcesContent":[],"mappings":";;;;;;;AAuGA;;;;;AAEoB;;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
@@ -0,0 +1,116 @@
1
+ import { DEFAULT_EVENT_ID_MAPPING } from "./types.js";
2
+ import { validateWindowsPlatform } from "./platform.js";
3
+ import { EVENTLOG_ERROR_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, WindowsEventLogFFI } from "./ffi.deno.js";
4
+ import { getLogger } from "@logtape/logtape";
5
+
6
+ //#region sink.deno.ts
7
+ /**
8
+ * Formats a log record message into a string suitable for Windows Event Log.
9
+ * Combines the template and arguments into a readable message.
10
+ */
11
+ function formatMessage(record) {
12
+ let message = "";
13
+ for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
14
+ else {
15
+ const arg = record.message[i];
16
+ if (typeof arg === "string") message += arg;
17
+ else message += JSON.stringify(arg);
18
+ }
19
+ return message;
20
+ }
21
+ /**
22
+ * Formats additional context information for the log entry.
23
+ * Includes category, properties, and other metadata.
24
+ */
25
+ function formatContext(record) {
26
+ const context = [];
27
+ if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
28
+ if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
29
+ context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
30
+ return context.length > 0 ? `\n\n${context.join("\n")}` : "";
31
+ }
32
+ /**
33
+ * Maps LogTape log levels to Windows Event Log types.
34
+ */
35
+ function getEventType(level) {
36
+ switch (level) {
37
+ case "fatal":
38
+ case "error": return EVENTLOG_ERROR_TYPE;
39
+ case "warning": return EVENTLOG_WARNING_TYPE;
40
+ case "info":
41
+ case "debug":
42
+ case "trace":
43
+ default: return EVENTLOG_INFORMATION_TYPE;
44
+ }
45
+ }
46
+ /**
47
+ * Creates a Windows Event Log sink for Deno environments using FFI.
48
+ *
49
+ * This implementation uses Deno's Foreign Function Interface to directly
50
+ * call Windows Event Log APIs, providing reliable Event Log integration
51
+ * without depending on external packages.
52
+ *
53
+ * @param options Configuration options for the sink
54
+ * @returns A LogTape sink that writes to Windows Event Log
55
+ * @throws {WindowsPlatformError} If not running on Windows
56
+ * @throws {WindowsEventLogError} If Event Log operations fail
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
61
+ *
62
+ * const sink = getWindowsEventLogSink({
63
+ * sourceName: "MyApp",
64
+ * logName: "Application"
65
+ * });
66
+ * ```
67
+ *
68
+ * @since 1.0.0
69
+ */
70
+ function getWindowsEventLogSink(options) {
71
+ validateWindowsPlatform();
72
+ const { sourceName, logName: _logName = "Application", eventIdMapping = {} } = options;
73
+ const eventIds = {
74
+ ...DEFAULT_EVENT_ID_MAPPING,
75
+ ...eventIdMapping
76
+ };
77
+ let ffi = null;
78
+ const metaLogger = getLogger([
79
+ "logtape",
80
+ "meta",
81
+ "windows-eventlog"
82
+ ]);
83
+ const sink = (record) => {
84
+ if (!ffi) try {
85
+ ffi = new WindowsEventLogFFI(sourceName);
86
+ ffi.initialize();
87
+ } catch (error) {
88
+ metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
89
+ return;
90
+ }
91
+ const message = formatMessage(record);
92
+ const context = formatContext(record);
93
+ const fullMessage = message + context;
94
+ const eventType = getEventType(record.level);
95
+ const eventId = eventIds[record.level];
96
+ try {
97
+ ffi.writeEvent(eventType, eventId, fullMessage);
98
+ } catch (error) {
99
+ metaLogger.error("Failed to write {level} message to Windows Event Log: {error}", {
100
+ level: record.level,
101
+ error
102
+ });
103
+ }
104
+ };
105
+ sink[Symbol.dispose] = () => {
106
+ if (ffi) {
107
+ ffi.dispose();
108
+ ffi = null;
109
+ }
110
+ };
111
+ return sink;
112
+ }
113
+
114
+ //#endregion
115
+ export { getWindowsEventLogSink };
116
+ //# sourceMappingURL=sink.deno.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.deno.js","names":["record: LogRecord","context: string[]","level: string","options: WindowsEventLogSinkOptions","ffi: WindowsEventLogFFI | null","sink: Sink & Disposable"],"sources":["../sink.deno.ts"],"sourcesContent":["import type { LogRecord, Sink } from \"@logtape/logtape\";\nimport { getLogger } from \"@logtape/logtape\";\nimport {\n EVENTLOG_ERROR_TYPE,\n EVENTLOG_INFORMATION_TYPE,\n EVENTLOG_WARNING_TYPE,\n WindowsEventLogFFI,\n} from \"./ffi.deno.ts\";\nimport { validateWindowsPlatform } from \"./platform.ts\";\nimport type { WindowsEventLogSinkOptions } from \"./types.ts\";\nimport { DEFAULT_EVENT_ID_MAPPING } from \"./types.ts\";\n\n/**\n * Formats a log record message into a string suitable for Windows Event Log.\n * Combines the template and arguments into a readable message.\n */\nfunction formatMessage(record: LogRecord): string {\n let message = \"\";\n\n // Combine template parts with arguments\n for (let i = 0; i < record.message.length; i++) {\n if (i % 2 === 0) {\n // Template part\n message += record.message[i];\n } else {\n // Argument - serialize it\n const arg = record.message[i];\n if (typeof arg === \"string\") {\n message += arg;\n } else {\n message += JSON.stringify(arg);\n }\n }\n }\n\n return message;\n}\n\n/**\n * Formats additional context information for the log entry.\n * Includes category, properties, and other metadata.\n */\nfunction formatContext(record: LogRecord): string {\n const context: string[] = [];\n\n // Add category if present\n if (record.category && record.category.length > 0) {\n context.push(`Category: ${record.category.join(\".\")}`);\n }\n\n // Add properties if present\n if (record.properties && Object.keys(record.properties).length > 0) {\n context.push(`Properties: ${JSON.stringify(record.properties)}`);\n }\n\n // Add timestamp\n context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);\n\n return context.length > 0 ? `\\n\\n${context.join(\"\\n\")}` : \"\";\n}\n\n/**\n * Maps LogTape log levels to Windows Event Log types.\n */\nfunction getEventType(level: string): number {\n switch (level) {\n case \"fatal\":\n case \"error\":\n return EVENTLOG_ERROR_TYPE;\n case \"warning\":\n return EVENTLOG_WARNING_TYPE;\n case \"info\":\n case \"debug\":\n case \"trace\":\n default:\n return EVENTLOG_INFORMATION_TYPE;\n }\n}\n\n/**\n * Creates a Windows Event Log sink for Deno environments using FFI.\n *\n * This implementation uses Deno's Foreign Function Interface to directly\n * call Windows Event Log APIs, providing reliable Event Log integration\n * without depending on external packages.\n *\n * @param options Configuration options for the sink\n * @returns A LogTape sink that writes to Windows Event Log\n * @throws {WindowsPlatformError} If not running on Windows\n * @throws {WindowsEventLogError} If Event Log operations fail\n *\n * @example\n * ```typescript\n * import { getWindowsEventLogSink } from \"@logtape/windows-eventlog\";\n *\n * const sink = getWindowsEventLogSink({\n * sourceName: \"MyApp\",\n * logName: \"Application\"\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function getWindowsEventLogSink(\n options: WindowsEventLogSinkOptions,\n): Sink & Disposable {\n // Validate platform early\n validateWindowsPlatform();\n\n const {\n sourceName,\n logName: _logName = \"Application\",\n eventIdMapping = {},\n } = options;\n\n // Merge with default event ID mapping\n const eventIds = { ...DEFAULT_EVENT_ID_MAPPING, ...eventIdMapping };\n\n let ffi: WindowsEventLogFFI | null = null;\n const metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n const sink: Sink & Disposable = (record: LogRecord) => {\n // Initialize FFI if needed\n if (!ffi) {\n try {\n ffi = new WindowsEventLogFFI(sourceName);\n ffi.initialize();\n } catch (error) {\n metaLogger.error(\n \"Failed to initialize Windows Event Log FFI: {error}\",\n { error },\n );\n return; // Skip this log record\n }\n }\n\n // Format the complete message\n const message = formatMessage(record);\n const context = formatContext(record);\n const fullMessage = message + context;\n\n // Get event type and ID for this log level\n const eventType = getEventType(record.level);\n const eventId = eventIds[record.level];\n\n // Write to Event Log\n try {\n ffi.writeEvent(eventType, eventId, fullMessage);\n } catch (error) {\n metaLogger.error(\n \"Failed to write {level} message to Windows Event Log: {error}\",\n { level: record.level, error },\n );\n }\n };\n\n // Implement Disposable for cleanup\n sink[Symbol.dispose] = () => {\n // Clean up FFI resources\n if (ffi) {\n ffi.dispose();\n ffi = null;\n }\n };\n\n return sink;\n}\n"],"mappings":";;;;;;;;;;AAgBA,SAAS,cAAcA,QAA2B;CAChD,IAAI,UAAU;AAGd,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IACzC,KAAI,IAAI,MAAM,EAEZ,YAAW,OAAO,QAAQ;MACrB;EAEL,MAAM,MAAM,OAAO,QAAQ;AAC3B,aAAW,QAAQ,SACjB,YAAW;MAEX,YAAW,KAAK,UAAU,IAAI;CAEjC;AAGH,QAAO;AACR;;;;;AAMD,SAAS,cAAcA,QAA2B;CAChD,MAAMC,UAAoB,CAAE;AAG5B,KAAI,OAAO,YAAY,OAAO,SAAS,SAAS,EAC9C,SAAQ,MAAM,YAAY,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE;AAIxD,KAAI,OAAO,cAAc,OAAO,KAAK,OAAO,WAAW,CAAC,SAAS,EAC/D,SAAQ,MAAM,cAAc,KAAK,UAAU,OAAO,WAAW,CAAC,EAAE;AAIlE,SAAQ,MAAM,aAAa,IAAI,KAAK,OAAO,WAAW,aAAa,CAAC,EAAE;AAEtE,QAAO,QAAQ,SAAS,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC,IAAI;AAC3D;;;;AAKD,SAAS,aAAaC,OAAuB;AAC3C,SAAQ,OAAR;EACE,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,QACE,QAAO;CACV;AACF;;;;;;;;;;;;;;;;;;;;;;;;;AA0BD,SAAgB,uBACdC,SACmB;AAEnB,0BAAyB;CAEzB,MAAM,EACJ,YACA,SAAS,WAAW,eACpB,iBAAiB,CAAE,GACpB,GAAG;CAGJ,MAAM,WAAW;EAAE,GAAG;EAA0B,GAAG;CAAgB;CAEnE,IAAIC,MAAiC;CACrC,MAAM,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;CAErE,MAAMC,OAA0B,CAACL,WAAsB;AAErD,OAAK,IACH,KAAI;AACF,SAAM,IAAI,mBAAmB;AAC7B,OAAI,YAAY;EACjB,SAAQ,OAAO;AACd,cAAW,MACT,uDACA,EAAE,MAAO,EACV;AACD;EACD;EAIH,MAAM,UAAU,cAAc,OAAO;EACrC,MAAM,UAAU,cAAc,OAAO;EACrC,MAAM,cAAc,UAAU;EAG9B,MAAM,YAAY,aAAa,OAAO,MAAM;EAC5C,MAAM,UAAU,SAAS,OAAO;AAGhC,MAAI;AACF,OAAI,WAAW,WAAW,SAAS,YAAY;EAChD,SAAQ,OAAO;AACd,cAAW,MACT,iEACA;IAAE,OAAO,OAAO;IAAO;GAAO,EAC/B;EACF;CACF;AAGD,MAAK,OAAO,WAAW,MAAM;AAE3B,MAAI,KAAK;AACP,OAAI,SAAS;AACb,SAAM;EACP;CACF;AAED,QAAO;AACR"}
@@ -0,0 +1,112 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const require_types = require('./types.cjs');
3
+ const require_platform = require('./platform.cjs');
4
+ const require_ffi_node = require('./ffi.node.cjs');
5
+ const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
6
+
7
+ //#region sink.node.ts
8
+ /**
9
+ * Formats a log record message into a string suitable for Windows Event Log.
10
+ * Combines the template and arguments into a readable message.
11
+ */
12
+ function formatMessage(record) {
13
+ let message = "";
14
+ for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
15
+ else {
16
+ const arg = record.message[i];
17
+ if (typeof arg === "string") message += arg;
18
+ else message += JSON.stringify(arg);
19
+ }
20
+ return message;
21
+ }
22
+ /**
23
+ * Formats additional context information for the log entry.
24
+ * Includes category, properties, and other metadata.
25
+ */
26
+ function formatContext(record) {
27
+ const context = [];
28
+ if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
29
+ if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
30
+ context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
31
+ return context.length > 0 ? `\n\n${context.join("\n")}` : "";
32
+ }
33
+ /**
34
+ * Creates a Windows Event Log sink for Node.js environments using FFI.
35
+ *
36
+ * This implementation uses koffi to call Windows Event Log API directly,
37
+ * providing high performance logging without external dependencies.
38
+ *
39
+ * @param options Configuration options for the sink
40
+ * @returns A LogTape sink that writes to Windows Event Log
41
+ * @throws {WindowsPlatformError} If not running on Windows
42
+ * @throws {WindowsEventLogError} If Event Log operations fail
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
47
+ *
48
+ * const sink = getWindowsEventLogSink({
49
+ * sourceName: "MyApp",
50
+ * logName: "Application"
51
+ * });
52
+ * ```
53
+ *
54
+ * @since 1.0.0
55
+ */
56
+ function getWindowsEventLogSink(options) {
57
+ require_platform.validateWindowsPlatform();
58
+ const { sourceName, logName: _logName = "Application", eventIdMapping = {} } = options;
59
+ const eventIds = {
60
+ ...require_types.DEFAULT_EVENT_ID_MAPPING,
61
+ ...eventIdMapping
62
+ };
63
+ let ffi = null;
64
+ let initPromise = null;
65
+ const metaLogger = (0, __logtape_logtape.getLogger)([
66
+ "logtape",
67
+ "meta",
68
+ "windows-eventlog"
69
+ ]);
70
+ const sink = (record) => {
71
+ const message = formatMessage(record);
72
+ const context = formatContext(record);
73
+ const fullMessage = message + context;
74
+ const eventType = require_types.mapLogLevelToEventType(record.level);
75
+ const eventId = eventIds[record.level];
76
+ if (!ffi) {
77
+ ffi = new require_ffi_node.WindowsEventLogFFI(sourceName);
78
+ initPromise = ffi.initialize().then(() => {
79
+ if (ffi) try {
80
+ ffi.writeEvent(eventType, eventId, fullMessage);
81
+ } catch (error) {
82
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
83
+ }
84
+ }).catch((error) => {
85
+ metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
86
+ ffi = null;
87
+ initPromise = null;
88
+ });
89
+ } else if (initPromise) initPromise = initPromise.then(() => {
90
+ if (ffi) try {
91
+ ffi.writeEvent(eventType, eventId, fullMessage);
92
+ } catch (error) {
93
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
94
+ }
95
+ });
96
+ else try {
97
+ ffi.writeEvent(eventType, eventId, fullMessage);
98
+ } catch (error) {
99
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
100
+ }
101
+ };
102
+ sink[Symbol.dispose] = () => {
103
+ if (ffi) {
104
+ ffi.dispose();
105
+ ffi = null;
106
+ }
107
+ };
108
+ return sink;
109
+ }
110
+
111
+ //#endregion
112
+ exports.getWindowsEventLogSink = getWindowsEventLogSink;
@@ -0,0 +1,33 @@
1
+ import { WindowsEventLogSinkOptions } from "./types.cjs";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region sink.node.d.ts
5
+
6
+ /**
7
+ * Creates a Windows Event Log sink for Node.js environments using FFI.
8
+ *
9
+ * This implementation uses koffi to call Windows Event Log API directly,
10
+ * providing high performance logging without external dependencies.
11
+ *
12
+ * @param options Configuration options for the sink
13
+ * @returns A LogTape sink that writes to Windows Event Log
14
+ * @throws {WindowsPlatformError} If not running on Windows
15
+ * @throws {WindowsEventLogError} If Event Log operations fail
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
20
+ *
21
+ * const sink = getWindowsEventLogSink({
22
+ * sourceName: "MyApp",
23
+ * logName: "Application"
24
+ * });
25
+ * ```
26
+ *
27
+ * @since 1.0.0
28
+ */
29
+ declare function getWindowsEventLogSink(options: WindowsEventLogSinkOptions): Sink & Disposable;
30
+ //# sourceMappingURL=sink.node.d.ts.map
31
+ //#endregion
32
+ export { getWindowsEventLogSink };
33
+ //# sourceMappingURL=sink.node.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.node.d.cts","names":[],"sources":["../sink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;AAmFA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
@@ -0,0 +1,33 @@
1
+ import { WindowsEventLogSinkOptions } from "./types.js";
2
+ import { Sink } from "@logtape/logtape";
3
+
4
+ //#region sink.node.d.ts
5
+
6
+ /**
7
+ * Creates a Windows Event Log sink for Node.js environments using FFI.
8
+ *
9
+ * This implementation uses koffi to call Windows Event Log API directly,
10
+ * providing high performance logging without external dependencies.
11
+ *
12
+ * @param options Configuration options for the sink
13
+ * @returns A LogTape sink that writes to Windows Event Log
14
+ * @throws {WindowsPlatformError} If not running on Windows
15
+ * @throws {WindowsEventLogError} If Event Log operations fail
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
20
+ *
21
+ * const sink = getWindowsEventLogSink({
22
+ * sourceName: "MyApp",
23
+ * logName: "Application"
24
+ * });
25
+ * ```
26
+ *
27
+ * @since 1.0.0
28
+ */
29
+ declare function getWindowsEventLogSink(options: WindowsEventLogSinkOptions): Sink & Disposable;
30
+ //# sourceMappingURL=sink.node.d.ts.map
31
+ //#endregion
32
+ export { getWindowsEventLogSink };
33
+ //# sourceMappingURL=sink.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.node.d.ts","names":[],"sources":["../sink.node.ts"],"sourcesContent":[],"mappings":";;;;;;;AAmFA;;;;;AAEoB;;;;;;;;;;;;;;;;iBAFJ,sBAAA,UACL,6BACR,OAAO"}
@@ -0,0 +1,112 @@
1
+ import { DEFAULT_EVENT_ID_MAPPING, mapLogLevelToEventType } from "./types.js";
2
+ import { validateWindowsPlatform } from "./platform.js";
3
+ import { WindowsEventLogFFI } from "./ffi.node.js";
4
+ import { getLogger } from "@logtape/logtape";
5
+
6
+ //#region sink.node.ts
7
+ /**
8
+ * Formats a log record message into a string suitable for Windows Event Log.
9
+ * Combines the template and arguments into a readable message.
10
+ */
11
+ function formatMessage(record) {
12
+ let message = "";
13
+ for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
14
+ else {
15
+ const arg = record.message[i];
16
+ if (typeof arg === "string") message += arg;
17
+ else message += JSON.stringify(arg);
18
+ }
19
+ return message;
20
+ }
21
+ /**
22
+ * Formats additional context information for the log entry.
23
+ * Includes category, properties, and other metadata.
24
+ */
25
+ function formatContext(record) {
26
+ const context = [];
27
+ if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
28
+ if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
29
+ context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
30
+ return context.length > 0 ? `\n\n${context.join("\n")}` : "";
31
+ }
32
+ /**
33
+ * Creates a Windows Event Log sink for Node.js environments using FFI.
34
+ *
35
+ * This implementation uses koffi to call Windows Event Log API directly,
36
+ * providing high performance logging without external dependencies.
37
+ *
38
+ * @param options Configuration options for the sink
39
+ * @returns A LogTape sink that writes to Windows Event Log
40
+ * @throws {WindowsPlatformError} If not running on Windows
41
+ * @throws {WindowsEventLogError} If Event Log operations fail
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { getWindowsEventLogSink } from "@logtape/windows-eventlog";
46
+ *
47
+ * const sink = getWindowsEventLogSink({
48
+ * sourceName: "MyApp",
49
+ * logName: "Application"
50
+ * });
51
+ * ```
52
+ *
53
+ * @since 1.0.0
54
+ */
55
+ function getWindowsEventLogSink(options) {
56
+ validateWindowsPlatform();
57
+ const { sourceName, logName: _logName = "Application", eventIdMapping = {} } = options;
58
+ const eventIds = {
59
+ ...DEFAULT_EVENT_ID_MAPPING,
60
+ ...eventIdMapping
61
+ };
62
+ let ffi = null;
63
+ let initPromise = null;
64
+ const metaLogger = getLogger([
65
+ "logtape",
66
+ "meta",
67
+ "windows-eventlog"
68
+ ]);
69
+ const sink = (record) => {
70
+ const message = formatMessage(record);
71
+ const context = formatContext(record);
72
+ const fullMessage = message + context;
73
+ const eventType = mapLogLevelToEventType(record.level);
74
+ const eventId = eventIds[record.level];
75
+ if (!ffi) {
76
+ ffi = new WindowsEventLogFFI(sourceName);
77
+ initPromise = ffi.initialize().then(() => {
78
+ if (ffi) try {
79
+ ffi.writeEvent(eventType, eventId, fullMessage);
80
+ } catch (error) {
81
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
82
+ }
83
+ }).catch((error) => {
84
+ metaLogger.error("Failed to initialize Windows Event Log FFI: {error}", { error });
85
+ ffi = null;
86
+ initPromise = null;
87
+ });
88
+ } else if (initPromise) initPromise = initPromise.then(() => {
89
+ if (ffi) try {
90
+ ffi.writeEvent(eventType, eventId, fullMessage);
91
+ } catch (error) {
92
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
93
+ }
94
+ });
95
+ else try {
96
+ ffi.writeEvent(eventType, eventId, fullMessage);
97
+ } catch (error) {
98
+ metaLogger.error("Failed to write to Windows Event Log: {error}", { error });
99
+ }
100
+ };
101
+ sink[Symbol.dispose] = () => {
102
+ if (ffi) {
103
+ ffi.dispose();
104
+ ffi = null;
105
+ }
106
+ };
107
+ return sink;
108
+ }
109
+
110
+ //#endregion
111
+ export { getWindowsEventLogSink };
112
+ //# sourceMappingURL=sink.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink.node.js","names":["record: LogRecord","context: string[]","options: WindowsEventLogSinkOptions","ffi: WindowsEventLogFFI | null","initPromise: Promise<void> | null","sink: Sink & Disposable"],"sources":["../sink.node.ts"],"sourcesContent":["import type { LogRecord, Sink } from \"@logtape/logtape\";\nimport { getLogger } from \"@logtape/logtape\";\nimport type { WindowsEventLogSinkOptions } from \"./types.ts\";\nimport {\n DEFAULT_EVENT_ID_MAPPING,\n mapLogLevelToEventType,\n type WindowsEventLogError as _WindowsEventLogError,\n} from \"./types.ts\";\nimport { validateWindowsPlatform } from \"./platform.ts\";\nimport { WindowsEventLogFFI } from \"./ffi.node.ts\";\n\n/**\n * Formats a log record message into a string suitable for Windows Event Log.\n * Combines the template and arguments into a readable message.\n */\nfunction formatMessage(record: LogRecord): string {\n let message = \"\";\n\n // Combine template parts with arguments\n for (let i = 0; i < record.message.length; i++) {\n if (i % 2 === 0) {\n // Template part\n message += record.message[i];\n } else {\n // Argument - serialize it\n const arg = record.message[i];\n if (typeof arg === \"string\") {\n message += arg;\n } else {\n message += JSON.stringify(arg);\n }\n }\n }\n\n return message;\n}\n\n/**\n * Formats additional context information for the log entry.\n * Includes category, properties, and other metadata.\n */\nfunction formatContext(record: LogRecord): string {\n const context: string[] = [];\n\n // Add category if present\n if (record.category && record.category.length > 0) {\n context.push(`Category: ${record.category.join(\".\")}`);\n }\n\n // Add properties if present\n if (record.properties && Object.keys(record.properties).length > 0) {\n context.push(`Properties: ${JSON.stringify(record.properties)}`);\n }\n\n // Add timestamp\n context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);\n\n return context.length > 0 ? `\\n\\n${context.join(\"\\n\")}` : \"\";\n}\n\n/**\n * Creates a Windows Event Log sink for Node.js environments using FFI.\n *\n * This implementation uses koffi to call Windows Event Log API directly,\n * providing high performance logging without external dependencies.\n *\n * @param options Configuration options for the sink\n * @returns A LogTape sink that writes to Windows Event Log\n * @throws {WindowsPlatformError} If not running on Windows\n * @throws {WindowsEventLogError} If Event Log operations fail\n *\n * @example\n * ```typescript\n * import { getWindowsEventLogSink } from \"@logtape/windows-eventlog\";\n *\n * const sink = getWindowsEventLogSink({\n * sourceName: \"MyApp\",\n * logName: \"Application\"\n * });\n * ```\n *\n * @since 1.0.0\n */\nexport function getWindowsEventLogSink(\n options: WindowsEventLogSinkOptions,\n): Sink & Disposable {\n // Validate platform early\n validateWindowsPlatform();\n\n const {\n sourceName,\n logName: _logName = \"Application\",\n eventIdMapping = {},\n } = options;\n\n // Merge with default event ID mapping\n const eventIds = { ...DEFAULT_EVENT_ID_MAPPING, ...eventIdMapping };\n\n let ffi: WindowsEventLogFFI | null = null;\n let initPromise: Promise<void> | null = null;\n const metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n const sink: Sink & Disposable = (record: LogRecord) => {\n // Format the complete message\n const message = formatMessage(record);\n const context = formatContext(record);\n const fullMessage = message + context;\n\n // Get event type and ID for this log level\n const eventType = mapLogLevelToEventType(record.level);\n const eventId = eventIds[record.level];\n\n // Initialize FFI on first use\n if (!ffi) {\n ffi = new WindowsEventLogFFI(sourceName);\n initPromise = ffi.initialize()\n .then(() => {\n // Write the first event after initialization\n if (ffi) {\n try {\n ffi.writeEvent(eventType, eventId, fullMessage);\n } catch (error) {\n metaLogger.error(\n \"Failed to write to Windows Event Log: {error}\",\n { error },\n );\n }\n }\n })\n .catch((error) => {\n metaLogger.error(\n \"Failed to initialize Windows Event Log FFI: {error}\",\n { error },\n );\n ffi = null; // Reset FFI on error\n initPromise = null;\n });\n } else if (initPromise) {\n // Still initializing - queue the write operation\n initPromise = initPromise.then(() => {\n if (ffi) {\n try {\n ffi.writeEvent(eventType, eventId, fullMessage);\n } catch (error) {\n metaLogger.error(\n \"Failed to write to Windows Event Log: {error}\",\n { error },\n );\n }\n }\n });\n } else {\n // Already initialized\n try {\n ffi.writeEvent(eventType, eventId, fullMessage);\n } catch (error) {\n metaLogger.error(\n \"Failed to write to Windows Event Log: {error}\",\n { error },\n );\n }\n }\n };\n\n // Implement Disposable for cleanup\n sink[Symbol.dispose] = () => {\n if (ffi) {\n ffi.dispose();\n ffi = null;\n }\n };\n\n return sink;\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAS,cAAcA,QAA2B;CAChD,IAAI,UAAU;AAGd,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IACzC,KAAI,IAAI,MAAM,EAEZ,YAAW,OAAO,QAAQ;MACrB;EAEL,MAAM,MAAM,OAAO,QAAQ;AAC3B,aAAW,QAAQ,SACjB,YAAW;MAEX,YAAW,KAAK,UAAU,IAAI;CAEjC;AAGH,QAAO;AACR;;;;;AAMD,SAAS,cAAcA,QAA2B;CAChD,MAAMC,UAAoB,CAAE;AAG5B,KAAI,OAAO,YAAY,OAAO,SAAS,SAAS,EAC9C,SAAQ,MAAM,YAAY,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE;AAIxD,KAAI,OAAO,cAAc,OAAO,KAAK,OAAO,WAAW,CAAC,SAAS,EAC/D,SAAQ,MAAM,cAAc,KAAK,UAAU,OAAO,WAAW,CAAC,EAAE;AAIlE,SAAQ,MAAM,aAAa,IAAI,KAAK,OAAO,WAAW,aAAa,CAAC,EAAE;AAEtE,QAAO,QAAQ,SAAS,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC,IAAI;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;AAyBD,SAAgB,uBACdC,SACmB;AAEnB,0BAAyB;CAEzB,MAAM,EACJ,YACA,SAAS,WAAW,eACpB,iBAAiB,CAAE,GACpB,GAAG;CAGJ,MAAM,WAAW;EAAE,GAAG;EAA0B,GAAG;CAAgB;CAEnE,IAAIC,MAAiC;CACrC,IAAIC,cAAoC;CACxC,MAAM,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;CAErE,MAAMC,OAA0B,CAACL,WAAsB;EAErD,MAAM,UAAU,cAAc,OAAO;EACrC,MAAM,UAAU,cAAc,OAAO;EACrC,MAAM,cAAc,UAAU;EAG9B,MAAM,YAAY,uBAAuB,OAAO,MAAM;EACtD,MAAM,UAAU,SAAS,OAAO;AAGhC,OAAK,KAAK;AACR,SAAM,IAAI,mBAAmB;AAC7B,iBAAc,IAAI,YAAY,CAC3B,KAAK,MAAM;AAEV,QAAI,IACF,KAAI;AACF,SAAI,WAAW,WAAW,SAAS,YAAY;IAChD,SAAQ,OAAO;AACd,gBAAW,MACT,iDACA,EAAE,MAAO,EACV;IACF;GAEJ,EAAC,CACD,MAAM,CAAC,UAAU;AAChB,eAAW,MACT,uDACA,EAAE,MAAO,EACV;AACD,UAAM;AACN,kBAAc;GACf,EAAC;EACL,WAAU,YAET,eAAc,YAAY,KAAK,MAAM;AACnC,OAAI,IACF,KAAI;AACF,QAAI,WAAW,WAAW,SAAS,YAAY;GAChD,SAAQ,OAAO;AACd,eAAW,MACT,iDACA,EAAE,MAAO,EACV;GACF;EAEJ,EAAC;MAGF,KAAI;AACF,OAAI,WAAW,WAAW,SAAS,YAAY;EAChD,SAAQ,OAAO;AACd,cAAW,MACT,iDACA,EAAE,MAAO,EACV;EACF;CAEJ;AAGD,MAAK,OAAO,WAAW,MAAM;AAC3B,MAAI,KAAK;AACP,OAAI,SAAS;AACb,SAAM;EACP;CACF;AAED,QAAO;AACR"}