ff-serv 0.0.2

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/dist/index.cjs ADDED
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Logger: () => Logger
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/logger.ts
38
+ var import_effect = require("effect");
39
+ var import_pino = __toESM(require("pino"), 1);
40
+ var LoggerType;
41
+ ((LoggerType2) => {
42
+ function fromPino(x) {
43
+ return {
44
+ info: x.info.bind(x),
45
+ error: x.error.bind(x),
46
+ warn: x.warn.bind(x),
47
+ debug: x.debug.bind(x),
48
+ child: (...params) => {
49
+ return fromPino(
50
+ x.child(...params)
51
+ );
52
+ },
53
+ flush: x.flush.bind(x),
54
+ _pino: x
55
+ };
56
+ }
57
+ LoggerType2.fromPino = fromPino;
58
+ function create(params) {
59
+ const logger = (0, import_pino.default)(
60
+ {
61
+ level: params?.level ?? "info",
62
+ serializers: {
63
+ error: import_pino.default.stdSerializers.errWithCause,
64
+ err: import_pino.default.stdSerializers.errWithCause
65
+ },
66
+ formatters: {
67
+ level: (label) => {
68
+ return { level: label };
69
+ }
70
+ }
71
+ },
72
+ params?.stream
73
+ );
74
+ return fromPino(logger);
75
+ }
76
+ LoggerType2.create = create;
77
+ function is(x) {
78
+ return "_pino" in x;
79
+ }
80
+ LoggerType2.is = is;
81
+ })(LoggerType || (LoggerType = {}));
82
+ var createInstance = import_effect.Effect.fn(function* (params) {
83
+ const isDev = import_effect.Option.getOrNull(
84
+ yield* import_effect.Config.boolean("DEV").pipe(import_effect.Config.option)
85
+ );
86
+ const logFile = import_effect.Option.getOrNull(
87
+ yield* import_effect.Config.boolean("LOGGER_LOGFILE").pipe(import_effect.Config.option)
88
+ );
89
+ return LoggerType.create({
90
+ ...params,
91
+ ...isDev && {
92
+ stream: logFile ? import_pino.default.transport({
93
+ target: "pino/file",
94
+ options: {
95
+ destination: "./logs/server.log",
96
+ mkdir: true
97
+ }
98
+ }) : import_pino.default.transport({
99
+ target: "pino-pretty",
100
+ options: {
101
+ ignore: "pid,hostname"
102
+ }
103
+ })
104
+ }
105
+ });
106
+ });
107
+ var tag = "ff-serv/logger";
108
+ var Logger = class _Logger extends import_effect.Effect.Service()(tag, {
109
+ effect: createInstance()
110
+ }) {
111
+ static create(params) {
112
+ return _Logger.make(LoggerType.create(params));
113
+ }
114
+ static layer = (params) => import_effect.Layer.effect(
115
+ _Logger,
116
+ import_effect.Effect.gen(function* () {
117
+ return _Logger.make(yield* createInstance(params));
118
+ })
119
+ );
120
+ //
121
+ static get = import_effect.Effect.fn(function* () {
122
+ const logger = yield* import_effect.Effect.serviceOption(_Logger);
123
+ if (import_effect.Option.isNone(logger)) return void 0;
124
+ return logger.value;
125
+ });
126
+ static replace = (logger) => (e) => {
127
+ if (logger == null) return e;
128
+ if (logger instanceof _Logger)
129
+ return import_effect.Effect.provideService(e, _Logger, logger);
130
+ if (LoggerType.is(logger)) {
131
+ return import_effect.Effect.provideService(e, _Logger, _Logger.make(logger));
132
+ }
133
+ return import_effect.Effect.provideService(
134
+ e,
135
+ _Logger,
136
+ _Logger.make(LoggerType.fromPino(logger))
137
+ );
138
+ };
139
+ static replaceChild = (...params) => (e) => import_effect.Effect.gen(function* () {
140
+ const logger = yield* _Logger.get();
141
+ if (logger == null) return yield* e;
142
+ const child = logger.child(...params);
143
+ return yield* import_effect.Effect.provideService(e, _Logger, _Logger.make(child));
144
+ });
145
+ // --
146
+ static info = import_effect.Effect.fn(function* (...params) {
147
+ const logger = yield* _Logger.get();
148
+ if (logger == null) return;
149
+ logger.info(...params);
150
+ });
151
+ static debug = import_effect.Effect.fn(function* (...params) {
152
+ const logger = yield* _Logger.get();
153
+ if (logger == null) return;
154
+ logger.debug(...params);
155
+ });
156
+ static warn = import_effect.Effect.fn(function* (...params) {
157
+ const logger = yield* _Logger.get();
158
+ if (logger == null) return;
159
+ logger.warn(...params);
160
+ });
161
+ static error = import_effect.Effect.fn(function* (...params) {
162
+ const logger = yield* _Logger.get();
163
+ if (logger == null) return;
164
+ logger.error(...params);
165
+ });
166
+ static flush = import_effect.Effect.fn(function* (...params) {
167
+ const logger = yield* _Logger.get();
168
+ if (logger == null) return;
169
+ logger.flush(...params);
170
+ });
171
+ };
172
+ // Annotate the CommonJS export names for ESM import in node:
173
+ 0 && (module.exports = {
174
+ Logger
175
+ });
176
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/logger.ts"],"sourcesContent":["export { Logger } from './logger.js';\n","import { Config, Effect, Layer, Option } from 'effect';\nimport pino from 'pino';\n\n// Base logger\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tlevel?: pino.Level;\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: params?.level ?? 'info',\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport function is(x: object): x is LoggerType {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = ReturnType<typeof LoggerType.create>;\n\n// Effect service\nconst createInstance = Effect.fn(function* (params?: LoggerType.CreateParams) {\n\tconst isDev = Option.getOrNull(\n\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t);\n\tconst logFile = Option.getOrNull(\n\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t);\n\n\treturn LoggerType.create({\n\t\t...params,\n\t\t...(isDev && {\n\t\t\tstream: logFile\n\t\t\t\t? pino.transport({\n\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t: pino.transport({\n\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t}),\n\t});\n});\n\nconst tag = 'ff-serv/logger' as const;\nexport class Logger extends Effect.Service<Logger>()(tag, {\n\teffect: createInstance(),\n}) {\n\tstatic create(params?: LoggerType.CreateParams) {\n\t\treturn Logger.make(LoggerType.create(params));\n\t}\n\n\tstatic layer = (params?: Parameters<typeof createInstance>[0]) =>\n\t\tLayer.effect(\n\t\t\tLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn Logger.make(yield* createInstance(params));\n\t\t\t}),\n\t\t);\n\n\t//\n\n\tstatic get = Effect.fn(function* () {\n\t\tconst logger = yield* Effect.serviceOption(Logger);\n\t\tif (Option.isNone(logger)) return undefined;\n\t\treturn logger.value;\n\t});\n\n\tstatic replace =\n\t\t(logger: Logger | LoggerType | pino.Logger | undefined) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) => {\n\t\t\tif (logger == null) return e;\n\t\t\tif (logger instanceof Logger)\n\t\t\t\treturn Effect.provideService(e, Logger, logger);\n\n\t\t\tif (LoggerType.is(logger)) {\n\t\t\t\treturn Effect.provideService(e, Logger, Logger.make(logger));\n\t\t\t}\n\n\t\t\treturn Effect.provideService(\n\t\t\t\te,\n\t\t\t\tLogger,\n\t\t\t\tLogger.make(LoggerType.fromPino(logger)),\n\t\t\t);\n\t\t};\n\n\tstatic replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst logger = yield* Logger.get();\n\t\t\t\tif (logger == null) return yield* e;\n\n\t\t\t\tconst child = logger.child(...params);\n\t\t\t\treturn yield* Effect.provideService(e, Logger, Logger.make(child));\n\t\t\t});\n\n\t// --\n\n\tstatic info = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['info']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.info(...params);\n\t});\n\n\tstatic debug = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['debug']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.debug(...params);\n\t});\n\n\tstatic warn = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['warn']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.warn(...params);\n\t});\n\n\tstatic error = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['error']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.error(...params);\n\t});\n\n\tstatic flush = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['flush']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.flush(...params);\n\t});\n}\n"],"mappings":"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","names":["LoggerType","pino"]}
@@ -0,0 +1,64 @@
1
+ import * as effect_ConfigError from 'effect/ConfigError';
2
+ import { Effect, Layer } from 'effect';
3
+ import pino from 'pino';
4
+
5
+ declare namespace LoggerType {
6
+ function fromPino(x: pino.Logger<never, boolean>): {
7
+ info: pino.LogFn;
8
+ error: pino.LogFn;
9
+ warn: pino.LogFn;
10
+ debug: pino.LogFn;
11
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
12
+ flush: (cb?: (err?: Error) => void) => void;
13
+ _pino: pino.Logger<never, boolean>;
14
+ };
15
+ type CreateParams = {
16
+ level?: pino.Level;
17
+ stream?: pino.DestinationStream;
18
+ };
19
+ function create(params?: CreateParams): {
20
+ info: pino.LogFn;
21
+ error: pino.LogFn;
22
+ warn: pino.LogFn;
23
+ debug: pino.LogFn;
24
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
25
+ flush: (cb?: (err?: Error) => void) => void;
26
+ _pino: pino.Logger<never, boolean>;
27
+ };
28
+ function is(x: object): x is LoggerType;
29
+ }
30
+ type LoggerType = ReturnType<typeof LoggerType.create>;
31
+ declare const createInstance: (params?: LoggerType.CreateParams | undefined) => Effect.Effect<{
32
+ info: pino.LogFn;
33
+ error: pino.LogFn;
34
+ warn: pino.LogFn;
35
+ debug: pino.LogFn;
36
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
37
+ flush: (cb?: (err?: Error) => void) => void;
38
+ _pino: pino.Logger<never, boolean>;
39
+ }, effect_ConfigError.ConfigError, never>;
40
+ declare const Logger_base: Effect.Service.Class<Logger, "ff-serv/logger", {
41
+ readonly effect: Effect.Effect<{
42
+ info: pino.LogFn;
43
+ error: pino.LogFn;
44
+ warn: pino.LogFn;
45
+ debug: pino.LogFn;
46
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
47
+ flush: (cb?: (err?: Error) => void) => void;
48
+ _pino: pino.Logger<never, boolean>;
49
+ }, effect_ConfigError.ConfigError, never>;
50
+ }>;
51
+ declare class Logger extends Logger_base {
52
+ static create(params?: LoggerType.CreateParams): Logger;
53
+ static layer: (params?: Parameters<typeof createInstance>[0]) => Layer.Layer<Logger, effect_ConfigError.ConfigError, never>;
54
+ static get: () => Effect.Effect<Logger | undefined, never, never>;
55
+ static replace: (logger: Logger | LoggerType | pino.Logger | undefined) => <A, E, R>(e: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
56
+ static replaceChild: (...params: Parameters<LoggerType["child"]>) => <A, E, R>(e: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
57
+ static info: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
58
+ static debug: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
59
+ static warn: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
60
+ static error: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
61
+ static flush: (cb?: ((err?: Error) => void) | undefined) => Effect.Effect<void, never, never>;
62
+ }
63
+
64
+ export { Logger };
@@ -0,0 +1,64 @@
1
+ import * as effect_ConfigError from 'effect/ConfigError';
2
+ import { Effect, Layer } from 'effect';
3
+ import pino from 'pino';
4
+
5
+ declare namespace LoggerType {
6
+ function fromPino(x: pino.Logger<never, boolean>): {
7
+ info: pino.LogFn;
8
+ error: pino.LogFn;
9
+ warn: pino.LogFn;
10
+ debug: pino.LogFn;
11
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
12
+ flush: (cb?: (err?: Error) => void) => void;
13
+ _pino: pino.Logger<never, boolean>;
14
+ };
15
+ type CreateParams = {
16
+ level?: pino.Level;
17
+ stream?: pino.DestinationStream;
18
+ };
19
+ function create(params?: CreateParams): {
20
+ info: pino.LogFn;
21
+ error: pino.LogFn;
22
+ warn: pino.LogFn;
23
+ debug: pino.LogFn;
24
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
25
+ flush: (cb?: (err?: Error) => void) => void;
26
+ _pino: pino.Logger<never, boolean>;
27
+ };
28
+ function is(x: object): x is LoggerType;
29
+ }
30
+ type LoggerType = ReturnType<typeof LoggerType.create>;
31
+ declare const createInstance: (params?: LoggerType.CreateParams | undefined) => Effect.Effect<{
32
+ info: pino.LogFn;
33
+ error: pino.LogFn;
34
+ warn: pino.LogFn;
35
+ debug: pino.LogFn;
36
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
37
+ flush: (cb?: (err?: Error) => void) => void;
38
+ _pino: pino.Logger<never, boolean>;
39
+ }, effect_ConfigError.ConfigError, never>;
40
+ declare const Logger_base: Effect.Service.Class<Logger, "ff-serv/logger", {
41
+ readonly effect: Effect.Effect<{
42
+ info: pino.LogFn;
43
+ error: pino.LogFn;
44
+ warn: pino.LogFn;
45
+ debug: pino.LogFn;
46
+ child: (bindings: pino.Bindings, options?: pino.ChildLoggerOptions<string> | undefined) => /*elided*/ any;
47
+ flush: (cb?: (err?: Error) => void) => void;
48
+ _pino: pino.Logger<never, boolean>;
49
+ }, effect_ConfigError.ConfigError, never>;
50
+ }>;
51
+ declare class Logger extends Logger_base {
52
+ static create(params?: LoggerType.CreateParams): Logger;
53
+ static layer: (params?: Parameters<typeof createInstance>[0]) => Layer.Layer<Logger, effect_ConfigError.ConfigError, never>;
54
+ static get: () => Effect.Effect<Logger | undefined, never, never>;
55
+ static replace: (logger: Logger | LoggerType | pino.Logger | undefined) => <A, E, R>(e: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
56
+ static replaceChild: (...params: Parameters<LoggerType["child"]>) => <A, E, R>(e: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
57
+ static info: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
58
+ static debug: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
59
+ static warn: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
60
+ static error: (obj: unknown, msg?: string | undefined, ...args: unknown[]) => Effect.Effect<void, never, never>;
61
+ static flush: (cb?: ((err?: Error) => void) | undefined) => Effect.Effect<void, never, never>;
62
+ }
63
+
64
+ export { Logger };
package/dist/index.js ADDED
@@ -0,0 +1,139 @@
1
+ // src/logger.ts
2
+ import { Config, Effect, Layer, Option } from "effect";
3
+ import pino from "pino";
4
+ var LoggerType;
5
+ ((LoggerType2) => {
6
+ function fromPino(x) {
7
+ return {
8
+ info: x.info.bind(x),
9
+ error: x.error.bind(x),
10
+ warn: x.warn.bind(x),
11
+ debug: x.debug.bind(x),
12
+ child: (...params) => {
13
+ return fromPino(
14
+ x.child(...params)
15
+ );
16
+ },
17
+ flush: x.flush.bind(x),
18
+ _pino: x
19
+ };
20
+ }
21
+ LoggerType2.fromPino = fromPino;
22
+ function create(params) {
23
+ const logger = pino(
24
+ {
25
+ level: params?.level ?? "info",
26
+ serializers: {
27
+ error: pino.stdSerializers.errWithCause,
28
+ err: pino.stdSerializers.errWithCause
29
+ },
30
+ formatters: {
31
+ level: (label) => {
32
+ return { level: label };
33
+ }
34
+ }
35
+ },
36
+ params?.stream
37
+ );
38
+ return fromPino(logger);
39
+ }
40
+ LoggerType2.create = create;
41
+ function is(x) {
42
+ return "_pino" in x;
43
+ }
44
+ LoggerType2.is = is;
45
+ })(LoggerType || (LoggerType = {}));
46
+ var createInstance = Effect.fn(function* (params) {
47
+ const isDev = Option.getOrNull(
48
+ yield* Config.boolean("DEV").pipe(Config.option)
49
+ );
50
+ const logFile = Option.getOrNull(
51
+ yield* Config.boolean("LOGGER_LOGFILE").pipe(Config.option)
52
+ );
53
+ return LoggerType.create({
54
+ ...params,
55
+ ...isDev && {
56
+ stream: logFile ? pino.transport({
57
+ target: "pino/file",
58
+ options: {
59
+ destination: "./logs/server.log",
60
+ mkdir: true
61
+ }
62
+ }) : pino.transport({
63
+ target: "pino-pretty",
64
+ options: {
65
+ ignore: "pid,hostname"
66
+ }
67
+ })
68
+ }
69
+ });
70
+ });
71
+ var tag = "ff-serv/logger";
72
+ var Logger = class _Logger extends Effect.Service()(tag, {
73
+ effect: createInstance()
74
+ }) {
75
+ static create(params) {
76
+ return _Logger.make(LoggerType.create(params));
77
+ }
78
+ static layer = (params) => Layer.effect(
79
+ _Logger,
80
+ Effect.gen(function* () {
81
+ return _Logger.make(yield* createInstance(params));
82
+ })
83
+ );
84
+ //
85
+ static get = Effect.fn(function* () {
86
+ const logger = yield* Effect.serviceOption(_Logger);
87
+ if (Option.isNone(logger)) return void 0;
88
+ return logger.value;
89
+ });
90
+ static replace = (logger) => (e) => {
91
+ if (logger == null) return e;
92
+ if (logger instanceof _Logger)
93
+ return Effect.provideService(e, _Logger, logger);
94
+ if (LoggerType.is(logger)) {
95
+ return Effect.provideService(e, _Logger, _Logger.make(logger));
96
+ }
97
+ return Effect.provideService(
98
+ e,
99
+ _Logger,
100
+ _Logger.make(LoggerType.fromPino(logger))
101
+ );
102
+ };
103
+ static replaceChild = (...params) => (e) => Effect.gen(function* () {
104
+ const logger = yield* _Logger.get();
105
+ if (logger == null) return yield* e;
106
+ const child = logger.child(...params);
107
+ return yield* Effect.provideService(e, _Logger, _Logger.make(child));
108
+ });
109
+ // --
110
+ static info = Effect.fn(function* (...params) {
111
+ const logger = yield* _Logger.get();
112
+ if (logger == null) return;
113
+ logger.info(...params);
114
+ });
115
+ static debug = Effect.fn(function* (...params) {
116
+ const logger = yield* _Logger.get();
117
+ if (logger == null) return;
118
+ logger.debug(...params);
119
+ });
120
+ static warn = Effect.fn(function* (...params) {
121
+ const logger = yield* _Logger.get();
122
+ if (logger == null) return;
123
+ logger.warn(...params);
124
+ });
125
+ static error = Effect.fn(function* (...params) {
126
+ const logger = yield* _Logger.get();
127
+ if (logger == null) return;
128
+ logger.error(...params);
129
+ });
130
+ static flush = Effect.fn(function* (...params) {
131
+ const logger = yield* _Logger.get();
132
+ if (logger == null) return;
133
+ logger.flush(...params);
134
+ });
135
+ };
136
+ export {
137
+ Logger
138
+ };
139
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/logger.ts"],"sourcesContent":["import { Config, Effect, Layer, Option } from 'effect';\nimport pino from 'pino';\n\n// Base logger\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tlevel?: pino.Level;\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: params?.level ?? 'info',\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport function is(x: object): x is LoggerType {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = ReturnType<typeof LoggerType.create>;\n\n// Effect service\nconst createInstance = Effect.fn(function* (params?: LoggerType.CreateParams) {\n\tconst isDev = Option.getOrNull(\n\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t);\n\tconst logFile = Option.getOrNull(\n\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t);\n\n\treturn LoggerType.create({\n\t\t...params,\n\t\t...(isDev && {\n\t\t\tstream: logFile\n\t\t\t\t? pino.transport({\n\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t: pino.transport({\n\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t}),\n\t});\n});\n\nconst tag = 'ff-serv/logger' as const;\nexport class Logger extends Effect.Service<Logger>()(tag, {\n\teffect: createInstance(),\n}) {\n\tstatic create(params?: LoggerType.CreateParams) {\n\t\treturn Logger.make(LoggerType.create(params));\n\t}\n\n\tstatic layer = (params?: Parameters<typeof createInstance>[0]) =>\n\t\tLayer.effect(\n\t\t\tLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn Logger.make(yield* createInstance(params));\n\t\t\t}),\n\t\t);\n\n\t//\n\n\tstatic get = Effect.fn(function* () {\n\t\tconst logger = yield* Effect.serviceOption(Logger);\n\t\tif (Option.isNone(logger)) return undefined;\n\t\treturn logger.value;\n\t});\n\n\tstatic replace =\n\t\t(logger: Logger | LoggerType | pino.Logger | undefined) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) => {\n\t\t\tif (logger == null) return e;\n\t\t\tif (logger instanceof Logger)\n\t\t\t\treturn Effect.provideService(e, Logger, logger);\n\n\t\t\tif (LoggerType.is(logger)) {\n\t\t\t\treturn Effect.provideService(e, Logger, Logger.make(logger));\n\t\t\t}\n\n\t\t\treturn Effect.provideService(\n\t\t\t\te,\n\t\t\t\tLogger,\n\t\t\t\tLogger.make(LoggerType.fromPino(logger)),\n\t\t\t);\n\t\t};\n\n\tstatic replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst logger = yield* Logger.get();\n\t\t\t\tif (logger == null) return yield* e;\n\n\t\t\t\tconst child = logger.child(...params);\n\t\t\t\treturn yield* Effect.provideService(e, Logger, Logger.make(child));\n\t\t\t});\n\n\t// --\n\n\tstatic info = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['info']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.info(...params);\n\t});\n\n\tstatic debug = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['debug']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.debug(...params);\n\t});\n\n\tstatic warn = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['warn']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.warn(...params);\n\t});\n\n\tstatic error = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['error']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.error(...params);\n\t});\n\n\tstatic flush = Effect.fn(function* (\n\t\t...params: Parameters<LoggerType['flush']>\n\t) {\n\t\tconst logger = yield* Logger.get();\n\t\tif (logger == null) return;\n\t\tlogger.flush(...params);\n\t});\n}\n"],"mappings":"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","names":["LoggerType"]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "ff-serv",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js",
9
+ "require": "./dist/index.cjs"
10
+ }
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "src"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "test": "vitest run",
19
+ "dev": "tsup --watch"
20
+ },
21
+ "devDependencies": {
22
+ "@types/bun": "^1.3.2",
23
+ "tsup": "^8.5.0",
24
+ "typescript": "^5.9.3"
25
+ },
26
+ "peerDependencies": {
27
+ "effect": "^3.19.3",
28
+ "pino": "^9"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "homepage": "https://github.com/fdarian/ff.git",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/fdarian/ff.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/fdarian/ff/issues"
40
+ },
41
+ "keywords": [
42
+ "effect",
43
+ "server",
44
+ "service"
45
+ ]
46
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { Logger } from './logger.js';
package/src/logger.ts ADDED
@@ -0,0 +1,177 @@
1
+ import { Config, Effect, Layer, Option } from 'effect';
2
+ import pino from 'pino';
3
+
4
+ // Base logger
5
+
6
+ namespace LoggerType {
7
+ export function fromPino(x: pino.Logger<never, boolean>) {
8
+ return {
9
+ info: x.info.bind(x),
10
+ error: x.error.bind(x),
11
+ warn: x.warn.bind(x),
12
+ debug: x.debug.bind(x),
13
+ child: (...params: Parameters<typeof x.child>) => {
14
+ return fromPino(
15
+ x.child(...params) as unknown as pino.Logger<never, boolean>,
16
+ );
17
+ },
18
+ flush: x.flush.bind(x),
19
+ _pino: x,
20
+ };
21
+ }
22
+
23
+ export type CreateParams = {
24
+ level?: pino.Level;
25
+ stream?: pino.DestinationStream;
26
+ };
27
+
28
+ export function create(params?: CreateParams) {
29
+ const logger = pino(
30
+ {
31
+ level: params?.level ?? 'info',
32
+ serializers: {
33
+ error: pino.stdSerializers.errWithCause,
34
+ err: pino.stdSerializers.errWithCause,
35
+ },
36
+ formatters: {
37
+ level: (label) => {
38
+ return { level: label };
39
+ },
40
+ },
41
+ },
42
+ params?.stream,
43
+ );
44
+ return fromPino(logger);
45
+ }
46
+
47
+ export function is(x: object): x is LoggerType {
48
+ return '_pino' in x;
49
+ }
50
+ }
51
+ type LoggerType = ReturnType<typeof LoggerType.create>;
52
+
53
+ // Effect service
54
+ const createInstance = Effect.fn(function* (params?: LoggerType.CreateParams) {
55
+ const isDev = Option.getOrNull(
56
+ yield* Config.boolean('DEV').pipe(Config.option),
57
+ );
58
+ const logFile = Option.getOrNull(
59
+ yield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),
60
+ );
61
+
62
+ return LoggerType.create({
63
+ ...params,
64
+ ...(isDev && {
65
+ stream: logFile
66
+ ? pino.transport({
67
+ target: 'pino/file',
68
+ options: {
69
+ destination: './logs/server.log',
70
+ mkdir: true,
71
+ },
72
+ })
73
+ : pino.transport({
74
+ target: 'pino-pretty',
75
+ options: {
76
+ ignore: 'pid,hostname',
77
+ },
78
+ }),
79
+ }),
80
+ });
81
+ });
82
+
83
+ const tag = 'ff-serv/logger' as const;
84
+ export class Logger extends Effect.Service<Logger>()(tag, {
85
+ effect: createInstance(),
86
+ }) {
87
+ static create(params?: LoggerType.CreateParams) {
88
+ return Logger.make(LoggerType.create(params));
89
+ }
90
+
91
+ static layer = (params?: Parameters<typeof createInstance>[0]) =>
92
+ Layer.effect(
93
+ Logger,
94
+ Effect.gen(function* () {
95
+ return Logger.make(yield* createInstance(params));
96
+ }),
97
+ );
98
+
99
+ //
100
+
101
+ static get = Effect.fn(function* () {
102
+ const logger = yield* Effect.serviceOption(Logger);
103
+ if (Option.isNone(logger)) return undefined;
104
+ return logger.value;
105
+ });
106
+
107
+ static replace =
108
+ (logger: Logger | LoggerType | pino.Logger | undefined) =>
109
+ <A, E, R>(e: Effect.Effect<A, E, R>) => {
110
+ if (logger == null) return e;
111
+ if (logger instanceof Logger)
112
+ return Effect.provideService(e, Logger, logger);
113
+
114
+ if (LoggerType.is(logger)) {
115
+ return Effect.provideService(e, Logger, Logger.make(logger));
116
+ }
117
+
118
+ return Effect.provideService(
119
+ e,
120
+ Logger,
121
+ Logger.make(LoggerType.fromPino(logger)),
122
+ );
123
+ };
124
+
125
+ static replaceChild =
126
+ (...params: Parameters<LoggerType['child']>) =>
127
+ <A, E, R>(e: Effect.Effect<A, E, R>) =>
128
+ Effect.gen(function* () {
129
+ const logger = yield* Logger.get();
130
+ if (logger == null) return yield* e;
131
+
132
+ const child = logger.child(...params);
133
+ return yield* Effect.provideService(e, Logger, Logger.make(child));
134
+ });
135
+
136
+ // --
137
+
138
+ static info = Effect.fn(function* (
139
+ ...params: Parameters<LoggerType['info']>
140
+ ) {
141
+ const logger = yield* Logger.get();
142
+ if (logger == null) return;
143
+ logger.info(...params);
144
+ });
145
+
146
+ static debug = Effect.fn(function* (
147
+ ...params: Parameters<LoggerType['debug']>
148
+ ) {
149
+ const logger = yield* Logger.get();
150
+ if (logger == null) return;
151
+ logger.debug(...params);
152
+ });
153
+
154
+ static warn = Effect.fn(function* (
155
+ ...params: Parameters<LoggerType['warn']>
156
+ ) {
157
+ const logger = yield* Logger.get();
158
+ if (logger == null) return;
159
+ logger.warn(...params);
160
+ });
161
+
162
+ static error = Effect.fn(function* (
163
+ ...params: Parameters<LoggerType['error']>
164
+ ) {
165
+ const logger = yield* Logger.get();
166
+ if (logger == null) return;
167
+ logger.error(...params);
168
+ });
169
+
170
+ static flush = Effect.fn(function* (
171
+ ...params: Parameters<LoggerType['flush']>
172
+ ) {
173
+ const logger = yield* Logger.get();
174
+ if (logger == null) return;
175
+ logger.flush(...params);
176
+ });
177
+ }