function convertModel2CMDObjectDiscriminator()

in src/typespec-aaz/src/convertor.ts [984:1090]


function convertModel2CMDObjectDiscriminator(
  context: AAZSchemaEmitterContext,
  model: Model,
  discriminatorInfo: DiscriminatorInfo,
): CMDObjectSchemaDiscriminator | undefined {
  const object: CMDObjectSchemaDiscriminator = {
    property: discriminatorInfo.propertyName,
    value: discriminatorInfo.value,
  };

  const payloadModel = context.metadateInfo.getEffectivePayloadType(model, context.visibility) as Model;

  const properties: Record<string, CMDSchema> = {};
  const discriminator = getDiscriminator(context.program, payloadModel);

  for (const prop of payloadModel.properties.values()) {
    if (isNeverType(prop.type)) {
      // If the property has a type of 'never', don't include it in the schema
      continue;
    }
    if (!context.metadateInfo.isPayloadProperty(prop, context.visibility)) {
      continue;
    }

    const jsonName = getJsonName(context, prop);
    if (jsonName === discriminatorInfo.propertyName) {
      // if this property is a discriminator property, remove it as autorest
      continue;
    }
    let schema = convert2CMDSchema(
      {
        ...context,
        supportClsSchema: true,
      },
      prop,
      jsonName,
    );

    if (schema) {
      if (isReadonlyProperty(context.program, prop)) {
        schema.readOnly = true;
      }
      if (!context.metadateInfo.isOptional(prop, context.visibility) || prop.name === discriminator?.propertyName) {
        schema.required = true;
      }
      if (shouldClientFlatten(context, prop)) {
        if (schema.type === "object") {
          schema = {
            ...schema,
            clientFlatten: true,
          } as CMDObjectSchema;
        } else if (schema.type instanceof ClsType) {
          schema = {
            ...schema,
            clientFlatten: true,
          } as CMDClsSchema;
        }
      }
      properties[schema.name] = schema;
    }
  }

  // TODO: handle discriminator.propertyName === discriminatorInfo.propertyName
  if (discriminator && discriminator.propertyName !== discriminatorInfo.propertyName) {
    const { propertyName } = discriminator;
    console.assert(object.discriminators === undefined, "Discriminator should be undefined.");
    // Push discriminator into base type, but only if it is not already there
    if (!payloadModel.properties.get(propertyName)) {
      const discriminatorProperty: CMDStringSchema = {
        name: propertyName,
        type: "string",
        required: true,
        description: `Discriminator property for ${payloadModel.name}.`,
      };
      properties[propertyName] = discriminatorProperty;
    }

    const discProperty = properties[propertyName] as CMDStringSchema;

    const derivedModels = payloadModel.derivedModels.filter(includeDerivedModel);
    for (const child of derivedModels) {
      const childDiscriminatorValue = getDiscriminatorInfo(context, child);
      if (childDiscriminatorValue) {
        const disc = convertModel2CMDObjectDiscriminator(context, child, childDiscriminatorValue);
        if (disc) {
          object.discriminators ??= [];
          object.discriminators.push(disc);
          discProperty.enum ??= {
            items: [],
          };
          discProperty.enum.items.push({
            value: childDiscriminatorValue.value,
          });
        }
      }
    }
  }

  if (Object.keys(properties).length > 0) {
    object.props = Object.values(properties).filter((prop) => !isEmptiedSchema(prop));
    if (object.props.length === 0) {
      object.props = undefined;
    }
  }

  return object;
}