From 1b8db6da78d7b5ea5689b82202553ed27e05e623 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 17 Jul 2026 17:10:51 +0300 Subject: [PATCH 1/3] feat(database): disable eager collection creation for all schemas Set autoCreate and autoIndex to false on every Mongoose schema so collections are only created on first write or explicit index creation. Co-authored-by: Cursor --- .../src/adapters/mongoose-adapter/MongooseSchema.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts index fca460bfd..abd6f7c20 100644 --- a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts +++ b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts @@ -50,12 +50,8 @@ export class MongooseSchema extends SchemaAdapter> { } const mongooseSchema = new Schema(cloneDeep(schema.fields as Indexable), { ...cloneDeep(schema.modelOptions), - ...(isView - ? { - autoCreate: false, - autoIndex: false, - } - : {}), + autoCreate: false, + autoIndex: false, }); this.model = mongoose.model(cloneDeep(schema.name), mongooseSchema); } From 1585783c31f2b19c545ce58ea0b17579bd407d50 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 23 Jul 2026 11:53:58 +0300 Subject: [PATCH 2/3] fix(database): explicitly create mongoose field indexes With autoIndex disabled, field-level unique/index definitions and single-field indexes moved onto fields by SchemaConverter were not being created on fresh databases. Create them explicitly from the compiled Mongoose schema while skipping the default _id index so schemas without other indexes remain lazy. Co-authored-by: Cursor --- .../src/adapters/mongoose-adapter/index.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/modules/database/src/adapters/mongoose-adapter/index.ts b/modules/database/src/adapters/mongoose-adapter/index.ts index 2959be4f7..0f4b7e23c 100644 --- a/modules/database/src/adapters/mongoose-adapter/index.ts +++ b/modules/database/src/adapters/mongoose-adapter/index.ts @@ -289,6 +289,39 @@ export class MongooseAdapter extends DatabaseAdapter { return 'Indexes created!'; } + private async createMongooseFieldIndexes(schemaName: string): Promise { + const model = this.models[schemaName]; + if (!model) throw new GrpcError(status.NOT_FOUND, 'Requested schema not found'); + if (model.isView) return; + + const declaredIndexes = model.model.schema.indexes(); + if (!declaredIndexes.length) return; + + const collection = this.mongoose.model(schemaName).collection; + for (const [keys, rawOptions] of declaredIndexes) { + if (this.isDefaultIdIndex(keys)) continue; + + const options = this.sanitizeMongooseIndexOptions(rawOptions); + await collection.createIndex(keys, options).catch((e: Error) => { + throw new GrpcError(status.INTERNAL, e.message); + }); + } + } + + private isDefaultIdIndex(keys: Record): boolean { + const entries = Object.entries(keys); + return entries.length === 1 && entries[0][0] === '_id' && entries[0][1] === 1; + } + + private sanitizeMongooseIndexOptions( + options?: Record, + ): Record | undefined { + if (!options) return undefined; + const sanitized = { ...options }; + delete sanitized._autoIndex; + return Object.keys(sanitized).length > 0 ? sanitized : undefined; + } + async getIndexes(schemaName: string): Promise { if (!this.models[schemaName]) throw new GrpcError(status.NOT_FOUND, 'Requested schema not found'); @@ -455,6 +488,9 @@ export class MongooseAdapter extends DatabaseAdapter { if (indexes && !isInstanceSync) { await this.createIndexes(schema.name, indexes, schema.ownerModule); } + if (!isInstanceSync) { + await this.createMongooseFieldIndexes(schema.name); + } return this.models[schema.name]; } From bbaa1fe78805731250e31994f4925e71d0c03990 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 23 Jul 2026 12:08:26 +0300 Subject: [PATCH 3/3] fix(database): cast mongoose field index keys for createIndex Align explicit field-index creation with MongoDB IndexSpecification typing so the database module builds on v0.16.x. Co-authored-by: Cursor --- .../src/adapters/mongoose-adapter/index.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/database/src/adapters/mongoose-adapter/index.ts b/modules/database/src/adapters/mongoose-adapter/index.ts index 0f4b7e23c..73bfd5910 100644 --- a/modules/database/src/adapters/mongoose-adapter/index.ts +++ b/modules/database/src/adapters/mongoose-adapter/index.ts @@ -1,4 +1,5 @@ import { ConnectOptions, Mongoose, Types } from 'mongoose'; +import type { IndexSpecification } from 'mongodb'; import { MongooseSchema } from './MongooseSchema.js'; import { schemaConverter } from './SchemaConverter.js'; import { @@ -299,17 +300,21 @@ export class MongooseAdapter extends DatabaseAdapter { const collection = this.mongoose.model(schemaName).collection; for (const [keys, rawOptions] of declaredIndexes) { - if (this.isDefaultIdIndex(keys)) continue; + const indexKeys = keys as IndexSpecification; + if (this.isDefaultIdIndex(indexKeys)) continue; - const options = this.sanitizeMongooseIndexOptions(rawOptions); - await collection.createIndex(keys, options).catch((e: Error) => { + const options = this.sanitizeMongooseIndexOptions( + rawOptions as Record, + ); + await collection.createIndex(indexKeys, options).catch((e: Error) => { throw new GrpcError(status.INTERNAL, e.message); }); } } - private isDefaultIdIndex(keys: Record): boolean { - const entries = Object.entries(keys); + private isDefaultIdIndex(keys: IndexSpecification): boolean { + if (!keys || typeof keys !== 'object' || Array.isArray(keys)) return false; + const entries = Object.entries(keys as Record); return entries.length === 1 && entries[0][0] === '_id' && entries[0][1] === 1; }