@playcanvas/splat-transform
Version:
Library and CLI tool for 3D Gaussian splat format conversion and transformation
271 lines (270 loc) • 10.6 kB
TypeScript
/**
* Verbosity level controlling which messages reach the renderer.
*
* - `quiet` - errors and warnings only.
* - `normal` - tasks, bars, info, warn, error (default).
* - `verbose` - normal + debug messages.
*/
type Verbosity = 'quiet' | 'normal' | 'verbose';
/** Severity tag for free-form messages (ordered descending by severity). */
type MessageKind = 'error' | 'warn' | 'info' | 'debug';
/**
* Semantic event delivered to a {@link Renderer}. Renderers can filter, format
* and display these as they wish.
*
* `scopeStart` / `scopeEnd` represent the open/close of a {@link Group}.
* They carry optional `index` / `total` fields when the scope is part of a
* numbered series, which renderers can use to switch to a `[N/T] name` style.
*
* `barStart` / `barTick` / `barEnd` represent a determinate progress bar.
* The bar's `name` is repeated on every event so the renderer can keep its
* label stable across in-place updates while tracking progress via `current`
* and `total`.
*
* `output` is the pipeable channel: each event represents a single logical
* unit of output (typically one line - or a multi-line block treated as a
* unit) that the renderer is expected to terminate with a newline. Callers
* should not include a trailing `\n` themselves.
*/
type LogEvent = {
kind: 'scopeStart';
depth: number;
name: string;
index?: number;
total?: number;
} | {
kind: 'scopeEnd';
depth: number;
name: string;
durationMs: number;
failed?: boolean;
index?: number;
total?: number;
} | {
kind: 'barStart';
depth: number;
name: string;
total: number;
} | {
kind: 'barTick';
depth: number;
name: string;
current: number;
total: number;
} | {
kind: 'barEnd';
depth: number;
name: string;
durationMs: number;
current: number;
total: number;
failed?: boolean;
} | {
kind: 'message';
depth: number;
level: MessageKind;
text: string;
} | {
kind: 'output';
text: string;
};
/**
* Renderer interface. Receives the full stream of semantic lifecycle
* events ({@link LogEvent}) and decides how to display them. The core
* does not filter scope/bar events by verbosity, so renderers see a
* faithful record of every scope open/close and bar progress update -
* embedders consuming the event stream can rely on this for progress
* UIs that must close themselves on completion. Visibility decisions
* (e.g. hiding successful `scopeEnd` footers at non-`verbose`
* verbosity) are the renderer's responsibility; {@link logger.getVerbosity}
* is available to consult.
*
* `message` events for `info`, `warn` and `debug` are gated by verbosity
* at the façade (see {@link LoggerCore.isLevelVisible}) before reaching
* the renderer; `error` is always delivered.
*/
interface Renderer {
/**
* Handle a log event.
* @param event - The event to render.
*/
handle(event: LogEvent): void;
}
/**
* Determinate progress bar handle. Closed explicitly via `end()`, or
* implicitly when an enclosing {@link Group}'s `end()` (or a
* {@link Logger.unwindAll}) pops it as part of cleanup.
*
* Carries a `[Symbol.dispose]` slot directly (rather than extending the
* built-in `Disposable` lib type) so the published `.d.ts` stays free of
* any reference to the `Disposable` interface. `Symbol.dispose` itself is
* still a TS 5.2+ / `esnext.disposable` (or `es2024.disposable`) lib
* symbol, so consumers compiling against these declarations need that
* lib enabled (or `skipLibCheck: true`). Callers on TS 5.2+ / Node 20+
* can adopt `using bar = logger.bar(...)` because `using` only requires
* the `[Symbol.dispose]` shape structurally.
*/
interface Bar {
/**
* Advance the bar by `n` ticks.
* @param n - Number of ticks to advance (default 1).
*/
tick(n?: number): void;
/**
* Set the bar's absolute progress. Clamped to `[0, total]`. Suppresses
* a `barTick` event when the value is unchanged.
* @param current - Absolute progress value.
*/
update(current: number): void;
/**
* Close the bar and emit final timing.
*/
end(): void;
/** Dispose hook so `using` syntax closes the bar on scope exit. */
[Symbol.dispose](): void;
}
/**
* Named, timed scope returned from {@link Logger.group}. Manages the scope's
* lifecycle only - free-form messages, nested groups and bars are emitted via
* the global `logger` (they auto-indent under whatever is on top of the
* active-scope stack).
*
* Open scopes with `logger.group(name)` and close them with `sub.end()` after
* the body. Embedders that catch their own exceptions (rather than letting
* them propagate to a `logger.error()` call) should call
* {@link Logger.unwindAll} from their catch to close any scopes/bars left
* dangling on the stack.
*
* Carries a `[Symbol.dispose]` slot directly (rather than extending the
* built-in `Disposable` lib type) so the published `.d.ts` stays free of
* any reference to the `Disposable` interface. `Symbol.dispose` itself is
* still a TS 5.2+ / `esnext.disposable` (or `es2024.disposable`) lib
* symbol, so consumers compiling against these declarations need that
* lib enabled (or `skipLibCheck: true`). Callers on TS 5.2+ / Node 20+
* can adopt `using g = logger.group(...)` because `using` only requires
* the `[Symbol.dispose]` shape structurally.
*/
interface Group {
/**
* Close the group, popping anything still open above it on the stack
* (defensively handles forgotten inner scopes) and emit the timing event.
*/
end(): void;
/** Dispose hook so `using` syntax closes the group on scope exit. */
[Symbol.dispose](): void;
}
declare const verbosityRank: Record<Verbosity, number>;
/**
* Public logger surface.
*
* Open named, timed scopes with {@link Logger.group}. Pass `{ index, total }`
* to render the group as part of a numbered series. Indeterminate progress is
* reported with {@link Logger.bar}. Free-form messages route through `info` /
* `warn` / `error` / `debug`, indented under whatever is on top of the
* active-scope stack.
*
* Both `group` and `bar` are pure-push operations: opening a new scope simply
* places it on top of the stack without auto-closing siblings, so call order
* directly determines nesting. Close scopes with `handle.end()` after the
* body. Callers that route failures through {@link Logger.error} get scope
* cleanup for free; embedders that swallow exceptions should call
* {@link Logger.unwindAll} from their catch to close every still-open scope.
*/
declare const logger: {
/**
* Open a named, timed scope. Returns a {@link Group} handle. Call `end()`
* to close it. Group children indent automatically based on call depth.
*
* Pass `{ index, total }` to render the group as part of a numbered
* series (e.g. `[2/5] name`). Both fields must be supplied together.
*
* @param name - The group name.
* @param options - Optional configuration.
* @param options.index - 1-based position in the numbered series.
* @param options.total - Total length of the numbered series.
* @returns A handle for closing the group and writing nested log entries.
*/
group(name: string, options?: {
index?: number;
total?: number;
}): Group;
/**
* Open a labelled progress bar nested directly under whatever scope is
* currently on top of the active-scope stack. Renders as a single line
* at child indent.
*
* Like {@link Logger.group}, this is a pure-push operation: it does not
* close any sibling already on the stack. Close with `bar.end()`, or let
* an enclosing group's `end()` / {@link Logger.unwindAll} pop it.
*
* @param name - The bar's label.
* @param total - Expected number of ticks (or absolute total when using
* {@link Bar.update}).
* @returns A handle for advancing and closing the bar.
*/
bar(name: string, total: number): Bar;
/**
* Emit an info message indented under the innermost active scope.
* @param args - Message parts (joined with a space).
*/
info(...args: any[]): void;
/**
* Emit a warning indented under the innermost active scope.
* @param args - Message parts.
*/
warn(...args: any[]): void;
/**
* Emit an error message. Always shown, regardless of verbosity. Triggers
* an automatic unwind of all open scopes, marking each as failed.
* @param args - Message parts.
*/
error(...args: any[]): void;
/**
* Emit a debug message. Shown only at `verbose` verbosity.
* @param args - Message parts.
*/
debug(...args: any[]): void;
/**
* Emit a logical unit of pipeable output (typically one line, or a
* multi-line block treated as a single unit). The renderer terminates
* each unit with a newline, so callers should not include a trailing
* `\n`. Always shown, regardless of verbosity.
* @param text - The text to emit (without a trailing newline).
*/
output(text: string): void;
/**
* Replace the active renderer. Embedders install their own renderer here
* to consume `LogEvent`s; the default renderer is a no-op. Renderers
* receive every scope/bar lifecycle event regardless of verbosity, so
* progress UIs can rely on `scopeStart`/`scopeEnd` and `barStart`/`barEnd`
* to manage their state.
* @param r - The renderer to install.
*/
setRenderer(r: Renderer): void;
/**
* Set verbosity: `quiet` (errors and warnings), `normal` (default),
* `verbose` (includes debug).
* @param v - The verbosity level.
*/
setVerbosity(v: Verbosity): void;
/**
* Close every open scope and bar, optionally marking them as failed.
* Use this from an embedder's catch when an exception is being swallowed
* (rather than rethrown into a `logger.error()` call), to prevent
* dangling scopes from corrupting subsequent output.
* @param failed - When true, mark every closed scope as having failed.
*/
unwindAll(failed?: boolean): void;
/**
* Get the current verbosity level.
* @returns The active verbosity level.
*/
getVerbosity(): Verbosity;
};
/**
* Public type alias for the logger object. Embedders can type-hint against
* this to inject a configured logger.
*/
type Logger = typeof logger;
export { logger, verbosityRank };
export type { Bar, Group, LogEvent, Logger, MessageKind, Renderer, Verbosity };