@utility-kit/deprecated
v0.1.0
Published
Framework-agnostic deprecation utility with configurable labels, environment-aware alerts, and optional telemetry hooks. Zero dependencies.
Maintainers
Readme
@utility-kit/deprecated
A framework-agnostic deprecation utility. Mark old APIs as deprecated with a single function call — get environment-aware logging, dev-only browser alerts, structured migration messages, and optional telemetry, with zero dependencies.
Install
npm install @utility-kit/deprecatedWhy
Most "deprecate this function" helpers hard-code console.warn and call it a day. This one is a primitive: you plug in your own environment flags (dev/prod, browser/server) and telemetry sink, and it stays consistent across every app, package, and framework in your stack.
- Zero dependencies, fully tree-shakeable
- Works in Node, browsers, and edge runtimes — you decide what "dev" and "browser" mean
- Throws by default (fail loud in tests/CI), or downgrade to a warning per call-site
- Every user-facing string is overridable
- Optional
onDeprecatedhook for analytics/telemetry pipelines
Usage
import { createDeprecated } from "@utility-kit/deprecated";
const deprecated = createDeprecated({
env: {
isDev: process.env.NODE_ENV !== "production",
isBrowser: typeof window !== "undefined"
}
});
function oldBookingApi() {
deprecated("oldBookingApi() is deprecated", {
since: "v2.4.0",
until: "v3.0.0",
alternative: "createBooking()",
path: "src/legacy/booking.ts"
});
// ...
}By default, calling deprecated() throws. This is intentional: deprecations should be loud enough to fail a test or crash a dev build, not quietly scroll past in a log. Use warnOnly where a hard throw isn't appropriate (e.g. production runtime paths you can't break):
deprecated("oldBookingApi() is deprecated", {
warnOnly: true,
alternative: "createBooking()"
});
// logs via console.warn instead of throwingSvelteKit example
import { browser, dev } from "$app/environment";
import { createDeprecated } from "@utility-kit/deprecated";
export const deprecated = createDeprecated({
env: { isDev: dev, isBrowser: browser },
onDeprecated: ({ message, severity }) => {
analytics.track("deprecated_api_used", { message, severity });
}
});Next.js / generic browser example
export const deprecated = createDeprecated({
env: {
isDev: process.env.NODE_ENV === "development",
isBrowser: typeof window !== "undefined"
}
});API
createDeprecated(config)
Returns a deprecated(message, options?) function bound to your environment and labels.
config
| Field | Type | Description |
|---|---|---|
| env.isDev | boolean | Enables console.error logging and (if isBrowser) a browser alert(). |
| env.isBrowser | boolean | Enables the alert() in dev. Ignored outside dev. |
| labels | Partial<DeprecatedLabels> | Override any user-facing string. Shallow-merged with defaults. |
| onDeprecated | (payload) => void | Fired on every call, before throwing/warning. Use for telemetry. |
deprecated(message, options?)
| Option | Type | Description |
|---|---|---|
| path | string | File, module, or endpoint where the deprecation originates. Appended as [Origin]. |
| since | string | When it was deprecated (e.g. "v2.4.0"). Appended as part of [Lifecycle]. |
| until | string | When it will be removed. Appended as part of [Lifecycle]. |
| alternative | string | Suggested replacement API. Appended as [Migration]. |
| warnOnly | boolean | Downgrade from throwing to console.warn. Default false. |
| devMessage | string | Replaces the built message in the dev console.error log only — the thrown/warned message is unaffected. |
| meta | Record<string, unknown> | Extra data passed straight through to console.warn/console.error and the onDeprecated payload. |
Behavior:
- Default (
warnOnlyunset): throws anErrorcontaining the built message. warnOnly: true: logs viaconsole.warnand returnsundefinedinstead of throwing.env.isDev: true: additionally logs viaconsole.error(usingdevMessageif provided), regardless ofwarnOnly.env.isDev: trueandenv.isBrowser: true: additionally callsglobalThis.alert()if it exists.onDeprecated, if provided, always fires with{ message, options, severity }before the throw/return.
DEFAULT_LABELS
The default label set, exported so you can reference or partially extend it instead of retyping everything.
Design notes
- No global state. Every
createDeprecated()call returns an independent handler — call it once per app/package and export the instance, or create scoped instances per module. - No auto-detection.
isDev/isBrowserare passed in explicitly. This package doesn't guess based onprocess.envortypeof window, so it works identically in bundlers, edge runtimes, and test environments. - Message building is deterministic. Lifecycle → Migration → Origin, always in that order, only including the parts you provide.
License
MIT
