diff options
Diffstat (limited to 'deno/base')
| -rw-r--r-- | deno/base/config.ts | 7 | ||||
| -rw-r--r-- | deno/base/date.ts | 6 | ||||
| -rw-r--r-- | deno/base/deno.json | 6 | ||||
| -rw-r--r-- | deno/base/lib.ts | 30 | ||||
| -rw-r--r-- | deno/base/log.ts | 164 | ||||
| -rw-r--r-- | deno/base/text.ts | 3 |
6 files changed, 36 insertions, 180 deletions
diff --git a/deno/base/config.ts b/deno/base/config.ts index 98722f6..96cc869 100644 --- a/deno/base/config.ts +++ b/deno/base/config.ts @@ -1,4 +1,4 @@ -import { camelCaseToKebabCase } from "./text.ts"; +import { StringUtils } from "./lib.ts"; export interface ConfigDefinitionItem { readonly description: string; @@ -29,7 +29,9 @@ export class ConfigProvider<K extends string> { for (const [key, def] of Object.entries(definition as ConfigDefinition)) { map[key] = { ...def, - env: `${this.#prefix}-${camelCaseToKebabCase(key as string)}` + env: `${this.#prefix}-${ + StringUtils.camelCaseToKebabCase(key as string) + }` .replaceAll("-", "_") .toUpperCase(), }; @@ -91,4 +93,3 @@ export class ConfigProvider<K extends string> { .join("\n"); } } - diff --git a/deno/base/date.ts b/deno/base/date.ts deleted file mode 100644 index e65691e..0000000 --- a/deno/base/date.ts +++ /dev/null @@ -1,6 +0,0 @@ -export function toFileNameString(date: Date, dateOnly?: boolean): string { - const str = date.toISOString(); - return dateOnly === true - ? str.slice(0, str.indexOf("T")) - : str.replaceAll(/:|\./g, "-"); -} diff --git a/deno/base/deno.json b/deno/base/deno.json index 2c2d550..582f0f6 100644 --- a/deno/base/deno.json +++ b/deno/base/deno.json @@ -2,10 +2,8 @@ "name": "@crupest/base", "version": "0.1.0", "exports": { + ".": "./lib.ts", "./config": "./config.ts", - "./cron": "./cron.ts", - "./date": "./date.ts", - "./text": "./text.ts", - "./log": "./log.ts" + "./cron": "./cron.ts" } } diff --git a/deno/base/lib.ts b/deno/base/lib.ts new file mode 100644 index 0000000..af75115 --- /dev/null +++ b/deno/base/lib.ts @@ -0,0 +1,30 @@ +function camelCaseToKebabCase(str: string): string { + return str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()); +} + +function prependNonEmpty<T>( + object: T | null | undefined, + prefix: string = " ", +): string { + if (object == null) return ""; + const string = typeof object === "string" ? object : String(object); + return string.length === 0 ? "" : prefix + string; +} + +export const StringUtils = Object.freeze({ + camelCaseToKebabCase, + prependNonEmpty, +}); + +function toFileNameString(date: Date, dateOnly?: boolean): string { + const str = date.toISOString(); + return dateOnly === true + ? str.slice(0, str.indexOf("T")) + : str.replaceAll(/:|\./g, "-"); +} + +export const DateUtils = Object.freeze( + { + toFileNameString, + } as const, +); diff --git a/deno/base/log.ts b/deno/base/log.ts deleted file mode 100644 index 1a4942d..0000000 --- a/deno/base/log.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { join } from "@std/path"; - -import { toFileNameString } from "./date.ts"; - -export type LogLevel = "error" | "warn" | "info"; - -export interface LogEntry { - content: [unknown, ...unknown[]]; - level?: LogLevel; - cause?: unknown; -} - -export interface LogEntryBuilder { - withLevel(level: LogLevel): LogEntryBuilder; - withCause(cause: unknown): LogEntryBuilder; - setError(error: boolean): LogEntryBuilder; - write(): void; -} - -export interface ExternalLogStream extends Disposable { - stream: WritableStream; -} - -export class Logger { - #indentSize = 2; - #externalLogDir?: string; - - #contextStack: { depth: number; level: LogLevel }[] = [ - { depth: 0, level: "info" }, - ]; - - get #context() { - return this.#contextStack.at(-1)!; - } - - get indentSize() { - return this.#indentSize; - } - - set indentSize(value: number) { - this.#indentSize = value; - } - - get externalLogDir() { - return this.#externalLogDir; - } - - set externalLogDir(value: string | undefined) { - this.#externalLogDir = value; - if (value != null) { - Deno.mkdirSync(value, { - recursive: true, - }); - } - } - - write(entry: LogEntry): void { - const { content, level, cause } = entry; - const [message, ...rest] = content; - console[level ?? this.#context.level]( - " ".repeat(this.#indentSize * this.#context.depth) + String(message), - ...(cause != null ? [cause, ...rest] : rest), - ); - } - - push(entry: LogEntry): Disposable { - this.write(entry); - this.#contextStack.push({ - depth: this.#context.depth + 1, - level: entry.level ?? this.#context.level, - }); - return { - [Symbol.dispose]: () => { - this.#contextStack.pop(); - }, - }; - } - - info(message: unknown, ...args: unknown[]) { - this.write({ level: "info", content: [message, ...args] }); - } - - warn(message: unknown, ...args: unknown[]) { - this.write({ level: "warn", content: [message, ...args] }); - } - - error(message: unknown, ...args: unknown[]) { - this.write({ level: "error", content: [message, ...args] }); - } - - builder(message: unknown, ...args: unknown[]): LogEntryBuilder { - const entry: LogEntry = { - content: [message, ...args], - level: "info", - cause: undefined, - }; - const builder: LogEntryBuilder = { - withCause: (cause) => { - entry.cause = cause; - return builder; - }, - withLevel: (level) => { - entry.level = level; - return builder; - }, - setError: (error) => { - if (error) entry.level = "error"; - return builder; - }, - write: () => { - this.write(entry); - }, - }; - return builder; - } - - async createExternalLogStream( - name: string, - options?: { - noTime?: boolean; - }, - ): Promise<ExternalLogStream> { - if (name.includes("/")) { - throw new Error(`External log stream's name (${name}) contains '/'.`); - } - if (this.#externalLogDir == null) { - throw new Error("External log directory is not set."); - } - - const logPath = join( - this.#externalLogDir, - options?.noTime === true - ? name - : `${name}-${toFileNameString(new Date())}`, - ); - - const file = await Deno.open(logPath, { - read: false, - write: true, - append: true, - create: true, - }); - return { - stream: file.writable, - [Symbol.dispose]: file[Symbol.dispose].bind(file), - }; - } - - async createExternalLogStreamsForProgram( - program: string, - ): Promise<{ stdout: WritableStream; stderr: WritableStream } & Disposable> { - const stdout = await this.createExternalLogStream(`${program}-stdout`); - const stderr = await this.createExternalLogStream(`${program}-stderr`); - return { - stdout: stdout.stream, - stderr: stderr.stream, - [Symbol.dispose]: () => { - stdout[Symbol.dispose](); - stderr[Symbol.dispose](); - }, - }; - } -} - diff --git a/deno/base/text.ts b/deno/base/text.ts deleted file mode 100644 index f3e4020..0000000 --- a/deno/base/text.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function camelCaseToKebabCase(str: string): string { - return str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()); -} |
