@warlock.js/cascade 4.0.31 → 4.0.39
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/cjs/index.js +15 -1
- package/cjs/index.js.map +1 -1
- package/esm/index.js +15 -1
- package/esm/index.js.map +1 -1
- package/package.json +52 -61
- package/cjs/aggregate/DeselectPipeline.d.ts +0 -10
- package/cjs/aggregate/DeselectPipeline.d.ts.map +0 -1
- package/cjs/aggregate/DeselectPipeline.js +0 -17
- package/cjs/aggregate/DeselectPipeline.js.map +0 -1
- package/cjs/aggregate/GeoNearPipeline.d.ts +0 -34
- package/cjs/aggregate/GeoNearPipeline.d.ts.map +0 -1
- package/cjs/aggregate/GeoNearPipeline.js +0 -44
- package/cjs/aggregate/GeoNearPipeline.js.map +0 -1
- package/cjs/aggregate/GroupByPipeline.d.ts +0 -12
- package/cjs/aggregate/GroupByPipeline.d.ts.map +0 -1
- package/cjs/aggregate/GroupByPipeline.js +0 -28
- package/cjs/aggregate/GroupByPipeline.js.map +0 -1
- package/cjs/aggregate/LimitPipeline.d.ts +0 -10
- package/cjs/aggregate/LimitPipeline.d.ts.map +0 -1
- package/cjs/aggregate/LimitPipeline.js +0 -14
- package/cjs/aggregate/LimitPipeline.js.map +0 -1
- package/cjs/aggregate/LookupPipeline.d.ts +0 -19
- package/cjs/aggregate/LookupPipeline.d.ts.map +0 -1
- package/cjs/aggregate/LookupPipeline.js +0 -23
- package/cjs/aggregate/LookupPipeline.js.map +0 -1
- package/cjs/aggregate/OrWherePipeline.d.ts +0 -21
- package/cjs/aggregate/OrWherePipeline.d.ts.map +0 -1
- package/cjs/aggregate/OrWherePipeline.js +0 -63
- package/cjs/aggregate/OrWherePipeline.js.map +0 -1
- package/cjs/aggregate/SelectPipeline.d.ts +0 -10
- package/cjs/aggregate/SelectPipeline.d.ts.map +0 -1
- package/cjs/aggregate/SelectPipeline.js +0 -26
- package/cjs/aggregate/SelectPipeline.js.map +0 -1
- package/cjs/aggregate/SkipPipeline.d.ts +0 -10
- package/cjs/aggregate/SkipPipeline.d.ts.map +0 -1
- package/cjs/aggregate/SkipPipeline.js +0 -14
- package/cjs/aggregate/SkipPipeline.js.map +0 -1
- package/cjs/aggregate/SortByPipeline.d.ts +0 -10
- package/cjs/aggregate/SortByPipeline.d.ts.map +0 -1
- package/cjs/aggregate/SortByPipeline.js +0 -18
- package/cjs/aggregate/SortByPipeline.js.map +0 -1
- package/cjs/aggregate/SortPipeline.d.ts +0 -11
- package/cjs/aggregate/SortPipeline.d.ts.map +0 -1
- package/cjs/aggregate/SortPipeline.js +0 -18
- package/cjs/aggregate/SortPipeline.js.map +0 -1
- package/cjs/aggregate/SortRandomPipeline.d.ts +0 -10
- package/cjs/aggregate/SortRandomPipeline.d.ts.map +0 -1
- package/cjs/aggregate/SortRandomPipeline.js +0 -16
- package/cjs/aggregate/SortRandomPipeline.js.map +0 -1
- package/cjs/aggregate/UnwindPipeline.d.ts +0 -14
- package/cjs/aggregate/UnwindPipeline.d.ts.map +0 -1
- package/cjs/aggregate/UnwindPipeline.js +0 -19
- package/cjs/aggregate/UnwindPipeline.js.map +0 -1
- package/cjs/aggregate/WhereExpression.d.ts +0 -17
- package/cjs/aggregate/WhereExpression.d.ts.map +0 -1
- package/cjs/aggregate/WhereExpression.js +0 -149
- package/cjs/aggregate/WhereExpression.js.map +0 -1
- package/cjs/aggregate/WhereExpressionPipeline.d.ts +0 -10
- package/cjs/aggregate/WhereExpressionPipeline.d.ts.map +0 -1
- package/cjs/aggregate/WhereExpressionPipeline.js +0 -15
- package/cjs/aggregate/WhereExpressionPipeline.js.map +0 -1
- package/cjs/aggregate/WherePipeline.d.ts +0 -13
- package/cjs/aggregate/WherePipeline.d.ts.map +0 -1
- package/cjs/aggregate/WherePipeline.js +0 -12
- package/cjs/aggregate/WherePipeline.js.map +0 -1
- package/cjs/aggregate/aggregate.d.ts +0 -409
- package/cjs/aggregate/aggregate.d.ts.map +0 -1
- package/cjs/aggregate/aggregate.js +0 -911
- package/cjs/aggregate/aggregate.js.map +0 -1
- package/cjs/aggregate/expressions.d.ts +0 -361
- package/cjs/aggregate/expressions.d.ts.map +0 -1
- package/cjs/aggregate/expressions.js +0 -536
- package/cjs/aggregate/expressions.js.map +0 -1
- package/cjs/aggregate/filters/apply-filters.d.ts +0 -3
- package/cjs/aggregate/filters/apply-filters.d.ts.map +0 -1
- package/cjs/aggregate/filters/apply-filters.js +0 -75
- package/cjs/aggregate/filters/apply-filters.js.map +0 -1
- package/cjs/aggregate/filters/boolean-filters.d.ts +0 -3
- package/cjs/aggregate/filters/boolean-filters.d.ts.map +0 -1
- package/cjs/aggregate/filters/boolean-filters.js +0 -33
- package/cjs/aggregate/filters/boolean-filters.js.map +0 -1
- package/cjs/aggregate/filters/date-filters.d.ts +0 -3
- package/cjs/aggregate/filters/date-filters.d.ts.map +0 -1
- package/cjs/aggregate/filters/date-filters.js +0 -128
- package/cjs/aggregate/filters/date-filters.js.map +0 -1
- package/cjs/aggregate/filters/index.d.ts +0 -3
- package/cjs/aggregate/filters/index.d.ts.map +0 -1
- package/cjs/aggregate/filters/numeric-filters.d.ts +0 -3
- package/cjs/aggregate/filters/numeric-filters.d.ts.map +0 -1
- package/cjs/aggregate/filters/numeric-filters.js +0 -99
- package/cjs/aggregate/filters/numeric-filters.js.map +0 -1
- package/cjs/aggregate/filters/types.d.ts +0 -46
- package/cjs/aggregate/filters/types.d.ts.map +0 -1
- package/cjs/aggregate/filters/utils.d.ts +0 -13
- package/cjs/aggregate/filters/utils.d.ts.map +0 -1
- package/cjs/aggregate/filters/utils.js +0 -38
- package/cjs/aggregate/filters/utils.js.map +0 -1
- package/cjs/aggregate/index.d.ts +0 -21
- package/cjs/aggregate/index.d.ts.map +0 -1
- package/cjs/aggregate/parsePipelines.d.ts +0 -5
- package/cjs/aggregate/parsePipelines.d.ts.map +0 -1
- package/cjs/aggregate/parsePipelines.js +0 -6
- package/cjs/aggregate/parsePipelines.js.map +0 -1
- package/cjs/aggregate/pipeline.d.ts +0 -31
- package/cjs/aggregate/pipeline.d.ts.map +0 -1
- package/cjs/aggregate/pipeline.js +0 -42
- package/cjs/aggregate/pipeline.js.map +0 -1
- package/cjs/aggregate/types.d.ts +0 -8
- package/cjs/aggregate/types.d.ts.map +0 -1
- package/cjs/aggregate/types.js +0 -31
- package/cjs/aggregate/types.js.map +0 -1
- package/cjs/blueprint/blueprint-column.d.ts +0 -82
- package/cjs/blueprint/blueprint-column.d.ts.map +0 -1
- package/cjs/blueprint/blueprint.d.ts +0 -162
- package/cjs/blueprint/blueprint.d.ts.map +0 -1
- package/cjs/blueprint/blueprint.js +0 -340
- package/cjs/blueprint/blueprint.js.map +0 -1
- package/cjs/blueprint/index.d.ts +0 -3
- package/cjs/blueprint/index.d.ts.map +0 -1
- package/cjs/blueprint/model-blueprint.d.ts +0 -15
- package/cjs/blueprint/model-blueprint.d.ts.map +0 -1
- package/cjs/blueprint/model-blueprint.js +0 -16
- package/cjs/blueprint/model-blueprint.js.map +0 -1
- package/cjs/casts/arrayOf.d.ts +0 -5
- package/cjs/casts/arrayOf.d.ts.map +0 -1
- package/cjs/casts/arrayOf.js +0 -18
- package/cjs/casts/arrayOf.js.map +0 -1
- package/cjs/casts/cast-email.d.ts +0 -2
- package/cjs/casts/cast-email.d.ts.map +0 -1
- package/cjs/casts/cast-email.js +0 -5
- package/cjs/casts/cast-email.js.map +0 -1
- package/cjs/casts/castModel.d.ts +0 -3
- package/cjs/casts/castModel.d.ts.map +0 -1
- package/cjs/casts/castModel.js +0 -49
- package/cjs/casts/castModel.js.map +0 -1
- package/cjs/casts/expiresAfter.d.ts +0 -3
- package/cjs/casts/expiresAfter.d.ts.map +0 -1
- package/cjs/casts/expiresAfter.js +0 -5
- package/cjs/casts/expiresAfter.js.map +0 -1
- package/cjs/casts/index.d.ts +0 -9
- package/cjs/casts/index.d.ts.map +0 -1
- package/cjs/casts/oneOf.d.ts +0 -3
- package/cjs/casts/oneOf.d.ts.map +0 -1
- package/cjs/casts/oneOf.js +0 -22
- package/cjs/casts/oneOf.js.map +0 -1
- package/cjs/casts/random-string.d.ts +0 -2
- package/cjs/casts/random-string.d.ts.map +0 -1
- package/cjs/casts/random-string.js +0 -5
- package/cjs/casts/random-string.js.map +0 -1
- package/cjs/casts/randomInteger.d.ts +0 -2
- package/cjs/casts/randomInteger.d.ts.map +0 -1
- package/cjs/casts/randomInteger.js +0 -7
- package/cjs/casts/randomInteger.js.map +0 -1
- package/cjs/casts/shapedArray.d.ts +0 -26
- package/cjs/casts/shapedArray.d.ts.map +0 -1
- package/cjs/casts/shapedArray.js +0 -100
- package/cjs/casts/shapedArray.js.map +0 -1
- package/cjs/config.d.ts +0 -6
- package/cjs/config.d.ts.map +0 -1
- package/cjs/config.js +0 -16
- package/cjs/config.js.map +0 -1
- package/cjs/connection.d.ts +0 -49
- package/cjs/connection.d.ts.map +0 -1
- package/cjs/connection.js +0 -108
- package/cjs/connection.js.map +0 -1
- package/cjs/database.d.ts +0 -97
- package/cjs/database.d.ts.map +0 -1
- package/cjs/database.js +0 -164
- package/cjs/database.js.map +0 -1
- package/cjs/index.d.ts +0 -13
- package/cjs/index.d.ts.map +0 -1
- package/cjs/migration/index.d.ts +0 -4
- package/cjs/migration/index.d.ts.map +0 -1
- package/cjs/migration/migrate.d.ts +0 -13
- package/cjs/migration/migrate.d.ts.map +0 -1
- package/cjs/migration/migrate.js +0 -72
- package/cjs/migration/migrate.js.map +0 -1
- package/cjs/migration/migration-office.d.ts +0 -21
- package/cjs/migration/migration-office.d.ts.map +0 -1
- package/cjs/migration/migration-office.js +0 -39
- package/cjs/migration/migration-office.js.map +0 -1
- package/cjs/migration/migration-officer.d.ts +0 -33
- package/cjs/migration/migration-officer.d.ts.map +0 -1
- package/cjs/migration/migration-officer.js +0 -55
- package/cjs/migration/migration-officer.js.map +0 -1
- package/cjs/migration/types.d.ts +0 -34
- package/cjs/migration/types.d.ts.map +0 -1
- package/cjs/model/ModelAggregate.d.ts +0 -114
- package/cjs/model/ModelAggregate.d.ts.map +0 -1
- package/cjs/model/ModelAggregate.js +0 -182
- package/cjs/model/ModelAggregate.js.map +0 -1
- package/cjs/model/ModelSync.d.ts +0 -73
- package/cjs/model/ModelSync.d.ts.map +0 -1
- package/cjs/model/ModelSync.js +0 -215
- package/cjs/model/ModelSync.js.map +0 -1
- package/cjs/model/RelationshipWithMany.d.ts +0 -24
- package/cjs/model/RelationshipWithMany.d.ts.map +0 -1
- package/cjs/model/RelationshipWithMany.js +0 -42
- package/cjs/model/RelationshipWithMany.js.map +0 -1
- package/cjs/model/base-model.d.ts +0 -161
- package/cjs/model/base-model.d.ts.map +0 -1
- package/cjs/model/base-model.js +0 -265
- package/cjs/model/base-model.js.map +0 -1
- package/cjs/model/crud-model.d.ts +0 -122
- package/cjs/model/crud-model.d.ts.map +0 -1
- package/cjs/model/crud-model.js +0 -366
- package/cjs/model/crud-model.js.map +0 -1
- package/cjs/model/index.d.ts +0 -10
- package/cjs/model/index.d.ts.map +0 -1
- package/cjs/model/joinable.d.ts +0 -87
- package/cjs/model/joinable.d.ts.map +0 -1
- package/cjs/model/joinable.js +0 -158
- package/cjs/model/joinable.js.map +0 -1
- package/cjs/model/master-mind.d.ts +0 -44
- package/cjs/model/master-mind.d.ts.map +0 -1
- package/cjs/model/master-mind.js +0 -118
- package/cjs/model/master-mind.js.map +0 -1
- package/cjs/model/model-events.d.ts +0 -57
- package/cjs/model/model-events.d.ts.map +0 -1
- package/cjs/model/model-events.js +0 -102
- package/cjs/model/model-events.js.map +0 -1
- package/cjs/model/model.d.ts +0 -464
- package/cjs/model/model.d.ts.map +0 -1
- package/cjs/model/model.js +0 -1134
- package/cjs/model/model.js.map +0 -1
- package/cjs/model/types.d.ts +0 -149
- package/cjs/model/types.d.ts.map +0 -1
- package/cjs/model/types.js +0 -11
- package/cjs/model/types.js.map +0 -1
- package/cjs/query/index.d.ts +0 -2
- package/cjs/query/index.d.ts.map +0 -1
- package/cjs/query/query.d.ts +0 -218
- package/cjs/query/query.d.ts.map +0 -1
- package/cjs/query/query.js +0 -672
- package/cjs/query/query.js.map +0 -1
- package/cjs/query/types.d.ts +0 -60
- package/cjs/query/types.d.ts.map +0 -1
- package/cjs/types.d.ts +0 -75
- package/cjs/types.d.ts.map +0 -1
- package/cjs/utils/connectToDatabase.d.ts +0 -3
- package/cjs/utils/connectToDatabase.d.ts.map +0 -1
- package/cjs/utils/connectToDatabase.js +0 -3
- package/cjs/utils/connectToDatabase.js.map +0 -1
- package/cjs/utils/deep-diff.d.ts +0 -9
- package/cjs/utils/deep-diff.d.ts.map +0 -1
- package/cjs/utils/deep-diff.js +0 -44
- package/cjs/utils/deep-diff.js.map +0 -1
- package/cjs/utils/dropAllDatabaseIndexes.d.ts +0 -2
- package/cjs/utils/dropAllDatabaseIndexes.d.ts.map +0 -1
- package/cjs/utils/dropAllDatabaseIndexes.js +0 -10
- package/cjs/utils/dropAllDatabaseIndexes.js.map +0 -1
- package/cjs/utils/index.d.ts +0 -6
- package/cjs/utils/index.d.ts.map +0 -1
- package/cjs/utils/joinable-proxy.d.ts +0 -3
- package/cjs/utils/joinable-proxy.d.ts.map +0 -1
- package/cjs/utils/joinable-proxy.js +0 -14
- package/cjs/utils/joinable-proxy.js.map +0 -1
- package/cjs/utils/listDatabaseIndexes.d.ts +0 -4
- package/cjs/utils/listDatabaseIndexes.d.ts.map +0 -1
- package/cjs/utils/listDatabaseIndexes.js +0 -101
- package/cjs/utils/listDatabaseIndexes.js.map +0 -1
- package/cjs/utils/onceConnected.d.ts +0 -2
- package/cjs/utils/onceConnected.d.ts.map +0 -1
- package/cjs/utils/onceConnected.js +0 -8
- package/cjs/utils/onceConnected.js.map +0 -1
- package/cjs/utils/sync-with.d.ts +0 -27
- package/cjs/utils/sync-with.d.ts.map +0 -1
- package/cjs/utils/sync-with.js +0 -60
- package/cjs/utils/sync-with.js.map +0 -1
- package/esm/aggregate/DeselectPipeline.d.ts +0 -10
- package/esm/aggregate/DeselectPipeline.d.ts.map +0 -1
- package/esm/aggregate/DeselectPipeline.js +0 -17
- package/esm/aggregate/DeselectPipeline.js.map +0 -1
- package/esm/aggregate/GeoNearPipeline.d.ts +0 -34
- package/esm/aggregate/GeoNearPipeline.d.ts.map +0 -1
- package/esm/aggregate/GeoNearPipeline.js +0 -44
- package/esm/aggregate/GeoNearPipeline.js.map +0 -1
- package/esm/aggregate/GroupByPipeline.d.ts +0 -12
- package/esm/aggregate/GroupByPipeline.d.ts.map +0 -1
- package/esm/aggregate/GroupByPipeline.js +0 -28
- package/esm/aggregate/GroupByPipeline.js.map +0 -1
- package/esm/aggregate/LimitPipeline.d.ts +0 -10
- package/esm/aggregate/LimitPipeline.d.ts.map +0 -1
- package/esm/aggregate/LimitPipeline.js +0 -14
- package/esm/aggregate/LimitPipeline.js.map +0 -1
- package/esm/aggregate/LookupPipeline.d.ts +0 -19
- package/esm/aggregate/LookupPipeline.d.ts.map +0 -1
- package/esm/aggregate/LookupPipeline.js +0 -23
- package/esm/aggregate/LookupPipeline.js.map +0 -1
- package/esm/aggregate/OrWherePipeline.d.ts +0 -21
- package/esm/aggregate/OrWherePipeline.d.ts.map +0 -1
- package/esm/aggregate/OrWherePipeline.js +0 -63
- package/esm/aggregate/OrWherePipeline.js.map +0 -1
- package/esm/aggregate/SelectPipeline.d.ts +0 -10
- package/esm/aggregate/SelectPipeline.d.ts.map +0 -1
- package/esm/aggregate/SelectPipeline.js +0 -26
- package/esm/aggregate/SelectPipeline.js.map +0 -1
- package/esm/aggregate/SkipPipeline.d.ts +0 -10
- package/esm/aggregate/SkipPipeline.d.ts.map +0 -1
- package/esm/aggregate/SkipPipeline.js +0 -14
- package/esm/aggregate/SkipPipeline.js.map +0 -1
- package/esm/aggregate/SortByPipeline.d.ts +0 -10
- package/esm/aggregate/SortByPipeline.d.ts.map +0 -1
- package/esm/aggregate/SortByPipeline.js +0 -18
- package/esm/aggregate/SortByPipeline.js.map +0 -1
- package/esm/aggregate/SortPipeline.d.ts +0 -11
- package/esm/aggregate/SortPipeline.d.ts.map +0 -1
- package/esm/aggregate/SortPipeline.js +0 -18
- package/esm/aggregate/SortPipeline.js.map +0 -1
- package/esm/aggregate/SortRandomPipeline.d.ts +0 -10
- package/esm/aggregate/SortRandomPipeline.d.ts.map +0 -1
- package/esm/aggregate/SortRandomPipeline.js +0 -16
- package/esm/aggregate/SortRandomPipeline.js.map +0 -1
- package/esm/aggregate/UnwindPipeline.d.ts +0 -14
- package/esm/aggregate/UnwindPipeline.d.ts.map +0 -1
- package/esm/aggregate/UnwindPipeline.js +0 -19
- package/esm/aggregate/UnwindPipeline.js.map +0 -1
- package/esm/aggregate/WhereExpression.d.ts +0 -17
- package/esm/aggregate/WhereExpression.d.ts.map +0 -1
- package/esm/aggregate/WhereExpression.js +0 -149
- package/esm/aggregate/WhereExpression.js.map +0 -1
- package/esm/aggregate/WhereExpressionPipeline.d.ts +0 -10
- package/esm/aggregate/WhereExpressionPipeline.d.ts.map +0 -1
- package/esm/aggregate/WhereExpressionPipeline.js +0 -15
- package/esm/aggregate/WhereExpressionPipeline.js.map +0 -1
- package/esm/aggregate/WherePipeline.d.ts +0 -13
- package/esm/aggregate/WherePipeline.d.ts.map +0 -1
- package/esm/aggregate/WherePipeline.js +0 -12
- package/esm/aggregate/WherePipeline.js.map +0 -1
- package/esm/aggregate/aggregate.d.ts +0 -409
- package/esm/aggregate/aggregate.d.ts.map +0 -1
- package/esm/aggregate/aggregate.js +0 -911
- package/esm/aggregate/aggregate.js.map +0 -1
- package/esm/aggregate/expressions.d.ts +0 -361
- package/esm/aggregate/expressions.d.ts.map +0 -1
- package/esm/aggregate/expressions.js +0 -536
- package/esm/aggregate/expressions.js.map +0 -1
- package/esm/aggregate/filters/apply-filters.d.ts +0 -3
- package/esm/aggregate/filters/apply-filters.d.ts.map +0 -1
- package/esm/aggregate/filters/apply-filters.js +0 -75
- package/esm/aggregate/filters/apply-filters.js.map +0 -1
- package/esm/aggregate/filters/boolean-filters.d.ts +0 -3
- package/esm/aggregate/filters/boolean-filters.d.ts.map +0 -1
- package/esm/aggregate/filters/boolean-filters.js +0 -33
- package/esm/aggregate/filters/boolean-filters.js.map +0 -1
- package/esm/aggregate/filters/date-filters.d.ts +0 -3
- package/esm/aggregate/filters/date-filters.d.ts.map +0 -1
- package/esm/aggregate/filters/date-filters.js +0 -128
- package/esm/aggregate/filters/date-filters.js.map +0 -1
- package/esm/aggregate/filters/index.d.ts +0 -3
- package/esm/aggregate/filters/index.d.ts.map +0 -1
- package/esm/aggregate/filters/numeric-filters.d.ts +0 -3
- package/esm/aggregate/filters/numeric-filters.d.ts.map +0 -1
- package/esm/aggregate/filters/numeric-filters.js +0 -99
- package/esm/aggregate/filters/numeric-filters.js.map +0 -1
- package/esm/aggregate/filters/types.d.ts +0 -46
- package/esm/aggregate/filters/types.d.ts.map +0 -1
- package/esm/aggregate/filters/utils.d.ts +0 -13
- package/esm/aggregate/filters/utils.d.ts.map +0 -1
- package/esm/aggregate/filters/utils.js +0 -38
- package/esm/aggregate/filters/utils.js.map +0 -1
- package/esm/aggregate/index.d.ts +0 -21
- package/esm/aggregate/index.d.ts.map +0 -1
- package/esm/aggregate/parsePipelines.d.ts +0 -5
- package/esm/aggregate/parsePipelines.d.ts.map +0 -1
- package/esm/aggregate/parsePipelines.js +0 -6
- package/esm/aggregate/parsePipelines.js.map +0 -1
- package/esm/aggregate/pipeline.d.ts +0 -31
- package/esm/aggregate/pipeline.d.ts.map +0 -1
- package/esm/aggregate/pipeline.js +0 -42
- package/esm/aggregate/pipeline.js.map +0 -1
- package/esm/aggregate/types.d.ts +0 -8
- package/esm/aggregate/types.d.ts.map +0 -1
- package/esm/aggregate/types.js +0 -31
- package/esm/aggregate/types.js.map +0 -1
- package/esm/blueprint/blueprint-column.d.ts +0 -82
- package/esm/blueprint/blueprint-column.d.ts.map +0 -1
- package/esm/blueprint/blueprint.d.ts +0 -162
- package/esm/blueprint/blueprint.d.ts.map +0 -1
- package/esm/blueprint/blueprint.js +0 -340
- package/esm/blueprint/blueprint.js.map +0 -1
- package/esm/blueprint/index.d.ts +0 -3
- package/esm/blueprint/index.d.ts.map +0 -1
- package/esm/blueprint/model-blueprint.d.ts +0 -15
- package/esm/blueprint/model-blueprint.d.ts.map +0 -1
- package/esm/blueprint/model-blueprint.js +0 -16
- package/esm/blueprint/model-blueprint.js.map +0 -1
- package/esm/casts/arrayOf.d.ts +0 -5
- package/esm/casts/arrayOf.d.ts.map +0 -1
- package/esm/casts/arrayOf.js +0 -18
- package/esm/casts/arrayOf.js.map +0 -1
- package/esm/casts/cast-email.d.ts +0 -2
- package/esm/casts/cast-email.d.ts.map +0 -1
- package/esm/casts/cast-email.js +0 -5
- package/esm/casts/cast-email.js.map +0 -1
- package/esm/casts/castModel.d.ts +0 -3
- package/esm/casts/castModel.d.ts.map +0 -1
- package/esm/casts/castModel.js +0 -49
- package/esm/casts/castModel.js.map +0 -1
- package/esm/casts/expiresAfter.d.ts +0 -3
- package/esm/casts/expiresAfter.d.ts.map +0 -1
- package/esm/casts/expiresAfter.js +0 -5
- package/esm/casts/expiresAfter.js.map +0 -1
- package/esm/casts/index.d.ts +0 -9
- package/esm/casts/index.d.ts.map +0 -1
- package/esm/casts/oneOf.d.ts +0 -3
- package/esm/casts/oneOf.d.ts.map +0 -1
- package/esm/casts/oneOf.js +0 -22
- package/esm/casts/oneOf.js.map +0 -1
- package/esm/casts/random-string.d.ts +0 -2
- package/esm/casts/random-string.d.ts.map +0 -1
- package/esm/casts/random-string.js +0 -5
- package/esm/casts/random-string.js.map +0 -1
- package/esm/casts/randomInteger.d.ts +0 -2
- package/esm/casts/randomInteger.d.ts.map +0 -1
- package/esm/casts/randomInteger.js +0 -7
- package/esm/casts/randomInteger.js.map +0 -1
- package/esm/casts/shapedArray.d.ts +0 -26
- package/esm/casts/shapedArray.d.ts.map +0 -1
- package/esm/casts/shapedArray.js +0 -100
- package/esm/casts/shapedArray.js.map +0 -1
- package/esm/config.d.ts +0 -6
- package/esm/config.d.ts.map +0 -1
- package/esm/config.js +0 -16
- package/esm/config.js.map +0 -1
- package/esm/connection.d.ts +0 -49
- package/esm/connection.d.ts.map +0 -1
- package/esm/connection.js +0 -108
- package/esm/connection.js.map +0 -1
- package/esm/database.d.ts +0 -97
- package/esm/database.d.ts.map +0 -1
- package/esm/database.js +0 -164
- package/esm/database.js.map +0 -1
- package/esm/index.d.ts +0 -13
- package/esm/index.d.ts.map +0 -1
- package/esm/migration/index.d.ts +0 -4
- package/esm/migration/index.d.ts.map +0 -1
- package/esm/migration/migrate.d.ts +0 -13
- package/esm/migration/migrate.d.ts.map +0 -1
- package/esm/migration/migrate.js +0 -72
- package/esm/migration/migrate.js.map +0 -1
- package/esm/migration/migration-office.d.ts +0 -21
- package/esm/migration/migration-office.d.ts.map +0 -1
- package/esm/migration/migration-office.js +0 -39
- package/esm/migration/migration-office.js.map +0 -1
- package/esm/migration/migration-officer.d.ts +0 -33
- package/esm/migration/migration-officer.d.ts.map +0 -1
- package/esm/migration/migration-officer.js +0 -55
- package/esm/migration/migration-officer.js.map +0 -1
- package/esm/migration/types.d.ts +0 -34
- package/esm/migration/types.d.ts.map +0 -1
- package/esm/model/ModelAggregate.d.ts +0 -114
- package/esm/model/ModelAggregate.d.ts.map +0 -1
- package/esm/model/ModelAggregate.js +0 -182
- package/esm/model/ModelAggregate.js.map +0 -1
- package/esm/model/ModelSync.d.ts +0 -73
- package/esm/model/ModelSync.d.ts.map +0 -1
- package/esm/model/ModelSync.js +0 -215
- package/esm/model/ModelSync.js.map +0 -1
- package/esm/model/RelationshipWithMany.d.ts +0 -24
- package/esm/model/RelationshipWithMany.d.ts.map +0 -1
- package/esm/model/RelationshipWithMany.js +0 -42
- package/esm/model/RelationshipWithMany.js.map +0 -1
- package/esm/model/base-model.d.ts +0 -161
- package/esm/model/base-model.d.ts.map +0 -1
- package/esm/model/base-model.js +0 -265
- package/esm/model/base-model.js.map +0 -1
- package/esm/model/crud-model.d.ts +0 -122
- package/esm/model/crud-model.d.ts.map +0 -1
- package/esm/model/crud-model.js +0 -366
- package/esm/model/crud-model.js.map +0 -1
- package/esm/model/index.d.ts +0 -10
- package/esm/model/index.d.ts.map +0 -1
- package/esm/model/joinable.d.ts +0 -87
- package/esm/model/joinable.d.ts.map +0 -1
- package/esm/model/joinable.js +0 -158
- package/esm/model/joinable.js.map +0 -1
- package/esm/model/master-mind.d.ts +0 -44
- package/esm/model/master-mind.d.ts.map +0 -1
- package/esm/model/master-mind.js +0 -118
- package/esm/model/master-mind.js.map +0 -1
- package/esm/model/model-events.d.ts +0 -57
- package/esm/model/model-events.d.ts.map +0 -1
- package/esm/model/model-events.js +0 -102
- package/esm/model/model-events.js.map +0 -1
- package/esm/model/model.d.ts +0 -464
- package/esm/model/model.d.ts.map +0 -1
- package/esm/model/model.js +0 -1134
- package/esm/model/model.js.map +0 -1
- package/esm/model/types.d.ts +0 -149
- package/esm/model/types.d.ts.map +0 -1
- package/esm/model/types.js +0 -11
- package/esm/model/types.js.map +0 -1
- package/esm/query/index.d.ts +0 -2
- package/esm/query/index.d.ts.map +0 -1
- package/esm/query/query.d.ts +0 -218
- package/esm/query/query.d.ts.map +0 -1
- package/esm/query/query.js +0 -672
- package/esm/query/query.js.map +0 -1
- package/esm/query/types.d.ts +0 -60
- package/esm/query/types.d.ts.map +0 -1
- package/esm/types.d.ts +0 -75
- package/esm/types.d.ts.map +0 -1
- package/esm/utils/connectToDatabase.d.ts +0 -3
- package/esm/utils/connectToDatabase.d.ts.map +0 -1
- package/esm/utils/connectToDatabase.js +0 -3
- package/esm/utils/connectToDatabase.js.map +0 -1
- package/esm/utils/deep-diff.d.ts +0 -9
- package/esm/utils/deep-diff.d.ts.map +0 -1
- package/esm/utils/deep-diff.js +0 -44
- package/esm/utils/deep-diff.js.map +0 -1
- package/esm/utils/dropAllDatabaseIndexes.d.ts +0 -2
- package/esm/utils/dropAllDatabaseIndexes.d.ts.map +0 -1
- package/esm/utils/dropAllDatabaseIndexes.js +0 -10
- package/esm/utils/dropAllDatabaseIndexes.js.map +0 -1
- package/esm/utils/index.d.ts +0 -6
- package/esm/utils/index.d.ts.map +0 -1
- package/esm/utils/joinable-proxy.d.ts +0 -3
- package/esm/utils/joinable-proxy.d.ts.map +0 -1
- package/esm/utils/joinable-proxy.js +0 -14
- package/esm/utils/joinable-proxy.js.map +0 -1
- package/esm/utils/listDatabaseIndexes.d.ts +0 -4
- package/esm/utils/listDatabaseIndexes.d.ts.map +0 -1
- package/esm/utils/listDatabaseIndexes.js +0 -101
- package/esm/utils/listDatabaseIndexes.js.map +0 -1
- package/esm/utils/onceConnected.d.ts +0 -2
- package/esm/utils/onceConnected.d.ts.map +0 -1
- package/esm/utils/onceConnected.js +0 -8
- package/esm/utils/onceConnected.js.map +0 -1
- package/esm/utils/sync-with.d.ts +0 -27
- package/esm/utils/sync-with.d.ts.map +0 -1
- package/esm/utils/sync-with.js +0 -60
- package/esm/utils/sync-with.js.map +0 -1
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../warlock.js/cascade/src/context/database-data-source-context.ts","../../../../../../../warlock.js/cascade/src/context/database-transaction-context.ts","../../../../../../../warlock.js/cascade/src/data-source/data-source.ts","../../../../../../../warlock.js/cascade/src/errors/missing-data-source.error.ts","../../../../../../../warlock.js/cascade/src/data-source/data-source-registry.ts","../../../../../../../warlock.js/cascade/src/database-dirty-tracker.ts","../../../../../../../warlock.js/cascade/src/events/model-events.ts","../../../../../../../warlock.js/cascade/src/sync/model-events.ts","../../../../../../../warlock.js/cascade/src/remover/database-remover.ts","../../../../../../../warlock.js/cascade/src/restorer/database-restorer.ts","../../../../../../../warlock.js/cascade/src/sync/sync-context.ts","../../../../../../../warlock.js/cascade/src/sync/sync-manager.ts","../../../../../../../warlock.js/cascade/src/sync/model-sync-operation.ts","../../../../../../../warlock.js/cascade/src/sync/model-sync.ts","../../../../../../../warlock.js/cascade/src/validation/database-writer-validation-error.ts","../../../../../../../warlock.js/cascade/src/model/register-model.ts","../../../../../../../warlock.js/cascade/src/validation/mutators/embed-mutator.ts","../../../../../../../warlock.js/cascade/src/validation/rules/database-model-rule.ts","../../../../../../../warlock.js/cascade/src/validation/transformers/embed-model-transformer.ts","../../../../../../../warlock.js/cascade/src/validation/validators/embed-validator.ts","../../../../../../../warlock.js/cascade/src/validation/plugins/embed-validator-plugin.ts","../../../../../../../warlock.js/cascade/src/validation/database-seal-plugins.ts","../../../../../../../warlock.js/cascade/src/writer/database-writer.ts","../../../../../../../warlock.js/cascade/src/model/model.ts","../../../../../../../warlock.js/cascade/src/expressions/aggregate-expressions.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-id-generator.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-query-operations.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-query-parser.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-query-builder.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-sync-adapter.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongo-migration-driver.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongodb-blueprint.ts","../../../../../../../warlock.js/cascade/src/drivers/mongo/mongodb-driver.ts","../../../../../../../warlock.js/cascade/src/utils/connect-to-database.ts","../../../../../../../warlock.js/cascade/src/utils/database-writer.utils.ts","../../../../../../../warlock.js/cascade/src/utils/define-model.ts","../../../../../../../warlock.js/cascade/src/utils/once-connected.ts","../../../../../../../warlock.js/cascade/src/migration/column-builder.ts","../../../../../../../warlock.js/cascade/src/migration/foreign-key-builder.ts","../../../../../../../warlock.js/cascade/src/migration/migration.ts","../../../../../../../warlock.js/cascade/src/migration/migration-runner.ts"],"names":["DatabaseDataSourceContext","Context","dataSource","databaseDataSourceContext","contextManager","DatabaseTransactionContext","session","databaseTransactionContext","DataSource","options","driver","MissingDataSourceError","_MissingDataSourceError","message","dataSourceName","DataSourceRegistry","EventEmitter","source","isNewDefault","event","listener","name","contextSource","override","dataSourceRegistry","canBeFlatten","object","isPlainObject","flatten","separator","keepNestedOriginalObject","parent","root","key","value","keyChain","DatabaseDirtyTracker","data","column","result","hasCurrent","partial","columns","targets","path","keys","hasInitial","initialValue","currentValue","areEqual","target","segments","container","index","lastSegment","numericIndex","segment","clone","ModelEvents","wrapper","model","context","listeners","query","globalModelEvents","MODEL_EVENT_PREFIX","ModelSyncEventType","getModelUpdatedEvent","modelClass","getModelDeletedEvent","DatabaseRemover","strategy","primaryKeyValue","deletedCount","trashRecord","filter","trashTable","documentData","trashData","updateOperations","events","DatabaseRestorer","id","onIdConflict","skipEvents","recordData","restoredData","finalData","deletedAtColumn","recordsToRestore","restoredCount","conflicts","restoredRecords","trashFilter","error","strategyOption","originalId","isMongoDb","newData","DEFAULT_MAX_SYNC_DEPTH","SyncContextManager","instruction","affectedCount","depth","chain","targetModel","maxDepth","preventCircular","modelName","currentDepth","SyncManager","sourceModel","sourceId","updatedData","changedFields","syncConfigs","instructions","config","payload","validation","embedData","nextLevelInstructions","parentInstruction","parentConfig","parentOptions","targetModelClass","targetSyncConfigs","nextOptions","update","instructionsByDepth","depthInstructions","instructionsByTable","table","tableInstructions","updateResult","errorMessage","syncError","baseMessage","grouped","a","b","field","Model","syncWith","builder","ModelSyncOperation","sourceModelClass","targetField","isMany","method","fields","subscription","primaryKey","ModelSyncFacade","operation","callback","scopedOperations","currentScope","modelSync","DatabaseWriterValidationError","_DatabaseWriterValidationError","errors","modelMatch","lines","colors","errorsByField","err","fieldName","fieldErrors","fieldError","valueStr","fieldPath","modelsRegistry","RegisterModel","registerModelInRegistry","getModelFromRegistry","getAllModelsFromRegistry","cleanupModelsRegistery","removeModelFromRegistery","databaseModelMutator","ModelClass","databaseModelsMutator","item","ids","databaseModelRule","VALID_RULE","invalidRule","databaseModelsRule","databaseModelTransformer","embed","EmbedModelValidator","BaseValidator","rule","arrayRule","embedValidator","v","registerPlugin","DatabaseWriter","isInsert","validationSchema","getSealConfig","dataToInsert","createdAtColumn","updatedAtColumn","document","operations","idGenerator","initialId","incrementIdBy","dirtyColumns","removedColumns","min","max","MISSING_VALUE","modelEventsRegistry","_Model","initialData","TargetModel","defaultValue","get","only","set","amount","incrementedValue","decrementedValue","unset","values","merge","ref","defaults","queryBuilder","allGlobalScopes","models","BuilderClass","args","existing","deserializedData","resource","toJsonColumns","resourceColumns","isAggregateExpression","$agg","MongoIdGenerator","counterCollection","MongoQueryOperations","type","mergeable","stage","MongoQueryParser","pipeline","currentStage","currentBuffer","op","builtStage","stageIndex","fieldNames","processed","i","projection","aggregateFields","output","stageName","stageData","indent","spaces","coloredKey","formattedValue","andFilter","orClauses","pendingSimpleWhere","topLevelOrMode","pushOr","clause","mergeAnd","condition","queueSimpleWhere","enterTopLevelOrMode","flushPendingSimpleWhere","callbackCondition","negated","nested","hasAnd","hasOr","match","subBuilder","matchOps","hasInternalOr","nestedCondition","operator","pattern","notPattern","nestedNot","nestedExists","expression","bindings","first","second","lower","upper","start","end","parsed","date","copy","projectionObj","resolved","aggregate","cases","otherwise","thenValue","elseValue","driverCallbacks","expr","alias","sort","groupId","aggregates","groupStage","acc","normalized","MongoQueryBuilder","_MongoQueryBuilder","scopeNames","_","scopeName","scopeCallback","beforeOps","afterOps","timing","tempBuilder","comparisons","left","right","lowerColumn","upperColumn","filters","range","param","prefix","arg","definitions","definition","spec","fieldOrFields","direction","dir","limit","after","before","extension","_args","cloned","startTime","rawRecords","hydratedRecords","results","ignoreNull","doc","size","chunkIndex","hasMore","chunk","page","skip","total","cursor","sortOrder","nextCursor","prevCursor","hasPrev","firstItem","lastItem","matchStage","aggregationPipeline","MongoSyncAdapter","totalAffected","affected","arrayFilters","transformedUpdate","optimizedFilter","originalFilter","arrayField","identifierField","transformed","transformedFields","transformedField","MongoMigrationDriver","from","to","_table","_column","collection","unsetFields","indexSpec","indexNameOrColumns","indexName","col","indexes","idx","indexKeys","indexOptions","indexType","searchIndexes","expireAfterSeconds","_foreignKey","_name","_columns","schema","transaction","MongoDBBlueprint","database","DEFAULT_TRANSACTION_OPTIONS","ObjectId","MongoDbDriver","driverOptions","uri","MongoClient","ObjectIdMongoDB","client","log","mongoOptions","documents","insertedId","finished","finalize","host","port","baseOptions","connectToDatabase","driverType","isDefault","useModelTransformer","isChanged","isNew","defineModel","DefinedModel","onceConnected","dataSourceOrNameOrCallback","targetDataSource","actualCallback","resolvedDataSource","ds","onceDisconnected","ColumnBuilder","migration","text","ForeignKeyBuilder","action","Migration","_Migration","BoundMigration","seconds","fk","newName","length","precision","scale","dimensions","cols","nameOrColumns","migrate","MigrationRunner","MigrationClass","m","migrations","dryRun","record","pending","nextBatch","successCount","r","batches","toRollback","executed","maxBatch","rollbackResults","runResults","executedMap","instance","success","batch","durationMs","executedNames","batchNumbers","createdAt","migrationRunner"],"mappings":"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","file":"index.js","sourcesContent":["import { Context, contextManager } from \"@warlock.js/context\";\nimport type { DataSource } from \"../data-source/data-source\";\n\ntype DataSourceContextValue = string | DataSource;\n\ntype DataSourceContextStore = {\n dataSource?: DataSourceContextValue;\n};\n\n/**\n * Database DataSource Context\n *\n * Manages the active database connection/data source using AsyncLocalStorage.\n * Extends the base Context class for consistent API.\n */\nclass DatabaseDataSourceContext extends Context<DataSourceContextStore> {\n /**\n * Get the current data source\n */\n public getDataSource(): DataSourceContextValue | undefined {\n return this.get(\"dataSource\");\n }\n\n /**\n * Set the data source in context\n */\n public setDataSource(dataSource: DataSourceContextValue): void {\n this.set(\"dataSource\", dataSource);\n }\n\n /**\n * Build the initial data source store with defaults\n */\n public buildStore(): DataSourceContextStore {\n return { dataSource: undefined };\n }\n}\n\nexport const databaseDataSourceContext = new DatabaseDataSourceContext();\n\ncontextManager.register(\"db.datasource\", databaseDataSourceContext);\n","import { Context, contextManager } from \"@warlock.js/context\";\n\ninterface TransactionContextStore {\n session?: unknown;\n}\n\n/**\n * Database Transaction Context\n *\n * Manages database transaction sessions using AsyncLocalStorage.\n * Extends the base Context class for consistent API.\n */\nclass DatabaseTransactionContext extends Context<TransactionContextStore> {\n /**\n * Get the current transaction session\n */\n public getSession<TSession = unknown>(): TSession | undefined {\n return this.get(\"session\") as TSession | undefined;\n }\n\n /**\n * Set the transaction session in context\n */\n public setSession(session: unknown): void {\n this.set(\"session\", session);\n }\n\n /**\n * Exit the transaction context\n */\n public exit(): void {\n this.clear();\n }\n\n /**\n * Build the initial transaction store with defaults\n */\n public buildStore(): TransactionContextStore {\n return { session: undefined };\n }\n}\n\nexport const databaseTransactionContext = new DatabaseTransactionContext();\n\ncontextManager.register(\"db.transaction\", databaseTransactionContext);\n","import type { DriverContract, IdGeneratorContract } from \"../contracts\";\nimport type { DeleteStrategy } from \"../types\";\nimport type { ModelDefaultConfig } from \"../utils/connect-to-database\";\n\n/**\n * Configuration options used when registering a data source.\n */\nexport type DataSourceOptions = {\n /** Unique name identifying the data source. */\n name: string;\n /** Driver bound to the data source. */\n driver: DriverContract;\n /** Whether this data source should be considered the default one. */\n isDefault?: boolean;\n /**\n * Default delete strategy for models using this data source.\n *\n * - MongoDB: Typically `\"trash\"` (uses RecycleBin collection)\n * - PostgreSQL: Typically `\"permanent\"` or `\"soft\"`\n *\n * Can be overridden by model static property or destroy() options.\n *\n * @default undefined (falls back to \"permanent\")\n */\n defaultDeleteStrategy?: DeleteStrategy;\n\n /**\n * Default trash table/collection name for \"trash\" delete strategy.\n *\n * - MongoDB: Typically `\"RecycleBin\"`\n * - If not set, defaults to `{table}Trash` pattern\n *\n * Can be overridden by Model.trashTable static property.\n *\n * @default undefined (uses {table}Trash pattern)\n */\n defaultTrashTable?: string;\n\n /**\n * Default model configuration for all models using this data source.\n *\n * @default undefined\n */\n modelDefaults?: ModelDefaultConfig;\n};\n\n/**\n * Wrapper that couples a driver with its metadata.\n *\n * A data source represents a database connection with all its associated services.\n * The ID generator (if needed) is provided by the driver itself.\n *\n * @example\n * ```typescript\n * // MongoDB with auto ID generation\n * const mongoDriver = new MongoDbDriver({\n * host: \"localhost\",\n * port: 27017,\n * database: \"myapp\",\n * autoGenerateId: true, // Driver creates its own ID generator\n * });\n *\n * const dataSource = new DataSource({\n * name: \"primary\",\n * driver: mongoDriver,\n * isDefault: true,\n * });\n *\n * // Access ID generator from driver\n * const idGenerator = dataSource.idGenerator;\n * ```\n */\nexport class DataSource {\n /** Unique name identifying this data source. */\n public readonly name: string;\n\n /** Database driver for executing queries. */\n public readonly driver: DriverContract;\n\n /** Whether this is the default data source. */\n public readonly isDefault: boolean;\n\n /** Default delete strategy for models using this data source. */\n public readonly defaultDeleteStrategy?: DeleteStrategy;\n\n /** Default trash table/collection name for \"trash\" delete strategy. */\n public readonly defaultTrashTable?: string;\n\n /** Default model configuration for all models using this data source. */\n public readonly modelDefaults?: ModelDefaultConfig;\n\n /**\n * Create a new data source.\n *\n * @param options - Configuration options\n */\n public constructor(options: DataSourceOptions) {\n this.name = options.name;\n this.driver = options.driver;\n this.isDefault = Boolean(options.isDefault);\n this.defaultDeleteStrategy = options.defaultDeleteStrategy;\n this.defaultTrashTable = options.defaultTrashTable;\n this.modelDefaults = options.modelDefaults;\n }\n\n /**\n * Get the ID generator from the driver (if available).\n *\n * NoSQL drivers like MongoDB can provide their own ID generator.\n * SQL drivers return undefined as they use native AUTO_INCREMENT.\n *\n * @returns The ID generator instance, or undefined\n *\n * @example\n * ```typescript\n * const idGenerator = dataSource.idGenerator;\n * if (idGenerator) {\n * const id = await idGenerator.generateNextId({ table: \"users\" });\n * }\n * ```\n */\n public get idGenerator(): IdGeneratorContract | undefined {\n // Check if driver has a getIdGenerator method (duck typing)\n const driver = this.driver as any;\n if (typeof driver.getIdGenerator === \"function\") {\n return driver.getIdGenerator();\n }\n return undefined;\n }\n}\n","/**\n * Error thrown when a requested data source is not found in the registry.\n *\n * This can occur when:\n * - Attempting to retrieve a non-existent named data source\n * - Trying to get the default data source before any have been registered\n * - Context override references an unregistered data source name\n */\nexport class MissingDataSourceError extends Error {\n /**\n * The name of the data source that was not found (if applicable).\n */\n public readonly dataSourceName?: string;\n\n /**\n * Creates a new MissingDataSourceError.\n *\n * @param message - Descriptive error message\n * @param dataSourceName - Optional data source name that was not found\n */\n public constructor(message: string, dataSourceName?: string) {\n super(message);\n this.name = \"MissingDataSourceError\";\n this.dataSourceName = dataSourceName;\n\n // Maintains proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, MissingDataSourceError);\n }\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport { databaseDataSourceContext } from \"../context/database-data-source-context\";\nimport { MissingDataSourceError } from \"../errors/missing-data-source.error\";\nimport { DataSource, type DataSourceOptions } from \"./data-source\";\n\n/**\n * Event types emitted by the DataSourceRegistry.\n *\n * - `registered`: Emitted when any data source is registered\n * - `default-registered`: Emitted when a default data source is registered\n * - `connected`: Emitted when a data source's driver connects\n * - `disconnected`: Emitted when a data source's driver disconnects\n */\nexport type DataSourceRegistryEvent =\n | \"registered\"\n | \"default-registered\"\n | \"connected\"\n | \"disconnected\";\n\n/**\n * Callback signature for registry events.\n */\nexport type DataSourceRegistryListener = (dataSource: DataSource) => void;\n\n/** Maintains registry of named data sources. */\nclass DataSourceRegistry {\n private readonly sources = new Map<string, DataSource>();\n private defaultSource?: DataSource;\n private readonly events = new EventEmitter();\n\n /**\n * Register a new data source definition.\n *\n * Sets up event forwarding from the driver to the registry, allowing\n * centralized listening for connection state changes.\n *\n * **Emits:**\n * - `registered` - When the data source is registered\n * - `default-registered` - If this becomes the default data source\n * - `connected` - When the driver connects (forwarded from driver)\n * - `disconnected` - When the driver disconnects (forwarded from driver)\n *\n * @param options - Data source configuration\n * @returns The registered data source instance\n */\n public register(options: DataSourceOptions): DataSource {\n const source = new DataSource(options);\n this.sources.set(source.name, source);\n\n const isNewDefault = source.isDefault || !this.defaultSource;\n\n if (isNewDefault) {\n this.defaultSource = source;\n }\n\n // Emit registration events\n this.events.emit(\"registered\", source);\n\n if (isNewDefault) {\n this.events.emit(\"default-registered\", source);\n }\n\n source.driver.on(\"connected\", () => {\n this.events.emit(\"connected\", source);\n });\n\n source.driver.on(\"disconnected\", () => {\n this.events.emit(\"disconnected\", source);\n });\n\n return source;\n }\n\n /**\n * Listen for data source registry events.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n *\n * @example\n * ```typescript\n * // Listen for registration\n * dataSourceRegistry.on(\"registered\", (ds) => {\n * console.log(`Data source \"${ds.name}\" registered`);\n * console.log(`Driver: ${ds.driver.name}`); // e.g., \"mongodb\"\n * });\n *\n * // Listen for default data source\n * dataSourceRegistry.on(\"default-registered\", (ds) => {\n * console.log(`Default data source set to \"${ds.name}\"`);\n * });\n *\n * // Listen for connection events (forwarded from drivers)\n * dataSourceRegistry.on(\"connected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" connected`);\n * });\n *\n * dataSourceRegistry.on(\"disconnected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" disconnected`);\n * });\n * ```\n */\n public on(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.on(event, listener);\n }\n\n /**\n * Listen for a data source registration event once.\n *\n * The listener is automatically removed after being called once.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n */\n public once(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.once(event, listener);\n }\n\n /**\n * Remove a listener for a data source registration event.\n *\n * @param event - The event to stop listening for\n * @param listener - The listener to remove\n */\n public off(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.off(event, listener);\n }\n\n /** Retrieve a data source either by name or the default one. */\n public get(name?: string): DataSource {\n const contextSource = name == null ? databaseDataSourceContext.get() : null;\n\n if (contextSource) {\n if (contextSource instanceof DataSource) {\n return contextSource;\n }\n\n const override = this.sources.get(contextSource);\n\n if (!override) {\n throw new MissingDataSourceError(\n `Data source \"${contextSource}\" is not registered (context override).`,\n contextSource,\n );\n }\n\n return override;\n }\n\n if (name != null) {\n const source = this.sources.get(name);\n if (!source) {\n throw new MissingDataSourceError(`Data source \"${name}\" is not registered.`, name);\n }\n return source;\n }\n\n if (!this.defaultSource) {\n throw new MissingDataSourceError(\"No default data source registered.\");\n }\n\n return this.defaultSource;\n }\n\n /**\n * Get all registered data sources.\n *\n * Useful for operations that need to iterate over all sources,\n * such as shutting down all connections.\n *\n * @returns Array of all registered data sources\n *\n * @example\n * ```typescript\n * // Shutdown all data sources\n * for (const dataSource of dataSourceRegistry.getAllDataSources()) {\n * await dataSource.driver.disconnect();\n * }\n * ```\n */\n public getAllDataSources(): DataSource[] {\n return Array.from(this.sources.values());\n }\n}\n\nexport const dataSourceRegistry = new DataSourceRegistry();\n","import { areEqual, clone } from \"@mongez/reinforcements\";\nimport { isPlainObject } from \"@mongez/supportive-is\";\n\nfunction canBeFlatten(object: unknown): boolean {\n return isPlainObject(object);\n}\n\n/**\n * A fix for flatten as non-plain object is being flatten as well which it should not be\n */\nfunction flatten(\n object: Record<string, unknown>,\n separator = \".\",\n keepNestedOriginalObject = false,\n parent?: string,\n root: Record<string, unknown> = {},\n) {\n if (canBeFlatten(object) === false) {\n return object;\n }\n // object = toPlainObject(object);\n for (const key of Object.keys(object)) {\n const value = object[key];\n const keyChain = parent ? parent + separator + key : key;\n if ((Array.isArray(value) && value.length === 0) || typeof value === \"function\") {\n root[keyChain] = value;\n } else if (canBeFlatten(value)) {\n if (keepNestedOriginalObject) {\n root[keyChain] = value;\n }\n flatten(\n value as Record<string, unknown>,\n separator,\n keepNestedOriginalObject,\n keyChain,\n root,\n );\n } else {\n root[keyChain] = value;\n }\n }\n return root;\n}\n\n/**\n * Flattened record type representing dot-notation paths mapped to their values.\n */\ntype FlatRecord = Record<string, unknown>;\n\n/**\n * Represents the old and new values of a dirty column.\n */\ntype DirtyColumnValues = { oldValue: unknown; newValue: unknown };\n\n/**\n * Tracks changes to model data by maintaining snapshots of initial and current state.\n *\n * The tracker stores both raw (nested) and flattened (dot-notation) versions of the data\n * to accurately detect modifications, additions, and removals at any nesting level.\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\", age: 30 });\n * tracker.mergeChanges({ age: 31 });\n * console.log(tracker.hasChanges()); // true\n * console.log(tracker.getDirtyColumns()); // [\"age\"]\n * console.log(tracker.getDirtyColumnsWithValues());\n * // { age: { oldValue: 30, newValue: 31 } }\n * ```\n */\nexport class DatabaseDirtyTracker {\n /**\n * The initial raw data snapshot taken at construction or last reset.\n * Used as the baseline for comparison.\n */\n private initialRaw: Record<string, unknown>;\n\n /**\n * The current raw data snapshot reflecting all changes made via merge/unset.\n */\n private currentRaw: Record<string, unknown>;\n\n /**\n * Flattened version of the initial data using dot-notation keys.\n * Example: { \"address.city\": \"NYC\" }\n */\n private initialFlattened: FlatRecord;\n\n /**\n * Flattened version of the current data using dot-notation keys.\n */\n private currentFlattened: FlatRecord;\n\n /**\n * Set of column names (dot-notation paths) that have been modified.\n */\n private readonly dirtyColumns = new Set<string>();\n\n /**\n * Set of column names (dot-notation paths) that existed initially but have been removed.\n */\n private readonly removedColumns = new Set<string>();\n\n /**\n * Constructs a new dirty tracker with the provided initial data.\n *\n * @param data - The initial data to track\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\", email: \"alice@example.com\" });\n * ```\n */\n public constructor(data: Record<string, unknown>) {\n this.initialRaw = this.cloneData(data);\n this.currentRaw = this.cloneData(data);\n\n this.initialFlattened = flatten(this.initialRaw);\n this.currentFlattened = { ...this.initialFlattened };\n\n this.updateDirtyState();\n }\n\n /**\n * Returns the list of dirty columns using dot-notation.\n *\n * A column is considered dirty if its value has changed compared to the initial snapshot.\n *\n * @returns An array of column names (dot-notation paths) that have been modified\n *\n * @example\n * ```typescript\n * tracker.mergeChanges({ name: \"Bob\", \"address.city\": \"LA\" });\n * tracker.getDirtyColumns(); // [\"name\", \"address.city\"]\n * ```\n */\n public getDirtyColumns(): string[] {\n return Array.from(this.dirtyColumns);\n }\n\n /**\n * Determines whether there are any tracked changes.\n *\n * Returns `true` if any columns have been modified or removed since the initial snapshot.\n *\n * @returns `true` if there are changes, `false` otherwise\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\" });\n * tracker.hasChanges(); // false\n * tracker.mergeChanges({ name: \"Bob\" });\n * tracker.hasChanges(); // true\n * tracker.unset(\"name\");\n * tracker.hasChanges(); // true (removed column counts as a change)\n * ```\n */\n public hasChanges(): boolean {\n return this.dirtyColumns.size > 0 || this.removedColumns.size > 0;\n }\n\n /**\n * Check if the given column is dirty (changed)\n */\n public isDirty(column: string): boolean {\n return this.dirtyColumns.has(column);\n }\n\n /**\n * Returns the set of columns that have been removed compared to the baseline.\n *\n * A column is considered removed if it existed in the initial snapshot but has been\n * explicitly unset or deleted from the current data.\n *\n * @returns An array of column names (dot-notation paths) that have been removed\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\", temp: \"value\" });\n * tracker.unset(\"temp\");\n * tracker.getRemovedColumns(); // [\"temp\"]\n * ```\n */\n public getRemovedColumns(): string[] {\n return Array.from(this.removedColumns);\n }\n\n /**\n * Provides a mapping of dirty columns to their previous and current values.\n *\n * This is useful for generating audit logs, building partial update payloads,\n * or displaying change summaries to users.\n *\n * @returns A record mapping each dirty column to an object containing oldValue and newValue\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\", age: 30 });\n * tracker.mergeChanges({ age: 31 });\n * tracker.getDirtyColumnsWithValues();\n * // { age: { oldValue: 30, newValue: 31 } }\n * ```\n */\n public getDirtyColumnsWithValues(): Record<string, DirtyColumnValues> {\n const result: Record<string, DirtyColumnValues> = {};\n\n for (const column of this.dirtyColumns) {\n const hasCurrent =\n this.currentFlattened[column] !== undefined || column in this.currentFlattened;\n\n result[column] = {\n oldValue: this.initialFlattened[column],\n newValue: hasCurrent ? this.currentFlattened[column] : undefined,\n };\n }\n\n return result;\n }\n\n /**\n * Replaces the current data snapshot entirely and recomputes the diff.\n *\n * This is useful when you want to replace all current data with a new set,\n * while keeping the initial baseline for comparison.\n *\n * @param data - The new data to set as the current snapshot\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\" });\n * tracker.replaceCurrentData({ name: \"Bob\", email: \"bob@example.com\" });\n * tracker.getDirtyColumns(); // [\"name\", \"email\"]\n * ```\n */\n public replaceCurrentData(data: Record<string, unknown>): void {\n this.currentRaw = this.cloneData(data);\n this.currentFlattened = flatten(this.currentRaw);\n this.updateDirtyState();\n }\n\n /**\n * Merges a partial payload into the current snapshot and recomputes the diff.\n *\n * This performs a deep merge, preserving existing nested structures while\n * updating only the specified fields.\n *\n * @param partial - Partial data to merge into the current snapshot\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\", address: { city: \"NYC\" } });\n * tracker.mergeChanges({ address: { zip: \"10001\" } });\n * // Current data: { name: \"Alice\", address: { city: \"NYC\", zip: \"10001\" } }\n * tracker.getDirtyColumns(); // [\"address.zip\"]\n * ```\n */\n public mergeChanges(partial: Record<string, unknown>): void {\n this.mergeIntoRaw(this.currentRaw, partial);\n this.currentFlattened = flatten(this.currentRaw);\n this.updateDirtyState();\n }\n\n /**\n * Explicitly removes one or more columns from the current data.\n *\n * Supports both single column names and arrays of column names.\n * Columns can be specified using dot-notation for nested paths.\n *\n * @param columns - A single column name or an array of column names to remove\n *\n * @example\n * ```typescript\n * tracker.unset(\"tempField\");\n * tracker.unset([\"field1\", \"field2\", \"nested.field\"]);\n * tracker.getRemovedColumns(); // [\"tempField\", \"field1\", \"field2\", \"nested.field\"]\n * ```\n */\n public unset(columns: string | string[]): void {\n const targets = Array.isArray(columns) ? columns : [columns];\n\n for (const path of targets) {\n this.deleteFromRaw(path);\n }\n\n this.currentFlattened = flatten(this.currentRaw);\n this.updateDirtyState();\n }\n\n /**\n * Resets both the initial and current snapshots to the provided data.\n *\n * If no data is provided, the current snapshot becomes the new baseline.\n * This clears all tracked changes and removed columns.\n *\n * @param data - Optional new data to use as the baseline. If omitted, uses current data.\n *\n * @example\n * ```typescript\n * const tracker = new DatabaseDirtyTracker({ name: \"Alice\" });\n * tracker.mergeChanges({ name: \"Bob\" });\n * tracker.hasChanges(); // true\n * tracker.reset(); // Make current state the new baseline\n * tracker.hasChanges(); // false\n *\n * // Or reset to entirely new data:\n * tracker.reset({ name: \"Charlie\", age: 25 });\n * ```\n */\n public reset(data?: Record<string, unknown>): void {\n const source = data ?? this.currentRaw;\n this.initialRaw = this.cloneData(source);\n this.currentRaw = this.cloneData(source);\n\n this.initialFlattened = flatten(this.initialRaw);\n this.currentFlattened = flatten(this.currentRaw);\n\n this.dirtyColumns.clear();\n this.removedColumns.clear();\n }\n\n /**\n * Recomputes the dirty and removed column sets by comparing initial and current snapshots.\n *\n * This method is called internally after any operation that modifies the current data.\n * It iterates through all keys in both flattened snapshots and determines which columns\n * have been modified or removed.\n *\n * @private\n */\n private updateDirtyState(): void {\n this.dirtyColumns.clear();\n this.removedColumns.clear();\n\n const keys = new Set([\n ...Object.keys(this.initialFlattened),\n ...Object.keys(this.currentFlattened),\n ]);\n\n for (const key of keys) {\n const hasCurrent = this.currentFlattened[key] !== undefined || key in this.currentFlattened;\n const hasInitial = this.initialFlattened[key] !== undefined || key in this.initialFlattened;\n\n if (!hasCurrent && hasInitial) {\n this.removedColumns.add(key);\n }\n\n const initialValue = this.initialFlattened[key];\n const currentValue = hasCurrent ? this.currentFlattened[key] : undefined;\n\n if (!areEqual(initialValue, currentValue)) {\n this.dirtyColumns.add(key);\n }\n }\n }\n\n /**\n * Recursively merges source object into target object, performing a deep merge.\n *\n * For nested objects, the merge is recursive. For arrays and primitives, the source\n * value replaces the target value. All values are cloned to prevent reference sharing.\n *\n * @param target - The object to merge into\n * @param source - The object to merge from\n * @private\n */\n private mergeIntoRaw(target: Record<string, unknown>, source: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(source)) {\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n target[key] &&\n typeof target[key] === \"object\" &&\n !Array.isArray(target[key])\n ) {\n this.mergeIntoRaw(target[key] as Record<string, unknown>, value as Record<string, unknown>);\n continue;\n }\n\n target[key] = this.cloneData(value);\n }\n }\n\n /**\n * Deletes a field from the current raw data using a dot-notation path.\n *\n * Supports nested paths (e.g., \"address.city\") and array indices (e.g., \"items.0\").\n * If any segment in the path doesn't exist, the operation is a no-op.\n *\n * @param path - The dot-notation path to the field to delete\n * @private\n */\n private deleteFromRaw(path: string): void {\n const segments = path.split(\".\");\n let container: unknown = this.currentRaw;\n\n for (let index = 0; index < segments.length - 1; index += 1) {\n if (container === undefined || container === null) {\n return;\n }\n\n container = this.resolveSegment(container, segments[index]);\n }\n\n if (container === undefined || container === null) {\n return;\n }\n\n const lastSegment = segments[segments.length - 1];\n if (Array.isArray(container)) {\n const numericIndex = Number(lastSegment);\n if (!Number.isNaN(numericIndex)) {\n container.splice(numericIndex, 1);\n }\n return;\n }\n\n if (typeof container === \"object\") {\n delete (container as Record<string, unknown>)[lastSegment];\n }\n }\n\n /**\n * Resolves a single segment of a dot-notation path within a container.\n *\n * Handles both object property access and array index access.\n *\n * @param container - The object or array to access\n * @param segment - The property name or array index as a string\n * @returns The value at the specified segment, or undefined if not found\n * @private\n */\n private resolveSegment(container: unknown, segment: string): unknown {\n if (Array.isArray(container)) {\n const numericIndex = Number(segment);\n if (Number.isNaN(numericIndex)) {\n return undefined;\n }\n\n return container[numericIndex];\n }\n\n if (container && typeof container === \"object\") {\n return (container as Record<string, unknown>)[segment];\n }\n\n return undefined;\n }\n\n /**\n * Creates a deep clone of the provided data.\n *\n * @param data - The data to clone\n * @returns A deep clone of the data\n * @private\n */\n private cloneData<T>(data: T): T {\n return clone(data);\n }\n}\n","import { QueryBuilderContract } from \"../contracts\";\nimport type { Model } from \"../model/model\";\nimport { DeleteStrategy } from \"../types\";\n\ntype OnValidatingEventContext = {\n isInsert: boolean;\n mode: \"insert\" | \"update\";\n};\n\ntype OnSavingEventContext = {\n isInsert: boolean;\n mode: \"insert\" | \"update\";\n};\n\ntype OnDeletingEventContext = {\n strategy: DeleteStrategy;\n primaryKeyValue: string | number;\n primaryKey: string;\n};\n\nexport type OnDeletedEventContext = OnDeletingEventContext & {\n deletedCount: number;\n trashRecord?: Record<string, unknown>;\n};\n\ntype OnFetchingEventContext = {\n table: string;\n modelClass: any;\n};\n\ntype OnHydratingEventContext = {\n query: QueryBuilderContract;\n hydrateCallback?: (data: any, index: number) => any;\n};\n\ntype OnFetchedEventContext = {\n query: QueryBuilderContract;\n rawRecords: any[];\n duration: number;\n};\n\n/**\n * Lifecycle events understood by Cascade models.\n *\n * The list mirrors the hooks in the legacy ORM so downstream code can subscribe\n * with consistent semantics.\n */\nexport type ModelEventName =\n | \"initializing\"\n | \"fetching\"\n | \"hydrating\"\n | \"fetched\"\n | \"validating\"\n | \"validated\"\n | \"saving\"\n | \"saved\"\n | \"creating\"\n | \"created\"\n | \"updating\"\n | \"updated\"\n | \"deleting\"\n | \"deleted\"\n | \"restoring\"\n | \"restored\";\n\n/** Signature of an event listener registered against a model lifecycle hook. */\nexport type ModelEventListener<TModel, TContext = unknown> = (\n model: TModel,\n context: TContext,\n) => void | Promise<void>;\n\n/**\n * Light-weight async event emitter used to power model lifecycle hooks.\n *\n * The implementation intentionally avoids any external dependency so we can\n * re-use it in drivers, writers, and other core services without pulling in\n * heavier event libraries.\n */\nexport class ModelEvents<TModel> {\n public readonly listeners = new Map<ModelEventName, Set<ModelEventListener<TModel>>>();\n\n /**\n * Register a listener for the given event.\n * Returns an unsubscribe function for convenience.\n */\n public on<TContext = unknown>(\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n const listeners = this.ensureListenerSet(event);\n listeners.add(listener as ModelEventListener<TModel>);\n return () => this.off(event, listener);\n }\n\n /**\n * Register a listener that automatically unsubscribes after the first call.\n */\n public once<TContext = unknown>(\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n const wrapper: ModelEventListener<TModel, TContext> = async (model, context) => {\n try {\n await listener(model, context);\n } finally {\n this.off(event, wrapper);\n }\n };\n return this.on(event, wrapper);\n }\n\n /**\n * Deregister a listener for the given event.\n */\n public off<TContext = unknown>(\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): void {\n const listeners = this.listeners.get(event);\n if (!listeners) {\n return;\n }\n listeners.delete(listener as ModelEventListener<TModel>);\n if (listeners.size === 0) {\n this.listeners.delete(event);\n }\n }\n\n /**\n * Emit an event to all registered listeners.\n */\n public async emit<TContext = unknown>(\n event: ModelEventName,\n model: TModel,\n context: TContext,\n ): Promise<void> {\n const listeners = this.listeners.get(event);\n if (!listeners || listeners.size === 0) {\n return;\n }\n for (const listener of Array.from(listeners)) {\n await listener(model, context);\n }\n }\n\n /**\n * Emit events for fetching\n */\n public async emitFetching<TContext = unknown>(\n query: QueryBuilderContract,\n context?: TContext,\n ): Promise<void> {\n await this.emit(\"fetching\", query as any, context);\n }\n\n /**\n * Remove all registered listeners.\n */\n public clear(): void {\n this.listeners.clear();\n }\n\n /**\n * Registers a listener for the \"saving\" event.\n *\n * Fired before a model is persisted (both insert and update), and before validation.\n * Use this hook for data enrichment and preparation (e.g., setting createdBy, updatedBy).\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onSaving<TContext = OnSavingEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"saving\", listener);\n }\n\n /**\n * Registers a listener for the \"saved\" event.\n *\n * Fired after a model has been successfully persisted.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onSaved<TContext = unknown>(listener: ModelEventListener<TModel, TContext>) {\n return this.on(\"saved\", listener);\n }\n\n /**\n * Registers a listener for the \"creating\" event.\n *\n * Fired before a new model is inserted into the database.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onCreating<TContext = unknown>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"creating\", listener);\n }\n\n /**\n * Registers a listener for the \"created\" event.\n *\n * Fired after a new model has been successfully inserted.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onCreated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\n return this.on(\"created\", listener);\n }\n\n /**\n * Registers a listener for the \"updating\" event.\n *\n * Fired before an existing model is updated in the database.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onUpdating<TContext = unknown>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"updating\", listener);\n }\n\n /**\n * Registers a listener for the \"updated\" event.\n *\n * Fired after an existing model has been successfully updated.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onUpdated<TContext = unknown>(listener: ModelEventListener<TModel, TContext>): () => void {\n return this.on(\"updated\", listener);\n }\n\n /**\n * Registers a listener for the \"deleting\" event.\n *\n * Fired before a model is deleted from the database.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onDeleting<TContext = OnDeletingEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"deleting\", listener);\n }\n\n /**\n * Registers a listener for the \"deleted\" event.\n *\n * Fired after a model has been successfully deleted.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onDeleted<TContext = OnDeletedEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"deleted\", listener);\n }\n\n /**\n * Registers a listener for the \"validating\" event.\n *\n * Fired before model validation is performed.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onValidating<TContext = OnValidatingEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"validating\", listener);\n }\n\n /**\n * Registers a listener for the \"validated\" event.\n *\n * Fired after model validation has completed.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onValidated<TContext = unknown>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"validated\", listener);\n }\n\n /**\n * Registers a listener for the \"fetching\" event.\n *\n * Fired before a query is executed to fetch models.\n * Receives the query builder instance, allowing modification before execution.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onFetching<TContext = OnFetchingEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"fetching\", listener);\n }\n\n /**\n * Registers a listener for the \"hydrating\" event.\n *\n * Fired after raw records are fetched but before they are hydrated into model instances.\n * Allows modification of raw data before hydration.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onHydrating<TContext = OnHydratingEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"hydrating\", listener);\n }\n\n /**\n * Registers a listener for the \"fetched\" event.\n *\n * Fired after models have been fetched and hydrated.\n * Receives hydrated model instances and query context.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onFetched<TContext = OnFetchedEventContext>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"fetched\", listener);\n }\n\n /**\n * Registers a listener for the \"restoring\" event.\n *\n * Fired before a soft-deleted model is restored.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onRestoring<TContext = unknown>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"restoring\", listener);\n }\n\n /**\n * Registers a listener for the \"restored\" event.\n *\n * Fired after a soft-deleted model has been successfully restored.\n *\n * @param listener - The callback to invoke\n * @returns An unsubscribe function\n */\n public onRestored<TContext = unknown>(\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.on(\"restored\", listener);\n }\n\n /**\n * Ensures a listener set exists for the given event.\n *\n * @param event - The event name\n * @returns The listener set for the event\n * @private\n */\n private ensureListenerSet(event: ModelEventName): Set<ModelEventListener<TModel>> {\n let listeners = this.listeners.get(event);\n if (!listeners) {\n listeners = new Set();\n this.listeners.set(event, listeners);\n }\n return listeners;\n }\n}\n\n/**\n * Global event emitter invoked for every model instance, regardless of type.\n * Useful for cross-cutting concerns like auditing or request-scoped enrichment.\n */\nexport const globalModelEvents = new ModelEvents<Model>();\n","/**\n * Model sync event name helpers.\n *\n * Provides type-safe event names for model sync operations.\n * Avoids hardcoded string literals throughout the codebase.\n *\n * @module cascade-next/sync/model-events\n */\n\nimport type { ChildModel, Model } from \"../model/model\";\n\n/**\n * Event name prefix for all model sync events.\n */\nexport const MODEL_EVENT_PREFIX = \"model\";\n\n/**\n * Model sync event types.\n */\nexport const ModelSyncEventType = {\n UPDATED: \"updated\",\n DELETED: \"deleted\",\n} as const;\n\nexport type ModelSyncEventTypeName = (typeof ModelSyncEventType)[keyof typeof ModelSyncEventType];\n\n/**\n * Get the event name for a model update.\n *\n * @param modelClass - The model class\n * @returns Event name string (e.g., \"model.Category.updated\")\n *\n * @example\n * ```typescript\n * const eventName = getModelUpdatedEvent(Category);\n * // Returns: \"model.Category.updated\"\n * ```\n */\nexport function getModelUpdatedEvent(modelClass: ChildModel<Model>): string {\n return `${MODEL_EVENT_PREFIX}.${modelClass.name}.${ModelSyncEventType.UPDATED}`;\n}\n\n/**\n * Get the event name for a model deletion.\n *\n * @param modelClass - The model class\n * @returns Event name string (e.g., \"model.Category.deleted\")\n *\n * @example\n * ```typescript\n * const eventName = getModelDeletedEvent(Category);\n * // Returns: \"model.Category.deleted\"\n * ```\n */\nexport function getModelDeletedEvent(modelClass: ChildModel<Model>): string {\n return `${MODEL_EVENT_PREFIX}.${modelClass.name}.${ModelSyncEventType.DELETED}`;\n}\n\n/**\n * Get the event name for a model by name string.\n *\n * @param modelName - The model class name\n * @param eventType - The event type\n * @returns Event name string\n *\n * @example\n * ```typescript\n * const eventName = getModelEvent(\"Category\", \"updated\");\n * // Returns: \"model.Category.updated\"\n * ```\n */\nexport function getModelEvent(modelName: string, eventType: ModelSyncEventTypeName): string {\n return `${MODEL_EVENT_PREFIX}.${modelName}.${eventType}`;\n}\n","import events from \"@mongez/events\";\nimport type { DriverContract, UpdateOperations } from \"../contracts/database-driver.contract\";\nimport type {\n RemoverContract,\n RemoverOptions,\n RemoverResult,\n} from \"../contracts/database-remover.contract\";\nimport type { OnDeletedEventContext } from \"../events/model-events\";\nimport type { ChildModel, Model } from \"../model/model\";\nimport { getModelDeletedEvent } from \"../sync/model-events\";\nimport type { DataSource } from \"./../data-source/data-source\";\n\n/**\n * Database remover service that orchestrates model deletion.\n *\n * Handles the complete deletion pipeline:\n * 1. Strategy resolution (options → model static → data source default)\n * 2. Validation (check if model is new, has primary key)\n * 3. Event emission (deleting, deleted)\n * 4. Driver execution (based on strategy: trash, permanent, or soft)\n * 5. Post-deletion cleanup (mark as new, reset state)\n *\n * @example\n * ```typescript\n * const user = await User.find(1);\n * const remover = new DatabaseRemover(user);\n * const result = await remover.destroy();\n *\n * console.log(result.success); // true\n * console.log(result.strategy); // \"trash\" | \"permanent\" | \"soft\"\n * ```\n */\nexport class DatabaseRemover implements RemoverContract {\n /** The model instance being deleted */\n private readonly model: Model;\n\n /** Model constructor reference */\n private readonly ctor: ChildModel<Model>;\n\n /** Data source containing driver */\n private readonly dataSource: DataSource;\n\n /** Database driver for executing queries */\n private readonly driver: DriverContract;\n\n /** Table/collection name */\n private readonly table: string;\n\n /** Primary key field name */\n private readonly primaryKey: string;\n\n /**\n * Create a new remover instance for a model.\n *\n * @param model - The model instance to delete\n *\n * @example\n * ```typescript\n * const user = await User.find(1);\n * const remover = new DatabaseRemover(user);\n * await remover.destroy();\n * ```\n */\n public constructor(model: Model) {\n this.model = model;\n this.ctor = model.constructor as ChildModel<Model>;\n this.dataSource = this.ctor.getDataSource();\n this.driver = this.dataSource.driver;\n this.table = this.ctor.table;\n this.primaryKey = this.ctor.primaryKey;\n }\n\n /**\n * Destroy (delete) the model instance from the database.\n *\n * @param options - Remover options\n * @returns Result containing success status, strategy used, and metadata\n * @throws {Error} If model is new (not saved) or if deletion fails\n */\n public async destroy(options: RemoverOptions = {}): Promise<RemoverResult> {\n // 1. Resolve strategy (options → model static → data source default → permanent)\n const strategy =\n options.strategy ??\n this.ctor.deleteStrategy ??\n this.dataSource.defaultDeleteStrategy ??\n \"permanent\";\n\n // 2. Validate model is not new and has primary key\n if (this.model.isNew) {\n throw new Error(\n `Cannot destroy ${this.ctor.name} instance that hasn't been saved to the database.`,\n );\n }\n\n const primaryKeyValue = this.model.get(this.primaryKey);\n if (!primaryKeyValue) {\n throw new Error(\n `Cannot destroy ${this.ctor.name} instance: primary key (${this.primaryKey}) is missing.`,\n );\n }\n\n // 3. Emit deleting event (unless skipEvents)\n if (!options.skipEvents) {\n await this.model.emitEvent(\"deleting\", {\n strategy,\n primaryKeyValue,\n primaryKey: this.primaryKey,\n });\n }\n\n // 4. Execute deletion based on strategy\n let deletedCount = 0;\n let trashRecord: Record<string, unknown> | undefined;\n\n const filter = { [this.primaryKey]: primaryKeyValue };\n\n const context: Partial<OnDeletedEventContext> = {\n strategy,\n primaryKeyValue,\n primaryKey: this.primaryKey,\n };\n\n switch (strategy) {\n case \"trash\": {\n // Move to trash table, then delete\n const trashTable = this.resolveTrashTable();\n const documentData = { ...this.model.data };\n\n // Prepare trash record with metadata and handle ID conflicts\n const trashData = this.prepareTrashRecord(documentData);\n\n // Insert into trash table\n const insertResult = await this.driver.insert(trashTable, trashData);\n trashRecord = insertResult.document as Record<string, unknown>;\n\n context.trashRecord = trashRecord;\n\n // Delete original\n const result = await this.driver.delete(this.table, filter);\n deletedCount = result > 0 ? 1 : 0;\n break;\n }\n\n case \"permanent\": {\n // Direct deletion\n const result = await this.driver.delete(this.table, filter);\n deletedCount = result > 0 ? 1 : 0;\n break;\n }\n\n case \"soft\": {\n // Set deletedAt timestamp\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n const updateOperations: UpdateOperations = {\n $set: { [deletedAtColumn]: new Date() },\n };\n const updateResult = await this.driver.update(this.table, filter, updateOperations);\n deletedCount = updateResult.modifiedCount > 0 ? 1 : 0;\n break;\n }\n }\n\n if (deletedCount === 0) {\n throw new Error(`Failed to destroy ${this.ctor.name} instance: record not found.`);\n }\n\n context.deletedCount = deletedCount;\n\n // 5. Post-deletion cleanup\n // Only mark as new for permanent and trash (soft delete keeps the record)\n if (strategy !== \"soft\") {\n this.model.isNew = true;\n }\n\n // 6. Emit deleted event (unless skipEvents)\n if (!options.skipEvents) {\n await this.model.emitEvent(\"deleted\", context);\n }\n\n // 7. Trigger sync operations (fire-and-forget, non-blocking)\n if (!options.skipSync) {\n void this.triggerSync();\n }\n\n return {\n success: true,\n deletedCount,\n strategy,\n trashRecord,\n };\n }\n\n /**\n * Prepare the trash record by preserving all original fields and adding deletion metadata.\n *\n * Keeps all original fields intact for easy restoration and adds:\n * - `deletedAt`: Timestamp when the record was deleted\n * - `originalTable`: The table/collection the record came from (for filtering in restoreAll)\n *\n * **ID Handling:**\n * - MongoDB with `_id`: Keeps `_id` as-is (unique across database)\n * - MongoDB with auto-increment `id`: Keeps `id` as a regular field (not primary key)\n * - SQL: Keeps original `id` as a regular field (trash table uses its own auto-increment primary key)\n *\n * The trash table should use its own primary key structure:\n * - MongoDB: Uses `_id` (ObjectId) as primary key, original `id` is just a field\n * - SQL: Uses auto-increment `trashId` as primary key, original `id` is just a field\n *\n * @param documentData - The original document data\n * @returns Prepared trash record data with all original fields + deletedAt + originalTable\n * @private\n */\n private prepareTrashRecord(documentData: Record<string, unknown>): Record<string, unknown> {\n // Preserve all original fields and add deletion metadata\n return {\n ...documentData,\n deletedAt: new Date(),\n originalTable: this.table,\n };\n }\n\n /**\n * Resolve the trash table/collection name.\n *\n * Priority:\n * 1. Model.trashTable (if set)\n * 2. Data source defaultTrashTable (e.g., \"RecycleBin\" for MongoDB)\n * 3. Default pattern: `{table}Trash`\n *\n * @returns The trash table/collection name\n * @private\n */\n private resolveTrashTable(): string {\n if (this.ctor.trashTable) {\n return this.ctor.trashTable;\n }\n\n if (this.dataSource.defaultTrashTable) {\n return this.dataSource.defaultTrashTable;\n }\n\n return `${this.table}Trash`;\n }\n\n /**\n * Trigger sync operations after successful deletion.\n *\n * Emits a model.deleted event that ModelSyncOperation listens to.\n * The sync is handled by registered sync operations, not directly here.\n *\n * @private\n */\n private async triggerSync(): Promise<void> {\n // Emit model.deleted event - ModelSyncOperation listens to these\n await events.triggerAll(getModelDeletedEvent(this.ctor), this.model);\n }\n}\n","import type {\n DriverContract,\n UpdateOperations,\n} from \"../contracts/database-driver.contract\";\nimport type {\n RestorerContract,\n RestorerOptions,\n RestorerResult,\n} from \"../contracts/database-restorer.contract\";\nimport type { DataSource } from \"../data-source/data-source\";\nimport type { Model } from \"../model/model\";\nimport type { DeleteStrategy } from \"../types\";\n\n/**\n * Database restorer service that orchestrates model restoration.\n *\n * Handles the complete restoration pipeline:\n * 1. Strategy detection (trash vs soft delete)\n * 2. Record retrieval from trash table or soft-deleted records\n * 3. ID conflict resolution\n * 4. Event emission (restoring, restored)\n * 5. Driver execution (insert back to original table, remove from trash/clear deletedAt)\n *\n * @example\n * ```typescript\n * const restorer = new DatabaseRestorer(User);\n * const result = await restorer.restore(123);\n *\n * console.log(result.success); // true\n * console.log(result.strategy); // \"trash\" | \"soft\"\n * ```\n */\nexport class DatabaseRestorer implements RestorerContract {\n /** Model constructor reference */\n private readonly ctor: typeof Model;\n\n /** Data source containing driver */\n private readonly dataSource: DataSource;\n\n /** Database driver for executing queries */\n private readonly driver: DriverContract;\n\n /** Table/collection name */\n private readonly table: string;\n\n /** Primary key field name */\n private readonly primaryKey: string;\n\n /**\n * Create a new restorer instance for a model class.\n *\n * @param modelClass - The model class (static context)\n *\n * @example\n * ```typescript\n * const restorer = new DatabaseRestorer(User);\n * await restorer.restore(123);\n * ```\n */\n public constructor(modelClass: typeof Model) {\n this.ctor = modelClass;\n this.dataSource = modelClass.getDataSource();\n this.driver = this.dataSource.driver;\n this.table = modelClass.table;\n this.primaryKey = modelClass.primaryKey;\n }\n\n /**\n * Restore a single deleted record by its ID.\n *\n * @param id - The primary key value of the record to restore\n * @param options - Restorer options\n * @returns Result containing success status, strategy used, and restored record\n * @throws {Error} If record not found in trash or soft-deleted records\n * @throws {Error} If ID conflict and onIdConflict is \"fail\"\n */\n public async restore(\n id: string | number,\n options: RestorerOptions = {},\n ): Promise<RestorerResult> {\n const onIdConflict = options.onIdConflict ?? \"assignNew\";\n const skipEvents = options.skipEvents ?? false;\n\n // 1. Resolve strategy (options → model static → data source default)\n const strategy = this.resolveStrategy(options.strategy);\n\n // 2. Validate strategy (cannot restore permanent deletes)\n if (strategy === \"permanent\") {\n throw new Error(\n `Cannot restore ${this.ctor.name} with ${this.primaryKey} ${id}: permanently deleted records cannot be restored.`,\n );\n }\n\n // 3. Fetch record based on strategy\n const recordData = await this.fetchRecordByStrategy(id, strategy);\n\n if (!recordData) {\n throw new Error(\n `Cannot restore ${this.ctor.name} with ${this.primaryKey} ${id}: record not found in ${strategy === \"trash\" ? \"trash table\" : \"soft-deleted records\"}.`,\n );\n }\n\n // 4. Prepare record data (remove metadata fields)\n const restoredData = { ...recordData };\n delete restoredData.deletedAt;\n delete restoredData.originalTable;\n\n // 5. Check for ID conflict and handle\n const finalData = await this.handleIdConflict(\n restoredData,\n id,\n onIdConflict,\n );\n\n // 6. Create temporary model instance for event emission\n // Note: Model is abstract, but at runtime this.ctor is a concrete subclass\n const model = new (this.ctor as any)(finalData) as Model;\n\n // 7. Emit restoring event (unless skipEvents)\n if (!skipEvents) {\n await model.emitEvent(\"restoring\");\n }\n\n // 8. Restore based on strategy\n if (strategy === \"trash\") {\n // Insert record back into original table (was moved to trash)\n await this.driver.insert(this.table, finalData);\n model.isNew = false;\n\n // Remove from trash table\n await this.driver.delete(this.resolveTrashTable(), {\n [this.primaryKey]: id,\n });\n } else if (strategy === \"soft\") {\n // Record still exists, just unset deletedAt (don't insert - would create duplicate!)\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n const filter = { [this.primaryKey]: id };\n const updateOperations: UpdateOperations = {\n $unset: { [deletedAtColumn]: 1 },\n };\n\n await this.driver.update(this.table, filter, updateOperations);\n model.isNew = false;\n }\n\n // 10. Emit restored event (unless skipEvents)\n if (!skipEvents) {\n await model.emitEvent(\"restored\");\n }\n\n return {\n success: true,\n restoredCount: 1,\n strategy,\n restoredRecord: model,\n };\n }\n\n /**\n * Restore all deleted records for the model's table.\n *\n * @param options - Restorer options\n * @returns Result containing success status, strategy used, and aggregate counts\n */\n public async restoreAll(\n options: RestorerOptions = {},\n ): Promise<RestorerResult> {\n const onIdConflict = options.onIdConflict ?? \"assignNew\";\n const skipEvents = options.skipEvents ?? false;\n\n // 1. Resolve strategy (options → model static → data source default)\n const strategy = this.resolveStrategy(options.strategy);\n\n // 2. Validate strategy (cannot restore permanent deletes)\n if (strategy === \"permanent\") {\n throw new Error(\n `Cannot restore all ${this.ctor.name} records: permanently deleted records cannot be restored.`,\n );\n }\n\n // 3. Fetch all records based on strategy\n const recordsToRestore = await this.fetchAllRecordsByStrategy(strategy);\n\n if (recordsToRestore.length === 0) {\n return {\n success: true,\n restoredCount: 0,\n strategy,\n };\n }\n\n // 4. Restore each record\n let restoredCount = 0;\n const conflicts: Array<{ id: string | number; reason: string }> = [];\n\n const restoredRecords: Model[] = [];\n\n for (const recordData of recordsToRestore) {\n const id = recordData[this.primaryKey] as string | number;\n\n try {\n // Prepare record data (remove metadata fields)\n const restoredData = { ...recordData };\n delete restoredData.deletedAt;\n delete restoredData.originalTable;\n\n // Check for ID conflict\n const idExists = await this.checkIdExists(id);\n if (idExists) {\n if (onIdConflict === \"fail\") {\n throw new Error(\n `Cannot restore ${this.ctor.name} with ${this.primaryKey} ${id}: ID already exists in target table.`,\n );\n }\n\n // Assign new ID\n const finalData = await this.assignNewId(restoredData);\n conflicts.push({\n id,\n reason: `ID ${id} already exists, assigned new ID ${finalData[this.primaryKey]}`,\n });\n\n // Create temporary model for events\n const model = new (this.ctor as any)(finalData) as Model;\n\n // Emit restoring event\n if (!skipEvents) {\n await model.emitEvent(\"restoring\");\n }\n\n // Restore based on strategy\n if (strategy === \"trash\") {\n // Insert with new ID (was moved to trash)\n await this.driver.insert(this.table, finalData);\n model.isNew = false;\n } else if (strategy === \"soft\") {\n // Record still exists, just unset deletedAt\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n const filter = { [this.primaryKey]: id };\n const updateOperations: UpdateOperations = {\n $unset: { [deletedAtColumn]: 1 },\n };\n await this.driver.update(this.table, filter, updateOperations);\n model.isNew = false;\n }\n\n restoredRecords.push(model);\n\n // Emit restored event\n if (!skipEvents) {\n await model.emitEvent(\"restored\");\n }\n } else {\n // No conflict, restore with original ID\n const model = new (this.ctor as any)(restoredData) as Model;\n\n // Emit restoring event\n if (!skipEvents) {\n await model.emitEvent(\"restoring\");\n }\n\n // Restore based on strategy\n if (strategy === \"trash\") {\n // Insert with original ID (was moved to trash)\n await this.driver.insert(this.table, restoredData);\n model.isNew = false;\n } else if (strategy === \"soft\") {\n // Record still exists, just unset deletedAt\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n const filter = { [this.primaryKey]: id };\n const updateOperations: UpdateOperations = {\n $unset: { [deletedAtColumn]: 1 },\n };\n await this.driver.update(this.table, filter, updateOperations);\n model.isNew = false;\n }\n\n restoredRecords.push(model);\n\n // Emit restored event\n if (!skipEvents) {\n await model.emitEvent(\"restored\");\n }\n }\n\n // Remove from trash (only for trash strategy)\n if (strategy === \"trash\") {\n const trashTable = this.resolveTrashTable();\n const trashFilter = { [this.primaryKey]: id };\n await this.driver.delete(trashTable, trashFilter);\n }\n\n restoredCount++;\n } catch (error) {\n if (onIdConflict === \"fail\") {\n throw error;\n }\n // Continue with next record if assignNew mode\n conflicts.push({\n id,\n reason: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return {\n success: true,\n restoredCount,\n restoredRecords,\n strategy,\n conflicts: conflicts.length > 0 ? conflicts : undefined,\n };\n }\n\n /**\n * Resolve the delete strategy.\n *\n * Priority: options → model static → data source default → \"permanent\"\n *\n * @param strategyOption - Optional strategy override from options\n * @returns The resolved delete strategy\n * @private\n */\n private resolveStrategy(strategyOption?: \"trash\" | \"soft\"): DeleteStrategy {\n return (\n strategyOption ??\n this.ctor.deleteStrategy ??\n this.dataSource.defaultDeleteStrategy ??\n \"permanent\"\n );\n }\n\n /**\n * Fetch a record by ID based on the delete strategy.\n *\n * @param id - The primary key value\n * @param strategy - The delete strategy to use\n * @returns The record data, or null if not found\n * @private\n */\n private async fetchRecordByStrategy(\n id: string | number,\n strategy: \"trash\" | \"soft\",\n ) {\n if (strategy === \"trash\") {\n const trashTable = this.resolveTrashTable();\n try {\n const trashQuery = await this.driver\n .queryBuilder(trashTable)\n .where(this.primaryKey, id)\n .first<Record<string, unknown>>();\n\n return trashQuery;\n } catch {\n return null;\n }\n } else if (strategy === \"soft\") {\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n try {\n const softDeletedQuery = await this.driver\n .queryBuilder(this.table)\n .where(this.primaryKey, id)\n .whereNotNull(deletedAtColumn)\n .first<Record<string, unknown>>();\n\n return softDeletedQuery;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n /**\n * Fetch all records based on the delete strategy.\n *\n * @param strategy - The delete strategy to use\n * @returns Array of record data\n * @private\n */\n private async fetchAllRecordsByStrategy(\n strategy: \"trash\" | \"soft\",\n ): Promise<Record<string, unknown>[]> {\n if (strategy === \"trash\") {\n const trashTable = this.resolveTrashTable();\n try {\n const trashQuery = this.driver\n .queryBuilder(trashTable)\n .where(\"originalTable\", this.table)\n .get();\n\n return (await trashQuery) as Record<string, unknown>[];\n } catch {\n return [];\n }\n } else if (strategy === \"soft\") {\n const deletedAtColumn = this.ctor.deletedAtColumn ?? \"deletedAt\";\n try {\n const softDeletedQuery = this.driver\n .queryBuilder(this.table)\n .whereNotNull(deletedAtColumn)\n .get();\n\n return (await softDeletedQuery) as Record<string, unknown>[];\n } catch {\n return [];\n }\n }\n\n return [];\n }\n\n /**\n * Handle ID conflict by checking if ID exists and assigning new one if needed.\n *\n * @param recordData - The record data to restore\n * @param originalId - The original ID value\n * @param onIdConflict - Conflict resolution strategy\n * @returns Record data with potentially new ID\n * @private\n */\n private async handleIdConflict(\n recordData: Record<string, unknown>,\n originalId: string | number,\n onIdConflict: \"fail\" | \"assignNew\",\n ): Promise<Record<string, unknown>> {\n const idExists = await this.checkIdExists(originalId);\n\n if (idExists) {\n if (onIdConflict === \"fail\") {\n throw new Error(\n `Cannot restore ${this.ctor.name} with ${this.primaryKey} ${originalId}: ID already exists in target table.`,\n );\n }\n\n // Assign new ID\n return await this.assignNewId(recordData);\n }\n\n return recordData;\n }\n\n /**\n * Check if an ID already exists in the target table.\n *\n * @param id - The ID to check\n * @returns True if ID exists, false otherwise\n * @private\n */\n private async checkIdExists(id: string | number): Promise<boolean> {\n try {\n const query = this.driver\n .queryBuilder(this.table)\n .where(this.primaryKey, id)\n .exists();\n\n return await query;\n } catch {\n return false;\n }\n }\n\n /**\n * Assign a new ID to the record data.\n *\n * For MongoDB: Generates new ObjectId for `_id`, keeps `id` if it exists\n * For SQL: Removes `id` to let database auto-increment\n *\n * @param recordData - The record data\n * @returns Record data with new ID assigned\n * @private\n */\n private async assignNewId(\n recordData: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n const isMongoDb = this.driver.name === \"mongodb\";\n const newData = { ...recordData };\n\n if (isMongoDb) {\n // MongoDB: Generate new ObjectId for _id\n if (this.primaryKey === \"_id\") {\n // Remove _id to let MongoDB generate new one\n delete newData._id;\n } else if (this.primaryKey === \"id\") {\n // Remove id to let ID generator create new one\n delete newData.id;\n }\n } else {\n // SQL: Remove primary key to let database auto-increment\n delete newData[this.primaryKey];\n }\n\n return newData;\n }\n\n /**\n * Resolve the trash table/collection name.\n *\n * Priority:\n * 1. Model.trashTable (if set)\n * 2. Data source defaultTrashTable (e.g., \"RecycleBin\" for MongoDB)\n * 3. Default pattern: `{table}Trash`\n *\n * @returns The trash table/collection name\n * @private\n */\n private resolveTrashTable(): string {\n if (this.ctor.trashTable) {\n return this.ctor.trashTable;\n }\n\n if (this.dataSource.defaultTrashTable) {\n return this.dataSource.defaultTrashTable;\n }\n\n return `${this.table}Trash`;\n }\n}\n","/**\n * Sync context management and validation.\n *\n * @module cascade-next/sync/sync-context\n */\n\nimport type { SyncContext, SyncInstruction } from \"./types\";\n\n/**\n * Default maximum sync depth.\n * Prevents infinite sync chains.\n */\nexport const DEFAULT_MAX_SYNC_DEPTH = 3;\n\n/**\n * Manages sync context and provides validation utilities.\n */\nexport class SyncContextManager {\n /**\n * Creates a new sync context from a sync instruction.\n *\n * @param instruction - The sync instruction to create context from\n * @param affectedCount - Number of documents affected\n * @returns A new sync context\n */\n public static createContext(\n instruction: SyncInstruction,\n affectedCount: number,\n ): SyncContext {\n return {\n sourceModel: instruction.sourceModel,\n sourceId: instruction.sourceId,\n currentDepth: instruction.depth,\n syncChain: [...instruction.chain],\n targetModel: instruction.targetModel,\n filter: { ...instruction.filter },\n update: { ...instruction.update },\n affectedCount,\n timestamp: new Date(),\n };\n }\n\n /**\n * Validates if a sync operation can proceed based on depth and cycle detection.\n *\n * @param depth - Current sync depth\n * @param chain - Current sync chain\n * @param targetModel - Target model name\n * @param maxDepth - Maximum allowed depth\n * @param preventCircular - Whether to prevent circular references\n * @returns Validation result with success flag and optional error message\n */\n public static validate(\n depth: number,\n chain: string[],\n targetModel: string,\n maxDepth: number,\n preventCircular: boolean,\n ): { valid: boolean; error?: string } {\n // Check depth limit\n if (depth > maxDepth) {\n return {\n valid: false,\n error: `Sync depth limit exceeded: ${depth} > ${maxDepth}. Chain: ${chain.join(\" → \")}`,\n };\n }\n\n // Check for circular references\n if (preventCircular && this.hasCycle(chain, targetModel)) {\n return {\n valid: false,\n error: `Circular sync detected: ${targetModel} already exists in chain [${chain.join(\" → \")}]`,\n };\n }\n\n return { valid: true };\n }\n\n /**\n * Checks if adding a target model would create a cycle in the sync chain.\n *\n * @param chain - Current sync chain\n * @param targetModel - Model to be added to the chain\n * @returns True if adding the model would create a cycle\n */\n public static hasCycle(chain: string[], targetModel: string): boolean {\n return chain.includes(targetModel);\n }\n\n /**\n * Creates a new sync chain by appending a model name.\n *\n * @param chain - Current sync chain\n * @param modelName - Model name to append\n * @returns New sync chain array\n */\n public static extendChain(chain: string[], modelName: string): string[] {\n return [...chain, modelName];\n }\n\n /**\n * Formats a sync chain for display.\n *\n * @param chain - Sync chain to format\n * @returns Formatted string (e.g., \"Category → Product → Module\")\n */\n public static formatChain(chain: string[]): string {\n return chain.join(\" → \");\n }\n\n /**\n * Checks if the current depth allows for further syncing.\n *\n * @param currentDepth - Current depth in the chain\n * @param maxDepth - Maximum allowed depth\n * @returns True if more syncing is allowed\n */\n public static canSyncDeeper(\n currentDepth: number,\n maxDepth: number,\n ): boolean {\n return currentDepth < maxDepth;\n }\n}\n\n","/**\n * Sync manager service for handling multi-level sync operations.\n *\n * @module cascade-next/sync/sync-manager\n */\n\nimport type { DriverContract } from \"../contracts/database-driver.contract\";\nimport { ChildModel, Model } from \"../model/model\";\nimport { DEFAULT_MAX_SYNC_DEPTH, SyncContextManager } from \"./sync-context\";\nimport type {\n CollectInstructionsPayload,\n SyncConfig,\n SyncEventPayload,\n SyncInstruction,\n SyncInstructionOptions,\n SyncResult,\n} from \"./types\";\n\n/**\n * Manages sync operations across models with multi-level support.\n */\nexport class SyncManager {\n private readonly sourceModel: ChildModel<Model>;\n private readonly driver: DriverContract;\n\n /**\n * Creates a new sync manager.\n *\n * @param sourceModel - The source model class\n * @param driver - The database driver\n */\n public constructor(sourceModel: ChildModel<Model>, driver: DriverContract) {\n this.sourceModel = sourceModel;\n this.driver = driver;\n }\n\n /**\n * Executes sync operations for a model update.\n *\n * @param sourceId - The source model ID\n * @param updatedData - The updated data to sync (Model instance or plain data)\n * @param changedFields - Fields that were changed (for filtering)\n * @returns Sync result with success status and details\n */\n public async syncUpdate(\n sourceId: string | number,\n updatedData: Record<string, unknown> | Model,\n changedFields: string[],\n ): Promise<SyncResult> {\n try {\n const syncConfigs = this.getSyncConfigs();\n\n if (syncConfigs.length === 0) {\n return this.createEmptyResult();\n }\n\n const options: SyncInstructionOptions = {\n currentDepth: 1,\n syncChain: [this.sourceModel.name],\n maxDepth: DEFAULT_MAX_SYNC_DEPTH,\n preventCircular: true,\n };\n\n const instructions = await this.collectInstructions({\n sourceId,\n updatedData,\n changedFields,\n syncConfigs,\n options,\n });\n\n return await this.executeInstructions(instructions);\n } catch (error) {\n // Catch-all error handler for unexpected failures\n console.error(`Sync update failed for ${this.sourceModel.name}#${sourceId}:`, error);\n\n return {\n success: false,\n attempted: 0,\n succeeded: 0,\n failed: 1,\n errors: [\n {\n instruction: {\n targetTable: \"\",\n targetModel: \"\",\n filter: {},\n update: {},\n depth: 0,\n chain: [this.sourceModel.name],\n sourceModel: this.sourceModel.name,\n sourceId,\n },\n error: error instanceof Error ? error : new Error(String(error)),\n },\n ],\n depthReached: 0,\n contexts: [],\n };\n }\n }\n\n /**\n * Executes sync operations for a model update with a specific config.\n * Used by ModelSyncOperation for event-based sync.\n *\n * @param sourceId - The source model ID\n * @param updatedData - The updated data to sync\n * @param changedFields - Fields that were changed\n * @param config - The sync configuration to use\n * @returns Sync result with success status and details\n */\n public async syncUpdateWithConfig(\n sourceId: string | number,\n updatedData: Record<string, unknown> | Model,\n changedFields: string[],\n config: SyncConfig,\n ): Promise<SyncResult> {\n try {\n const options: SyncInstructionOptions = {\n currentDepth: 1,\n syncChain: [this.sourceModel.name],\n maxDepth: config.maxSyncDepth,\n preventCircular: config.preventCircularSync,\n };\n\n const instructions = await this.collectInstructions({\n sourceId,\n updatedData,\n changedFields,\n syncConfigs: [config],\n options,\n });\n\n return await this.executeInstructions(instructions);\n } catch (error) {\n console.error(\n `Sync update with config failed for ${this.sourceModel.name}#${sourceId}:`,\n error,\n );\n\n return {\n success: false,\n attempted: 0,\n succeeded: 0,\n failed: 1,\n errors: [\n {\n instruction: {\n targetTable: \"\",\n targetModel: \"\",\n filter: {},\n update: {},\n depth: 0,\n chain: [this.sourceModel.name],\n sourceModel: this.sourceModel.name,\n sourceId,\n },\n error: error instanceof Error ? error : new Error(String(error)),\n },\n ],\n depthReached: 0,\n contexts: [],\n };\n }\n }\n\n /**\n * Executes sync delete operations with a specific config.\n * Used by ModelSyncOperation for event-based sync.\n *\n * @param sourceId - The source model ID\n * @param config - The sync configuration to use\n * @returns Sync result with success status and details\n */\n public async syncDeleteWithConfig(\n sourceId: string | number,\n config: SyncConfig,\n ): Promise<SyncResult> {\n try {\n if (!config.unsetOnDelete) {\n return this.createEmptyResult();\n }\n\n const options: SyncInstructionOptions = {\n currentDepth: 1,\n syncChain: [this.sourceModel.name],\n maxDepth: config.maxSyncDepth,\n preventCircular: config.preventCircularSync,\n };\n\n const instructions = await this.collectDeleteInstructions(sourceId, [config], options);\n\n return await this.executeInstructions(instructions);\n } catch (error) {\n console.error(\n `Sync delete with config failed for ${this.sourceModel.name}#${sourceId}:`,\n error,\n );\n\n return {\n success: false,\n attempted: 0,\n succeeded: 0,\n failed: 1,\n errors: [\n {\n instruction: {\n targetTable: \"\",\n targetModel: \"\",\n filter: {},\n update: {},\n depth: 0,\n chain: [this.sourceModel.name],\n sourceModel: this.sourceModel.name,\n sourceId,\n },\n error: error instanceof Error ? error : new Error(String(error)),\n },\n ],\n depthReached: 0,\n contexts: [],\n };\n }\n }\n\n /**\n * Executes sync operations for a model deletion.\n *\n * @param sourceId - The source model ID\n * @returns Sync result with success status and details\n */\n public async syncDelete(sourceId: string | number): Promise<SyncResult> {\n try {\n const syncConfigs = this.getSyncConfigs();\n\n if (syncConfigs.length === 0) {\n return this.createEmptyResult();\n }\n\n const options: SyncInstructionOptions = {\n currentDepth: 1,\n syncChain: [this.sourceModel.name],\n maxDepth: DEFAULT_MAX_SYNC_DEPTH,\n preventCircular: true,\n };\n\n const instructions = await this.collectDeleteInstructions(sourceId, syncConfigs, options);\n\n return await this.executeInstructions(instructions);\n } catch (error) {\n // Catch-all error handler for unexpected failures\n console.error(`Sync delete failed for ${this.sourceModel.name}#${sourceId}:`, error);\n\n return {\n success: false,\n attempted: 0,\n succeeded: 0,\n failed: 1,\n errors: [\n {\n instruction: {\n targetTable: \"\",\n targetModel: \"\",\n filter: {},\n update: {},\n depth: 0,\n chain: [this.sourceModel.name],\n sourceModel: this.sourceModel.name,\n sourceId,\n },\n error: error instanceof Error ? error : new Error(String(error)),\n },\n ],\n depthReached: 0,\n contexts: [],\n };\n }\n }\n\n /**\n * Collects sync instructions recursively with depth limiting.\n *\n * @param payload - Data payload\n * @returns Array of sync instructions\n */\n private async collectInstructions(\n payload: CollectInstructionsPayload,\n ): Promise<SyncInstruction[]> {\n const { sourceId, updatedData, changedFields, syncConfigs, options } = payload;\n const instructions: SyncInstruction[] = [];\n\n for (const config of syncConfigs) {\n // Check if we should sync based on watched fields\n if (!this.shouldSync(config, changedFields)) {\n continue;\n }\n\n // Validate depth and circular references\n const validation = SyncContextManager.validate(\n options.currentDepth,\n options.syncChain,\n config.targetModelClass.name,\n config.maxSyncDepth,\n config.preventCircularSync,\n );\n\n if (!validation.valid) {\n console.warn(`Sync validation failed: ${validation.error}`);\n continue;\n }\n\n // Get embedded data (handle both Model instance and plain data)\n const embedData = await this.getEmbedData(updatedData, config);\n\n // Build instruction\n const instruction = this.buildUpdateInstruction(sourceId, config, embedData, options);\n\n instructions.push(instruction);\n\n // Emit syncing event\n await this.emitSyncingEvent(instruction);\n\n // Recursively collect instructions for next level\n if (SyncContextManager.canSyncDeeper(options.currentDepth, config.maxSyncDepth)) {\n const nextLevelInstructions = await this.collectNextLevelInstructions(\n instruction,\n embedData,\n changedFields,\n config,\n options,\n );\n instructions.push(...nextLevelInstructions);\n }\n }\n\n return instructions;\n }\n\n /**\n * Collects delete sync instructions.\n *\n * @param sourceId - Source model ID\n * @param syncConfigs - Sync configurations\n * @param options - Instruction options\n * @returns Array of sync instructions\n */\n private async collectDeleteInstructions(\n sourceId: string | number,\n syncConfigs: SyncConfig[],\n options: SyncInstructionOptions,\n ): Promise<SyncInstruction[]> {\n const instructions: SyncInstruction[] = [];\n\n for (const config of syncConfigs) {\n if (!config.unsetOnDelete) {\n continue;\n }\n\n const validation = SyncContextManager.validate(\n options.currentDepth,\n options.syncChain,\n config.targetModelClass.name,\n config.maxSyncDepth,\n config.preventCircularSync,\n );\n\n if (!validation.valid) {\n continue;\n }\n\n const instruction = this.buildDeleteInstruction(sourceId, config, options);\n instructions.push(instruction);\n\n await this.emitSyncingEvent(instruction);\n }\n\n return instructions;\n }\n\n /**\n * Collects instructions for the next level in the sync chain.\n *\n * @param parentInstruction - The parent instruction\n * @param embedData - Embedded data from parent\n * @param changedFields - Changed fields\n * @param parentConfig - Parent sync config\n * @param parentOptions - Parent instruction options\n * @returns Array of next-level sync instructions\n */\n private async collectNextLevelInstructions(\n parentInstruction: SyncInstruction,\n embedData: Record<string, unknown>,\n changedFields: string[],\n parentConfig: SyncConfig,\n parentOptions: SyncInstructionOptions,\n ): Promise<SyncInstruction[]> {\n const targetModelClass = parentConfig.targetModelClass;\n const targetSyncConfigs = this.getSyncConfigsForModel(targetModelClass);\n\n if (targetSyncConfigs.length === 0) {\n return [];\n }\n\n const nextOptions: SyncInstructionOptions = {\n currentDepth: parentOptions.currentDepth + 1,\n syncChain: SyncContextManager.extendChain(parentOptions.syncChain, targetModelClass.name),\n maxDepth: Math.min(parentConfig.maxSyncDepth, parentOptions.maxDepth),\n preventCircular: parentOptions.preventCircular && parentConfig.preventCircularSync,\n };\n\n // Get the ID from embed data for next level\n const sourceId = embedData[parentConfig.identifierField] as string | number;\n\n return await this.collectInstructions({\n sourceId,\n updatedData: embedData,\n changedFields,\n syncConfigs: targetSyncConfigs,\n options: nextOptions,\n });\n }\n\n /**\n * Builds an update sync instruction.\n *\n * @param sourceId - Source model ID\n * @param config - Sync configuration\n * @param embedData - Embedded data to sync\n * @param options - Instruction options\n * @returns Sync instruction\n */\n private buildUpdateInstruction(\n sourceId: string | number,\n config: SyncConfig,\n embedData: Record<string, unknown>,\n options: SyncInstructionOptions,\n ): SyncInstruction {\n const targetModelClass = config.targetModelClass;\n const filter = this.buildFilter(sourceId, config);\n const update = this.buildUpdate(embedData, config);\n\n const instruction: SyncInstruction = {\n targetTable: targetModelClass.table,\n targetModel: targetModelClass.name,\n filter,\n update,\n depth: options.currentDepth,\n chain: [...options.syncChain],\n sourceModel: this.sourceModel.name,\n sourceId,\n };\n\n // Add array update metadata if needed\n if (config.isMany) {\n instruction.isArrayUpdate = true;\n instruction.arrayField = config.targetField;\n instruction.identifierField = config.identifierField;\n instruction.identifierValue = sourceId;\n }\n\n return instruction;\n }\n\n /**\n * Builds a delete sync instruction.\n *\n * @param sourceId - Source model ID\n * @param config - Sync configuration\n * @param options - Instruction options\n * @returns Sync instruction\n */\n private buildDeleteInstruction(\n sourceId: string | number,\n config: SyncConfig,\n options: SyncInstructionOptions,\n ): SyncInstruction {\n const targetModelClass = config.targetModelClass;\n const filter = this.buildFilter(sourceId, config);\n const update = { $unset: { [config.targetField]: 1 } };\n\n return {\n targetTable: targetModelClass.table,\n targetModel: targetModelClass.name,\n filter,\n update,\n depth: options.currentDepth,\n chain: [...options.syncChain],\n sourceModel: this.sourceModel.name,\n sourceId,\n };\n }\n\n /**\n * Builds a filter for identifying target documents.\n *\n * @param sourceId - Source model ID\n * @param config - Sync configuration\n * @returns Filter object\n */\n private buildFilter(sourceId: string | number, config: SyncConfig): Record<string, unknown> {\n if (config.isMany) {\n // For arrays: { \"products.id\": productId }\n return { [`${config.targetField}.${config.identifierField}`]: sourceId };\n } else {\n // For single: { \"category.id\": categoryId }\n return { [`${config.targetField}.${config.identifierField}`]: sourceId };\n }\n }\n\n /**\n * Builds an update operation for syncing data.\n *\n * @param embedData - Embedded data to sync\n * @param config - Sync configuration\n * @returns Update operation object\n */\n private buildUpdate(\n embedData: Record<string, unknown>,\n config: SyncConfig,\n ): Record<string, unknown> {\n if (config.isMany) {\n // For arrays: use positional operator $\n return { $set: { [`${config.targetField}.$`]: embedData } };\n } else {\n // For single: direct set\n return { $set: { [config.targetField]: embedData } };\n }\n }\n\n /**\n * Executes sync instructions with batch optimization.\n * Groups by depth and target table for optimal batching.\n *\n * @param instructions - Array of sync instructions\n * @returns Sync result\n */\n private async executeInstructions(instructions: SyncInstruction[]): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n attempted: instructions.length,\n succeeded: 0,\n failed: 0,\n errors: [],\n depthReached: 0,\n contexts: [],\n };\n\n if (instructions.length === 0) {\n return result;\n }\n\n // Group instructions by depth for sequential execution\n const instructionsByDepth = this.groupByDepth(instructions);\n\n for (const [depth, depthInstructions] of instructionsByDepth) {\n result.depthReached = Math.max(result.depthReached, depth);\n\n // Further group by target table for better batching\n const instructionsByTable = this.groupByTable(depthInstructions);\n\n for (const [table, tableInstructions] of instructionsByTable) {\n try {\n // Try batch execution first (all instructions for this table)\n await this.executeBatch(tableInstructions, result);\n } catch (batchError) {\n // Fallback to individual execution on batch failure\n console.warn(\n `Batch execution failed for table ${table} at depth ${depth}, falling back to individual execution`,\n );\n await this.executeIndividual(tableInstructions, result);\n }\n }\n }\n\n result.success = result.failed === 0;\n return result;\n }\n\n /**\n * Executes instructions in batch.\n *\n * @param instructions - Instructions to execute\n * @param result - Result object to update\n */\n private async executeBatch(instructions: SyncInstruction[], result: SyncResult): Promise<void> {\n for (const instruction of instructions) {\n try {\n const updateResult = await this.driver.updateMany(\n instruction.targetTable,\n instruction.filter,\n instruction.update,\n );\n\n const context = SyncContextManager.createContext(instruction, updateResult.modifiedCount);\n result.contexts.push(context);\n result.succeeded++;\n\n await this.emitSyncedEvent(context);\n } catch (error) {\n throw error; // Re-throw for batch fallback\n }\n }\n }\n\n /**\n * Executes instructions individually (fallback).\n * Provides detailed error reporting for each failed instruction.\n *\n * @param instructions - Instructions to execute\n * @param result - Result object to update\n */\n private async executeIndividual(\n instructions: SyncInstruction[],\n result: SyncResult,\n ): Promise<void> {\n for (const instruction of instructions) {\n try {\n const updateResult = await this.driver.updateMany(\n instruction.targetTable,\n instruction.filter,\n instruction.update,\n );\n\n const context = SyncContextManager.createContext(instruction, updateResult.modifiedCount);\n result.contexts.push(context);\n result.succeeded++;\n\n await this.emitSyncedEvent(context);\n } catch (error) {\n result.failed++;\n\n const errorMessage = this.formatSyncError(instruction, error);\n const syncError = new Error(errorMessage);\n\n // Preserve original error stack if available\n if (error instanceof Error && error.stack) {\n syncError.stack = error.stack;\n }\n\n result.errors.push({\n instruction,\n error: syncError,\n });\n\n // Log detailed error for debugging\n console.error(`Sync operation failed:`, {\n sourceModel: instruction.sourceModel,\n sourceId: instruction.sourceId,\n targetModel: instruction.targetModel,\n targetTable: instruction.targetTable,\n depth: instruction.depth,\n chain: SyncContextManager.formatChain(instruction.chain),\n filter: instruction.filter,\n error: errorMessage,\n });\n }\n }\n }\n\n /**\n * Formats a sync error with detailed context.\n *\n * @param instruction - The failed instruction\n * @param error - The error that occurred\n * @returns Formatted error message\n */\n private formatSyncError(instruction: SyncInstruction, error: unknown): string {\n const baseMessage = error instanceof Error ? error.message : String(error);\n const chain = SyncContextManager.formatChain(instruction.chain);\n\n return [\n `Sync failed at depth ${instruction.depth}:`,\n `Chain: ${chain} → ${instruction.targetModel}`,\n `Source: ${instruction.sourceModel}#${instruction.sourceId}`,\n `Target: ${instruction.targetTable}`,\n `Error: ${baseMessage}`,\n ].join(\" | \");\n }\n\n /**\n * Groups instructions by depth for batch processing.\n *\n * @param instructions - Instructions to group\n * @returns Map of depth to instructions (sorted ascending)\n */\n private groupByDepth(instructions: SyncInstruction[]): Map<number, SyncInstruction[]> {\n const grouped = new Map<number, SyncInstruction[]>();\n\n for (const instruction of instructions) {\n const depth = instruction.depth;\n if (!grouped.has(depth)) {\n grouped.set(depth, []);\n }\n grouped.get(depth)!.push(instruction);\n }\n\n // Sort by depth (ascending) for sequential execution\n return new Map([...grouped.entries()].sort((a, b) => a[0] - b[0]));\n }\n\n /**\n * Groups instructions by target table for batch optimization.\n *\n * @param instructions - Instructions to group\n * @returns Map of table name to instructions\n */\n private groupByTable(instructions: SyncInstruction[]): Map<string, SyncInstruction[]> {\n const grouped = new Map<string, SyncInstruction[]>();\n\n for (const instruction of instructions) {\n const table = instruction.targetTable;\n if (!grouped.has(table)) {\n grouped.set(table, []);\n }\n grouped.get(table)!.push(instruction);\n }\n\n return grouped;\n }\n\n /**\n * Checks if sync should proceed based on watched fields.\n *\n * @param config - Sync configuration\n * @param changedFields - Fields that changed\n * @returns True if sync should proceed\n */\n private shouldSync(config: SyncConfig, changedFields: string[]): boolean {\n if (config.watchFields.length === 0) {\n return true; // Watch all fields\n }\n\n return config.watchFields.some((field) => changedFields.includes(field));\n }\n\n /**\n * Gets embedded data from the source model.\n *\n * @param data - Source model data or Model instance\n * @param config - Sync configuration\n * @returns Embedded data\n */\n private async getEmbedData(\n data: Record<string, unknown> | Model,\n config: SyncConfig,\n ): Promise<Record<string, unknown>> {\n // If data is a Model instance, call the embed method on it\n if (data instanceof Model) {\n if (Array.isArray(config.embedKey)) {\n return data.only(config.embedKey);\n }\n\n if (typeof data[config.embedKey as keyof Model] !== \"function\") {\n return data[config.embedKey as keyof Model];\n }\n // Fallback: use embedData() if available\n if (typeof data.embedData === \"function\") {\n return data.embedData;\n }\n // Last resort: return model data\n return data.data;\n }\n\n // Otherwise, return the data as-is\n return data as Record<string, unknown>;\n }\n\n /**\n * Gets sync configurations from the source model.\n *\n * @returns Array of sync configurations\n */\n private getSyncConfigs(): SyncConfig[] {\n const syncWith = (this.sourceModel as any).syncWith;\n\n if (!syncWith || !Array.isArray(syncWith)) {\n return [];\n }\n\n return syncWith.map((builder: any) =>\n typeof builder.build === \"function\" ? builder.build() : builder,\n );\n }\n\n /**\n * Gets sync configurations for a specific model.\n *\n * @param modelClass - The model class\n * @returns Array of sync configurations\n */\n private getSyncConfigsForModel(modelClass: ChildModel<Model>): SyncConfig[] {\n const syncWith = (modelClass as any).syncWith;\n\n if (!syncWith || !Array.isArray(syncWith)) {\n return [];\n }\n\n return syncWith.map((builder: any) =>\n typeof builder.build === \"function\" ? builder.build() : builder,\n );\n }\n\n /**\n * Emits a syncing event.\n *\n * @param instruction - The sync instruction\n */\n private async emitSyncingEvent(instruction: SyncInstruction): Promise<void> {\n const payload: SyncEventPayload = {\n sourceModel: instruction.sourceModel,\n sourceId: instruction.sourceId,\n targetModel: instruction.targetModel,\n filter: instruction.filter,\n update: instruction.update,\n affectedCount: 0, // Not yet known\n depth: instruction.depth,\n chain: instruction.chain,\n };\n\n // Emit on source model\n if (typeof (this.sourceModel as any).emitSyncEvent === \"function\") {\n await (this.sourceModel as any).emitSyncEvent(\"syncing\", payload);\n }\n }\n\n /**\n * Emits a synced event.\n *\n * @param context - The sync context\n */\n private async emitSyncedEvent(context: any): Promise<void> {\n const payload: SyncEventPayload = {\n sourceModel: context.sourceModel,\n sourceId: context.sourceId,\n targetModel: context.targetModel,\n filter: context.filter,\n update: context.update,\n affectedCount: context.affectedCount,\n depth: context.currentDepth,\n chain: context.syncChain,\n };\n\n // Emit on source model\n if (typeof (this.sourceModel as any).emitSyncEvent === \"function\") {\n await (this.sourceModel as any).emitSyncEvent(\"synced\", payload);\n }\n }\n\n /**\n * Creates an empty sync result.\n *\n * @returns Empty sync result\n */\n private createEmptyResult(): SyncResult {\n return {\n success: true,\n attempted: 0,\n succeeded: 0,\n failed: 0,\n errors: [],\n depthReached: 0,\n contexts: [],\n };\n }\n}\n","/**\n * Model sync operation class.\n *\n * Manages a single sync relationship between a source and target model.\n * Subscribes to source model events and triggers sync operations when\n * the source is updated or deleted.\n *\n * @module cascade-next/sync/model-sync-operation\n */\n\nimport events, { type EventSubscription } from \"@mongez/events\";\nimport type { ChildModel, Model } from \"../model/model\";\nimport { getModelDeletedEvent, getModelUpdatedEvent } from \"./model-events\";\nimport { DEFAULT_MAX_SYNC_DEPTH } from \"./sync-context\";\nimport { SyncManager } from \"./sync-manager\";\nimport type { ModelSyncConfig, ModelSyncOperationContract } from \"./types\";\n\n/**\n * Manages a single model sync operation.\n *\n * Subscribes to source model events (updated, deleted) and triggers\n * sync operations to update embedded data in target models.\n *\n * @example\n * ```typescript\n * // Created via modelSync.sync() or Model.sync()\n * const operation = new ModelSyncOperation(Category, Product, \"category\", false);\n * operation\n * .embed(\"embedMinimal\")\n * .watchFields([\"name\", \"slug\"])\n * .unsetOnDelete();\n * ```\n */\nexport class ModelSyncOperation implements ModelSyncOperationContract {\n /**\n * Configuration for this sync operation.\n */\n private readonly config: ModelSyncConfig;\n\n /**\n * Active event subscriptions for cleanup.\n */\n private readonly subscriptions: EventSubscription[] = [];\n\n /**\n * Whether this operation is currently subscribed to events.\n */\n private isSubscribed = false;\n\n /**\n * Create a new model sync operation.\n *\n * @param sourceModel - Source model class that triggers sync\n * @param targetModel - Target model class that receives data\n * @param targetField - Field path in target model\n * @param isMany - Whether this syncs to an array field\n */\n public constructor(\n sourceModelClass: ChildModel<Model>,\n targetModelClass: ChildModel<Model>,\n targetField: string,\n isMany: boolean,\n ) {\n this.config = {\n sourceModel: sourceModelClass,\n targetModel: targetModelClass,\n targetField,\n isMany,\n embedKey: \"embedData\",\n identifierField: \"id\",\n maxSyncDepth: DEFAULT_MAX_SYNC_DEPTH,\n watchFields: [],\n unsetOnDelete: false,\n removeOnDelete: false,\n };\n\n this.subscribe();\n }\n\n // ============================================================================\n // FLUENT CONFIGURATION\n // ============================================================================\n\n /**\n * Set the embed method to call on source model.\n *\n * @param embed - getter property name (e.g., \"embedData\", \"embedMinimal\") Or Array of fields\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * Category.sync(Product, \"category\").embed(\"embedMinimal\");\n * ```\n */\n public embed(method: string | string[]): this {\n this.config.embedKey = method;\n return this;\n }\n\n /**\n * Set the identifier field for array matching.\n * Required when syncing to array fields (syncMany).\n *\n * @param field - Field name used as identifier (default: \"id\")\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * Tag.syncMany(Post, \"tags\").identifyBy(\"tagId\");\n * ```\n */\n public identifyBy(field: string): this {\n this.config.identifierField = field;\n return this;\n }\n\n /**\n * Set the maximum sync depth for chained operations.\n *\n * @param depth - Maximum depth (default: 3)\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * Category.sync(Product, \"category\").maxDepth(2);\n * ```\n */\n public maxDepth(depth: number): this {\n this.config.maxSyncDepth = depth;\n return this;\n }\n\n /**\n * Set which fields to watch for changes.\n * Sync only triggers when these fields change.\n *\n * @param fields - Array of field names to watch (empty = all)\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * Category.sync(Product, \"category\").watchFields([\"name\", \"slug\"]);\n * ```\n */\n public watchFields(fields: string[]): this {\n this.config.watchFields = fields;\n return this;\n }\n\n /**\n * Unset the target field when source is deleted.\n *\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * Category.sync(Product, \"category\").unsetOnDelete();\n * ```\n */\n public unsetOnDelete(): this {\n this.config.unsetOnDelete = true;\n return this;\n }\n\n /**\n * Delete target documents when source is deleted.\n *\n * @returns This operation for chaining\n *\n * @example\n * ```typescript\n * User.sync(Profile, \"user\").removeOnDelete();\n * ```\n */\n public removeOnDelete(): this {\n this.config.removeOnDelete = true;\n return this;\n }\n\n // ============================================================================\n // LIFECYCLE\n // ============================================================================\n\n /**\n * Subscribe to source model events.\n * Called automatically in constructor.\n */\n private subscribe(): void {\n if (this.isSubscribed) {\n return;\n }\n\n const sourceModel = this.config.sourceModel;\n\n // Subscribe to model.updated event\n this.subscriptions.push(\n events.subscribe(getModelUpdatedEvent(sourceModel), this.handleModelUpdated),\n );\n\n // Subscribe to model.deleted event\n this.subscriptions.push(\n events.subscribe(getModelDeletedEvent(sourceModel), this.handleModelDeleted),\n );\n\n this.isSubscribed = true;\n }\n\n /**\n * Unsubscribe from all events and cleanup.\n * Called automatically when using modelSync.register().\n */\n public unsubscribe(): void {\n for (const subscription of this.subscriptions) {\n subscription.unsubscribe();\n }\n\n this.subscriptions.length = 0;\n this.isSubscribed = false;\n }\n\n /**\n * Cleanup the sync operations\n */\n public $cleanup() {\n return this.unsubscribe();\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n /**\n * Handle model updated event.\n * Triggers sync to update embedded data in target models.\n */\n private handleModelUpdated = async (model: Model, changedFields: string[]): Promise<void> => {\n // Check if we should sync based on watched fields\n if (!this.shouldSync(changedFields)) {\n return;\n }\n\n try {\n const primaryKey = (this.config.sourceModel as any).primaryKey || \"id\";\n const sourceId = model.get(primaryKey) as string | number;\n\n if (!sourceId) {\n return;\n }\n\n // Get the driver from the source model's data source\n const dataSource = this.config.sourceModel.getDataSource();\n const driver = dataSource.driver;\n\n // Create sync manager and execute\n const syncManager = new SyncManager(this.config.sourceModel, driver);\n await syncManager.syncUpdateWithConfig(\n sourceId,\n model,\n changedFields,\n this.buildSyncConfig(),\n );\n } catch (error) {\n console.error(\n `[ModelSync] Failed to sync ${this.config.sourceModel.name} -> ${this.config.targetModel.name}:`,\n error,\n );\n }\n };\n\n /**\n * Handle model deleted event.\n * Triggers unset or remove based on configuration.\n */\n private handleModelDeleted = async (model: Model): Promise<void> => {\n if (!this.config.unsetOnDelete && !this.config.removeOnDelete) {\n return;\n }\n\n try {\n const primaryKey = (this.config.sourceModel as any).primaryKey || \"id\";\n const sourceId = model.get(primaryKey) as string | number;\n\n if (!sourceId) {\n return;\n }\n\n const dataSource = this.config.sourceModel.getDataSource();\n const driver = dataSource.driver;\n\n if (this.config.removeOnDelete) {\n // Delete all target documents that reference this source\n await this.removeTargetDocuments(sourceId, driver);\n } else if (this.config.unsetOnDelete) {\n // Unset the field in target documents\n const syncManager = new SyncManager(this.config.sourceModel, driver);\n await syncManager.syncDeleteWithConfig(sourceId, this.buildSyncConfig());\n }\n } catch (error) {\n console.error(\n `[ModelSync] Failed to handle delete for ${this.config.sourceModel.name}:`,\n error,\n );\n }\n };\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Check if sync should proceed based on watched fields.\n */\n private shouldSync(changedFields: string[]): boolean {\n if (this.config.watchFields.length === 0) {\n return true; // Watch all fields\n }\n\n return this.config.watchFields.some((field) => changedFields.includes(field));\n }\n\n /**\n * Build sync config compatible with SyncManager.\n */\n private buildSyncConfig(): any {\n return {\n targetField: this.config.targetField,\n isMany: this.config.isMany,\n embedKey: this.config.embedKey,\n identifierField: this.config.identifierField,\n maxSyncDepth: this.config.maxSyncDepth,\n preventCircularSync: true,\n watchFields: this.config.watchFields,\n unsetOnDelete: this.config.unsetOnDelete,\n targetModelClass: this.config.targetModel,\n };\n }\n\n /**\n * Remove target documents that reference the deleted source.\n */\n private async removeTargetDocuments(sourceId: string | number, driver: any): Promise<void> {\n const filter = this.config.isMany\n ? { [`${this.config.targetField}.${this.config.identifierField}`]: sourceId }\n : { [`${this.config.targetField}.${this.config.identifierField}`]: sourceId };\n\n await driver.deleteMany(this.config.targetModel.table, filter);\n }\n\n /**\n * Get the current configuration (for debugging/testing).\n */\n public getConfig(): Readonly<ModelSyncConfig> {\n return { ...this.config };\n }\n}\n","/**\n * ModelSync facade for registering sync operations.\n *\n * Provides a clean API for defining sync relationships between models\n * with automatic cleanup support for HMR (Hot Module Replacement).\n *\n * @module cascade-next/sync/model-sync\n */\n\nimport type { ChildModel, Model } from \"../model/model\";\nimport { ModelSyncOperation } from \"./model-sync-operation\";\nimport type { ModelSyncContract, ModelSyncOperationContract } from \"./types\";\n\n/**\n * ModelSync facade implementation.\n *\n * Manages sync operation registration with scoped cleanup support.\n * Uses a registration stack to track operations created during\n * a `register()` callback for proper HMR cleanup.\n *\n * @example\n * ```typescript\n * // In events file\n * export const cleanup = modelSync.register(() => {\n * Category.sync(Product, \"category\");\n * Tag.syncMany(Post, \"tags\").identifyBy(\"id\");\n * });\n * ```\n */\nclass ModelSyncFacade implements ModelSyncContract {\n /**\n * All active sync operations.\n */\n private readonly operations: ModelSyncOperation[] = [];\n\n /**\n * Stack for tracking operations during register() callbacks.\n * Each element is an array of operations created in that scope.\n */\n private readonly registrationStack: ModelSyncOperation[][] = [];\n\n // ============================================================================\n // PUBLIC API\n // ============================================================================\n\n /**\n * Create a sync operation for a single embedded document.\n *\n * When the source model is updated, the target model's field\n * will be updated with the embedded data.\n *\n * @param source - Source model class that triggers sync\n * @param target - Target model class that receives data\n * @param field - Field path in target model\n * @returns Sync operation for chaining configuration\n *\n * @example\n * ```typescript\n * // When Category updates, update Product.category\n * modelSync.sync(Category, Product, \"category\");\n *\n * // With configuration\n * modelSync.sync(Category, Product, \"category\")\n * .embed(\"embedMinimal\")\n * .watchFields([\"name\", \"slug\"]);\n * ```\n */\n public sync(\n source: ChildModel<Model>,\n target: ChildModel<Model>,\n field: string,\n ): ModelSyncOperationContract {\n const operation = new ModelSyncOperation(source, target, field, false);\n this.trackOperation(operation);\n return operation;\n }\n\n /**\n * Create a sync operation for an array of embedded documents.\n *\n * When the source model is updated, the corresponding element\n * in the target model's array field will be updated.\n *\n * @param source - Source model class that triggers sync\n * @param target - Target model class that receives data\n * @param field - Array field path in target model\n * @returns Sync operation for chaining configuration\n *\n * @example\n * ```typescript\n * // When Tag updates, update Post.tags[i] where tags[i].id matches\n * modelSync.syncMany(Tag, Post, \"tags\").identifyBy(\"id\");\n * ```\n */\n public syncMany(\n source: ChildModel<Model>,\n target: ChildModel<Model>,\n field: string,\n ): ModelSyncOperationContract {\n const operation = new ModelSyncOperation(source, target, field, true);\n this.trackOperation(operation);\n return operation;\n }\n\n /**\n * Register sync operations with automatic cleanup.\n *\n * Executes the callback function which should contain sync registrations.\n * Returns a cleanup function that unsubscribes all operations created\n * during the callback - perfect for HMR module cleanup.\n *\n * @param callback - Function that registers sync operations\n * @returns Cleanup function that unsubscribes all registered operations\n *\n * @example\n * ```typescript\n * // In src/app/blog/events/sync.ts\n * export const cleanup = modelSync.register(() => {\n * Category.sync(Product, \"category\");\n * Tag.syncMany(Post, \"tags\").identifyBy(\"id\");\n * Author.sync(Article, \"author\").unsetOnDelete();\n * });\n * ```\n */\n public register(callback: () => void): () => void {\n // Create a new scope for tracking operations\n const scopedOperations: ModelSyncOperation[] = [];\n this.registrationStack.push(scopedOperations);\n\n try {\n // Execute callback - operations are tracked via trackOperation()\n callback();\n } finally {\n // Remove the scope from stack\n this.registrationStack.pop();\n }\n\n // Return cleanup function for just these scoped operations\n return () => {\n for (const operation of scopedOperations) {\n operation.unsubscribe();\n\n // Remove from global operations array\n const index = this.operations.indexOf(operation);\n if (index !== -1) {\n this.operations.splice(index, 1);\n }\n }\n };\n }\n\n /**\n * Clear all registered sync operations.\n * Useful for testing or complete reset.\n */\n public clear(): void {\n for (const operation of this.operations) {\n operation.unsubscribe();\n }\n this.operations.length = 0;\n }\n\n /**\n * Get count of active sync operations.\n * Useful for debugging and testing.\n */\n public get count(): number {\n return this.operations.length;\n }\n\n // ============================================================================\n // PRIVATE HELPERS\n // ============================================================================\n\n /**\n * Track a new operation in global list and current registration scope.\n */\n private trackOperation(operation: ModelSyncOperation): void {\n // Always add to global operations\n this.operations.push(operation);\n\n // If inside a register() callback, also track in the current scope\n const currentScope = this.registrationStack[this.registrationStack.length - 1];\n if (currentScope) {\n currentScope.push(operation);\n }\n }\n}\n\n/**\n * Global modelSync facade instance.\n *\n * Use this to register sync operations between models.\n *\n * @example\n * ```typescript\n * import { modelSync } from \"@warlock.js/cascade\";\n *\n * export const cleanup = modelSync.register(() => {\n * Category.sync(Product, \"category\");\n * });\n * ```\n */\nexport const modelSync = new ModelSyncFacade();\n","import { colors } from \"@mongez/copper\";\nimport type { ValidationResult } from \"@warlock.js/seal\";\n\n/**\n * Error thrown when model validation fails during database write operations.\n *\n * Contains detailed information about all validation errors,\n * including field paths, error messages, and validation rules that failed.\n *\n * @example\n * ```typescript\n * try {\n * const user = new User({ name: \"\", age: -5 });\n * await user.save();\n * } catch (error) {\n * if (error instanceof DatabaseWriterValidationError) {\n * console.log(error.message); // \"Validation failed\"\n * console.log(error.errors);\n * // [\n * // { path: \"name\", error: \"name is required\", rule: \"required\" },\n * // { path: \"age\", error: \"age must be at least 0\", rule: \"min\" }\n * // ]\n * }\n * }\n * ```\n */\nexport class DatabaseWriterValidationError extends Error {\n /**\n * Array of validation errors from @warlock.js/seal.\n *\n * Each error contains:\n * - `path`: Dot-notation path to the field (e.g., \"address.city\")\n * - `error`: Human-readable error message\n * - `rule`: The validation rule that failed (e.g., \"required\", \"email\")\n * - Additional context depending on the rule\n */\n public readonly errors: ValidationResult[\"errors\"];\n\n /**\n * Create a new DatabaseWriterValidationError.\n *\n * @param message - Error message (typically \"Validation failed\")\n * @param errors - Array of validation errors from seal\n *\n * @example\n * ```typescript\n * const error = new DatabaseWriterValidationError(\"Validation failed\", [\n * { path: \"email\", error: \"email must be valid\", rule: \"email\" }\n * ]);\n * ```\n */\n public constructor(message: string, errors: ValidationResult[\"errors\"]) {\n super(message);\n this.name = \"DatabaseWriterValidationError\";\n this.errors = errors;\n\n // Maintain proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, DatabaseWriterValidationError);\n }\n\n // Override Node.js inspect to use our formatted output\n Object.defineProperty(this, \"inspect\", {\n value: () => this.toString(),\n enumerable: false,\n });\n }\n\n /**\n * Custom inspect method for Node.js console output.\n * This makes console.log and error logging use our beautiful format.\n */\n [Symbol.for(\"nodejs.util.inspect.custom\")](): string {\n return this.toString();\n }\n\n /**\n * Get a formatted string representation of all validation errors.\n *\n * Provides beautiful, colored terminal output with clear field-by-field breakdown.\n *\n * @returns Multi-line string with all errors, formatted for terminal\n *\n * @example\n * ```typescript\n * console.log(error.toString());\n * // ❌ Validation Error: UserModel\n * //\n * // Field: email\n * // Error: Email already exists\n * // Value: \"john@example.com\"\n * ```\n */\n public toString(): string {\n // Extract model name from message (e.g., \"[UserModel Model]\")\n const modelMatch = this.message.match(/\\[(\\w+)\\s+Model\\]/);\n const modelName = modelMatch ? modelMatch[1] : \"Model\";\n const operation = this.message.includes(\"Insert\") ? \"Insert\" : \"Update\";\n\n // Build header\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(colors.red(`❌ Validation Error: ${modelName} (${operation})`));\n lines.push(\"\");\n\n // Group errors by field for better readability\n const errorsByField = new Map<string, Array<{ error: string; type?: string; value?: any }>>();\n\n for (const err of this.errors) {\n const fieldName = err.input || \"unknown\";\n if (!errorsByField.has(fieldName)) {\n errorsByField.set(fieldName, []);\n }\n errorsByField.get(fieldName)!.push({\n error: err.error,\n type: err.type,\n value: (err as any).value,\n });\n }\n\n // Format each field's errors\n for (const [fieldName, fieldErrors] of errorsByField) {\n lines.push(colors.yellow(` Field: ${fieldName}`));\n\n for (const fieldError of fieldErrors) {\n lines.push(colors.white(` Error: ${fieldError.error}`));\n\n if (fieldError.value !== undefined) {\n const valueStr =\n typeof fieldError.value === \"string\"\n ? `\"${fieldError.value}\"`\n : JSON.stringify(fieldError.value);\n lines.push(colors.gray(` Value: ${valueStr}`));\n }\n\n if (fieldError.type) {\n lines.push(colors.cyan(` Type: ${fieldError.type}`));\n }\n }\n\n lines.push(\"\"); // Blank line between fields\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Get validation errors for a specific field.\n *\n * @param fieldPath - Dot-notation path to the field\n * @returns Array of errors for that field\n *\n * @example\n * ```typescript\n * const emailErrors = error.getFieldErrors(\"email\");\n * console.log(emailErrors);\n * // [{ path: \"email\", error: \"email must be valid\", rule: \"email\" }]\n * ```\n */\n public getFieldErrors(fieldPath: string): ValidationResult[\"errors\"] {\n return this.errors.filter((err) => err.input === fieldPath);\n }\n\n /**\n * Check if a specific field has validation errors.\n *\n * @param fieldPath - Dot-notation path to the field\n * @returns True if the field has errors\n *\n * @example\n * ```typescript\n * if (error.hasFieldError(\"email\")) {\n * console.log(\"Email is invalid\");\n * }\n * ```\n */\n public hasFieldError(fieldPath: string): boolean {\n return this.errors.some((err) => err.input === fieldPath);\n }\n}\n","import type { ChildModel, Model } from \"./model\";\n\n/**\n * Options for the RegisterModel decorator\n */\nexport type RegisterModelOptions = {\n /**\n * Custom name for the model in the global registry.\n * If not provided, uses the class name.\n *\n * @example\n * ```typescript\n * @RegisterModel({ name: \"CustomUser\" })\n * export class User extends Model {}\n * ```\n */\n name?: string;\n};\n\n/**\n * Global model registry that maps model class names to their constructors.\n * This allows for string-based model references to avoid circular dependencies.\n */\nconst modelsRegistry = new Map<string, ChildModel<Model>>();\n\n/**\n * Class decorator that registers a model in the global registry.\n *\n * This is an opt-in mechanism that allows models to be referenced by string name\n * instead of direct class imports, helping avoid circular dependencies.\n *\n * @param options - Optional configuration for registration\n *\n * @example\n * ```typescript\n * // Auto-capture class name\n * @RegisterModel()\n * export class User extends Model {\n * static table = \"users\";\n * }\n *\n * // Custom name\n * @RegisterModel({ name: \"UserModel\" })\n * export class User extends Model {\n * static table = \"users\";\n * }\n *\n * // Later, retrieve by name:\n * const UserModel = Model.getModel(\"User\");\n * ```\n */\nexport function RegisterModel(options?: RegisterModelOptions) {\n return function <T extends ChildModel<Model>>(target: T): T {\n const modelName = options?.name || target.name;\n\n if (!modelName) {\n throw new Error(\n \"@RegisterModel decorator: Unable to determine model name. \" +\n \"Please provide a name in options or ensure your class has a name.\",\n );\n }\n\n if (modelsRegistry.has(modelName)) {\n console.warn(\n `⚠️ Model \"${modelName}\" is already registered. ` +\n `This will overwrite the previous registration.`,\n );\n }\n\n modelsRegistry.set(modelName, target);\n\n return target;\n };\n}\n\nexport function registerModelInRegistry(name: string, model: ChildModel<Model>) {\n modelsRegistry.set(name, model);\n}\n\n/**\n * Get a model class by its name from the global registry.\n *\n * @param name - The model class name\n * @returns The model class or undefined if not found\n *\n * @example\n * ```typescript\n * const UserModel = getModelFromRegistry(\"User\");\n * if (UserModel) {\n * const user = await UserModel.find(1);\n * }\n * ```\n */\nexport function getModelFromRegistry(name: string) {\n return modelsRegistry.get(name);\n}\n\n/**\n * Get all registered models from the global registry.\n *\n * @returns A Map of all registered model classes by name\n *\n * @example\n * ```typescript\n * const allModels = getAllModelsFromRegistry();\n * for (const [name, ModelClass] of allModels) {\n * console.log(`Found model: ${name}`);\n * }\n * ```\n */\nexport function getAllModelsFromRegistry() {\n return new Map(modelsRegistry);\n}\n\n/**\n * Clean up all models from register\n */\nexport function cleanupModelsRegistery() {\n modelsRegistry.clear();\n}\n\nexport function removeModelFromRegistery(name: string) {\n modelsRegistry.delete(name);\n}\n","import type { Mutator } from \"@warlock.js/seal\";\nimport { ChildModel, Model } from \"../../model/model\";\nimport { getModelFromRegistry } from \"../../model/register-model\";\n\ntype DatabaseModelMutatorOptions = {\n model: ChildModel<any> | string;\n};\n\nexport const databaseModelMutator: Mutator<DatabaseModelMutatorOptions> = async (\n value,\n context,\n) => {\n let { model: ModelClass } = context.options;\n\n if (typeof ModelClass === \"string\") {\n ModelClass = getModelFromRegistry(ModelClass)!;\n }\n\n if (!ModelClass) {\n throw new Error(`Model ${ModelClass} not found in registry`);\n }\n\n if (value instanceof Model) return value;\n\n if (typeof value === \"object\" && value?.id) {\n value = Number(value.id);\n }\n\n if (typeof value !== \"number\") return value;\n\n return await ModelClass.find(value);\n};\n\nexport const databaseModelsMutator: Mutator<DatabaseModelMutatorOptions> = async (\n value,\n context,\n) => {\n if (!Array.isArray(value)) return value;\n\n let { model: ModelClass } = context.options;\n\n if (typeof ModelClass === \"string\") {\n ModelClass = getModelFromRegistry(ModelClass)!;\n }\n\n if (!ModelClass) {\n throw new Error(`Model ${ModelClass} not found in registry`);\n }\n\n // first, if all values are list of models, then return them.\n if (value.every((item) => item instanceof Model)) return value;\n\n const ids = value.map((item) => item?.id || item).filter((item) => item !== undefined);\n\n return await ModelClass.query().whereIn(\"id\", ids).get();\n};\n","import { invalidRule, VALID_RULE, type SchemaRule } from \"@warlock.js/seal\";\nimport { ChildModel, Model } from \"./../../model/model\";\nimport { getModelFromRegistry } from \"./../../model/register-model\";\n\nexport const databaseModelRule: SchemaRule = {\n name: \"databaseModule\",\n defaultErrorMessage: \"The :input must be a valid :model model\",\n async validate(value, context) {\n if (value instanceof Model === false) {\n this.context.attributesList.model = this.context.options.model.name;\n return invalidRule(this, context);\n }\n\n return VALID_RULE;\n },\n};\n\nexport const databaseModelsRule: SchemaRule<{ model: ChildModel<any> | string }> = {\n name: \"databaseModels\",\n defaultErrorMessage: \"The :input must be a list of valid :model\",\n async validate(value, context) {\n let { model } = this.context.options;\n if (typeof model === \"string\") {\n model = getModelFromRegistry(model)!;\n }\n\n this.context.attributesList.model = model.name;\n\n if (!Array.isArray(value)) return invalidRule(this, context);\n\n if (value.every((item) => item instanceof Model)) return VALID_RULE;\n\n return invalidRule(this, context);\n },\n};\n","import { type TransformerCallback } from \"@warlock.js/seal\";\nimport { Model } from \"../../model/model\";\n\nexport const databaseModelTransformer: TransformerCallback = (value, context) => {\n const embed = context.options.embed ?? \"embedData\";\n\n if (value instanceof Model === false && !Array.isArray(value)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => {\n if (typeof embed === \"string\") {\n return item[embed];\n }\n\n return item.only(embed);\n });\n }\n\n if (typeof embed === \"string\") {\n return (value as any)[embed];\n }\n\n return value.only(embed);\n};\n","import { arrayRule, BaseValidator } from \"@warlock.js/seal\";\nimport { Model, type ChildModel } from \"../../model/model\";\nimport { databaseModelMutator, databaseModelsMutator } from \"../mutators/embed-mutator\";\nimport { databaseModelRule, databaseModelsRule } from \"../rules/database-model-rule\";\nimport { databaseModelTransformer } from \"../transformers/embed-model-transformer\";\n\nexport class EmbedModelValidator extends BaseValidator {\n /**\n * Check if value is a string type\n */\n public matchesType(value: any): boolean {\n return (\n value instanceof Model ||\n typeof value === \"number\" ||\n (Array.isArray(value) && value.every((item) => item instanceof Model))\n );\n }\n\n /**\n * Mutate the value to be a model, also fail if the mutated value is not a valid model\n */\n public model(model: ChildModel<any> | string) {\n this.addMutator(databaseModelMutator, {\n model,\n });\n\n const rule = this.addRule(databaseModelRule);\n\n rule.context.options.model = model;\n\n return this;\n }\n\n /**\n * Validate the value is a list of models\n */\n public models(model: ChildModel<any> | string) {\n this.addMutator(databaseModelsMutator, {\n model,\n });\n\n this.addRule(arrayRule);\n const rule = this.addRule(databaseModelsRule);\n\n rule.context.options.model = model;\n\n return this;\n }\n\n /**\n * Determine how the data will be stored as an embedded document\n */\n public embed(embed?: string | string[]) {\n this.addTransformer(databaseModelTransformer, {\n embed,\n });\n\n return this;\n }\n}\n","/**\n * File Validator Plugin\n *\n * Adds file validation to Seal v factory\n */\n\nimport type { SealPlugin } from \"@warlock.js/seal\";\nimport { v } from \"@warlock.js/seal\";\nimport type { ChildModel } from \"../../model/model\";\nimport { EmbedModelValidator } from \"../validators/embed-validator\";\n\ntype EmbedOptions = {\n errorMessage?: string;\n embed?: string | string[];\n};\n\ndeclare module \"@warlock.js/seal\" {\n interface ValidatorV {\n embed(model: ChildModel<any> | string, options?: EmbedOptions): EmbedModelValidator;\n embedMany(model: ChildModel<any> | string, options?: EmbedOptions): EmbedModelValidator;\n }\n}\n\n/**\n * File validation plugin for Seal\n */\nexport const embedValidator: SealPlugin = {\n name: \"embed\",\n version: \"1.0.0\",\n description: \"Adds file upload validation (v.file())\",\n\n install() {\n // Inject file() method into v factory\n v.embed = (model: ChildModel<any> | string, options?: EmbedOptions) =>\n new EmbedModelValidator().model(model).embed(options?.embed);\n v.embedMany = (model: ChildModel<any> | string, options?: EmbedOptions) =>\n new EmbedModelValidator().models(model).embed(options?.embed);\n },\n};\n","import { registerPlugin } from \"@warlock.js/seal\";\nimport { embedValidator } from \"./plugins/embed-validator-plugin\";\n\n// We need to introduce new validators\n// 1. v.embed(model: typeof Model, options: EmbedOptions)\n// 2. v.embedMany(model: typeof Model, options: EmbedManyOptions)\n\nregisterPlugin(embedValidator);\n","import events from \"@mongez/events\";\nimport { getSealConfig, v, type ObjectValidator } from \"@warlock.js/seal\";\nimport type {\n DriverContract,\n InsertResult,\n UpdateOperations,\n UpdateResult,\n} from \"../contracts/database-driver.contract\";\nimport type {\n WriterContract,\n WriterOptions,\n WriterResult,\n} from \"../contracts/database-writer.contract\";\nimport type { ChildModel, Model } from \"../model/model\";\nimport { getModelUpdatedEvent } from \"../sync/model-events\";\nimport type { StrictMode } from \"../types\";\nimport { DatabaseWriterValidationError } from \"../validation\";\nimport type { DataSource } from \"./../data-source/data-source\";\n\n/**\n * Database writer service that orchestrates model persistence.\n *\n * Handles the complete save pipeline:\n * 1. Check for changes (skip if no changes and not new)\n * 2. Emit `saving` event (for data enrichment)\n * 3. Emit `validating` event\n * 4. Validate and cast data via @warlock.js/seal schema\n * 5. Emit `validated` event\n * 6. Generate ID (for new NoSQL records)\n * 7. Emit `creating`/`updating` events\n * 8. Execute insert or update via driver\n * 9. Merge returned data into model\n * 10. Reset dirty tracker and update `isNew` flag\n * 11. Emit `saved` and `created`/`updated` events\n *\n * @example\n * ```typescript\n * const user = new User({ name: \"Alice\", email: \"alice@example.com\" });\n * const writer = new DatabaseWriter(user);\n * await writer.save();\n *\n * console.log(user.get(\"id\")); // 1 (auto-generated)\n * console.log(user.get(\"_id\")); // ObjectId(\"...\")\n *\n * // Update existing record\n * user.set(\"name\", \"Alice Smith\");\n * await writer.save();\n * // Only updates the \"name\" field (partial update)\n *\n * // Silent save (no events)\n * await writer.save({ skipEvents: true });\n * ```\n */\nexport class DatabaseWriter implements WriterContract {\n /** The model instance being persisted */\n private readonly model: Model;\n\n /** Model constructor reference */\n private readonly ctor: ChildModel<Model>;\n\n /** Data source containing driver and ID generator */\n private readonly dataSource: DataSource;\n\n /** Database driver for executing queries */\n private readonly driver: DriverContract;\n\n /** Table/collection name */\n private readonly table: string;\n\n /** Primary key field name */\n private readonly primaryKey: string;\n\n /** Validation schema (if defined) */\n private readonly schema?: ObjectValidator;\n\n /** Strict mode configuration */\n private readonly strictMode: StrictMode;\n\n /**\n * Create a new writer instance for a model.\n *\n * @param model - The model instance to persist\n *\n * @example\n * ```typescript\n * const user = new User({ name: \"Alice\" });\n * const writer = new DatabaseWriter(user);\n * await writer.save();\n * ```\n */\n public constructor(model: Model) {\n this.model = model;\n this.ctor = model.constructor as ChildModel<Model>;\n this.dataSource = this.ctor.getDataSource();\n this.driver = this.dataSource.driver;\n this.table = this.ctor.table;\n this.primaryKey = this.ctor.primaryKey;\n this.schema = this.ctor.schema;\n this.strictMode = this.ctor.strictMode;\n }\n\n /**\n * Save the model instance to the database.\n *\n * @param options - Save options\n * @returns Result with success status, document, and metadata\n * @throws {ValidationError} If validation fails\n */\n public async save(options: WriterOptions = {}): Promise<WriterResult> {\n const isInsert = this.model.isNew;\n\n // 1. Check if model has changes (skip if no changes and not new)\n if (!isInsert && !this.model.hasChanges()) {\n return {\n success: true,\n document: this.model.data,\n isNew: false,\n modifiedCount: 0,\n };\n }\n\n // 2. Emit saving event (before validation for data enrichment)\n if (!options.skipEvents) {\n await this.model.emitEvent(\"saving\", {\n isInsert,\n options,\n mode: isInsert ? \"insert\" : \"update\",\n });\n }\n\n // 3. Validate and cast data\n await this.validateAndCast(isInsert, options);\n\n // 4. Execute insert or update\n let result: InsertResult | UpdateResult;\n\n if (isInsert) {\n result = await this.performInsert(options);\n } else {\n result = await this.performUpdate(options);\n }\n\n // 5. Reset dirty tracker and update isNew flag\n const changedFields = isInsert ? [] : this.model.getDirtyColumns();\n this.model.dirtyTracker.reset();\n this.model.isNew = false;\n\n // 6. Emit post-save events\n if (!options.skipEvents) {\n await this.model.emitEvent(\"saved\");\n await this.model.emitEvent(isInsert ? \"created\" : \"updated\");\n }\n\n // 7. Trigger sync operations (fire-and-forget, non-blocking)\n if (!options.skipSync && !isInsert) {\n void this.triggerSync(changedFields);\n }\n\n return {\n success: true,\n document: this.model.data,\n isNew: isInsert,\n modifiedCount: isInsert ? undefined : (result as UpdateResult).modifiedCount,\n };\n }\n\n /**\n * Validate and cast model data using the schema.\n *\n * Updates the model's data in-place with validated/casted values.\n *\n * @param isInsert - Whether this is an insert operation\n * @param options - Save options\n * @throws {ValidationError} If validation fails\n * @private\n */\n private async validateAndCast(isInsert: boolean, options: WriterOptions): Promise<void> {\n // Emit validating event\n if (!options.skipEvents) {\n await this.model.emitEvent(\"validating\", {\n isInsert,\n options,\n mode: isInsert ? \"insert\" : \"update\",\n });\n }\n\n // Skip validation if requested or no schema defined\n if (options.skipValidation || !this.schema) {\n return;\n }\n\n // Clone schema for partial data (updates only)\n const validationSchema = isInsert\n ? this.schema.clone()\n : this.schema.clone(Object.keys(this.model.data)).extend({\n id: v.int(),\n _id: v.any(),\n createdAt: v.date(),\n updatedAt: v.date(),\n });\n\n // Apply strict mode\n if (this.strictMode === \"strip\") {\n validationSchema.stripUnknown();\n } else if (this.strictMode === \"fail\") {\n validationSchema.allowUnknown(false);\n } else if (this.strictMode === \"allow\") {\n validationSchema.allowUnknown(true);\n }\n\n // Run validation\n const result = await v.validate(validationSchema, this.model.data, {\n context: {\n model: this.model,\n },\n ...getSealConfig(),\n });\n\n if (!result.isValid) {\n const error = new DatabaseWriterValidationError(\n `[${this.model.constructor.name} Model] ${isInsert ? \"Insert\" : \"Update\"} Validation failed`,\n result.errors,\n );\n if (!options.skipEvents) {\n await this.model.emitEvent(\"validated\", { result, error });\n }\n throw error;\n }\n\n // Update model data with validated/casted data\n this.model.replaceData(result.data);\n\n // Emit validated event\n if (!options.skipEvents) {\n await this.model.emitEvent(\"validated\", { result });\n }\n }\n\n /**\n * Perform an insert operation.\n *\n * @param options - Save options\n * @returns Insert result\n * @private\n */\n private async performInsert(options: WriterOptions): Promise<InsertResult> {\n // Generate ID if needed (NoSQL only)\n await this.generateIdIfNeeded();\n\n // Get data to insert (already validated and casted)\n const dataToInsert = this.model.data;\n\n // add createdAt and updatedAt to the data\n const createdAtColumn = this.ctor.createdAtColumn ?? \"createdAt\";\n if (createdAtColumn) {\n dataToInsert[createdAtColumn] = new Date();\n }\n\n const updatedAtColumn = this.ctor.updatedAtColumn ?? \"updatedAt\";\n if (updatedAtColumn) {\n dataToInsert[updatedAtColumn] = new Date();\n }\n\n // Emit creating event\n if (!options.skipEvents) {\n await this.model.emitEvent(\"creating\");\n }\n\n // INSERT: use full validated data\n const result = await this.driver.insert(this.table, dataToInsert);\n\n // Merge returned data (e.g., generated _id, timestamps)\n // Note: We use merge here because the result might not include all fields\n // (e.g., our generated 'id' field), and we don't want to lose them\n this.model.merge(result.document as Record<string, unknown>);\n\n // Reset dirty tracker immediately after merge to prevent\n // database-generated fields (like _id) from being marked as dirty\n this.model.dirtyTracker.reset();\n\n return result;\n }\n\n /**\n * Perform an update operation.\n *\n * @param options - Save options\n * @returns Update result\n * @private\n */\n private async performUpdate(options: WriterOptions): Promise<UpdateResult> {\n // Emit updating event\n if (!options.skipEvents) {\n await this.model.emitEvent(\"updating\");\n }\n\n if (this.ctor.updatedAtColumn !== false) {\n this.model.set(this.ctor.updatedAtColumn ?? \"updatedAt\", new Date());\n }\n\n if (options.replace) {\n const document = await this.driver.replace(\n this.table,\n {\n [this.primaryKey]: this.model.get(this.primaryKey),\n },\n this.model.data,\n );\n\n if (document) {\n this.model.replaceData(document as Record<string, unknown>);\n }\n\n return { modifiedCount: document ? 1 : 0 };\n }\n\n // Build operations from dirty tracker\n const operations = this.buildUpdateOperations();\n\n // Build filter using primary key\n const filter = { [this.primaryKey]: this.model.get(this.primaryKey) };\n\n // Execute update with operations\n return await this.driver.update(this.table, filter, operations);\n }\n\n /**\n * Generate ID for the model if auto-generation is enabled.\n *\n * @private\n */\n private async generateIdIfNeeded(): Promise<void> {\n if (!this.ctor.autoGenerateId || this.model.get(\"id\")) {\n return;\n }\n\n const idGenerator = this.dataSource.idGenerator;\n if (!idGenerator) {\n return;\n }\n\n // Resolve ID generation options from model configuration\n const initialId = this.resolveInitialId();\n\n const incrementIdBy = this.resolveIncrementBy();\n\n const id = await idGenerator.generateNextId({\n table: this.table,\n initialId,\n incrementIdBy,\n });\n\n this.model.set(\"id\", id);\n }\n\n /**\n * Build update operations from the model's dirty tracker.\n *\n * Handles both modified fields ($set) and removed fields ($unset).\n *\n * @returns Update operations for the driver\n * @private\n *\n * @example\n * ```typescript\n * // Model with changes\n * user.set(\"name\", \"Alice\");\n * user.unset(\"tempField\");\n *\n * const operations = this.buildUpdateOperations();\n * // {\n * // $set: { name: \"Alice\" },\n * // $unset: { tempField: 1 }\n * // }\n * ```\n */\n private buildUpdateOperations(): UpdateOperations {\n const operations: UpdateOperations = {};\n\n // Get dirty columns (modified fields)\n const dirtyColumns = this.model.getDirtyColumns();\n\n if (dirtyColumns.length > 0) {\n operations.$set = {};\n for (const column of dirtyColumns) {\n const value = this.model.get(column);\n if (value === undefined) continue;\n\n operations.$set[column] = this.model.get(column);\n }\n }\n\n // Get removed columns\n const removedColumns = this.model.getRemovedColumns();\n if (removedColumns.length > 0) {\n operations.$unset = {};\n for (const column of removedColumns) {\n operations.$unset[column] = 1;\n }\n }\n\n return operations;\n }\n\n /**\n * Resolve the initial ID from model configuration.\n *\n * Priority:\n * 1. Model.initialId (explicit value)\n * 2. Model.randomInitialId (random or function)\n * 3. Default: 1\n *\n * @returns The initial ID value\n * @private\n */\n private resolveInitialId(): number {\n if (this.ctor.initialId) {\n return this.ctor.initialId;\n }\n\n if (this.ctor.randomInitialId) {\n return typeof this.ctor.randomInitialId === \"function\"\n ? this.ctor.randomInitialId()\n : this.randomInt(10000, 499999);\n }\n\n return 1; // Default initial ID\n }\n\n /**\n * Resolve the increment value from model configuration.\n *\n * Priority:\n * 1. Model.incrementIdBy (explicit value)\n * 2. Model.randomIncrement (random or function)\n * 3. Default: 1\n *\n * @returns The increment value\n * @private\n */\n private resolveIncrementBy(): number {\n if (this.ctor.incrementIdBy) {\n return this.ctor.incrementIdBy;\n }\n\n if (this.ctor.randomIncrement) {\n return typeof this.ctor.randomIncrement === \"function\"\n ? this.ctor.randomIncrement()\n : this.randomInt(1, 10);\n }\n\n return 1; // Default increment\n }\n\n /**\n * Generate a random integer between min and max (inclusive).\n *\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random integer\n * @private\n */\n private randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n }\n\n /**\n * Trigger sync operations after successful save.\n * Only syncs on updates (not creates) unless sync config specifies embedOnCreate.\n *\n * @param changedFields - Fields that were changed (for filtering)\n * @private\n */\n /**\n * Trigger sync operations after successful save.\n *\n * Emits a model.updated event that ModelSyncOperation listens to.\n * The sync is handled by registered sync operations, not directly here.\n *\n * @param changedFields - Fields that were changed (for filtering)\n * @private\n */\n private async triggerSync(changedFields: string[]): Promise<void> {\n // Emit model.updated event - ModelSyncOperation listens to these\n await events.triggerAll(getModelUpdatedEvent(this.ctor), this.model, changedFields);\n }\n}\n","import { get, merge, only, set, unset } from \"@mongez/reinforcements\";\nimport type { ObjectValidator } from \"@warlock.js/seal\";\nimport type { RemoverResult, WriterOptions } from \"../contracts\";\nimport { QueryBuilderContract, WhereCallback, WhereObject, WhereOperator } from \"../contracts\";\nimport type { DataSource } from \"../data-source/data-source\";\nimport { dataSourceRegistry } from \"../data-source/data-source-registry\";\nimport { DatabaseDirtyTracker } from \"../database-dirty-tracker\";\nimport type { ModelEventListener, ModelEventName } from \"../events/model-events\";\nimport { ModelEvents, globalModelEvents } from \"../events/model-events\";\nimport { DatabaseRemover } from \"../remover/database-remover\";\nimport { DatabaseRestorer } from \"../restorer/database-restorer\";\nimport { modelSync } from \"../sync/model-sync\";\nimport type { ModelSyncOperationContract } from \"../sync/types\";\nimport type { DeleteStrategy, StrictMode } from \"../types\";\nimport { DatabaseWriter } from \"../writer/database-writer\";\nimport {\n getAllModelsFromRegistry,\n getModelFromRegistry,\n removeModelFromRegistery,\n} from \"./register-model\";\n\n/**\n * Timing control for global scopes\n */\nexport type ScopeTiming = \"before\" | \"after\";\n\n/**\n * Global scope definition with callback and timing\n */\nexport type GlobalScopeDefinition = {\n callback: (query: QueryBuilderContract) => void;\n timing: ScopeTiming;\n};\n\n/**\n * Local scope callback function\n */\nexport type LocalScopeCallback = (query: QueryBuilderContract) => void;\n\n/**\n * Options for adding global scopes\n */\nexport type GlobalScopeOptions = {\n timing?: ScopeTiming;\n};\n\nexport type ChildModel<TModel extends Model> = (new (...args: any[]) => TModel) &\n Pick<\n typeof Model,\n | \"table\"\n | \"primaryKey\"\n | \"dataSource\"\n | \"schema\"\n | \"strictMode\"\n | \"autoGenerateId\"\n | \"initialId\"\n | \"randomInitialId\"\n | \"incrementIdBy\"\n | \"resource\"\n | \"resourceColumns\"\n | \"toJsonColumns\"\n | \"randomIncrement\"\n | \"getDataSource\"\n | \"query\"\n | \"find\"\n | \"first\"\n | \"last\"\n | \"all\"\n | \"latest\"\n | \"count\"\n | \"where\"\n | \"increase\"\n | \"decrease\"\n | \"atomic\"\n | \"events\"\n | \"on\"\n | \"once\"\n | \"off\"\n | \"globalEvents\"\n | \"delete\"\n | \"deleteOne\"\n | \"deleteStrategy\"\n | \"trashTable\"\n | \"restore\"\n | \"restoreAll\"\n | \"deletedAtColumn\"\n | \"createdAtColumn\"\n | \"updatedAtColumn\"\n | \"create\"\n | \"createMany\"\n | \"sync\"\n | \"embed\"\n | \"deserialize\"\n | \"syncMany\"\n | \"addGlobalScope\"\n | \"removeGlobalScope\"\n | \"addScope\"\n | \"removeScope\"\n | \"localScopes\"\n | \"globalScopes\"\n | \"newQueryBuilder\"\n | \"builder\"\n >;\n\n/**\n * Generic schema type representing the structure of model data.\n */\nexport type ModelSchema = Record<string, any>;\n\n/**\n * Sentinel value used to distinguish between undefined and missing fields.\n */\nconst MISSING_VALUE = Symbol(\"missing\");\n\n/**\n * WeakMap registry that associates each model constructor with its own event emitter.\n */\nconst modelEventsRegistry = new WeakMap<any, any>();\n\n/**\n * Base class that powers all Cascade models.\n *\n * Provides:\n * - Type-safe value accessors with dot-notation support (get, set, has, unset, merge)\n * - Automatic dirty tracking for efficient partial updates\n * - Lifecycle event hooks (saving, created, deleting, etc.)\n * - Integration with the data-source registry for multi-database support\n * - Support for both per-model and global event listeners\n *\n * @template TSchema - The shape of the model's underlying data\n *\n * @example\n * ```typescript\n * interface UserSchema {\n * id: number;\n * name: string;\n * email: string;\n * }\n *\n * class User extends Model<UserSchema> {\n * public static table = \"users\";\n * }\n *\n * const user = new User({ name: \"Alice\" });\n * user.set(\"email\", \"alice@example.com\");\n * console.log(user.hasChanges()); // true\n * ```\n */\nexport abstract class Model<TSchema extends ModelSchema = ModelSchema> {\n /**\n * The database table or collection name associated with this model.\n *\n * Must be defined by each concrete model subclass.\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static table = \"users\";\n * }\n * ```\n */\n public static table: string;\n\n /**\n * Resource for this model.\n * It is a class that holds a toJSON function\n * Called when the model is being converted to JSON (by calling toJSON or JSON.stringify(model))\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static resource = UserResource;\n * }\n * ```\n */\n public static resource?: any;\n\n /**\n * Resource columns\n * Define what columns should be sent to the resource (if any) when converting to JSON\n */\n public static resourceColumns?: string[];\n\n /**\n * JSON keys for this model.\n * This could be used if resource is not passed\n * It will select only these keys from the model\n * @example\n * ```typescript\n * class User extends Model {\n * public static toJsonColumns = [\"id\", \"name\"];\n * }\n * ```\n */\n public static toJsonColumns?: string[];\n\n /**\n * Data source reference for this model.\n *\n * Can be:\n * - A string name registered in the data-source registry\n * - A DataSource instance\n * - Undefined (falls back to the default data source)\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static dataSource = \"primary\";\n * }\n * ```\n */\n public static dataSource?: string | DataSource;\n\n /**\n * Query builder class\n */\n public static builder?: new (...args: any[]) => QueryBuilderContract<Model>;\n\n /**\n * Primary key field name used to identify records.\n *\n * @default \"id\"\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static primaryKey = \"_id\"; // MongoDB\n * }\n *\n * class Product extends Model {\n * public static primaryKey = \"id\"; // SQL\n * }\n * ```\n */\n public static primaryKey: string = \"id\";\n\n /**\n * Embeded fields when document is Being embeded\n */\n public static embed?: string[];\n\n /**\n * Validation and casting schema using @warlock.js/seal.\n *\n * Defines validation rules and data transformations for the model.\n * Used automatically during save operations.\n *\n * @example\n * ```typescript\n * import { v } from \"@warlock.js/seal\";\n *\n * class User extends Model {\n * public static schema = v.object({\n * name: v.string().required().trim(),\n * age: v.number().min(0).max(120),\n * email: v.string().email().required().toLowerCase(),\n * createdAt: v.date().default(() => new Date()),\n * });\n * }\n * ```\n */\n public static schema?: ObjectValidator;\n\n /**\n * Strict mode behavior for unknown fields.\n *\n * - `\"strip\"`: Remove unknown fields silently (default, recommended for APIs)\n * - `\"fail\"`: Throw validation error on unknown fields (strict validation)\n * - `\"allow\"`: Allow unknown fields to pass through (permissive)\n *\n * @default \"strip\"\n *\n * @example\n * ```typescript\n * import { Model, type StrictMode } from \"@warlock.js/cascade\";\n *\n * class User extends Model {\n * public static strictMode: StrictMode = \"fail\"; // Throw on unknown fields\n * }\n *\n * const user = new User({ name: \"Alice\", unknownField: \"value\" });\n * await user.save(); // DatabaseWriterValidationError: unknown field\n * ```\n */\n public static strictMode: StrictMode = \"strip\";\n\n /**\n * Auto-generate incremental `id` field on insert (NoSQL only).\n *\n * When enabled, the ID generator creates a sequential integer ID\n * separate from the database's native ID (_id for MongoDB).\n *\n * **Note:** SQL databases use native AUTO_INCREMENT and don't need this.\n *\n * @default true\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static autoGenerateId = true;\n * }\n *\n * const user = new User({ name: \"Alice\" });\n * await user.save();\n * console.log(user.get(\"_id\")); // ObjectId(\"...\") - MongoDB\n * console.log(user.get(\"id\")); // 1 - Generated\n * ```\n */\n public static autoGenerateId = true;\n\n /**\n * Initial ID value for the first record.\n *\n * If not set, defaults to 1 or uses `randomInitialId`.\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static initialId = 1000; // Start from 1000\n * }\n * ```\n */\n public static initialId?: number;\n\n /**\n * Randomly generate the initial ID.\n *\n * Can be:\n * - `true`: Generate random ID between 10000-499999\n * - Function: Custom random ID generator\n * - `false`: Use `initialId` or default to 1\n *\n * @default false\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static randomInitialId = true; // Random 10000-499999\n * }\n *\n * class Product extends Model {\n * public static randomInitialId = () => Math.floor(Math.random() * 1000000);\n * }\n * ```\n */\n public static randomInitialId?: boolean | (() => number);\n\n /**\n * Amount to increment ID by for each new record.\n *\n * If not set, defaults to 1 or uses `randomIncrement`.\n *\n * @default 1\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static incrementIdBy = 5; // Increment by 5\n * }\n * ```\n */\n public static incrementIdBy?: number = 1;\n\n /**\n * Randomly generate the increment amount.\n *\n * Can be:\n * - `true`: Generate random increment between 1-10\n * - Function: Custom random increment generator\n * - `false`: Use `incrementIdBy` or default to 1\n *\n * @default false\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static randomIncrement = true; // Random 1-10\n * }\n *\n * class Product extends Model {\n * public static randomIncrement = () => Math.floor(Math.random() * 100);\n * }\n * ```\n */\n public static randomIncrement?: boolean | (() => number);\n\n /**\n * Created at column name.\n */\n public static createdAtColumn?: string | false = \"createdAt\";\n\n /**\n * Updated at column name.\n */\n public static updatedAtColumn?: string | false = \"updatedAt\";\n\n /**\n * Delete strategy for this model.\n *\n * Controls how models are deleted:\n * - `\"trash\"` - Moves to trash collection, then deletes\n * - `\"permanent\"` - Direct deletion (hard delete)\n * - `\"soft\"` - Sets deletedAt timestamp (soft delete)\n *\n * Can be overridden by destroy() options.\n * Falls back to data source default if not set.\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static deleteStrategy: DeleteStrategy = \"soft\";\n * }\n * ```\n */\n public static deleteStrategy?: DeleteStrategy;\n\n /**\n * Column name for soft delete timestamp.\n *\n * Used when delete strategy is \"soft\".\n *\n * @default \"deletedAt\"\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static deletedAtColumn = \"archivedAt\";\n * }\n * ```\n */\n public static deletedAtColumn: string = \"deletedAt\";\n\n /**\n * Trash table/collection name override.\n *\n * If not set, defaults to `{table}Trash` or data source default.\n * Used when delete strategy is \"trash\".\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static trashTable = \"userRecycleBin\";\n * }\n * ```\n */\n public static trashTable?: string;\n\n /**\n * Global scopes that are automatically applied to all queries.\n * These scopes are inherited by child models.\n */\n public static globalScopes = new Map<string, GlobalScopeDefinition>();\n\n /**\n * Local scopes that can be manually applied to queries.\n * These are reusable query snippets that developers opt into.\n */\n public static localScopes = new Map<string, LocalScopeCallback>();\n\n /**\n * Flag indicating whether this model instance represents a new (unsaved) record.\n *\n * - `true`: The model has not been persisted to the database yet\n * - `false`: The model represents an existing database record\n *\n * This flag is used by the writer to determine whether to perform an insert or update.\n */\n public isNew = true;\n\n /**\n * The raw mutable data backing this model instance.\n *\n * All field accessors (get, set, merge, etc.) operate on this object.\n */\n public data: TSchema;\n\n /**\n * Dirty tracker that monitors changes to the model's data.\n *\n * Tracks:\n * - Which fields have been modified (dirty columns)\n * - Which fields have been removed\n * - Original vs. current values for each dirty field\n *\n * Used by the writer to generate efficient partial update payloads.\n */\n public readonly dirtyTracker: DatabaseDirtyTracker;\n\n /**\n * Constructs a new model instance with optional initial data.\n *\n * Initializes the dirty tracker with a snapshot of the provided data.\n *\n * @param initialData - Partial data to populate the model\n *\n * @example\n * ```typescript\n * const user = new User({ name: \"Alice\", email: \"alice@example.com\" });\n * ```\n */\n public constructor(initialData: Partial<TSchema> = {}) {\n this.data = initialData as TSchema;\n this.dirtyTracker = new DatabaseDirtyTracker(this.data);\n }\n\n /**\n * Get a model class by its name from the global registry.\n *\n * Models must be decorated with @RegisterModel() to be available in the registry.\n *\n * @param name - The model class name\n * @returns The model class or undefined if not found\n *\n * @example\n * ```typescript\n * const UserModel = Model.getModel(\"User\");\n * if (UserModel) {\n * const user = await UserModel.find(1);\n * }\n * ```\n */\n public static getModel(name: string) {\n return getModelFromRegistry(name);\n }\n\n /**\n * Get all registered models from the global registry.\n *\n * Only models decorated with @RegisterModel() will appear here.\n *\n * @returns A Map of all registered model classes by name\n *\n * @example\n * ```typescript\n * const allModels = Model.getAllModels();\n * for (const [name, ModelClass] of allModels) {\n * console.log(`Found model: ${name} with table: ${ModelClass.table}`);\n * }\n * ```\n */\n public static getAllModels() {\n return getAllModelsFromRegistry();\n }\n\n // ============================================================================\n // STATIC SYNC METHODS\n // ============================================================================\n\n /**\n * Create a sync operation for a single embedded document.\n *\n * When this model is updated, the target model's field\n * will be updated with the embedded data.\n *\n * @param TargetModel - Target model class that receives data\n * @param targetField - Field path in target model\n * @returns Sync operation for chaining configuration\n *\n * @example\n * ```typescript\n * // When Category updates, update Product.category\n * Category.sync(Product, \"category\");\n * ```\n */\n public static sync<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n TargetModel: ChildModel<Model>,\n targetField: string,\n ): ModelSyncOperationContract {\n return modelSync.sync(this, TargetModel, targetField);\n }\n\n /**\n * Create a sync operation for an array of embedded documents.\n *\n * When this model is updated, the corresponding element\n * in the target model's array field will be updated.\n *\n * @param TargetModel - Target model class that receives data\n * @param targetField - Array field path in target model\n * @returns Sync operation for chaining configuration\n *\n * @example\n * ```typescript\n * // When Tag updates, update Post.tags[i] where tags[i].id matches\n * Tag.syncMany(Post, \"tags\").identifyBy(\"id\");\n * ```\n */\n public static syncMany<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n TargetModel: ChildModel<Model>,\n targetField: string,\n ): ModelSyncOperationContract {\n return modelSync.syncMany(this, TargetModel, targetField);\n }\n\n /**\n * Get model id\n */\n public get id(): number | undefined {\n return this.get(\"id\");\n }\n\n /**\n * Retrieves a field value from the model's data.\n *\n * Supports both top-level keys and dot-notation paths for nested access.\n *\n * @param field - The field name or dot-notation path (e.g., \"address.city\")\n * @param defaultValue - Value to return if the field is missing\n * @returns The field value or the default value if not found\n *\n * @example\n * ```typescript\n * user.get(\"name\"); // \"Alice\"\n * user.get(\"address.city\", \"Unknown\"); // \"Unknown\" if address.city is missing\n * ```\n */\n public get<TKey extends keyof TSchema & string>(field: TKey): TSchema[TKey];\n public get<TKey extends keyof TSchema & string>(\n field: TKey,\n defaultValue: TSchema[TKey],\n ): TSchema[TKey];\n public get(field: string): unknown;\n public get(field: string, defaultValue: unknown): unknown;\n public get(field: string, defaultValue?: unknown): unknown {\n return get(this.data, field, defaultValue);\n }\n\n /**\n * Get only the values of the given fields\n */\n public only<TKey extends keyof TSchema & string>(fields: TKey[]): Record<TKey, TSchema[TKey]>;\n public only(fields: string[]): Record<string, unknown>;\n public only(fields: string[]): Record<string, unknown> {\n return only(this.data, fields);\n }\n\n /**\n * Get a string value\n */\n public string(key: string, defaultValue?: string): string | undefined {\n return this.get(key, defaultValue) as string | undefined;\n }\n\n /**\n * Get a number value\n */\n public number(key: string, defaultValue?: number): number | undefined {\n return this.get(key, defaultValue) as number | undefined;\n }\n\n /**\n * Get a boolean value\n */\n public boolean(key: string, defaultValue?: boolean): boolean | undefined {\n return this.get(key, defaultValue) as boolean | undefined;\n }\n\n /**\n * Sets a field value in the model's data and marks it as dirty.\n *\n * Supports both top-level keys and dot-notation paths for nested assignment.\n * Automatically updates the dirty tracker to reflect the change.\n *\n * @param field - The field name or dot-notation path (e.g., \"address.city\")\n * @param value - The value to assign\n * @returns The model instance for method chaining\n *\n * @example\n * ```typescript\n * user.set(\"name\", \"Bob\").set(\"address.city\", \"NYC\");\n * ```\n */\n public set<TKey extends keyof TSchema & string>(field: TKey, value: TSchema[TKey]): this;\n public set(field: string, value: unknown): this;\n public set(field: string, value: unknown): this {\n const path = String(field);\n set(this.data, path, value);\n\n const partial: Record<string, unknown> = {};\n set(partial, path, value);\n this.dirtyTracker.mergeChanges(partial);\n\n return this;\n }\n\n /**\n * Checks whether a field exists in the model's data.\n *\n * Supports both top-level keys and dot-notation paths.\n *\n * @param field - The field name or dot-notation path\n * @returns `true` if the field exists, `false` otherwise\n *\n * @example\n * ```typescript\n * user.has(\"name\"); // true\n * user.has(\"address.zipCode\"); // false\n * ```\n */\n public has<TKey extends keyof TSchema & string>(field: TKey): boolean;\n public has(field: string): boolean;\n public has(field: string): boolean {\n return get(this.data, field, MISSING_VALUE) !== MISSING_VALUE;\n }\n\n /**\n * Increment the given field by the given amount\n */\n public increment<TKey extends keyof TSchema & string>(field: TKey, amount: number): this;\n public increment(field: string, amount: number): this;\n public increment(field: string, amount: number): this {\n const value = this.get(field, 0) as number;\n const incrementedValue = value + amount;\n return this.set(field, incrementedValue);\n }\n\n /**\n * Decrement the given field by the given amount\n */\n public decrement<TKey extends keyof TSchema & string>(field: TKey, amount: number): this;\n public decrement(field: string, amount: number): this;\n public decrement(field: string, amount: number): this {\n const value = this.get(field, 0) as number;\n const decrementedValue = value - amount;\n return this.set(field, decrementedValue);\n }\n\n /**\n * Removes one or more fields from the model's data and marks them as removed.\n *\n * Supports both top-level keys and dot-notation paths.\n * Automatically updates the dirty tracker to reflect the removal.\n *\n * @param fields - One or more field names or dot-notation paths to remove\n * @returns The model instance for method chaining\n *\n * @example\n * ```typescript\n * user.unset(\"tempField\", \"address.oldZip\");\n * ```\n */\n public unset(...fields: (keyof TSchema & string)[]): this;\n public unset(...fields: string[]): this;\n public unset(...fields: string[]): this {\n this.data = unset(this.data, fields);\n this.dirtyTracker.unset(fields);\n\n return this;\n }\n\n /**\n * Merges new values into the model's data and marks changed fields as dirty.\n *\n * Performs a deep merge, preserving existing nested structures.\n * Automatically updates the dirty tracker to reflect all changes.\n *\n * @param values - Partial data to merge into the model\n * @returns The model instance for method chaining\n *\n * @example\n * ```typescript\n * user.merge({ name: \"Charlie\", address: { city: \"LA\" } });\n * ```\n */\n public merge(values: Partial<TSchema>): this;\n public merge(values: Record<string, unknown>): this;\n public merge(values: Record<string, unknown>): this {\n this.data = merge(this.data, values) as TSchema;\n this.dirtyTracker.mergeChanges(values);\n return this;\n }\n\n /**\n * Checks whether the model's data has changed since instantiation or last reset.\n *\n * @returns `true` if any fields have been modified or removed, `false` otherwise\n *\n * @example\n * ```typescript\n * const user = new User({ name: \"Alice\" });\n * user.hasChanges(); // false\n * user.set(\"name\", \"Bob\");\n * user.hasChanges(); // true\n * ```\n */\n public hasChanges(): boolean {\n return this.dirtyTracker.hasChanges();\n }\n\n /**\n * Check if the given column has been modified.\n *\n * @param column - The column name to check\n * @returns `true` if the column has been modified, `false` otherwise\n *\n * @example\n * ```typescript\n * user.set(\"name\", \"Bob\");\n * user.isDirty(\"name\"); // true\n * ```\n */\n public isDirty(column: string): boolean {\n return this.dirtyTracker.isDirty(column);\n }\n\n /**\n * Retrieves all dirty columns with their old and new values.\n *\n * @returns A record mapping each dirty column to its previous and current value\n *\n * @example\n * ```typescript\n * user.set(\"name\", \"Bob\");\n * user.getDirtyColumnsWithValues();\n * // { name: { oldValue: \"Alice\", newValue: \"Bob\" } }\n * ```\n */\n public getDirtyColumnsWithValues(): Record<string, { oldValue: unknown; newValue: unknown }> {\n return this.dirtyTracker.getDirtyColumnsWithValues();\n }\n\n /**\n * Lists all columns that have been removed from the model's data.\n *\n * @returns An array of field names that were present initially but have been unset\n *\n * @example\n * ```typescript\n * user.unset(\"tempField\");\n * user.getRemovedColumns(); // [\"tempField\"]\n * ```\n */\n public getRemovedColumns(): string[] {\n return this.dirtyTracker.getRemovedColumns();\n }\n\n /**\n * Lists all columns that have been modified since instantiation or last reset.\n *\n * @returns An array of field names that have changed\n *\n * @example\n * ```typescript\n * user.set(\"name\", \"Bob\");\n * user.getDirtyColumns(); // [\"name\"]\n * ```\n */\n public getDirtyColumns(): string[] {\n return this.dirtyTracker.getDirtyColumns();\n }\n\n /**\n * Emits a lifecycle event to both per-model and global listeners.\n *\n * This method is public so that external services (like the writer) can trigger\n * lifecycle events when appropriate.\n *\n * @param event - The event name (e.g., \"saving\", \"created\", \"deleting\")\n * @param context - Optional context data to pass to listeners\n *\n * @example\n * ```typescript\n * await user.emitEvent(\"saving\");\n * await user.emitEvent(\"validated\", { errors: [] });\n * ```\n */\n public async emitEvent<TContext = unknown>(\n event: ModelEventName,\n context?: TContext,\n ): Promise<void> {\n const ctor = this.constructor as any;\n await ctor.events().emit(event, this, context as TContext);\n await globalModelEvents.emit(event, this, context as TContext);\n }\n\n /**\n * Resolves the data source associated with this model.\n *\n * Resolution order:\n * 1. If `dataSource` is a string, looks it up in the data-source registry\n * 2. If `dataSource` is a DataSource instance, returns it directly\n * 3. Otherwise, returns the default data source from the registry\n *\n * @returns The resolved DataSource instance\n * @throws Error if no data source is found\n *\n * @example\n * ```typescript\n * class User extends Model {\n * public static dataSource = \"primary\";\n * }\n *\n * const ds = User.getDataSource();\n * ```\n */\n public static getDataSource(): DataSource {\n const ref = this.dataSource;\n let dataSource: DataSource;\n\n if (typeof ref === \"string\") {\n dataSource = dataSourceRegistry.get(ref);\n } else if (ref) {\n dataSource = ref;\n } else {\n dataSource = dataSourceRegistry.get();\n }\n\n // Apply model defaults from data source (only once per model class)\n if (!this.hasOwnProperty(\"_defaultsApplied\") && dataSource.modelDefaults) {\n (this as any).applyModelDefaults(dataSource.modelDefaults);\n (this as any)._defaultsApplied = true;\n }\n\n return dataSource;\n }\n\n /**\n * Apply model defaults from data source configuration.\n *\n * This is called automatically by getDataSource() the first time\n * a model accesses its data source. Defaults are only applied if\n * the model doesn't already have its own value set.\n *\n * @param defaults - Model default configuration from data source\n * @private\n */\n public static applyModelDefaults(defaults: any): void {\n // Only apply defaults if model doesn't have its own value\n // Note: autoGenerateId is not applied here as it's a driver-level setting\n if (defaults.initialId !== undefined && this.initialId === undefined) {\n this.initialId = defaults.initialId;\n }\n if (defaults.randomInitialId !== undefined && this.randomInitialId === undefined) {\n this.randomInitialId = defaults.randomInitialId;\n }\n if (defaults.incrementIdBy !== undefined && this.incrementIdBy === undefined) {\n this.incrementIdBy = defaults.incrementIdBy;\n }\n if (defaults.randomIncrement !== undefined && this.randomIncrement === undefined) {\n this.randomIncrement = defaults.randomIncrement;\n }\n if (defaults.deleteStrategy !== undefined && this.deleteStrategy === undefined) {\n this.deleteStrategy = defaults.deleteStrategy;\n }\n if (defaults.strictMode !== undefined && this.strictMode === undefined) {\n this.strictMode = defaults.strictMode;\n }\n }\n\n /**\n * Add a global scope that is automatically applied to all queries.\n *\n * Global scopes are inherited by child models and applied before query execution.\n * Use for security filters, multi-tenancy, soft deletes, etc.\n *\n * @param name - Unique name for the scope\n * @param callback - Function that modifies the query\n * @param options - Scope options (timing: 'before' | 'after')\n *\n * @example\n * ```typescript\n * // Multi-tenancy scope\n * Model.addGlobalScope('tenant', (query) => {\n * query.where('tenantId', getCurrentTenant());\n * }, { timing: 'before' });\n *\n * // Soft delete scope\n * User.addGlobalScope('notDeleted', (query) => {\n * query.whereNull('deletedAt');\n * });\n * ```\n */\n public static addGlobalScope(\n name: string,\n callback: (query: QueryBuilderContract) => void,\n options: GlobalScopeOptions = {},\n ): void {\n this.globalScopes.set(name, {\n callback,\n timing: options.timing || \"before\",\n });\n }\n\n /**\n * Remove a global scope by name.\n *\n * @param name - Name of the scope to remove\n *\n * @example\n * ```typescript\n * Model.removeGlobalScope('tenant');\n * ```\n */\n public static removeGlobalScope(name: string): void {\n this.globalScopes.delete(name);\n }\n\n /**\n * Add a local scope that can be manually applied to queries.\n *\n * Local scopes are reusable query snippets that developers opt into.\n * They are not automatically applied.\n *\n * @param name - Unique name for the scope\n * @param callback - Function that modifies the query\n *\n * @example\n * ```typescript\n * // Define reusable scopes\n * User.addScope('active', (query) => {\n * query.where('isActive', true);\n * });\n *\n * User.addScope('admins', (query) => {\n * query.where('role', 'admin');\n * });\n *\n * // Use explicitly\n * await User.query().scope('active').get();\n * await User.query().scope('admins').get();\n * ```\n */\n public static addScope(name: string, callback: LocalScopeCallback): void {\n this.localScopes.set(name, callback);\n }\n\n /**\n * Remove a local scope by name.\n *\n * @param name - Name of the scope to remove\n *\n * @example\n * ```typescript\n * User.removeScope('active');\n * ```\n */\n public static removeScope(name: string): void {\n this.localScopes.delete(name);\n }\n\n /**\n * Create a new query builder for this model\n */\n public static query<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n ): ReturnType<ChildModel<TModel>[\"newQueryBuilder\"]> {\n // Call newQueryBuilder as a static method (may be overridden in child classes)\n const queryBuilder = this.newQueryBuilder<TModel>();\n const ModelClass = this as new (...args: any[]) => TModel;\n\n // Collect global scopes from base Model and child model\n const allGlobalScopes = new Map<string, GlobalScopeDefinition>([\n ...Model.globalScopes,\n ...this.globalScopes,\n ]);\n\n // Pass scopes to query builder\n queryBuilder.pendingGlobalScopes = allGlobalScopes;\n\n queryBuilder.availableLocalScopes = this.localScopes;\n queryBuilder.disabledGlobalScopes = new Set();\n\n // Emit fetching event\n this.events().emitFetching(queryBuilder, { table: this.table, modelClass: this });\n\n queryBuilder.hydrate((data: any) => {\n const model = new ModelClass(data);\n model.isNew = false;\n return model;\n });\n\n // Wire up onFetched callback to emit model-level event\n queryBuilder.onFetched(async (models: any, context: any) => {\n await this.events().emit(\"fetched\", models as any, context);\n });\n\n return queryBuilder;\n }\n\n /**\n * Create new query builder.\n *\n * If the model has a static `builder` property set to a query builder class,\n * it will be instantiated instead of the default driver query builder.\n *\n * @example\n * ```typescript\n * class UserQueryBuilder<T = User> extends MongoQueryBuilder<T> {\n * active() { return this.where(\"isActive\", true); }\n * }\n *\n * class User extends Model {\n * static builder = UserQueryBuilder; // That's it! ✨\n * }\n *\n * // Now User.query() returns UserQueryBuilder<User> with autocomplete!\n * ```\n */\n public static newQueryBuilder<TModel extends Model = Model>(this: ChildModel<TModel>) {\n const dataSource = this.getDataSource();\n\n // Check if model has a custom builder class\n if (this.builder) {\n const BuilderClass = this.builder;\n return new BuilderClass(this.table, dataSource);\n }\n\n // Use default driver query builder\n const queryBuilder = dataSource.driver.queryBuilder<TModel>(this.table);\n return queryBuilder;\n }\n\n /**\n * Get First matched record for the given filter\n */\n public static async first<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<TModel | null> {\n const query = this.query();\n if (filter) {\n query.where(filter);\n }\n\n return query.first();\n }\n\n /**\n * Get last matched record for the given filter\n */\n public static async last<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<TModel | null> {\n const query = this.query();\n if (filter) {\n query.where(filter);\n }\n\n return query.last();\n }\n\n /**\n * Use where clause directly\n */\n public static where<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n field: string,\n value: unknown,\n ): QueryBuilderContract<TModel>;\n public static where<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n field: string,\n operator: WhereOperator,\n value: unknown,\n ): QueryBuilderContract<TModel>;\n public static where<TModel extends Model = Model>(\n this: (new (...args: any[]) => TModel) &\n Pick<typeof Model, \"query\" | \"getDataSource\" | \"table\">,\n conditions: WhereObject,\n ): QueryBuilderContract<TModel>;\n public static where<TModel extends Model = Model>(\n this: (new (...args: any[]) => TModel) &\n Pick<typeof Model, \"query\" | \"getDataSource\" | \"table\">,\n callback: WhereCallback<TModel>,\n ): QueryBuilderContract<TModel>;\n public static where<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n ...args: any[]\n ): QueryBuilderContract<TModel> {\n return (this.query().where as any)(...args);\n }\n\n /**\n * Count the number of records in the table\n * @param filter - The filter to apply to the query\n */\n public static count<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<number> {\n const query = this.query();\n if (filter) {\n query.where(filter);\n }\n\n return query.count();\n }\n\n /**\n * Find record by id\n */\n public static async find<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n id: string | number,\n ): Promise<TModel | null> {\n const query = this.query();\n return query.where(this.primaryKey, id).first();\n }\n\n /**\n * Get all records from the table\n *\n * @param filter - The filter to apply to the query\n * @returns All records from the table\n */\n public static async all<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<TModel[]> {\n const query = this.query();\n if (filter) {\n query.where(filter);\n }\n return query.get();\n }\n\n /**\n * Get latest records from the table\n *\n * @param filter - The filter to apply to the query\n */\n public static async latest<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<TModel[]> {\n const query = this.query();\n if (filter) {\n query.where(filter);\n }\n\n return (await query.latest()) as unknown as TModel[];\n }\n\n /**\n * Increment the given field by the given amount\n *\n * @example ```typescript\n * // Increase age by 1 for user id 1\n * User.increment({id: 1}, \"age\", 1);\n * // Increase age by 1 and views by 2 for user id 1\n * User.increment({id: 1}, {age: 1, views: 2});\n * ```\n */\n public static increase<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n ): Promise<number> {\n const query = this.query().where(filter);\n\n return query.increment(field, amount);\n }\n\n /**\n * Decrement the given field by the given amount\n * @example ```typescript\n * // Decrease age by 1 for user id 1\n * User.decrement({id: 1}, \"age\", 1);\n * // Decrease age by 1 and views by 2 for user id 1\n * User.decrement({id: 1}, {age: 1, views: 2});\n * ```\n */\n public static decrease<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter: Record<string, unknown>,\n field: string,\n amount: number,\n ): Promise<number> {\n const query = this.query().where(filter);\n return query.decrement(field, amount);\n }\n\n /**\n * Perform atomic operation\n */\n public static async atomic<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter: Record<string, unknown>,\n operations: Record<string, unknown>,\n ): Promise<number> {\n const dataSource = this.getDataSource();\n const result = await dataSource.driver.atomic(this.table, filter, operations);\n return result.modifiedCount;\n }\n\n /**\n * Destroy (delete) the current model instance from the database.\n *\n * Emits lifecycle events:\n * - `deleting` - Before deletion\n * - `deleted` - After successful deletion\n *\n * @param options - Destroy options (strategy override, skipEvents)\n * @throws {Error} If the model is new (not saved) or if deletion fails\n *\n * @example\n * ```typescript\n * const user = await User.find(1);\n * await user.destroy(); // Uses default strategy\n * await user.destroy({ strategy: \"permanent\" }); // Override strategy\n * await user.destroy({ skipEvents: true }); // Silent delete\n * ```\n */\n public async destroy(options?: {\n strategy?: DeleteStrategy;\n skipEvents?: boolean;\n }): Promise<RemoverResult> {\n const remover = new DatabaseRemover(this);\n return await remover.destroy(options);\n }\n\n /**\n * Get the class constructor from an instance.\n *\n * This helper method allows instance methods to access static properties\n * and methods of the model class in a type-safe way.\n *\n * @returns The model class constructor\n *\n * @example\n * ```typescript\n * const constructor = this.self();\n * const table = constructor.table;\n * await constructor.deleteOne({ id: 1 });\n * ```\n */\n protected self<TModel extends Model = this>(): ChildModel<TModel> {\n return this.constructor as any as ChildModel<TModel>;\n }\n\n /**\n * Get table name\n */\n public getTableName(): string {\n return this.self().table;\n }\n\n /**\n * Get primary key name\n */\n public getPrimaryKey(): string {\n return this.self().primaryKey;\n }\n\n /**\n * Get model schema\n */\n public getSchema() {\n return this.self().schema;\n }\n\n /**\n * Check if schema has the given key\n */\n public schemaHas(key: string): boolean {\n return this.self().schema?.schema[key] !== undefined;\n }\n\n /**\n * Get strict mode\n */\n public getStrictMode(): StrictMode {\n return this.self().strictMode;\n }\n\n /**\n * Get data source (Connection)\n */\n public getConnection(): DataSource {\n return this.self().getDataSource();\n }\n\n /**\n * Delete all matching documents from the table.\n */\n public static async delete<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<number> {\n return await this.getDataSource().driver.deleteMany(this.table, filter);\n }\n\n /**\n * Delete a single matching document from the table.\n */\n public static async deleteOne<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n filter?: Record<string, unknown>,\n ): Promise<number> {\n return await this.getDataSource().driver.delete(this.table, filter);\n }\n\n /**\n * Restore a single deleted record by its ID.\n *\n * Automatically detects whether the record was deleted via \"trash\" or \"soft\" strategy.\n * Handles ID conflicts based on options.\n *\n * @param id - The primary key value of the record to restore\n * @param options - Restorer options (onIdConflict, skipEvents)\n * @returns The restored model instance\n *\n * @throws {Error} If record not found in trash or soft-deleted records\n * @throws {Error} If ID conflict and onIdConflict is \"fail\"\n *\n * @example\n * ```typescript\n * // Restore with default options (assign new ID if conflict)\n * const user = await User.restore(123);\n *\n * // Restore and fail if ID conflict\n * const user = await User.restore(123, { onIdConflict: \"fail\" });\n *\n * // Silent restore (skip events)\n * const user = await User.restore(123, { skipEvents: true });\n * ```\n */\n public static async restore<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n id: string | number,\n options?: {\n onIdConflict?: \"fail\" | \"assignNew\";\n skipEvents?: boolean;\n },\n ): Promise<TModel> {\n const restorer = new DatabaseRestorer(this as unknown as typeof Model);\n const result = await restorer.restore(id, options);\n\n if (!result.restoredRecord) {\n throw new Error(\n `Failed to restore ${this.name} with ${this.primaryKey} ${id}: no record returned.`,\n );\n }\n\n return result.restoredRecord as TModel;\n }\n\n /**\n * Restore all deleted records for the model's table.\n *\n * Restores all records from the trash table (if using trash strategy)\n * or all soft-deleted records (if using soft strategy).\n *\n * @param options - Restorer options (onIdConflict, skipEvents)\n * @returns Array of restored model instances\n *\n * @example\n * ```typescript\n * // Restore all with default options\n * const users = await User.restoreAll();\n *\n * // Restore all and fail on any ID conflict\n * const users = await User.restoreAll({ onIdConflict: \"fail\" });\n * ```\n */\n public static async restoreAll<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n options?: {\n onIdConflict?: \"fail\" | \"assignNew\";\n skipEvents?: boolean;\n },\n ): Promise<TModel[]> {\n const restorer = new DatabaseRestorer(this as unknown as typeof Model);\n const result = await restorer.restoreAll(options);\n\n if (result.restoredCount === 0) {\n return [];\n }\n\n return result.restoredRecords as TModel[];\n }\n\n /**\n * Create a new record in database and return the model instance.\n *\n * The data type is automatically inferred from the model's schema type.\n *\n * @param data - Partial data matching the model's schema type\n * @returns The created model instance\n *\n * @example\n * ```typescript\n * // TypeScript automatically infers UserSchema from User model\n * const user = await User.create({\n * name: \"Alice\",\n * email: \"alice@example.com\",\n * age: 30\n * });\n * // Type: User (with UserSchema inferred)\n * ```\n */\n public static async create<\n TModel extends Model = Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n >(this: ChildModel<TModel>, data: Partial<TSchema>): Promise<TModel> {\n const model = new this(data);\n await model.save();\n return model;\n }\n\n /**\n * Create many documents and return an array of created models\n */\n public static async createMany<\n TModel extends Model = Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n >(this: ChildModel<TModel>, data: Partial<TSchema>[]): Promise<TModel[]> {\n return await Promise.all(data.map((data) => this.create(data)));\n }\n\n /**\n * Find a record or create it if not found.\n *\n * Does NOT update existing records - returns them as-is.\n * Useful when you want to ensure a record exists without modifying it.\n *\n * @param filter - Conditions to find by\n * @param data - Data to create if not found (merged with filter)\n * @returns Promise resolving to found or created model\n *\n * @example\n * ```typescript\n * // Ensure default admin exists (don't modify if exists)\n * const admin = await User.findOrCreate(\n * { email: \"admin@example.com\" },\n * { email: \"admin@example.com\", name: \"Admin\", role: \"admin\" }\n * );\n * // If admin exists, returns existing (password unchanged)\n * // If not found, creates new admin\n * ```\n */\n public static async findOrCreate<\n TModel extends Model = Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n >(this: ChildModel<TModel>, filter: Partial<TSchema>, data: Partial<TSchema>): Promise<TModel> {\n // Try to find existing record\n const existing = await this.first(filter);\n\n if (existing) {\n return existing; // Return as-is, no update\n }\n\n // Create new record with merged data\n return await this.create({ ...filter, ...data } as Partial<TSchema>);\n }\n\n /**\n * Update a record or create it if not found (upsert).\n *\n * DOES update existing records with new data.\n * Useful when you want to ensure a record exists with the latest data.\n *\n * Includes full Model features:\n * - ID generation (if creating)\n * - createdAt timestamp (if creating)\n * - updatedAt timestamp (always)\n * - Validation & casting\n * - Lifecycle events\n * - Sync operations\n *\n * @param filter - Conditions to find by\n * @param data - Data to update or create (merged with filter)\n * @returns Promise resolving to updated or created model\n *\n * @example\n * ```typescript\n * // Sync user from external API (update if exists, create if not)\n * const user = await User.updateOrCreate(\n * { externalId: \"ext-123\" },\n * {\n * externalId: \"ext-123\",\n * name: \"John Updated\",\n * email: \"john.new@example.com\",\n * lastSyncedAt: new Date()\n * }\n * );\n * // User always has latest data from API\n * ```\n */\n public static async updateOrCreate<\n TModel extends Model = Model,\n TSchema extends ModelSchema = TModel extends Model<infer S> ? S : ModelSchema,\n >(this: ChildModel<TModel>, filter: Partial<TSchema>, data: Partial<TSchema>): Promise<TModel> {\n // Try to find existing record\n const existing = await this.first(filter);\n\n if (existing) {\n // Update existing record\n await existing.save({ merge: data });\n return existing;\n }\n\n // Create new record with merged data\n return await this.create({ ...filter, ...data } as Partial<TSchema>);\n }\n\n /**\n * Returns embedded data for sync operations.\n * Excludes internal MongoDB fields and ensures proper date serialization.\n *\n * @returns Embedded data object suitable for syncing\n *\n * @example\n * ```typescript\n * const user = await User.find(1);\n * const embedData = user.embedData;\n * // Returns: { id: 1, name: \"Alice\", email: \"alice@example.com\", ... }\n * // Excludes: _id\n * ```\n */\n public get embedData(): Record<string, unknown> {\n return this.self().embed ? this.only(this.self().embed as any) : this.data;\n }\n\n /**\n * Accesses the event emitter dedicated to this model constructor.\n *\n * Each model subclass gets its own isolated event emitter, allowing you to\n * register lifecycle hooks that only apply to that specific model.\n *\n * @returns The ModelEvents instance for this model constructor\n *\n * @example\n * ```typescript\n * User.events().onSaving((user) => {\n * console.log(\"User is being saved:\", user);\n * });\n * ```\n */\n public static events<TModel extends Model = Model>(\n this: ChildModel<TModel>,\n ): ModelEvents<TModel> {\n let events = modelEventsRegistry.get(this);\n if (!events) {\n events = new ModelEvents<TModel>();\n modelEventsRegistry.set(this, events);\n }\n\n return events as ModelEvents<TModel>;\n }\n\n /**\n * Cleanup model events\n */\n public static $cleanup() {\n modelEventsRegistry.delete(this);\n removeModelFromRegistery(this.name);\n }\n\n /**\n * Registers an event listener for this model constructor.\n *\n * Convenience shorthand for `Model.events().on(...)`.\n *\n * @param event - The event name (e.g., \"saving\", \"created\")\n * @param listener - The callback to invoke when the event fires\n * @returns An unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = User.on(\"saving\", (user) => {\n * console.log(\"Saving user:\", user);\n * });\n * ```\n */\n public static on<TModel extends Model = Model, TContext = unknown>(\n this: ChildModel<TModel>,\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.events<TModel>().on(event, listener);\n }\n\n /**\n * Registers a one-time event listener for this model constructor.\n *\n * The listener will automatically unsubscribe after its first invocation.\n * Convenience shorthand for `Model.events().once(...)`.\n *\n * @param event - The event name (e.g., \"saving\", \"created\")\n * @param listener - The callback to invoke when the event fires\n * @returns An unsubscribe function\n *\n * @example\n * ```typescript\n * User.once(\"created\", (user) => {\n * console.log(\"First user created:\", user);\n * });\n * ```\n */\n public static once<TModel extends Model = Model, TContext = unknown>(\n this: ChildModel<TModel>,\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): () => void {\n return this.events<TModel>().once(event, listener);\n }\n\n /**\n * Removes an event listener from this model constructor.\n *\n * Convenience shorthand for `Model.events().off(...)`.\n *\n * @param event - The event name\n * @param listener - The callback to remove\n *\n * @example\n * ```typescript\n * const listener = (user) => console.log(user);\n * User.on(\"saving\", listener);\n * User.off(\"saving\", listener);\n * ```\n */\n public static off<TModel extends Model = Model, TContext = unknown>(\n this: ChildModel<TModel>,\n event: ModelEventName,\n listener: ModelEventListener<TModel, TContext>,\n ): void {\n this.events<TModel>().off(event, listener);\n }\n\n /**\n * Accesses the global event emitter shared by all model instances.\n *\n * Use this for cross-cutting concerns like auditing, logging, or injecting\n * common fields (e.g., `createdBy`, `updatedBy`) across all models.\n *\n * @returns The global ModelEvents instance\n *\n * @example\n * ```typescript\n * Model.globalEvents().onSaving((model) => {\n * model.set(\"updatedAt\", new Date());\n * });\n * ```\n */\n public static globalEvents(): ModelEvents<Model> {\n return globalModelEvents;\n }\n\n /**\n * Replace the model's data entirely.\n *\n * Used internally by the writer after validation to update the model\n * with validated/casted data.\n *\n * **Warning:** This replaces all data and updates the dirty tracker.\n * Use with caution in application code.\n *\n * @param data - New data to replace current data\n *\n * @example\n * ```typescript\n * // Internal usage by writer\n * model.replaceData(validatedData);\n * ```\n */\n public replaceData(data: Record<string, unknown>): void {\n this.data = data as TSchema;\n this.dirtyTracker.replaceCurrentData(data);\n }\n\n /**\n * Save the model to the database.\n *\n * Performs insert if `isNew === true`, otherwise performs update.\n * Automatically validates, casts, generates IDs, and emits lifecycle events.\n *\n * **Features:**\n * - Validation via @warlock.js/seal schema\n * - Data casting (string → number, etc.)\n * - ID generation (NoSQL only)\n * - Partial updates (only changed fields)\n * - Lifecycle events (validating, saving, created/updated, saved)\n *\n * @param data - Optional data to merge before saving\n * @param options - Save options\n * @returns The model instance for method chaining\n *\n * @throws {ValidationError} If validation fails\n * @throws {Error} If database operation fails\n *\n * @example\n * ```typescript\n * // Simple save\n * const user = new User({ name: \"Alice\" });\n * await user.save();\n *\n * // Merge data before saving\n * await user.save({ age: 31, email: \"alice@example.com\" });\n *\n * // Silent save (no events)\n * await user.save(null, { skipEvents: true });\n *\n * // Skip validation\n * await user.save(null, { skipValidation: true });\n *\n * // Method chaining\n * await user.set(\"name\", \"Bob\").save();\n * ```\n */\n public async save(options?: WriterOptions & { merge?: Partial<TSchema> }): Promise<this> {\n if (options?.merge) {\n this.merge(options.merge);\n }\n\n const writer = new DatabaseWriter(this);\n await writer.save(options);\n return this;\n }\n\n /**\n * Serialize the model data for storage in database\n */\n public serialize() {\n return this.self().getDataSource().driver.serialize(this.data);\n }\n\n /**\n * Deseriaze the given data\n */\n public static deserialize<TModel extends Model>(this: ChildModel<TModel>, data: any) {\n const deserializedData = this.getDataSource().driver.deserialize(data);\n\n const model = new this(deserializedData as any);\n model.isNew = false;\n\n return model;\n }\n\n /**\n * Convert the model into JSON\n */\n public toJSON() {\n const resource = this.self().resource;\n\n if (!resource) {\n const toJsonColumns = this.self().toJsonColumns;\n\n if (toJsonColumns && toJsonColumns.length > 0) {\n return this.only(toJsonColumns);\n }\n\n return this.data;\n }\n\n const resourceColumns = this.self().resourceColumns;\n\n const data =\n resourceColumns !== undefined && resourceColumns.length > 0\n ? this.only(resourceColumns)\n : this.data;\n\n return new resource(data).toJSON();\n }\n}\n","/**\n * Database-agnostic aggregation expressions.\n *\n * These helpers provide a unified API for building aggregate queries that work\n * across different database types (MongoDB, PostgreSQL, MySQL, etc.).\n *\n * Each driver implementation translates these abstract expressions to their\n * native format:\n * - MongoDB: { $sum: 1 }, { $sum: \"$field\" }, etc.\n * - SQL: COUNT(*), SUM(field), etc.\n *\n * @example\n * ```typescript\n * import { $agg } from '@warlock.js/cascade';\n *\n * // Works for both MongoDB and SQL\n * Lesson.query()\n * .groupBy(\"type\", {\n * count: $agg.count(),\n * total: $agg.sum(\"duration\"),\n * avg: $agg.avg(\"rating\")\n * })\n * .get();\n * ```\n */\n\n/**\n * Abstract aggregate expression format.\n *\n * This format is database-agnostic and will be translated by each driver\n * to their native syntax.\n */\nexport type AggregateExpression = {\n /** The aggregate function type */\n __agg: AggregateFunction;\n /** The field to aggregate (null for count) */\n __field: string | null;\n};\n\n/**\n * Supported aggregate functions.\n */\nexport type AggregateFunction =\n | \"count\"\n | \"sum\"\n | \"avg\"\n | \"min\"\n | \"max\"\n | \"first\"\n | \"last\"\n | \"distinct\"\n | \"floor\";\n\n/**\n * Checks if a value is an abstract aggregate expression.\n */\nexport function isAggregateExpression(value: unknown): value is AggregateExpression {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__field\" in value &&\n typeof (value as AggregateExpression).__agg === \"string\"\n );\n}\n\n/**\n * Database-agnostic aggregation expression helpers.\n *\n * These helpers create abstract expressions that each driver translates\n * to their native format.\n */\nexport const $agg = {\n /**\n * Count documents in each group.\n *\n * @returns Abstract count expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * count: $agg.count()\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $sum: 1 }`\n * - SQL: `COUNT(*)`\n */\n count(): AggregateExpression {\n return { __agg: \"count\", __field: null };\n },\n\n /**\n * Sum a numeric field across documents in each group.\n *\n * @param field - The field name to sum\n * @returns Abstract sum expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * totalDuration: $agg.sum(\"duration\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $sum: \"$duration\" }`\n * - SQL: `SUM(duration)`\n */\n sum(field: string): AggregateExpression {\n return { __agg: \"sum\", __field: field };\n },\n\n /**\n * Calculate the average value of a field across documents in each group.\n *\n * @param field - The field name to average\n * @returns Abstract average expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * avgRating: $agg.avg(\"rating\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $avg: \"$rating\" }`\n * - SQL: `AVG(rating)`\n */\n avg(field: string): AggregateExpression {\n return { __agg: \"avg\", __field: field };\n },\n\n /**\n * Get the minimum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract min expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * minPrice: $agg.min(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $min: \"$price\" }`\n * - SQL: `MIN(price)`\n */\n min(field: string): AggregateExpression {\n return { __agg: \"min\", __field: field };\n },\n\n /**\n * Get the maximum value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract max expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * maxPrice: $agg.max(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $max: \"$price\" }`\n * - SQL: `MAX(price)`\n */\n max(field: string): AggregateExpression {\n return { __agg: \"max\", __field: field };\n },\n\n /**\n * Get the distinct values of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract distinct expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * distinctColors: $agg.distinct(\"color\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $distinct: \"$color\" }`\n * - SQL: `DISTINCT(color)`\n */\n distinct(field: string): AggregateExpression {\n return { __agg: \"distinct\", __field: field };\n },\n\n /**\n * Get the floor value of a field across documents in each group.\n *\n * @param field - The field name\n * @returns Abstract floor expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * floorPrice: $agg.floor(\"price\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $floor: \"$price\" }`\n * - SQL: `FLOOR(price)`\n */\n floor(field: string): AggregateExpression {\n return { __agg: \"floor\", __field: field };\n },\n\n /**\n * Get the first value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract first expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * firstName: $agg.first(\"name\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $first: \"$name\" }`\n * - SQL: `FIRST_VALUE(name) OVER (...)`\n */\n first(field: string): AggregateExpression {\n return { __agg: \"first\", __field: field };\n },\n\n /**\n * Get the last value of a field in each group (order-dependent).\n *\n * @param field - The field name\n * @returns Abstract last expression\n *\n * @example\n * ```typescript\n * query.groupBy(\"type\", {\n * lastName: $agg.last(\"name\")\n * });\n * ```\n *\n * Translates to:\n * - MongoDB: `{ $last: \"$name\" }`\n * - SQL: `LAST_VALUE(name) OVER (...)`\n */\n last(field: string): AggregateExpression {\n return { __agg: \"last\", __field: field };\n },\n};\n","import type { GenerateIdOptions, IdGeneratorContract } from \"../../contracts\";\nimport type { MongoDbDriver } from \"./mongodb-driver\";\n\n/**\n * MongoDB-specific ID generator for auto-incrementing integer IDs.\n *\n * Maintains a separate collection that tracks the last generated ID for each table.\n * Generates auto-incrementing IDs similar to SQL's AUTO_INCREMENT feature.\n *\n * **Collection Structure:**\n * ```json\n * {\n * \"collection\": \"users\",\n * \"id\": 12345\n * }\n * ```\n *\n * **Features:**\n * - Atomic ID generation using findOneAndUpdate with aggregation pipeline\n * - Automatic transaction support (driver handles session context)\n * - Configurable initial ID and increment values\n * - Thread-safe and concurrent-safe\n *\n * @example\n * ```typescript\n * const mongoDriver = new MongoDbDriver(config);\n * const idGenerator = new MongoIdGenerator(mongoDriver);\n *\n * const dataSource = new DataSource({\n * name: \"primary\",\n * driver: mongoDriver,\n * idGenerator,\n * });\n *\n * // Generate IDs with custom configuration\n * const id = await idGenerator.generateNextId({\n * table: \"users\",\n * initialId: 1000,\n * incrementIdBy: 1\n * });\n * ```\n */\nexport class MongoIdGenerator implements IdGeneratorContract {\n /**\n * The collection name that stores ID counters.\n * Each document tracks the last ID for a specific table.\n *\n * Named \"MasterMind\" for backward compatibility with legacy Cascade.\n */\n public readonly counterCollection: string = \"MasterMind\";\n\n /**\n * Create a new MongoDB ID generator instance.\n *\n * @param driver - The MongoDB driver instance\n * @param counterCollection - Name of the collection storing ID counters (default: \"MasterMind\")\n *\n * @example\n * ```typescript\n * const idGenerator = new MongoIdGenerator(mongoDriver, \"id_counters\");\n * ```\n */\n public constructor(\n private readonly driver: MongoDbDriver,\n counterCollection?: string,\n ) {\n if (counterCollection) {\n this.counterCollection = counterCollection;\n }\n }\n\n /**\n * Generate the next ID for a table.\n *\n * Uses atomic findOneAndUpdate with aggregation pipeline to ensure uniqueness\n * even in concurrent scenarios. Automatically participates in active transactions.\n *\n * @param options - Configuration for ID generation\n * @returns The generated ID\n *\n * @example\n * ```typescript\n * // Simple usage\n * const id = await idGenerator.generateNextId({ table: \"users\" });\n *\n * // With custom initial ID\n * const id = await idGenerator.generateNextId({\n * table: \"products\",\n * initialId: 1000,\n * incrementIdBy: 1\n * });\n * ```\n */\n public async generateNextId(options: GenerateIdOptions): Promise<number> {\n const { table, initialId = 1, incrementIdBy = 1 } = options;\n\n // Get the MongoDB database instance\n const database = this.driver.getDatabase();\n const collection = database.collection(this.counterCollection);\n\n // Use atomic findOneAndUpdate with aggregation pipeline\n // The driver's withSession method will automatically attach the session if in a transaction\n const result = await collection.findOneAndUpdate(\n { collection: table },\n [\n {\n $set: {\n id: {\n $cond: {\n if: { $or: [{ $eq: [\"$id\", null] }, { $not: \"$id\" }] },\n then: initialId,\n else: { $add: [\"$id\", incrementIdBy] },\n },\n },\n collection: table,\n },\n },\n ],\n {\n upsert: true,\n returnDocument: \"after\",\n },\n );\n\n return result?.id ?? initialId;\n }\n\n /**\n * Get the last generated ID for a table.\n *\n * @param table - The table/collection name\n * @returns The last generated ID, or 0 if none exists\n *\n * @example\n * ```typescript\n * const lastId = await idGenerator.getLastId(\"users\");\n * console.log(`Last user ID: ${lastId}`);\n * ```\n */\n public async getLastId(table: string): Promise<number> {\n const query = this.driver.queryBuilder(this.counterCollection);\n const doc = (await query.where(\"collection\", table).first()) as Record<string, unknown> | null;\n return (doc?.id as number) ?? 0;\n }\n\n /**\n * Set the last ID for a table.\n *\n * Creates or updates the counter document for the specified table.\n * Useful for seeding or resetting ID sequences.\n *\n * @param table - The table/collection name\n * @param id - The ID to set as the last generated ID\n *\n * @example\n * ```typescript\n * // Reset user IDs to start from 1000\n * await idGenerator.setLastId(\"users\", 1000);\n * ```\n */\n public async setLastId(table: string, id: number): Promise<void> {\n await this.driver.update(\n this.counterCollection,\n { collection: table },\n { $set: { id, collection: table } },\n { upsert: true },\n );\n }\n}\n","import type { Operation, PipelineStage } from \"./types\";\n\n/**\n * Helper class for constructing MongoDB aggregation pipeline operations.\n *\n * This class encapsulates the logic for creating operation objects that will be\n * converted to MongoDB aggregation stages by the query parser. It provides a\n * clean abstraction over the low-level operation structure, making the query\n * builder code more maintainable and testable.\n *\n * Each operation consists of:\n * - **stage**: The MongoDB aggregation stage name (e.g., \"$match\", \"$project\")\n * - **type**: An internal identifier for the operation type\n * - **payload**: The data associated with the operation\n * - **mergeable**: Whether this operation can be merged with adjacent similar operations\n *\n * @internal This class is for internal use within the MongoDB driver\n *\n * @example\n * ```typescript\n * const operations: Operation[] = [];\n * const helper = new MongoQueryOperations(operations);\n *\n * // Add a match operation\n * helper.addMatchOperation(\"whereIn\", { field: \"status\", values: [\"active\", \"pending\"] });\n *\n * // Add a project operation\n * helper.addProjectOperation(\"select\", { fields: [\"name\", \"email\"] });\n *\n * // Operations array is now populated\n * console.log(operations);\n * // [\n * // { stage: \"$match\", mergeable: true, type: \"whereIn\", payload: {...} },\n * // { stage: \"$project\", mergeable: true, type: \"select\", payload: {...} }\n * // ]\n * ```\n */\nexport class MongoQueryOperations {\n /**\n * Creates a new operations helper.\n *\n * The helper maintains a reference to the operations array and populates it\n * as methods are called. This allows the query builder to maintain a single\n * ordered list of operations that will be converted to a MongoDB aggregation\n * pipeline.\n *\n * @param operations - Reference to the operations array to populate\n *\n * @example\n * ```typescript\n * const operations: Operation[] = [];\n * const helper = new MongoQueryOperations(operations);\n * ```\n */\n public constructor(private operations: Operation[]) {}\n\n public setOperations(operations: Operation[]): void {\n this.operations = operations;\n }\n\n /**\n * Adds a $match stage operation to the pipeline.\n *\n * Match operations filter documents in the aggregation pipeline, similar to\n * the WHERE clause in SQL. Multiple match operations can be merged together\n * by the parser for optimization.\n *\n * @param type - The operation type identifier (e.g., \"where\", \"whereIn\", \"whereLike\")\n * @param payload - The operation payload data containing filter criteria\n * @param mergeable - Whether this operation can be merged with adjacent match operations (default: true)\n *\n * @example\n * ```typescript\n * // Simple where operation\n * helper.addMatchOperation(\"where\", { field: \"age\", operator: \">\", value: 18 });\n *\n * // WhereIn operation\n * helper.addMatchOperation(\"whereIn\", { field: \"status\", values: [\"active\", \"pending\"] });\n *\n * // Non-mergeable match (e.g., after a group stage)\n * helper.addMatchOperation(\"having\", { field: \"count\", operator: \">\", value: 5 }, false);\n * ```\n */\n public addMatchOperation(type: string, payload: Record<string, unknown>, mergeable = true): void {\n this.operations.push({\n stage: \"$match\",\n mergeable,\n type,\n payload,\n });\n }\n\n /**\n * Adds a $project stage operation to the pipeline.\n *\n * Project operations control which fields are included or excluded in the\n * output documents, similar to the SELECT clause in SQL. They can also be\n * used to compute new fields or reshape documents.\n *\n * @param type - The operation type identifier (e.g., \"select\", \"deselect\", \"selectRaw\")\n * @param payload - The operation payload data containing projection specifications\n * @param mergeable - Whether this operation can be merged with adjacent project operations (default: true)\n *\n * @example\n * ```typescript\n * // Select specific fields\n * helper.addProjectOperation(\"select\", { fields: [\"name\", \"email\", \"age\"] });\n *\n * // Deselect fields\n * helper.addProjectOperation(\"deselect\", { fields: [\"password\", \"secret\"] });\n *\n * // Computed field\n * helper.addProjectOperation(\"selectRaw\", {\n * expression: { fullName: { $concat: [\"$firstName\", \" \", \"$lastName\"] } }\n * });\n * ```\n */\n public addProjectOperation(\n type: string,\n payload: Record<string, unknown>,\n mergeable = true,\n ): void {\n this.operations.push({\n stage: \"$project\",\n mergeable,\n type,\n payload,\n });\n }\n\n /**\n * Adds a $sort stage operation to the pipeline.\n *\n * Sort operations order the documents in the pipeline, similar to the ORDER BY\n * clause in SQL. Multiple sort operations can be merged to create compound\n * sorting.\n *\n * @param type - The operation type identifier (e.g., \"orderBy\", \"orderByRandom\")\n * @param payload - The operation payload data containing sort specifications\n * @param mergeable - Whether this operation can be merged with adjacent sort operations (default: true)\n *\n * @example\n * ```typescript\n * // Order by a single field\n * helper.addSortOperation(\"orderBy\", { field: \"createdAt\", direction: \"desc\" });\n *\n * // Random ordering (not mergeable)\n * helper.addSortOperation(\"orderByRandom\", {limit: 1000}, false);\n *\n * // Order by raw expression\n * helper.addSortOperation(\"orderByRaw\", {\n * expression: { score: -1, name: 1 }\n * });\n * ```\n */\n public addSortOperation(type: string, payload: Record<string, unknown>, mergeable = true): void {\n this.operations.push({\n stage: \"$sort\",\n mergeable,\n type,\n payload,\n });\n }\n\n /**\n * Adds a $group stage operation to the pipeline.\n *\n * Group operations aggregate documents by specified fields and compute\n * aggregate values, similar to the GROUP BY clause in SQL. Group operations\n * are typically not mergeable as they represent distinct aggregation boundaries.\n *\n * @param type - The operation type identifier (e.g., \"groupBy\", \"distinct\")\n * @param payload - The operation payload data containing grouping specifications\n * @param mergeable - Whether this operation can be merged with adjacent group operations (default: false)\n *\n * @example\n * ```typescript\n * // Group by a single field\n * helper.addGroupOperation(\"groupBy\", { fields: \"category\" });\n *\n * // Group by multiple fields\n * helper.addGroupOperation(\"groupBy\", {\n * fields: { category: \"$category\", status: \"$status\" }\n * });\n *\n * // Distinct operation (special case of grouping)\n * helper.addGroupOperation(\"distinct\", { fields: [\"email\"] });\n * ```\n */\n public addGroupOperation(\n type: string,\n payload: Record<string, unknown>,\n mergeable = false,\n ): void {\n this.operations.push({\n stage: \"$group\",\n mergeable,\n type,\n payload,\n });\n }\n\n /**\n * Adds a $lookup stage operation to the pipeline.\n *\n * Lookup operations perform left outer joins with other collections, similar\n * to JOIN in SQL. Lookup operations are never mergeable as each represents a\n * distinct join operation.\n *\n * @param type - The operation type identifier (typically \"join\")\n * @param payload - The operation payload data containing join specifications\n *\n * @example\n * ```typescript\n * // Simple lookup\n * helper.addLookupOperation(\"join\", {\n * table: \"orders\",\n * localField: \"id\",\n * foreignField: \"userId\",\n * alias: \"userOrders\"\n * });\n *\n * // Lookup with pipeline\n * helper.addLookupOperation(\"join\", {\n * table: \"products\",\n * pipeline: [\n * { $match: { inStock: true } },\n * { $sort: { price: 1 } }\n * ],\n * alias: \"availableProducts\"\n * });\n * ```\n */\n public addLookupOperation(type: string, payload: Record<string, unknown>): void {\n this.operations.push({\n stage: \"$lookup\",\n mergeable: false,\n type,\n payload,\n });\n }\n\n /**\n * Adds a generic stage operation to the pipeline.\n *\n * This method provides flexibility to add any MongoDB aggregation stage,\n * including less common stages like $facet, $bucket, $setWindowFields, etc.\n * Use this for operations that don't fit into the standard categories.\n *\n * @param stage - The MongoDB aggregation stage name (e.g., \"$limit\", \"$skip\", \"$unwind\")\n * @param type - The operation type identifier\n * @param payload - The operation payload data\n * @param mergeable - Whether this operation can be merged with adjacent operations (default: false)\n *\n * @example\n * ```typescript\n * // Add a limit operation\n * helper.addOperation(\"$limit\", \"limit\", { value: 10 });\n *\n * // Add a skip operation\n * helper.addOperation(\"$skip\", \"skip\", { value: 20 });\n *\n * // Add an unwind operation\n * helper.addOperation(\"$unwind\", \"unwind\", { path: \"$tags\" });\n *\n * // Add a window function\n * helper.addOperation(\"$setWindowFields\", \"selectWindow\", {\n * spec: {\n * partitionBy: \"$category\",\n * sortBy: { price: 1 },\n * output: { rank: { $rank: {} } }\n * }\n * });\n * ```\n */\n public addOperation(\n stage: PipelineStage,\n type: string,\n payload: Record<string, unknown>,\n mergeable = false,\n ): void {\n this.operations.push({\n stage,\n mergeable,\n type,\n payload,\n });\n }\n}\n","import { colors } from \"@mongez/copper\";\nimport type { Collection } from \"mongodb\";\nimport type { GroupByInput, RawExpression, WhereOperator } from \"../../contracts\";\nimport {\n isAggregateExpression,\n type AggregateExpression,\n} from \"../../expressions/aggregate-expressions\";\nimport type { MongoQueryBuilder } from \"./mongo-query-builder\";\nimport type { Operation, PipelineStage } from \"./types\";\n\n/**\n * Options for configuring the MongoDB query parser.\n */\nexport type MongoQueryParserOptions = {\n /** The MongoDB collection being queried */\n collection: Collection;\n /** The ordered list of operations to parse */\n operations: Operation[];\n /** Factory method for creating sub-builders (used for callbacks) */\n createSubBuilder: () => MongoQueryBuilder;\n};\n\n/**\n * Parses query builder operations into MongoDB aggregation pipeline.\n *\n * This parser is responsible for converting the abstract operations collected\n * by the query builder into a concrete MongoDB aggregation pipeline. It handles\n * intelligent grouping of mergeable operations (like multiple where clauses)\n * into single pipeline stages for optimal performance.\n */\nexport class MongoQueryParser {\n /**\n * The MongoDB collection being queried.\n */\n private readonly collection: Collection;\n\n /**\n * The ordered list of operations to parse.\n */\n private readonly operations: Operation[];\n\n /**\n * Factory for creating sub-builders (used when resolving callbacks).\n */\n private readonly createSubBuilder: () => MongoQueryBuilder;\n\n /**\n * Track group field names for automatic _id renaming.\n * Maps pipeline index to field names.\n */\n private readonly groupFieldNames = new Map<number, string | string[]>();\n\n /**\n * Create a new MongoDB query parser.\n *\n * @param options - Configuration options for the parser\n */\n public constructor(options: MongoQueryParserOptions) {\n this.collection = options.collection;\n this.operations = options.operations;\n this.createSubBuilder = options.createSubBuilder;\n }\n\n /**\n * Parse the operations into a MongoDB aggregation pipeline.\n *\n * This method intelligently groups mergeable operations (e.g., multiple where\n * clauses) into single pipeline stages while maintaining the correct execution\n * order for non-mergeable operations.\n *\n * @returns The MongoDB aggregation pipeline\n *\n * @example\n * ```typescript\n * const parser = new MongoQueryParser({ collection, operations });\n * const pipeline = parser.parse();\n * // [\n * // { $match: { status: 'active', age: { $gt: 18 } } },\n * // { $sort: { createdAt: -1 } },\n * // { $limit: 10 }\n * // ]\n * ```\n */\n public parse(): any[] {\n const pipeline: any[] = [];\n let currentStage: PipelineStage | null = null;\n let currentBuffer: Operation[] = [];\n\n for (const op of this.operations) {\n if (op.mergeable && op.stage === currentStage) {\n // Same mergeable stage, add to buffer\n currentBuffer.push(op);\n } else {\n // Different stage or non-mergeable, flush buffer\n if (currentBuffer.length > 0) {\n const builtStage = this.buildStage(currentStage!, currentBuffer);\n if (builtStage) {\n const stageIndex = pipeline.length;\n pipeline.push(builtStage);\n // Track field names for group stages with aggregates\n this.trackGroupFieldNames(currentStage!, currentBuffer, stageIndex);\n }\n currentBuffer = [];\n }\n\n if (op.mergeable) {\n // Start new buffer\n currentStage = op.stage;\n currentBuffer.push(op);\n } else {\n // Non-mergeable, add directly\n const builtStage = this.buildStage(op.stage, [op]);\n if (builtStage) {\n const stageIndex = pipeline.length;\n pipeline.push(builtStage);\n // Track field names for group stages with aggregates\n this.trackGroupFieldNames(op.stage, [op], stageIndex);\n }\n currentStage = null;\n }\n }\n }\n\n // Flush remaining buffer\n if (currentBuffer.length > 0) {\n const builtStage = this.buildStage(currentStage!, currentBuffer);\n if (builtStage) {\n const stageIndex = pipeline.length;\n pipeline.push(builtStage);\n // Track field names for group stages with aggregates\n this.trackGroupFieldNames(currentStage!, currentBuffer, stageIndex);\n }\n }\n\n // Post-process: Rename _id to actual field names after $group stages with aggregates\n return this.postProcessGroupStages(pipeline);\n }\n\n /**\n * Track field names for group stages that need _id renaming.\n */\n private trackGroupFieldNames(\n stage: PipelineStage,\n operations: Operation[],\n stageIndex: number,\n ): void {\n if (stage === \"$group\") {\n const op = operations[0];\n if (op.type === \"groupByWithAggregates\" && op.payload.fields) {\n const fieldNames = this.extractGroupFieldNames(op.payload.fields);\n if (fieldNames) {\n this.groupFieldNames.set(stageIndex, fieldNames);\n }\n }\n }\n }\n\n /**\n * Post-process pipeline to rename _id fields after $group stages.\n *\n * This automatically renames MongoDB's `_id` field to the actual field name(s)\n * used for grouping, making the results more intuitive.\n *\n * @param pipeline - The aggregation pipeline\n * @returns The processed pipeline\n */\n private postProcessGroupStages(pipeline: any[]): any[] {\n const processed: any[] = [];\n\n for (let i = 0; i < pipeline.length; i++) {\n const stage = pipeline[i];\n\n // Check if this is a $group stage that needs _id renaming\n if (stage.$group && this.groupFieldNames.has(i)) {\n const fieldNames = this.groupFieldNames.get(i)!;\n\n // Add the $group stage\n processed.push(stage);\n\n // Add a $project stage to rename _id\n const projection: Record<string, unknown> = {};\n\n if (typeof fieldNames === \"string\") {\n // Single field: rename _id to field name\n projection[fieldNames] = \"$_id\";\n } else if (Array.isArray(fieldNames) && fieldNames.length > 0) {\n // Multiple fields: _id is an object, spread it\n for (const fieldName of fieldNames) {\n projection[fieldName] = `$_id.${fieldName}`;\n }\n }\n\n // Include all aggregate fields\n const aggregateFields = Object.keys(stage.$group).filter((key) => key !== \"_id\");\n for (const field of aggregateFields) {\n projection[field] = 1;\n }\n\n if (Object.keys(projection).length > 0) {\n // now unselect the _id field\n projection._id = 0;\n processed.push({ $project: projection });\n }\n } else {\n // Regular stage, add as-is\n processed.push(stage);\n }\n }\n\n return processed;\n }\n\n /**\n * Convert the parsed pipeline to a pretty-printed string for debugging.\n *\n * This method formats the MongoDB aggregation pipeline in a human-readable\n * way, making it easier to understand and debug complex queries.\n *\n * @returns A formatted string representation of the pipeline\n *\n * @example\n * ```typescript\n * const parser = new MongoQueryParser({ collection, operations });\n * console.log(parser.toPrettyString());\n * // Output:\n * // MongoDB Aggregation Pipeline:\n * // ════════════════════════════\n * // Stage 1: $match\n * // status: \"active\"\n * // age: { $gt: 18 }\n * //\n * // Stage 2: $sort\n * // createdAt: -1\n * ```\n */\n public toPrettyString(): string {\n const pipeline = this.parse();\n\n if (pipeline.length === 0) {\n return \"MongoDB Aggregation Pipeline: (empty)\";\n }\n\n let output = \"MongoDB Aggregation Pipeline:\\n\";\n output += \"═\".repeat(50) + \"\\n\";\n\n pipeline.forEach((stage, index) => {\n const stageName = Object.keys(stage)[0];\n const stageData = stage[stageName];\n\n if (index > 0) {\n output += \"\\n\";\n }\n\n output += `Stage ${index + 1}: ${colors.redBright(stageName)}\\n`;\n output += this.formatStageData(stageData, 2);\n });\n\n return output;\n }\n\n /**\n * Format stage data with proper indentation.\n *\n * @param data - The stage data to format\n * @param indent - The indentation level\n * @returns Formatted string\n */\n private formatStageData(data: any, indent: number = 0): string {\n const spaces = \" \".repeat(indent);\n\n if (typeof data !== \"object\" || data === null) {\n return `${spaces}${JSON.stringify(data)}\\n`;\n }\n\n if (Array.isArray(data)) {\n if (data.length === 0) return `${spaces}[]`;\n\n let result = \"\";\n data.forEach((item, index) => {\n result += `${spaces}[${colors.magenta(index)}]:\\n`;\n result += this.formatStageData(item, indent + 2);\n });\n return result;\n }\n\n let result = \"\";\n Object.entries(data).forEach(([key, value]) => {\n const isOperator = key.startsWith(\"$\");\n const coloredKey = isOperator ? colors.magentaBright(key) : colors.blue(key);\n\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n result += `${spaces}${coloredKey}:\\n`;\n result += this.formatStageData(value, indent + 2);\n } else if (Array.isArray(value)) {\n result += `${spaces}${coloredKey}:\\n`;\n result += this.formatStageData(value, indent + 2);\n } else {\n const formattedValue =\n typeof value === \"number\"\n ? colors.yellowBright(value)\n : typeof value === \"boolean\"\n ? colors.cyanBright(value.toString())\n : typeof value === \"string\"\n ? colors.greenBright(JSON.stringify(value))\n : colors.greenBright(String(value));\n result += `${spaces}${coloredKey}: ${formattedValue}\\n`;\n }\n });\n\n return result.endsWith(\"\\n\") ? result : `${result}\\n`;\n }\n\n /**\n * Build a single pipeline stage from a group of operations.\n *\n * @param stage - The pipeline stage type\n * @param operations - The operations to build the stage from\n * @returns The built pipeline stage or null if no stage should be added\n */\n private buildStage(stage: PipelineStage, operations: Operation[]): any {\n switch (stage) {\n case \"$match\":\n return this.buildMatchStage(operations);\n case \"$project\":\n return this.buildProjectStage(operations);\n case \"$sort\":\n return this.buildSortStage(operations);\n case \"$group\":\n return this.buildGroupStage(operations);\n case \"$lookup\":\n return this.buildLookupStage(operations);\n case \"$limit\":\n return { $limit: operations[0].payload.value };\n case \"$skip\":\n return { $skip: operations[0].payload.value };\n case \"$setWindowFields\":\n return {\n $setWindowFields: operations[0].payload.spec,\n };\n default:\n return null;\n }\n }\n\n /**\n * Build a $match stage from where operations.\n *\n * Query building strategy:\n * - Top-level where() + orWhere() = Pure OR\n * - Use callbacks for AND + OR grouping\n *\n * @param operations - The where operations\n * @returns The $match stage or null\n */\n private buildMatchStage(operations: Operation[]): any {\n const andFilter: Record<string, any> = {};\n const orClauses: any[] = [];\n const pendingSimpleWhere: any[] = [];\n let topLevelOrMode = false;\n\n const pushOr = (clause: any): void => {\n if (!clause) {\n return;\n }\n\n if (this.isPureOrCondition(clause)) {\n orClauses.push(...clause.$or);\n return;\n }\n\n if (Array.isArray(clause)) {\n orClauses.push(...clause);\n return;\n }\n\n orClauses.push(clause);\n };\n\n const mergeAnd = (condition: any): void => {\n if (!condition) {\n return;\n }\n\n Object.entries(condition).forEach(([key, value]) => {\n if (key === \"$or\") {\n pushOr(value);\n return;\n }\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n andFilter[key] &&\n typeof andFilter[key] === \"object\" &&\n !Array.isArray(andFilter[key])\n ) {\n andFilter[key] = { ...andFilter[key], ...value };\n } else {\n andFilter[key] = value;\n }\n });\n };\n\n const queueSimpleWhere = (condition: any): void => {\n if (!condition) {\n return;\n }\n if (topLevelOrMode) {\n pushOr(condition);\n } else {\n pendingSimpleWhere.push(condition);\n }\n };\n\n const enterTopLevelOrMode = (): void => {\n if (topLevelOrMode) {\n return;\n }\n topLevelOrMode = true;\n while (pendingSimpleWhere.length > 0) {\n const condition = pendingSimpleWhere.shift();\n if (condition) {\n pushOr(condition);\n }\n }\n };\n\n const flushPendingSimpleWhere = (): void => {\n if (pendingSimpleWhere.length === 0) {\n return;\n }\n if (topLevelOrMode) {\n pendingSimpleWhere.forEach(pushOr);\n } else {\n pendingSimpleWhere.forEach(mergeAnd);\n }\n pendingSimpleWhere.length = 0;\n };\n\n for (const op of operations) {\n if (op.type === \"where:callback\" || op.type === \"orWhere:callback\") {\n flushPendingSimpleWhere();\n const callbackCondition = this.buildCallbackCondition(op.payload);\n if (!callbackCondition) {\n continue;\n }\n\n const treatAsOr =\n op.type === \"orWhere:callback\" ||\n (topLevelOrMode && !this.isPureOrCondition(callbackCondition)) ||\n this.isPureOrCondition(callbackCondition);\n\n if (treatAsOr) {\n if (op.type === \"orWhere:callback\") {\n enterTopLevelOrMode();\n }\n pushOr(callbackCondition);\n } else {\n mergeAnd(callbackCondition);\n }\n continue;\n }\n\n if (op.type === \"where:object\") {\n queueSimpleWhere(op.payload);\n continue;\n }\n\n if (\n op.type === \"where:not\" ||\n op.type === \"orWhere:not\" ||\n op.type === \"where:exists\" ||\n op.type === \"where:notExists\"\n ) {\n const negated = op.type === \"where:not\" || op.type === \"where:notExists\";\n const nested = this.buildCallbackCondition(op.payload.callback);\n if (nested) {\n const condition = negated ? { $nor: [nested] } : nested;\n if (op.type.startsWith(\"orWhere\")) {\n enterTopLevelOrMode();\n pushOr(condition);\n } else {\n queueSimpleWhere(condition);\n }\n }\n continue;\n }\n\n if (op.type === \"orWhere:object\") {\n enterTopLevelOrMode();\n pushOr(op.payload);\n continue;\n }\n\n const condition = this.buildWhereCondition(op);\n if (!condition) {\n continue;\n }\n\n if (op.type.startsWith(\"orWhere\")) {\n enterTopLevelOrMode();\n pushOr(condition);\n } else {\n queueSimpleWhere(condition);\n }\n }\n\n flushPendingSimpleWhere();\n\n const hasAnd = Object.keys(andFilter).length > 0;\n const hasOr = orClauses.length > 0;\n\n if (!hasAnd && !hasOr) {\n return null;\n }\n\n const match: any = {};\n if (hasAnd) {\n Object.assign(match, andFilter);\n }\n if (hasOr) {\n match.$or = orClauses;\n }\n\n return { $match: match };\n }\n\n private isPureOrCondition(condition: any): condition is { $or: any[] } {\n return (\n condition &&\n typeof condition === \"object\" &&\n !Array.isArray(condition) &&\n Object.keys(condition).length === 1 &&\n Array.isArray((condition as any).$or)\n );\n }\n\n /**\n * Build a condition from a callback-based where clause.\n * Creates a sub-builder, executes the callback, and extracts the conditions.\n * If callback has orWhere, all conditions become OR.\n *\n * @param callback - The callback function\n * @returns The built condition or null\n */\n private buildCallbackCondition(callback: any): any {\n // Create a temporary sub-builder\n const subBuilder = this.createSubBuilder();\n\n // Execute the callback with the sub-builder\n callback(subBuilder);\n\n // Extract only match operations from the sub-builder\n const matchOps = subBuilder.operations.filter((op: Operation) => op.stage === \"$match\");\n\n if (matchOps.length === 0) {\n return null;\n }\n\n const andFilter: Record<string, any> = {};\n const orClauses: any[] = [];\n const hasInternalOr = matchOps.some((op) => op.type.startsWith(\"orWhere\"));\n\n const pushOr = (clause: any): void => {\n if (!clause) {\n return;\n }\n if (this.isPureOrCondition(clause)) {\n orClauses.push(...clause.$or);\n return;\n }\n orClauses.push(clause);\n };\n\n if (hasInternalOr) {\n for (const op of matchOps) {\n if (op.type === \"where:callback\" || op.type === \"orWhere:callback\") {\n const nestedCondition = this.buildCallbackCondition(op.payload);\n if (nestedCondition) {\n pushOr(nestedCondition);\n }\n continue;\n }\n\n if (op.type === \"where:object\" || op.type === \"orWhere:object\") {\n pushOr(op.payload);\n continue;\n }\n\n const condition = this.buildWhereCondition(op);\n if (condition) {\n pushOr(condition);\n }\n }\n\n return orClauses.length > 0 ? { $or: orClauses } : null;\n }\n\n for (const op of matchOps) {\n if (op.type === \"where:callback\") {\n const nestedCondition = this.buildCallbackCondition(op.payload);\n if (nestedCondition) {\n Object.assign(andFilter, nestedCondition);\n }\n } else if (op.type === \"where:object\") {\n Object.assign(andFilter, op.payload);\n } else {\n const condition = this.buildWhereCondition(op);\n if (condition) {\n Object.assign(andFilter, condition);\n }\n }\n }\n\n return Object.keys(andFilter).length > 0 ? andFilter : null;\n }\n\n /**\n * Build a MongoDB filter condition from a where operation.\n *\n * @param op - The operation to build\n * @returns The MongoDB filter condition\n */\n private buildWhereCondition(op: Operation): any {\n const { field, operator, value } = op.payload;\n\n switch (op.type) {\n case \"where\":\n case \"orWhere\":\n return this.buildOperatorCondition(field, operator, value);\n\n case \"whereIn\":\n return { [field]: { $in: value || op.payload.values } };\n\n case \"whereNotIn\":\n return { [field]: { $nin: value || op.payload.values } };\n\n case \"whereNull\":\n return { [field]: null };\n\n case \"whereNotNull\":\n return { [field]: { $ne: null } };\n\n case \"whereBetween\":\n return {\n [field]: {\n $gte: op.payload.range[0],\n $lte: op.payload.range[1],\n },\n };\n\n case \"whereNotBetween\":\n return {\n [field]: {\n $not: {\n $gte: op.payload.range[0],\n $lte: op.payload.range[1],\n },\n },\n };\n\n case \"whereLike\": {\n const pattern =\n typeof op.payload.pattern === \"string\" ? op.payload.pattern : op.payload.pattern.source;\n return { [field]: { $regex: pattern, $options: \"i\" } };\n }\n\n case \"whereNotLike\": {\n const notPattern =\n typeof op.payload.pattern === \"string\" ? op.payload.pattern : op.payload.pattern.source;\n return { [field]: { $not: { $regex: notPattern, $options: \"i\" } } };\n }\n\n case \"whereStartsWith\":\n return { [field]: { $regex: `^${op.payload.value}`, $options: \"i\" } };\n\n case \"whereNotStartsWith\":\n return {\n [field]: { $not: { $regex: `^${op.payload.value}`, $options: \"i\" } },\n };\n\n case \"whereEndsWith\":\n return { [field]: { $regex: `${op.payload.value}$`, $options: \"i\" } };\n\n case \"whereNotEndsWith\":\n return {\n [field]: { $not: { $regex: `${op.payload.value}$`, $options: \"i\" } },\n };\n\n case \"whereExists\":\n return { [field]: { $exists: true } };\n\n case \"whereNotExists\":\n return { [field]: { $exists: false } };\n\n case \"whereSize\":\n if (op.payload.operator === \"=\") {\n return { [field]: { $size: op.payload.size } };\n } else {\n const mongoOp = this.getMongoOperator(op.payload.operator);\n return {\n $expr: {\n [mongoOp]: [{ $size: `$${field}` }, op.payload.size],\n },\n };\n }\n\n case \"textSearch\":\n return {\n $text: { $search: op.payload.query },\n ...(op.payload.filters || {}),\n };\n\n case \"whereRaw\":\n case \"orWhereRaw\":\n return this.resolveRawExpression(\n op.payload.expression as RawExpression,\n op.payload.bindings,\n );\n\n case \"whereColumn\":\n case \"orWhereColumn\":\n return this.buildColumnComparison(op.payload.first, op.payload.operator, op.payload.second);\n\n case \"whereBetweenColumns\":\n return this.buildBetweenColumnsCondition(\n op.payload.field,\n op.payload.lowerColumn,\n op.payload.upperColumn,\n );\n\n case \"whereDate\":\n case \"whereDateEquals\":\n return this.buildDateEqualityCondition(op.payload.field, op.payload.value);\n\n case \"whereDateBefore\":\n return this.buildDateBeforeCondition(op.payload.field, op.payload.value);\n\n case \"whereDateAfter\":\n return this.buildDateAfterCondition(op.payload.field, op.payload.value);\n\n case \"whereTime\":\n return this.buildTimeCondition(op.payload.field, op.payload.value);\n\n case \"whereDay\":\n return this.buildDatePartCondition(op.payload.field, \"$dayOfMonth\", op.payload.value);\n\n case \"whereMonth\":\n return this.buildDatePartCondition(op.payload.field, \"$month\", op.payload.value);\n\n case \"whereYear\":\n return this.buildDatePartCondition(op.payload.field, \"$year\", op.payload.value);\n\n case \"whereJsonContains\":\n return this.buildJsonContainsCondition(op.payload.path, op.payload.value);\n\n case \"whereJsonDoesntContain\":\n return this.buildJsonDoesntContainCondition(op.payload.path, op.payload.value);\n\n case \"whereJsonContainsKey\":\n return this.buildJsonContainsKeyCondition(op.payload.path);\n\n case \"whereJsonLength\":\n return this.buildJsonLengthCondition(\n op.payload.path,\n op.payload.operator,\n op.payload.value,\n );\n\n case \"whereJsonIsArray\":\n return this.buildJsonTypeCondition(op.payload.path, \"array\");\n\n case \"whereJsonIsObject\":\n return this.buildJsonTypeCondition(op.payload.path, \"object\");\n\n case \"whereArrayLength\":\n return this.buildArrayLengthCondition(\n op.payload.field,\n op.payload.operator,\n op.payload.value,\n );\n\n case \"whereFullText\":\n case \"orWhereFullText\":\n return { $text: { $search: op.payload.query } };\n\n case \"whereSearch\":\n return {\n [op.payload.field]: {\n $regex: op.payload.query,\n $options: \"i\",\n },\n };\n\n case \"where:not\":\n case \"orWhere:not\": {\n const nestedNot = this.buildCallbackCondition(op.payload.callback);\n return nestedNot ? { $nor: [nestedNot] } : null;\n }\n\n case \"where:exists\":\n return this.buildCallbackCondition(op.payload.callback);\n\n case \"where:notExists\": {\n const nestedExists = this.buildCallbackCondition(op.payload.callback);\n return nestedExists ? { $nor: [nestedExists] } : null;\n }\n\n case \"whereArrayContains\":\n if (op.payload.key) {\n return {\n [field]: {\n $elemMatch: { [op.payload.key]: op.payload.value },\n },\n };\n } else {\n return { [field]: op.payload.value };\n }\n\n default:\n return null;\n }\n }\n\n /**\n * Build a condition based on the operator.\n *\n * @param field - The field name\n * @param operator - The comparison operator\n * @param value - The value to compare\n * @returns The MongoDB filter condition\n */\n private buildOperatorCondition(field: string, operator: string, value: unknown): any {\n switch (operator) {\n case \"=\":\n return { [field]: value };\n case \"!=\":\n return { [field]: { $ne: value } };\n case \">\":\n return { [field]: { $gt: value } };\n case \">=\":\n return { [field]: { $gte: value } };\n case \"<\":\n return { [field]: { $lt: value } };\n case \"<=\":\n return { [field]: { $lte: value } };\n default:\n return { [field]: value };\n }\n }\n\n /**\n * Get MongoDB operator from comparison operator.\n *\n * @param operator - The comparison operator\n * @returns The MongoDB operator\n */\n private getMongoOperator(operator: string): string {\n const map: Record<string, string> = {\n \"=\": \"$eq\",\n \"!=\": \"$ne\",\n \">\": \"$gt\",\n \">=\": \"$gte\",\n \"<\": \"$lt\",\n \"<=\": \"$lte\",\n };\n return map[operator] || \"$eq\";\n }\n\n private resolveRawExpression(expression: RawExpression, bindings?: unknown[]): any {\n if (typeof expression === \"string\") {\n const bound = this.bindRawString(expression, bindings);\n return { $where: bound };\n }\n\n if (typeof expression === \"object\" && expression !== null) {\n return expression;\n }\n\n return null;\n }\n\n private bindRawString(expression: string, bindings?: unknown[]): string {\n if (!bindings || bindings.length === 0) {\n return expression;\n }\n\n let index = 0;\n return expression.replace(/\\?/g, () => {\n const value = bindings[index++];\n return value === undefined ? \"?\" : JSON.stringify(value);\n });\n }\n\n private buildColumnComparison(first: string, operator: WhereOperator, second: string): any {\n const mongoOperator = this.getMongoOperator(operator);\n return {\n $expr: {\n [mongoOperator]: [this.wrapColumn(first), this.wrapColumn(second)],\n },\n };\n }\n\n private buildBetweenColumnsCondition(field: string, lower: string, upper: string): any {\n return {\n $expr: {\n $and: [\n { $gte: [this.wrapColumn(field), this.wrapColumn(lower)] },\n { $lte: [this.wrapColumn(field), this.wrapColumn(upper)] },\n ],\n },\n };\n }\n\n private wrapColumn(column: string): string {\n return column.startsWith(\"$\") ? column : `$${column}`;\n }\n\n private buildDateEqualityCondition(field: string, value: Date | string): any {\n const target = this.normalizeDateInput(value);\n const start = this.startOfDay(target);\n const end = this.endOfDay(target);\n return { [field]: { $gte: start, $lte: end } };\n }\n\n private buildDateBeforeCondition(field: string, value: Date | string): any {\n const target = this.startOfDay(this.normalizeDateInput(value));\n return { [field]: { $lt: target } };\n }\n\n private buildDateAfterCondition(field: string, value: Date | string): any {\n const target = this.endOfDay(this.normalizeDateInput(value));\n return { [field]: { $gt: target } };\n }\n\n private buildTimeCondition(field: string, value: string): any {\n return {\n $expr: {\n $eq: [\n {\n $dateToString: {\n format: \"%H:%M\",\n date: `$${field}`,\n },\n },\n value,\n ],\n },\n };\n }\n\n private buildDatePartCondition(\n field: string,\n operator: \"$dayOfMonth\" | \"$month\" | \"$year\",\n value: number,\n ): any {\n return {\n $expr: {\n $eq: [\n {\n [operator]: `$${field}`,\n },\n value,\n ],\n },\n };\n }\n\n private buildJsonContainsCondition(path: string, value: unknown): any {\n const fieldPath = this.normalizePath(path);\n if (Array.isArray(value)) {\n return { [fieldPath]: { $all: value } };\n }\n return { [fieldPath]: value };\n }\n\n private buildJsonDoesntContainCondition(path: string, value: unknown): any {\n const fieldPath = this.normalizePath(path);\n const values = Array.isArray(value) ? value : [value];\n return { [fieldPath]: { $nin: values } };\n }\n\n private buildJsonContainsKeyCondition(path: string): any {\n return {\n [this.normalizePath(path)]: { $exists: true },\n };\n }\n\n private buildJsonLengthCondition(path: string, operator: WhereOperator, value: number): any {\n const mongoOperator = this.getMongoOperator(operator);\n return {\n $expr: {\n [mongoOperator]: [{ $size: { $ifNull: [`$${this.normalizePath(path)}`, []] } }, value],\n },\n };\n }\n\n private buildJsonTypeCondition(path: string, type: string): any {\n return {\n $expr: {\n $eq: [{ $type: `$${this.normalizePath(path)}` }, type],\n },\n };\n }\n\n private buildArrayLengthCondition(field: string, operator: WhereOperator, value: number): any {\n const mongoOperator = this.getMongoOperator(operator);\n return {\n $expr: {\n [mongoOperator]: [{ $size: { $ifNull: [`$${field}`, []] } }, value],\n },\n };\n }\n\n private normalizeDateInput(value: Date | string): Date {\n if (value instanceof Date) {\n return value;\n }\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(`Invalid date value: ${value}`);\n }\n return parsed;\n }\n\n private startOfDay(date: Date): Date {\n const copy = new Date(date);\n copy.setHours(0, 0, 0, 0);\n return copy;\n }\n\n private endOfDay(date: Date): Date {\n const copy = new Date(date);\n copy.setHours(23, 59, 59, 999);\n return copy;\n }\n\n private normalizePath(path: string): string {\n return path.replace(/->/g, \".\");\n }\n\n private applyProjectionFields(\n projection: Record<string, unknown>,\n fields: string[],\n value: 0 | 1,\n ): void {\n for (const field of fields) {\n projection[field] = value;\n }\n }\n\n /**\n * Apply projection object with aliases and inclusion/exclusion.\n * @param projection - The projection object to modify\n * @param projectionObj - The projection specification\n */\n private applyProjectionObject(\n projection: Record<string, unknown>,\n projectionObj: Record<string, unknown>,\n ): void {\n for (const [field, value] of Object.entries(projectionObj)) {\n // Handle boolean values (true = 1, false = 0)\n if (typeof value === \"boolean\") {\n projection[field] = value ? 1 : 0;\n continue;\n }\n\n // Handle numeric values (0 or 1)\n if (typeof value === \"number\") {\n projection[field] = value;\n continue;\n }\n\n // Handle string values (aliases)\n if (typeof value === \"string\") {\n // Alias: project the field with a new name\n projection[value] = `$${field}`;\n continue;\n }\n\n // Handle complex expressions (objects)\n if (typeof value === \"object\" && value !== null) {\n projection[field] = value;\n continue;\n }\n\n // Default: include the field\n projection[field] = 1;\n }\n }\n\n private applyRawProjection(\n projection: Record<string, unknown>,\n expression: RawExpression,\n bindings?: unknown[],\n ): void {\n const resolved = this.resolveProjectionExpression(expression, bindings);\n if (!resolved) {\n return;\n }\n\n if (typeof resolved === \"object\" && resolved !== null && !Array.isArray(resolved)) {\n Object.assign(projection, resolved as Record<string, unknown>);\n }\n }\n\n private resolveProjectionExpression(\n expression: RawExpression | unknown,\n bindings?: unknown[],\n ): any {\n if (typeof expression === \"string\") {\n const source =\n bindings && expression.includes(\"?\")\n ? this.bindRawString(expression, bindings)\n : expression;\n if (source.startsWith(\":\")) {\n return source.slice(1);\n }\n return this.normalizeFieldReference(source);\n }\n\n if (typeof expression === \"object\" && expression !== null && !(expression instanceof Date)) {\n return expression;\n }\n\n if (typeof expression === \"number\" || typeof expression === \"boolean\") {\n return expression;\n }\n\n return expression;\n }\n\n private normalizeFieldReference(value: string | RawExpression): any {\n if (typeof value === \"string\") {\n if (value.startsWith(\":\")) {\n return value.slice(1);\n }\n // If already a field reference, return as-is\n if (value.startsWith(\"$\")) {\n return value;\n }\n // Check if it's a string literal (contains spaces or special chars)\n // Field paths are typically: alphanumeric, underscore, dot only\n if (!/^[a-zA-Z0-9_.]+$/.test(value)) {\n return value; // Return as literal\n }\n // Otherwise, treat as field reference\n return `$${value}`;\n }\n return value;\n }\n\n private buildAggregateProjection(field: string, aggregate: string): any {\n if (aggregate === \"count\") {\n return this.buildArraySizeExpression(field);\n }\n\n const map: Record<string, string> = {\n sum: \"$sum\",\n avg: \"$avg\",\n min: \"$min\",\n max: \"$max\",\n first: \"$first\",\n last: \"$last\",\n };\n\n const operator = map[aggregate];\n if (!operator) {\n return null;\n }\n\n return {\n [operator]: this.normalizeFieldReference(field),\n };\n }\n\n private buildExistsProjection(field: string): any {\n return {\n $ne: [{ $type: `$${field}` }, \"missing\"],\n };\n }\n\n private buildArraySizeExpression(field: string): any {\n return {\n $size: { $ifNull: [`$${field}`, []] },\n };\n }\n\n private buildCaseExpression(\n cases: Array<{ when: RawExpression; then: RawExpression | unknown }>,\n otherwise: RawExpression | unknown,\n ): any {\n return {\n $switch: {\n branches: cases.map((item) => ({\n case: this.resolveProjectionExpression(item.when),\n then: this.resolveLiteralOrExpression(item.then),\n })),\n default: this.resolveLiteralOrExpression(otherwise),\n },\n };\n }\n\n private buildCondExpression(\n condition: RawExpression,\n thenValue: RawExpression | unknown,\n elseValue: RawExpression | unknown,\n ): any {\n return {\n $cond: [\n this.resolveProjectionExpression(condition),\n this.resolveLiteralOrExpression(thenValue),\n this.resolveLiteralOrExpression(elseValue),\n ],\n };\n }\n\n /**\n * Resolve a value as a literal (if it's a plain string) or as an expression.\n * Used for `then`/`default` values in CASE/WHEN expressions.\n */\n private resolveLiteralOrExpression(value: RawExpression | unknown): any {\n // If it's a string that starts with $, treat as field reference\n if (typeof value === \"string\" && value.startsWith(\"$\")) {\n return value;\n }\n // If it's a plain string (not starting with $), treat as literal\n if (typeof value === \"string\") {\n return value;\n }\n // For objects (expressions), numbers, booleans, etc., use normal resolution\n return this.resolveProjectionExpression(value);\n }\n\n private inferJsonAlias(path: string): string {\n const normalized = this.normalizePath(path);\n const segments = normalized.split(\".\");\n return segments[segments.length - 1];\n }\n\n private buildConcatExpression(values: Array<string | RawExpression>): any {\n return {\n $concat: values.map((value) => this.normalizeFieldReference(value)),\n };\n }\n\n private buildCoalesceExpression(values: Array<string | RawExpression>): any {\n if (values.length === 0) {\n return null;\n }\n\n let expression = this.normalizeFieldReference(values[values.length - 1]);\n\n for (let index = values.length - 2; index >= 0; index--) {\n expression = {\n $ifNull: [this.normalizeFieldReference(values[index]), expression],\n };\n }\n\n return expression;\n }\n\n /**\n * Build a $project stage from select operations.\n *\n * @param operations - The select operations\n * @returns The $project stage or null\n */\n private buildProjectStage(operations: Operation[]): any {\n if (operations.length === 0) {\n return null;\n }\n\n const projection: Record<string, unknown> = {};\n const driverCallbacks: Array<(projection: Record<string, unknown>) => void> = [];\n\n for (const op of operations) {\n switch (op.type) {\n case \"select\":\n // Handle new projection format with aliases\n if (op.payload.projection) {\n this.applyProjectionObject(projection, op.payload.projection);\n } else if (op.payload.fields) {\n this.applyProjectionFields(projection, op.payload.fields, 1);\n }\n break;\n\n case \"deselect\":\n this.applyProjectionFields(projection, op.payload.fields, 0);\n break;\n\n case \"addSelect\":\n this.applyProjectionFields(projection, op.payload.fields, 1);\n break;\n\n case \"selectRaw\":\n this.applyRawProjection(projection, op.payload.expression, op.payload.bindings);\n break;\n\n case \"selectSub\":\n case \"addSelectSub\": {\n const expr = this.resolveProjectionExpression(op.payload.expression, op.payload.bindings);\n if (expr !== undefined) {\n projection[op.payload.alias] = expr;\n }\n break;\n }\n\n case \"selectAggregate\":\n projection[op.payload.alias] = this.buildAggregateProjection(\n op.payload.field,\n op.payload.aggregate,\n );\n break;\n\n case \"selectExists\":\n projection[op.payload.alias] = this.buildExistsProjection(op.payload.field);\n break;\n\n case \"selectCount\":\n projection[op.payload.alias] = this.buildArraySizeExpression(op.payload.field);\n break;\n\n case \"selectCase\":\n projection[op.payload.alias] = this.buildCaseExpression(\n op.payload.cases,\n op.payload.otherwise,\n );\n break;\n\n case \"selectWhen\":\n projection[op.payload.alias] = this.buildCondExpression(\n op.payload.condition,\n op.payload.thenValue,\n op.payload.elseValue,\n );\n break;\n\n case \"selectDriverProjection\":\n driverCallbacks.push(op.payload.callback);\n break;\n\n case \"selectJson\": {\n const alias = op.payload.alias ?? this.inferJsonAlias(op.payload.path);\n projection[alias] = this.normalizeFieldReference(\n `$${this.normalizePath(op.payload.path)}`,\n );\n break;\n }\n\n case \"selectJsonRaw\": {\n projection[op.payload.alias] = this.resolveProjectionExpression(op.payload.expression);\n break;\n }\n\n case \"deselectJson\":\n projection[this.normalizePath(op.payload.path)] = 0;\n break;\n\n case \"selectConcat\":\n projection[op.payload.alias] = this.buildConcatExpression(op.payload.fields);\n break;\n\n case \"selectCoalesce\":\n projection[op.payload.alias] = this.buildCoalesceExpression(op.payload.fields);\n break;\n\n default:\n break;\n }\n }\n\n for (const callback of driverCallbacks) {\n callback(projection);\n }\n\n return Object.keys(projection).length > 0 ? { $project: projection } : null;\n }\n\n /**\n * Build a $sort stage from order operations.\n *\n * @param operations - The order operations\n * @returns The $sort stage or null\n */\n private buildSortStage(operations: Operation[]): any {\n const sort: any = {};\n\n for (const op of operations) {\n switch (op.type) {\n case \"orderBy\":\n sort[op.payload.field] = op.payload.direction === \"asc\" ? 1 : -1;\n break;\n\n case \"orderByRandom\":\n return { $sample: { size: op.payload.limit } };\n\n case \"orderByRaw\":\n // TODO: Handle raw expressions\n break;\n }\n }\n\n return Object.keys(sort).length > 0 ? { $sort: sort } : null;\n }\n\n /**\n * Build a $group stage from group operations.\n *\n * @param operations - The group operations\n * @returns The $group stage or null\n */\n private buildGroupStage(operations: Operation[]): any {\n const op = operations[0];\n\n switch (op.type) {\n case \"groupBy\": {\n const stage = this.buildGroupByStage(op.payload.fields);\n if (stage) {\n return stage;\n }\n break;\n }\n case \"groupByWithAggregates\": {\n const stage = this.buildGroupByWithAggregatesStage(\n op.payload.fields,\n op.payload.aggregates,\n );\n if (stage) {\n return stage;\n }\n break;\n }\n case \"groupByRaw\": {\n const expression = op.payload.expression;\n if (expression && typeof expression === \"object\") {\n return { $group: expression };\n }\n // If expression is not an object, it might be a string or other type\n // In that case, we should still return it as a $group stage\n if (expression) {\n return { $group: { _id: expression } };\n }\n break;\n }\n case \"distinct\": {\n const stage = this.buildGroupByStage(op.payload.fields);\n if (stage) {\n return stage;\n }\n break;\n }\n default:\n break;\n }\n\n return null;\n }\n\n private buildGroupByStage(fields: GroupByInput): any {\n const groupId = this.buildGroupId(fields);\n if (!groupId) {\n return null;\n }\n\n return { $group: { _id: groupId } };\n }\n\n /**\n * Build a $group stage with aggregates from group operations.\n *\n * @param fields - Fields to group by\n * @param aggregates - Aggregate operations (abstract or raw)\n * @returns The $group stage or null\n */\n private buildGroupByWithAggregatesStage(\n fields: GroupByInput,\n aggregates: Record<string, RawExpression>,\n ): any {\n const groupId = this.buildGroupId(fields);\n if (!groupId) {\n return null;\n }\n\n const groupStage: Record<string, unknown> = {\n _id: groupId,\n };\n\n // Translate each aggregate expression\n for (const [alias, expression] of Object.entries(aggregates)) {\n if (isAggregateExpression(expression)) {\n // Translate abstract expression to MongoDB format\n groupStage[alias] = this.translateAggregateExpression(expression);\n } else {\n // Use raw expression as-is (already in MongoDB format)\n groupStage[alias] = expression;\n }\n }\n\n return { $group: groupStage };\n }\n\n /**\n * Extract field names from GroupByInput for renaming _id.\n *\n * @param fields - The grouping fields\n * @returns Field name(s) to use for renaming _id\n */\n private extractGroupFieldNames(fields: GroupByInput): string | string[] | null {\n if (typeof fields === \"string\") {\n return fields;\n }\n\n if (Array.isArray(fields)) {\n const allStrings = fields.every((field) => typeof field === \"string\");\n if (allStrings) {\n return fields as string[];\n }\n // For complex arrays, return null (don't rename)\n return null;\n }\n\n if (typeof fields === \"object\" && fields !== null) {\n // For object syntax, use the keys as field names\n return Object.keys(fields);\n }\n\n return null;\n }\n\n /**\n * Translate an abstract aggregate expression to MongoDB format.\n *\n * @param expr - Abstract aggregate expression\n * @returns MongoDB aggregation expression\n */\n private translateAggregateExpression(expr: AggregateExpression): Record<string, unknown> {\n switch (expr.__agg) {\n case \"count\":\n return { $sum: 1 };\n\n case \"sum\":\n if (!expr.__field) {\n throw new Error(\"Sum aggregate requires a field name\");\n }\n return { $sum: `$${expr.__field}` };\n\n case \"avg\":\n if (!expr.__field) {\n throw new Error(\"Average aggregate requires a field name\");\n }\n return { $avg: `$${expr.__field}` };\n\n case \"min\":\n if (!expr.__field) {\n throw new Error(\"Min aggregate requires a field name\");\n }\n return { $min: `$${expr.__field}` };\n\n case \"max\":\n if (!expr.__field) {\n throw new Error(\"Max aggregate requires a field name\");\n }\n return { $max: `$${expr.__field}` };\n\n case \"first\":\n if (!expr.__field) {\n throw new Error(\"First aggregate requires a field name\");\n }\n return { $first: `$${expr.__field}` };\n\n case \"last\":\n if (!expr.__field) {\n throw new Error(\"Last aggregate requires a field name\");\n }\n return { $last: `$${expr.__field}` };\n\n case \"distinct\":\n if (!expr.__field) {\n throw new Error(\"Distinct aggregate requires a field name\");\n }\n return { $distinct: `$${expr.__field}` };\n\n case \"floor\":\n if (!expr.__field) {\n throw new Error(\"Floor aggregate requires a field name\");\n }\n\n return { $floor: `$${expr.__field}` };\n\n default:\n throw new Error(`Unknown aggregate function: ${expr.__agg}`);\n }\n }\n\n private buildGroupId(fields: GroupByInput): any {\n if (!fields) {\n return null;\n }\n\n if (typeof fields === \"string\") {\n return `$${fields}`;\n }\n\n if (Array.isArray(fields)) {\n if (fields.length === 0) {\n return null;\n }\n\n const allStrings = fields.every((field) => typeof field === \"string\");\n if (allStrings) {\n const result: Record<string, string> = {};\n for (const field of fields as string[]) {\n result[field] = `$${field}`;\n }\n return result;\n }\n\n // Array of objects - merge them to build complex _id structures\n return (fields as Record<string, unknown>[]).reduce((acc, item) => ({ ...acc, ...item }), {});\n }\n\n if (typeof fields === \"object\") {\n const normalized: Record<string, unknown> = {};\n Object.entries(fields).forEach(([key, value]) => {\n if (typeof value === \"string\" && !value.startsWith(\"$\")) {\n normalized[key] = `$${value}`;\n } else {\n normalized[key] = value;\n }\n });\n return normalized;\n }\n\n return null;\n }\n\n /**\n * Build a $lookup stage from join operations.\n *\n * @param operations - The join operations\n * @returns The $lookup stage or null\n */\n private buildLookupStage(operations: Operation[]): any {\n const op = operations[0];\n const options = op.payload;\n\n return {\n $lookup: {\n from: options.table,\n localField: options.localField,\n foreignField: options.foreignField,\n as: options.alias || options.table,\n },\n };\n }\n}\n","/* eslint-disable no-case-declarations */\nimport { GenericObject, get } from \"@mongez/reinforcements\";\nimport type { AggregateOptions, ClientSession, Collection } from \"mongodb\";\nimport { databaseTransactionContext } from \"../../context/database-transaction-context\";\nimport type {\n CursorPaginationOptions,\n CursorPaginationResult,\n GroupByInput,\n HavingInput,\n JoinOptions,\n OrderDirection,\n PaginationOptions,\n PaginationResult,\n QueryBuilderContract,\n RawExpression,\n WhereCallback,\n WhereObject,\n WhereOperator,\n} from \"../../contracts\";\nimport { type DataSource } from \"../../data-source/data-source\";\nimport { dataSourceRegistry } from \"../../data-source/data-source-registry\";\nimport { MongoQueryOperations } from \"./mongo-query-operations\";\nimport { MongoQueryParser } from \"./mongo-query-parser\";\nimport { type MongoDbDriver } from \"./mongodb-driver\";\nimport type { Operation } from \"./types\";\n\n/**\n * MongoDB-specific query builder implementation using aggregation pipeline.\n */\nexport class MongoQueryBuilder<T = unknown> implements QueryBuilderContract<T> {\n /**\n * Ordered list of operations to be converted to MongoDB aggregation pipeline.\n * Public to allow parser access.\n */\n public operations: Operation[] = [];\n\n /**\n * Data source instance\n */\n public readonly dataSource: DataSource;\n\n /**\n * Lazy-loaded operations helper for constructing pipeline operations.\n */\n protected _operationsHelper?: MongoQueryOperations;\n\n public hydrateCallback?: (data: any, index: number) => any;\n\n private fetchingCallback?: (query: this) => void | Promise<void>;\n private hydratingCallback?: (records: any[], context: any) => void | Promise<void>;\n private fetchedCallback?: (records: any[], context: any) => void | Promise<void>;\n\n // Scope properties\n public pendingGlobalScopes?: Map<string, any>;\n public availableLocalScopes?: Map<string, any>;\n public disabledGlobalScopes = new Set<string>();\n public scopesApplied = false;\n\n /**\n * Create a new query builder for the given collection.\n * @param collection - The MongoDB collection to query\n */\n public constructor(\n public readonly table: string,\n dataSource?: DataSource,\n ) {\n this.dataSource = dataSource || dataSourceRegistry.get()!;\n // TODO: Trigger the fetching event\n }\n\n /**\n * Gets the operations helper instance, creating it if needed.\n * @returns The operations helper instance\n */\n protected get operationsHelper(): MongoQueryOperations {\n if (!this._operationsHelper) {\n this._operationsHelper = new MongoQueryOperations(this.operations);\n }\n return this._operationsHelper;\n }\n\n /**\n * Get collection instance\n */\n public get collection(): Collection {\n const driver = this.dataSource.driver as MongoDbDriver;\n\n return driver.database!.collection(this.table);\n }\n\n /**\n * Add hydrate callback function\n */\n public hydrate(callback: (data: any, index: number) => any): this {\n this.hydrateCallback = callback;\n return this;\n }\n\n /**\n * Register a callback to be invoked before query execution\n * @returns Unsubscribe function to remove the callback\n */\n public onFetching(callback: (query: this) => void | Promise<void>): () => void {\n this.fetchingCallback = callback;\n return () => {\n this.fetchingCallback = undefined;\n };\n }\n\n /**\n * Register a callback to be invoked after records are fetched but before hydration\n * @returns Unsubscribe function to remove the callback\n */\n public onHydrating(callback: (records: any[], context: any) => void | Promise<void>): () => void {\n this.hydratingCallback = callback;\n return () => {\n this.hydratingCallback = undefined;\n };\n }\n\n /**\n * Register a callback to be invoked after records are fetched and hydrated\n * @returns Unsubscribe function to remove the callback\n */\n public onFetched(callback: (records: any[], context: any) => void | Promise<void>): () => void {\n this.fetchedCallback = callback;\n return () => {\n this.fetchedCallback = undefined;\n };\n }\n\n /**\n * Disable one or more global scopes for this query\n */\n public withoutGlobalScope(...scopeNames: string[]): this {\n scopeNames.forEach((name) => this.disabledGlobalScopes.add(name));\n return this;\n }\n\n /**\n * Disable all global scopes for this query\n */\n public withoutGlobalScopes(): this {\n if (this.pendingGlobalScopes) {\n this.pendingGlobalScopes.forEach((_, name) => {\n this.disabledGlobalScopes.add(name);\n });\n }\n return this;\n }\n\n /**\n * Apply a local scope to this query\n */\n public scope(scopeName: string): this {\n if (!this.availableLocalScopes) {\n throw new Error(`No local scopes available`);\n }\n\n const scopeCallback = this.availableLocalScopes.get(scopeName);\n if (!scopeCallback) {\n throw new Error(`Local scope \"${scopeName}\" not found`);\n }\n\n // Apply scope immediately (not deferred)\n scopeCallback(this);\n return this;\n }\n\n /**\n * Apply pending global scopes before query execution\n */\n private applyPendingScopes(): void {\n if (!this.pendingGlobalScopes || this.scopesApplied) {\n return;\n }\n\n const beforeOps: any[] = [];\n const afterOps: any[] = [];\n\n for (const [name, { callback, timing }] of this.pendingGlobalScopes) {\n // Skip disabled scopes\n if (this.disabledGlobalScopes.has(name)) {\n continue;\n }\n\n // Create temporary query builder to capture operations\n const tempBuilder = new MongoQueryBuilder(this.table, this.dataSource);\n callback(tempBuilder);\n\n // Collect operations based on timing\n if (timing === \"before\") {\n beforeOps.push(...tempBuilder.operations);\n } else {\n afterOps.push(...tempBuilder.operations);\n }\n }\n\n // Apply: before scopes + user operations + after scopes\n this.operations = [...beforeOps, ...this.operations, ...afterOps];\n this.scopesApplied = true;\n }\n\n // ============================================================================\n // WHERE CLAUSES - BASIC\n // ============================================================================\n\n /**\n * Adds a WHERE clause to filter documents. Supports equality, operators, objects, or callbacks.\n * @param field - Field name, or conditions object, or callback\n * @param operator - Comparison operator\n * @param value - Value to compare\n */\n public where(field: string, value: unknown): this;\n public where(field: string, operator: WhereOperator, value: unknown): this;\n public where(conditions: WhereObject): this;\n public where(callback: WhereCallback<T>): this;\n public where(...args: any[]): this {\n this.addWhereClause(\"where\", args);\n return this;\n }\n\n /**\n * Adds an OR WHERE clause. Works like where() but uses OR logic.\n * @param field - Field name, or conditions object, or callback\n * @param operator - Comparison operator\n * @param value - Value to compare\n */\n public orWhere(field: string, value: unknown): this;\n public orWhere(field: string, operator: WhereOperator, value: unknown): this;\n public orWhere(conditions: WhereObject): this;\n public orWhere(callback: WhereCallback<T>): this;\n public orWhere(...args: any[]): this {\n this.addWhereClause(\"orWhere\", args);\n return this;\n }\n\n /**\n * Adds a raw WHERE clause using MongoDB's native query syntax.\n * @param expression - Raw MongoDB expression\n * @param bindings - Optional parameter bindings for string expressions\n */\n public whereRaw(expression: RawExpression, bindings?: unknown[]): this {\n return this.addRawWhere(\"whereRaw\", expression, bindings);\n }\n\n /**\n * Adds a raw OR WHERE clause using MongoDB's native query syntax.\n * @param expression - Raw MongoDB expression\n * @param bindings - Optional parameter bindings\n */\n public orWhereRaw(expression: RawExpression, bindings?: unknown[]): this {\n return this.addRawWhere(\"orWhereRaw\", expression, bindings);\n }\n\n // ============================================================================\n // WHERE CLAUSES - COLUMN COMPARISONS\n // ============================================================================\n\n /**\n * Adds a WHERE clause comparing two columns/fields directly.\n * @param first - The first field name\n * @param operator - The comparison operator\n * @param second - The second field name\n */\n public whereColumn(first: string, operator: WhereOperator, second: string): this {\n this.operationsHelper.addMatchOperation(\"whereColumn\", {\n first,\n operator,\n second,\n });\n return this;\n }\n\n /**\n * Adds an OR WHERE clause comparing two columns/fields directly.\n * @param first - The first field name\n * @param operator - The comparison operator\n * @param second - The second field name\n */\n public orWhereColumn(first: string, operator: WhereOperator, second: string): this {\n this.operationsHelper.addMatchOperation(\"orWhereColumn\", {\n first,\n operator,\n second,\n });\n return this;\n }\n\n /**\n * Adds multiple column comparison clauses at once.\n * @param comparisons - Array of tuples [leftField, operator, rightField]\n */\n public whereColumns(\n comparisons: Array<[left: string, operator: WhereOperator, right: string]>,\n ): this {\n for (const [left, operator, right] of comparisons) {\n this.whereColumn(left, operator, right);\n }\n return this;\n }\n\n /**\n * Filters documents where a field's value falls between two other fields.\n * @param field - The field to check\n * @param lowerColumn - The field defining the lower bound\n * @param upperColumn - The field defining the upper bound\n */\n public whereBetweenColumns(field: string, lowerColumn: string, upperColumn: string): this {\n this.operationsHelper.addMatchOperation(\"whereBetweenColumns\", {\n field,\n lowerColumn,\n upperColumn,\n });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - DATE OPERATIONS\n // ============================================================================\n\n /**\n * Filters documents where a date field matches the given date (ignoring time).\n * @param field - The date field name\n * @param value - The date to match\n */\n public whereDate(field: string, value: Date | string): this {\n this.operationsHelper.addMatchOperation(\"whereDate\", { field, value });\n return this;\n }\n\n /**\n * Alias for `whereDate()`. Filters by exact date match (ignoring time).\n * @param field - The date field name\n * @param value - The date to match\n */\n public whereDateEquals(field: string, value: Date | string): this {\n this.operationsHelper.addMatchOperation(\"whereDateEquals\", {\n field,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a date field is before the given date.\n * @param field - The date field name\n * @param value - The cutoff date\n */\n public whereDateBefore(field: string, value: Date | string): this {\n this.operationsHelper.addMatchOperation(\"whereDateBefore\", {\n field,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a date field is after the given date.\n * @param field - The date field name\n * @param value - The cutoff date\n */\n public whereDateAfter(field: string, value: Date | string): this {\n this.operationsHelper.addMatchOperation(\"whereDateAfter\", { field, value });\n return this;\n }\n\n /**\n * Filters documents where a time field matches the given time (HH:MM:SS format).\n * @param field - The time/datetime field name\n * @param value - The time string in HH:MM:SS format\n */\n public whereTime(field: string, value: string): this {\n this.operationsHelper.addMatchOperation(\"whereTime\", { field, value });\n return this;\n }\n\n /**\n * Filters documents where the day of the month matches the given value (1-31).\n * @param field - The date field name\n * @param value - The day of the month\n */\n public whereDay(field: string, value: number): this {\n this.operationsHelper.addMatchOperation(\"whereDay\", { field, value });\n return this;\n }\n\n /**\n * Filters documents where the month matches the given value (1-12).\n * @param field - The date field name\n * @param value - The month number\n */\n public whereMonth(field: string, value: number): this {\n this.operationsHelper.addMatchOperation(\"whereMonth\", { field, value });\n return this;\n }\n\n /**\n * Filters documents where the year matches the given value.\n * @param field - The date field name\n * @param value - The year\n */\n public whereYear(field: string, value: number): this {\n this.operationsHelper.addMatchOperation(\"whereYear\", { field, value });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - JSON OPERATIONS\n // ============================================================================\n\n /**\n * Filters documents where a JSON field contains the specified value.\n * @param path - The JSON path to check\n * @param value - The value to search for\n */\n public whereJsonContains(path: string, value: unknown): this {\n this.operationsHelper.addMatchOperation(\"whereJsonContains\", {\n path,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a JSON field does NOT contain the specified value.\n * @param path - The JSON path to check\n * @param value - The value to exclude\n */\n public whereJsonDoesntContain(path: string, value: unknown): this {\n this.operationsHelper.addMatchOperation(\"whereJsonDoesntContain\", {\n path,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a JSON field contains a specific key.\n * @param path - The JSON path to check for key existence\n */\n public whereJsonContainsKey(path: string): this {\n this.operationsHelper.addMatchOperation(\"whereJsonContainsKey\", { path });\n return this;\n }\n\n /**\n * Filters documents where a JSON array or string has a specific length.\n * @param path - The JSON path to check\n * @param operator - The comparison operator\n * @param value - The length value to compare against\n */\n public whereJsonLength(path: string, operator: WhereOperator, value: number): this {\n this.operationsHelper.addMatchOperation(\"whereJsonLength\", {\n path,\n operator,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a JSON field is an array.\n * @param path - The JSON path to check\n */\n public whereJsonIsArray(path: string): this {\n this.operationsHelper.addMatchOperation(\"whereJsonIsArray\", { path });\n return this;\n }\n\n /**\n * Filters documents where a JSON field is an object.\n * @param path - The JSON path to check\n */\n public whereJsonIsObject(path: string): this {\n this.operationsHelper.addMatchOperation(\"whereJsonIsObject\", { path });\n return this;\n }\n\n /**\n * Filters documents where an array field has a specific length.\n * @param field - The array field name\n * @param operator - The comparison operator\n * @param value - The length value to compare against\n */\n public whereArrayLength(field: string, operator: WhereOperator, value: number): this {\n this.operationsHelper.addMatchOperation(\"whereArrayLength\", {\n field,\n operator,\n value,\n });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - CONVENIENCE METHODS\n // ============================================================================\n\n /**\n * Filters documents by ID (convenience method for `where(\"id\", value)`).\n * @param value - The ID value to match\n */\n public whereId(value: string | number): this {\n return this.where(\"id\", value);\n }\n\n /**\n * Filters documents by multiple IDs (convenience method for `whereIn(\"id\", values)`).\n * @param values - Array of ID values to match\n */\n public whereIds(values: Array<string | number>): this {\n return this.whereIn(\"id\", values);\n }\n\n /**\n * Filters documents by UUID (convenience method for `where(\"uuid\", value)`).\n * @param value - The UUID string to match\n */\n public whereUuid(value: string): this {\n return this.where(\"uuid\", value);\n }\n\n /**\n * Filters documents by ULID (convenience method for `where(\"ulid\", value)`).\n * @param value - The ULID string to match\n */\n public whereUlid(value: string): this {\n return this.where(\"ulid\", value);\n }\n\n /**\n * Performs full-text search on one or more fields.\n * @param fields - Field name or array of field names to search\n * @param query - The search query string\n */\n public whereFullText(fields: string | string[], query: string): this {\n const filters = typeof fields === \"string\" ? { fields: [fields] } : { fields: fields ?? [] };\n this.operationsHelper.addMatchOperation(\"whereFullText\", {\n fields: filters.fields,\n query,\n });\n return this;\n }\n\n /**\n * Performs full-text search with OR logic.\n * @param fields - Field name or array of field names to search\n * @param query - The search query string\n */\n public orWhereFullText(fields: string | string[], query: string): this {\n const filters = typeof fields === \"string\" ? { fields: [fields] } : { fields: fields ?? [] };\n this.operationsHelper.addMatchOperation(\"orWhereFullText\", {\n fields: filters.fields,\n query,\n });\n return this;\n }\n\n /**\n * Alias for `whereFullText()` with a single field.\n * @param field - The field name to search\n * @param query - The search query string\n */\n public whereSearch(field: string, query: string): this {\n return this.whereFullText(field, query);\n }\n\n /**\n * Negates a set of conditions using a callback.\n * @param callback - Callback function defining conditions to negate\n */\n public whereNot(callback: WhereCallback<T>): this {\n this.operationsHelper.addMatchOperation(\"where:not\", { callback });\n return this;\n }\n\n /**\n * Negates a set of conditions with OR logic.\n * @param callback - Callback function defining conditions to negate\n */\n public orWhereNot(callback: WhereCallback<T>): this {\n this.operationsHelper.addMatchOperation(\"orWhere:not\", { callback });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - COMPARISON OPERATORS\n // ============================================================================\n\n /**\n * Filters documents where a field's value matches any value in the given array.\n * @param field - The field name to check\n * @param values - Array of values to match against\n */\n public whereIn(field: string, values: unknown[]): this {\n this.operationsHelper.addMatchOperation(\"whereIn\", { field, values });\n return this;\n }\n\n /**\n * Filters documents where a field's value does NOT match any value in the array.\n * @param field - The field name to check\n * @param values - Array of values to exclude\n */\n public whereNotIn(field: string, values: unknown[]): this {\n this.operationsHelper.addMatchOperation(\"whereNotIn\", { field, values });\n return this;\n }\n\n /**\n * Filters documents where a field's value is null or undefined.\n * @param field - The field name to check\n */\n public whereNull(field: string): this {\n this.operationsHelper.addMatchOperation(\"whereNull\", { field });\n return this;\n }\n\n /**\n * Filters documents where a field's value is NOT null or undefined.\n * @param field - The field name to check\n */\n public whereNotNull(field: string): this {\n this.operationsHelper.addMatchOperation(\"whereNotNull\", { field });\n return this;\n }\n\n /**\n * Filters documents where a field's value falls within the given range (inclusive).\n * @param field - The field name to check\n * @param range - Tuple of [min, max] values\n */\n public whereBetween(field: string, range: [unknown, unknown]): this {\n this.operationsHelper.addMatchOperation(\"whereBetween\", { field, range });\n return this;\n }\n\n /**\n * Filters documents where a field's value is NOT within the given range.\n * @param field - The field name to check\n * @param range - Tuple of [min, max] values to exclude\n */\n public whereNotBetween(field: string, range: [unknown, unknown]): this {\n this.operationsHelper.addMatchOperation(\"whereNotBetween\", {\n field,\n range,\n });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - PATTERN MATCHING\n // ============================================================================\n\n /**\n * Filters documents where a field matches the given pattern (case-insensitive).\n * @param field - The field name to search\n * @param pattern - The pattern to match\n */\n public whereLike(field: string, pattern: RegExp | string): this {\n this.operationsHelper.addMatchOperation(\"whereLike\", { field, pattern });\n return this;\n }\n\n /**\n * Filters documents where a field does NOT match the given pattern.\n * @param field - The field name to search\n * @param pattern - The pattern to exclude\n */\n public whereNotLike(field: string, pattern: RegExp | string): this {\n this.operationsHelper.addMatchOperation(\"whereNotLike\", { field, pattern });\n return this;\n }\n\n /**\n * Filters documents where a field's value starts with the given prefix.\n * @param field - The field name to check\n * @param value - The prefix to match\n */\n public whereStartsWith(field: string, value: string | number): this {\n this.operationsHelper.addMatchOperation(\"whereStartsWith\", {\n field,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a field's value does NOT start with the given prefix.\n * @param field - The field name to check\n * @param value - The prefix to exclude\n */\n public whereNotStartsWith(field: string, value: string | number): this {\n this.operationsHelper.addMatchOperation(\"whereNotStartsWith\", {\n field,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a field's value ends with the given suffix.\n * @param field - The field name to check\n * @param value - The suffix to match\n */\n public whereEndsWith(field: string, value: string | number): this {\n this.operationsHelper.addMatchOperation(\"whereEndsWith\", { field, value });\n return this;\n }\n\n /**\n * Filters documents where a field's value does NOT end with the given suffix.\n * @param field - The field name to check\n * @param value - The suffix to exclude\n */\n public whereNotEndsWith(field: string, value: string | number): this {\n this.operationsHelper.addMatchOperation(\"whereNotEndsWith\", {\n field,\n value,\n });\n return this;\n }\n\n /**\n * Filters documents where a date field falls within the given date range.\n * @param field - The date field name\n * @param range - Tuple of [startDate, endDate]\n */\n public whereDateBetween(field: string, range: [Date, Date]): this {\n this.operationsHelper.addMatchOperation(\"whereDateBetween\", {\n field,\n range,\n });\n return this;\n }\n\n /**\n * Filters documents where a date field is NOT within the given date range.\n * @param field - The date field name\n * @param range - Tuple of [startDate, endDate] to exclude\n */\n public whereDateNotBetween(field: string, range: [Date, Date]): this {\n this.operationsHelper.addMatchOperation(\"whereDateNotBetween\", {\n field,\n range,\n });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - EXISTENCE CHECKS\n // ============================================================================\n\n /**\n * Filters documents where a field exists (has any value including null).\n * @param field - The field name to check for existence\n * @param callback - Optional callback for subquery existence\n */\n public whereExists(field: string): this;\n public whereExists(callback: WhereCallback<T>): this;\n public whereExists(param: string | WhereCallback<T>): this {\n if (typeof param === \"function\") {\n this.operationsHelper.addMatchOperation(\"where:exists\", {\n callback: param,\n });\n return this;\n }\n\n this.operationsHelper.addMatchOperation(\"whereExists\", { field: param });\n return this;\n }\n\n /**\n * Filters documents where a field does NOT exist in the document.\n * @param field - The field name to check for absence\n * @param callback - Optional callback for subquery non-existence\n */\n public whereNotExists(field: string): this;\n public whereNotExists(callback: WhereCallback<T>): this;\n public whereNotExists(param: string | WhereCallback<T>): this {\n if (typeof param === \"function\") {\n this.operationsHelper.addMatchOperation(\"where:notExists\", {\n callback: param,\n });\n return this;\n }\n\n this.operationsHelper.addMatchOperation(\"whereNotExists\", {\n field: param,\n });\n return this;\n }\n\n /**\n * Filters documents where an array field has a specific size.\n * @param field - The array field name\n * @param size - The exact size to match\n * @param operator - Optional comparison operator\n */\n public whereSize(field: string, size: number): this;\n public whereSize(field: string, operator: \">\" | \">=\" | \"=\" | \"<\" | \"<=\", size: number): this;\n public whereSize(field: string, ...args: any[]): this {\n if (args.length === 1) {\n this.operationsHelper.addMatchOperation(\"whereSize\", {\n field,\n operator: \"=\",\n size: args[0],\n });\n } else {\n this.operationsHelper.addMatchOperation(\"whereSize\", {\n field,\n operator: args[0],\n size: args[1],\n });\n }\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - FULL-TEXT SEARCH\n // ============================================================================\n\n /**\n * Performs a full-text search on the specified fields.\n * @param query - The search query string\n * @param filters - Optional additional filter conditions\n */\n public textSearch(query: string, filters?: WhereObject): this {\n this.operationsHelper.addMatchOperation(\"textSearch\", { query, filters });\n return this;\n }\n\n // ============================================================================\n // WHERE CLAUSES - ARRAY OPERATIONS\n // ============================================================================\n\n /**\n * Filters documents where an array field contains the given value.\n * @param field - The array field name\n * @param value - The value to search for in the array\n * @param key - Optional key to check within array objects\n */\n public whereArrayContains(field: string, value: unknown, key?: string): this {\n this.operationsHelper.addMatchOperation(\"whereArrayContains\", {\n field,\n value,\n key,\n });\n return this;\n }\n\n /**\n * Filters documents where an array field does NOT contain the given value.\n * @param field - The array field name\n * @param value - The value to exclude from the array\n * @param key - Optional key to check within array objects\n */\n public whereArrayNotContains(field: string, value: unknown, key?: string): this {\n this.operationsHelper.addMatchOperation(\"whereArrayNotContains\", {\n field,\n value,\n key,\n });\n return this;\n }\n\n /**\n * Filters documents where an array field contains the value OR is empty.\n * @param field - The array field name\n * @param value - The value to search for\n * @param key - Optional key to check within array objects\n */\n public whereArrayHasOrEmpty(field: string, value: unknown, key?: string): this {\n this.operationsHelper.addMatchOperation(\"whereArrayHasOrEmpty\", {\n field,\n value,\n key,\n });\n return this;\n }\n\n /**\n * Filters documents where an array field does NOT contain the value AND is not empty.\n * @param field - The array field name\n * @param value - The value to exclude\n * @param key - Optional key to check within array objects\n */\n public whereArrayNotHaveOrEmpty(field: string, value: unknown, key?: string): this {\n this.operationsHelper.addMatchOperation(\"whereArrayNotHaveOrEmpty\", {\n field,\n value,\n key,\n });\n return this;\n }\n\n /**\n * Internal helper for processing where clause arguments.\n * @param prefix - The operation prefix\n * @param args - The arguments passed to where/orWhere\n */\n protected addWhereClause(prefix: \"where\" | \"orWhere\", args: any[]): void {\n if (args.length === 1) {\n if (typeof args[0] === \"function\") {\n // Callback-based where\n this.operationsHelper.addMatchOperation(`${prefix}:callback`, args[0]);\n } else {\n // Object-based where\n this.operationsHelper.addMatchOperation(`${prefix}:object`, args[0]);\n }\n } else if (args.length === 2) {\n // Simple equality: where(field, value)\n this.operationsHelper.addMatchOperation(prefix, {\n field: args[0],\n operator: \"=\",\n value: args[1],\n });\n } else if (args.length === 3) {\n // With operator: where(field, operator, value)\n this.operationsHelper.addMatchOperation(prefix, {\n field: args[0],\n operator: args[1],\n value: args[2],\n });\n }\n }\n\n /**\n * Internal helper for adding raw where clauses.\n * @param type - The operation type\n * @param expression - The raw expression in MongoDB query language\n * @param bindings - Optional bindings for the expression\n */\n protected addRawWhere(\n type: \"whereRaw\" | \"orWhereRaw\",\n expression: RawExpression,\n bindings?: unknown[],\n ): this {\n this.operationsHelper.addMatchOperation(type, { expression, bindings });\n return this;\n }\n\n /**\n * Normalizes select field arguments into a structured format.\n * @param args - The arguments to normalize\n * @returns Normalized selection object with fields and aliases\n */\n protected normalizeSelectFields(args: any[]): {\n fields?: string[];\n projection?: Record<string, unknown>;\n } {\n // Single argument cases\n if (args.length === 1) {\n const arg = args[0];\n\n // Object format: { field: 1, field2: 0, field3: \"alias\", field4: true }\n if (typeof arg === \"object\" && !Array.isArray(arg)) {\n return { projection: arg };\n }\n\n // Array format: [\"field1\", \"field2\"]\n if (Array.isArray(arg)) {\n return { fields: arg };\n }\n\n // Single string: \"field\"\n if (typeof arg === \"string\") {\n return { fields: [arg] };\n }\n }\n\n // Multiple string arguments: select(\"field1\", \"field2\", \"field3\")\n return { fields: args.filter((arg) => typeof arg === \"string\") };\n }\n\n // ============================================================================\n // SELECT / PROJECTION\n // ============================================================================\n\n /**\n * Specifies which fields to include in the query results.\n * Supports arrays, multiple args, or object with aliases/inclusion/exclusion.\n * @param fields - Field names, array, or projection object\n */\n public select(fields: string[]): this;\n public select(fields: Record<string, 0 | 1 | boolean | string>): this;\n public select(...fields: string[]): this;\n public select(...args: any): this {\n const normalized = this.normalizeSelectFields(args);\n this.operationsHelper.addProjectOperation(\"select\", normalized);\n return this;\n }\n\n /**\n * Selects a field with an alias.\n * @param field - The field to select\n * @param alias - The alias name for the field\n * @returns The query builder instance\n */\n public selectAs(field: string, alias: string): this {\n return this.select({ [field]: alias });\n }\n\n /**\n * Adds a computed field using a raw MongoDB expression.\n * @param expression - The raw MongoDB expression\n * @param bindings - Optional parameter bindings for string expressions\n */\n public selectRaw(expression: RawExpression, bindings?: unknown[]): this {\n this.operationsHelper.addProjectOperation(\"selectRaw\", {\n expression,\n bindings,\n });\n return this;\n }\n\n /**\n * Adds multiple computed fields using raw MongoDB expressions.\n * @param definitions - Array of field definitions with alias, expression, and optional bindings\n */\n public selectRawMany(\n definitions: Array<{\n alias: string;\n expression: RawExpression;\n bindings?: unknown[];\n }>,\n ): this {\n for (const definition of definitions) {\n this.selectRaw({ [definition.alias]: definition.expression }, definition.bindings);\n }\n return this;\n }\n\n /**\n * Adds a subquery as a computed field.\n * @param expression - The subquery expression\n * @param alias - The alias for the computed field\n */\n public selectSub(expression: RawExpression, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectSub\", {\n expression,\n alias,\n });\n return this;\n }\n\n /**\n * Adds an additional subquery field to existing selections.\n * @param expression - The subquery expression\n * @param alias - The alias for the computed field\n */\n public addSelectSub(expression: RawExpression, alias: string): this {\n this.operationsHelper.addProjectOperation(\"addSelectSub\", {\n expression,\n alias,\n });\n return this;\n }\n\n /**\n * Adds an aggregate value as a computed field.\n * @param field - The field to aggregate\n * @param aggregate - The aggregate function to apply\n * @param alias - The alias for the computed field\n */\n public selectAggregate(\n field: string,\n aggregate: \"sum\" | \"avg\" | \"min\" | \"max\" | \"count\" | \"first\" | \"last\",\n alias: string,\n ): this {\n this.operationsHelper.addProjectOperation(\"selectAggregate\", {\n field,\n aggregate,\n alias,\n });\n return this;\n }\n\n /**\n * Adds a boolean field indicating whether a related document exists.\n * @param field - The field to check for existence\n * @param alias - The alias for the boolean field\n */\n public selectExists(field: string, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectExists\", {\n field,\n alias,\n });\n return this;\n }\n\n /**\n * Adds a count field for a related collection.\n * @param field - The field to count\n * @param alias - The alias for the count field\n */\n public selectCount(field: string, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectCount\", { field, alias });\n return this;\n }\n\n /**\n * Adds a CASE-like conditional field using multiple conditions.\n * @param cases - Array of when/then pairs\n * @param otherwise - Default value if no conditions match\n * @param alias - The alias for the computed field\n */\n public selectCase(\n cases: Array<{ when: RawExpression; then: RawExpression | unknown }>,\n otherwise: RawExpression | unknown,\n alias: string,\n ): this {\n this.operationsHelper.addProjectOperation(\"selectCase\", {\n cases,\n otherwise,\n alias,\n });\n return this;\n }\n\n /**\n * Adds a simple conditional field (if/else).\n * @param condition - The condition to evaluate\n * @param thenValue - Value if condition is true\n * @param elseValue - Value if condition is false\n * @param alias - The alias for the computed field\n */\n public selectWhen(\n condition: RawExpression,\n thenValue: RawExpression | unknown,\n elseValue: RawExpression | unknown,\n alias: string,\n ): this {\n this.operationsHelper.addProjectOperation(\"selectWhen\", {\n condition,\n thenValue,\n elseValue,\n alias,\n });\n return this;\n }\n\n /**\n * Allows direct manipulation of the MongoDB projection object.\n * @param callback - Function that receives and modifies the projection object\n */\n public selectDriverProjection(callback: (projection: Record<string, unknown>) => void): this {\n this.operationsHelper.addProjectOperation(\"selectDriverProjection\", {\n callback,\n });\n return this;\n }\n\n /**\n * Extracts a JSON field from a document.\n * @param path - The JSON path to extract\n * @param alias - Optional alias for the extracted field\n */\n public selectJson(path: string, alias?: string): this {\n this.operationsHelper.addProjectOperation(\"selectJson\", { path, alias });\n return this;\n }\n\n /**\n * Extracts a JSON field using a raw MongoDB expression.\n * @param path - The JSON path\n * @param expression - The raw expression for extraction\n * @param alias - The alias for the extracted field\n */\n public selectJsonRaw(path: string, expression: RawExpression, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectJsonRaw\", {\n path,\n expression,\n alias,\n });\n return this;\n }\n\n /**\n * Excludes a JSON path from the results.\n * @param path - The JSON path to exclude\n */\n public deselectJson(path: string): this {\n this.operationsHelper.addProjectOperation(\"deselectJson\", { path });\n return this;\n }\n\n /**\n * Concatenates multiple fields into a single string field.\n * @param fields - Array of fields or expressions to concatenate\n * @param alias - The alias for the concatenated field\n */\n public selectConcat(fields: Array<string | RawExpression>, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectConcat\", {\n fields,\n alias,\n });\n return this;\n }\n\n /**\n * Returns the first non-null value from a list of fields.\n * @param fields - Array of fields to check\n * @param alias - The alias for the coalesced field\n */\n public selectCoalesce(fields: Array<string | RawExpression>, alias: string): this {\n this.operationsHelper.addProjectOperation(\"selectCoalesce\", {\n fields,\n alias,\n });\n return this;\n }\n\n /**\n * Adds window function operations to the query.\n * @param spec - The window function specification\n */\n public selectWindow(spec: RawExpression): this {\n this.operationsHelper.addOperation(\"$setWindowFields\", \"selectWindow\", { spec }, false);\n return this;\n }\n\n /**\n * Excludes specific fields from the query results.\n * @param fields - Field names to exclude\n */\n public deselect(fields: string[]): this;\n public deselect(...fields: Array<string | string[]>): this;\n public deselect(...args: Array<string | string[]>): this {\n const fields = this.normalizeSelectFields(args);\n this.operationsHelper.addProjectOperation(\"deselect\", { fields });\n return this;\n }\n\n /**\n * Returns only distinct values for the specified fields.\n * @param fields - Optional field names to use for distinctness\n */\n public distinctValues(fields?: string | string[]): this {\n this.operationsHelper.addGroupOperation(\"distinct\", { fields }, false);\n return this;\n }\n\n /**\n * Adds additional fields to an existing selection.\n * @param fields - Additional field names to include\n */\n public addSelect(fields: string[]): this;\n public addSelect(...fields: Array<string | string[]>): this;\n public addSelect(...args: Array<string | string[]>): this {\n const fields = this.normalizeSelectFields(args);\n this.operationsHelper.addProjectOperation(\"addSelect\", { fields });\n return this;\n }\n\n /**\n * Removes all field selection restrictions.\n */\n public clearSelect(): this {\n this.operations = this.operations.filter((op) => op.stage !== \"$project\");\n return this;\n }\n\n /**\n * Alias for `clearSelect()`. Removes all field restrictions.\n */\n public selectAll(): this {\n return this.clearSelect();\n }\n\n /**\n * Alias for `clearSelect()`. Resets to default field selection.\n */\n public selectDefault(): this {\n return this.clearSelect();\n }\n\n // ============================================================================\n // ORDERING\n // ============================================================================\n\n /**\n * Orders the query results by a specific field or multiple fields.\n *\n * @param field - The field name to sort by, or an object with multiple fields\n * @param direction - The sort direction (only used when field is a string)\n *\n * @example\n * ```typescript\n * // Single field\n * query.orderBy(\"createdAt\", \"desc\");\n *\n * // Multiple fields\n * query.orderBy({ id: \"asc\", age: \"desc\", createdAt: \"desc\" });\n * ```\n */\n public orderBy(field: string, direction?: OrderDirection): this;\n public orderBy(fields: Record<string, OrderDirection>): this;\n public orderBy(\n fieldOrFields: string | Record<string, OrderDirection>,\n direction: OrderDirection = \"asc\",\n ): this {\n if (typeof fieldOrFields === \"string\") {\n // Single field\n this.operationsHelper.addSortOperation(\"orderBy\", {\n field: fieldOrFields,\n direction,\n });\n } else {\n // Multiple fields - add each as a separate operation (they'll be merged)\n for (const [field, dir] of Object.entries(fieldOrFields)) {\n this.operationsHelper.addSortOperation(\"orderBy\", {\n field,\n direction: dir,\n });\n }\n }\n return this;\n }\n\n /**\n * Orders the query results by a field in descending order.\n * @param field - The field name to sort by\n */\n public orderByDesc(field: string): this {\n return this.orderBy(field, \"desc\");\n }\n\n /**\n * Orders the query results using a raw MongoDB sort expression.\n * @param expression - The raw MongoDB sort expression\n * @param bindings - Optional parameter bindings\n */\n public orderByRaw(expression: RawExpression, bindings?: unknown[]): this {\n this.operationsHelper.addSortOperation(\"orderByRaw\", {\n expression,\n bindings,\n });\n return this;\n }\n\n /**\n * Orders the query results randomly.\n */\n public orderByRandom(limit: number = 1000): this {\n this.operationsHelper.addSortOperation(\"orderByRandom\", { limit }, false);\n return this;\n }\n\n /**\n * Orders results by a date field in descending order (newest first).\n * @param column - The date column to sort by\n */\n public latest(column: string = \"createdAt\") {\n return this.orderBy(column, \"desc\").get();\n }\n\n /**\n * Orders results by a date field in ascending order (oldest first).\n * @param column - The date column to sort by\n */\n public oldest(column: string = \"createdAt\"): this {\n return this.orderBy(column, \"asc\");\n }\n\n // ============================================================================\n // LIMITING / PAGINATION\n // ============================================================================\n\n /**\n * Limits the number of documents returned by the query.\n * @param value - The maximum number of documents to return\n */\n public limit(value: number): this {\n this.operationsHelper.addOperation(\"$limit\", \"limit\", { value }, false);\n return this;\n }\n\n /**\n * Skips a specified number of documents in the query results.\n * @param value - The number of documents to skip\n */\n public skip(value: number): this {\n this.operationsHelper.addOperation(\"$skip\", \"skip\", { value }, false);\n return this;\n }\n\n /**\n * Alias for `skip()`. Skips a specified number of documents.\n * @param value - The number of documents to skip\n */\n public offset(value: number): this {\n return this.skip(value);\n }\n\n /**\n * Alias for `limit()`. Limits the number of documents returned.\n * @param value - The maximum number of documents to return\n */\n public take(value: number): this {\n return this.limit(value);\n }\n\n /**\n * Applies cursor-based filtering for pagination.\n * @param after - Cursor value for forward pagination\n * @param before - Cursor value for backward pagination\n */\n public cursor(after?: unknown, before?: unknown): this {\n this.operationsHelper.addMatchOperation(\"cursor\", { after, before });\n return this;\n }\n\n // ============================================================================\n // GROUPING / AGGREGATION\n // ============================================================================\n\n /**\n * Groups documents by one or more fields.\n *\n * @param fields - Field(s) to group by\n * @param aggregates - Optional aggregate operations to perform\n *\n * @example\n * ```typescript\n * import { $agg } from '@warlock.js/cascade';\n *\n * // Simple grouping\n * query.groupBy(\"type\");\n *\n * // Grouping with aggregates\n * query.groupBy(\"type\", {\n * count: $agg.count(),\n * total: $agg.sum(\"duration\")\n * });\n * ```\n */\n public groupBy(fields: GroupByInput): this;\n public groupBy(fields: GroupByInput, aggregates: Record<string, RawExpression>): this;\n public groupBy(fields: GroupByInput, aggregates?: Record<string, RawExpression>): this {\n if (aggregates) {\n this.operationsHelper.addGroupOperation(\n \"groupByWithAggregates\",\n { fields, aggregates },\n false,\n );\n } else {\n this.operationsHelper.addGroupOperation(\"groupBy\", { fields }, false);\n }\n\n return this;\n }\n\n /**\n * Groups documents using a raw MongoDB expression.\n * @param expression - The raw grouping expression\n * @param bindings - Optional parameter bindings\n */\n public groupByRaw(expression: RawExpression, bindings?: unknown[]): this {\n this.operationsHelper.addGroupOperation(\"groupByRaw\", { expression, bindings }, false);\n return this;\n }\n\n /**\n * Filters grouped results based on aggregate conditions.\n * @param field - The aggregate field to filter on\n * @param value - The value to compare against\n * @param operator - The comparison operator\n * @param condition - A condition object for complex filters\n */\n public having(field: string, value: unknown): this;\n public having(field: string, operator: WhereOperator, value: unknown): this;\n public having(condition: HavingInput): this;\n public having(...args: any[]): this {\n if (args.length === 1) {\n this.operationsHelper.addMatchOperation(\"having:condition\", args[0], false);\n } else if (args.length === 2) {\n this.operationsHelper.addMatchOperation(\n \"having\",\n { field: args[0], operator: \"=\", value: args[1] },\n false,\n );\n } else {\n this.operationsHelper.addMatchOperation(\n \"having\",\n { field: args[0], operator: args[1], value: args[2] },\n false,\n );\n }\n return this;\n }\n\n /**\n * Filters grouped results using a raw MongoDB expression.\n * @param expression - The raw having expression\n * @param bindings - Optional parameter bindings\n */\n public havingRaw(expression: RawExpression, bindings?: unknown[]): this {\n this.operationsHelper.addMatchOperation(\"havingRaw\", { expression, bindings }, false);\n return this;\n }\n\n // ============================================================================\n // JOINS\n // ============================================================================\n\n /**\n * Performs a left outer join with another collection.\n * @param options - Join configuration including table, fields, and optional pipeline\n */\n public join(options: JoinOptions): this {\n this.operationsHelper.addLookupOperation(\"join\", options);\n return this;\n }\n\n // ============================================================================\n // UTILITY / EXTENSIONS\n // ============================================================================\n\n /**\n * Allows direct manipulation of the native MongoDB query.\n * @param builder - Function that receives and modifies the native query\n */\n public raw(builder: (native: unknown) => unknown): this {\n this.operationsHelper.addMatchOperation(\"raw\", { builder }, false);\n return this;\n }\n\n /**\n * Extends the query builder with driver-specific functionality.\n * @param extension - The extension name\n * @param _args - Extension-specific arguments\n * @returns The extension's return value\n */\n public extend<R>(extension: string, ..._args: unknown[]): R {\n // Driver-specific extensions can be added here\n throw new Error(`Extension '${extension}' is not supported by MongoQueryBuilder`);\n }\n\n /**\n * Creates a deep copy of the query builder.\n * @returns A new query builder instance with copied operations\n */\n public clone(): this {\n const cloned = new MongoQueryBuilder<T>(this.table, this.dataSource) as this;\n cloned.operations = [...this.operations];\n cloned.hydrateCallback = this.hydrateCallback?.bind(cloned);\n cloned.fetchingCallback = this.fetchingCallback?.bind(cloned);\n cloned.hydratingCallback = this.hydratingCallback?.bind(cloned);\n cloned.fetchedCallback = this.fetchedCallback?.bind(cloned);\n\n // Copy scope state\n cloned.pendingGlobalScopes = this.pendingGlobalScopes;\n cloned.availableLocalScopes = this.availableLocalScopes;\n cloned.disabledGlobalScopes = new Set(this.disabledGlobalScopes);\n cloned.scopesApplied = this.scopesApplied;\n\n (cloned as any).__operationsHelper = (this as any).__operationsHelper;\n return cloned;\n }\n\n /**\n * Executes a callback with the query builder without breaking the chain.\n * @param callback - Function to execute with the builder\n */\n public tap(callback: (builder: this) => void): this {\n callback(this);\n return this;\n }\n\n /**\n * Conditionally applies query modifications based on a condition.\n * @param condition - The condition to evaluate\n * @param callback - Function to execute if condition is true\n * @param otherwise - Optional function to execute if condition is false\n *\n * @example\n * query.when(searchTerm, (q, term) => q.whereLike('name', term))\n */\n public when<V>(\n condition: V | boolean,\n callback: (builder: this, value: V) => void,\n otherwise?: (builder: this) => void,\n ): this {\n if (condition) {\n callback(this, condition as V);\n } else if (otherwise) {\n otherwise(this);\n }\n return this;\n }\n\n // ============================================================================\n // EXECUTION METHODS\n // ============================================================================\n\n /**\n * Executes the query and returns all matching documents.\n * @returns an array of matching documents\n */\n public async get<Output = T>(): Promise<Output[]> {\n const startTime = Date.now();\n\n // Emit onFetching event\n if (this.fetchingCallback) {\n await this.fetchingCallback(this);\n }\n\n // Execute query and get raw records\n const rawRecords = await this.execute<Output>();\n\n // Emit onHydrating event\n if (this.hydratingCallback) {\n await this.hydratingCallback(rawRecords, {\n query: this,\n hydrateCallback: this.hydrateCallback,\n });\n }\n\n // Hydrate records\n const hydratedRecords = this.hydrateCallback\n ? rawRecords.map(this.hydrateCallback)\n : rawRecords;\n\n // Emit onFetched event\n if (this.fetchedCallback) {\n await this.fetchedCallback(hydratedRecords, {\n query: this,\n rawRecords,\n duration: Date.now() - startTime,\n });\n }\n\n return hydratedRecords;\n }\n\n /**\n * Execute the query and get first result\n * This is different than `first` as first adds a `limit = 1` to the pipeline\n */\n public async getFirst<Output = T>(): Promise<Output | null> {\n return (await this.get<Output>())?.[0] ?? null;\n }\n\n /**\n * Executes the query and returns the first matching document.\n * @returns the first document or null\n */\n public async first<Output = T>(): Promise<Output | null> {\n const results = await this.limit(1).get<Output>();\n return results.length > 0 ? results[0] : null;\n }\n\n /**\n * Executes the query and returns the first matching document, throwing if none found.\n * @returns the first document\n */\n public async firstOrFail<Output = T>(): Promise<Output> {\n const result = await this.first<Output>();\n if (!result) {\n throw new Error(\"No records found matching the query\");\n }\n return result;\n }\n\n /**\n * Configures the query to retrieve the last matching document.\n */\n public last<Output = T>(field: string = \"createdAt\"): Promise<Output | null> {\n this.orderBy(field, \"desc\");\n return this.first<Output>();\n }\n\n /**\n * Counts the number of documents matching the query.\n * @returns the count of matching documents\n */\n public async count(): Promise<number> {\n const pipeline = this.buildPipeline();\n pipeline.push({ $count: \"total\" });\n\n const results = await this.execute<{ total: number }>(pipeline);\n\n return results.length > 0 ? results[0].total : 0;\n }\n\n /**\n * Calculates the sum of a numeric field across matching documents.\n * @param field - The numeric field to sum\n * @returns the sum value\n */\n public async sum(field: string): Promise<number> {\n this.groupByRaw({\n _id: null,\n total: { $sum: `$${field}` },\n });\n\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n const result = await this.getFirst<{ total: number }>();\n\n return result?.total ?? 0;\n }\n\n /**\n * Calculates the average value of a numeric field across matching documents.\n * @param field - The numeric field to average\n * @returns the average value\n */\n public async avg(field: string): Promise<number> {\n this.groupByRaw({\n _id: null,\n average: { $avg: `$${field}` },\n });\n\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n return (await this.getFirst<{ average: number }>())?.average ?? 0;\n }\n\n /**\n * Finds the minimum value of a field across matching documents.\n * @param field - The field to find the minimum of\n * @returns the minimum value\n */\n public async min(field: string): Promise<number> {\n this.groupByRaw({\n _id: null,\n minimum: { $min: `$${field}` },\n });\n\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n return (await this.getFirst<{ minimum: number }>())?.minimum ?? 0;\n }\n\n /**\n * Finds the maximum value of a field across matching documents.\n * @param field - The field to find the maximum of\n * @returns the maximum value\n */\n public async max(field: string): Promise<number> {\n this.groupByRaw({\n _id: null,\n maximum: { $max: `$${field}` },\n });\n\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n return (await this.getFirst<{ maximum: number }>())?.maximum ?? 0;\n }\n\n /**\n * Returns an array of distinct values for a field, respecting query filters.\n * @param field - The field to get distinct values from\n * @returns an array of distinct values\n */\n public async distinct<T = unknown>(field: string, ignoreNull = true): Promise<T[]> {\n if (ignoreNull) {\n this.whereNotNull(field);\n }\n\n this.groupBy(field);\n\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n const results = await this.get<{ _id: T }>();\n return results.map((doc) => doc._id);\n }\n\n /**\n * Count distinct values for a field, respecting query filters.\n * @param field - The field to count distinct values for\n * @returns the count of distinct values\n */\n public async countDistinct(field: string, ignoreNull = true): Promise<number> {\n if (ignoreNull) {\n this.whereNotNull(field);\n }\n\n return await this.groupBy(field).count();\n }\n\n /**\n * Extracts a single field value from each matching document.\n * @param field - The field to extract\n * @returns an array of field values\n */\n public async pluck<T = unknown>(field: string): Promise<T[]> {\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n // Use object aliasing: { [field]: \"value\" } to project field as \"value\"\n const results = await this.selectAs(field, \"value\").get<{\n value: T;\n }>();\n\n return results.map((doc) => doc.value).filter((value) => value !== undefined);\n }\n\n /**\n * Gets the value of a single field from the first matching document.\n * @param field - The field to extract\n * @returns the field value or null\n */\n public async value<T = unknown>(field: string): Promise<T | null> {\n // make sure to clear the data map callback\n this.hydrateCallback = undefined;\n\n const result = await this.selectAs(field, \"value\").first<{ value: T }>();\n return result?.value ?? null;\n }\n\n /**\n * Checks if any documents match the query.\n * @param filter - Optional filter to apply to the query\n * @returns true if documents exist, false otherwise\n */\n public async exists(filter?: GenericObject): Promise<boolean> {\n if (filter) {\n this.where(filter);\n }\n\n const count = await this.limit(1).count();\n return count > 0;\n }\n\n /**\n * Checks if no documents match the query.\n * @param filter - Optional filter to apply to the query\n * @returns true if no documents exist, false otherwise\n */\n public async notExists(filter?: GenericObject): Promise<boolean> {\n return !(await this.exists(filter));\n }\n\n /**\n * Increments a numeric field by the specified amount for first matching document.\n * @param field - The field to increment\n * @param amount - The amount to increment by (default: 1)\n * @returns the new value\n */\n public async increment(field: string, amount: number = 1): Promise<number> {\n const filter = this.buildFilter();\n\n const result = await this.collection.findOneAndUpdate(\n filter,\n {\n $inc: { [field]: amount },\n },\n {\n returnDocument: \"after\",\n },\n );\n\n return get(result, field, 0);\n }\n\n /**\n * Decrements a numeric field by the specified amount.\n * @param field - The field to decrement\n * @param amount - The amount to decrement by\n * @returns the new value\n */\n public async decrement(field: string, amount: number = 1): Promise<number> {\n return this.increment(field, -amount);\n }\n\n /**\n * Increments a numeric field by the specified amount for all matching documents.\n * @param field - The field to increment\n * @param amount - The amount to increment by (default: 1)\n * @returns the number of documents modified\n */\n public async incrementMany(field: string, amount: number = 1): Promise<number> {\n const filter = this.buildFilter();\n\n const result = await this.dataSource.driver.updateMany(this.table, filter, {\n $inc: { [field]: amount },\n });\n\n return result.modifiedCount;\n }\n\n /**\n * Decrements a numeric field by the specified amount for all matching documents.\n * @param field - The field to decrement\n * @param amount - The amount to decrement by (default: 1)\n * @returns the number of documents modified\n */\n public async decrementMany(field: string, amount: number = 1): Promise<number> {\n return this.incrementMany(field, -amount);\n }\n\n /**\n * Delete all documents matching the query.\n */\n public async delete(): Promise<number> {\n const filter = this.buildFilter();\n return await this.dataSource.driver.deleteMany(this.table, filter);\n }\n\n /**\n * Delete a single document matching the query.\n */\n public async deleteOne(): Promise<number> {\n const filter = this.buildFilter();\n return await this.dataSource.driver.delete(this.table, filter);\n }\n\n /**\n * Update the given fields for all documents matching the query.\n */\n public async update(fields: Record<string, unknown>): Promise<number> {\n const filter = this.buildFilter();\n const result = await this.dataSource.driver.updateMany(this.table, filter, {\n $set: fields,\n });\n return result.modifiedCount;\n }\n\n /**\n * Unset the given fields from all documents matching the query.\n */\n public async unset(...fields: string[]): Promise<number> {\n const filter = this.buildFilter();\n const result = await this.dataSource.driver.updateMany(this.table, filter, {\n $unset: fields.reduce(\n (acc, field) => {\n acc[field] = 1;\n return acc;\n },\n {} as Record<string, 1 | true>,\n ),\n });\n return result.modifiedCount;\n }\n\n // ============================================================================\n // CHUNKING / PAGINATION\n // ============================================================================\n\n /**\n * Processes query results in chunks, executing a callback for each chunk.\n * @param size - The number of documents per chunk\n * @param callback - Function to execute for each chunk\n * @returns void\n */\n public async chunk(\n size: number,\n callback: (rows: T[], chunkIndex: number) => Promise<boolean | void> | boolean | void,\n ): Promise<void> {\n let chunkIndex = 0;\n let hasMore = true;\n\n while (hasMore) {\n const chunk = await this.clone()\n .skip(chunkIndex * size)\n .limit(size)\n .get();\n\n if (chunk.length === 0) {\n break;\n }\n\n const shouldContinue = await callback(chunk, chunkIndex);\n\n if (shouldContinue === false) {\n break;\n }\n\n hasMore = chunk.length === size;\n chunkIndex++;\n }\n }\n\n /**\n * Executes the query with traditional page-based pagination.\n * @param options - Pagination options\n * @returns pagination result with data and metadata\n */\n public async paginate(options: PaginationOptions): Promise<PaginationResult<T>> {\n const page = options.page ?? 1;\n const limit = options.limit ?? 10;\n const skip = (page - 1) * limit;\n\n const [data, total] = await Promise.all([\n this.clone().skip(skip).limit(limit).get(),\n this.count(),\n ]);\n\n return {\n data,\n pagination: {\n total,\n page,\n limit,\n pages: Math.ceil(total / limit),\n },\n };\n }\n\n /**\n * Executes the query with cursor-based pagination supporting both directions.\n * @param options - Cursor pagination options\n * @returns cursor pagination result with data and cursor info\n */\n public async cursorPaginate(\n options: CursorPaginationOptions,\n ): Promise<CursorPaginationResult<T>> {\n const limit = options.limit;\n const cursor = options.cursor;\n const column = options.column ?? \"_id\";\n const direction = options.direction ?? \"next\";\n\n // Apply cursor filter\n if (cursor) {\n const operator = direction === \"next\" ? \">\" : \"<\";\n this.where(column, operator, cursor);\n }\n\n // Apply sorting\n const sortOrder = direction === \"next\" ? \"asc\" : \"desc\";\n this.orderBy(column, sortOrder);\n\n this.orderBy(\"_id\", sortOrder); // Always sort by _id to ensure consistent order\n\n // Fetch one extra to detect if there are more results\n const results = await this.limit(limit + 1).get<T>();\n\n const hasMore = results.length > limit;\n let data = hasMore ? results.slice(0, limit) : results;\n\n // Reverse results if fetching previous page to keep natural order\n if (direction === \"prev\") {\n data = data.reverse();\n }\n\n // Determine cursors based on actual data\n let nextCursor: unknown | undefined;\n let prevCursor: unknown | undefined;\n let hasPrev = false;\n\n if (data.length > 0) {\n const firstItem = (data[0] as any)[column];\n const lastItem = (data[data.length - 1] as any)[column];\n\n if (direction === \"next\") {\n // Forward pagination\n nextCursor = hasMore ? lastItem : undefined;\n\n // Check if there's a previous page\n if (cursor) {\n hasPrev = true;\n prevCursor = firstItem;\n }\n } else {\n // Backward pagination\n prevCursor = hasMore ? firstItem : undefined;\n hasPrev = hasMore;\n\n // Check if there's a next page\n if (cursor) {\n nextCursor = lastItem;\n }\n }\n }\n\n return {\n data,\n pagination: {\n hasMore,\n hasPrev,\n nextCursor,\n prevCursor,\n },\n };\n }\n\n // ============================================================================\n // INSPECTION / DEBUGGING\n // ============================================================================\n\n /**\n * Returns the MongoDB aggregation pipeline that will be executed.\n * @returns The MongoDB aggregation pipeline array\n */\n public parse() {\n return this.buildPipeline();\n }\n\n /**\n * Returns a formatted string representation of the query pipeline.\n * @returns A formatted string representation of the pipeline\n */\n public pretty() {\n return this.getParser().toPrettyString();\n }\n\n /**\n * Returns the MongoDB query execution plan.\n * @returns MongoDB's explain output\n */\n public async explain(): Promise<unknown> {\n // TODO: Trigger the explaining event\n const pipeline = this.buildPipeline();\n const session = databaseTransactionContext.getSession();\n const options = session ? { session, explain: true } : { explain: true };\n\n return this.collection.aggregate(pipeline, options as any).toArray();\n }\n\n // ============================================================================\n // INTERNAL PIPELINE BUILDING\n // ============================================================================\n\n /**\n * Get query parser instance\n */\n protected getParser(): MongoQueryParser {\n this.applyPendingScopes();\n\n return new MongoQueryParser({\n collection: this.collection,\n operations: this.operations,\n createSubBuilder: () => new MongoQueryBuilder(this.table, this.dataSource),\n });\n }\n\n /**\n * Build the MongoDB aggregation pipeline from the operations list.\n * @returns The MongoDB aggregation pipeline\n */\n protected buildPipeline() {\n const parser = this.getParser();\n\n return parser.parse();\n }\n\n /**\n * Build a MongoDB filter object from the query's where clauses.\n * Used for update operations like increment/decrement.\n * @returns The MongoDB filter object\n */\n protected buildFilter(): Record<string, unknown> {\n // Get all match operations\n const matchOperations = this.operations.filter((op) => op.stage === \"$match\");\n\n if (matchOperations.length === 0) {\n return {}; // No filters, match all documents\n }\n\n // Build the pipeline and extract the first $match stage\n const pipeline = this.buildPipeline();\n const matchStage = pipeline.find((stage) => stage.$match);\n\n if (matchStage && matchStage.$match) {\n return matchStage.$match;\n }\n\n return {};\n }\n\n /**\n * Execute the aggregate command\n */\n protected async execute<T extends any = any>(pipeline?: any[]): Promise<T[]> {\n const aggregationPipeline = pipeline || this.buildPipeline();\n const session = databaseTransactionContext.getSession() as ClientSession | undefined;\n const options: AggregateOptions = { session };\n\n // TODO: Trigger the executing event\n const results = (await this.collection\n .aggregate(aggregationPipeline, options)\n .toArray()) as T[];\n\n // TODO: Trigger the fetched event\n\n // we need to cleanup the operations list\n this.operations = [];\n this.operationsHelper.setOperations(this.operations);\n\n return results;\n }\n}\n","/**\n * MongoDB-specific sync adapter implementation.\n *\n * @module cascade-next/drivers/mongo/mongo-sync-adapter\n */\n\nimport type {\n SyncAdapterContract,\n SyncInstruction,\n} from \"../../contracts/sync-adapter.contract\";\nimport type { MongoDbDriver } from \"./mongodb-driver\";\n\n/**\n * MongoDB implementation of the sync adapter.\n * Handles array updates using positional operators and arrayFilters.\n * Automatically participates in active transactions via the driver's session context.\n */\nexport class MongoSyncAdapter implements SyncAdapterContract {\n private readonly driver: MongoDbDriver;\n\n /**\n * Creates a new MongoDB sync adapter.\n *\n * @param driver - The MongoDB driver instance (provides session-aware operations)\n */\n public constructor(driver: MongoDbDriver) {\n this.driver = driver;\n }\n\n /**\n * Executes a batch of sync instructions.\n *\n * @param instructions - Array of sync instructions\n * @returns Total number of documents affected\n */\n public async executeBatch(instructions: SyncInstruction[]): Promise<number> {\n let totalAffected = 0;\n\n for (const instruction of instructions) {\n const affected = instruction.isArrayUpdate\n ? await this.executeArrayUpdate(instruction)\n : await this.executeOne(instruction);\n\n totalAffected += affected;\n }\n\n return totalAffected;\n }\n\n /**\n * Executes a single sync instruction.\n * Uses the driver's updateMany to automatically participate in active transactions.\n *\n * @param instruction - The sync instruction\n * @returns Number of documents affected\n */\n public async executeOne(instruction: SyncInstruction): Promise<number> {\n const result = await this.driver.updateMany(\n instruction.targetTable,\n instruction.filter,\n instruction.update,\n );\n\n return result.modifiedCount;\n }\n\n /**\n * Executes an array update using MongoDB positional operators.\n * Uses the driver's updateMany to automatically participate in active transactions.\n *\n * @param instruction - The sync instruction with array info\n * @returns Number of documents affected\n */\n public async executeArrayUpdate(\n instruction: SyncInstruction,\n ): Promise<number> {\n if (!instruction.arrayField || !instruction.identifierField) {\n throw new Error(\n \"Array update requires arrayField and identifierField to be specified\",\n );\n }\n\n // Strategy 1: Try positional operator $ (simpler, faster)\n // Works when filter already identifies the array element\n if (this.canUsePositionalOperator(instruction)) {\n const result = await this.driver.updateMany(\n instruction.targetTable,\n instruction.filter,\n instruction.update,\n );\n return result.modifiedCount;\n }\n\n // Strategy 2: Use arrayFilters (more flexible)\n // Works for any array update scenario\n return await this.executeWithArrayFilters(instruction);\n }\n\n /**\n * Checks if positional operator $ can be used.\n * Requires filter to already match the array element.\n *\n * @param instruction - The sync instruction\n * @returns True if positional operator can be used\n */\n private canUsePositionalOperator(instruction: SyncInstruction): boolean {\n // Check if filter already includes array element match\n const arrayElementFilter = `${instruction.arrayField}.${instruction.identifierField}`;\n return arrayElementFilter in instruction.filter;\n }\n\n /**\n * Executes array update using arrayFilters.\n * Uses the driver's updateMany with arrayFilters option to participate in transactions.\n *\n * @param instruction - The sync instruction\n * @returns Number of documents affected\n */\n private async executeWithArrayFilters(\n instruction: SyncInstruction,\n ): Promise<number> {\n // Build arrayFilters to match array elements\n const arrayFilters = [\n {\n [`elem.${instruction.identifierField}`]: instruction.identifierValue,\n },\n ];\n\n // Transform update to use array filter placeholder\n const transformedUpdate = this.transformUpdateForArrayFilters(\n instruction.update,\n instruction.arrayField!,\n );\n\n // Build optimized filter to reduce documents scanned\n const optimizedFilter = this.buildOptimizedFilter(\n instruction.filter,\n instruction.arrayField!,\n instruction.identifierField!,\n );\n\n // Use driver's updateMany (session-aware) with arrayFilters\n const result = await this.driver.updateMany(\n instruction.targetTable,\n optimizedFilter,\n transformedUpdate,\n { arrayFilters },\n );\n\n return result.modifiedCount;\n }\n\n /**\n * Builds an optimized filter to reduce the number of documents scanned.\n * Adds array existence check when filter doesn't already match array elements.\n *\n * @param originalFilter - The original filter from the instruction\n * @param arrayField - The array field path\n * @param identifierField - The identifier field within array elements\n * @returns Optimized filter\n */\n private buildOptimizedFilter(\n originalFilter: Record<string, unknown>,\n arrayField: string,\n identifierField: string,\n ): Record<string, unknown> {\n // If filter already has array element match, use it as-is\n const arrayElementFilter = `${arrayField}.${identifierField}`;\n if (arrayElementFilter in originalFilter) {\n return originalFilter;\n }\n\n // Otherwise, add array existence check to avoid full collection scan\n return {\n ...originalFilter,\n [arrayField]: { $exists: true, $ne: [] }, // Array exists and not empty\n };\n }\n\n /**\n * Transforms update operation to use arrayFilters placeholder.\n *\n * @param update - Original update operation\n * @param arrayField - Array field path\n * @returns Transformed update operation\n */\n private transformUpdateForArrayFilters(\n update: Record<string, unknown>,\n arrayField: string,\n ): Record<string, unknown> {\n const transformed: Record<string, unknown> = {};\n\n for (const [operator, fields] of Object.entries(update)) {\n if (typeof fields === \"object\" && fields !== null) {\n const transformedFields: Record<string, unknown> = {};\n\n for (const [field, value] of Object.entries(fields)) {\n // Replace positional $ with arrayFilters placeholder $[elem]\n const transformedField = field.replace(\n `${arrayField}.$`,\n `${arrayField}.$[elem]`,\n );\n transformedFields[transformedField] = value;\n }\n\n transformed[operator] = transformedFields;\n }\n }\n\n return transformed;\n }\n\n}\n","import type { ClientSession, CreateIndexesOptions, Db, IndexDescription } from \"mongodb\";\nimport { databaseTransactionContext } from \"../../context/database-transaction-context\";\nimport type {\n ColumnDefinition,\n ForeignKeyDefinition,\n FullTextIndexOptions,\n GeoIndexOptions,\n IndexDefinition,\n MigrationDriverContract,\n VectorIndexOptions,\n} from \"../../contracts/migration-driver.contract\";\nimport type { MongoDbDriver } from \"./mongodb-driver\";\n\n/**\n * MongoDB-specific migration driver implementation.\n *\n * Key behaviors:\n * - Column operations are **no-ops** (MongoDB is schema-less)\n * - Index operations use native `createIndex()`\n * - Foreign keys are **no-ops** (MongoDB has no FK constraints)\n * - TTL indexes supported natively\n * - Vector indexes use Atlas Search (when available)\n * - Schema validation uses `collMod` command\n *\n * @example\n * ```typescript\n * const migrationDriver = new MongoMigrationDriver(mongoDriver);\n * await migrationDriver.createIndex(\"users\", {\n * columns: [\"email\"],\n * unique: true,\n * });\n * ```\n */\nexport class MongoMigrationDriver implements MigrationDriverContract {\n /** Active transaction session (if any) */\n private session?: ClientSession;\n\n /**\n * Create a new MongoDB migration driver.\n *\n * @param driver - The MongoDB driver instance\n */\n public constructor(private readonly driver: MongoDbDriver) {}\n\n /**\n * Get the MongoDB database instance.\n */\n private get db(): Db {\n return this.driver.getDatabase();\n }\n\n /**\n * Get session options for operations.\n */\n private get sessionOptions(): { session?: ClientSession } | undefined {\n const session = databaseTransactionContext.getSession<ClientSession>();\n return session ? { session } : undefined;\n }\n\n // ============================================================================\n // TABLE/COLLECTION OPERATIONS\n // ============================================================================\n\n /**\n * Create a new collection.\n *\n * MongoDB creates collections lazily on first insert, but this method\n * creates them explicitly for migrations that need to add indexes or\n * schema validation.\n */\n public async createTable(table: string): Promise<void> {\n try {\n await this.db.createCollection(table);\n } catch (error: any) {\n // Collection already exists - ignore\n if (error.codeName === \"NamespaceExists\") {\n return;\n }\n throw error;\n }\n }\n\n /**\n * Create table if not exists\n */\n public async createTableIfNotExists(table: string): Promise<void> {\n try {\n await this.db.createCollection(table);\n } catch (error: any) {\n // Collection already exists - ignore\n if (error.codeName === \"NamespaceExists\") {\n return;\n }\n throw error;\n }\n }\n\n /**\n * Drop an existing collection.\n *\n * @throws Error if collection doesn't exist\n */\n public async dropTable(table: string): Promise<void> {\n await this.db.dropCollection(table);\n }\n\n /**\n * Drop collection if it exists (no error if missing).\n */\n public async dropTableIfExists(table: string): Promise<void> {\n try {\n await this.db.dropCollection(table);\n } catch {\n // Collection doesn't exist - ignore\n }\n }\n\n /**\n * Rename a collection.\n */\n public async renameTable(from: string, to: string): Promise<void> {\n await this.db.renameCollection(from, to);\n }\n\n /**\n * Check if a collection exists.\n */\n public async tableExists(table: string): Promise<boolean> {\n const collections = await this.db.listCollections({ name: table }).toArray();\n return collections.length > 0;\n }\n\n // ============================================================================\n // COLUMN OPERATIONS (No-ops for MongoDB)\n // ============================================================================\n\n /**\n * Add a column (no-op for MongoDB).\n *\n * MongoDB is schema-less, so columns don't need to be declared.\n */\n public async addColumn(_table: string, _column: ColumnDefinition): Promise<void> {\n // No-op: MongoDB is schema-less\n }\n\n /**\n * Drop a column by running $unset on all documents.\n *\n * This actually removes the field from all documents in the collection.\n */\n public async dropColumn(table: string, column: string): Promise<void> {\n const collection = this.db.collection(table);\n await collection.updateMany({}, { $unset: { [column]: \"\" } }, this.sessionOptions);\n }\n\n /**\n * Drop multiple columns by running $unset on all documents.\n */\n public async dropColumns(table: string, columns: string[]): Promise<void> {\n const collection = this.db.collection(table);\n const unsetFields: Record<string, string> = {};\n for (const column of columns) {\n unsetFields[column] = \"\";\n }\n await collection.updateMany({}, { $unset: unsetFields }, this.sessionOptions);\n }\n\n /**\n * Rename a column by running $rename on all documents.\n */\n public async renameColumn(table: string, from: string, to: string): Promise<void> {\n const collection = this.db.collection(table);\n await collection.updateMany({}, { $rename: { [from]: to } }, this.sessionOptions);\n }\n\n /**\n * Modify a column definition (no-op for MongoDB).\n *\n * MongoDB is schema-less, so column types don't need to be modified.\n */\n public async modifyColumn(_table: string, _column: ColumnDefinition): Promise<void> {\n // No-op: MongoDB is schema-less\n }\n\n // ============================================================================\n // INDEX OPERATIONS\n // ============================================================================\n\n /**\n * Create an index on one or more columns.\n */\n public async createIndex(table: string, index: IndexDefinition): Promise<void> {\n const collection = this.db.collection(table);\n\n // Build index specification\n const indexSpec: IndexDescription[\"key\"] = {};\n for (let i = 0; i < index.columns.length; i++) {\n const column = index.columns[i];\n const direction = index.directions?.[i] === \"desc\" ? -1 : 1;\n indexSpec[column] = direction;\n }\n\n // Build index options\n const options: CreateIndexesOptions = {};\n if (index.name) {\n options.name = index.name;\n }\n if (index.unique) {\n options.unique = true;\n }\n if (index.sparse) {\n options.sparse = true;\n }\n if (index.where) {\n options.partialFilterExpression = index.where;\n }\n\n await collection.createIndex(indexSpec, options);\n }\n\n /**\n * Drop an index by name or columns.\n *\n * @param indexNameOrColumns - Index name (string) or columns array\n */\n public async dropIndex(table: string, indexNameOrColumns: string | string[]): Promise<void> {\n const collection = this.db.collection(table);\n\n if (!Array.isArray(indexNameOrColumns)) {\n indexNameOrColumns = [indexNameOrColumns];\n }\n\n // If columns array provided, generate MongoDB-style index name\n // MongoDB creates index names like: \"column1_1_column2_1\"\n const indexName = indexNameOrColumns.map((col) => `${col}_1`).join(\"_\");\n\n await collection.dropIndex(indexName);\n }\n\n /**\n * Create a unique index/constraint.\n */\n public async createUniqueIndex(table: string, columns: string[], name?: string): Promise<void> {\n await this.createIndex(table, {\n columns,\n unique: true,\n name,\n });\n }\n\n /**\n * Drop a unique index by finding its name from columns.\n */\n public async dropUniqueIndex(table: string, columns: string[]): Promise<void> {\n const collection = this.db.collection(table);\n const indexes = await collection.indexes();\n\n // Find the index that matches the columns\n for (const idx of indexes) {\n const indexKeys = Object.keys(idx.key || {});\n if (indexKeys.length === columns.length && indexKeys.every((key, i) => key === columns[i])) {\n if (idx.name && idx.name !== \"_id_\") {\n await collection.dropIndex(idx.name);\n return;\n }\n }\n }\n }\n\n // ============================================================================\n // SPECIALIZED INDEXES\n // ============================================================================\n\n /**\n * Create a full-text search index.\n *\n * MongoDB uses \"text\" index type for full-text search.\n */\n public async createFullTextIndex(\n table: string,\n columns: string[],\n options?: FullTextIndexOptions,\n ): Promise<void> {\n const collection = this.db.collection(table);\n\n // Build text index specification\n const indexSpec: Record<string, \"text\"> = {};\n for (const column of columns) {\n indexSpec[column] = \"text\";\n }\n\n // Build options\n const indexOptions: CreateIndexesOptions = {};\n if (options?.name) {\n indexOptions.name = options.name;\n }\n if (options?.language) {\n indexOptions.default_language = options.language;\n }\n if (options?.weights) {\n indexOptions.weights = options.weights;\n }\n\n await collection.createIndex(indexSpec, indexOptions);\n }\n\n /**\n * Drop a full-text search index.\n */\n public async dropFullTextIndex(table: string, name: string): Promise<void> {\n await this.dropIndex(table, name);\n }\n\n /**\n * Create a geo-spatial index.\n */\n public async createGeoIndex(\n table: string,\n column: string,\n options?: GeoIndexOptions,\n ): Promise<void> {\n const collection = this.db.collection(table);\n\n // Build geo index specification - MongoDB accepts string values for geo indexes\n const indexType = options?.type ?? \"2dsphere\";\n\n // Build options\n const indexOptions: CreateIndexesOptions = {};\n if (options?.name) {\n indexOptions.name = options.name;\n }\n if (options?.min !== undefined) {\n indexOptions.min = options.min;\n }\n if (options?.max !== undefined) {\n indexOptions.max = options.max;\n }\n\n await collection.createIndex({ [column]: indexType } as any, indexOptions);\n }\n\n /**\n * Drop a geo-spatial index.\n */\n public async dropGeoIndex(table: string, column: string): Promise<void> {\n const collection = this.db.collection(table);\n const indexes = await collection.indexes();\n\n // Find the geo index for this column\n for (const idx of indexes) {\n const key = idx.key || {};\n if (column in key && (key[column] === \"2dsphere\" || key[column] === \"2d\")) {\n if (idx.name && idx.name !== \"_id_\") {\n await collection.dropIndex(idx.name);\n return;\n }\n }\n }\n }\n\n /**\n * Create a vector search index for AI embeddings.\n *\n * Note: This requires MongoDB Atlas with Vector Search enabled.\n * For self-hosted MongoDB, this will create a regular index on the field.\n */\n public async createVectorIndex(\n table: string,\n column: string,\n options: VectorIndexOptions,\n ): Promise<void> {\n const collection = this.db.collection(table);\n\n // Try to create Atlas vector search index first\n try {\n // Check if we're on Atlas by looking for vectorSearch indexes\n const searchIndexes = await (collection as any).listSearchIndexes?.()?.toArray?.();\n if (Array.isArray(searchIndexes)) {\n // We're on Atlas - create a vector search index\n await (collection as any).createSearchIndex({\n name: options.name ?? `${column}_vector_idx`,\n definition: {\n mappings: {\n dynamic: false,\n fields: {\n [column]: {\n type: \"knnVector\",\n dimensions: options.dimensions,\n similarity: options.similarity ?? \"cosine\",\n },\n },\n },\n },\n });\n return;\n }\n } catch {\n // Not on Atlas or doesn't support search indexes\n }\n\n // Fallback: Create a regular index on the vector field\n // This won't provide vector search capabilities but ensures the field is indexed\n await collection.createIndex({ [column]: 1 }, { name: options.name ?? `${column}_vector_idx` });\n }\n\n /**\n * Drop a vector search index.\n */\n public async dropVectorIndex(table: string, column: string): Promise<void> {\n const collection = this.db.collection(table);\n\n // Try to drop Atlas search index first\n try {\n const searchIndexes = await (collection as any).listSearchIndexes?.()?.toArray?.();\n if (Array.isArray(searchIndexes)) {\n for (const idx of searchIndexes) {\n if (idx.name?.includes(column)) {\n await (collection as any).dropSearchIndex(idx.name);\n return;\n }\n }\n }\n } catch {\n // Not on Atlas\n }\n\n // Fallback: Try to drop regular index\n const indexName = `${column}_vector_idx`;\n try {\n await collection.dropIndex(indexName);\n } catch {\n // Index doesn't exist\n }\n }\n\n /**\n * Create a TTL (time-to-live) index for automatic document expiration.\n */\n public async createTTLIndex(\n table: string,\n column: string,\n expireAfterSeconds: number,\n ): Promise<void> {\n const collection = this.db.collection(table);\n await collection.createIndex({ [column]: 1 }, { expireAfterSeconds });\n }\n\n /**\n * Drop a TTL index.\n */\n public async dropTTLIndex(table: string, column: string): Promise<void> {\n const collection = this.db.collection(table);\n const indexes = await collection.indexes();\n\n // Find the TTL index for this column\n for (const idx of indexes) {\n const key = idx.key || {};\n if (column in key && idx.expireAfterSeconds !== undefined) {\n if (idx.name && idx.name !== \"_id_\") {\n await collection.dropIndex(idx.name);\n return;\n }\n }\n }\n }\n\n // ============================================================================\n // CONSTRAINTS (No-ops for MongoDB)\n // ============================================================================\n\n /**\n * Add a foreign key constraint (no-op for MongoDB).\n *\n * MongoDB doesn't support foreign key constraints.\n * Use application-level validation or DBRefs instead.\n */\n public async addForeignKey(_table: string, _foreignKey: ForeignKeyDefinition): Promise<void> {\n // No-op: MongoDB doesn't support foreign keys\n }\n\n /**\n * Drop a foreign key constraint (no-op for MongoDB).\n */\n public async dropForeignKey(_table: string, _name: string): Promise<void> {\n // No-op: MongoDB doesn't support foreign keys\n }\n\n /**\n * Add a primary key constraint (no-op for MongoDB).\n *\n * MongoDB always has _id as the primary key.\n */\n public async addPrimaryKey(_table: string, _columns: string[]): Promise<void> {\n // No-op: MongoDB always has _id as primary key\n }\n\n /**\n * Drop the primary key constraint (no-op for MongoDB).\n */\n public async dropPrimaryKey(_table: string): Promise<void> {\n // No-op: Cannot drop _id index in MongoDB\n }\n\n // ============================================================================\n // SCHEMA VALIDATION (NoSQL)\n // ============================================================================\n\n /**\n * Set JSON schema validation rules on a collection.\n *\n * Uses MongoDB's validator feature to enforce document structure.\n *\n * @example\n * ```typescript\n * await driver.setSchemaValidation(\"users\", {\n * bsonType: \"object\",\n * required: [\"name\", \"email\"],\n * properties: {\n * name: { bsonType: \"string\" },\n * email: { bsonType: \"string\" },\n * },\n * });\n * ```\n */\n public async setSchemaValidation(table: string, schema: object): Promise<void> {\n await this.db.command({\n collMod: table,\n validator: { $jsonSchema: schema },\n validationLevel: \"strict\",\n validationAction: \"error\",\n });\n }\n\n /**\n * Remove schema validation rules from a collection.\n */\n public async removeSchemaValidation(table: string): Promise<void> {\n await this.db.command({\n collMod: table,\n validator: {},\n validationLevel: \"off\",\n });\n }\n\n // ============================================================================\n // TRANSACTIONS\n // ============================================================================\n\n /**\n * Begin a database transaction.\n *\n * Uses the driver's transaction mechanism.\n */\n public async beginTransaction(): Promise<void> {\n const transaction = await this.driver.beginTransaction();\n this.session = transaction.context;\n }\n\n /**\n * Commit the current transaction.\n */\n public async commit(): Promise<void> {\n if (this.session) {\n await this.session.commitTransaction();\n await this.session.endSession();\n this.session = undefined;\n }\n }\n\n /**\n * Rollback the current transaction.\n */\n public async rollback(): Promise<void> {\n if (this.session) {\n await this.session.abortTransaction();\n await this.session.endSession();\n this.session = undefined;\n }\n }\n\n /**\n * MongoDB supports transactions (requires replica set).\n */\n public supportsTransactions(): boolean {\n return true;\n }\n\n // ============================================================================\n // RAW ACCESS\n // ============================================================================\n\n /**\n * Execute raw operations with direct database access.\n *\n * @param callback - Callback receiving the MongoDB Db instance\n * @returns Result from callback\n *\n * @example\n * ```typescript\n * await driver.raw(async (db) => {\n * await db.collection(\"users\").updateMany({}, { $set: { active: true } });\n * });\n * ```\n */\n public async raw<T>(callback: (connection: unknown) => Promise<T>): Promise<T> {\n return callback(this.db);\n }\n}\n","import { colors } from \"@mongez/copper\";\nimport type { Db, IndexDescriptionInfo } from \"mongodb\";\nimport {\n DriverBlueprintContract,\n TableIndexInformation,\n} from \"../../contracts/driver-blueprint.contract\";\n\nexport class MongoDBBlueprint implements DriverBlueprintContract {\n /**\n * Constructor\n */\n public constructor(protected database: Db) {}\n\n /**\n * List all tables in the database\n */\n public async listTables(): Promise<string[]> {\n const collections = await this.database.listCollections().toArray();\n return collections.map((collection) => collection.name);\n }\n\n /**\n * List all indexes for a specific table\n */\n public async listIndexes(table: string): Promise<TableIndexInformation[]> {\n const collection = this.database.collection(table);\n const indexes = await collection.indexes();\n return indexes.map(this.buildIndexInformation);\n }\n\n /**\n * Build index information\n */\n protected buildIndexInformation(index: IndexDescriptionInfo): TableIndexInformation {\n return {\n name: index.name!,\n type: index.type,\n columns: Object.keys(index.key),\n unique: !!index.unique,\n partial: !!index.partialFilterExpression,\n options: index,\n };\n }\n\n /**\n * List all columns for a specific table\n */\n public async listColumns(table: string): Promise<string[]> {\n console.log(\n colors.yellowBright(\n `MongoDBBlueprint: listColumns(${table}) MongoDB does not have static columns`,\n ),\n );\n\n return [];\n }\n\n /**\n * Check if the given table exists\n */\n public async tableExists(table: string): Promise<boolean> {\n const collections = await this.database.listCollections().toArray();\n return collections.some((collection) => collection.name === table);\n }\n}\n","import { colors } from \"@mongez/copper\";\nimport { log } from \"@warlock.js/logger\";\nimport type {\n BulkWriteOptions,\n ClientSession,\n Db,\n DeleteOptions,\n InsertManyResult,\n InsertOneOptions,\n MongoClient,\n MongoClientOptions,\n TransactionOptions,\n UpdateFilter,\n UpdateOptions,\n} from \"mongodb\";\nimport { EventEmitter } from \"node:events\";\nimport { databaseTransactionContext } from \"../../context/database-transaction-context\";\nimport type {\n DriverBlueprintContract,\n DriverContract,\n DriverEvent,\n DriverEventListener,\n DriverTransactionContract,\n IdGeneratorContract,\n InsertResult,\n MigrationDriverContract,\n QueryBuilderContract,\n SyncAdapterContract,\n UpdateResult,\n} from \"../../contracts\";\nimport { dataSourceRegistry } from \"../../data-source/data-source-registry\";\nimport { MongoIdGenerator } from \"./mongo-id-generator\";\nimport { MongoMigrationDriver } from \"./mongo-migration-driver\";\nimport { MongoQueryBuilder } from \"./mongo-query-builder\";\nimport { MongoSyncAdapter } from \"./mongo-sync-adapter\";\nimport { MongoDBBlueprint } from \"./mongodb-blueprint\";\nimport type { MongoDriverOptions } from \"./types\";\n\nconst DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = {\n readPreference: \"primary\",\n readConcern: { level: \"local\" },\n writeConcern: { w: \"majority\" },\n};\n\nlet ObjectId: typeof import(\"mongodb\").ObjectId;\n\n/**\n * MongoDB driver implementation that fulfils the Cascade driver contract.\n *\n * It encapsulates the native Mongo client, exposes lifecycle events, and\n * provides helpers for CRUD, transactions, atomic updates, and sync adapters.\n */\nexport class MongoDbDriver implements DriverContract {\n private readonly events = new EventEmitter();\n public client?: MongoClient;\n public database?: Db;\n private connected = false;\n private syncAdapterInstance?: MongoSyncAdapter;\n private migrationDriverInstance?: MigrationDriverContract;\n private readonly transactionOptions: TransactionOptions;\n private idGeneratorInstance?: IdGeneratorContract;\n private _blueprint?: DriverBlueprintContract;\n\n public get blueprint(): DriverBlueprintContract {\n if (!this._blueprint) {\n this._blueprint = new MongoDBBlueprint(this.database!);\n }\n\n return this._blueprint;\n }\n\n /**\n * The name of this driver.\n */\n public readonly name = \"mongodb\";\n\n /**\n * Create a new MongoDB driver using the supplied connection options.\n *\n * @param config - Connection configuration\n * @param driverOptions - Driver-specific options\n */\n public constructor(\n private readonly config: {\n database: string;\n uri?: string;\n host?: string;\n port?: number;\n username?: string;\n password?: string;\n authSource?: string;\n clientOptions?: MongoClientOptions;\n },\n private readonly driverOptions?: MongoDriverOptions,\n ) {\n this.transactionOptions = {\n ...DEFAULT_TRANSACTION_OPTIONS,\n ...driverOptions?.transactionOptions,\n };\n }\n\n /**\n * Indicates whether the driver currently maintains an active connection.\n */\n public get isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Get the MongoDB database instance.\n *\n * @returns The MongoDB Db instance\n * @throws {Error} If not connected\n *\n * @example\n * ```typescript\n * const db = driver.getDatabase();\n * const collection = db.collection(\"users\");\n * ```\n */\n public getDatabase(): Db {\n if (!this.database) {\n throw new Error(\n \"Database not available. Ensure the driver is connected before accessing the database.\",\n );\n }\n return this.database;\n }\n\n /**\n * Get the ID generator instance for this driver.\n *\n * Creates a MongoIdGenerator on first access if autoGenerateId is enabled.\n *\n * @returns The ID generator instance, or undefined if disabled\n *\n * @example\n * ```typescript\n * const idGenerator = driver.getIdGenerator();\n * if (idGenerator) {\n * const id = await idGenerator.generateNextId({ table: \"users\" });\n * }\n * ```\n */\n public getIdGenerator(): IdGeneratorContract | undefined {\n // Return undefined if ID generation is disabled\n if (this.driverOptions?.autoGenerateId === false) {\n return undefined;\n }\n\n // Create ID generator lazily on first access\n if (!this.idGeneratorInstance) {\n this.idGeneratorInstance = new MongoIdGenerator(this, this.driverOptions?.counterCollection);\n }\n\n return this.idGeneratorInstance;\n }\n\n /**\n * Establish a MongoDB connection using the configured options.\n * Throws if the connection attempt fails.\n */\n public async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const uri = this.resolveUri();\n const { MongoClient, ObjectId: ObjectIdMongoDB } = await import(\"mongodb\");\n\n ObjectId = ObjectIdMongoDB;\n\n const client = new MongoClient(uri, this.buildClientOptions());\n\n try {\n log.info(\n \"database\",\n \"connection\",\n `Connecting to database ${colors.bold(colors.yellowBright(this.config.database))}`,\n );\n await client.connect();\n this.client = client;\n this.database = client.db(this.config.database);\n this.connected = true;\n log.success(\"database\", \"connection\", \"Connected to database\");\n\n client.on(\"close\", () => {\n if (this.connected) {\n this.connected = false;\n this.emit(\"disconnected\");\n log.warn(\"database\", \"connection\", \"Disconnected from database\");\n }\n });\n\n this.emit(\"connected\");\n } catch (error) {\n await client.close().catch(() => undefined);\n this.emit(\"disconnected\");\n throw error;\n }\n }\n\n /**\n * Close the underlying MongoDB connection.\n */\n public async disconnect(): Promise<void> {\n if (!this.client) {\n return;\n }\n\n try {\n await this.client.close();\n } finally {\n this.connected = false;\n this.emit(\"disconnected\");\n }\n }\n\n /**\n * Subscribe to driver lifecycle events.\n */\n public on(event: DriverEvent, listener: DriverEventListener): void {\n this.events.on(event, listener);\n }\n\n /**\n * Insert a single document into the given collection.\n */\n public async insert(\n table: string,\n document: Record<string, unknown>,\n options?: Record<string, unknown>,\n ): Promise<InsertResult> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<InsertOneOptions>(options);\n const result = await collection.insertOne(document, mongoOptions);\n\n return {\n document: {\n ...document,\n _id: result.insertedId,\n },\n };\n }\n\n /**\n * Insert multiple documents into the given collection.\n */\n public async insertMany(\n table: string,\n documents: Record<string, unknown>[],\n options?: Record<string, unknown>,\n ): Promise<InsertResult[]> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<BulkWriteOptions>(options);\n const result: InsertManyResult<Record<string, unknown>> = await collection.insertMany(\n documents,\n mongoOptions,\n );\n\n return documents.map((document, index) => {\n const insertedId = result.insertedIds[index as unknown as keyof typeof result.insertedIds];\n\n return {\n document: {\n ...document,\n _id: insertedId,\n },\n };\n });\n }\n\n /**\n * Update a single document that matches the provided filter.\n */\n public async update(\n table: string,\n filter: Record<string, unknown>,\n update: Record<string, unknown>,\n options?: Record<string, unknown>,\n ): Promise<UpdateResult> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<UpdateOptions>(options);\n const result = await collection.updateOne(\n filter,\n update as UpdateFilter<Record<string, unknown>>,\n mongoOptions,\n );\n\n return { modifiedCount: result.modifiedCount };\n }\n\n /**\n * Replace a single document that matches the provided filter.\n */\n public async replace<T = unknown>(\n table: string,\n filter: Record<string, unknown>,\n document: Record<string, unknown>,\n options?: Record<string, unknown>,\n ): Promise<T | null> {\n const collection = this.getDatabaseInstance().collection(table);\n const result = await collection.findOneAndReplace(filter, document as Record<string, unknown>);\n\n return result?.value as T | null;\n }\n\n /**\n * Update multiple documents that match the provided filter.\n */\n public async updateMany(\n table: string,\n filter: Record<string, unknown>,\n update: Record<string, unknown>,\n options?: Record<string, unknown>,\n ): Promise<UpdateResult> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<UpdateOptions>(options);\n const result = await collection.updateMany(\n filter,\n update as UpdateFilter<Record<string, unknown>>,\n mongoOptions,\n );\n\n return { modifiedCount: result.modifiedCount };\n }\n\n /**\n * Delete a single document that matches the provided filter.\n */\n public async delete(\n table: string,\n filter: Record<string, unknown> = {},\n options?: Record<string, unknown>,\n ): Promise<number> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<DeleteOptions>(options);\n const result = await collection.deleteOne(filter, mongoOptions);\n\n return result.deletedCount > 0 ? 1 : 0;\n }\n\n /**\n * Delete documents that match the provided filter.\n */\n public async deleteMany(\n table: string,\n filter: Record<string, unknown> = {},\n options?: Record<string, unknown>,\n ): Promise<number> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<DeleteOptions>(options);\n\n const result = await collection.deleteMany(filter, mongoOptions);\n\n return result.deletedCount ?? 0;\n }\n\n /**\n * Remove all records from a collection.\n *\n * This uses deleteMany with an empty filter to remove all documents.\n * For very large collections, consider using the migration driver's\n * dropTable + createTable approach for better performance.\n */\n public async truncateTable(table: string, options?: Record<string, unknown>): Promise<number> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<DeleteOptions>(options);\n const result = await collection.deleteMany({}, mongoOptions);\n\n return result.deletedCount ?? 0;\n }\n\n /**\n * Serialize the given data\n */\n public serialize(data: Record<string, unknown>): Record<string, unknown> {\n if (data._id && data._id instanceof ObjectId) {\n data._id = data._id.toString();\n }\n\n return data;\n }\n\n /**\n * Deserialize the given data\n */\n public deserialize(data: Record<string, unknown>): Record<string, unknown> {\n if (data._id && typeof data._id === \"string\") {\n data._id = new ObjectId(data._id);\n }\n\n return data;\n }\n\n /**\n * Provide a Mongo-backed query builder instance for the given collection.\n */\n public queryBuilder<T = unknown>(table: string): QueryBuilderContract<T> {\n return new MongoQueryBuilder(table, dataSourceRegistry.get());\n }\n\n /**\n * Begin a MongoDB transaction, returning commit/rollback helpers.\n */\n public async beginTransaction(): Promise<DriverTransactionContract<ClientSession>> {\n const client = this.getClientInstance();\n const session = client.startSession();\n\n await session.startTransaction(this.transactionOptions);\n databaseTransactionContext.enter({ session });\n let finished = false;\n\n const finalize = async (operation: () => Promise<void>): Promise<void> => {\n if (finished) return;\n\n try {\n await operation();\n } finally {\n finished = true;\n databaseTransactionContext.exit();\n await session.endSession().catch(() => undefined);\n }\n };\n\n return {\n context: session,\n commit: async () => {\n await finalize(async () => {\n try {\n await session.commitTransaction();\n } catch (error) {\n await session.abortTransaction().catch(() => undefined);\n throw error;\n }\n });\n },\n rollback: async () => {\n await finalize(async () => {\n await session.abortTransaction();\n });\n },\n };\n }\n\n /**\n * Execute atomic operations (typically $inc/$set style updates) against documents.\n *\n * Uses `updateMany` so callers can atomically modify any set of documents.\n */\n public async atomic(\n table: string,\n filter: Record<string, unknown>,\n operations: Record<string, unknown>,\n options?: Record<string, unknown>,\n ): Promise<UpdateResult> {\n const collection = this.getDatabaseInstance().collection(table);\n const mongoOptions = this.withSession<UpdateOptions>(options);\n const result = await collection.updateMany(\n filter,\n operations as UpdateFilter<Record<string, unknown>>,\n mongoOptions,\n );\n\n return { modifiedCount: result.modifiedCount };\n }\n\n /**\n * Lazily create (and cache) the Mongo sync adapter.\n * The adapter uses this driver instance to ensure all operations\n * participate in active transactions via the session context.\n */\n public syncAdapter(): SyncAdapterContract {\n if (!this.syncAdapterInstance) {\n this.syncAdapterInstance = new MongoSyncAdapter(this);\n }\n\n return this.syncAdapterInstance;\n }\n\n /**\n * Lazily create (and cache) the Mongo migration driver.\n * The migration driver handles schema operations like indexes, collections, etc.\n */\n public migrationDriver(): MigrationDriverContract {\n if (!this.migrationDriverInstance) {\n this.migrationDriverInstance = new MongoMigrationDriver(this);\n }\n\n return this.migrationDriverInstance!;\n }\n\n /**\n * Expose the underlying Mongo client for advanced consumers.\n */\n public getClient(): MongoClient {\n return this.getClientInstance();\n }\n\n /**\n * Retrieve the active Mongo client, throwing if the driver is disconnected.\n */\n private getClientInstance(): MongoClient {\n if (!this.client) {\n throw new Error(\"Mongo driver is not connected.\");\n }\n\n return this.client;\n }\n\n /**\n * Retrieve the active Mongo database, throwing if the driver is disconnected.\n * @private\n */\n private getDatabaseInstance(): Db {\n if (!this.database) {\n throw new Error(\"Mongo driver is not connected to a database.\");\n }\n\n return this.database;\n }\n\n /**\n * Resolve the Mongo connection string based on provided options.\n */\n private resolveUri(): string {\n if (this.config.uri) {\n return this.config.uri;\n }\n\n const host = this.config.host ?? \"localhost\";\n const port = this.config.port ?? 27017;\n\n return `mongodb://${host}:${port}`;\n }\n\n /**\n * Build the Mongo client options derived from the driver configuration.\n */\n private buildClientOptions(): MongoClientOptions {\n const baseOptions: MongoClientOptions = {\n ...(this.config.clientOptions ?? {}),\n };\n\n if (this.config.username && !baseOptions.auth) {\n baseOptions.auth = {\n username: this.config.username,\n password: this.config.password,\n };\n }\n\n if (this.config.authSource && !baseOptions.authSource) {\n baseOptions.authSource = this.config.authSource;\n }\n\n return baseOptions;\n }\n\n /**\n * Emit a driver lifecycle event.\n */\n private emit(event: DriverEvent, ...args: unknown[]): void {\n this.events.emit(event, ...args);\n }\n\n /**\n * Attach the active transaction session (when available) to Mongo options.\n */\n private withSession<TOptions extends { session?: ClientSession }>(\n options?: Record<string, unknown>,\n ): TOptions | undefined {\n const session = databaseTransactionContext.getSession<ClientSession>();\n\n if (!session) {\n return options as TOptions | undefined;\n }\n\n const baseOptions = options ? ({ ...options } as TOptions) : ({} as TOptions);\n\n baseOptions.session = session;\n\n return baseOptions;\n }\n}\n","import { DriverContract } from \"../contracts\";\nimport { DataSource } from \"../data-source/data-source\";\nimport { dataSourceRegistry } from \"../data-source/data-source-registry\";\nimport { MongoDbDriver } from \"../drivers/mongo/mongodb-driver\";\nimport type { DeleteStrategy, StrictMode } from \"../types\";\n\n/**\n * Supported database driver types.\n */\nexport type DatabaseDriver = \"mongodb\" | \"postgres\" | \"mysql\";\n\n/**\n * Default model configuration options.\n *\n * These settings will be applied to all models using this data source,\n * unless overridden by individual model static properties.\n *\n * Note: `autoGenerateId` is NOT included here as it's a driver-level\n * setting (configured in MongoDriverOptions), not a model-level one.\n */\nexport type ModelDefaultConfig = {\n /**\n * Initial ID value for auto-generated IDs.\n * Can be a number or a function that returns a number.\n * @default 1\n */\n initialId?: number | (() => number);\n\n /**\n * Randomly generate the initial ID.\n * - `true`: Random ID between 10000-499999\n * - Function: Custom random ID generator\n * @default false\n */\n randomInitialId?: boolean | (() => number);\n\n /**\n * Amount to increment ID by for each new record.\n * @default 1\n */\n incrementIdBy?: number;\n\n /**\n * Randomly generate the increment amount.\n * - `true`: Random increment between 1-10\n * - Function: Custom random increment generator\n * @default false\n */\n randomIncrement?: boolean | (() => number);\n\n /**\n * Default delete strategy for models.\n * @default undefined (uses data source default or \"permanent\")\n */\n deleteStrategy?: DeleteStrategy;\n\n /**\n * Default validation strict mode.\n * - `\"allow\"`: Allow unknown fields\n * - `\"strip\"`: Strip unknown fields\n * - `\"fail\"`: Fail on unknown fields\n * @default \"strip\"\n */\n strictMode?: StrictMode;\n};\n\n/**\n * Connection options for establishing a database connection.\n *\n * Generic type that separates concerns:\n * - Shared config (driver, name, database, connection details)\n * - Driver options (cascade-next driver-specific settings)\n * - Client options (native database client settings)\n * - Model options (default model behaviors)\n *\n * @template TDriverOptions - Driver-specific options (e.g., MongoDriverOptions)\n * @template TClientOptions - Native client options (e.g., MongoClientOptions from mongodb package)\n *\n * @example\n * ```typescript\n * // MongoDB\n * import type { MongoClientOptions } from \"mongodb\";\n * import type { MongoDriverOptions } from \"@warlock.js/cascade\";\n *\n * const config: ConnectionOptions<MongoDriverOptions, MongoClientOptions> = {\n * driver: \"mongodb\",\n * database: \"myapp\",\n * host: \"localhost\",\n * port: 27017,\n * driverOptions: {\n * autoGenerateId: true,\n * counterCollection: \"counters\",\n * },\n * clientOptions: {\n * minPoolSize: 5,\n * maxPoolSize: 10,\n * },\n * modelOptions: {\n * randomIncrement: true,\n * initialId: 1000,\n * },\n * };\n * ```\n */\nexport type ConnectionOptions<TDriverOptions = any, TClientOptions = any> = {\n // ============================================================================\n // SHARED CONFIGURATION (Framework-level)\n // ============================================================================\n\n /**\n * Database driver to use.\n * @default \"mongodb\"\n */\n driver?: DatabaseDriver;\n\n /**\n * Unique name for this data source.\n * Used for registration in DataSourceRegistry.\n * @default \"default\"\n */\n name?: string;\n\n /**\n * Whether this should be the default data source.\n * @default true\n */\n isDefault?: boolean;\n\n /**\n * Database name (required).\n */\n database: string;\n\n // ============================================================================\n // CONNECTION DETAILS (Shared across drivers)\n // ============================================================================\n\n /**\n * Database connection URI.\n * Alternative to specifying host/port separately.\n *\n * @example \"mongodb://localhost:27017/mydb\"\n * @example \"postgresql://user:pass@localhost:5432/mydb\"\n */\n uri?: string;\n\n /**\n * Database host.\n * @default \"localhost\"\n */\n host?: string;\n\n /**\n * Database port.\n * @default 27017 (MongoDB), 5432 (PostgreSQL)\n */\n port?: number;\n\n /**\n * Database username for authentication.\n */\n username?: string;\n\n /**\n * Database password for authentication.\n */\n password?: string;\n\n /**\n * Authentication source database.\n * Typically \"admin\" for MongoDB.\n */\n authSource?: string;\n\n // ============================================================================\n // DRIVER OPTIONS (Package-level, driver-specific)\n // ============================================================================\n\n /**\n * Driver-specific options.\n *\n * For MongoDB: { autoGenerateId, counterCollection, transactionOptions }\n * For PostgreSQL: { schema, ... }\n */\n driverOptions?: TDriverOptions;\n\n // ============================================================================\n // CLIENT OPTIONS (Native database client library)\n // ============================================================================\n\n /**\n * Native database client options.\n *\n * For MongoDB: MongoClientOptions from 'mongodb' package\n * For PostgreSQL: PoolConfig from 'pg' package\n */\n clientOptions?: TClientOptions;\n\n // ============================================================================\n // MODEL OPTIONS (Model defaults)\n // ============================================================================\n\n /**\n * Default model configuration for all models using this data source.\n *\n * These settings will be applied to models that don't have their own\n * static property overrides.\n *\n * @example\n * ```typescript\n * {\n * modelOptions: {\n * randomIncrement: true,\n * initialId: 1000,\n * deleteStrategy: \"soft\",\n * }\n * }\n * ```\n */\n modelOptions?: ModelDefaultConfig;\n\n // ============================================================================\n // DATA SOURCE DEFAULTS\n // ============================================================================\n\n /**\n * Default delete strategy for models using this data source.\n *\n * - MongoDB: Typically `\"trash\"` (uses RecycleBin collection)\n * - PostgreSQL: Typically `\"permanent\"` or `\"soft\"`\n *\n * Can be overridden by model static property or destroy() options.\n *\n * @default undefined (falls back to \"permanent\")\n */\n defaultDeleteStrategy?: DeleteStrategy;\n\n /**\n * Default trash table/collection name for \"trash\" delete strategy.\n *\n * - MongoDB: Typically `\"RecycleBin\"`\n * - If not set, defaults to `{table}Trash` pattern\n *\n * Can be overridden by Model.trashTable static property.\n *\n * @default undefined (uses {table}Trash pattern)\n */\n defaultTrashTable?: string;\n};\n\n/**\n * Connect to a database and register the data source.\n *\n * This is a high-level utility function that simplifies database connection\n * for small to medium projects. It handles driver instantiation, connection,\n * data source creation, and automatic registration.\n *\n * **Supported Drivers:**\n * - `mongodb` (default) - MongoDB driver with optional auto ID generation\n * - `postgres` - PostgreSQL driver (not yet implemented)\n * - `mysql` - MySQL driver (not yet implemented)\n *\n * **Features:**\n * - Automatic driver instantiation based on driver name\n * - Connection establishment and error handling\n * - DataSource creation and registration\n * - Support for MongoDB-specific features (ID generation, transactions)\n *\n * @param options - Connection configuration options\n * @returns A connected and registered DataSource instance\n * @throws {Error} If connection fails or driver is not implemented\n *\n * @example\n * ```typescript\n * // MongoDB with new structure\n * const dataSource = await connectToDatabase({\n * driver: \"mongodb\",\n * database: \"myapp\",\n * host: \"localhost\",\n * port: 27017,\n * driverOptions: {\n * autoGenerateId: true,\n * },\n * clientOptions: {\n * minPoolSize: 5,\n * maxPoolSize: 10,\n * },\n * modelOptions: {\n * randomIncrement: true,\n * initialId: 1000,\n * },\n * });\n * ```\n */\nexport async function connectToDatabase<TDriverOptions = any, TClientOptions = any>(\n options: ConnectionOptions<TDriverOptions, TClientOptions>,\n): Promise<DataSource> {\n // Default values\n const driverType = options.driver ?? \"mongodb\";\n const dataSourceName = options.name ?? \"default\";\n const isDefault = options.isDefault ?? true;\n\n // Create driver based on type\n let driver: DriverContract;\n\n switch (driverType) {\n case \"mongodb\": {\n driver = new MongoDbDriver(\n {\n database: options.database,\n uri: options.uri,\n host: options.host,\n port: options.port,\n username: options.username,\n password: options.password,\n authSource: options.authSource,\n clientOptions: options.clientOptions as any,\n },\n options.driverOptions as any,\n );\n break;\n }\n\n case \"postgres\":\n throw new Error(\"PostgreSQL driver is not yet implemented. Coming soon!\");\n\n case \"mysql\":\n throw new Error(\"MySQL driver is not yet implemented. Coming soon!\");\n\n default:\n throw new Error(\n `Unknown driver: \"${driverType}\". Supported drivers: mongodb, postgres, mysql`,\n );\n }\n\n // Create data source\n const dataSource = new DataSource({\n name: dataSourceName,\n driver,\n isDefault,\n defaultDeleteStrategy: options.defaultDeleteStrategy,\n defaultTrashTable: options.defaultTrashTable,\n modelDefaults: options.modelOptions,\n });\n\n // Register data source\n dataSourceRegistry.register(dataSource);\n\n // Connect to the database\n try {\n await driver.connect();\n } catch (error) {\n throw new Error(\n `Failed to connect to ${driverType} database: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n return dataSource;\n}\n","import { type TransformerCallback } from \"@warlock.js/seal\";\nimport { type Model } from \"../model/model\";\n\ntype transformCallbackOptions = {\n model: Model;\n column: string;\n value: any;\n isChanged: boolean;\n isNew: boolean;\n};\n\ntype ModelTransformCallback = (options: transformCallbackOptions) => string;\n\n/**\n * Transfer value before saving it into the database\n */\nexport function useModelTransformer(callback: ModelTransformCallback) {\n const transformCallback: TransformerCallback = (data, { context }) => {\n const model = context.rootContext?.model as Model;\n const column = context.key;\n const value = data;\n const isChanged = model.isDirty(column);\n const isNew = model.isNew;\n return callback({ model, column, value, isChanged, isNew });\n };\n\n return transformCallback;\n}\n","import type { Infer, ObjectValidator } from \"@warlock.js/seal\";\nimport type { ModelSchema } from \"../model/model\";\nimport { Model } from \"../model/model\";\nimport { registerModelInRegistry } from \"../model/register-model\";\nimport type { DeleteStrategy, StrictMode } from \"../types\";\n\n/**\n * Configuration options for defining a model.\n */\nexport type DefineModelOptions<TSchema extends ModelSchema> = {\n /**\n * The database table/collection name.\n */\n table: string;\n\n /**\n * Model name\n * If provided, it will be registered in the models registery\n */\n name?: string;\n\n /**\n * The validation schema for the model.\n * Use `v.object()` from @warlock.js/seal to define the schema.\n */\n schema: ObjectValidator;\n\n /**\n * Optional: Delete strategy for the model.\n * - \"hard\": Permanently delete records (default)\n * - \"soft\": Mark records as deleted but keep them in the database\n * - \"disable\": Mark records as disabled\n */\n deleteStrategy?: DeleteStrategy;\n\n /**\n * Optional: Strict mode for unknown fields.\n * - \"strip\": Remove unknown fields (default)\n * - \"fail\": Throw error on unknown fields\n */\n strictMode?: StrictMode;\n\n /**\n * Optional: Whether to automatically generate IDs.\n * Default: false (use MongoDB's _id)\n */\n autoGenerateId?: boolean;\n\n /**\n * Optional: Whether to use random increments for IDs.\n * Default: false\n */\n randomIncrement?: boolean;\n\n /**\n * Optional: Initial ID value when auto-generating.\n * Default: 1\n */\n initialId?: number;\n\n /**\n * Optional: Custom instance properties (getters/setters/methods).\n * Define computed properties, custom getters, or instance methods.\n *\n * The `this` context will be the Model instance, giving you access to\n * all Model methods like `get()`, `set()`, `save()`, etc.\n *\n * @example\n * ```typescript\n * properties: {\n * get fullName(this: Model<UserSchema>) {\n * return `${this.get(\"firstName\")} ${this.get(\"lastName\")}`;\n * },\n * get isActive(this: Model<UserSchema>) {\n * return this.get(\"status\") === \"active\";\n * },\n * async sendEmail(this: Model<UserSchema>, subject: string) {\n * // this.get(), this.save(), etc. all work!\n * },\n * }\n * ```\n */\n properties?: ThisType<Model<TSchema>> & Record<string, any>;\n\n /**\n * Optional: Custom static methods.\n * Define class-level methods like custom finders or utilities.\n *\n * @example\n * ```typescript\n * statics: {\n * async findByEmail(email: string) {\n * return this.first({ email });\n * },\n * async findActive() {\n * return this.query().where(\"status\", \"active\").get();\n * },\n * }\n * ```\n */\n statics?: Record<string, any>;\n};\n\n/**\n * Define a model with a clean, concise API.\n *\n * This utility function creates a Model class with the specified configuration,\n * reducing boilerplate and providing a more declarative way to define models.\n *\n * @param options - Model configuration options\n * @returns A Model class with the specified configuration\n *\n * @example\n * ```typescript\n * import { defineModel } from \"@warlock.js/cascade\";\n * import { v } from \"@warlock.js/seal\";\n *\n * export const User = defineModel({\n * table: \"users\",\n * schema: v.object({\n * name: v.string().required().trim(),\n * email: v.string().email().required().lowercase(),\n * password: v.string().required().min(6),\n * role: v.string().default(\"user\"),\n * }),\n * deleteStrategy: \"soft\",\n * });\n *\n * // Usage\n * const user = await User.create({\n * name: \"John Doe\",\n * email: \"john@example.com\",\n * password: \"secret123\",\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With type inference\n * export const Post = defineModel({\n * table: \"posts\",\n * schema: v.object({\n * title: v.string().required(),\n * content: v.string().required(),\n * authorId: v.number().required(),\n * published: v.boolean().default(false),\n * }),\n * });\n *\n * // TypeScript knows the exact type!\n * const post = await Post.create({\n * title: \"Hello World\",\n * content: \"My first post\",\n * authorId: 1,\n * });\n *\n * console.log(post.title); // ✅ Type-safe!\n * ```\n */\nexport function defineModel<\n TSchema extends ModelSchema,\n TSchemaValidator extends ObjectValidator = ObjectValidator,\n TProperties extends Record<string, any> = {},\n TStatics extends Record<string, any> = {},\n>(\n options: DefineModelOptions<TSchema> & {\n schema: TSchemaValidator;\n properties?: ThisType<Model<Infer<TSchemaValidator>>> & TProperties;\n statics?: ThisType<typeof Model<Infer<TSchemaValidator>>> & TStatics;\n },\n) {\n type InferredSchema = Infer<TSchemaValidator>;\n\n class DefinedModel extends Model<InferredSchema> {\n /**\n * Table/collection name\n */\n public static table = options.table;\n\n /**\n * Validation schema\n */\n public static schema = options.schema;\n\n /**\n * Delete strategy\n */\n public static deleteStrategy: DeleteStrategy = options.deleteStrategy || \"trash\";\n\n /**\n * Strict mode\n */\n public static strictMode = options.strictMode || \"strip\";\n\n /**\n * Auto-generate ID\n */\n public static autoGenerateId = options.autoGenerateId || false;\n\n /**\n * Random increment\n */\n public static randomIncrement = options.randomIncrement || false;\n\n /**\n * Initial ID\n */\n public static initialId = options.initialId || 1;\n }\n\n // Apply custom instance properties (getters/setters/methods)\n if (options.properties) {\n Object.defineProperties(\n DefinedModel.prototype,\n Object.getOwnPropertyDescriptors(options.properties),\n );\n }\n\n if (options.name) {\n registerModelInRegistry(options.name, DefinedModel);\n }\n\n // Apply custom static methods\n if (options.statics) {\n Object.defineProperties(DefinedModel, Object.getOwnPropertyDescriptors(options.statics));\n }\n\n // Return with proper type inference\n type ReturnType = {\n new (initialData?: Partial<InferredSchema>): DefinedModel & TProperties;\n } & Omit<typeof DefinedModel, \"new\"> &\n TStatics;\n\n return DefinedModel as unknown as ReturnType;\n}\n\n/**\n * Type helper to infer the schema type from a defined model.\n *\n * @example\n * ```typescript\n * const User = defineModel({\n * table: \"users\",\n * schema: v.object({\n * name: v.string(),\n * email: v.string(),\n * }),\n * });\n *\n * type UserType = ModelType<typeof User>;\n * // { name: string; email: string; }\n * ```\n */\nexport type ModelType<T extends ReturnType<typeof defineModel>> = T extends new (\n ...args: any[]\n) => infer R\n ? R extends Model<infer S>\n ? S\n : never\n : never;\n","import type { DataSource } from \"../data-source/data-source\";\nimport { dataSourceRegistry } from \"../data-source/data-source-registry\";\n\n/**\n * Execute a callback once the driver is connected.\n *\n * If the driver is already connected, the callback is executed immediately.\n * Otherwise, it waits for the \"connected\" event.\n *\n * **Use Case:**\n * Useful for ensuring database-dependent operations only run after connection\n * is established, especially in small to medium projects with a single data source.\n *\n * @param dataSourceOrNameOrCallback - Data source instance, name, or callback function\n * @param callback - Function to execute once connected (optional if first param is callback)\n *\n * @example\n * ```typescript\n * // With default data source (just callback)\n * await connectToDatabase({ database: \"myapp\" });\n *\n * onceConnected((ds) => {\n * console.log(\"Database is ready!\");\n * console.log(\"Connected to:\", ds.name);\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With data source name\n * onceConnected(\"primary\", (ds) => {\n * console.log(\"Primary database is ready!\");\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With data source instance\n * const dataSource = await connectToDatabase({ database: \"myapp\" });\n *\n * onceConnected(dataSource, (ds) => {\n * console.log(\"Database is ready!\");\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With driver instance\n * const driver = new MongoDbDriver(config);\n * const dataSource = new DataSource({ name: \"primary\", driver });\n *\n * onceConnected(dataSource, () => {\n * // Start application server\n * app.listen(3000);\n * });\n *\n * // Connect after setting up the callback\n * await driver.connect();\n * ```\n *\n * @example\n * ```typescript\n * // Chaining operations\n * onceConnected(async (ds) => {\n * // Seed database\n * await seedDatabase();\n *\n * // Run migrations\n * await runMigrations();\n *\n * console.log(\"Database ready!\");\n * });\n * ```\n */\nexport function onceConnected(\n dataSourceOrNameOrCallback:\n | DataSource\n | string\n | ((dataSource: DataSource) => void),\n callback?: (dataSource: DataSource) => void,\n): void {\n // Determine if first parameter is a callback\n let targetDataSource: DataSource | string;\n let actualCallback: (dataSource: DataSource) => void;\n\n if (typeof dataSourceOrNameOrCallback === \"function\") {\n // First param is callback, use default data source\n actualCallback = dataSourceOrNameOrCallback;\n targetDataSource = \"default\";\n } else {\n // First param is data source name or instance\n if (!callback) {\n throw new Error(\n \"Callback is required when providing a data source name or instance.\",\n );\n }\n actualCallback = callback;\n targetDataSource = dataSourceOrNameOrCallback;\n }\n\n // Try to get the data source if it's a string\n let resolvedDataSource: DataSource | undefined;\n if (typeof targetDataSource === \"string\") {\n try {\n resolvedDataSource =\n targetDataSource === \"default\"\n ? dataSourceRegistry.get()\n : dataSourceRegistry.get(targetDataSource);\n } catch {\n // Data source not registered yet, will wait for event\n }\n } else {\n resolvedDataSource = targetDataSource;\n }\n\n // If data source is resolved and already connected, fire immediately\n if (resolvedDataSource && resolvedDataSource.driver.isConnected) {\n actualCallback(resolvedDataSource);\n return;\n }\n\n // Otherwise, wait for the connected event\n const listener = (ds: DataSource) => {\n const matches =\n typeof targetDataSource === \"string\"\n ? targetDataSource === \"default\"\n ? ds.isDefault\n : ds.name === targetDataSource\n : ds === targetDataSource;\n\n if (matches) {\n actualCallback(ds);\n } else {\n // Not the one we're looking for, keep listening\n dataSourceRegistry.once(\"connected\", listener);\n }\n };\n\n dataSourceRegistry.once(\"connected\", listener);\n}\n\n/**\n * Execute a callback once the driver is disconnected.\n *\n * If the driver is already disconnected, the callback is executed immediately.\n * Otherwise, it waits for the \"disconnected\" event.\n *\n * **Use Case:**\n * Useful for cleanup operations, graceful shutdown, or reconnection logic.\n *\n * @param dataSourceOrNameOrCallback - Data source instance, name, or callback function\n * @param callback - Function to execute once disconnected (optional if first param is callback)\n *\n * @example\n * ```typescript\n * // With default data source (just callback)\n * await connectToDatabase({ database: \"myapp\" });\n *\n * onceDisconnected((ds) => {\n * console.log(\"Database disconnected!\");\n * console.log(\"Attempting reconnection...\");\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With data source name\n * onceDisconnected(\"primary\", (ds) => {\n * console.log(\"Primary database disconnected!\");\n * });\n * ```\n *\n * @example\n * ```typescript\n * // With data source instance\n * const dataSource = await connectToDatabase({ database: \"myapp\" });\n *\n * onceDisconnected(dataSource, (ds) => {\n * console.log(\"Database disconnected!\");\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Graceful shutdown with default data source\n * process.on(\"SIGTERM\", async () => {\n * console.log(\"Shutting down...\");\n *\n * onceDisconnected(() => {\n * console.log(\"Database closed, exiting process\");\n * process.exit(0);\n * });\n *\n * const dataSource = DataSourceRegistry.getDefault();\n * await dataSource?.driver.disconnect();\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Cleanup resources on disconnect\n * onceDisconnected(async (ds) => {\n * // Close file handles\n * await closeFileHandles();\n *\n * // Clear caches\n * clearCaches();\n *\n * console.log(\"Cleanup complete\");\n * });\n * ```\n */\nexport function onceDisconnected(\n dataSourceOrNameOrCallback:\n | DataSource\n | string\n | ((dataSource: DataSource) => void),\n callback?: (dataSource: DataSource) => void,\n): void {\n // Determine if first parameter is a callback\n let targetDataSource: DataSource | string;\n let actualCallback: (dataSource: DataSource) => void;\n\n if (typeof dataSourceOrNameOrCallback === \"function\") {\n // First param is callback, use default data source\n actualCallback = dataSourceOrNameOrCallback;\n targetDataSource = \"default\";\n } else {\n // First param is data source name or instance\n if (!callback) {\n throw new Error(\n \"Callback is required when providing a data source name or instance.\",\n );\n }\n actualCallback = callback;\n targetDataSource = dataSourceOrNameOrCallback;\n }\n\n // Try to get the data source if it's a string\n let resolvedDataSource: DataSource | undefined;\n if (typeof targetDataSource === \"string\") {\n try {\n resolvedDataSource =\n targetDataSource === \"default\"\n ? dataSourceRegistry.get()\n : dataSourceRegistry.get(targetDataSource);\n } catch {\n // Data source not registered yet, will wait for event\n }\n } else {\n resolvedDataSource = targetDataSource;\n }\n\n // If data source is resolved and already disconnected, fire immediately\n if (resolvedDataSource && !resolvedDataSource.driver.isConnected) {\n actualCallback(resolvedDataSource);\n return;\n }\n\n // Otherwise, wait for the disconnected event\n const listener = (ds: DataSource) => {\n const matches =\n typeof targetDataSource === \"string\"\n ? targetDataSource === \"default\"\n ? ds.isDefault\n : ds.name === targetDataSource\n : ds === targetDataSource;\n\n if (matches) {\n actualCallback(ds);\n } else {\n // Not the one we're looking for, keep listening\n dataSourceRegistry.once(\"disconnected\", listener);\n }\n };\n\n dataSourceRegistry.once(\"disconnected\", listener);\n}\n","import type { ColumnDefinition, ColumnType } from \"../contracts/migration-driver.contract\";\n\n/**\n * Reference to the Migration type to avoid circular imports.\n * The actual type is injected at runtime.\n */\ntype MigrationLike = {\n addPendingIndex(index: { columns: string[]; unique?: boolean }): void;\n};\n\n/**\n * Fluent builder for defining column properties.\n *\n * Allows chaining modifiers like `.nullable()`, `.unique()`, `.default()`.\n * Each column builder is bound to a parent migration and accumulates\n * the column definition through method chains.\n *\n * @example\n * ```typescript\n * this.string(\"email\")\n * .nullable()\n * .unique()\n * .default(\"guest@example.com\");\n * ```\n *\n * @example\n * ```typescript\n * this.integer(\"age\")\n * .unsigned()\n * .comment(\"User's age in years\");\n * ```\n */\nexport class ColumnBuilder {\n /** Mutable column definition being accumulated */\n private readonly definition: ColumnDefinition;\n\n /**\n * Create a new column builder.\n *\n * @param migration - Parent migration instance for index registration\n * @param name - Column name\n * @param type - Column data type\n * @param options - Optional initial configuration\n */\n public constructor(\n private readonly migration: MigrationLike,\n name: string,\n type: ColumnType,\n options: Partial<\n Pick<ColumnDefinition, \"length\" | \"precision\" | \"scale\" | \"dimensions\" | \"values\">\n > = {},\n ) {\n this.definition = {\n name,\n type,\n nullable: false,\n ...options,\n };\n }\n\n // ============================================================================\n // NULLABILITY\n // ============================================================================\n\n /**\n * Mark column as nullable (allows NULL values).\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"middleName\").nullable();\n * ```\n */\n public nullable(): this {\n this.definition.nullable = true;\n return this;\n }\n\n /**\n * Mark column as not nullable (disallows NULL values).\n *\n * This is the default, but can be used for clarity.\n *\n * @returns This builder for chaining\n */\n public notNullable(): this {\n this.definition.nullable = false;\n return this;\n }\n\n // ============================================================================\n // DEFAULT VALUES\n // ============================================================================\n\n /**\n * Set default value for the column.\n *\n * @param value - Default value (can be a literal or expression)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.boolean(\"isActive\").default(true);\n * this.dateTime(\"createdAt\").default(\"NOW()\");\n * ```\n */\n public default(value: unknown): this {\n this.definition.defaultValue = value;\n return this;\n }\n\n // ============================================================================\n // INDEXES\n // ============================================================================\n\n /**\n * Add unique constraint/index on this column.\n *\n * Registers a pending unique index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").unique();\n * ```\n */\n public unique(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n unique: true,\n });\n return this;\n }\n\n /**\n * Add regular index on this column.\n *\n * Registers a pending index with the parent migration.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"email\").index();\n * ```\n */\n public index(): this {\n this.migration.addPendingIndex({\n columns: [this.definition.name],\n });\n return this;\n }\n\n // ============================================================================\n // PRIMARY KEY & AUTO INCREMENT\n // ============================================================================\n\n /**\n * Mark as primary key.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary();\n * ```\n */\n public primary(): this {\n this.definition.primary = true;\n return this;\n }\n\n /**\n * Mark as auto-increment (numeric types only).\n *\n * SQL databases will use native AUTO_INCREMENT/SERIAL.\n * NoSQL databases ignore this.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"id\").primary().autoIncrement();\n * ```\n */\n public autoIncrement(): this {\n this.definition.autoIncrement = true;\n return this;\n }\n\n // ============================================================================\n // NUMERIC MODIFIERS\n // ============================================================================\n\n /**\n * Mark as unsigned (numeric types only).\n *\n * Disallows negative values and doubles the positive range.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.integer(\"age\").unsigned();\n * ```\n */\n public unsigned(): this {\n this.definition.unsigned = true;\n return this;\n }\n\n // ============================================================================\n // METADATA\n // ============================================================================\n\n /**\n * Add comment/description to column.\n *\n * Stored as column metadata in the database.\n *\n * @param text - Comment text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.string(\"sku\").comment(\"Stock Keeping Unit code\");\n * ```\n */\n public comment(text: string): this {\n this.definition.comment = text;\n return this;\n }\n\n // ============================================================================\n // ACCESSOR\n // ============================================================================\n\n /**\n * Get the built column definition.\n *\n * Called internally by the Migration class to extract the final definition.\n *\n * @returns The accumulated column definition\n */\n public getDefinition(): ColumnDefinition {\n return this.definition;\n }\n}\n","import type { ForeignKeyDefinition } from \"../contracts/migration-driver.contract\";\n\n/**\n * Reference to the Migration type to avoid circular imports.\n */\ntype MigrationLike = {\n addForeignKeyOperation(fk: ForeignKeyDefinition): void;\n};\n\n/**\n * Mutable foreign key definition being built.\n */\ninterface MutableForeignKeyDefinition {\n name?: string;\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete: ForeignKeyDefinition[\"onDelete\"];\n onUpdate: ForeignKeyDefinition[\"onUpdate\"];\n}\n\n/**\n * Fluent builder for foreign key constraints.\n *\n * Allows building foreign key definitions with a chainable API.\n * SQL-only feature; NoSQL drivers ignore foreign keys.\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\")\n * .references(\"users\", \"id\")\n * .onDelete(\"cascade\")\n * .onUpdate(\"cascade\")\n * .add();\n * ```\n */\nexport class ForeignKeyBuilder {\n /** Mutable foreign key definition being accumulated */\n private readonly definition: MutableForeignKeyDefinition;\n\n /**\n * Create a new foreign key builder.\n *\n * @param migration - Parent migration instance\n * @param column - Local column name that will reference another table\n */\n public constructor(\n private readonly migration: MigrationLike,\n column: string,\n ) {\n this.definition = {\n column,\n referencesTable: \"\",\n referencesColumn: \"id\",\n onDelete: \"restrict\",\n onUpdate: \"restrict\",\n };\n }\n\n /**\n * Set the constraint name.\n *\n * @param name - Constraint name (auto-generated if not provided)\n * @returns This builder for chaining\n */\n public name(name: string): this {\n this.definition.name = name;\n return this;\n }\n\n /**\n * Set the referenced table and column.\n *\n * @param table - Referenced table name\n * @param column - Referenced column name (default: \"id\")\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\").references(\"users\", \"id\");\n * this.foreign(\"category_id\").references(\"categories\"); // defaults to \"id\"\n * ```\n */\n public references(table: string, column = \"id\"): this {\n this.definition.referencesTable = table;\n this.definition.referencesColumn = column;\n return this;\n }\n\n /**\n * Set the ON DELETE action.\n *\n * @param action - Action to take when referenced row is deleted\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\")\n * .references(\"users\")\n * .onDelete(\"cascade\"); // Delete child when parent is deleted\n * ```\n */\n public onDelete(action: ForeignKeyDefinition[\"onDelete\"]): this {\n this.definition.onDelete = action;\n return this;\n }\n\n /**\n * Set the ON UPDATE action.\n *\n * @param action - Action to take when referenced row's key is updated\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\")\n * .references(\"users\")\n * .onUpdate(\"cascade\"); // Update child when parent key changes\n * ```\n */\n public onUpdate(action: ForeignKeyDefinition[\"onUpdate\"]): this {\n this.definition.onUpdate = action;\n return this;\n }\n\n /**\n * Shorthand for `.onDelete(\"cascade\").onUpdate(\"cascade\")`.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\").references(\"users\").cascadeAll();\n * ```\n */\n public cascadeAll(): this {\n this.definition.onDelete = \"cascade\";\n this.definition.onUpdate = \"cascade\";\n return this;\n }\n\n /**\n * Finalize and add the foreign key constraint to the migration.\n *\n * This must be called to register the foreign key.\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\")\n * .references(\"users\")\n * .onDelete(\"cascade\")\n * .add(); // Required!\n * ```\n */\n public add(): void {\n this.migration.addForeignKeyOperation(this.definition as ForeignKeyDefinition);\n }\n}\n","import type {\n ColumnDefinition,\n ForeignKeyDefinition,\n FullTextIndexOptions,\n GeoIndexOptions,\n IndexDefinition,\n MigrationDriverContract,\n VectorIndexOptions,\n} from \"../contracts/migration-driver.contract\";\nimport type { DataSource } from \"../data-source/data-source\";\nimport type { ChildModel, Model } from \"../model/model\";\nimport { ColumnBuilder } from \"./column-builder\";\nimport { ForeignKeyBuilder } from \"./foreign-key-builder\";\n\n/**\n * Pending operation types supported by migrations.\n */\ntype OperationType =\n | \"addColumn\"\n | \"dropColumn\"\n | \"dropColumns\"\n | \"renameColumn\"\n | \"modifyColumn\"\n | \"createIndex\"\n | \"dropIndex\"\n | \"createUniqueIndex\"\n | \"dropUniqueIndex\"\n | \"createFullTextIndex\"\n | \"dropFullTextIndex\"\n | \"createGeoIndex\"\n | \"dropGeoIndex\"\n | \"createVectorIndex\"\n | \"dropVectorIndex\"\n | \"createTTLIndex\"\n | \"dropTTLIndex\"\n | \"addForeignKey\"\n | \"dropForeignKey\"\n | \"addPrimaryKey\"\n | \"dropPrimaryKey\"\n | \"createTable\"\n | \"createTableIfNotExists\"\n | \"dropTable\"\n | \"dropTableIfExists\"\n | \"renameTable\"\n | \"setSchemaValidation\"\n | \"removeSchemaValidation\";\n\n/**\n * Pending operation to be executed when migration runs.\n */\ntype PendingOperation = {\n readonly type: OperationType;\n readonly payload: unknown;\n};\n\n/**\n * Base class for all database migrations.\n *\n * Provides a fluent API for defining schema changes that work across\n * both SQL and NoSQL databases. The migration driver handles translating\n * operations to native database commands.\n *\n * Migrations are executed in order based on their `createdAt` timestamp,\n * which is typically extracted from the filename (e.g., `2024-01-15_create-users`).\n *\n * @example\n * ```typescript\n * // Using Migration.for() to bind to a model\n * export default class extends Migration.for(User) {\n * public up(): void {\n * this.string(\"email\").unique();\n * this.integer(\"age\").nullable();\n * this.geoIndex(\"location\");\n * }\n *\n * public down(): void {\n * this.dropColumn(\"email\");\n * this.dropColumn(\"age\");\n * this.dropGeoIndex(\"location\");\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Manual table migration (without model binding)\n * export default class CreateUsersTable extends Migration {\n * public readonly table = \"users\";\n *\n * public up(): void {\n * this.createTable();\n * this.id();\n * this.string(\"name\");\n * this.string(\"email\").unique();\n * this.timestamps();\n * }\n *\n * public down(): void {\n * this.dropTable();\n * }\n * }\n * ```\n */\nexport abstract class Migration {\n /**\n * Migration name that will be labeled with\n * If record is enabled in migration, it will be stored as migration name\n * in database\n *\n * @example\n * ```typescript\n * \"2024-01-15_create-users\";\n * ```\n */\n public static migrationName?: string;\n\n /**\n * Table/collection name for this migration.\n *\n * Must be defined by each migration class (either directly or via `Migration.for()`).\n */\n public readonly table!: string;\n\n /**\n * Sort order\n * If not provided, it will be ordered alphabetically\n */\n public static readonly order?: number;\n\n /**\n * Optional data source override.\n *\n * If specified, this migration will use a specific data source\n * instead of the default one. Can be a string name or DataSource instance.\n */\n public readonly dataSource?: string | DataSource;\n\n /**\n * Optional timestamp override.\n *\n * By default, the migration runner extracts this from the filename.\n * Set explicitly to override the execution order.\n *\n * Format: ISO 8601 or any parseable date string.\n */\n public readonly createdAt?: string;\n\n /**\n * Whether to wrap migration in a transaction.\n *\n * Defaults to `true` for SQL databases that support DDL transactions.\n * Set to `false` for operations that cannot be transactional.\n *\n * Note: MongoDB does not support transactions for most DDL operations.\n */\n public readonly transactional?: boolean;\n\n /**\n * Migration driver instance (injected by the runner).\n */\n protected driver!: MigrationDriverContract;\n\n /**\n * Queued operations to execute.\n */\n private readonly pendingOperations: PendingOperation[] = [];\n\n /**\n * Pending indexes from column builders.\n */\n private readonly pendingIndexes: IndexDefinition[] = [];\n\n // ============================================================================\n // ABSTRACT METHODS\n // ============================================================================\n\n /**\n * Define schema changes for the up migration.\n *\n * Called when running migrations forward. Add columns, indexes,\n * constraints, etc. in this method.\n */\n public abstract up(): void | Promise<void>;\n\n /**\n * Define rollback operations for the down migration.\n *\n * Called when rolling back migrations. Drop columns, indexes,\n * and undo any changes made in `up()`.\n */\n public abstract down(): void | Promise<void>;\n\n // ============================================================================\n // STATIC FACTORY\n // ============================================================================\n\n /**\n * Create a migration class bound to a specific model.\n *\n * Automatically inherits the model's table name and data source,\n * reducing boilerplate and ensuring consistency.\n *\n * @param model - Model class to bind\n * @returns Abstract migration class bound to the model\n *\n * @example\n * ```typescript\n * export default class extends Migration.for(User) {\n * public up(): void {\n * this.string(\"avatar\").nullable();\n * }\n *\n * public down(): void {\n * this.dropColumn(\"avatar\");\n * }\n * }\n * ```\n */\n public static for<T extends ChildModel<Model>>(model: T): typeof Migration {\n abstract class BoundMigration extends Migration {\n public readonly table = model.table;\n public readonly dataSource = model.dataSource;\n }\n\n return BoundMigration;\n }\n\n // ============================================================================\n // DRIVER INJECTION\n // ============================================================================\n\n /**\n * Set the migration driver.\n *\n * Called by the migration runner before executing up/down.\n *\n * @param driver - Migration driver instance\n * @internal\n */\n public setDriver(driver: MigrationDriverContract): void {\n this.driver = driver;\n }\n\n /**\n * Get the migration driver.\n *\n * @returns The migration driver instance\n */\n public getDriver(): MigrationDriverContract {\n return this.driver;\n }\n\n // ============================================================================\n // EXECUTE OPERATIONS\n // ============================================================================\n\n /**\n * Execute all pending operations.\n *\n * Called by the migration runner after up() or down() completes.\n * Executes operations in the order they were defined.\n *\n * @internal\n */\n public async execute(): Promise<void> {\n // Execute column/table operations\n for (const op of this.pendingOperations) {\n await this.executeOperation(op);\n }\n\n // Execute pending indexes from column builders\n for (const index of this.pendingIndexes) {\n if (index.unique) {\n await this.driver.createUniqueIndex(this.table, index.columns, index.name);\n } else {\n await this.driver.createIndex(this.table, index);\n }\n }\n\n // Clear pending operations after execution\n this.pendingOperations.length = 0;\n this.pendingIndexes.length = 0;\n }\n\n /**\n * Execute a single pending operation.\n */\n private async executeOperation(op: PendingOperation): Promise<void> {\n switch (op.type) {\n case \"addColumn\":\n await this.driver.addColumn(this.table, op.payload as ColumnDefinition);\n break;\n\n case \"dropColumn\":\n await this.driver.dropColumn(this.table, op.payload as string);\n break;\n\n case \"dropColumns\":\n await this.driver.dropColumns(this.table, op.payload as string[]);\n break;\n\n case \"renameColumn\": {\n const { from, to } = op.payload as { from: string; to: string };\n await this.driver.renameColumn(this.table, from, to);\n break;\n }\n\n case \"modifyColumn\":\n await this.driver.modifyColumn(this.table, op.payload as ColumnDefinition);\n break;\n\n case \"createIndex\":\n await this.driver.createIndex(this.table, op.payload as IndexDefinition);\n break;\n\n case \"dropIndex\":\n await this.driver.dropIndex(this.table, op.payload as string);\n break;\n\n case \"createUniqueIndex\": {\n const { columns, name } = op.payload as {\n columns: string[];\n name?: string;\n };\n await this.driver.createUniqueIndex(this.table, columns, name);\n break;\n }\n\n case \"dropUniqueIndex\":\n await this.driver.dropUniqueIndex(this.table, op.payload as string[]);\n break;\n\n case \"createFullTextIndex\": {\n const { columns, options } = op.payload as {\n columns: string[];\n options?: FullTextIndexOptions;\n };\n await this.driver.createFullTextIndex(this.table, columns, options);\n break;\n }\n\n case \"dropFullTextIndex\":\n await this.driver.dropFullTextIndex(this.table, op.payload as string);\n break;\n\n case \"createGeoIndex\": {\n const { column, options } = op.payload as {\n column: string;\n options?: GeoIndexOptions;\n };\n await this.driver.createGeoIndex(this.table, column, options);\n break;\n }\n\n case \"dropGeoIndex\":\n await this.driver.dropGeoIndex(this.table, op.payload as string);\n break;\n\n case \"createVectorIndex\": {\n const { column, options } = op.payload as {\n column: string;\n options: VectorIndexOptions;\n };\n await this.driver.createVectorIndex(this.table, column, options);\n break;\n }\n\n case \"dropVectorIndex\":\n await this.driver.dropVectorIndex(this.table, op.payload as string);\n break;\n\n case \"createTTLIndex\": {\n const { column, seconds } = op.payload as {\n column: string;\n seconds: number;\n };\n await this.driver.createTTLIndex(this.table, column, seconds);\n break;\n }\n\n case \"dropTTLIndex\":\n await this.driver.dropTTLIndex(this.table, op.payload as string);\n break;\n\n case \"addForeignKey\":\n await this.driver.addForeignKey(this.table, op.payload as ForeignKeyDefinition);\n break;\n\n case \"dropForeignKey\":\n await this.driver.dropForeignKey(this.table, op.payload as string);\n break;\n\n case \"addPrimaryKey\":\n await this.driver.addPrimaryKey(this.table, op.payload as string[]);\n break;\n\n case \"dropPrimaryKey\":\n await this.driver.dropPrimaryKey(this.table);\n break;\n\n case \"createTable\":\n await this.driver.createTable(this.table);\n break;\n\n case \"createTableIfNotExists\":\n await this.driver.createTableIfNotExists(this.table);\n break;\n\n case \"dropTable\":\n await this.driver.dropTable(this.table);\n break;\n\n case \"dropTableIfExists\":\n await this.driver.dropTableIfExists(this.table);\n break;\n\n case \"renameTable\":\n await this.driver.renameTable(this.table, op.payload as string);\n break;\n\n case \"setSchemaValidation\":\n await this.driver.setSchemaValidation(this.table, op.payload as object);\n break;\n\n case \"removeSchemaValidation\":\n await this.driver.removeSchemaValidation(this.table);\n break;\n }\n }\n\n // ============================================================================\n // INTERNAL HELPERS\n // ============================================================================\n\n /**\n * Add a pending index definition.\n *\n * Called by ColumnBuilder when .unique() or .index() is chained.\n *\n * @param index - Index definition\n * @internal\n */\n public addPendingIndex(index: IndexDefinition): void {\n this.pendingIndexes.push(index);\n }\n\n /**\n * Add a foreign key operation.\n *\n * Called by ForeignKeyBuilder when .add() is called.\n *\n * @param fk - Foreign key definition\n * @internal\n */\n public addForeignKeyOperation(fk: ForeignKeyDefinition): void {\n this.pendingOperations.push({\n type: \"addForeignKey\",\n payload: fk,\n });\n }\n\n // ============================================================================\n // TABLE OPERATIONS\n // ============================================================================\n\n /**\n * Create the table/collection.\n *\n * For SQL, this creates an empty table.\n * For MongoDB, this creates the collection.\n *\n * @returns This migration for chaining\n */\n public createTable(): this {\n this.pendingOperations.push({ type: \"createTable\", payload: null });\n return this;\n }\n\n /**\n * Create table if not exists\n */\n public createTableIfNotExists(): this {\n this.pendingOperations.push({ type: \"createTableIfNotExists\", payload: null });\n return this;\n }\n\n /**\n * Drop the table/collection.\n *\n * @returns This migration for chaining\n */\n public dropTable(): this {\n this.pendingOperations.push({ type: \"dropTable\", payload: null });\n return this;\n }\n\n /**\n * Drop the table/collection if it exists.\n *\n * No error is thrown if the table doesn't exist.\n *\n * @returns This migration for chaining\n */\n public dropTableIfExists(): this {\n this.pendingOperations.push({ type: \"dropTableIfExists\", payload: null });\n return this;\n }\n\n /**\n * Rename the table/collection.\n *\n * @param newName - New table name\n * @returns This migration for chaining\n */\n public renameTableTo(newName: string): this {\n this.pendingOperations.push({ type: \"renameTable\", payload: newName });\n return this;\n }\n\n // ============================================================================\n // COLUMN TYPES - STRING\n // ============================================================================\n\n /**\n * Add a string/varchar column.\n *\n * @param column - Column name\n * @param length - Max length (default: 255)\n * @returns Column builder for chaining modifiers\n *\n * @example\n * ```typescript\n * this.string(\"name\"); // VARCHAR(255)\n * this.string(\"code\", 10); // VARCHAR(10)\n * ```\n */\n public string(column: string, length = 255): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"string\", { length });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a fixed-length char column.\n *\n * @param column - Column name\n * @param length - Exact length\n * @returns Column builder for chaining modifiers\n */\n public char(column: string, length: number): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"char\", { length });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a text column (unlimited length).\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public text(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"text\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a medium text column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public mediumText(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"mediumText\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a long text column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public longText(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"longText\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - NUMERIC\n // ============================================================================\n\n /**\n * Add an integer column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public integer(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"integer\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for integer().\n */\n public int(column: string): ColumnBuilder {\n return this.integer(column);\n }\n\n /**\n * Add a small integer column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public smallInteger(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"smallInteger\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for smallInteger().\n */\n public smallInt(column: string): ColumnBuilder {\n return this.smallInteger(column);\n }\n\n /**\n * Add a tiny integer column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public tinyInteger(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"tinyInteger\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for tinyInteger().\n */\n public tinyInt(column: string): ColumnBuilder {\n return this.tinyInteger(column);\n }\n\n /**\n * Add a big integer column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public bigInteger(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"bigInteger\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for bigInteger().\n */\n public bigInt(column: string): ColumnBuilder {\n return this.bigInteger(column);\n }\n\n /**\n * Add a float column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public float(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"float\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a double precision column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public double(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"double\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a decimal column with precision and scale.\n *\n * @param column - Column name\n * @param precision - Total digits (default: 8)\n * @param scale - Decimal places (default: 2)\n * @returns Column builder for chaining modifiers\n *\n * @example\n * ```typescript\n * this.decimal(\"price\", 10, 2); // DECIMAL(10,2) - up to 99999999.99\n * ```\n */\n public decimal(column: string, precision = 8, scale = 2): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"decimal\", {\n precision,\n scale,\n });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - BOOLEAN\n // ============================================================================\n\n /**\n * Add a boolean column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public boolean(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"boolean\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for boolean().\n */\n public bool(column: string): ColumnBuilder {\n return this.boolean(column);\n }\n\n // ============================================================================\n // COLUMN TYPES - DATE/TIME\n // ============================================================================\n\n /**\n * Add a date column (date only, no time).\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public date(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"date\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a datetime column (date and time).\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public dateTime(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"dateTime\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a timestamp column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public timestamp(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"timestamp\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a time column (time only, no date).\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public time(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"time\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a year column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public year(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"year\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - JSON & BINARY\n // ============================================================================\n\n /**\n * Add a JSON column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public json(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"json\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for json().\n */\n public object(column: string): ColumnBuilder {\n return this.json(column);\n }\n\n /**\n * Add a binary/blob column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public binary(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"binary\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Alias for binary().\n */\n public blob(column: string): ColumnBuilder {\n return this.binary(column);\n }\n\n // ============================================================================\n // COLUMN TYPES - IDENTIFIERS\n // ============================================================================\n\n /**\n * Add a UUID column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public uuid(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"uuid\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a ULID column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public ulid(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"ulid\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - NETWORK\n // ============================================================================\n\n /**\n * Add an IP address column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public ipAddress(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"ipAddress\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a MAC address column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public macAddress(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"macAddress\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - GEO & SPATIAL\n // ============================================================================\n\n /**\n * Add a geo point column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public point(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"point\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a polygon column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public polygon(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"polygon\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a line string column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public lineString(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"lineString\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a generic geometry column.\n *\n * @param column - Column name\n * @returns Column builder for chaining modifiers\n */\n public geometry(column: string): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"geometry\");\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - AI/ML\n // ============================================================================\n\n /**\n * Add a vector column for AI embeddings.\n *\n * Used for storing and searching ML embeddings (e.g., OpenAI, Cohere).\n *\n * @param column - Column name\n * @param dimensions - Vector dimensions (e.g., 1536 for OpenAI ada-002)\n * @returns Column builder for chaining modifiers\n *\n * @example\n * ```typescript\n * this.vector(\"embedding\", 1536); // OpenAI ada-002\n * this.vector(\"embedding\", 384); // Sentence Transformers\n * ```\n */\n public vector(column: string, dimensions: number): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"vector\", { dimensions });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // COLUMN TYPES - ENUM & SET\n // ============================================================================\n\n /**\n * Add an enum column with allowed values.\n *\n * @param column - Column name\n * @param values - Allowed enum values\n * @returns Column builder for chaining modifiers\n *\n * @example\n * ```typescript\n * this.enum(\"status\", [\"pending\", \"active\", \"archived\"]);\n * ```\n */\n public enum(column: string, values: string[]): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"enum\", { values });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n /**\n * Add a set column (multiple values from a set).\n *\n * @param column - Column name\n * @param values - Allowed set values\n * @returns Column builder for chaining modifiers\n */\n public set(column: string, values: string[]): ColumnBuilder {\n const builder = new ColumnBuilder(this, column, \"set\", { values });\n this.pendingOperations.push({\n type: \"addColumn\",\n payload: builder.getDefinition(),\n });\n return builder;\n }\n\n // ============================================================================\n // SHORTCUTS\n // ============================================================================\n\n /**\n * Add an auto-increment primary key column.\n *\n * Creates an unsigned integer with primary key and auto-increment.\n *\n * @param name - Column name (default: \"id\")\n * @returns Column builder for chaining modifiers\n *\n * @example\n * ```typescript\n * this.id(); // Creates \"id\" column\n * this.id(\"userId\"); // Creates \"userId\" column\n * ```\n */\n public id(name = \"id\"): ColumnBuilder {\n return this.integer(name).primary().autoIncrement().unsigned();\n }\n\n /**\n * Add a big integer auto-increment primary key column.\n *\n * @param name - Column name (default: \"id\")\n * @returns Column builder for chaining modifiers\n */\n public bigId(name = \"id\"): ColumnBuilder {\n return this.bigInteger(name).primary().autoIncrement().unsigned();\n }\n\n /**\n * Add a UUID primary key column.\n *\n * @param name - Column name (default: \"id\")\n * @returns Column builder for chaining modifiers\n */\n public uuidId(name = \"id\"): ColumnBuilder {\n return this.uuid(name).primary();\n }\n\n /**\n * Add createdAt and updatedAt timestamp columns.\n *\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.timestamps(); // Creates createdAt and updatedAt\n * ```\n */\n public timestamps(): this {\n this.dateTime(\"createdAt\");\n this.dateTime(\"updatedAt\");\n return this;\n }\n\n /**\n * Add a deletedAt column for soft deletes.\n *\n * @param column - Column name (default: \"deletedAt\")\n * @returns Column builder for chaining modifiers\n */\n public softDeletes(column = \"deletedAt\"): ColumnBuilder {\n return this.dateTime(column).nullable();\n }\n\n // ============================================================================\n // DROP COLUMN OPERATIONS\n // ============================================================================\n\n /**\n * Drop a column.\n *\n * @param column - Column name to drop\n * @returns This migration for chaining\n */\n public dropColumn(column: string): this {\n this.pendingOperations.push({ type: \"dropColumn\", payload: column });\n return this;\n }\n\n /**\n * Drop multiple columns.\n *\n * @param columns - Column names to drop\n * @returns This migration for chaining\n */\n public dropColumns(...columns: string[]): this {\n this.pendingOperations.push({ type: \"dropColumns\", payload: columns });\n return this;\n }\n\n /**\n * Rename a column.\n *\n * @param from - Current column name\n * @param to - New column name\n * @returns This migration for chaining\n */\n public renameColumn(from: string, to: string): this {\n this.pendingOperations.push({\n type: \"renameColumn\",\n payload: { from, to },\n });\n return this;\n }\n\n // ============================================================================\n // INDEX OPERATIONS\n // ============================================================================\n\n /**\n * Create an index on one or more columns.\n *\n * @param columns - Column(s) to index\n * @param name - Optional index name\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.index(\"email\");\n * this.index([\"firstName\", \"lastName\"], \"name_idx\");\n * ```\n */\n public index(columns: string | string[], name?: string): this {\n const cols = Array.isArray(columns) ? columns : [columns];\n this.pendingOperations.push({\n type: \"createIndex\",\n payload: { columns: cols, name } as IndexDefinition,\n });\n return this;\n }\n\n /**\n * Drop an index by name or columns.\n *\n * @param nameOrColumns - Index name (string) or columns array\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.dropIndex(\"email_idx\"); // Drop by name\n * this.dropIndex([\"firstName\", \"lastName\"]); // Drop by columns\n * ```\n */\n public dropIndex(nameOrColumns: string | string[]): this {\n this.pendingOperations.push({\n type: \"dropIndex\",\n payload: nameOrColumns,\n });\n return this;\n }\n\n /**\n * Create a unique constraint/index.\n *\n * @param columns - Column(s) to make unique\n * @param name - Optional constraint name\n * @returns This migration for chaining\n */\n public unique(columns: string | string[], name?: string): this {\n const cols = Array.isArray(columns) ? columns : [columns];\n this.pendingOperations.push({\n type: \"createUniqueIndex\",\n payload: { columns: cols, name },\n });\n return this;\n }\n\n /**\n * Drop a unique constraint/index.\n *\n * @param columns - Columns in the unique constraint\n * @returns This migration for chaining\n */\n public dropUnique(columns: string | string[]): this {\n const cols = Array.isArray(columns) ? columns : [columns];\n this.pendingOperations.push({ type: \"dropUniqueIndex\", payload: cols });\n return this;\n }\n\n // ============================================================================\n // FULL-TEXT INDEX\n // ============================================================================\n\n /**\n * Create a full-text search index.\n *\n * @param columns - Column(s) to index\n * @param options - Full-text options\n * @returns This migration for chaining\n */\n public fullText(columns: string | string[], options?: FullTextIndexOptions): this {\n const cols = Array.isArray(columns) ? columns : [columns];\n this.pendingOperations.push({\n type: \"createFullTextIndex\",\n payload: { columns: cols, options },\n });\n return this;\n }\n\n /**\n * Drop a full-text search index.\n *\n * @param name - Index name\n * @returns This migration for chaining\n */\n public dropFullText(name: string): this {\n this.pendingOperations.push({ type: \"dropFullTextIndex\", payload: name });\n return this;\n }\n\n // ============================================================================\n // GEO INDEX\n // ============================================================================\n\n /**\n * Create a geo-spatial index.\n *\n * @param column - Geo column\n * @param options - Geo index options\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.geoIndex(\"location\"); // 2dsphere index\n * this.geoIndex(\"coordinates\", { type: \"2d\" }); // 2d index\n * ```\n */\n public geoIndex(column: string, options?: GeoIndexOptions): this {\n this.pendingOperations.push({\n type: \"createGeoIndex\",\n payload: { column, options },\n });\n return this;\n }\n\n /**\n * Drop a geo-spatial index.\n *\n * @param column - Geo column\n * @returns This migration for chaining\n */\n public dropGeoIndex(column: string): this {\n this.pendingOperations.push({ type: \"dropGeoIndex\", payload: column });\n return this;\n }\n\n // ============================================================================\n // VECTOR INDEX\n // ============================================================================\n\n /**\n * Create a vector search index for AI embeddings.\n *\n * @param column - Vector column\n * @param options - Vector index options\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.vectorIndex(\"embedding\", {\n * dimensions: 1536,\n * similarity: \"cosine\",\n * });\n * ```\n */\n public vectorIndex(column: string, options: VectorIndexOptions): this {\n this.pendingOperations.push({\n type: \"createVectorIndex\",\n payload: { column, options },\n });\n return this;\n }\n\n /**\n * Drop a vector search index.\n *\n * @param column - Vector column\n * @returns This migration for chaining\n */\n public dropVectorIndex(column: string): this {\n this.pendingOperations.push({ type: \"dropVectorIndex\", payload: column });\n return this;\n }\n\n // ============================================================================\n // TTL INDEX\n // ============================================================================\n\n /**\n * Create a TTL (time-to-live) index for automatic document expiration.\n *\n * Primarily for MongoDB. Documents are automatically deleted after the\n * specified time has passed since the date in the column.\n *\n * @param column - Date column to check for expiration\n * @param expireAfterSeconds - Seconds after which documents expire\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * // Delete sessions 24 hours after createdAt\n * this.ttlIndex(\"createdAt\", 86400);\n * ```\n */\n public ttlIndex(column: string, expireAfterSeconds: number): this {\n this.pendingOperations.push({\n type: \"createTTLIndex\",\n payload: { column, seconds: expireAfterSeconds },\n });\n return this;\n }\n\n /**\n * Drop a TTL index.\n *\n * @param column - Column with TTL\n * @returns This migration for chaining\n */\n public dropTTLIndex(column: string): this {\n this.pendingOperations.push({ type: \"dropTTLIndex\", payload: column });\n return this;\n }\n\n // ============================================================================\n // PRIMARY KEY\n // ============================================================================\n\n /**\n * Add a composite primary key.\n *\n * @param columns - Columns to include in the primary key\n * @returns This migration for chaining\n */\n public primaryKey(columns: string[]): this {\n this.pendingOperations.push({ type: \"addPrimaryKey\", payload: columns });\n return this;\n }\n\n /**\n * Drop the primary key constraint.\n *\n * @returns This migration for chaining\n */\n public dropPrimaryKey(): this {\n this.pendingOperations.push({ type: \"dropPrimaryKey\", payload: null });\n return this;\n }\n\n // ============================================================================\n // FOREIGN KEYS (SQL)\n // ============================================================================\n\n /**\n * Start building a foreign key constraint.\n *\n * SQL-only feature; NoSQL drivers ignore foreign keys.\n *\n * @param column - Local column that references another table\n * @returns Foreign key builder for chaining\n *\n * @example\n * ```typescript\n * this.foreign(\"user_id\")\n * .references(\"users\", \"id\")\n * .onDelete(\"cascade\")\n * .add();\n * ```\n */\n public foreign(column: string): ForeignKeyBuilder {\n return new ForeignKeyBuilder(this, column);\n }\n\n /**\n * Drop a foreign key constraint by name.\n *\n * @param name - Constraint name\n * @returns This migration for chaining\n */\n public dropForeign(name: string): this {\n this.pendingOperations.push({ type: \"dropForeignKey\", payload: name });\n return this;\n }\n\n // ============================================================================\n // SCHEMA VALIDATION (NoSQL)\n // ============================================================================\n\n /**\n * Set JSON schema validation rules on the collection.\n *\n * MongoDB-only feature. SQL databases ignore this.\n *\n * @param schema - JSON Schema object\n * @returns This migration for chaining\n *\n * @example\n * ```typescript\n * this.schemaValidation({\n * bsonType: \"object\",\n * required: [\"name\", \"email\"],\n * properties: {\n * name: { bsonType: \"string\" },\n * email: { bsonType: \"string\" },\n * },\n * });\n * ```\n */\n public schemaValidation(schema: object): this {\n this.pendingOperations.push({\n type: \"setSchemaValidation\",\n payload: schema,\n });\n return this;\n }\n\n /**\n * Remove schema validation rules from the collection.\n *\n * @returns This migration for chaining\n */\n public dropSchemaValidation(): this {\n this.pendingOperations.push({\n type: \"removeSchemaValidation\",\n payload: null,\n });\n return this;\n }\n\n // ============================================================================\n // RAW ACCESS\n // ============================================================================\n\n /**\n * Execute raw operations with direct driver access.\n *\n * Use this for database-specific operations not covered by the API.\n *\n * @param callback - Callback receiving the native connection\n * @returns Result from callback\n *\n * @example\n * ```typescript\n * await this.raw(async (db) => {\n * await db.collection(\"users\").updateMany({}, { $set: { active: true } });\n * });\n * ```\n */\n public async raw<T>(callback: (connection: unknown) => Promise<T>): Promise<T> {\n return this.driver.raw(callback);\n }\n}\n\nexport function migrate(\n model: ChildModel<Model<any>>,\n options?: {\n createdAt?: string;\n name?: string;\n up?: (this: Migration) => void;\n down?: (this: Migration) => void;\n transactional?: boolean;\n },\n) {\n return class AnonymousMigration extends Migration {\n public static migrationName?: string = options?.name;\n public static createdAt?: string = options?.createdAt;\n public readonly table: string = model.table;\n public static transactional?: boolean = options?.transactional;\n\n public async up() {\n options?.up?.call(this);\n }\n\n public async down() {\n options?.down?.call(this);\n }\n };\n}\n","import { colors } from \"@mongez/copper\";\nimport { log } from \"@warlock.js/logger\";\nimport type { MigrationDriverContract } from \"../contracts/migration-driver.contract\";\nimport type { DataSource } from \"../data-source/data-source\";\nimport { dataSourceRegistry } from \"../data-source/data-source-registry\";\nimport { type Migration } from \"./migration\";\nimport type { MigrationRecord, MigrationResult } from \"./types\";\n\n/**\n * Migration class type with static name property.\n */\ntype MigrationClass = (new () => Migration) & {\n migrationName: string;\n order?: number;\n createdAt?: string;\n};\n\n/**\n * Options for migration execution.\n */\ntype ExecuteOptions = {\n /** Run in dry-run mode (no actual changes) */\n readonly dryRun?: boolean;\n /** Record to migrations table (default: true for batch, false for single) */\n readonly record?: boolean;\n};\n\n/**\n * Migration runner that executes migrations.\n *\n * This is a pure executor - it doesn't discover migrations.\n * Discovery is handled by the framework (e.g., @warlock.js/core CLI).\n *\n * The migration name is read from the static `name` property on the class,\n * which should be set by the CLI after importing:\n *\n * @example\n * ```typescript\n * // In CLI after importing:\n * const { default: MigrationClass } = await import(\"./create-users.migration.ts\");\n * MigrationClass.migrationName ??= \"create-users\";\n *\n * // Then register or execute:\n * runner.register(MigrationClass);\n * // or\n * await runner.execute(MigrationClass);\n * ```\n *\n * @example\n * ```typescript\n * // Simple direct execution\n * await runner.execute(CreateUsersTable);\n * await runner.rollback(CreateUsersTable);\n *\n * // Registry pattern for batch operations\n * runner.register(CreateUsersTable);\n * runner.register(AddEmailIndex);\n * await runner.runAll();\n * await runner.rollbackAll();\n * ```\n */\nexport class MigrationRunner {\n /** Registered migrations */\n public readonly migrations: MigrationClass[] = [];\n\n /** Data source to use */\n private dataSource?: DataSource;\n\n /** Cached migration driver */\n private cachedMigrationDriver?: MigrationDriverContract;\n\n /** Table name for tracking migrations */\n private readonly migrationsTable: string;\n\n /** Whether to log operations */\n private readonly verbose: boolean;\n\n /**\n * Create a new migration runner.\n *\n * @param options - Runner options\n */\n public constructor(\n options: {\n dataSource?: DataSource;\n migrationsTable?: string;\n verbose?: boolean;\n } = {},\n ) {\n this.dataSource = options.dataSource;\n this.migrationsTable = options.migrationsTable ?? \"_migrations\";\n this.verbose = options.verbose ?? true;\n }\n\n // ============================================================================\n // DATA SOURCE\n // ============================================================================\n\n /**\n * Set the data source.\n */\n public setDataSource(dataSource: DataSource): this {\n this.dataSource = dataSource;\n this.cachedMigrationDriver = undefined;\n return this;\n }\n\n /**\n * Get the data source.\n */\n private getDataSource(): DataSource {\n if (!this.dataSource) {\n this.dataSource = dataSourceRegistry.get();\n }\n return this.dataSource;\n }\n\n /**\n * Get the migration driver.\n */\n private getMigrationDriver(): MigrationDriverContract {\n if (!this.cachedMigrationDriver) {\n this.cachedMigrationDriver = this.getDataSource().driver.migrationDriver();\n }\n return this.cachedMigrationDriver;\n }\n\n // ============================================================================\n // REGISTRATION\n // ============================================================================\n\n /**\n * Register a migration.\n *\n * The migration name is read from `MigrationClass.migrationName`.\n *\n * @param MigrationClass - Migration class (must have static `name` set)\n * @param createdAt - Optional timestamp for ordering\n * @returns This runner for chaining\n *\n * @example\n * ```typescript\n * CreateUsersTable.migrationName = \"2024-01-15_create-users\";\n * runner.register(CreateUsersTable);\n * ```\n */\n public register(MigrationClass: MigrationClass): this {\n const name = MigrationClass.migrationName;\n if (!name) {\n throw new Error(\n `Migration class must have a static 'migrationName' property set. ` +\n `Set it in CLI after importing: MigrationClass.migrationName = \"filename\";`,\n );\n }\n // Avoid duplicates\n if (!this.migrations.some((m) => m.migrationName === name)) {\n this.migrations.push(MigrationClass);\n }\n\n return this;\n }\n\n /**\n * Register multiple migrations.\n *\n * @param migrations - Array of migration classes\n * @returns This runner for chaining\n */\n public registerMany(migrations: MigrationClass[]): this {\n for (const MigrationClass of migrations) {\n this.register(MigrationClass);\n }\n return this;\n }\n\n /**\n * Clear all registered migrations.\n */\n public clear(): this {\n this.migrations.length = 0;\n return this;\n }\n\n /**\n * Get all registered migration names.\n */\n public getRegisteredNames(): string[] {\n return this.migrations.map((m) => m.migrationName);\n }\n\n // ============================================================================\n // SINGLE EXECUTION\n // ============================================================================\n\n /**\n * Execute a single migration's up() method.\n *\n * @param MigrationClass - Migration class to execute\n * @param options - Execution options\n * @returns Migration result\n *\n * @example\n * ```typescript\n * await runner.execute(CreateUsersTable);\n * await runner.execute(AddEmailIndex, { dryRun: true });\n * ```\n */\n public async run(\n MigrationClass: MigrationClass,\n options: ExecuteOptions = {},\n ): Promise<MigrationResult> {\n return this.runMigration(MigrationClass, \"up\", {\n dryRun: options.dryRun,\n record: options.record ?? false,\n });\n }\n\n /**\n * Execute a single migration's down() method.\n *\n * @param MigrationClass - Migration class to rollback\n * @param options - Execution options\n * @returns Migration result\n *\n * @example\n * ```typescript\n * await runner.rollback(CreateUsersTable);\n * ```\n */\n public async rollback(\n MigrationClass: MigrationClass,\n options: ExecuteOptions = {},\n ): Promise<MigrationResult> {\n return this.runMigration(MigrationClass, \"down\", {\n dryRun: options.dryRun,\n record: options.record ?? false,\n });\n }\n\n // ============================================================================\n // BATCH EXECUTION (REGISTERED MIGRATIONS)\n // ============================================================================\n\n /**\n * Run all pending registered migrations.\n *\n * Only runs migrations not already in the migrations table.\n *\n * @param options - Execution options\n * @returns Results for each migration\n *\n * @example\n * ```typescript\n * runner.register(CreateUsersTable);\n * runner.register(AddEmailIndex);\n * const results = await runner.runAll();\n * ```\n */\n public async runAll(options: ExecuteOptions = {}): Promise<MigrationResult[]> {\n const { dryRun = false, record = true } = options;\n\n const results: MigrationResult[] = [];\n\n // Get pending migrations\n const pending = await this.getPendingMigrations();\n\n if (pending.length === 0) {\n log.warn(\"database\", \"migration\", \"Nothing to migrate.\");\n return results;\n }\n\n log.info(\"database\", \"migration\", `Found ${pending.length} pending migration(s).`);\n const nextBatch = await this.getNextBatchNumber();\n\n for (const MigrationClass of pending) {\n const result = await this.runMigration(MigrationClass, \"up\", {\n dryRun,\n record,\n batch: nextBatch,\n });\n results.push(result);\n\n if (!result.success) {\n break; // Stop on first error\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n log.success(\n \"database\",\n \"migration\",\n `Migration complete: ${successCount}/${pending.length} successful.`,\n );\n\n return results;\n }\n\n /**\n * Rollback the last batch of migrations.\n *\n * @param options - Execution options\n * @returns Results for each migration\n */\n public async rollbackLast(options: ExecuteOptions = {}): Promise<MigrationResult[]> {\n return this.rollbackBatches(1, options);\n }\n\n /**\n * Rollback N batches of migrations.\n *\n * @param batches - Number of batches to rollback\n * @param options - Execution options\n * @returns Results for each migration\n */\n public async rollbackBatches(\n batches: number,\n options: ExecuteOptions = {},\n ): Promise<MigrationResult[]> {\n const dryRun = options.dryRun ?? false;\n const record = options.record ?? true;\n const results: MigrationResult[] = [];\n\n const toRollback = await this.getMigrationsToRollback(batches);\n\n if (toRollback.length === 0) {\n log.warn(\"database\", \"migration\", \"Nothing to rollback.\");\n return results;\n }\n\n log.info(\"database\", \"migration\", `Rolling back ${toRollback.length} migration(s).`);\n\n for (const MigrationClass of toRollback) {\n const result = await this.runMigration(MigrationClass, \"down\", {\n dryRun,\n record,\n });\n results.push(result);\n\n if (!result.success) {\n break;\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n log.success(\n \"database\",\n \"migration\",\n `Rollback complete: ${successCount}/${toRollback.length} successful.`,\n );\n\n return results;\n }\n\n /**\n * Rollback all executed migrations.\n *\n * @param options - Execution options\n * @returns Results for each migration\n */\n public async rollbackAll(options: ExecuteOptions = {}): Promise<MigrationResult[]> {\n const executed = await this.getExecutedMigrations();\n if (executed.length === 0) {\n log.warn(\"database\", \"migration\", \"Nothing to rollback.\");\n return [];\n }\n\n const maxBatch = Math.max(...executed.map((r) => r.batch));\n return this.rollbackBatches(maxBatch, options);\n }\n\n /**\n * Reset and re-run: rollback all then run all.\n *\n * @param options - Execution options\n * @returns Combined results\n */\n public async fresh(options: ExecuteOptions = {}): Promise<MigrationResult[]> {\n const rollbackResults = await this.rollbackAll(options);\n const runResults = await this.runAll(options);\n return [...rollbackResults, ...runResults];\n }\n\n // ============================================================================\n // STATUS\n // ============================================================================\n\n /**\n * Get status of all registered migrations.\n */\n public async status(): Promise<\n Array<{\n name: string;\n table: string;\n executed: boolean;\n batch: number | null;\n }>\n > {\n const executed = await this.getExecutedMigrations();\n const executedMap = new Map(executed.map((r) => [r.name, r]));\n\n return this.migrations.map((MigrationClass) => {\n const instance = new MigrationClass();\n const name = MigrationClass.migrationName;\n const record = executedMap.get(name);\n return {\n name,\n table: instance.table,\n executed: !!record,\n batch: record?.batch ?? null,\n };\n });\n }\n\n // ============================================================================\n // PRIVATE HELPERS\n // ============================================================================\n\n /**\n * Run a single migration.\n */\n private async runMigration(\n MigrationClass: MigrationClass,\n direction: \"up\" | \"down\",\n options: {\n dryRun?: boolean;\n record?: boolean;\n batch?: number;\n } = {},\n ): Promise<MigrationResult> {\n const { dryRun = false, record = true } = options;\n const startTime = Date.now();\n let success = true;\n let error: string | undefined;\n\n const migration = new MigrationClass();\n const name = MigrationClass.migrationName;\n\n log.info(\n \"database\",\n \"migration\",\n `${direction === \"up\" ? \"Migrating\" : \"Rolling back\"}: ${colors.magenta(name)}...`,\n );\n\n try {\n if (!dryRun) {\n const driver = this.getMigrationDriver();\n migration.setDriver(driver);\n\n if (direction === \"up\") {\n await migration.up();\n } else {\n await migration.down();\n }\n\n await migration.execute();\n\n if (record) {\n if (direction === \"up\") {\n const batch = options.batch ?? (await this.getNextBatchNumber());\n await this.recordMigration(\n name,\n batch,\n MigrationClass.createdAt ? new Date(MigrationClass.createdAt) : undefined,\n );\n } else {\n await this.removeMigrationRecord(name);\n }\n }\n }\n } catch (err) {\n success = false;\n error = err instanceof Error ? err.message : String(err);\n log.error(\"database\", \"migration\", `${colors.magenta(name)}: ✗ Failed: ${error}`);\n }\n\n const durationMs = Date.now() - startTime;\n\n if (success) {\n log.success(\n \"database\",\n \"migration\",\n `${direction == \"up\" ? \"Migrated\" : \"Rolled back\"} ${colors.magenta(name)}: successfully (${durationMs}ms)`,\n );\n }\n\n return {\n name,\n table: migration.table,\n direction,\n success,\n error,\n durationMs,\n executedAt: new Date(),\n };\n }\n\n /**\n * Get pending (not executed) registered migrations.\n */\n private async getPendingMigrations(): Promise<MigrationClass[]> {\n const executed = await this.getExecutedMigrations();\n const executedNames = new Set(executed.map((r) => r.name));\n const migrations = this.migrations.filter((m) => !executedNames.has(m.migrationName));\n\n return migrations.sort((a, b) => {\n if (a.order && b.order) {\n return a.order - b.order;\n }\n\n return a.migrationName.localeCompare(b.migrationName);\n });\n }\n\n /**\n * Get migrations to rollback.\n */\n private async getMigrationsToRollback(batches: number): Promise<MigrationClass[]> {\n const executed = await this.getExecutedMigrations();\n if (executed.length === 0) return [];\n\n const batchNumbers = [...new Set(executed.map((r) => r.batch))]\n .sort((a, b) => b - a)\n .slice(0, batches);\n\n const toRollback = executed.filter((r) => batchNumbers.includes(r.batch)).reverse();\n\n const migrations = toRollback\n .map((r) => this.migrations.find((m) => m.migrationName === r.name))\n .filter((m): m is MigrationClass => !!m);\n\n return migrations.sort((a, b) => {\n if (a.order && b.order) {\n return a.order - b.order;\n }\n\n return a.migrationName.localeCompare(b.migrationName);\n });\n }\n\n /**\n * Get executed migration records.\n */\n public async getExecutedMigrations(): Promise<MigrationRecord[]> {\n const driver = this.getDataSource().driver;\n\n try {\n const queryBuilder = driver.queryBuilder<MigrationRecord>(this.migrationsTable);\n return await queryBuilder.orderBy(\"batch\", \"asc\").orderBy(\"name\", \"asc\").get();\n } catch {\n return [];\n }\n }\n\n /**\n * Record a migration.\n */\n private async recordMigration(name: string, batch: number, createdAt?: Date): Promise<void> {\n const driver = this.getDataSource().driver;\n\n await driver.insert(this.migrationsTable, {\n name,\n batch,\n executedAt: new Date(),\n createdAt,\n });\n }\n\n /**\n * Remove a migration record.\n */\n private async removeMigrationRecord(name: string): Promise<void> {\n const driver = this.getDataSource().driver;\n await driver.delete(this.migrationsTable, { name });\n }\n\n /**\n * Get next batch number.\n */\n private async getNextBatchNumber(): Promise<number> {\n const executed = await this.getExecutedMigrations();\n if (executed.length === 0) return 1;\n return Math.max(...executed.map((r) => r.batch)) + 1;\n }\n}\n\nexport const migrationRunner = new MigrationRunner();\n"]}
|