@wireio/shared 1.0.1 → 1.0.3

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 (40) hide show
  1. package/README.md +424 -0
  2. package/package.json +5 -1
  3. package/src/guards/applyTypeGuardExtras.ts +0 -9
  4. package/src/guards/array.ts +0 -5
  5. package/src/guards/assert.ts +0 -83
  6. package/src/guards/class.ts +0 -56
  7. package/src/guards/guard-tools.ts +0 -78
  8. package/src/guards/index.ts +0 -7
  9. package/src/guards/primitive.ts +0 -77
  10. package/src/guards/types.ts +0 -15
  11. package/src/helpers/Deferred.ts +0 -149
  12. package/src/helpers/index.ts +0 -1
  13. package/src/index.ts +0 -3
  14. package/src/logging/Appender.ts +0 -5
  15. package/src/logging/Formatter.ts +0 -8
  16. package/src/logging/InternalLogger.ts +0 -6
  17. package/src/logging/Level.ts +0 -19
  18. package/src/logging/LogRecord.ts +0 -17
  19. package/src/logging/Logger.ts +0 -222
  20. package/src/logging/LoggingManager.ts +0 -306
  21. package/src/logging/appenders/ConsoleAppender.ts +0 -110
  22. package/src/logging/appenders/DebugAppender.ts +0 -254
  23. package/src/logging/appenders/FileAppender.ts +0 -281
  24. package/src/logging/appenders/aws-firehose/AWSFirehoseAppender.ts +0 -176
  25. package/src/logging/appenders/aws-firehose/AWSFirehoseCredentialManager.ts +0 -132
  26. package/src/logging/appenders/index.ts +0 -3
  27. package/src/logging/context/LogContext.ts +0 -74
  28. package/src/logging/context/LogContextContainer.ts +0 -28
  29. package/src/logging/context/LogContextProvider.ts +0 -43
  30. package/src/logging/context/index.ts +0 -3
  31. package/src/logging/context/providers/node/NodeContextProvider.ts +0 -45
  32. package/src/logging/context/providers/node/index.ts +0 -3
  33. package/src/logging/examples/example-debug-appender.ts +0 -19
  34. package/src/logging/examples/example-file-appender.ts +0 -19
  35. package/src/logging/getLogger.ts +0 -9
  36. package/src/logging/index-node.ts +0 -2
  37. package/src/logging/index.ts +0 -11
  38. package/src/logging/util.ts +0 -6
  39. package/tsconfig.json +0 -9
  40. package/tsconfig.tsbuildinfo +0 -1
@@ -1,306 +0,0 @@
1
- import { isNumber, isObject, isString } from "../guards/index.js"
2
- import { Option } from "prelude-ts"
3
- import { flatten, isEmpty, min, negate } from "lodash"
4
- import type { Appender } from "./Appender.js"
5
- import { ConsoleAppender } from "./appenders/ConsoleAppender.js"
6
- import { Level, LevelKind, LevelThresholds } from "./Level.js"
7
- import { Logger, LoggerOptions } from "./Logger.js"
8
- import type { LogRecord } from "./LogRecord.js"
9
- import { LogContext, LogContextContainer } from "./context/index.js"
10
- import { flow, get, nth } from "lodash/fp.js"
11
-
12
- export type CategoryMatch = RegExp | string
13
-
14
- export type ThresholdOverride = [match: CategoryMatch, level: LevelKind]
15
-
16
- export interface LoggingManagerState<Record extends LogRecord> {
17
- rootLevel: LevelKind
18
- appenders: Array<Appender<Record>>
19
- thresholdOverrides: Array<ThresholdOverride>
20
- }
21
-
22
- export type LoggingManagerOptions<Record extends LogRecord> = Partial<
23
- LoggingManagerState<Record>
24
- >
25
-
26
- function parseThresholdOverridePatterns(
27
- value: string,
28
- level: LevelKind = "debug"
29
- ): ThresholdOverride[] {
30
- return value
31
- .split(",")
32
- .map((s) => [new RegExp(s), level] as ThresholdOverride)
33
- }
34
-
35
- export const kEnvThresholdOverrides = Option.ofNullable(typeof process !== "undefined" && process.env.DEBUG_PATTERNS)
36
- .filter(negate(isEmpty))
37
- .map(parseThresholdOverridePatterns)
38
- .getOrElse([])
39
-
40
- /**
41
- * Logging manager
42
- */
43
- export class LoggingManager<Record extends LogRecord = any> {
44
- private readonly loggers = new Map<string, Logger>()
45
-
46
- private readonly state: LoggingManagerState<Record> = {
47
- appenders: [],
48
- rootLevel: Level.info,
49
- thresholdOverrides: kEnvThresholdOverrides
50
- }
51
-
52
- get rootLevel() {
53
- return this.state.rootLevel
54
- }
55
-
56
- set rootLevel(newRootLevel: LevelKind) {
57
- this.state.rootLevel = newRootLevel
58
- }
59
-
60
- get rootThreshold() {
61
- return LevelThresholds[this.rootLevel]
62
- }
63
-
64
- /**
65
- * Get the current handler
66
- *
67
- * @returns {Appender<Record>}
68
- */
69
- get appenders(): Array<Appender<Record>> {
70
- return Option.ofNullable(this.state.appenders)
71
- .filter((appenders) => appenders.length > 0)
72
- .getOrCall(() => {
73
- this.state.appenders.push(new ConsoleAppender())
74
- return this.state.appenders
75
- })
76
- }
77
-
78
- /**
79
- * Global threshold overrides
80
- */
81
- get thresholdOverrides() {
82
- return this.state.thresholdOverrides
83
- }
84
-
85
- /**
86
- * Update the overrides
87
- *
88
- * @param newOverrides
89
- */
90
- set thresholdOverrides(newOverrides:ThresholdOverride[]) {
91
- this.state.thresholdOverrides = newOverrides
92
- }
93
-
94
- /**
95
- * Set global appenders
96
- *
97
- * @param {Array<Appender<Record>>} newAppenders
98
- */
99
- setAppenders(...newAppenders: Array<Appender<Record> | Appender<Record>[]>) {
100
- // WE MUTATE DO TO THE LIKELIHOOD OF SOMEONE HOLDING A REF TO THE ARRAY,
101
- // CONVERT TO OBSERVABLE AT SOME POINT
102
- const persistentAppenders = this.state.appenders
103
- persistentAppenders.length = 0
104
- persistentAppenders.push(...flatten(newAppenders))
105
-
106
- return this
107
- }
108
-
109
- /**
110
- * Add one or more appenders to existing appender set
111
- *
112
- * @param {Appender<Record> | Appender<Record>[]} newAppenders
113
- * @returns {this<Record>}
114
- */
115
- addAppenders(...newAppenders: Array<Appender<Record> | Appender<Record>[]>): this {
116
- this.state.appenders.push(...flatten(newAppenders))
117
- return this
118
- }
119
-
120
- /**
121
- * Clear threshold overrides
122
- *
123
- * @returns {this<Record>}
124
- */
125
- clearThresholdOverrides(): this {
126
- this.state.thresholdOverrides.length = 0
127
- return this
128
- }
129
-
130
- setThresholdOverrides(...overrides: Array<ThresholdOverride>) {
131
- this.state.thresholdOverrides.length = 0
132
- this.state.thresholdOverrides.push(...overrides)
133
- return this
134
- }
135
-
136
- addThresholdOverrides(...overrides: Array<ThresholdOverride>) {
137
- this.state.thresholdOverrides.push(...overrides)
138
- return this
139
- }
140
-
141
- /**
142
- * Get applicable current contexts
143
- *
144
- * @param {string} category
145
- * @returns {LogContext[]}
146
- */
147
- getApplicableCurrentContexts(category: string): LogContext[] {
148
- return LogContextContainer.currentContext().filter(
149
- ({ pattern }) => !pattern || pattern.test(category)
150
- )
151
- }
152
-
153
- /**
154
- * Check for any matching threshold overrides
155
- *
156
- * @param category
157
- */
158
- determineThresholdOverride(category: string): number {
159
- const contexts = this.getApplicableCurrentContexts(category),
160
-
161
- // FIND CONFIGURED OVERRIDE LEVEL
162
- overrideThreshold = Option.ofNullable(
163
- this.thresholdOverrides.find(([match]) =>
164
- isString(match) ? match === category : (match as RegExp).test(category)
165
- )
166
- )
167
- .map(nth(1))
168
- .map((level) => LevelThresholds[level as Level])
169
- .getOrNull(),
170
- // FIND `LogContext` OVERRIDE LEVEL
171
- contextThresholds = contexts
172
- .filter(flow(get("thresholdLevel"), isString))
173
- .map(({ thresholdLevel }) => LevelThresholds[thresholdLevel]),
174
- // IF ANY OVERRIDES, GET THE MOST VERBOSE LEVEL
175
- override = Option.ofNullable(
176
- [...contextThresholds, overrideThreshold].filter(isNumber)
177
- )
178
- .filter(negate(isEmpty))
179
- .map(min)
180
- .getOrNull()
181
-
182
- return override as number
183
- }
184
-
185
- /**
186
- * Set the root logging level
187
- *
188
- * @param {LevelKind} newLevel
189
- * @returns {this<Record>}
190
- */
191
- setRootLevel(newLevel: LevelKind): this {
192
- this.state.rootLevel = newLevel
193
- return this
194
- }
195
-
196
- /**
197
- * Fire a log event, eventually
198
- * invert this by making `Logger` an
199
- * `EventEmitter3` and having the `LoggingManager`
200
- * subscribe to `record` event
201
- *
202
- * @param {LogRecord<Record>} record
203
- * @internal
204
- */
205
- fire(record: LogRecord<Record>) {
206
- const { category } = record,
207
- contexts = this.getApplicableCurrentContexts(category),
208
- contextAppenders = contexts.flatMap(get("appenders")),
209
- appenders = [...this.appenders, ...contextAppenders]
210
-
211
- appenders.forEach((appender) => appender.append(record as Record))
212
- }
213
-
214
- /**
215
- * Get a logger from cache, if the category
216
- * does not have an existing logger, then create one.
217
- *
218
- * @param {string} categoryOrFilename
219
- * @param {Partial<LoggerOptions>} inOptions
220
- * @returns {Logger}
221
- */
222
- getLogger(
223
- categoryOrFilename: string,
224
- inOptions: Partial<LoggerOptions> = {}
225
- ): Logger {
226
- const options = Logger.hydrateOptions(inOptions)
227
- const category = Logger.interoplateCategory(categoryOrFilename, options)
228
-
229
- return Option.ofNullable(category)
230
- .map((category) => this.loggers.get(category))
231
- .getOrCall(() => {
232
- const logger = new Logger(this, category, options)
233
- this.loggers.set(category, logger)
234
- return logger
235
- })
236
- }
237
-
238
- /**
239
- * Configure the logging manager,
240
- * this function is additive, so simply calling
241
- * `configure` with a single option `rootLevel`,
242
- * will not affect other options like `appenders` *
243
- *
244
- * @param {LoggingManagerOptions<any>} options
245
- * @returns {this<Record>}
246
- */
247
- configure(options: LoggingManagerOptions<any>): this {
248
- if (Level[options?.rootLevel]) {
249
- this.setRootLevel(options.rootLevel)
250
- }
251
-
252
- if (options?.appenders) {
253
- this.setAppenders(options.appenders)
254
- }
255
-
256
- if (options?.thresholdOverrides) {
257
- this.addThresholdOverrides(...options.thresholdOverrides)
258
- }
259
-
260
- return this
261
- }
262
-
263
- private constructor() {
264
- this.configure({})
265
- }
266
-
267
- /**
268
- * Singleton instance
269
- *
270
- * @type {LoggingManager}
271
- * @private
272
- */
273
- private static manager: LoggingManager
274
-
275
- /**
276
- * Get logging manager and optionally provided
277
- * configuration options
278
- *
279
- * @param {LoggingManagerOptions<Record>} options
280
- * @returns {LoggingManager<Record>}
281
- */
282
- static get<Record extends LogRecord = any>(
283
- options: LoggingManagerOptions<Record> = null
284
- ): LoggingManager<Record> {
285
- if (!this.manager) {
286
- this.manager = new LoggingManager<Record>()
287
- }
288
-
289
- if (options) {
290
- this.manager.configure(options)
291
- }
292
-
293
- return this.manager
294
- }
295
- }
296
-
297
- export function getLoggingManager(): LoggingManager {
298
- return LoggingManager.get()
299
- }
300
-
301
- if (Option.try_(() => process.env.NODE_ENV === "development").getOrElse(false)) {
302
- [typeof window !== "undefined" && window, typeof global !== "undefined" && global].filter(isObject)
303
- .map(target => Object.assign(target, {
304
- loggingManager: getLoggingManager()
305
- }))
306
- }
@@ -1,110 +0,0 @@
1
- import type { LogRecord } from "../LogRecord"
2
- import type { Appender } from "../Appender"
3
- import { Option } from "prelude-ts"
4
- import type { LevelKind } from "../Level"
5
- import type { Formatter } from "../Formatter"
6
-
7
- const consoleLogBindings = new Map<LevelKind, (...args: any[]) => any>()
8
-
9
- function getBoundConsoleFn(level: LevelKind) {
10
- return (console[level] ?? console.log).bind(console)
11
- }
12
-
13
- /**
14
- * Get a cached console bound log function
15
- *
16
- * @param {LevelKind} level
17
- * @returns {(...args: any[]) => any}
18
- */
19
- export function getConsoleLogBinding(level: LevelKind) {
20
- if (!consoleLogBindings.has(level)) {
21
- consoleLogBindings.set(level, getBoundConsoleFn(level))
22
- }
23
-
24
- return consoleLogBindings.get(level)
25
- }
26
-
27
- /**
28
- * ConsoleAppender Configuration
29
- */
30
- export interface ConsoleAppenderConfig<Record extends LogRecord = any> {
31
- cacheEnabled: boolean
32
- prettyPrint: boolean
33
- formatter?: Formatter<string | Array<any>>
34
- }
35
-
36
- /**
37
- * Partial of config, used for shortening instead of Partial<...>
38
- */
39
- export type ConsoleAppenderOptions<Record extends LogRecord> = Partial<
40
- ConsoleAppenderConfig<Record>
41
- >
42
-
43
- export const consoleFormatter: Formatter<Array<any>> = ({
44
- level,
45
- message,
46
- data,
47
- args,
48
- category,
49
- timestamp
50
- }) => [
51
- `[${category}] (${level}) ${message}`,
52
- ...(Array.isArray(args) ? args : [args])
53
- ]
54
-
55
- /**
56
- * Default console config
57
- * @type {ConsoleAppenderConfig}
58
- */
59
- export const kDefaultConsoleAppenderConfig: ConsoleAppenderConfig = {
60
- cacheEnabled: true,
61
- prettyPrint: true,
62
- formatter: consoleFormatter
63
- }
64
-
65
- /**
66
- * Console appender, the simple default appender used
67
- * everywhere OOB
68
- */
69
- export class ConsoleAppender<Record extends LogRecord>
70
- implements Appender<Record>
71
- {
72
- readonly config: ConsoleAppenderConfig
73
-
74
- /**
75
- * Handle log records, transform, push to ES
76
- *
77
- * @param record
78
- */
79
- append(record: Record): void {
80
- const { level, message, data, args, category, timestamp } = record
81
- const { formatter = consoleFormatter } = this.config
82
- Option.ofNullable(formatter(record)).map((result) => {
83
- const args = Array.isArray(result) ? result : [result]
84
- this.write(level, ...args)
85
- })
86
- }
87
-
88
- /**
89
- * Write args to console
90
- *
91
- * @param level
92
- * @param args
93
- */
94
- protected write(level: LevelKind, ...args: any[]) {
95
- Option.ofNullable(console[level])
96
- .orCall(() => Option.ofNullable(console.log))
97
- .map((fn: Function) => fn.apply(console, args))
98
- }
99
-
100
- /**
101
- *
102
- * @param {Partial<ConsoleAppenderOptions<Record>>} options
103
- */
104
- constructor(options: Partial<ConsoleAppenderOptions<Record>> = {}) {
105
- this.config = {
106
- ...kDefaultConsoleAppenderConfig,
107
- ...options
108
- }
109
- }
110
- }
@@ -1,254 +0,0 @@
1
- import type { LogRecord } from "../LogRecord"
2
- import type { Appender } from "../Appender"
3
- import type { LevelKind } from "../Level"
4
- import Debug from "debug"
5
- import {
6
- ConsoleAppender, ConsoleAppenderConfig, kDefaultConsoleAppenderConfig
7
- } from "./ConsoleAppender.js"
8
- import type { Formatter } from "../Formatter"
9
- import { isEmpty, negate } from "lodash"
10
-
11
-
12
- // let chalk: any = null
13
- // if (
14
- // typeof process !== "undefined" &&
15
- // (process as any).type !== "renderer" &&
16
- // (process as any).browser !== true
17
- // ) {
18
- // chalk = require("chalk")
19
- // }
20
-
21
- const useColors = false
22
-
23
- const makeColorFn = (fn: (chalk: any, s: string) => string) => {
24
- // if (!useColors) {
25
- // return (s: string) => s
26
- // }
27
- //
28
- // return (s: string) => fn(chalk, s)
29
- return (s: string) => s
30
- }
31
-
32
- const colorFns: Record<LevelKind, (s: string) => string> = {
33
- debug: makeColorFn((c, s) => c.green(s)),
34
- error: makeColorFn((c, s) => c.red(s)),
35
- fatal: makeColorFn((c, s) => c.bgRed.black(s)),
36
- info: makeColorFn((c, s) => c.blue(s)),
37
- trace: makeColorFn((c, s) => c.gray(s)),
38
- warn: makeColorFn((c, s) => c.yellow(s))
39
- }
40
-
41
- /**
42
- * DebugAppender Configuration
43
- */
44
- export interface DebugAppenderConfig extends ConsoleAppenderConfig {
45
- hideDate: boolean
46
- timeOnly: boolean
47
- useConsole: boolean
48
- useStdout: boolean
49
- categoryPrefix: string
50
- }
51
-
52
- /**
53
- * Partial of config, used for shortening instead of Partial<...>
54
- */
55
- export type DebugAppenderOptions = Partial<DebugAppenderConfig>
56
-
57
- const debuggers = new Map<string, Debug.Debugger>()
58
-
59
- //const debugAppPrefix = "app"
60
-
61
- function getDebug({categoryPrefix}: DebugAppenderConfig, cat: string) {
62
- let debug = debuggers.get(cat)
63
- if (!debug) {
64
- debug = Debug([categoryPrefix, cat].filter(negate(isEmpty)).join(":"))
65
- debuggers.set(cat, debug)
66
- }
67
-
68
- return debug
69
- }
70
-
71
- // const timeFormatter = new Intl.DateTimeFormat('en-US', {
72
- // timeStyle: "short"
73
- // })
74
-
75
- /**
76
- *
77
- * Get ISO date if `hideDate !== true`
78
- *
79
- * @param {DebugFormatterContext}
80
- * @returns
81
- */
82
- function getDate({ debugConfig: config }: DebugFormatterContext) {
83
- if (config.hideDate) {
84
- return ""
85
- }
86
-
87
- const date = new Date()
88
- return config.timeOnly
89
- ? date.toLocaleTimeString("default", {
90
- hour12: false
91
- })
92
- : date.toISOString()
93
- }
94
-
95
- /**
96
- *
97
- * Formats args for output, directly based on Debug.formatArgs
98
- *
99
- * @param {DebugFormatterContext} context
100
- * @param {any[]} args
101
- */
102
- function formatArgs(
103
- context: DebugFormatterContext,
104
- record: LogRecord,
105
- args: any[]
106
- ) {
107
- const { debug } = context
108
- const { namespace: name } = debug as any
109
-
110
- const prefix = colorFns[record.level](
111
- [
112
- getDate(context),
113
- Debug.humanize(debug.diff),
114
- `(` + record.level.toUpperCase() + `)`,
115
- `[${name}]`
116
- ]
117
- .filter(negate(isEmpty))
118
- .join(" ")
119
- )
120
- const msg = [prefix, args[0]].filter(negate(isEmpty)).join(" ")
121
-
122
- args[0] = msg
123
- }
124
-
125
- /**
126
- * Context for using `debugFormatter`
127
- */
128
- export type DebugFormatterContext = {
129
- debugConfig: DebugAppenderConfig
130
- debug: Debug.Debugger
131
- }
132
-
133
- /**
134
- * Uses `debug` package for logging, very useful
135
- *
136
- * @param {LogRecord} record to format
137
- * @param {DebugFormatterContext} context for this formatter
138
- * @returns
139
- */
140
- export const debugFormatter: Formatter<Array<any>, DebugFormatterContext> = (
141
- record,
142
- { debug, debugConfig: config }
143
- ): any[] => {
144
- const { level, message, data, args: argsIn, category, timestamp } = record
145
- const args = [message, ...argsIn]
146
- args[0] = Debug.coerce(args[0])
147
-
148
- if (typeof args[0] !== "string") {
149
- // Anything else let's inspect with %O
150
- args.unshift("%O")
151
- }
152
-
153
- // Apply any `formatters` transformations
154
- let index = 0
155
- args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
156
- // If we encounter an escaped % then don't increase the array index
157
- if (match === "%%") {
158
- return "%"
159
- }
160
- index++
161
- const formatter = Debug.formatters[format]
162
- if (typeof formatter === "function") {
163
- const val = args[index]
164
- match = formatter.call(debug, val)
165
-
166
- // Now we need to remove `args[index]` since it's inlined in the `format`
167
- args.splice(index, 1)
168
- index--
169
- }
170
- return match
171
- })
172
-
173
- // Apply env-specific formatting (colors, etc.)
174
- formatArgs({ debug, debugConfig: config }, record, args)
175
-
176
- return args
177
- }
178
- // [
179
- // `[${category}] (${level}) ${message}`,
180
- // ...(Array.isArray(args) ? args : [args])
181
- // ]
182
-
183
- /**
184
- * Default console config
185
- * @type {DebugAppenderConfig}
186
- */
187
- const defaultConfig: DebugAppenderConfig = {
188
- hideDate: false,
189
- timeOnly: true,
190
- useConsole: false,
191
- useStdout: true,
192
- categoryPrefix: null,
193
- ...kDefaultConsoleAppenderConfig,
194
- formatter: debugFormatter
195
- }
196
- /**
197
- * Debug appender, the simple default appender used
198
- * everywhere OOB
199
- */
200
- export class DebugAppender<Record extends LogRecord>
201
- extends ConsoleAppender<Record>
202
- implements Appender<Record>
203
- {
204
- readonly debugConfig: DebugAppenderConfig
205
-
206
-
207
- /**
208
- * Handle log records, transform, push to ES
209
- *
210
- * @param record
211
- */
212
- append(record: Record): void {
213
- const { level, message, args: argsIn, category } = record
214
-
215
- // if (!this.levels.includes(level)) {
216
- // super.append(record)
217
- // return
218
- // }
219
-
220
- const debug = getDebug(this.debugConfig, category) as any
221
- let prevTime = debug.prevTime
222
- // Set `diff` timestamp
223
- const curr = Number(new Date())
224
- const ms = curr - (prevTime || curr)
225
- debug.diff = ms
226
- debug.prev = prevTime
227
- debug.curr = curr
228
- debug.prevTime = curr
229
- const logFn = debug.log || Debug.log
230
- const args = debugFormatter!(record, { debug, debugConfig: this.debugConfig })
231
-
232
- if (this.debugConfig.useConsole) {
233
- super.write(level, ...args)
234
- }
235
-
236
- if (this.debugConfig.useStdout) {
237
- logFn.apply(debug, args)
238
- }
239
- }
240
-
241
- /**
242
- *
243
- * @param {Partial<DebugAppenderOptions>} options
244
- */
245
- constructor(options: Partial<Omit<DebugAppenderOptions, "formatter">> = {}) {
246
- super({
247
- ...defaultConfig,
248
- ...options,
249
- formatter: debugFormatter
250
- })
251
-
252
- this.debugConfig = this.config as DebugAppenderConfig
253
- }
254
- }