Migration (v6 to v7)
Upgrade from envapt v6 to v7, where the default decorators become TC39 Stage 3 accessors and the legacy ones move to envapt/legacy.
v7 changes the decorators. Everything else (the Envapter readers, converters, sources, and types) is unchanged and stays on envapt.
Decorators are now TC39 accessor decorators
The default @Envapt and the sugar decorators are now TC39 Stage 3 accessor decorators. They don't need the experimentalDecorators flag. Bun and Deno run them from a .ts file directly, and Node runs them once you compile.
Declare the field with the accessor keyword. A static field uses static accessor x: T. An instance field uses accessor x!: T with the definite-assignment !.
// v6 (legacy form)
import { Envapt, Converters } from 'envapt';
class Config {
@Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
static readonly port: number;
}
// v7 default (accessor form, no experimentalDecorators)
import { Envapt, Converters } from 'envapt';
class Config {
@Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
static accessor port: number;
}For an instance field, the change is from declare readonly x: T to accessor x!: T.
Keeping the legacy decorators
The v6 decorators move to the envapt/legacy subpath, for code that can't switch to the accessor form yet. They keep the static readonly / declare readonly form and still need experimentalDecorators.
// keep the v6 behavior
import { Envapt, Converters } from 'envapt/legacy';
class Config {
@Envapt('PORT', { converter: Converters.Number, fallback: 3000 })
static readonly port: number;
}Only the decorators move. In v7, a module that imports decorators only from envapt/legacy must also import 'envapt' once so envapt binds FileSource on Node.
Decorated properties are read-only
Assigning to a decorated property now throws EnvaptError with InvalidUserDefinedConfig. Before v7 the legacy decorator installed only a getter, so an assignment did nothing in sloppy mode and threw a native TypeError in strict mode. Both the accessor and legacy forms throw EnvaptError in v7.
Decorated fields are typechecked
TypeScript checks the decorated field's declared type against the converter's output. If the field can't hold the value, the compiler reports this error:
[envapt] field type must hold the converter outputA read with no fallback can be null in v7. A field that compiled as static readonly port: number for @EnvNum('PORT') on v6 now needs number | null. In the accessor form that's static accessor port: number | null. v8 changes that null to undefined, as v7 to v8 explains. This check applies to both the accessor and legacy decorators.
Migration (v7 to v8)
Upgrade from envapt v7 to v8, where the source classes get shorter names and one envapt import replaces the workerd and browser subpaths.
Migration (v5 to v6)
Upgrade from envapt v5 to v6, where the positional decorator form is removed and NODE_ENV=test resolves to the test environment.