Skip to content

Commit 967c479

Browse files
committed
recreate the tsc crash we're seeing in mongosh
1 parent 1770691 commit 967c479

File tree

1 file changed

+156
-0
lines changed
  • packages/mql-typescript/tests

1 file changed

+156
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
import type * as schema from '../out/schema';
3+
import type { Document } from 'bson';
4+
5+
interface GenericCollectionSchema {
6+
schema: Document;
7+
}
8+
interface GenericDatabaseSchema {
9+
[key: string]: GenericCollectionSchema;
10+
}
11+
interface GenericServerSideSchema {
12+
[key: string]: GenericDatabaseSchema;
13+
}
14+
type StringKey<T> = keyof T & string;
15+
16+
class Mongo<M extends GenericServerSideSchema = GenericServerSideSchema> {}
17+
18+
type CollectionWithSchema<
19+
M extends GenericServerSideSchema = GenericServerSideSchema,
20+
D extends GenericDatabaseSchema = M[keyof M],
21+
C extends GenericCollectionSchema = D[keyof D],
22+
N extends StringKey<D> = StringKey<D>,
23+
> = Collection<M, D, C, N> & {
24+
[k in StringKey<D> as k extends `${N}.${infer S}` ? S : never]: Collection<
25+
M,
26+
D,
27+
D[k],
28+
k
29+
>;
30+
};
31+
32+
class Collection<
33+
M extends GenericServerSideSchema = GenericServerSideSchema,
34+
D extends GenericDatabaseSchema = M[keyof M],
35+
C extends GenericCollectionSchema = D[keyof D],
36+
N extends StringKey<D> = StringKey<D>,
37+
> {
38+
_mongo: Mongo<M>;
39+
_database: DatabaseWithSchema<M, D>;
40+
_name: N;
41+
constructor(
42+
mongo: Mongo<M>,
43+
database: DatabaseWithSchema<M, D> | Database<M, D>,
44+
name: N,
45+
) {
46+
this._mongo = mongo;
47+
this._database = database as DatabaseWithSchema<M, D>;
48+
this._name = name;
49+
}
50+
getName(): N {
51+
return this._name;
52+
}
53+
async find(
54+
query?: schema.Query<Document>,
55+
projection?: Document,
56+
options: Document = {},
57+
): Promise<schema.Query<Document> | undefined> {
58+
//): Promise<Document | undefined> {
59+
return Promise.resolve(query);
60+
}
61+
}
62+
63+
type DatabaseWithSchema<
64+
M extends GenericServerSideSchema = GenericServerSideSchema,
65+
D extends GenericDatabaseSchema = GenericDatabaseSchema,
66+
> = Database<M, D> & {
67+
[k in StringKey<D>]: Collection<M, D, D[k], k>;
68+
};
69+
70+
function isValidCollectionName(name: string): boolean {
71+
return !!name && !/[$\0]/.test(name);
72+
}
73+
74+
export class Database<
75+
M extends GenericServerSideSchema = GenericServerSideSchema,
76+
D extends GenericDatabaseSchema = GenericDatabaseSchema,
77+
> {
78+
_mongo: Mongo<M>;
79+
_name: StringKey<M>;
80+
_collections: Record<StringKey<D>, CollectionWithSchema<M, D>>;
81+
82+
constructor(mongo: Mongo<M>, name: StringKey<M>) {
83+
this._mongo = mongo;
84+
this._name = name;
85+
const collections: Record<
86+
string,
87+
CollectionWithSchema<M, D>
88+
> = Object.create(null);
89+
this._collections = collections;
90+
91+
const proxy = new Proxy(this, {
92+
get: (target, prop): any => {
93+
if (prop in target) {
94+
return (target as any)[prop];
95+
}
96+
97+
if (
98+
typeof prop !== 'string' ||
99+
prop.startsWith('_') ||
100+
!isValidCollectionName(prop)
101+
) {
102+
return;
103+
}
104+
105+
if (!collections[prop]) {
106+
collections[prop] = new Collection<M, D>(
107+
mongo,
108+
proxy,
109+
prop,
110+
) as CollectionWithSchema<M, D>;
111+
}
112+
113+
return collections[prop];
114+
},
115+
});
116+
return proxy;
117+
}
118+
119+
getCollection<K extends StringKey<D>>(
120+
coll: K,
121+
): CollectionWithSchema<M, D, D[K], K> {
122+
const collection = new Collection<M, D, D['myCollection']>(
123+
this._mongo,
124+
this,
125+
'myCollection',
126+
);
127+
128+
return collection as CollectionWithSchema<M, D, D[K], K>;
129+
}
130+
}
131+
132+
async function run() {
133+
const serverSchema = {
134+
myDatabase: {
135+
myCollection: {
136+
schema: {
137+
_id: 'ObjectId',
138+
name: 'string',
139+
age: 'number',
140+
},
141+
},
142+
},
143+
};
144+
const mongo = new Mongo<typeof serverSchema>();
145+
const db = new Database<
146+
typeof serverSchema,
147+
(typeof serverSchema)['myDatabase']
148+
>(mongo, 'myDatabase') as DatabaseWithSchema<
149+
typeof serverSchema,
150+
(typeof serverSchema)['myDatabase']
151+
>;
152+
const query = await db.myCollection.find({ name: 'foo' });
153+
console.log(query);
154+
}
155+
156+
run().catch(console.error);

0 commit comments

Comments
 (0)