@decohere/scribe-pino 0.0.1-dev.19 → 0.0.1-dev.20261105.103

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 ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025-2026 Typesmiths
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/es6/src/index.js CHANGED
@@ -1,4 +1,3 @@
1
1
  export * from "./pino.adapater.js";
2
+ export * from "./pino.recipe.js";
2
3
  export * from "./scribe-pino.js";
3
-
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vcGluby5hZGFwYXRlci5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vc2NyaWJlLXBpbm8uanNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHFCQUFxQjtBQUNuQyxjQUFjLG1CQUFtQiJ9
@@ -4,6 +4,8 @@ export class PinoAdapter extends LogAdapter {
4
4
  _pino;
5
5
  options;
6
6
  stream;
7
+ disposed = false;
8
+ retired = false;
7
9
  constructor(options, stream){
8
10
  super();
9
11
  this.options = options;
@@ -33,8 +35,122 @@ export class PinoAdapter extends LogAdapter {
33
35
  return logger;
34
36
  }
35
37
  flush(cb) {
38
+ if (this.retired || !this._pino) {
39
+ cb?.();
40
+ return;
41
+ }
36
42
  this._pino.flush(cb);
37
43
  }
44
+ /**
45
+ * Immediately stop accepting writes into the destination (ThreadStream).
46
+ * Does not wait for flush — use `stop()` for async drain after retire.
47
+ */ retire() {
48
+ if (this.retired) {
49
+ return;
50
+ }
51
+ this.retired = true;
52
+ const guarded = this.stream;
53
+ if (typeof guarded?.retire === "function") {
54
+ guarded.retire("adapter retired");
55
+ return;
56
+ }
57
+ destroyDestination(this.stream);
58
+ }
59
+ async [Symbol.asyncDispose]() {
60
+ if (this.disposed) {
61
+ return;
62
+ }
63
+ this.disposed = true;
64
+ if (!this.retired) {
65
+ const dest = this.stream;
66
+ if (dest != null && typeof dest.end === "function") {
67
+ // pino.transport() is a ThreadStream: pino.flush() → Atomics.waitAsync can
68
+ // hang forever after concurrent writes. end() flushSyncs then signals
69
+ // finish/close (it does not accept a Node Writable callback).
70
+ await endDestination(dest);
71
+ } else if (this._pino) {
72
+ await new Promise((resolve, reject)=>{
73
+ try {
74
+ this._pino.flush((err)=>{
75
+ if (err != null) {
76
+ reject(err);
77
+ return;
78
+ }
79
+ resolve();
80
+ });
81
+ } catch (err) {
82
+ reject(err instanceof Error ? err : new Error(String(err)));
83
+ }
84
+ });
85
+ }
86
+ }
87
+ // Mark dead after graceful end (or immediately if already force-retired).
88
+ this.retire();
89
+ }
90
+ }
91
+ function destroyDestination(stream) {
92
+ const destroyable = stream;
93
+ if (typeof destroyable?.destroy === "function") {
94
+ try {
95
+ destroyable.destroy();
96
+ } catch {
97
+ // already dead
98
+ }
99
+ }
100
+ }
101
+ /**
102
+ * Drain a pino destination.
103
+ *
104
+ * Node `Writable.end(cb)` invokes `cb`. `pino.transport()` returns a
105
+ * ThreadStream whose `end()` takes no callback and signals via `finish`/`close`
106
+ * instead — waiting only on `end(cb)` hangs forever and blocks Flux HMR.
107
+ */ function endDestination(stream) {
108
+ if (typeof stream.end !== "function") {
109
+ return Promise.resolve();
110
+ }
111
+ if (stream.destroyed || stream.closed || stream.writableFinished) {
112
+ return Promise.resolve();
113
+ }
114
+ return new Promise((resolve, reject)=>{
115
+ let settled = false;
116
+ const settle = (err)=>{
117
+ if (settled) {
118
+ return;
119
+ }
120
+ settled = true;
121
+ stream.off?.("finish", onFinish);
122
+ stream.off?.("close", onClose);
123
+ stream.off?.("error", onError);
124
+ if (err != null) {
125
+ reject(err);
126
+ return;
127
+ }
128
+ resolve();
129
+ };
130
+ const onFinish = ()=>settle();
131
+ const onClose = ()=>settle();
132
+ const onError = (err)=>{
133
+ // ThreadStream may emit error then close during teardown; closed = done.
134
+ if (stream.destroyed || stream.closed) {
135
+ settle();
136
+ return;
137
+ }
138
+ settle(err);
139
+ };
140
+ stream.once?.("finish", onFinish);
141
+ stream.once?.("close", onClose);
142
+ stream.once?.("error", onError);
143
+ try {
144
+ stream.end((err)=>settle(err));
145
+ } catch (err) {
146
+ settle(err instanceof Error ? err : new Error(String(err)));
147
+ return;
148
+ }
149
+ // ThreadStream.end() is a no-op when already destroyed (no events).
150
+ if (stream.destroyed || stream.closed || stream.writableFinished) {
151
+ settle();
152
+ }
153
+ });
38
154
  }
39
155
  function logMethod(args, method) {
40
156
  let message = args.at(0);
@@ -48,9 +164,7 @@ function logMethod(args, method) {
48
164
  if (data instanceof Error) {
49
165
  message = {
50
166
  msg: message,
51
- ...{
52
- error: data
53
- }
167
+ error: data
54
168
  };
55
169
  } else if (typeof data === "object") {
56
170
  message = {
@@ -65,15 +179,18 @@ function logMethod(args, method) {
65
179
  }
66
180
  method.call(this, message);
67
181
  }
68
- function pinoMix(logger) {
182
+ /**
183
+ * Add Scribe's logger members to a Pino logger. `spawn` is Pino's own `child`:
184
+ * a Pino child inherits its parent's members through the prototype, so
185
+ * `logger.child` would be the parent's override.
186
+ */ function pinoMix(logger, spawn = logger.child) {
69
187
  return Object.assign(logger, {
70
188
  get currentLevel () {
71
189
  return logger.level;
72
190
  },
73
191
  get logLevels () {
74
192
  return logger.levels.values;
75
- }
193
+ },
194
+ child: (fields)=>pinoMix(spawn.call(logger, fields), spawn)
76
195
  });
77
196
  }
78
-
79
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvcGluby5hZGFwYXRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHR0eXBlIEJhc2VMb2dnZXIsXG5cdGZvcm1hdEVycm9yLFxuXHRMb2dBZGFwdGVyLFxuXHR0eXBlIExvZ2dlcixcblx0dHlwZSBTY3JpYmVPcHRpb25zLFxufSBmcm9tIFwiQGRlY29oZXJlL3NjcmliZVwiO1xuaW1wb3J0IHBpbm8sIHsgdHlwZSBMb2dGbiB9IGZyb20gXCJwaW5vXCI7XG5cbmV4cG9ydCB0eXBlIFBpbm9BZGFwYXRlck9wdGlvbnMgPSB7XG5cdG9wdGlvbnM/OiBwaW5vLkxvZ2dlck9wdGlvbnM7XG5cdHN0cmVhbT86IHBpbm8uRGVzdGluYXRpb25TdHJlYW07XG59O1xuXG5leHBvcnQgY2xhc3MgUGlub0FkYXB0ZXIgZXh0ZW5kcyBMb2dBZGFwdGVyIHtcblx0cHJpdmF0ZSBfcGlubzogcGluby5Mb2dnZXI7XG5cdHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogcGluby5Mb2dnZXJPcHRpb25zO1xuXHRwcml2YXRlIHJlYWRvbmx5IHN0cmVhbTogcGluby5EZXN0aW5hdGlvblN0cmVhbTtcblx0cHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IHBpbm8uTG9nZ2VyT3B0aW9ucywgc3RyZWFtPzogcGluby5EZXN0aW5hdGlvblN0cmVhbSkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5vcHRpb25zID0gb3B0aW9ucztcblx0XHR0aGlzLnN0cmVhbSA9IHN0cmVhbTtcblx0fVxuXG5cdHB1YmxpYyBjb25maWd1cmU8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRcdHNjcmliZU9wdGlvbnM6IFNjcmliZU9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdCkge1xuXHRcdGNvbnN0IHsgbG9nTGV2ZWwsIHJlZGFjdGlvbnMgfSA9IHNjcmliZU9wdGlvbnM7XG5cdFx0Y29uc3QgY3VzdG9tTGV2ZWxzID0gdGhpcy5nZXRMb2dMZXZlbHMoc2NyaWJlT3B0aW9ucyk7XG5cblx0XHRjb25zdCBwaW5vT3B0aW9uczogcGluby5Mb2dnZXJPcHRpb25zID0ge1xuXHRcdFx0Y3VzdG9tTGV2ZWxzLFxuXHRcdFx0bGV2ZWw6IGxvZ0xldmVsLFxuXHRcdFx0aG9va3M6IHsgbG9nTWV0aG9kIH0sXG5cdFx0XHRzZXJpYWxpemVyczoge1xuXHRcdFx0XHRlcnJvcjogcGluby5zdGRTZXJpYWxpemVycy5lcnIsXG5cdFx0XHR9LFxuXHRcdFx0cmVkYWN0OiByZWRhY3Rpb25zLFxuXHRcdFx0Li4udGhpcy5vcHRpb25zLFxuXHRcdH07XG5cdFx0dGhpcy5fcGlubyA9IHBpbm8ocGlub09wdGlvbnMsIHRoaXMuc3RyZWFtKTtcblx0fVxuXG5cdHB1YmxpYyBnZXRMb2dnZXI8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRcdG5hbWU6IHN0cmluZyxcblx0KTogTG9nZ2VyPFQsIEN1c3RvbU9ubHk+IHtcblx0XHRjb25zdCBsb2dnZXIgPSBwaW5vTWl4PFQsIEN1c3RvbU9ubHk+KHRoaXMuX3Bpbm8uY2hpbGQoeyBuYW1lIH0pKTtcblx0XHRyZXR1cm4gbG9nZ2VyO1xuXHR9XG5cblx0cHVibGljIGZsdXNoKGNiPzogKCkgPT4gdm9pZCk6IHZvaWQge1xuXHRcdHRoaXMuX3Bpbm8uZmx1c2goY2IpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGxvZ01ldGhvZCh0aGlzOiBwaW5vLkxvZ2dlciwgYXJnczogUGFyYW1ldGVyczxMb2dGbj4sIG1ldGhvZDogTG9nRm4pIHtcblx0bGV0IG1lc3NhZ2UgPSBhcmdzLmF0KDApO1xuXHRjb25zdCBkYXRhID0gYXJncy5hdCgxKTtcblxuXHRpZiAobWVzc2FnZSBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0bWV0aG9kLmNhbGwodGhpcywgeyBlcnI6IG1lc3NhZ2UgfSwgZm9ybWF0RXJyb3IobWVzc2FnZSkpO1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmIChkYXRhIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRtZXNzYWdlID0geyBtc2c6IG1lc3NhZ2UsIC4uLnsgZXJyb3I6IGRhdGEgfSB9O1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSBcIm9iamVjdFwiKSB7XG5cdFx0bWVzc2FnZSA9IHsgbXNnOiBtZXNzYWdlLCAuLi5kYXRhIH07XG5cdH0gZWxzZSB7XG5cdFx0bWVzc2FnZSA9IHsgbXNnOiBtZXNzYWdlLCBkYXRhIH07XG5cdH1cblxuXHRtZXRob2QuY2FsbCh0aGlzLCBtZXNzYWdlKTtcbn1cblxuZnVuY3Rpb24gcGlub01peDxUIGV4dGVuZHMgc3RyaW5nID0gbmV2ZXIsIEN1c3RvbU9ubHkgZXh0ZW5kcyB0cnVlIHwgZmFsc2UgPSBmYWxzZT4oXG5cdGxvZ2dlcjogcGluby5Mb2dnZXIsXG4pOiBMb2dnZXI8VCwgQ3VzdG9tT25seT4ge1xuXHRyZXR1cm4gT2JqZWN0LmFzc2lnbjxwaW5vLkxvZ2dlciwgQmFzZUxvZ2dlcj4obG9nZ2VyLCB7XG5cdFx0Z2V0IGN1cnJlbnRMZXZlbCgpIHtcblx0XHRcdHJldHVybiBsb2dnZXIubGV2ZWw7XG5cdFx0fSxcblx0XHRnZXQgbG9nTGV2ZWxzKCkge1xuXHRcdFx0cmV0dXJuIGxvZ2dlci5sZXZlbHMudmFsdWVzO1xuXHRcdH0sXG5cdH0pIGFzIExvZ2dlcjxULCBDdXN0b21Pbmx5Pjtcbn1cbiJdLCJuYW1lcyI6WyJmb3JtYXRFcnJvciIsIkxvZ0FkYXB0ZXIiLCJwaW5vIiwiUGlub0FkYXB0ZXIiLCJfcGlubyIsIm9wdGlvbnMiLCJzdHJlYW0iLCJjb25maWd1cmUiLCJzY3JpYmVPcHRpb25zIiwibG9nTGV2ZWwiLCJyZWRhY3Rpb25zIiwiY3VzdG9tTGV2ZWxzIiwiZ2V0TG9nTGV2ZWxzIiwicGlub09wdGlvbnMiLCJsZXZlbCIsImhvb2tzIiwibG9nTWV0aG9kIiwic2VyaWFsaXplcnMiLCJlcnJvciIsInN0ZFNlcmlhbGl6ZXJzIiwiZXJyIiwicmVkYWN0IiwiZ2V0TG9nZ2VyIiwibmFtZSIsImxvZ2dlciIsInBpbm9NaXgiLCJjaGlsZCIsImZsdXNoIiwiY2IiLCJhcmdzIiwibWV0aG9kIiwibWVzc2FnZSIsImF0IiwiZGF0YSIsIkVycm9yIiwiY2FsbCIsIm1zZyIsIk9iamVjdCIsImFzc2lnbiIsImN1cnJlbnRMZXZlbCIsImxvZ0xldmVscyIsImxldmVscyIsInZhbHVlcyJdLCJtYXBwaW5ncyI6IkFBQUEsU0FFQ0EsV0FBVyxFQUNYQyxVQUFVLFFBR0osbUJBQW1CO0FBQzFCLE9BQU9DLFVBQTBCLE9BQU87QUFPeEMsT0FBTyxNQUFNQyxvQkFBb0JGO0lBQ3hCRyxNQUFtQjtJQUNWQyxRQUE0QjtJQUM1QkMsT0FBK0I7SUFDaEQsWUFBbUJELE9BQTJCLEVBQUVDLE1BQStCLENBQUU7UUFDaEYsS0FBSztRQUNMLElBQUksQ0FBQ0QsT0FBTyxHQUFHQTtRQUNmLElBQUksQ0FBQ0MsTUFBTSxHQUFHQTtJQUNmO0lBRU9DLFVBQ05DLGFBQTJDLEVBQzFDO1FBQ0QsTUFBTSxFQUFFQyxRQUFRLEVBQUVDLFVBQVUsRUFBRSxHQUFHRjtRQUNqQyxNQUFNRyxlQUFlLElBQUksQ0FBQ0MsWUFBWSxDQUFDSjtRQUV2QyxNQUFNSyxjQUFrQztZQUN2Q0Y7WUFDQUcsT0FBT0w7WUFDUE0sT0FBTztnQkFBRUM7WUFBVTtZQUNuQkMsYUFBYTtnQkFDWkMsT0FBT2hCLEtBQUtpQixjQUFjLENBQUNDLEdBQUc7WUFDL0I7WUFDQUMsUUFBUVg7WUFDUixHQUFHLElBQUksQ0FBQ0wsT0FBTztRQUNoQjtRQUNBLElBQUksQ0FBQ0QsS0FBSyxHQUFHRixLQUFLVyxhQUFhLElBQUksQ0FBQ1AsTUFBTTtJQUMzQztJQUVPZ0IsVUFDTkMsSUFBWSxFQUNZO1FBQ3hCLE1BQU1DLFNBQVNDLFFBQXVCLElBQUksQ0FBQ3JCLEtBQUssQ0FBQ3NCLEtBQUssQ0FBQztZQUFFSDtRQUFLO1FBQzlELE9BQU9DO0lBQ1I7SUFFT0csTUFBTUMsRUFBZSxFQUFRO1FBQ25DLElBQUksQ0FBQ3hCLEtBQUssQ0FBQ3VCLEtBQUssQ0FBQ0M7SUFDbEI7QUFDRDtBQUVBLFNBQVNaLFVBQTZCYSxJQUF1QixFQUFFQyxNQUFhO0lBQzNFLElBQUlDLFVBQVVGLEtBQUtHLEVBQUUsQ0FBQztJQUN0QixNQUFNQyxPQUFPSixLQUFLRyxFQUFFLENBQUM7SUFFckIsSUFBSUQsbUJBQW1CRyxPQUFPO1FBQzdCSixPQUFPSyxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQUVmLEtBQUtXO1FBQVEsR0FBRy9CLFlBQVkrQjtRQUNoRDtJQUNEO0lBRUEsSUFBSUUsZ0JBQWdCQyxPQUFPO1FBQzFCSCxVQUFVO1lBQUVLLEtBQUtMO1lBQVMsR0FBRztnQkFBRWIsT0FBT2U7WUFBSyxDQUFDO1FBQUM7SUFDOUMsT0FBTyxJQUFJLE9BQU9BLFNBQVMsVUFBVTtRQUNwQ0YsVUFBVTtZQUFFSyxLQUFLTDtZQUFTLEdBQUdFLElBQUk7UUFBQztJQUNuQyxPQUFPO1FBQ05GLFVBQVU7WUFBRUssS0FBS0w7WUFBU0U7UUFBSztJQUNoQztJQUVBSCxPQUFPSyxJQUFJLENBQUMsSUFBSSxFQUFFSjtBQUNuQjtBQUVBLFNBQVNOLFFBQ1JELE1BQW1CO0lBRW5CLE9BQU9hLE9BQU9DLE1BQU0sQ0FBMEJkLFFBQVE7UUFDckQsSUFBSWUsZ0JBQWU7WUFDbEIsT0FBT2YsT0FBT1YsS0FBSztRQUNwQjtRQUNBLElBQUkwQixhQUFZO1lBQ2YsT0FBT2hCLE9BQU9pQixNQUFNLENBQUNDLE1BQU07UUFDNUI7SUFDRDtBQUNEIn0=
@@ -0,0 +1,96 @@
1
+ import { Environments } from "@decohere/core/system";
2
+ const DEFAULT_ROLL_SIZE = "10m";
3
+ const DEFAULT_ROLL_FREQUENCY = "daily";
4
+ const DEFAULT_ROLL_KEEP = 14;
5
+ const ENV_LOG_FILE = "SCRIBE_LOG_FILE";
6
+ const ENV_LOG_SIZE = "SCRIBE_LOG_SIZE";
7
+ const ENV_LOG_FREQUENCY = "SCRIBE_LOG_FREQUENCY";
8
+ const ENV_LOG_KEEP = "SCRIBE_LOG_KEEP";
9
+ function currentEnvironment() {
10
+ return process.env.NODE_ENV === Environments.production ? Environments.production : Environments.development;
11
+ }
12
+ function isEnabled(when, environment) {
13
+ return (when ?? "development") === "always" || environment === Environments.development;
14
+ }
15
+ function envString(name) {
16
+ const value = process.env[name]?.trim();
17
+ return value ? value : undefined;
18
+ }
19
+ function envFrequency() {
20
+ const raw = envString(ENV_LOG_FREQUENCY);
21
+ if (raw == null) {
22
+ return undefined;
23
+ }
24
+ if (/^\d+$/.test(raw)) {
25
+ return Number(raw);
26
+ }
27
+ return raw;
28
+ }
29
+ function envKeep() {
30
+ const raw = envString(ENV_LOG_KEEP);
31
+ if (raw == null) {
32
+ return undefined;
33
+ }
34
+ const keep = Number(raw);
35
+ return Number.isFinite(keep) && keep >= 0 ? keep : undefined;
36
+ }
37
+ /**
38
+ * Resolve roll options. `SCRIBE_LOG_FILE` overrides `file` so ops can redirect
39
+ * without touching app code. Size / frequency / keep: explicit > env > default.
40
+ */ function resolveRoll(options) {
41
+ return {
42
+ file: envString(ENV_LOG_FILE) ?? options.file,
43
+ size: options.size ?? envString(ENV_LOG_SIZE) ?? DEFAULT_ROLL_SIZE,
44
+ frequency: options.frequency ?? envFrequency() ?? DEFAULT_ROLL_FREQUENCY,
45
+ keep: options.keep ?? envKeep() ?? DEFAULT_ROLL_KEEP,
46
+ mkdir: options.mkdir ?? true,
47
+ symlink: options.symlink ?? false
48
+ };
49
+ }
50
+ function prettyTarget(options) {
51
+ return {
52
+ target: "pino-pretty",
53
+ options: {
54
+ colorize: options.colorize ?? true
55
+ }
56
+ };
57
+ }
58
+ function rollTarget(options) {
59
+ const roll = resolveRoll(options);
60
+ return {
61
+ target: "pino-roll",
62
+ options: {
63
+ file: roll.file,
64
+ mkdir: roll.mkdir,
65
+ size: roll.size,
66
+ frequency: roll.frequency,
67
+ limit: {
68
+ count: roll.keep
69
+ },
70
+ symlink: roll.symlink
71
+ }
72
+ };
73
+ }
74
+ function transport(plan, environment = currentEnvironment()) {
75
+ const targets = [];
76
+ if (plan.pretty && isEnabled(plan.pretty.when, environment)) {
77
+ targets.push(prettyTarget(plan.pretty));
78
+ }
79
+ if (plan.roll && isEnabled(plan.roll.when, environment)) {
80
+ targets.push(rollTarget(plan.roll));
81
+ }
82
+ if (targets.length === 0) {
83
+ return undefined;
84
+ }
85
+ if (targets.length === 1) {
86
+ return targets[0];
87
+ }
88
+ return {
89
+ targets
90
+ };
91
+ }
92
+ export const pinoRecipe = {
93
+ transport,
94
+ currentEnvironment,
95
+ resolveRoll
96
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Wrap a pino worker transport so a dead ThreadStream cannot spam or crash.
3
+ * On first error / write throw: report once, destroy, no-op further writes.
4
+ */ export function guardTransport(transport) {
5
+ const stream = transport;
6
+ let retired = false;
7
+ let reported = false;
8
+ const retire = (reason = "retired")=>{
9
+ if (retired) {
10
+ return;
11
+ }
12
+ retired = true;
13
+ if (!reported) {
14
+ reported = true;
15
+ process.stderr.write(`[scribe-pino] transport retired: ${reason}\n`);
16
+ }
17
+ if (typeof stream.destroy === "function") {
18
+ try {
19
+ stream.destroy();
20
+ } catch {
21
+ // already dead
22
+ }
23
+ }
24
+ };
25
+ if (typeof stream.on === "function") {
26
+ stream.on("error", (err)=>{
27
+ retire(err?.message ?? String(err));
28
+ });
29
+ }
30
+ if (typeof stream.write === "function") {
31
+ const originalWrite = stream.write.bind(stream);
32
+ stream.write = (chunk, encodingOrCb, cb)=>{
33
+ if (retired) {
34
+ completeWrite(encodingOrCb, cb);
35
+ return true;
36
+ }
37
+ try {
38
+ return originalWrite(chunk, encodingOrCb, cb);
39
+ } catch (err) {
40
+ retire(err instanceof Error ? err.message : String(err));
41
+ completeWrite(encodingOrCb, cb);
42
+ return true;
43
+ }
44
+ };
45
+ }
46
+ Object.defineProperty(stream, "retired", {
47
+ get: ()=>retired,
48
+ enumerable: true
49
+ });
50
+ Object.defineProperty(stream, "retire", {
51
+ value: retire,
52
+ enumerable: true
53
+ });
54
+ return stream;
55
+ }
56
+ function completeWrite(encodingOrCb, cb) {
57
+ const done = typeof encodingOrCb === "function" ? encodingOrCb : typeof cb === "function" ? cb : undefined;
58
+ if (typeof done === "function") {
59
+ done();
60
+ }
61
+ }
@@ -7,33 +7,42 @@ function _ts_decorate(decorators, target, key, desc) {
7
7
  function _ts_metadata(k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  }
10
- import { extension } from "@decohere/nexus/extensibility";
11
- import { DefaultEnvironment } from "@decohere/nexus/system";
12
- import { DefaultLogLevel, LoggingConfigurationError, scribe } from "@decohere/scribe";
10
+ import { extension } from "@decohere/core/extensibility";
11
+ import { DefaultEnvironment } from "@decohere/core/system";
12
+ import { LoggingConfigurationError, scribe } from "@decohere/scribe";
13
+ import pino from "pino";
13
14
  import { PinoAdapter } from "./pino.adapater.js";
15
+ import { pinoRecipe } from "./pino.recipe.js";
16
+ import { guardTransport } from "./pino.transport-guard.js";
17
+ export { guardTransport } from "./pino.transport-guard.js";
14
18
  export class PinoExtensions {
15
19
  static withPino(factory, config, logLevel) {
16
- return configureScribe(factory, {
20
+ return configureScribe(factory, logLevel != null ? {
17
21
  logLevel
18
- }, config);
22
+ } : undefined, config);
19
23
  }
20
- static withPinoPretty(factory, logLevel) {
21
- return PinoExtensions.withPino(factory, {
22
- transports: {
23
- target: "pino-pretty",
24
- options: {
25
- colorize: true
26
- }
27
- }
28
- }, logLevel);
24
+ static withPinoPretty(factory, logLevelOrOptions) {
25
+ const pretty = parsePrettyArg(logLevelOrOptions);
26
+ return attachRecipe(factory, {
27
+ pretty,
28
+ logLevel: pretty.logLevel
29
+ });
30
+ }
31
+ static withPinoRoll(factory, options) {
32
+ return attachRecipe(factory, {
33
+ roll: options,
34
+ logLevel: options.logLevel
35
+ });
29
36
  }
30
37
  static withPinoCustom(factory, options) {
31
- const { scribe, transports } = options;
38
+ const { scribe, transports } = options ?? {};
32
39
  return configureScribe(factory, scribe, transports);
33
40
  }
34
41
  }
35
42
  _ts_decorate([
36
- extension(scribe),
43
+ extension(scribe, {
44
+ static: true
45
+ }),
37
46
  _ts_metadata("design:type", Function),
38
47
  _ts_metadata("design:paramtypes", [
39
48
  typeof scribe === "undefined" ? Object : scribe,
@@ -43,7 +52,9 @@ _ts_decorate([
43
52
  _ts_metadata("design:returntype", void 0)
44
53
  ], PinoExtensions, "withPino", null);
45
54
  _ts_decorate([
46
- extension(scribe),
55
+ extension(scribe, {
56
+ static: true
57
+ }),
47
58
  _ts_metadata("design:type", Function),
48
59
  _ts_metadata("design:paramtypes", [
49
60
  typeof scribe === "undefined" ? Object : scribe,
@@ -52,7 +63,20 @@ _ts_decorate([
52
63
  _ts_metadata("design:returntype", void 0)
53
64
  ], PinoExtensions, "withPinoPretty", null);
54
65
  _ts_decorate([
55
- extension(scribe),
66
+ extension(scribe, {
67
+ static: true
68
+ }),
69
+ _ts_metadata("design:type", Function),
70
+ _ts_metadata("design:paramtypes", [
71
+ typeof scribe === "undefined" ? Object : scribe,
72
+ typeof PinoRollRecipeOptions === "undefined" ? Object : PinoRollRecipeOptions
73
+ ]),
74
+ _ts_metadata("design:returntype", void 0)
75
+ ], PinoExtensions, "withPinoRoll", null);
76
+ _ts_decorate([
77
+ extension(scribe, {
78
+ static: true
79
+ }),
56
80
  _ts_metadata("design:type", Function),
57
81
  _ts_metadata("design:paramtypes", [
58
82
  typeof scribe === "undefined" ? Object : scribe,
@@ -60,26 +84,85 @@ _ts_decorate([
60
84
  ]),
61
85
  _ts_metadata("design:returntype", void 0)
62
86
  ], PinoExtensions, "withPinoCustom", null);
87
+ function parsePrettyArg(logLevelOrOptions) {
88
+ if (logLevelOrOptions == null) {
89
+ return {};
90
+ }
91
+ if (typeof logLevelOrOptions === "string") {
92
+ return {
93
+ logLevel: logLevelOrOptions
94
+ };
95
+ }
96
+ return logLevelOrOptions;
97
+ }
98
+ function attachRecipe(factory, plan) {
99
+ const loggerFactory = applyRecipe(factory, plan);
100
+ const chain = {
101
+ withPinoPretty (logLevelOrOptions) {
102
+ const pretty = parsePrettyArg(logLevelOrOptions);
103
+ return attachRecipe(factory, {
104
+ ...plan,
105
+ pretty: {
106
+ ...plan.pretty,
107
+ ...pretty
108
+ },
109
+ logLevel: pretty.logLevel ?? plan.logLevel
110
+ });
111
+ },
112
+ withPinoRoll (options) {
113
+ return attachRecipe(factory, {
114
+ ...plan,
115
+ roll: options,
116
+ logLevel: options.logLevel ?? plan.logLevel
117
+ });
118
+ }
119
+ };
120
+ return Object.assign(loggerFactory, chain, {
121
+ and: chain
122
+ });
123
+ }
124
+ /**
125
+ * Guard a worker transport so failures (roll EEXIST, worker exit) neither
126
+ * crash the process nor spam stderr on every subsequent log write.
127
+ */ function createSafeTransport(options) {
128
+ return guardTransport(pino.transport(options));
129
+ }
130
+ function adapterForTransport(transport) {
131
+ if (transport == null) {
132
+ return new PinoAdapter({});
133
+ }
134
+ return new PinoAdapter({}, createSafeTransport(transport));
135
+ }
136
+ function applyRecipe(factory, plan) {
137
+ const adapter = adapterForTransport(pinoRecipe.transport(plan));
138
+ // Omit logLevel when unset so mergeDefaults can read LOG_LEVEL / SCRIBE_LOG_LEVEL.
139
+ return factory.configure({
140
+ options: plan.logLevel != null ? {
141
+ logLevel: plan.logLevel
142
+ } : {},
143
+ adapter
144
+ });
145
+ }
63
146
  function configureScribe(factory, options, config) {
64
147
  const environment = process.env.NODE_ENV ?? DefaultEnvironment;
65
- const configs = Array.isArray(config) ? config : [
148
+ const configs = (Array.isArray(config) ? config : config != null ? [
66
149
  config
67
- ];
68
- const transports = configs.filter((config)=>config.environment && config.environment === environment || true);
69
- if (transports.length > 1) {
150
+ ] : []).filter((item)=>item.environment == null || item.environment === environment);
151
+ if (configs.length > 1) {
70
152
  throw new LoggingConfigurationError(`There should only be one configuration per environment for logging`);
71
153
  }
72
- const transport = transports.at(0)?.transports;
73
- const adapter = new PinoAdapter({
74
- transport
75
- });
154
+ const adapter = adapterForTransport(configs.at(0)?.transports);
155
+ // Do not force DefaultLogLevel — that would shadow env resolution in mergeDefaults.
76
156
  return factory.configure({
77
- options: {
78
- ...options,
79
- logLevel: options?.logLevel ?? DefaultLogLevel
80
- },
157
+ options: options ?? {},
81
158
  adapter
82
159
  });
83
160
  }
84
-
85
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvc2NyaWJlLXBpbm8udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXh0ZW5zaW9uIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9leHRlbnNpYmlsaXR5XCI7XG5pbXBvcnQgeyBEZWZhdWx0RW52aXJvbm1lbnQsIHR5cGUgRW52aXJvbm1lbnQgfSBmcm9tIFwiQGRlY29oZXJlL25leHVzL3N5c3RlbVwiO1xuaW1wb3J0IHtcblx0dHlwZSBEZWZhdWx0TGV2ZWxzLFxuXHREZWZhdWx0TG9nTGV2ZWwsXG5cdHR5cGUgTG9nZ2VyLFxuXHRMb2dnaW5nQ29uZmlndXJhdGlvbkVycm9yLFxuXHR0eXBlIFNjcmliZU9wdGlvbnMsXG5cdHNjcmliZSxcbn0gZnJvbSBcIkBkZWNvaGVyZS9zY3JpYmVcIjtcbmltcG9ydCB0eXBlIHtcblx0VHJhbnNwb3J0TXVsdGlPcHRpb25zLFxuXHRUcmFuc3BvcnRQaXBlbGluZU9wdGlvbnMsXG5cdFRyYW5zcG9ydFNpbmdsZU9wdGlvbnMsXG59IGZyb20gXCJwaW5vXCI7XG5cbmltcG9ydCB7IFBpbm9BZGFwdGVyIH0gZnJvbSBcIi4vcGluby5hZGFwYXRlci5qc1wiO1xuXG50eXBlIFRyYW5zcG9ydENvbmZpZyA9IHtcblx0ZW52aXJvbm1lbnQ/OiBFbnZpcm9ubWVudDtcblx0dHJhbnNwb3J0czogVHJhbnNwb3J0U2luZ2xlT3B0aW9ucyB8IFRyYW5zcG9ydE11bHRpT3B0aW9ucyB8IFRyYW5zcG9ydFBpcGVsaW5lT3B0aW9ucztcbn07XG5cbnR5cGUgQ3VzdG9tTGV2ZWxPcHRpb25zPFQgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlciwgQ3VzdG9tT25seSBleHRlbmRzIHRydWUgPSB1bmRlZmluZWQ+ID0ge1xuXHRzY3JpYmU/OiBTY3JpYmVPcHRpb25zPFQsIEN1c3RvbU9ubHk+O1xuXHR0cmFuc3BvcnRzPzogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW107XG59O1xuXG5kZWNsYXJlIG1vZHVsZSBcIkBkZWNvaGVyZS9zY3JpYmVcIiB7XG5cdGludGVyZmFjZSBzY3JpYmUge1xuXHRcdHdpdGhQaW5vKFxuXHRcdFx0dHJhbnNwb3J0czogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW10sXG5cdFx0XHRsb2dsZXZlbD86IERlZmF1bHRMZXZlbHMgfCBzdHJpbmcsXG5cdFx0KTogKG5hbWU/OiBzdHJpbmcpID0+IExvZ2dlcjtcblx0XHR3aXRoUGlub1ByZXR0eShsb2dMZXZlbD86IERlZmF1bHRMZXZlbHMgfCBzdHJpbmcpOiAobmFtZT86IHN0cmluZykgPT4gTG9nZ2VyO1xuXHRcdHdpdGhQaW5vQ3VzdG9tPFQgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlciwgQ3VzdG9tT25seSBleHRlbmRzIHRydWUgPSB1bmRlZmluZWQ+KFxuXHRcdFx0b3B0aW9ucz86IEN1c3RvbUxldmVsT3B0aW9uczxULCBDdXN0b21Pbmx5Pixcblx0XHQpOiAobmFtZT86IHN0cmluZykgPT4gTG9nZ2VyPFQsIEN1c3RvbU9ubHk+O1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBQaW5vRXh0ZW5zaW9ucyB7XG5cdEBleHRlbnNpb24oc2NyaWJlKVxuXHRwdWJsaWMgc3RhdGljIHdpdGhQaW5vKFxuXHRcdGZhY3Rvcnk6IHNjcmliZSxcblx0XHRjb25maWc6IFRyYW5zcG9ydENvbmZpZyB8IFRyYW5zcG9ydENvbmZpZ1tdLFxuXHRcdGxvZ0xldmVsPzogRGVmYXVsdExldmVscyB8IHN0cmluZyxcblx0KSB7XG5cdFx0cmV0dXJuIGNvbmZpZ3VyZVNjcmliZShmYWN0b3J5LCB7IGxvZ0xldmVsIH0sIGNvbmZpZyk7XG5cdH1cblxuXHRAZXh0ZW5zaW9uKHNjcmliZSlcblx0cHVibGljIHN0YXRpYyB3aXRoUGlub1ByZXR0eShmYWN0b3J5OiBzY3JpYmUsIGxvZ0xldmVsPzogRGVmYXVsdExldmVscyB8IHN0cmluZykge1xuXHRcdHJldHVybiBQaW5vRXh0ZW5zaW9ucy53aXRoUGlubyhcblx0XHRcdGZhY3RvcnksXG5cdFx0XHR7IHRyYW5zcG9ydHM6IHsgdGFyZ2V0OiBcInBpbm8tcHJldHR5XCIsIG9wdGlvbnM6IHsgY29sb3JpemU6IHRydWUgfSB9IH0sXG5cdFx0XHRsb2dMZXZlbCxcblx0XHQpO1xuXHR9XG5cblx0QGV4dGVuc2lvbihzY3JpYmUpXG5cdHB1YmxpYyBzdGF0aWMgd2l0aFBpbm9DdXN0b208VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSA9IHVuZGVmaW5lZD4oXG5cdFx0ZmFjdG9yeTogc2NyaWJlLFxuXHRcdG9wdGlvbnM/OiBDdXN0b21MZXZlbE9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdCkge1xuXHRcdGNvbnN0IHsgc2NyaWJlLCB0cmFuc3BvcnRzIH0gPSBvcHRpb25zO1xuXHRcdHJldHVybiBjb25maWd1cmVTY3JpYmUoZmFjdG9yeSwgc2NyaWJlLCB0cmFuc3BvcnRzKTtcblx0fVxufVxuXG5mdW5jdGlvbiBjb25maWd1cmVTY3JpYmU8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRmYWN0b3J5OiBzY3JpYmUsXG5cdG9wdGlvbnM6IFNjcmliZU9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdGNvbmZpZzogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW10sXG4pIHtcblx0Y29uc3QgZW52aXJvbm1lbnQgPSBwcm9jZXNzLmVudi5OT0RFX0VOViA/PyBEZWZhdWx0RW52aXJvbm1lbnQ7XG5cdGNvbnN0IGNvbmZpZ3MgPSBBcnJheS5pc0FycmF5KGNvbmZpZykgPyBjb25maWcgOiBbY29uZmlnXTtcblx0Y29uc3QgdHJhbnNwb3J0cyA9IGNvbmZpZ3MuZmlsdGVyKFxuXHRcdChjb25maWcpID0+IChjb25maWcuZW52aXJvbm1lbnQgJiYgY29uZmlnLmVudmlyb25tZW50ID09PSBlbnZpcm9ubWVudCkgfHwgdHJ1ZSxcblx0KTtcblxuXHRpZiAodHJhbnNwb3J0cy5sZW5ndGggPiAxKSB7XG5cdFx0dGhyb3cgbmV3IExvZ2dpbmdDb25maWd1cmF0aW9uRXJyb3IoXG5cdFx0XHRgVGhlcmUgc2hvdWxkIG9ubHkgYmUgb25lIGNvbmZpZ3VyYXRpb24gcGVyIGVudmlyb25tZW50IGZvciBsb2dnaW5nYCxcblx0XHQpO1xuXHR9XG5cblx0Y29uc3QgdHJhbnNwb3J0ID0gdHJhbnNwb3J0cy5hdCgwKT8udHJhbnNwb3J0cztcblx0Y29uc3QgYWRhcHRlciA9IG5ldyBQaW5vQWRhcHRlcih7IHRyYW5zcG9ydCB9KTtcblx0cmV0dXJuIGZhY3RvcnkuY29uZmlndXJlKHtcblx0XHRvcHRpb25zOiB7IC4uLm9wdGlvbnMsIGxvZ0xldmVsOiBvcHRpb25zPy5sb2dMZXZlbCA/PyBEZWZhdWx0TG9nTGV2ZWwgfSxcblx0XHRhZGFwdGVyLFxuXHR9KTtcbn1cbiJdLCJuYW1lcyI6WyJleHRlbnNpb24iLCJEZWZhdWx0RW52aXJvbm1lbnQiLCJEZWZhdWx0TG9nTGV2ZWwiLCJMb2dnaW5nQ29uZmlndXJhdGlvbkVycm9yIiwic2NyaWJlIiwiUGlub0FkYXB0ZXIiLCJQaW5vRXh0ZW5zaW9ucyIsIndpdGhQaW5vIiwiZmFjdG9yeSIsImNvbmZpZyIsImxvZ0xldmVsIiwiY29uZmlndXJlU2NyaWJlIiwid2l0aFBpbm9QcmV0dHkiLCJ0cmFuc3BvcnRzIiwidGFyZ2V0Iiwib3B0aW9ucyIsImNvbG9yaXplIiwid2l0aFBpbm9DdXN0b20iLCJlbnZpcm9ubWVudCIsInByb2Nlc3MiLCJlbnYiLCJOT0RFX0VOViIsImNvbmZpZ3MiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJsZW5ndGgiLCJ0cmFuc3BvcnQiLCJhdCIsImFkYXB0ZXIiLCJjb25maWd1cmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLFNBQVNBLFNBQVMsUUFBUSxnQ0FBZ0M7QUFDMUQsU0FBU0Msa0JBQWtCLFFBQTBCLHlCQUF5QjtBQUM5RSxTQUVDQyxlQUFlLEVBRWZDLHlCQUF5QixFQUV6QkMsTUFBTSxRQUNBLG1CQUFtQjtBQU8xQixTQUFTQyxXQUFXLFFBQVEscUJBQXFCO0FBeUJqRCxPQUFPLE1BQU1DO0lBQ1osT0FDY0MsU0FDYkMsT0FBZSxFQUNmQyxNQUEyQyxFQUMzQ0MsUUFBaUMsRUFDaEM7UUFDRCxPQUFPQyxnQkFBZ0JILFNBQVM7WUFBRUU7UUFBUyxHQUFHRDtJQUMvQztJQUVBLE9BQ2NHLGVBQWVKLE9BQWUsRUFBRUUsUUFBaUMsRUFBRTtRQUNoRixPQUFPSixlQUFlQyxRQUFRLENBQzdCQyxTQUNBO1lBQUVLLFlBQVk7Z0JBQUVDLFFBQVE7Z0JBQWVDLFNBQVM7b0JBQUVDLFVBQVU7Z0JBQUs7WUFBRTtRQUFFLEdBQ3JFTjtJQUVGO0lBRUEsT0FDY08sZUFDYlQsT0FBZSxFQUNmTyxPQUEyQyxFQUMxQztRQUNELE1BQU0sRUFBRVgsTUFBTSxFQUFFUyxVQUFVLEVBQUUsR0FBR0U7UUFDL0IsT0FBT0osZ0JBQWdCSCxTQUFTSixRQUFRUztJQUN6QztBQUNEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLFNBQVNGLGdCQUNSSCxPQUFlLEVBQ2ZPLE9BQXFDLEVBQ3JDTixNQUEyQztJQUUzQyxNQUFNUyxjQUFjQyxRQUFRQyxHQUFHLENBQUNDLFFBQVEsSUFBSXBCO0lBQzVDLE1BQU1xQixVQUFVQyxNQUFNQyxPQUFPLENBQUNmLFVBQVVBLFNBQVM7UUFBQ0E7S0FBTztJQUN6RCxNQUFNSSxhQUFhUyxRQUFRRyxNQUFNLENBQ2hDLENBQUNoQixTQUFXLEFBQUNBLE9BQU9TLFdBQVcsSUFBSVQsT0FBT1MsV0FBVyxLQUFLQSxlQUFnQjtJQUczRSxJQUFJTCxXQUFXYSxNQUFNLEdBQUcsR0FBRztRQUMxQixNQUFNLElBQUl2QiwwQkFDVCxDQUFDLGtFQUFrRSxDQUFDO0lBRXRFO0lBRUEsTUFBTXdCLFlBQVlkLFdBQVdlLEVBQUUsQ0FBQyxJQUFJZjtJQUNwQyxNQUFNZ0IsVUFBVSxJQUFJeEIsWUFBWTtRQUFFc0I7SUFBVTtJQUM1QyxPQUFPbkIsUUFBUXNCLFNBQVMsQ0FBQztRQUN4QmYsU0FBUztZQUFFLEdBQUdBLE9BQU87WUFBRUwsVUFBVUssU0FBU0wsWUFBWVI7UUFBZ0I7UUFDdEUyQjtJQUNEO0FBQ0QifQ==
161
+ /** @deprecated Use {@link guardTransport} — kept for callers/tests from the silence-only era. */ function silenceErrors(transport) {
162
+ return guardTransport(transport);
163
+ }
164
+ export const pinoTransport = {
165
+ createSafeTransport,
166
+ guardTransport,
167
+ silenceErrors
168
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/scribe-pino",
3
- "version": "0.0.1-dev.19",
3
+ "version": "0.0.1-dev.20261105.103",
4
4
  "description": "Pino adapter for @decohere/scribe",
5
5
  "keywords": [
6
6
  "typescript",
@@ -8,6 +8,15 @@
8
8
  "pino",
9
9
  "decohere"
10
10
  ],
11
+ "homepage": "https://github.com/typesmiths/decohere/tree/main/projects/scribe/scribe-pino#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/typesmiths/decohere/issues"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/typesmiths/decohere.git",
18
+ "directory": "projects/scribe/scribe-pino"
19
+ },
11
20
  "license": "ISC",
12
21
  "author": "Typesmiths",
13
22
  "type": "module",
@@ -15,17 +24,28 @@
15
24
  "exports": {
16
25
  ".": {
17
26
  "types": "./types/src/index.d.ts",
18
- "import": "./es6/src/index.js",
19
- "require": "./commonjs/src/index.js"
27
+ "import": "./es6/src/index.js"
20
28
  }
21
29
  },
22
30
  "scripts": {
23
31
  "test": "echo \"Error: no test specified\" && exit 1"
24
32
  },
25
33
  "dependencies": {
26
- "@decohere/nexus": "0.0.1-dev.19",
27
- "@decohere/scribe": "0.0.1-dev.19",
34
+ "@decohere/core": "0.0.1-dev.20261105.103",
35
+ "@decohere/scribe": "0.0.1-dev.20261105.103",
28
36
  "pino": "^10.3.0"
29
37
  },
30
- "devDependencies": {}
38
+ "devDependencies": {},
39
+ "peerDependencies": {
40
+ "pino-pretty": "^13.1.3",
41
+ "pino-roll": "^4.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "pino-pretty": {
45
+ "optional": true
46
+ },
47
+ "pino-roll": {
48
+ "optional": true
49
+ }
50
+ }
31
51
  }
@@ -1,2 +1,3 @@
1
1
  export * from "./pino.adapater.js";
2
+ export * from "./pino.recipe.js";
2
3
  export * from "./scribe-pino.js";
@@ -8,8 +8,16 @@ export declare class PinoAdapter extends LogAdapter {
8
8
  private _pino;
9
9
  private readonly options;
10
10
  private readonly stream;
11
+ private disposed;
12
+ private retired;
11
13
  constructor(options: pino.LoggerOptions, stream?: pino.DestinationStream);
12
14
  configure<T extends string = never, CustomOnly extends true | false = false>(scribeOptions: ScribeOptions<T, CustomOnly>): void;
13
15
  getLogger<T extends string = never, CustomOnly extends true | false = false>(name: string): Logger<T, CustomOnly>;
14
16
  flush(cb?: () => void): void;
17
+ /**
18
+ * Immediately stop accepting writes into the destination (ThreadStream).
19
+ * Does not wait for flush — use `stop()` for async drain after retire.
20
+ */
21
+ retire(): void;
22
+ [Symbol.asyncDispose](): Promise<void>;
15
23
  }
@@ -0,0 +1,45 @@
1
+ import { type Environment } from "@decohere/core/system";
2
+ import type { TransportMultiOptions, TransportSingleOptions } from "pino";
3
+ /** Pretty and roll are local-dev conveniences. Production ships JSON on stdout. */
4
+ export type PinoWhen = "development" | "always";
5
+ export type PinoPrettyRecipeOptions = {
6
+ colorize?: boolean;
7
+ logLevel?: string;
8
+ when?: PinoWhen;
9
+ };
10
+ export type PinoRollRecipeOptions = {
11
+ /** Default roll path. Overridden at runtime by `SCRIBE_LOG_FILE` when set. */
12
+ file: string;
13
+ size?: string;
14
+ frequency?: string | number;
15
+ keep?: number;
16
+ mkdir?: boolean;
17
+ symlink?: boolean;
18
+ logLevel?: string;
19
+ when?: PinoWhen;
20
+ };
21
+ export type PinoRecipePlan = {
22
+ pretty?: PinoPrettyRecipeOptions;
23
+ roll?: PinoRollRecipeOptions;
24
+ logLevel?: string;
25
+ };
26
+ declare function currentEnvironment(): Environment;
27
+ /**
28
+ * Resolve roll options. `SCRIBE_LOG_FILE` overrides `file` so ops can redirect
29
+ * without touching app code. Size / frequency / keep: explicit > env > default.
30
+ */
31
+ declare function resolveRoll(options: PinoRollRecipeOptions): {
32
+ file: string;
33
+ size: string;
34
+ frequency: string | number;
35
+ keep: number;
36
+ mkdir: boolean;
37
+ symlink: boolean;
38
+ };
39
+ declare function transport(plan: PinoRecipePlan, environment?: Environment): TransportSingleOptions | TransportMultiOptions | undefined;
40
+ export declare const pinoRecipe: {
41
+ transport: typeof transport;
42
+ currentEnvironment: typeof currentEnvironment;
43
+ resolveRoll: typeof resolveRoll;
44
+ };
45
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { DestinationStream } from "pino";
2
+ export type GuardedTransport = DestinationStream & {
3
+ readonly retired: boolean;
4
+ retire(reason?: string): void;
5
+ };
6
+ /**
7
+ * Wrap a pino worker transport so a dead ThreadStream cannot spam or crash.
8
+ * On first error / write throw: report once, destroy, no-op further writes.
9
+ */
10
+ export declare function guardTransport(transport: DestinationStream): GuardedTransport;
@@ -1,24 +1,72 @@
1
- import { type Environment } from "@decohere/nexus/system";
1
+ import { type Environment } from "@decohere/core/system";
2
2
  import { type DefaultLevels, type Logger, type ScribeOptions, scribe } from "@decohere/scribe";
3
- import type { TransportMultiOptions, TransportPipelineOptions, TransportSingleOptions } from "pino";
3
+ import { type DestinationStream, type TransportMultiOptions, type TransportPipelineOptions, type TransportSingleOptions } from "pino";
4
+ import { type PinoPrettyRecipeOptions, type PinoRollRecipeOptions } from "./pino.recipe.js";
5
+ import { type GuardedTransport, guardTransport } from "./pino.transport-guard.js";
6
+ export type { GuardedTransport } from "./pino.transport-guard.js";
7
+ export { guardTransport } from "./pino.transport-guard.js";
8
+ type TransportOptions = TransportSingleOptions | TransportMultiOptions | TransportPipelineOptions;
4
9
  type TransportConfig = {
5
10
  environment?: Environment;
6
- transports: TransportSingleOptions | TransportMultiOptions | TransportPipelineOptions;
11
+ transports: TransportOptions;
7
12
  };
8
13
  type CustomLevelOptions<T extends string = never, CustomOnly extends true = undefined> = {
9
14
  scribe?: ScribeOptions<T, CustomOnly>;
10
15
  transports?: TransportConfig | TransportConfig[];
11
16
  };
17
+ export type PinoLoggerFactory = (name?: string) => Logger;
18
+ export type PinoRecipeChain = {
19
+ withPinoPretty(logLevelOrOptions?: DefaultLevels | string | PinoPrettyRecipeOptions): PinoRecipe;
20
+ withPinoRoll(options: PinoRollRecipeOptions): PinoRecipe;
21
+ };
22
+ export type PinoRecipe = PinoLoggerFactory & PinoRecipeChain & {
23
+ readonly and: PinoRecipeChain;
24
+ };
12
25
  declare module "@decohere/scribe" {
13
26
  interface scribe {
14
- withPino(transports: TransportConfig | TransportConfig[], loglevel?: DefaultLevels | string): (name?: string) => Logger;
15
- withPinoPretty(logLevel?: DefaultLevels | string): (name?: string) => Logger;
16
- withPinoCustom<T extends string = never, CustomOnly extends true = undefined>(options?: CustomLevelOptions<T, CustomOnly>): (name?: string) => Logger<T, CustomOnly>;
27
+ withPino(transports: TransportConfig | TransportConfig[], loglevel?: DefaultLevels | string): PinoLoggerFactory;
28
+ /**
29
+ * Colorized pretty transport. Development only unless `{ when: "always" }`.
30
+ * Chain with `.and.withPinoRoll({ file })`. Production writes JSON to stdout
31
+ * so log shipping stays outside the process.
32
+ */
33
+ withPinoPretty(logLevelOrOptions?: DefaultLevels | string | PinoPrettyRecipeOptions): PinoRecipe;
34
+ /**
35
+ * Rolling log files. Development only unless `{ when: "always" }`.
36
+ * Do not enable in production — ship stdout from a sidecar or platform agent.
37
+ * `symlink` defaults off; enabling it can race under multi-worker / HMR.
38
+ * Ops may override path/size/frequency/keep via `SCRIBE_LOG_FILE`,
39
+ * `SCRIBE_LOG_SIZE`, `SCRIBE_LOG_FREQUENCY`, and `SCRIBE_LOG_KEEP`
40
+ * (file env wins over `options.file`; other explicit options beat env).
41
+ */
42
+ withPinoRoll(options: PinoRollRecipeOptions): PinoRecipe;
43
+ withPinoCustom<T extends string = never, CustomOnly extends true = undefined>(options?: CustomLevelOptions<T, CustomOnly>): PinoLoggerFactory;
44
+ }
45
+ namespace scribe {
46
+ function withPino(transports: TransportConfig | TransportConfig[], loglevel?: DefaultLevels | string): PinoLoggerFactory;
47
+ function withPinoPretty(logLevelOrOptions?: DefaultLevels | string | PinoPrettyRecipeOptions): PinoRecipe;
48
+ function withPinoRoll(options: PinoRollRecipeOptions): PinoRecipe;
49
+ function withPinoCustom<T extends string = never, CustomOnly extends true = undefined>(options?: CustomLevelOptions<T, CustomOnly>): PinoLoggerFactory;
17
50
  }
18
51
  }
19
52
  export declare class PinoExtensions {
20
53
  static withPino(factory: scribe, config: TransportConfig | TransportConfig[], logLevel?: DefaultLevels | string): (name?: string) => Logger<never, false>;
21
- static withPinoPretty(factory: scribe, logLevel?: DefaultLevels | string): (name?: string) => Logger<never, false>;
54
+ static withPinoPretty(factory: scribe, logLevelOrOptions?: DefaultLevels | string | PinoPrettyRecipeOptions): PinoRecipe;
55
+ static withPinoRoll(factory: scribe, options: PinoRollRecipeOptions): PinoRecipe;
22
56
  static withPinoCustom<T extends string = never, CustomOnly extends true = undefined>(factory: scribe, options?: CustomLevelOptions<T, CustomOnly>): (name?: string) => Logger<T, CustomOnly>;
23
57
  }
24
- export {};
58
+ /**
59
+ * Guard a worker transport so failures (roll EEXIST, worker exit) neither
60
+ * crash the process nor spam stderr on every subsequent log write.
61
+ */
62
+ declare function createSafeTransport(options: TransportOptions): DestinationStream;
63
+ /** @deprecated Use {@link guardTransport} — kept for callers/tests from the silence-only era. */
64
+ declare function silenceErrors(transport: {
65
+ on(event: "error", listener: (err: Error) => void): unknown;
66
+ write?: (...args: never[]) => unknown;
67
+ }): GuardedTransport;
68
+ export declare const pinoTransport: {
69
+ createSafeTransport: typeof createSafeTransport;
70
+ guardTransport: typeof guardTransport;
71
+ silenceErrors: typeof silenceErrors;
72
+ };
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- _export_star(require("./pino.adapater.js"), exports);
6
- _export_star(require("./scribe-pino.js"), exports);
7
- function _export_star(from, to) {
8
- Object.keys(from).forEach(function(k) {
9
- if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
10
- Object.defineProperty(to, k, {
11
- enumerable: true,
12
- get: function() {
13
- return from[k];
14
- }
15
- });
16
- }
17
- });
18
- return from;
19
- }
20
-
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSBcIi4vcGluby5hZGFwYXRlci5qc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vc2NyaWJlLXBpbm8uanNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O3FCQUFjO3FCQUNBIn0=
@@ -1,94 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "PinoAdapter", {
6
- enumerable: true,
7
- get: function() {
8
- return PinoAdapter;
9
- }
10
- });
11
- const _scribe = require("@decohere/scribe");
12
- const _pino = /*#__PURE__*/ _interop_require_default(require("pino"));
13
- function _interop_require_default(obj) {
14
- return obj && obj.__esModule ? obj : {
15
- default: obj
16
- };
17
- }
18
- class PinoAdapter extends _scribe.LogAdapter {
19
- _pino;
20
- options;
21
- stream;
22
- constructor(options, stream){
23
- super();
24
- this.options = options;
25
- this.stream = stream;
26
- }
27
- configure(scribeOptions) {
28
- const { logLevel, redactions } = scribeOptions;
29
- const customLevels = this.getLogLevels(scribeOptions);
30
- const pinoOptions = {
31
- customLevels,
32
- level: logLevel,
33
- hooks: {
34
- logMethod
35
- },
36
- serializers: {
37
- error: _pino.default.stdSerializers.err
38
- },
39
- redact: redactions,
40
- ...this.options
41
- };
42
- this._pino = (0, _pino.default)(pinoOptions, this.stream);
43
- }
44
- getLogger(name) {
45
- const logger = pinoMix(this._pino.child({
46
- name
47
- }));
48
- return logger;
49
- }
50
- flush(cb) {
51
- this._pino.flush(cb);
52
- }
53
- }
54
- function logMethod(args, method) {
55
- let message = args.at(0);
56
- const data = args.at(1);
57
- if (message instanceof Error) {
58
- method.call(this, {
59
- err: message
60
- }, (0, _scribe.formatError)(message));
61
- return;
62
- }
63
- if (data instanceof Error) {
64
- message = {
65
- msg: message,
66
- ...{
67
- error: data
68
- }
69
- };
70
- } else if (typeof data === "object") {
71
- message = {
72
- msg: message,
73
- ...data
74
- };
75
- } else {
76
- message = {
77
- msg: message,
78
- data
79
- };
80
- }
81
- method.call(this, message);
82
- }
83
- function pinoMix(logger) {
84
- return Object.assign(logger, {
85
- get currentLevel () {
86
- return logger.level;
87
- },
88
- get logLevels () {
89
- return logger.levels.values;
90
- }
91
- });
92
- }
93
-
94
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvcGluby5hZGFwYXRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHR0eXBlIEJhc2VMb2dnZXIsXG5cdGZvcm1hdEVycm9yLFxuXHRMb2dBZGFwdGVyLFxuXHR0eXBlIExvZ2dlcixcblx0dHlwZSBTY3JpYmVPcHRpb25zLFxufSBmcm9tIFwiQGRlY29oZXJlL3NjcmliZVwiO1xuaW1wb3J0IHBpbm8sIHsgdHlwZSBMb2dGbiB9IGZyb20gXCJwaW5vXCI7XG5cbmV4cG9ydCB0eXBlIFBpbm9BZGFwYXRlck9wdGlvbnMgPSB7XG5cdG9wdGlvbnM/OiBwaW5vLkxvZ2dlck9wdGlvbnM7XG5cdHN0cmVhbT86IHBpbm8uRGVzdGluYXRpb25TdHJlYW07XG59O1xuXG5leHBvcnQgY2xhc3MgUGlub0FkYXB0ZXIgZXh0ZW5kcyBMb2dBZGFwdGVyIHtcblx0cHJpdmF0ZSBfcGlubzogcGluby5Mb2dnZXI7XG5cdHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogcGluby5Mb2dnZXJPcHRpb25zO1xuXHRwcml2YXRlIHJlYWRvbmx5IHN0cmVhbTogcGluby5EZXN0aW5hdGlvblN0cmVhbTtcblx0cHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IHBpbm8uTG9nZ2VyT3B0aW9ucywgc3RyZWFtPzogcGluby5EZXN0aW5hdGlvblN0cmVhbSkge1xuXHRcdHN1cGVyKCk7XG5cdFx0dGhpcy5vcHRpb25zID0gb3B0aW9ucztcblx0XHR0aGlzLnN0cmVhbSA9IHN0cmVhbTtcblx0fVxuXG5cdHB1YmxpYyBjb25maWd1cmU8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRcdHNjcmliZU9wdGlvbnM6IFNjcmliZU9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdCkge1xuXHRcdGNvbnN0IHsgbG9nTGV2ZWwsIHJlZGFjdGlvbnMgfSA9IHNjcmliZU9wdGlvbnM7XG5cdFx0Y29uc3QgY3VzdG9tTGV2ZWxzID0gdGhpcy5nZXRMb2dMZXZlbHMoc2NyaWJlT3B0aW9ucyk7XG5cblx0XHRjb25zdCBwaW5vT3B0aW9uczogcGluby5Mb2dnZXJPcHRpb25zID0ge1xuXHRcdFx0Y3VzdG9tTGV2ZWxzLFxuXHRcdFx0bGV2ZWw6IGxvZ0xldmVsLFxuXHRcdFx0aG9va3M6IHsgbG9nTWV0aG9kIH0sXG5cdFx0XHRzZXJpYWxpemVyczoge1xuXHRcdFx0XHRlcnJvcjogcGluby5zdGRTZXJpYWxpemVycy5lcnIsXG5cdFx0XHR9LFxuXHRcdFx0cmVkYWN0OiByZWRhY3Rpb25zLFxuXHRcdFx0Li4udGhpcy5vcHRpb25zLFxuXHRcdH07XG5cdFx0dGhpcy5fcGlubyA9IHBpbm8ocGlub09wdGlvbnMsIHRoaXMuc3RyZWFtKTtcblx0fVxuXG5cdHB1YmxpYyBnZXRMb2dnZXI8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRcdG5hbWU6IHN0cmluZyxcblx0KTogTG9nZ2VyPFQsIEN1c3RvbU9ubHk+IHtcblx0XHRjb25zdCBsb2dnZXIgPSBwaW5vTWl4PFQsIEN1c3RvbU9ubHk+KHRoaXMuX3Bpbm8uY2hpbGQoeyBuYW1lIH0pKTtcblx0XHRyZXR1cm4gbG9nZ2VyO1xuXHR9XG5cblx0cHVibGljIGZsdXNoKGNiPzogKCkgPT4gdm9pZCk6IHZvaWQge1xuXHRcdHRoaXMuX3Bpbm8uZmx1c2goY2IpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGxvZ01ldGhvZCh0aGlzOiBwaW5vLkxvZ2dlciwgYXJnczogUGFyYW1ldGVyczxMb2dGbj4sIG1ldGhvZDogTG9nRm4pIHtcblx0bGV0IG1lc3NhZ2UgPSBhcmdzLmF0KDApO1xuXHRjb25zdCBkYXRhID0gYXJncy5hdCgxKTtcblxuXHRpZiAobWVzc2FnZSBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0bWV0aG9kLmNhbGwodGhpcywgeyBlcnI6IG1lc3NhZ2UgfSwgZm9ybWF0RXJyb3IobWVzc2FnZSkpO1xuXHRcdHJldHVybjtcblx0fVxuXG5cdGlmIChkYXRhIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRtZXNzYWdlID0geyBtc2c6IG1lc3NhZ2UsIC4uLnsgZXJyb3I6IGRhdGEgfSB9O1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSBcIm9iamVjdFwiKSB7XG5cdFx0bWVzc2FnZSA9IHsgbXNnOiBtZXNzYWdlLCAuLi5kYXRhIH07XG5cdH0gZWxzZSB7XG5cdFx0bWVzc2FnZSA9IHsgbXNnOiBtZXNzYWdlLCBkYXRhIH07XG5cdH1cblxuXHRtZXRob2QuY2FsbCh0aGlzLCBtZXNzYWdlKTtcbn1cblxuZnVuY3Rpb24gcGlub01peDxUIGV4dGVuZHMgc3RyaW5nID0gbmV2ZXIsIEN1c3RvbU9ubHkgZXh0ZW5kcyB0cnVlIHwgZmFsc2UgPSBmYWxzZT4oXG5cdGxvZ2dlcjogcGluby5Mb2dnZXIsXG4pOiBMb2dnZXI8VCwgQ3VzdG9tT25seT4ge1xuXHRyZXR1cm4gT2JqZWN0LmFzc2lnbjxwaW5vLkxvZ2dlciwgQmFzZUxvZ2dlcj4obG9nZ2VyLCB7XG5cdFx0Z2V0IGN1cnJlbnRMZXZlbCgpIHtcblx0XHRcdHJldHVybiBsb2dnZXIubGV2ZWw7XG5cdFx0fSxcblx0XHRnZXQgbG9nTGV2ZWxzKCkge1xuXHRcdFx0cmV0dXJuIGxvZ2dlci5sZXZlbHMudmFsdWVzO1xuXHRcdH0sXG5cdH0pIGFzIExvZ2dlcjxULCBDdXN0b21Pbmx5Pjtcbn1cbiJdLCJuYW1lcyI6WyJQaW5vQWRhcHRlciIsIkxvZ0FkYXB0ZXIiLCJfcGlubyIsIm9wdGlvbnMiLCJzdHJlYW0iLCJjb25maWd1cmUiLCJzY3JpYmVPcHRpb25zIiwibG9nTGV2ZWwiLCJyZWRhY3Rpb25zIiwiY3VzdG9tTGV2ZWxzIiwiZ2V0TG9nTGV2ZWxzIiwicGlub09wdGlvbnMiLCJsZXZlbCIsImhvb2tzIiwibG9nTWV0aG9kIiwic2VyaWFsaXplcnMiLCJlcnJvciIsInBpbm8iLCJzdGRTZXJpYWxpemVycyIsImVyciIsInJlZGFjdCIsImdldExvZ2dlciIsIm5hbWUiLCJsb2dnZXIiLCJwaW5vTWl4IiwiY2hpbGQiLCJmbHVzaCIsImNiIiwiYXJncyIsIm1ldGhvZCIsIm1lc3NhZ2UiLCJhdCIsImRhdGEiLCJFcnJvciIsImNhbGwiLCJmb3JtYXRFcnJvciIsIm1zZyIsIk9iamVjdCIsImFzc2lnbiIsImN1cnJlbnRMZXZlbCIsImxvZ0xldmVscyIsImxldmVscyIsInZhbHVlcyJdLCJtYXBwaW5ncyI6Ijs7OzsrQkFjYUE7OztlQUFBQTs7O3dCQVJOOzZEQUMwQjs7Ozs7O0FBTzFCLE1BQU1BLG9CQUFvQkMsa0JBQVU7SUFDbENDLE1BQW1CO0lBQ1ZDLFFBQTRCO0lBQzVCQyxPQUErQjtJQUNoRCxZQUFtQkQsT0FBMkIsRUFBRUMsTUFBK0IsQ0FBRTtRQUNoRixLQUFLO1FBQ0wsSUFBSSxDQUFDRCxPQUFPLEdBQUdBO1FBQ2YsSUFBSSxDQUFDQyxNQUFNLEdBQUdBO0lBQ2Y7SUFFT0MsVUFDTkMsYUFBMkMsRUFDMUM7UUFDRCxNQUFNLEVBQUVDLFFBQVEsRUFBRUMsVUFBVSxFQUFFLEdBQUdGO1FBQ2pDLE1BQU1HLGVBQWUsSUFBSSxDQUFDQyxZQUFZLENBQUNKO1FBRXZDLE1BQU1LLGNBQWtDO1lBQ3ZDRjtZQUNBRyxPQUFPTDtZQUNQTSxPQUFPO2dCQUFFQztZQUFVO1lBQ25CQyxhQUFhO2dCQUNaQyxPQUFPQyxhQUFJLENBQUNDLGNBQWMsQ0FBQ0MsR0FBRztZQUMvQjtZQUNBQyxRQUFRWjtZQUNSLEdBQUcsSUFBSSxDQUFDTCxPQUFPO1FBQ2hCO1FBQ0EsSUFBSSxDQUFDRCxLQUFLLEdBQUdlLElBQUFBLGFBQUksRUFBQ04sYUFBYSxJQUFJLENBQUNQLE1BQU07SUFDM0M7SUFFT2lCLFVBQ05DLElBQVksRUFDWTtRQUN4QixNQUFNQyxTQUFTQyxRQUF1QixJQUFJLENBQUN0QixLQUFLLENBQUN1QixLQUFLLENBQUM7WUFBRUg7UUFBSztRQUM5RCxPQUFPQztJQUNSO0lBRU9HLE1BQU1DLEVBQWUsRUFBUTtRQUNuQyxJQUFJLENBQUN6QixLQUFLLENBQUN3QixLQUFLLENBQUNDO0lBQ2xCO0FBQ0Q7QUFFQSxTQUFTYixVQUE2QmMsSUFBdUIsRUFBRUMsTUFBYTtJQUMzRSxJQUFJQyxVQUFVRixLQUFLRyxFQUFFLENBQUM7SUFDdEIsTUFBTUMsT0FBT0osS0FBS0csRUFBRSxDQUFDO0lBRXJCLElBQUlELG1CQUFtQkcsT0FBTztRQUM3QkosT0FBT0ssSUFBSSxDQUFDLElBQUksRUFBRTtZQUFFZixLQUFLVztRQUFRLEdBQUdLLElBQUFBLG1CQUFXLEVBQUNMO1FBQ2hEO0lBQ0Q7SUFFQSxJQUFJRSxnQkFBZ0JDLE9BQU87UUFDMUJILFVBQVU7WUFBRU0sS0FBS047WUFBUyxHQUFHO2dCQUFFZCxPQUFPZ0I7WUFBSyxDQUFDO1FBQUM7SUFDOUMsT0FBTyxJQUFJLE9BQU9BLFNBQVMsVUFBVTtRQUNwQ0YsVUFBVTtZQUFFTSxLQUFLTjtZQUFTLEdBQUdFLElBQUk7UUFBQztJQUNuQyxPQUFPO1FBQ05GLFVBQVU7WUFBRU0sS0FBS047WUFBU0U7UUFBSztJQUNoQztJQUVBSCxPQUFPSyxJQUFJLENBQUMsSUFBSSxFQUFFSjtBQUNuQjtBQUVBLFNBQVNOLFFBQ1JELE1BQW1CO0lBRW5CLE9BQU9jLE9BQU9DLE1BQU0sQ0FBMEJmLFFBQVE7UUFDckQsSUFBSWdCLGdCQUFlO1lBQ2xCLE9BQU9oQixPQUFPWCxLQUFLO1FBQ3BCO1FBQ0EsSUFBSTRCLGFBQVk7WUFDZixPQUFPakIsT0FBT2tCLE1BQU0sQ0FBQ0MsTUFBTTtRQUM1QjtJQUNEO0FBQ0QifQ==
@@ -1,95 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "PinoExtensions", {
6
- enumerable: true,
7
- get: function() {
8
- return PinoExtensions;
9
- }
10
- });
11
- const _extensibility = require("@decohere/nexus/extensibility");
12
- const _system = require("@decohere/nexus/system");
13
- const _scribe = require("@decohere/scribe");
14
- const _pinoadapater = require("./pino.adapater.js");
15
- function _ts_decorate(decorators, target, key, desc) {
16
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
17
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
18
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
19
- return c > 3 && r && Object.defineProperty(target, key, r), r;
20
- }
21
- function _ts_metadata(k, v) {
22
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
23
- }
24
- class PinoExtensions {
25
- static withPino(factory, config, logLevel) {
26
- return configureScribe(factory, {
27
- logLevel
28
- }, config);
29
- }
30
- static withPinoPretty(factory, logLevel) {
31
- return PinoExtensions.withPino(factory, {
32
- transports: {
33
- target: "pino-pretty",
34
- options: {
35
- colorize: true
36
- }
37
- }
38
- }, logLevel);
39
- }
40
- static withPinoCustom(factory, options) {
41
- const { scribe, transports } = options;
42
- return configureScribe(factory, scribe, transports);
43
- }
44
- }
45
- _ts_decorate([
46
- (0, _extensibility.extension)(_scribe.scribe),
47
- _ts_metadata("design:type", Function),
48
- _ts_metadata("design:paramtypes", [
49
- typeof _scribe.scribe === "undefined" ? Object : _scribe.scribe,
50
- Object,
51
- Object
52
- ]),
53
- _ts_metadata("design:returntype", void 0)
54
- ], PinoExtensions, "withPino", null);
55
- _ts_decorate([
56
- (0, _extensibility.extension)(_scribe.scribe),
57
- _ts_metadata("design:type", Function),
58
- _ts_metadata("design:paramtypes", [
59
- typeof _scribe.scribe === "undefined" ? Object : _scribe.scribe,
60
- Object
61
- ]),
62
- _ts_metadata("design:returntype", void 0)
63
- ], PinoExtensions, "withPinoPretty", null);
64
- _ts_decorate([
65
- (0, _extensibility.extension)(_scribe.scribe),
66
- _ts_metadata("design:type", Function),
67
- _ts_metadata("design:paramtypes", [
68
- typeof _scribe.scribe === "undefined" ? Object : _scribe.scribe,
69
- typeof CustomLevelOptions === "undefined" ? Object : CustomLevelOptions
70
- ]),
71
- _ts_metadata("design:returntype", void 0)
72
- ], PinoExtensions, "withPinoCustom", null);
73
- function configureScribe(factory, options, config) {
74
- const environment = process.env.NODE_ENV ?? _system.DefaultEnvironment;
75
- const configs = Array.isArray(config) ? config : [
76
- config
77
- ];
78
- const transports = configs.filter((config)=>config.environment && config.environment === environment || true);
79
- if (transports.length > 1) {
80
- throw new _scribe.LoggingConfigurationError(`There should only be one configuration per environment for logging`);
81
- }
82
- const transport = transports.at(0)?.transports;
83
- const adapter = new _pinoadapater.PinoAdapter({
84
- transport
85
- });
86
- return factory.configure({
87
- options: {
88
- ...options,
89
- logLevel: options?.logLevel ?? _scribe.DefaultLogLevel
90
- },
91
- adapter
92
- });
93
- }
94
-
95
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjcmliZS9zY3JpYmUtcGluby9zcmMvc2NyaWJlLXBpbm8udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXh0ZW5zaW9uIH0gZnJvbSBcIkBkZWNvaGVyZS9uZXh1cy9leHRlbnNpYmlsaXR5XCI7XG5pbXBvcnQgeyBEZWZhdWx0RW52aXJvbm1lbnQsIHR5cGUgRW52aXJvbm1lbnQgfSBmcm9tIFwiQGRlY29oZXJlL25leHVzL3N5c3RlbVwiO1xuaW1wb3J0IHtcblx0dHlwZSBEZWZhdWx0TGV2ZWxzLFxuXHREZWZhdWx0TG9nTGV2ZWwsXG5cdHR5cGUgTG9nZ2VyLFxuXHRMb2dnaW5nQ29uZmlndXJhdGlvbkVycm9yLFxuXHR0eXBlIFNjcmliZU9wdGlvbnMsXG5cdHNjcmliZSxcbn0gZnJvbSBcIkBkZWNvaGVyZS9zY3JpYmVcIjtcbmltcG9ydCB0eXBlIHtcblx0VHJhbnNwb3J0TXVsdGlPcHRpb25zLFxuXHRUcmFuc3BvcnRQaXBlbGluZU9wdGlvbnMsXG5cdFRyYW5zcG9ydFNpbmdsZU9wdGlvbnMsXG59IGZyb20gXCJwaW5vXCI7XG5cbmltcG9ydCB7IFBpbm9BZGFwdGVyIH0gZnJvbSBcIi4vcGluby5hZGFwYXRlci5qc1wiO1xuXG50eXBlIFRyYW5zcG9ydENvbmZpZyA9IHtcblx0ZW52aXJvbm1lbnQ/OiBFbnZpcm9ubWVudDtcblx0dHJhbnNwb3J0czogVHJhbnNwb3J0U2luZ2xlT3B0aW9ucyB8IFRyYW5zcG9ydE11bHRpT3B0aW9ucyB8IFRyYW5zcG9ydFBpcGVsaW5lT3B0aW9ucztcbn07XG5cbnR5cGUgQ3VzdG9tTGV2ZWxPcHRpb25zPFQgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlciwgQ3VzdG9tT25seSBleHRlbmRzIHRydWUgPSB1bmRlZmluZWQ+ID0ge1xuXHRzY3JpYmU/OiBTY3JpYmVPcHRpb25zPFQsIEN1c3RvbU9ubHk+O1xuXHR0cmFuc3BvcnRzPzogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW107XG59O1xuXG5kZWNsYXJlIG1vZHVsZSBcIkBkZWNvaGVyZS9zY3JpYmVcIiB7XG5cdGludGVyZmFjZSBzY3JpYmUge1xuXHRcdHdpdGhQaW5vKFxuXHRcdFx0dHJhbnNwb3J0czogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW10sXG5cdFx0XHRsb2dsZXZlbD86IERlZmF1bHRMZXZlbHMgfCBzdHJpbmcsXG5cdFx0KTogKG5hbWU/OiBzdHJpbmcpID0+IExvZ2dlcjtcblx0XHR3aXRoUGlub1ByZXR0eShsb2dMZXZlbD86IERlZmF1bHRMZXZlbHMgfCBzdHJpbmcpOiAobmFtZT86IHN0cmluZykgPT4gTG9nZ2VyO1xuXHRcdHdpdGhQaW5vQ3VzdG9tPFQgZXh0ZW5kcyBzdHJpbmcgPSBuZXZlciwgQ3VzdG9tT25seSBleHRlbmRzIHRydWUgPSB1bmRlZmluZWQ+KFxuXHRcdFx0b3B0aW9ucz86IEN1c3RvbUxldmVsT3B0aW9uczxULCBDdXN0b21Pbmx5Pixcblx0XHQpOiAobmFtZT86IHN0cmluZykgPT4gTG9nZ2VyPFQsIEN1c3RvbU9ubHk+O1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBQaW5vRXh0ZW5zaW9ucyB7XG5cdEBleHRlbnNpb24oc2NyaWJlKVxuXHRwdWJsaWMgc3RhdGljIHdpdGhQaW5vKFxuXHRcdGZhY3Rvcnk6IHNjcmliZSxcblx0XHRjb25maWc6IFRyYW5zcG9ydENvbmZpZyB8IFRyYW5zcG9ydENvbmZpZ1tdLFxuXHRcdGxvZ0xldmVsPzogRGVmYXVsdExldmVscyB8IHN0cmluZyxcblx0KSB7XG5cdFx0cmV0dXJuIGNvbmZpZ3VyZVNjcmliZShmYWN0b3J5LCB7IGxvZ0xldmVsIH0sIGNvbmZpZyk7XG5cdH1cblxuXHRAZXh0ZW5zaW9uKHNjcmliZSlcblx0cHVibGljIHN0YXRpYyB3aXRoUGlub1ByZXR0eShmYWN0b3J5OiBzY3JpYmUsIGxvZ0xldmVsPzogRGVmYXVsdExldmVscyB8IHN0cmluZykge1xuXHRcdHJldHVybiBQaW5vRXh0ZW5zaW9ucy53aXRoUGlubyhcblx0XHRcdGZhY3RvcnksXG5cdFx0XHR7IHRyYW5zcG9ydHM6IHsgdGFyZ2V0OiBcInBpbm8tcHJldHR5XCIsIG9wdGlvbnM6IHsgY29sb3JpemU6IHRydWUgfSB9IH0sXG5cdFx0XHRsb2dMZXZlbCxcblx0XHQpO1xuXHR9XG5cblx0QGV4dGVuc2lvbihzY3JpYmUpXG5cdHB1YmxpYyBzdGF0aWMgd2l0aFBpbm9DdXN0b208VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSA9IHVuZGVmaW5lZD4oXG5cdFx0ZmFjdG9yeTogc2NyaWJlLFxuXHRcdG9wdGlvbnM/OiBDdXN0b21MZXZlbE9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdCkge1xuXHRcdGNvbnN0IHsgc2NyaWJlLCB0cmFuc3BvcnRzIH0gPSBvcHRpb25zO1xuXHRcdHJldHVybiBjb25maWd1cmVTY3JpYmUoZmFjdG9yeSwgc2NyaWJlLCB0cmFuc3BvcnRzKTtcblx0fVxufVxuXG5mdW5jdGlvbiBjb25maWd1cmVTY3JpYmU8VCBleHRlbmRzIHN0cmluZyA9IG5ldmVyLCBDdXN0b21Pbmx5IGV4dGVuZHMgdHJ1ZSB8IGZhbHNlID0gZmFsc2U+KFxuXHRmYWN0b3J5OiBzY3JpYmUsXG5cdG9wdGlvbnM6IFNjcmliZU9wdGlvbnM8VCwgQ3VzdG9tT25seT4sXG5cdGNvbmZpZzogVHJhbnNwb3J0Q29uZmlnIHwgVHJhbnNwb3J0Q29uZmlnW10sXG4pIHtcblx0Y29uc3QgZW52aXJvbm1lbnQgPSBwcm9jZXNzLmVudi5OT0RFX0VOViA/PyBEZWZhdWx0RW52aXJvbm1lbnQ7XG5cdGNvbnN0IGNvbmZpZ3MgPSBBcnJheS5pc0FycmF5KGNvbmZpZykgPyBjb25maWcgOiBbY29uZmlnXTtcblx0Y29uc3QgdHJhbnNwb3J0cyA9IGNvbmZpZ3MuZmlsdGVyKFxuXHRcdChjb25maWcpID0+IChjb25maWcuZW52aXJvbm1lbnQgJiYgY29uZmlnLmVudmlyb25tZW50ID09PSBlbnZpcm9ubWVudCkgfHwgdHJ1ZSxcblx0KTtcblxuXHRpZiAodHJhbnNwb3J0cy5sZW5ndGggPiAxKSB7XG5cdFx0dGhyb3cgbmV3IExvZ2dpbmdDb25maWd1cmF0aW9uRXJyb3IoXG5cdFx0XHRgVGhlcmUgc2hvdWxkIG9ubHkgYmUgb25lIGNvbmZpZ3VyYXRpb24gcGVyIGVudmlyb25tZW50IGZvciBsb2dnaW5nYCxcblx0XHQpO1xuXHR9XG5cblx0Y29uc3QgdHJhbnNwb3J0ID0gdHJhbnNwb3J0cy5hdCgwKT8udHJhbnNwb3J0cztcblx0Y29uc3QgYWRhcHRlciA9IG5ldyBQaW5vQWRhcHRlcih7IHRyYW5zcG9ydCB9KTtcblx0cmV0dXJuIGZhY3RvcnkuY29uZmlndXJlKHtcblx0XHRvcHRpb25zOiB7IC4uLm9wdGlvbnMsIGxvZ0xldmVsOiBvcHRpb25zPy5sb2dMZXZlbCA/PyBEZWZhdWx0TG9nTGV2ZWwgfSxcblx0XHRhZGFwdGVyLFxuXHR9KTtcbn1cbiJdLCJuYW1lcyI6WyJQaW5vRXh0ZW5zaW9ucyIsIndpdGhQaW5vIiwiZmFjdG9yeSIsImNvbmZpZyIsImxvZ0xldmVsIiwiY29uZmlndXJlU2NyaWJlIiwid2l0aFBpbm9QcmV0dHkiLCJ0cmFuc3BvcnRzIiwidGFyZ2V0Iiwib3B0aW9ucyIsImNvbG9yaXplIiwid2l0aFBpbm9DdXN0b20iLCJzY3JpYmUiLCJlbnZpcm9ubWVudCIsInByb2Nlc3MiLCJlbnYiLCJOT0RFX0VOViIsIkRlZmF1bHRFbnZpcm9ubWVudCIsImNvbmZpZ3MiLCJBcnJheSIsImlzQXJyYXkiLCJmaWx0ZXIiLCJsZW5ndGgiLCJMb2dnaW5nQ29uZmlndXJhdGlvbkVycm9yIiwidHJhbnNwb3J0IiwiYXQiLCJhZGFwdGVyIiwiUGlub0FkYXB0ZXIiLCJjb25maWd1cmUiLCJEZWZhdWx0TG9nTGV2ZWwiXSwibWFwcGluZ3MiOiI7Ozs7K0JBeUNhQTs7O2VBQUFBOzs7K0JBekNhO3dCQUMyQjt3QkFROUM7OEJBT3FCOzs7Ozs7Ozs7O0FBeUJyQixNQUFNQTtJQUNaLE9BQ2NDLFNBQ2JDLE9BQWUsRUFDZkMsTUFBMkMsRUFDM0NDLFFBQWlDLEVBQ2hDO1FBQ0QsT0FBT0MsZ0JBQWdCSCxTQUFTO1lBQUVFO1FBQVMsR0FBR0Q7SUFDL0M7SUFFQSxPQUNjRyxlQUFlSixPQUFlLEVBQUVFLFFBQWlDLEVBQUU7UUFDaEYsT0FBT0osZUFBZUMsUUFBUSxDQUM3QkMsU0FDQTtZQUFFSyxZQUFZO2dCQUFFQyxRQUFRO2dCQUFlQyxTQUFTO29CQUFFQyxVQUFVO2dCQUFLO1lBQUU7UUFBRSxHQUNyRU47SUFFRjtJQUVBLE9BQ2NPLGVBQ2JULE9BQWUsRUFDZk8sT0FBMkMsRUFDMUM7UUFDRCxNQUFNLEVBQUVHLE1BQU0sRUFBRUwsVUFBVSxFQUFFLEdBQUdFO1FBQy9CLE9BQU9KLGdCQUFnQkgsU0FBU1UsUUFBUUw7SUFDekM7QUFDRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSxTQUFTRixnQkFDUkgsT0FBZSxFQUNmTyxPQUFxQyxFQUNyQ04sTUFBMkM7SUFFM0MsTUFBTVUsY0FBY0MsUUFBUUMsR0FBRyxDQUFDQyxRQUFRLElBQUlDLDBCQUFrQjtJQUM5RCxNQUFNQyxVQUFVQyxNQUFNQyxPQUFPLENBQUNqQixVQUFVQSxTQUFTO1FBQUNBO0tBQU87SUFDekQsTUFBTUksYUFBYVcsUUFBUUcsTUFBTSxDQUNoQyxDQUFDbEIsU0FBVyxBQUFDQSxPQUFPVSxXQUFXLElBQUlWLE9BQU9VLFdBQVcsS0FBS0EsZUFBZ0I7SUFHM0UsSUFBSU4sV0FBV2UsTUFBTSxHQUFHLEdBQUc7UUFDMUIsTUFBTSxJQUFJQyxpQ0FBeUIsQ0FDbEMsQ0FBQyxrRUFBa0UsQ0FBQztJQUV0RTtJQUVBLE1BQU1DLFlBQVlqQixXQUFXa0IsRUFBRSxDQUFDLElBQUlsQjtJQUNwQyxNQUFNbUIsVUFBVSxJQUFJQyx5QkFBVyxDQUFDO1FBQUVIO0lBQVU7SUFDNUMsT0FBT3RCLFFBQVEwQixTQUFTLENBQUM7UUFDeEJuQixTQUFTO1lBQUUsR0FBR0EsT0FBTztZQUFFTCxVQUFVSyxTQUFTTCxZQUFZeUIsdUJBQWU7UUFBQztRQUN0RUg7SUFDRDtBQUNEIn0=