This page documents the 0.4 release candidates of @nexusdi/core. The newest on npm is 0.4.0-rc.1. The documentation for 0.3.2, the current release, is at nexus.js.org. Try the release candidate.
NEXUS_DISPOSED
NEXUS_DISPOSED means code called a method of a container or a scope, or a lazy() thunk, after its disposal started. On the root container, get(), has(), resolve(), validate(), createScope() and load() throw it, with target=container. A load() or createScope() still running when disposal starts rejects with it too. A scope throws it from get(), has() and resolve(), and its extend() rejects with it. It reports target=scope once the scope is disposed and target=container while its container is disposing. A thunk reports target=instance when it is called after the instance it reaches was disposed, either from a later disposer or after disposal finished. A factory that calls another, disposed container or scope while Nexus.create runs sees the error as the cause of NEXUS_PROVIDER_FAILED.
Reproduce NEXUS_DISPOSED
The region disposes the container and then calls get(). Without a plugin, core prints a one-line message that starts with the code and ends with the address of this page. With errors() from @nexusdi/errors registered (npm install @nexusdi/errors@next), the same error carries the full text and its fix.
import { Nexus, Token, isNexusError, provide } from '@nexusdi/core';
import type { NexusPlugin } from '@nexusdi/core';
import { errors } from '@nexusdi/errors';
interface IReactorCore {
readonly output: number;
}
const REACTOR = new Token<IReactorCore>('ReactorCore');
class FusionReactor implements IReactorCore {
readonly output = 1.21;
}
const afterScram = async (plugins: NexusPlugin[]) => {
const ship = await Nexus.create(
[provide(REACTOR, { useClass: FusionReactor })],
{ plugins },
);
await ship[Symbol.asyncDispose]();
try {
return ship.get(REACTOR);
} catch (error) {
return error;
}
};
const thin = await afterScram([]);
const line = isNexusError(thin) ? thin.message : null; // -> '[NEXUS_DISPOSED] target=container. https://nexus.js.org/errors/NEXUS_DISPOSED'
console.log(line);
const full = await afterScram([errors()]);
const text = isNexusError(full) ? full.message : null; // -> '[NEXUS_DISPOSED] the container is disposed or disposing.'
console.log(text);Try it: save the region as error.ts and run npx tsx error.ts. It prints the one-line message, then the full text, [NEXUS_DISPOSED] the container is disposed or disposing., with no fix line. The target field says whether the disposed object is a container or a scope, or an instance that a lazy() target names. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints 1.21.
Fix NEXUS_DISPOSED
NEXUS_DISPOSED is fixed by keeping every use of a container inside its lifetime. await using disposes the container when its block ends, so every call inside the block runs while the container is open.
import { Nexus, Token, provide } from '@nexusdi/core';
interface IReactorCore {
readonly output: number;
}
const REACTOR = new Token<IReactorCore>('ReactorCore');
class FusionReactor implements IReactorCore {
readonly output = 1.21;
}
async function runVoyage(): Promise<number> {
await using ship = await Nexus.create([
provide(REACTOR, { useClass: FusionReactor }),
]);
return ship.get(REACTOR).output;
}
const output = await runVoyage(); // -> 1.21
console.log(output);Try it: in runVoyage of fixed.ts, add the line await ship[Symbol.asyncDispose](); before the return, and run it again. tsc accepts the file. tsx throws an uncaught DisposedError that starts with [NEXUS_DISPOSED] target=container.. Delete the line and the program prints 1.21 again.
Fields of DisposedError
DisposedError has one field:
target:containerorscopefor the disposed object, andinstancefor alazy()target.