Skip to content

Commit fee8ae5

Browse files
Vandita2020Vandita Patidar
authored andcommitted
feat(lambda): Building Quick Pick structure and Entrypoints (aws#6592)
## Problem Adding entry points and Quick Pick structure for Serverless Land integration project. The attached images demonstrate the functionality. The `metadata.json` file is currently a sample, but it will be modified to include the exact list of patterns. ## Solution ### **EntryPoints** From AWS Application Builder <img width="698" alt="Screenshot 2025-02-16 at 7 33 29 PM" src="https://github.com/user-attachments/assets/1b0b563e-e6f3-414e-ad7d-b895c172b5f3" /> From Command Palette <img width="920" alt="Screenshot 2025-02-16 at 5 10 37 PM" src="https://github.com/user-attachments/assets/773c2727-344c-4100-8ee5-09efb52809f7" /> From Lambda in AWS Explorer <img width="481" alt="Screenshot 2025-02-18 at 3 22 54 PM" src="https://github.com/user-attachments/assets/b4b9a9f8-1e34-44ed-8b6d-0aeaac03e7a0" /> From the link in Getting Started Walkthrough <img width="669" alt="Screenshot 2025-02-18 at 3 36 42 PM" src="https://github.com/user-attachments/assets/f57a3b20-41df-4845-bbb8-c253bf8db592" /> ### **Quick Pick** Pattern selection <img width="893" alt="Screenshot 2025-02-16 at 7 28 25 PM" src="https://github.com/user-attachments/assets/1844dd2e-f996-4d54-a9f2-bae9af4eee84" /> Runtime selection <img width="917" alt="Screenshot 2025-02-16 at 7 28 33 PM" src="https://github.com/user-attachments/assets/73532262-70b1-412a-92e3-7ad12075ecb1" /> IaC selection <img width="907" alt="Screenshot 2025-02-16 at 7 28 39 PM" src="https://github.com/user-attachments/assets/92c093ce-8e0f-42b5-91f9-f0672dbce9f9" /> Project location selection <img width="921" alt="Screenshot 2025-02-16 at 5 12 04 PM" src="https://github.com/user-attachments/assets/c24b1b99-834b-4e1a-b34a-062ad927bafa" /> Project Name <img width="909" alt="Screenshot 2025-02-16 at 5 12 19 PM" src="https://github.com/user-attachments/assets/423165bb-ad59-4c15-b6da-582a44de8753" /> --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Co-authored-by: Vandita Patidar <[email protected]>
1 parent a05780a commit fee8ae5

File tree

8 files changed

+476
-7
lines changed

8 files changed

+476
-7
lines changed

packages/core/package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,5 +461,6 @@
461461
"AWS.toolkit.lambda.walkthrough.step1.title": "Iterate locally",
462462
"AWS.toolkit.lambda.walkthrough.step1.description": "Locally test and debug your code.",
463463
"AWS.toolkit.lambda.walkthrough.step2.title": "Deploy to the cloud",
464-
"AWS.toolkit.lambda.walkthrough.step2.description": "Test your application in the cloud from within VS Code. \n\nNote: The AWS CLI and the SAM CLI require AWS Credentials to interact with the cloud. For information on setting up your credentials, see [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). \n\n[Configure credentials](command:aws.toolkit.lambda.walkthrough.credential)"
464+
"AWS.toolkit.lambda.walkthrough.step2.description": "Test your application in the cloud from within VS Code. \n\nNote: The AWS CLI and the SAM CLI require AWS Credentials to interact with the cloud. For information on setting up your credentials, see [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). \n\n[Configure credentials](command:aws.toolkit.lambda.walkthrough.credential)",
465+
"AWS.toolkit.lambda.serverlessLand.quickpickTitle": "Create Lambda Application from template"
465466
}

packages/core/resources/walkthrough/appBuilder/AppPicker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
</checkbox>
2121
</div>
2222
</checklist>
23-
<checkbox class="theme-picker-link" when-checked="command:aws.lambda.createNewSamApp" checked-on="false">
23+
<checkbox class="theme-picker-link" when-checked="command:aws.toolkit.lambda.createServerlessLandProject" checked-on="false">
2424
See more application example...
2525
</checkbox>

packages/core/src/awsService/appBuilder/activation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { ResourceNode } from './explorer/nodes/resourceNode'
2323
import { getSyncWizard, runSync } from '../../shared/sam/sync'
2424
import { getDeployWizard, runDeploy } from '../../shared/sam/deploy'
2525
import { DeployTypeWizard } from './wizards/deployTypeWizard'
26-
26+
import { createNewServerlessLandProject } from './serverlessLand/main'
2727
export const templateToOpenAppComposer = 'aws.toolkit.appComposer.templateToOpenOnStart'
2828

2929
/**
@@ -200,6 +200,9 @@ async function registerAppBuilderCommands(context: ExtContext): Promise<void> {
200200
await runSync('infra', arg, undefined, choices.syncParam)
201201
}
202202
}
203+
}),
204+
Commands.register({ id: 'aws.toolkit.lambda.createServerlessLandProject', autoconnect: false }, async () => {
205+
await createNewServerlessLandProject(context)
203206
})
204207
)
205208
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as nls from 'vscode-nls'
7+
const localize = nls.loadMessageBundle()
8+
import * as path from 'path'
9+
import { getTelemetryReason, getTelemetryResult } from '../../../shared/errors'
10+
import { getLogger } from '../../../shared/logger/logger'
11+
import globals from '../../../shared/extensionGlobals'
12+
import { checklogs } from '../../../shared/localizedText'
13+
import { Result, telemetry } from '../../../shared/telemetry/telemetry'
14+
import { CreateServerlessLandWizard } from './wizard'
15+
import { ExtContext } from '../../../shared/extensions'
16+
import { addFolderToWorkspace } from '../../../shared/utilities/workspaceUtils'
17+
18+
export const readmeFile: string = 'README.md'
19+
20+
/**
21+
* Creates a new Serverless Land project using the provided extension context
22+
* @param extContext Extension context containing AWS credentials and region information
23+
* @returns Promise that resolves when the project creation is complete
24+
*
25+
* This function:
26+
* 1. Validates AWS credentials and regions
27+
* 2. Launches the Serverless Land project creation wizard
28+
* 3. Creates the project structure
29+
* 4. Adds the project folder to the workspace
30+
* 5. Opens the README.md file if available
31+
* 6. Handles errors and emits telemetry
32+
*/
33+
export async function createNewServerlessLandProject(extContext: ExtContext): Promise<void> {
34+
const awsContext = extContext.awsContext
35+
let createResult: Result = 'Succeeded'
36+
let reason: string | undefined
37+
38+
try {
39+
const credentials = await awsContext.getCredentials()
40+
const defaultRegion = awsContext.getCredentialDefaultRegion()
41+
42+
// Launch the project creation wizard
43+
const config = await new CreateServerlessLandWizard({
44+
credentials,
45+
defaultRegion,
46+
}).run()
47+
if (!config) {
48+
createResult = 'Cancelled'
49+
reason = 'userCancelled'
50+
return
51+
}
52+
53+
// Add the project folder to the workspace
54+
await addFolderToWorkspace(
55+
{
56+
uri: config.location,
57+
name: path.basename(config.location.fsPath),
58+
},
59+
true
60+
)
61+
} catch (err) {
62+
createResult = getTelemetryResult(err)
63+
reason = getTelemetryReason(err)
64+
65+
globals.outputChannel.show(true)
66+
getLogger().error(
67+
localize(
68+
'AWS.serverlessland.initWizard.general.error',
69+
'Error creating new Serverless Land Application. {0}',
70+
checklogs()
71+
)
72+
)
73+
getLogger().error('Error creating new Serverless Land Application: %O', err as Error)
74+
} finally {
75+
// add telemetry
76+
// TODO: Will add telemetry once the implementation gets completed
77+
telemetry.sam_init.emit({
78+
result: createResult,
79+
reason: reason,
80+
})
81+
}
82+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"patterns": {
3+
"s3-lambda-resizing-sam": {
4+
"name": "Resizing image",
5+
"description": "Lambda, S3 • Python, Javascript, Java, .NET • SAM",
6+
"runtimes": [
7+
{
8+
"id": "python",
9+
"name": "Python"
10+
},
11+
{
12+
"id": "javascript",
13+
"name": "Javascript"
14+
},
15+
{
16+
"id": "dotnet",
17+
"name": "Dotnet"
18+
},
19+
{
20+
"id": "java",
21+
"name": "Java"
22+
}
23+
],
24+
"iac": [
25+
{
26+
"id": "sam",
27+
"name": "SAM"
28+
}
29+
]
30+
},
31+
"apigw-rest-api-lambda-sam": {
32+
"name": "Rest API",
33+
"description": "Lambda, API Gateway • Python, Javascript, Java, .NET • SAM",
34+
"runtimes": [
35+
{
36+
"id": "python",
37+
"name": "Python"
38+
},
39+
{
40+
"id": "javascript",
41+
"name": "Javascript"
42+
},
43+
{
44+
"id": "dotnet",
45+
"name": "Dotnet"
46+
},
47+
{
48+
"id": "java",
49+
"name": "Java"
50+
}
51+
],
52+
"iac": [
53+
{
54+
"id": "sam",
55+
"name": "AWS SAM"
56+
}
57+
]
58+
}
59+
}
60+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import * as nodefs from 'fs' // eslint-disable-line no-restricted-imports
6+
import { ToolkitError } from '../../../shared/errors'
7+
8+
interface IaC {
9+
id: string
10+
name: string
11+
}
12+
interface Runtime {
13+
id: string
14+
name: string
15+
version: string
16+
}
17+
interface PatternData {
18+
name: string
19+
description: string
20+
runtimes: Runtime[]
21+
iac: IaC[]
22+
}
23+
24+
export interface ProjectMetadata {
25+
patterns: Record<string, PatternData>
26+
}
27+
28+
/**
29+
* Manages metadata for serverless application patterns
30+
*/
31+
32+
export class MetadataManager {
33+
private static instance: MetadataManager
34+
private metadata: ProjectMetadata | undefined
35+
36+
private constructor() {}
37+
38+
public static getInstance(): MetadataManager {
39+
if (!MetadataManager.instance) {
40+
MetadataManager.instance = new MetadataManager()
41+
}
42+
return MetadataManager.instance
43+
}
44+
45+
/**
46+
* Loads metadata from a JSON file
47+
* @param metadataPath Path to the metadata JSON file
48+
* @returns Promise containing the parsed ProjectMetadata
49+
*/
50+
public async loadMetadata(metadataPath: string): Promise<ProjectMetadata> {
51+
try {
52+
if (!this.metadata) {
53+
const metadataContent = nodefs.readFileSync(metadataPath, { encoding: 'utf-8' })
54+
const parseMetadata = JSON.parse(metadataContent) as ProjectMetadata
55+
this.metadata = parseMetadata
56+
}
57+
return this.metadata
58+
} catch (err) {
59+
throw new ToolkitError(`Failed to load metadata: ${err instanceof Error ? err.message : String(err)}`)
60+
}
61+
}
62+
63+
/**
64+
* Retrieves available patterns with their descriptions
65+
* @returns Array of pattern objects containing labels and descriptions
66+
*/
67+
public getPatterns(): { label: string; description?: string }[] {
68+
if (!this.metadata) {
69+
return []
70+
}
71+
return Object.entries(this.metadata.patterns).map(([patternName, patternData]) => {
72+
let description: string | undefined = undefined
73+
if (typeof patternData === 'string') {
74+
description = patternData
75+
} else if (Array.isArray(patternData)) {
76+
// If description is an array, join it into a single string
77+
description = patternData.join(' ')
78+
}
79+
if (!patternData || !patternData.name) {
80+
return {
81+
label: patternName,
82+
description: description || 'No description available',
83+
}
84+
}
85+
return {
86+
label: patternName,
87+
description: patternData.description,
88+
}
89+
})
90+
}
91+
92+
/**
93+
* Gets available runtimes for a specific pattern
94+
* @param pattern The pattern name to get runtimes for
95+
* @returns Array of runtime options with labels
96+
*/
97+
public getRuntimes(pattern: string): { label: string }[] {
98+
const patternData = this.metadata?.patterns?.[pattern]
99+
if (!patternData || !patternData.runtimes) {
100+
return []
101+
}
102+
return patternData.runtimes.map((runtime) => ({
103+
label: runtime.name,
104+
}))
105+
}
106+
107+
/**
108+
* Gets available Infrastructure as Code options for a specific pattern
109+
* @param pattern The pattern name to get IaC options for
110+
* @returns Array of IaC options with labels
111+
*/
112+
public getIacOptions(pattern: string): { label: string }[] {
113+
const patternData = this.metadata?.patterns?.[pattern]
114+
if (!patternData || !patternData.iac) {
115+
return []
116+
}
117+
return patternData.iac.map((iac) => ({
118+
label: iac.name,
119+
}))
120+
}
121+
}

0 commit comments

Comments
 (0)