Skip to content

Commit 899a54f

Browse files
authored
Merge #336 always use custom logger if given
2 parents a19148b + 84c2aea commit 899a54f

File tree

14 files changed

+178
-84
lines changed

14 files changed

+178
-84
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- fix: console.log() writes to RPC channel #202 #329
66
- feat: eliminate `which` dependency
77
- feat: improve logs + error messages
8+
- fix: always use custom logger if one is given
89

910
## [5.0.1](https://github.com/neovim/node-client/compare/v4.11.0...v5.0.1) (2024-03-01)
1011

packages/integration-tests/src/factory.test.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
/* eslint-env jest */
2-
import { NvimPlugin, loadPlugin } from 'neovim';
2+
import { Neovim, NeovimClient, NvimPlugin, loadPlugin } from 'neovim';
3+
4+
function getFakeNvimClient(): NeovimClient {
5+
const logged: string[] = [];
6+
let logger2 = {};
7+
const fakeLog = (msg: any) => {
8+
logged.push(msg);
9+
return logger2;
10+
};
11+
logger2 = {
12+
info: fakeLog,
13+
warn: fakeLog,
14+
debug: fakeLog,
15+
error: fakeLog,
16+
};
17+
return {
18+
logger: logger2 as any,
19+
} as NeovimClient;
20+
}
321

422
describe('Plugin Factory (used by host)', () => {
523
let pluginObj: NvimPlugin;
624

725
beforeEach(() => {
8-
pluginObj = loadPlugin('@neovim/example-plugin', null);
26+
const p = loadPlugin('@neovim/example-plugin', getFakeNvimClient());
27+
if (!p) {
28+
throw new Error();
29+
}
30+
pluginObj = p;
931
});
1032

1133
it('should collect the specs from a plugin file', () => {
@@ -58,21 +80,28 @@ describe('Plugin Factory (used by host)', () => {
5880
});
5981

6082
it('loads plugin with instance of nvim API', () => {
61-
const nvim = {};
83+
const nvim = getFakeNvimClient();
6284
const plugin = loadPlugin('@neovim/example-plugin', nvim);
63-
expect(plugin.nvim).toBe(nvim);
85+
expect(plugin?.nvim).toBe(nvim);
6486
});
6587

6688
it('returns null on invalid module', () => {
67-
expect(loadPlugin('/asdlfjka/fl', {}, {})).toBeNull();
89+
expect(loadPlugin('/asdlfjka/fl', {} as Neovim, {})).toBeNull();
6890
});
6991
});
7092

7193
describe('Plugin Factory (decorator api)', () => {
7294
let pluginObj: NvimPlugin;
7395

7496
beforeEach(() => {
75-
pluginObj = loadPlugin('@neovim/example-plugin-decorators', null);
97+
const p = loadPlugin(
98+
'@neovim/example-plugin-decorators',
99+
getFakeNvimClient()
100+
);
101+
if (!p) {
102+
throw new Error();
103+
}
104+
pluginObj = p;
76105
});
77106

78107
it('should collect the specs from a plugin file', () => {
@@ -123,21 +152,21 @@ describe('Plugin Factory (decorator api)', () => {
123152
});
124153

125154
it('loads plugin with instance of nvim API', () => {
126-
const nvim = {} as any;
155+
const nvim = getFakeNvimClient();
127156
const plugin = loadPlugin('@neovim/example-plugin-decorators', nvim, {});
128-
expect(plugin.nvim).toBe(nvim);
157+
expect(plugin!.nvim).toBe(nvim);
129158
});
130159

131160
it('cannot call illegal process functions', () => {
132-
const nvim = {} as any;
161+
const nvim = getFakeNvimClient();
133162
const plugin = loadPlugin('@neovim/example-plugin-decorators', nvim, {});
134-
expect(plugin.functions.Illegal.fn).toThrow();
163+
expect(plugin!.functions.Illegal.fn).toThrow();
135164
});
136165

137166
it('can read process.umask()', () => {
138-
const nvim = {} as any;
167+
const nvim = getFakeNvimClient();
139168
const plugin = loadPlugin('@neovim/example-plugin-decorators', nvim, {});
140-
expect(() => plugin.functions.Umask.fn()).not.toThrow();
141-
expect(plugin.functions.Umask.fn()).toBeDefined();
169+
expect(() => plugin!.functions.Umask.fn()).not.toThrow();
170+
expect(plugin!.functions.Umask.fn()).toBeDefined();
142171
});
143172
});

packages/neovim/bin/cli.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env node
22
const { Host } = require('../lib/host');
3-
const { logger } = require('../lib/utils/logger');
43
const { spawnSync } = require('child_process');
54

65
// node <current script> <rest of args>
@@ -35,9 +34,9 @@ try {
3534
const host = new Host(args);
3635
host.start({ proc: process });
3736
} catch (err) {
38-
logger.error(err);
37+
process.stderr.write(`failed to start Nvim plugin host: ${err.name}: ${err.message}\n`);
3938
}
4039

4140
process.on('unhandledRejection', (reason, p) => {
42-
logger.info('Unhandled Rejection at:', p, 'reason:', reason);
41+
process.stderr.write(`Unhandled Rejection at: ${p} reason: ${reason}\n`);
4342
});

packages/neovim/src/api/Base.ts

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { EventEmitter } from 'node:events';
22

33
import { Transport } from '../utils/transport';
4-
import { Logger } from '../utils/logger';
4+
import { Logger, getLogger } from '../utils/logger';
55
import { VimValue } from '../types/VimValue';
66

77
export interface BaseConstructorOptions {
@@ -50,7 +50,7 @@ export class BaseApi extends EventEmitter {
5050
this.setTransport(transport);
5151
this.data = data;
5252
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
53-
this.logger = logger || require('../utils/logger').logger;
53+
this.logger = logger || getLogger();
5454
this.client = client;
5555

5656
if (metadata) {
@@ -73,7 +73,7 @@ export class BaseApi extends EventEmitter {
7373
[DO_REQUEST] = (name: string, args: any[] = []): Promise<any> =>
7474
new Promise((resolve, reject) => {
7575
this.transport.request(name, args, (err: any, res: any) => {
76-
this.logger.debug(`response -> neovim.api.${name}: ${res}`);
76+
this.logger.debug(`response -> ${name}: ${res}`);
7777
if (err) {
7878
reject(new Error(`${name}: ${err[1]}`));
7979
} else {
@@ -82,22 +82,18 @@ export class BaseApi extends EventEmitter {
8282
});
8383
});
8484

85-
async asyncRequest(
86-
name: string,
87-
args: any[] = [],
88-
stack: string | undefined = undefined
89-
): Promise<any> {
85+
async asyncRequest(name: string, args: any[] = []): Promise<any> {
9086
// `this._isReady` is undefined in ExtType classes (i.e. Buffer, Window, Tabpage)
9187
// But this is just for Neovim API, since it's possible to call this method from Neovim class
9288
// before transport is ready.
9389
// Not possible for ExtType classes since they are only created after transport is ready
9490
await this._isReady;
9591

96-
this.logger.debug(`request -> neovim.api.${name}`);
92+
this.logger.debug(`request -> ${name}`);
9793

9894
return this[DO_REQUEST](name, args).catch(err => {
95+
// XXX: Get a `*.ts stacktrace. If we re-throw `err` we get a `*.js` trace. tsconfig issue?
9996
const newError = new Error(err.message);
100-
newError.stack = stack;
10197
this.logger.error(
10298
`failed request to "%s": %s: %s`,
10399
name,
@@ -109,12 +105,7 @@ export class BaseApi extends EventEmitter {
109105
}
110106

111107
request(name: string, args: any[] = []): Promise<any> {
112-
// Dummy error, to get stacktrace.
113-
const error = new Error(
114-
`failed request to "${name}" (see $NVIM_NODE_LOG_FILE for details, if it was set)`
115-
);
116-
117-
return this.asyncRequest(name, args, error.stack);
108+
return this.asyncRequest(name, args);
118109
}
119110

120111
_getArgsByPrefix(...args: any[]): any[] {
@@ -169,7 +160,7 @@ export class BaseApi extends EventEmitter {
169160
// TODO: Is this necessary?
170161
/** `request` is basically the same except you can choose to wait forpromise to be resolved */
171162
notify(name: string, args: any[]): void {
172-
this.logger.debug(`notify -> neovim.api.${name}`);
163+
this.logger.debug(`notify -> ${name}`);
173164
this.transport.notify(name, args);
174165
}
175166
}

packages/neovim/src/api/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Handles attaching transport
33
*/
4-
import { logger } from '../utils/logger';
4+
import { Logger } from '../utils/logger';
55
import { Transport } from '../utils/transport';
66
import { VimValue } from '../types/VimValue';
77
import { Neovim } from './Neovim';
@@ -18,7 +18,7 @@ export class NeovimClient extends Neovim {
1818

1919
private attachedBuffers: Map<string, Map<string, Function[]>> = new Map();
2020

21-
constructor(options: { transport?: Transport; logger?: typeof logger } = {}) {
21+
constructor(options: { transport?: Transport; logger?: Logger } = {}) {
2222
// Neovim has no `data` or `metadata`
2323
super({
2424
logger: options.logger,

packages/neovim/src/attach/attach.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createConnection } from 'node:net';
22
import * as child from 'node:child_process';
33

44
import { NeovimClient } from '../api/client';
5-
import { Logger } from '../utils/logger';
5+
import { Logger, getLogger } from '../utils/logger';
66

77
export interface Attach {
88
reader?: NodeJS.ReadableStream;
@@ -38,7 +38,7 @@ export function attach({
3838

3939
if (writer && reader) {
4040
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
41-
const loggerInstance = options.logger || require('../utils/logger').logger; // lazy load to winston only if needed
41+
const loggerInstance = options.logger || getLogger(); // lazy load to winston only if needed
4242
const neovim = new NeovimClient({ logger: loggerInstance });
4343
neovim.attach({
4444
writer,

packages/neovim/src/host/NvimPlugin.test.ts

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,37 @@
11
/* eslint-env jest */
2+
import { getFakeNvimClient } from '../testUtil';
23
import { callable, NvimPlugin } from './NvimPlugin';
34

45
describe('NvimPlugin', () => {
56
it('should initialise variables', () => {
6-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
7+
const fakeNvimClient = getFakeNvimClient();
8+
const plugin = new NvimPlugin('/tmp/filename', () => {}, fakeNvimClient);
79

810
expect(plugin.filename).toEqual('/tmp/filename');
9-
expect(plugin.nvim).toEqual({});
11+
expect(plugin.nvim).toEqual(fakeNvimClient);
1012
expect(plugin.dev).toBe(false);
1113
expect(Object.keys(plugin.autocmds)).toHaveLength(0);
1214
expect(Object.keys(plugin.commands)).toHaveLength(0);
1315
expect(Object.keys(plugin.functions)).toHaveLength(0);
1416
});
1517

1618
it('should set dev options when you call setOptions', () => {
17-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
19+
const plugin = new NvimPlugin(
20+
'/tmp/filename',
21+
() => {},
22+
getFakeNvimClient()
23+
);
1824
plugin.setOptions({ dev: true });
1925
expect(plugin.dev).toBe(true);
2026
expect(plugin.shouldCacheModule).toBe(false);
2127
});
2228

2329
it('should store registered autocmds', () => {
24-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
30+
const plugin = new NvimPlugin(
31+
'/tmp/filename',
32+
() => {},
33+
getFakeNvimClient()
34+
);
2535
const fn = () => {};
2636
const opts = { pattern: '*' };
2737
const spec = {
@@ -36,7 +46,11 @@ describe('NvimPlugin', () => {
3646
});
3747

3848
it('should store registered commands', () => {
39-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
49+
const plugin = new NvimPlugin(
50+
'/tmp/filename',
51+
() => {},
52+
getFakeNvimClient()
53+
);
4054
const fn = () => {};
4155
const opts = { sync: true };
4256
const spec = {
@@ -51,7 +65,11 @@ describe('NvimPlugin', () => {
5165
});
5266

5367
it('should store registered functions', () => {
54-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
68+
const plugin = new NvimPlugin(
69+
'/tmp/filename',
70+
() => {},
71+
getFakeNvimClient()
72+
);
5573
const fn = () => {};
5674
const opts = { sync: true };
5775
const spec = {
@@ -66,7 +84,11 @@ describe('NvimPlugin', () => {
6684
});
6785

6886
it('should not add autocmds with no pattern option', () => {
69-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
87+
const plugin = new NvimPlugin(
88+
'/tmp/filename',
89+
() => {},
90+
getFakeNvimClient()
91+
);
7092
plugin.registerAutocmd('BufWritePre', () => {}, { pattern: '' });
7193
expect(Object.keys(plugin.autocmds)).toHaveLength(0);
7294
});
@@ -82,7 +104,11 @@ describe('NvimPlugin', () => {
82104
const thisObj = {};
83105
expect(callable([thisObj, fn])()).toBe(thisObj);
84106

85-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
107+
const plugin = new NvimPlugin(
108+
'/tmp/filename',
109+
() => {},
110+
getFakeNvimClient()
111+
);
86112
const obj = {
87113
func: jest.fn(function () {
88114
return this;
@@ -97,13 +123,21 @@ describe('NvimPlugin', () => {
97123
});
98124

99125
it('should not register commands with incorrect callable arguments', () => {
100-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
126+
const plugin = new NvimPlugin(
127+
'/tmp/filename',
128+
() => {},
129+
getFakeNvimClient()
130+
);
101131
plugin.registerCommand('MyCommand', [], {});
102132
expect(Object.keys(plugin.commands)).toHaveLength(0);
103133
});
104134

105135
it('should return specs for registered commands', () => {
106-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
136+
const plugin = new NvimPlugin(
137+
'/tmp/filename',
138+
() => {},
139+
getFakeNvimClient()
140+
);
107141
const fn = () => {};
108142
const aOpts = { pattern: '*' };
109143
const aSpec = {
@@ -136,7 +170,11 @@ describe('NvimPlugin', () => {
136170
});
137171

138172
it('should handle requests for registered commands', async () => {
139-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
173+
const plugin = new NvimPlugin(
174+
'/tmp/filename',
175+
() => {},
176+
getFakeNvimClient()
177+
);
140178
const fn = arg => arg;
141179

142180
plugin.registerAutocmd('BufWritePre', fn, { pattern: '*', sync: true });
@@ -155,7 +193,11 @@ describe('NvimPlugin', () => {
155193
});
156194

157195
it('should throw on unknown request', () => {
158-
const plugin = new NvimPlugin('/tmp/filename', () => {}, {});
196+
const plugin = new NvimPlugin(
197+
'/tmp/filename',
198+
() => {},
199+
getFakeNvimClient()
200+
);
159201
expect.assertions(1);
160202
plugin.handleRequest('BufWritePre *', 'autocmd', [true]).catch(err => {
161203
expect(err).toEqual(

0 commit comments

Comments
 (0)