
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
atraceApplication development and telemetry toolkit.
pinoGood error handling is a prerequisite for good logging. To help with this,
atrace provides two simple but powerful building blocks.
The libraryErrorClass function generates a base error class which provides:
import {libraryErrorClass} from 'atrace';
// Flexible error class, allowing arbitrary strings as codes.
const GenericError = libraryErrorClass('my-lib');
const err1 = new GenericError('SOMETHING_FAILED'); // OK.
// Strongly typed error codes.
type ErrorID = 'BAR_MISSING' | 'BAZ_BROKEN';
const SpecificError = libraryErrorClass<ErrorID>('my-lib');
const err2 = new SpecificError('BAR_MISSING'); // OK.
const err3 = new SpecificError('SOMETHING_FAILED'); // Fails (unknown ID).
// For even more customization, you can extend the class as usual.
class CustomError extends libraryErrorClass<ErrorID>('my-lib') {
constructor(id: ErrorID, someData: number) {
super(id, {values: {someData}});
}
// ...
}
const err4 = new CustomError('BAZ_BROKEN', 123);
Beyond the capabilities offered by library errors, applications typically also
need the ability to surface statuses back to the client. As a convenience, the
standardError function is also available to create application errors from a
status.
import {applicationErrorFactory, standardError} from 'atrace';
// For large applications, prefer to create your own error codes:
const newError = applicationErrorFactory('bar', {
'BAD_TOGGLE': 'INVALID_ARGUMENT',
'BOOM': 'INTERNAL',
});
const err1 = newError('BAD_TOGGLE'); // Error with invalid argument status.
// For simple use-cases, you can use the convenience standard errors.
const err2 = standardError('NOT_FOUND');
import {
intSetting,
invalidSource,
settingsProvider,
stringSetting,
} from 'atrace';
const settings = settingsProvider((env) => ({
port: intSetting(env.PORT ?? 8080), // Integer value
auth: { // Hierarchical settings
clientID: stringSetting(env.CLIENT_ID ?? 'my-client'), // String value
clientSecret: stringSetting({
source: env.CLIENT_SECRET ?? invalidSource, // Required string value
sensitive: true, // Redact field from parsed sources
}),
},
tag: stringSetting(env.TAG), // Optional string value
}));
const val = settings(); // Parsed values
Importantly, val's type will automatically be inferred as:
{
readonly port: number;
readonly auth: {
readonly clientID: string;
readonly clientSecret: string;
}
readonly tag: string | undefined;
}
If CLIENT_SECRET wasn't defined in the environment, the config provider will
throw an informative exception. To test different setting values without needing
mocks, pass in a custom environment when calling the config provider.
const val = settings({
CLIENT_ID: 'test-id',
CLIENT_SECRET: 'test-secret',
});
We provide a convenience factory builder for types which do not need any non-standard creation arguments.
import {simpleSettingFactory} from 'atrace';
// A setting which will have values inferred as `Date`s.
const dateSetting = simpleSettingFactory((s): Date => new Date(s));
If additional arguments are desired, it's always possible--just more verbose--to use the underlying setting factory directly. For example, here's one way to implement an enum setting:
import {newSetting, Setting, SettingParams, SettingSource} from 'atrace';
/** Enum setting creation parameters. */
export interface EnumSettingParams<E extends string, S>
extends SettingParams<S> {
/** Allowed enum values. */
readonly symbols: ReadonlyArray<E>;
}
/** Creates a new enum setting. */
export function enumSetting<E extends string, S extends SettingSource>(
params: EnumSettingParams<E, S>
): Setting<S, E> {
return newSetting(params, (s): any => {
if (!~params.symbols.indexOf(s as any)) {
throw new Error('Invalid enum value');
}
return s;
});
}
In production code, we recommend using modular configuration types. Performing
post-processing on setting values is easy with a settingsManager:
// src/config.ts
import {settingsManager} from 'atrace';
// First the (private) underlying settings resource manager.
const withSettings = settingsManager((env) => ({/* ... */}));
// Then the (public) configuration types. These can be different from the raw
// settings for example discriminated unions are often handy. These are meant
// to be used everywhere in the application. Smaller, more specific, types will
// make testing easier and increase modularity.
export interface ModuleAConfig {/* ... */}
export interface ModuleBConfig {/* ... */}
export interface Config {
readonly moduleA: ModuleAConfig;
readonly moduleB: ModuleBConfig;
// ...
}
// Now the (public, though not meant for use everywhere - see below)
// configuration factory. This function should only be imported in the
// application's entry point and this module's unit-tests. Other modules should
// accept already instantiated configuration types, making testing much easier
// and dependencies explicit.
export const config = withSettings((val) => {
// Transform the setting values into the public configuration types...
return {/* ... */};
});
// test/config.test.ts
import * as sut from '../src/config';
// Within a test...
const env = {/* ... */}; // Test environment.
expect(config(env)).toEqual(/* ... */); // Expected config for the environment.
FAQs
Application tracing
The npm package atrace receives a total of 0 weekly downloads. As such, atrace popularity was classified as not popular.
We found that atrace demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.