Skip to content

Commit dbced06

Browse files
authored
Support MultiSelect List in OperationContextParams (#1536)
1 parent 1db3e9f commit dbced06

File tree

3 files changed

+89
-37
lines changed

3 files changed

+89
-37
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/endpointsV2/RuleSetParameterFinder.java

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -277,39 +277,7 @@ public Map<String, String> getOperationContextParamValues(OperationShape operati
277277
String separator = "?.";
278278
String value = "input";
279279
String path = definition.getPath();
280-
281-
// Split JMESPath expression string on separator and add JavaScript equivalent.
282-
for (String part : path.split("[" + separator + "]")) {
283-
if (value.endsWith(")")) {
284-
// The value is an object, which needs to run on map.
285-
value += ".map((obj: any) => obj";
286-
}
287-
288-
// Process keys https://jmespath.org/specification.html#keys
289-
if (part.startsWith("keys(")) {
290-
// Get provided object for which keys are to be extracted.
291-
String object = part.substring(5, part.length() - 1);
292-
value = "Object.keys(" + value + separator + object + " ?? {})";
293-
continue;
294-
}
295-
296-
// Process list wildcard expression https://jmespath.org/specification.html#wildcard-expressions
297-
if (part.equals("*") || part.equals("[*]")) {
298-
value = "Object.values(" + value + " ?? {})";
299-
continue;
300-
}
301-
302-
// Process hash wildcard expression https://jmespath.org/specification.html#wildcard-expressions
303-
if (part.endsWith("[*]")) {
304-
// Get key to run hash wildcard on.
305-
String key = part.substring(0, part.length() - 3);
306-
value = value + separator + key + separator + "map((obj: any) => obj";
307-
continue;
308-
}
309-
310-
// Treat remaining part as identifier without spaces https://jmespath.org/specification.html#identifiers
311-
value += separator + part;
312-
}
280+
value = getJmesPathExpression(separator, value, path);
313281

314282
// Remove no-op map, if it exists.
315283
final String noOpMap = "map((obj: any) => obj";
@@ -328,6 +296,74 @@ public Map<String, String> getOperationContextParamValues(OperationShape operati
328296
return map;
329297
}
330298

299+
private String getJmesPathExpression(String separator, String value, String path) {
300+
// Split JMESPath expression string on separator and add JavaScript equivalent.
301+
while (path.length() > 0) {
302+
if (path.startsWith("[") && !path.startsWith("[*]")) {
303+
// Process MultiSelect List https://jmespath.org/specification.html#multiselect-list
304+
if (value.endsWith("obj")) {
305+
value = value.substring(0, value.length() - 3);
306+
}
307+
308+
value += "[";
309+
path = path.substring(1);
310+
311+
while (true) {
312+
int commaIndex = path.indexOf(",");
313+
int sepIndex = (commaIndex == -1) ? path.indexOf("]") : commaIndex;
314+
String part = path.substring(0, sepIndex);
315+
path = path.substring(sepIndex + 1).trim();
316+
value += getJmesPathExpression(separator, "obj", part) + ",";
317+
if (commaIndex == -1) {
318+
// Remove trailing comma and close bracket.
319+
value = value.substring(0, value.length() - 1) + "].filter((i) => i))";
320+
break;
321+
}
322+
}
323+
continue;
324+
}
325+
326+
int dotIndex = path.indexOf(".");
327+
String part = dotIndex == -1 ? path : path.substring(0, dotIndex);
328+
path = dotIndex == -1 ? "" : path.substring(dotIndex + 1);
329+
value = getJmesPathExpressionSection(separator, value, part);
330+
}
331+
return value;
332+
}
333+
334+
private String getJmesPathExpressionSection(String separator, String value, String part) {
335+
if (value.endsWith(")")) {
336+
// The value is an object, which needs to run on map.
337+
value += ".map((obj: any) => obj";
338+
}
339+
340+
// Process keys https://jmespath.org/specification.html#keys
341+
if (part.startsWith("keys(")) {
342+
// Get provided object for which keys are to be extracted.
343+
String object = part.substring(5, part.length() - 1);
344+
value = "Object.keys(" + value + separator + object + " ?? {})";
345+
return value;
346+
}
347+
348+
// Process list wildcard expression https://jmespath.org/specification.html#wildcard-expressions
349+
if (part.equals("*") || part.equals("[*]")) {
350+
value = "Object.values(" + value + " ?? {})";
351+
return value;
352+
}
353+
354+
// Process hash wildcard expression https://jmespath.org/specification.html#wildcard-expressions
355+
if (part.endsWith("[*]")) {
356+
// Get key to run hash wildcard on.
357+
String key = part.substring(0, part.length() - 3);
358+
value = value + separator + key + separator + "map((obj: any) => obj";
359+
return value;
360+
}
361+
362+
// Treat remaining part as identifier without spaces https://jmespath.org/specification.html#identifiers
363+
value += separator + part;
364+
return value;
365+
}
366+
331367
private static class RuleSetParameterFinderVisitor extends NodeVisitor.Default<Void> {
332368
private final Map<String, String> map;
333369

smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/CommandGeneratorTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public void writesOperationContextParamValues() {
4444
"opContextParamWildcardExpressionList: { type: \"operationContextParams\", get: (input?: any) => input?.fooList }",
4545
"opContextParamWildcardExpressionListObj: { type: \"operationContextParams\", get: (input?: any) => input?.fooListObj?.map((obj: any) => obj?.key) }",
4646
"opContextParamWildcardExpressionHash: { type: \"operationContextParams\", get: (input?: any) => Object.values(input?.fooObjObj ?? {}).map((obj: any) => obj?.bar) }",
47+
"opContextParamMultiSelectList: { type: \"operationContextParams\", get: (input?: any) => input?.fooListObjObj?.map((obj: any) => [obj?.fooList[0],obj?.fooObject?.bar,obj?.fooString].filter((i) => i)) }",
4748
"opContextParamKeys: { type: \"operationContextParams\", get: (input?: any) => Object.keys(input?.fooKeys ?? {}) }",
4849
}
4950
);

smithy-typescript-codegen/src/test/resources/software/amazon/smithy/typescript/codegen/endpointsV2/endpoints-operation-context-params.smithy

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ namespace smithy.example
2020
opContextParamWildcardExpressionHash: {
2121
type: "stringArray",
2222
},
23+
opContextParamMultiSelectList: {
24+
type: "stringArray",
25+
},
2326
opContextParamKeys: {
2427
type: "stringArray",
2528
},
@@ -37,6 +40,7 @@ service Example {
3740
"opContextParamWildcardExpressionList": { path: "fooList[*]" }
3841
"opContextParamWildcardExpressionListObj": { path: "fooListObj[*].key" }
3942
"opContextParamWildcardExpressionHash": { path: "fooObjObj.*.bar" }
43+
"opContextParamMultiSelectList": { path: "fooListObjObj[*].[fooList[0], fooObject.bar, fooString]" }
4044
"opContextParamKeys": { path: "keys(fooKeys)" }
4145
)
4246
operation GetFoo {
@@ -48,7 +52,8 @@ operation GetFoo {
4852
structure GetFooInput {
4953
fooKeys: FooObject,
5054
fooList: FooList,
51-
fooListObj: FooListObj,
55+
fooListObj: FooListObject,
56+
fooListObjObj: FooListObjectObject,
5257
fooObj: FooObject,
5358
fooObjObj: FooObjectObject,
5459
fooString: String,
@@ -58,6 +63,16 @@ structure FooObject {
5863
bar: String
5964
}
6065

66+
list FooListObjectObject {
67+
member: FooMultiSelectObjectObject
68+
}
69+
70+
structure FooMultiSelectObjectObject {
71+
fooList: FooList
72+
fooObject: FooObject
73+
fooString: String
74+
}
75+
6176
structure FooObjectObject {
6277
baz: FooObject
6378
}
@@ -66,11 +81,11 @@ list FooList {
6681
member: String
6782
}
6883

69-
list FooListObj {
70-
member: FooListObjMember
84+
list FooListObject {
85+
member: FooListObjectMember
7186
}
7287

73-
structure FooListObjMember {
88+
structure FooListObjectMember {
7489
key: String
7590
}
7691

0 commit comments

Comments
 (0)