@adviser/cement 0.2.40 → 0.2.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/{chunk-USQXEZHL.js → chunk-3RHIVQAA.js} +2 -2
  2. package/{chunk-W2GV5KXV.js → chunk-N3NUTN4B.js} +3 -3
  3. package/{chunk-F5W6VELE.js → chunk-N5LQQXOU.js} +2 -2
  4. package/chunk-PPS4L4VW.js +38 -0
  5. package/{chunk-GES3MUGV.js.map → chunk-PPS4L4VW.js.map} +1 -1
  6. package/index.cjs +500 -179
  7. package/index.cjs.map +1 -1
  8. package/index.d.cts +73 -30
  9. package/index.d.ts +73 -30
  10. package/index.js +506 -141
  11. package/index.js.map +1 -1
  12. package/node/index.js +2 -2
  13. package/package.json +2 -2
  14. package/src/http_header.ts +161 -0
  15. package/src/index.ts +1 -0
  16. package/src/jsr.json +1 -1
  17. package/src/log-level-impl.ts +7 -0
  18. package/src/logger-impl.ts +70 -43
  19. package/src/logger.ts +37 -9
  20. package/src/option.ts +7 -0
  21. package/src/result.ts +7 -1
  22. package/src/uri.ts +35 -11
  23. package/src/utils/relative-path.ts +161 -0
  24. package/ts/http_header.d.ts +29 -0
  25. package/ts/http_header.d.ts.map +1 -0
  26. package/ts/http_header.js +155 -0
  27. package/ts/http_header.js.map +1 -0
  28. package/ts/http_header.test.d.ts +2 -0
  29. package/ts/http_header.test.d.ts.map +1 -0
  30. package/ts/http_header.test.js +90 -0
  31. package/ts/http_header.test.js.map +1 -0
  32. package/ts/index.d.ts +1 -0
  33. package/ts/index.d.ts.map +1 -1
  34. package/ts/index.js +1 -0
  35. package/ts/index.js.map +1 -1
  36. package/ts/log-level-impl.d.ts +3 -0
  37. package/ts/log-level-impl.d.ts.map +1 -1
  38. package/ts/log-level-impl.js +5 -0
  39. package/ts/log-level-impl.js.map +1 -1
  40. package/ts/logger-impl.d.ts +2 -1
  41. package/ts/logger-impl.d.ts.map +1 -1
  42. package/ts/logger-impl.js +66 -47
  43. package/ts/logger-impl.js.map +1 -1
  44. package/ts/logger.d.ts +10 -1
  45. package/ts/logger.d.ts.map +1 -1
  46. package/ts/logger.js +22 -8
  47. package/ts/logger.js.map +1 -1
  48. package/ts/logger.test.js +111 -58
  49. package/ts/logger.test.js.map +1 -1
  50. package/ts/option.d.ts +1 -0
  51. package/ts/option.d.ts.map +1 -1
  52. package/ts/option.js +6 -0
  53. package/ts/option.js.map +1 -1
  54. package/ts/result.d.ts +1 -1
  55. package/ts/result.d.ts.map +1 -1
  56. package/ts/result.js +6 -0
  57. package/ts/result.js.map +1 -1
  58. package/ts/result.test.js +6 -0
  59. package/ts/result.test.js.map +1 -1
  60. package/ts/tracer.js +24 -6
  61. package/ts/tracer.js.map +1 -1
  62. package/ts/uri.d.ts +3 -1
  63. package/ts/uri.d.ts.map +1 -1
  64. package/ts/uri.js +27 -10
  65. package/ts/uri.js.map +1 -1
  66. package/ts/uri.test.js +39 -10
  67. package/ts/uri.test.js.map +1 -1
  68. package/ts/utils/relative-path.d.ts +17 -0
  69. package/ts/utils/relative-path.d.ts.map +1 -0
  70. package/ts/utils/relative-path.js +148 -0
  71. package/ts/utils/relative-path.js.map +1 -0
  72. package/ts/utils/relative-path.test.d.ts +2 -0
  73. package/ts/utils/relative-path.test.d.ts.map +1 -0
  74. package/ts/utils/relative-path.test.js +187 -0
  75. package/ts/utils/relative-path.test.js.map +1 -0
  76. package/ts/utils/stripper.js +1 -1
  77. package/ts/utils/stripper.js.map +1 -1
  78. package/utils/index.js +2 -2
  79. package/web/index.js +3 -3
  80. package/chunk-GES3MUGV.js +0 -92
  81. /package/{chunk-USQXEZHL.js.map → chunk-3RHIVQAA.js.map} +0 -0
  82. /package/{chunk-W2GV5KXV.js.map → chunk-N3NUTN4B.js.map} +0 -0
  83. /package/{chunk-F5W6VELE.js.map → chunk-N5LQQXOU.js.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adviser/cement",
3
- "version": "0.2.40",
3
+ "version": "0.2.42",
4
4
  "description": "better try/catch/finally handling",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -49,7 +49,7 @@
49
49
  "@vitest/browser": "^2.1.1",
50
50
  "esbuild-plugin-replace": "^1.4.0",
51
51
  "esbuild-plugin-resolve": "^2.0.0",
52
- "eslint": "9.15.0",
52
+ "eslint": "9.17.0",
53
53
  "prettier": "^3.3.3",
54
54
  "tsup": "^8.3.0",
55
55
  "tsx": "^4.19.1",
@@ -0,0 +1,161 @@
1
+ export class HeadersImpl extends Headers {
2
+ readonly _headers: Map<string, string>;
3
+
4
+ constructor(init: Map<string, string>) {
5
+ super();
6
+ this._headers = init;
7
+ }
8
+
9
+ [Symbol.iterator](): HeadersIterator<[string, string]> {
10
+ return this.entries();
11
+ }
12
+
13
+ entries(): HeadersIterator<[string, string]> {
14
+ return this._headers.entries();
15
+ }
16
+ keys(): HeadersIterator<string> {
17
+ return this._headers.keys();
18
+ }
19
+ values(): HeadersIterator<string> {
20
+ return this._headers.values();
21
+ }
22
+
23
+ append(key: string, value: string | string[] | undefined): HeadersImpl {
24
+ const values = this._headers.get(key);
25
+ if (typeof value === "undefined") {
26
+ value = "";
27
+ }
28
+ if (Array.isArray(value)) {
29
+ this._headers.set(key, [values, ...value].filter((i) => i).join(", "));
30
+ } else {
31
+ this._headers.set(key, [values, value].filter((i) => i).join(", "));
32
+ }
33
+ return this;
34
+ }
35
+ }
36
+
37
+ export class HttpHeader {
38
+ readonly _headers: Map<string, string[]> = new Map<string, string[]>();
39
+
40
+ static from(headers?: HeadersInit | NodeJS.Dict<string | string[]> | Headers): HttpHeader {
41
+ const h = new HttpHeader();
42
+ if (headers) {
43
+ if (Array.isArray(headers)) {
44
+ for (const [k, v] of headers) {
45
+ if (v) {
46
+ h.Add(k, v);
47
+ }
48
+ }
49
+ } else if (headers instanceof Headers) {
50
+ for (const [k, v] of headers.entries()) {
51
+ if (v) {
52
+ h.Add(
53
+ k,
54
+ v.split(",").map((v) => v.trim()),
55
+ );
56
+ }
57
+ }
58
+ } else {
59
+ for (const k in headers) {
60
+ const v = headers[k];
61
+ if (v) {
62
+ h.Add(k, v);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return h;
68
+ }
69
+
70
+ _asStringString(): Map<string, string> {
71
+ const ret = new Map<string, string>();
72
+ for (const [key, values] of this._headers) {
73
+ ret.set(key, values.join(", "));
74
+ }
75
+ return ret;
76
+ }
77
+
78
+ _key(key: string): string {
79
+ return key.toLowerCase();
80
+ }
81
+ Values(key: string): string[] {
82
+ const values = this._headers.get(this._key(key));
83
+ return values || [];
84
+ }
85
+ Get(key: string): string | undefined {
86
+ const values = this._headers.get(this._key(key));
87
+ if (values === undefined || values.length === 0) {
88
+ return undefined;
89
+ }
90
+ return values[0];
91
+ }
92
+ Set(key: string, valueOr: string | string[]): HttpHeader {
93
+ const value = Array.isArray(valueOr) ? valueOr : [valueOr];
94
+ this._headers.set(this._key(key), value);
95
+ return this;
96
+ }
97
+ Add(key: string, value: string | string[] | undefined): HttpHeader {
98
+ if (typeof value === "undefined") {
99
+ return this;
100
+ }
101
+ const vs = Array.isArray(value) ? value : [value];
102
+ const values = this._headers.get(this._key(key));
103
+ if (values === undefined) {
104
+ this._headers.set(this._key(key), vs);
105
+ } else {
106
+ values.push(...vs);
107
+ }
108
+ return this;
109
+ }
110
+ Del(ey: string): HttpHeader {
111
+ this._headers.delete(this._key(ey));
112
+ return this;
113
+ }
114
+ Items(): [string, string[]][] {
115
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
116
+ return Array.from(this._headers).filter(([_, vs]) => vs.length > 0);
117
+ }
118
+ SortItems(): [string, string[]][] {
119
+ return this.Items().sort(([[a]], [[b]]) => a.localeCompare(b));
120
+ }
121
+ Clone(): HttpHeader {
122
+ const clone = new HttpHeader();
123
+ for (const [key, values] of this._headers.entries()) {
124
+ clone._headers.set(key, values.slice());
125
+ }
126
+ return clone;
127
+ }
128
+ AsRecordStringStringArray(): Record<string, string[]> {
129
+ const obj: Record<string, string[]> = {};
130
+ for (const [key, values] of this._headers.entries()) {
131
+ obj[key] = [...values];
132
+ }
133
+ return obj;
134
+ }
135
+ AsRecordStringString(): Record<string, string> {
136
+ const obj: Record<string, string> = {};
137
+ for (const [key, values] of this._headers.entries()) {
138
+ obj[key] = values.join(", ");
139
+ }
140
+ return obj;
141
+ }
142
+ AsHeaderInit(): HeadersInit {
143
+ const obj: HeadersInit = {};
144
+ for (const [key, values] of this._headers.entries()) {
145
+ obj[key] = values[0];
146
+ }
147
+ return obj;
148
+ }
149
+ AsHeaders(): Headers {
150
+ return new HeadersImpl(this._asStringString());
151
+ }
152
+ Merge(other?: HttpHeader): HttpHeader {
153
+ const ret = this.Clone();
154
+ if (other) {
155
+ for (const [key, values] of other.Items()) {
156
+ ret.Add(key, values);
157
+ }
158
+ }
159
+ return ret;
160
+ }
161
+ }
package/src/index.ts CHANGED
@@ -19,4 +19,5 @@ export * from "./crypto.js";
19
19
  export * from "./base-sys-abstraction.js";
20
20
  export * from "./bin2text.js";
21
21
  export * from "./version.js";
22
+ export * from "./http_header.js";
22
23
  export * as utils from "./utils/index.js";
package/src/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adviser/cement",
3
- "version": "0.2.40",
3
+ "version": "0.2.42",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./web": "./web/index.ts",
@@ -1,8 +1,11 @@
1
1
  import { LevelHandler, Level } from "./logger.js";
2
+ import { Option } from "./option.js";
2
3
 
3
4
  export class LevelHandlerImpl implements LevelHandler {
4
5
  readonly _globalLevels: Set<Level> = new Set<Level>([Level.INFO, Level.ERROR, Level.WARN]);
5
6
  readonly _modules: Map<string, Set<Level>> = new Map<string, Set<Level>>();
7
+
8
+ ignoreAttr: Option<RegExp> = Option.Some(/^_/);
6
9
  isStackExposed = false;
7
10
  enableLevel(level: Level, ...modules: string[]): void {
8
11
  if (modules.length == 0) {
@@ -35,6 +38,10 @@ export class LevelHandlerImpl implements LevelHandler {
35
38
  this.isStackExposed = !!enable;
36
39
  }
37
40
 
41
+ setIgnoreAttr(re?: RegExp): void {
42
+ this.ignoreAttr = Option.From(re);
43
+ }
44
+
38
45
  forModules(level: Level, fnAction: (p: string) => void, ...modules: (string | string[])[]): void {
39
46
  for (const m of modules.flat()) {
40
47
  if (typeof m !== "string") {
@@ -18,6 +18,7 @@ import {
18
18
  LogFormatter,
19
19
  LogValueArg,
20
20
  HttpType,
21
+ LogValueState,
21
22
  } from "./logger.js";
22
23
  import { WebSysAbstraction } from "./web/web-sys-abstraction.js";
23
24
  import { SysAbstraction } from "./sys-abstraction.js";
@@ -29,20 +30,20 @@ import { LogWriterStream } from "./log-writer-impl.js";
29
30
  import { TxtEnDecoder, Utf8EnDecoderSingleton } from "./txt-en-decoder.js";
30
31
  import { LevelHandlerSingleton } from "./log-level-impl.js";
31
32
 
32
- function getLen(value: unknown): LogValue {
33
+ function getLen(value: unknown, lvs: LogValueState): LogValue {
33
34
  if (Array.isArray(value)) {
34
- return logValue(() => value.length);
35
+ return logValue(() => value.length, lvs);
35
36
  } else if (typeof value === "string") {
36
- return logValue(() => value.length);
37
+ return logValue(() => value.length, lvs);
37
38
  } else if (typeof value === "object" && value !== null) {
38
39
  if (typeof (value as Sized).size === "number") {
39
- return logValue(() => (value as Sized).size);
40
+ return logValue(() => (value as Sized).size, lvs);
40
41
  } else if (typeof (value as Lengthed).length === "number") {
41
- return logValue(() => (value as Lengthed).length);
42
+ return logValue(() => (value as Lengthed).length, lvs);
42
43
  }
43
- return logValue(() => Object.keys(value).length);
44
+ return logValue(() => Object.keys(value).length, lvs);
44
45
  }
45
- return logValue(() => -1);
46
+ return logValue(() => -1, lvs);
46
47
  }
47
48
 
48
49
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -100,12 +101,18 @@ export interface LoggerImplParams {
100
101
  readonly formatter?: LogFormatter;
101
102
  }
102
103
 
104
+ function toLogValueCtx(lvh: LevelHandler): LogValueState {
105
+ return {
106
+ ignoreAttr: lvh.ignoreAttr,
107
+ };
108
+ }
109
+
103
110
  export class LoggerImpl implements Logger {
104
111
  readonly _sys: SysAbstraction;
105
112
  readonly _attributes: LogSerializable = {};
106
113
  readonly _withAttributes: LogSerializable;
107
114
  readonly _logWriter: LogWriterStream;
108
- readonly _levelHandler: LevelHandler;
115
+ readonly levelHandler: LevelHandler;
109
116
  readonly _txtEnDe: TxtEnDecoder;
110
117
  _formatter: LogFormatter;
111
118
  // readonly _id: string = "logger-" + Math.random().toString(36)
@@ -157,9 +164,9 @@ export class LoggerImpl implements Logger {
157
164
  }
158
165
  this._attributes = { ...this._withAttributes };
159
166
  if (params.levelHandler) {
160
- this._levelHandler = params.levelHandler;
167
+ this.levelHandler = params.levelHandler;
161
168
  } else {
162
- this._levelHandler = LevelHandlerSingleton();
169
+ this.levelHandler = LevelHandlerSingleton();
163
170
  }
164
171
  // console.log("LoggerImpl", this._id, this._attributes, this._withAttributes)
165
172
  }
@@ -182,27 +189,32 @@ export class LoggerImpl implements Logger {
182
189
  }
183
190
 
184
191
  SetExposeStack(enable?: boolean): Logger {
185
- this._levelHandler.setExposeStack(enable);
192
+ this.levelHandler.setExposeStack(enable);
186
193
  return this;
187
194
  }
188
195
 
189
196
  EnableLevel(level: Level, ...modules: string[]): Logger {
190
- this._levelHandler.enableLevel(level, ...modules);
197
+ this.levelHandler.enableLevel(level, ...modules);
191
198
  return this;
192
199
  }
193
200
  DisableLevel(level: Level, ...modules: string[]): Logger {
194
- this._levelHandler.disableLevel(level, ...modules);
201
+ this.levelHandler.disableLevel(level, ...modules);
195
202
  return this;
196
203
  }
197
204
 
198
205
  Module(key: string): Logger {
199
- this._attributes["module"] = logValue(key);
200
- this._withAttributes["module"] = logValue(key);
206
+ this._attributes["module"] = logValue(key, toLogValueCtx(this.levelHandler));
207
+ this._withAttributes["module"] = logValue(key, toLogValueCtx(this.levelHandler));
201
208
  return this;
202
209
  }
203
210
  // if the string is "*" it will enable for all modules
204
211
  SetDebug(...modules: (string | string[])[]): Logger {
205
- this._levelHandler.setDebug(...modules);
212
+ this.levelHandler.setDebug(...modules);
213
+ return this;
214
+ }
215
+
216
+ SetIgnoreAttribute(re?: RegExp): Logger {
217
+ this.levelHandler.setIgnoreAttr(re);
206
218
  return this;
207
219
  }
208
220
 
@@ -212,57 +224,63 @@ export class LoggerImpl implements Logger {
212
224
  }
213
225
 
214
226
  Timestamp(): Logger {
215
- this._attributes["ts"] = logValue(() => this._sys.Time().Now().toISOString());
227
+ this._attributes["ts"] = logValue(() => this._sys.Time().Now().toISOString(), toLogValueCtx(this.levelHandler));
216
228
  return this;
217
229
  }
218
230
  Warn(): Logger {
219
- this._attributes["level"] = logValue(Level.WARN);
231
+ this._attributes["level"] = logValue(Level.WARN, toLogValueCtx(this.levelHandler));
220
232
  return this;
221
233
  }
222
234
  Log(): Logger {
223
235
  return this;
224
236
  }
225
237
  Debug(): Logger {
226
- this._attributes["level"] = logValue(Level.DEBUG);
238
+ this._attributes["level"] = logValue(Level.DEBUG, toLogValueCtx(this.levelHandler));
227
239
  return this;
228
240
  }
229
241
  Error(): Logger {
230
- this._attributes["level"] = logValue(Level.ERROR);
242
+ this._attributes["level"] = logValue(Level.ERROR, toLogValueCtx(this.levelHandler));
231
243
  return this;
232
244
  }
233
245
  Info(): Logger {
234
- this._attributes["level"] = logValue(Level.INFO);
246
+ this._attributes["level"] = logValue(Level.INFO, toLogValueCtx(this.levelHandler));
235
247
  return this;
236
248
  }
237
249
  Err(err: unknown | Result<unknown> | Error): Logger {
250
+ let key = "error";
238
251
  if (Result.Is(err)) {
239
252
  if (err.isOk()) {
240
- this.Result("noerror", err);
253
+ key = "noerror";
254
+ err = err.Ok();
241
255
  } else {
242
- this.Result("error", err);
256
+ err = err.Err();
243
257
  }
244
- } else if (err instanceof Error) {
245
- this._attributes["error"] = logValue(err.message);
246
- if (this._levelHandler.isStackExposed) {
247
- this._attributes["stack"] = logValue(err.stack?.split("\n").map((s) => s.trim()));
258
+ }
259
+ if (err instanceof Error) {
260
+ this._attributes[key] = logValue(err.message, toLogValueCtx(this.levelHandler));
261
+ if (this.levelHandler.isStackExposed) {
262
+ this._attributes["stack"] = logValue(
263
+ err.stack?.split("\n").map((s) => s.trim()),
264
+ toLogValueCtx(this.levelHandler),
265
+ );
248
266
  }
249
267
  } else {
250
- this._attributes["error"] = logValue("" + err);
268
+ this.Any(key, err as LogSerializable);
251
269
  }
252
270
  return this;
253
271
  }
254
272
  WithLevel(l: Level): Logger {
255
- this._attributes["level"] = logValue(l);
273
+ this._attributes["level"] = logValue(l, toLogValueCtx(this.levelHandler));
256
274
  return this;
257
275
  }
258
276
 
259
277
  Ref(key: string, action: { toString: () => string } | FnSerialized): Logger {
260
278
  if (typeof action === "function") {
261
- this._attributes[key] = logValue(action as FnSerialized);
279
+ this._attributes[key] = logValue(action as FnSerialized, toLogValueCtx(this.levelHandler));
262
280
  } else if (typeof action.toString === "function") {
263
- this._attributes[key] = logValue(() => action.toString());
281
+ this._attributes[key] = logValue(() => action.toString(), toLogValueCtx(this.levelHandler));
264
282
  } else {
265
- this._attributes[key] = logValue("INVALID REF");
283
+ this._attributes[key] = logValue("INVALID REF", toLogValueCtx(this.levelHandler));
266
284
  }
267
285
  return this;
268
286
  }
@@ -319,7 +337,7 @@ export class LoggerImpl implements Logger {
319
337
 
320
338
  Result<T>(key: string, res: Result<T, Error>): Logger {
321
339
  if (res.isOk()) {
322
- this._attributes[key] = logValue(res.Ok() as Serialized);
340
+ this._attributes[key] = logValue(res.Ok() as Serialized, toLogValueCtx(this.levelHandler));
323
341
  } else {
324
342
  this.Err(res.Err());
325
343
  }
@@ -327,12 +345,14 @@ export class LoggerImpl implements Logger {
327
345
  }
328
346
 
329
347
  Len(value: unknown, key = "len"): Logger {
330
- this._attributes[key] = getLen(value);
348
+ this._attributes[key] = getLen(value, toLogValueCtx(this.levelHandler));
331
349
  return this;
332
350
  }
333
351
 
334
352
  Hash(value: unknown, key = "hash"): Logger {
335
- this._attributes[key] = asyncLogValue(async () => `${getLen(value).value()}:${await hash(value)}`);
353
+ this._attributes[key] = asyncLogValue(
354
+ async () => `${getLen(value, toLogValueCtx(this.levelHandler)).value()}:${await hash(value)}`,
355
+ );
336
356
  return this;
337
357
  }
338
358
 
@@ -343,7 +363,7 @@ export class LoggerImpl implements Logger {
343
363
 
344
364
  private coerceKey(key: string | Record<string, unknown>, value?: unknown): void {
345
365
  if (typeof key === "string") {
346
- this._attributes[key] = logValue(value as LogValueArg);
366
+ this._attributes[key] = logValue(value as LogValueArg, toLogValueCtx(this.levelHandler));
347
367
  } else {
348
368
  this.Pair(key);
349
369
  }
@@ -360,7 +380,7 @@ export class LoggerImpl implements Logger {
360
380
  return this;
361
381
  }
362
382
  Dur(key: string, nsec: number): Logger {
363
- this._attributes[key] = logValue(`${nsec}ms`);
383
+ this._attributes[key] = logValue(`${nsec}ms`, toLogValueCtx(this.levelHandler));
364
384
  // new Intl.DurationFormat("en", { style: "narrow" }).format(nsec);
365
385
  return this;
366
386
  }
@@ -385,7 +405,7 @@ export class LoggerImpl implements Logger {
385
405
  new LoggerImpl({
386
406
  logWriter: this._logWriter,
387
407
  sys: this._sys,
388
- levelHandler: this._levelHandler,
408
+ levelHandler: this.levelHandler,
389
409
  formatter: this._formatter,
390
410
  withAttributes: {
391
411
  module: this._attributes["module"],
@@ -407,11 +427,11 @@ export class LoggerImpl implements Logger {
407
427
 
408
428
  Msg(...args: string[]): AsError {
409
429
  const fnError = this._resetAttributes(() => {
410
- const doWrite = this._levelHandler.isEnabled(
430
+ const doWrite = this.levelHandler.isEnabled(
411
431
  toLogValue(this._attributes["level"])?.value(),
412
432
  toLogValue(this._attributes["module"])?.value(),
413
433
  );
414
- this._attributes["msg"] = logValue(args.join(" "));
434
+ this._attributes["msg"] = logValue(args.join(" "), toLogValueCtx(this.levelHandler));
415
435
  const msg = this._attributes["msg"].value();
416
436
  if (typeof msg === "string" && !msg.trim().length) {
417
437
  delete this._attributes["msg"];
@@ -434,8 +454,10 @@ export class LoggerImpl implements Logger {
434
454
 
435
455
  class WithLoggerBuilder implements WithLogger {
436
456
  readonly _li: LoggerImpl;
457
+ readonly levelHandler: LevelHandler;
437
458
  constructor(li: LoggerImpl) {
438
459
  this._li = li;
460
+ this.levelHandler = li.levelHandler;
439
461
  }
440
462
 
441
463
  TxtEnDe(): TxtEnDecoder {
@@ -452,7 +474,12 @@ class WithLoggerBuilder implements WithLogger {
452
474
  }
453
475
 
454
476
  SetExposeStack(enable?: boolean): WithLogger {
455
- this._li._levelHandler.setExposeStack(enable);
477
+ this._li.levelHandler.setExposeStack(enable);
478
+ return this;
479
+ }
480
+
481
+ SetIgnoreAttribute(re?: RegExp): WithLogger {
482
+ this._li.levelHandler.setIgnoreAttr(re);
456
483
  return this;
457
484
  }
458
485
 
@@ -462,11 +489,11 @@ class WithLoggerBuilder implements WithLogger {
462
489
  }
463
490
 
464
491
  EnableLevel(level: Level, ...modules: string[]): WithLogger {
465
- this._li._levelHandler.enableLevel(level, ...modules);
492
+ this._li.levelHandler.enableLevel(level, ...modules);
466
493
  return this;
467
494
  }
468
495
  DisableLevel(level: Level, ...modules: string[]): WithLogger {
469
- this._li._levelHandler.enableLevel(level, ...modules);
496
+ this._li.levelHandler.enableLevel(level, ...modules);
470
497
  return this;
471
498
  }
472
499
 
package/src/logger.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { bin2string } from "./bin2text.js";
2
+ import { Option } from "./option.js";
2
3
  import { Result } from "./result.js";
3
4
  import { TxtEnDecoder } from "./txt-en-decoder.js";
4
5
  import { CoerceURI } from "./uri.js";
@@ -50,7 +51,25 @@ export function asyncLogValue(val: () => Promise<Serialized>): Promise<LogValue>
50
51
 
51
52
  export type LogValueArg = LogValue | Serialized | Serialized[] | FnSerialized | undefined | null;
52
53
 
53
- export function logValue(val: LogValueArg, state: Set<unknown> = new Set<unknown>([Math.random()])): LogValue {
54
+ export interface LogValueState {
55
+ readonly state?: Set<unknown>;
56
+ readonly ignoreAttr: Option<RegExp>;
57
+ }
58
+
59
+ export function logValue(val: LogValueArg, ctx: LogValueState): LogValue {
60
+ return logValueInternal(val, {
61
+ ...ctx,
62
+ state: ctx.state || new Set<unknown>([Math.random()]),
63
+ });
64
+ }
65
+
66
+ type LogValueStateInternal = LogValueState & { readonly state: Set<unknown> };
67
+
68
+ function logValueInternal(val: LogValueArg, ctx: LogValueStateInternal): LogValue {
69
+ ctx = {
70
+ ...ctx,
71
+ state: ctx.state || new Set<unknown>([Math.random()]),
72
+ } satisfies LogValueStateInternal;
54
73
  switch (typeof val) {
55
74
  case "function":
56
75
  return new LogValue(val);
@@ -58,7 +77,7 @@ export function logValue(val: LogValueArg, state: Set<unknown> = new Set<unknown
58
77
  try {
59
78
  const ret = JSON.parse(val);
60
79
  if (typeof ret === "object" && ret !== null) {
61
- return logValue(ret, state);
80
+ return logValueInternal(ret, ctx);
62
81
  }
63
82
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
83
  } catch (e) {
@@ -83,14 +102,16 @@ export function logValue(val: LogValueArg, state: Set<unknown> = new Set<unknown
83
102
  const decoder = new TextDecoder();
84
103
  const asStr = decoder.decode(val);
85
104
  const obj = JSON.parse(asStr);
86
- return logValue(obj, state);
105
+ return logValueInternal(obj, ctx);
87
106
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
88
107
  } catch (e) {
89
- return logValue(bin2string(val, 512));
108
+ return logValueInternal(bin2string(val, 512), ctx);
90
109
  }
91
110
  }
92
111
  if (Array.isArray(val)) {
93
- return new LogValue(() => (val as Serialized[]).map((v) => logValue(v).value() as Serialized));
112
+ return new LogValue(() =>
113
+ (val as Serialized[]).map((v) => logValue(v, { ...ctx, state: undefined }).value() as Serialized),
114
+ );
94
115
  }
95
116
  // if (val instanceof Response) {
96
117
  // // my = my.clone() as unknown as LogValue | Serialized[] | null
@@ -109,10 +130,10 @@ export function logValue(val: LogValueArg, state: Set<unknown> = new Set<unknown
109
130
  }
110
131
 
111
132
  // Duplicate reference found, discard key
112
- if (state.has(val)) {
133
+ if (ctx.state?.has(val)) {
113
134
  return new LogValue(() => "...");
114
135
  }
115
- state.add(val);
136
+ ctx.state?.add(val);
116
137
  if (typeof val.toJSON === "function") {
117
138
  return new LogValue(() => val.toJSON());
118
139
  }
@@ -120,14 +141,16 @@ export function logValue(val: LogValueArg, state: Set<unknown> = new Set<unknown
120
141
  const res: Record<string, LogValue> = {};
121
142
  const typedVal = val as unknown as Record<string, LogValueArg>;
122
143
  for (const key in typedVal) {
144
+ if (ctx.ignoreAttr.IsSome() && ctx.ignoreAttr.unwrap().test(key)) {
145
+ continue;
146
+ }
123
147
  const element = typedVal[key];
124
148
  if (element instanceof LogValue) {
125
149
  res[key] = element;
126
150
  } else {
127
151
  if (typeof element !== "function") {
128
- res[key] = logValue(element, state);
152
+ res[key] = logValueInternal(element, ctx);
129
153
  }
130
- // res[key] = logValue(element, state);
131
154
  }
132
155
  }
133
156
  // ugly as hell cast but how declare a self-referencing type?
@@ -157,6 +180,8 @@ export interface LevelHandler {
157
180
  enableLevel(level: Level, ...modules: string[]): void;
158
181
  disableLevel(level: Level, ...modules: string[]): void;
159
182
  setExposeStack(enable?: boolean): void;
183
+ setIgnoreAttr(re?: RegExp): void;
184
+ ignoreAttr: Option<RegExp>;
160
185
  isStackExposed: boolean;
161
186
  setDebug(...modules: (string | string[])[]): void;
162
187
  isEnabled(ilevel: unknown, module: unknown): boolean;
@@ -165,6 +190,7 @@ export interface LevelHandler {
165
190
  export type HttpType = Response | Result<Response> | Request | Result<Request>;
166
191
 
167
192
  export interface LoggerInterface<R> {
193
+ readonly levelHandler: LevelHandler;
168
194
  TxtEnDe(): TxtEnDecoder;
169
195
  Module(key: string): R;
170
196
  // if modules is empty, set for all Levels
@@ -174,6 +200,8 @@ export interface LoggerInterface<R> {
174
200
  Attributes(): Record<string, unknown>;
175
201
 
176
202
  SetDebug(...modules: (string | string[])[]): R;
203
+ // default is /^_/
204
+ SetIgnoreAttribute(re?: RegExp): R;
177
205
  SetExposeStack(enable?: boolean): R;
178
206
  SetFormatter(fmt: LogFormatter): R;
179
207
 
package/src/option.ts CHANGED
@@ -11,6 +11,13 @@ export abstract class Option<T> {
11
11
  return t instanceof Option;
12
12
  }
13
13
 
14
+ static From<T>(t?: T): Option<T> {
15
+ if (!t) {
16
+ return new None();
17
+ }
18
+ return new Some(t);
19
+ }
20
+
14
21
  IsNone(): boolean {
15
22
  return this.is_none();
16
23
  }
package/src/result.ts CHANGED
@@ -2,10 +2,16 @@ export abstract class Result<T, E = Error> {
2
2
  static Ok<T = void>(t: T): Result<T, Error> {
3
3
  return new ResultOK(t);
4
4
  }
5
- static Err<T, E extends Error = Error>(t: E | string): Result<T, E> {
5
+ static Err<T, E extends Error = Error>(t: E | string | Result<unknown, E>): Result<T, E> {
6
6
  if (typeof t === "string") {
7
7
  return new ResultError(new Error(t) as E);
8
8
  }
9
+ if (Result.Is(t)) {
10
+ if (t.is_ok()) {
11
+ return new ResultError(new Error("Result Error is Ok") as E);
12
+ }
13
+ return t as Result<T, E>;
14
+ }
9
15
  return new ResultError(t);
10
16
  }
11
17
  static Is<T>(t: unknown): t is Result<T> {