Skip to content

Repository Mixins removed

FieldsVisibilityMixin and DefaultFilterMixin were removed from IGNIS - this page is a tombstone documenting where their behavior lives now. For the current repository hierarchy, start with the Repositories overview.

Files:

Removed

FieldsVisibilityMixin and DefaultFilterMixin are no longer exported and must not be imported or composed in new code.

What They Were

Before the connectors restructure, AbstractRepository composed two mixins onto BaseHelper:

MixinResponsibility
FieldsVisibilityMixinHidden-properties exclusion at SQL level (reads hiddenProperties from @model settings)
DefaultFilterMixinAutomatic default-filter merging (reads defaultFilter from @model settings)

Where the Behavior Lives Now

The functionality was not dropped - it was folded directly into the repository hierarchy.

Engine-neutral: AbstractRepository

AbstractRepository resolves @model settings by class (Reflect target) via MetadataRegistry and exposes them as protected getters, memoized after first access:

typescript
protected get modelSettings(): IModelMetadata['settings'];  // full @model settings
protected get hiddenFields(): string[];                     // settings.hiddenProperties ?? []
protected get defaultWhere(): TWhere | undefined;           // settings.defaultFilter?.where
protected get defaultLimit(): number | undefined;           // settings.defaultLimit

PostgreSQL: RelationalBaseRepository

Builds on those getters to implement SQL-level column exclusion and full-filter merging for Drizzle:

typescript
getHiddenProperties(): Set<string>;                       // memoized Set of hiddenFields
hasHiddenProperties(): boolean;
getVisibleProperties(): Record<string, any> | undefined;  // memoized Drizzle column-selection map

getDefaultFilter(): TFilter | undefined;                  // settings.defaultFilter
getDefaultLimit(): number | undefined;
hasDefaultFilter(): boolean;
applyDefaultFilter(opts: {
  userFilter?: TFilter;
  shouldSkipDefaultFilter?: boolean;
}): TFilter;                                              // merges via queryDialect.mergeFilter

Hidden columns are excluded from select() and returning() calls at query time - the same SQL-level guarantee the mixins provided. The typesense connector implements its own equivalent natively since it is not Drizzle-aware.

Migration

Old (mixin)New
FieldsVisibilityMixin -> getHiddenProperties()RelationalBaseRepository.getHiddenProperties()
FieldsVisibilityMixin -> getVisibleProperties()RelationalBaseRepository.getVisibleProperties()
FieldsVisibilityMixin -> hasHiddenProperties()RelationalBaseRepository.hasHiddenProperties()
DefaultFilterMixin -> getDefaultFilter()RelationalBaseRepository.getDefaultFilter()
DefaultFilterMixin -> hasDefaultFilter()RelationalBaseRepository.hasDefaultFilter()
DefaultFilterMixin -> applyDefaultFilter()RelationalBaseRepository.applyDefaultFilter()

If you extended DefaultCRUDRepository (or any class in the PostgreSQL hierarchy), no change is needed - these methods have always been available on your repository instances; only the internal composition changed.

Custom Mixins Still Work

The mixin pattern remains a valid technique for your own repository code, via TMixinTarget from @venizia/ignis-helpers:

typescript
import { TMixinTarget } from '@venizia/ignis-helpers';

export const AuditLogMixin = <T extends TMixinTarget<object>>(baseClass: T) => {
  class Mixed extends baseClass {
    logOperation(opts: { operation: string; data: unknown }): void {
      // custom behavior
    }
  }
  return Mixed;
};

export class ProductRepository extends AuditLogMixin(
  DefaultCRUDRepository<typeof Product.schema>,
) {}

See also