UNPKG

@autorest/openapi-to-typespec

Version:

Autorest plugin to scaffold a Typespec definition from an OpenAPI document

104 lines (88 loc) 3.84 kB
import { isConstantSchema } from "../utils/schemas"; import { ManagementGroupPath, ManagementGroupScopePrefix, ProvidersSegment, ResourceGroupPath, ResourceGroupScopePrefix, SubscriptionPath, SubscriptionScopePrefix, TenantPath, TenantScopePrefix, } from "./constants"; import { OperationSet } from "./operation-set"; export function getResourceType(path: string): string { const index = path.lastIndexOf(ProvidersSegment); if (index < 0 || path.substring(index + ProvidersSegment.length).includes("/") === false) { const pathToLower = path.toLowerCase(); if (pathToLower.startsWith(ResourceGroupScopePrefix.toLowerCase())) return "Microsoft.Resources/resourceGroups"; if (pathToLower.startsWith(SubscriptionScopePrefix.toLowerCase())) return "Microsoft.Resources/subscriptions"; if (pathToLower.startsWith(TenantScopePrefix.toLowerCase())) return "Microsoft.Resources/tenants"; throw `Path ${path} doesn't have resource type`; } return path .substring(index + ProvidersSegment.length) .split("/") .reduce((result, current, index) => { if (index === 0 || index % 2 === 1) return result === "" ? current : `${result}/${current}`; else return result; }, ""); } export function getResourceKey(path: string): string { const segments = path.split("/"); return segments[segments.length - 1].replace(/^\{(\w+)\}$/, "$1"); } export function getResourceKeySegment(path: string): string { const segments = path.split("/"); return segments[segments.length - 2]; } export function getScopePath(path: string): string { const pathToLower = path.toLowerCase(); const index = pathToLower.lastIndexOf(ProvidersSegment); if (pathToLower.startsWith(ManagementGroupScopePrefix.toLowerCase())) return ManagementGroupPath; if (index >= 0) return path.slice(0, index); if (pathToLower.startsWith(ResourceGroupScopePrefix.toLowerCase())) return ResourceGroupPath; if (pathToLower.startsWith(SubscriptionScopePrefix.toLowerCase())) return SubscriptionPath; if (pathToLower.startsWith(TenantScopePrefix.toLowerCase())) return TenantPath; return path; } export function isScopedSegment(path: string): boolean { const pattern = /^\/?\{\w+\}\/?$/; return path.match(pattern) !== null; } export function isScopedPath(path: string): boolean { return isScopedSegment(getScopePath(path)); } export function isSingleton(set: OperationSet): boolean { const lastSegment = getLastSegment(set.RequestPath); if (!isVariable(lastSegment)) return true; const resourceKey = lastSegment.replace(/^\{(\w+)\}$/, "$1"); const resourceKeyParameter = set.Operations[0].parameters?.find( (p) => p.language.default.name === resourceKey || p.language.default.serializedName === resourceKey, ); if (resourceKeyParameter === undefined) throw `Cannot find parameter ${resourceKey} in operation ${set.Operations[0].operationId}`; return isConstantSchema(resourceKeyParameter?.schema); } export function pathIncludes(path1: string, path2: string): boolean { const lowerPath1 = path1.toLowerCase(); const lowerPath2 = path2.toLowerCase(); const segments1 = lowerPath1.split("/"); const segments2 = lowerPath2.split("/"); if (segments2.length > segments1.length) return false; // If the segment is a variable, then different variable names are still equivalent for (let index = 0; index < segments2.length; ++index) { if (isVariable(segments1[index])) { if (!isVariable(segments2[index])) return false; } else if (segments1[index] !== segments2[index]) return false; } return true; } // {variableName} function isVariable(segment: string): boolean { return segment.match(/^\{\w+\}$/) !== null; } function getLastSegment(path: string): string { const segments = path.split("/"); return segments[segments.length - 1]; }