Skip to content

Commit

Permalink
Add Logger IoC context entry (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
surol authored Jul 17, 2021
1 parent f3f640d commit 0ed2657
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"exports": "./dist/logger.js",
"devDependencies": {
"@jest/globals": "^27.0.6",
"@proc7ts/context-builder": "^7.0.1",
"@rollup/plugin-node-resolve": "^13.0.2",
"@run-z/eslint-config": "^1.3.0",
"@run-z/rollup-helpers": "^1.1.1",
Expand Down Expand Up @@ -60,5 +61,8 @@
"lint:md": "run-z +z --then remark .",
"test": "run-z +z env:NODE_OPTIONS='--experimental-vm-modules --no-warnings' --then jest",
"z": "run-z +cmd:rollup,+cmd:typedoc,+cmd:eslint,+cmd:remark,+cmd:jest"
},
"dependencies": {
"@proc7ts/context-values": "^7.0.0"
}
}
72 changes: 72 additions & 0 deletions src/logger.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
import { CxBuilder, cxConstAsset } from '@proc7ts/context-builder';
import { CxGlobals } from '@proc7ts/context-values';
import { SpyInstance, spyOn } from 'jest-mock';
import { Logger } from './logger';
import { consoleLogger } from './loggers';

describe('Logger', () => {

let cxBuilder: CxBuilder;

beforeEach(() => {
cxBuilder = new CxBuilder(get => ({ get }));
cxBuilder.provide(cxConstAsset(CxGlobals, cxBuilder.context));
});

let logger: Logger;

beforeEach(() => {
logger = cxBuilder.get(Logger);
});

it('logs to most recent logger', () => {

const testLogger = {
error: jest.fn<void, unknown[]>(),
} as Partial<Logger> as Logger;

cxBuilder.provide(cxConstAsset(Logger, testLogger));

const error = new Error('Test');

logger.error('Error', error);

expect(testLogger.error).toHaveBeenCalledWith('Error', error);
expect(testLogger.error).toHaveBeenCalledTimes(1);
});
it('is singleton', () => {

const cxBuilder2 = new CxBuilder(get => ({ get }), cxBuilder);

expect(cxBuilder2.get(Logger)).toBe(logger);
});

describe('by default', () => {

let errorSpy: SpyInstance<void, unknown[]>;

beforeEach(() => {
errorSpy = spyOn(consoleLogger, 'error').mockImplementation(() => void 0);
});
afterEach(() => {
errorSpy.mockRestore();
});

it('logs to console', () => {

const error = new Error('Test');

logger.error('Error', error);

expect(errorSpy).toHaveBeenCalledWith('Error', error);
expect(errorSpy).toHaveBeenCalledTimes(1);
});
});

describe('toString', () => {
it('provides string representation', () => {
expect(String(Logger)).toBe('[Logger]');
});
});
});
25 changes: 25 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { CxEntry, CxGlobals, cxRecent, cxScoped } from '@proc7ts/context-values';
import { consoleLogger, proxyLogger } from './loggers';

/**
* Basic logger interface.
*/
Expand Down Expand Up @@ -41,3 +44,25 @@ export interface Logger {
trace(...args: unknown[]): void;

}

/**
* Global context entry containing logger to use.
*
* Logs to {@link consoleLogger console} by default.
*/
export const Logger: CxEntry<Logger> = {
perContext: (/*#__PURE__*/ cxScoped(
CxGlobals,
(/*#__PURE__*/ cxRecent({
create: (recent, _) => recent,
byDefault: _ => consoleLogger,
assign({ get, to }) {

const logger = proxyLogger(get);

return receiver => to((_, by) => receiver(logger, by));
},
})),
)),
toString: () => '[Logger]',
};

0 comments on commit 0ed2657

Please sign in to comment.