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_DUPLICATE_PROVIDER
NEXUS_DUPLICATE_PROVIDER means one module lists two providers for the same Token or class. Nexus.create reports it inside NEXUS_BLUEPRINT_INVALID, because the container would not know which provider a lookup means.
Reproduce NEXUS_DUPLICATE_PROVIDER
The region binds ReactorCore to FusionReactor and again to SimulatedReactor in Engineering. 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, defineModule, isNexusError } from '@nexusdi/core';
import { provide } 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;
}
class SimulatedReactor implements IReactorCore {
readonly output = 0;
}
const Engineering = defineModule({
name: 'Engineering',
providers: [
provide(REACTOR, { useClass: FusionReactor }),
provide(REACTOR, { useClass: SimulatedReactor }),
],
});
const thin = await Nexus.create(Engineering).catch((error: unknown) => error);
if (!isNexusError(thin, 'NEXUS_BLUEPRINT_INVALID')) throw thin;
const line = thin.errors[0]?.message; // -> '[NEXUS_DUPLICATE_PROVIDER] token=ReactorCore module=Engineering. https://nexus.js.org/errors/NEXUS_DUPLICATE_PROVIDER'
console.log(line);
const full = await Nexus.create(Engineering, { plugins: [errors()] }).catch(
(error: unknown) => error,
);
if (!isNexusError(full, 'NEXUS_BLUEPRINT_INVALID')) throw full;
const text = full.errors[0]?.message.split('\n'); // -> ['[NEXUS_DUPLICATE_PROVIDER] Engineering provides ReactorCore twice.', ' Fix: remove one of them, or use a MultiToken to collect several.']
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, which names Engineering as the module that provides ReactorCore twice. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints [ 'reactor', 'hull' ].
Fix NEXUS_DUPLICATE_PROVIDER
NEXUS_DUPLICATE_PROVIDER is fixed by keeping one provider of the token in the module. To swap the implementation, put the second provider in a second module, such as a SimulatorEngineering that the root imports where it imported Engineering (see Modules). To collect several values, use a MultiToken, which takes one contribution per provide() call and resolves to an array:
import { MultiToken, Nexus, defineModule, provide } from '@nexusdi/core';
interface Diagnostic {
readonly system: string;
run(): boolean;
}
const DIAGNOSTICS = new MultiToken<Diagnostic>('Diagnostics');
const Engineering = defineModule({
name: 'Engineering',
providers: [
provide(DIAGNOSTICS, { useValue: { system: 'reactor', run: () => true } }),
provide(DIAGNOSTICS, { useValue: { system: 'hull', run: () => true } }),
],
});
await using ship = await Nexus.create(Engineering);
const systems = ship.get(DIAGNOSTICS).map((check) => check.system); // -> ['reactor', 'hull']
console.log(systems);Try it: in fixed.ts, change MultiToken<Diagnostic> to Token<Diagnostic> and import Token in place of MultiToken. tsc flags the .map call with Property 'map' does not exist on type 'Diagnostic' and the check parameter as implicitly any (TS7006), and run anyway, Nexus.create rejects with NEXUS_DUPLICATE_PROVIDER for Diagnostics. Change both back and it prints [ 'reactor', 'hull' ].
Fields of DuplicateProviderError
DuplicateProviderError carries these fields:
token: the display name of the token provided twice.module: the module that provides it twice.