@bairock/lenz 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -8
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +66 -79
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +22 -30
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/studio.js +15 -21
- package/dist/cli/commands/studio.js.map +1 -1
- package/dist/cli/index.js +11 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +4 -6
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +31 -15
- package/dist/config/index.js.map +1 -1
- package/dist/engine/CodeGenerator.d.ts +8 -28
- package/dist/engine/CodeGenerator.d.ts.map +1 -1
- package/dist/engine/CodeGenerator.js +26 -1935
- package/dist/engine/CodeGenerator.js.map +1 -1
- package/dist/engine/GraphQLParseHelpers.d.ts +25 -0
- package/dist/engine/GraphQLParseHelpers.d.ts.map +1 -0
- package/dist/engine/GraphQLParseHelpers.js +128 -0
- package/dist/engine/GraphQLParseHelpers.js.map +1 -0
- package/dist/engine/GraphQLParser.d.ts +23 -8
- package/dist/engine/GraphQLParser.d.ts.map +1 -1
- package/dist/engine/GraphQLParser.js +165 -248
- package/dist/engine/GraphQLParser.js.map +1 -1
- package/dist/engine/GraphQLRelationAnalyzer.d.ts +10 -0
- package/dist/engine/GraphQLRelationAnalyzer.d.ts.map +1 -0
- package/dist/engine/GraphQLRelationAnalyzer.js +117 -0
- package/dist/engine/GraphQLRelationAnalyzer.js.map +1 -0
- package/dist/engine/LenzEngine.d.ts +4 -4
- package/dist/engine/LenzEngine.d.ts.map +1 -1
- package/dist/engine/LenzEngine.js +59 -46
- package/dist/engine/LenzEngine.js.map +1 -1
- package/dist/engine/SchemaRelationValidator.d.ts +15 -0
- package/dist/engine/SchemaRelationValidator.d.ts.map +1 -0
- package/dist/engine/SchemaRelationValidator.js +133 -0
- package/dist/engine/SchemaRelationValidator.js.map +1 -0
- package/dist/engine/SchemaValidator.d.ts +12 -11
- package/dist/engine/SchemaValidator.d.ts.map +1 -1
- package/dist/engine/SchemaValidator.js +163 -169
- package/dist/engine/SchemaValidator.js.map +1 -1
- package/dist/engine/directives.d.ts +10 -0
- package/dist/engine/directives.d.ts.map +1 -1
- package/dist/engine/directives.js +192 -47
- package/dist/engine/directives.js.map +1 -1
- package/dist/engine/generators/ClientGenerator.d.ts +7 -0
- package/dist/engine/generators/ClientGenerator.d.ts.map +1 -0
- package/dist/engine/generators/ClientGenerator.js +386 -0
- package/dist/engine/generators/ClientGenerator.js.map +1 -0
- package/dist/engine/generators/DelegateGenerator.d.ts +9 -0
- package/dist/engine/generators/DelegateGenerator.d.ts.map +1 -0
- package/dist/engine/generators/DelegateGenerator.js +453 -0
- package/dist/engine/generators/DelegateGenerator.js.map +1 -0
- package/dist/engine/generators/DelegateHelpers.d.ts +7 -0
- package/dist/engine/generators/DelegateHelpers.d.ts.map +1 -0
- package/dist/engine/generators/DelegateHelpers.js +144 -0
- package/dist/engine/generators/DelegateHelpers.js.map +1 -0
- package/dist/engine/generators/DelegateRelations.d.ts +11 -0
- package/dist/engine/generators/DelegateRelations.d.ts.map +1 -0
- package/dist/engine/generators/DelegateRelations.js +794 -0
- package/dist/engine/generators/DelegateRelations.js.map +1 -0
- package/dist/engine/generators/DelegateTemplateBody.d.ts +8 -0
- package/dist/engine/generators/DelegateTemplateBody.d.ts.map +1 -0
- package/dist/engine/generators/DelegateTemplateBody.js +776 -0
- package/dist/engine/generators/DelegateTemplateBody.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimeErrors.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimeErrors.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimeErrors.js +140 -0
- package/dist/engine/generators/GenerateRuntimeErrors.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimeIndex.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimeIndex.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimeIndex.js +21 -0
- package/dist/engine/generators/GenerateRuntimeIndex.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimeLogger.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimeLogger.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimeLogger.js +125 -0
- package/dist/engine/generators/GenerateRuntimeLogger.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimePagination.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimePagination.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimePagination.js +159 -0
- package/dist/engine/generators/GenerateRuntimePagination.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimeQuery.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimeQuery.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimeQuery.js +427 -0
- package/dist/engine/generators/GenerateRuntimeQuery.js.map +1 -0
- package/dist/engine/generators/GenerateRuntimeRelations.d.ts +2 -0
- package/dist/engine/generators/GenerateRuntimeRelations.d.ts.map +1 -0
- package/dist/engine/generators/GenerateRuntimeRelations.js +130 -0
- package/dist/engine/generators/GenerateRuntimeRelations.js.map +1 -0
- package/dist/engine/generators/RuntimeGenerator.d.ts +16 -0
- package/dist/engine/generators/RuntimeGenerator.d.ts.map +1 -0
- package/dist/engine/generators/RuntimeGenerator.js +16 -0
- package/dist/engine/generators/RuntimeGenerator.js.map +1 -0
- package/dist/engine/generators/TypeFilterTypes.d.ts +2 -0
- package/dist/engine/generators/TypeFilterTypes.d.ts.map +1 -0
- package/dist/engine/generators/TypeFilterTypes.js +220 -0
- package/dist/engine/generators/TypeFilterTypes.js.map +1 -0
- package/dist/engine/generators/TypeGenerator.d.ts +16 -0
- package/dist/engine/generators/TypeGenerator.d.ts.map +1 -0
- package/dist/engine/generators/TypeGenerator.js +493 -0
- package/dist/engine/generators/TypeGenerator.js.map +1 -0
- package/dist/engine/generators/helpers.d.ts +13 -0
- package/dist/engine/generators/helpers.d.ts.map +1 -0
- package/dist/engine/generators/helpers.js +316 -0
- package/dist/engine/generators/helpers.js.map +1 -0
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +3 -9
- package/dist/engine/index.js.map +1 -1
- package/dist/errors/index.d.ts +3 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +25 -32
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -30
- package/dist/index.js.map +1 -1
- package/package.json +6 -7
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { toCamelCase } from './helpers.js';
|
|
2
|
+
export class ClientGenerator {
|
|
3
|
+
generateIndex(clientName) {
|
|
4
|
+
return `// This file was auto-generated by Lenz. Do not edit manually.
|
|
5
|
+
// @generated
|
|
6
|
+
|
|
7
|
+
export { ${clientName} } from './client'
|
|
8
|
+
export * from './types'
|
|
9
|
+
export * from './enums'
|
|
10
|
+
|
|
11
|
+
import { ${clientName} } from './client'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default export for the Lenz client
|
|
15
|
+
*/
|
|
16
|
+
const lenz = new ${clientName}()
|
|
17
|
+
export default lenz
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
generateClient(clientName, models) {
|
|
21
|
+
return `// This file was auto-generated by Lenz. Do not edit manually.
|
|
22
|
+
// @generated
|
|
23
|
+
|
|
24
|
+
import { MongoClient, Db, ObjectId, Collection, Document } from 'mongodb'
|
|
25
|
+
import type { LenzConfig } from './types'
|
|
26
|
+
import { QueryBuilder } from './runtime/query'
|
|
27
|
+
import { RelationResolver } from './runtime/relations'
|
|
28
|
+
import { Logger } from './runtime/logger'
|
|
29
|
+
|
|
30
|
+
${models.map(model => `
|
|
31
|
+
import { ${model.name}Delegate } from './models/${model.name}'`).join('\n')}
|
|
32
|
+
|
|
33
|
+
export class ${clientName} {
|
|
34
|
+
private mongoClient: MongoClient | null = null
|
|
35
|
+
private db: Db | null = null
|
|
36
|
+
private config: LenzConfig
|
|
37
|
+
private database: string
|
|
38
|
+
private supportsTransactions: boolean = false
|
|
39
|
+
private logger: Logger
|
|
40
|
+
|
|
41
|
+
// Model delegates
|
|
42
|
+
${models.map(model => ` public ${toCamelCase(model.name)}: ${model.name}Delegate`).join('\n')}
|
|
43
|
+
|
|
44
|
+
private extractDatabaseFromUrl(url: string): string {
|
|
45
|
+
try {
|
|
46
|
+
const parsed = new URL(url);
|
|
47
|
+
const db = parsed.pathname.replace(/^\//, '').split('/')[0];
|
|
48
|
+
return db || 'myapp';
|
|
49
|
+
} catch {
|
|
50
|
+
return 'myapp';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
constructor(config: LenzConfig = {}) {
|
|
55
|
+
this.config = {
|
|
56
|
+
...config,
|
|
57
|
+
url: config.url || process.env.MONGODB_URI || 'mongodb://localhost:27017/myapp',
|
|
58
|
+
log: config.log || []
|
|
59
|
+
};
|
|
60
|
+
this.database = config.database || this.extractDatabaseFromUrl(this.config.url);
|
|
61
|
+
this.logger = new Logger(this.config.log);
|
|
62
|
+
|
|
63
|
+
// Initialize model delegates
|
|
64
|
+
${models.map(model => ` this.${toCamelCase(model.name)} = new ${model.name}Delegate(this)`).join('\n')}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Extensions storage ($extends support)
|
|
68
|
+
private extensions: Array<{
|
|
69
|
+
query?: Record<string, Record<string, (params: { args: any; query: (args: any) => Promise<any> }) => Promise<any>>>
|
|
70
|
+
result?: Record<string, Record<string, { needs?: Record<string, boolean>; compute: (parent: any) => any }>>
|
|
71
|
+
client?: Record<string, (...args: any[]) => any>
|
|
72
|
+
}> = []
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Prisma-compatible $extends — add query interception, computed fields, and client methods
|
|
76
|
+
* @example
|
|
77
|
+
* const xprisma = lenz.$extends({
|
|
78
|
+
* query: {
|
|
79
|
+
* user: {
|
|
80
|
+
* findMany: async ({ args, query }) => {
|
|
81
|
+
* args.where = { ...args.where, deleted: false }
|
|
82
|
+
* return query(args)
|
|
83
|
+
* }
|
|
84
|
+
* }
|
|
85
|
+
* },
|
|
86
|
+
* result: {
|
|
87
|
+
* user: {
|
|
88
|
+
* fullName: {
|
|
89
|
+
* needs: { firstName: true, lastName: true },
|
|
90
|
+
* compute: (user) => \`\${user.firstName} \${user.lastName}\`
|
|
91
|
+
* }
|
|
92
|
+
* }
|
|
93
|
+
* },
|
|
94
|
+
* client: {
|
|
95
|
+
* ping: async () => lenz.$mongo.client.db().admin().ping()
|
|
96
|
+
* }
|
|
97
|
+
* })
|
|
98
|
+
*/
|
|
99
|
+
$extends(extension: any): this {
|
|
100
|
+
this.extensions.push(extension)
|
|
101
|
+
|
|
102
|
+
if (extension.client) {
|
|
103
|
+
for (const [key, fn] of Object.entries(extension.client)) {
|
|
104
|
+
;(this as any)[key] = fn
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return this
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getQueryExtension(modelName: string, method: string): ((params: { args: any; query: (args: any) => Promise<any> }) => Promise<any>) | null {
|
|
112
|
+
for (const ext of this.extensions) {
|
|
113
|
+
if (ext.query?.[modelName]?.[method]) {
|
|
114
|
+
return ext.query[modelName][method]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getResultExtensions(modelName: string): Array<{ name: string; compute: (parent: any) => any }> | null {
|
|
121
|
+
const exts: Array<{ name: string; compute: (parent: any) => any }> = []
|
|
122
|
+
for (const ext of this.extensions) {
|
|
123
|
+
if (ext.result?.[modelName]) {
|
|
124
|
+
for (const [name, config] of Object.entries(ext.result[modelName])) {
|
|
125
|
+
exts.push({ name, compute: (config as any).compute })
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return exts.length > 0 ? exts : null
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
$on(event: string, callback: any): void {
|
|
133
|
+
this.logger.on(event, callback)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get $logger(): Logger {
|
|
137
|
+
return this.logger
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async $connect(): Promise<void> {
|
|
141
|
+
if (this.mongoClient) return
|
|
142
|
+
|
|
143
|
+
this.mongoClient = new MongoClient(this.config.url, {
|
|
144
|
+
maxPoolSize: this.config.maxPoolSize || 10,
|
|
145
|
+
connectTimeoutMS: this.config.connectTimeoutMS || 10000,
|
|
146
|
+
socketTimeoutMS: this.config.socketTimeoutMS || 45000
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
await this.mongoClient.connect()
|
|
150
|
+
this.db = this.mongoClient.db(this.database)
|
|
151
|
+
|
|
152
|
+
await this.db.command({ ping: 1 })
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const serverInfo = await this.db.admin().serverInfo()
|
|
156
|
+
this.supportsTransactions = serverInfo.repl?.replSetName !== undefined
|
|
157
|
+
|
|
158
|
+
if (!this.supportsTransactions) {
|
|
159
|
+
console.warn('⚠️ MongoDB is running in standalone mode. Transactions will not work.')
|
|
160
|
+
console.warn(' Consider setting up a replica set for transaction support.')
|
|
161
|
+
console.warn(' Example: mongod --replSet rs0 --port 27017')
|
|
162
|
+
}
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.warn('⚠️ Could not determine MongoDB deployment type:', error.message)
|
|
165
|
+
this.supportsTransactions = false
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
await this.initializeCollections()
|
|
169
|
+
|
|
170
|
+
if (this.config.log?.includes('info')) {
|
|
171
|
+
console.log('✅ Connected to MongoDB')
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async $disconnect(): Promise<void> {
|
|
176
|
+
if (this.mongoClient) {
|
|
177
|
+
await this.mongoClient.close()
|
|
178
|
+
this.mongoClient = null
|
|
179
|
+
this.db = null
|
|
180
|
+
|
|
181
|
+
if (this.config.log?.includes('info')) {
|
|
182
|
+
console.log('👋 Disconnected from MongoDB')
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async $transaction<T>(
|
|
188
|
+
args: Array<(tx: any) => Promise<any>> | ((tx: any) => Promise<T>),
|
|
189
|
+
options?: { maxRetry?: number; timeout?: number }
|
|
190
|
+
): Promise<any> {
|
|
191
|
+
if (!this.mongoClient) {
|
|
192
|
+
throw new Error('Not connected to database')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!this.supportsTransactions) {
|
|
196
|
+
throw new Error(
|
|
197
|
+
'Transactions are not supported in standalone MongoDB. ' +
|
|
198
|
+
'Set up a replica set or use alternative consistency patterns. ' +
|
|
199
|
+
'During development: mongod --replSet rs0 --port 27017'
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const maxRetry = options?.maxRetry ?? 3;
|
|
204
|
+
|
|
205
|
+
const isTransientError = (error: any): boolean => {
|
|
206
|
+
return error?.code === 112 ||
|
|
207
|
+
error?.code === 245 ||
|
|
208
|
+
error?.code === 246 ||
|
|
209
|
+
error?.errorLabels?.includes('TransientTransactionError') ||
|
|
210
|
+
error?.errorLabels?.includes('UnknownTransactionCommitResult')
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (Array.isArray(args)) {
|
|
214
|
+
const session = this.mongoClient.startSession()
|
|
215
|
+
try {
|
|
216
|
+
session.startTransaction()
|
|
217
|
+
const fns = args as Array<(tx: any) => Promise<any>>;
|
|
218
|
+
const results: any[] = [];
|
|
219
|
+
for (const fn of fns) {
|
|
220
|
+
results.push(await fn(session));
|
|
221
|
+
}
|
|
222
|
+
await session.commitTransaction()
|
|
223
|
+
return results
|
|
224
|
+
} catch (error) {
|
|
225
|
+
await session.abortTransaction().catch(() => {})
|
|
226
|
+
throw error
|
|
227
|
+
} finally {
|
|
228
|
+
session.endSession()
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let lastError: any;
|
|
233
|
+
for (let attempt = 0; attempt <= maxRetry; attempt++) {
|
|
234
|
+
const session = this.mongoClient.startSession()
|
|
235
|
+
try {
|
|
236
|
+
session.startTransaction()
|
|
237
|
+
|
|
238
|
+
const result = await (args as (tx: any) => Promise<T>)(session)
|
|
239
|
+
|
|
240
|
+
let committed = false;
|
|
241
|
+
for (let commitAttempt = 0; commitAttempt < 3; commitAttempt++) {
|
|
242
|
+
try {
|
|
243
|
+
await session.commitTransaction()
|
|
244
|
+
committed = true;
|
|
245
|
+
break;
|
|
246
|
+
} catch (commitError: any) {
|
|
247
|
+
if (commitAttempt < 2 && isTransientError(commitError)) {
|
|
248
|
+
await new Promise(r => setTimeout(r, Math.min(100 * Math.pow(2, commitAttempt), 1000)))
|
|
249
|
+
continue
|
|
250
|
+
}
|
|
251
|
+
throw commitError
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (!committed) {
|
|
256
|
+
throw new Error('Failed to commit transaction after retries')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return result
|
|
260
|
+
} catch (error: any) {
|
|
261
|
+
await session.abortTransaction().catch(() => {})
|
|
262
|
+
|
|
263
|
+
if (attempt < maxRetry && isTransientError(error)) {
|
|
264
|
+
const delay = Math.min(100 * Math.pow(2, attempt), 2000)
|
|
265
|
+
await new Promise(r => setTimeout(r, delay))
|
|
266
|
+
lastError = error
|
|
267
|
+
continue
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
throw error
|
|
271
|
+
} finally {
|
|
272
|
+
session.endSession()
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
throw lastError || new Error('Transaction failed')
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
$supportsTransactions(): boolean {
|
|
280
|
+
return this.supportsTransactions
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private async initializeCollections(): Promise<void> {
|
|
284
|
+
if (!this.db) return
|
|
285
|
+
|
|
286
|
+
const models = ${JSON.stringify(this.getModelsForRuntime(models), null, 2)}
|
|
287
|
+
|
|
288
|
+
for (const model of models) {
|
|
289
|
+
if (!model.collectionName) continue
|
|
290
|
+
|
|
291
|
+
const collections = await this.db.listCollections({ name: model.collectionName }).toArray()
|
|
292
|
+
|
|
293
|
+
if (collections.length === 0) {
|
|
294
|
+
await this.db.createCollection(model.collectionName)
|
|
295
|
+
|
|
296
|
+
if (model.indexes.length > 0) {
|
|
297
|
+
const indexes = model.indexes.map(index => {
|
|
298
|
+
const spec: any = {
|
|
299
|
+
key: index.fields.reduce((acc, field) => {
|
|
300
|
+
const dbField = model.fieldDbNames?.[field] || field
|
|
301
|
+
acc[dbField] = 1
|
|
302
|
+
return acc
|
|
303
|
+
}, {}),
|
|
304
|
+
unique: index.unique,
|
|
305
|
+
sparse: index.sparse || false
|
|
306
|
+
};
|
|
307
|
+
if (index.name) spec.name = index.name;
|
|
308
|
+
return spec;
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
await this.db.collection(model.collectionName).createIndexes(indexes)
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.warn(\`Failed to create indexes for \${model.name}:\`, error)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Create full-text search index (if configured)
|
|
319
|
+
if (model.fulltextFields && model.fulltextFields.length > 0) {
|
|
320
|
+
try {
|
|
321
|
+
const textIndex: any = {};
|
|
322
|
+
for (const field of model.fulltextFields) {
|
|
323
|
+
const dbField = model.fieldDbNames?.[field] || field
|
|
324
|
+
textIndex[dbField] = 'text'
|
|
325
|
+
}
|
|
326
|
+
await this.db.collection(model.collectionName).createIndex(textIndex, { name: \`\${model.collectionName}_text\` })
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.warn(\`Failed to create text index for \${model.name}:\`, error)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
$isConnected(): boolean {
|
|
336
|
+
return this.mongoClient !== null
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
get $db(): Db {
|
|
340
|
+
if (!this.db) {
|
|
341
|
+
throw new Error('Database not connected. Call $connect() first.')
|
|
342
|
+
}
|
|
343
|
+
return this.db
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
get $mongo(): { client: MongoClient; ObjectId: any } {
|
|
347
|
+
if (!this.mongoClient) {
|
|
348
|
+
throw new Error('Database not connected. Call $connect() first.')
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
client: this.mongoClient,
|
|
352
|
+
ObjectId: ObjectId
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
get $raw(): { collection: (name: string) => Collection<Document> } {
|
|
357
|
+
if (!this.db) {
|
|
358
|
+
throw new Error('Database not connected. Call $connect() first.')
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
collection: (name: string) => this.db!.collection(name)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
`;
|
|
366
|
+
}
|
|
367
|
+
getModelsForRuntime(models) {
|
|
368
|
+
return models.map(model => ({
|
|
369
|
+
name: model.name,
|
|
370
|
+
collectionName: model.collectionName,
|
|
371
|
+
fieldDbNames: Object.fromEntries(model.fields.filter(f => f.dbName).map(f => [f.name, f.dbName])),
|
|
372
|
+
indexes: model.indexes.map(index => {
|
|
373
|
+
const idx = {
|
|
374
|
+
fields: index.fields,
|
|
375
|
+
unique: index.unique,
|
|
376
|
+
sparse: index.sparse ?? false
|
|
377
|
+
};
|
|
378
|
+
if (index.name)
|
|
379
|
+
idx.name = index.name;
|
|
380
|
+
return idx;
|
|
381
|
+
}),
|
|
382
|
+
fulltextFields: model.fulltextFields
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=ClientGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientGenerator.js","sourceRoot":"","sources":["../../../src/engine/generators/ClientGenerator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,OAAO,eAAe;IAC1B,aAAa,CAAC,UAAkB;QAC9B,OAAO;;;WAGA,UAAU;;;;WAIV,UAAU;;;;;mBAKF,UAAU;;CAE5B,CAAC;IACA,CAAC;IAED,cAAc,CAAC,UAAkB,EAAE,MAAsB;QACvD,OAAO;;;;;;;;;EAST,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;WACX,KAAK,CAAC,IAAI,6BAA6B,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;eAE5D,UAAU;;;;;;;;;EASvB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;EAsB5F,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA8NpF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+E7E,CAAC;IACA,CAAC;IAED,mBAAmB,CAAC,MAAsB;QACxC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,YAAY,EAAE,MAAM,CAAC,WAAW,CAC9B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAChE;YACD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;gBACjC,MAAM,GAAG,GAAQ;oBACf,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK;iBAC9B,CAAC;gBACF,IAAI,KAAK,CAAC,IAAI;oBAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;gBACtC,OAAO,GAAG,CAAC;YACb,CAAC,CAAC;YACF,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { GraphQLModel } from '../GraphQLParser.js';
|
|
2
|
+
export declare class DelegateGenerator {
|
|
3
|
+
private helpers;
|
|
4
|
+
private relations;
|
|
5
|
+
generateModelsIndex(models: GraphQLModel[]): string;
|
|
6
|
+
generateModelFiles(models: GraphQLModel[]): Record<string, string>;
|
|
7
|
+
generateModelDelegate(model: GraphQLModel, collectionNameMap?: Record<string, string>): string;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=DelegateGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DelegateGenerator.d.ts","sourceRoot":"","sources":["../../../src/engine/generators/DelegateGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKnD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,SAAS,CAA2B;IAE5C,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM;IAInD,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWlE,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,iBAAiB,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM;CAgbnG"}
|