Skip to content

Commit eb562c0

Browse files
committed
StackToolbox#49 Add partial replace .vscode/launch.json
1 parent 7276a4a commit eb562c0

File tree

3 files changed

+203
-1
lines changed

3 files changed

+203
-1
lines changed

src/__tests__/__snapshots__/integration.test.ts.snap

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Resources:
4343
".vscode/launch.json": "{
4444
\\"version\\": \\"0.2.0\\",
4545
\\"configurations\\": [
46+
// BEGIN AwsSamPlugin
4647
{
4748
\\"name\\": \\"MyLambda\\",
4849
\\"type\\": \\"node\\",
@@ -62,6 +63,7 @@ Resources:
6263
\\"<node_internals>/**/*.js\\"
6364
]
6465
}
66+
// END AwsSamPlugin
6567
]
6668
}",
6769
},
@@ -89,6 +91,7 @@ Resources:
8991
".vscode/launch.json": "{
9092
\\"version\\": \\"0.2.0\\",
9193
\\"configurations\\": [
94+
// BEGIN AwsSamPlugin
9295
{
9396
\\"name\\": \\"MyLambda\\",
9497
\\"type\\": \\"node\\",
@@ -108,6 +111,7 @@ Resources:
108111
\\"<node_internals>/**/*.js\\"
109112
]
110113
}
114+
// END AwsSamPlugin
111115
]
112116
}",
113117
},
@@ -135,6 +139,7 @@ Resources:
135139
".vscode/launch.json": "{
136140
\\"version\\": \\"0.2.0\\",
137141
\\"configurations\\": [
142+
// BEGIN AwsSamPlugin
138143
{
139144
\\"name\\": \\"MyLambda\\",
140145
\\"type\\": \\"node\\",
@@ -154,6 +159,7 @@ Resources:
154159
\\"<node_internals>/**/*.js\\"
155160
]
156161
}
162+
// END AwsSamPlugin
157163
]
158164
}",
159165
},
@@ -181,6 +187,7 @@ Resources:
181187
".vscode/launch.json": "{
182188
\\"version\\": \\"0.2.0\\",
183189
\\"configurations\\": [
190+
// BEGIN AwsSamPlugin
184191
{
185192
\\"name\\": \\"MyLambda\\",
186193
\\"type\\": \\"node\\",
@@ -200,6 +207,7 @@ Resources:
200207
\\"<node_internals>/**/*.js\\"
201208
]
202209
}
210+
// END AwsSamPlugin
203211
]
204212
}",
205213
},
@@ -216,6 +224,7 @@ Object {
216224
".vscode/launch.json": "{
217225
\\"version\\": \\"0.2.0\\",
218226
\\"configurations\\": [
227+
// BEGIN AwsSamPlugin
219228
{
220229
\\"name\\": \\"a:MyLambda\\",
221230
\\"type\\": \\"node\\",
@@ -254,6 +263,7 @@ Object {
254263
\\"<node_internals>/**/*.js\\"
255264
]
256265
}
266+
// END AwsSamPlugin
257267
]
258268
}",
259269
"project-a/.aws-sam/build/template.yaml": "AWSTemplateFormatVersion: 2010-09-09
@@ -294,6 +304,7 @@ Object {
294304
".vscode/launch.json": "{
295305
\\"version\\": \\"0.2.0\\",
296306
\\"configurations\\": [
307+
// BEGIN AwsSamPlugin
297308
{
298309
\\"name\\": \\"a:MyLambda\\",
299310
\\"type\\": \\"node\\",
@@ -332,6 +343,7 @@ Object {
332343
\\"<node_internals>/**/*.js\\"
333344
]
334345
}
346+
// END AwsSamPlugin
335347
]
336348
}",
337349
"project-a/.aws-sam/build/template.yaml": "AWSTemplateFormatVersion: 2010-09-09

src/__tests__/integration.test.ts

+159
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,165 @@ test("Happy path with VS Code debugging disabled", () => {
189189
expect({ entryPoints, files: fs.__getMockWrittenFiles() }).toMatchSnapshot();
190190
});
191191

192+
const vscodeLaunchJson1 = `{
193+
"version": "0.2.0",
194+
"configurations": [
195+
{
196+
"name": "CustomLambda",
197+
"type": "node",
198+
"request": "attach",
199+
"address": "localhost",
200+
"port": 5858,
201+
"localRoot": "\${workspaceFolder}/.aws-sam/build/CustomLambda",
202+
"remoteRoot": "/var/task",
203+
"protocol": "inspector",
204+
"stopOnEntry": false,
205+
"outFiles": [
206+
"\${workspaceFolder}/.aws-sam/build/CustomLambda/**/*.js"
207+
],
208+
"sourceMaps": true,
209+
"skipFiles": [
210+
"/var/runtime/**/*.js",
211+
"<node_internals>/**/*.js"
212+
]
213+
}
214+
]
215+
}`;
216+
const vscodeLaunchJson2 = `{
217+
"version": "0.2.0",
218+
"configurations": [
219+
{
220+
"name": "CustomLambda",
221+
"type": "node",
222+
"request": "attach",
223+
"address": "localhost",
224+
"port": 5858,
225+
"localRoot": "\${workspaceFolder}/.aws-sam/build/CustomLambda",
226+
"remoteRoot": "/var/task",
227+
"protocol": "inspector",
228+
"stopOnEntry": false,
229+
"outFiles": [
230+
"\${workspaceFolder}/.aws-sam/build/CustomLambda/**/*.js"
231+
],
232+
"sourceMaps": true,
233+
"skipFiles": [
234+
"/var/runtime/**/*.js",
235+
"<node_internals>/**/*.js"
236+
]
237+
},
238+
// BEGIN AwsSamPlugin
239+
{
240+
"name": "OldLambda",
241+
"type": "node",
242+
"request": "attach",
243+
"address": "localhost",
244+
"port": 5858,
245+
"localRoot": "\${workspaceFolder}/.aws-sam/build/OldLambda",
246+
"remoteRoot": "/var/task",
247+
"protocol": "inspector",
248+
"stopOnEntry": false,
249+
"outFiles": [
250+
"\${workspaceFolder}/.aws-sam/build/OldLambda/**/*.js"
251+
],
252+
"sourceMaps": true,
253+
"skipFiles": [
254+
"/var/runtime/**/*.js",
255+
"<node_internals>/**/*.js"
256+
]
257+
}
258+
// END AwsSamPlugin
259+
]
260+
}`;
261+
const vscodeLaunchJsonTest = `{
262+
"version": "0.2.0",
263+
"configurations": [
264+
{
265+
"name": "CustomLambda",
266+
"type": "node",
267+
"request": "attach",
268+
"address": "localhost",
269+
"port": 5858,
270+
"localRoot": "\${workspaceFolder}/.aws-sam/build/CustomLambda",
271+
"remoteRoot": "/var/task",
272+
"protocol": "inspector",
273+
"stopOnEntry": false,
274+
"outFiles": [
275+
"\${workspaceFolder}/.aws-sam/build/CustomLambda/**/*.js"
276+
],
277+
"sourceMaps": true,
278+
"skipFiles": [
279+
"/var/runtime/**/*.js",
280+
"<node_internals>/**/*.js"
281+
]
282+
},
283+
// BEGIN AwsSamPlugin
284+
{
285+
"name": "MyLambda",
286+
"type": "node",
287+
"request": "attach",
288+
"address": "localhost",
289+
"port": 5858,
290+
"localRoot": "\${workspaceFolder}/.aws-sam/build/MyLambda",
291+
"remoteRoot": "/var/task",
292+
"protocol": "inspector",
293+
"stopOnEntry": false,
294+
"outFiles": [
295+
"\${workspaceFolder}/.aws-sam/build/MyLambda/**/*.js"
296+
],
297+
"sourceMaps": true,
298+
"skipFiles": [
299+
"/var/runtime/**/*.js",
300+
"<node_internals>/**/*.js"
301+
]
302+
}
303+
// END AwsSamPlugin
304+
]
305+
}`;
306+
307+
test.each([
308+
[vscodeLaunchJson1, vscodeLaunchJsonTest],
309+
[vscodeLaunchJson2, vscodeLaunchJsonTest],
310+
])("Happy build launch.json with replace old content", (srcData, testData) => {
311+
const plugin = new SamPlugin({ vscodeDebug: true });
312+
313+
// @ts-ignore
314+
fs.__clearMocks();
315+
// @ts-ignore
316+
fs.__setMockDirs(["."]);
317+
// @ts-ignore
318+
fs.__setMockFiles({ "./template.yaml": samTemplate, ".vscode/launch.json": srcData });
319+
320+
// @ts-ignore
321+
path.__clearMocks();
322+
// @ts-ignore
323+
path.__setMockBasenames({ "./template.yaml": "template.yaml" });
324+
// @ts-ignore
325+
path.__setMockDirnames({ "./template.yaml": "." });
326+
// @ts-ignore
327+
path.__setMockRelatives({ ".#.": "" });
328+
329+
const entryPoints = plugin.entry();
330+
331+
let afterEmit: (_compilation: any) => void;
332+
333+
plugin.apply({
334+
hooks: {
335+
afterEmit: {
336+
tap: (n: string, f: (_compilation: any) => void) => {
337+
afterEmit = f;
338+
},
339+
},
340+
},
341+
});
342+
// @ts-ignore
343+
afterEmit(null);
344+
345+
// @ts-ignore
346+
const vscodeLaunchJsonContent = fs.__getMockWrittenFiles()[".vscode/launch.json"];
347+
348+
expect(vscodeLaunchJsonContent).toEqual(testData);
349+
});
350+
192351
test("Happy path with multiple projects works", () => {
193352
const plugin = new SamPlugin({ projects: { a: "project-a", b: "project-b" } });
194353

src/index.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,38 @@ class AwsSamPlugin {
329329
if (!fs.existsSync(".vscode")) {
330330
fs.mkdirSync(".vscode");
331331
}
332-
fs.writeFileSync(".vscode/launch.json", JSON.stringify(this.launchConfig, null, 2));
332+
333+
const launchPath = ".vscode/launch.json";
334+
335+
const launchContent = JSON.stringify(this.launchConfig, null, 2)
336+
.replace(/^(.*"configurations": \[\s*)$/m, "$1\n // BEGIN AwsSamPlugin")
337+
.replace(/(\n \s*\][\r\n]+\})$/m, "\n // END AwsSamPlugin$1");
338+
const regexBlock = /\s+\/\/ BEGIN AwsSamPlugin(\r|\n|.)+\/\/ END AwsSamPlugin/m;
339+
340+
// get new "configurations" content
341+
const matches = launchContent.match(regexBlock);
342+
if (!matches) {
343+
throw new Error(launchPath + " new content does not match");
344+
}
345+
const launchConfigurations = matches[0];
346+
347+
if (fs.existsSync(launchPath)) {
348+
const launchContentOld = fs.readFileSync(launchPath).toString("utf8");
349+
if (launchContentOld.match(regexBlock)) {
350+
// partial rewrite contents
351+
const newContent = launchContentOld.replace(regexBlock, () => launchConfigurations);
352+
fs.writeFileSync(launchPath, newContent);
353+
} else {
354+
// add configurations
355+
const newContent = launchContentOld.replace(
356+
/(\n \]\n\})$/m,
357+
(p0, p1) => `,${launchConfigurations}${p1}`
358+
);
359+
fs.writeFileSync(launchPath, newContent);
360+
}
361+
} else {
362+
fs.writeFileSync(launchPath, launchContent);
363+
}
333364
}
334365
} else {
335366
throw new Error("It looks like AwsSamPlugin.entry() was not called");

0 commit comments

Comments
 (0)