Documentation

Core Utilities

Lazy, Logger, and the non-UI nanolib primitives every project needs.

@alwatr/core is a pure aggregator over the non-UI half of @alwatr/nanolib — utilities with zero DOM assumptions, so they run identically in the browser, Bun, or Node. Two of them are load-bearing enough for the rest of the docs to lean on directly: Lazy and Logger.

Lazy

A generic, memory-efficient deferred-initialization wrapper. The initializer runs on first .instance access, is cached forever, and is then deleted (not nulled) from the object — a strong hint to V8 that the closure can be reclaimed.

ts
import {lazy} from '@alwatr/core';

const db = lazy(() => new DatabaseConnection(config));

db.isInitialized(); // false
const conn = db.instance; // initializer runs here, cached forever
db.isInitialized(); // true
Note

lazy(...) is preferred over new Lazy(...) for better type inference. There is deliberately no reset() — Lazy is a permanent-singleton primitive; reach for a StateSignal if you need resettable or reactive state, and @alwatr/flatomise or Signals if you need async support.

Commonly paired with EmbeddedDataCollector for deferred SSR-data extraction (see Storage & Hydration) and with StateSignal subscriptions for lazily initializing a service only once something actually needs it.

Logger

A scoped, colorful console logger whose debug-only methods are stripped entirely in production. createLogger(scopeName) returns an instance with methods grouped by intent:

MethodUse for
banner(message)A prominent startup/version message. Always active.
logMethod?.(name) / logMethodArgs?.(name, args)Method-entry tracing — dev-mode only, called with ?.().
incident?.(method, code, ...)An expected, recoverable event — informational, not alarming.
accident(method, code, ...)Unexpected but recoverable — console.warn.
error(method, code, ...)Critical, unrecoverable — console.error. Never stripped.
ts
import {createLogger} from '@alwatr/core';

const logger = createLogger('api-service');
logger.banner('API Service Initialized — v2.0');

function fetchData(url: string) {
  DEV_MODE && logger.logMethodArgs?.('fetchData', {url});
  try {
    // ...
  } catch (error) {
    logger.error('fetchData', 'network_failure', error, {url});
  }
}

This is exactly the pattern used across every Alwatr app layer: DEV_MODE && this.logger_.logMethodArgs?.(...) — the DEV_MODE && guard lets a bundler dead-code-eliminate the whole call in production, and the optional-chained call keeps it a no-op even when it isn't.

Debug mode

  • NODE_ENV=development auto-enables debug output.
  • In the browser, override with localStorage.setItem('ALWATR_DEBUG', '1').
  • In Node/Bun, override with the DEBUG=1 environment variable.

The logger preserves accurate call-site file/line attribution in devtools — its own internals never pollute the stack trace.

Other primitives

Everything covered in the Flux family pages — @alwatr/signal, @alwatr/action, @alwatr/directive, @alwatr/bind, @alwatr/embedded-data, @alwatr/local-storage, @alwatr/session-storage — can be installed and used completely standalone, without pulling in the rest of @alwatr/flux. Beyond those, @alwatr/core also bundles smaller utilities worth knowing about:

  • @alwatr/debounce — a type-safe, framework-agnostic debouncer, used internally by every storage-backed signal for write-debouncing.
  • @alwatr/dedupe — a dev-time helper that detects and warns about duplicate-version imports of the same package across an app.
  • @alwatr/deep-clone, @alwatr/fetch, @alwatr/resolve-url, @alwatr/parse-duration, and a handful of hashing utilities (cyrb53, djb2-hash) round out the bundle.