Skip to content

Commit 5ad5568

Browse files
committed
fix: refactor, lint and bump to 0.0.10
1 parent 403a3ea commit 5ad5568

File tree

14 files changed

+101
-121
lines changed

14 files changed

+101
-121
lines changed

snippets/ai/.eslintrc.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
const { fixCygwinPath } = require('@mongodb-js/eslint-config-mongosh/utils');
21

32
module.exports = {
43
root: true,
5-
extends: ['@mongodb-js/eslint-config-mongosh'],
4+
extends: ['@mongodb-js/eslint-config-devtools'],
65
parserOptions: {
7-
tsconfigRootDir: fixCygwinPath(__dirname),
6+
tsconfigRootDir: __dirname,
87
project: ['./tsconfig-lint.json'],
98
},
9+
rules: {
10+
'@typescript-eslint/consistent-type-imports': 'off',
11+
'@typescript-eslint/no-var-requires': 'off',
12+
},
1013
};

snippets/ai/package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

snippets/ai/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@gagik.co/snippet-ai",
33
"snippetName": "ai",
4-
"version": "0.0.2",
4+
"version": "0.0.10",
55
"description": "Provides a ai command suite for mongosh to ask for MongoDB query expressions in natural language.",
66
"author": "Gagik Amaryan",
77
"main": "dist/index.js",
@@ -12,6 +12,7 @@
1212
},
1313
"scripts": {
1414
"build": "tsc",
15+
"lint": "eslint src",
1516
"prepare": "npm run build"
1617
},
1718
"dependencies": {
@@ -27,6 +28,7 @@
2728
"devDependencies": {
2829
"@mongodb-js/connection-info": "^0.12.0",
2930
"@mongodb-js/eslint-config-compass": "^1.3.8",
31+
"@mongodb-js/eslint-config-devtools": "^0.9.11",
3032
"@mongodb-js/prettier-config-devtools": "^1.0.2",
3133
"@types/node": "^20.17.47",
3234
"mongodb-rag-core": "^0.7.0",

snippets/ai/src/ai.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Config, ConfigSchema } from './config.js';
33
import type { CliContext } from './helpers.js';
44
import type { Models } from './providers/generic/ai-sdk-provider.js';
55

6-
module.exports = ((globalThis: CliContext) => {
6+
module.exports = (async (globalThis: CliContext) => {
77
const _localRequire = require('module').createRequire(__filename);
88
const localRequire = <T>(module: string): T => _localRequire(module);
99

@@ -16,7 +16,7 @@ module.exports = ((globalThis: CliContext) => {
1616
const chalk = localRequire<typeof import('chalk')>('chalk');
1717
class AI {
1818
private readonly replConfig: {
19-
set: (key: string, value: any) => Promise<void>;
19+
set: (key: string, value: unknown) => Promise<void>;
2020
get: <T>(key: string) => Promise<T>;
2121
};
2222

@@ -36,14 +36,15 @@ class AI {
3636
this.config = new Config(this.replConfig);
3737

3838
// Set up provider change listener
39+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
3940
this.config.on('change', async (event) => {
4041
switch (event.key) {
4142
case 'provider':
4243
this.ai = this.getProvider(event.value as ConfigSchema['provider']);
4344
break;
4445
case 'model':
4546
if (!Object.keys(models).includes(this.config.get('provider') as Models)) {
46-
if (event.value == 'default') {
47+
if (event.value === 'default') {
4748
return;
4849
}
4950
await this.config.set('model', 'default');
@@ -52,13 +53,13 @@ class AI {
5253
try {
5354
this.ai = getAiSdkProvider(
5455
models[this.config.get('provider') as keyof typeof models](
55-
event.value == 'default' ? undefined : event.value as string,
56+
event.value === 'default' ? undefined : event.value as string,
5657
),
5758
this.cliContext,
5859
this.config,
5960
);
6061
} catch (error) {
61-
throw new Error(`Invalid model, please ensure your name is correct: ${error}`);
62+
throw new Error(`Invalid model, please ensure your name is correct: ${error as string}`);
6263
}
6364
break;
6465
default:
@@ -71,10 +72,9 @@ class AI {
7172
);
7273
wrapAllFunctions(this.cliContext, this);
7374

74-
this.setupConfig();
7575
}
7676

77-
async setupConfig() {
77+
async setup() {
7878
await this.config.setup();
7979

8080
this.ai = this.getProvider(this.config.get('provider'));
@@ -88,13 +88,14 @@ class AI {
8888
return getDocsAiProvider(this.cliContext, this.config);
8989
case 'openai':
9090
case 'mistral':
91-
case 'ollama':
91+
case 'ollama': {
9292
const model = this.config.get('model');
9393
return getAiSdkProvider(
9494
models[provider](model === 'default' ? undefined : model),
9595
this.cliContext,
9696
this.config,
9797
);
98+
}
9899
default:
99100
return new EmptyAiProvider(this.cliContext, this.config);
100101
}
@@ -131,32 +132,32 @@ class AI {
131132
}
132133

133134
@aiCommand({requiresPrompt: false})
134-
async help() {
135+
help() {
135136
this.ai.help({
136137
provider: this.config.get('provider'),
137138
model: this.config.get('model'),
138139
});
139140
}
140141

141142
@aiCommand()
142-
async clear() {
143+
clear() {
143144
this.ai.clear();
144145
}
145146

146147
@aiCommand()
147-
async collection(name: string) {
148-
await this.ai.collection(name);
148+
collection(name: string) {
149+
this.ai.collection(name);
149150
}
150151

151152
@aiCommand()
152153
async provider(provider: string) {
153-
this.config.set('provider', provider);
154+
await this.config.set('provider', provider);
154155
this.ai.respond(`Switched to ${chalk.blue(provider)} provider`);
155156
}
156157

157158
@aiCommand()
158159
async model(model: string) {
159-
this.config.set('model', model);
160+
await this.config.set('model', model);
160161
this.ai.respond(`Switched to ${chalk.blue(model)} model`);
161162
}
162163

@@ -168,4 +169,8 @@ class AI {
168169

169170

170171
(globalThis as unknown as CliContext).ai = new AI(globalThis as unknown as CliContext);
172+
await (globalThis as unknown as {
173+
ai: AI;
174+
}).ai.setup();
175+
171176
});

snippets/ai/src/config.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const _localRequire = <T>(module: string): T => require(module).createRequire(__filename);
1+
const _localRequire = require('module').createRequire(__filename);
22
const localRequire = <T>(module: string): T => _localRequire(module);
33
import type { z as ZodType } from 'zod';
44

@@ -19,7 +19,7 @@ const configKeys = Object.keys(configSchema.shape) as Array<keyof ConfigSchema>;
1919
export type ConfigSchema = ZodType.infer<typeof configSchema>;
2020
type ConfigKeys = keyof ConfigSchema;
2121

22-
const defaults: Record<ConfigKeys, any> = {
22+
const defaults: Record<ConfigKeys, ConfigSchema[ConfigKeys]> = {
2323
provider: process.env.MONGOSH_AI_PROVIDER ?? 'docs',
2424
model: process.env.MONGOSH_AI_MODEL ?? 'default',
2525
includeSampleDocs: process.env.MONGOSH_AI_INCLUDE_SAMPLE_DOCS ?? true,
@@ -34,11 +34,11 @@ export class Config extends EventEmitter<{
3434
},
3535
];
3636
}> {
37-
private configMap: Record<string, any> = {};
37+
private configMap: Record<ConfigKeys, ConfigSchema[ConfigKeys]> = defaults;
3838

3939
constructor(
4040
private readonly replConfig: {
41-
set: (key: string, value: any) => Promise<void>;
41+
set: (key: string, value: unknown) => Promise<void>;
4242
get: <T>(key: string) => Promise<T>;
4343
},
4444
) {
@@ -48,13 +48,13 @@ export class Config extends EventEmitter<{
4848
async setup(): Promise<void> {
4949
const keys = Object.keys(configSchema.shape) as Array<keyof ConfigSchema>;
5050
for (const key of keys) {
51-
this.configMap[key] = (await this.replConfig.get(key)) ?? defaults[key];
51+
this.configMap[key] ??= (await this.replConfig.get(key));
5252
}
5353
}
5454

5555
get<K extends keyof ConfigSchema>(key: K): ConfigSchema[K] {
5656
this.assertKey(key);
57-
return this.configMap[key];
57+
return this.configMap[key] as ConfigSchema[K];
5858
}
5959

6060
assertKey(key: string): asserts key is ConfigKeys {
@@ -65,7 +65,7 @@ export class Config extends EventEmitter<{
6565
}
6666
}
6767

68-
async set(key: ConfigKeys, value: any): Promise<void> {
68+
async set(key: ConfigKeys, value: ConfigSchema[ConfigKeys]): Promise<void> {
6969
this.assertKey(key);
7070

7171
// Validate the value based on the key
@@ -82,9 +82,9 @@ export class Config extends EventEmitter<{
8282
if (schema._def.typeName === 'ZodEnum') {
8383
type = `${schema._def.values.join(' | ')}`;
8484
}
85-
const i = (value: any) => inspect(value, {colors: true});
85+
const i = (value: unknown) => inspect(value, {colors: true});
8686

87-
return ` ${i(key)}: ${chalk.white(i(this.configMap[key]))},${type ? chalk.gray(` // ${type}`) : ''}`;
87+
return ` ${i(key)}: ${chalk.white(i(this.configMap[key as ConfigKeys]))},${type ? chalk.gray(` // ${type}`) : ''}`;
8888
});
8989

9090
return `{\n${lines.join('\n')}\n}`;

snippets/ai/src/decorators.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ export interface AiCommandOptions {
55
export function aiCommand({
66
requiresPrompt = true,
77
}: AiCommandOptions = {}) {
8-
return function decorator<T extends Function>(
8+
return function decorator<T extends (...args: string[]) => unknown>(
99
value: T,
1010
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1111
context: ClassMethodDecoratorContext
1212
): T & { isDirectShellCommand: true } {
13-
const wrappedFunction = function(this: any, ...args: any[]) {
13+
const wrappedFunction = function(this: unknown, ...args: string[]) {
1414
if (requiresPrompt === false && args.length > 0) {
1515
throw new Error('This command does not accept any arguments');
1616
} else if (requiresPrompt && args.length === 0) {

snippets/ai/src/helpers.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,30 +54,37 @@ export class LoadingAnimation {
5454
export interface CliContext {
5555
ai: unknown;
5656
db: {
57+
_name: string;
58+
getCollectionNames: () => Promise<string[]>;
59+
getCollection: (name: string) => {
60+
aggregate: (pipeline: unknown[]) => Promise<{
61+
toArray: () => Promise<Record<string, unknown>[]>;
62+
}>;
63+
};
5764
_mongo: {
5865
_instanceState: {
5966
evaluationListener: {
60-
setConfig: (key: string, value: any) => Promise<void>;
67+
setConfig: (key: string, value: unknown) => Promise<void>;
6168
getConfig: <T>(key: string) => Promise<T>;
6269
};
63-
registerPlugin: (plugin: any) => void;
64-
shellApi: Record<string, any>;
65-
context: Record<string, any>;
70+
registerPlugin: (plugin: unknown) => void;
71+
shellApi: Record<string, unknown>;
72+
context: Record<string, unknown>;
6673
};
6774
};
6875
};
6976
}
7077

7178
export function wrapFunction(
7279
cliContext: CliContext,
73-
instance: any,
80+
instance: unknown,
7481
name: string | undefined,
75-
fn: Function,
82+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
83+
fn: (..._args: unknown[]) => Record<string, unknown>,
7684
) {
77-
const wrapperFn = (...args: string[]) => {
78-
return Object.assign(fn(...args), {
79-
[Symbol.for('@@mongosh.syntheticPromise')]: true,
80-
});
85+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
86+
const wrapperFn = (..._args: unknown[]) => {
87+
return fn(..._args);
8188
};
8289
wrapperFn.isDirectShellCommand = true;
8390
wrapperFn.returnsPromise = true;
@@ -89,8 +96,14 @@ export function wrapFunction(
8996
] = wrapperFn;
9097
}
9198

92-
export function wrapAllFunctions(cliContext: CliContext, instance: any) {
99+
export function wrapAllFunctions(cliContext: CliContext, currentInstance: unknown) {
93100
const instanceState = cliContext.db._mongo._instanceState;
101+
const instance = currentInstance as {
102+
[key: string]: (...args: unknown[]) => Record<string, unknown> | {
103+
isDirectShellCommand: boolean;
104+
}
105+
};
106+
94107
const methods = Object.getOwnPropertyNames(
95108
Object.getPrototypeOf(instance),
96109
).filter((name) => {
@@ -105,10 +118,12 @@ export function wrapAllFunctions(cliContext: CliContext, instance: any) {
105118
);
106119
});
107120

121+
122+
108123
// for all methods, wrap them with the wrapFunction method
109124
for (const methodName of methods) {
110125
const method = instance[methodName];
111-
if (typeof method === 'function' && method.isDirectShellCommand) {
126+
if (typeof method === 'function' && (method as unknown as { isDirectShellCommand: boolean }).isDirectShellCommand) {
112127
wrapFunction(cliContext, instance, methodName, method.bind(instance));
113128
}
114129
}

snippets/ai/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// tsc generates a module.exports for TypeScript files so we have this wrapper to load the module
22
(() => {
33
const localRequire = require('module').createRequire(__filename);
4+
// eslint-disable-next-line no-undef
45
localRequire('./ai.js')(globalThis);
56
})();

snippets/ai/src/logger.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,23 @@ const IS_DEBUG = process.env.DEBUG === 'true';
77
class Logger extends EventEmitter {
88
debug(...args: unknown[]) {
99
if (IS_DEBUG) {
10+
// eslint-disable-next-line no-console
1011
console.debug(...args);
1112
this.emit('debug', ...args);
1213
}
1314
}
1415

1516
info(...args: unknown[]) {
1617
if (IS_DEBUG) {
18+
// eslint-disable-next-line no-console
1719
console.info(...args);
1820
this.emit('info', ...args);
1921
}
2022
}
2123

2224
error(...args: unknown[]) {
2325
if (IS_DEBUG) {
26+
// eslint-disable-next-line no-console
2427
console.error(...args);
2528
this.emit('error', ...args);
2629
}

0 commit comments

Comments
 (0)