UNPKG

@azure-tools/typespec-azure-resource-manager

Version:

TypeSpec Azure Resource Manager library

176 lines 7.12 kB
import { isTypeSpecValueTypeOf, } from "@typespec/compiler"; import { $useDependency, getVersion } from "@typespec/versioning"; import { ArmCommonTypesDefaultVersion, getCommonTypeRecords, } from "./commontypes.private.decorators.js"; import { createDiagnostic } from "./lib.js"; import { ArmStateKeys } from "./state.js"; export function getArmCommonTypesVersions(program) { // There is a single instance of ArmCommonTypeVersions stored inside of the // state map so just pull the first (only) item from the map. const map = program.stateMap(ArmStateKeys.armCommonTypesVersions); return map?.values().next().value; } export function getArmCommonTypesVersionFromString(program, entity, versionStr) { const commonTypeVersionEnum = program.resolveTypeReference(`Azure.ResourceManager.CommonTypes.Versions.${versionStr}`)[0]; if (commonTypeVersionEnum === undefined) { return [ undefined, [ createDiagnostic({ code: "arm-common-types-invalid-version", target: entity, format: { versionString: versionStr, supportedVersions: [...getArmCommonTypesVersions(program).type.members.keys()].join(", "), }, }), ], ]; } else { return [commonTypeVersionEnum, []]; } } /** * Check if a given model or model property is an ARM common type. * @param {Type} entity - The entity to be checked. * @return {boolean} - A boolean value indicating whether an entity is an ARM common type. */ export function isArmCommonType(entity) { const commonDecorators = ["$armCommonDefinition", "$armCommonParameter"]; if (isTypeSpecValueTypeOf(entity, ["Model", "ModelProperty", "Enum", "Union"])) { return commonDecorators.some((commonDecorator) => entity.decorators.some((d) => d.decorator.name === commonDecorator)); } return false; } /** * `@armCommonTypesVersion` sets the ARM common-types version used by the service. * @param {DecoratorContext} context DecoratorContext object * @param {type} entity Target of the decorator. Must be `Namespace` or `EnumMember` type */ export const $armCommonTypesVersion = (context, entity, version) => { // try convert string to EnumMember let versionEnum; if (typeof version === "string") { const [foundEnumMember, diagnostics] = getArmCommonTypesVersionFromString(context.program, entity, version); if (!foundEnumMember) { context.program.reportDiagnostics(diagnostics); return; } versionEnum = foundEnumMember; } else { versionEnum = version.value; } context.program.stateMap(ArmStateKeys.armCommonTypesVersion).set(entity, versionEnum.name); if (entity.kind === "Namespace") { const versioned = entity.decorators.find((x) => x.definition?.name === "@versioned"); // If it is versioned namespace, we will skip adding @useDependency to namespace if (versioned) { return; } } // Add @useDependency on version enum members or on unversioned namespace context.call($useDependency, entity, versionEnum); }; /** * Returns the ARM common-types version used by the service. * @param {Program} program Program object * @param {type} entity Target of the decorator. Must be `Namespace` or `EnumMember` type */ export function getArmCommonTypesVersion(program, entity) { return program.stateMap(ArmStateKeys.armCommonTypesVersion).get(entity); } /** * Get the common-types.json ref for the given common type. */ export function getArmCommonTypeOpenAPIRef(program, entity, params) { const [record, diagnostics] = findArmCommonTypeRecord(program, entity, params); if (record) { return record.basePath.endsWith(".json") ? `${record.basePath}#/${record.kind}/${record.name}` : `${record.basePath}/${record.version}/${record.referenceFile}#/${record.kind}/${record.name}`; } else { program.reportDiagnostics(diagnostics); return undefined; } } export function findArmCommonTypeRecord(program, entity, params) { const { records, defaultKey } = getCommonTypeRecords(program, entity); const commonTypes = resolveCommonTypesVersion(program, params); const selectedVersion = commonTypes.selectedVersion; // Find closest version that matches the dependency (based on version enum order) let record; if (selectedVersion) { let foundSelectedVersion = false; for (const version of commonTypes.allVersions) { if (!foundSelectedVersion) { if (selectedVersion !== version.name) { continue; } foundSelectedVersion = true; } const maybeRecord = records[version.name]; if (maybeRecord) { record = maybeRecord; break; } } } if (record === undefined) { // If no version was found, use the default version record = records[defaultKey ?? ArmCommonTypesDefaultVersion]; } // If after resolve version AND unable to load default version, report diagnostic if (record === undefined) { return [ undefined, [ createDiagnostic({ code: "arm-common-types-incompatible-version", target: entity, format: { selectedVersion: selectedVersion ?? ArmCommonTypesDefaultVersion, supportedVersions: Object.keys(records).join(", "), }, }), ], ]; } else { return [record, []]; } } /** * Resolve which version of the Common Types to use. */ function resolveCommonTypesVersion(program, params) { let selectedVersion; const { allVersions } = getArmCommonTypesVersions(program) ?? {}; const versionMap = getVersion(program, params.service.type); // If the service is versioned, extract the common-types version from the // service version enum if (params.version && versionMap) { const versionEnumMember = versionMap .getVersions() .find((x) => x.value === params.version)?.enumMember; if (versionEnumMember) { selectedVersion = getArmCommonTypesVersion(program, versionEnumMember); } } // Extract the version from the service namespace instead if (selectedVersion === undefined) { selectedVersion = getArmCommonTypesVersion(program, params.service.type); } return { selectedVersion, allVersions: allVersions ?? [], }; } export const $externalTypeRef = (context, entity, jsonRef) => { context.program.stateMap(ArmStateKeys.externalTypeRef).set(entity, jsonRef); }; export function getExternalTypeRef(program, entity) { return program.stateMap(ArmStateKeys.externalTypeRef).get(entity); } //# sourceMappingURL=common-types.js.map