Skip to content

Commit 1e35324

Browse files
author
Vandita Patidar
committed
Building Quick Pick structure
1 parent b279b41 commit 1e35324

File tree

6 files changed

+351
-184
lines changed

6 files changed

+351
-184
lines changed

aws-toolkit-vscode.code-workspace

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,50 @@
11
{
2-
"folders": [
3-
{
4-
"path": "."
5-
},
6-
{
7-
"path": "packages/toolkit"
8-
},
9-
{
10-
"path": "packages/core"
11-
},
12-
{
13-
"path": "packages/amazonq"
14-
}
15-
],
16-
"settings": {
17-
"typescript.tsdk": "node_modules/typescript/lib"
18-
}
19-
}
2+
"folders": [
3+
{
4+
"path": ".",
5+
},
6+
{
7+
"path": "packages/toolkit",
8+
},
9+
{
10+
"path": "packages/core",
11+
},
12+
{
13+
"path": "packages/amazonq",
14+
},
15+
],
16+
"settings": {
17+
"typescript.tsdk": "node_modules/typescript/lib",
18+
},
19+
"launch": {
20+
"configurations": [
21+
{
22+
"type": "aws-sam",
23+
"request": "direct-invoke",
24+
"name": "core:src/awsService/appBuilder/serverlessLand.getProjectUri (nodejs14.x)",
25+
"invokeTarget": {
26+
"target": "code",
27+
"projectRoot": "/Users/vanditap/src/github.com/aws-toolkit-vscode/packages/core",
28+
"lambdaHandler": "src/awsService/appBuilder/serverlessLand.getProjectUri",
29+
},
30+
"lambda": {
31+
"runtime": "nodejs14.x",
32+
"payload": {},
33+
"environmentVariables": {},
34+
},
35+
},
36+
{
37+
"name": "Test Lint",
38+
"type": "node",
39+
"request": "launch",
40+
"program": "${workspaceFolder}/scripts/lint/testLint.ts",
41+
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
42+
"preLaunchTask": "build",
43+
"presentation": {
44+
"group": "7_TestLint",
45+
"order": 1,
46+
},
47+
},
48+
],
49+
},
50+
}

packages/core/scripts/build/copyFiles.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const tasks: CopyTask[] = [
4444
target: path.join('../../node_modules', 'aws-ssm-document-language-service', 'dist', 'server.js.map'),
4545
destination: path.join('src', 'ssmDocument', 'ssm', 'server.js.map'),
4646
},
47+
{
48+
target: path.join('../core', 'src', 'awsService', 'appBuilder', 'serverlessLand', 'metadata.json'),
49+
destination: path.join('src', 'awsService', 'appBuilder', 'serverlessLand', 'metadata.json'),
50+
},
4751
]
4852

4953
function copy(task: CopyTask): void {

packages/core/src/awsService/appBuilder/serverlessLand/main.ts

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@
66
import * as nls from 'vscode-nls'
77
const localize = nls.loadMessageBundle()
88
import * as path from 'path'
9+
import * as vscode from 'vscode'
910
import { getTelemetryReason, getTelemetryResult } from '../../../shared/errors'
1011
import { getLogger } from '../../../shared/logger/logger'
1112
import globals from '../../../shared/extensionGlobals'
1213
import { checklogs } from '../../../shared/localizedText'
1314
import { Result, telemetry } from '../../../shared/telemetry/telemetry'
14-
import { CreateServerlessLandWizard } from './wizard'
15+
import { CreateServerlessLandWizardForm, CreateServerlessLandWizard } from './wizard'
1516
import { ExtContext } from '../../../shared/extensions'
1617
import { addFolderToWorkspace } from '../../../shared/utilities/workspaceUtils'
18+
import { ToolkitError } from '../../../shared/errors'
19+
import { fs } from '../../../shared/fs/fs'
20+
import { getPattern } from '../../../shared/utilities/downloadPatterns'
1721

1822
export const readmeFile: string = 'README.md'
23+
const serverlessLandOwner = 'aws-samples'
24+
const serverlessLandRepo = 'serverless-patterns'
1925

2026
/**
2127
* Creates a new Serverless Land project using the provided extension context
@@ -31,30 +37,24 @@ export const readmeFile: string = 'README.md'
3137
* 6. Handles errors and emits telemetry
3238
*/
3339
export async function createNewServerlessLandProject(extContext: ExtContext): Promise<void> {
34-
const awsContext = extContext.awsContext
3540
let createResult: Result = 'Succeeded'
3641
let reason: string | undefined
3742

3843
try {
39-
const credentials = await awsContext.getCredentials()
40-
const defaultRegion = awsContext.getCredentialDefaultRegion()
41-
4244
// Launch the project creation wizard
43-
const config = await new CreateServerlessLandWizard({
44-
credentials,
45-
defaultRegion,
46-
}).run()
45+
const config = await launchProjectCreationWizard(extContext)
4746
if (!config) {
4847
createResult = 'Cancelled'
4948
reason = 'userCancelled'
5049
return
5150
}
5251

53-
// Add the project folder to the workspace
52+
await downloadPatternCode(config)
53+
await openReadmeFile(config)
5454
await addFolderToWorkspace(
5555
{
56-
uri: config.location,
57-
name: path.basename(config.location.fsPath),
56+
uri: vscode.Uri.joinPath(config.location, config.name),
57+
name: path.basename(config.name),
5858
},
5959
true
6060
)
@@ -80,3 +80,66 @@ export async function createNewServerlessLandProject(extContext: ExtContext): Pr
8080
})
8181
}
8282
}
83+
84+
async function launchProjectCreationWizard(
85+
extContext: ExtContext
86+
): Promise<CreateServerlessLandWizardForm | undefined> {
87+
const awsContext = extContext.awsContext
88+
const credentials = await awsContext.getCredentials()
89+
const defaultRegion = awsContext.getCredentialDefaultRegion()
90+
91+
return new CreateServerlessLandWizard({
92+
credentials,
93+
defaultRegion,
94+
}).run()
95+
}
96+
97+
async function downloadPatternCode(config: CreateServerlessLandWizardForm): Promise<void> {
98+
const assetName = config.assetName + '.zip'
99+
const location = vscode.Uri.joinPath(config.location, config.name)
100+
try {
101+
await getPattern(serverlessLandOwner, serverlessLandRepo, assetName, location, true)
102+
} catch (error) {
103+
if (error instanceof ToolkitError) {
104+
throw error
105+
}
106+
throw new ToolkitError(`Failed to download pattern: ${error}`)
107+
}
108+
}
109+
110+
async function openReadmeFile(config: CreateServerlessLandWizardForm): Promise<void> {
111+
try {
112+
const readmeUri = await getProjectUri(config, readmeFile)
113+
if (!readmeUri) {
114+
getLogger().warn('README.md file not found in the project directory')
115+
return
116+
}
117+
118+
await vscode.commands.executeCommand('workbench.action.focusFirstEditorGroup')
119+
await vscode.window.showTextDocument(readmeUri)
120+
} catch (err) {
121+
getLogger().error(`Error in openReadmeFile: ${err}`)
122+
throw new ToolkitError('Error processing README file')
123+
}
124+
}
125+
126+
async function getProjectUri(
127+
config: Pick<CreateServerlessLandWizardForm, 'location' | 'name'>,
128+
file: string
129+
): Promise<vscode.Uri | undefined> {
130+
if (!file) {
131+
throw Error('expected "file" parameter to have at least one item')
132+
}
133+
const cfnTemplatePath = path.resolve(config.location.fsPath, config.name, file)
134+
if (await fs.exists(cfnTemplatePath)) {
135+
return vscode.Uri.file(cfnTemplatePath)
136+
}
137+
void vscode.window.showWarningMessage(
138+
localize(
139+
'AWS.serverlessLand.initWizard.source.error.notFound',
140+
'Project created successfully, but {0} file not found: {1}',
141+
file!,
142+
cfnTemplatePath!
143+
)
144+
)
145+
}

packages/core/src/awsService/appBuilder/serverlessLand/metadata.json

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,52 @@
33
"s3-lambda-resizing-sam": {
44
"name": "Resizing image",
55
"description": "Lambda, S3 • Python, Javascript, Java, .NET • SAM",
6-
"runtimes": [
6+
"implementation": [
77
{
8-
"id": "python",
9-
"name": "Python"
8+
"iac": "sam",
9+
"runtime": "python",
10+
"assetName": "s3-lambda-resizing-python"
1011
},
1112
{
12-
"id": "javascript",
13-
"name": "Javascript"
13+
"iac": "sam",
14+
"runtime": "javascript",
15+
"assetName": "s3-lambda"
1416
},
1517
{
16-
"id": "dotnet",
17-
"name": "Dotnet"
18+
"iac": "sam",
19+
"runtime": "java",
20+
"assetName": "s3-lambda-resizing-java"
1821
},
1922
{
20-
"id": "java",
21-
"name": "Java"
22-
}
23-
],
24-
"iac": [
25-
{
26-
"id": "sam",
27-
"name": "SAM"
23+
"iac": "sam",
24+
"runtime": "dotnet",
25+
"assetName": "s3-lambda-dotnet"
2826
}
2927
]
3028
},
3129
"apigw-rest-api-lambda-sam": {
3230
"name": "Rest API",
3331
"description": "Lambda, API Gateway • Python, Javascript, Java, .NET • SAM",
34-
"runtimes": [
32+
"implementation": [
3533
{
36-
"id": "python",
37-
"name": "Python"
34+
"iac": "sam",
35+
"runtime": "python",
36+
"assetName": "apigw-rest-api-lambda-python"
3837
},
3938
{
40-
"id": "javascript",
41-
"name": "Javascript"
39+
"iac": "sam",
40+
"runtime": "javascript",
41+
"assetName": "apigw-rest-api-lambda-node"
4242
},
4343
{
44-
"id": "dotnet",
45-
"name": "Dotnet"
44+
"iac": "sam",
45+
"runtime": "java",
46+
"assetName": "apigw-rest-api-lambda-java"
4647
},
4748
{
48-
"id": "java",
49-
"name": "Java"
50-
}
51-
],
52-
"iac": [
53-
{
54-
"id": "sam",
55-
"name": "AWS SAM"
49+
"iac": "sam",
50+
"runtime": "dotnet",
51+
"assetName": "apigw-rest-api-lambda-dotnet"
5652
}
5753
]
5854
}

packages/core/src/awsService/appBuilder/serverlessLand/metadataManager.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,15 @@
55
import * as nodefs from 'fs' // eslint-disable-line no-restricted-imports
66
import { ToolkitError } from '../../../shared/errors'
77

8-
interface IaC {
9-
id: string
10-
name: string
11-
}
12-
interface Runtime {
13-
id: string
14-
name: string
15-
version: string
8+
interface Implementation {
9+
iac: string
10+
runtime: string
11+
assetName: string
1612
}
1713
interface PatternData {
1814
name: string
1915
description: string
20-
runtimes: Runtime[]
21-
iac: IaC[]
16+
implementation: Implementation[]
2217
}
2318

2419
export interface ProjectMetadata {
@@ -96,11 +91,12 @@ export class MetadataManager {
9691
*/
9792
public getRuntimes(pattern: string): { label: string }[] {
9893
const patternData = this.metadata?.patterns?.[pattern]
99-
if (!patternData || !patternData.runtimes) {
94+
if (!patternData || !patternData.implementation) {
10095
return []
10196
}
102-
return patternData.runtimes.map((runtime) => ({
103-
label: runtime.name,
97+
const uniqueRuntimes = new Set(patternData.implementation.map((item) => item.runtime))
98+
return Array.from(uniqueRuntimes).map((runtime) => ({
99+
label: runtime,
104100
}))
105101
}
106102

@@ -111,11 +107,22 @@ export class MetadataManager {
111107
*/
112108
public getIacOptions(pattern: string): { label: string }[] {
113109
const patternData = this.metadata?.patterns?.[pattern]
114-
if (!patternData || !patternData.iac) {
110+
if (!patternData || !patternData.implementation) {
115111
return []
116112
}
117-
return patternData.iac.map((iac) => ({
118-
label: iac.name,
113+
const uniqueIaCs = new Set(patternData.implementation.map((item) => item.iac))
114+
return Array.from(uniqueIaCs).map((iac) => ({
115+
label: iac,
119116
}))
120117
}
118+
public getAssetName(selectedPattern: string, selectedRuntime: string, selectedIaC: string): string {
119+
const patternData = this.metadata?.patterns?.[selectedPattern]
120+
if (!patternData || !patternData.implementation) {
121+
return ''
122+
}
123+
const matchingImplementation = patternData.implementation.find(
124+
(impl) => impl.runtime === selectedRuntime && impl.iac === selectedIaC
125+
)
126+
return matchingImplementation?.assetName ?? ''
127+
}
121128
}

0 commit comments

Comments
 (0)