From e28ce54d5262a63df5f412769a5dc339898c09c4 Mon Sep 17 00:00:00 2001 From: Paul Marechal Date: Fri, 26 May 2023 17:44:12 -0400 Subject: [PATCH] better stringify key in LAZY_IN_SYNC --- src/constants/error_msgs.ts | 16 +++++++++++++--- test/constants/error_message.test.ts | 16 +++++++++++++++- test/resolution/resolver.test.ts | 17 ++++++----------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/constants/error_msgs.ts b/src/constants/error_msgs.ts index 5a8d7d7a6..16910434e 100644 --- a/src/constants/error_msgs.ts +++ b/src/constants/error_msgs.ts @@ -9,7 +9,7 @@ export const MISSING_INJECTABLE_ANNOTATION = 'Missing required @injectable annot export const MISSING_INJECT_ANNOTATION = 'Missing required @inject or @multiInject annotation in:'; export const UNDEFINED_INJECT_ANNOTATION = (name: string) => `@inject called with undefined this could mean that the class ${name} has ` + - 'a circular dependency problem. You can use a LazyServiceIdentifer to ' + + 'a circular dependency problem. You can use a LazyServiceIdentifer to ' + 'overcome this limitation.'; export const CIRCULAR_DEPENDENCY = 'Circular dependency found:'; export const NOT_IMPLEMENTED = 'Sorry, this feature is not fully implemented yet.'; @@ -17,8 +17,8 @@ export const INVALID_BINDING_TYPE = 'Invalid binding type:'; export const NO_MORE_SNAPSHOTS_AVAILABLE = 'No snapshot available to restore.'; export const INVALID_MIDDLEWARE_RETURN = 'Invalid return type in middleware. Middleware must return!'; export const INVALID_FUNCTION_BINDING = 'Value provided to function binding must be a function!'; -export const LAZY_IN_SYNC = (key: unknown) => `You are attempting to construct '${key}' in a synchronous way - but it has asynchronous dependencies.`; +export const LAZY_IN_SYNC = (key: unknown) => `You are attempting to construct ${keyToString(key)} in a synchronous way ` + + 'but it has asynchronous dependencies.'; export const INVALID_TO_SELF_VALUE = 'The toSelf function can only be applied when a constructor is ' + 'used as service identifier'; @@ -53,3 +53,13 @@ export const CIRCULAR_DEPENDENCY_IN_FACTORY = (factoryType: string, serviceIdent `service identifier '${serviceIdentifier}'.`; export const STACK_OVERFLOW = 'Maximum call stack size exceeded'; + +function keyToString(key: unknown): string { + if (typeof key === 'function') { + return `[function/class ${key.name || ''}]`; + } + if (typeof key === 'symbol') { + return key.toString(); + } + return `'${key}'`; +} diff --git a/test/constants/error_message.test.ts b/test/constants/error_message.test.ts index 56924f665..a9cebbeb5 100644 --- a/test/constants/error_message.test.ts +++ b/test/constants/error_message.test.ts @@ -8,4 +8,18 @@ describe('ERROR_MSGS', () => { expect(error).eql('@postConstruct error in class a: b'); }); -}); \ No newline at end of file + it('Should properly stringify symbol in LAZY_IN_SYNC', () => { + const error = ERROR_MSGS.LAZY_IN_SYNC(Symbol('a')); + expect(error).eql(`You are attempting to construct Symbol(a) in a synchronous way but it has asynchronous dependencies.`); + }); + + it('Should properly stringify class in LAZY_IN_SYNC', () => { + const error = ERROR_MSGS.LAZY_IN_SYNC(class B {}); + expect(error).eql(`You are attempting to construct [function/class B] in a synchronous way but it has asynchronous dependencies.`); + }); + + it('Should properly stringify string in LAZY_IN_SYNC', () => { + const error = ERROR_MSGS.LAZY_IN_SYNC('c'); + expect(error).eql(`You are attempting to construct 'c' in a synchronous way but it has asynchronous dependencies.`); + }); +}); diff --git a/test/resolution/resolver.test.ts b/test/resolution/resolver.test.ts index ebcf22371..423621b35 100644 --- a/test/resolution/resolver.test.ts +++ b/test/resolution/resolver.test.ts @@ -1837,8 +1837,7 @@ describe('Resolve', () => { container.bind('Constructable').to(Constructable).inSingletonScope() .onActivation(() => Promise.resolve()); - expect(() => container.get('Constructable')).to.throw(`You are attempting to construct 'Constructable' in a synchronous way - but it has asynchronous dependencies.`); + expect(() => container.get('Constructable')).to.throw(`You are attempting to construct 'Constructable' in a synchronous way but it has asynchronous dependencies.`); }); it('Should force a class with an async post construct to use the async api', async () => { @@ -1853,8 +1852,7 @@ describe('Resolve', () => { const container = new Container(); container.bind('Constructable').to(Constructable); - expect(() => container.get('Constructable')).to.throw(`You are attempting to construct 'Constructable' in a synchronous way - but it has asynchronous dependencies.`); + expect(() => container.get('Constructable')).to.throw(`You are attempting to construct 'Constructable' in a synchronous way but it has asynchronous dependencies.`); }); it('Should retry promise if first time failed', async () => { @@ -1906,8 +1904,7 @@ describe('Resolve', () => { container.onActivation('foo', () => Promise.resolve('baz')); - expect(() => container.get('foo')).to.throw(`You are attempting to construct 'foo' in a synchronous way - but it has asynchronous dependencies.`); + expect(() => container.get('foo')).to.throw(`You are attempting to construct 'foo' in a synchronous way but it has asynchronous dependencies.`); }); it('Should allow onActivation (sync) of a previously binded sync object (without activation)', async () => { @@ -2530,8 +2527,7 @@ describe('Resolve', () => { container.bind('UseDate').to(UseDate); container.bind('Date').toDynamicValue(() => Promise.resolve(new Date())); - expect(() => container.get('UseDate')).to.throw(`You are attempting to construct 'UseDate' in a synchronous way - but it has asynchronous dependencies.`); + expect(() => container.get('UseDate')).to.throw(`You are attempting to construct 'UseDate' in a synchronous way but it has asynchronous dependencies.`); }); it('Should be able to resolve indirect Promise bindings', async () => { @@ -2569,8 +2565,7 @@ describe('Resolve', () => { const container = new Container(); container.bind('async').toDynamicValue(() => Promise.resolve('foobar')); - expect(() => container.get('async')).to.throw(`You are attempting to construct 'async' in a synchronous way - but it has asynchronous dependencies.`); + expect(() => container.get('async')).to.throw(`You are attempting to construct 'async' in a synchronous way but it has asynchronous dependencies.`); }); it('Should cache a a resolved value on singleton when possible', async () => { @@ -2597,4 +2592,4 @@ describe('Resolve', () => { expect(serviceFromGetAsync).eql(asyncServiceDynamicResolvedValue); expect(serviceFromGet).eql(asyncServiceDynamicResolvedValue); }); -}); \ No newline at end of file +});