File

src/app/core/basic-datatypes/schema-embed/schema-embed.datatype.ts

Description

Datatype for the EntitySchemaService transforming values of complex objects recursively.

Can be used in two ways:

  1. Config-based (directly via annotation): Set dataType: "schema-embed" and define the inner schema in additional as a SchemaEmbedDatatypeAdditional map.
  2. Subclass-based (extending this class): Override embeddedType to point to a class with @DatabaseField() annotations.

The config in additional is merged with the embeddedType schema (if present), allowing runtime config to extend or override a class's annotations.

Extends

DefaultDatatype

Index

Properties
Methods

Methods

transformToDatabaseFormat
transformToDatabaseFormat(value: EntityType, schemaField?: EntitySchemaField)
Inherited from DefaultDatatype
Defined in DefaultDatatype:92
Parameters :
Name Type Optional
value EntityType No
schemaField EntitySchemaField Yes
Returns : DBType
transformToObjectFormat
transformToObjectFormat(value: DBType, schemaField?: EntitySchemaField)
Inherited from DefaultDatatype
Parameters :
Name Type Optional
value DBType No
schemaField EntitySchemaField Yes
Returns : EntityType
Async anonymize
anonymize(value: EntityType, schemaField: EntitySchemaField, parent: any)
Inherited from DefaultDatatype

(Partially) anonymize to "retain-anonymized" for reporting purposes without personal identifiable information.

Parameters :
Name Type Optional Description
value EntityType No

The original value to be anonymized

schemaField EntitySchemaField No
parent any No
Returns : Promise<any>
Static detectFieldInEntity
detectFieldInEntity(entityOrType: Entity | EntityConstructor, dataTypes: string | string[])
Inherited from DefaultDatatype
Defined in DefaultDatatype:57

Detect the first field of the given datatype(s) in an entity's schema.

Scans the schema for a field whose dataType matches one of the provided strings and returns its property name.

Subclasses typically override this without the extra dataTypes parameter, forwarding their own relevant datatype identifiers.

Parameters :
Name Type Optional Description
entityOrType Entity | EntityConstructor No

An entity instance or entity constructor to inspect.

dataTypes string | string[] No

One or more datatype identifiers to match against.

Returns : string | undefined

The field name of the first matching field, or undefined if none is found.

importIncompleteAdditionalConfigBadge
importIncompleteAdditionalConfigBadge(col: ColumnMapping)
Inherited from DefaultDatatype

Output a label indicating whether the given column mapping needs user configuration for the "additional" config or has a valid, complete "additional" config. returns "undefined" if no user action is required.

Parameters :
Name Type Optional
col ColumnMapping No
Returns : string
Async importMapFunction
importMapFunction(val: any, schemaField: EntitySchemaField, additional?: any, importProcessingContext?: any)
Inherited from DefaultDatatype

The function used to map values from the import data to values in the entities to be created. to share information across processing of multiple columns and rows.

Parameters :
Name Type Optional Description
val any No

The value from an imported cell to be mapped

schemaField EntitySchemaField No

The schema field definition for the target property into which the value is mapped

additional any Yes

config as returned by the configComponent

importProcessingContext any Yes

an object that the datatype can use to store any relevant context across multiple calls to share information across processing of multiple columns and rows.

normalizeSchemaField
normalizeSchemaField(schemaField: EntitySchemaField)
Inherited from DefaultDatatype

Return the (potentially adjusted) schema field for this datatype.

Called when schema fields are set up (e.g. from config), allowing the datatype to normalize or fill in required settings.

Override this in a subclass to enforce constraints (e.g. always setting isArray: true).

Parameters :
Name Type Optional Description
schemaField EntitySchemaField No

The current schema field definition

Returns : EntitySchemaField

The schema field to use (default: unchanged)

Properties

Static Readonly dataType
Type : string
Default value : "schema-embed"
Inherited from DefaultDatatype
Defined in DefaultDatatype:66
Optional embeddedType
Type : SchemaEmbeddedType<EntityType>
Protected Readonly schemaService
Type : unknown
Default value : inject(EntitySchemaService)
editComponent
Type : string
Default value : "EditText"
Inherited from DefaultDatatype
Readonly importAllowsMultiMapping
Type : boolean
Default value : false
Inherited from DefaultDatatype
Defined in DefaultDatatype:80

Whether this datatype allows multiple values to be mapped to the same entity field during import.

Optional importConfigComponent
Type : string
Inherited from DefaultDatatype

A component to be display as a dialog to configure the transformation function (e.g. defining a format or mapping)

Static label
Type : string
Default value : $localize`:datatype-label:any`
Inherited from DefaultDatatype
Defined in DefaultDatatype:89

The human-readable name for this dataType, used in config UIs.

viewComponent
Type : string
Default value : "DisplayText"
Inherited from DefaultDatatype

The default component how this datatype should be displayed in lists and forms.

The edit component has to be a registered component. Components that are registered contain the DynamicComponent decorator

import { DefaultDatatype } from "../../entity/default-datatype/default.datatype";
import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
import { EntitySchemaField } from "../../entity/schema/entity-schema-field";
import {
  EntitySchema,
  SchemaEmbeddedType,
} from "../../entity/schema/entity-schema";
import { inject, Injectable } from "@angular/core";

/**
 * Configuration for the "schema-embed" datatype's `additional` field.
 *
 * Defines the inner schema of the embedded object, using the same format as
 * entity `attributes` config: a map of field names to their schema definitions.
 *
 * @example
 * ```
 * @DatabaseField({
 *   dataType: "schema-embed",
 *   additional: {
 *     "phoneNumber": { dataType: "string" },
 *     "type": { dataType: "string" }
 *   } as SchemaEmbedDatatypeAdditional
 * })
 * phoneNumber: { phoneNumber: string; type: string };
 * ```
 */
export interface SchemaEmbedDatatypeAdditional {
  [fieldId: string]: EntitySchemaField;
}

/**
 * Datatype for the EntitySchemaService transforming values of complex objects recursively.
 *
 * Can be used in two ways:
 * 1. **Config-based** (directly via annotation): Set `dataType: "schema-embed"` and define the inner schema
 *    in `additional` as a {@link SchemaEmbedDatatypeAdditional} map.
 * 2. **Subclass-based** (extending this class): Override `embeddedType` to point to a class
 *    with `@DatabaseField()` annotations.
 *
 * The config in `additional` is merged with the `embeddedType` schema (if present),
 * allowing runtime config to extend or override a class's annotations.
 */
@Injectable()
export class SchemaEmbedDatatype<
  EntityType = any,
  DBType = any,
> extends DefaultDatatype<EntityType, DBType> {
  static override readonly dataType: string = "schema-embed";

  embeddedType?: SchemaEmbeddedType<EntityType>;

  protected readonly schemaService = inject(EntitySchemaService);

  /**
   * Build the effective inner schema from the embedded type's annotations
   * and/or the `additional` config.
   */
  private getEffectiveSchema(schemaField?: EntitySchemaField): EntitySchema {
    // Clone the base schema to avoid mutating the original class schema
    const baseSchema: EntitySchema = new Map(
      this.embeddedType?.schema ?? new Map(),
    );
    const additional: SchemaEmbedDatatypeAdditional =
      schemaField?.additional ?? {};

    // Add schema from additional config, taking precedence over baseSchema if present
    for (const [key, value] of Object.entries(additional)) {
      baseSchema.set(key, { ...value, id: key });
    }

    return baseSchema;
  }

  override transformToDatabaseFormat(
    value: EntityType,
    schemaField?: EntitySchemaField,
  ): DBType {
    const schema = this.getEffectiveSchema(schemaField);
    return this.schemaService.transformEntityToDatabaseFormat(
      value as any,
      schema,
    ) as DBType;
  }

  override transformToObjectFormat(
    value: DBType,
    schemaField?: EntitySchemaField,
  ): EntityType {
    const schema = this.getEffectiveSchema(schemaField);

    const transformedValue =
      this.schemaService.transformDatabaseToEntityFormat<EntityType>(
        value,
        schema,
      );

    if (this.embeddedType) {
      const instance = new this.embeddedType();
      Object.assign(instance, transformedValue);
      return instance;
    }

    return transformedValue;
  }
}

results matching ""

    No results matching ""