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_LAZY_ASYNC
NEXUS_LAZY_ASYNC means a provider with eager: false was built on demand, and its factory returned a promise, or the onInit of its singleton instance did. get() cannot wait for a promise, so it throws. get(), resolve(), the get() of a scope for a scoped factory and a lazy() thunk throw it directly, also when the request reaches the provider through the dependencies of another eager: false provider. The container stores nothing, so the next request builds again and throws again.
Reproduce NEXUS_LAZY_ASYNC
TypeScript rejects eager: false on an async factory and on a class whose onInit returns a promise. It reports TS2769 on the provide( call, and the error for the matching overload names this code:
Fails the type check
provide(NAV_CHARTS, { useFactory: async () => charts, eager: false });
// TS2769: No overload matches this call. The error for the factory overload ends with:
// Type 'false' is not assignable to type 'true | "NEXUS_LAZY_ASYNC: an async provider is built during create or createScope, so it cannot be eager: false. Remove eager: false, or make the token a function type and provide () => Promise<T>" | undefined'.The error reaches run time when the types cannot see the promise. The region uses a JavaScript helper whose typings say it returns charts. 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 INavCharts {
plot(to: string): string;
}
const NAV_CHARTS = new Token<INavCharts>('NavCharts');
// downloadCharts stands in for a JavaScript helper whose typings say it
// returns charts. At run time it returns a promise, which TypeScript cannot see.
const downloadCharts = (async () => ({
plot: (to: string) => `course to ${to}`,
})) as unknown as () => INavCharts;
const Tactical = defineModule({
name: 'Tactical',
providers: [
provide(NAV_CHARTS, { useFactory: () => downloadCharts(), eager: false }),
],
exports: [NAV_CHARTS],
});
const getCharts = (ship: Nexus) => {
try {
return ship.get(NAV_CHARTS);
} catch (error) {
return error;
}
};
await using ship = await Nexus.create(Tactical);
const thin = getCharts(ship);
const line = isNexusError(thin) ? thin.message : null; // -> '[NEXUS_LAZY_ASYNC] token=NavCharts module=Tactical. https://nexus.js.org/errors/NEXUS_LAZY_ASYNC'
console.log(line);
await using fullShip = await Nexus.create(Tactical, { plugins: [errors()] });
const full = getCharts(fullShip);
const text = isNexusError(full) ? full.message.split('\n') : null; // -> ['[NEXUS_LAZY_ASYNC] NavCharts (module Tactical) is eager: false and its build returned a promise; get() cannot wait for it.', ' Fix: remove eager: false, or make the token a function type and provide () => Promise<T>.']
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 as an array of two strings. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints course to Kepler-442b.
Fix NEXUS_LAZY_ASYNC
NEXUS_LAZY_ASYNC is fixed by removing eager: false from an async provider, so create awaits it. Alternatively, make the token a function type and provide () => Promise<T>.
import { Nexus, Token, defineModule, provide } from '@nexusdi/core';
interface INavCharts {
plot(to: string): string;
}
const NAV_CHARTS = new Token<INavCharts>('NavCharts');
async function downloadCharts(): Promise<INavCharts> {
return { plot: (to) => `course to ${to}` };
}
const Tactical = defineModule({
name: 'Tactical',
providers: [provide(NAV_CHARTS, { useFactory: downloadCharts })],
exports: [NAV_CHARTS],
});
await using ship = await Nexus.create(Tactical);
const course = ship.get(NAV_CHARTS).plot('Kepler-442b'); // -> 'course to Kepler-442b'
console.log(course);Try it: in fixed.ts, add eager: false to the options of provide(NAV_CHARTS, ...) and run it again. tsc reports TS2769 on the provide( call, with the message shown above. tsx skips the type check, and ship.get(NAV_CHARTS) throws an uncaught LazyAsyncError that starts with [NEXUS_LAZY_ASYNC] token=NavCharts module=Tactical.. Remove eager: false and the program prints course to Kepler-442b again.
Fields of LazyAsyncError
LazyAsyncError carries these fields:
token: the display name of the provider.module: its module.