Skip to content

Commit fac8734

Browse files
committed
format schema and construct the db object to work the way the shell-api expects
1 parent 1789f77 commit fac8734

File tree

6 files changed

+84
-38
lines changed

6 files changed

+84
-38
lines changed

packages/mongodb-ts-autocomplete/scripts/extract-types.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ async function run() {
3333
),
3434
'/mql.ts': path.join(__dirname, '..', 'src', 'fixtures', 'mql.ts'),
3535
'/shell-api.ts': path.join(
36-
__dirname,
36+
require.resolve('@mongosh/shell-api'),
3737
'..',
38-
'src',
39-
'fixtures',
40-
'shell-api.ts',
38+
'api-processed.d.ts',
4139
),
4240
};
4341
const files = await loadSources(input);

packages/mongodb-ts-autocomplete/src/autocompleter.spec.ts

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { AutocompletionContext } from './autocompletion-context';
33
import { analyzeDocuments } from 'mongodb-schema';
44
import { expect } from 'chai';
55

6-
describe('MongoDBAutocompleter', function () {
6+
describe.only('MongoDBAutocompleter', function () {
77
let autocompleterContext: AutocompletionContext;
88
let autocompleter: MongoDBAutocompleter;
99

@@ -59,32 +59,22 @@ describe('MongoDBAutocompleter', function () {
5959
// Note that the types are all blank objects for now because we haven't
6060
// sampled any of these collections' schemas yet
6161
expect(
62-
completions.filter((c) => /property|method/.test(c.kind)),
62+
completions
63+
.filter((c) => /property|method/.test(c.kind))
64+
.filter((c) => c.name === 'foo'),
6365
).to.deep.equal([
64-
{
65-
kind: 'property',
66-
name: 'bar',
67-
result: 'db.bar',
68-
},
69-
{
70-
kind: 'property',
71-
name: 'baz',
72-
result: 'db.baz',
73-
},
7466
{
7567
kind: 'property',
7668
name: 'foo',
7769
result: 'db.foo',
7870
},
79-
{
80-
kind: 'method',
81-
name: 'runCommand',
82-
result: 'db.runCommand',
83-
},
8471
]);
8572
});
8673

87-
it('completes a collection field name in a query', async function () {
74+
// TODO: We need MONGOSH-2170 so that we can use the generated MQL types via
75+
// the Shell API to autocomplete fields in
76+
// ServerSchema[databaseName][collectionName].schema
77+
it.skip('completes a collection field name in a query', async function () {
8878
const completions = await autocompleter.autocomplete('db.foo.find({ fo');
8979

9080
expect(
@@ -107,4 +97,49 @@ describe('MongoDBAutocompleter', function () {
10797
},
10898
]);
10999
});
100+
101+
describe('getConnectionCode', function () {
102+
it('generates code for a connection', async function () {
103+
const docs = [
104+
{
105+
foo: 'foo',
106+
bar: 1,
107+
baz: {
108+
a: 1,
109+
b: 'b',
110+
},
111+
},
112+
];
113+
114+
const analyzedDocuments = await analyzeDocuments(docs);
115+
const schema = await analyzedDocuments.getMongoDBJsonSchema();
116+
117+
const connection = autocompleter.addConnection('my-connectionId');
118+
connection.addCollectionSchema(
119+
'my-databaseName',
120+
'my-collectionName',
121+
schema,
122+
);
123+
const code = autocompleter.getConnectionCode('my-connectionId');
124+
expect(code).to.equal(`
125+
import * as ShellAPI from '/shell-api.ts';
126+
import * as bson from '/bson.ts';
127+
128+
export type ServerSchema = {
129+
'my-databaseName': {
130+
'my-collectionName': {
131+
schema: {
132+
bar?: bson.Double | number;
133+
baz?: {
134+
a?: bson.Double | number;
135+
b?: string;
136+
};
137+
foo?: string;
138+
}
139+
};
140+
}
141+
};
142+
`);
143+
});
144+
});
110145
});

packages/mongodb-ts-autocomplete/src/autocompleter.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,17 @@ class DatabaseSchema {
5757
toTypescriptTypeDefinition(): string {
5858
const collectionProperties = Object.entries(this.collectionSchemas).map(
5959
([collectionName, schema]) => {
60-
const def = schema ? toTypescriptTypeDefinition(schema) : `{}`;
61-
return ` '${collectionName}': ShellAPI.Collection<${def}>;`;
60+
const def: string = schema ? toTypescriptTypeDefinition(schema) : `{}`;
61+
const lines = def.split(/\n/g).map((line) => ` ${line}`);
62+
return ` '${collectionName}': {
63+
schema: ${lines.join('\n').trim()}
64+
};`;
6265
},
6366
);
6467

6568
return `{
6669
${collectionProperties.join('\n')}
67-
}`;
70+
}`;
6871
}
6972
}
7073

@@ -107,7 +110,7 @@ class ConnectionSchema {
107110
const databaseProperties = Object.entries(this.databaseSchemas).map(
108111
([databaseName, schema]) => {
109112
const def = schema.toTypescriptTypeDefinition();
110-
return ` '${databaseName}': ShellAPI.Database & ${def}`;
113+
return `'${databaseName}': ${def}`;
111114
},
112115
);
113116

@@ -151,12 +154,13 @@ export type ServerSchema = ${this.connectionSchemas[
151154

152155
getCurrentGlobalsCode(connectionId: string, databaseName: string) {
153156
return `
157+
import * as ShellAPI from '/shell-api.ts';
154158
import { ServerSchema } from '/${connectionId}.ts';
155159
156160
type CurrentDatabaseSchema = ServerSchema['${databaseName}'];
157161
158162
declare global {
159-
var db: CurrentDatabaseSchema;
163+
var db: ShellAPI.Database<ServerSchema, CurrentDatabaseSchema>;
160164
}
161165
`;
162166
}

packages/mongodb-ts-autocomplete/src/fixtures/autocomplete-types.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/mongodb-ts-autocomplete/src/fixtures/shell-api.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33

44
import type * as mql from './mql.ts';
55

6-
export interface Collection<T> {
7-
find(query: mql.Filter<T>): mql.Cursor<T>;
8-
findOne(query: mql.Filter<T>): T;
9-
aggregate(pipeline: mql.Pipeline<T>): mql.Cursor<T>;
10-
insertOne(value: T): void;
11-
insertMany(value: mql.Array<T>): void;
12-
updateOne(query: mql.Filter<T>, modifier: Partial<T> | mql.Pipeline<T>): void;
6+
export interface Collection<T extends { schema: mql.Document }> {
7+
find(query: mql.Filter<T['schema']>): mql.Cursor<T['schema']>;
8+
findOne(query: mql.Filter<T['schema']>): T['schema'];
9+
aggregate(pipeline: mql.Pipeline<T['schema']>): mql.Cursor<T['schema']>;
10+
insertOne(value: T['schema']): void;
11+
insertMany(value: mql.Array<T['schema']>): void;
12+
updateOne(
13+
query: mql.Filter<T['schema']>,
14+
modifier: Partial<T> | mql.Pipeline<T['schema']>,
15+
): void;
1316
updateMany(
14-
query: mql.Filter<T>,
15-
modifier: Partial<T> | mql.Pipeline<T>,
17+
query: mql.Filter<T['schema']>,
18+
modifier: Partial<T['schema']> | mql.Pipeline<T['schema']>,
1619
): void;
1720
}
1821

packages/ts-autocomplete/src/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ function getVirtualLanguageService(): {
2121
target: ts.ScriptTarget.ES2022,
2222
allowJs: true,
2323
moduleResolution: ts.ModuleResolutionKind.NodeNext,
24-
typeRoots: [],
24+
types: ['node'],
25+
//typeRoots: [],
2526
allowImportingTsExtensions: true,
2627
};
2728

@@ -162,6 +163,11 @@ function filterDiagnostics(diagnostics: ts.Diagnostic[]): {
162163
..._.pick(item.file, 'fileName', 'text'),
163164
..._.pick(item, 'messageText'),
164165
};
166+
167+
if (result.fileName === '/shell-api.ts') {
168+
delete result.text;
169+
}
170+
165171
return result;
166172
});
167173
}

0 commit comments

Comments
 (0)