Skip to main content
Glama
addDefaultProps.ts7.58 kB
import _ from "lodash"; import { ExpandedPkgSpec } from "../../../spec/pkgs.ts"; import { addPropSuggestSource, bfsPropTree, createObjectProp, createScalarProp, ExpandedPropSpec, findPropByName, toPropPath, } from "../../../spec/props.ts"; import { AzureSchema } from "../schema.ts"; export interface PropUsageMap { createOnly: string[]; updatable: string[]; // Maps discriminator property -> subtype definition name -> enum value // e.g., { "kind": { "AzurePowerShellScript": "AzurePowerShell", "AzureCliScript": "AzureCLI" } } discriminators: Record<string, Record<string, string>> | undefined; // Maps discriminator property -> subtype definition name -> list of properties defined by that subtype // e.g., { "kind": { "AzurePowerShellScript": ["properties"], "AzureCliScript": ["properties"] } } discriminatorSubtypeProps: | Record<string, Record<string, string[]>> | undefined; } export function addDefaultProps( specs: ExpandedPkgSpec[], ): ExpandedPkgSpec[] { const newSpecs = [] as ExpandedPkgSpec[]; for (const spec of specs) { const [schema] = spec.schemas; const [schemaVariant] = schema.variants; const { domain } = schemaVariant; // Add suggestions to resourceGroupName // TODO if resourceGroupName prop exists with a different name, support that const resourceGroupNameProp = findPropByName(domain, "resourceGroupName"); if (resourceGroupNameProp) { resourceGroupNameProp.data.documentation ??= "The name of the resource group where this resource will be created"; resourceGroupNameProp.data.docLink ??= "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal"; resourceGroupNameProp.metadata.createOnly = true; addPropSuggestSource(resourceGroupNameProp, { schema: "Microsoft.Resources/resourceGroups", prop: "/domain/name", }); } // Add suggestions to subscriptionId const subscriptionIdProp = findPropByName(domain, "subscriptionId"); if (subscriptionIdProp) { subscriptionIdProp.data.documentation ??= "The Azure subscription ID where this resource will be created"; subscriptionIdProp.data.docLink ??= "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-subscription"; subscriptionIdProp.metadata.createOnly = true; addPropSuggestSource(subscriptionIdProp, { schema: "Microsoft.Resources/subscriptions", prop: "/domain/subscriptionId", }); } // Extra prop const extraProp = createObjectProp( "extra", domain.metadata.propPath, undefined, true, ); extraProp.data.hidden = true; // Create AzureResourceType prop // TODO remove this; kept because a few functions reference it right now { const resourceTypeProp = createScalarProp( "AzureResourceType", "string", extraProp.metadata.propPath, false, ); resourceTypeProp.data.defaultValue = schema.name; resourceTypeProp.data.hidden = true; extraProp.entries.push(resourceTypeProp); } // Create AzureResourceType prop { const resourceIdProp = createScalarProp( "resourceId", "string", extraProp.metadata.propPath, false, ); const { resourceId } = schemaVariant.superSchema as AzureSchema; resourceIdProp.data.defaultValue = resourceId; resourceIdProp.data.hidden = true; extraProp.entries.push(resourceIdProp); } // Create apiVersion prop { const apiVersionProp = createScalarProp( "apiVersion", "string", extraProp.metadata.propPath, false, ); const azureSchema = schemaVariant.superSchema as AzureSchema; apiVersionProp.data.defaultValue = azureSchema?.apiVersion || "2023-01-01"; extraProp.entries.push(apiVersionProp); } // Create PropUsageMap { const propUsageMapProp = createScalarProp( "PropUsageMap", "string", extraProp.metadata.propPath, false, ); const propUsageMap: PropUsageMap = { createOnly: [], updatable: [], discriminators: {}, discriminatorSubtypeProps: {}, }; const azureSchema = schemaVariant.superSchema as AzureSchema; propUsageMap.discriminators = azureSchema.discriminators; // Derive discriminatorSubtypeProps by walking the domain schema structure const discriminatorSubtypePropsMap: Record< string, Record<string, string[]> > = {}; if (azureSchema.discriminators) { for ( const [discriminatorProp, subtypeMap] of Object.entries( azureSchema.discriminators, ) ) { const domainProp = findPropByName(domain, discriminatorProp); if (domainProp && domainProp.kind === "object") { discriminatorSubtypePropsMap[discriminatorProp] = {}; for (const subtypeName of Object.keys(subtypeMap)) { const subtypeProp = domainProp.entries.find((e) => e.name === subtypeName ); if (subtypeProp && subtypeProp.kind === "object") { const allPropNames: string[] = []; bfsPropTree(subtypeProp.entries, (prop) => { allPropNames.push(prop.name); }); discriminatorSubtypePropsMap[discriminatorProp][subtypeName] = allPropNames; } } } } } propUsageMap.discriminatorSubtypeProps = discriminatorSubtypePropsMap; const queue: ExpandedPropSpec[] = _.cloneDeep(domain.entries); while (queue.length > 0) { const prop = queue.pop(); if (!prop) break; const fullPath = toPropPath(prop.metadata.propPath); if (prop.metadata.createOnly) { propUsageMap.createOnly.push(fullPath); } else if (!prop.metadata.readOnly) { propUsageMap.updatable.push(fullPath); } if (prop.kind === "object") { prop.entries.forEach((p) => queue.unshift(p)); } } propUsageMapProp.data.defaultValue = JSON.stringify(propUsageMap); propUsageMapProp.data.hidden = true; extraProp.entries.push(propUsageMapProp); } // Add Azure credential to secrets { const credProp = createScalarProp( "Microsoft Credential", "string", extraProp.metadata.propPath, true, ); credProp.data.widgetKind = "Secret"; credProp.data.widgetOptions = [ { label: "secretKind", value: "Microsoft Credential", }, ]; if (schemaVariant.secrets.kind !== "object") { console.log( `Could not generate default props for ${spec.name}: secrets is not object`, ); continue; } addPropSuggestSource(credProp, { schema: "Microsoft Credential", prop: "/secrets/Microsoft Credential", }); schemaVariant.secrets.entries.push(credProp); } // location prop suggest source { const locationProp = findPropByName(domain, "location"); if (locationProp) { addPropSuggestSource(locationProp, { schema: "Microsoft.Resources/location", prop: "/domain/name", }); } } domain.entries.push(extraProp); newSpecs.push(spec); } return newSpecs; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server