[vscode-spring-cli]: project-catalog commands
This commit is contained in:
@@ -51,6 +51,16 @@
|
||||
"command": "vscode-spring-cli.boot.add",
|
||||
"title": "Add to Boot Project",
|
||||
"category": "Spring CLI"
|
||||
},
|
||||
{
|
||||
"command": "vscode-spring-cli.project-catalog.add",
|
||||
"title": "Add Project Catalog",
|
||||
"category": "Spring CLI"
|
||||
},
|
||||
{
|
||||
"command": "vscode-spring-cli.project-catalog.remove",
|
||||
"title": "Remove Project Catalog",
|
||||
"category": "Spring CLI"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -58,7 +68,7 @@
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile",
|
||||
"compile": "rm -rf ./out && tsc -p .",
|
||||
"watch": "rm -rf ./out && tsc -watch -p .",
|
||||
"watch": "npm run compile && tsc -watch -p .",
|
||||
"clean": "rm -fr node_modules out *.vsix package-lock.json",
|
||||
"vsce-package": "vsce package",
|
||||
"vsce-pre-release-package": "vsce package --pre-release"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import * as path from "path";
|
||||
import { BootAddMetadata, BootNewMetadata, ProjectType } from "../cli/types";
|
||||
import { CLI } from "../extension";
|
||||
import { enterText, getTargetPomXml, openDialogForFolder } from "../utils";
|
||||
import { BootAddMetadata, BootNewMetadata, Project } from "./cli-types";
|
||||
import { CLI } from "./extension";
|
||||
import { enterText, getTargetPomXml, openDialogForFolder } from "./utils";
|
||||
import vscode, { QuickPickItem, QuickPickItemKind } from 'vscode';
|
||||
import fs from 'fs'
|
||||
|
||||
const OPEN_IN_NEW_WORKSPACE = "Open";
|
||||
const OPEN_IN_CURRENT_WORKSPACE = "Add to Workspace";
|
||||
|
||||
export async function handleAdd(pom?: vscode.Uri): Promise<void> {
|
||||
export async function handleBootAdd(pom?: vscode.Uri): Promise<void> {
|
||||
const metadata: BootAddMetadata = {};
|
||||
pom = pom || await getTargetPomXml();
|
||||
if (pom) {
|
||||
@@ -19,24 +19,24 @@ export async function handleAdd(pom?: vscode.Uri): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (!metadata.catalogType) {
|
||||
metadata.catalogType = (await vscode.window.showQuickPick(CLI.getProjectTypes().map(mapProjectTypetoQuickPick), { canPickMany: false }))?.label;
|
||||
metadata.catalogType = (await vscode.window.showQuickPick(CLI.projectList().map(mapProjectTypetoQuickPick), { canPickMany: false }))?.label;
|
||||
}
|
||||
return CLI.bootAdd(metadata);
|
||||
}
|
||||
|
||||
export async function handleNew(targetFolder?: string): Promise<void> {
|
||||
export async function handleBootNew(targetFolder?: string): Promise<void> {
|
||||
const metadata: BootNewMetadata = {};
|
||||
|
||||
// Select parent folder
|
||||
metadata.targetFolder = targetFolder || (await openDialogForFolder({title: "Select Parent Folder"})).fsPath;
|
||||
|
||||
// Select project type from the list of available types
|
||||
metadata.catalogType = (await vscode.window.showQuickPick(CLI.getProjectTypes().map(mapProjectTypetoQuickPick), { canPickMany: false }))?.label;
|
||||
metadata.catalogId = (await vscode.window.showQuickPick(CLI.projectList().map(mapProjectTypetoQuickPick), { canPickMany: false }))?.label;
|
||||
|
||||
metadata.name = await enterText({
|
||||
title: "Project Name",
|
||||
prompt: "Enter Project Name",
|
||||
defaultValue: metadata.name || metadata.catalogType,
|
||||
defaultValue: metadata.name || metadata.catalogId,
|
||||
validate: value => {
|
||||
if (!/^[a-z_][a-z0-9_]*(-[a-z_][a-z0-9_]*)*$/.test(value)) {
|
||||
return "Invalid Project Name";
|
||||
@@ -70,7 +70,7 @@ export async function handleNew(targetFolder?: string): Promise<void> {
|
||||
});
|
||||
|
||||
// Create project and open in the workspace or new window
|
||||
if (metadata.name && metadata.catalogType && metadata.targetFolder) {
|
||||
if (metadata.name && metadata.catalogId && metadata.targetFolder) {
|
||||
await CLI.bootNew(metadata);
|
||||
|
||||
// Open project either is the same workspace or new workspace
|
||||
@@ -95,7 +95,7 @@ export async function handleNew(targetFolder?: string): Promise<void> {
|
||||
|
||||
}
|
||||
|
||||
function mapProjectTypetoQuickPick(metadata: ProjectType): QuickPickItem {
|
||||
function mapProjectTypetoQuickPick(metadata: Project): QuickPickItem {
|
||||
return {
|
||||
label: metadata.id,
|
||||
kind: QuickPickItemKind.Default,
|
||||
@@ -1,8 +1,8 @@
|
||||
export interface ProjectType {
|
||||
export interface Project {
|
||||
id: string;
|
||||
url: string;
|
||||
description?: string;
|
||||
url?: string;
|
||||
catalogId: string;
|
||||
catalogId?: string;
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface BootNewMetadata {
|
||||
name?: string;
|
||||
groupId?: string;
|
||||
artifactId?: string;
|
||||
catalogType?: string;
|
||||
catalogId?: string;
|
||||
rootPackage?: string;
|
||||
targetFolder?: string;
|
||||
}
|
||||
@@ -18,4 +18,11 @@ export interface BootNewMetadata {
|
||||
export interface BootAddMetadata {
|
||||
targetFolder?: string;
|
||||
catalogType?: string;
|
||||
}
|
||||
|
||||
export interface ProjectCatalog {
|
||||
name: string;
|
||||
url: string;
|
||||
description?: string;
|
||||
tags?: string[];
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { BootAddMetadata, BootNewMetadata, ProjectType } from "./types";
|
||||
import vscode from "vscode";
|
||||
import { BootAddMetadata, BootNewMetadata, Project, ProjectCatalog } from "./cli-types";
|
||||
import vscode, { TaskScope } from "vscode";
|
||||
|
||||
const SPRING_CLI_TASK_TYPE = 'spring-cli';
|
||||
|
||||
export class Cli {
|
||||
|
||||
getProjectTypes() : ProjectType[] {
|
||||
projectList() : Project[] {
|
||||
return [
|
||||
{
|
||||
id: 'web',
|
||||
@@ -31,6 +31,70 @@ export class Cli {
|
||||
];
|
||||
}
|
||||
|
||||
projectCatalogList(): Thenable<ProjectCatalog[]> {
|
||||
return Promise.resolve([
|
||||
{
|
||||
name: "gs",
|
||||
url: "https://github.com/rd-1-2022/spring-gs-catalog",
|
||||
description: "Getting Started Catalog",
|
||||
tags: ["java-17", "boot-3.1"]
|
||||
},
|
||||
{
|
||||
name: "ai-azure",
|
||||
url: "https://github.com/rd-1-2022/ai-azure-catalog",
|
||||
description: "Azure OpenAI Catalog",
|
||||
tags: ["java-17", "boot-3.1.x", "ai", "azure"]
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
projectCatalogListAvailable(): Thenable<ProjectCatalog[]> {
|
||||
return Promise.resolve([
|
||||
{
|
||||
name: "ai-azure",
|
||||
url: "https://github.com/rd-1-2022/ai-azure-catalog",
|
||||
description: "Azure OpenAI Catalog",
|
||||
tags: ["java-17", "boot-3.1.x", "ai", "azure"]
|
||||
},
|
||||
{
|
||||
name: "dapr",
|
||||
url: "https://github.com/ciberkleid/spring-cli-dapr-catalog",
|
||||
description: "Dapr Catalog",
|
||||
tags: ["java-17", "boot-3.1.x", "dapr"]
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
projectCatalogAdd(catalog: ProjectCatalog): Promise<void> {
|
||||
const args = [
|
||||
"project-catalog",
|
||||
"add",
|
||||
"--name",
|
||||
catalog.name,
|
||||
"--url",
|
||||
catalog.url
|
||||
];
|
||||
if (catalog.description) {
|
||||
args.push("--description");
|
||||
args.push(catalog.description);
|
||||
}
|
||||
if (catalog.tags) {
|
||||
args.push("--tags");
|
||||
args.push(catalog.tags.join(","));
|
||||
}
|
||||
return this.exec("Add Project Catalog", `"${catalog.name}"`, args);
|
||||
}
|
||||
|
||||
projectCatalogRemove(name: string): Promise<void> {
|
||||
const args = [
|
||||
"project-catalog",
|
||||
"remove",
|
||||
"--name",
|
||||
name,
|
||||
];
|
||||
return this.exec("Remove Project Catalog", `"${name}"`, args);
|
||||
}
|
||||
|
||||
bootNew(metadata: BootNewMetadata): Promise<void> {
|
||||
const args = [
|
||||
"boot",
|
||||
@@ -38,7 +102,7 @@ export class Cli {
|
||||
"--name",
|
||||
`"${metadata.name}"`,
|
||||
"--from",
|
||||
`"${metadata.catalogType}"`
|
||||
`"${metadata.catalogId}"`
|
||||
];
|
||||
if (metadata.groupId) {
|
||||
args.push("--group-id")
|
||||
@@ -52,7 +116,7 @@ export class Cli {
|
||||
args.push("--package-name");
|
||||
args.push(`"${metadata.rootPackage}"`);
|
||||
}
|
||||
return this.exec("New Boot Project", `'${metadata.catalogType}'`, metadata.targetFolder, args);
|
||||
return this.exec("New Boot Project", `'${metadata.catalogId}'`, args, metadata.targetFolder);
|
||||
}
|
||||
|
||||
bootAdd(metadata: BootAddMetadata): Promise<void> {
|
||||
@@ -62,10 +126,10 @@ export class Cli {
|
||||
"--from",
|
||||
metadata.catalogType
|
||||
];
|
||||
return this.exec("Add to Boot Project", `'${metadata.catalogType}'`, metadata.targetFolder, args);
|
||||
return this.exec("Add to Boot Project", `'${metadata.catalogType}'`, args, metadata.targetFolder);
|
||||
}
|
||||
|
||||
private async exec(title: string, message: string, cwd: string, args: string[]): Promise<void> {
|
||||
private async exec(title: string, message: string, args: string[], cwd?: string): Promise<void> {
|
||||
|
||||
return vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Window,
|
||||
@@ -77,7 +141,7 @@ export class Cli {
|
||||
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
const process = new vscode.ProcessExecution('spring', args, { cwd });
|
||||
const task = new vscode.Task({ type: SPRING_CLI_TASK_TYPE}, vscode.workspace.getWorkspaceFolder(vscode.Uri.file(cwd)), `${title}: ${message}`, SPRING_CLI_TASK_TYPE, process);
|
||||
const task = new vscode.Task({ type: SPRING_CLI_TASK_TYPE}, cwd ? vscode.workspace.getWorkspaceFolder(vscode.Uri.file(cwd)) : TaskScope.Global, `${title}: ${message}`, SPRING_CLI_TASK_TYPE, process);
|
||||
const taskExecution = await vscode.tasks.executeTask(task);
|
||||
if (cancellation.isCancellationRequested) {
|
||||
reject();
|
||||
@@ -1,16 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
"use strict";
|
||||
import * as vscode from "vscode";
|
||||
import { Cli } from "./cli/core";
|
||||
import { handleAdd, handleNew } from "./boot-project/boot-project";
|
||||
import { Cli } from "./cli";
|
||||
import { handleBootAdd, handleBootNew } from "./boot";
|
||||
import { handleCatalogAdd, handleCatalogRemove } from "./project-catalog";
|
||||
|
||||
export const CLI = new Cli();
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||
vscode.commands.registerCommand('vscode-spring-cli.boot.new', handleNew);
|
||||
vscode.commands.registerCommand('vscode-spring-cli.boot.add', handleAdd);
|
||||
vscode.commands.registerCommand('vscode-spring-cli.boot.new', handleBootNew);
|
||||
vscode.commands.registerCommand('vscode-spring-cli.boot.add', handleBootAdd);
|
||||
vscode.commands.registerCommand('vscode-spring-cli.project-catalog.add', handleCatalogAdd);
|
||||
vscode.commands.registerCommand('vscode-spring-cli.project-catalog.remove', handleCatalogRemove);
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
|
||||
94
vscode-extensions/vscode-spring-cli/src/project-catalog.ts
Normal file
94
vscode-extensions/vscode-spring-cli/src/project-catalog.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { ProjectCatalog } from "./cli-types";
|
||||
import { CLI } from "./extension";
|
||||
import { window, QuickPickItem, Uri } from "vscode";
|
||||
import { enterText } from "./utils";
|
||||
|
||||
interface ProjectCatalogQuickPick extends QuickPickItem {
|
||||
projectCatalog: ProjectCatalog;
|
||||
}
|
||||
|
||||
const CUSTOM_CATALOG: ProjectCatalog = {
|
||||
name: "<Enter Custom Catalog>",
|
||||
url: "Provide URL",
|
||||
description: "Provide NAME, URL and optionally DESCRIPTION and TAGS"
|
||||
}
|
||||
|
||||
export async function handleCatalogAdd() {
|
||||
|
||||
let currentCatalogNames = [];
|
||||
|
||||
// Select from available project catalog - currentle added project ctalogs
|
||||
let catalog = await pickCatalog(async () => {
|
||||
const [available, current] = await Promise.all([CLI.projectCatalogListAvailable(), CLI.projectCatalogList()]);
|
||||
const currentCatalogNames = current.map(c => c.name);
|
||||
return [CUSTOM_CATALOG, ...available.filter(a => !currentCatalogNames.includes(a.name))];
|
||||
});
|
||||
|
||||
if (catalog === CUSTOM_CATALOG) {
|
||||
// No available catalog selected enter the catalog manually
|
||||
const name = await enterText({
|
||||
title: "Name",
|
||||
prompt: "Enter Name:",
|
||||
validate: v => {
|
||||
if (!/^\S+$/.test(v)) {
|
||||
return "Invalid Project Catalog Name";
|
||||
}
|
||||
if (currentCatalogNames.includes(v)) {
|
||||
return "Name alreasy exists"
|
||||
}
|
||||
}
|
||||
});
|
||||
const url = await enterText({
|
||||
title: "URL",
|
||||
prompt: "Enter URL:",
|
||||
placeholder: "https://github.com/my-org/my-project-catalog",
|
||||
validate: v => /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)?/gi.test(v) ? "" : "Invalid URL value"
|
||||
});
|
||||
const description = await enterText({
|
||||
title: "Description",
|
||||
prompt: "Enter Description:"
|
||||
});
|
||||
const tags = (await enterText({
|
||||
title: "Tags",
|
||||
prompt: "Enter Tags as strings separated by spaces and/or commas",
|
||||
placeholder: "java, spring, eureka, config"
|
||||
})).split(/(,)?\s+/);
|
||||
catalog = {name, url, description, tags};
|
||||
}
|
||||
|
||||
if (catalog) {
|
||||
return CLI.projectCatalogAdd(catalog);
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleCatalogRemove() {
|
||||
const catalog = await pickCatalog(CLI.projectCatalogList);
|
||||
if (catalog) {
|
||||
return CLI.projectCatalogRemove(catalog.name);
|
||||
}
|
||||
}
|
||||
|
||||
async function pickCatalog(fetch: () => Thenable<ProjectCatalog[]>): Promise<ProjectCatalog | undefined> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const quickPick = window.createQuickPick<ProjectCatalogQuickPick>();
|
||||
quickPick.busy = true;
|
||||
quickPick.title = "Loading Project Catalogs...";
|
||||
quickPick.canSelectMany = false;
|
||||
quickPick.show();
|
||||
const catalogs = await fetch();
|
||||
|
||||
quickPick.items = catalogs.map(c => ({
|
||||
label: c.name,
|
||||
description: c.description,
|
||||
details: c.tags ? c.tags.join(", ") : undefined,
|
||||
projectCatalog: c
|
||||
}));
|
||||
quickPick.title = "Select Project Catalog";
|
||||
quickPick.busy = false;
|
||||
|
||||
quickPick.onDidAccept(() => {
|
||||
resolve(quickPick.selectedItems.length ? quickPick.selectedItems[0].projectCatalog : undefined);
|
||||
quickPick.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user