@orieljs/log 0.1.0-alpha.6 → 0.1.0-alpha.8

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/NOTICE CHANGED
@@ -10,3 +10,7 @@ The Oriel name and logo are not covered by that license; see TRADEMARKS.md
10
10
 
11
11
  @orieljs/support (and @orieljs/framework, which bundles it) includes transliteration data from
12
12
  voku/portable-ascii (https://github.com/voku/portable-ascii), Copyright (C) 2019 Lars Moelleken, MIT License.
13
+
14
+ @orieljs/notifications (and @orieljs/framework, which bundles it) includes the HTML and CSS of
15
+ Laravel's default notification mail (laravel/framework, https://github.com/laravel/framework),
16
+ Copyright (c) Taylor Otwell, MIT License.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @orieljs/log
2
+
3
+ Logging for Oriel: the `Log` facade over named channels, written with pino. It is Oriel's counterpart of Laravel's logger. Log is part of `@orieljs/framework`, which every Oriel app already installs, and is re-exported from it. In an app, import it from `@orieljs/framework`; `@orieljs/log` is also published on its own.
4
+
5
+ ```bash
6
+ npm install @orieljs/framework
7
+ ```
8
+
9
+ ```ts title="app/Jobs/TranscodePodcast.ts"
10
+ import { Log, Queueable } from '@orieljs/framework'
11
+ import type { Podcast } from '../Models/Podcast'
12
+
13
+ export class TranscodePodcast extends Queueable {
14
+ constructor(public podcast: Podcast) {
15
+ super()
16
+ }
17
+
18
+ async handle(): Promise<void> {
19
+ Log.withContext({ podcast: this.podcast.id })
20
+ Log.info('Transcoding', { path: this.podcast.audio_path })
21
+ if (!this.podcast.audio_path.endsWith('.mp3')) Log.channel('daily').warning('Not an MP3 file')
22
+ }
23
+ }
24
+ ```
25
+
26
+ `Log` has a method for each level, from `debug()` to `emergency()`, and `log(level, message)`. `Log.channel(name)` and `Log.stack(names)` pick channels from `config/logging.ts` (the drivers are `single`, `daily`, `stderr`, `stack` and `null`), and `Log.withContext()` adds context to the later entries of the current request or job. `logger(message)` logs at `debug`.
27
+
28
+ Documentation: https://orieljs.vercel.app/docs/logging
29
+
30
+ Status: early alpha. APIs will change.
31
+
32
+ ## License
33
+
34
+ Oriel is open-source software licensed under the Apache License 2.0 (Apache-2.0; see `LICENSE` and `NOTICE`). The Oriel name and logo are trademarks; see `TRADEMARKS.md`.
35
+
36
+ Website: https://orieljs.vercel.app
package/TRADEMARKS.md ADDED
@@ -0,0 +1,33 @@
1
+ # Oriel trademark policy
2
+
3
+ The Oriel code is open source under the Apache License 2.0. The **Oriel name and logo** are not: the license covers
4
+ the code only (section 6 of the license says so), and the name and logo stay with the project. This page explains
5
+ what you can and can't do with them. The goal is simple: people should always be able to tell what is the real Oriel
6
+ and what isn't.
7
+
8
+ ## You can, without asking
9
+
10
+ - Use, change, ship and sell the code, as the license allows.
11
+ - Say that your app or package is "built with Oriel", "for Oriel" or "compatible with Oriel".
12
+ - Name a package `oriel-<something>` or `<something>-for-oriel` when it works with Oriel, as long as it is clear that
13
+ it is not official (for example, don't publish it under the `@orieljs` npm scope).
14
+ - Use the name and logo to write about Oriel, teach it, or link to it, in articles, talks, videos and courses.
15
+ - Use the unmodified logo to point to the project, as it is (no recolouring, cropping or
16
+ distortion).
17
+
18
+ ## You can't, without written permission
19
+
20
+ - Call a fork, a modified copy or a competing product "Oriel", or anything likely to be confused with it.
21
+ - Use the name or logo as the name, logo or domain of your own product, company or service.
22
+ - Suggest that the Oriel project made, endorses or supports your work when it doesn't.
23
+ - Sell merchandise with the name or logo.
24
+
25
+ ## Forks
26
+
27
+ Forks are welcome. Please give yours a different name and logo, keep the `LICENSE` and `NOTICE` files, and say that
28
+ it is based on Oriel.
29
+
30
+ ## Questions
31
+
32
+ Open an issue at https://github.com/orieljs/framework or email meeeet.dev@gmail.com. If you're unsure whether a use
33
+ is fine, ask; the answer is usually yes.
package/dist/index.js CHANGED
@@ -506,6 +506,10 @@ var LogServiceProvider = class extends ServiceProvider {
506
506
  "logging"
507
507
  );
508
508
  this.app.singleton(LogManagerToken3, (container) => new LogManager(container));
509
+ this.app.onShutdown(async () => {
510
+ if (!this.app.resolved(LogManagerToken3)) return;
511
+ await this.app.make(LogManagerToken3).flush?.();
512
+ });
509
513
  }
510
514
  };
511
515
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../context.ts","../errors.ts","../levels.ts","../BaseLogger.ts","../channels.ts","../DailyRotatingStream.ts","../writeFailure.ts","../flush.ts","../PinoLogger.ts","../facade.ts","../LogManager.ts","../NullLogger.ts","../StackLogger.ts","../LogServiceProvider.ts"],"sourcesContent":["import { currentContainer } from '@orieljs/container'\n\n/** Used as the WeakMap key when there is no current container at all (context added outside any scope). */\nconst rootKey: object = {}\n\n/**\n * Log context, keyed by the current scope. `Application.handle()` creates a fresh child container per request\n * (`this.createScope()`) and runs the kernel inside `scope.run(...)`, so `currentContainer()` returns a distinct\n * object per in-flight request; two concurrent requests never share a key here, so context added during one never\n * leaks into the other. Outside of any scope (CLI, boot), everything shares `rootKey`.\n */\nconst contexts = new WeakMap<object, Record<string, unknown>>()\n\n/** Merges `context` into the log context for the current scope (Laravel's `Log::withContext()`). */\nexport function mergeLogContext(context: Record<string, unknown>): void {\n const key = currentContainer() ?? rootKey\n contexts.set(key, { ...contexts.get(key), ...context })\n}\n\n/** The merged log context for the current scope, or `{}` if none has been added. */\nexport function currentLogContext(): Record<string, unknown> {\n return contexts.get(currentContainer() ?? rootKey) ?? {}\n}\n","import type { ErrorKind, OrielError } from '@orieljs/contracts'\n\nexport class UnknownLogChannelError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly channel: string) {\n super(`Log channel [${channel}] is not defined in config('logging.channels').`)\n this.name = 'UnknownLogChannelError'\n }\n}\n\nexport class UnknownLogDriverError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly driver: string) {\n super(`Log driver [${driver}] is not registered.`)\n this.name = 'UnknownLogDriverError'\n }\n}\n\nexport class LogChannelCycleError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly channel: string) {\n super(`Log channel [${channel}] includes itself.`)\n this.name = 'LogChannelCycleError'\n }\n}\n\nexport class InvalidLogLevelError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly level: string) {\n super(`Invalid log level [${level}].`)\n this.name = 'InvalidLogLevelError'\n }\n}\n","import type { LogLevel } from '@orieljs/contracts'\nimport { InvalidLogLevelError } from './errors'\n\n/** RFC 5424 severities, most severe first. Higher numbers are more severe. */\nexport const LEVEL_SEVERITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n notice: 30,\n warning: 40,\n error: 50,\n critical: 60,\n alert: 70,\n emergency: 80,\n}\n\n/** Throws `InvalidLogLevelError` unless `level` is one of the eight RFC 5424 names (no aliases like `warn`). */\nexport function assertLogLevel(level: unknown): asserts level is LogLevel {\n if (typeof level !== 'string' || !Object.hasOwn(LEVEL_SEVERITY, level)) throw new InvalidLogLevelError(String(level))\n}\n\n/** True when `level` is at least as severe as `minimum` (e.g. `error` meets a `warning` threshold). */\nexport function meetsLevel(level: LogLevel, minimum: LogLevel): boolean {\n return LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[minimum]\n}\n\n/**\n * `Error` objects don't survive `JSON.stringify` (message/stack/name aren't own enumerable properties), so any\n * `Error` values directly on the context object are expanded one level deep into a plain `{ name, message, stack }`.\n * This is how `LogManager.error(message, { exception })` (Http's exception handler) ends up readable in log output.\n */\nexport function serializeContext(context: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!context) return {}\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(context)) {\n result[key] = value instanceof Error ? { name: value.name, message: value.message, stack: value.stack } : value\n }\n return result\n}\n","import type { Logger, LogLevel } from '@orieljs/contracts'\nimport { currentLogContext, mergeLogContext } from './context'\nimport { assertLogLevel, meetsLevel, serializeContext } from './levels'\n\n/**\n * Implements the full `Logger` contract on top of one `write()` method: level filtering, merging in the current\n * scope's context (`context.ts`) and serializing `Error` values (`levels.ts`) all happen here, once.\n */\nexport abstract class BaseLogger implements Logger {\n constructor(protected readonly minimumLevel: LogLevel = 'debug') {\n assertLogLevel(minimumLevel)\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!meetsLevel(level, this.minimumLevel)) return\n this.write(level, message, serializeContext({ ...currentLogContext(), ...context }))\n }\n\n emergency(message: string, context?: Record<string, unknown>): void {\n this.log('emergency', message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.log('alert', message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.log('critical', message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.log('warning', message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.log('notice', message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context)\n }\n\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n\n /** Called only when `level` already meets this logger's configured minimum, with context fully resolved. */\n protected abstract write(level: LogLevel, message: string, context: Record<string, unknown>): void\n}\n","import pino from 'pino'\nimport type { LogLevel } from '@orieljs/contracts'\nimport { DailyRotatingStream } from './DailyRotatingStream'\nimport { destinationCloser, writableCloser } from './flush'\nimport { assertLogLevel } from './levels'\nimport { PinoLogger } from './PinoLogger'\nimport { reportLogWriteFailure } from './writeFailure'\n\n/** Pino passes everything through; `BaseLogger` already filtered by the channel's own minimum level. */\nconst PINO_OPTIONS = { level: 'debug' } as const\n\n/** The `single` channel: everything appended to one file, e.g. `storage/logs/oriel.log`. */\nexport function createSingleChannel(path: string, minimumLevel: LogLevel = 'debug'): PinoLogger {\n assertLogLevel(minimumLevel) // before opening the file, so a rejected channel leaves nothing open\n const destination = pino.destination({ dest: path, mkdir: true, sync: false })\n // Without a listener, an I/O error on the destination (EACCES, ENOTDIR, disk full, ...) is re-emitted as an\n // unhandled 'error' event and takes the process down.\n destination.on('error', (error: Error) => reportLogWriteFailure(path, error))\n return new PinoLogger(pino(PINO_OPTIONS, destination), minimumLevel, destinationCloser(destination))\n}\n\n/** The `daily` channel: one file per day under the same directory, pruned after `days`. */\nexport function createDailyChannel(path: string, days = 14, minimumLevel: LogLevel = 'debug', now?: () => Date): PinoLogger {\n assertLogLevel(minimumLevel)\n const stream = new DailyRotatingStream(path, days, now)\n return new PinoLogger(pino(PINO_OPTIONS, stream), minimumLevel, writableCloser(stream))\n}\n\n/** The `stderr` channel. */\nexport function createStderrChannel(minimumLevel: LogLevel = 'debug'): PinoLogger {\n assertLogLevel(minimumLevel)\n const destination = pino.destination({ dest: 2, sync: false })\n // Nowhere left to report a failure writing to stderr itself, so it's swallowed rather than crashing the process.\n destination.on('error', () => {})\n return new PinoLogger(pino(PINO_OPTIONS, destination), minimumLevel, destinationCloser(destination))\n}\n","import { createWriteStream, mkdirSync, readdirSync, rmSync, type WriteStream } from 'node:fs'\nimport { basename, dirname, extname, join } from 'node:path'\nimport { Writable } from 'node:stream'\nimport { reportLogWriteFailure } from './writeFailure'\n\n/** `YYYY-MM-DD` for the local calendar day of `date`. */\nfunction localDay(date: Date): string {\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${date.getFullYear()}-${month}-${day}`\n}\n\nconst DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/**\n * Writes to `<dir>/<stem>-<YYYY-MM-DD>.log`, switching files when the local calendar day changes and deleting files\n * older than `days` each time it rolls over. `now` is injectable so tests can simulate day boundaries without a\n * fake timer.\n */\nexport class DailyRotatingStream extends Writable {\n private readonly dir: string\n private readonly stem: string\n private currentDate = ''\n private stream: WriteStream | undefined\n /**\n * The in-flight `_write()`'s callback, if any, tagged with the exact child stream it was issued for. Resolved\n * either by that stream's own write completing or by that same stream's `'error'` listener, whichever comes\n * first, so a write can never hang on a broken destination. Scoping it to `stream` (rather than just tracking\n * \"the current callback\") matters across a rollover: a superseded stream can still emit a late `'error'` (e.g.\n * a failed flush during its fire-and-forget `end()`) after a write is already pending on the *new* stream, and\n * that stale error must only produce its own stderr notice, never resolve someone else's pending write.\n */\n private pending: { readonly stream: WriteStream; readonly callback: () => void } | undefined\n\n constructor(\n basePath: string,\n private readonly days: number,\n private readonly now: () => Date = () => new Date(),\n ) {\n super()\n this.dir = dirname(basePath)\n this.stem = basename(basePath, extname(basePath) || undefined)\n mkdirSync(this.dir, { recursive: true })\n }\n\n private pathFor(date: string): string {\n return join(this.dir, `${this.stem}-${date}.log`)\n }\n\n private today(): string {\n return localDay(this.now())\n }\n\n /**\n * Opens the file at `path` and attaches an `'error'` listener so an I/O failure (disk full, EACCES, EISDIR, ...)\n * on this one child stream can never crash the process: it's reported as a one-line notice on `process.stderr`,\n * the stream is dropped (the next write reopens it), and it is never re-emitted on `this`.\n *\n * `protected` rather than `private` only so a test can subclass and capture the real child streams this opens\n * (node:fs's ESM module namespace can't be `vi.spyOn()`'d), to simulate a stream retired by rollover emitting a\n * late error while a write is already pending on its replacement.\n */\n protected openStream(path: string): WriteStream {\n const stream = createWriteStream(path, { flags: 'a' })\n stream.on('error', (error: Error) => {\n reportLogWriteFailure(path, error)\n if (this.stream === stream) this.stream = undefined\n if (this.pending?.stream === stream) {\n const { callback } = this.pending\n this.pending = undefined\n callback()\n }\n })\n return stream\n }\n\n private ensureStream(): WriteStream {\n const date = this.today()\n const dateChanged = date !== this.currentDate\n if (dateChanged || !this.stream) {\n this.stream?.end()\n this.currentDate = date\n this.stream = this.openStream(this.pathFor(date))\n if (dateChanged) this.prune()\n }\n return this.stream\n }\n\n /**\n * Deletes this channel's files dated before the oldest of the `days` most recent local days (today included).\n * Only names that are exactly `<stem>-<YYYY-MM-DD>.log` count, so a sibling channel sharing the prefix\n * (e.g. `oriel-worker-<date>.log` next to `oriel-<date>.log`) is never touched.\n */\n private prune(): void {\n if (this.days <= 0) return\n const prefix = `${this.stem}-`\n const now = this.now()\n const cutoff = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (this.days - 1)).getTime()\n for (const file of readdirSync(this.dir)) {\n if (!file.startsWith(prefix) || !file.endsWith('.log')) continue\n const match = DATE_PATTERN.exec(file.slice(prefix.length, -'.log'.length))\n if (!match) continue\n const time = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])).getTime()\n if (time < cutoff) rmSync(join(this.dir, file), { force: true })\n }\n }\n\n override _write(chunk: unknown, encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n const stream = this.ensureStream()\n this.pending = { stream, callback: () => callback() }\n stream.write(chunk as Uint8Array, encoding, () => {\n if (this.pending?.stream === stream) {\n this.pending = undefined\n callback()\n }\n })\n }\n\n override _final(callback: (error?: Error | null) => void): void {\n const stream = this.stream\n if (!stream) {\n callback()\n return\n }\n let done = false\n const finish = () => {\n if (done) return\n done = true\n callback()\n }\n stream.once('finish', finish)\n stream.once('error', finish)\n stream.end()\n }\n}\n","/** Reports a log destination I/O failure as one line on `process.stderr`, so it never crashes the process. */\nexport function reportLogWriteFailure(path: string, error: Error): void {\n process.stderr.write(`Unable to write log file ${path}: ${error.message}\\n`)\n}\n","import type { Writable } from 'node:stream'\nimport type pino from 'pino'\n\n/** pino's file and stderr destinations (SonicBoom). */\ntype Destination = ReturnType<typeof pino.destination>\n\n/**\n * What flush() does for one pino destination, set up as soon as the destination exists so it sees the file open or\n * fail. SonicBoom opens a file asynchronously and holds the lines until then: a process that exits first loses them,\n * and pino's exit hook throws \"sonic boom is not ready yet\", which Bun turns into exit code 1. The returned function\n * waits for the open, ends the destination, and resolves once everything it held is written and the file is closed.\n * It never rejects (a failure was already reported by the destination's own 'error' listener), and calling it again\n * returns the same promise.\n */\nexport function destinationCloser(destination: Destination): () => Promise<void> {\n const opened = new Promise<boolean>((resolve) => {\n const onReady = () => {\n destination.off('error', onError)\n resolve(true)\n }\n const onError = () => {\n destination.off('ready', onReady)\n // It never opened, so pino's exit hook would throw on flushSync(); pino itself does this for a broken pipe.\n destination.flushSync = () => {}\n resolve(false)\n }\n destination.once('ready', onReady)\n destination.once('error', onError)\n })\n let closing: Promise<void> | undefined\n const close = async (): Promise<void> => {\n if (!(await opened)) return\n await new Promise<void>((resolve) => {\n destination.once('close', () => resolve())\n destination.once('error', () => resolve())\n destination.end()\n })\n }\n return () => (closing ??= close())\n}\n\n/** The same for a Node stream (the daily channel's): ends it and resolves once it has finished. Never rejects. */\nexport function writableCloser(stream: Writable): () => Promise<void> {\n let closing: Promise<void> | undefined\n const close = () =>\n new Promise<void>((resolve) => {\n if (stream.writableFinished || stream.destroyed) return resolve()\n stream.once('finish', () => resolve())\n stream.once('error', () => resolve())\n stream.end()\n })\n return () => (closing ??= close())\n}\n","import pino from 'pino'\nimport type { LogLevel } from '@orieljs/contracts'\nimport { BaseLogger } from './BaseLogger'\n\n/** Maps an RFC 5424 level onto pino's own (narrower) level methods. The real level is kept in the payload. */\nconst PINO_METHOD: Record<LogLevel, 'fatal' | 'error' | 'warn' | 'info' | 'debug'> = {\n emergency: 'fatal',\n alert: 'fatal',\n critical: 'fatal',\n error: 'error',\n warning: 'warn',\n notice: 'info',\n info: 'info',\n debug: 'debug',\n}\n\n/** A channel backed by a pino logger writing to an arbitrary destination stream (file, stderr, ...). */\nexport class PinoLogger extends BaseLogger {\n private flushing: Promise<void> | undefined\n\n constructor(\n private readonly pinoInstance: pino.Logger,\n minimumLevel: LogLevel = 'debug',\n /** Writes out and closes the destination; the channel factories pass one for each destination they open. */\n private readonly closeDestination: () => Promise<void> = async () => {},\n ) {\n super(minimumLevel)\n }\n\n /**\n * Writes out every entry still buffered and closes the destination. pino writes asynchronously, so a process\n * awaits this before it exits (runConsoleAndExit does). The channel takes no entries afterwards: they're dropped.\n * Not in Laravel, whose handlers write synchronously.\n */\n flush(): Promise<void> {\n return (this.flushing ??= this.closeDestination())\n }\n\n protected write(level: LogLevel, message: string, context: Record<string, unknown>): void {\n if (this.flushing) return\n this.pinoInstance[PINO_METHOD[level]]({ ...context, rfc5424Level: level }, message)\n }\n}\n","import type { LogManager } from '@orieljs/contracts'\nimport { LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { facade } from '@orieljs/support'\n\n/** The `Log` facade (Laravel's `Illuminate\\Support\\Facades\\Log`). `Log.channel('single').info(...)`. */\nexport const Log = facade<LogManager>(LogManagerToken)\n\n/** With no args, the LogManager itself. With a message, logs it at `debug` (Laravel's `logger()` helper). */\nexport function logger(): LogManager\nexport function logger(message: string, context?: Record<string, unknown>): void\nexport function logger(message?: string, context?: Record<string, unknown>): LogManager | void {\n const manager = inject(LogManagerToken)\n if (message === undefined) return manager\n manager.debug(message, context)\n}\n","import type { Container, Logger, LogLevel } from '@orieljs/contracts'\nimport { ConfigRepository, LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { createDailyChannel, createSingleChannel, createStderrChannel } from './channels'\nimport { mergeLogContext } from './context'\nimport { LogChannelCycleError, UnknownLogChannelError, UnknownLogDriverError } from './errors'\nimport { NullLogger } from './NullLogger'\nimport { StackLogger } from './StackLogger'\n\ntype ChannelConfig = Record<string, unknown>\ntype Driver = (config: ChannelConfig) => Logger\n\n/** A channel holding buffered entries (PinoLogger); the null and stack channels have nothing of their own. */\ninterface Flushable {\n flush(): Promise<void>\n}\nconst isFlushable = (channel: Logger): channel is Logger & Flushable => typeof (channel as Partial<Flushable>).flush === 'function'\n\ninterface LoggingConfig {\n default: string\n channels: Record<string, ChannelConfig>\n}\n\nconst level = (config: ChannelConfig): LogLevel => (config.level as LogLevel | undefined) ?? 'debug'\n\n/** `LogManager`: resolves channels by name from `config('logging')`, lazily and cached. */\nexport class LogManager implements LogManagerToken {\n private readonly channels = new Map<string, Logger>()\n private readonly drivers = new Map<string, Driver>()\n private readonly resolving = new Set<string>()\n\n constructor(private readonly container: Container) {\n this.drivers.set('single', (config) => createSingleChannel(String(config.path ?? ''), level(config)))\n this.drivers.set('daily', (config) => createDailyChannel(String(config.path ?? ''), Number(config.days ?? 14), level(config)))\n this.drivers.set('stderr', (config) => createStderrChannel(level(config)))\n this.drivers.set('null', () => new NullLogger())\n this.drivers.set('stack', (config) => this.stack((config.channels as string[] | undefined) ?? []))\n }\n\n private loggingConfig(): LoggingConfig {\n return this.container.make(ConfigRepository).get<LoggingConfig>('logging', { default: 'stack', channels: {} })\n }\n\n channel(name?: string): Logger {\n const loggingConfig = this.loggingConfig()\n const channelName = name ?? loggingConfig.default\n let channel = this.channels.get(channelName)\n if (!channel) {\n if (this.resolving.has(channelName)) throw new LogChannelCycleError(channelName)\n const channelConfig = loggingConfig.channels[channelName]\n if (!channelConfig) throw new UnknownLogChannelError(channelName)\n const driverName = channelConfig.driver as string | undefined\n const driver = driverName ? this.drivers.get(driverName) : undefined\n if (!driver) throw new UnknownLogDriverError(String(driverName))\n this.resolving.add(channelName)\n try {\n channel = driver(channelConfig)\n } finally {\n this.resolving.delete(channelName)\n }\n this.channels.set(channelName, channel)\n }\n return channel\n }\n\n stack(channels: string[]): Logger {\n return new StackLogger(channels.map((name) => this.channel(name)))\n }\n\n /**\n * Writes out and closes every channel resolved so far, then forgets them, so the next entry opens its file again.\n * pino writes asynchronously, so a console process awaits this before it exits (runConsoleAndExit does). Not in\n * Laravel, whose handlers write synchronously.\n */\n async flush(): Promise<void> {\n const channels = [...this.channels.values()]\n this.channels.clear()\n await Promise.all(channels.filter(isFlushable).map((channel) => channel.flush()))\n }\n\n log(logLevel: LogLevel, message: string, context?: Record<string, unknown>): void {\n this.channel().log(logLevel, message, context)\n }\n emergency(message: string, context?: Record<string, unknown>): void {\n this.channel().emergency(message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.channel().alert(message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.channel().critical(message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.channel().error(message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.channel().warning(message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.channel().notice(message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.channel().info(message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.channel().debug(message, context)\n }\n\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n}\n","import { BaseLogger } from './BaseLogger'\n\n/** The `null` channel: discards every entry (Laravel's `NullHandler`). */\nexport class NullLogger extends BaseLogger {\n protected write(): void {\n // Intentionally does nothing.\n }\n}\n","import type { Logger, LogLevel } from '@orieljs/contracts'\nimport { mergeLogContext } from './context'\n\n/** `Log.stack([...])`: fans every entry out to each constituent channel, which does its own level filtering. */\nexport class StackLogger implements Logger {\n constructor(private readonly channels: Logger[]) {}\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n for (const channel of this.channels) channel.log(level, message, context)\n }\n emergency(message: string, context?: Record<string, unknown>): void {\n this.log('emergency', message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.log('alert', message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.log('critical', message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.log('warning', message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.log('notice', message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context)\n }\n\n /** Context is scoped by the container (see context.ts), not per-instance, so this affects every channel. */\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n}\n","import { LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { LogManager } from './LogManager'\n\n/** Binds the LogManager and merges Laravel 11's `logging` defaults (stack -> single, LOG_LEVEL=debug). */\nexport class LogServiceProvider extends ServiceProvider {\n override register(): void {\n const level = process.env.LOG_LEVEL ?? 'debug'\n this.mergeConfigFrom(\n {\n default: process.env.LOG_CHANNEL ?? 'stack',\n channels: {\n stack: { driver: 'stack', channels: (process.env.LOG_STACK ?? 'single').split(',') },\n single: { driver: 'single', path: this.app.storagePath('logs/oriel.log'), level },\n daily: { driver: 'daily', path: this.app.storagePath('logs/oriel.log'), level, days: 14 },\n stderr: { driver: 'stderr', level },\n null: { driver: 'null' },\n },\n },\n 'logging',\n )\n this.app.singleton(LogManagerToken, (container) => new LogManager(container))\n }\n}\n"],"mappings":"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","names":["level","level","level","pino","level","pino","level","LogManagerToken","level","LogManagerToken"]}
1
+ {"version":3,"sources":["../context.ts","../errors.ts","../levels.ts","../BaseLogger.ts","../channels.ts","../DailyRotatingStream.ts","../writeFailure.ts","../flush.ts","../PinoLogger.ts","../facade.ts","../LogManager.ts","../NullLogger.ts","../StackLogger.ts","../LogServiceProvider.ts"],"sourcesContent":["import { currentContainer } from '@orieljs/container'\n\n/** Used as the WeakMap key when there is no current container at all (context added outside any scope). */\nconst rootKey: object = {}\n\n/**\n * Log context, keyed by the current scope. `Application.handle()` creates a fresh child container per request\n * (`this.createScope()`) and runs the kernel inside `scope.run(...)`, so `currentContainer()` returns a distinct\n * object per in-flight request; two concurrent requests never share a key here, so context added during one never\n * leaks into the other. Outside of any scope (CLI, boot), everything shares `rootKey`.\n */\nconst contexts = new WeakMap<object, Record<string, unknown>>()\n\n/** Merges `context` into the log context for the current scope (Laravel's `Log::withContext()`). */\nexport function mergeLogContext(context: Record<string, unknown>): void {\n const key = currentContainer() ?? rootKey\n contexts.set(key, { ...contexts.get(key), ...context })\n}\n\n/** The merged log context for the current scope, or `{}` if none has been added. */\nexport function currentLogContext(): Record<string, unknown> {\n return contexts.get(currentContainer() ?? rootKey) ?? {}\n}\n","import type { ErrorKind, OrielError } from '@orieljs/contracts'\n\nexport class UnknownLogChannelError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly channel: string) {\n super(`Log channel [${channel}] is not defined in config('logging.channels').`)\n this.name = 'UnknownLogChannelError'\n }\n}\n\nexport class UnknownLogDriverError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly driver: string) {\n super(`Log driver [${driver}] is not registered.`)\n this.name = 'UnknownLogDriverError'\n }\n}\n\nexport class LogChannelCycleError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly channel: string) {\n super(`Log channel [${channel}] includes itself.`)\n this.name = 'LogChannelCycleError'\n }\n}\n\nexport class InvalidLogLevelError extends Error implements OrielError {\n readonly kind: ErrorKind = 'Server'\n constructor(readonly level: string) {\n super(`Invalid log level [${level}].`)\n this.name = 'InvalidLogLevelError'\n }\n}\n","import type { LogLevel } from '@orieljs/contracts'\nimport { InvalidLogLevelError } from './errors'\n\n/** RFC 5424 severities, most severe first. Higher numbers are more severe. */\nexport const LEVEL_SEVERITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n notice: 30,\n warning: 40,\n error: 50,\n critical: 60,\n alert: 70,\n emergency: 80,\n}\n\n/** Throws `InvalidLogLevelError` unless `level` is one of the eight RFC 5424 names (no aliases like `warn`). */\nexport function assertLogLevel(level: unknown): asserts level is LogLevel {\n if (typeof level !== 'string' || !Object.hasOwn(LEVEL_SEVERITY, level)) throw new InvalidLogLevelError(String(level))\n}\n\n/** True when `level` is at least as severe as `minimum` (e.g. `error` meets a `warning` threshold). */\nexport function meetsLevel(level: LogLevel, minimum: LogLevel): boolean {\n return LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[minimum]\n}\n\n/**\n * `Error` objects don't survive `JSON.stringify` (message/stack/name aren't own enumerable properties), so any\n * `Error` values directly on the context object are expanded one level deep into a plain `{ name, message, stack }`.\n * This is how `LogManager.error(message, { exception })` (Http's exception handler) ends up readable in log output.\n */\nexport function serializeContext(context: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!context) return {}\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(context)) {\n result[key] = value instanceof Error ? { name: value.name, message: value.message, stack: value.stack } : value\n }\n return result\n}\n","import type { Logger, LogLevel } from '@orieljs/contracts'\nimport { currentLogContext, mergeLogContext } from './context'\nimport { assertLogLevel, meetsLevel, serializeContext } from './levels'\n\n/**\n * Implements the full `Logger` contract on top of one `write()` method: level filtering, merging in the current\n * scope's context (`context.ts`) and serializing `Error` values (`levels.ts`) all happen here, once.\n */\nexport abstract class BaseLogger implements Logger {\n constructor(protected readonly minimumLevel: LogLevel = 'debug') {\n assertLogLevel(minimumLevel)\n }\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n if (!meetsLevel(level, this.minimumLevel)) return\n this.write(level, message, serializeContext({ ...currentLogContext(), ...context }))\n }\n\n emergency(message: string, context?: Record<string, unknown>): void {\n this.log('emergency', message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.log('alert', message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.log('critical', message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.log('warning', message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.log('notice', message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context)\n }\n\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n\n /** Called only when `level` already meets this logger's configured minimum, with context fully resolved. */\n protected abstract write(level: LogLevel, message: string, context: Record<string, unknown>): void\n}\n","import pino from 'pino'\nimport type { LogLevel } from '@orieljs/contracts'\nimport { DailyRotatingStream } from './DailyRotatingStream'\nimport { destinationCloser, writableCloser } from './flush'\nimport { assertLogLevel } from './levels'\nimport { PinoLogger } from './PinoLogger'\nimport { reportLogWriteFailure } from './writeFailure'\n\n/** Pino passes everything through; `BaseLogger` already filtered by the channel's own minimum level. */\nconst PINO_OPTIONS = { level: 'debug' } as const\n\n/** The `single` channel: everything appended to one file, e.g. `storage/logs/oriel.log`. */\nexport function createSingleChannel(path: string, minimumLevel: LogLevel = 'debug'): PinoLogger {\n assertLogLevel(minimumLevel) // before opening the file, so a rejected channel leaves nothing open\n const destination = pino.destination({ dest: path, mkdir: true, sync: false })\n // Without a listener, an I/O error on the destination (EACCES, ENOTDIR, disk full, ...) is re-emitted as an\n // unhandled 'error' event and takes the process down.\n destination.on('error', (error: Error) => reportLogWriteFailure(path, error))\n return new PinoLogger(pino(PINO_OPTIONS, destination), minimumLevel, destinationCloser(destination))\n}\n\n/** The `daily` channel: one file per day under the same directory, pruned after `days`. */\nexport function createDailyChannel(path: string, days = 14, minimumLevel: LogLevel = 'debug', now?: () => Date): PinoLogger {\n assertLogLevel(minimumLevel)\n const stream = new DailyRotatingStream(path, days, now)\n return new PinoLogger(pino(PINO_OPTIONS, stream), minimumLevel, writableCloser(stream))\n}\n\n/** The `stderr` channel. */\nexport function createStderrChannel(minimumLevel: LogLevel = 'debug'): PinoLogger {\n assertLogLevel(minimumLevel)\n const destination = pino.destination({ dest: 2, sync: false })\n // Nowhere left to report a failure writing to stderr itself, so it's swallowed rather than crashing the process.\n destination.on('error', () => {})\n return new PinoLogger(pino(PINO_OPTIONS, destination), minimumLevel, destinationCloser(destination))\n}\n","import { createWriteStream, mkdirSync, readdirSync, rmSync, type WriteStream } from 'node:fs'\nimport { basename, dirname, extname, join } from 'node:path'\nimport { Writable } from 'node:stream'\nimport { reportLogWriteFailure } from './writeFailure'\n\n/** `YYYY-MM-DD` for the local calendar day of `date`. */\nfunction localDay(date: Date): string {\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${date.getFullYear()}-${month}-${day}`\n}\n\nconst DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/**\n * Writes to `<dir>/<stem>-<YYYY-MM-DD>.log`, switching files when the local calendar day changes and deleting files\n * older than `days` each time it rolls over. `now` is injectable so tests can simulate day boundaries without a\n * fake timer.\n */\nexport class DailyRotatingStream extends Writable {\n private readonly dir: string\n private readonly stem: string\n private currentDate = ''\n private stream: WriteStream | undefined\n /**\n * The in-flight `_write()`'s callback, if any, tagged with the exact child stream it was issued for. Resolved\n * either by that stream's own write completing or by that same stream's `'error'` listener, whichever comes\n * first, so a write can never hang on a broken destination. Scoping it to `stream` (rather than just tracking\n * \"the current callback\") matters across a rollover: a superseded stream can still emit a late `'error'` (e.g.\n * a failed flush during its fire-and-forget `end()`) after a write is already pending on the *new* stream, and\n * that stale error must only produce its own stderr notice, never resolve someone else's pending write.\n */\n private pending: { readonly stream: WriteStream; readonly callback: () => void } | undefined\n\n constructor(\n basePath: string,\n private readonly days: number,\n private readonly now: () => Date = () => new Date(),\n ) {\n super()\n this.dir = dirname(basePath)\n this.stem = basename(basePath, extname(basePath) || undefined)\n mkdirSync(this.dir, { recursive: true })\n }\n\n private pathFor(date: string): string {\n return join(this.dir, `${this.stem}-${date}.log`)\n }\n\n private today(): string {\n return localDay(this.now())\n }\n\n /**\n * Opens the file at `path` and attaches an `'error'` listener so an I/O failure (disk full, EACCES, EISDIR, ...)\n * on this one child stream can never crash the process: it's reported as a one-line notice on `process.stderr`,\n * the stream is dropped (the next write reopens it), and it is never re-emitted on `this`.\n *\n * `protected` rather than `private` only so a test can subclass and capture the real child streams this opens\n * (node:fs's ESM module namespace can't be `vi.spyOn()`'d), to simulate a stream retired by rollover emitting a\n * late error while a write is already pending on its replacement.\n */\n protected openStream(path: string): WriteStream {\n const stream = createWriteStream(path, { flags: 'a' })\n stream.on('error', (error: Error) => {\n reportLogWriteFailure(path, error)\n if (this.stream === stream) this.stream = undefined\n if (this.pending?.stream === stream) {\n const { callback } = this.pending\n this.pending = undefined\n callback()\n }\n })\n return stream\n }\n\n private ensureStream(): WriteStream {\n const date = this.today()\n const dateChanged = date !== this.currentDate\n if (dateChanged || !this.stream) {\n this.stream?.end()\n this.currentDate = date\n this.stream = this.openStream(this.pathFor(date))\n if (dateChanged) this.prune()\n }\n return this.stream\n }\n\n /**\n * Deletes this channel's files dated before the oldest of the `days` most recent local days (today included).\n * Only names that are exactly `<stem>-<YYYY-MM-DD>.log` count, so a sibling channel sharing the prefix\n * (e.g. `oriel-worker-<date>.log` next to `oriel-<date>.log`) is never touched.\n */\n private prune(): void {\n if (this.days <= 0) return\n const prefix = `${this.stem}-`\n const now = this.now()\n const cutoff = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (this.days - 1)).getTime()\n for (const file of readdirSync(this.dir)) {\n if (!file.startsWith(prefix) || !file.endsWith('.log')) continue\n const match = DATE_PATTERN.exec(file.slice(prefix.length, -'.log'.length))\n if (!match) continue\n const time = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])).getTime()\n if (time < cutoff) rmSync(join(this.dir, file), { force: true })\n }\n }\n\n override _write(chunk: unknown, encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n const stream = this.ensureStream()\n this.pending = { stream, callback: () => callback() }\n stream.write(chunk as Uint8Array, encoding, () => {\n if (this.pending?.stream === stream) {\n this.pending = undefined\n callback()\n }\n })\n }\n\n override _final(callback: (error?: Error | null) => void): void {\n const stream = this.stream\n if (!stream) {\n callback()\n return\n }\n let done = false\n const finish = () => {\n if (done) return\n done = true\n callback()\n }\n stream.once('finish', finish)\n stream.once('error', finish)\n stream.end()\n }\n}\n","/** Reports a log destination I/O failure as one line on `process.stderr`, so it never crashes the process. */\nexport function reportLogWriteFailure(path: string, error: Error): void {\n process.stderr.write(`Unable to write log file ${path}: ${error.message}\\n`)\n}\n","import type { Writable } from 'node:stream'\nimport type pino from 'pino'\n\n/** pino's file and stderr destinations (SonicBoom). */\ntype Destination = ReturnType<typeof pino.destination>\n\n/**\n * What flush() does for one pino destination, set up as soon as the destination exists so it sees the file open or\n * fail. SonicBoom opens a file asynchronously and holds the lines until then: a process that exits first loses them,\n * and pino's exit hook throws \"sonic boom is not ready yet\", which Bun turns into exit code 1. The returned function\n * waits for the open, ends the destination, and resolves once everything it held is written and the file is closed.\n * It never rejects (a failure was already reported by the destination's own 'error' listener), and calling it again\n * returns the same promise.\n */\nexport function destinationCloser(destination: Destination): () => Promise<void> {\n const opened = new Promise<boolean>((resolve) => {\n const onReady = () => {\n destination.off('error', onError)\n resolve(true)\n }\n const onError = () => {\n destination.off('ready', onReady)\n // It never opened, so pino's exit hook would throw on flushSync(); pino itself does this for a broken pipe.\n destination.flushSync = () => {}\n resolve(false)\n }\n destination.once('ready', onReady)\n destination.once('error', onError)\n })\n let closing: Promise<void> | undefined\n const close = async (): Promise<void> => {\n if (!(await opened)) return\n await new Promise<void>((resolve) => {\n destination.once('close', () => resolve())\n destination.once('error', () => resolve())\n destination.end()\n })\n }\n return () => (closing ??= close())\n}\n\n/** The same for a Node stream (the daily channel's): ends it and resolves once it has finished. Never rejects. */\nexport function writableCloser(stream: Writable): () => Promise<void> {\n let closing: Promise<void> | undefined\n const close = () =>\n new Promise<void>((resolve) => {\n if (stream.writableFinished || stream.destroyed) return resolve()\n stream.once('finish', () => resolve())\n stream.once('error', () => resolve())\n stream.end()\n })\n return () => (closing ??= close())\n}\n","import pino from 'pino'\nimport type { LogLevel } from '@orieljs/contracts'\nimport { BaseLogger } from './BaseLogger'\n\n/** Maps an RFC 5424 level onto pino's own (narrower) level methods. The real level is kept in the payload. */\nconst PINO_METHOD: Record<LogLevel, 'fatal' | 'error' | 'warn' | 'info' | 'debug'> = {\n emergency: 'fatal',\n alert: 'fatal',\n critical: 'fatal',\n error: 'error',\n warning: 'warn',\n notice: 'info',\n info: 'info',\n debug: 'debug',\n}\n\n/** A channel backed by a pino logger writing to an arbitrary destination stream (file, stderr, ...). */\nexport class PinoLogger extends BaseLogger {\n private flushing: Promise<void> | undefined\n\n constructor(\n private readonly pinoInstance: pino.Logger,\n minimumLevel: LogLevel = 'debug',\n /** Writes out and closes the destination; the channel factories pass one for each destination they open. */\n private readonly closeDestination: () => Promise<void> = async () => {},\n ) {\n super(minimumLevel)\n }\n\n /**\n * Writes out every entry still buffered and closes the destination. pino writes asynchronously, so a process\n * awaits this before it exits (runConsoleAndExit does). The channel takes no entries afterwards: they're dropped.\n * Not in Laravel, whose handlers write synchronously.\n */\n flush(): Promise<void> {\n return (this.flushing ??= this.closeDestination())\n }\n\n protected write(level: LogLevel, message: string, context: Record<string, unknown>): void {\n if (this.flushing) return\n this.pinoInstance[PINO_METHOD[level]]({ ...context, rfc5424Level: level }, message)\n }\n}\n","import type { LogManager } from '@orieljs/contracts'\nimport { LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { inject } from '@orieljs/container'\nimport { facade } from '@orieljs/support'\n\n/** The `Log` facade (Laravel's `Illuminate\\Support\\Facades\\Log`). `Log.channel('single').info(...)`. */\nexport const Log = facade<LogManager>(LogManagerToken)\n\n/** With no args, the LogManager itself. With a message, logs it at `debug` (Laravel's `logger()` helper). */\nexport function logger(): LogManager\nexport function logger(message: string, context?: Record<string, unknown>): void\nexport function logger(message?: string, context?: Record<string, unknown>): LogManager | void {\n const manager = inject(LogManagerToken)\n if (message === undefined) return manager\n manager.debug(message, context)\n}\n","import type { Container, Logger, LogLevel } from '@orieljs/contracts'\nimport { ConfigRepository, LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { createDailyChannel, createSingleChannel, createStderrChannel } from './channels'\nimport { mergeLogContext } from './context'\nimport { LogChannelCycleError, UnknownLogChannelError, UnknownLogDriverError } from './errors'\nimport { NullLogger } from './NullLogger'\nimport { StackLogger } from './StackLogger'\n\ntype ChannelConfig = Record<string, unknown>\ntype Driver = (config: ChannelConfig) => Logger\n\n/** A channel holding buffered entries (PinoLogger); the null and stack channels have nothing of their own. */\ninterface Flushable {\n flush(): Promise<void>\n}\nconst isFlushable = (channel: Logger): channel is Logger & Flushable => typeof (channel as Partial<Flushable>).flush === 'function'\n\ninterface LoggingConfig {\n default: string\n channels: Record<string, ChannelConfig>\n}\n\nconst level = (config: ChannelConfig): LogLevel => (config.level as LogLevel | undefined) ?? 'debug'\n\n/** `LogManager`: resolves channels by name from `config('logging')`, lazily and cached. */\nexport class LogManager implements LogManagerToken {\n private readonly channels = new Map<string, Logger>()\n private readonly drivers = new Map<string, Driver>()\n private readonly resolving = new Set<string>()\n\n constructor(private readonly container: Container) {\n this.drivers.set('single', (config) => createSingleChannel(String(config.path ?? ''), level(config)))\n this.drivers.set('daily', (config) => createDailyChannel(String(config.path ?? ''), Number(config.days ?? 14), level(config)))\n this.drivers.set('stderr', (config) => createStderrChannel(level(config)))\n this.drivers.set('null', () => new NullLogger())\n this.drivers.set('stack', (config) => this.stack((config.channels as string[] | undefined) ?? []))\n }\n\n private loggingConfig(): LoggingConfig {\n return this.container.make(ConfigRepository).get<LoggingConfig>('logging', { default: 'stack', channels: {} })\n }\n\n channel(name?: string): Logger {\n const loggingConfig = this.loggingConfig()\n const channelName = name ?? loggingConfig.default\n let channel = this.channels.get(channelName)\n if (!channel) {\n if (this.resolving.has(channelName)) throw new LogChannelCycleError(channelName)\n const channelConfig = loggingConfig.channels[channelName]\n if (!channelConfig) throw new UnknownLogChannelError(channelName)\n const driverName = channelConfig.driver as string | undefined\n const driver = driverName ? this.drivers.get(driverName) : undefined\n if (!driver) throw new UnknownLogDriverError(String(driverName))\n this.resolving.add(channelName)\n try {\n channel = driver(channelConfig)\n } finally {\n this.resolving.delete(channelName)\n }\n this.channels.set(channelName, channel)\n }\n return channel\n }\n\n stack(channels: string[]): Logger {\n return new StackLogger(channels.map((name) => this.channel(name)))\n }\n\n /**\n * Writes out and closes every channel resolved so far, then forgets them, so the next entry opens its file again.\n * pino writes asynchronously, so a console process awaits this before it exits (runConsoleAndExit does). Not in\n * Laravel, whose handlers write synchronously.\n */\n async flush(): Promise<void> {\n const channels = [...this.channels.values()]\n this.channels.clear()\n await Promise.all(channels.filter(isFlushable).map((channel) => channel.flush()))\n }\n\n log(logLevel: LogLevel, message: string, context?: Record<string, unknown>): void {\n this.channel().log(logLevel, message, context)\n }\n emergency(message: string, context?: Record<string, unknown>): void {\n this.channel().emergency(message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.channel().alert(message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.channel().critical(message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.channel().error(message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.channel().warning(message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.channel().notice(message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.channel().info(message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.channel().debug(message, context)\n }\n\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n}\n","import { BaseLogger } from './BaseLogger'\n\n/** The `null` channel: discards every entry (Laravel's `NullHandler`). */\nexport class NullLogger extends BaseLogger {\n protected write(): void {\n // Intentionally does nothing.\n }\n}\n","import type { Logger, LogLevel } from '@orieljs/contracts'\nimport { mergeLogContext } from './context'\n\n/** `Log.stack([...])`: fans every entry out to each constituent channel, which does its own level filtering. */\nexport class StackLogger implements Logger {\n constructor(private readonly channels: Logger[]) {}\n\n log(level: LogLevel, message: string, context?: Record<string, unknown>): void {\n for (const channel of this.channels) channel.log(level, message, context)\n }\n emergency(message: string, context?: Record<string, unknown>): void {\n this.log('emergency', message, context)\n }\n alert(message: string, context?: Record<string, unknown>): void {\n this.log('alert', message, context)\n }\n critical(message: string, context?: Record<string, unknown>): void {\n this.log('critical', message, context)\n }\n error(message: string, context?: Record<string, unknown>): void {\n this.log('error', message, context)\n }\n warning(message: string, context?: Record<string, unknown>): void {\n this.log('warning', message, context)\n }\n notice(message: string, context?: Record<string, unknown>): void {\n this.log('notice', message, context)\n }\n info(message: string, context?: Record<string, unknown>): void {\n this.log('info', message, context)\n }\n debug(message: string, context?: Record<string, unknown>): void {\n this.log('debug', message, context)\n }\n\n /** Context is scoped by the container (see context.ts), not per-instance, so this affects every channel. */\n withContext(context: Record<string, unknown>): this {\n mergeLogContext(context)\n return this\n }\n}\n","import { LogManager as LogManagerToken } from '@orieljs/contracts'\nimport { ServiceProvider } from '@orieljs/support'\nimport { LogManager } from './LogManager'\n\n/** Binds the LogManager and merges Laravel 11's `logging` defaults (stack -> single, LOG_LEVEL=debug). */\nexport class LogServiceProvider extends ServiceProvider {\n override register(): void {\n const level = process.env.LOG_LEVEL ?? 'debug'\n this.mergeConfigFrom(\n {\n default: process.env.LOG_CHANNEL ?? 'stack',\n channels: {\n stack: { driver: 'stack', channels: (process.env.LOG_STACK ?? 'single').split(',') },\n single: { driver: 'single', path: this.app.storagePath('logs/oriel.log'), level },\n daily: { driver: 'daily', path: this.app.storagePath('logs/oriel.log'), level, days: 14 },\n stderr: { driver: 'stderr', level },\n null: { driver: 'null' },\n },\n },\n 'logging',\n )\n this.app.singleton(LogManagerToken, (container) => new LogManager(container))\n // At the end of the process: write out and close the log files. Shutdown callbacks run newest first, so this\n // runs after those of the providers registered after Log (Database, Queue, Cache...) and keeps what they log;\n // those registered before Log (Session) run after it.\n this.app.onShutdown(async () => {\n if (!this.app.resolved(LogManagerToken)) return\n await (this.app.make(LogManagerToken) as { flush?(): Promise<void> }).flush?.()\n })\n }\n}\n"],"mappings":"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","names":["level","level","level","pino","level","pino","level","LogManagerToken","level","LogManagerToken"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orieljs/log",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.8",
4
4
  "description": "The Oriel Log component.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -27,13 +27,14 @@
27
27
  "files": [
28
28
  "dist",
29
29
  "LICENSE",
30
- "NOTICE"
30
+ "NOTICE",
31
+ "TRADEMARKS.md"
31
32
  ],
32
33
  "dependencies": {
33
34
  "pino": "10.3.1",
34
- "@orieljs/contracts": "0.1.0-alpha.6",
35
- "@orieljs/support": "0.1.0-alpha.6",
36
- "@orieljs/container": "0.1.0-alpha.6"
35
+ "@orieljs/contracts": "0.1.0-alpha.8",
36
+ "@orieljs/container": "0.1.0-alpha.8",
37
+ "@orieljs/support": "0.1.0-alpha.8"
37
38
  },
38
39
  "scripts": {
39
40
  "build": "tsup && node ../../../scripts/copy-license.mjs"