func collectExtensionMetadata()

in cli/azd/extensions/microsoft.azd.extensions/internal/cmd/init.go [390:552]


func collectExtensionMetadata(ctx context.Context, azdClient *azdext.AzdClient) (*models.ExtensionSchema, error) {
	fmt.Println()
	fmt.Println("Please provide the following information to create your extension.")
	fmt.Printf("Values can be changed later in the %s file.\n", output.WithHighLightFormat("extension.yaml"))
	fmt.Println()

	idPrompt, err := azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{
		Options: &azdext.PromptOptions{
			Message:         "Enter a unique identifier for your extension",
			Placeholder:     "company.extension",
			RequiredMessage: "Extension ID is required",
			Required:        true,
			Hint: "Extension ID is used to identify your extension in the AZD ecosystem. " +
				"It should be unique and follow the format 'company.extension'.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for extension ID: %w", err)
	}

	displayNamePrompt, err := azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{
		Options: &azdext.PromptOptions{
			Message:         "Enter a display name for your extension",
			Placeholder:     "My Extension",
			RequiredMessage: "Display name is required",
			Required:        true,
			HelpMessage: "Display name is used to show the extension name in the AZD CLI. " +
				"It should be user-friendly and descriptive.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for display name: %w", err)
	}

	descriptionPrompt, err := azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{
		Options: &azdext.PromptOptions{
			Message:         "Enter a description for your extension",
			Placeholder:     "A brief description of your extension",
			RequiredMessage: "Description is required",
			Required:        true,
			HelpMessage: "Description is used to provide more information about your extension. " +
				"It should be concise and informative.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for description: %w", err)
	}

	tagsPrompt, err := azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{
		Options: &azdext.PromptOptions{
			Message:         "Enter tags for your extension (comma-separated)",
			Placeholder:     "tag1, tag2",
			RequiredMessage: "Tags are required",
			Required:        true,
			HelpMessage: "Tags are used to categorize your extension. " +
				"You can enter multiple tags separated by commas.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for tags: %w", err)
	}

	namespacePrompt, err := azdClient.Prompt().Prompt(ctx, &azdext.PromptRequest{
		Options: &azdext.PromptOptions{
			Message:         "Enter a namespace for your extension",
			RequiredMessage: "Namespace is required",
			Required:        true,
			HelpMessage: "Namespace is used to group custom commands into a single command " +
				"group used for executing the extension.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for namespace: %w", err)
	}

	capabilitiesPrompt, err := azdClient.Prompt().MultiSelect(ctx, &azdext.MultiSelectRequest{
		Options: &azdext.MultiSelectOptions{
			Message: "Select capabilities for your extension",
			Choices: []*azdext.MultiSelectChoice{
				{
					Label: "Custom Commands",
					Value: "custom-commands",
				},
				{
					Label: "Lifecycle Events",
					Value: "lifecycle-events",
				},
			},
			EnableFiltering: internal.ToPtr(false),
			DisplayNumbers:  internal.ToPtr(false),
			HelpMessage: "Capabilities define the features and functionalities of your extension. " +
				"You can select multiple capabilities.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for capabilities: %w", err)
	}

	languageChoices := []*azdext.SelectChoice{
		{
			Label: "Go",
			Value: "go",
		},
		{
			Label: "C#",
			Value: "dotnet",
		},
		{
			Label: "JavaScript",
			Value: "javascript",
		},
		{
			Label: "Python",
			Value: "python",
		},
	}

	programmingLanguagePrompt, err := azdClient.Prompt().Select(ctx, &azdext.SelectRequest{
		Options: &azdext.SelectOptions{
			Message:         "Select a programming language for your extension",
			Choices:         languageChoices,
			EnableFiltering: internal.ToPtr(false),
			DisplayNumbers:  internal.ToPtr(false),
			HelpMessage: "Programming language is used to define the language in which your extension is written. " +
				"You can select one programming language.",
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to prompt for programming language: %w", err)
	}

	capabilities := make([]extensions.CapabilityType, len(capabilitiesPrompt.Values))
	for i, capability := range capabilitiesPrompt.Values {
		capabilities[i] = extensions.CapabilityType(capability.Value)
	}

	tags := []string{}
	strings.Split(tagsPrompt.Value, ",")
	for _, tag := range tags {
		tag = strings.TrimSpace(tag)
		if tag != "" {
			tags = append(tags, tag)
		}
	}

	absExtensionPath, err := filepath.Abs(idPrompt.Value)
	if err != nil {
		return nil, fmt.Errorf("failed to get absolute path for extension directory: %w", err)
	}

	return &models.ExtensionSchema{
		Id:           idPrompt.Value,
		DisplayName:  displayNamePrompt.Value,
		Description:  descriptionPrompt.Value,
		Namespace:    namespacePrompt.Value,
		Capabilities: capabilities,
		Language:     languageChoices[*programmingLanguagePrompt.Value].Value,
		Tags:         tags,
		Usage:        fmt.Sprintf("azd %s <command> [options]", namespacePrompt.Value),
		Version:      "0.0.1",
		Path:         absExtensionPath,
	}, nil
}