functype-log 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +172 -0
- package/dist/ConsoleLogger-6gnkQctP.d.ts +11 -0
- package/dist/LogLayerAdapter-CtytCNjQ.d.ts +8 -0
- package/dist/LogMiddleware-Bv7EDRjF.d.ts +11 -0
- package/dist/Logger-BFum_d5a.d.ts +27 -0
- package/dist/LoggerLayer-B-tD-_gO.d.ts +14 -0
- package/dist/SilentLogger-BWfCzQqB.d.ts +7 -0
- package/dist/TestLogger-4s7rQHxR.d.ts +14 -0
- package/dist/adapter/LogLayerAdapter.d.ts +2 -0
- package/dist/adapter/LogLayerAdapter.js +2 -0
- package/dist/adapter/LogLayerAdapter.js.map +1 -0
- package/dist/adapter/index.d.ts +2 -0
- package/dist/adapter/index.js +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -0
- package/dist/layers/ConsoleLogger.d.ts +2 -0
- package/dist/layers/ConsoleLogger.js +2 -0
- package/dist/layers/ConsoleLogger.js.map +1 -0
- package/dist/layers/LoggerLayer.d.ts +2 -0
- package/dist/layers/LoggerLayer.js +2 -0
- package/dist/layers/LoggerLayer.js.map +1 -0
- package/dist/layers/SilentLogger.d.ts +2 -0
- package/dist/layers/SilentLogger.js +2 -0
- package/dist/layers/SilentLogger.js.map +1 -0
- package/dist/layers/index.d.ts +4 -0
- package/dist/layers/index.js +1 -0
- package/dist/logger/Logger.d.ts +2 -0
- package/dist/logger/Logger.js +2 -0
- package/dist/logger/Logger.js.map +1 -0
- package/dist/logger/index.d.ts +2 -0
- package/dist/logger/index.js +1 -0
- package/dist/middleware/LogMiddleware.d.ts +2 -0
- package/dist/middleware/LogMiddleware.js +2 -0
- package/dist/middleware/LogMiddleware.js.map +1 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +1 -0
- package/dist/testing/TestLogger.d.ts +2 -0
- package/dist/testing/TestLogger.js +2 -0
- package/dist/testing/TestLogger.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Jordan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# functype-log
|
|
2
|
+
|
|
3
|
+
IO-native logging for the [functype](https://github.com/jordanburke/functype) ecosystem. Wraps [LogLayer](https://loglayer.dev/) with functype's `Tag`/`Layer` dependency injection system.
|
|
4
|
+
|
|
5
|
+
Every log method returns `IO<never, never, void>` — logging is lazy, composable, and testable.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add functype-log functype
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { IO } from "functype"
|
|
17
|
+
import { Logger, LoggerLive } from "functype-log"
|
|
18
|
+
|
|
19
|
+
const program = IO.gen(function* () {
|
|
20
|
+
const log = yield* IO.service(Logger)
|
|
21
|
+
yield* log.info("Starting", { version: "1.0.0" })
|
|
22
|
+
const result = yield* doWork()
|
|
23
|
+
yield* log.info("Done", { result })
|
|
24
|
+
return result
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Run with console logging
|
|
28
|
+
await program.provideLayer(LoggerLive.console()).runOrThrow()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Layers
|
|
32
|
+
|
|
33
|
+
### Console (dev)
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
await program.provideLayer(LoggerLive.console()).runOrThrow()
|
|
37
|
+
await program.provideLayer(LoggerLive.console({ prefix: "[APP]" })).runOrThrow()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Silent (testing/suppression)
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
await program.provideLayer(LoggerLive.silent()).runOrThrow()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### From LogLayer (production)
|
|
47
|
+
|
|
48
|
+
Use any of LogLayer's 40+ transports — pino, winston, datadog, bunyan, OpenTelemetry, etc.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { LogLayer } from "loglayer"
|
|
52
|
+
import { PinoTransport } from "@loglayer/transport-pino"
|
|
53
|
+
import pino from "pino"
|
|
54
|
+
|
|
55
|
+
const pinoLog = new LogLayer({
|
|
56
|
+
transport: new PinoTransport({ logger: pino() }),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
await program.provideLayer(LoggerLive.fromLogLayer(pinoLog)).runOrThrow()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### OpenTelemetry
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { openTelemetryPlugin } from "@loglayer/plugin-opentelemetry"
|
|
66
|
+
|
|
67
|
+
const otelLog = new LogLayer({
|
|
68
|
+
transport: new PinoTransport({ logger: pino() }),
|
|
69
|
+
plugins: [openTelemetryPlugin()],
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
await program.provideLayer(LoggerLive.fromLogLayer(otelLog)).runOrThrow()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Logger API
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const log = yield * IO.service(Logger)
|
|
79
|
+
|
|
80
|
+
// Log levels
|
|
81
|
+
yield * log.trace("verbose detail")
|
|
82
|
+
yield * log.debug("debug info")
|
|
83
|
+
yield * log.info("informational")
|
|
84
|
+
yield * log.warn("warning")
|
|
85
|
+
yield * log.error("error occurred")
|
|
86
|
+
yield * log.fatal("fatal error")
|
|
87
|
+
|
|
88
|
+
// Structured metadata
|
|
89
|
+
yield * log.info("user action", { userId: "123", action: "login" })
|
|
90
|
+
|
|
91
|
+
// Error context
|
|
92
|
+
yield * log.withError(err).error("operation failed")
|
|
93
|
+
|
|
94
|
+
// Persistent context
|
|
95
|
+
const reqLog = log.withContext({ requestId: "req-1" })
|
|
96
|
+
yield * reqLog.info("first") // includes requestId
|
|
97
|
+
yield * reqLog.info("second") // includes requestId
|
|
98
|
+
|
|
99
|
+
// Child logger
|
|
100
|
+
const child = log.child({ handler: "users" })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Middleware
|
|
104
|
+
|
|
105
|
+
### withLogging
|
|
106
|
+
|
|
107
|
+
Wraps any IO with start/complete logging at debug level:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { withLogging } from "functype-log"
|
|
111
|
+
|
|
112
|
+
const fetchUsers = Http.get("/api/users", { validate: UserSchema })
|
|
113
|
+
const logged = withLogging("fetchUsers", fetchUsers)
|
|
114
|
+
// Logs: "fetchUsers: starting" then "fetchUsers: completed"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### tapLog
|
|
118
|
+
|
|
119
|
+
Logs after an effect completes:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { tapLog } from "functype-log"
|
|
123
|
+
|
|
124
|
+
const result = await tapLog<number[]>(
|
|
125
|
+
"info",
|
|
126
|
+
(arr) => `fetched ${arr.length} items`,
|
|
127
|
+
)(IO.succeed([1, 2, 3]))
|
|
128
|
+
.provideService(Logger, logger)
|
|
129
|
+
.runOrThrow()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Testing
|
|
133
|
+
|
|
134
|
+
`createTestLogger` captures log entries in memory for assertions:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { createTestLogger } from "functype-log"
|
|
138
|
+
|
|
139
|
+
const { logger, entries, hasEntry, clear } = createTestLogger()
|
|
140
|
+
|
|
141
|
+
await myProgram.provideService(Logger, logger).runOrThrow()
|
|
142
|
+
|
|
143
|
+
// Assert on captured entries
|
|
144
|
+
expect(entries().size).toBe(2)
|
|
145
|
+
expect(hasEntry("info", "Starting")).toBe(true)
|
|
146
|
+
expect(hasEntry("info", /fetched \d+ items/)).toBe(true)
|
|
147
|
+
|
|
148
|
+
// Entries are List<LogEntry> with full metadata
|
|
149
|
+
const first = entries().head
|
|
150
|
+
expect(first.level).toBe("info")
|
|
151
|
+
expect(first.metadata).toEqual({ version: "1.0.0" })
|
|
152
|
+
expect(first.timestamp).toBeInstanceOf(Date)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Subpath Exports
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { Logger } from "functype-log" // everything
|
|
159
|
+
import { Logger } from "functype-log/logger" // types only
|
|
160
|
+
import { LoggerLive } from "functype-log/layers" // layer constructors
|
|
161
|
+
import { createTestLogger } from "functype-log/testing" // test utilities
|
|
162
|
+
import { withLogging } from "functype-log/middleware" // middleware
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Requirements
|
|
166
|
+
|
|
167
|
+
- functype >= 0.55.0
|
|
168
|
+
- Node.js >= 18.17.0
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { i as Logger, n as LogLevel } from "./Logger-BFum_d5a.js";
|
|
2
|
+
|
|
3
|
+
//#region src/layers/ConsoleLogger.d.ts
|
|
4
|
+
type ConsoleLoggerOptions = {
|
|
5
|
+
readonly level?: LogLevel;
|
|
6
|
+
readonly prefix?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const createConsoleLogger: (options?: ConsoleLoggerOptions) => Logger;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { createConsoleLogger as n, ConsoleLoggerOptions as t };
|
|
11
|
+
//# sourceMappingURL=ConsoleLogger-6gnkQctP.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { i as Logger } from "./Logger-BFum_d5a.js";
|
|
2
|
+
import { ILogLayer } from "loglayer";
|
|
3
|
+
|
|
4
|
+
//#region src/adapter/LogLayerAdapter.d.ts
|
|
5
|
+
declare const logLayerAdapter: (logLayer: ILogLayer, baseError?: Error) => Logger;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { logLayerAdapter as t };
|
|
8
|
+
//# sourceMappingURL=LogLayerAdapter-CtytCNjQ.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { i as Logger, n as LogLevel } from "./Logger-BFum_d5a.js";
|
|
2
|
+
import { IO } from "functype";
|
|
3
|
+
|
|
4
|
+
//#region src/middleware/LogMiddleware.d.ts
|
|
5
|
+
/** Wrap any IO with start/complete/error logging at debug level */
|
|
6
|
+
declare const withLogging: <R, E, A>(name: string, effect: IO<R, E, A>) => IO<R | Logger, E, A>;
|
|
7
|
+
/** Create a tap function that logs at the specified level */
|
|
8
|
+
declare const tapLog: <A>(level: LogLevel, message: string | ((a: A) => string)) => <R, E>(effect: IO<R, E, A>) => IO<R | Logger, E, A>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { withLogging as n, tapLog as t };
|
|
11
|
+
//# sourceMappingURL=LogMiddleware-Bv7EDRjF.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IO, Tag } from "functype";
|
|
2
|
+
|
|
3
|
+
//#region src/logger/Logger.d.ts
|
|
4
|
+
type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
5
|
+
type LogMetadata = Record<string, unknown>;
|
|
6
|
+
type LogEntry = {
|
|
7
|
+
readonly level: LogLevel;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly metadata?: LogMetadata;
|
|
10
|
+
readonly error?: Error;
|
|
11
|
+
readonly timestamp: Date;
|
|
12
|
+
};
|
|
13
|
+
type Logger = {
|
|
14
|
+
readonly trace: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
15
|
+
readonly debug: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
16
|
+
readonly info: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
17
|
+
readonly warn: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
18
|
+
readonly error: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
19
|
+
readonly fatal: (message: string, metadata?: LogMetadata) => IO<never, never, void>;
|
|
20
|
+
readonly withError: (error: Error) => Logger;
|
|
21
|
+
readonly withContext: (context: LogMetadata) => Logger;
|
|
22
|
+
readonly child: (context?: LogMetadata) => Logger;
|
|
23
|
+
};
|
|
24
|
+
declare const Logger: Tag<Logger>;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Logger as i, LogLevel as n, LogMetadata as r, LogEntry as t };
|
|
27
|
+
//# sourceMappingURL=Logger-BFum_d5a.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { i as Logger } from "./Logger-BFum_d5a.js";
|
|
2
|
+
import { t as ConsoleLoggerOptions } from "./ConsoleLogger-6gnkQctP.js";
|
|
3
|
+
import { Layer } from "functype";
|
|
4
|
+
import { ILogLayer } from "loglayer";
|
|
5
|
+
|
|
6
|
+
//#region src/layers/LoggerLayer.d.ts
|
|
7
|
+
declare const LoggerLive: {
|
|
8
|
+
/** From an existing LogLayer instance — escape hatch for power users (pino, winston, datadog, etc.) */fromLogLayer: (logLayer: ILogLayer) => Layer<never, never, Logger>; /** Console logger — zero config, great for dev */
|
|
9
|
+
console: (options?: ConsoleLoggerOptions) => Layer<never, never, Logger>; /** Silent/noop logger — for testing or suppression */
|
|
10
|
+
silent: () => Layer<never, never, Logger>;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { LoggerLive as t };
|
|
14
|
+
//# sourceMappingURL=LoggerLayer-B-tD-_gO.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { i as Logger, n as LogLevel, t as LogEntry } from "./Logger-BFum_d5a.js";
|
|
2
|
+
import { List } from "functype";
|
|
3
|
+
|
|
4
|
+
//#region src/testing/TestLogger.d.ts
|
|
5
|
+
type TestLoggerHandle = {
|
|
6
|
+
readonly logger: Logger;
|
|
7
|
+
readonly entries: () => List<LogEntry>;
|
|
8
|
+
readonly clear: () => void;
|
|
9
|
+
readonly hasEntry: (level: LogLevel, messagePattern: string | RegExp) => boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const createTestLogger: () => TestLoggerHandle;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createTestLogger as n, TestLoggerHandle as t };
|
|
14
|
+
//# sourceMappingURL=TestLogger-4s7rQHxR.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{IO as e}from"functype";const t=(t,n,r)=>(i,a)=>e.sync(()=>{let e=a?t.withMetadata(a):t;r&&(e=e.withError(r)),e[n](i)}),n=(e,r)=>({trace:t(e,`trace`,r),debug:t(e,`debug`,r),info:t(e,`info`,r),warn:t(e,`warn`,r),error:t(e,`error`,r),fatal:t(e,`fatal`,r),withError:t=>n(e,t),withContext:t=>n(e.withContext(t),r),child:t=>{let r=e.child();return n(t?r.withContext(t):r)}});export{n as logLayerAdapter};
|
|
2
|
+
//# sourceMappingURL=LogLayerAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogLayerAdapter.js","names":[],"sources":["../../src/adapter/LogLayerAdapter.ts"],"sourcesContent":["import { IO } from \"functype\"\nimport type { ILogLayer } from \"loglayer\"\n\nimport type { Logger, LogLevel, LogMetadata } from \"../logger/Logger\"\n\nconst makeMethod =\n (logLayer: ILogLayer, level: LogLevel, baseError?: Error) =>\n (message: string, metadata?: LogMetadata): IO<never, never, void> =>\n IO.sync(() => {\n let entry = metadata ? logLayer.withMetadata(metadata) : logLayer\n if (baseError) {\n entry = entry.withError(baseError)\n }\n entry[level](message)\n })\n\nexport const logLayerAdapter = (logLayer: ILogLayer, baseError?: Error): Logger => ({\n trace: makeMethod(logLayer, \"trace\", baseError),\n debug: makeMethod(logLayer, \"debug\", baseError),\n info: makeMethod(logLayer, \"info\", baseError),\n warn: makeMethod(logLayer, \"warn\", baseError),\n error: makeMethod(logLayer, \"error\", baseError),\n fatal: makeMethod(logLayer, \"fatal\", baseError),\n withError: (err: Error) => logLayerAdapter(logLayer, err),\n withContext: (ctx: LogMetadata) => logLayerAdapter(logLayer.withContext(ctx), baseError),\n child: (ctx?: LogMetadata) => {\n const childLog = logLayer.child()\n return ctx ? logLayerAdapter(childLog.withContext(ctx)) : logLayerAdapter(childLog)\n },\n})\n"],"mappings":"8BAKA,MAAM,GACH,EAAqB,EAAiB,KACtC,EAAiB,IAChB,EAAG,SAAW,CACZ,IAAI,EAAQ,EAAW,EAAS,aAAa,EAAS,CAAG,EACrD,IACF,EAAQ,EAAM,UAAU,EAAU,EAEpC,EAAM,GAAO,EAAQ,EACrB,CAEO,GAAmB,EAAqB,KAA+B,CAClF,MAAO,EAAW,EAAU,QAAS,EAAU,CAC/C,MAAO,EAAW,EAAU,QAAS,EAAU,CAC/C,KAAM,EAAW,EAAU,OAAQ,EAAU,CAC7C,KAAM,EAAW,EAAU,OAAQ,EAAU,CAC7C,MAAO,EAAW,EAAU,QAAS,EAAU,CAC/C,MAAO,EAAW,EAAU,QAAS,EAAU,CAC/C,UAAY,GAAe,EAAgB,EAAU,EAAI,CACzD,YAAc,GAAqB,EAAgB,EAAS,YAAY,EAAI,CAAE,EAAU,CACxF,MAAQ,GAAsB,CAC5B,IAAM,EAAW,EAAS,OAAO,CACjC,OAAa,EAAN,EAAsB,EAAS,YAAY,EAAI,CAAoB,EAAS,EAEtF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{logLayerAdapter as e}from"./LogLayerAdapter.js";export{e as logLayerAdapter};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { i as Logger, n as LogLevel, r as LogMetadata, t as LogEntry } from "./Logger-BFum_d5a.js";
|
|
2
|
+
import { t as logLayerAdapter } from "./LogLayerAdapter-CtytCNjQ.js";
|
|
3
|
+
import { n as createConsoleLogger, t as ConsoleLoggerOptions } from "./ConsoleLogger-6gnkQctP.js";
|
|
4
|
+
import { t as LoggerLive } from "./LoggerLayer-B-tD-_gO.js";
|
|
5
|
+
import { t as silentLogger } from "./SilentLogger-BWfCzQqB.js";
|
|
6
|
+
import { n as createTestLogger, t as TestLoggerHandle } from "./TestLogger-4s7rQHxR.js";
|
|
7
|
+
import { n as withLogging, t as tapLog } from "./LogMiddleware-Bv7EDRjF.js";
|
|
8
|
+
export { type ConsoleLoggerOptions, type LogEntry, type LogLevel, type LogMetadata, Logger, LoggerLive, type TestLoggerHandle, createConsoleLogger, createTestLogger, logLayerAdapter, silentLogger, tapLog, withLogging };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Logger as e}from"./logger/Logger.js";import"./logger/index.js";import{logLayerAdapter as t}from"./adapter/LogLayerAdapter.js";import{createConsoleLogger as n}from"./layers/ConsoleLogger.js";import{silentLogger as r}from"./layers/SilentLogger.js";import{LoggerLive as i}from"./layers/LoggerLayer.js";import"./layers/index.js";import"./adapter/index.js";import{createTestLogger as a}from"./testing/TestLogger.js";import"./testing/index.js";import{tapLog as o,withLogging as s}from"./middleware/LogMiddleware.js";import"./middleware/index.js";export{e as Logger,i as LoggerLive,n as createConsoleLogger,a as createTestLogger,t as logLayerAdapter,r as silentLogger,o as tapLog,s as withLogging};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{logLayerAdapter as e}from"../adapter/LogLayerAdapter.js";import{ConsoleTransport as t,LogLayer as n}from"loglayer";const r=r=>e(new n({transport:new t({logger:console}),...r?.prefix?{prefix:r.prefix}:{}}));export{r as createConsoleLogger};
|
|
2
|
+
//# sourceMappingURL=ConsoleLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleLogger.js","names":[],"sources":["../../src/layers/ConsoleLogger.ts"],"sourcesContent":["import { ConsoleTransport, LogLayer } from \"loglayer\"\n\nimport { logLayerAdapter } from \"../adapter/LogLayerAdapter\"\nimport type { Logger, LogLevel } from \"../logger/Logger\"\n\nexport type ConsoleLoggerOptions = {\n readonly level?: LogLevel\n readonly prefix?: string\n}\n\nexport const createConsoleLogger = (options?: ConsoleLoggerOptions): Logger => {\n const logLayer = new LogLayer({\n transport: new ConsoleTransport({ logger: console }),\n ...(options?.prefix ? { prefix: options.prefix } : {}),\n })\n\n return logLayerAdapter(logLayer)\n}\n"],"mappings":"0HAUA,MAAa,EAAuB,GAM3B,EALU,IAAI,EAAS,CAC5B,UAAW,IAAI,EAAiB,CAAE,OAAQ,QAAS,CAAC,CACpD,GAAI,GAAS,OAAS,CAAE,OAAQ,EAAQ,OAAQ,CAAG,EAAE,CACtD,CAAC,CAE8B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Logger as e}from"../logger/Logger.js";import{logLayerAdapter as t}from"../adapter/LogLayerAdapter.js";import{createConsoleLogger as n}from"./ConsoleLogger.js";import{silentLogger as r}from"./SilentLogger.js";import{Layer as i}from"functype";const a={fromLogLayer:n=>i.succeed(e,t(n)),console:t=>i.sync(e,()=>n(t)),silent:()=>i.succeed(e,r)};export{a as LoggerLive};
|
|
2
|
+
//# sourceMappingURL=LoggerLayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoggerLayer.js","names":[],"sources":["../../src/layers/LoggerLayer.ts"],"sourcesContent":["import { Layer } from \"functype\"\nimport type { ILogLayer } from \"loglayer\"\n\nimport { logLayerAdapter } from \"../adapter/LogLayerAdapter\"\nimport { Logger } from \"../logger/Logger\"\nimport type { ConsoleLoggerOptions } from \"./ConsoleLogger\"\nimport { createConsoleLogger } from \"./ConsoleLogger\"\nimport { silentLogger } from \"./SilentLogger\"\n\nexport const LoggerLive = {\n /** From an existing LogLayer instance — escape hatch for power users (pino, winston, datadog, etc.) */\n fromLogLayer: (logLayer: ILogLayer): Layer<never, never, Logger> => Layer.succeed(Logger, logLayerAdapter(logLayer)),\n\n /** Console logger — zero config, great for dev */\n console: (options?: ConsoleLoggerOptions): Layer<never, never, Logger> =>\n Layer.sync(Logger, () => createConsoleLogger(options)),\n\n /** Silent/noop logger — for testing or suppression */\n silent: (): Layer<never, never, Logger> => Layer.succeed(Logger, silentLogger),\n}\n"],"mappings":"wPASA,MAAa,EAAa,CAExB,aAAe,GAAqD,EAAM,QAAQ,EAAQ,EAAgB,EAAS,CAAC,CAGpH,QAAU,GACR,EAAM,KAAK,MAAc,EAAoB,EAAQ,CAAC,CAGxD,WAA2C,EAAM,QAAQ,EAAQ,EAAa,CAC/E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SilentLogger.js","names":[],"sources":["../../src/layers/SilentLogger.ts"],"sourcesContent":["import { IO } from \"functype\"\n\nimport type { Logger, LogMetadata } from \"../logger/Logger\"\n\nconst noop = (_message: string, _metadata?: LogMetadata): IO<never, never, void> => IO.succeed(undefined as void)\n\nexport const silentLogger: Logger = {\n trace: noop,\n debug: noop,\n info: noop,\n warn: noop,\n error: noop,\n fatal: noop,\n withError: () => silentLogger,\n withContext: () => silentLogger,\n child: () => silentLogger,\n}\n"],"mappings":"8BAIA,MAAM,GAAQ,EAAkB,IAAoD,EAAG,QAAQ,IAAA,GAAkB,CAEpG,EAAuB,CAClC,MAAO,EACP,MAAO,EACP,KAAM,EACN,KAAM,EACN,MAAO,EACP,MAAO,EACP,cAAiB,EACjB,gBAAmB,EACnB,UAAa,EACd"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { n as createConsoleLogger, t as ConsoleLoggerOptions } from "../ConsoleLogger-6gnkQctP.js";
|
|
2
|
+
import { t as LoggerLive } from "../LoggerLayer-B-tD-_gO.js";
|
|
3
|
+
import { t as silentLogger } from "../SilentLogger-BWfCzQqB.js";
|
|
4
|
+
export { type ConsoleLoggerOptions, LoggerLive, createConsoleLogger, silentLogger };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createConsoleLogger as e}from"./ConsoleLogger.js";import{silentLogger as t}from"./SilentLogger.js";import{LoggerLive as n}from"./LoggerLayer.js";export{n as LoggerLive,e as createConsoleLogger,t as silentLogger};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.js","names":[],"sources":["../../src/logger/Logger.ts"],"sourcesContent":["import type { IO } from \"functype\"\nimport { Tag } from \"functype\"\n\nexport type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\"\n\nexport type LogMetadata = Record<string, unknown>\n\nexport type LogEntry = {\n readonly level: LogLevel\n readonly message: string\n readonly metadata?: LogMetadata\n readonly error?: Error\n readonly timestamp: Date\n}\n\nexport type Logger = {\n readonly trace: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly debug: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly info: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly warn: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly error: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly fatal: (message: string, metadata?: LogMetadata) => IO<never, never, void>\n readonly withError: (error: Error) => Logger\n readonly withContext: (context: LogMetadata) => Logger\n readonly child: (context?: LogMetadata) => Logger\n}\n\nexport const Logger = Tag<Logger>(\"Logger\")\n"],"mappings":"+BA2BA,MAAa,EAAS,EAAY,SAAS"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Logger as e}from"./Logger.js";export{e as Logger};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Logger as e}from"../logger/Logger.js";import{IO as t}from"functype";const n=(n,r)=>t.gen(function*(){let i=yield*t.service(e);yield*i.debug(`${n}: starting`);let a=yield*r;return yield*i.debug(`${n}: completed`),a}),r=(n,r)=>i=>t.gen(function*(){let a=yield*i,o=yield*t.service(e),s=typeof r==`string`?r:r(a);return yield*o[n](s),a});export{r as tapLog,n as withLogging};
|
|
2
|
+
//# sourceMappingURL=LogMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogMiddleware.js","names":["IOImpl","LoggerTag"],"sources":["../../src/middleware/LogMiddleware.ts"],"sourcesContent":["import type { IO } from \"functype\"\nimport { IO as IOImpl } from \"functype\"\n\nimport type { Logger, LogLevel } from \"../logger/Logger\"\nimport { Logger as LoggerTag } from \"../logger/Logger\"\n\n/** Wrap any IO with start/complete/error logging at debug level */\nexport const withLogging = <R, E, A>(name: string, effect: IO<R, E, A>): IO<R | Logger, E, A> =>\n IOImpl.gen(function* () {\n const log = yield* IOImpl.service(LoggerTag)\n yield* log.debug(`${name}: starting`)\n const result = yield* effect\n yield* log.debug(`${name}: completed`)\n return result\n }) as IO<R | Logger, E, A>\n\n/** Create a tap function that logs at the specified level */\nexport const tapLog =\n <A>(level: LogLevel, message: string | ((a: A) => string)) =>\n <R, E>(effect: IO<R, E, A>): IO<R | Logger, E, A> =>\n IOImpl.gen(function* () {\n const result = yield* effect\n const log = yield* IOImpl.service(LoggerTag)\n const msg = typeof message === \"string\" ? message : message(result)\n yield* log[level](msg)\n return result\n }) as IO<R | Logger, E, A>\n"],"mappings":"2EAOA,MAAa,GAAwB,EAAc,IACjDA,EAAO,IAAI,WAAa,CACtB,IAAM,EAAM,MAAOA,EAAO,QAAQC,EAAU,CAC5C,MAAO,EAAI,MAAM,GAAG,EAAK,YAAY,CACrC,IAAM,EAAS,MAAO,EAEtB,OADA,MAAO,EAAI,MAAM,GAAG,EAAK,aAAa,CAC/B,GACP,CAGS,GACP,EAAiB,IACd,GACLD,EAAO,IAAI,WAAa,CACtB,IAAM,EAAS,MAAO,EAChB,EAAM,MAAOA,EAAO,QAAQC,EAAU,CACtC,EAAM,OAAO,GAAY,SAAW,EAAU,EAAQ,EAAO,CAEnE,OADA,MAAO,EAAI,GAAO,EAAI,CACf,GACP"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tapLog as e,withLogging as t}from"./LogMiddleware.js";export{e as tapLog,t as withLogging};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{IO as e,List as t}from"functype";const n=(t,r,i)=>{let a=n=>(a,o)=>e.sync(()=>{t.push({level:n,message:a,metadata:Object.keys(r).length>0||o?{...r,...o}:void 0,error:i,timestamp:new Date})});return{trace:a(`trace`),debug:a(`debug`),info:a(`info`),warn:a(`warn`),error:a(`error`),fatal:a(`fatal`),withError:e=>n(t,r,e),withContext:e=>n(t,{...r,...e},i),child:e=>n(t,{...r,...e},void 0)}},r=()=>{let e=[];return{logger:n(e,{}),entries:()=>t(e),clear:()=>{e.length=0},hasEntry:(t,n)=>e.some(e=>e.level===t&&(typeof n==`string`?e.message.includes(n):n.test(e.message)))}};export{r as createTestLogger};
|
|
2
|
+
//# sourceMappingURL=TestLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestLogger.js","names":[],"sources":["../../src/testing/TestLogger.ts"],"sourcesContent":["import { IO, List } from \"functype\"\n\nimport type { LogEntry, Logger, LogLevel, LogMetadata } from \"../logger/Logger\"\n\nexport type TestLoggerHandle = {\n readonly logger: Logger\n readonly entries: () => List<LogEntry>\n readonly clear: () => void\n readonly hasEntry: (level: LogLevel, messagePattern: string | RegExp) => boolean\n}\n\nconst createLoggerFromStore = (store: LogEntry[], baseContext: LogMetadata, baseError?: Error): Logger => {\n const makeMethod =\n (level: LogLevel) =>\n (message: string, metadata?: LogMetadata): IO<never, never, void> =>\n IO.sync(() => {\n store.push({\n level,\n message,\n metadata: Object.keys(baseContext).length > 0 || metadata ? { ...baseContext, ...metadata } : undefined,\n error: baseError,\n timestamp: new Date(),\n })\n })\n\n return {\n trace: makeMethod(\"trace\"),\n debug: makeMethod(\"debug\"),\n info: makeMethod(\"info\"),\n warn: makeMethod(\"warn\"),\n error: makeMethod(\"error\"),\n fatal: makeMethod(\"fatal\"),\n withError: (err: Error) => createLoggerFromStore(store, baseContext, err),\n withContext: (ctx: LogMetadata) => createLoggerFromStore(store, { ...baseContext, ...ctx }, baseError),\n child: (ctx?: LogMetadata) => createLoggerFromStore(store, { ...baseContext, ...ctx }, undefined),\n }\n}\n\nexport const createTestLogger = (): TestLoggerHandle => {\n const store: LogEntry[] = []\n\n return {\n logger: createLoggerFromStore(store, {}),\n entries: () => List(store),\n clear: () => {\n store.length = 0\n },\n hasEntry: (level: LogLevel, messagePattern: string | RegExp) =>\n store.some(\n (e) =>\n e.level === level &&\n (typeof messagePattern === \"string\" ? e.message.includes(messagePattern) : messagePattern.test(e.message)),\n ),\n }\n}\n"],"mappings":"wCAWA,MAAM,GAAyB,EAAmB,EAA0B,IAA8B,CACxG,IAAM,EACH,IACA,EAAiB,IAChB,EAAG,SAAW,CACZ,EAAM,KAAK,CACT,QACA,UACA,SAAU,OAAO,KAAK,EAAY,CAAC,OAAS,GAAK,EAAW,CAAE,GAAG,EAAa,GAAG,EAAU,CAAG,IAAA,GAC9F,MAAO,EACP,UAAW,IAAI,KAChB,CAAC,EACF,CAEN,MAAO,CACL,MAAO,EAAW,QAAQ,CAC1B,MAAO,EAAW,QAAQ,CAC1B,KAAM,EAAW,OAAO,CACxB,KAAM,EAAW,OAAO,CACxB,MAAO,EAAW,QAAQ,CAC1B,MAAO,EAAW,QAAQ,CAC1B,UAAY,GAAe,EAAsB,EAAO,EAAa,EAAI,CACzE,YAAc,GAAqB,EAAsB,EAAO,CAAE,GAAG,EAAa,GAAG,EAAK,CAAE,EAAU,CACtG,MAAQ,GAAsB,EAAsB,EAAO,CAAE,GAAG,EAAa,GAAG,EAAK,CAAE,IAAA,GAAU,CAClG,EAGU,MAA2C,CACtD,IAAM,EAAoB,EAAE,CAE5B,MAAO,CACL,OAAQ,EAAsB,EAAO,EAAE,CAAC,CACxC,YAAe,EAAK,EAAM,CAC1B,UAAa,CACX,EAAM,OAAS,GAEjB,UAAW,EAAiB,IAC1B,EAAM,KACH,GACC,EAAE,QAAU,IACX,OAAO,GAAmB,SAAW,EAAE,QAAQ,SAAS,EAAe,CAAG,EAAe,KAAK,EAAE,QAAQ,EAC5G,CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createTestLogger as e}from"./TestLogger.js";export{e as createTestLogger};
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "functype-log",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "IO-native logging for functype — wraps LogLayer with Tag/Layer DI, structured logging, and test utilities",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"functype",
|
|
7
|
+
"functional",
|
|
8
|
+
"logging",
|
|
9
|
+
"loglayer",
|
|
10
|
+
"io",
|
|
11
|
+
"dependency-injection",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"author": "jordan.burke@gmail.com",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"homepage": "https://github.com/jordanburke/functype-log",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/jordanburke/functype-log"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"functype": ">=0.55.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"loglayer": "^9.1.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^24.12.0",
|
|
29
|
+
"functype": "^0.56.0",
|
|
30
|
+
"ts-builds": "^2.6.3",
|
|
31
|
+
"tsdown": "^0.21.7"
|
|
32
|
+
},
|
|
33
|
+
"type": "module",
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"module": "./dist/index.js",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js",
|
|
41
|
+
"default": "./dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./logger": {
|
|
44
|
+
"types": "./dist/logger/index.d.ts",
|
|
45
|
+
"import": "./dist/logger/index.js",
|
|
46
|
+
"default": "./dist/logger/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./layers": {
|
|
49
|
+
"types": "./dist/layers/index.d.ts",
|
|
50
|
+
"import": "./dist/layers/index.js",
|
|
51
|
+
"default": "./dist/layers/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./testing": {
|
|
54
|
+
"types": "./dist/testing/index.d.ts",
|
|
55
|
+
"import": "./dist/testing/index.js",
|
|
56
|
+
"default": "./dist/testing/index.js"
|
|
57
|
+
},
|
|
58
|
+
"./middleware": {
|
|
59
|
+
"types": "./dist/middleware/index.d.ts",
|
|
60
|
+
"import": "./dist/middleware/index.js",
|
|
61
|
+
"default": "./dist/middleware/index.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"files": [
|
|
65
|
+
"lib",
|
|
66
|
+
"dist"
|
|
67
|
+
],
|
|
68
|
+
"prettier": "ts-builds/prettier",
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18.17.0"
|
|
71
|
+
},
|
|
72
|
+
"scripts": {
|
|
73
|
+
"validate": "ts-builds validate",
|
|
74
|
+
"format": "ts-builds format",
|
|
75
|
+
"format:check": "ts-builds format:check",
|
|
76
|
+
"lint": "ts-builds lint",
|
|
77
|
+
"lint:check": "ts-builds lint:check",
|
|
78
|
+
"typecheck": "ts-builds typecheck",
|
|
79
|
+
"test": "ts-builds test",
|
|
80
|
+
"test:watch": "ts-builds test:watch",
|
|
81
|
+
"test:coverage": "ts-builds test:coverage",
|
|
82
|
+
"build": "ts-builds build",
|
|
83
|
+
"dev": "ts-builds dev"
|
|
84
|
+
}
|
|
85
|
+
}
|